@@ -100,13 +100,13 @@ abstract class MessageActionSheetMenuItemButton extends StatelessWidget {
100100 IconData get icon;
101101 String label (ZulipLocalizations zulipLocalizations);
102102
103- /// Called when the button is pressed.
103+ /// Called when the button is pressed, after dismissing the action sheet .
104104 ///
105- /// Generally this method's implementation should begin by dismissing the
106- /// action sheet with [NavigatorState.pop] .
107- /// After that step, the given `context` may no longer be mounted;
108- /// operations that need a [BuildContext] should typically use [pageContext] .
109- void onPressed (BuildContext context );
105+ /// If the action may take a long time, this method is responsible for
106+ /// arranging any form of progress feedback that may be desired .
107+ ///
108+ /// For operations that need a [BuildContext] , see [pageContext] .
109+ void onPressed ();
110110
111111 final Message message;
112112
@@ -124,6 +124,15 @@ abstract class MessageActionSheetMenuItemButton extends StatelessWidget {
124124 return MessageListPage .ancestorOf (pageContext);
125125 }
126126
127+ void _handlePressed (BuildContext context) {
128+ // Dismiss the enclosing action sheet immediately,
129+ // for swift UI feedback that the user's selection was received.
130+ Navigator .of (context).pop ();
131+
132+ assert (pageContext.mounted);
133+ onPressed ();
134+ }
135+
127136 @override
128137 Widget build (BuildContext context) {
129138 final designVariables = DesignVariables .of (context);
@@ -137,7 +146,7 @@ abstract class MessageActionSheetMenuItemButton extends StatelessWidget {
137146 ).copyWith (backgroundColor: WidgetStateColor .resolveWith ((states) =>
138147 designVariables.contextMenuItemBg.withValues (
139148 alpha: states.contains (WidgetState .pressed) ? 0.20 : 0.12 ))),
140- onPressed: () => onPressed (context),
149+ onPressed: () => _handlePressed (context),
141150 child: Text (label (zulipLocalizations),
142151 style: const TextStyle (fontSize: 20 , height: 24 / 20 )
143152 .merge (weightVariableTextStyle (context, wght: 600 )),
@@ -186,8 +195,7 @@ class AddThumbsUpButton extends MessageActionSheetMenuItemButton {
186195 return 'React with 👍' ; // TODO(i18n) skip translation for now
187196 }
188197
189- @override void onPressed (BuildContext context) async {
190- Navigator .of (context).pop ();
198+ @override void onPressed () async {
191199 String ? errorMessage;
192200 try {
193201 await addReaction (PerAccountStoreWidget .of (pageContext).connection,
@@ -231,8 +239,7 @@ class StarButton extends MessageActionSheetMenuItemButton {
231239 : zulipLocalizations.actionSheetOptionStarMessage;
232240 }
233241
234- @override void onPressed (BuildContext context) async {
235- Navigator .of (context).pop ();
242+ @override void onPressed () async {
236243 final zulipLocalizations = ZulipLocalizations .of (pageContext);
237244 final op = message.flags.contains (MessageFlag .starred)
238245 ? UpdateMessageFlagsOp .remove
@@ -325,10 +332,7 @@ class QuoteAndReplyButton extends MessageActionSheetMenuItemButton {
325332 return zulipLocalizations.actionSheetOptionQuoteAndReply;
326333 }
327334
328- @override void onPressed (BuildContext context) async {
329- // Close the message action sheet. We'll show the request progress
330- // in the compose-box content input with a "[Quoting…]" placeholder.
331- Navigator .of (context).pop ();
335+ @override void onPressed () async {
332336 final zulipLocalizations = ZulipLocalizations .of (pageContext);
333337
334338 // This will be null only if the compose box disappeared after the
@@ -343,6 +347,9 @@ class QuoteAndReplyButton extends MessageActionSheetMenuItemButton {
343347 ) {
344348 topicController.value = TextEditingValue (text: message.topic);
345349 }
350+
351+ // This inserts a "[Quoting…]" placeholder into the content input,
352+ // giving the user a form of progress feedback.
346353 final tag = composeBoxController.contentController
347354 .registerQuoteAndReplyStart (PerAccountStoreWidget .of (pageContext),
348355 message: message,
@@ -388,8 +395,7 @@ class MarkAsUnreadButton extends MessageActionSheetMenuItemButton {
388395 return zulipLocalizations.actionSheetOptionMarkAsUnread;
389396 }
390397
391- @override void onPressed (BuildContext context) async {
392- Navigator .of (context).pop ();
398+ @override void onPressed () async {
393399 unawaited (markNarrowAsUnreadFromMessage (pageContext, message, narrow));
394400 }
395401}
@@ -408,11 +414,11 @@ class CopyMessageTextButton extends MessageActionSheetMenuItemButton {
408414 return zulipLocalizations.actionSheetOptionCopyMessageText;
409415 }
410416
411- @override void onPressed (BuildContext context ) async {
412- // Close the message action sheet. We won 't be showing request progress,
413- // but hopefully it won't take long at all, and
417+ @override void onPressed () async {
418+ // This action doesn 't show request progress.
419+ // But hopefully it won't take long at all; and
414420 // fetchRawContentWithFeedback has a TODO for giving feedback if it does.
415- Navigator . of (context). pop ();
421+
416422 final zulipLocalizations = ZulipLocalizations .of (pageContext);
417423
418424 final rawContent = await fetchRawContentWithFeedback (
@@ -445,8 +451,7 @@ class CopyMessageLinkButton extends MessageActionSheetMenuItemButton {
445451 return zulipLocalizations.actionSheetOptionCopyMessageLink;
446452 }
447453
448- @override void onPressed (BuildContext context) {
449- Navigator .of (context).pop ();
454+ @override void onPressed () {
450455 final zulipLocalizations = ZulipLocalizations .of (pageContext);
451456
452457 final store = PerAccountStoreWidget .of (pageContext);
@@ -479,15 +484,16 @@ class ShareButton extends MessageActionSheetMenuItemButton {
479484 return zulipLocalizations.actionSheetOptionShare;
480485 }
481486
482- @override void onPressed (BuildContext context) async {
483- // Close the message action sheet; we're about to show the share
484- // sheet. (We could do this after the sharing Future settles
485- // with [ShareResultStatus.success], but on iOS I get impatient with
486- // how slowly our action sheet dismisses in that case.)
487+ @override void onPressed () async {
487488 // TODO(#591): Fix iOS bug where if the keyboard was open before the call
488489 // to `showMessageActionSheet`, it reappears briefly between
489490 // the `pop` of the action sheet and the appearance of the share sheet.
490- Navigator .of (context).pop ();
491+ //
492+ // (Alternatively we could delay the [NavigatorState.pop] that
493+ // dismisses the action sheet until after the sharing Future settles
494+ // with [ShareResultStatus.success]. But on iOS one gets impatient with
495+ // how slowly our action sheet dismisses in that case.)
496+
491497 final zulipLocalizations = ZulipLocalizations .of (pageContext);
492498
493499 final rawContent = await fetchRawContentWithFeedback (
0 commit comments