Compare commits

...

2 Commits

Author SHA1 Message Date
599dd4827b 💄 Show the most typical reaction 2024-12-06 00:28:51 +08:00
45f489dcb6 Post visibility hint 2024-12-06 00:21:48 +08:00
3 changed files with 63 additions and 13 deletions

View File

@ -62,7 +62,8 @@ class _AttachmentListState extends State<AttachmentList> {
'audio' => 16 / 9, 'audio' => 16 / 9,
'video' => 16 / 9, 'video' => 16 / 9,
_ => 1, _ => 1,
}; }
.toDouble();
return Container( return Container(
constraints: ResponsiveBreakpoints.of(context).largerThan(MOBILE) constraints: ResponsiveBreakpoints.of(context).largerThan(MOBILE)

View File

@ -11,12 +11,14 @@ import 'package:styled_widget/styled_widget.dart';
import 'package:surface/providers/sn_network.dart'; import 'package:surface/providers/sn_network.dart';
import 'package:surface/providers/userinfo.dart'; import 'package:surface/providers/userinfo.dart';
import 'package:surface/types/post.dart'; import 'package:surface/types/post.dart';
import 'package:surface/types/reaction.dart';
import 'package:surface/widgets/account/account_image.dart'; import 'package:surface/widgets/account/account_image.dart';
import 'package:surface/widgets/attachment/attachment_list.dart'; import 'package:surface/widgets/attachment/attachment_list.dart';
import 'package:surface/widgets/dialog.dart'; import 'package:surface/widgets/dialog.dart';
import 'package:surface/widgets/markdown_content.dart'; import 'package:surface/widgets/markdown_content.dart';
import 'package:gap/gap.dart'; import 'package:gap/gap.dart';
import 'package:surface/widgets/post/post_comment_list.dart'; import 'package:surface/widgets/post/post_comment_list.dart';
import 'package:surface/widgets/post/post_meta_editor.dart';
import 'package:surface/widgets/post/post_reaction.dart'; import 'package:surface/widgets/post/post_reaction.dart';
import 'package:surface/widgets/post/publisher_popover.dart'; import 'package:surface/widgets/post/publisher_popover.dart';
@ -69,6 +71,11 @@ class PostItem extends StatelessWidget {
_PostQuoteContent(child: data.repostTo!).padding( _PostQuoteContent(child: data.repostTo!).padding(
horizontal: 12, horizontal: 12,
), ),
if (data.visibility > 0)
_PostVisibilityHint(data: data).padding(
horizontal: 16,
vertical: 4,
),
if (data.body['content_truncated'] == true) if (data.body['content_truncated'] == true)
_PostTruncatedHint(data: data).padding( _PostTruncatedHint(data: data).padding(
horizontal: 16, horizontal: 16,
@ -121,6 +128,13 @@ class _PostBottomAction extends StatelessWidget {
final iconColor = Theme.of(context).colorScheme.onSurface.withAlpha( final iconColor = Theme.of(context).colorScheme.onSurface.withAlpha(
(255 * 0.8).round(), (255 * 0.8).round(),
); );
final String? mostTypicalReaction = data.metric.reactionList.isNotEmpty
? data.metric.reactionList.entries
.reduce((a, b) => a.value > b.value ? a : b)
.key
: null;
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
@ -131,7 +145,18 @@ class _PostBottomAction extends StatelessWidget {
InkWell( InkWell(
child: Row( child: Row(
children: [ children: [
Icon(Symbols.add_reaction, size: 20, color: iconColor), if (mostTypicalReaction == null ||
kTemplateReactions[mostTypicalReaction] == null)
Icon(Symbols.add_reaction, size: 20, color: iconColor)
else
Text(
kTemplateReactions[mostTypicalReaction]!.icon,
style: TextStyle(
fontSize: 16,
height: 1.2,
letterSpacing: 0,
),
),
const Gap(8), const Gap(8),
if (data.totalUpvote > 0 && if (data.totalUpvote > 0 &&
data.totalUpvote >= data.totalDownvote) data.totalUpvote >= data.totalDownvote)
@ -478,6 +503,30 @@ class _PostTagsList extends StatelessWidget {
} }
} }
class _PostVisibilityHint extends StatelessWidget {
final SnPost data;
const _PostVisibilityHint({super.key, required this.data});
static const List<IconData> kVisibilityIcons = [
Symbols.public,
Symbols.group,
Symbols.person_check,
Symbols.person_remove,
Symbols.lock,
];
@override
Widget build(BuildContext context) {
return Row(
children: [
Icon(kVisibilityIcons[data.visibility], size: 20),
const Gap(4),
Text(kPostVisibilityLevel[data.visibility] ?? 'postVisibilityAll').tr(),
],
).opacity(0.75);
}
}
class _PostTruncatedHint extends StatelessWidget { class _PostTruncatedHint extends StatelessWidget {
final SnPost data; final SnPost data;
const _PostTruncatedHint({super.key, required this.data}); const _PostTruncatedHint({super.key, required this.data});
@ -495,9 +544,9 @@ class _PostTruncatedHint extends StatelessWidget {
const Gap(4), const Gap(4),
Text('postReadEstimate').tr(args: [ Text('postReadEstimate').tr(args: [
'${Duration( '${Duration(
seconds: ((data.body['content_length'] as num).toDouble() / seconds: (data.body['content_length'] as num).toDouble() *
kHumanReadSpeed) 60 ~/
.round(), kHumanReadSpeed,
).inSeconds}s', ).inSeconds}s',
]), ]),
], ],

View File

@ -9,17 +9,17 @@ import 'package:surface/controllers/post_write_controller.dart';
import 'package:surface/widgets/account/account_select.dart'; import 'package:surface/widgets/account/account_select.dart';
import 'package:surface/widgets/post/post_tags_field.dart'; import 'package:surface/widgets/post/post_tags_field.dart';
class PostMetaEditor extends StatelessWidget { const Map<int, String> kPostVisibilityLevel = {
final PostWriteController controller;
const PostMetaEditor({super.key, required this.controller});
static Map<int, String> kPostVisibilityLevel = {
0: 'postVisibilityAll', 0: 'postVisibilityAll',
1: 'postVisibilityFriends', 1: 'postVisibilityFriends',
2: 'postVisibilitySelected', 2: 'postVisibilitySelected',
3: 'postVisibilityFiltered', 3: 'postVisibilityFiltered',
4: 'postVisibilityNone', 4: 'postVisibilityNone',
}; };
class PostMetaEditor extends StatelessWidget {
final PostWriteController controller;
const PostMetaEditor({super.key, required this.controller});
Future<DateTime?> _selectDate( Future<DateTime?> _selectDate(
BuildContext context, { BuildContext context, {