@@ -45,7 +45,7 @@ export 'database.dart' show Account, AccountsCompanion, AccountAlreadyExistsExce
45
45
/// we use outside of tests.
46
46
abstract class GlobalStore extends ChangeNotifier {
47
47
GlobalStore ({required Iterable <Account > accounts})
48
- : _accounts = Map .fromEntries (accounts.map ((a) => MapEntry (a.id, a)));
48
+ : _accounts = Map .fromEntries (accounts.map ((a) => MapEntry (a.id, a)));
49
49
50
50
/// A cache of the [Accounts] table in the underlying data store.
51
51
final Map <int , Account > _accounts;
@@ -67,8 +67,8 @@ abstract class GlobalStore extends ChangeNotifier {
67
67
68
68
ApiConnection apiConnectionFromAccount (Account account) {
69
69
return apiConnection (
70
- realmUrl: account.realmUrl, zulipFeatureLevel: account.zulipFeatureLevel,
71
- email: account.email, apiKey: account.apiKey);
70
+ realmUrl: account.realmUrl, zulipFeatureLevel: account.zulipFeatureLevel,
71
+ email: account.email, apiKey: account.apiKey);
72
72
}
73
73
74
74
final Map <int , PerAccountStore > _perAccountStores = {};
@@ -186,6 +186,7 @@ class PerAccountStore extends ChangeNotifier with StreamStore {
186
186
/// to `globalStore.apiConnectionFromAccount(account)` .
187
187
/// When present, it should be a connection that came from that method call,
188
188
/// but it may have already been used for other requests.
189
+ bool isstale= true ; // Drives the connecting snackbar
189
190
factory PerAccountStore .fromInitialSnapshot ({
190
191
required GlobalStore globalStore,
191
192
required int accountId,
@@ -208,18 +209,18 @@ class PerAccountStore extends ChangeNotifier with StreamStore {
208
209
selfUserId: account.userId,
209
210
userSettings: initialSnapshot.userSettings,
210
211
users: Map .fromEntries (
211
- initialSnapshot.realmUsers
212
- .followedBy (initialSnapshot.realmNonActiveUsers)
213
- .followedBy (initialSnapshot.crossRealmBots)
214
- .map ((user) => MapEntry (user.userId, user))),
212
+ initialSnapshot.realmUsers
213
+ .followedBy (initialSnapshot.realmNonActiveUsers)
214
+ .followedBy (initialSnapshot.crossRealmBots)
215
+ .map ((user) => MapEntry (user.userId, user))),
215
216
streams: streams,
216
217
unreads: Unreads (
217
218
initial: initialSnapshot.unreadMsgs,
218
219
selfUserId: account.userId,
219
220
streamStore: streams,
220
221
),
221
222
recentDmConversationsView: RecentDmConversationsView (
222
- initial: initialSnapshot.recentPrivateConversations, selfUserId: account.userId),
223
+ initial: initialSnapshot.recentPrivateConversations, selfUserId: account.userId),
223
224
);
224
225
}
225
226
@@ -240,10 +241,10 @@ class PerAccountStore extends ChangeNotifier with StreamStore {
240
241
required this .unreads,
241
242
required this .recentDmConversationsView,
242
243
}) : assert (selfUserId == globalStore.getAccount (accountId)! .userId),
243
- assert (realmUrl == globalStore.getAccount (accountId)! .realmUrl),
244
- assert (realmUrl == connection.realmUrl),
245
- _globalStore = globalStore,
246
- _streams = streams;
244
+ assert (realmUrl == globalStore.getAccount (accountId)! .realmUrl),
245
+ assert (realmUrl == connection.realmUrl),
246
+ _globalStore = globalStore,
247
+ _streams = streams;
247
248
248
249
////////////////////////////////////////////////////////////////
249
250
// Data.
@@ -298,7 +299,7 @@ class PerAccountStore extends ChangeNotifier with StreamStore {
298
299
Map <int , Subscription > get subscriptions => _streams.subscriptions;
299
300
@override
300
301
UserTopicVisibilityPolicy topicVisibilityPolicy (int streamId, String topic) =>
301
- _streams.topicVisibilityPolicy (streamId, topic);
302
+ _streams.topicVisibilityPolicy (streamId, topic);
302
303
303
304
final StreamStoreImpl _streams;
304
305
@@ -356,6 +357,7 @@ class PerAccountStore extends ChangeNotifier with StreamStore {
356
357
void handleEvent (Event event) {
357
358
if (event is HeartbeatEvent ) {
358
359
assert (debugLog ("server event: heartbeat" ));
360
+ isstale= false ; // Dismiss the connecting snackbar
359
361
} else if (event is RealmEmojiUpdateEvent ) {
360
362
assert (debugLog ("server event: realm_emoji/update" ));
361
363
realmEmoji = event.realmEmoji;
@@ -526,11 +528,11 @@ class LiveGlobalStore extends GlobalStore {
526
528
527
529
@override
528
530
ApiConnection apiConnection ({
529
- required Uri realmUrl, required int ? zulipFeatureLevel,
530
- String ? email, String ? apiKey}) {
531
+ required Uri realmUrl, required int ? zulipFeatureLevel,
532
+ String ? email, String ? apiKey}) {
531
533
return ApiConnection .live (
532
- realmUrl: realmUrl, zulipFeatureLevel: zulipFeatureLevel,
533
- email: email, apiKey: apiKey);
534
+ realmUrl: realmUrl, zulipFeatureLevel: zulipFeatureLevel,
535
+ email: email, apiKey: apiKey);
534
536
}
535
537
536
538
// We keep the API simple and synchronous for the bulk of the app's code
@@ -591,11 +593,11 @@ class UpdateMachine {
591
593
required this .store,
592
594
required InitialSnapshot initialSnapshot,
593
595
}) : queueId = initialSnapshot.queueId ?? (() {
594
- // The queueId is optional in the type, but should only be missing in the
595
- // case of unauthenticated access to a web-public realm. We authenticated.
596
- throw Exception ("bad initial snapshot: missing queueId" );
597
- })(),
598
- lastEventId = initialSnapshot.lastEventId;
596
+ // The queueId is optional in the type, but should only be missing in the
597
+ // case of unauthenticated access to a web-public realm. We authenticated.
598
+ throw Exception ("bad initial snapshot: missing queueId" );
599
+ })(),
600
+ lastEventId = initialSnapshot.lastEventId;
599
601
600
602
/// Load the user's data from the server, and start an event queue going.
601
603
///
@@ -616,7 +618,7 @@ class UpdateMachine {
616
618
initialSnapshot: initialSnapshot,
617
619
);
618
620
final updateMachine = UpdateMachine .fromInitialSnapshot (
619
- store: store, initialSnapshot: initialSnapshot);
621
+ store: store, initialSnapshot: initialSnapshot);
620
622
updateMachine.poll ();
621
623
// TODO do registerNotificationToken before registerQueue:
622
624
// https://github.com/zulip/zulip-flutter/pull/325#discussion_r1365982807
@@ -636,7 +638,7 @@ class UpdateMachine {
636
638
return await registerQueue (connection);
637
639
} catch (e) {
638
640
assert (debugLog ('Error fetching initial snapshot: $e \n '
639
- 'Backing off, then will retry…' ));
641
+ 'Backing off, then will retry…' ));
640
642
// TODO tell user if initial-fetch errors persist, or look non-transient
641
643
await (backoffMachine ?? = BackoffMachine ()).wait ();
642
644
assert (debugLog ('… Backoff wait complete, retrying initial fetch.' ));
@@ -680,10 +682,11 @@ class UpdateMachine {
680
682
final GetEventsResult result;
681
683
try {
682
684
result = await getEvents (store.connection,
683
- queueId: queueId, lastEventId: lastEventId);
685
+ queueId: queueId, lastEventId: lastEventId);
684
686
} catch (e) {
685
687
switch (e) {
686
688
case ZulipApiException (code: 'BAD_EVENT_QUEUE_ID' ):
689
+
687
690
assert (debugLog ('Lost event queue for $store . Replacing…' ));
688
691
await store._globalStore._reloadPerAccount (store.accountId);
689
692
dispose ();
@@ -693,6 +696,7 @@ class UpdateMachine {
693
696
case Server5xxException () || NetworkException ():
694
697
assert (debugLog ('Transient error polling event queue for $store : $e \n '
695
698
'Backing off, then will retry…' ));
699
+ store.isstale= true ; // drives the connecting snackbar
696
700
// TODO tell user if transient polling errors persist
697
701
// TODO reset to short backoff eventually
698
702
await backoffMachine.wait ();
0 commit comments