Skip to content

Commit 13ffb86

Browse files
committed
draft; Support outbox managed by MessageStore, w/ a flag
1 parent b3ec791 commit 13ffb86

File tree

3 files changed

+43
-10
lines changed

3 files changed

+43
-10
lines changed

lib/model/message.dart

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,11 +215,27 @@ class MessageStoreImpl with MessageStore {
215215
destination, selfUserId: selfUserId, content: content);
216216
final localMessageId = outboxMessage.localMessageId;
217217
assert(!outboxMessages.containsKey(localMessageId));
218-
// TODO debounce new outbox messages
219218
outboxMessages[localMessageId] = outboxMessage;
220-
for (final view in _messageListViews) {
221-
view.handleOutboxMessage(outboxMessage);
222-
}
219+
220+
// The outbox message only become visible to views after
221+
// [kLocalEchoDebounceDuration].
222+
Future<void>.delayed(kLocalEchoDebounceDuration, () {
223+
if (!outboxMessages.containsKey(outboxMessage.localMessageId)) {
224+
// The outbox message was deleted, one such reason can be that the
225+
// corresponding "message" event arrived quickly.
226+
return;
227+
}
228+
if (!outboxMessage.hidden) {
229+
// The outbox message was unhidden due to an error from the
230+
// send-message request.
231+
assert(outboxMessage.state == OutboxMessageLifecycle.failed);
232+
return;
233+
}
234+
outboxMessage.unhide();
235+
for (final view in _messageListViews) {
236+
view.handleOutboxMessage(outboxMessage);
237+
}
238+
});
223239

224240
try {
225241
await _apiSendMessage(connection,
@@ -231,6 +247,10 @@ class MessageStoreImpl with MessageStore {
231247
_updateOutboxMessage(
232248
localMessageId: localMessageId, newState: OutboxMessageLifecycle.sent);
233249
} on ApiRequestException {
250+
outboxMessage.unhide();
251+
for (final view in _messageListViews) {
252+
view.handleOutboxMessage(outboxMessage);
253+
}
234254
_updateOutboxMessage(
235255
localMessageId: localMessageId, newState: OutboxMessageLifecycle.failed);
236256
rethrow;

test/model/message_checks.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ import 'package:zulip/model/message.dart';
33

44
extension OutboxMessageChecks on Subject<OutboxMessage> {
55
Subject<OutboxMessageLifecycle> get state => has((x) => x.state, 'state');
6+
Subject<bool> get hidden => has((x) => x.hidden, 'hidden');
67
}

test/model/message_test.dart

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,14 +93,18 @@ void main() {
9393
delay: Duration.zero);
9494
final future = store.sendMessage(destination: destination, content: 'content');
9595
final outboxMessage = store.outboxMessages.values.single;
96-
check(outboxMessage).state.equals(OutboxMessageLifecycle.sending);
96+
check(outboxMessage)
97+
..state.equals(OutboxMessageLifecycle.sending)
98+
..hidden.isTrue();
9799
checkNotNotified();
98100
check(connection.lastRequest).isA<http.Request>()
99101
..bodyFields['queue_id'].equals(store.queueId)
100102
..bodyFields['local_id'].equals('${outboxMessage.localMessageId}');
101103

102104
await future;
103-
check(outboxMessage).state.equals(OutboxMessageLifecycle.sent);
105+
check(outboxMessage)
106+
..state.equals(OutboxMessageLifecycle.sent)
107+
..hidden.isTrue();
104108
checkNotifiedOnce();
105109

106110
await store.handleEvent(eg.messageEvent(
@@ -116,11 +120,15 @@ void main() {
116120
connection.prepare(json: SendMessageResult(id: 1).toJson());
117121
await store.sendMessage(destination: destination, content: 'content');
118122
final outboxMessage = store.outboxMessages.values.single;
119-
check(outboxMessage).state.equals(OutboxMessageLifecycle.sent);
123+
check(outboxMessage)
124+
..state.equals(OutboxMessageLifecycle.sent)
125+
..hidden.isTrue();
120126
checkNotifiedOnce();
121127

122128
async.elapse(kLocalEchoDebounceDuration);
123-
check(outboxMessage).state.equals(OutboxMessageLifecycle.sent);
129+
check(outboxMessage)
130+
..state.equals(OutboxMessageLifecycle.sent)
131+
..hidden.isFalse();
124132

125133
await store.handleEvent(eg.messageEvent(
126134
eg.streamMessage(), localMessageId: outboxMessage.localMessageId));
@@ -136,11 +144,15 @@ void main() {
136144
delay: Duration.zero);
137145
final future = store.sendMessage(destination: destination, content: 'content');
138146
final outboxMessage = store.outboxMessages.values.single;
139-
check(outboxMessage).state.equals(OutboxMessageLifecycle.sending);
147+
check(outboxMessage)
148+
..state.equals(OutboxMessageLifecycle.sending)
149+
..hidden.isTrue();
140150
checkNotNotified();
141151

142152
await check(future).throws();
143-
check(outboxMessage).state.equals(OutboxMessageLifecycle.failed);
153+
check(outboxMessage)
154+
..state.equals(OutboxMessageLifecycle.failed)
155+
..hidden.isFalse();
144156
checkNotifiedOnce();
145157
});
146158
});

0 commit comments

Comments
 (0)