Skip to content

Commit

Permalink
Add user and community avatar options for feed/post pages (#1318)
Browse files Browse the repository at this point in the history
  • Loading branch information
iparks99 committed Apr 24, 2024
1 parent 7eb91dd commit 436b12f
Show file tree
Hide file tree
Showing 12 changed files with 134 additions and 13 deletions.
5 changes: 5 additions & 0 deletions lib/core/enums/local_settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ enum LocalSettings {
name: 'setting_general_post_body_show_user_instance', key: 'postBodyShowUserInstance', category: LocalSettingsCategories.posts, subCategory: LocalSettingsSubCategories.general),
postBodyShowCommunityInstance(
name: 'setting_general_post_body_show_community_instance', key: 'postBodyShowCommunityInstance', category: LocalSettingsCategories.posts, subCategory: LocalSettingsSubCategories.general),
postBodyShowCommunityAvatar(
name: 'setting_general_post_body_show_community_avatar', key: 'postBodyShowCommunityAvatar', category: LocalSettingsCategories.posts, subCategory: LocalSettingsSubCategories.general),

// Advanced Settings
imageCachingMode(name: 'setting_advanced_image_caching_mode', key: 'imageCachingMode', category: LocalSettingsCategories.general, subCategory: LocalSettingsSubCategories.advanced),
Expand All @@ -160,6 +162,7 @@ enum LocalSettings {
showCommentActionButtons(
name: 'setting_general_show_comment_button_actions', key: 'showCommentActionButtons', category: LocalSettingsCategories.comments, subCategory: LocalSettingsSubCategories.general),
commentShowUserInstance(name: 'settings_comment_show_user_instance', key: 'showUserInstance', category: LocalSettingsCategories.comments, subCategory: LocalSettingsSubCategories.comments),
commentShowUserAvatar(name: 'settings_comment_show_user_avatar', key: 'showUserAvatar', category: LocalSettingsCategories.comments, subCategory: LocalSettingsSubCategories.comments),
combineCommentScores(name: 'setting_general_combine_comment_scores', key: 'combineCommentScores', category: LocalSettingsCategories.comments, subCategory: LocalSettingsSubCategories.comments),
nestedCommentIndicatorStyle(
name: 'setting_general_nested_comment_indicator_style', key: 'nestedCommentIndicatorStyle', category: LocalSettingsCategories.comments, subCategory: LocalSettingsSubCategories.comments),
Expand Down Expand Up @@ -348,6 +351,7 @@ extension LocalizationExt on AppLocalizations {
'showCrossPosts': showCrossPosts,
'postBodyShowUserInstance': postBodyShowUserInstance,
'postBodyShowCommunityInstance': postBodyShowCommunityInstance,
'postBodyShowCommunityAvatar': postBodyShowCommunityAvatar,
'keywordFilters': keywordFilters,
'hideTopBarOnScroll': hideTopBarOnScroll,
'compactPostCardMetadataItems': compactPostCardMetadataItems,
Expand All @@ -362,6 +366,7 @@ extension LocalizationExt on AppLocalizations {
'collapseParentCommentBodyOnGesture': collapseParentCommentBodyOnGesture,
'showCommentActionButtons': showCommentActionButtons,
'showUserInstance': showUserInstance,
'showUserAvatar': showUserAvatar,
'combineCommentScores': combineCommentScores,
'nestedCommentIndicatorStyle': nestedCommentIndicatorStyle,
'nestedCommentIndicatorColor': nestedCommentIndicatorColor,
Expand Down
12 changes: 12 additions & 0 deletions lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,10 @@
"@commentReported": {},
"commentSavedAsDraft": "Comment saved as draft",
"@commentSavedAsDraft": {},
"commentShowUserAvatar": "Show User Avatar",
"@commentShowUserAvatar": {
"description": "Settings toggle to display user avatar alongside their display name in comments"
},
"commentShowUserInstance": "Show User Instance",
"@commentShowUserInstance": {
"description": "Settings toggle to display user instance alongside their display name in comments"
Expand Down Expand Up @@ -1193,6 +1197,10 @@
"@postBodySettingsDescription": {
"description": "Description of post body settings"
},
"postBodyShowCommunityAvatar": "Show Community Avatar",
"@postBodyShowCommunityAvatar": {
"description": "Whether to show the community avatar for post bodies"
},
"postBodyShowCommunityInstance": "Show Community Instance",
"@postBodyShowCommunityInstance": {
"description": "Whether to show the community instance for post bodies"
Expand Down Expand Up @@ -1661,6 +1669,10 @@
"@showUpdateChangelogsSubtitle": {
"description": "Subtitle for setting for showing changelogs after updates"
},
"showUserAvatar": "Show User Avatar",
"@showUserAvatar": {
"description": "Toggle to show user avatar."
},
"showUserDisplayNames": "Show User Display Names",
"@showUserDisplayNames": {
"description": "Toggle to show user display names."
Expand Down
6 changes: 6 additions & 0 deletions lib/post/widgets/post_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import 'package:thunder/post/bloc/post_bloc.dart';
import 'package:thunder/post/cubit/create_post_cubit.dart';
import 'package:thunder/post/widgets/post_metadata.dart';
import 'package:thunder/post/widgets/post_quick_actions_bar.dart';
import 'package:thunder/shared/avatars/community_avatar.dart';
import 'package:thunder/shared/avatars/user_avatar.dart';
import 'package:thunder/shared/chips/community_chip.dart';
import 'package:thunder/shared/chips/user_chip.dart';
import 'package:thunder/shared/common_markdown_body.dart';
Expand Down Expand Up @@ -193,13 +195,16 @@ class _PostSubviewState extends State<PostSubview> with SingleTickerProviderStat
width: MediaQuery.of(context).size.width,
child: Wrap(
alignment: WrapAlignment.spaceBetween,
crossAxisAlignment: WrapCrossAlignment.center,
runSpacing: 8.0,
children: [
Wrap(
spacing: 6.0,
crossAxisAlignment: WrapCrossAlignment.center,
children: [
UserChip(
personId: postView.creator.id,
personAvatar: UserAvatar(person: postView.creator, radius: 10, thumbnailSize: 20, format: 'png'),
personName: postView.creator.name,
personDisplayName: postView.creator.displayName ?? postView.creator.name,
personUrl: postView.creator.actorId,
Expand All @@ -215,6 +220,7 @@ class _PostSubviewState extends State<PostSubview> with SingleTickerProviderStat
),
CommunityChip(
communityId: postView.community.id,
communityAvatar: CommunityAvatar(community: postView.community, radius: 10, thumbnailSize: 20, format: 'png'),
communityName: postView.community.name,
communityUrl: postView.community.actorId,
),
Expand Down
19 changes: 18 additions & 1 deletion lib/settings/pages/comment_appearance_settings_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ class _CommentAppearanceSettingsPageState extends State<CommentAppearanceSetting
/// When toggled on, user instance is displayed alongside the display name/username
bool commentShowUserInstance = false;

/// When toggled on, user avatar is displayed to the left of the display name/username
bool commentShowUserAvatar = false;

/// When toggled on, comment scores will be combined instead of having separate upvotes and downvotes
bool combineCommentScores = false;

Expand All @@ -64,6 +67,7 @@ class _CommentAppearanceSettingsPageState extends State<CommentAppearanceSetting
setState(() {
showCommentButtonActions = prefs.getBool(LocalSettings.showCommentActionButtons.name) ?? false;
commentShowUserInstance = prefs.getBool(LocalSettings.commentShowUserInstance.name) ?? false;
commentShowUserAvatar = prefs.getBool(LocalSettings.commentShowUserAvatar.name) ?? false;
combineCommentScores = prefs.getBool(LocalSettings.combineCommentScores.name) ?? false;
nestedIndicatorStyle = NestedCommentIndicatorStyle.values.byName(prefs.getString(LocalSettings.nestedCommentIndicatorStyle.name) ?? DEFAULT_NESTED_COMMENT_INDICATOR_STYLE.name);
nestedIndicatorColor = NestedCommentIndicatorColor.values.byName(prefs.getString(LocalSettings.nestedCommentIndicatorColor.name) ?? DEFAULT_NESTED_COMMENT_INDICATOR_COLOR.name);
Expand All @@ -84,6 +88,9 @@ class _CommentAppearanceSettingsPageState extends State<CommentAppearanceSetting
case LocalSettings.commentShowUserInstance:
await prefs.setBool(LocalSettings.commentShowUserInstance.name, value);
setState(() => commentShowUserInstance = value);
case LocalSettings.commentShowUserAvatar:
await prefs.setBool(LocalSettings.commentShowUserAvatar.name, value);
setState(() => commentShowUserAvatar = value);
case LocalSettings.combineCommentScores:
await prefs.setBool(LocalSettings.combineCommentScores.name, value);
setState(() => combineCommentScores = value);
Expand Down Expand Up @@ -112,6 +119,7 @@ class _CommentAppearanceSettingsPageState extends State<CommentAppearanceSetting
await prefs.remove(LocalSettings.nestedCommentIndicatorStyle.name);
await prefs.remove(LocalSettings.nestedCommentIndicatorColor.name);
await prefs.remove(LocalSettings.commentShowUserInstance.name);
await prefs.remove(LocalSettings.commentShowUserAvatar.name);

await initPreferences();

Expand Down Expand Up @@ -348,7 +356,16 @@ class _CommentAppearanceSettingsPageState extends State<CommentAppearanceSetting
highlightKey: settingToHighlight == LocalSettings.commentShowUserInstance ? settingToHighlightKey : null,
),
),

SliverToBoxAdapter(
child: ToggleOption(
description: l10n.commentShowUserAvatar,
value: commentShowUserAvatar,
iconEnabled: Icons.account_circle,
iconDisabled: Icons.account_circle_outlined,
onToggle: (bool value) => setPreferences(LocalSettings.commentShowUserAvatar, value),
highlightKey: settingToHighlight == LocalSettings.commentShowUserAvatar ? settingToHighlightKey : null,
),
),
SliverToBoxAdapter(
child: ListOption(
description: l10n.nestedCommentIndicatorStyle,
Expand Down
21 changes: 20 additions & 1 deletion lib/settings/pages/post_appearance_settings_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ class _PostAppearanceSettingsPageState extends State<PostAppearanceSettingsPage>
/// When enabled, shows the instance of the community in posts
bool postBodyShowCommunityInstance = false;

/// When enabled, shows the avatar of the community in chips
bool postBodyShowCommunityAvatar = false;

/// 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<PostCardMetadataItem> compactPostCardMetadataItems = [];
Expand Down Expand Up @@ -166,6 +169,7 @@ class _PostAppearanceSettingsPageState extends State<PostAppearanceSettingsPage>
postBodyViewType = PostBodyViewType.values.byName(prefs.getString(LocalSettings.postBodyViewType.name) ?? PostBodyViewType.expanded.name);
postBodyShowUserInstance = prefs.getBool(LocalSettings.postBodyShowUserInstance.name) ?? false;
postBodyShowCommunityInstance = prefs.getBool(LocalSettings.postBodyShowCommunityInstance.name) ?? false;
postBodyShowCommunityAvatar = prefs.getBool(LocalSettings.postBodyShowCommunityAvatar.name) ?? false;
});
}

Expand Down Expand Up @@ -274,6 +278,10 @@ class _PostAppearanceSettingsPageState extends State<PostAppearanceSettingsPage>
await prefs.setBool(LocalSettings.postBodyShowCommunityInstance.name, value);
setState(() => postBodyShowCommunityInstance = value);
break;
case LocalSettings.postBodyShowCommunityAvatar:
await prefs.setBool(LocalSettings.postBodyShowCommunityAvatar.name, value);
setState(() => postBodyShowCommunityAvatar = value);
break;
}

if (context.mounted) {
Expand Down Expand Up @@ -310,6 +318,7 @@ class _PostAppearanceSettingsPageState extends State<PostAppearanceSettingsPage>
await prefs.remove(LocalSettings.postBodyViewType.name);
await prefs.remove(LocalSettings.postBodyShowUserInstance.name);
await prefs.remove(LocalSettings.postBodyShowCommunityInstance.name);
await prefs.remove(LocalSettings.postBodyShowCommunityAvatar.name);

await initPreferences();

Expand Down Expand Up @@ -1022,6 +1031,16 @@ class _PostAppearanceSettingsPageState extends State<PostAppearanceSettingsPage>
highlightKey: settingToHighlight == LocalSettings.postBodyShowCommunityInstance ? settingToHighlightKey : null,
),
),
SliverToBoxAdapter(
child: ToggleOption(
description: l10n.postBodyShowCommunityAvatar,
value: postBodyShowCommunityAvatar,
iconEnabled: Icons.image,
iconDisabled: Icons.image_not_supported,
onToggle: (bool value) => setPreferences(LocalSettings.postBodyShowCommunityAvatar, value),
highlightKey: settingToHighlight == LocalSettings.postBodyShowCommunityAvatar ? settingToHighlightKey : null,
),
),
const SliverToBoxAdapter(child: SizedBox(height: 128.0)),
],
),
Expand Down Expand Up @@ -1295,7 +1314,7 @@ class PostCardMetadataDraggableTarget extends StatelessWidget {
),
),
onLeave: (data) => HapticFeedback.mediumImpact(),
onWillAccept: (data) {
onWillAcceptWithDetails: (data) {
if (!containedPostCardMetadataItems.contains(data)) {
return true;
}
Expand Down
17 changes: 15 additions & 2 deletions lib/shared/avatars/community_avatar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@ class CommunityAvatar extends StatelessWidget {
/// Whether to show the community status (locked)
final bool showCommunityStatus;

const CommunityAvatar({super.key, this.community, this.radius = 12.0, this.showCommunityStatus = false});
/// The size of the thumbnail's height
final int? thumbnailSize;

/// The image format to request from the instance
final String? format;

const CommunityAvatar({super.key, this.community, this.radius = 12.0, this.showCommunityStatus = false, this.thumbnailSize, this.format});

@override
Widget build(BuildContext context) {
Expand All @@ -41,8 +47,15 @@ class CommunityAvatar extends StatelessWidget {

if (community?.icon?.isNotEmpty != true) return placeholderIcon;

Uri imageUri = Uri.parse(community!.icon!);
bool isPictrsImageEndpoint = imageUri.toString().contains('/pictrs/image/');
Map<String, dynamic> queryParameters = {};
if (isPictrsImageEndpoint && thumbnailSize != null) queryParameters['thumbnail'] = thumbnailSize.toString();
if (isPictrsImageEndpoint && format != null) queryParameters['format'] = format;
Uri thumbnailUri = Uri.https(imageUri.host, imageUri.path, queryParameters);

return CachedNetworkImage(
imageUrl: community!.icon!,
imageUrl: thumbnailUri.toString(),
imageBuilder: (context, imageProvider) {
return Stack(
children: [
Expand Down
17 changes: 15 additions & 2 deletions lib/shared/avatars/user_avatar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@ class UserAvatar extends StatelessWidget {
/// The radius of the avatar. Defaults to 16
final double radius;

const UserAvatar({super.key, this.person, this.radius = 16.0});
/// The size of the thumbnail's height
final int? thumbnailSize;

/// The image format to request from the instance
final String? format;

const UserAvatar({super.key, this.person, this.radius = 16.0, this.thumbnailSize, this.format});

@override
Widget build(BuildContext context) {
Expand All @@ -36,8 +42,15 @@ class UserAvatar extends StatelessWidget {

if (person?.avatar?.isNotEmpty != true) return placeholderIcon;

Uri imageUri = Uri.parse(person!.avatar!);
bool isPictrsImageEndpoint = imageUri.toString().contains('/pictrs/image/');
Map<String, dynamic> queryParameters = {};
if (isPictrsImageEndpoint && thumbnailSize != null) queryParameters['thumbnail'] = thumbnailSize.toString();
if (isPictrsImageEndpoint && format != null) queryParameters['format'] = format;
Uri thumbnailUri = Uri.https(imageUri.host, imageUri.path, queryParameters);

return CachedNetworkImage(
imageUrl: person!.avatar!,
imageUrl: thumbnailUri.toString(),
imageBuilder: (context, imageProvider) {
return CircleAvatar(
backgroundColor: Colors.transparent,
Expand Down
27 changes: 20 additions & 7 deletions lib/shared/chips/community_chip.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:thunder/core/enums/full_name.dart';
import 'package:thunder/feed/utils/utils.dart';
import 'package:thunder/feed/view/feed_page.dart';
import 'package:thunder/shared/avatars/community_avatar.dart';
import 'package:thunder/shared/full_name_widgets.dart';
import 'package:thunder/thunder/bloc/thunder_bloc.dart';
import 'package:thunder/utils/instance.dart';
Expand All @@ -15,13 +16,17 @@ class CommunityChip extends StatelessWidget {
const CommunityChip({
super.key,
this.communityId,
this.communityAvatar,
this.communityName,
this.communityUrl,
});

/// The ID of the community.
final int? communityId;

/// The avatar of the community.
final CommunityAvatar? communityAvatar;

/// The name of the community.
final String? communityName;

Expand All @@ -31,6 +36,7 @@ class CommunityChip extends StatelessWidget {
@override
Widget build(BuildContext context) {
final state = context.read<ThunderBloc>().state;
final showCommunityAvatar = state.postBodyShowCommunityAvatar;

return InkWell(
borderRadius: BorderRadius.circular(5),
Expand All @@ -39,13 +45,20 @@ class CommunityChip extends StatelessWidget {
excludeFromSemantics: true,
message: generateCommunityFullName(context, communityName, fetchInstanceNameFromUrl(communityUrl) ?? '-'),
preferBelow: false,
child: CommunityFullNameWidget(
context,
communityName,
fetchInstanceNameFromUrl(communityUrl),
includeInstance: state.postBodyShowCommunityInstance,
fontScale: state.metadataFontSizeScale,
transformColor: (color) => color?.withOpacity(0.75),
child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
if (showCommunityAvatar && communityAvatar != null) Padding(padding: const EdgeInsets.only(top: 3, bottom: 3, right: 3), child: communityAvatar!),
CommunityFullNameWidget(
context,
communityName,
fetchInstanceNameFromUrl(communityUrl),
includeInstance: state.postBodyShowCommunityInstance,
fontScale: state.metadataFontSizeScale,
transformColor: (color) => color?.withOpacity(0.75),
),
],
),
),
);
Expand Down
7 changes: 7 additions & 0 deletions lib/shared/chips/user_chip.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:thunder/core/enums/full_name.dart';
import 'package:thunder/core/enums/user_type.dart';
import 'package:thunder/feed/utils/utils.dart';
import 'package:thunder/feed/view/feed_page.dart';
import 'package:thunder/shared/avatars/user_avatar.dart';
import 'package:thunder/shared/full_name_widgets.dart';
import 'package:thunder/thunder/bloc/thunder_bloc.dart';
import 'package:thunder/thunder/thunder_icons.dart';
Expand All @@ -19,6 +20,7 @@ class UserChip extends StatelessWidget {
const UserChip({
super.key,
this.personId,
this.personAvatar,
this.personName,
this.personDisplayName,
this.personUrl,
Expand All @@ -31,6 +33,9 @@ class UserChip extends StatelessWidget {
/// The ID of the user
final int? personId;

/// The avatar of the user
final UserAvatar? personAvatar;

/// The username of the user
final String? personName;

Expand All @@ -57,6 +62,7 @@ class UserChip extends StatelessWidget {
Widget build(BuildContext context) {
final theme = Theme.of(context);
final state = context.read<ThunderBloc>().state;
final showUserAvatar = state.commentShowUserAvatar;

return IgnorePointer(
ignoring: ignorePointerEvents,
Expand All @@ -77,6 +83,7 @@ class UserChip extends StatelessWidget {
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (showUserAvatar && personAvatar != null) Padding(padding: const EdgeInsets.only(top: 3, bottom: 3, right: 3), child: personAvatar!),
UserFullNameWidget(
context,
personDisplayName != null && state.useDisplayNames ? personDisplayName! : personName,
Expand Down

0 comments on commit 436b12f

Please sign in to comment.