diff --git a/app/android/app/src/main/res/drawable-hdpi/ic_notification_icon.png b/app/android/app/src/main/res/drawable-hdpi/ic_notification_icon.png
new file mode 100644
index 000000000..515a345df
Binary files /dev/null and b/app/android/app/src/main/res/drawable-hdpi/ic_notification_icon.png differ
diff --git a/app/android/app/src/main/res/drawable-mdpi/ic_notification_icon.png b/app/android/app/src/main/res/drawable-mdpi/ic_notification_icon.png
new file mode 100644
index 000000000..7d545361c
Binary files /dev/null and b/app/android/app/src/main/res/drawable-mdpi/ic_notification_icon.png differ
diff --git a/app/android/app/src/main/res/drawable-xhdpi/ic_notification_icon.png b/app/android/app/src/main/res/drawable-xhdpi/ic_notification_icon.png
new file mode 100644
index 000000000..52adbb769
Binary files /dev/null and b/app/android/app/src/main/res/drawable-xhdpi/ic_notification_icon.png differ
diff --git a/app/android/app/src/main/res/drawable-xxhdpi/ic_notification_icon.png b/app/android/app/src/main/res/drawable-xxhdpi/ic_notification_icon.png
new file mode 100644
index 000000000..06cc348bd
Binary files /dev/null and b/app/android/app/src/main/res/drawable-xxhdpi/ic_notification_icon.png differ
diff --git a/app/android/app/src/main/res/drawable-xxxhdpi/ic_notification_icon.png b/app/android/app/src/main/res/drawable-xxxhdpi/ic_notification_icon.png
new file mode 100644
index 000000000..822c57ee1
Binary files /dev/null and b/app/android/app/src/main/res/drawable-xxxhdpi/ic_notification_icon.png differ
diff --git a/app/assets/docs/about_this_app.md b/app/assets/docs/about_this_app.md
new file mode 100644
index 000000000..7cd10c474
--- /dev/null
+++ b/app/assets/docs/about_this_app.md
@@ -0,0 +1,57 @@
+#### **緊急地震速報のP, S波到達予想円について**
+
+[JMA2001走時表]に対し、線形補間を行い、揺れの到達予想円を算出しています。
+走時表の仕様により、以下の場合到達予想円が表示されない場合があります。
+
+- P, S波の到達範囲が半径2,001km以上
+- 震源の深さが701km以上
+
+強震モニタで表示される揺れ・実際の揺れ・到達予想円はそれぞれ差異が生じる場合があります。
+
+#### **地震情報(緊急地震速報を含む)について**
+
+[Project DM(Disaster Mitigation)-Data Send Service] (以降 Project DM-D.S.S)を利用し、各種地震情報の取得を行っています。
+Project DM-D.S.Sから受信したデータを、EQMonitor用に開発者が用意したプライベートAPI(HTTP, WebSocket)で再配信しています。
+
+- 緊急地震速報の再配信については、Project DM-D.S.Sの[再配信ポリシー](https://dmdata.jp/docs/eew#%E5%86%8D%E9%85%8D%E4%BF%A1%E3%83%9D%E3%83%AA%E3%82%B7%E3%83%BC)に基づき、事前の許可を得ています。(2022年12月3日承認済み)
+ - ※本アプリケーションの開発に、Project DM-D.S.Sの運営者は一切関係がありません。したがって、本アプリケーションに関するお問い合わせをProject DM-D.S.Sの運営者にすることはお控えください。
+
+[JMA2001走時表]: https://www.data.jma.go.jp/eqev/data/bulletin/catalog/appendix/trtime/trt_j.html
+[Project DM(Disaster Mitigation)-Data Send Service]: https://dmdata.jp/
+
+#### **著作権関連**
+
+- 地図データ
+ - 日本: 国土数値情報 行政区域
+ - 日本以外: Natural Earth
+- 強震モニタの観測点データ
+ - 防災科学技術研究所(NIED)
+- 各種地震情報
+ - 気象庁
+
+#### **Special Thanks**
+
+- [JQuake(フランソワ) 様]
+ - 強震モニタ画像解析手法 [多項式補間を使用して強震モニタ画像から数値データを決定する](https://qiita.com/NoneType1/items/a4d2cf932e20b56ca444)
+- [ingen084 様]
+ - 各種処理の参考 [KyoshinEewViewerIngen]
+ - 強震モニタの観測点データ [KyoshinMonitorLib]
+ - 強震モニタ画像解析手法 [強震モニタの画像から震度と地点を特定するまで](https://qiita.com/ingen084/items/7e91f8da2996972ac586)
+- [Laddge 様] ウェブサイトの制作
+- [ともりん 様] 通知音・効果音の制作
+
+[JQuake(フランソワ) 様]: https://twitter.com/NoneType1
+[KyoshinEewViewerIngen]: https://github.com/ingen084/KyoshinEewViewerIngen
+[ingen084 様]: https://twitter.com/ingen084
+[KyoshinMonitorLib]: https://github.com/ingen084/KyoshinMonitorLib
+[Laddge 様]: https://twitter.com/laddge_
+[ともりん 様]: https://twitter.com/tomorin1223
+
+#### **本アプリの開発者**
+
+EQMonitorは、もぐもぐ (Ryotaro Onoue)によって開発されました。
+MIT License に基づき、ソースコードを公開しています。(GitHub: [YumNumm/EQMonitor](https://github.com/YumNumm/EQMonitor))
+
+- Twitter: [@YumNumm](https://twitter.com/YumNumm), [@EQMonitorApp](https://twitter.com/EQMonitorApp)
+- GitHub: [@YumNumm](https://github.com/YumNumm)
+- Mail: [admin@yumnumm.dev](admin@yumnumm.dev) もしくは [contacts@eqmonitor.app](contacts@eqmonitor.app)
diff --git a/app/ios/Runner.xcodeproj/project.pbxproj b/app/ios/Runner.xcodeproj/project.pbxproj
index 48365a863..9be93a1a9 100644
--- a/app/ios/Runner.xcodeproj/project.pbxproj
+++ b/app/ios/Runner.xcodeproj/project.pbxproj
@@ -525,7 +525,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
- CURRENT_PROJECT_VERSION = 1152;
+ CURRENT_PROJECT_VERSION = 1157;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = CPL7H8SHVM;
ENABLE_BITCODE = NO;
@@ -560,7 +560,7 @@
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
- CURRENT_PROJECT_VERSION = 1152;
+ CURRENT_PROJECT_VERSION = 1157;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = CPL7H8SHVM;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
@@ -602,7 +602,7 @@
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
- CURRENT_PROJECT_VERSION = 1152;
+ CURRENT_PROJECT_VERSION = 1157;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = CPL7H8SHVM;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
@@ -643,7 +643,7 @@
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
- CURRENT_PROJECT_VERSION = 1152;
+ CURRENT_PROJECT_VERSION = 1157;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = CPL7H8SHVM;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
@@ -787,7 +787,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
- CURRENT_PROJECT_VERSION = 1152;
+ CURRENT_PROJECT_VERSION = 1157;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = CPL7H8SHVM;
ENABLE_BITCODE = NO;
@@ -819,7 +819,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
- CURRENT_PROJECT_VERSION = 1152;
+ CURRENT_PROJECT_VERSION = 1157;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = CPL7H8SHVM;
ENABLE_BITCODE = NO;
diff --git a/app/ios/Runner/Info.plist b/app/ios/Runner/Info.plist
index 2f41daa55..49f47eb81 100644
--- a/app/ios/Runner/Info.plist
+++ b/app/ios/Runner/Info.plist
@@ -1,43 +1,6 @@
-
- CADisableMinimumFrameDurationOnPhone
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleDisplayName
- EQMonitor
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- eqmonitor
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- $(FLUTTER_BUILD_NAME)
- CFBundleSignature
- ????
- CFBundleVersion
- 1152
- LSRequiresIPhoneOS
-
- UIApplicationSupportsIndirectInputEvents
-
- UIBackgroundModes
-
- fetch
- remote-notification
-
- UILaunchStoryboardName
- LaunchScreen
- UIMainStoryboardFile
- Main
- NSAppTransportSecurity
CADisableMinimumFrameDurationOnPhone
@@ -60,9 +23,7 @@
CFBundleSignature
????
CFBundleVersion
- 1154
- UIViewControllerBasedStatusBarAppearance
-
+ 1157
LSRequiresIPhoneOS
UIApplicationSupportsIndirectInputEvents
@@ -95,4 +56,4 @@
UIInterfaceOrientationPortraitUpsideDown
-
+
\ No newline at end of file
diff --git a/app/lib/app.dart b/app/lib/app.dart
index 3a836cff3..02ad925dd 100644
--- a/app/lib/app.dart
+++ b/app/lib/app.dart
@@ -72,7 +72,6 @@ class App extends HookConsumerWidget {
child: Banner(
message: 'v${packageInfo.version}-${packageInfo.buildNumber}',
location: BannerLocation.bottomStart,
- color: Colors.red.shade900,
child: app,
),
);
diff --git a/app/lib/core/component/sheet/basic_modal_sheet.dart b/app/lib/core/component/sheet/basic_modal_sheet.dart
index 27ce30ae4..91eb0f2d1 100644
--- a/app/lib/core/component/sheet/basic_modal_sheet.dart
+++ b/app/lib/core/component/sheet/basic_modal_sheet.dart
@@ -63,27 +63,25 @@ class BasicModalSheet extends HookWidget {
child: SafeArea(
top: hasAppBar,
bottom: false,
- child: RepaintBoundary(
- child: Column(
- children: [
- barWidget,
- if (useColumn)
- Expanded(
- child: SingleChildScrollView(
- child: Column(
- children: children,
- ),
- ),
- )
- else
- Expanded(
- child: ListView(
- padding: const EdgeInsets.all(2),
+ child: Column(
+ children: [
+ barWidget,
+ if (useColumn)
+ Expanded(
+ child: SingleChildScrollView(
+ child: Column(
children: children,
),
),
- ],
- ),
+ )
+ else
+ Expanded(
+ child: ListView(
+ padding: const EdgeInsets.all(2),
+ children: children,
+ ),
+ ),
+ ],
),
),
),
diff --git a/app/lib/core/provider/app_information/app_information_model.freezed.dart b/app/lib/core/provider/app_information/app_information_model.freezed.dart
index 681738baf..94bf867f4 100644
--- a/app/lib/core/provider/app_information/app_information_model.freezed.dart
+++ b/app/lib/core/provider/app_information/app_information_model.freezed.dart
@@ -12,7 +12,7 @@ part of 'app_information_model.dart';
T _$identity(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
- 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
+ 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
AppInformationModel _$AppInformationModelFromJson(Map json) {
return _AppInformationModel.fromJson(json);
diff --git a/app/lib/core/provider/config/theme/intensity_color/model/intensity_color_model.freezed.dart b/app/lib/core/provider/config/theme/intensity_color/model/intensity_color_model.freezed.dart
index f23e629b1..3f5431be5 100644
--- a/app/lib/core/provider/config/theme/intensity_color/model/intensity_color_model.freezed.dart
+++ b/app/lib/core/provider/config/theme/intensity_color/model/intensity_color_model.freezed.dart
@@ -12,7 +12,7 @@ part of 'intensity_color_model.dart';
T _$identity(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
- 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
+ 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
IntensityColorModel _$IntensityColorModelFromJson(Map json) {
return _IntensityColorModel.fromJson(json);
diff --git a/app/lib/core/router/router.dart b/app/lib/core/router/router.dart
index 9b394b5e8..df60151f6 100644
--- a/app/lib/core/router/router.dart
+++ b/app/lib/core/router/router.dart
@@ -11,6 +11,7 @@ import 'package:eqmonitor/feature/earthquake_history_details/screen/earthquake_h
import 'package:eqmonitor/feature/home/view/home_view.dart';
import 'package:eqmonitor/feature/information_history/page/information_history_page.dart';
import 'package:eqmonitor/feature/information_history_details/information_history_details_page.dart';
+import 'package:eqmonitor/feature/settings/children/application_info/about_this_app.dart';
import 'package:eqmonitor/feature/settings/children/application_info/license_page.dart';
import 'package:eqmonitor/feature/settings/children/application_info/privacy_policy_screen.dart';
import 'package:eqmonitor/feature/settings/children/application_info/term_of_service_screen.dart';
@@ -152,6 +153,9 @@ class KmoniRoute extends GoRouteData {
TypedGoRoute(
path: 'earthquake-history',
),
+ TypedGoRoute(
+ path: 'about-this-app',
+ ),
TypedGoRoute(
path: 'donation',
routes: [
@@ -263,6 +267,14 @@ class LicenseRoute extends GoRouteData {
const LicensePage();
}
+class AboutThisAppRoute extends GoRouteData {
+ const AboutThisAppRoute();
+
+ @override
+ Widget build(BuildContext context, GoRouterState state) =>
+ const AboutThisAppScreen();
+}
+
class NotificationSettingsRoute extends GoRouteData {
const NotificationSettingsRoute();
diff --git a/app/lib/core/router/router.g.dart b/app/lib/core/router/router.g.dart
index 10c5d21d0..4a93420ee 100644
--- a/app/lib/core/router/router.g.dart
+++ b/app/lib/core/router/router.g.dart
@@ -232,6 +232,10 @@ RouteBase get $settingsRoute => GoRouteData.$route(
path: 'earthquake-history',
factory: $EarthquakeHistoryConfigRouteExtension._fromState,
),
+ GoRouteData.$route(
+ path: 'about-this-app',
+ factory: $AboutThisAppRouteExtension._fromState,
+ ),
GoRouteData.$route(
path: 'donation',
factory: $DonationRouteExtension._fromState,
@@ -402,6 +406,24 @@ extension $EarthquakeHistoryConfigRouteExtension
void replace(BuildContext context) => context.replace(location);
}
+extension $AboutThisAppRouteExtension on AboutThisAppRoute {
+ static AboutThisAppRoute _fromState(GoRouterState state) =>
+ const AboutThisAppRoute();
+
+ String get location => GoRouteData.$location(
+ '/settings/about-this-app',
+ );
+
+ void go(BuildContext context) => context.go(location);
+
+ Future push(BuildContext context) => context.push(location);
+
+ void pushReplacement(BuildContext context) =>
+ context.pushReplacement(location);
+
+ void replace(BuildContext context) => context.replace(location);
+}
+
extension $DonationRouteExtension on DonationRoute {
static DonationRoute _fromState(GoRouterState state) => const DonationRoute();
diff --git a/app/lib/core/theme/build_theme.dart b/app/lib/core/theme/build_theme.dart
index aaedfa470..63745e106 100644
--- a/app/lib/core/theme/build_theme.dart
+++ b/app/lib/core/theme/build_theme.dart
@@ -1,4 +1,5 @@
import 'package:eqmonitor/core/theme/custom_colors.dart';
+import 'package:eqmonitor/gen/fonts.gen.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
@@ -6,15 +7,12 @@ ThemeData buildTheme({
ColorScheme? colorScheme,
CustomColors? customColors,
}) {
- final notoSansJp = GoogleFonts.notoSansJp().fontFamily;
- final robotoMono = GoogleFonts.robotoMono().fontFamily;
return ThemeData(
colorScheme: colorScheme,
extensions: [if (customColors != null) customColors],
useMaterial3: true,
- fontFamily: robotoMono,
- fontFamilyFallback: [
- if (notoSansJp != null) notoSansJp,
- ],
+ fontFamily: FontFamily.notoSansJP,
);
}
+
+final monoFont = GoogleFonts.fragmentMono().fontFamily;
diff --git a/app/lib/core/util/license/init_licenses.dart b/app/lib/core/util/license/init_licenses.dart
new file mode 100644
index 000000000..e06707944
--- /dev/null
+++ b/app/lib/core/util/license/init_licenses.dart
@@ -0,0 +1,68 @@
+import 'package:flutter/foundation.dart';
+
+Future initLicenses() async {
+ LicenseRegistry.addLicense(
+ () async* {
+ yield const LicenseEntryWithLineBreaks(
+ ['KyoshinEewViewerIngen'],
+ '''
+MIT License
+
+Copyright (c) 2019 ingen084
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+''',
+ );
+ yield const LicenseEntryWithLineBreaks(
+ ['KyoshinMonitorLib'],
+ '''
+MIT License
+
+Copyright (c) 2020 ingen084
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.''',
+ );
+ yield const LicenseEntryWithLineBreaks(
+ ['「国土数値情報(行政区域データ)」(国土交通省)(当該ページのURL)を加工して作成'],
+ '''
+https://nlftp.mlit.go.jp/ksj/other/agreement.html に従います''',
+ );
+ yield const LicenseEntryWithLineBreaks(
+ ['Natural Earth(世界地図)'],
+ '© 2009 - 2024. Natural Earth. All rights reserved.\nhttps://www.naturalearthdata.com/',
+ );
+ },
+ );
+}
diff --git a/app/lib/feature/donation/ui/donation_choice_modal.dart b/app/lib/feature/donation/ui/donation_choice_modal.dart
index cbd8cd529..942a8f110 100644
--- a/app/lib/feature/donation/ui/donation_choice_modal.dart
+++ b/app/lib/feature/donation/ui/donation_choice_modal.dart
@@ -62,7 +62,7 @@ class DonationChoiceModal extends HookConsumerWidget {
final product = e.$2;
final emoji = product.emoji;
return ListTile(
- title: Text(choice.title),
+ title: Text(product.productName),
subtitle: Text(choice.description),
trailing: Text(
choice.priceString,
@@ -106,4 +106,11 @@ extension ProductEx on Products {
return '🍱';
}
}
+
+ String get productName => switch (this) {
+ Products.coffee => 'コーヒー',
+ Products.enegyDrink => 'エナジードリンクセット',
+ Products.meat => '美味しい牛肉',
+ Products.eel => 'うな重'
+ };
}
diff --git a/app/lib/feature/donation/ui/donation_executed_screen.dart b/app/lib/feature/donation/ui/donation_executed_screen.dart
index 94dfff308..8e1a60dec 100644
--- a/app/lib/feature/donation/ui/donation_executed_screen.dart
+++ b/app/lib/feature/donation/ui/donation_executed_screen.dart
@@ -163,8 +163,16 @@ class _ScrollView extends StatelessWidget {
),
),
TextSpan(
- text: 'あなたの支援のお陰で、より良いアプリを作ることができます。\n\n'
- 'Twitter(X)やメールで私へ連絡いただけると嬉しいです!'
+ text: 'あなたの支援のお陰で、より良いアプリを作ることができます。\n\n',
+ ),
+ TextSpan(
+ text: '皆様の声が励みになります!\n',
+ style: TextStyle(
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ TextSpan(
+ text: 'Twitter(X)やメールで私へ連絡いただけると嬉しいです!'
'もしくは、アプリストアへのレビューもお待ちしております\n\n'
'ご意見やご要望があれば、お気軽にお知らせください!\n\n'
'- Ryotaro Onoue',
@@ -190,23 +198,25 @@ class _Detail extends StatelessWidget {
required this.product,
required this.textTheme,
required this.customer,
+ this.isScreenshot = false,
});
final Products productEnum;
final StoreProduct product;
final TextTheme textTheme;
final CustomerInfo customer;
+ final bool isScreenshot;
@override
Widget build(BuildContext context) {
return Column(
children: [
- const Padding(
- padding: EdgeInsets.all(8),
+ Padding(
+ padding: const EdgeInsets.all(8),
child: Center(
child: Text(
- 'ありがとうございます! 💖',
- style: TextStyle(
+ isScreenshot ? 'EQMontorを支援しました✌' : 'ありがとうございます! 💖',
+ style: const TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.w900,
diff --git a/app/lib/feature/donation/ui/donation_screen.dart b/app/lib/feature/donation/ui/donation_screen.dart
index be921fa62..6896d50ae 100644
--- a/app/lib/feature/donation/ui/donation_screen.dart
+++ b/app/lib/feature/donation/ui/donation_screen.dart
@@ -182,8 +182,9 @@ class _ShowDonationButton extends HookConsumerWidget {
showDialog(
context: context,
barrierDismissible: false,
- builder: (context) =>
- const CircularProgressIndicator.adaptive(),
+ builder: (context) => const Center(
+ child: CircularProgressIndicator.adaptive(),
+ ),
),
);
try {
diff --git a/app/lib/feature/earthquake_history/data/model/earthquake_history_parameter.freezed.dart b/app/lib/feature/earthquake_history/data/model/earthquake_history_parameter.freezed.dart
index bf68a6050..443808ac5 100644
--- a/app/lib/feature/earthquake_history/data/model/earthquake_history_parameter.freezed.dart
+++ b/app/lib/feature/earthquake_history/data/model/earthquake_history_parameter.freezed.dart
@@ -12,7 +12,7 @@ part of 'earthquake_history_parameter.dart';
T _$identity(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
- 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
+ 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
/// @nodoc
mixin _$EarthquakeHistoryParameter {
diff --git a/app/lib/feature/home/features/map/view/main_map_view.dart b/app/lib/feature/home/features/map/view/main_map_view.dart
index e1c9d19ef..9407419a7 100644
--- a/app/lib/feature/home/features/map/view/main_map_view.dart
+++ b/app/lib/feature/home/features/map/view/main_map_view.dart
@@ -46,7 +46,6 @@ class MainMapView extends HookConsumerWidget {
final controller = useAnimationController(
duration: const Duration(microseconds: 1000),
);
- useAnimation(controller);
useEffect(
() {
controller
@@ -95,7 +94,7 @@ class MainMapView extends HookConsumerWidget {
child: MaplibreMap(
initialCameraPosition: const CameraPosition(
target: LatLng(35.681236, 139.767125),
- zoom: 3,
+ zoom: 5,
),
styleString: stylePath.value ?? '',
onMapCreated: (controller) {
diff --git a/app/lib/feature/home/features/map/viewmodel/main_map_viewmodel.freezed.dart b/app/lib/feature/home/features/map/viewmodel/main_map_viewmodel.freezed.dart
index ee0dd7fe3..4070d9f61 100644
--- a/app/lib/feature/home/features/map/viewmodel/main_map_viewmodel.freezed.dart
+++ b/app/lib/feature/home/features/map/viewmodel/main_map_viewmodel.freezed.dart
@@ -12,7 +12,7 @@ part of 'main_map_viewmodel.dart';
T _$identity(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
- 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
+ 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
_EewHypocenterProperties _$EewHypocenterPropertiesFromJson(
Map json) {
diff --git a/app/lib/feature/home/view/home_view.dart b/app/lib/feature/home/view/home_view.dart
index 5228686e9..16c3df347 100644
--- a/app/lib/feature/home/view/home_view.dart
+++ b/app/lib/feature/home/view/home_view.dart
@@ -3,6 +3,7 @@ import 'dart:developer';
import 'package:collection/collection.dart';
import 'package:eqapi_types/eqapi_types.dart';
+import 'package:eqapi_types/model/components/eew_intensity.dart';
import 'package:eqmonitor/core/component/container/bordered_container.dart';
import 'package:eqmonitor/core/component/intenisty/intensity_icon_type.dart';
import 'package:eqmonitor/core/component/intenisty/jma_forecast_intensity_icon.dart';
@@ -217,16 +218,29 @@ class _IntensityIcons extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final aliveEews = ref.watch(eewAliveNormalTelegramProvider);
- final maxEstimatedIntensities =
- aliveEews.map((e) => e.forecastMaxIntensity).whereNotNull().toList();
+ final maxEstimatedIntensities = aliveEews
+ .map(
+ (e) => e.regions
+ ?.map(
+ (region) => region.forecastMaxInt.toDisplayMaxInt().maxInt,
+ )
+ .toList(),
+ )
+ .whereNotNull()
+ .flattened
+ .whereNotNull()
+ .toList();
final maxIntensity = maxEstimatedIntensities.isNotEmpty
? maxEstimatedIntensities.reduce((a, b) => a > b ? a : b)
: null;
- final intensities = maxIntensity != null
+ final minIntensity = maxEstimatedIntensities.isNotEmpty
+ ? maxEstimatedIntensities.reduce((a, b) => a < b ? a : b)
+ : null;
+ final intensities = maxIntensity != null && minIntensity != null
? [
...JmaForecastIntensity.values,
].where(
- (e) => e <= maxIntensity && e >= JmaForecastIntensity.four,
+ (e) => e <= maxIntensity && e >= minIntensity,
)
: null;
if (intensities == null || intensities.isEmpty) {
@@ -246,12 +260,8 @@ class _IntensityIcons extends ConsumerWidget {
spacing: 8,
runSpacing: 8,
children: [
- if (maxIntensity != null)
- for (final intensity in [
- ...JmaForecastIntensity.values,
- ].where(
- (e) => e <= maxIntensity && e >= JmaForecastIntensity.four,
- ))
+ if (maxIntensity != null && minIntensity != null)
+ for (final intensity in intensities)
JmaForecastIntensityWidget(
intensity: intensity,
size: 25,
diff --git a/app/lib/feature/settings/children/application_info/about_this_app.dart b/app/lib/feature/settings/children/application_info/about_this_app.dart
new file mode 100644
index 000000000..82280e2bf
--- /dev/null
+++ b/app/lib/feature/settings/children/application_info/about_this_app.dart
@@ -0,0 +1,65 @@
+import 'package:eqmonitor/core/component/container/bordered_container.dart';
+import 'package:eqmonitor/core/router/router.dart';
+import 'package:eqmonitor/gen/assets.gen.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_hooks/flutter_hooks.dart';
+import 'package:flutter_markdown/flutter_markdown.dart';
+import 'package:url_launcher/url_launcher.dart';
+
+class AboutThisAppScreen extends HookWidget {
+ const AboutThisAppScreen({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ final markdownFuture =
+ useMemoized(() => rootBundle.loadString(Assets.docs.aboutThisApp));
+ final markdown = useFuture(markdownFuture);
+ return Scaffold(
+ appBar: AppBar(
+ title: const Text('このアプリについて'),
+ ),
+ body: SingleChildScrollView(
+ child: SafeArea(
+ child: Column(
+ children: [
+ ListTile(
+ title: const Text('利用規約'),
+ leading: const Icon(Icons.description),
+ onTap: () =>
+ const TermOfServiceRoute($extra: null).push(context),
+ ),
+ ListTile(
+ title: const Text('プライバシーポリシー'),
+ leading: const Icon(Icons.info),
+ onTap: () =>
+ const PrivacyPolicyRoute($extra: null).push(context),
+ ),
+ ListTile(
+ title: const Text('ライセンス情報'),
+ subtitle:
+ Text('MIT License ${DateTime.now().year} Ryotaro Onoue'),
+ leading: const Icon(Icons.settings),
+ onTap: () => const LicenseRoute().push(context),
+ ),
+ const Divider(),
+ BorderedContainer(
+ elevation: 1,
+ child: MarkdownBody(
+ softLineBreak: true,
+ data: markdown.data ?? '',
+ onTapLink: (text, href, title) async {
+ final uri = Uri.tryParse(href ?? '');
+ if (uri != null && await canLaunchUrl(uri)) {
+ await launchUrl(uri);
+ }
+ },
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/app/lib/feature/settings/children/config/notification/notification_setting_page.dart b/app/lib/feature/settings/children/config/notification/notification_setting_page.dart
index 031ec2a9a..a3db62316 100644
--- a/app/lib/feature/settings/children/config/notification/notification_setting_page.dart
+++ b/app/lib/feature/settings/children/config/notification/notification_setting_page.dart
@@ -3,6 +3,7 @@ import 'package:eqmonitor/core/component/container/bordered_container.dart';
import 'package:eqmonitor/core/foundation/result.dart';
import 'package:eqmonitor/core/provider/config/notification/fcm_topic_manager.dart';
import 'package:eqmonitor/core/provider/config/permission/permission_status_provider.dart';
+import 'package:eqmonitor/core/provider/debugger/debugger_provider.dart';
import 'package:eqmonitor/core/provider/notification_token.dart';
import 'package:eqmonitor/core/router/router.dart';
import 'package:eqmonitor/core/util/fullscreen_loading_overlay.dart';
@@ -189,58 +190,63 @@ class _OnNotificationPermissionAllowed extends ConsumerWidget {
title: const Text('お知らせ'),
subtitle: const Text('アップデート情報や開発者からのお知らせをお伝えします'),
),
- const SettingsSectionHeader(text: 'FCM DEBUG'),
- Consumer(
- builder: (context, ref, _) {
- final notificationTokenState = ref.watch(notificationTokenProvider);
- return notificationTokenState.when(
- data: (value) => Column(
- children: [
- ListTile(
- title: const Text('FCM デバイストークン'),
- trailing: Text(
- value.fcmToken?.obfuscate ?? '不明',
- ),
- onTap: () => Clipboard.setData(
- ClipboardData(text: value.fcmToken ?? ''),
- ).then((_) {
- ScaffoldMessenger.of(context).showSnackBar(
- const SnackBar(
- content: Text('コピーしました'),
- ),
- );
- }),
- visualDensity: VisualDensity.compact,
- ),
- ListTile(
- title: const Text(
- 'APNS デバイストークン',
+ if (ref.watch(debuggerProvider.select(
+ (value) => value.isDebugger,
+ ))) ...[
+ const SettingsSectionHeader(text: 'FCM DEBUG'),
+ Consumer(
+ builder: (context, ref, _) {
+ final notificationTokenState =
+ ref.watch(notificationTokenProvider);
+ return notificationTokenState.when(
+ data: (value) => Column(
+ children: [
+ ListTile(
+ title: const Text('FCM デバイストークン'),
+ trailing: Text(
+ value.fcmToken?.obfuscate ?? '不明',
+ ),
+ onTap: () => Clipboard.setData(
+ ClipboardData(text: value.fcmToken ?? ''),
+ ).then((_) {
+ ScaffoldMessenger.of(context).showSnackBar(
+ const SnackBar(
+ content: Text('コピーしました'),
+ ),
+ );
+ }),
+ visualDensity: VisualDensity.compact,
),
- trailing: Text(
- value.apnsToken?.obfuscate ?? '不明',
+ ListTile(
+ title: const Text(
+ 'APNS デバイストークン',
+ ),
+ trailing: Text(
+ value.apnsToken?.obfuscate ?? '不明',
+ ),
+ onTap: () => Clipboard.setData(
+ ClipboardData(text: value.apnsToken ?? ''),
+ ).then((_) {
+ ScaffoldMessenger.of(context).showSnackBar(
+ const SnackBar(
+ content: Text('コピーしました'),
+ ),
+ );
+ }),
+ visualDensity: VisualDensity.compact,
),
- onTap: () => Clipboard.setData(
- ClipboardData(text: value.apnsToken ?? ''),
- ).then((_) {
- ScaffoldMessenger.of(context).showSnackBar(
- const SnackBar(
- content: Text('コピーしました'),
- ),
- );
- }),
- visualDensity: VisualDensity.compact,
- ),
- ],
- ),
- error: (error, stackTrace) => Text(
- 'エラーが発生しました: $error',
- ),
- loading: () => const Center(
- child: CircularProgressIndicator.adaptive(),
- ),
- );
- },
- ),
+ ],
+ ),
+ error: (error, stackTrace) => Text(
+ 'エラーが発生しました: $error',
+ ),
+ loading: () => const Center(
+ child: CircularProgressIndicator.adaptive(),
+ ),
+ );
+ },
+ ),
+ ],
],
);
}
diff --git a/app/lib/feature/settings/children/config/notification/notifiication_settings_view_model.freezed.dart b/app/lib/feature/settings/children/config/notification/notifiication_settings_view_model.freezed.dart
index 9d53a838e..5a8aa17ad 100644
--- a/app/lib/feature/settings/children/config/notification/notifiication_settings_view_model.freezed.dart
+++ b/app/lib/feature/settings/children/config/notification/notifiication_settings_view_model.freezed.dart
@@ -12,7 +12,7 @@ part of 'notifiication_settings_view_model.dart';
T _$identity(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
- 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
+ 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
NotificationSettingsState _$NotificationSettingsStateFromJson(
Map json) {
diff --git a/app/lib/feature/settings/settings_screen.dart b/app/lib/feature/settings/settings_screen.dart
index dc724f7b7..b8f826c46 100644
--- a/app/lib/feature/settings/settings_screen.dart
+++ b/app/lib/feature/settings/settings_screen.dart
@@ -111,26 +111,11 @@ class SettingsScreen extends HookConsumerWidget {
onTap: () => _onInquiryTap(context, ref),
),
ListTile(
- title: const Text('利用規約'),
+ title: const Text('このアプリケーションについて'),
+ subtitle: const Text('利用規約やプライバシーポリシーを確認できます'),
leading: const Icon(Icons.description),
- onTap: () => context.push(
- const TermOfServiceRoute($extra: null).location,
- ),
- ),
- ListTile(
- title: const Text('プライバシーポリシー'),
- leading: const Icon(Icons.info),
- onTap: () => context.push(
- const PrivacyPolicyRoute($extra: null).location,
- ),
- ),
- ListTile(
- title: const Text('ライセンス情報'),
- subtitle: Text('MIT License ${DateTime.now().year} Ryotaro Onoue'),
- leading: const Icon(Icons.settings),
- onTap: () => context.push(
- const LicenseRoute().location,
- ),
+
+ onTap: () => const AboutThisAppRoute().push(context),
),
ListTile(
title: const Text('サーバの稼働状況'),
@@ -141,14 +126,6 @@ class SettingsScreen extends HookConsumerWidget {
mode: LaunchMode.externalApplication,
),
),
- ListTile(
- title: const Text('ロードマップ'),
- subtitle: const Text('アプリの開発ロードマップを確認できます'),
- leading: const Icon(Icons.view_timeline),
- onTap: () => launchUrlString(
- 'https://github.com/YumNumm/EQMonitor/issues/412',
- ),
- ),
Center(
child: Padding(
padding: const EdgeInsets.only(bottom: 16),
diff --git a/app/lib/main.dart b/app/lib/main.dart
index 616d0d4a8..7b2379710 100644
--- a/app/lib/main.dart
+++ b/app/lib/main.dart
@@ -13,6 +13,7 @@ import 'package:eqmonitor/core/provider/kmoni_observation_points/provider/kyoshi
import 'package:eqmonitor/core/provider/log/talker.dart';
import 'package:eqmonitor/core/provider/package_info.dart';
import 'package:eqmonitor/core/provider/shared_preferences.dart';
+import 'package:eqmonitor/core/util/license/init_licenses.dart';
import 'package:eqmonitor/feature/donation/data/donation_notifier.dart';
import 'package:eqmonitor/firebase_options.dart';
import 'package:firebase_core/firebase_core.dart';
@@ -107,7 +108,10 @@ Future main() async {
),
).wait;
- await initInAppPurchase();
+ await (
+ initInAppPurchase(),
+ initLicenses(),
+ ).wait;
FirebaseMessaging.onBackgroundMessage(onBackgroundMessage);
if (!kIsWeb) {