@@ -161,13 +161,21 @@ abstract class BaseDeviceInfo {
161161
162162/// Like [device_info_plus.AndroidDeviceInfo] , but without things we don't use.
163163class AndroidDeviceInfo extends BaseDeviceInfo {
164+ /// The Android version string, Build.VERSION.RELEASE, e.g. "14".
165+ ///
166+ /// Upstream documents this as an opaque string with no particular structure,
167+ /// but e.g. on stock Android 14 it's "14".
168+ ///
169+ /// See: https://developer.android.com/reference/android/os/Build.VERSION#RELEASE
170+ final String release;
171+
164172 /// The Android SDK version.
165173 ///
166174 /// Possible values are defined in:
167175 /// https://developer.android.com/reference/android/os/Build.VERSION_CODES.html
168176 final int sdkInt;
169177
170- AndroidDeviceInfo ({required this .sdkInt});
178+ AndroidDeviceInfo ({required this .release, required this . sdkInt});
171179}
172180
173181/// Like [device_info_plus.IosDeviceInfo] , but without things we don't use.
@@ -180,6 +188,70 @@ class IosDeviceInfo extends BaseDeviceInfo {
180188 IosDeviceInfo ({required this .systemVersion});
181189}
182190
191+ /// Like [device_info_plus.MacOsDeviceInfo] , but without things we don't use.
192+ class MacOsDeviceInfo extends BaseDeviceInfo {
193+ /// See: https://developer.apple.com/documentation/foundation/operatingsystemversion/1414662-majorversion
194+ final int majorVersion;
195+
196+ /// See: https://developer.apple.com/documentation/foundation/operatingsystemversion/1413801-minorversion
197+ final int minorVersion;
198+
199+ /// See: https://developer.apple.com/documentation/foundation/operatingsystemversion/1415564-patchversion
200+ final int patchVersion;
201+
202+ MacOsDeviceInfo ({
203+ required this .majorVersion,
204+ required this .minorVersion,
205+ required this .patchVersion,
206+ });
207+ }
208+
209+ /// Like [device_info_plus.WindowsDeviceInfo] , currently only used to
210+ /// determine if we're on Windows.
211+ // TODO Determine a method to identify the Windows version.
212+ // Currently, we do not include Windows version information because
213+ // Windows OS does not provide a straightforward way to obtain
214+ // recognizable version information.
215+ // Here's an example of `WindowsDeviceInfo` data[1]. Based on that
216+ // data, there are two possible approaches to identify the Windows
217+ // version:
218+ // - One approach is to use a combination of the majorVersion,
219+ // minorVersion, and buildNumber fields. However, this data does
220+ // not directly correspond to recognizable Windows versions
221+ // (for example major=10, minor=0, build=22631 actually represents
222+ // "Windows 11, 23H2"). Refer to the link in this comment[2] for
223+ // Chromium's implementation of parsing Windows version numbers.
224+ // - Another approach is to use the productName field. While this
225+ // field contains the Windows version, it also includes extraneous
226+ // information. For example, some productName strings are:
227+ // "Windows 11 Pro" and "Windows 10 Home Single Language", which
228+ // makes it less ideal.
229+ // [1]: https://gist.github.com/rajveermalviya/58b3add437280cc7f8356f3697099b7c
230+ // [2]: https://github.com/zulip/zulip-flutter/pull/724#discussion_r1628318991
231+ class WindowsDeviceInfo implements BaseDeviceInfo {}
232+
233+ /// Like [device_info_plus.LinuxDeviceInfo] , but without things we don't use.
234+ class LinuxDeviceInfo implements BaseDeviceInfo {
235+ /// The operating system name, 'NAME' field in /etc/os-release.
236+ ///
237+ /// Examples: 'Fedora', 'Debian GNU/Linux', or just 'Linux'.
238+ ///
239+ /// See: https://www.freedesktop.org/software/systemd/man/latest/os-release.html#NAME=
240+ final String name;
241+
242+ /// The operating system version, 'VERSION_ID' field in /etc/os-release.
243+ ///
244+ /// This string contains only the version number and excludes the
245+ /// OS name and version codenames.
246+ ///
247+ /// Examples: '17', '11.04'.
248+ ///
249+ /// See: https://www.freedesktop.org/software/systemd/man/latest/os-release.html#VERSION_ID=
250+ final String ? versionId;
251+
252+ LinuxDeviceInfo ({required this .name, required this .versionId});
253+ }
254+
183255/// Like [package_info_plus.PackageInfo] , but without things we don't use.
184256class PackageInfo {
185257 final String version;
@@ -251,9 +323,16 @@ class LiveZulipBinding extends ZulipBinding {
251323 try {
252324 final info = await device_info_plus.DeviceInfoPlugin ().deviceInfo;
253325 _syncDeviceInfo = switch (info) {
254- device_info_plus.AndroidDeviceInfo (: var version) => AndroidDeviceInfo (sdkInt: version.sdkInt),
255- device_info_plus.IosDeviceInfo (: var systemVersion) => IosDeviceInfo (systemVersion: systemVersion),
256- _ => throw UnimplementedError (),
326+ device_info_plus.AndroidDeviceInfo () => AndroidDeviceInfo (release: info.version.release,
327+ sdkInt: info.version.sdkInt),
328+ device_info_plus.IosDeviceInfo () => IosDeviceInfo (systemVersion: info.systemVersion),
329+ device_info_plus.MacOsDeviceInfo () => MacOsDeviceInfo (majorVersion: info.majorVersion,
330+ minorVersion: info.minorVersion,
331+ patchVersion: info.patchVersion),
332+ device_info_plus.WindowsDeviceInfo () => WindowsDeviceInfo (),
333+ device_info_plus.LinuxDeviceInfo () => LinuxDeviceInfo (name: info.name,
334+ versionId: info.versionId),
335+ _ => throw UnimplementedError (),
257336 };
258337 } catch (e, st) {
259338 assert (debugLog ('Failed to prefetch device info: $e \n $st ' )); // TODO(log)
0 commit comments