diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index 4519df1..f65db03 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -14,7 +14,7 @@ jobs: - name: Get version from lib/dev_config.dart id: set-version run: | - echo version=$(grep "kClientVersion" lib/dev_config.dart | cut -d '=' -f 2 | tr -d ';' | tr -d "\'" | tr -d " ") >> $GITHUB_OUTPUT + echo version=$(grep "version:" pubspec.yaml | head -1 | cut -d ':' -f 2 | tr -d ' ') >> $GITHUB_OUTPUT # - name: Extract version from pubspec.yaml # id: extract_version diff --git a/do_builds.sh b/do_builds.sh index 8e3f548..3601b30 100755 --- a/do_builds.sh +++ b/do_builds.sh @@ -23,7 +23,7 @@ for arg in "$@"; do esac done -appver=$(grep "kClientVersion" lib/dev_config.dart | cut -d '=' -f 2 | tr -d ';' | tr -d "\'" | tr -d " ") +appver=$(grep "version:" pubspec.yaml | head -1 | cut -d ':' -f 2 | tr -d ' ') echo echo "Building app version ${appver}..." echo diff --git a/lib/dev_config.dart b/lib/dev_config.dart index fc34336..80eb388 100644 --- a/lib/dev_config.dart +++ b/lib/dev_config.dart @@ -34,12 +34,12 @@ double bottomPositionFromButtonBar(double spacingAboveButtonBar, double safeArea // Add Camera icon vertical offset (no offset needed since circle is centered) const double kAddPinYOffset = 0.0; -// Client name and version for OSM uploads ("created_by" tag) +// Client name for OSM uploads ("created_by" tag) const String kClientName = 'DeFlock'; -const String kClientVersion = '1.0.2'; +// Note: Version is now dynamically retrieved from VersionService // Development/testing features - set to false for production builds -const bool kEnableDevelopmentModes = false; // Set to false to hide sandbox/simulate modes and force production mode +const bool kEnableDevelopmentModes = true; // Set to false to hide sandbox/simulate modes and force production mode // Navigation features - set to false to hide navigation UI elements while in development const bool kEnableNavigationFeatures = kEnableDevelopmentModes; // Hide navigation until fully implemented diff --git a/lib/main.dart b/lib/main.dart index bc875a5..8c68fed 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -11,12 +11,16 @@ import 'screens/advanced_settings_screen.dart'; import 'screens/language_settings_screen.dart'; import 'screens/about_screen.dart'; import 'services/localization_service.dart'; +import 'services/version_service.dart'; Future main() async { WidgetsFlutterBinding.ensureInitialized(); + // Initialize version service + await VersionService().init(); + // Initialize localization service await LocalizationService.instance.init(); diff --git a/lib/screens/settings_screen.dart b/lib/screens/settings_screen.dart index f63c4c8..e2a0301 100644 --- a/lib/screens/settings_screen.dart +++ b/lib/screens/settings_screen.dart @@ -3,6 +3,7 @@ import 'settings/sections/auth_section.dart'; import 'settings/sections/upload_mode_section.dart'; import 'settings/sections/queue_section.dart'; import '../services/localization_service.dart'; +import '../services/version_service.dart'; import '../dev_config.dart'; class SettingsScreen extends StatelessWidget { @@ -91,7 +92,7 @@ class SettingsScreen extends StatelessWidget { Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: Text( - 'Version: $kClientVersion', + 'Version: ${VersionService().version}', style: Theme.of(context).textTheme.bodySmall?.copyWith( color: Theme.of(context).textTheme.bodySmall?.color?.withOpacity(0.6), ), diff --git a/lib/services/uploader.dart b/lib/services/uploader.dart index 59f61da..2b6c4e5 100644 --- a/lib/services/uploader.dart +++ b/lib/services/uploader.dart @@ -3,6 +3,7 @@ import 'package:http/http.dart' as http; import '../models/pending_upload.dart'; import '../dev_config.dart'; +import 'version_service.dart'; import '../app_state.dart'; class Uploader { @@ -32,7 +33,7 @@ class Uploader { final csXml = ''' - + '''; diff --git a/lib/services/version_service.dart b/lib/services/version_service.dart new file mode 100644 index 0000000..5e5b744 --- /dev/null +++ b/lib/services/version_service.dart @@ -0,0 +1,68 @@ +import 'package:flutter/foundation.dart'; +import 'package:package_info_plus/package_info_plus.dart'; + +/// Service for getting app version information from pubspec.yaml. +/// This ensures we have a single source of truth for version info. +class VersionService { + static final VersionService _instance = VersionService._internal(); + factory VersionService() => _instance; + VersionService._internal(); + + PackageInfo? _packageInfo; + bool _initialized = false; + + /// Initialize the service by loading package info + Future init() async { + if (_initialized) return; + + try { + _packageInfo = await PackageInfo.fromPlatform(); + _initialized = true; + debugPrint('[VersionService] Loaded version: ${_packageInfo!.version}'); + } catch (e) { + debugPrint('[VersionService] Failed to load package info: $e'); + _initialized = false; + } + } + + /// Get the app version (e.g., "1.0.2") + String get version { + if (!_initialized || _packageInfo == null) { + debugPrint('[VersionService] Warning: Service not initialized, returning fallback version'); + return 'unknown'; // Fallback for development/testing + } + return _packageInfo!.version; + } + + /// Get the app name + String get appName { + if (!_initialized || _packageInfo == null) { + return 'DeFlock'; // Fallback + } + return _packageInfo!.appName; + } + + /// Get the package name/bundle ID + String get packageName { + if (!_initialized || _packageInfo == null) { + return 'me.deflock.deflockapp'; // Fallback + } + return _packageInfo!.packageName; + } + + /// Get the build number + String get buildNumber { + if (!_initialized || _packageInfo == null) { + return '1'; // Fallback + } + return _packageInfo!.buildNumber; + } + + /// Get full version string with build number (e.g., "1.0.2+1") + String get fullVersion { + return '$version+$buildNumber'; + } + + /// Check if the service is properly initialized + bool get isInitialized => _initialized && _packageInfo != null; +} \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index 2285fa5..2bf35ab 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -443,6 +443,22 @@ packages: url: "https://pub.dev" source: hosted version: "4.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: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 1945444..6811c3f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: deflockapp description: Map public surveillance infrastructure with OpenStreetMap publish_to: "none" -version: 1.0.2 +version: 1.0.7 environment: sdk: ">=3.5.0 <4.0.0" # oauth2_client 4.x needs Dart 3.5+ @@ -29,6 +29,7 @@ dependencies: # Persistence shared_preferences: ^2.2.2 uuid: ^4.0.0 + package_info_plus: ^8.0.0 dev_dependencies: flutter_launcher_icons: ^0.14.4