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