diff --git a/apps/chanora_flutter/lib/main.dart b/apps/chanora_flutter/lib/main.dart index 7fa5867..e5fd2ea 100644 --- a/apps/chanora_flutter/lib/main.dart +++ b/apps/chanora_flutter/lib/main.dart @@ -37,21 +37,29 @@ bool get _isTouchOnlyPttHost { } /// Public version string shown in the About dialog. Resolved at -/// app init from `package_info_plus`, which reads the platform- -/// canonical version (iOS `CFBundleShortVersionString` + `CFBundleVersion`, -/// Android `versionName` + `versionCode`). Flutter populates both -/// from the SAME `pubspec.yaml` `version:` field, so whatever the -/// user sees in the About dialog is guaranteed to match the -/// commit that produced the build they're running. The "+build" -/// suffix is the post-`+` portion of the pubspec version and -/// distinguishes successive test builds during the iOS audio -/// rollout (every test commit bumps the build number). +/// app init by combining a hardcoded semver baseline (kept in sync +/// with the git tag and pubspec.yaml's `version:` field) with the +/// platform-canonical build counter from `package_info_plus`. /// -/// Initialised before `runApp` in `main()`. Falls back to the -/// hardcoded baseline if `PackageInfo.fromPlatform()` fails -/// (extremely unlikely — the platform channel call is a simple -/// constant lookup). -String _kAppVersion = 'v1.0.0-rc.8'; +/// Why hardcode the semver instead of reading the whole string +/// from `package_info_plus`: iOS rejects non-numeric characters +/// in `CFBundleShortVersionString` and Flutter therefore strips +/// `-rc.8` to `.8` when populating the Info.plist field. The +/// resulting `1.0.0.8` is technically valid on the App Store but +/// useless to humans tracking pre-release builds. +/// `package_info_plus.version` reflects that mangled value. The +/// build counter (`CFBundleVersion` / Android `versionCode`) does +/// pass through unmodified, so we use platform info for the +/// `+` suffix only and pair it with the human-readable +/// semver baseline that this codebase already maintains as the +/// canonical release identity. +/// +/// Bump `_kSemverBaseline` whenever the semver portion of +/// pubspec.yaml advances (e.g. rc.8 -> rc.9 -> 1.0.0). The +/// build-counter suffix changes automatically on every pubspec +/// `+` bump because Flutter writes it into Info.plist. +const String _kSemverBaseline = 'v1.0.0-rc.8'; +String _kAppVersion = _kSemverBaseline; Future main() async { WidgetsFlutterBinding.ensureInitialized(); @@ -62,20 +70,22 @@ Future main() async { runApp(const ChanoraApp()); } -/// Populate `_kAppVersion` from the platform manifest. Format is -/// `v+` (e.g. `v1.0.0-rc.8+60`). The `+` is -/// the iOS `CFBundleVersion` / Android `versionCode`, kept in -/// sync with `pubspec.yaml`'s `version: +`. +/// Populate `_kAppVersion` by suffixing the platform-canonical +/// build number to `_kSemverBaseline`. Format: +/// `v1.0.0-rc.8+` (e.g. `v1.0.0-rc.8+64`). The build +/// number is iOS `CFBundleVersion` / Android `versionCode`, +/// kept in sync with pubspec.yaml's `version: +`. Future _resolveAppVersion() async { try { final info = await PackageInfo.fromPlatform(); - // info.version = "1.0.0-rc.8" (CFBundleShortVersionString) - // info.buildNumber = "60" (CFBundleVersion) + // info.buildNumber = "64" (CFBundleVersion on iOS; survives + // the iOS version-string sanitiser that mangles + // CFBundleShortVersionString). final build = info.buildNumber.isEmpty ? '' : '+${info.buildNumber}'; - _kAppVersion = 'v${info.version}$build'; + _kAppVersion = '$_kSemverBaseline$build'; } catch (_) { - // Keep the hardcoded fallback. Already-correct for the - // semver portion; only the build counter is lost. + // Keep the hardcoded baseline. The build counter is lost + // but the semver stays correct. } } diff --git a/apps/chanora_flutter/pubspec.yaml b/apps/chanora_flutter/pubspec.yaml index d14ad2f..924086f 100644 --- a/apps/chanora_flutter/pubspec.yaml +++ b/apps/chanora_flutter/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.0.0-rc.8+64 +version: 1.0.0-rc.8+65 environment: sdk: ^3.11.5