Skip to content

Commit 24508b3

Browse files
committed
msglist: Support retrieving failed outbox message content
1 parent 1f83717 commit 24508b3

14 files changed

+299
-23
lines changed

assets/l10n/app_en.arb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,10 @@
864864
"@messageIsMovedLabel": {
865865
"description": "Label for a moved message. (Use ALL CAPS for cased alphabets: Latin, Greek, Cyrillic, etc.)"
866866
},
867+
"messageNotSentLabel": "MESSAGE NOT SENT",
868+
"@messageNotSentLabel": {
869+
"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.)"
870+
},
867871
"pollVoterNames": "({voterNames})",
868872
"@pollVoterNames": {
869873
"description": "The list of people who voted for a poll option, wrapped in parentheses.",

lib/generated/l10n/zulip_localizations.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1277,6 +1277,12 @@ abstract class ZulipLocalizations {
12771277
/// **'MOVED'**
12781278
String get messageIsMovedLabel;
12791279

1280+
/// 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.)
1281+
///
1282+
/// In en, this message translates to:
1283+
/// **'MESSAGE NOT SENT'**
1284+
String get messageNotSentLabel;
1285+
12801286
/// The list of people who voted for a poll option, wrapped in parentheses.
12811287
///
12821288
/// In en, this message translates to:

lib/generated/l10n/zulip_localizations_ar.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,9 @@ class ZulipLocalizationsAr extends ZulipLocalizations {
704704
@override
705705
String get messageIsMovedLabel => 'MOVED';
706706

707+
@override
708+
String get messageNotSentLabel => 'MESSAGE NOT SENT';
709+
707710
@override
708711
String pollVoterNames(String voterNames) {
709712
return '($voterNames)';

lib/generated/l10n/zulip_localizations_de.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,9 @@ class ZulipLocalizationsDe extends ZulipLocalizations {
704704
@override
705705
String get messageIsMovedLabel => 'MOVED';
706706

707+
@override
708+
String get messageNotSentLabel => 'MESSAGE NOT SENT';
709+
707710
@override
708711
String pollVoterNames(String voterNames) {
709712
return '($voterNames)';

lib/generated/l10n/zulip_localizations_en.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,9 @@ class ZulipLocalizationsEn extends ZulipLocalizations {
704704
@override
705705
String get messageIsMovedLabel => 'MOVED';
706706

707+
@override
708+
String get messageNotSentLabel => 'MESSAGE NOT SENT';
709+
707710
@override
708711
String pollVoterNames(String voterNames) {
709712
return '($voterNames)';

lib/generated/l10n/zulip_localizations_ja.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,9 @@ class ZulipLocalizationsJa extends ZulipLocalizations {
704704
@override
705705
String get messageIsMovedLabel => 'MOVED';
706706

707+
@override
708+
String get messageNotSentLabel => 'MESSAGE NOT SENT';
709+
707710
@override
708711
String pollVoterNames(String voterNames) {
709712
return '($voterNames)';

lib/generated/l10n/zulip_localizations_nb.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,9 @@ class ZulipLocalizationsNb extends ZulipLocalizations {
704704
@override
705705
String get messageIsMovedLabel => 'MOVED';
706706

707+
@override
708+
String get messageNotSentLabel => 'MESSAGE NOT SENT';
709+
707710
@override
708711
String pollVoterNames(String voterNames) {
709712
return '($voterNames)';

lib/generated/l10n/zulip_localizations_pl.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,9 @@ class ZulipLocalizationsPl extends ZulipLocalizations {
713713
@override
714714
String get messageIsMovedLabel => 'PRZENIESIONO';
715715

716+
@override
717+
String get messageNotSentLabel => 'MESSAGE NOT SENT';
718+
716719
@override
717720
String pollVoterNames(String voterNames) {
718721
return '($voterNames)';

lib/generated/l10n/zulip_localizations_ru.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,9 @@ class ZulipLocalizationsRu extends ZulipLocalizations {
717717
@override
718718
String get messageIsMovedLabel => 'ПЕРЕМЕЩЕНО';
719719

720+
@override
721+
String get messageNotSentLabel => 'MESSAGE NOT SENT';
722+
720723
@override
721724
String pollVoterNames(String voterNames) {
722725
return '($voterNames)';

lib/generated/l10n/zulip_localizations_sk.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,9 @@ class ZulipLocalizationsSk extends ZulipLocalizations {
706706
@override
707707
String get messageIsMovedLabel => 'PRESUNUTÉ';
708708

709+
@override
710+
String get messageNotSentLabel => 'MESSAGE NOT SENT';
711+
709712
@override
710713
String pollVoterNames(String voterNames) {
711714
return '($voterNames)';

lib/generated/l10n/zulip_localizations_uk.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,9 @@ class ZulipLocalizationsUk extends ZulipLocalizations {
716716
@override
717717
String get messageIsMovedLabel => 'ПЕРЕМІЩЕНО';
718718

719+
@override
720+
String get messageNotSentLabel => 'MESSAGE NOT SENT';
721+
719722
@override
720723
String pollVoterNames(String voterNames) {
721724
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/message_list.dart

Lines changed: 102 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import 'package:intl/intl.dart' hide TextDirection;
55

66
import '../api/model/model.dart';
77
import '../generated/l10n/zulip_localizations.dart';
8+
import '../model/message.dart';
89
import '../model/message_list.dart';
910
import '../model/narrow.dart';
1011
import '../model/store.dart';
@@ -1614,22 +1615,108 @@ class OutboxMessageWithPossibleSender extends StatelessWidget {
16141615

16151616
final MessageListOutboxMessageItem item;
16161617

1618+
// TODO restore the topic too
1619+
void _handlePress(BuildContext context) {
1620+
final store = PerAccountStoreWidget.of(context);
1621+
assert(store.outboxMessages.containsKey(item.message.localMessageId));
1622+
final message = store.takeOutboxMessage(item.message.localMessageId);
1623+
1624+
final content = message.contentMarkdown.endsWith('\n')
1625+
? message.contentMarkdown : '${message.contentMarkdown}\n';
1626+
1627+
final composeBoxController =
1628+
MessageListPage.ancestorOf(context).composeBoxState!.controller;
1629+
composeBoxController.content.insertPadded(content);
1630+
if (!composeBoxController.contentFocusNode.hasFocus) {
1631+
composeBoxController.contentFocusNode.requestFocus();
1632+
}
1633+
}
1634+
16171635
@override
16181636
Widget build(BuildContext context) {
1619-
final message = item.message;
1620-
return Padding(
1621-
padding: const EdgeInsets.symmetric(vertical: 4),
1622-
child: Column(children: [
1623-
if (item.showSender)
1624-
_SenderRow(message: message, showTimestamp: false),
1625-
Padding(
1626-
padding: const EdgeInsets.symmetric(horizontal: 16),
1627-
// This is adapated from [MessageContent].
1628-
// TODO(#576): Offer InheritedMessage ancestor once we are ready
1629-
// to support local echoing images and lightbox.
1630-
child: DefaultTextStyle(
1631-
style: ContentTheme.of(context).textStylePlainParagraph,
1632-
child: BlockContentList(nodes: item.content.nodes))),
1633-
]));
1637+
final GestureTapCallback? handleTap;
1638+
final double opacity;
1639+
switch (item.message.state) {
1640+
case OutboxMessageState.hidden:
1641+
assert(false,
1642+
'Hidden OutboxMessage messages should not appear in message lists');
1643+
handleTap = null;
1644+
opacity = 1.0;
1645+
1646+
case OutboxMessageState.waiting:
1647+
handleTap = null;
1648+
opacity = 1.0;
1649+
1650+
case OutboxMessageState.failed:
1651+
case OutboxMessageState.waitPeriodExpired:
1652+
final isComposeBoxOffered =
1653+
MessageListPage.ancestorOf(context).composeBoxState != null;
1654+
handleTap = isComposeBoxOffered ? () => _handlePress(context) : null;
1655+
opacity = 0.6;
1656+
}
1657+
1658+
return GestureDetector(
1659+
onTap: handleTap,
1660+
behavior: HitTestBehavior.opaque,
1661+
child: Padding(
1662+
padding: const EdgeInsets.only(top: 4),
1663+
child: Column(children: [
1664+
if (item.showSender)
1665+
_SenderRow(message: item.message, showTimestamp: false),
1666+
Padding(
1667+
padding: const EdgeInsets.symmetric(horizontal: 16),
1668+
child: Column(crossAxisAlignment: CrossAxisAlignment.stretch,
1669+
children: [
1670+
// This is adapted from [MessageContent].
1671+
// TODO(#576): Offer InheritedMessage ancestor once we are ready
1672+
// to support local echoing images and lightbox.
1673+
Opacity(opacity: opacity, child: DefaultTextStyle(
1674+
style: ContentTheme.of(context).textStylePlainParagraph,
1675+
child: BlockContentList(nodes: item.content.nodes))),
1676+
1677+
_OutboxMessageStatusRow(outboxMessageState: item.message.state),
1678+
])),
1679+
])));
1680+
}
1681+
}
1682+
1683+
class _OutboxMessageStatusRow extends StatelessWidget {
1684+
const _OutboxMessageStatusRow({required this.outboxMessageState});
1685+
1686+
final OutboxMessageState outboxMessageState;
1687+
1688+
@override
1689+
Widget build(BuildContext context) {
1690+
switch (outboxMessageState) {
1691+
case OutboxMessageState.hidden:
1692+
assert(false,
1693+
'Hidden OutboxMessage messages should not appear in message lists');
1694+
return SizedBox.shrink();
1695+
1696+
case OutboxMessageState.waiting:
1697+
final designVariables = DesignVariables.of(context);
1698+
return Padding(
1699+
padding: const EdgeInsetsGeometry.only(top: 1.5, bottom: 0.5),
1700+
child: LinearProgressIndicator(
1701+
minHeight: 2,
1702+
color: designVariables.foreground.withFadedAlpha(0.5),
1703+
backgroundColor: designVariables.foreground.withFadedAlpha(0.2)));
1704+
1705+
case OutboxMessageState.failed:
1706+
case OutboxMessageState.waitPeriodExpired:
1707+
final designVariables = DesignVariables.of(context);
1708+
final zulipLocalizations = ZulipLocalizations.of(context);
1709+
return Padding(
1710+
padding: const EdgeInsets.only(bottom: 4),
1711+
child: Text(
1712+
zulipLocalizations.messageNotSentLabel,
1713+
textAlign: TextAlign.end,
1714+
style: TextStyle(
1715+
color: designVariables.btnLabelAttLowIntDanger,
1716+
fontSize: 12,
1717+
height: 12 / 12,
1718+
letterSpacing: proportionalLetterSpacing(
1719+
context, 0.05, baseFontSize: 12))));
1720+
}
16341721
}
16351722
}

0 commit comments

Comments
 (0)