diff --git a/lib/config.dart b/lib/config.dart index ed07fad3..bd865c9f 100644 --- a/lib/config.dart +++ b/lib/config.dart @@ -23,9 +23,8 @@ abstract class Config { /// Returns a supported language code, falling back to English if not supported /// Uses the app's l10n configuration automatically - no manual maintenance needed static String getSupportedLocale(String locale) { - final supportedLocaleCodes = AppLocalizations.supportedLocales - .map((l) => l.languageCode) - .toList(); + final supportedLocaleCodes = + AppLocalizations.supportedLocales.map((l) => l.languageCode).toList(); return supportedLocaleCodes.contains(locale) ? locale : 'en'; } @@ -33,6 +32,7 @@ abstract class Config { // Wallet-app specific endpoints (can be versioned independently in future) static const dapps = "/wallet-app/dapps/dapps.json"; static dappLocale(String locale) => "/wallet-app/dapps/locales/$locale.json"; + static const appVersionCheck = "/wallet-app/version-check.json"; // General/ecosystem endpoints (shared across Qubic ecosystem) static const smartContracts = "/general/data/smart_contracts.json"; @@ -96,7 +96,7 @@ abstract class Config { static const String proxyIP = '192.168.1.1'; // Replace with actual proxy IP static const int proxyPort = 8888; // Replace with actual proxy port static const DeviceIntegrityResponse deviceIntegrityResponse = - DeviceIntegrityResponse.restrict; + DeviceIntegrityResponse.none; // Configuration for Wallet Connect static const walletConnectProjectId = "b2ace378845f0e4806ef23d2732f77a4"; diff --git a/lib/di.dart b/lib/di.dart index e363edaa..a17c74e9 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -12,6 +12,7 @@ import 'package:qubic_wallet/resources/qubic_cmd.dart'; import 'package:qubic_wallet/resources/secure_storage.dart'; import 'package:qubic_wallet/services/biometric_service.dart'; import 'package:qubic_wallet/services/wallet_connect_service.dart'; +import 'package:qubic_wallet/stores/app_update_store.dart'; import 'package:qubic_wallet/stores/application_store.dart'; import 'package:qubic_wallet/stores/network_store.dart'; import 'package:qubic_wallet/stores/root_jailbreak_flag_store.dart'; @@ -42,6 +43,7 @@ Future setupDI() async { await getIt().initialize(); getIt.registerSingleton(HiveStorage()); await getIt().initialize(); + getIt.registerSingleton(AppUpdateStore()); //Providers getIt.registerSingleton(GlobalSnackBar()); diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 9be88ac2..f628503e 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -961,5 +961,15 @@ "type": "String" } } - } + }, + "updateRequiredTitle": "Update Required", + "updateRequiredMessage": "A new version of Qubic Wallet is required to continue. Please update to the latest version.", + "updateAvailableTitle": "Update Available", + "updateAvailableMessage": "A new version of Qubic Wallet is available with improvements and bug fixes.", + "updateButton": "Update Now", + "laterButton": "Remind Me Later", + "ignoreVersionButton": "Skip This Version", + "updateScreenCurrentVersion": "Current Version", + "updateScreenNewVersion": "New Version", + "updateScreenWhatsNew": "What's New" } \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 7fadd29c..82b3cf30 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,6 +19,7 @@ import 'package:qubic_wallet/stores/application_store.dart'; import 'package:qubic_wallet/stores/wallet_content_store.dart'; import 'package:qubic_wallet/stores/root_jailbreak_flag_store.dart'; import 'package:qubic_wallet/stores/settings_store.dart'; +import 'package:qubic_wallet/stores/app_update_store.dart'; import 'package:qubic_wallet/styles/button_styles.dart'; import 'package:universal_platform/universal_platform.dart'; @@ -41,6 +42,7 @@ Future main() async { getIt.get().setBuildNumber(packageInfo.buildNumber); getIt.get().checkWalletIsInitialized(); + await getIt.get().checkForUpdate(); } catch (e) { appLogger.e(e.toString()); } diff --git a/lib/models/app_version_check_model.dart b/lib/models/app_version_check_model.dart new file mode 100644 index 00000000..4f53cb32 --- /dev/null +++ b/lib/models/app_version_check_model.dart @@ -0,0 +1,80 @@ +import 'package:universal_platform/universal_platform.dart'; + +enum UpdateType { + force, + flexible, + none, +} + +class AppVersionCheckModel { + final String version; + final String? releaseNotes; + final bool showLaterButton; + final bool showIgnoreButton; + final Map updateUrls; + final List platforms; + + static const List _defaultPlatforms = [ + 'android', + 'ios', + ]; + + static const Map _defaultUpdateUrls = { + 'ios': 'https://apps.apple.com/app/qubic-wallet/id6502265811', + 'android': 'https://play.google.com/store/apps/details?id=org.qubic.wallet', + }; + + AppVersionCheckModel({ + required this.version, + this.releaseNotes, + this.showLaterButton = false, + this.showIgnoreButton = false, + this.updateUrls = _defaultUpdateUrls, + this.platforms = _defaultPlatforms, + }); + + /// Derive update type from button visibility: + /// - If both buttons are hidden -> force update + /// - If any button is visible -> flexible update + UpdateType get updateType { + if (!showLaterButton && !showIgnoreButton) { + return UpdateType.force; + } + return UpdateType.flexible; + } + + static AppVersionCheckModel? fromJson(Map? json) { + if (json == null || json.isEmpty) { + return null; + } + + final updateUrls = json['update_urls'] != null + ? Map.from(json['update_urls']) + : _defaultUpdateUrls; + + final platforms = json['platforms'] != null + ? List.from(json['platforms']) + : _defaultPlatforms; + + return AppVersionCheckModel( + version: json['version'], + releaseNotes: json['release_notes'], + showLaterButton: json['show_later_button'] ?? false, + showIgnoreButton: json['show_ignore_button'] ?? false, + updateUrls: updateUrls, + platforms: platforms, + ); + } + + bool isApplicableForCurrentPlatform() { + if (UniversalPlatform.isIOS) return platforms.contains('ios'); + if (UniversalPlatform.isAndroid) return platforms.contains('android'); + return false; + } + + String? getUpdateUrlForPlatform() { + if (UniversalPlatform.isIOS) return updateUrls['ios']; + if (UniversalPlatform.isAndroid) return updateUrls['android']; + return null; + } +} diff --git a/lib/pages/update/app_update_screen.dart b/lib/pages/update/app_update_screen.dart new file mode 100644 index 00000000..81155e5c --- /dev/null +++ b/lib/pages/update/app_update_screen.dart @@ -0,0 +1,99 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:go_router/go_router.dart'; +import 'package:qubic_wallet/di.dart'; +import 'package:qubic_wallet/flutter_flow/theme_paddings.dart'; +import 'package:qubic_wallet/helpers/app_logger.dart'; +import 'package:qubic_wallet/l10n/l10n.dart'; +import 'package:qubic_wallet/models/app_version_check_model.dart'; +import 'package:qubic_wallet/stores/app_update_store.dart'; +import 'package:qubic_wallet/stores/settings_store.dart'; +import 'package:qubic_wallet/styles/text_styles.dart'; +import 'package:qubic_wallet/styles/themed_controls.dart'; +import 'package:url_launcher/url_launcher_string.dart'; + +part 'components/app_update_logo.dart'; +part 'components/app_update_header.dart'; +part 'components/app_update_info_card.dart'; +part 'components/app_update_buttons.dart'; + +class AppUpdateScreen extends StatelessWidget { + const AppUpdateScreen({super.key}); + + @override + Widget build(BuildContext context) { + final appUpdateStore = getIt(); + final settingsStore = getIt(); + + return Observer( + builder: (context) { + final versionInfo = appUpdateStore.currentVersionInfo; + + if (versionInfo == null) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (context.mounted) { + context.go('/'); + } + }); + return const Scaffold( + body: Center(child: CircularProgressIndicator()), + ); + } + + final isForceUpdate = versionInfo.updateType == UpdateType.force; + + return Scaffold( + backgroundColor: LightThemeColors.background, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(ThemePaddings.hugePadding), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const Spacer(), + const _AppUpdateLogo(), + _AppUpdateHeader(isForceUpdate: isForceUpdate), + ThemedControls.spacerVerticalBig(), + _AppUpdateInfoCard( + versionInfo: versionInfo, + currentVersion: settingsStore.versionInfo, + onUpdatePressed: () => _launchUpdateUrl(versionInfo), + ), + const Spacer(), + _AppUpdateButtons( + versionInfo: versionInfo, + onUpdatePressed: () => _launchUpdateUrl(versionInfo), + onLaterPressed: () { + appUpdateStore.handleLaterAction(); + context.go('/'); + }, + onIgnorePressed: () { + appUpdateStore.handleIgnoreAction(versionInfo.version); + context.go('/'); + }, + ), + ], + ), + ), + ), + ); + }, + ); + } + + Future _launchUpdateUrl(AppVersionCheckModel versionInfo) async { + final url = versionInfo.getUpdateUrlForPlatform(); + if (url == null) { + appLogger.e('[AppUpdateScreen] No update URL available for platform'); + return; + } + + try { + await launchUrlString(url, mode: LaunchMode.externalApplication); + } catch (e) { + appLogger.e('[AppUpdateScreen] Failed to launch update URL: $e'); + return; + } + } +} diff --git a/lib/pages/update/components/app_update_buttons.dart b/lib/pages/update/components/app_update_buttons.dart new file mode 100644 index 00000000..4620d5b5 --- /dev/null +++ b/lib/pages/update/components/app_update_buttons.dart @@ -0,0 +1,82 @@ +part of '../app_update_screen.dart'; + +class _AppUpdateButtons extends StatelessWidget { + final AppVersionCheckModel versionInfo; + final VoidCallback onUpdatePressed; + final VoidCallback onLaterPressed; + final VoidCallback onIgnorePressed; + + const _AppUpdateButtons({ + required this.versionInfo, + required this.onUpdatePressed, + required this.onLaterPressed, + required this.onIgnorePressed, + }); + + bool get _hasAllOptions => + versionInfo.showLaterButton && versionInfo.showIgnoreButton; + + @override + Widget build(BuildContext context) { + final l10n = l10nOf(context); + + // Scenario 1: Force update - only Update button at bottom + if (versionInfo.updateType == UpdateType.force) { + return ThemedControls.primaryButtonBig( + onPressed: onUpdatePressed, + text: l10n.updateButton, + ); + } + + final showLater = versionInfo.showLaterButton; + final showIgnore = versionInfo.showIgnoreButton; + + // Scenario 3: All three options - Update in card, Later & Skip in row + if (_hasAllOptions) { + return Row( + children: [ + Expanded( + child: ThemedControls.transparentButtonNormal( + onPressed: onLaterPressed, + text: l10n.laterButton, + ), + ), + ThemedControls.spacerHorizontalNormal(), + Expanded( + child: ThemedControls.dangerButtonBigWithClild( + onPressed: onIgnorePressed, + child: Text( + l10n.ignoreVersionButton, + style: TextStyles.destructiveButtonText, + ), + ), + ), + ], + ); + } + + // Scenario 2: Two options - Update first, then the other option + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + ThemedControls.primaryButtonBig( + onPressed: onUpdatePressed, + text: l10n.updateButton, + ), + if (showLater) + ThemedControls.transparentButtonNormal( + onPressed: onLaterPressed, + text: l10n.laterButton, + ), + if (showIgnore) + ThemedControls.dangerButtonBigWithClild( + onPressed: onIgnorePressed, + child: Text( + l10n.ignoreVersionButton, + style: TextStyles.destructiveButtonText, + ), + ), + ], + ); + } +} diff --git a/lib/pages/update/components/app_update_header.dart b/lib/pages/update/components/app_update_header.dart new file mode 100644 index 00000000..9cc7ed5e --- /dev/null +++ b/lib/pages/update/components/app_update_header.dart @@ -0,0 +1,35 @@ +part of '../app_update_screen.dart'; + +class _AppUpdateHeader extends StatelessWidget { + final bool isForceUpdate; + + const _AppUpdateHeader({required this.isForceUpdate}); + + @override + Widget build(BuildContext context) { + final l10n = l10nOf(context); + + return Column( + children: [ + Text( + isForceUpdate ? l10n.updateRequiredTitle : l10n.updateAvailableTitle, + style: TextStyles.textEnormous.copyWith( + fontWeight: FontWeight.bold, + color: LightThemeColors.primary, + ), + textAlign: TextAlign.center, + ), + ThemedControls.spacerVerticalBig(), + Text( + isForceUpdate + ? l10n.updateRequiredMessage + : l10n.updateAvailableMessage, + style: TextStyles.textNormal.copyWith( + color: LightThemeColors.textColorSecondary, + ), + textAlign: TextAlign.center, + ), + ], + ); + } +} diff --git a/lib/pages/update/components/app_update_info_card.dart b/lib/pages/update/components/app_update_info_card.dart new file mode 100644 index 00000000..ca068fb0 --- /dev/null +++ b/lib/pages/update/components/app_update_info_card.dart @@ -0,0 +1,92 @@ +part of '../app_update_screen.dart'; + +class _AppUpdateInfoCard extends StatelessWidget { + final AppVersionCheckModel versionInfo; + final String? currentVersion; + final VoidCallback onUpdatePressed; + + const _AppUpdateInfoCard({ + required this.versionInfo, + required this.currentVersion, + required this.onUpdatePressed, + }); + + bool get _hasAllOptions => + versionInfo.showLaterButton && versionInfo.showIgnoreButton; + + @override + Widget build(BuildContext context) { + final l10n = l10nOf(context); + + return ThemedControls.card( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _AppUpdateInfoRow( + label: l10n.updateScreenCurrentVersion, + value: currentVersion ?? 'Unknown', + ), + ThemedControls.spacerVerticalSmall(), + _AppUpdateInfoRow( + label: l10n.updateScreenNewVersion, + value: versionInfo.version, + ), + if (versionInfo.releaseNotes != null) ...[ + ThemedControls.spacerVerticalSmall(), + Text( + l10n.updateScreenWhatsNew, + style: TextStyles.secondaryText, + ), + ThemedControls.spacerVerticalSmall(), + Text( + versionInfo.releaseNotes!, + style: TextStyles.textNormal.copyWith( + color: LightThemeColors.primary, + ), + ), + ], + if (_hasAllOptions) ...[ + ThemedControls.spacerVerticalBig(), + SizedBox( + width: double.infinity, + child: ThemedControls.primaryButtonBig( + onPressed: onUpdatePressed, + text: l10n.updateButton, + ), + ), + ], + ], + ), + ); + } +} + +class _AppUpdateInfoRow extends StatelessWidget { + final String label; + final String value; + + const _AppUpdateInfoRow({ + required this.label, + required this.value, + }); + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + label, + style: TextStyles.secondaryText, + ), + Text( + value, + style: TextStyles.textNormal.copyWith( + fontWeight: FontWeight.w600, + color: LightThemeColors.primary, + ), + ), + ], + ); + } +} diff --git a/lib/pages/update/components/app_update_logo.dart b/lib/pages/update/components/app_update_logo.dart new file mode 100644 index 00000000..58baa3bc --- /dev/null +++ b/lib/pages/update/components/app_update_logo.dart @@ -0,0 +1,15 @@ +part of '../app_update_screen.dart'; + +class _AppUpdateLogo extends StatelessWidget { + const _AppUpdateLogo(); + + @override + Widget build(BuildContext context) { + return Center( + child: Image.asset( + 'assets/images/blue-logo.png', + height: 100, + ), + ); + } +} diff --git a/lib/resources/apis/static/qubic_static_api.dart b/lib/resources/apis/static/qubic_static_api.dart index c54c26ef..2c1a9c3e 100644 --- a/lib/resources/apis/static/qubic_static_api.dart +++ b/lib/resources/apis/static/qubic_static_api.dart @@ -1,6 +1,9 @@ import 'package:dio/dio.dart'; import 'package:qubic_wallet/config.dart'; import 'package:qubic_wallet/dtos/dapp_dto.dart'; +import 'package:qubic_wallet/helpers/app_logger.dart'; +import 'package:qubic_wallet/models/app_version_check_model.dart' + show AppVersionCheckModel; import 'package:qubic_wallet/models/labeled_address_model.dart'; import 'package:qubic_wallet/models/smart_contracts_response.dart'; import 'package:qubic_wallet/services/dio_client.dart'; @@ -53,4 +56,26 @@ class QubicStaticApi { throw Exception('Failed to fetch labeled addresses data'); } } + + Future getAppVersionCheck() async { + try { + // TODO: Replace with real API call before production + if (Config.useDevEnvironment) { + return AppVersionCheckModel.fromJson({ + 'version': '2.5.0', + 'release_notes': + '- Critical security fixes\n- Improved transaction reliability\n- Enhanced wallet performance', + 'show_later_button': false, + 'show_ignore_button': false, + 'platforms': ['android', 'ios'], + }); + } + + final response = await _dio.get(Config.appVersionCheck); + return AppVersionCheckModel.fromJson(response.data); + } catch (e) { + appLogger.e('[QubicStaticApi] Failed to fetch app version check: $e'); + throw Exception('Failed to fetch app version check'); + } + } } diff --git a/lib/routes.dart b/lib/routes.dart index da39c3c9..f2bb9255 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -1,9 +1,12 @@ import 'package:flutter/widgets.dart'; import 'package:go_router/go_router.dart'; import 'package:qubic_wallet/di.dart'; +import 'package:qubic_wallet/helpers/app_logger.dart'; import 'package:qubic_wallet/pages/auth/sign_in.dart'; import 'package:qubic_wallet/pages/main/main_screen.dart'; +import 'package:qubic_wallet/pages/update/app_update_screen.dart'; import 'package:qubic_wallet/stores/application_store.dart'; +import 'package:qubic_wallet/stores/app_update_store.dart'; CustomTransitionPage buildPageWithDefaultTransition({ required BuildContext context, @@ -34,15 +37,33 @@ bool isSignedIn() { return getIt().isSignedIn; } +bool needsUpdate() { + final result = getIt().shouldShowUpdateScreen; + appLogger.i('[Routes] needsUpdate() called, result: $result'); + return result; +} + // GoRouter configuration final appRouter = GoRouter( navigatorKey: rootNavigatorKey, routes: [ + GoRoute( + path: '/update', + name: 'update', + pageBuilder: defaultPageBuilder(const AppUpdateScreen()), + ), GoRoute( path: '/signIn', name: 'signIn', builder: (context, state) => const SignIn(), pageBuilder: defaultPageBuilder(const SignIn()), + redirect: (BuildContext context, GoRouterState state) { + // Check for update BEFORE auth + if (needsUpdate()) { + return '/update'; + } + return null; + }, ), GoRoute( path: '/signInNoAuth', @@ -50,6 +71,13 @@ final appRouter = GoRouter( builder: (context, state) => SignIn( disableLocalAuth: state.pathParameters['disableLocalAuth'] == 'true'), pageBuilder: defaultPageBuilder(const SignIn(disableLocalAuth: true)), + redirect: (BuildContext context, GoRouterState state) { + // Check for update BEFORE auth + if (needsUpdate()) { + return '/update'; + } + return null; + }, ), GoRoute( path: '/', @@ -57,6 +85,11 @@ final appRouter = GoRouter( builder: (context, state) => const MainScreen(), pageBuilder: defaultPageBuilder(const MainScreen()), redirect: (BuildContext context, GoRouterState state) { + // Check for update FIRST + if (needsUpdate()) { + return '/update'; + } + // Then check auth if (!isSignedIn()) { return '/signin'; } diff --git a/lib/stores/app_update_store.dart b/lib/stores/app_update_store.dart new file mode 100644 index 00000000..3523caa7 --- /dev/null +++ b/lib/stores/app_update_store.dart @@ -0,0 +1,76 @@ +// ignore_for_file: library_private_types_in_public_api + +import 'package:mobx/mobx.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:version/version.dart'; +import 'package:qubic_wallet/di.dart'; +import 'package:qubic_wallet/models/app_version_check_model.dart' + show UpdateType, AppVersionCheckModel; +import 'package:qubic_wallet/resources/apis/static/qubic_static_api.dart'; +import 'package:qubic_wallet/stores/settings_store.dart'; + +part 'app_update_store.g.dart'; + +class AppUpdateStore = _AppUpdateStore with _$AppUpdateStore; + +abstract class _AppUpdateStore with Store { + static const String _ignoredVersionKey = 'ignored_update_version'; + + final QubicStaticApi _staticApi = getIt(); + final SettingsStore _settingsStore = getIt(); + + /// Latest version info fetched from the API + @observable + AppVersionCheckModel? _versionInfo; + + bool _dismissedForSession = false; + String? _ignoredVersion; + + bool get shouldShowUpdateScreen { + if (_versionInfo == null || _dismissedForSession) return false; + return _shouldShowForVersion(_versionInfo!); + } + + @computed + AppVersionCheckModel? get currentVersionInfo => + shouldShowUpdateScreen ? _versionInfo : null; + + bool _shouldShowForVersion(AppVersionCheckModel info) { + if (!info.isApplicableForCurrentPlatform()) return false; + + final currentVersion = _parseVersion(_settingsStore.versionInfo); + final requiredVersion = _parseVersion(info.version); + final isOutdated = currentVersion < requiredVersion; + final isIgnored = + info.updateType == UpdateType.flexible && _ignoredVersion == info.version; + + return isOutdated && !isIgnored; + } + + Version _parseVersion(String? versionString) { + try { + return Version.parse(versionString ?? '0.0.0'); + } catch (_) { + return Version(0, 0, 0); + } + } + + @action + Future checkForUpdate() async { + final prefs = await SharedPreferences.getInstance(); + _ignoredVersion = prefs.getString(_ignoredVersionKey); + _versionInfo = await _staticApi.getAppVersionCheck(); + } + + @action + void handleLaterAction() { + _dismissedForSession = true; + } + + @action + Future handleIgnoreAction(String version) async { + final prefs = await SharedPreferences.getInstance(); + await prefs.setString(_ignoredVersionKey, version); + _ignoredVersion = version; + } +} diff --git a/lib/stores/app_update_store.g.dart b/lib/stores/app_update_store.g.dart new file mode 100644 index 00000000..8bd47274 --- /dev/null +++ b/lib/stores/app_update_store.g.dart @@ -0,0 +1,74 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'app_update_store.dart'; + +// ************************************************************************** +// StoreGenerator +// ************************************************************************** + +// ignore_for_file: non_constant_identifier_names, unnecessary_brace_in_string_interps, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic, no_leading_underscores_for_local_identifiers + +mixin _$AppUpdateStore on _AppUpdateStore, Store { + Computed? _$currentVersionInfoComputed; + + @override + AppVersionCheckModel? get currentVersionInfo => + (_$currentVersionInfoComputed ??= Computed( + () => super.currentVersionInfo, + name: '_AppUpdateStore.currentVersionInfo')) + .value; + + late final _$_versionInfoAtom = + Atom(name: '_AppUpdateStore._versionInfo', context: context); + + @override + AppVersionCheckModel? get _versionInfo { + _$_versionInfoAtom.reportRead(); + return super._versionInfo; + } + + @override + set _versionInfo(AppVersionCheckModel? value) { + _$_versionInfoAtom.reportWrite(value, super._versionInfo, () { + super._versionInfo = value; + }); + } + + late final _$checkForUpdateAsyncAction = + AsyncAction('_AppUpdateStore.checkForUpdate', context: context); + + @override + Future checkForUpdate() { + return _$checkForUpdateAsyncAction.run(() => super.checkForUpdate()); + } + + late final _$handleIgnoreActionAsyncAction = + AsyncAction('_AppUpdateStore.handleIgnoreAction', context: context); + + @override + Future handleIgnoreAction(String version) { + return _$handleIgnoreActionAsyncAction + .run(() => super.handleIgnoreAction(version)); + } + + late final _$_AppUpdateStoreActionController = + ActionController(name: '_AppUpdateStore', context: context); + + @override + void handleLaterAction() { + final _$actionInfo = _$_AppUpdateStoreActionController.startAction( + name: '_AppUpdateStore.handleLaterAction'); + try { + return super.handleLaterAction(); + } finally { + _$_AppUpdateStoreActionController.endAction(_$actionInfo); + } + } + + @override + String toString() { + return ''' +currentVersionInfo: ${currentVersionInfo} + '''; + } +} diff --git a/pubspec.lock b/pubspec.lock index ca4fae3c..9f02e910 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,15 +5,10 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: "16e298750b6d0af7ce8a3ba7c18c69c3785d11b15ec83f6dcd0ad2a0009b3cab" + sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7" url: "https://pub.dev" source: hosted - version: "76.0.0" - _macros: - dependency: transitive - description: dart - source: sdk - version: "0.3.3" + version: "67.0.0" adaptive_number: dependency: transitive description: @@ -26,10 +21,10 @@ packages: dependency: transitive description: name: analyzer - sha256: "1f14db053a8c23e260789e9b0980fa27f2680dd640932cae5e1137cce0e46e1e" + sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d" url: "https://pub.dev" source: hosted - version: "6.11.0" + version: "6.4.1" animated_snack_bar: dependency: "direct main" description: @@ -371,10 +366,10 @@ packages: dependency: transitive description: name: dart_style - sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab" + sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9" url: "https://pub.dev" source: hosted - version: "2.3.7" + version: "2.3.6" dartx: dependency: transitive description: @@ -395,10 +390,10 @@ packages: dependency: "direct main" description: name: decimal - sha256: "4140a688f9e443e2f4de3a1162387bf25e1ac6d51e24c9da263f245210f41440" + sha256: fc706a5618b81e5b367b01dd62621def37abc096f2b46a9bd9068b64c1fa36d0 url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.2.4" diacritic: dependency: transitive description: @@ -560,10 +555,10 @@ packages: dependency: "direct main" description: name: flutter_form_builder - sha256: c278ef69b08957d484f83413f0e77b656a39b7a7bb4eb8a295da3a820ecc6545 + sha256: "375da52998c72f80dec9187bd93afa7ab202b89d5d066699368ff96d39fd4876" url: "https://pub.dev" source: hosted - version: "9.5.0" + version: "9.7.0" flutter_inappwebview: dependency: "direct main" description: @@ -775,10 +770,10 @@ packages: dependency: "direct main" description: name: form_builder_validators - sha256: c61ed7b1deecf0e1ebe49e2fa79e3283937c5a21c7e48e3ed9856a4a14e1191a + sha256: cd617fa346250293ff3e2709961d0faf7b80e6e4f0ff7b500126b28d7422dd67 url: "https://pub.dev" source: hosted - version: "11.0.0" + version: "11.1.2" freezed_annotation: dependency: transitive description: @@ -1039,10 +1034,10 @@ packages: dependency: transitive description: name: local_auth_android - sha256: "6763aaf8965f21822624cb2fd3c03d2a8b3791037b5efb0fe4b13e110f5afc92" + sha256: "316503f6772dea9c0c038bb7aac4f68ab00112d707d258c770f7fc3c250a2d88" url: "https://pub.dev" source: hosted - version: "1.0.46" + version: "1.0.51" local_auth_darwin: dependency: transitive description: @@ -1083,14 +1078,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" - macros: - dependency: transitive - description: - name: macros - sha256: "1d9e801cd66f7ea3663c45fc708450db1fa57f988142c64289142c9b7ee80656" - url: "https://pub.dev" - source: hosted - version: "0.1.3-main.0" matcher: dependency: transitive description: @@ -1740,10 +1727,10 @@ packages: dependency: "direct main" description: name: timeago - sha256: "054cedf68706bb142839ba0ae6b135f6b68039f0b8301cbe8784ae653d5ff8de" + sha256: b05159406a97e1cbb2b9ee4faa9fb096fe0e2dfcd8b08fcd2a00553450d3422e url: "https://pub.dev" source: hosted - version: "3.7.0" + version: "3.7.1" timing: dependency: transitive description: @@ -1880,6 +1867,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + version: + dependency: "direct main" + description: + name: version + sha256: "3d4140128e6ea10d83da32fef2fa4003fccbf6852217bb854845802f04191f94" + url: "https://pub.dev" + source: hosted + version: "3.0.2" vm_service: dependency: transitive description: @@ -1993,5 +1988,5 @@ packages: source: hosted version: "3.1.3" sdks: - dart: ">=3.5.0 <4.0.0" - flutter: ">=3.24.0" + dart: ">=3.6.0 <4.0.0" + flutter: ">=3.27.0" diff --git a/pubspec.yaml b/pubspec.yaml index ccd688cb..4f0ffee9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -76,6 +76,7 @@ dependencies: safe_device: ^1.2.1 cryptography: ^2.7.0 no_screenshot: ^0.3.1 + version: ^3.0.0 implicitly_animated_list: ^2.3.0 cached_network_image: ^3.4.1