-
Notifications
You must be signed in to change notification settings - Fork 310
local echo (7/7): Support simplified version of local echo #1453
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
109562b
72ffbd8
3b9366e
d56e20f
419e17b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ import 'package:intl/intl.dart' hide TextDirection; | |
|
||
import '../api/model/model.dart'; | ||
import '../generated/l10n/zulip_localizations.dart'; | ||
import '../model/message.dart'; | ||
import '../model/message_list.dart'; | ||
import '../model/narrow.dart'; | ||
import '../model/store.dart'; | ||
|
@@ -760,6 +761,9 @@ class _MessageListState extends State<MessageList> with PerAccountStoreAwareStat | |
key: ValueKey(data.message.id), | ||
header: header, | ||
item: data); | ||
case MessageListOutboxMessageItem(): | ||
final header = RecipientHeader(message: data.message, narrow: widget.narrow); | ||
return MessageItem(header: header, item: data); | ||
} | ||
} | ||
} | ||
|
@@ -1071,6 +1075,7 @@ class MessageItem extends StatelessWidget { | |
child: Column(children: [ | ||
switch (item) { | ||
MessageListMessageItem() => MessageWithPossibleSender(item: item), | ||
MessageListOutboxMessageItem() => OutboxMessageWithPossibleSender(item: item), | ||
}, | ||
// TODO refine this padding; discussion: | ||
// https://github.com/zulip/zulip-flutter/pull/1453#discussion_r2106526985 | ||
|
@@ -1651,3 +1656,126 @@ class _RestoreEditMessageGestureDetector extends StatelessWidget { | |
child: child); | ||
} | ||
} | ||
|
||
/// A "local echo" placeholder for a Zulip message to be sent by the self-user. | ||
/// | ||
/// See also [OutboxMessage]. | ||
class OutboxMessageWithPossibleSender extends StatelessWidget { | ||
const OutboxMessageWithPossibleSender({super.key, required this.item}); | ||
|
||
final MessageListOutboxMessageItem item; | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
final message = item.message; | ||
final localMessageId = message.localMessageId; | ||
final state = item.message.state; | ||
|
||
// This is adapted from [MessageContent]. | ||
// TODO(#576): Offer InheritedMessage ancestor once we are ready | ||
// to support local echoing images and lightbox. | ||
Widget content = DefaultTextStyle( | ||
style: ContentTheme.of(context).textStylePlainParagraph, | ||
child: BlockContentList(nodes: item.content.nodes)); | ||
|
||
switch (state) { | ||
case OutboxMessageState.hidden: | ||
throw StateError('Hidden OutboxMessage messages should not appear in message lists'); | ||
case OutboxMessageState.waiting: | ||
break; | ||
case OutboxMessageState.failed: | ||
case OutboxMessageState.waitPeriodExpired: | ||
// TODO(#576): When we support rendered-content local echo, | ||
// use IgnorePointer along with this faded appearance, | ||
// like we do for the failed-message-edit state | ||
content = _RestoreOutboxMessageGestureDetector( | ||
localMessageId: localMessageId, | ||
child: Opacity(opacity: 0.6, child: content)); | ||
} | ||
|
||
return Padding( | ||
padding: const EdgeInsets.only(top: 4), | ||
child: Column(children: [ | ||
if (item.showSender) | ||
_SenderRow(message: message, showTimestamp: false), | ||
Padding( | ||
padding: const EdgeInsets.symmetric(horizontal: 16), | ||
child: Column(crossAxisAlignment: CrossAxisAlignment.stretch, | ||
children: [ | ||
content, | ||
_OutboxMessageStatusRow( | ||
localMessageId: localMessageId, outboxMessageState: state), | ||
])), | ||
])); | ||
} | ||
} | ||
|
||
class _OutboxMessageStatusRow extends StatelessWidget { | ||
const _OutboxMessageStatusRow({ | ||
required this.localMessageId, | ||
required this.outboxMessageState, | ||
}); | ||
|
||
final int localMessageId; | ||
final OutboxMessageState outboxMessageState; | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
switch (outboxMessageState) { | ||
case OutboxMessageState.hidden: | ||
assert(false, | ||
'Hidden OutboxMessage messages should not appear in message lists'); | ||
return SizedBox.shrink(); | ||
|
||
case OutboxMessageState.waiting: | ||
final designVariables = DesignVariables.of(context); | ||
return Padding( | ||
padding: const EdgeInsetsGeometry.only(bottom: 2), | ||
child: LinearProgressIndicator( | ||
minHeight: 2, | ||
color: designVariables.foreground.withFadedAlpha(0.5), | ||
backgroundColor: designVariables.foreground.withFadedAlpha(0.2))); | ||
|
||
case OutboxMessageState.failed: | ||
case OutboxMessageState.waitPeriodExpired: | ||
Comment on lines
+1739
to
+1740
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it intentional to show "MESSAGE NOT SENT" in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In v0.0.29 we'd enter this state even if we got a success response from the send request, if the event didn't then show up. I suspect that's what happened in the report in #1525. In the current revision of this PR, a success response will put the outbox-message into (The exact status in that case is more like "tried sending the message, it's been a while, haven't heard any response yet, so it may or may not have made it through, up to you if you want to retry". Not sure there's a good concise way to communicate that.) |
||
final designVariables = DesignVariables.of(context); | ||
final zulipLocalizations = ZulipLocalizations.of(context); | ||
return Padding( | ||
padding: const EdgeInsets.only(bottom: 4), | ||
child: _RestoreOutboxMessageGestureDetector( | ||
localMessageId: localMessageId, | ||
child: Text( | ||
zulipLocalizations.messageNotSentLabel, | ||
textAlign: TextAlign.end, | ||
style: TextStyle( | ||
color: designVariables.btnLabelAttLowIntDanger, | ||
fontSize: 12, | ||
height: 12 / 12, | ||
letterSpacing: proportionalLetterSpacing( | ||
context, 0.05, baseFontSize: 12))))); | ||
} | ||
} | ||
} | ||
|
||
class _RestoreOutboxMessageGestureDetector extends StatelessWidget { | ||
const _RestoreOutboxMessageGestureDetector({ | ||
required this.localMessageId, | ||
required this.child, | ||
}); | ||
|
||
final int localMessageId; | ||
final Widget child; | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return GestureDetector( | ||
behavior: HitTestBehavior.opaque, | ||
onTap: () { | ||
final composeBoxState = MessageListPage.ancestorOf(context).composeBoxState; | ||
// TODO(#1518) allow restore-outbox-message from any message-list page | ||
if (composeBoxState == null) return; | ||
composeBoxState.restoreMessageNotSent(localMessageId); | ||
}, | ||
child: child); | ||
} | ||
} |
Large diffs are not rendered by default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there — ah, I guess that was in the commits you temporarily removed as mentioned at #1453 (comment) .