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