Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#665: Indicators for locked posts + reply prevention #676

Merged
merged 9 commits into from
Aug 24, 2023
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- Added access to saved comments from account page - contribution from @CTalvio
- Added Polish translation - contribution from @pazdikan
- Show default avatar for users without an avatar - contribution from @coslu
- Added lock icon indicating a post is locked. Visible in feed and post view. Also blocks commenting functionality and instead shows a toast indicating the post is blocked - contribution from @ajsosa
- Added the ability to combine the post FAB with the comment navigation buttons - contribution from @micahmo

### Changed
Expand Down
111 changes: 64 additions & 47 deletions lib/community/widgets/post_card_view_comfortable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,27 @@ class PostCardViewComfortable extends StatelessWidget {
child: Text.rich(
TextSpan(
children: [
if (postViewMedia.postView.post.locked) ...[
WidgetSpan(
child: Icon(
Icons.lock,
color: indicateRead && postViewMedia.postView.read ? Colors.red.withOpacity(0.55) : Colors.red,
size: 17.0 * textScaleFactor,
)),
if (!postViewMedia.postView.post.featuredCommunity)
const WidgetSpan(
child: SizedBox(
width: 3,
)),
],
if (postViewMedia.postView.post.featuredCommunity)
WidgetSpan(
child: Icon(
Icons.push_pin_rounded,
size: 17.0 * textScaleFactor,
color: indicateRead && postViewMedia.postView.read ? Colors.green.withOpacity(0.55) : Colors.green,
),
),
TextSpan(
text: postViewMedia.postView.post.name,
style: theme.textTheme.bodyMedium?.copyWith(
Expand All @@ -115,19 +136,6 @@ class PostCardViewComfortable extends StatelessWidget {
: (indicateRead && postViewMedia.postView.read ? theme.textTheme.bodyMedium?.color?.withOpacity(0.55) : null),
),
),
if (postViewMedia.postView.post.featuredCommunity)
WidgetSpan(
child: Padding(
padding: const EdgeInsets.only(
left: 8.0,
),
child: Icon(
Icons.push_pin_rounded,
size: 17.0 * textScaleFactor,
color: indicateRead && postViewMedia.postView.read ? Colors.green.withOpacity(0.55) : Colors.green,
),
),
),
if (!useSaveButton && postViewMedia.postView.saved)
WidgetSpan(
child: Padding(
Expand Down Expand Up @@ -159,49 +167,58 @@ class PostCardViewComfortable extends StatelessWidget {
),
if (!showTitleFirst)
Padding(
padding: const EdgeInsets.only(top: 4.0, bottom: 6.0, left: 12.0, right: 12.0),
child: Text.rich(
TextSpan(
children: [
TextSpan(
text: postViewMedia.postView.post.name,
style: theme.textTheme.bodyMedium?.copyWith(
fontWeight: FontWeight.w600,
color: indicateRead && postViewMedia.postView.read ? theme.textTheme.bodyMedium?.color?.withOpacity(0.65) : null,
),
),
if (postViewMedia.postView.post.featuredCommunity)
WidgetSpan(
child: Padding(
padding: const EdgeInsets.only(
left: 8.0,
),
padding: const EdgeInsets.only(top: 4.0, bottom: 6.0, left: 12.0, right: 12.0),
child: Text.rich(
TextSpan(
children: [
if (postViewMedia.postView.post.locked) ...[
WidgetSpan(
child: Icon(
Icons.lock,
color: indicateRead && postViewMedia.postView.read ? Colors.red.withOpacity(0.55) : Colors.red,
size: 17.0 * textScaleFactor,
)),
if (!postViewMedia.postView.post.featuredCommunity)
const WidgetSpan(
child: SizedBox(
width: 3,
)),
],
if (postViewMedia.postView.post.featuredCommunity)
WidgetSpan(
child: Icon(
Icons.push_pin_rounded,
size: 17.0 * textScaleFactor,
color: indicateRead && postViewMedia.postView.read ? Colors.green.withOpacity(0.55) : Colors.green,
),
),
TextSpan(
text: postViewMedia.postView.post.name,
style: theme.textTheme.bodyMedium?.copyWith(
fontWeight: FontWeight.w600,
color: postViewMedia.postView.post.featuredCommunity
? (indicateRead && postViewMedia.postView.read ? Colors.green.withOpacity(0.55) : Colors.green)
: (indicateRead && postViewMedia.postView.read ? theme.textTheme.bodyMedium?.color?.withOpacity(0.55) : null),
),
),
if (!useSaveButton && postViewMedia.postView.saved)
WidgetSpan(
child: Padding(
padding: const EdgeInsets.only(
left: 8.0,
),
child: Icon(
Icons.star_rounded,
color: indicateRead && postViewMedia.postView.read ? Colors.purple.withOpacity(0.55) : Colors.purple,
size: 16.0 * textScaleFactor,
semanticLabel: 'Saved',
if (!useSaveButton && postViewMedia.postView.saved)
WidgetSpan(
child: Padding(
padding: const EdgeInsets.only(
left: 8.0,
),
child: Icon(
Icons.star_rounded,
color: indicateRead && postViewMedia.postView.read ? Colors.purple.withOpacity(0.55) : Colors.purple,
size: 16.0 * textScaleFactor,
semanticLabel: 'Saved',
),
),
),
),
],
),
textScaleFactor: MediaQuery.of(context).textScaleFactor * textScaleFactor,
),
),
],
),
textScaleFactor: MediaQuery.of(context).textScaleFactor * textScaleFactor,
)),
Visibility(
visible: showTextContent && textContent.isNotEmpty,
child: Padding(
Expand Down
34 changes: 21 additions & 13 deletions lib/community/widgets/post_card_view_compact.dart
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,27 @@ class PostCardViewCompact extends StatelessWidget {
Text.rich(
TextSpan(
children: [
if (postViewMedia.postView.post.locked) ...[
WidgetSpan(
child: Icon(
Icons.lock,
color: indicateRead && postViewMedia.postView.read ? Colors.red.withOpacity(0.55) : Colors.red,
size: 17.0 * textScaleFactor,
)),
if (!postViewMedia.postView.post.featuredCommunity)
const WidgetSpan(
child: SizedBox(
width: 3,
)),
],
if (postViewMedia.postView.post.featuredCommunity)
WidgetSpan(
child: Icon(
Icons.push_pin_rounded,
size: 17.0 * textScaleFactor,
color: indicateRead && postViewMedia.postView.read ? Colors.green.withOpacity(0.55) : Colors.green,
),
),
TextSpan(
text: postViewMedia.postView.post.name,
style: theme.textTheme.bodyMedium?.copyWith(
Expand All @@ -114,19 +135,6 @@ class PostCardViewCompact extends StatelessWidget {
: (indicateRead && postViewMedia.postView.read ? theme.textTheme.bodyMedium?.color?.withOpacity(0.55) : null),
),
),
if (postViewMedia.postView.post.featuredCommunity)
WidgetSpan(
child: Padding(
padding: const EdgeInsets.only(
left: 8.0,
),
child: Icon(
Icons.push_pin_rounded,
size: 17.0 * textScaleFactor,
color: indicateRead && postViewMedia.postView.read ? Colors.green.withOpacity(0.55) : Colors.green,
),
),
),
if (postViewMedia.postView.saved)
WidgetSpan(
child: Padding(
Expand Down
10 changes: 8 additions & 2 deletions lib/core/enums/fab_action.dart
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ enum PostFabAction {
changeSort(),
replyToPost();

IconData getIcon({IconData? override}) {
IconData getIcon({IconData? override, bool postLocked = false}) {
if (override != null) {
return override;
}
Expand All @@ -155,11 +155,14 @@ enum PostFabAction {
case PostFabAction.changeSort:
return Icons.sort_rounded;
case PostFabAction.replyToPost:
if (postLocked) {
return Icons.lock;
}
return Icons.reply_rounded;
}
}

String getTitle(BuildContext context) {
String getTitle(BuildContext context, {bool postLocked = false}) {
switch (this) {
case PostFabAction.openFab:
return AppLocalizations.of(context)!.open;
Expand All @@ -168,6 +171,9 @@ enum PostFabAction {
case PostFabAction.changeSort:
return AppLocalizations.of(context)!.changeSort;
case PostFabAction.replyToPost:
if (postLocked) {
return AppLocalizations.of(context)!.postLocked;
}
return AppLocalizations.of(context)!.replyToPost;
}
}
Expand Down
1 change: 1 addition & 0 deletions lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"editComment": "Edit Comment",
"reply": "Reply",
"comment": "Comment",
"postLocked": "Post is locked, replies not allowed",
"replyingTo": "Replying to {author}",
"unexpectedError": "Unexpected Error",
"fetchAccountError": "Could not determine account",
Expand Down
1 change: 1 addition & 0 deletions lib/l10n/app_es.arb
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"editComment": "Editar comentario",
"reply": "Responder",
"comment": "Comentario",
"postLocked": "Post is locked, replies not allowed",
"replyingTo": "Responder a {author}",
"unexpectedError": "Error inesperado",
"fetchAccountError": "No se pudo determinar la cuenta",
Expand Down
1 change: 1 addition & 0 deletions lib/l10n/app_fi.arb
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"editComment": "Edit Comment",
"reply": "Reply",
"comment": "Comment",
"postLocked": "Post is locked, replies not allowed",
"replyingTo": "Replying to {author}",
"unexpectedError": "Unexpected Error",
"fetchAccountError": "Could not determine account",
Expand Down
1 change: 1 addition & 0 deletions lib/l10n/app_pl.arb
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"editComment": "Edytuj komentarz",
"reply": "Odpowiedz",
"comment": "Comment",
"postLocked": "Post is locked, replies not allowed",
"replyingTo": "Replying to {author}",
"unexpectedError": "Wystąpił niespodziewany błąd",
"fetchAccountError": "Nie można określić konta",
Expand Down
1 change: 1 addition & 0 deletions lib/l10n/app_sv.arb
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"editComment": "Edit Comment",
"reply": "Reply",
"comment": "Comment",
"postLocked": "Post is locked, replies not allowed",
"replyingTo": "Replying to {author}",
"unexpectedError": "Unexpected Error",
"fetchAccountError": "Could not determine account",
Expand Down
20 changes: 13 additions & 7 deletions lib/post/pages/post_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ class _PostPageState extends State<PostPage> {
bool enableChangeSort = thunderState.postFabEnableChangeSort;
bool enableReplyToPost = thunderState.postFabEnableReplyToPost;

bool postLocked = widget.postView?.postView.post.locked == true;

PostFabAction singlePressAction = thunderState.postFabSinglePressAction;
PostFabAction longPressAction = thunderState.postFabLongPressAction;

Expand Down Expand Up @@ -192,8 +194,8 @@ class _PostPageState extends State<PostPage> {
centered: combineNavAndFab,
distance: 60,
icon: Icon(
singlePressAction.getIcon(override: singlePressAction == PostFabAction.changeSort ? sortTypeIcon : null),
semanticLabel: singlePressAction.getTitle(context),
singlePressAction.getIcon(override: singlePressAction == PostFabAction.changeSort ? sortTypeIcon : null, postLocked: postLocked),
semanticLabel: singlePressAction.getTitle(context, postLocked: postLocked),
size: 35,
),
onPressed: () => singlePressAction.execute(
Expand All @@ -209,7 +211,7 @@ class _PostPageState extends State<PostPage> {
: singlePressAction == PostFabAction.changeSort
? () => showSortBottomSheet(context, state)
: singlePressAction == PostFabAction.replyToPost
? () => replyToPost(context)
? () => replyToPost(context, postLocked: postLocked)
: null),
onLongPress: () => longPressAction.execute(
context: context,
Expand All @@ -224,7 +226,7 @@ class _PostPageState extends State<PostPage> {
: longPressAction == PostFabAction.changeSort
? () => showSortBottomSheet(context, state)
: longPressAction == PostFabAction.replyToPost
? () => replyToPost(context)
? () => replyToPost(context, postLocked: postLocked)
: null),
children: [
if (enableReplyToPost)
Expand All @@ -233,12 +235,12 @@ class _PostPageState extends State<PostPage> {
onPressed: () {
HapticFeedback.mediumImpact();
PostFabAction.replyToPost.execute(
override: () => replyToPost(context),
override: () => replyToPost(context, postLocked: postLocked),
);
},
title: PostFabAction.replyToPost.getTitle(context),
icon: Icon(
PostFabAction.replyToPost.getIcon(),
postLocked ? Icons.lock : PostFabAction.replyToPost.getIcon(),
),
),
if (enableChangeSort)
Expand Down Expand Up @@ -420,7 +422,11 @@ class _PostPageState extends State<PostPage> {
);
}

void replyToPost(BuildContext context) {
void replyToPost(BuildContext context, {bool postLocked = false}) {
if (postLocked) {
showSnackbar(context, AppLocalizations.of(context)!.postLocked);
return;
}
PostBloc postBloc = context.read<PostBloc>();
ThunderBloc thunderBloc = context.read<ThunderBloc>();
AuthBloc authBloc = context.read<AuthBloc>();
Expand Down
11 changes: 10 additions & 1 deletion lib/post/widgets/post_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import 'package:thunder/user/utils/special_user_checks.dart';
import 'package:thunder/utils/instance.dart';
import 'package:thunder/utils/numbers.dart';
import 'package:thunder/utils/swipe.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:thunder/shared/snackbar.dart';

class PostSubview extends StatelessWidget {
final PostViewMedia postViewMedia;
Expand Down Expand Up @@ -272,6 +274,11 @@ class PostSubview extends StatelessWidget {
child: IconButton(
onPressed: isUserLoggedIn
? () {
if (postView.post.locked) {
showSnackbar(context, AppLocalizations.of(context)!.postLocked);
return;
}

PostBloc postBloc = context.read<PostBloc>();
ThunderBloc thunderBloc = context.read<ThunderBloc>();
account_bloc.AccountBloc accountBloc = context.read<account_bloc.AccountBloc>();
Expand All @@ -294,7 +301,9 @@ class PostSubview extends StatelessWidget {
);
}
: null,
icon: const Icon(Icons.reply_rounded, semanticLabel: 'Reply'),
icon: postView.post.locked
? Icon(Icons.lock, semanticLabel: AppLocalizations.of(context)!.postLocked, color: Colors.red)
: Icon(Icons.reply_rounded, semanticLabel: AppLocalizations.of(context)!.reply),
),
),
Expanded(
Expand Down