feat(ui): show build number in About dialog (v1.0.0-rc.8+<build>)
Add package_info_plus 8.3.1 (Flutter Community Plus, BSD-3, ~3M downloads) and resolve the displayed version string from the platform manifest at app init. The string shown in the About dialog is now formatted as 'v<version>+<build>' (e.g. 'v1.0.0-rc.8+60') where both halves come from the SAME pubspec.yaml 'version:' field that Flutter uses to populate iOS's CFBundleShortVersionString + CFBundleVersion and Android's versionName + versionCode. Motivation: during the iOS VoiceProcessingIO audio rollout the user is rebuilding repeatedly from Xcode. Without a build-number suffix there is no way to confirm from inside the app which commit produced the build under test — they all read 'v1.0.0-rc.8'. Every test commit going forward bumps the +<build> field in pubspec.yaml so the About dialog uniquely identifies the build. Implementation: * pubspec.yaml: version 1.0.0-rc.8+59 -> +60 (this commit is a test build). Add package_info_plus: ^8.0.0. * main.dart: _kAppVersion changes from 'const String' to 'String' (resolved at runtime). Populated in main() before runApp() via new _resolveAppVersion() helper that calls PackageInfo.fromPlatform() and formats 'v<info.version>+<info.buildNumber>'. Falls back to the hardcoded 'v1.0.0-rc.8' baseline if the platform call fails (extremely unlikely; the platform channel is a constant lookup). The consumer site at the About dialog (l10n.aboutVersion(_kAppVersion)) is unchanged — the variable still resolves to a String. flutter analyze: clean.
This commit is contained in:
@@ -16,6 +16,7 @@ import 'dart:io' show Platform;
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
|
||||||
import 'l10n/generated/app_localizations.dart';
|
import 'l10n/generated/app_localizations.dart';
|
||||||
@@ -35,20 +36,49 @@ bool get _isTouchOnlyPttHost {
|
|||||||
return Platform.isIOS || Platform.isAndroid;
|
return Platform.isIOS || Platform.isAndroid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Public version string shown in the About dialog. Aligned with
|
/// Public version string shown in the About dialog. Resolved at
|
||||||
/// `pubspec.yaml` and the git tag for the MVP release candidate.
|
/// app init from `package_info_plus`, which reads the platform-
|
||||||
/// Bumped to rc.8 for the post-rc.7 v1 audio + PTT lifecycle work
|
/// canonical version (iOS `CFBundleShortVersionString` + `CFBundleVersion`,
|
||||||
/// (SDD-094..097, DEC-029..031).
|
/// Android `versionName` + `versionCode`). Flutter populates both
|
||||||
const String _kAppVersion = 'v1.0.0-rc.8';
|
/// 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).
|
||||||
|
///
|
||||||
|
/// 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';
|
||||||
|
|
||||||
Future<void> main() async {
|
Future<void> main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
await RustLib.init();
|
await RustLib.init();
|
||||||
|
await _resolveAppVersion();
|
||||||
unawaited(_wireStorage());
|
unawaited(_wireStorage());
|
||||||
unawaited(_wireConnectivity());
|
unawaited(_wireConnectivity());
|
||||||
runApp(const ChanoraApp());
|
runApp(const ChanoraApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Populate `_kAppVersion` from the platform manifest. Format is
|
||||||
|
/// `v<version>+<build>` (e.g. `v1.0.0-rc.8+60`). The `+<build>` is
|
||||||
|
/// the iOS `CFBundleVersion` / Android `versionCode`, kept in
|
||||||
|
/// sync with `pubspec.yaml`'s `version: <semver>+<build>`.
|
||||||
|
Future<void> _resolveAppVersion() async {
|
||||||
|
try {
|
||||||
|
final info = await PackageInfo.fromPlatform();
|
||||||
|
// info.version = "1.0.0-rc.8" (CFBundleShortVersionString)
|
||||||
|
// info.buildNumber = "60" (CFBundleVersion)
|
||||||
|
final build = info.buildNumber.isEmpty ? '' : '+${info.buildNumber}';
|
||||||
|
_kAppVersion = 'v${info.version}$build';
|
||||||
|
} catch (_) {
|
||||||
|
// Keep the hardcoded fallback. Already-correct for the
|
||||||
|
// semver portion; only the build counter is lost.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _wireStorage() async {
|
Future<void> _wireStorage() async {
|
||||||
try {
|
try {
|
||||||
final dir = await getApplicationSupportDirectory();
|
final dir = await getApplicationSupportDirectory();
|
||||||
|
|||||||
@@ -309,6 +309,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.3"
|
version: "1.0.3"
|
||||||
|
http:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: http
|
||||||
|
sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.6.0"
|
||||||
http_multi_server:
|
http_multi_server:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -469,6 +477,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.0"
|
version: "2.2.0"
|
||||||
|
package_info_plus:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: package_info_plus
|
||||||
|
sha256: "16eee997588c60225bda0488b6dcfac69280a6b7a3cf02c741895dd370a02968"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "8.3.1"
|
||||||
|
package_info_plus_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: package_info_plus_platform_interface
|
||||||
|
sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.2.1"
|
||||||
path:
|
path:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -730,6 +754,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.3"
|
version: "3.0.3"
|
||||||
|
win32:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: win32
|
||||||
|
sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.15.0"
|
||||||
xdg_directories:
|
xdg_directories:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -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
|
# 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
|
# 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.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 1.0.0-rc.8+59
|
version: 1.0.0-rc.8+60
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.11.5
|
sdk: ^3.11.5
|
||||||
@@ -63,6 +63,17 @@ dependencies:
|
|||||||
# wrong UI: only lists AirPlay output destinations, not the
|
# wrong UI: only lists AirPlay output destinations, not the
|
||||||
# speaker/receiver/Bluetooth choices we actually want.
|
# speaker/receiver/Bluetooth choices we actually want.
|
||||||
audio_session: ^0.2.3
|
audio_session: ^0.2.3
|
||||||
|
# package_info_plus 8.x (Flutter Community Plus, BSD-3, ~3M
|
||||||
|
# downloads) exposes the platform-canonical app version + build
|
||||||
|
# number at runtime so the About dialog (and any future
|
||||||
|
# diagnostic export) can display "v1.0.0-rc.8+60" sourced from
|
||||||
|
# the SAME pubspec.yaml field that drives CFBundleShortVersionString
|
||||||
|
# + CFBundleVersion on iOS and versionName + versionCode on
|
||||||
|
# Android. Single source of truth means the version on the
|
||||||
|
# iPhone screen always matches the commit that built it; no
|
||||||
|
# more "am I testing the right build?" question during the
|
||||||
|
# iOS audio test cycle.
|
||||||
|
package_info_plus: ^8.0.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
Reference in New Issue
Block a user