Skip to content

Commit 0142dbd

Browse files
notif: Concurrently initialize NotificationOpenManager
Move NotificationOpenManager initialization to NotificationService and wait for future to complete, while also loading the GlobalStore, displaying a loading spinner while both of them load concurrently. This is an optimization where previously the NotificationOpenManager initialization would happen sequentially before the GlobalStore load.
1 parent c109c1c commit 0142dbd

File tree

6 files changed

+51
-33
lines changed

6 files changed

+51
-33
lines changed

lib/main.dart

+2-10
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,20 @@
1-
import 'dart:async';
2-
31
import 'package:flutter/foundation.dart';
42
import 'package:flutter/widgets.dart';
53

64
import 'licenses.dart';
75
import 'log.dart';
86
import 'model/binding.dart';
9-
import 'notifications/open.dart';
107
import 'notifications/receive.dart';
118
import 'widgets/app.dart';
129

13-
Future<void> main() async {
10+
void main() {
1411
assert(() {
1512
debugLogEnabled = true;
1613
return true;
1714
}());
1815
LicenseRegistry.addLicense(additionalLicenses);
1916
WidgetsFlutterBinding.ensureInitialized();
2017
LiveZulipBinding.ensureInitialized();
21-
22-
// TODO remove this await here
23-
// TODO move this initialization to NotificationService.instance.start()
24-
await NotificationOpenManager.instance.init();
25-
26-
unawaited(NotificationService.instance.start());
18+
NotificationService.instance.start();
2719
runApp(const ZulipApp());
2820
}

lib/notifications/open.dart

+20-12
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,27 @@ class NotificationOpenManager {
2929

3030
NotificationPayloadForOpen? _notifLaunchData;
3131

32+
Completer<void>? _intializedSignal;
33+
Future<void>? get intializationFuture => _intializedSignal?.future;
34+
3235
Future<void> init() async {
33-
switch (defaultTargetPlatform) {
34-
case TargetPlatform.iOS:
35-
case TargetPlatform.android:
36-
_notifLaunchData = await _notifPigeonApi.getNotificationDataFromLaunch();
37-
_notifPigeonApi.notificationTapEventsStream()
38-
.listen(_navigateForNotification);
39-
40-
case TargetPlatform.fuchsia:
41-
case TargetPlatform.linux:
42-
case TargetPlatform.macOS:
43-
case TargetPlatform.windows:
44-
break;
36+
_intializedSignal = Completer();
37+
try {
38+
switch (defaultTargetPlatform) {
39+
case TargetPlatform.iOS:
40+
case TargetPlatform.android:
41+
_notifLaunchData = await _notifPigeonApi.getNotificationDataFromLaunch();
42+
_notifPigeonApi.notificationTapEventsStream()
43+
.listen(_navigateForNotification);
44+
45+
case TargetPlatform.fuchsia:
46+
case TargetPlatform.linux:
47+
case TargetPlatform.macOS:
48+
case TargetPlatform.windows:
49+
break;
50+
}
51+
} finally {
52+
_intializedSignal!.complete();
4553
}
4654
}
4755

lib/notifications/receive.dart

+5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import '../firebase_options.dart';
88
import '../log.dart';
99
import '../model/binding.dart';
1010
import 'display.dart';
11+
import 'open.dart';
1112

1213
@pragma('vm:entry-point')
1314
class NotificationService {
@@ -53,6 +54,8 @@ class NotificationService {
5354
Future<void> start() async {
5455
switch (defaultTargetPlatform) {
5556
case TargetPlatform.android:
57+
await NotificationOpenManager.instance.init();
58+
5659
await ZulipBinding.instance.firebaseInitializeApp(
5760
options: kFirebaseOptionsAndroid);
5861

@@ -77,6 +80,8 @@ class NotificationService {
7780
await _getFcmToken();
7881

7982
case TargetPlatform.iOS: // TODO(#324): defer requesting notif permission
83+
await NotificationOpenManager.instance.init();
84+
8085
await ZulipBinding.instance.firebaseInitializeApp(
8186
options: kFirebaseOptionsIos);
8287

lib/widgets/app.dart

+5
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,11 @@ class _ZulipAppState extends State<ZulipApp> with WidgetsBindingObserver {
202202
Widget build(BuildContext context) {
203203
final themeData = zulipThemeData(context);
204204
return GlobalStoreWidget(
205+
otherAsyncTasks: [
206+
if (NotificationOpenManager.instance.intializationFuture
207+
case final Future<void> future)
208+
future,
209+
],
205210
child: MaterialApp(
206211
onGenerateTitle: (BuildContext context) {
207212
return ZulipLocalizations.of(context).zulipAppTitle;

lib/widgets/store.dart

+19-9
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@ import 'page.dart';
1616
class GlobalStoreWidget extends StatefulWidget {
1717
const GlobalStoreWidget({
1818
super.key,
19+
this.otherAsyncTasks = const [],
1920
this.placeholder = const LoadingPlaceholder(),
2021
required this.child,
2122
});
2223

24+
final Iterable<Future<void>> otherAsyncTasks;
2325
final Widget placeholder;
2426
final Widget child;
2527

@@ -56,24 +58,32 @@ class GlobalStoreWidget extends StatefulWidget {
5658
}
5759

5860
class _GlobalStoreWidgetState extends State<GlobalStoreWidget> {
61+
bool isLoading = true;
5962
GlobalStore? store;
6063

64+
Future<void> _loadGlobalStore() async {
65+
store = await ZulipBinding.instance.getGlobalStoreUniquely();
66+
}
67+
6168
@override
6269
void initState() {
6370
super.initState();
64-
(() async {
65-
final store = await ZulipBinding.instance.getGlobalStoreUniquely();
66-
setState(() {
67-
this.store = store;
68-
});
69-
})();
71+
() async {
72+
try {
73+
await Future.wait([
74+
_loadGlobalStore(),
75+
...widget.otherAsyncTasks,
76+
]);
77+
} finally {
78+
if (mounted) setState(() => isLoading = false);
79+
}
80+
}();
7081
}
7182

7283
@override
7384
Widget build(BuildContext context) {
74-
final store = this.store;
75-
if (store == null) return widget.placeholder;
76-
return _GlobalStoreInheritedWidget(store: store, child: widget.child);
85+
if (isLoading) return widget.placeholder;
86+
return _GlobalStoreInheritedWidget(store: store!, child: widget.child);
7787
}
7888
}
7989

test/notifications/display_test.dart

-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import 'package:zulip/model/localizations.dart';
1616
import 'package:zulip/model/narrow.dart';
1717
import 'package:zulip/model/store.dart';
1818
import 'package:zulip/notifications/display.dart';
19-
import 'package:zulip/notifications/open.dart';
2019
import 'package:zulip/notifications/receive.dart';
2120
import 'package:zulip/widgets/color.dart';
2221
import 'package:zulip/widgets/theme.dart';
@@ -107,7 +106,6 @@ void main() {
107106
testBinding.firebaseMessagingInitialToken = '012abc';
108107
addTearDown(NotificationService.debugReset);
109108
NotificationService.debugBackgroundIsolateIsLive = false;
110-
await NotificationOpenManager.instance.init();
111109
await NotificationService.instance.start();
112110
}
113111

0 commit comments

Comments
 (0)