@@ -163,6 +163,57 @@ class ActionSheetCancelButton extends StatelessWidget {
163163 }
164164}
165165
166+ /// Show a sheet of actions you can take on a channel.
167+ ///
168+ /// Needs a [PageRoot] ancestor.
169+ void showChannelActionSheet (BuildContext context, {
170+ required int channelId,
171+ }) {
172+ final pageContext = PageRoot .contextOf (context);
173+ final store = PerAccountStoreWidget .of (pageContext);
174+
175+ final optionButtons = < ActionSheetMenuItemButton > [];
176+ final unreadCount = store.unreads.countInChannelNarrow (channelId);
177+ if (unreadCount > 0 ) {
178+ optionButtons.add (
179+ MarkChannelAsReadButton (pageContext: pageContext, channelId: channelId));
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 (pageContext, optionButtons: optionButtons);
191+ }
192+
193+ class MarkChannelAsReadButton extends ActionSheetMenuItemButton {
194+ const MarkChannelAsReadButton ({
195+ super .key,
196+ required this .channelId,
197+ required super .pageContext,
198+ });
199+
200+ final int channelId;
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 (channelId);
213+ await ZulipAction .markNarrowAsRead (pageContext, narrow);
214+ }
215+ }
216+
166217/// Show a sheet of actions you can take on a topic.
167218///
168219/// Needs a [PageRoot] ancestor.
0 commit comments