From 90c4f7b438839526f12b1d4f1905d999e4b5daaf Mon Sep 17 00:00:00 2001 From: YumNumm Date: Thu, 20 Jun 2024 00:03:35 +0900 Subject: [PATCH 1/3] add: shorebird --- app/pubspec.yaml | 1 + app/shorebird.yaml | 14 ++++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 app/shorebird.yaml diff --git a/app/pubspec.yaml b/app/pubspec.yaml index 2eeca1e1..397175bc 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -129,6 +129,7 @@ flutter: - assets/images/theme/ - assets/fonts/ - assets/docs/ + - shorebird.yaml shaders: - shaders/introduction.glsl diff --git a/app/shorebird.yaml b/app/shorebird.yaml new file mode 100644 index 00000000..da6abc07 --- /dev/null +++ b/app/shorebird.yaml @@ -0,0 +1,14 @@ +# This file is used to configure the Shorebird updater used by your app. +# Learn more at https://docs.shorebird.dev +# This file should be checked into version control. + +# This is the unique identifier assigned to your app. +# Your app_id is not a secret and is just used to identify your app +# when requesting patches from Shorebird's servers. +app_id: 674ef9fa-cd89-41c7-b2f2-e99662c5823c + +# auto_update controls if Shorebird should automatically update in the background on launch. +# If auto_update: false, you will need to use package:shorebird_code_push to trigger updates. +# https://pub.dev/packages/shorebird_code_push +# Uncomment the following line to disable automatic updates. +# auto_update: false From 7dcc29997011bcdcbbb2a425e323f10ae1192132 Mon Sep 17 00:00:00 2001 From: YumNumm Date: Thu, 20 Jun 2024 01:15:17 +0900 Subject: [PATCH 2/3] fix --- .../provider/ntp/ntp_config_provider.dart | 5 +- app/lib/feature/home/view/home_view.dart | 65 ++++++++++++------- app/lib/feature/settings/settings_screen.dart | 59 ++++++++++++++--- app/pubspec.lock | 8 +++ app/pubspec.yaml | 3 +- 5 files changed, 105 insertions(+), 35 deletions(-) diff --git a/app/lib/core/provider/ntp/ntp_config_provider.dart b/app/lib/core/provider/ntp/ntp_config_provider.dart index 322ced7e..41dbcb65 100644 --- a/app/lib/core/provider/ntp/ntp_config_provider.dart +++ b/app/lib/core/provider/ntp/ntp_config_provider.dart @@ -16,8 +16,11 @@ class NtpConfig extends _$NtpConfig { NtpConfigModel _load() { final prefs = ref.read(sharedPreferencesProvider); final json = prefs.getString(_prefsKey); + if (json == null) { + return const NtpConfigModel(); + } try { - return NtpConfigModel.fromJson(jsonDecode(json!) as Map); + return NtpConfigModel.fromJson(jsonDecode(json) as Map); // ignore: avoid_catches_without_on_clauses } catch (e) { return const NtpConfigModel(); diff --git a/app/lib/feature/home/view/home_view.dart b/app/lib/feature/home/view/home_view.dart index bc5cfaab..6359dcf1 100644 --- a/app/lib/feature/home/view/home_view.dart +++ b/app/lib/feature/home/view/home_view.dart @@ -40,6 +40,7 @@ import 'package:eqmonitor/feature/settings/features/notification_remote_settings import 'package:eqmonitor/feature/settings/features/notification_remote_settings/data/service/notification_remote_settings_migrate_service.dart'; import 'package:firebase_analytics/firebase_analytics.dart'; import 'package:firebase_crashlytics/firebase_crashlytics.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -96,30 +97,48 @@ class _HomeBodyWidget extends HookConsumerWidget { ref.read(permissionProvider.notifier).initialize(), ref.read(ntpProvider.notifier).sync(), () async { - final token = await ref.read(notificationTokenProvider.future); - final fcmToken = token.fcmToken; - if (fcmToken == null) { - return; + final talker = ref.read(talkerProvider); + try { + talker.log('Start Initialize'); + final token = await ref.read(notificationTokenProvider.future); + talker.log('Token: ${token.toJson()}'); + final fcmToken = token.fcmToken; + if (fcmToken == null) { + throw Exception('fcmToken is null'); + } + talker.log('updateToken...'); + await ref + .read(notificationRemoteAuthenticateServiceProvider) + .updateToken(fcmToken: fcmToken); + talker.log('updateToken... Done'); + await ref + .read(fcmTokenChangeDetectorProvider.notifier) + .save(fcmToken); + talker.log('fcmTokenChangeDetectorProvider... Done'); + final authenticationService = + ref.read(apiAuthenticationServiceProvider.notifier); + final ( + id: id, + role: role, + ) = await authenticationService.extractPayload(); + talker.log( + 'Authentication: id=$id, role=$role', + ); + await FirebaseCrashlytics.instance.setUserIdentifier(id); + await FirebaseAnalytics.instance.setUserId( + id: id, + ); + // ignore: avoid_catches_without_on_clauses + } catch (e) { + ref.read(talkerProvider).log( + 'Authentication Error: $e', + ); + await FirebaseCrashlytics.instance.recordError( + e, + StackTrace.current, + ); + rethrow; } - await ref - .read(notificationRemoteAuthenticateServiceProvider) - .updateToken(fcmToken: fcmToken); - await ref - .read(fcmTokenChangeDetectorProvider.notifier) - .save(fcmToken); - final authenticationService = - ref.read(apiAuthenticationServiceProvider.notifier); - final ( - id: id, - role: role, - ) = await authenticationService.extractPayload(); - ref.read(talkerProvider).log( - 'Authentication: id=$id, role=$role', - ); - await FirebaseCrashlytics.instance.setUserIdentifier(id); - await FirebaseAnalytics.instance.setUserId( - id: id, - ); }(), Future.doWhile(() async { try { diff --git a/app/lib/feature/settings/settings_screen.dart b/app/lib/feature/settings/settings_screen.dart index 5b586ad7..140217c1 100644 --- a/app/lib/feature/settings/settings_screen.dart +++ b/app/lib/feature/settings/settings_screen.dart @@ -14,9 +14,11 @@ import 'package:feedback/feedback.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_email_sender/flutter_email_sender.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:path_provider/path_provider.dart'; +import 'package:shorebird_code_push/shorebird_code_push.dart'; import 'package:url_launcher/url_launcher_string.dart'; class SettingsScreen extends ConsumerWidget { @@ -52,16 +54,7 @@ class SettingsScreen extends ConsumerWidget { ), ), ), - Center( - child: Padding( - padding: const EdgeInsets.only(bottom: 16), - child: Text( - 'EQMonitor v${packageInfo.version} ' - '(${packageInfo.buildNumber})', - style: textTheme.bodyMedium, - ), - ), - ), + const _AppVersionInformation(), BorderedContainer( accentColor: Theme.of(context).colorScheme.secondaryContainer, padding: EdgeInsets.zero, @@ -149,6 +142,52 @@ class SettingsScreen extends ConsumerWidget { } } +class _AppVersionInformation extends HookConsumerWidget { + const _AppVersionInformation(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final packageInfo = ref.watch(packageInfoProvider); + final theme = Theme.of(context); + final textTheme = theme.textTheme; + + final patchInfoFuture = useMemoized( + () => ( + ShorebirdCodePush().currentPatchNumber(), + ShorebirdCodePush().nextPatchNumber(), + ).wait, + ); + final patchInfo = useFuture(patchInfoFuture); + + var text = 'EQMonitor v${packageInfo.version} ' + '(${packageInfo.buildNumber}'; + if (patchInfo.hasData) { + final currentPatch = patchInfo.data!.$1; + final nextPatch = patchInfo.data!.$2; + text += switch ((currentPatch, nextPatch)) { + (null, null) => ')', + (null, final int next) => '+$next)\n&' + '新しいパッチが利用可能です。2回アプリケーションを再起動して適用できます。', + (final int current, null) => '+$current)', + (final int current, final int next) => '+$current->$next)\n' + '新しいパッチが利用可能です。2回アプリケーションを再起動して適用できます。', + }; + } else { + text += ')'; + } + + return Center( + child: Padding( + padding: const EdgeInsets.only(bottom: 16), + child: Text( + text, + style: textTheme.bodyMedium, + ), + ), + ); + } +} + Future _onInquiryTap(BuildContext context, WidgetRef ref) async { BetterFeedback.of(context).show( (feedback) async { diff --git a/app/pubspec.lock b/app/pubspec.lock index 2996cd9f..7ce98eef 100644 --- a/app/pubspec.lock +++ b/app/pubspec.lock @@ -1588,6 +1588,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.4" + shorebird_code_push: + dependency: "direct main" + description: + name: shorebird_code_push + sha256: "872839ac1e9b86f97db99c6456c4886620246f15e1cff9d29d4101e2beb991eb" + url: "https://pub.dev" + source: hosted + version: "1.1.3" sky_engine: dependency: transitive description: flutter diff --git a/app/pubspec.yaml b/app/pubspec.yaml index 397175bc..4858463b 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -2,7 +2,7 @@ name: eqmonitor description: An earthquake monitoring Application publish_to: "none" -version: 2.5.1+1190 +version: 2.5.1+1200 environment: sdk: ^3.4.0 @@ -96,6 +96,7 @@ dependencies: url: https://github.com/YumNumm/modal_bottom_sheet.git branch: main path: sheet + shorebird_code_push: ^1.1.3 talker_dio_logger: ^4.2.4 talker_flutter: 4.2.4 url_launcher: ^6.3.0 From da05600885bce898f06da7b5d23d757d8b17ee96 Mon Sep 17 00:00:00 2001 From: YumNumm Date: Thu, 20 Jun 2024 01:20:14 +0900 Subject: [PATCH 3/3] fix: bug --- .../earthquake_history/data/earthquake_history_notifier.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/lib/feature/earthquake_history/data/earthquake_history_notifier.dart b/app/lib/feature/earthquake_history/data/earthquake_history_notifier.dart index 2acb8f50..431438b5 100644 --- a/app/lib/feature/earthquake_history/data/earthquake_history_notifier.dart +++ b/app/lib/feature/earthquake_history/data/earthquake_history_notifier.dart @@ -36,6 +36,7 @@ class EarthquakeHistoryNotifier extends _$EarthquakeHistoryNotifier { ref.watch(jmaParameterProvider).valueOrNull?.earthquake; if (earthquakeParameter == null) { + ref.invalidate(jmaParameterProvider); throw EarthquakeParameterHasNotInitializedException(); } // 検索条件を指定していないNotifierでのみ、30秒ごとにデータ再取得するタイマーを設定 @@ -112,6 +113,9 @@ class EarthquakeHistoryNotifier extends _$EarthquakeHistoryNotifier { await AsyncValue.guard<(List, int totalCount)>( () async { // ensure earthquakeParameter has been initialized. + if (ref.read(jmaParameterProvider).hasError) { + ref.invalidate(jmaParameterProvider); + } await ref.read(jmaParameterProvider.future); final earthquakeParameter = ref.watch(jmaParameterProvider).valueOrNull!.earthquake;