Web feed

This commit is contained in:
2025-06-30 23:33:14 +08:00
parent 666a2dfbf5
commit d6c829c26a
18 changed files with 1351 additions and 53 deletions

View File

@ -0,0 +1,51 @@
import 'package:flutter/material.dart';
class EmptyState extends StatelessWidget {
final IconData icon;
final String title;
final String description;
final Widget? action;
const EmptyState({
super.key,
required this.icon,
required this.title,
required this.description,
this.action,
});
@override
Widget build(BuildContext context) {
return Center(
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
icon,
size: 64,
color: Theme.of(context).colorScheme.outline,
),
const SizedBox(height: 16),
Text(
title,
style: Theme.of(context).textTheme.titleLarge,
textAlign: TextAlign.center,
),
const SizedBox(height: 8),
Text(
description,
style: Theme.of(context).textTheme.bodyMedium,
textAlign: TextAlign.center,
),
if (action != null) ...[
const SizedBox(height: 24),
action!,
],
],
),
),
);
}
}

View File

@ -542,14 +542,14 @@ Widget _buildReferencePost(BuildContext context, SnPost item) {
class PostReactionList extends HookConsumerWidget {
final String parentId;
final Map<String, int> reactions;
final Function(String symbol, int attitude, int delta) onReact;
final Function(String symbol, int attitude, int delta)? onReact;
final EdgeInsets? padding;
const PostReactionList({
super.key,
required this.parentId,
required this.reactions,
this.padding,
required this.onReact,
this.onReact,
});
@override
@ -570,7 +570,7 @@ class PostReactionList extends HookConsumerWidget {
})
.then((resp) {
var isRemoving = resp.statusCode == 204;
onReact(symbol, attitude, isRemoving ? -1 : 1);
onReact?.call(symbol, attitude, isRemoving ? -1 : 1);
HapticFeedback.heavyImpact();
});
submitting.value = false;
@ -582,33 +582,34 @@ class PostReactionList extends HookConsumerWidget {
scrollDirection: Axis.horizontal,
padding: padding ?? EdgeInsets.zero,
children: [
Padding(
padding: const EdgeInsets.only(right: 8),
child: ActionChip(
avatar: Icon(Symbols.add_reaction),
label: Text('react').tr(),
visualDensity: const VisualDensity(
horizontal: VisualDensity.minimumDensity,
vertical: VisualDensity.minimumDensity,
if (onReact != null)
Padding(
padding: const EdgeInsets.only(right: 8),
child: ActionChip(
avatar: Icon(Symbols.add_reaction),
label: Text('react').tr(),
visualDensity: const VisualDensity(
horizontal: VisualDensity.minimumDensity,
vertical: VisualDensity.minimumDensity,
),
onPressed:
submitting.value
? null
: () {
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return _PostReactionSheet(
reactionsCount: reactions,
onReact: (symbol, attitude) {
reactPost(symbol, attitude);
},
);
},
);
},
),
onPressed:
submitting.value
? null
: () {
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return _PostReactionSheet(
reactionsCount: reactions,
onReact: (symbol, attitude) {
reactPost(symbol, attitude);
},
);
},
);
},
),
),
for (final symbol in reactions.keys)
Padding(
padding: const EdgeInsets.only(right: 8),

View File

@ -365,11 +365,6 @@ class PostItemCreator extends HookConsumerWidget {
parentId: item.id,
reactions: item.reactionsCount,
padding: EdgeInsets.zero,
onReact: (symbol, attitude, delta) {
final reactionsCount = Map<String, int>.from(item.reactionsCount);
reactionsCount[symbol] = (reactionsCount[symbol] ?? 0) + delta;
onUpdate?.call(item.copyWith(reactionsCount: reactionsCount));
},
),
const Gap(16),
],