Skip to content

Commit 72ac73d

Browse files
author
chimnayajith
committed
action_sheet: Add channel action sheet with mark as read option
Fixes: zulip#1226
1 parent e905a72 commit 72ac73d

13 files changed

+272
-0
lines changed

Diff for: assets/l10n/app_en.arb

+8
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@
7676
"@permissionsDeniedReadExternalStorage": {
7777
"description": "Message for dialog asking the user to grant permissions for external storage read access."
7878
},
79+
"actionSheetOptionMarkChannelAsRead": "Mark channel as read",
80+
"@actionSheetOptionMarkChannelAsRead": {
81+
"description": "Label for marking a channel as read."
82+
},
7983
"actionSheetOptionMuteTopic": "Mute topic",
8084
"@actionSheetOptionMuteTopic": {
8185
"description": "Label for muting a topic on action sheet."
@@ -245,6 +249,10 @@
245249
"url": {"type": "String", "example": "https://chat.example.com"}
246250
}
247251
},
252+
"errorMarkChannelAsReadFailed": "Failed to mark channel as read",
253+
"@errorMarkChannelAsReadFailed": {
254+
"description": "Error message when marking a channel as read."
255+
},
248256
"errorMuteTopicFailed": "Failed to mute topic",
249257
"@errorMuteTopicFailed": {
250258
"description": "Error message when muting a topic failed."

Diff for: lib/generated/l10n/zulip_localizations.dart

+12
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,12 @@ abstract class ZulipLocalizations {
219219
/// **'To upload files, please grant Zulip additional permissions in Settings.'**
220220
String get permissionsDeniedReadExternalStorage;
221221

222+
/// Label for marking a channel as read.
223+
///
224+
/// In en, this message translates to:
225+
/// **'Mark channel as read'**
226+
String get actionSheetOptionMarkChannelAsRead;
227+
222228
/// Label for muting a topic on action sheet.
223229
///
224230
/// In en, this message translates to:
@@ -423,6 +429,12 @@ abstract class ZulipLocalizations {
423429
/// **'Link could not be opened: {url}'**
424430
String errorCouldNotOpenLink(String url);
425431

432+
/// Error message when marking a channel as read.
433+
///
434+
/// In en, this message translates to:
435+
/// **'Failed to mark channel as read'**
436+
String get errorMarkChannelAsReadFailed;
437+
426438
/// Error message when muting a topic failed.
427439
///
428440
/// In en, this message translates to:

Diff for: lib/generated/l10n/zulip_localizations_ar.dart

+6
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ class ZulipLocalizationsAr extends ZulipLocalizations {
6767
@override
6868
String get permissionsDeniedReadExternalStorage => 'To upload files, please grant Zulip additional permissions in Settings.';
6969

70+
@override
71+
String get actionSheetOptionMarkChannelAsRead => 'Mark channel as read';
72+
7073
@override
7174
String get actionSheetOptionMuteTopic => 'Mute topic';
7275

@@ -199,6 +202,9 @@ class ZulipLocalizationsAr extends ZulipLocalizations {
199202
return 'Link could not be opened: $url';
200203
}
201204

205+
@override
206+
String get errorMarkChannelAsReadFailed => 'Failed to mark channel as read';
207+
202208
@override
203209
String get errorMuteTopicFailed => 'Failed to mute topic';
204210

Diff for: lib/generated/l10n/zulip_localizations_en.dart

+6
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ class ZulipLocalizationsEn extends ZulipLocalizations {
6767
@override
6868
String get permissionsDeniedReadExternalStorage => 'To upload files, please grant Zulip additional permissions in Settings.';
6969

70+
@override
71+
String get actionSheetOptionMarkChannelAsRead => 'Mark channel as read';
72+
7073
@override
7174
String get actionSheetOptionMuteTopic => 'Mute topic';
7275

@@ -199,6 +202,9 @@ class ZulipLocalizationsEn extends ZulipLocalizations {
199202
return 'Link could not be opened: $url';
200203
}
201204

205+
@override
206+
String get errorMarkChannelAsReadFailed => 'Failed to mark channel as read';
207+
202208
@override
203209
String get errorMuteTopicFailed => 'Failed to mute topic';
204210

Diff for: lib/generated/l10n/zulip_localizations_ja.dart

+6
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ class ZulipLocalizationsJa extends ZulipLocalizations {
6767
@override
6868
String get permissionsDeniedReadExternalStorage => 'To upload files, please grant Zulip additional permissions in Settings.';
6969

70+
@override
71+
String get actionSheetOptionMarkChannelAsRead => 'Mark channel as read';
72+
7073
@override
7174
String get actionSheetOptionMuteTopic => 'Mute topic';
7275

@@ -199,6 +202,9 @@ class ZulipLocalizationsJa extends ZulipLocalizations {
199202
return 'Link could not be opened: $url';
200203
}
201204

205+
@override
206+
String get errorMarkChannelAsReadFailed => 'Failed to mark channel as read';
207+
202208
@override
203209
String get errorMuteTopicFailed => 'Failed to mute topic';
204210

Diff for: lib/generated/l10n/zulip_localizations_nb.dart

+6
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ class ZulipLocalizationsNb extends ZulipLocalizations {
6767
@override
6868
String get permissionsDeniedReadExternalStorage => 'To upload files, please grant Zulip additional permissions in Settings.';
6969

70+
@override
71+
String get actionSheetOptionMarkChannelAsRead => 'Mark channel as read';
72+
7073
@override
7174
String get actionSheetOptionMuteTopic => 'Mute topic';
7275

@@ -199,6 +202,9 @@ class ZulipLocalizationsNb extends ZulipLocalizations {
199202
return 'Link could not be opened: $url';
200203
}
201204

205+
@override
206+
String get errorMarkChannelAsReadFailed => 'Failed to mark channel as read';
207+
202208
@override
203209
String get errorMuteTopicFailed => 'Failed to mute topic';
204210

Diff for: lib/generated/l10n/zulip_localizations_pl.dart

+6
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ class ZulipLocalizationsPl extends ZulipLocalizations {
6767
@override
6868
String get permissionsDeniedReadExternalStorage => 'Aby odebrać pliki Zulip musi uzyskać dodatkowe uprawnienia w Ustawieniach.';
6969

70+
@override
71+
String get actionSheetOptionMarkChannelAsRead => 'Mark channel as read';
72+
7073
@override
7174
String get actionSheetOptionMuteTopic => 'Wycisz wątek';
7275

@@ -199,6 +202,9 @@ class ZulipLocalizationsPl extends ZulipLocalizations {
199202
return 'Link could not be opened: $url';
200203
}
201204

205+
@override
206+
String get errorMarkChannelAsReadFailed => 'Failed to mark channel as read';
207+
202208
@override
203209
String get errorMuteTopicFailed => 'Wyciszenie bez powodzenia';
204210

Diff for: lib/generated/l10n/zulip_localizations_ru.dart

+6
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ class ZulipLocalizationsRu extends ZulipLocalizations {
6767
@override
6868
String get permissionsDeniedReadExternalStorage => 'Для загрузки файлов, пожалуйста, предоставьте Zulip дополнительные разрешения в настройках.';
6969

70+
@override
71+
String get actionSheetOptionMarkChannelAsRead => 'Mark channel as read';
72+
7073
@override
7174
String get actionSheetOptionMuteTopic => 'Отключить тему';
7275

@@ -199,6 +202,9 @@ class ZulipLocalizationsRu extends ZulipLocalizations {
199202
return 'Link could not be opened: $url';
200203
}
201204

205+
@override
206+
String get errorMarkChannelAsReadFailed => 'Failed to mark channel as read';
207+
202208
@override
203209
String get errorMuteTopicFailed => 'Не удалось отключить тему';
204210

Diff for: lib/generated/l10n/zulip_localizations_sk.dart

+6
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ class ZulipLocalizationsSk extends ZulipLocalizations {
6767
@override
6868
String get permissionsDeniedReadExternalStorage => 'To upload files, please grant Zulip additional permissions in Settings.';
6969

70+
@override
71+
String get actionSheetOptionMarkChannelAsRead => 'Mark channel as read';
72+
7073
@override
7174
String get actionSheetOptionMuteTopic => 'Stlmiť tému';
7275

@@ -199,6 +202,9 @@ class ZulipLocalizationsSk extends ZulipLocalizations {
199202
return 'Link could not be opened: $url';
200203
}
201204

205+
@override
206+
String get errorMarkChannelAsReadFailed => 'Failed to mark channel as read';
207+
202208
@override
203209
String get errorMuteTopicFailed => 'Nepodarilo sa ztíšiť tému';
204210

Diff for: lib/widgets/action_sheet.dart

+52
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,58 @@ class ActionSheetCancelButton extends StatelessWidget {
162162
}
163163
}
164164

165+
/// Show a sheet of actions you can take on a channel.
166+
void showChannelActionSheet(BuildContext context, {
167+
required int streamId,
168+
}) {
169+
final store = PerAccountStoreWidget.of(context);
170+
171+
final optionButtons = <ActionSheetMenuItemButton>[];
172+
final unreadCount = store.unreads.countInChannelNarrow(streamId);
173+
if (unreadCount > 0) {
174+
optionButtons.add(
175+
MarkChannelAsReadButton(
176+
streamId: streamId,
177+
pageContext: context,
178+
),
179+
);
180+
}
181+
if (optionButtons.isEmpty) {
182+
// TODO(a11y): This case makes a no-op gesture handler; as a consequence,
183+
// we're presenting some UI (to people who use screen-reader software) as
184+
// though it offers a gesture interaction that it doesn't meaningfully
185+
// offer, which is confusing. The solution here is probably to remove this
186+
// is-empty case by having at least one button that's always present,
187+
// such as "copy link to channel".
188+
return;
189+
}
190+
_showActionSheet(context, optionButtons: optionButtons);
191+
}
192+
193+
class MarkChannelAsReadButton extends ActionSheetMenuItemButton {
194+
const MarkChannelAsReadButton({
195+
super.key,
196+
required this.streamId,
197+
required super.pageContext
198+
});
199+
200+
final int streamId;
201+
202+
@override
203+
IconData get icon => ZulipIcons.message_checked;
204+
205+
@override
206+
String label(ZulipLocalizations zulipLocalizations) {
207+
return zulipLocalizations.actionSheetOptionMarkChannelAsRead;
208+
}
209+
210+
@override
211+
void onPressed() async {
212+
final narrow = ChannelNarrow(streamId);
213+
await ZulipAction.markNarrowAsRead(pageContext, narrow);
214+
}
215+
}
216+
165217
/// Show a sheet of actions you can take on a topic.
166218
void showTopicActionSheet(BuildContext context, {
167219
required int channelId,

Diff for: lib/widgets/inbox.dart

+13
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ abstract class _HeaderItem extends StatelessWidget {
255255
}
256256

257257
Future<void> onRowTap();
258+
Future<void> onLongPress();
258259

259260
@override
260261
Widget build(BuildContext context) {
@@ -272,6 +273,7 @@ abstract class _HeaderItem extends StatelessWidget {
272273
// But that's in tension with the Figma, which gives these header rows
273274
// 40px min height.
274275
onTap: onCollapseButtonTap,
276+
onLongPress: onLongPress,
275277
child: Row(crossAxisAlignment: CrossAxisAlignment.center, children: [
276278
Padding(padding: const EdgeInsets.all(10),
277279
child: Icon(size: 20, color: designVariables.sectionCollapseIcon,
@@ -330,6 +332,12 @@ class _AllDmsHeaderItem extends _HeaderItem {
330332
pageState.allDmsCollapsed = !collapsed;
331333
}
332334
@override Future<void> onRowTap() => onCollapseButtonTap(); // TODO open all-DMs narrow?
335+
336+
@override
337+
Future<void> onLongPress() async {
338+
// TODO(#1272) action sheet for DM conversation
339+
return;
340+
}
333341
}
334342

335343
class _AllDmsSection extends StatelessWidget {
@@ -464,6 +472,11 @@ class _StreamHeaderItem extends _HeaderItem {
464472
}
465473
}
466474
@override Future<void> onRowTap() => onCollapseButtonTap(); // TODO open channel narrow
475+
476+
@override
477+
Future<void> onLongPress() async {
478+
showChannelActionSheet(sectionContext, streamId: subscription.streamId);
479+
}
467480
}
468481

469482
class _StreamSection extends StatelessWidget {

Diff for: lib/widgets/subscription_list.dart

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import '../api/model/model.dart';
44
import '../generated/l10n/zulip_localizations.dart';
55
import '../model/narrow.dart';
66
import '../model/unreads.dart';
7+
import 'action_sheet.dart';
78
import 'icons.dart';
89
import 'message_list.dart';
910
import 'store.dart';
@@ -230,6 +231,7 @@ class SubscriptionItem extends StatelessWidget {
230231
MessageListPage.buildRoute(context: context,
231232
narrow: ChannelNarrow(subscription.streamId)));
232233
},
234+
onLongPress: () => showChannelActionSheet(context, streamId: subscription.streamId),
233235
child: Row(crossAxisAlignment: CrossAxisAlignment.center, children: [
234236
const SizedBox(width: 16),
235237
Padding(

0 commit comments

Comments
 (0)