Skip to content

Commit 7be37dd

Browse files
binding: Prefetch deviceInfo during initialization
This is a preparatory commit for the work of embedding the device info in user-agent header.
1 parent 74de34c commit 7be37dd

File tree

4 files changed

+49
-27
lines changed

4 files changed

+49
-27
lines changed

lib/main.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ void main() {
1313
return true;
1414
}());
1515
LicenseRegistry.addLicense(additionalLicenses);
16-
LiveZulipBinding.ensureInitialized();
1716
WidgetsFlutterBinding.ensureInitialized();
17+
LiveZulipBinding.ensureInitialized();
1818
NotificationService.instance.start();
1919
runApp(const ZulipApp());
2020
}

lib/model/binding.dart

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart';
66
import 'package:url_launcher/url_launcher.dart' as url_launcher;
77

88
import '../host/android_notifications.dart';
9+
import '../log.dart';
910
import '../widgets/store.dart';
1011
import 'store.dart';
1112

@@ -66,6 +67,20 @@ abstract class ZulipBinding {
6667
_instance = this;
6768
}
6869

70+
/// Provides device and operating system information,
71+
/// via package:device_info_plus.
72+
///
73+
/// The returned Future resolves to null if an error is
74+
/// encountered while fetching the data.
75+
Future<BaseDeviceInfo?> get deviceInfo;
76+
77+
/// Provides device and operating system information,
78+
/// via package:device_info_plus.
79+
///
80+
/// May return null if prefetching hasn't completed yet,
81+
/// or an error occured while fetching the data.
82+
BaseDeviceInfo? get maybeDeviceInfo;
83+
6984
/// Prepare the app's [GlobalStore], loading the necessary data.
7085
///
7186
/// Generally the app should call this function only once.
@@ -98,12 +113,6 @@ abstract class ZulipBinding {
98113
/// This wraps [url_launcher.closeInAppWebView].
99114
Future<void> closeInAppWebView();
100115

101-
/// Provides device and operating system information,
102-
/// via package:device_info_plus.
103-
///
104-
/// This wraps [device_info_plus.DeviceInfoPlugin.deviceInfo].
105-
Future<BaseDeviceInfo> deviceInfo();
106-
107116
/// Initialize Firebase, to use for notifications.
108117
///
109118
/// This wraps [firebase_core.Firebase.initializeApp].
@@ -164,11 +173,35 @@ class LiveZulipBinding extends ZulipBinding {
164173
/// Initialize the binding if necessary, and ensure it is a [LiveZulipBinding].
165174
static LiveZulipBinding ensureInitialized() {
166175
if (ZulipBinding._instance == null) {
167-
LiveZulipBinding();
176+
final binding = LiveZulipBinding();
177+
binding._deviceInfo = binding._prefetchDeviceInfo();
168178
}
169179
return ZulipBinding.instance as LiveZulipBinding;
170180
}
171181

182+
@override
183+
Future<BaseDeviceInfo?> get deviceInfo => _deviceInfo;
184+
late Future<BaseDeviceInfo?> _deviceInfo;
185+
186+
@override
187+
BaseDeviceInfo? get maybeDeviceInfo => _maybeDeviceInfo;
188+
BaseDeviceInfo? _maybeDeviceInfo;
189+
190+
Future<BaseDeviceInfo?> _prefetchDeviceInfo() async {
191+
try {
192+
final info = await device_info_plus.DeviceInfoPlugin().deviceInfo;
193+
_maybeDeviceInfo = switch (info) {
194+
device_info_plus.AndroidDeviceInfo(:var version) => AndroidDeviceInfo(sdkInt: version.sdkInt),
195+
device_info_plus.IosDeviceInfo(:var systemVersion) => IosDeviceInfo(systemVersion: systemVersion),
196+
_ => throw UnimplementedError(),
197+
};
198+
} catch (e) {
199+
assert(debugLog('Failed to prefetch device info: $e'));
200+
// TODO(log)
201+
}
202+
return _maybeDeviceInfo;
203+
}
204+
172205
@override
173206
Future<GlobalStore> loadGlobalStore() {
174207
return LiveGlobalStore.load();
@@ -195,16 +228,6 @@ class LiveZulipBinding extends ZulipBinding {
195228
return url_launcher.closeInAppWebView();
196229
}
197230

198-
@override
199-
Future<BaseDeviceInfo> deviceInfo() async {
200-
final deviceInfo = await device_info_plus.DeviceInfoPlugin().deviceInfo;
201-
return switch (deviceInfo) {
202-
device_info_plus.AndroidDeviceInfo(:var version) => AndroidDeviceInfo(sdkInt: version.sdkInt),
203-
device_info_plus.IosDeviceInfo(:var systemVersion) => IosDeviceInfo(systemVersion: systemVersion),
204-
_ => throw UnimplementedError(),
205-
};
206-
}
207-
208231
@override
209232
Future<void> firebaseInitializeApp({
210233
required firebase_core.FirebaseOptions options}) {

lib/widgets/clipboard.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ void copyWithPopup({
1818
required Widget successContent,
1919
}) async {
2020
await Clipboard.setData(data);
21-
final deviceInfo = await ZulipBinding.instance.deviceInfo();
21+
final deviceInfo = await ZulipBinding.instance.deviceInfo;
2222

2323
if (!context.mounted) return;
2424

test/model/binding.dart

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -204,21 +204,20 @@ class TestZulipBinding extends ZulipBinding {
204204
_closeInAppWebViewCallCount++;
205205
}
206206

207-
/// The value that `ZulipBinding.instance.deviceInfo()` should return.
208-
///
209-
/// See also [takeDeviceInfoCalls].
207+
@override
208+
Future<BaseDeviceInfo?> get deviceInfo async => deviceInfoResult;
209+
210+
@override
211+
BaseDeviceInfo? get maybeDeviceInfo => deviceInfoResult;
212+
213+
/// The value that `ZulipBinding.instance.deviceInfo` should return.
210214
BaseDeviceInfo deviceInfoResult = _defaultDeviceInfoResult;
211215
static final _defaultDeviceInfoResult = AndroidDeviceInfo(sdkInt: 33);
212216

213217
void _resetDeviceInfo() {
214218
deviceInfoResult = _defaultDeviceInfoResult;
215219
}
216220

217-
@override
218-
Future<BaseDeviceInfo> deviceInfo() {
219-
return Future(() => deviceInfoResult);
220-
}
221-
222221
void _resetFirebase() {
223222
_firebaseInitialized = false;
224223
_firebaseMessaging = null;

0 commit comments

Comments
 (0)