From 625634bc8078c61f03b67ccb0a5bb2da77ca7d2b Mon Sep 17 00:00:00 2001 From: Hamlet Jiang Su Date: Fri, 19 Jan 2024 15:41:48 -0800 Subject: [PATCH 01/11] initial implementation for customizable post card metadata --- lib/community/widgets/post_card_metadata.dart | 205 ++++++++++++++++++ .../widgets/post_card_view_compact.dart | 25 ++- lib/post/enums/post_card_metadata_item.dart | 1 + 3 files changed, 224 insertions(+), 7 deletions(-) create mode 100644 lib/post/enums/post_card_metadata_item.dart diff --git a/lib/community/widgets/post_card_metadata.dart b/lib/community/widgets/post_card_metadata.dart index 4e18fa768..ffc59f7d3 100644 --- a/lib/community/widgets/post_card_metadata.dart +++ b/lib/community/widgets/post_card_metadata.dart @@ -6,6 +6,7 @@ import 'package:lemmy_api_client/v3.dart'; import 'package:thunder/core/auth/bloc/auth_bloc.dart'; import 'package:thunder/core/enums/full_name_separator.dart'; import 'package:thunder/feed/feed.dart'; +import 'package:thunder/post/enums/post_card_metadata_item.dart'; import 'package:thunder/shared/avatars/community_avatar.dart'; import 'package:thunder/shared/icon_text.dart'; import 'package:thunder/shared/text/scalable_text.dart'; @@ -14,6 +15,11 @@ import 'package:thunder/utils/date_time.dart'; import 'package:thunder/utils/instance.dart'; import 'package:thunder/utils/navigate_user.dart'; import 'package:thunder/utils/numbers.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +const Color upVoteColor = Colors.orange; +const Color downVoteColor = Colors.blue; +Color readColor = Colors.grey.shade700; class PostCardMetaData extends StatelessWidget { final int score; @@ -112,6 +118,205 @@ class PostCardMetaData extends StatelessWidget { } } +/// Contains metadata related to a given post. This is generally displayed as part of the post card. +/// +/// This information is customizable, and can be changed by the user in the settings. +/// The order in which the items are displayed depends on the order in the [postCardMetadataItems] list +class PostCardMetadata extends StatelessWidget { + /// The score of the post. If null, no score will be displayed. + final int? score; + + /// The number of upvotes on the post. If null, no upvote count will be displayed. + final int? upvoteCount; + + /// The number of downvotes on the post. If null, no downvote count will be displayed. + final int? downvoteCount; + + /// The vote for the post. This should be either 0, 1 or -1. Defaults to 0 if not specified. + /// When specified, this will change the color of the upvote/downvote/score icons. + final int? voteType; + + /// The number of comments on the post. If null, no comment count will be displayed. + final int? commentCount; + + /// The date/time the post was created or updated. This string should conform to ISO-8601 format. + final String? dateTime; + + /// Whether or not the post has been edited. This determines the icon for the [dateTime] field. + final bool? hasBeenEdited; + + /// Whether or not the post has been read. This is passed down to the individual [PostCardMetadataItem] widgets to determine the color. + final bool? hasBeenRead; + + /// The URL to display in the metadata. If null, no URL will be displayed. + final String? url; + + const PostCardMetadata({ + super.key, + this.score, + this.upvoteCount, + this.downvoteCount, + this.voteType = 0, + this.commentCount, + this.dateTime, + this.hasBeenEdited = false, + this.hasBeenRead = false, + this.url, + }); + + @override + Widget build(BuildContext context) { + final state = context.watch().state; + final showScores = state.getSiteResponse?.myUser?.localUserView.localUser.showScores ?? true; + + List postCardMetadataItems = [ + PostCardMetadataItem.score, + PostCardMetadataItem.upvote, + PostCardMetadataItem.downvote, + PostCardMetadataItem.commentCount, + PostCardMetadataItem.dateTime, + PostCardMetadataItem.url, + ]; + + return Wrap( + spacing: 8.0, + children: postCardMetadataItems.map( + (PostCardMetadataItem postCardMetadataItem) { + return switch (postCardMetadataItem) { + PostCardMetadataItem.score => showScores ? ScorePostCardMetaData(score: score, voteType: voteType, hasBeenRead: hasBeenRead ?? false) : Container(), + PostCardMetadataItem.upvote => showScores ? UpvotePostCardMetaData(upvotes: upvoteCount, isUpvoted: voteType == 1, hasBeenRead: hasBeenRead ?? false) : Container(), + PostCardMetadataItem.downvote => showScores ? DownvotePostCardMetaData(downvotes: downvoteCount, isDownvoted: voteType == -1, hasBeenRead: hasBeenRead ?? false) : Container(), + PostCardMetadataItem.commentCount => Container(), + PostCardMetadataItem.dateTime => Container(), + PostCardMetadataItem.url => Container(), + }; + }, + ).toList(), + ); + } +} + +/// Contains metadata related to the score of a given post. This is used in the [PostCardMetadata] widget. +class ScorePostCardMetaData extends StatelessWidget { + /// The score of the post. Defaults to 0 if not specified. + final int? score; + + /// The vote for the post. This should be either 0, 1 or -1. Defaults to 0 if not specified. + final int? voteType; + + /// Whether or not the post has been read. This is used to determine the color. + final bool hasBeenRead; + + const ScorePostCardMetaData({ + super.key, + this.score = 0, + this.voteType = 0, + this.hasBeenRead = false, + }); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + final l10n = AppLocalizations.of(context)!; + final state = context.read().state; + + final color = switch (voteType) { + 1 => upVoteColor, + -1 => downVoteColor, + _ => hasBeenRead ? readColor : null, + }; + + return Wrap( + spacing: 2.0, + crossAxisAlignment: WrapCrossAlignment.center, + children: [ + Icon(Icons.arrow_upward, size: 20.0, color: color), + ScalableText( + formatNumberToK(score ?? 0), + semanticsLabel: l10n.xScore(formatNumberToK(score ?? 0)), + fontScale: state.metadataFontSizeScale, + style: theme.textTheme.bodyMedium?.copyWith(color: color), + ), + Icon(Icons.arrow_downward, size: 20.0, color: color), + ], + ); + } +} + +/// Contains metadata related to the upvotes of a given post. This is used in the [PostCardMetadata] widget. +class UpvotePostCardMetaData extends StatelessWidget { + /// The number of upvotes on the post. Defaults to 0 if not specified. + final int? upvotes; + + /// Whether or not the post has been upvoted. Defaults to false if not specified. + final bool? isUpvoted; + + /// Whether or not the post has been read. This is used to determine the color. + final bool hasBeenRead; + + const UpvotePostCardMetaData({ + super.key, + this.upvotes = 0, + this.isUpvoted = false, + this.hasBeenRead = false, + }); + + @override + Widget build(BuildContext context) { + final state = context.read().state; + + final color = switch (isUpvoted) { + true => upVoteColor, + _ => hasBeenRead ? readColor : null, + }; + + return IconText( + fontScale: state.metadataFontSizeScale, + text: formatNumberToK(upvotes ?? 0), + textColor: color, + padding: 2.0, + icon: Icon(Icons.arrow_upward, size: 20.0, color: color), + ); + } +} + +/// Contains metadata related to the downvotes of a given post. This is used in the [PostCardMetadata] widget. +class DownvotePostCardMetaData extends StatelessWidget { + /// The number of downvotes on the post. Defaults to 0 if not specified. + final int? downvotes; + + /// Whether or not the post has been downvoted. Defaults to false if not specified. + final bool? isDownvoted; + + /// Whether or not the post has been read. This is used to determine the color. + final bool hasBeenRead; + + const DownvotePostCardMetaData({ + super.key, + this.downvotes = 0, + this.isDownvoted = false, + this.hasBeenRead = false, + }); + + @override + Widget build(BuildContext context) { + final state = context.read().state; + + final color = switch (isDownvoted) { + true => downVoteColor, + _ => hasBeenRead ? readColor : null, + }; + + return IconText( + fontScale: state.metadataFontSizeScale, + text: formatNumberToK(downvotes ?? 0), + textColor: color, + padding: 2.0, + icon: Icon(Icons.arrow_downward, size: 20.0, color: color), + ); + } +} + class PostViewMetaData extends StatelessWidget { final int unreadComments; final int comments; diff --git a/lib/community/widgets/post_card_view_compact.dart b/lib/community/widgets/post_card_view_compact.dart index 13729ebfb..7567208bf 100644 --- a/lib/community/widgets/post_card_view_compact.dart +++ b/lib/community/widgets/post_card_view_compact.dart @@ -129,16 +129,27 @@ class PostCardViewCompact extends StatelessWidget { showCommunitySubscription: showCommunitySubscription, ), const SizedBox(height: 6.0), - PostCardMetaData( - readColor: readColor, + PostCardMetadata( score: postViewMedia.postView.counts.score, + upvoteCount: postViewMedia.postView.counts.upvotes, + downvoteCount: postViewMedia.postView.counts.downvotes, voteType: postViewMedia.postView.myVote ?? 0, - comments: postViewMedia.postView.counts.comments, - unreadComments: postViewMedia.postView.unreadComments, + commentCount: postViewMedia.postView.counts.comments, + dateTime: postViewMedia.postView.post.updated != null ? postViewMedia.postView.post.updated?.toIso8601String() : postViewMedia.postView.post.published.toIso8601String(), hasBeenEdited: postViewMedia.postView.post.updated != null ? true : false, - published: postViewMedia.postView.post.updated != null ? postViewMedia.postView.post.updated! : postViewMedia.postView.post.published, - hostURL: postViewMedia.media.firstOrNull != null ? postViewMedia.media.first.originalUrl : null, - ), + url: postViewMedia.media.firstOrNull != null ? postViewMedia.media.first.originalUrl : null, + ) + + // PostCardMetaData( + // readColor: readColor, + // score: postViewMedia.postView.counts.score, + // voteType: postViewMedia.postView.myVote ?? 0, + // comments: postViewMedia.postView.counts.comments, + // unreadComments: postViewMedia.postView.unreadComments, + // hasBeenEdited: postViewMedia.postView.post.updated != null ? true : false, + // published: postViewMedia.postView.post.updated != null ? postViewMedia.postView.post.updated! : postViewMedia.postView.post.published, + // hostURL: postViewMedia.media.firstOrNull != null ? postViewMedia.media.first.originalUrl : null, + // ), ], ), ), diff --git a/lib/post/enums/post_card_metadata_item.dart b/lib/post/enums/post_card_metadata_item.dart new file mode 100644 index 000000000..289ee57e7 --- /dev/null +++ b/lib/post/enums/post_card_metadata_item.dart @@ -0,0 +1 @@ +enum PostCardMetadataItem { upvote, downvote, score, commentCount, dateTime, url } From 7c48f0336324f35fdf44f079b83febded46d31c3 Mon Sep 17 00:00:00 2001 From: Hamlet Jiang Su Date: Sat, 20 Jan 2024 10:01:40 -0800 Subject: [PATCH 02/11] added datetime and url widgets --- lib/community/widgets/post_card_metadata.dart | 135 ++++++++++++++++-- .../widgets/post_card_view_compact.dart | 14 +- 2 files changed, 126 insertions(+), 23 deletions(-) diff --git a/lib/community/widgets/post_card_metadata.dart b/lib/community/widgets/post_card_metadata.dart index ffc59f7d3..e6e8c1b2c 100644 --- a/lib/community/widgets/post_card_metadata.dart +++ b/lib/community/widgets/post_card_metadata.dart @@ -1,7 +1,8 @@ import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:lemmy_api_client/v3.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:thunder/core/auth/bloc/auth_bloc.dart'; import 'package:thunder/core/enums/full_name_separator.dart'; @@ -15,12 +16,12 @@ import 'package:thunder/utils/date_time.dart'; import 'package:thunder/utils/instance.dart'; import 'package:thunder/utils/navigate_user.dart'; import 'package:thunder/utils/numbers.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; const Color upVoteColor = Colors.orange; const Color downVoteColor = Colors.blue; Color readColor = Colors.grey.shade700; +@Deprecated("Use [PostViewMetaData] instead") class PostCardMetaData extends StatelessWidget { final int score; final int voteType; @@ -171,8 +172,8 @@ class PostCardMetadata extends StatelessWidget { List postCardMetadataItems = [ PostCardMetadataItem.score, - PostCardMetadataItem.upvote, - PostCardMetadataItem.downvote, + // PostCardMetadataItem.upvote, + // PostCardMetadataItem.downvote, PostCardMetadataItem.commentCount, PostCardMetadataItem.dateTime, PostCardMetadataItem.url, @@ -180,15 +181,16 @@ class PostCardMetadata extends StatelessWidget { return Wrap( spacing: 8.0, + crossAxisAlignment: WrapCrossAlignment.center, children: postCardMetadataItems.map( (PostCardMetadataItem postCardMetadataItem) { return switch (postCardMetadataItem) { PostCardMetadataItem.score => showScores ? ScorePostCardMetaData(score: score, voteType: voteType, hasBeenRead: hasBeenRead ?? false) : Container(), PostCardMetadataItem.upvote => showScores ? UpvotePostCardMetaData(upvotes: upvoteCount, isUpvoted: voteType == 1, hasBeenRead: hasBeenRead ?? false) : Container(), PostCardMetadataItem.downvote => showScores ? DownvotePostCardMetaData(downvotes: downvoteCount, isDownvoted: voteType == -1, hasBeenRead: hasBeenRead ?? false) : Container(), - PostCardMetadataItem.commentCount => Container(), - PostCardMetadataItem.dateTime => Container(), - PostCardMetadataItem.url => Container(), + PostCardMetadataItem.commentCount => CommentCountPostCardMetaData(commentCount: commentCount, hasBeenRead: hasBeenRead ?? false), + PostCardMetadataItem.dateTime => DateTimePostCardMetaData(dateTime: dateTime!, hasBeenRead: hasBeenRead ?? false, hasBeenEdited: hasBeenEdited ?? false), + PostCardMetadataItem.url => UrlPostCardMetaData(url: url, hasBeenRead: hasBeenRead ?? false), }; }, ).toList(), @@ -230,14 +232,14 @@ class ScorePostCardMetaData extends StatelessWidget { spacing: 2.0, crossAxisAlignment: WrapCrossAlignment.center, children: [ - Icon(Icons.arrow_upward, size: 20.0, color: color), + Icon(Icons.arrow_upward, size: 17.0, color: color), ScalableText( formatNumberToK(score ?? 0), semanticsLabel: l10n.xScore(formatNumberToK(score ?? 0)), fontScale: state.metadataFontSizeScale, style: theme.textTheme.bodyMedium?.copyWith(color: color), ), - Icon(Icons.arrow_downward, size: 20.0, color: color), + Icon(Icons.arrow_downward, size: 17.0, color: color), ], ); } @@ -275,7 +277,7 @@ class UpvotePostCardMetaData extends StatelessWidget { text: formatNumberToK(upvotes ?? 0), textColor: color, padding: 2.0, - icon: Icon(Icons.arrow_upward, size: 20.0, color: color), + icon: Icon(Icons.arrow_upward, size: 17.0, color: color), ); } } @@ -312,7 +314,118 @@ class DownvotePostCardMetaData extends StatelessWidget { text: formatNumberToK(downvotes ?? 0), textColor: color, padding: 2.0, - icon: Icon(Icons.arrow_downward, size: 20.0, color: color), + icon: Icon(Icons.arrow_downward, size: 17.0, color: color), + ); + } +} + +/// Contains metadata related to the number of comments for a given post. This is used in the [PostCardMetadata] widget. +class CommentCountPostCardMetaData extends StatelessWidget { + /// The number of comments on the post. Defaults to 0 if not specified. + final int? commentCount; + + /// Whether or not the post has been read. This is used to determine the color. + final bool hasBeenRead; + + const CommentCountPostCardMetaData({ + super.key, + this.commentCount = 0, + this.hasBeenRead = false, + }); + + @override + Widget build(BuildContext context) { + final state = context.read().state; + + final color = switch (hasBeenRead) { + true => readColor, + _ => null, + }; + + return IconText( + fontScale: state.metadataFontSizeScale, + text: formatNumberToK(commentCount ?? 0), + textColor: color, + padding: 5.0, + icon: Icon(Icons.chat_rounded, size: 17.0, color: color), + ); + } +} + +/// Contains metadata related to the number of comments for a given post. This is used in the [PostCardMetadata] widget. +class DateTimePostCardMetaData extends StatelessWidget { + /// The date/time the post was created or updated. This string should conform to ISO-8601 format. + final String dateTime; + + /// Whether or not the post has been read. This is used to determine the color. + final bool hasBeenRead; + + /// Whether or not the post has been edited. This determines the icon for the [dateTime] field. + final bool hasBeenEdited; + + const DateTimePostCardMetaData({ + super.key, + required this.dateTime, + this.hasBeenRead = false, + this.hasBeenEdited = false, + }); + + @override + Widget build(BuildContext context) { + final state = context.read().state; + + final color = switch (hasBeenRead) { + true => readColor, + _ => null, + }; + + return IconText( + fontScale: state.metadataFontSizeScale, + text: formatTimeToString(dateTime: dateTime), + textColor: color, + padding: 2.0, + icon: Icon(hasBeenEdited ? Icons.edit : Icons.history_rounded, size: 17.0, color: color), + ); + } +} + +/// Contains metadata related to the url/external link for a given post. This is used in the [PostCardMetadata] widget. +class UrlPostCardMetaData extends StatelessWidget { + /// The URL to display in the metadata. If null, no URL will be displayed. + final String? url; + + /// Whether or not the post has been read. This is used to determine the color. + final bool hasBeenRead; + + const UrlPostCardMetaData({ + super.key, + this.url, + this.hasBeenRead = false, + }); + + @override + Widget build(BuildContext context) { + final state = context.read().state; + + final color = switch (hasBeenRead) { + true => readColor, + _ => null, + }; + + if (url == null || url!.isEmpty == true) { + return Container(); + } + + return Tooltip( + message: url, + preferBelow: false, + child: IconText( + fontScale: state.metadataFontSizeScale, + text: Uri.parse(url ?? '').host.replaceFirst('www.', ''), + textColor: color, + padding: 3.0, + icon: Icon(Icons.public, size: 17.0, color: color), + ), ); } } diff --git a/lib/community/widgets/post_card_view_compact.dart b/lib/community/widgets/post_card_view_compact.dart index 7567208bf..779037aa9 100644 --- a/lib/community/widgets/post_card_view_compact.dart +++ b/lib/community/widgets/post_card_view_compact.dart @@ -138,18 +138,8 @@ class PostCardViewCompact extends StatelessWidget { dateTime: postViewMedia.postView.post.updated != null ? postViewMedia.postView.post.updated?.toIso8601String() : postViewMedia.postView.post.published.toIso8601String(), hasBeenEdited: postViewMedia.postView.post.updated != null ? true : false, url: postViewMedia.media.firstOrNull != null ? postViewMedia.media.first.originalUrl : null, - ) - - // PostCardMetaData( - // readColor: readColor, - // score: postViewMedia.postView.counts.score, - // voteType: postViewMedia.postView.myVote ?? 0, - // comments: postViewMedia.postView.counts.comments, - // unreadComments: postViewMedia.postView.unreadComments, - // hasBeenEdited: postViewMedia.postView.post.updated != null ? true : false, - // published: postViewMedia.postView.post.updated != null ? postViewMedia.postView.post.updated! : postViewMedia.postView.post.published, - // hostURL: postViewMedia.media.firstOrNull != null ? postViewMedia.media.first.originalUrl : null, - // ), + hasBeenRead: indicateRead && postViewMedia.postView.read, + ), ], ), ), From 93d6804b8a661178bf345df5016f416dc1738dc1 Mon Sep 17 00:00:00 2001 From: Hamlet Jiang Su Date: Mon, 22 Jan 2024 09:39:12 -0800 Subject: [PATCH 03/11] added setting to customize post metadata --- lib/community/widgets/post_card_metadata.dart | 10 +- lib/core/enums/local_settings.dart | 1 + .../pages/post_appearance_settings_page.dart | 205 ++++++++++++++++++ lib/thunder/bloc/thunder_bloc.dart | 4 + lib/thunder/bloc/thunder_state.dart | 5 + lib/utils/constants.dart | 9 + 6 files changed, 226 insertions(+), 8 deletions(-) diff --git a/lib/community/widgets/post_card_metadata.dart b/lib/community/widgets/post_card_metadata.dart index e6e8c1b2c..46cf4e9fb 100644 --- a/lib/community/widgets/post_card_metadata.dart +++ b/lib/community/widgets/post_card_metadata.dart @@ -170,14 +170,7 @@ class PostCardMetadata extends StatelessWidget { final state = context.watch().state; final showScores = state.getSiteResponse?.myUser?.localUserView.localUser.showScores ?? true; - List postCardMetadataItems = [ - PostCardMetadataItem.score, - // PostCardMetadataItem.upvote, - // PostCardMetadataItem.downvote, - PostCardMetadataItem.commentCount, - PostCardMetadataItem.dateTime, - PostCardMetadataItem.url, - ]; + List postCardMetadataItems = context.read().state.compactPostCardMetadataItems; return Wrap( spacing: 8.0, @@ -231,6 +224,7 @@ class ScorePostCardMetaData extends StatelessWidget { return Wrap( spacing: 2.0, crossAxisAlignment: WrapCrossAlignment.center, + runAlignment: WrapAlignment.center, children: [ Icon(Icons.arrow_upward, size: 17.0, color: color), ScalableText( diff --git a/lib/core/enums/local_settings.dart b/lib/core/enums/local_settings.dart index cbce040f4..eef5b2a5f 100644 --- a/lib/core/enums/local_settings.dart +++ b/lib/core/enums/local_settings.dart @@ -46,6 +46,7 @@ enum LocalSettings { showCrossPosts(name: 'setting_show_cross_posts', key: 'showCrossPosts'), keywordFilters(name: 'setting_general_keyword_filters', key: 'keywordFilters'), hideTopBarOnScroll(name: 'setting_general_hide_topbar_on_scroll', key: 'hideTopBarOnScroll'), + compactPostCardMetadataItems(name: 'setting_compact_post_card_metadata_items', key: 'compactPostCardMetadataItems'), // Advanced Settings userFormat(name: 'user_format', key: 'userFormat'), diff --git a/lib/settings/pages/post_appearance_settings_page.dart b/lib/settings/pages/post_appearance_settings_page.dart index f01b32595..d34bd1bb2 100644 --- a/lib/settings/pages/post_appearance_settings_page.dart +++ b/lib/settings/pages/post_appearance_settings_page.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:lemmy_api_client/v3.dart'; import 'package:expandable/expandable.dart'; @@ -13,11 +14,14 @@ import 'package:thunder/core/enums/post_body_view_type.dart'; import 'package:thunder/core/models/post_view_media.dart'; import 'package:thunder/core/singletons/preferences.dart'; import 'package:thunder/feed/utils/post.dart'; +import 'package:thunder/post/enums/post_card_metadata_item.dart'; import 'package:thunder/settings/widgets/list_option.dart'; import 'package:thunder/settings/widgets/toggle_option.dart'; import 'package:thunder/shared/dialogs.dart'; import 'package:thunder/thunder/bloc/thunder_bloc.dart'; import 'package:thunder/utils/bottom_sheet_list_picker.dart'; +import 'package:thunder/community/widgets/post_card_metadata.dart'; +import 'package:thunder/utils/constants.dart'; class PostAppearanceSettingsPage extends StatefulWidget { const PostAppearanceSettingsPage({super.key}); @@ -78,6 +82,10 @@ class _PostAppearanceSettingsPageState extends State /// Determines how post bodies are displayed PostBodyViewType postBodyViewType = PostBodyViewType.expanded; + /// List of compact post card metadata items to show on the post card + /// The order of the items is important as they will be displayed in that order + List compactPostCardMetadataItems = []; + /// Initialize the settings from the user's shared preferences Future initPreferences() async { final prefs = (await UserPreferences.instance).sharedPreferences; @@ -91,6 +99,8 @@ class _PostAppearanceSettingsPageState extends State dimReadPosts = prefs.getBool(LocalSettings.dimReadPosts.name) ?? true; // Compact View Settings + compactPostCardMetadataItems = + prefs.getStringList(LocalSettings.compactPostCardMetadataItems.name)?.map((e) => PostCardMetadataItem.values.byName(e)).toList() ?? DEFAULT_COMPACT_POST_CARD_METADATA; showThumbnailPreviewOnRight = prefs.getBool(LocalSettings.showThumbnailPreviewOnRight.name) ?? false; showTextPostIndicator = prefs.getBool(LocalSettings.showTextPostIndicator.name) ?? false; @@ -135,6 +145,9 @@ class _PostAppearanceSettingsPageState extends State setState(() => dimReadPosts = value); break; + case LocalSettings.compactPostCardMetadataItems: + await prefs.setStringList(LocalSettings.compactPostCardMetadataItems.name, value); + break; case LocalSettings.showThumbnailPreviewOnRight: await prefs.setBool(LocalSettings.showThumbnailPreviewOnRight.name, value); setState(() => showThumbnailPreviewOnRight = value); @@ -196,6 +209,7 @@ class _PostAppearanceSettingsPageState extends State await prefs.remove(LocalSettings.showPostAuthor.name); await prefs.remove(LocalSettings.useDisplayNamesForUsers.name); await prefs.remove(LocalSettings.dimReadPosts.name); + await prefs.remove(LocalSettings.compactPostCardMetadataItems.name); await prefs.remove(LocalSettings.showThumbnailPreviewOnRight.name); await prefs.remove(LocalSettings.showTextPostIndicator.name); await prefs.remove(LocalSettings.showPostTitleFirst.name); @@ -476,6 +490,13 @@ class _PostAppearanceSettingsPageState extends State Text(l10n.compactViewSettings, style: theme.textTheme.titleMedium), Text( l10n.compactViewDescription, + style: theme.textTheme.bodyMedium?.copyWith( + color: theme.textTheme.bodyMedium?.color?.withOpacity(0.6), + ), + ), + const SizedBox(height: 8.0), + Text( + 'You can customize the metadata information by dragging and dropping the desired information', style: theme.textTheme.bodyMedium?.copyWith( color: theme.textTheme.bodyMedium?.color?.withOpacity(0.8), ), @@ -484,6 +505,109 @@ class _PostAppearanceSettingsPageState extends State ), ), ), + SliverToBoxAdapter( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: Container( + padding: const EdgeInsets.only(bottom: 8.0, top: 6), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + !showThumbnailPreviewOnRight + ? Container( + width: 75, + height: 75, + margin: const EdgeInsets.only(right: 8.0), + decoration: BoxDecoration( + color: theme.dividerColor, + borderRadius: BorderRadius.circular((showEdgeToEdgeImages ? 0 : 12)), + ), + ) + : const SizedBox(width: 0), + Expanded( + child: Padding( + padding: EdgeInsets.only(right: showThumbnailPreviewOnRight ? 8.0 : 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: MediaQuery.of(context).size.width, + height: 25, + decoration: BoxDecoration( + color: theme.dividerColor, + borderRadius: BorderRadius.circular((showEdgeToEdgeImages ? 0 : 12)), + ), + ), // Title + const SizedBox(height: 6.0), + Container( + width: MediaQuery.of(context).size.width * 0.5, + height: 15, + decoration: BoxDecoration( + color: theme.dividerColor, + borderRadius: BorderRadius.circular((showEdgeToEdgeImages ? 0 : 12)), + ), + ), + const SizedBox(height: 6.0), + PostCardMetadataDraggableTarget( + containedPostCardMetadataItems: compactPostCardMetadataItems, + onAcceptedData: (data) { + setState(() { + compactPostCardMetadataItems.add(data); + setPreferences(LocalSettings.compactPostCardMetadataItems, compactPostCardMetadataItems.map((e) => e.name).toList()); + }); + }, + ), + ], + ), + ), + ), + showThumbnailPreviewOnRight + ? Container( + width: 75, + height: 75, + margin: const EdgeInsets.only(right: 8.0), + decoration: BoxDecoration( + color: theme.dividerColor, + borderRadius: BorderRadius.circular((showEdgeToEdgeImages ? 0 : 12)), + ), + ) + : const SizedBox(width: 0), + ], + ), + ), + ), + ), + SliverToBoxAdapter( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Available metadata widgets', + style: theme.textTheme.bodyMedium?.copyWith( + color: theme.textTheme.bodyMedium?.color?.withOpacity(0.9), + ), + ), + ], + ), + ), + ), + SliverToBoxAdapter( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: PostCardMetadataDraggableTarget( + containedPostCardMetadataItems: PostCardMetadataItem.values.where((element) => !compactPostCardMetadataItems.contains(element)).toList(), + onAcceptedData: (data) { + setState(() { + compactPostCardMetadataItems.remove(data); + setPreferences(LocalSettings.compactPostCardMetadataItems, compactPostCardMetadataItems.map((e) => e.name).toList()); + }); + }, + ), + ), + ), + const SliverToBoxAdapter(child: SizedBox(height: 16.0)), SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), @@ -668,3 +792,84 @@ class _PostAppearanceSettingsPageState extends State ); } } + +/// A draggable target for the post card metadata. +/// +/// Held in this draggable target is a list of [PostCardMetadataItem]s. Each of these items can be dragged outside the target. +class PostCardMetadataDraggableTarget extends StatelessWidget { + /// The items contained in the target + final List containedPostCardMetadataItems; + + /// Callback when data is accepted + final void Function(PostCardMetadataItem) onAcceptedData; + + const PostCardMetadataDraggableTarget({ + super.key, + required this.containedPostCardMetadataItems, + required this.onAcceptedData, + }); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + return SizedBox( + width: MediaQuery.of(context).size.width, + child: DragTarget( + builder: (context, candidateData, rejectedData) => containedPostCardMetadataItems.isEmpty + ? Container( + height: 50, + decoration: BoxDecoration( + border: Border.all(color: theme.dividerColor), + borderRadius: BorderRadius.circular(8), + ), + ) + : Wrap( + spacing: 8.0, + runSpacing: 8.0, + children: containedPostCardMetadataItems + .map( + (item) => Draggable( + data: item, + feedback: buildDraggableItem(context, item: item, isFeedback: true), + child: buildDraggableItem(context, item: item), + ), + ) + .toList(), + ), + onWillAccept: (data) { + if (!containedPostCardMetadataItems.contains(data)) return true; + return false; + }, + onAccept: (data) { + onAcceptedData(data); + }, + ), + ); + } + + Widget buildDraggableItem(context, {required PostCardMetadataItem item, bool isFeedback = false}) { + final theme = Theme.of(context); + + if (isFeedback) HapticFeedback.mediumImpact(); + + return Material( + type: MaterialType.transparency, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0), + decoration: BoxDecoration( + color: theme.dividerColor, + borderRadius: BorderRadius.circular(8), + ), + child: switch (item) { + PostCardMetadataItem.score => const ScorePostCardMetaData(score: 1222), + PostCardMetadataItem.commentCount => const CommentCountPostCardMetaData(commentCount: 4124), + PostCardMetadataItem.dateTime => DateTimePostCardMetaData(dateTime: DateTime.now().toIso8601String()), + PostCardMetadataItem.url => const UrlPostCardMetaData(url: 'https://github.com/thunder-app/thunder'), + PostCardMetadataItem.upvote => const UpvotePostCardMetaData(upvotes: 2412), + PostCardMetadataItem.downvote => const DownvotePostCardMetaData(downvotes: 532), + }, + ), + ); + } +} diff --git a/lib/thunder/bloc/thunder_bloc.dart b/lib/thunder/bloc/thunder_bloc.dart index a28bcf7f3..211e6d83a 100644 --- a/lib/thunder/bloc/thunder_bloc.dart +++ b/lib/thunder/bloc/thunder_bloc.dart @@ -20,6 +20,7 @@ import 'package:thunder/core/models/version.dart'; import 'package:thunder/core/singletons/lemmy_client.dart'; import 'package:thunder/core/singletons/preferences.dart'; import 'package:thunder/core/update/check_github_update.dart'; +import 'package:thunder/post/enums/post_card_metadata_item.dart'; import 'package:thunder/utils/constants.dart'; part 'thunder_event.dart'; @@ -138,6 +139,8 @@ class ThunderBloc extends Bloc { bool dimReadPosts = prefs.getBool(LocalSettings.dimReadPosts.name) ?? true; bool useAdvancedShareSheet = prefs.getBool(LocalSettings.useAdvancedShareSheet.name) ?? true; bool showCrossPosts = prefs.getBool(LocalSettings.showCrossPosts.name) ?? true; + List compactPostCardMetadataItems = + prefs.getStringList(LocalSettings.compactPostCardMetadataItems.name)?.map((e) => PostCardMetadataItem.values.byName(e)).toList() ?? DEFAULT_COMPACT_POST_CARD_METADATA; List keywordFilters = prefs.getStringList(LocalSettings.keywordFilters.name) ?? []; @@ -268,6 +271,7 @@ class ThunderBloc extends Bloc { dimReadPosts: dimReadPosts, useAdvancedShareSheet: useAdvancedShareSheet, showCrossPosts: showCrossPosts, + compactPostCardMetadataItems: compactPostCardMetadataItems, keywordFilters: keywordFilters, /// -------------------------- Post Page Related Settings -------------------------- diff --git a/lib/thunder/bloc/thunder_state.dart b/lib/thunder/bloc/thunder_state.dart index 4c25f61db..6be1e1413 100644 --- a/lib/thunder/bloc/thunder_state.dart +++ b/lib/thunder/bloc/thunder_state.dart @@ -56,6 +56,7 @@ class ThunderState extends Equatable { this.dimReadPosts = true, this.useAdvancedShareSheet = true, this.showCrossPosts = true, + this.compactPostCardMetadataItems = const [], this.keywordFilters = const [], this.appLanguageCode = 'en', @@ -185,6 +186,7 @@ class ThunderState extends Equatable { final bool dimReadPosts; final bool useAdvancedShareSheet; final bool showCrossPosts; + final List compactPostCardMetadataItems; final List keywordFilters; /// -------------------------- Post Page Related Settings -------------------------- @@ -320,6 +322,7 @@ class ThunderState extends Equatable { bool? dimReadPosts, bool? useAdvancedShareSheet, bool? showCrossPosts, + List? compactPostCardMetadataItems, String? appLanguageCode = 'en', List? keywordFilters, @@ -449,6 +452,7 @@ class ThunderState extends Equatable { dimReadPosts: dimReadPosts ?? this.dimReadPosts, useAdvancedShareSheet: useAdvancedShareSheet ?? this.useAdvancedShareSheet, showCrossPosts: showCrossPosts ?? this.showCrossPosts, + compactPostCardMetadataItems: compactPostCardMetadataItems ?? this.compactPostCardMetadataItems, keywordFilters: keywordFilters ?? this.keywordFilters, /// -------------------------- Post Page Related Settings -------------------------- @@ -582,6 +586,7 @@ class ThunderState extends Equatable { dimReadPosts, useAdvancedShareSheet, showCrossPosts, + compactPostCardMetadataItems, appLanguageCode, keywordFilters, diff --git a/lib/utils/constants.dart b/lib/utils/constants.dart index fbf18b805..41b26a69c 100644 --- a/lib/utils/constants.dart +++ b/lib/utils/constants.dart @@ -1,5 +1,7 @@ import 'package:lemmy_api_client/v3.dart'; + import 'package:thunder/core/enums/nested_comment_indicator.dart'; +import 'package:thunder/post/enums/post_card_metadata_item.dart'; const ListingType DEFAULT_LISTING_TYPE = ListingType.all; @@ -19,3 +21,10 @@ const NestedCommentIndicatorColor DEFAULT_NESTED_COMMENT_INDICATOR_COLOR = Neste const int ANDROID_INTENT_FLAG_ACTIVITY_NEW_TASK = 268435456; const String ANDROID_INTENT_ACTION_VIEW = "android.intent.action.VIEW"; + +List DEFAULT_COMPACT_POST_CARD_METADATA = [ + PostCardMetadataItem.score, + PostCardMetadataItem.commentCount, + PostCardMetadataItem.dateTime, + PostCardMetadataItem.url, +]; From c686dec651c1b1935e69ed825b1caedbe8d1ae94 Mon Sep 17 00:00:00 2001 From: Hamlet Jiang Su Date: Mon, 22 Jan 2024 12:30:59 -0800 Subject: [PATCH 04/11] added ability to disable dragging post metadata when view is not the correct one --- .../pages/post_appearance_settings_page.dart | 240 ++++++++++-------- 1 file changed, 139 insertions(+), 101 deletions(-) diff --git a/lib/settings/pages/post_appearance_settings_page.dart b/lib/settings/pages/post_appearance_settings_page.dart index d34bd1bb2..0d32639db 100644 --- a/lib/settings/pages/post_appearance_settings_page.dart +++ b/lib/settings/pages/post_appearance_settings_page.dart @@ -278,6 +278,8 @@ class _PostAppearanceSettingsPageState extends State final ThemeData theme = Theme.of(context); final l10n = AppLocalizations.of(context)!; + print(useCompactView); + return Scaffold( body: CustomScrollView( slivers: [ @@ -508,73 +510,7 @@ class _PostAppearanceSettingsPageState extends State SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: Container( - padding: const EdgeInsets.only(bottom: 8.0, top: 6), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - !showThumbnailPreviewOnRight - ? Container( - width: 75, - height: 75, - margin: const EdgeInsets.only(right: 8.0), - decoration: BoxDecoration( - color: theme.dividerColor, - borderRadius: BorderRadius.circular((showEdgeToEdgeImages ? 0 : 12)), - ), - ) - : const SizedBox(width: 0), - Expanded( - child: Padding( - padding: EdgeInsets.only(right: showThumbnailPreviewOnRight ? 8.0 : 0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - width: MediaQuery.of(context).size.width, - height: 25, - decoration: BoxDecoration( - color: theme.dividerColor, - borderRadius: BorderRadius.circular((showEdgeToEdgeImages ? 0 : 12)), - ), - ), // Title - const SizedBox(height: 6.0), - Container( - width: MediaQuery.of(context).size.width * 0.5, - height: 15, - decoration: BoxDecoration( - color: theme.dividerColor, - borderRadius: BorderRadius.circular((showEdgeToEdgeImages ? 0 : 12)), - ), - ), - const SizedBox(height: 6.0), - PostCardMetadataDraggableTarget( - containedPostCardMetadataItems: compactPostCardMetadataItems, - onAcceptedData: (data) { - setState(() { - compactPostCardMetadataItems.add(data); - setPreferences(LocalSettings.compactPostCardMetadataItems, compactPostCardMetadataItems.map((e) => e.name).toList()); - }); - }, - ), - ], - ), - ), - ), - showThumbnailPreviewOnRight - ? Container( - width: 75, - height: 75, - margin: const EdgeInsets.only(right: 8.0), - decoration: BoxDecoration( - color: theme.dividerColor, - borderRadius: BorderRadius.circular((showEdgeToEdgeImages ? 0 : 12)), - ), - ) - : const SizedBox(width: 0), - ], - ), - ), + child: buildCompactViewMetadataPreview(isDisabled: useCompactView == false), ), ), SliverToBoxAdapter( @@ -597,6 +533,7 @@ class _PostAppearanceSettingsPageState extends State child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), child: PostCardMetadataDraggableTarget( + isDisabled: useCompactView == false, containedPostCardMetadataItems: PostCardMetadataItem.values.where((element) => !compactPostCardMetadataItems.contains(element)).toList(), onAcceptedData: (data) { setState(() { @@ -791,6 +728,81 @@ class _PostAppearanceSettingsPageState extends State ), ); } + + Widget buildCompactViewMetadataPreview({bool isDisabled = false}) { + final theme = Theme.of(context); + + return Container( + padding: const EdgeInsets.only(bottom: 8.0, top: 6), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + !showThumbnailPreviewOnRight + ? Container( + width: 75, + height: 75, + margin: const EdgeInsets.only(right: 8.0), + decoration: BoxDecoration( + color: theme.dividerColor, + borderRadius: BorderRadius.circular((showEdgeToEdgeImages ? 0 : 12)), + ), + ) + : const SizedBox(width: 0), + Expanded( + child: Padding( + padding: EdgeInsets.only(right: showThumbnailPreviewOnRight ? 8.0 : 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: MediaQuery.of(context).size.width, + height: 25, + decoration: BoxDecoration( + color: theme.dividerColor, + borderRadius: BorderRadius.circular((showEdgeToEdgeImages ? 0 : 12)), + ), + ), // Title + const SizedBox(height: 6.0), + Container( + width: MediaQuery.of(context).size.width * 0.5, + height: 15, + decoration: BoxDecoration( + color: theme.dividerColor, + borderRadius: BorderRadius.circular((showEdgeToEdgeImages ? 0 : 12)), + ), + ), + const SizedBox(height: 6.0), + PostCardMetadataDraggableTarget( + isDisabled: useCompactView == false, + containerHeight: 25.0, + showEmptyTargetMessage: false, + containedPostCardMetadataItems: compactPostCardMetadataItems, + onAcceptedData: (data) { + setState(() { + compactPostCardMetadataItems.add(data); + setPreferences(LocalSettings.compactPostCardMetadataItems, compactPostCardMetadataItems.map((e) => e.name).toList()); + }); + }, + ), + ], + ), + ), + ), + showThumbnailPreviewOnRight + ? Container( + width: 75, + height: 75, + margin: const EdgeInsets.only(right: 8.0), + decoration: BoxDecoration( + color: theme.dividerColor, + borderRadius: BorderRadius.circular((showEdgeToEdgeImages ? 0 : 12)), + ), + ) + : const SizedBox(width: 0), + ], + ), + ); + } } /// A draggable target for the post card metadata. @@ -803,62 +815,88 @@ class PostCardMetadataDraggableTarget extends StatelessWidget { /// Callback when data is accepted final void Function(PostCardMetadataItem) onAcceptedData; + /// The height of the target container, when empty + final double containerHeight; + + /// Whether to display a message when the target is empty + final bool showEmptyTargetMessage; + + /// Whether the target is disabled + final bool isDisabled; + const PostCardMetadataDraggableTarget({ super.key, required this.containedPostCardMetadataItems, required this.onAcceptedData, + this.containerHeight = 50.0, + this.showEmptyTargetMessage = true, + this.isDisabled = false, }); @override Widget build(BuildContext context) { final theme = Theme.of(context); - return SizedBox( - width: MediaQuery.of(context).size.width, - child: DragTarget( - builder: (context, candidateData, rejectedData) => containedPostCardMetadataItems.isEmpty - ? Container( - height: 50, - decoration: BoxDecoration( - border: Border.all(color: theme.dividerColor), - borderRadius: BorderRadius.circular(8), + return AbsorbPointer( + absorbing: isDisabled, + child: SizedBox( + width: MediaQuery.of(context).size.width, + child: DragTarget( + builder: (context, candidateData, rejectedData) => containedPostCardMetadataItems.isEmpty + ? Container( + height: containerHeight, + decoration: BoxDecoration( + border: Border.all(color: theme.dividerColor), + borderRadius: BorderRadius.circular(8), + ), + child: Center( + child: Text( + showEmptyTargetMessage ? 'No items' : '', + style: TextStyle(color: theme.textTheme.bodyMedium?.color?.withOpacity(0.8)), + ), + ), + ) + : Container( + constraints: BoxConstraints(minHeight: containerHeight), + child: Wrap( + spacing: 8.0, + runSpacing: 8.0, + children: containedPostCardMetadataItems + .map( + (item) => Draggable( + data: item, + feedback: buildDraggableItem(context, item: item, isFeedback: true), + child: buildDraggableItem(context, item: item, isDisabled: isDisabled), + ), + ) + .toList(), + ), ), - ) - : Wrap( - spacing: 8.0, - runSpacing: 8.0, - children: containedPostCardMetadataItems - .map( - (item) => Draggable( - data: item, - feedback: buildDraggableItem(context, item: item, isFeedback: true), - child: buildDraggableItem(context, item: item), - ), - ) - .toList(), - ), - onWillAccept: (data) { - if (!containedPostCardMetadataItems.contains(data)) return true; - return false; - }, - onAccept: (data) { - onAcceptedData(data); - }, + onLeave: (data) => HapticFeedback.mediumImpact(), + onWillAccept: (data) { + if (!containedPostCardMetadataItems.contains(data)) { + return true; + } + return false; + }, + onAccept: (data) { + onAcceptedData(data); + }, + ), ), ); } - Widget buildDraggableItem(context, {required PostCardMetadataItem item, bool isFeedback = false}) { + Widget buildDraggableItem(context, {required PostCardMetadataItem item, bool isFeedback = false, bool isDisabled = false}) { final theme = Theme.of(context); - if (isFeedback) HapticFeedback.mediumImpact(); - return Material( type: MaterialType.transparency, child: Container( padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0), decoration: BoxDecoration( - color: theme.dividerColor, + color: isDisabled ? theme.cardColor : theme.dividerColor, + border: isDisabled ? Border.all(color: theme.dividerColor.withOpacity(0.4)) : null, borderRadius: BorderRadius.circular(8), ), child: switch (item) { From 5b1eb1d78b13d1d76f76a850788301a7dc3b3e73 Mon Sep 17 00:00:00 2001 From: Hamlet Jiang Su Date: Mon, 22 Jan 2024 14:01:06 -0800 Subject: [PATCH 05/11] added post card metadata customization --- lib/community/widgets/post_card_metadata.dart | 10 +- .../widgets/post_card_view_comfortable.dart | 27 ++- .../widgets/post_card_view_compact.dart | 1 + lib/core/enums/local_settings.dart | 1 + .../pages/post_appearance_settings_page.dart | 179 +++++++++++++++++- lib/thunder/bloc/thunder_bloc.dart | 3 + lib/thunder/bloc/thunder_state.dart | 5 + lib/utils/constants.dart | 7 + 8 files changed, 221 insertions(+), 12 deletions(-) diff --git a/lib/community/widgets/post_card_metadata.dart b/lib/community/widgets/post_card_metadata.dart index 16930e91e..f55f8b440 100644 --- a/lib/community/widgets/post_card_metadata.dart +++ b/lib/community/widgets/post_card_metadata.dart @@ -6,6 +6,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:thunder/core/auth/bloc/auth_bloc.dart'; import 'package:thunder/core/enums/full_name_separator.dart'; +import 'package:thunder/core/enums/view_mode.dart'; import 'package:thunder/feed/feed.dart'; import 'package:thunder/post/enums/post_card_metadata_item.dart'; import 'package:thunder/shared/avatars/community_avatar.dart'; @@ -124,6 +125,9 @@ class PostCardMetaData extends StatelessWidget { /// This information is customizable, and can be changed by the user in the settings. /// The order in which the items are displayed depends on the order in the [postCardMetadataItems] list class PostCardMetadata extends StatelessWidget { + /// The type of view the post card is in. This is used to determine the appropriate setting to read from. + final ViewMode postCardViewType; + /// The score of the post. If null, no score will be displayed. final int? score; @@ -154,6 +158,7 @@ class PostCardMetadata extends StatelessWidget { const PostCardMetadata({ super.key, + required this.postCardViewType, this.score, this.upvoteCount, this.downvoteCount, @@ -170,7 +175,10 @@ class PostCardMetadata extends StatelessWidget { final state = context.watch().state; final showScores = state.getSiteResponse?.myUser?.localUserView.localUser.showScores ?? true; - List postCardMetadataItems = context.read().state.compactPostCardMetadataItems; + List postCardMetadataItems = switch (postCardViewType) { + ViewMode.compact => context.read().state.compactPostCardMetadataItems, + ViewMode.comfortable => context.read().state.cardPostCardMetadataItems, + }; return Wrap( spacing: 8.0, diff --git a/lib/community/widgets/post_card_view_comfortable.dart b/lib/community/widgets/post_card_view_comfortable.dart index 8e8749f29..0641d38bb 100644 --- a/lib/community/widgets/post_card_view_comfortable.dart +++ b/lib/community/widgets/post_card_view_comfortable.dart @@ -11,6 +11,7 @@ import 'package:thunder/community/utils/post_card_action_helpers.dart'; import 'package:thunder/community/widgets/post_card_actions.dart'; import 'package:thunder/community/widgets/post_card_metadata.dart'; import 'package:thunder/core/enums/font_scale.dart'; +import 'package:thunder/core/enums/view_mode.dart'; import 'package:thunder/core/models/post_view_media.dart'; import 'package:thunder/core/theme/bloc/theme_bloc.dart'; import 'package:thunder/shared/media_view.dart'; @@ -255,16 +256,28 @@ class PostCardViewComfortable extends StatelessWidget { showCommunitySubscription: showCommunitySubscription, ), const SizedBox(height: 8.0), - PostCardMetaData( - readColor: readColor, - hostURL: postViewMedia.media.firstOrNull != null ? postViewMedia.media.first.originalUrl : null, + PostCardMetadata( + postCardViewType: ViewMode.comfortable, score: postViewMedia.postView.counts.score, + upvoteCount: postViewMedia.postView.counts.upvotes, + downvoteCount: postViewMedia.postView.counts.downvotes, voteType: postViewMedia.postView.myVote ?? 0, - comments: postViewMedia.postView.counts.comments, - unreadComments: postViewMedia.postView.unreadComments, + commentCount: postViewMedia.postView.counts.comments, + dateTime: postViewMedia.postView.post.updated != null ? postViewMedia.postView.post.updated?.toIso8601String() : postViewMedia.postView.post.published.toIso8601String(), hasBeenEdited: postViewMedia.postView.post.updated != null ? true : false, - published: postViewMedia.postView.post.updated != null ? postViewMedia.postView.post.updated! : postViewMedia.postView.post.published, - ) + url: postViewMedia.media.firstOrNull != null ? postViewMedia.media.first.originalUrl : null, + hasBeenRead: indicateRead && postViewMedia.postView.read, + ), + // PostCardMetaData( + // readColor: readColor, + // hostURL: postViewMedia.media.firstOrNull != null ? postViewMedia.media.first.originalUrl : null, + // score: postViewMedia.postView.counts.score, + // voteType: postViewMedia.postView.myVote ?? 0, + // comments: postViewMedia.postView.counts.comments, + // unreadComments: postViewMedia.postView.unreadComments, + // hasBeenEdited: postViewMedia.postView.post.updated != null ? true : false, + // published: postViewMedia.postView.post.updated != null ? postViewMedia.postView.post.updated! : postViewMedia.postView.post.published, + // ) ], ), ), diff --git a/lib/community/widgets/post_card_view_compact.dart b/lib/community/widgets/post_card_view_compact.dart index 779037aa9..f1dece259 100644 --- a/lib/community/widgets/post_card_view_compact.dart +++ b/lib/community/widgets/post_card_view_compact.dart @@ -130,6 +130,7 @@ class PostCardViewCompact extends StatelessWidget { ), const SizedBox(height: 6.0), PostCardMetadata( + postCardViewType: ViewMode.compact, score: postViewMedia.postView.counts.score, upvoteCount: postViewMedia.postView.counts.upvotes, downvoteCount: postViewMedia.postView.counts.downvotes, diff --git a/lib/core/enums/local_settings.dart b/lib/core/enums/local_settings.dart index eef5b2a5f..4ad50de94 100644 --- a/lib/core/enums/local_settings.dart +++ b/lib/core/enums/local_settings.dart @@ -47,6 +47,7 @@ enum LocalSettings { keywordFilters(name: 'setting_general_keyword_filters', key: 'keywordFilters'), hideTopBarOnScroll(name: 'setting_general_hide_topbar_on_scroll', key: 'hideTopBarOnScroll'), compactPostCardMetadataItems(name: 'setting_compact_post_card_metadata_items', key: 'compactPostCardMetadataItems'), + cardPostCardMetadataItems(name: 'setting_card_post_card_metadata_items', key: 'cardPostCardMetadataItems'), // Advanced Settings userFormat(name: 'user_format', key: 'userFormat'), diff --git a/lib/settings/pages/post_appearance_settings_page.dart b/lib/settings/pages/post_appearance_settings_page.dart index 0d32639db..3353cfd2c 100644 --- a/lib/settings/pages/post_appearance_settings_page.dart +++ b/lib/settings/pages/post_appearance_settings_page.dart @@ -18,6 +18,7 @@ import 'package:thunder/post/enums/post_card_metadata_item.dart'; import 'package:thunder/settings/widgets/list_option.dart'; import 'package:thunder/settings/widgets/toggle_option.dart'; import 'package:thunder/shared/dialogs.dart'; +import 'package:thunder/shared/text/scalable_text.dart'; import 'package:thunder/thunder/bloc/thunder_bloc.dart'; import 'package:thunder/utils/bottom_sheet_list_picker.dart'; import 'package:thunder/community/widgets/post_card_metadata.dart'; @@ -86,6 +87,10 @@ class _PostAppearanceSettingsPageState extends State /// The order of the items is important as they will be displayed in that order List compactPostCardMetadataItems = []; + /// List of card post card metadata items to show on the post card + /// The order of the items is important as they will be displayed in that order + List cardPostCardMetadataItems = []; + /// Initialize the settings from the user's shared preferences Future initPreferences() async { final prefs = (await UserPreferences.instance).sharedPreferences; @@ -101,6 +106,7 @@ class _PostAppearanceSettingsPageState extends State // Compact View Settings compactPostCardMetadataItems = prefs.getStringList(LocalSettings.compactPostCardMetadataItems.name)?.map((e) => PostCardMetadataItem.values.byName(e)).toList() ?? DEFAULT_COMPACT_POST_CARD_METADATA; + cardPostCardMetadataItems = prefs.getStringList(LocalSettings.cardPostCardMetadataItems.name)?.map((e) => PostCardMetadataItem.values.byName(e)).toList() ?? DEFAULT_CARD_POST_CARD_METADATA; showThumbnailPreviewOnRight = prefs.getBool(LocalSettings.showThumbnailPreviewOnRight.name) ?? false; showTextPostIndicator = prefs.getBool(LocalSettings.showTextPostIndicator.name) ?? false; @@ -156,6 +162,9 @@ class _PostAppearanceSettingsPageState extends State await prefs.setBool(LocalSettings.showTextPostIndicator.name, value); setState(() => showTextPostIndicator = value); break; + case LocalSettings.cardPostCardMetadataItems: + await prefs.setStringList(LocalSettings.cardPostCardMetadataItems.name, value); + break; case LocalSettings.showPostTitleFirst: await prefs.setBool(LocalSettings.showPostTitleFirst.name, value); setState(() => showTitleFirst = value); @@ -212,6 +221,7 @@ class _PostAppearanceSettingsPageState extends State await prefs.remove(LocalSettings.compactPostCardMetadataItems.name); await prefs.remove(LocalSettings.showThumbnailPreviewOnRight.name); await prefs.remove(LocalSettings.showTextPostIndicator.name); + await prefs.remove(LocalSettings.cardPostCardMetadataItems.name); await prefs.remove(LocalSettings.showPostTitleFirst.name); await prefs.remove(LocalSettings.showPostFullHeightImages.name); await prefs.remove(LocalSettings.showPostEdgeToEdgeImages.name); @@ -278,8 +288,6 @@ class _PostAppearanceSettingsPageState extends State final ThemeData theme = Theme.of(context); final l10n = AppLocalizations.of(context)!; - print(useCompactView); - return Scaffold( body: CustomScrollView( slivers: [ @@ -583,10 +591,57 @@ class _PostAppearanceSettingsPageState extends State color: theme.textTheme.bodyMedium?.color?.withOpacity(0.8), ), ), + const SizedBox(height: 8.0), + Text( + 'You can customize the metadata information by dragging and dropping the desired information', + style: theme.textTheme.bodyMedium?.copyWith( + color: theme.textTheme.bodyMedium?.color?.withOpacity(0.8), + ), + ), + ], + ), + ), + ), + const SliverToBoxAdapter(child: Divider()), + SliverToBoxAdapter( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: buildCardViewMetadataPreview(isDisabled: useCompactView == true), + ), + ), + SliverToBoxAdapter( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Available metadata widgets', + style: theme.textTheme.bodyMedium?.copyWith( + color: theme.textTheme.bodyMedium?.color?.withOpacity(0.9), + ), + ), ], ), ), ), + SliverToBoxAdapter( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: PostCardMetadataDraggableTarget( + isDisabled: useCompactView == true, + containedPostCardMetadataItems: PostCardMetadataItem.values.where((element) => !cardPostCardMetadataItems.contains(element)).toList(), + onAcceptedData: (data) { + setState(() { + cardPostCardMetadataItems.remove(data); + setPreferences(LocalSettings.cardPostCardMetadataItems, cardPostCardMetadataItems.map((e) => e.name).toList()); + }); + }, + ), + ), + ), + const SliverToBoxAdapter(child: Divider()), + const SliverToBoxAdapter(child: SizedBox(height: 16.0)), SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), @@ -729,6 +784,120 @@ class _PostAppearanceSettingsPageState extends State ); } + Widget buildCardViewMetadataPreview({bool isDisabled = false}) { + final theme = Theme.of(context); + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (showTitleFirst) ...[ + Container( + width: MediaQuery.of(context).size.width, + height: 25, + decoration: BoxDecoration( + color: theme.dividerColor, + borderRadius: BorderRadius.circular(12), + ), + ), // Title + const SizedBox(height: 4.0), + ], + Container( + height: showFullHeightImages ? 150 : 100, + margin: const EdgeInsets.symmetric(vertical: 8.0), + decoration: BoxDecoration( + color: theme.dividerColor, + borderRadius: BorderRadius.circular((showEdgeToEdgeImages ? 0 : 12)), + ), + ), + if (!showTitleFirst) ...[ + const SizedBox(height: 4.0), + Container( + width: MediaQuery.of(context).size.width, + height: 25, + decoration: BoxDecoration( + color: theme.dividerColor, + borderRadius: BorderRadius.circular(12), + ), + ), // Title + const SizedBox(height: 6.0), + ], + if (showTextContent) ...[ + ScalableText( + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', + maxLines: 4, + overflow: TextOverflow.ellipsis, + style: theme.textTheme.bodyMedium?.copyWith( + color: readColor, + ), + ), + const SizedBox(height: 4.0), + ], + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (showCommunityIcons) + Container( + width: 25, + height: 25, + margin: const EdgeInsets.only(right: 6.0), + decoration: BoxDecoration( + color: theme.dividerColor, + shape: BoxShape.circle, + ), + ), + Container( + width: MediaQuery.of(context).size.width * 0.5, + height: 15, + decoration: BoxDecoration( + color: theme.dividerColor, + borderRadius: BorderRadius.circular(12), + ), + ), + const SizedBox(height: 6.0), + PostCardMetadataDraggableTarget( + isDisabled: useCompactView == true, + containerHeight: 25.0, + showEmptyTargetMessage: false, + containedPostCardMetadataItems: cardPostCardMetadataItems, + onAcceptedData: (data) { + setState(() { + cardPostCardMetadataItems.add(data); + setPreferences(LocalSettings.cardPostCardMetadataItems, cardPostCardMetadataItems.map((e) => e.name).toList()); + }); + }, + ), + ], + ), + ), + const Padding( + padding: EdgeInsets.all(6.0), + child: Icon(Icons.more_horiz_rounded), + ), + if (showVoteActions) ...[ + const Padding( + padding: EdgeInsets.all(6.0), + child: Icon(Icons.arrow_upward_rounded), + ), + const Padding( + padding: EdgeInsets.all(6.0), + child: Icon(Icons.arrow_downward_rounded), + ), + ], + if (showSaveAction) + const Padding( + padding: EdgeInsets.all(6.0), + child: Icon(Icons.star_outline_rounded), + ), + ], + ), + ], + ); + } + Widget buildCompactViewMetadataPreview({bool isDisabled = false}) { final theme = Theme.of(context); @@ -864,6 +1033,7 @@ class PostCardMetadataDraggableTarget extends StatelessWidget { children: containedPostCardMetadataItems .map( (item) => Draggable( + key: ValueKey(item), data: item, feedback: buildDraggableItem(context, item: item, isFeedback: true), child: buildDraggableItem(context, item: item, isDisabled: isDisabled), @@ -879,8 +1049,9 @@ class PostCardMetadataDraggableTarget extends StatelessWidget { } return false; }, - onAccept: (data) { - onAcceptedData(data); + onAcceptWithDetails: (DragTargetDetails details) { + print(details.offset); + onAcceptedData(details.data); }, ), ), diff --git a/lib/thunder/bloc/thunder_bloc.dart b/lib/thunder/bloc/thunder_bloc.dart index 211e6d83a..f519e4e2c 100644 --- a/lib/thunder/bloc/thunder_bloc.dart +++ b/lib/thunder/bloc/thunder_bloc.dart @@ -141,6 +141,8 @@ class ThunderBloc extends Bloc { bool showCrossPosts = prefs.getBool(LocalSettings.showCrossPosts.name) ?? true; List compactPostCardMetadataItems = prefs.getStringList(LocalSettings.compactPostCardMetadataItems.name)?.map((e) => PostCardMetadataItem.values.byName(e)).toList() ?? DEFAULT_COMPACT_POST_CARD_METADATA; + List cardPostCardMetadataItems = + prefs.getStringList(LocalSettings.cardPostCardMetadataItems.name)?.map((e) => PostCardMetadataItem.values.byName(e)).toList() ?? DEFAULT_CARD_POST_CARD_METADATA; List keywordFilters = prefs.getStringList(LocalSettings.keywordFilters.name) ?? []; @@ -272,6 +274,7 @@ class ThunderBloc extends Bloc { useAdvancedShareSheet: useAdvancedShareSheet, showCrossPosts: showCrossPosts, compactPostCardMetadataItems: compactPostCardMetadataItems, + cardPostCardMetadataItems: cardPostCardMetadataItems, keywordFilters: keywordFilters, /// -------------------------- Post Page Related Settings -------------------------- diff --git a/lib/thunder/bloc/thunder_state.dart b/lib/thunder/bloc/thunder_state.dart index 6be1e1413..a3f27dea9 100644 --- a/lib/thunder/bloc/thunder_state.dart +++ b/lib/thunder/bloc/thunder_state.dart @@ -57,6 +57,7 @@ class ThunderState extends Equatable { this.useAdvancedShareSheet = true, this.showCrossPosts = true, this.compactPostCardMetadataItems = const [], + this.cardPostCardMetadataItems = const [], this.keywordFilters = const [], this.appLanguageCode = 'en', @@ -187,6 +188,7 @@ class ThunderState extends Equatable { final bool useAdvancedShareSheet; final bool showCrossPosts; final List compactPostCardMetadataItems; + final List cardPostCardMetadataItems; final List keywordFilters; /// -------------------------- Post Page Related Settings -------------------------- @@ -323,6 +325,7 @@ class ThunderState extends Equatable { bool? useAdvancedShareSheet, bool? showCrossPosts, List? compactPostCardMetadataItems, + List? cardPostCardMetadataItems, String? appLanguageCode = 'en', List? keywordFilters, @@ -453,6 +456,7 @@ class ThunderState extends Equatable { useAdvancedShareSheet: useAdvancedShareSheet ?? this.useAdvancedShareSheet, showCrossPosts: showCrossPosts ?? this.showCrossPosts, compactPostCardMetadataItems: compactPostCardMetadataItems ?? this.compactPostCardMetadataItems, + cardPostCardMetadataItems: cardPostCardMetadataItems ?? this.cardPostCardMetadataItems, keywordFilters: keywordFilters ?? this.keywordFilters, /// -------------------------- Post Page Related Settings -------------------------- @@ -587,6 +591,7 @@ class ThunderState extends Equatable { useAdvancedShareSheet, showCrossPosts, compactPostCardMetadataItems, + cardPostCardMetadataItems, appLanguageCode, keywordFilters, diff --git a/lib/utils/constants.dart b/lib/utils/constants.dart index 41b26a69c..11a8109c3 100644 --- a/lib/utils/constants.dart +++ b/lib/utils/constants.dart @@ -28,3 +28,10 @@ List DEFAULT_COMPACT_POST_CARD_METADATA = [ PostCardMetadataItem.dateTime, PostCardMetadataItem.url, ]; + +List DEFAULT_CARD_POST_CARD_METADATA = [ + PostCardMetadataItem.score, + PostCardMetadataItem.commentCount, + PostCardMetadataItem.dateTime, + PostCardMetadataItem.url, +]; From 84227d218cc6518ef29c4d8fe8ca5977d6c4e8cb Mon Sep 17 00:00:00 2001 From: Hamlet Jiang Su Date: Mon, 22 Jan 2024 16:58:18 -0800 Subject: [PATCH 06/11] adjusted styling and previews for post card metadata --- .../pages/post_appearance_settings_page.dart | 73 +++++++------------ 1 file changed, 26 insertions(+), 47 deletions(-) diff --git a/lib/settings/pages/post_appearance_settings_page.dart b/lib/settings/pages/post_appearance_settings_page.dart index 3353cfd2c..d98fbaf3d 100644 --- a/lib/settings/pages/post_appearance_settings_page.dart +++ b/lib/settings/pages/post_appearance_settings_page.dart @@ -504,13 +504,6 @@ class _PostAppearanceSettingsPageState extends State color: theme.textTheme.bodyMedium?.color?.withOpacity(0.6), ), ), - const SizedBox(height: 8.0), - Text( - 'You can customize the metadata information by dragging and dropping the desired information', - style: theme.textTheme.bodyMedium?.copyWith( - color: theme.textTheme.bodyMedium?.color?.withOpacity(0.8), - ), - ), ], ), ), @@ -522,24 +515,21 @@ class _PostAppearanceSettingsPageState extends State ), ), SliverToBoxAdapter( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Available metadata widgets', - style: theme.textTheme.bodyMedium?.copyWith( - color: theme.textTheme.bodyMedium?.color?.withOpacity(0.9), - ), - ), - ], + child: Container( + margin: const EdgeInsets.only(left: 16.0, right: 16.0, bottom: 8.0), + child: Text( + 'You can customize the metadata information by dragging and dropping the desired information', + style: theme.textTheme.bodyMedium?.copyWith( + color: theme.textTheme.bodyMedium?.color?.withOpacity(0.8), + ), ), ), ), SliverToBoxAdapter( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: Container( + decoration: BoxDecoration(border: Border.all(color: theme.dividerColor), borderRadius: BorderRadius.circular(8.0)), + margin: const EdgeInsets.symmetric(horizontal: 16.0), + padding: const EdgeInsets.all(8.0), child: PostCardMetadataDraggableTarget( isDisabled: useCompactView == false, containedPostCardMetadataItems: PostCardMetadataItem.values.where((element) => !compactPostCardMetadataItems.contains(element)).toList(), @@ -552,7 +542,7 @@ class _PostAppearanceSettingsPageState extends State ), ), ), - const SliverToBoxAdapter(child: SizedBox(height: 16.0)), + const SliverToBoxAdapter(child: SizedBox(height: 8.0)), SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), @@ -591,43 +581,33 @@ class _PostAppearanceSettingsPageState extends State color: theme.textTheme.bodyMedium?.color?.withOpacity(0.8), ), ), - const SizedBox(height: 8.0), - Text( - 'You can customize the metadata information by dragging and dropping the desired information', - style: theme.textTheme.bodyMedium?.copyWith( - color: theme.textTheme.bodyMedium?.color?.withOpacity(0.8), - ), - ), ], ), ), ), - const SliverToBoxAdapter(child: Divider()), SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), child: buildCardViewMetadataPreview(isDisabled: useCompactView == true), ), ), + const SliverToBoxAdapter(child: SizedBox(height: 16.0)), SliverToBoxAdapter( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Available metadata widgets', - style: theme.textTheme.bodyMedium?.copyWith( - color: theme.textTheme.bodyMedium?.color?.withOpacity(0.9), - ), - ), - ], + child: Container( + margin: const EdgeInsets.only(left: 16.0, right: 16.0, bottom: 8.0), + child: Text( + 'You can customize the metadata information by dragging and dropping the desired information', + style: theme.textTheme.bodyMedium?.copyWith( + color: theme.textTheme.bodyMedium?.color?.withOpacity(0.8), + ), ), ), ), SliverToBoxAdapter( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: Container( + decoration: BoxDecoration(border: Border.all(color: theme.dividerColor), borderRadius: BorderRadius.circular(8.0)), + margin: const EdgeInsets.symmetric(horizontal: 16.0), + padding: const EdgeInsets.all(8.0), child: PostCardMetadataDraggableTarget( isDisabled: useCompactView == true, containedPostCardMetadataItems: PostCardMetadataItem.values.where((element) => !cardPostCardMetadataItems.contains(element)).toList(), @@ -640,8 +620,7 @@ class _PostAppearanceSettingsPageState extends State ), ), ), - const SliverToBoxAdapter(child: Divider()), - const SliverToBoxAdapter(child: SizedBox(height: 16.0)), + const SliverToBoxAdapter(child: SizedBox(height: 8.0)), SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), @@ -857,7 +836,7 @@ class _PostAppearanceSettingsPageState extends State borderRadius: BorderRadius.circular(12), ), ), - const SizedBox(height: 6.0), + const SizedBox(height: 8.0), PostCardMetadataDraggableTarget( isDisabled: useCompactView == true, containerHeight: 25.0, From be525b0a42541fd76bbf86c32ddf076ac9cdf386 Mon Sep 17 00:00:00 2001 From: Hamlet Jiang Su Date: Wed, 24 Jan 2024 10:20:56 -0800 Subject: [PATCH 07/11] fixed rendering issue with community icons --- .../pages/post_appearance_settings_page.dart | 38 +++++++++++-------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/lib/settings/pages/post_appearance_settings_page.dart b/lib/settings/pages/post_appearance_settings_page.dart index d98fbaf3d..b5494ddc2 100644 --- a/lib/settings/pages/post_appearance_settings_page.dart +++ b/lib/settings/pages/post_appearance_settings_page.dart @@ -818,23 +818,29 @@ class _PostAppearanceSettingsPageState extends State child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (showCommunityIcons) - Container( - width: 25, - height: 25, - margin: const EdgeInsets.only(right: 6.0), - decoration: BoxDecoration( - color: theme.dividerColor, - shape: BoxShape.circle, + Row( + children: [ + if (showCommunityIcons) + Container( + width: 25, + height: 25, + margin: const EdgeInsets.only(right: 6.0), + decoration: BoxDecoration( + color: theme.dividerColor, + shape: BoxShape.circle, + ), + ), + Expanded( + child: Container( + width: MediaQuery.of(context).size.width * 0.5, + height: 15, + decoration: BoxDecoration( + color: theme.dividerColor, + borderRadius: BorderRadius.circular(12), + ), + ), ), - ), - Container( - width: MediaQuery.of(context).size.width * 0.5, - height: 15, - decoration: BoxDecoration( - color: theme.dividerColor, - borderRadius: BorderRadius.circular(12), - ), + ], ), const SizedBox(height: 8.0), PostCardMetadataDraggableTarget( From c0d1fe8446c11dbc95eeac0fdee4d6b2bd3841d1 Mon Sep 17 00:00:00 2001 From: Hamlet Jiang Su Date: Mon, 29 Jan 2024 13:27:24 -0800 Subject: [PATCH 08/11] added unread comment count indicators --- ios/Flutter/AppFrameworkInfo.plist | 2 +- ios/Podfile | 4 +-- ios/Podfile.lock | 36 ++++++++----------- ios/Runner.xcodeproj/project.pbxproj | 6 ++-- lib/community/widgets/post_card_metadata.dart | 19 +++++++--- .../widgets/post_card_view_comfortable.dart | 1 + .../widgets/post_card_view_compact.dart | 1 + 7 files changed, 36 insertions(+), 33 deletions(-) diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist index 9625e105d..7c5696400 100644 --- a/ios/Flutter/AppFrameworkInfo.plist +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 11.0 + 12.0 diff --git a/ios/Podfile b/ios/Podfile index f1344d775..3f9afe057 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '11.0' +# platform :ios, '12.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' @@ -100,4 +100,4 @@ post_install do |installer| end # End of the permission_handler configuration end -end \ No newline at end of file +end diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 2c1b2f11b..5221e1878 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1,5 +1,5 @@ PODS: - - background_fetch (1.2.1): + - background_fetch (1.2.2): - Flutter - device_info_plus (0.0.1): - Flutter @@ -16,9 +16,6 @@ PODS: - Flutter - flutter_native_splash (0.0.1): - Flutter - - FMDB (2.7.5): - - FMDB/standard (= 2.7.5) - - FMDB/standard (2.7.5) - gal (1.0.0): - Flutter - FlutterMacOS @@ -40,7 +37,7 @@ PODS: - FlutterMacOS - sqflite (0.0.3): - Flutter - - FMDB (>= 2.7.5) + - FlutterMacOS - uni_links (0.0.1): - Flutter - url_launcher_ios (0.0.1): @@ -66,15 +63,11 @@ DEPENDENCIES: - receive_sharing_intent (from `.symlinks/plugins/receive_sharing_intent/ios`) - share_plus (from `.symlinks/plugins/share_plus/ios`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - - sqflite (from `.symlinks/plugins/sqflite/ios`) + - sqflite (from `.symlinks/plugins/sqflite/darwin`) - uni_links (from `.symlinks/plugins/uni_links/ios`) - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) - webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/ios`) -SPEC REPOS: - trunk: - - FMDB - EXTERNAL SOURCES: background_fetch: :path: ".symlinks/plugins/background_fetch/ios" @@ -111,7 +104,7 @@ EXTERNAL SOURCES: shared_preferences_foundation: :path: ".symlinks/plugins/shared_preferences_foundation/darwin" sqflite: - :path: ".symlinks/plugins/sqflite/ios" + :path: ".symlinks/plugins/sqflite/darwin" uni_links: :path: ".symlinks/plugins/uni_links/ios" url_launcher_ios: @@ -120,29 +113,28 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/webview_flutter_wkwebview/ios" SPEC CHECKSUMS: - background_fetch: 896944864b038d2837fc750d470e9841e1e6a363 + background_fetch: ec64adecd504f2d0d333b4b11d31f47c8ee23d12 device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6 - Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 flutter_custom_tabs_ios: 62439c843b2691aae516fd50119a01eb9755fff7 flutter_file_dialog: 4c014a45b105709a27391e266c277d7e588e9299 flutter_icmp_ping: 2b159955eee0c487c766ad83fec224ae35e7c935 flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069 - flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743 + flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086 flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef - FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a gal: 61e868295d28fe67ffa297fae6dacebf56fd53e1 - image_picker_ios: 4a8aadfbb6dc30ad5141a2ce3832af9214a705b5 + image_picker_ios: 99dfe1854b4fa34d0364e74a78448a0151025425 package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85 - path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 + path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6 receive_sharing_intent: c0d87310754e74c0f9542947e7cbdf3a0335a3b1 share_plus: c3fef564749587fc939ef86ffb283ceac0baf9f5 - shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126 - sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a + shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695 + sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec uni_links: d97da20c7701486ba192624d99bffaaffcfc298a - url_launcher_ios: bf5ce03e0e2088bad9cc378ea97fa0ed5b49673b - webview_flutter_wkwebview: 2e2d318f21a5e036e2c3f26171342e95908bd60a + url_launcher_ios: bbd758c6e7f9fd7b5b1d4cde34d2b95fcce5e812 + webview_flutter_wkwebview: be0f0d33777f1bfd0c9fdcb594786704dbf65f36 -PODFILE CHECKSUM: 0b10e1f269736e810e149457dba01ee3b062862b +PODFILE CHECKSUM: 8d23d5c4d896af3a5f2a08e0206462ca9882e556 COCOAPODS: 1.14.3 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 8c79c744c..a37b00b11 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -569,7 +569,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -704,7 +704,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -753,7 +753,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; diff --git a/lib/community/widgets/post_card_metadata.dart b/lib/community/widgets/post_card_metadata.dart index b2feacad9..f108452fa 100644 --- a/lib/community/widgets/post_card_metadata.dart +++ b/lib/community/widgets/post_card_metadata.dart @@ -145,6 +145,9 @@ class PostCardMetadata extends StatelessWidget { /// The number of comments on the post. If null, no comment count will be displayed. final int? commentCount; + /// The number of unread comments on the post. If null, no unread comment count will be displayed. + final int? unreadCommentCount; + /// The date/time the post was created or updated. This string should conform to ISO-8601 format. final String? dateTime; @@ -165,6 +168,7 @@ class PostCardMetadata extends StatelessWidget { this.downvoteCount, this.voteType = 0, this.commentCount, + this.unreadCommentCount, this.dateTime, this.hasBeenEdited = false, this.hasBeenRead = false, @@ -190,7 +194,7 @@ class PostCardMetadata extends StatelessWidget { PostCardMetadataItem.score => showScores ? ScorePostCardMetaData(score: score, voteType: voteType, hasBeenRead: hasBeenRead ?? false) : Container(), PostCardMetadataItem.upvote => showScores ? UpvotePostCardMetaData(upvotes: upvoteCount, isUpvoted: voteType == 1, hasBeenRead: hasBeenRead ?? false) : Container(), PostCardMetadataItem.downvote => showScores ? DownvotePostCardMetaData(downvotes: downvoteCount, isDownvoted: voteType == -1, hasBeenRead: hasBeenRead ?? false) : Container(), - PostCardMetadataItem.commentCount => CommentCountPostCardMetaData(commentCount: commentCount, hasBeenRead: hasBeenRead ?? false), + PostCardMetadataItem.commentCount => CommentCountPostCardMetaData(commentCount: commentCount, unreadCommentCount: unreadCommentCount ?? 0, hasBeenRead: hasBeenRead ?? false), PostCardMetadataItem.dateTime => DateTimePostCardMetaData(dateTime: dateTime!, hasBeenRead: hasBeenRead ?? false, hasBeenEdited: hasBeenEdited ?? false), PostCardMetadataItem.url => UrlPostCardMetaData(url: url, hasBeenRead: hasBeenRead ?? false), }; @@ -327,30 +331,35 @@ class CommentCountPostCardMetaData extends StatelessWidget { /// The number of comments on the post. Defaults to 0 if not specified. final int? commentCount; + /// The number of unread comments on the post. Defaults to 0 if not specified. + final int? unreadCommentCount; + /// Whether or not the post has been read. This is used to determine the color. final bool hasBeenRead; const CommentCountPostCardMetaData({ super.key, this.commentCount = 0, + this.unreadCommentCount = 0, this.hasBeenRead = false, }); @override Widget build(BuildContext context) { + final theme = Theme.of(context); final state = context.read().state; final color = switch (hasBeenRead) { - true => readColor, - _ => null, + true => (unreadCommentCount != 0 && unreadCommentCount != commentCount) ? theme.primaryColor : readColor, + _ => (unreadCommentCount != 0 && unreadCommentCount != commentCount) ? theme.primaryColor : null, }; return IconText( fontScale: state.metadataFontSizeScale, - text: formatNumberToK(commentCount ?? 0), + text: (unreadCommentCount != 0 && unreadCommentCount != commentCount) ? '+${formatNumberToK(unreadCommentCount ?? 0)}' : formatNumberToK(commentCount ?? 0), textColor: color, padding: 5.0, - icon: Icon(Icons.chat_rounded, size: 17.0, color: color), + icon: Icon(unreadCommentCount != 0 && unreadCommentCount != commentCount ? Icons.mark_unread_chat_alt_rounded : Icons.chat, size: 17.0, color: color), ); } } diff --git a/lib/community/widgets/post_card_view_comfortable.dart b/lib/community/widgets/post_card_view_comfortable.dart index fca1be9dd..ab3e403a0 100644 --- a/lib/community/widgets/post_card_view_comfortable.dart +++ b/lib/community/widgets/post_card_view_comfortable.dart @@ -281,6 +281,7 @@ class PostCardViewComfortable extends StatelessWidget { downvoteCount: postViewMedia.postView.counts.downvotes, voteType: postViewMedia.postView.myVote ?? 0, commentCount: postViewMedia.postView.counts.comments, + unreadCommentCount: postViewMedia.postView.unreadComments, dateTime: postViewMedia.postView.post.updated != null ? postViewMedia.postView.post.updated?.toIso8601String() : postViewMedia.postView.post.published.toIso8601String(), hasBeenEdited: postViewMedia.postView.post.updated != null ? true : false, url: postViewMedia.media.firstOrNull != null ? postViewMedia.media.first.originalUrl : null, diff --git a/lib/community/widgets/post_card_view_compact.dart b/lib/community/widgets/post_card_view_compact.dart index 8f1117663..01ac69de4 100644 --- a/lib/community/widgets/post_card_view_compact.dart +++ b/lib/community/widgets/post_card_view_compact.dart @@ -148,6 +148,7 @@ class PostCardViewCompact extends StatelessWidget { downvoteCount: postViewMedia.postView.counts.downvotes, voteType: postViewMedia.postView.myVote ?? 0, commentCount: postViewMedia.postView.counts.comments, + unreadCommentCount: postViewMedia.postView.unreadComments, dateTime: postViewMedia.postView.post.updated != null ? postViewMedia.postView.post.updated?.toIso8601String() : postViewMedia.postView.post.published.toIso8601String(), hasBeenEdited: postViewMedia.postView.post.updated != null ? true : false, url: postViewMedia.media.firstOrNull != null ? postViewMedia.media.first.originalUrl : null, From d3c5eb40f0af44c9bac8f03ae5b50cff768e51be Mon Sep 17 00:00:00 2001 From: Hamlet Jiang Su Date: Mon, 29 Jan 2024 13:43:29 -0800 Subject: [PATCH 09/11] fixed issue with modifying unmodifiable list --- .../widgets/post_card_view_comfortable.dart | 10 ---------- .../pages/post_appearance_settings_page.dart | 17 ++++++++++++----- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/lib/community/widgets/post_card_view_comfortable.dart b/lib/community/widgets/post_card_view_comfortable.dart index ab3e403a0..d50b30395 100644 --- a/lib/community/widgets/post_card_view_comfortable.dart +++ b/lib/community/widgets/post_card_view_comfortable.dart @@ -287,16 +287,6 @@ class PostCardViewComfortable extends StatelessWidget { url: postViewMedia.media.firstOrNull != null ? postViewMedia.media.first.originalUrl : null, hasBeenRead: indicateRead && postViewMedia.postView.read, ), - // PostCardMetaData( - // readColor: readColor, - // hostURL: postViewMedia.media.firstOrNull != null ? postViewMedia.media.first.originalUrl : null, - // score: postViewMedia.postView.counts.score, - // voteType: postViewMedia.postView.myVote ?? 0, - // comments: postViewMedia.postView.counts.comments, - // unreadComments: postViewMedia.postView.unreadComments, - // hasBeenEdited: postViewMedia.postView.post.updated != null ? true : false, - // published: postViewMedia.postView.post.updated != null ? postViewMedia.postView.post.updated! : postViewMedia.postView.post.published, - // ) ], ), ), diff --git a/lib/settings/pages/post_appearance_settings_page.dart b/lib/settings/pages/post_appearance_settings_page.dart index b5494ddc2..ff741d8a9 100644 --- a/lib/settings/pages/post_appearance_settings_page.dart +++ b/lib/settings/pages/post_appearance_settings_page.dart @@ -534,8 +534,10 @@ class _PostAppearanceSettingsPageState extends State isDisabled: useCompactView == false, containedPostCardMetadataItems: PostCardMetadataItem.values.where((element) => !compactPostCardMetadataItems.contains(element)).toList(), onAcceptedData: (data) { + List newCompactPostCardMetadataItems = List.from(compactPostCardMetadataItems)..remove(data); + setState(() { - compactPostCardMetadataItems.remove(data); + compactPostCardMetadataItems = newCompactPostCardMetadataItems; setPreferences(LocalSettings.compactPostCardMetadataItems, compactPostCardMetadataItems.map((e) => e.name).toList()); }); }, @@ -612,8 +614,10 @@ class _PostAppearanceSettingsPageState extends State isDisabled: useCompactView == true, containedPostCardMetadataItems: PostCardMetadataItem.values.where((element) => !cardPostCardMetadataItems.contains(element)).toList(), onAcceptedData: (data) { + List newCardPostCardMetadataItems = List.from(cardPostCardMetadataItems)..remove(data); + setState(() { - cardPostCardMetadataItems.remove(data); + cardPostCardMetadataItems = newCardPostCardMetadataItems; setPreferences(LocalSettings.cardPostCardMetadataItems, cardPostCardMetadataItems.map((e) => e.name).toList()); }); }, @@ -849,8 +853,10 @@ class _PostAppearanceSettingsPageState extends State showEmptyTargetMessage: false, containedPostCardMetadataItems: cardPostCardMetadataItems, onAcceptedData: (data) { + List newCardPostCardMetadataItems = List.from(cardPostCardMetadataItems)..add(data); + setState(() { - cardPostCardMetadataItems.add(data); + cardPostCardMetadataItems = newCardPostCardMetadataItems; setPreferences(LocalSettings.cardPostCardMetadataItems, cardPostCardMetadataItems.map((e) => e.name).toList()); }); }, @@ -932,8 +938,10 @@ class _PostAppearanceSettingsPageState extends State showEmptyTargetMessage: false, containedPostCardMetadataItems: compactPostCardMetadataItems, onAcceptedData: (data) { + List newCompactPostCardMetadataItems = List.from(compactPostCardMetadataItems)..add(data); + setState(() { - compactPostCardMetadataItems.add(data); + compactPostCardMetadataItems = newCompactPostCardMetadataItems; setPreferences(LocalSettings.compactPostCardMetadataItems, compactPostCardMetadataItems.map((e) => e.name).toList()); }); }, @@ -1035,7 +1043,6 @@ class PostCardMetadataDraggableTarget extends StatelessWidget { return false; }, onAcceptWithDetails: (DragTargetDetails details) { - print(details.offset); onAcceptedData(details.data); }, ), From 2bba126e3707ec96ba0bd075490b1ed7ea2d4f5d Mon Sep 17 00:00:00 2001 From: Hamlet Jiang Su Date: Mon, 29 Jan 2024 13:54:36 -0800 Subject: [PATCH 10/11] added localization strings --- lib/l10n/app_en.arb | 12 ++++++++++++ .../pages/post_appearance_settings_page.dart | 10 ++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 0a26d1488..b9c6e08cd 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -715,6 +715,10 @@ }, "noInstanceBlocks": "No blocked instances.", "@noInstanceBlocks": {}, + "noItems": "No items", + "@noItems": { + "description": "Generic text when there are no items" + }, "noKeywordFilters": "No keyword filters added", "@noKeywordFilters": { "description": "Message for no keywords added" @@ -809,6 +813,10 @@ "@permissionDeniedMessage": { "description": "Explanation for error when user denies OS permissions" }, + "placeholderText": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", + "@placeholderText": { + "description": "Placeholder text for any previews. This comes from https://www.lipsum.com/" + }, "postBehaviourSettings": "Posts", "@postBehaviourSettings": { "description": "Subcategory in Setting -> General" @@ -837,6 +845,10 @@ }, "postLocked": "Post locked. No replies allowed.", "@postLocked": {}, + "postMetadataInstructions": "You can customize the metadata information by dragging and dropping the desired information", + "@postMetadataInstructions": { + "description": "Instructions on how to customize the post metadata information. This is found in the Appearance -> Post settings page" + }, "postNSFW": "Mark as NSFW", "@postNSFW": {}, "postPreview": "Show a preview of the post with the given settings", diff --git a/lib/settings/pages/post_appearance_settings_page.dart b/lib/settings/pages/post_appearance_settings_page.dart index ff741d8a9..a3545d049 100644 --- a/lib/settings/pages/post_appearance_settings_page.dart +++ b/lib/settings/pages/post_appearance_settings_page.dart @@ -518,7 +518,7 @@ class _PostAppearanceSettingsPageState extends State child: Container( margin: const EdgeInsets.only(left: 16.0, right: 16.0, bottom: 8.0), child: Text( - 'You can customize the metadata information by dragging and dropping the desired information', + l10n.postMetadataInstructions, style: theme.textTheme.bodyMedium?.copyWith( color: theme.textTheme.bodyMedium?.color?.withOpacity(0.8), ), @@ -598,7 +598,7 @@ class _PostAppearanceSettingsPageState extends State child: Container( margin: const EdgeInsets.only(left: 16.0, right: 16.0, bottom: 8.0), child: Text( - 'You can customize the metadata information by dragging and dropping the desired information', + l10n.postMetadataInstructions, style: theme.textTheme.bodyMedium?.copyWith( color: theme.textTheme.bodyMedium?.color?.withOpacity(0.8), ), @@ -769,6 +769,7 @@ class _PostAppearanceSettingsPageState extends State Widget buildCardViewMetadataPreview({bool isDisabled = false}) { final theme = Theme.of(context); + final l10n = AppLocalizations.of(context)!; return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -806,7 +807,7 @@ class _PostAppearanceSettingsPageState extends State ], if (showTextContent) ...[ ScalableText( - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', + l10n.placeholderText, maxLines: 4, overflow: TextOverflow.ellipsis, style: theme.textTheme.bodyMedium?.copyWith( @@ -998,6 +999,7 @@ class PostCardMetadataDraggableTarget extends StatelessWidget { @override Widget build(BuildContext context) { final theme = Theme.of(context); + final l10n = AppLocalizations.of(context)!; return AbsorbPointer( absorbing: isDisabled, @@ -1013,7 +1015,7 @@ class PostCardMetadataDraggableTarget extends StatelessWidget { ), child: Center( child: Text( - showEmptyTargetMessage ? 'No items' : '', + showEmptyTargetMessage ? l10n.noItems : '', style: TextStyle(color: theme.textTheme.bodyMedium?.color?.withOpacity(0.8)), ), ), From 373a130cb59c5819eb7eac20c524dc4825b6e427 Mon Sep 17 00:00:00 2001 From: Hamlet Jiang Su Date: Mon, 29 Jan 2024 14:01:33 -0800 Subject: [PATCH 11/11] fixed some visual bugs --- lib/settings/pages/post_appearance_settings_page.dart | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/settings/pages/post_appearance_settings_page.dart b/lib/settings/pages/post_appearance_settings_page.dart index a3545d049..29744ec73 100644 --- a/lib/settings/pages/post_appearance_settings_page.dart +++ b/lib/settings/pages/post_appearance_settings_page.dart @@ -1007,12 +1007,8 @@ class PostCardMetadataDraggableTarget extends StatelessWidget { width: MediaQuery.of(context).size.width, child: DragTarget( builder: (context, candidateData, rejectedData) => containedPostCardMetadataItems.isEmpty - ? Container( + ? SizedBox( height: containerHeight, - decoration: BoxDecoration( - border: Border.all(color: theme.dividerColor), - borderRadius: BorderRadius.circular(8), - ), child: Center( child: Text( showEmptyTargetMessage ? l10n.noItems : '',