@@ -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.
166218void showTopicActionSheet (BuildContext context, {
167219 required int channelId,
0 commit comments