@@ -87,6 +87,53 @@ class ShareButton extends MessageActionSheetMenuItemButton {
87
87
};
88
88
}
89
89
90
+ /// Fetch and return the raw Markdown content for [messageId] ,
91
+ /// showing an error dialog on failure.
92
+ Future <String ?> fetchRawContentWithFeedback ({
93
+ required BuildContext context,
94
+ required int messageId,
95
+ required String errorDialogTitle,
96
+ }) async {
97
+ Message ? fetchedMessage;
98
+ String ? errorMessage;
99
+ // TODO, supported by reusable code:
100
+ // - (?) Retry with backoff on plausibly transient errors.
101
+ // - If request(s) take(s) a long time, show snackbar with cancel
102
+ // button, like "Still working on quote-and-reply…".
103
+ // On final failure or success, auto-dismiss the snackbar.
104
+ try {
105
+ fetchedMessage = await getMessageCompat (PerAccountStoreWidget .of (context).connection,
106
+ messageId: messageId,
107
+ applyMarkdown: false ,
108
+ );
109
+ if (fetchedMessage == null ) {
110
+ errorMessage = 'That message does not seem to exist.' ;
111
+ }
112
+ } catch (e) {
113
+ switch (e) {
114
+ case ZulipApiException ():
115
+ errorMessage = e.message;
116
+ // TODO specific messages for common errors, like network errors
117
+ // (support with reusable code)
118
+ default :
119
+ errorMessage = 'Could not fetch message source.' ;
120
+ }
121
+ }
122
+
123
+ if (! context.mounted) return null ;
124
+
125
+ if (fetchedMessage == null ) {
126
+ assert (errorMessage != null );
127
+ // TODO(?) give no feedback on error conditions we expect to
128
+ // flag centrally in event polling, like invalid auth,
129
+ // user/realm deactivated. (Support with reusable code.)
130
+ await showErrorDialog (context: context,
131
+ title: errorDialogTitle, message: errorMessage);
132
+ }
133
+
134
+ return fetchedMessage? .content;
135
+ }
136
+
90
137
class QuoteAndReplyButton extends MessageActionSheetMenuItemButton {
91
138
QuoteAndReplyButton ({
92
139
super .key,
@@ -121,42 +168,11 @@ class QuoteAndReplyButton extends MessageActionSheetMenuItemButton {
121
168
message: message,
122
169
);
123
170
124
- Message ? fetchedMessage;
125
- String ? errorMessage;
126
- // TODO, supported by reusable code:
127
- // - (?) Retry with backoff on plausibly transient errors.
128
- // - If request(s) take(s) a long time, show snackbar with cancel
129
- // button, like "Still working on quote-and-reply…".
130
- // On final failure or success, auto-dismiss the snackbar.
131
- try {
132
- fetchedMessage = await getMessageCompat (PerAccountStoreWidget .of (messageListContext).connection,
133
- messageId: message.id,
134
- applyMarkdown: false ,
135
- );
136
- if (fetchedMessage == null ) {
137
- errorMessage = 'That message does not seem to exist.' ;
138
- }
139
- } catch (e) {
140
- switch (e) {
141
- case ZulipApiException ():
142
- errorMessage = e.message;
143
- // TODO specific messages for common errors, like network errors
144
- // (support with reusable code)
145
- default :
146
- errorMessage = 'Could not fetch message source.' ;
147
- }
148
- }
149
-
150
- if (! messageListContext.mounted) return ;
151
-
152
- if (fetchedMessage == null ) {
153
- assert (errorMessage != null );
154
- // TODO(?) give no feedback on error conditions we expect to
155
- // flag centrally in event polling, like invalid auth,
156
- // user/realm deactivated. (Support with reusable code.)
157
- await showErrorDialog (context: messageListContext,
158
- title: 'Quotation failed' , message: errorMessage);
159
- }
171
+ final rawContent = await fetchRawContentWithFeedback (
172
+ context: messageListContext,
173
+ messageId: message.id,
174
+ errorDialogTitle: 'Quotation failed' ,
175
+ );
160
176
161
177
if (! messageListContext.mounted) return ;
162
178
@@ -167,7 +183,7 @@ class QuoteAndReplyButton extends MessageActionSheetMenuItemButton {
167
183
composeBoxController.contentController
168
184
.registerQuoteAndReplyEnd (PerAccountStoreWidget .of (messageListContext), tag,
169
185
message: message,
170
- rawContent: fetchedMessage ? .content ,
186
+ rawContent: rawContent ,
171
187
);
172
188
if (! composeBoxController.contentFocusNode.hasFocus) {
173
189
composeBoxController.contentFocusNode.requestFocus ();
0 commit comments