Skip to content

Commit

Permalink
Add ability to sort inbox, adjust top bar actions for inbox page (#1373)
Browse files Browse the repository at this point in the history
* sort inbox

* formart changed lines

* fixed mark all as read not updating state properly, shifted app actions to conform with md3 guidelines

---------

Co-authored-by: Hamlet Jiang Su <hamlet.jiangsu@outlook.com>
  • Loading branch information
ggichure and hjiangsu authored Jul 8, 2024
1 parent 4238230 commit a5d7619
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 37 deletions.
29 changes: 23 additions & 6 deletions lib/inbox/bloc/inbox_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class InboxBloc extends Bloc<InboxEvent, InboxState> {
auth: account!.jwt!,
unreadOnly: !event.showAll,
limit: limit,
sort: CommentSortType.new_,
sort: event.commentSortType,
page: 1,
),
);
Expand All @@ -91,7 +91,7 @@ class InboxBloc extends Bloc<InboxEvent, InboxState> {
GetPersonMentions(
auth: account!.jwt!,
unreadOnly: !event.showAll,
sort: CommentSortType.new_,
sort: event.commentSortType,
limit: limit,
page: 1,
),
Expand All @@ -113,15 +113,15 @@ class InboxBloc extends Bloc<InboxEvent, InboxState> {
auth: account!.jwt!,
unreadOnly: !event.showAll,
limit: limit,
sort: CommentSortType.new_,
sort: event.commentSortType,
page: 1,
),
);
getPersonMentionsResponse = await lemmy.run(
GetPersonMentions(
auth: account.jwt!,
unreadOnly: !event.showAll,
sort: CommentSortType.new_,
sort: event.commentSortType,
limit: limit,
page: 1,
),
Expand Down Expand Up @@ -176,7 +176,7 @@ class InboxBloc extends Bloc<InboxEvent, InboxState> {
auth: account!.jwt!,
unreadOnly: state.showUnreadOnly,
limit: limit,
sort: CommentSortType.new_,
sort: event.commentSortType,
page: state.inboxReplyPage,
),
);
Expand All @@ -188,7 +188,7 @@ class InboxBloc extends Bloc<InboxEvent, InboxState> {
GetPersonMentions(
auth: account!.jwt!,
unreadOnly: state.showUnreadOnly,
sort: CommentSortType.new_,
sort: event.commentSortType,
limit: limit,
page: state.inboxMentionPage,
),
Expand Down Expand Up @@ -443,6 +443,23 @@ class InboxBloc extends Bloc<InboxEvent, InboxState> {

if (account?.jwt == null) return emit(state.copyWith(status: InboxStatus.success));
await lemmy.run(MarkAllAsRead(auth: account!.jwt!));

// Update all the replies, mentions, and messages to be read locally
List<CommentReplyView> updatedReplies = state.replies.map((commentReplyView) => commentReplyView.copyWith(commentReply: commentReplyView.commentReply.copyWith(read: true))).toList();
List<PersonMentionView> updatedMentions = state.mentions.map((personMentionView) => personMentionView.copyWith(personMention: personMentionView.personMention.copyWith(read: true))).toList();
List<PrivateMessageView> updatedPrivateMessages =
state.privateMessages.map((privateMessageView) => privateMessageView.copyWith(privateMessage: privateMessageView.privateMessage.copyWith(read: true))).toList();

return emit(state.copyWith(
status: InboxStatus.success,
replies: updatedReplies,
mentions: updatedMentions,
privateMessages: updatedPrivateMessages,
totalUnreadCount: 0,
repliesUnreadCount: 0,
mentionsUnreadCount: 0,
messagesUnreadCount: 0,
));
} catch (e) {
emit(state.copyWith(status: InboxStatus.failure, errorMessage: e.toString()));
}
Expand Down
5 changes: 4 additions & 1 deletion lib/inbox/bloc/inbox_event.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ class GetInboxEvent extends InboxEvent {
/// If true, it will reset the inbox and re-fetch everything depending on [inboxType]
final bool reset;

const GetInboxEvent({this.inboxType, this.showAll = false, this.reset = false});
/// The comment sort type to use for replies/mentions
final CommentSortType commentSortType;

const GetInboxEvent({this.inboxType, this.showAll = false, this.reset = false, this.commentSortType = CommentSortType.new_});
}

class InboxItemActionEvent extends InboxEvent {
Expand Down
87 changes: 60 additions & 27 deletions lib/inbox/pages/inbox_page.dart
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

import 'package:flutter_bloc/flutter_bloc.dart';
import "package:flutter_gen/gen_l10n/app_localizations.dart";
import 'package:lemmy_api_client/v3.dart';

import 'package:thunder/core/auth/bloc/auth_bloc.dart';
import 'package:thunder/core/singletons/lemmy_client.dart';
import 'package:thunder/inbox/bloc/inbox_bloc.dart';
import 'package:thunder/inbox/enums/inbox_type.dart';
import 'package:thunder/inbox/widgets/inbox_mentions_view.dart';
import 'package:thunder/inbox/widgets/inbox_private_messages_view.dart';
import 'package:thunder/inbox/widgets/inbox_replies_view.dart';
import 'package:thunder/shared/comment_sort_picker.dart';
import 'package:thunder/shared/dialogs.dart';
import 'package:thunder/shared/snackbar.dart';
import 'package:thunder/shared/thunder_popup_menu_item.dart';

/// A widget that displays the user's inbox replies, mentions, and private messages.
class InboxPage extends StatefulWidget {
Expand All @@ -30,6 +35,9 @@ class _InboxPageState extends State<InboxPage> with SingleTickerProviderStateMix
/// Whether to show all inbox mentions, replies, and private messages or not
bool showAll = false;

/// The current inbox sort type. This only applies to replies and mentions, since messages does not have a sort type
CommentSortType commentSortType = CommentSortType.new_;

/// The current account id. If this changes, and the current view is active, reload the view
int? accountId;

Expand Down Expand Up @@ -64,6 +72,25 @@ class _InboxPageState extends State<InboxPage> with SingleTickerProviderStateMix
super.dispose();
}

/// Displays the sort options bottom sheet for comments, since replies and mentions are technically comments
void showSortBottomSheet() {
final AppLocalizations l10n = AppLocalizations.of(context)!;

showModalBottomSheet<void>(
showDragHandle: true,
context: context,
builder: (builderContext) => CommentSortPicker(
title: l10n.sortOptions,
onSelect: (selected) async {
setState(() => commentSortType = selected.payload);
context.read<InboxBloc>().add(GetInboxEvent(inboxType: inboxType, reset: true, showAll: showAll, commentSortType: selected.payload));
},
previouslySelected: commentSortType,
minimumVersion: LemmyClient.instance.version,
),
);
}

@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
Expand Down Expand Up @@ -104,38 +131,44 @@ class _InboxPageState extends State<InboxPage> with SingleTickerProviderStateMix
forceElevated: innerBoxIsScrolled,
title: Text(l10n.inbox),
actions: [
IconButton(
icon: Icon(Icons.checklist, semanticLabel: l10n.readAll),
onPressed: () async {
await showThunderDialog<bool>(
context: context,
title: l10n.confirmMarkAllAsReadTitle,
contentText: l10n.confirmMarkAllAsReadBody,
onSecondaryButtonPressed: (dialogContext) => Navigator.of(dialogContext).pop(),
secondaryButtonText: l10n.cancel,
onPrimaryButtonPressed: (dialogContext, _) {
Navigator.of(dialogContext).pop();
context.read<InboxBloc>().add(MarkAllAsReadEvent());
},
primaryButtonText: l10n.markAllAsRead,
);
},
),
IconButton(
icon: Icon(Icons.refresh_rounded, semanticLabel: l10n.refresh),
onPressed: () => context.read<InboxBloc>().add(GetInboxEvent(inboxType: inboxType, reset: true, showAll: showAll)),
),
FilterChip(
shape: const StadiumBorder(),
visualDensity: VisualDensity.compact,
label: Text(l10n.showAll),
selected: showAll,
onSelected: (bool selected) {
setState(() => showAll = !showAll);
context.read<InboxBloc>().add(GetInboxEvent(inboxType: inboxType, reset: true, showAll: selected));
},
IconButton(onPressed: () => showSortBottomSheet(), icon: Icon(Icons.sort, semanticLabel: l10n.sortBy)),
PopupMenuButton(
onOpened: () => HapticFeedback.mediumImpact(),
itemBuilder: (context) => [
ThunderPopupMenuItem(
onTap: () async {
HapticFeedback.mediumImpact();
await showThunderDialog<bool>(
context: context,
title: l10n.confirmMarkAllAsReadTitle,
contentText: l10n.confirmMarkAllAsReadBody,
onSecondaryButtonPressed: (dialogContext) => Navigator.of(dialogContext).pop(),
secondaryButtonText: l10n.cancel,
onPrimaryButtonPressed: (dialogContext, _) {
Navigator.of(dialogContext).pop();
context.read<InboxBloc>().add(MarkAllAsReadEvent());
},
primaryButtonText: l10n.markAllAsRead,
);
},
icon: Icons.checklist,
title: l10n.markAllAsRead,
),
ThunderPopupMenuItem(
onTap: () async {
HapticFeedback.mediumImpact();
context.read<InboxBloc>().add(GetInboxEvent(inboxType: inboxType, reset: true, showAll: !showAll));
setState(() => showAll = !showAll);
},
icon: showAll ? Icons.mark_as_unread : Icons.all_inbox_rounded,
title: showAll ? l10n.showUnreadOnly : l10n.showAll,
),
],
),
const SizedBox(width: 16.0),
],
bottom: TabBar(
controller: tabController,
Expand Down
10 changes: 7 additions & 3 deletions lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@
"@confirmMarkAllAsReadBody": {
"description": "The body of the confirm mark all as read dialog"
},
"confirmMarkAllAsReadTitle": "Mark All As Read?",
"confirmMarkAllAsReadTitle": "Mark all as read?",
"@confirmMarkAllAsReadTitle": {
"description": "The title of the confirm mark all as read dialog"
},
Expand Down Expand Up @@ -1177,7 +1177,7 @@
},
"manageAccounts": "Manage Accounts",
"@manageAccounts": {},
"markAllAsRead": "Mark All As Read",
"markAllAsRead": "Mark all as read",
"@markAllAsRead": {
"description": "The mark all as read action"
},
Expand Down Expand Up @@ -1983,7 +1983,7 @@
"@shareUserLinkLocal": {
"description": "Menu item for sharing a local user link"
},
"showAll": "Show All",
"showAll": "Show all",
"@showAll": {},
"showBotAccounts": "Show Bot Accounts",
"@showBotAccounts": {
Expand Down Expand Up @@ -2087,6 +2087,10 @@
"@showThumbnailPreviewOnRight": {
"description": "Toggle to show thumbnails on the right side."
},
"showUnreadOnly": "Show unread only",
"@showUnreadOnly": {
"description": "Show unread replies/mentions/messages only"
},
"showUpdateChangelogs": "Show Update Changelogs",
"@showUpdateChangelogs": {
"description": "Setting for showing changelogs after updates"
Expand Down

0 comments on commit a5d7619

Please sign in to comment.