Skip to content

Commit 1fa9f24

Browse files
committed
msglist: Support retrieving failed outbox message content
Different from the Figma design, the bottom padding below the progress bar is changed from 0.5px to 2px, as discussed here: zulip#1453 (comment) Fixes: zulip#1441
1 parent c8295ae commit 1fa9f24

17 files changed

+461
-30
lines changed

assets/l10n/app_en.arb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,10 @@
377377
"@discardDraftForEditConfirmationDialogMessage": {
378378
"description": "Message for a confirmation dialog for discarding message text that was typed into the compose box, when editing a message."
379379
},
380+
"discardDraftForMessageNotSentConfirmationDialogMessage": "When you restore a message not sent, the content that was previously in the compose box is discarded.",
381+
"@discardDraftForMessageNotSentConfirmationDialogMessage": {
382+
"description": "Message for a confirmation dialog when restoring a message not sent, for discarding message text that was typed into the compose box."
383+
},
380384
"discardDraftConfirmationDialogConfirmButton": "Discard",
381385
"@discardDraftConfirmationDialogConfirmButton": {
382386
"description": "Label for the 'Discard' button on a confirmation dialog for discarding message text that was typed into the compose box."
@@ -864,6 +868,10 @@
864868
"@messageIsMovedLabel": {
865869
"description": "Label for a moved message. (Use ALL CAPS for cased alphabets: Latin, Greek, Cyrillic, etc.)"
866870
},
871+
"messageNotSentLabel": "MESSAGE NOT SENT",
872+
"@messageNotSentLabel": {
873+
"description": "Text on a message in the message list saying that a send message request failed. (Use ALL CAPS for cased alphabets: Latin, Greek, Cyrillic, etc.)"
874+
},
867875
"pollVoterNames": "({voterNames})",
868876
"@pollVoterNames": {
869877
"description": "The list of people who voted for a poll option, wrapped in parentheses.",

lib/generated/l10n/zulip_localizations.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,12 @@ abstract class ZulipLocalizations {
631631
/// **'When you edit a message, the content that was previously in the compose box is discarded.'**
632632
String get discardDraftForEditConfirmationDialogMessage;
633633

634+
/// Message for a confirmation dialog when restoring a message not sent, for discarding message text that was typed into the compose box.
635+
///
636+
/// In en, this message translates to:
637+
/// **'When you restore a message not sent, the content that was previously in the compose box is discarded.'**
638+
String get discardDraftForMessageNotSentConfirmationDialogMessage;
639+
634640
/// Label for the 'Discard' button on a confirmation dialog for discarding message text that was typed into the compose box.
635641
///
636642
/// In en, this message translates to:
@@ -1277,6 +1283,12 @@ abstract class ZulipLocalizations {
12771283
/// **'MOVED'**
12781284
String get messageIsMovedLabel;
12791285

1286+
/// Text on a message in the message list saying that a send message request failed. (Use ALL CAPS for cased alphabets: Latin, Greek, Cyrillic, etc.)
1287+
///
1288+
/// In en, this message translates to:
1289+
/// **'MESSAGE NOT SENT'**
1290+
String get messageNotSentLabel;
1291+
12801292
/// The list of people who voted for a poll option, wrapped in parentheses.
12811293
///
12821294
/// In en, this message translates to:

lib/generated/l10n/zulip_localizations_ar.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,10 @@ class ZulipLocalizationsAr extends ZulipLocalizations {
318318
String get discardDraftForEditConfirmationDialogMessage =>
319319
'When you edit a message, the content that was previously in the compose box is discarded.';
320320

321+
@override
322+
String get discardDraftForMessageNotSentConfirmationDialogMessage =>
323+
'When you restore a message not sent, the content that was previously in the compose box is discarded.';
324+
321325
@override
322326
String get discardDraftConfirmationDialogConfirmButton => 'Discard';
323327

@@ -704,6 +708,9 @@ class ZulipLocalizationsAr extends ZulipLocalizations {
704708
@override
705709
String get messageIsMovedLabel => 'MOVED';
706710

711+
@override
712+
String get messageNotSentLabel => 'MESSAGE NOT SENT';
713+
707714
@override
708715
String pollVoterNames(String voterNames) {
709716
return '($voterNames)';

lib/generated/l10n/zulip_localizations_de.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,10 @@ class ZulipLocalizationsDe extends ZulipLocalizations {
318318
String get discardDraftForEditConfirmationDialogMessage =>
319319
'When you edit a message, the content that was previously in the compose box is discarded.';
320320

321+
@override
322+
String get discardDraftForMessageNotSentConfirmationDialogMessage =>
323+
'When you restore a message not sent, the content that was previously in the compose box is discarded.';
324+
321325
@override
322326
String get discardDraftConfirmationDialogConfirmButton => 'Discard';
323327

@@ -704,6 +708,9 @@ class ZulipLocalizationsDe extends ZulipLocalizations {
704708
@override
705709
String get messageIsMovedLabel => 'MOVED';
706710

711+
@override
712+
String get messageNotSentLabel => 'MESSAGE NOT SENT';
713+
707714
@override
708715
String pollVoterNames(String voterNames) {
709716
return '($voterNames)';

lib/generated/l10n/zulip_localizations_en.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,10 @@ class ZulipLocalizationsEn extends ZulipLocalizations {
318318
String get discardDraftForEditConfirmationDialogMessage =>
319319
'When you edit a message, the content that was previously in the compose box is discarded.';
320320

321+
@override
322+
String get discardDraftForMessageNotSentConfirmationDialogMessage =>
323+
'When you restore a message not sent, the content that was previously in the compose box is discarded.';
324+
321325
@override
322326
String get discardDraftConfirmationDialogConfirmButton => 'Discard';
323327

@@ -704,6 +708,9 @@ class ZulipLocalizationsEn extends ZulipLocalizations {
704708
@override
705709
String get messageIsMovedLabel => 'MOVED';
706710

711+
@override
712+
String get messageNotSentLabel => 'MESSAGE NOT SENT';
713+
707714
@override
708715
String pollVoterNames(String voterNames) {
709716
return '($voterNames)';

lib/generated/l10n/zulip_localizations_ja.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,10 @@ class ZulipLocalizationsJa extends ZulipLocalizations {
318318
String get discardDraftForEditConfirmationDialogMessage =>
319319
'When you edit a message, the content that was previously in the compose box is discarded.';
320320

321+
@override
322+
String get discardDraftForMessageNotSentConfirmationDialogMessage =>
323+
'When you restore a message not sent, the content that was previously in the compose box is discarded.';
324+
321325
@override
322326
String get discardDraftConfirmationDialogConfirmButton => 'Discard';
323327

@@ -704,6 +708,9 @@ class ZulipLocalizationsJa extends ZulipLocalizations {
704708
@override
705709
String get messageIsMovedLabel => 'MOVED';
706710

711+
@override
712+
String get messageNotSentLabel => 'MESSAGE NOT SENT';
713+
707714
@override
708715
String pollVoterNames(String voterNames) {
709716
return '($voterNames)';

lib/generated/l10n/zulip_localizations_nb.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,10 @@ class ZulipLocalizationsNb extends ZulipLocalizations {
318318
String get discardDraftForEditConfirmationDialogMessage =>
319319
'When you edit a message, the content that was previously in the compose box is discarded.';
320320

321+
@override
322+
String get discardDraftForMessageNotSentConfirmationDialogMessage =>
323+
'When you restore a message not sent, the content that was previously in the compose box is discarded.';
324+
321325
@override
322326
String get discardDraftConfirmationDialogConfirmButton => 'Discard';
323327

@@ -704,6 +708,9 @@ class ZulipLocalizationsNb extends ZulipLocalizations {
704708
@override
705709
String get messageIsMovedLabel => 'MOVED';
706710

711+
@override
712+
String get messageNotSentLabel => 'MESSAGE NOT SENT';
713+
707714
@override
708715
String pollVoterNames(String voterNames) {
709716
return '($voterNames)';

lib/generated/l10n/zulip_localizations_pl.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,10 @@ class ZulipLocalizationsPl extends ZulipLocalizations {
325325
String get discardDraftForEditConfirmationDialogMessage =>
326326
'Miej na uwadze, że przechodząc do zmiany wiadomości wyczyścisz okno nowej wiadomości.';
327327

328+
@override
329+
String get discardDraftForMessageNotSentConfirmationDialogMessage =>
330+
'When you restore a message not sent, the content that was previously in the compose box is discarded.';
331+
328332
@override
329333
String get discardDraftConfirmationDialogConfirmButton => 'Odrzuć';
330334

@@ -713,6 +717,9 @@ class ZulipLocalizationsPl extends ZulipLocalizations {
713717
@override
714718
String get messageIsMovedLabel => 'PRZENIESIONO';
715719

720+
@override
721+
String get messageNotSentLabel => 'MESSAGE NOT SENT';
722+
716723
@override
717724
String pollVoterNames(String voterNames) {
718725
return '($voterNames)';

lib/generated/l10n/zulip_localizations_ru.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,10 @@ class ZulipLocalizationsRu extends ZulipLocalizations {
326326
String get discardDraftForEditConfirmationDialogMessage =>
327327
'When you edit a message, the content that was previously in the compose box is discarded.';
328328

329+
@override
330+
String get discardDraftForMessageNotSentConfirmationDialogMessage =>
331+
'When you restore a message not sent, the content that was previously in the compose box is discarded.';
332+
329333
@override
330334
String get discardDraftConfirmationDialogConfirmButton => 'Discard';
331335

@@ -717,6 +721,9 @@ class ZulipLocalizationsRu extends ZulipLocalizations {
717721
@override
718722
String get messageIsMovedLabel => 'ПЕРЕМЕЩЕНО';
719723

724+
@override
725+
String get messageNotSentLabel => 'MESSAGE NOT SENT';
726+
720727
@override
721728
String pollVoterNames(String voterNames) {
722729
return '($voterNames)';

lib/generated/l10n/zulip_localizations_sk.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,10 @@ class ZulipLocalizationsSk extends ZulipLocalizations {
318318
String get discardDraftForEditConfirmationDialogMessage =>
319319
'When you edit a message, the content that was previously in the compose box is discarded.';
320320

321+
@override
322+
String get discardDraftForMessageNotSentConfirmationDialogMessage =>
323+
'When you restore a message not sent, the content that was previously in the compose box is discarded.';
324+
321325
@override
322326
String get discardDraftConfirmationDialogConfirmButton => 'Discard';
323327

@@ -706,6 +710,9 @@ class ZulipLocalizationsSk extends ZulipLocalizations {
706710
@override
707711
String get messageIsMovedLabel => 'PRESUNUTÉ';
708712

713+
@override
714+
String get messageNotSentLabel => 'MESSAGE NOT SENT';
715+
709716
@override
710717
String pollVoterNames(String voterNames) {
711718
return '($voterNames)';

lib/generated/l10n/zulip_localizations_uk.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,10 @@ class ZulipLocalizationsUk extends ZulipLocalizations {
327327
String get discardDraftForEditConfirmationDialogMessage =>
328328
'When you edit a message, the content that was previously in the compose box is discarded.';
329329

330+
@override
331+
String get discardDraftForMessageNotSentConfirmationDialogMessage =>
332+
'When you restore a message not sent, the content that was previously in the compose box is discarded.';
333+
330334
@override
331335
String get discardDraftConfirmationDialogConfirmButton => 'Discard';
332336

@@ -716,6 +720,9 @@ class ZulipLocalizationsUk extends ZulipLocalizations {
716720
@override
717721
String get messageIsMovedLabel => 'ПЕРЕМІЩЕНО';
718722

723+
@override
724+
String get messageNotSentLabel => 'MESSAGE NOT SENT';
725+
719726
@override
720727
String pollVoterNames(String voterNames) {
721728
return '($voterNames)';

lib/model/message.dart

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -881,9 +881,8 @@ mixin _OutboxMessageStore on PerAccountStoreBase {
881881
void _handleMessageEventOutbox(MessageEvent event) {
882882
if (event.localMessageId != null) {
883883
final localMessageId = int.parse(event.localMessageId!, radix: 10);
884-
// The outbox message can be missing if the user removes it (to be
885-
// implemented in #1441) before the event arrives.
886-
// Nothing to do in that case.
884+
// The outbox message can be missing if the user removes it before the
885+
// event arrives. Nothing to do in that case.
887886
_outboxMessages.remove(localMessageId);
888887
_outboxMessageDebounceTimers.remove(localMessageId)?.cancel();
889888
_outboxMessageWaitPeriodTimers.remove(localMessageId)?.cancel();

lib/widgets/compose_box.dart

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import '../api/route/messages.dart';
1313
import '../generated/l10n/zulip_localizations.dart';
1414
import '../model/binding.dart';
1515
import '../model/compose.dart';
16+
import '../model/message.dart';
1617
import '../model/narrow.dart';
1718
import '../model/store.dart';
1819
import 'actions.dart';
@@ -1288,15 +1289,8 @@ class _SendButtonState extends State<_SendButton> {
12881289
final content = controller.content.textNormalized;
12891290

12901291
controller.content.clear();
1291-
// The following `stoppedComposing` call is currently redundant,
1292-
// because clearing input sends a "typing stopped" notice.
1293-
// It will be necessary once we resolve #720.
1294-
store.typingNotifier.stoppedComposing();
12951292

12961293
try {
1297-
// TODO(#720) clear content input only on success response;
1298-
// while waiting, put input(s) and send button into a disabled
1299-
// "working on it" state (letting input text be selected for copying).
13001294
await store.sendMessage(destination: widget.getDestination(), content: content);
13011295
} on ApiRequestException catch (e) {
13021296
if (!mounted) return;
@@ -1388,7 +1382,6 @@ class _ComposeBoxContainer extends StatelessWidget {
13881382
border: Border(top: BorderSide(color: designVariables.borderBar)),
13891383
boxShadow: ComposeBoxTheme.of(context).boxShadow,
13901384
),
1391-
// TODO(#720) try a Stack for the overlaid linear progress indicator
13921385
child: Material(
13931386
color: designVariables.composeBoxBg,
13941387
child: Column(
@@ -1724,10 +1717,6 @@ class _ErrorBanner extends _Banner {
17241717

17251718
@override
17261719
Widget? buildTrailing(context) {
1727-
// TODO(#720) "x" button goes here.
1728-
// 24px square with 8px touchable padding in all directions?
1729-
// and `bool get padEnd => false`; see Figma:
1730-
// https://www.figma.com/design/1JTNtYo9memgW7vV6d0ygq/Zulip-Mobile?node-id=4031-17029&m=dev
17311720
return null;
17321721
}
17331722
}
@@ -1826,6 +1815,15 @@ class ComposeBox extends StatefulWidget {
18261815
abstract class ComposeBoxState extends State<ComposeBox> {
18271816
ComposeBoxController get controller;
18281817

1818+
/// Restore a [OutboxMessage] for a failed [sendMessage] request.
1819+
///
1820+
/// [localMessageId], as in [OutboxMessage.localMessageId], must be present
1821+
/// in the message store.
1822+
///
1823+
/// If there is already text in the compose box, gives a confirmation dialog
1824+
/// to confirm that it is OK to discard that text.
1825+
void restoreMessageNotSent(int localMessageId);
1826+
18291827
/// Switch the compose box to editing mode.
18301828
///
18311829
/// If there is already text in the compose box, gives a confirmation dialog
@@ -1848,9 +1846,33 @@ class _ComposeBoxState extends State<ComposeBox> with PerAccountStoreAwareStateM
18481846
ComposeBoxController? _controller;
18491847

18501848
@override
1851-
void startEditInteraction(int messageId) async {
1849+
void restoreMessageNotSent(int localMessageId) async {
1850+
if (controller is EditMessageComposeBoxController) return;
18521851
final zulipLocalizations = ZulipLocalizations.of(context);
1852+
if (await _abortBecauseContentInputNotEmpty(
1853+
message: zulipLocalizations.discardDraftForMessageNotSentConfirmationDialogMessage)) {
1854+
return;
1855+
}
1856+
if (!mounted) return;
18531857

1858+
final store = PerAccountStoreWidget.of(context);
1859+
final outboxMessage = store.takeOutboxMessage(localMessageId);
1860+
setState(() {
1861+
_setNewController(store);
1862+
final controller = this.controller;
1863+
controller
1864+
..content.value = TextEditingValue(text: outboxMessage.contentMarkdown)
1865+
..contentFocusNode.requestFocus();
1866+
if (controller is StreamComposeBoxController) {
1867+
controller.topic.setTopic((
1868+
outboxMessage.conversation as StreamConversation).topic);
1869+
}
1870+
});
1871+
}
1872+
1873+
@override
1874+
void startEditInteraction(int messageId) async {
1875+
final zulipLocalizations = ZulipLocalizations.of(context);
18541876
if (await _abortBecauseContentInputNotEmpty(
18551877
message: zulipLocalizations.discardDraftForEditConfirmationDialogMessage)) {
18561878
return;
@@ -2067,11 +2089,6 @@ class _ComposeBoxState extends State<ComposeBox> with PerAccountStoreAwareStateM
20672089
}
20682090
}
20692091

2070-
// TODO(#720) dismissable message-send error, maybe something like:
2071-
// if (controller.sendMessageError.value != null) {
2072-
// errorBanner = _ErrorBanner(label:
2073-
// ZulipLocalizations.of(context).errorSendMessageTimeout);
2074-
// }
20752092
return ComposeBoxInheritedWidget.fromComposeBoxState(this,
20762093
child: _ComposeBoxContainer(body: body, banner: banner));
20772094
}

0 commit comments

Comments
 (0)