@@ -3,6 +3,7 @@ import 'package:firebase_core/firebase_core.dart' as firebase_core;
33import 'package:firebase_messaging/firebase_messaging.dart' as firebase_messaging;
44import 'package:flutter/foundation.dart' ;
55import 'package:flutter_local_notifications/flutter_local_notifications.dart' ;
6+ import 'package:package_info_plus/package_info_plus.dart' as package_info_plus;
67import 'package:url_launcher/url_launcher.dart' as url_launcher;
78
89import '../host/android_notifications.dart' ;
@@ -66,6 +67,18 @@ abstract class ZulipBinding {
6667 _instance = this ;
6768 }
6869
70+ /// Provides device and operating system information,
71+ /// via package:device_info_plus.
72+ ///
73+ /// This wraps [device_info_plus.DeviceInfoPlugin.deviceInfo] .
74+ BaseDeviceInfo get deviceInfo;
75+
76+ /// Provides application package information,
77+ /// via package:package_info_plus.
78+ ///
79+ /// This wraps [package_info_plus.PackageInfo.fromPlatform] .
80+ PackageInfo get packageInfo;
81+
6982 /// Prepare the app's [GlobalStore] , loading the necessary data.
7083 ///
7184 /// Generally the app should call this function only once.
@@ -98,12 +111,6 @@ abstract class ZulipBinding {
98111 /// This wraps [url_launcher.closeInAppWebView] .
99112 Future <void > closeInAppWebView ();
100113
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-
107114 /// Initialize Firebase, to use for notifications.
108115 ///
109116 /// This wraps [firebase_core.Firebase.initializeApp] .
@@ -133,13 +140,23 @@ abstract class BaseDeviceInfo {
133140
134141/// Like [device_info_plus.AndroidDeviceInfo] , but without things we don't use.
135142class AndroidDeviceInfo extends BaseDeviceInfo {
143+ /// The user-visible version string.
144+ ///
145+ /// E.g., "1.0" or "3.4b5" or "bananas". This field is an opaque string.
146+ /// Do not assume that its value has any particular structure or that
147+ /// values of RELEASE from different releases can be somehow ordered.
148+ final String release;
149+
136150 /// The Android SDK version.
137151 ///
138152 /// Possible values are defined in:
139153 /// https://developer.android.com/reference/android/os/Build.VERSION_CODES.html
140154 final int sdkInt;
141155
142- AndroidDeviceInfo ({required this .sdkInt});
156+ AndroidDeviceInfo ({
157+ required this .release,
158+ required this .sdkInt,
159+ });
143160}
144161
145162/// Like [device_info_plus.IosDeviceInfo] , but without things we don't use.
@@ -152,6 +169,41 @@ class IosDeviceInfo extends BaseDeviceInfo {
152169 IosDeviceInfo ({required this .systemVersion});
153170}
154171
172+ class MacOsDeviceInfo extends BaseDeviceInfo {
173+ final int majorVersion;
174+ final int minorVersion;
175+ final int patchVersion;
176+
177+ MacOsDeviceInfo ({
178+ required this .majorVersion,
179+ required this .minorVersion,
180+ required this .patchVersion,
181+ });
182+ }
183+
184+ class WindowsDeviceInfo implements BaseDeviceInfo {}
185+
186+ class LinuxDeviceInfo implements BaseDeviceInfo {
187+ final String name;
188+ final String ? versionId;
189+
190+ LinuxDeviceInfo ({
191+ required this .name,
192+ required this .versionId,
193+ });
194+ }
195+
196+ /// Like [package_info_plus.PackageInfo] , but without things we don't use.
197+ class PackageInfo {
198+ final String version;
199+ final String buildNumber;
200+
201+ PackageInfo ({
202+ required this .version,
203+ required this .buildNumber,
204+ });
205+ }
206+
155207/// A concrete binding for use in the live application.
156208///
157209/// The global store returned by [loadGlobalStore] , and consequently by
@@ -162,13 +214,49 @@ class IosDeviceInfo extends BaseDeviceInfo {
162214/// underlying plugin method.
163215class LiveZulipBinding extends ZulipBinding {
164216 /// Initialize the binding if necessary, and ensure it is a [LiveZulipBinding] .
165- static LiveZulipBinding ensureInitialized () {
217+ static Future < LiveZulipBinding > ensureInitialized () async {
166218 if (ZulipBinding ._instance == null ) {
167- LiveZulipBinding ();
219+ final binding = LiveZulipBinding ();
220+ await Future .wait (< Future <void >> [
221+ binding._prefetchDeviceInfo (),
222+ binding._prefetchPackageInfo (),
223+ ]);
168224 }
169225 return ZulipBinding .instance as LiveZulipBinding ;
170226 }
171227
228+ @override
229+ BaseDeviceInfo get deviceInfo => _deviceInfo! ;
230+ BaseDeviceInfo ? _deviceInfo;
231+
232+ @override
233+ PackageInfo get packageInfo => _packageInfo! ;
234+ PackageInfo ? _packageInfo;
235+
236+ Future <void > _prefetchDeviceInfo () async {
237+ final info = await device_info_plus.DeviceInfoPlugin ().deviceInfo;
238+ _deviceInfo = switch (info) {
239+ device_info_plus.AndroidDeviceInfo () => AndroidDeviceInfo (release: info.version.release,
240+ sdkInt: info.version.sdkInt),
241+ device_info_plus.IosDeviceInfo () => IosDeviceInfo (systemVersion: info.systemVersion),
242+ device_info_plus.MacOsDeviceInfo () => MacOsDeviceInfo (majorVersion: info.majorVersion,
243+ minorVersion: info.minorVersion,
244+ patchVersion: info.patchVersion),
245+ device_info_plus.WindowsDeviceInfo () => WindowsDeviceInfo (),
246+ device_info_plus.LinuxDeviceInfo () => LinuxDeviceInfo (name: info.name,
247+ versionId: info.versionId),
248+ _ => throw UnimplementedError (),
249+ };
250+ }
251+
252+ Future <void > _prefetchPackageInfo () async {
253+ final info = await package_info_plus.PackageInfo .fromPlatform ();
254+ _packageInfo = PackageInfo (
255+ version: info.version,
256+ buildNumber: info.buildNumber,
257+ );
258+ }
259+
172260 @override
173261 Future <GlobalStore > loadGlobalStore () {
174262 return LiveGlobalStore .load ();
@@ -195,16 +283,6 @@ class LiveZulipBinding extends ZulipBinding {
195283 return url_launcher.closeInAppWebView ();
196284 }
197285
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-
208286 @override
209287 Future <void > firebaseInitializeApp ({
210288 required firebase_core.FirebaseOptions options}) {
0 commit comments