Skip to content

Commit 3a1700d

Browse files
gnpricerajveermalviya
authored andcommitted
store: Add "blocking future" option on GlobalStoreWidget
1 parent 72e506a commit 3a1700d

File tree

2 files changed

+63
-2
lines changed

2 files changed

+63
-2
lines changed

lib/widgets/store.dart

+11
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,18 @@ import 'page.dart';
1818
class GlobalStoreWidget extends StatefulWidget {
1919
const GlobalStoreWidget({
2020
super.key,
21+
this.blockingFuture,
2122
this.placeholder = const LoadingPlaceholder(),
2223
required this.child,
2324
});
2425

26+
/// An additional future to await before showing the child.
27+
///
28+
/// If [blockingFuture] is non-null, then this widget will build [child]
29+
/// only after the future completes. This widget's behavior is not affected
30+
/// by whether the future's completion is with a value or with an error.
31+
final Future<void>? blockingFuture;
32+
2533
final Widget placeholder;
2634
final Widget child;
2735

@@ -87,6 +95,9 @@ class _GlobalStoreWidgetState extends State<GlobalStoreWidget> {
8795
super.initState();
8896
(() async {
8997
final store = await ZulipBinding.instance.getGlobalStoreUniquely();
98+
if (widget.blockingFuture != null) {
99+
await widget.blockingFuture!.catchError((_) {});
100+
}
90101
setState(() {
91102
this.store = store;
92103
});

test/widgets/store_test.dart

+52-2
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,12 @@ void main() {
7070
return const SizedBox.shrink();
7171
})));
7272
// First, shows a loading page instead of child.
73-
check(tester.any(find.byType(CircularProgressIndicator))).isTrue();
73+
check(find.byType(CircularProgressIndicator)).findsOne();
7474
check(globalStore).isNull();
7575

7676
await tester.pump();
7777
// Then after loading, mounts child instead, with provided store.
78-
check(tester.any(find.byType(CircularProgressIndicator))).isFalse();
78+
check(find.byType(CircularProgressIndicator)).findsNothing();
7979
check(globalStore).identicalTo(testBinding.globalStore);
8080

8181
await testBinding.globalStore.add(eg.selfAccount, eg.initialSnapshot());
@@ -84,6 +84,56 @@ void main() {
8484
.equals((accountId: eg.selfAccount.id, account: eg.selfAccount));
8585
});
8686

87+
testWidgets('GlobalStoreWidget awaits blockingFuture', (tester) async {
88+
addTearDown(testBinding.reset);
89+
90+
final completer = Completer<void>();
91+
await tester.pumpWidget(Directionality(textDirection: TextDirection.ltr,
92+
child: GlobalStoreWidget(
93+
blockingFuture: completer.future,
94+
child: Text('done'))));
95+
96+
await tester.pump();
97+
await tester.pump();
98+
await tester.pump();
99+
// Even after the store must have loaded,
100+
// still shows loading page while blockingFuture is pending.
101+
check(find.byType(CircularProgressIndicator)).findsOne();
102+
check(find.text('done')).findsNothing();
103+
104+
// Once blockingFuture completes…
105+
completer.complete();
106+
await tester.pump();
107+
// … mounts child instead of the loading page.
108+
check(find.byType(CircularProgressIndicator)).findsNothing();
109+
check(find.text('done')).findsOne();
110+
});
111+
112+
testWidgets('GlobalStoreWidget handles failed blockingFuture like success', (tester) async {
113+
addTearDown(testBinding.reset);
114+
115+
final completer = Completer<void>();
116+
await tester.pumpWidget(Directionality(textDirection: TextDirection.ltr,
117+
child: GlobalStoreWidget(
118+
blockingFuture: completer.future,
119+
child: Text('done'))));
120+
121+
await tester.pump();
122+
await tester.pump();
123+
await tester.pump();
124+
// Even after the store must have loaded,
125+
// still shows loading page while blockingFuture is pending.
126+
check(find.byType(CircularProgressIndicator)).findsOne();
127+
check(find.text('done')).findsNothing();
128+
129+
// Once blockingFuture completes, even with an error…
130+
completer.completeError(Exception('oops'));
131+
await tester.pump();
132+
// … mounts child instead of the loading page.
133+
check(find.byType(CircularProgressIndicator)).findsNothing();
134+
check(find.text('done')).findsOne();
135+
});
136+
87137
testWidgets('GlobalStoreWidget.of updates dependents', (tester) async {
88138
addTearDown(testBinding.reset);
89139

0 commit comments

Comments
 (0)