Skip to content

Commit ac35860

Browse files
committed
message: Create an outbox message on send; manage its states
While we do create outbox messages, there are in no way user-visible changes since the outbox messages don't end up in message list views. We create skeletons for helpers needed from message list view, but don't implement them yet, to make the diff smaller. For testing, similar to TypingNotifier.debugEnable, we add MessageStoreImpl.debugOutboxEnable for tests that do not intend to cover outbox messages. Some of the delays to fake responses added in tests are not necessary because the future of sendMessage is not completed immediately, but we still add them to keep the tests realistic.
1 parent c3c4d0f commit ac35860

12 files changed

+818
-60
lines changed

lib/model/message.dart

+335-9
Large diffs are not rendered by default.

lib/model/message_list.dart

+17
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import '../api/route/messages.dart';
1010
import 'algorithms.dart';
1111
import 'channel.dart';
1212
import 'content.dart';
13+
import 'message.dart';
1314
import 'narrow.dart';
1415
import 'store.dart';
1516

@@ -626,6 +627,17 @@ class MessageListView with ChangeNotifier, _MessageSequence {
626627
}
627628
}
628629

630+
void handleOutboxMessage(OutboxMessage outboxMessage) {
631+
// TODO(#1441) implement this
632+
}
633+
634+
/// Remove the [outboxMessage] from the view.
635+
///
636+
/// This is a no-op if the message is not found.
637+
void removeOutboxMessageIfExists(OutboxMessage outboxMessage) {
638+
// TODO(#1441) implement this
639+
}
640+
629641
void handleUserTopicEvent(UserTopicEvent event) {
630642
switch (_canAffectVisibility(event)) {
631643
case VisibilityEffect.none:
@@ -787,6 +799,11 @@ class MessageListView with ChangeNotifier, _MessageSequence {
787799
}
788800
}
789801

802+
/// Notify listeners if the given outbox message is present in this view.
803+
void notifyListenersIfOutboxMessagePresent(int localMessageId) {
804+
// TODO(#1441) implement this
805+
}
806+
790807
/// Called when the app is reassembled during debugging, e.g. for hot reload.
791808
///
792809
/// This will redo from scratch any computations we can, such as parsing

lib/model/store.dart

+7-1
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,8 @@ class PerAccountStore extends PerAccountStoreBase with ChangeNotifier, EmojiStor
494494
typingStartedExpiryPeriod: Duration(milliseconds: initialSnapshot.serverTypingStartedExpiryPeriodMilliseconds),
495495
),
496496
channels: channels,
497-
messages: MessageStoreImpl(core: core),
497+
messages: MessageStoreImpl(core: core,
498+
realmEmptyTopicDisplayName: initialSnapshot.realmEmptyTopicDisplayName),
498499
unreads: Unreads(
499500
initial: initialSnapshot.unreadMsgs,
500501
core: core,
@@ -725,6 +726,8 @@ class PerAccountStore extends PerAccountStoreBase with ChangeNotifier, EmojiStor
725726
@override
726727
Map<int, Message> get messages => _messages.messages;
727728
@override
729+
Map<int, OutboxMessage> get outboxMessages => _messages.outboxMessages;
730+
@override
728731
void registerMessageList(MessageListView view) =>
729732
_messages.registerMessageList(view);
730733
@override
@@ -904,6 +907,9 @@ class PerAccountStore extends PerAccountStoreBase with ChangeNotifier, EmojiStor
904907
return _messages.sendMessage(destination: destination, content: content);
905908
}
906909

910+
@override
911+
void removeOutboxMessage(int localMessageId) => _messages.removeOutboxMessage(localMessageId);
912+
907913
static List<CustomProfileField> _sortCustomProfileFields(List<CustomProfileField> initialCustomProfileFields) {
908914
// TODO(server): The realm-wide field objects have an `order` property,
909915
// but the actual API appears to be that the fields should be shown in

test/api/model/model_checks.dart

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ extension TopicNameChecks on Subject<TopicName> {
3030
}
3131

3232
extension StreamConversationChecks on Subject<StreamConversation> {
33+
Subject<TopicName> get topic => has((x) => x.topic, 'topic');
3334
Subject<String?> get displayRecipient => has((x) => x.displayRecipient, 'displayRecipient');
3435
}
3536

test/example_data.dart

+2-2
Original file line numberDiff line numberDiff line change
@@ -622,8 +622,8 @@ UserTopicEvent userTopicEvent(
622622
);
623623
}
624624

625-
MessageEvent messageEvent(Message message) =>
626-
MessageEvent(id: 0, message: message, localMessageId: null);
625+
MessageEvent messageEvent(Message message, {int? localMessageId}) =>
626+
MessageEvent(id: 0, message: message, localMessageId: localMessageId?.toString());
627627

628628
DeleteMessageEvent deleteMessageEvent(List<StreamMessage> messages) {
629629
assert(messages.isNotEmpty);

test/fake_async_checks.dart

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import 'package:checks/checks.dart';
2+
import 'package:fake_async/fake_async.dart';
3+
4+
extension FakeTimerChecks on Subject<FakeTimer> {
5+
Subject<Duration> get duration => has((t) => t.duration, 'duration');
6+
}

test/model/message_checks.dart

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import 'package:checks/checks.dart';
2+
import 'package:zulip/api/model/model.dart';
3+
import 'package:zulip/model/message.dart';
4+
5+
extension OutboxMessageChecks<T extends Conversation> on Subject<OutboxMessage<T>> {
6+
Subject<int> get localMessageId => has((x) => x.localMessageId, 'localMessageId');
7+
Subject<OutboxMessageLifecycle> get state => has((x) => x.state, 'state');
8+
Subject<bool> get hidden => has((x) => x.hidden, 'hidden');
9+
}

0 commit comments

Comments
 (0)