Skip to content

Commit fc80be1

Browse files
gnpricechrisbobbe
authored andcommitted
store [nfc]: Offer singleton global store on binding
This will be useful in the context of showing a notification, where there may not exist an element tree at all (because we may be in a background isolate), and even if there happens to be one (because we happen to be in the foreground) it doesn't otherwise relate to anything the code is doing.
1 parent 26c2aa0 commit fc80be1

File tree

3 files changed

+29
-11
lines changed

3 files changed

+29
-11
lines changed

lib/model/binding.dart

+23-8
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import 'dart:async';
2+
13
import 'package:device_info_plus/device_info_plus.dart' as device_info_plus;
24
import 'package:file_picker/file_picker.dart' as file_picker;
35
import 'package:firebase_core/firebase_core.dart' as firebase_core;
@@ -74,14 +76,20 @@ abstract class ZulipBinding {
7476
_instance = this;
7577
}
7678

77-
/// Prepare the app's [GlobalStore], loading the necessary data.
79+
/// Get the app's singleton [GlobalStore],
80+
/// calling [loadGlobalStore] if not already loaded.
7881
///
79-
/// Generally the app should call this function only once.
82+
/// Where possible, use [GlobalStoreWidget.of] to get access to a [GlobalStore].
83+
/// Use this method only in contexts like notifications where
84+
/// a widget tree may not exist.
85+
Future<GlobalStore> getGlobalStore();
86+
87+
/// Like [getGlobalStore], but assert this method was not previously called.
8088
///
81-
/// This is part of the implementation of [GlobalStoreWidget].
82-
/// In application code, use [GlobalStoreWidget.of] to get access
83-
/// to a [GlobalStore].
84-
Future<GlobalStore> loadGlobalStore();
89+
/// This is used by the implementation of [GlobalStoreWidget],
90+
/// so that our test framework code can detect some cases where
91+
/// a widget test neglects to clean up with `testBinding.reset`.
92+
Future<GlobalStore> getGlobalStoreUniquely();
8593

8694
/// Checks whether the platform can launch [url], via package:url_launcher.
8795
///
@@ -324,9 +332,16 @@ class LiveZulipBinding extends ZulipBinding {
324332
}
325333

326334
@override
327-
Future<GlobalStore> loadGlobalStore() {
328-
return LiveGlobalStore.load();
335+
Future<GlobalStore> getGlobalStore() => _globalStore ??= LiveGlobalStore.load();
336+
Future<GlobalStore>? _globalStore;
337+
338+
@override
339+
Future<GlobalStore> getGlobalStoreUniquely() {
340+
assert(!_debugCalledGetGlobalStoreUniquely);
341+
assert(_debugCalledGetGlobalStoreUniquely = true);
342+
return getGlobalStore();
329343
}
344+
bool _debugCalledGetGlobalStoreUniquely = false;
330345

331346
@override
332347
Future<bool> canLaunchUrl(Uri url) => url_launcher.canLaunchUrl(url);

lib/widgets/store.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class _GlobalStoreWidgetState extends State<GlobalStoreWidget> {
6060
void initState() {
6161
super.initState();
6262
(() async {
63-
final store = await ZulipBinding.instance.loadGlobalStore();
63+
final store = await ZulipBinding.instance.getGlobalStoreUniquely();
6464
setState(() {
6565
this.store = store;
6666
});

test/model/binding.dart

+5-2
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,10 @@ class TestZulipBinding extends ZulipBinding {
100100
}
101101

102102
@override
103-
Future<GlobalStore> loadGlobalStore() {
103+
Future<GlobalStore> getGlobalStore() => Future.value(globalStore);
104+
105+
@override
106+
Future<GlobalStore> getGlobalStoreUniquely() {
104107
assert(() {
105108
if (_debugAlreadyLoadedStore) {
106109
throw FlutterError.fromParts([
@@ -121,7 +124,7 @@ class TestZulipBinding extends ZulipBinding {
121124
_debugAlreadyLoadedStore = true;
122125
return true;
123126
}());
124-
return Future.value(globalStore);
127+
return getGlobalStore();
125128
}
126129

127130
/// The value that `ZulipBinding.instance.canLaunchUrl()` should return.

0 commit comments

Comments
 (0)