From bdd26b16b2c3ab935ded67fb6ee16912310792db Mon Sep 17 00:00:00 2001 From: Ryotaro Onoue <73390859+YumNumm@users.noreply.github.com> Date: Fri, 31 May 2024 21:06:00 +0900 Subject: [PATCH] =?UTF-8?q?[FEATURE]=20Deep=20Link=E3=81=AE=E5=AE=9F?= =?UTF-8?q?=E8=A3=85=E3=83=BB=E9=80=9A=E7=9F=A5=E3=82=BF=E3=83=83=E3=83=97?= =?UTF-8?q?=E6=99=82=E3=81=AE=E7=94=BB=E9=9D=A2=E9=81=B7=E7=A7=BB=E5=AE=9F?= =?UTF-8?q?=E8=A3=85=20(#712)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add --- app/ios/Runner.xcodeproj/project.pbxproj | 28 ++----- app/ios/Runner/Info.plist | 2 + app/ios/Runner/Runner.entitlements | 5 ++ app/lib/core/theme/build_theme.dart | 6 ++ .../earthquake_history_details_notifier.dart | 8 +- .../home/component/sheet/status_widget.dart | 1 - .../map/viewmodel/main_map_viewmodel.dart | 78 ++++++++++--------- app/lib/feature/home/view/home_view.dart | 68 +++++++++------- .../children/config/debug/debugger_page.dart | 69 ++++++++++++++++ ...ation_remote_settings_migrate_service.dart | 3 + 10 files changed, 176 insertions(+), 92 deletions(-) diff --git a/app/ios/Runner.xcodeproj/project.pbxproj b/app/ios/Runner.xcodeproj/project.pbxproj index eee8dce18..6cb79b001 100644 --- a/app/ios/Runner.xcodeproj/project.pbxproj +++ b/app/ios/Runner.xcodeproj/project.pbxproj @@ -584,11 +584,9 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Distribution: Ryotaro Onoue (CPL7H8SHVM)"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1169; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = CPL7H8SHVM; + DEVELOPMENT_TEAM = CPL7H8SHVM; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = EQMonitor; @@ -601,7 +599,6 @@ PRODUCT_BUNDLE_IDENTIFIER = net.yumnumm.eqmonitor; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore net.yumnumm.eqmonitor"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; @@ -621,11 +618,9 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_ENTITLEMENTS = FcmServiceExtension/FcmServiceExtension.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development: Ryotaro Onoue (7PWJ49VWRZ)"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1169; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = CPL7H8SHVM; + DEVELOPMENT_TEAM = CPL7H8SHVM; ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu17; GENERATE_INFOPLIST_FILE = YES; @@ -645,7 +640,6 @@ PRODUCT_BUNDLE_IDENTIFIER = net.yumnumm.eqmonitor.FcmServiceExtension; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match Development net.yumnumm.eqmonitor.FcmServiceExtension"; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; SWIFT_EMIT_LOC_STRINGS = YES; @@ -861,11 +855,9 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development: Ryotaro Onoue (7PWJ49VWRZ)"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1169; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = CPL7H8SHVM; + DEVELOPMENT_TEAM = CPL7H8SHVM; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = EQMonitor; @@ -878,7 +870,6 @@ PRODUCT_BUNDLE_IDENTIFIER = net.yumnumm.eqmonitor; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match Development net.yumnumm.eqmonitor"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -895,11 +886,9 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Distribution: Ryotaro Onoue (CPL7H8SHVM)"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1169; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = CPL7H8SHVM; + DEVELOPMENT_TEAM = CPL7H8SHVM; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = EQMonitor; @@ -912,7 +901,6 @@ PRODUCT_BUNDLE_IDENTIFIER = net.yumnumm.eqmonitor; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore net.yumnumm.eqmonitor"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; diff --git a/app/ios/Runner/Info.plist b/app/ios/Runner/Info.plist index c49fea8ba..80054cd98 100644 --- a/app/ios/Runner/Info.plist +++ b/app/ios/Runner/Info.plist @@ -48,6 +48,8 @@ LaunchScreen UIMainStoryboardFile Main + FlutterDeepLinkingEnabled + UISupportedInterfaceOrientations UIInterfaceOrientationLandscapeLeft diff --git a/app/ios/Runner/Runner.entitlements b/app/ios/Runner/Runner.entitlements index fead5277b..7327fe69c 100644 --- a/app/ios/Runner/Runner.entitlements +++ b/app/ios/Runner/Runner.entitlements @@ -4,6 +4,11 @@ aps-environment production + com.apple.developer.associated-domains + + applinks:deeplink.eqmonitor.app + applinks:deeplink.eqmonitor.app?mode=developer + com.apple.developer.usernotifications.critical-alerts com.apple.developer.usernotifications.time-sensitive diff --git a/app/lib/core/theme/build_theme.dart b/app/lib/core/theme/build_theme.dart index 63745e106..ca4fca6fe 100644 --- a/app/lib/core/theme/build_theme.dart +++ b/app/lib/core/theme/build_theme.dart @@ -12,6 +12,12 @@ ThemeData buildTheme({ extensions: [if (customColors != null) customColors], useMaterial3: true, fontFamily: FontFamily.notoSansJP, + pageTransitionsTheme: const PageTransitionsTheme( + builders: { + // MEMO(YumNumm): PredictiveBackを使うと、MediaQuery.sizeOf(context)の値が変わるので無効 + // TargetPlatform.android: PredictiveBackPageTransitionsBuilder(), + }, + ), ); } diff --git a/app/lib/feature/earthquake_history_details/data/earthquake_history_details_notifier.dart b/app/lib/feature/earthquake_history_details/data/earthquake_history_details_notifier.dart index c03d1ff82..dbf57d1d9 100644 --- a/app/lib/feature/earthquake_history_details/data/earthquake_history_details_notifier.dart +++ b/app/lib/feature/earthquake_history_details/data/earthquake_history_details_notifier.dart @@ -28,12 +28,8 @@ class EarthquakeHistoryDetailsNotifier final target = earthquakes?.$1.firstWhereOrNull( (earthquake) => earthquake.eventId == eventId, ); - if (target != null) { - if (target.intensityRegions != null) { - state = AsyncData(target); - } else { - ref.invalidateSelf(); - } + if (target?.intensityRegions != null) { + state = AsyncData(target!); } } }); diff --git a/app/lib/feature/home/component/sheet/status_widget.dart b/app/lib/feature/home/component/sheet/status_widget.dart index 882be2fd4..59ca311f6 100644 --- a/app/lib/feature/home/component/sheet/status_widget.dart +++ b/app/lib/feature/home/component/sheet/status_widget.dart @@ -59,7 +59,6 @@ class SheetStatusWidget extends ConsumerWidget { } return BorderedContainer( - elevation: 1, padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 4, diff --git a/app/lib/feature/home/features/map/viewmodel/main_map_viewmodel.dart b/app/lib/feature/home/features/map/viewmodel/main_map_viewmodel.dart index 1f6eac478..086300fb2 100644 --- a/app/lib/feature/home/features/map/viewmodel/main_map_viewmodel.dart +++ b/app/lib/feature/home/features/map/viewmodel/main_map_viewmodel.dart @@ -759,6 +759,21 @@ class _EewHypocenterService { double _lastOpacity = 0; + Future _changeOpacity(double opacity) => ( + controller.setLayerProperties( + hypocenterIconId, + SymbolLayerProperties( + iconOpacity: opacity, + ), + ), + controller.setLayerProperties( + hypocenterLowPreciseIconId, + SymbolLayerProperties( + iconOpacity: opacity, + ), + ), + ).wait; + Future tick() async { if (!hasInitialized) { return; @@ -768,24 +783,13 @@ class _EewHypocenterService { if (_lastOpacity == 1.0) { return; } - _lastOpacity = 1.0; - await controller.setLayerProperties( - hypocenterIconId, - const SymbolLayerProperties( - iconOpacity: 1.0, - ), - ); + await _changeOpacity(1); } else { if (_lastOpacity == 0.5) { return; } _lastOpacity = 0.5; - await controller.setLayerProperties( - hypocenterIconId, - const SymbolLayerProperties( - iconOpacity: 0.5, - ), - ); + await _changeOpacity(0.5); } } @@ -834,7 +838,7 @@ class _EewPsWaveService { _EewPWaveLineService(controller: controller), _EewSWaveLineService(controller: controller), // _EewPWaveFillService(controller: controller), - // _EewSWaveFillService(controller: controller), + _EewSWaveFillService(controller: controller), ); final MaplibreMapController controller; @@ -844,7 +848,7 @@ class _EewPsWaveService { _EewPWaveLineService, _EewSWaveLineService, // _EewPWaveFillService, - // _EewSWaveFillService + _EewSWaveFillService ) _children; Future init() async { @@ -860,7 +864,7 @@ class _EewPsWaveService { _children.$2.init(), ).wait; // fill - // await _children.$3.init(); + await _children.$3.init(); //_children.$4.init(), } @@ -930,26 +934,28 @@ class _EewPsWaveService { { 'type': 'Feature', 'geometry': { - 'type': 'LineString', + 'type': 'Polygon', 'coordinates': [ - // 0...360 - for (final bearing - in List.generate(361, (index) => index)) - () { - final latLng = const latlong2.Distance().offset( - latlong2.LatLng( - result.$2.lat, - result.$2.lon, - ), - ((type == _WaveType.sWave - ? result.$1.sDistance ?? 0 - : result.$1.pDistance ?? 0) * - 1000) - .toInt(), - bearing, - ); - return [latLng.longitude, latLng.latitude]; - }(), + [ + // 0...360 + for (final bearing + in List.generate(181, (index) => index * 2)) + () { + final latLng = const latlong2.Distance().offset( + latlong2.LatLng( + result.$2.lat, + result.$2.lon, + ), + ((type == _WaveType.sWave + ? result.$1.sDistance ?? 0 + : result.$1.pDistance ?? 0) * + 1000) + .toInt(), + bearing, + ); + return [latLng.longitude, latLng.latitude]; + }(), + ] ], }, 'properties': { @@ -1044,7 +1050,6 @@ class _EewSWaveLineService { static String get layerId => 's-wave-line'; } -/* class _EewPWaveFillService { _EewPWaveFillService({ required this.controller, @@ -1104,7 +1109,6 @@ class _EewSWaveFillService { static String get layerId => 's-wave-fill'; } -*/ @freezed class _EewHypocenterProperties with _$EewHypocenterProperties { diff --git a/app/lib/feature/home/view/home_view.dart b/app/lib/feature/home/view/home_view.dart index f24a026c1..a39bb96a7 100644 --- a/app/lib/feature/home/view/home_view.dart +++ b/app/lib/feature/home/view/home_view.dart @@ -232,24 +232,28 @@ class _HomeBodyWidget extends HookConsumerWidget { firebaseMessagingInteractionProvider, (_, next) async { if (next case AsyncData(:final value)) { - ref.read(talkerProvider).log( - 'Handle Firebase Message: ' - "${const JsonEncoder.withIndent(' ').convert(value.toMap())}", - ); + await WidgetsBinding.instance.endOfFrame.then((_) async { + ref.read(talkerProvider).log( + 'Handle Firebase Message: ' + "${const JsonEncoder.withIndent(' ').convert(value.toMap())}", + ); - final route = value.data['route']; - if (route is String) { - ref.read(goRouterProvider).go(route); - return; - } - final url = value.data['url']; - if (url is String) { - final canLaunch = await canLaunchUrlString(url); - if (canLaunch) { - await launchUrlString(url); + final route = value.data['route']; + if (route is String) { + unawaited( + ref.read(goRouterProvider).push(route), + ); + return; + } + final url = value.data['url']; + if (url is String) { + final canLaunch = await canLaunchUrlString(url); + if (canLaunch) { + await launchUrlString(url); + } + return; } - return; - } + }); } }, ); @@ -495,12 +499,15 @@ class _NotificationMigrationWidget extends ConsumerWidget { return switch (state) { AsyncLoading() => const ListTile( title: Text('通知設定の移行中'), - leading: CircularProgressIndicator(), + leading: CircularProgressIndicator.adaptive(), ), - AsyncError(:final error) => ListTile( - title: const Text('通知設定の移行に失敗しました'), - subtitle: Text(error.toString()), - leading: const Icon(Icons.error), + AsyncError(:final error) => BorderedContainer( + elevation: 1, + child: ListTile( + title: const Text('通知設定の初期化に失敗しました。アプリケーションを再起動することで 再度初期化を試みます。'), + subtitle: Text(error.runtimeType.toString()), + leading: const Icon(Icons.error), + ), ), AsyncData(:final value) => switch (value) { NotificationRemoteSettingsSetupState.initial || @@ -511,23 +518,28 @@ class _NotificationMigrationWidget extends ConsumerWidget { child: switch (value) { NotificationRemoteSettingsSetupState.waitingForFcmToken => const ListTile( - title: Text('FCMトークンの取得中'), - leading: CircularProgressIndicator(), + title: Text('通知配信用トークンの取得中...'), + leading: CircularProgressIndicator.adaptive(), ), NotificationRemoteSettingsSetupState.registering => const ListTile( - title: Text('FCMトークンの登録中'), - leading: CircularProgressIndicator(), + title: Text('通知配信用トークンの登録中...'), + leading: CircularProgressIndicator.adaptive(), ), NotificationRemoteSettingsSetupState.migrating => const ListTile( - title: Text('通知設定の移行中'), - leading: CircularProgressIndicator(), + title: Text('通知設定の初期化中...'), + leading: CircularProgressIndicator.adaptive(), ), NotificationRemoteSettingsSetupState.unsubscribingOldTopics => const ListTile( title: Text('旧通知設定の解除中'), - leading: CircularProgressIndicator(), + leading: CircularProgressIndicator.adaptive(), + ), + NotificationRemoteSettingsSetupState.completing => + const ListTile( + title: Text('通知設定のセットアップが完了しました'), + leading: Icon(Icons.check), ), _ => const SizedBox.shrink(), }, diff --git a/app/lib/feature/settings/children/config/debug/debugger_page.dart b/app/lib/feature/settings/children/config/debug/debugger_page.dart index 36d484e02..35db1688b 100644 --- a/app/lib/feature/settings/children/config/debug/debugger_page.dart +++ b/app/lib/feature/settings/children/config/debug/debugger_page.dart @@ -1,11 +1,14 @@ import 'package:eqmonitor/core/component/container/bordered_container.dart'; import 'package:eqmonitor/core/provider/dio_provider.dart'; +import 'package:eqmonitor/core/provider/notification_token.dart'; import 'package:eqmonitor/core/provider/telegram_url/provider/telegram_url_provider.dart'; +import 'package:eqmonitor/core/provider/websocket/websocket_provider.dart'; import 'package:eqmonitor/core/router/router.dart'; import 'package:eqmonitor/feature/home/component/kmoni/kmoni_settings_dialog.dart'; import 'package:eqmonitor/feature/home/component/sheet/sheet_header.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -60,6 +63,47 @@ class _DebugWidget extends ConsumerWidget { leading: const Icon(Icons.list), onTap: () => context.push(const TalkerRoute().location), ), + ListTile( + title: const Text('EEW Test'), + leading: const Icon(Icons.list), + onTap: () async { + final demoPayload = { + 'commit_timestamp': '2024-04-01T12:10:32.747Z', + 'eventType': 'INSERT', + 'new': { + 'id': -1, + 'event_id': 20240401210952, + 'info_type': '発表', + 'schema_type': 'eew-information', + 'status': '訓練', + 'type': '緊急地震速報(地震動予報)', + 'headline': null, + 'serial_no': 1, + 'is_canceled': false, + 'is_last_info': false, + 'arrival_time': DateTime.now().toIso8601String(), + 'depth': 40, + 'forecast_max_intensity': '1', + 'forecast_max_intensity_is_over': false, + 'forecast_max_lpgm_intensity': '0', + 'forecast_max_lpgm_intensity_is_over': false, + 'hypo_name': '石垣島北西沖', + 'is_warning': false, + 'latitude': 25.2, + 'longitude': 123.6, + 'magnitude': 3.6, + 'origin_time': DateTime.now().toIso8601String(), + 'regions': [], + 'report_time': DateTime.now().toIso8601String(), + }, + 'old': {}, + 'schema': 'public', + 'table': 'eew', + 'errors': null, + }; + ref.read(websocketMessagesProvider.notifier).emit(demoPayload); + }, + ), ListTile( title: const Text('強震モニタ'), leading: const Icon(Icons.settings), @@ -152,6 +196,31 @@ class _DebugWidget extends ConsumerWidget { } }, ), + ListTile( + title: const Text('FCM Token'), + subtitle: Text( + ref + .watch(notificationTokenProvider) + .valueOrNull + ?.fcmToken + ?.toString() ?? + 'null', + ), + onTap: () async { + final token = await FirebaseMessaging.instance.getToken(); + await Clipboard.setData(ClipboardData(text: token ?? '')); + }, + ), + FilledButton.icon( + onPressed: () => + context.push('/earthquake-history-details/20240526142329'), + // const EarthquakeHistoryDetailsRoute(eventId: 20201122190603) + // .push(context), + icon: const Icon(Icons.list), + label: const Text( + "context.push('/earthquake-history-details/20240526142329')", + ), + ), SwitchListTile.adaptive( value: ref.watch(isDioProxyEnabledProvider), onChanged: (value) => ref diff --git a/app/lib/feature/settings/features/notification_remote_settings/data/service/notification_remote_settings_migrate_service.dart b/app/lib/feature/settings/features/notification_remote_settings/data/service/notification_remote_settings_migrate_service.dart index 06c54e4c6..dbd614afa 100644 --- a/app/lib/feature/settings/features/notification_remote_settings/data/service/notification_remote_settings_migrate_service.dart +++ b/app/lib/feature/settings/features/notification_remote_settings/data/service/notification_remote_settings_migrate_service.dart @@ -54,6 +54,8 @@ class NotificationRemoteSettingsInitialSetupNotifier await _migrate(); } + yield NotificationRemoteSettingsSetupState.completing; + await Future.delayed(const Duration(seconds: 1)); yield NotificationRemoteSettingsSetupState.completed; } @@ -179,6 +181,7 @@ enum NotificationRemoteSettingsSetupState { registering, migrating, unsubscribingOldTopics, + completing, completed, ; }