import 'package:package_info_plus/package_info_plus.dart'; import 'version/app_identity.dart'; /// Single source of truth for the app's identity shown inside the running app. class AppInfo { AppInfo._(); /// Hard-coded fallback mirroring pubspec.yaml and AppIdentity static const String fallbackVersion = '1.0.2+102'; static PackageInfo? _cached; static Future _load() async { return _cached ??= await PackageInfo.fromPlatform(); } /// Resolves the build version in the form `MAJOR.MINOR.PATCH+BUILD` static Future versionString() async { try { final info = await _load(); final name = info.version.isEmpty ? AppIdentity.current().semanticVersion : info.version; final build = info.buildNumber.isEmpty ? '${AppIdentity.current().buildNumber}' : info.buildNumber; return '$name+$build'; } catch (_) { return AppIdentity.current().displayString; } } /// The user-facing `MAJOR.MINOR.PATCH` portion (e.g. `1.0.0`). static Future versionName() async { try { final info = await _load(); return info.version.isEmpty ? AppIdentity.current().semanticVersion : info.version; } catch (_) { return AppIdentity.current().semanticVersion; } } /// The monotonically increasing `+BUILD` portion (e.g. `100`). static Future buildNumber() async { try { final info = await _load(); return info.buildNumber.isEmpty ? '${AppIdentity.current().buildNumber}' : info.buildNumber; } catch (_) { return '${AppIdentity.current().buildNumber}'; } } /// The immutable application identity static AppIdentity get identity => AppIdentity.current(); }