ログインをメアドに変更
This commit is contained in:
@ -3,7 +3,7 @@
|
|||||||
archiveVersion = 1;
|
archiveVersion = 1;
|
||||||
classes = {
|
classes = {
|
||||||
};
|
};
|
||||||
objectVersion = 60;
|
objectVersion = 54;
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import 'package:rogapp/pages/index/index_controller.dart';
|
|||||||
import 'package:rogapp/routes/app_pages.dart';
|
import 'package:rogapp/routes/app_pages.dart';
|
||||||
import 'package:rogapp/utils/location_controller.dart';
|
import 'package:rogapp/utils/location_controller.dart';
|
||||||
import 'package:rogapp/utils/string_values.dart';
|
import 'package:rogapp/utils/string_values.dart';
|
||||||
|
import 'package:rogapp/widgets/debug_widget.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
// import 'package:is_lock_screen/is_lock_screen.dart';
|
// import 'package:is_lock_screen/is_lock_screen.dart';
|
||||||
|
|
||||||
@ -127,7 +128,7 @@ void main() async {
|
|||||||
FlutterError.presentError(details);
|
FlutterError.presentError(details);
|
||||||
Get.log('Flutter error: ${details.exception}');
|
Get.log('Flutter error: ${details.exception}');
|
||||||
Get.log('Stack trace: ${details.stack}');
|
Get.log('Stack trace: ${details.stack}');
|
||||||
ErrorService.reportError(details.exception, details.stack ?? StackTrace.current, deviceInfo);
|
ErrorService.reportError(details.exception, details.stack ?? StackTrace.current, deviceInfo, LogManager().operationLogs);
|
||||||
};
|
};
|
||||||
|
|
||||||
//Get.put(LocationController());
|
//Get.put(LocationController());
|
||||||
@ -153,7 +154,7 @@ void main() async {
|
|||||||
//runApp(const MyApp());
|
//runApp(const MyApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Future<void> requestLocationPermission() async {
|
Future<void> requestLocationPermission() async {
|
||||||
try {
|
try {
|
||||||
final status = await Permission.locationAlways.request();
|
final status = await Permission.locationAlways.request();
|
||||||
@ -167,7 +168,7 @@ Future<void> requestLocationPermission() async {
|
|||||||
print('Error requesting location permission: $e');
|
print('Error requesting location permission: $e');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// メモリ使用量の解説:https://qiita.com/hukusuke1007/items/e4e987836412e9bc73b9
|
// メモリ使用量の解説:https://qiita.com/hukusuke1007/items/e4e987836412e9bc73b9
|
||||||
@ -366,6 +367,11 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
|
|||||||
}
|
}
|
||||||
WidgetsBinding.instance.addObserver(this);
|
WidgetsBinding.instance.addObserver(this);
|
||||||
|
|
||||||
|
// Add to clear
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
showLocationDisclosure(context);
|
||||||
|
});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||||
await PermissionController.checkAndRequestPermissions();
|
await PermissionController.checkAndRequestPermissions();
|
||||||
@ -375,6 +381,45 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
|
|||||||
debugPrint("Start MyAppState...");
|
debugPrint("Start MyAppState...");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void showLocationDisclosure(BuildContext context) {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: false,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: Text('位置情報の使用について'),
|
||||||
|
content: const SingleChildScrollView(
|
||||||
|
child: ListBody(
|
||||||
|
children: <Widget>[
|
||||||
|
Text('このアプリでは、以下の目的で位置情報を使用します:'),
|
||||||
|
Text('• チェックポイントの自動チェックイン(アプリが閉じているときも含む)'),
|
||||||
|
Text('• 移動履歴の記録(バックグラウンドでも継続)'),
|
||||||
|
Text('• 現在地周辺の情報表示'),
|
||||||
|
Text('\nバックグラウンドでも位置情報を継続的に取得します。'),
|
||||||
|
Text('これにより、バッテリーの消費が増加する可能性があります。'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actions: <Widget>[
|
||||||
|
TextButton(
|
||||||
|
child: const Text('同意しない'),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
// アプリを終了するなどの処理
|
||||||
|
},
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
child: const Text('同意する'),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
requestLocationPermission();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
|||||||
@ -1,10 +1,13 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:rogapp/pages/index/index_controller.dart';
|
import 'package:rogapp/pages/index/index_controller.dart';
|
||||||
|
import 'package:rogapp/widgets/debug_widget.dart';
|
||||||
|
|
||||||
class ChangePasswordPage extends StatelessWidget {
|
class ChangePasswordPage extends StatelessWidget {
|
||||||
ChangePasswordPage({Key? key}) : super(key: key);
|
ChangePasswordPage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
LogManager logManager = LogManager();
|
||||||
|
|
||||||
IndexController indexController = Get.find<IndexController>();
|
IndexController indexController = Get.find<IndexController>();
|
||||||
|
|
||||||
TextEditingController oldPasswordController = TextEditingController();
|
TextEditingController oldPasswordController = TextEditingController();
|
||||||
@ -20,6 +23,7 @@ class ChangePasswordPage extends StatelessWidget {
|
|||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
logManager.addOperationLog('User clicked cancel button on the drawer');
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
@ -89,6 +93,7 @@ class ChangePasswordPage extends StatelessWidget {
|
|||||||
.text.isEmpty ||
|
.text.isEmpty ||
|
||||||
newPasswordController
|
newPasswordController
|
||||||
.text.isEmpty) {
|
.text.isEmpty) {
|
||||||
|
logManager.addOperationLog('User tried to login with blank old password ${oldPasswordController.text} or new password ${newPasswordController.text}.');
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"no_values".tr,
|
"no_values".tr,
|
||||||
"values_required".tr,
|
"values_required".tr,
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import 'package:rogapp/pages/index/index_controller.dart';
|
|||||||
import 'package:rogapp/routes/app_pages.dart';
|
import 'package:rogapp/routes/app_pages.dart';
|
||||||
import 'package:rogapp/services/auth_service.dart';
|
import 'package:rogapp/services/auth_service.dart';
|
||||||
import 'package:rogapp/utils/database_helper.dart';
|
import 'package:rogapp/utils/database_helper.dart';
|
||||||
|
import 'package:rogapp/widgets/debug_widget.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
import 'package:rogapp/pages/WebView/WebView_page.dart';
|
import 'package:rogapp/pages/WebView/WebView_page.dart';
|
||||||
|
|
||||||
@ -16,6 +17,8 @@ class DrawerPage extends StatelessWidget {
|
|||||||
|
|
||||||
final IndexController indexController = Get.find<IndexController>();
|
final IndexController indexController = Get.find<IndexController>();
|
||||||
|
|
||||||
|
LogManager logManager = LogManager();
|
||||||
|
|
||||||
// 要検討:URLの起動に失敗した場合のエラーハンドリングが不十分です。適切なエラーメッセージを表示するなどの処理を追加してください。
|
// 要検討:URLの起動に失敗した場合のエラーハンドリングが不十分です。適切なエラーメッセージを表示するなどの処理を追加してください。
|
||||||
//
|
//
|
||||||
/*
|
/*
|
||||||
@ -26,6 +29,7 @@ class DrawerPage extends StatelessWidget {
|
|||||||
|
|
||||||
void _launchURL(BuildContext context,String urlString) async {
|
void _launchURL(BuildContext context,String urlString) async {
|
||||||
try {
|
try {
|
||||||
|
logManager.addOperationLog('User clicked ${urlString} on the drawer');
|
||||||
Uri url = Uri.parse(urlString);
|
Uri url = Uri.parse(urlString);
|
||||||
if (await canLaunchUrl(url)) {
|
if (await canLaunchUrl(url)) {
|
||||||
await launchUrl(url);
|
await launchUrl(url);
|
||||||
@ -52,14 +56,8 @@ class DrawerPage extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SafeArea(
|
return SafeArea(
|
||||||
child: Drawer(
|
child: Drawer(
|
||||||
// Add a ListView to the drawer. This ensures the user can scroll
|
|
||||||
// through the options in the drawer if there isn't enough vertical
|
|
||||||
// space to fit everything.
|
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
// 最初のアイテムは、ユーザーのログイン状態に応じて表示が変わります。
|
|
||||||
// ユーザーがログインしていない場合は、"drawer_title".trというテキストを表示します。
|
|
||||||
// ユーザーがログインしている場合は、ユーザーのメールアドレスを表示します。
|
|
||||||
Container(
|
Container(
|
||||||
height: 100,
|
height: 100,
|
||||||
color: Colors.amber,
|
color: Colors.amber,
|
||||||
@ -81,9 +79,6 @@ class DrawerPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
),
|
),
|
||||||
// 次に、IndexControllerのcurrentUserリストが空かどうかに応じて、ログインまたはログアウトのアイテムを表示します。
|
|
||||||
// currentUserリストが空の場合は、"login".trというテキストのログインアイテムを表示し、タップするとAppPages.LOGINにナビゲートします。
|
|
||||||
// currentUserリストが空でない場合は、"logout".trというテキストのログアウトアイテムを表示し、タップするとindexController.logout()を呼び出してログアウトし、AppPages.LOGINにナビゲートします。
|
|
||||||
Obx(() => indexController.currentUser.isEmpty
|
Obx(() => indexController.currentUser.isEmpty
|
||||||
? ListTile(
|
? ListTile(
|
||||||
leading: const Icon(Icons.login),
|
leading: const Icon(Icons.login),
|
||||||
@ -100,8 +95,6 @@ class DrawerPage extends StatelessWidget {
|
|||||||
Get.toNamed(AppPages.LOGIN);
|
Get.toNamed(AppPages.LOGIN);
|
||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
// パスワード変更のアイテムは、ユーザーがログインしている場合にのみ表示されます。
|
|
||||||
// "change_password".trというテキストを表示し、タップするとAppPages.CHANGE_PASSWORDにナビゲートします。
|
|
||||||
indexController.currentUser.isNotEmpty
|
indexController.currentUser.isNotEmpty
|
||||||
? ListTile(
|
? ListTile(
|
||||||
leading: const Icon(Icons.password),
|
leading: const Icon(Icons.password),
|
||||||
@ -114,8 +107,6 @@ class DrawerPage extends StatelessWidget {
|
|||||||
width: 0,
|
width: 0,
|
||||||
height: 0,
|
height: 0,
|
||||||
),
|
),
|
||||||
// サインアップのアイテムは、ユーザーがログインしていない場合にのみ表示されます。
|
|
||||||
// "sign_up".trというテキストを表示し、タップするとAppPages.REGISTERにナビゲートします。
|
|
||||||
indexController.currentUser.isEmpty
|
indexController.currentUser.isEmpty
|
||||||
? ListTile(
|
? ListTile(
|
||||||
leading: const Icon(Icons.person),
|
leading: const Icon(Icons.person),
|
||||||
@ -128,20 +119,19 @@ class DrawerPage extends StatelessWidget {
|
|||||||
width: 0,
|
width: 0,
|
||||||
height: 0,
|
height: 0,
|
||||||
),
|
),
|
||||||
// リセットのアイテムは、ユーザーがログインしている場合にのみ表示されます。
|
|
||||||
// タップすると、確認ダイアログを表示し、ユーザーがリセットを確認するとDestinationControllerのresetRogaining()メソッドを呼び出してゲームデータをリセットします。
|
|
||||||
indexController.currentUser.isNotEmpty
|
indexController.currentUser.isNotEmpty
|
||||||
? ListTile(
|
? ListTile(
|
||||||
leading: const Icon(Icons.password),
|
leading: const Icon(Icons.password),
|
||||||
title: const Text("リセット"),
|
title: Text('reset_button'.tr),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
logManager.addOperationLog('User clicked RESET button on the drawer');
|
||||||
// 要検討:リセット操作の確認メッセージをローカライズすることを検討してください。
|
// 要検討:リセット操作の確認メッセージをローカライズすることを検討してください。
|
||||||
//
|
//
|
||||||
Get.defaultDialog(
|
Get.defaultDialog(
|
||||||
title: "リセットしますがよろしいですか?",
|
title: "reset_title".tr,
|
||||||
middleText: "これにより、すべてのゲーム データが削除され、すべての状態が削除されます",
|
middleText: "reset_message".tr,
|
||||||
textConfirm: "確認する",
|
textConfirm: "confirm".tr,
|
||||||
textCancel: "キャンセルする",
|
textCancel: "cancel".tr,
|
||||||
onCancel: () => Get.back(),
|
onCancel: () => Get.back(),
|
||||||
onConfirm: () async {
|
onConfirm: () async {
|
||||||
DestinationController destinationController =
|
DestinationController destinationController =
|
||||||
@ -157,8 +147,8 @@ class DrawerPage extends StatelessWidget {
|
|||||||
//destinationController.deleteDBDestinations();
|
//destinationController.deleteDBDestinations();
|
||||||
Get.back();
|
Get.back();
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"リセット完了",
|
"reset_done".tr,
|
||||||
"すべてリセットされました。ロゲ開始から再開して下さい。",
|
"reset_explain".tr,
|
||||||
backgroundColor: Colors.green,
|
backgroundColor: Colors.green,
|
||||||
colorText: Colors.white,
|
colorText: Colors.white,
|
||||||
duration: const Duration(seconds: 3),
|
duration: const Duration(seconds: 3),
|
||||||
@ -171,20 +161,19 @@ class DrawerPage extends StatelessWidget {
|
|||||||
width: 0,
|
width: 0,
|
||||||
height: 0,
|
height: 0,
|
||||||
),
|
),
|
||||||
// アカウント削除のアイテムは、ユーザーがログインしている場合にのみ表示されます。
|
|
||||||
// "delete_account".trというテキストを表示し、タップするとAuthService.deleteUser()を呼び出してアカウントを削除し、AppPages.TRAVELにナビゲートします。
|
|
||||||
indexController.currentUser.isNotEmpty
|
indexController.currentUser.isNotEmpty
|
||||||
? ListTile(
|
? ListTile(
|
||||||
leading: const Icon(Icons.delete_forever),
|
leading: const Icon(Icons.delete_forever),
|
||||||
title: Text("delete_account".tr),
|
title: Text("delete_account".tr),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Get.defaultDialog(
|
Get.defaultDialog(
|
||||||
title: "アカウントを削除しますがよろしいですか?",
|
title: "delete_account_title".tr,
|
||||||
middleText: "これにより、アカウント情報とすべてのゲーム データが削除され、すべての状態が削除されます",
|
middleText: "delete_account_middle".tr,
|
||||||
textConfirm: "確認する",
|
textConfirm: "confirm".tr,
|
||||||
textCancel: "キャンセルする",
|
textCancel: "cancel".tr,
|
||||||
onCancel: () => Get.back(),
|
onCancel: () => Get.back(),
|
||||||
onConfirm: () {
|
onConfirm: () {
|
||||||
|
logManager.addOperationLog('User clicked Confirm button on the account delete dialog');
|
||||||
String token = indexController.currentUser[0]['token'];
|
String token = indexController.currentUser[0]['token'];
|
||||||
AuthService.deleteUser(token).then((value) {
|
AuthService.deleteUser(token).then((value) {
|
||||||
if (value.isNotEmpty) {
|
if (value.isNotEmpty) {
|
||||||
@ -205,53 +194,6 @@ class DrawerPage extends StatelessWidget {
|
|||||||
width: 0,
|
width: 0,
|
||||||
height: 0,
|
height: 0,
|
||||||
),
|
),
|
||||||
/*
|
|
||||||
// ユーザーデータ削除のアイテムは、ユーザーがログインしている場合にのみ表示されます。
|
|
||||||
// タップすると、AuthService.deleteUser()を呼び出してユーザーデータを削除します。
|
|
||||||
indexController.currentUser.isNotEmpty
|
|
||||||
? ListTile(
|
|
||||||
// 要検討:アカウント削除のリクエストが失敗した場合のエラーハンドリングを追加することをお勧めします。
|
|
||||||
//
|
|
||||||
leading: const Icon(Icons.delete_forever),
|
|
||||||
title: Text("ユーザーデータを削除する".tr),
|
|
||||||
onTap: () {
|
|
||||||
Get.defaultDialog(
|
|
||||||
title: "アカウントを削除しますがよろしいですか?",
|
|
||||||
middleText: "これにより、アカウント情報とすべてのゲーム データが削除され、すべての状態が削除されます",
|
|
||||||
textConfirm: "確認する",
|
|
||||||
textCancel: "キャンセルする",
|
|
||||||
onCancel: () => Get.back(),
|
|
||||||
onConfirm: () {
|
|
||||||
String token = indexController.currentUser[0]['token'];
|
|
||||||
AuthService.deleteUser(token).then((value) {
|
|
||||||
Get.snackbar("ユーザーデータを削除する",
|
|
||||||
"データを削除するためにユーザーの同意が設定されています アプリとサーバーでユーザーデータが削除されました");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
)
|
|
||||||
: const SizedBox(
|
|
||||||
width: 0,
|
|
||||||
height: 0,
|
|
||||||
),
|
|
||||||
// ListTile(
|
|
||||||
// leading: const Icon(Icons.person),
|
|
||||||
// title: Text("profile".tr),
|
|
||||||
// onTap: (){},
|
|
||||||
// ),
|
|
||||||
// ListTile(
|
|
||||||
// leading: const Icon(Icons.route),
|
|
||||||
// title: Text("recommended_route".tr),
|
|
||||||
// onTap: (){},
|
|
||||||
// ),
|
|
||||||
// ListTile(
|
|
||||||
// leading: const Icon(Icons.favorite_rounded),
|
|
||||||
// title: Text("point_rank".tr),
|
|
||||||
// onTap: (){},
|
|
||||||
// ),
|
|
||||||
*/
|
|
||||||
// "rog_web".trというテキストのアイテムは、ユーザーがログインしている場合にのみ表示されます。
|
|
||||||
// タップすると、_launchURL()メソッドを呼び出して外部のウェブサイトを開きます。
|
|
||||||
indexController.currentUser.isNotEmpty
|
indexController.currentUser.isNotEmpty
|
||||||
? ListTile(
|
? ListTile(
|
||||||
leading: const Icon(Icons.featured_video),
|
leading: const Icon(Icons.featured_video),
|
||||||
@ -264,8 +206,6 @@ class DrawerPage extends StatelessWidget {
|
|||||||
width: 0,
|
width: 0,
|
||||||
height: 0,
|
height: 0,
|
||||||
),
|
),
|
||||||
// "privacy".trというテキストのアイテムは、常に表示されます。
|
|
||||||
// タップすると、_launchURL()メソッドを呼び出してプライバシーポリシーのURLを開きます。
|
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.privacy_tip),
|
leading: const Icon(Icons.privacy_tip),
|
||||||
title: Text("privacy".tr),
|
title: Text("privacy".tr),
|
||||||
@ -275,7 +215,7 @@ class DrawerPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.settings),
|
leading: const Icon(Icons.settings),
|
||||||
title: const Text('設定'),
|
title: Text('open_settings'.tr),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Get.back(); // ドロワーを閉じる
|
Get.back(); // ドロワーを閉じる
|
||||||
Get.toNamed(Routes.SETTINGS);
|
Get.toNamed(Routes.SETTINGS);
|
||||||
@ -284,7 +224,7 @@ class DrawerPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.developer_mode),
|
leading: const Icon(Icons.developer_mode),
|
||||||
title: const Text('開発者メニュー'),
|
title: const Text('open_settings'),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Get.back(); // ドロワーを閉じる
|
Get.back(); // ドロワーを閉じる
|
||||||
Get.toNamed('/debug'); // デバッグ画面に遷移
|
Get.toNamed('/debug'); // デバッグ画面に遷移
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import 'package:rogapp/routes/app_pages.dart';
|
|||||||
import 'package:rogapp/services/auth_service.dart';
|
import 'package:rogapp/services/auth_service.dart';
|
||||||
import 'package:rogapp/services/location_service.dart';
|
import 'package:rogapp/services/location_service.dart';
|
||||||
import 'package:rogapp/utils/database_helper.dart';
|
import 'package:rogapp/utils/database_helper.dart';
|
||||||
|
import 'package:rogapp/widgets/debug_widget.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
import '../../main.dart';
|
import '../../main.dart';
|
||||||
@ -52,6 +53,8 @@ class IndexController extends GetxController with WidgetsBindingObserver {
|
|||||||
MapController mapController = MapController();
|
MapController mapController = MapController();
|
||||||
MapController rogMapController = MapController();
|
MapController rogMapController = MapController();
|
||||||
|
|
||||||
|
LogManager logManager = LogManager();
|
||||||
|
|
||||||
String? userToken;
|
String? userToken;
|
||||||
|
|
||||||
// mode = 0 is map mode, mode = 1 list mode
|
// mode = 0 is map mode, mode = 1 list mode
|
||||||
@ -155,14 +158,15 @@ class IndexController extends GetxController with WidgetsBindingObserver {
|
|||||||
return WillPopScope(
|
return WillPopScope(
|
||||||
onWillPop: () async => false,
|
onWillPop: () async => false,
|
||||||
child: AlertDialog(
|
child: AlertDialog(
|
||||||
title: Text('位置情報の許可が必要です'),
|
title: Text('location_permission_needed_title'.tr),
|
||||||
content: Text('設定>プライバシーとセキュリティ>位置情報サービス を開いて、岐阜ナビを探し、「位置情報の許可」を「常に」にして下さい。'),
|
content: Text('location_permission_needed_main'.tr),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
logManager.addOperationLog("User tapped confirm button for location permission required.");
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
child: Text('OK'),
|
child: Text('confirm'.tr),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -230,6 +234,7 @@ class IndexController extends GetxController with WidgetsBindingObserver {
|
|||||||
void _startLocationService() async {
|
void _startLocationService() async {
|
||||||
const platform = MethodChannel('location');
|
const platform = MethodChannel('location');
|
||||||
try {
|
try {
|
||||||
|
logManager.addOperationLog("Called start location service.");
|
||||||
await platform.invokeMethod('startLocationService');
|
await platform.invokeMethod('startLocationService');
|
||||||
} on PlatformException catch (e) {
|
} on PlatformException catch (e) {
|
||||||
print("Failed to start location service: '${e.message}'.");
|
print("Failed to start location service: '${e.message}'.");
|
||||||
@ -239,6 +244,7 @@ class IndexController extends GetxController with WidgetsBindingObserver {
|
|||||||
void _stopLocationService() async {
|
void _stopLocationService() async {
|
||||||
const platform = MethodChannel('location');
|
const platform = MethodChannel('location');
|
||||||
try {
|
try {
|
||||||
|
logManager.addOperationLog("Called stop location service.");
|
||||||
await platform.invokeMethod('stopLocationService');
|
await platform.invokeMethod('stopLocationService');
|
||||||
} on PlatformException catch (e) {
|
} on PlatformException catch (e) {
|
||||||
print("Failed to stop location service: '${e.message}'.");
|
print("Failed to stop location service: '${e.message}'.");
|
||||||
@ -301,24 +307,29 @@ class IndexController extends GetxController with WidgetsBindingObserver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logManager.addOperationLog("Called boundsFromLatLngList (${x1!},${y1!})-(${x0!},${y0!}).");
|
||||||
|
|
||||||
return LatLngBounds(LatLng(x1!, y1!), LatLng(x0!, y0!));
|
return LatLngBounds(LatLng(x1!, y1!), LatLng(x0!, y0!));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 要検討:エラーハンドリングが行われていますが、エラーメッセージをローカライズすることを検討してください。
|
// 要検討:エラーハンドリングが行われていますが、エラーメッセージをローカライズすることを検討してください。
|
||||||
//
|
//
|
||||||
void login(String email, String password, BuildContext context) {
|
void login(String email, String password, BuildContext context) {
|
||||||
|
|
||||||
AuthService.login(email, password).then((value) {
|
AuthService.login(email, password).then((value) {
|
||||||
print("------- logged in user details ######## $value ###### --------");
|
print("------- logged in user details ######## $value ###### --------");
|
||||||
if (value.isNotEmpty) {
|
if (value.isNotEmpty) {
|
||||||
|
logManager.addOperationLog("User logged in : ${value}.");
|
||||||
|
|
||||||
// Navigator.pop(context);
|
// Navigator.pop(context);
|
||||||
print("--------- user details login ----- $value");
|
print("--------- user details login ----- $value");
|
||||||
//await Future.delayed(const Duration(milliseconds: 500)); // Added Akira:2024-4-6, #2800
|
|
||||||
changeUser(value);
|
changeUser(value);
|
||||||
} else {
|
} else {
|
||||||
|
logManager.addOperationLog("User failed login : ${email} , ${password}.");
|
||||||
isLoading.value = false;
|
isLoading.value = false;
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"ログイン失敗",
|
"login_failed".tr,
|
||||||
"ログインIDかパスワードを確認して下さい。",
|
"check_login_id_or_password".tr,
|
||||||
backgroundColor: Colors.red,
|
backgroundColor: Colors.red,
|
||||||
colorText: Colors.white,
|
colorText: Colors.white,
|
||||||
icon: const Icon(Icons.error, size: 40.0, color: Colors.blue),
|
icon: const Icon(Icons.error, size: 40.0, color: Colors.blue),
|
||||||
@ -340,6 +351,7 @@ class IndexController extends GetxController with WidgetsBindingObserver {
|
|||||||
AuthService.changePassword(oldpassword, newpassword, token).then((value) {
|
AuthService.changePassword(oldpassword, newpassword, token).then((value) {
|
||||||
////print("------- change password ######## $value ###### --------");
|
////print("------- change password ######## $value ###### --------");
|
||||||
if (value.isNotEmpty) {
|
if (value.isNotEmpty) {
|
||||||
|
logManager.addOperationLog("User successed to change password : ${oldpassword} , ${newpassword}.");
|
||||||
isLoading.value = false;
|
isLoading.value = false;
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
if (rogMode.value == 1) {
|
if (rogMode.value == 1) {
|
||||||
@ -348,6 +360,7 @@ class IndexController extends GetxController with WidgetsBindingObserver {
|
|||||||
switchPage(AppPages.INDEX);
|
switchPage(AppPages.INDEX);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
logManager.addOperationLog("User failed to change password : ${oldpassword} , ${newpassword}.");
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
'failed'.tr,
|
'failed'.tr,
|
||||||
'password_change_failed_please_try_again'.tr,
|
'password_change_failed_please_try_again'.tr,
|
||||||
@ -383,6 +396,7 @@ class IndexController extends GetxController with WidgetsBindingObserver {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
void logout() async {
|
void logout() async {
|
||||||
|
logManager.addOperationLog("User logout : ${currentUser} .");
|
||||||
saveGameState();
|
saveGameState();
|
||||||
locations.clear();
|
locations.clear();
|
||||||
DatabaseHelper db = DatabaseHelper.instance;
|
DatabaseHelper db = DatabaseHelper.instance;
|
||||||
@ -403,12 +417,15 @@ class IndexController extends GetxController with WidgetsBindingObserver {
|
|||||||
void register(String email, String password, BuildContext context) {
|
void register(String email, String password, BuildContext context) {
|
||||||
AuthService.register(email, password).then((value) {
|
AuthService.register(email, password).then((value) {
|
||||||
if (value.isNotEmpty) {
|
if (value.isNotEmpty) {
|
||||||
|
logManager.addOperationLog("User tried to register new account : ${email} , ${password} .");
|
||||||
|
|
||||||
currentUser.clear();
|
currentUser.clear();
|
||||||
currentUser.add(value);
|
currentUser.add(value);
|
||||||
isLoading.value = false;
|
isLoading.value = false;
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
Get.toNamed(AppPages.INDEX);
|
Get.toNamed(AppPages.INDEX);
|
||||||
} else {
|
} else {
|
||||||
|
logManager.addOperationLog("User failed to register new account : ${email} , ${password} .");
|
||||||
isLoading.value = false;
|
isLoading.value = false;
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
'failed'.tr,
|
'failed'.tr,
|
||||||
|
|||||||
@ -122,7 +122,7 @@ class LoginPage extends StatelessWidget {
|
|||||||
BorderRadius.circular(40)),
|
BorderRadius.circular(40)),
|
||||||
child: Text(
|
child: Text(
|
||||||
"login".tr,
|
"login".tr,
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
color: Colors.white70),
|
color: Colors.white70),
|
||||||
|
|||||||
@ -15,7 +15,7 @@ class RegisterPage extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
resizeToAvoidBottomInset: false,
|
resizeToAvoidBottomInset: true,
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import 'package:flutter/foundation.dart';
|
|||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
|
|
||||||
class ErrorService {
|
class ErrorService {
|
||||||
static Future<void> reportError(dynamic error, StackTrace stackTrace, Map<String, dynamic> deviceInfo) async {
|
static Future<void> reportError(dynamic error, StackTrace stackTrace, Map<String, dynamic> deviceInfo, List<String> operationLogs) async {
|
||||||
try {
|
try {
|
||||||
final String errorMessage = error.toString();
|
final String errorMessage = error.toString();
|
||||||
final String stackTraceString = stackTrace.toString();
|
final String stackTraceString = stackTrace.toString();
|
||||||
@ -19,16 +19,20 @@ class ErrorService {
|
|||||||
'stack_trace': stackTraceString,
|
'stack_trace': stackTraceString,
|
||||||
'estimated_cause': estimatedCause,
|
'estimated_cause': estimatedCause,
|
||||||
'device_info': deviceInfo,
|
'device_info': deviceInfo,
|
||||||
|
'operation_logs': operationLogs.join('\n'), // オペレーションログを改行で結合して送信
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
// エラー報告が成功した場合の処理(必要に応じて)
|
// エラー報告が成功した場合の処理(必要に応じて)
|
||||||
|
debugPrint("===== エラーログ送信成功しました。 ====");
|
||||||
} else {
|
} else {
|
||||||
// エラー報告が失敗した場合の処理(必要に応じて)
|
// エラー報告が失敗した場合の処理(必要に応じて)
|
||||||
|
debugPrint("===== エラーログ送信失敗しました。 ====");
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// エラー報告中にエラーが発生した場合の処理(必要に応じて)
|
// エラー報告中にエラーが発生した場合の処理(必要に応じて)
|
||||||
|
debugPrint("===== エラーログ送信中にエラーになりました。 ====");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,8 @@ class StringValues extends Translations{
|
|||||||
'drawer_title':'Rogaining participants can view checkpoints by logging in',
|
'drawer_title':'Rogaining participants can view checkpoints by logging in',
|
||||||
'app_title': '- Rogaining -',
|
'app_title': '- Rogaining -',
|
||||||
'address':'address',
|
'address':'address',
|
||||||
'email':'Email',
|
'bib':'Bib number',
|
||||||
|
'email':'Email address',
|
||||||
'password':'Password',
|
'password':'Password',
|
||||||
'web':'Web',
|
'web':'Web',
|
||||||
'wikipedia':'Wikipedia',
|
'wikipedia':'Wikipedia',
|
||||||
@ -70,6 +71,8 @@ class StringValues extends Translations{
|
|||||||
"Not reached the goal yet": "Not reached the goal yet",
|
"Not reached the goal yet": "Not reached the goal yet",
|
||||||
"You have not reached the goal yet.":"You have not reached the goal yet.",
|
"You have not reached the goal yet.":"You have not reached the goal yet.",
|
||||||
"delete_account": "Delete account",
|
"delete_account": "Delete account",
|
||||||
|
"delete_account_title": "Are you ok to delete your account?",
|
||||||
|
"delete_account_middle": "All your account information and data history will be removed from local device and server side.",
|
||||||
"accounted_deleted": "Account deleted",
|
"accounted_deleted": "Account deleted",
|
||||||
"account_deleted_message": "your account has beed successfully deleted",
|
"account_deleted_message": "your account has beed successfully deleted",
|
||||||
"privacy": "Privacy policy",
|
"privacy": "Privacy policy",
|
||||||
@ -95,7 +98,6 @@ class StringValues extends Translations{
|
|||||||
'already_have_account': 'Already have an account?',
|
'already_have_account': 'Already have an account?',
|
||||||
'sign_up': 'Sign Up',
|
'sign_up': 'Sign Up',
|
||||||
'create_account': 'Create an account, it\'s free',
|
'create_account': 'Create an account, it\'s free',
|
||||||
'email': 'Email',
|
|
||||||
'confirm_password': 'Confirm Password',
|
'confirm_password': 'Confirm Password',
|
||||||
'cancel_checkin': 'Cancel Check-in',
|
'cancel_checkin': 'Cancel Check-in',
|
||||||
'go_here': 'Show route',
|
'go_here': 'Show route',
|
||||||
@ -203,13 +205,19 @@ class StringValues extends Translations{
|
|||||||
'location_permission_required_title': 'Location Permission Required',
|
'location_permission_required_title': 'Location Permission Required',
|
||||||
'location_permission_required_message': 'This app requires access to your location. Please grant permission to continue.',
|
'location_permission_required_message': 'This app requires access to your location. Please grant permission to continue.',
|
||||||
'cancel': 'Cancel',
|
'cancel': 'Cancel',
|
||||||
'checkins': 'Check-ins'
|
'checkins': 'Check-ins',
|
||||||
|
'reset_button': 'Reset data',
|
||||||
|
'reset_title': 'Reset the data in this device.',
|
||||||
|
'reset_message': 'Are you ok to reset all data in this device?',
|
||||||
|
'reset_done': 'Reset Done.',
|
||||||
|
'reset_explain': 'All data has been reset. You should tap start rogaining to start game.',
|
||||||
},
|
},
|
||||||
'ja_JP': {
|
'ja_JP': {
|
||||||
'drawer_title':'ロゲイニング参加者はログイン するとチェックポイントが参照 できます',
|
'drawer_title':'ロゲイニング参加者はログイン するとチェックポイントが参照 できます',
|
||||||
'app_title': '旅行工程表',
|
'app_title': '旅行工程表',
|
||||||
'address':'住所',
|
'address':'住所',
|
||||||
'email':'ゼッケン番号',
|
'bib':'ゼッケン番号',
|
||||||
|
'email':'メールアドレス',
|
||||||
'password':'パスワード',
|
'password':'パスワード',
|
||||||
'web':'ウェブ',
|
'web':'ウェブ',
|
||||||
'wikipedia':'ウィキペディア',
|
'wikipedia':'ウィキペディア',
|
||||||
@ -245,7 +253,7 @@ class StringValues extends Translations{
|
|||||||
'confirm': '確認',
|
'confirm': '確認',
|
||||||
'cancel': 'キャンセル',
|
'cancel': 'キャンセル',
|
||||||
'all_destinations_are_deleted_successfully' : 'すべての宛先が正常に削除されました',
|
'all_destinations_are_deleted_successfully' : 'すべての宛先が正常に削除されました',
|
||||||
'deleted': "削除された",
|
'deleted': "削除されました",
|
||||||
'remarks' : '備考',
|
'remarks' : '備考',
|
||||||
'old_password' : '以前のパスワード',
|
'old_password' : '以前のパスワード',
|
||||||
'new_password' : '新しいパスワード',
|
'new_password' : '新しいパスワード',
|
||||||
@ -273,11 +281,13 @@ class StringValues extends Translations{
|
|||||||
"You have not started rogaining yet.":"あなたはまだロゲイニングを始めていません。",
|
"You have not started rogaining yet.":"あなたはまだロゲイニングを始めていません。",
|
||||||
"Not reached the goal yet": "まだ目標に達していない",
|
"Not reached the goal yet": "まだ目標に達していない",
|
||||||
"You have not reached the goal yet.":"あなたはまだゴールに達していません。",
|
"You have not reached the goal yet.":"あなたはまだゴールに達していません。",
|
||||||
"delete_account": "アカウントを削除する",
|
"delete_account": "アカウントを削除します",
|
||||||
|
"delete_account_title": "アカウントを削除しますがよろしいですか?",
|
||||||
|
"delete_account_middle": "これにより、アカウント情報とすべてのゲーム データが削除され、すべての状態が削除されます",
|
||||||
"accounted_deleted": "アカウントが削除されました",
|
"accounted_deleted": "アカウントが削除されました",
|
||||||
"account_deleted_message": "あなたのアカウントは正常に削除されました",
|
"account_deleted_message": "あなたのアカウントは正常に削除されました",
|
||||||
"privacy": "プライバシーポリシー",
|
"privacy": "プライバシーポリシー",
|
||||||
"app_developed_by_gifu_dx": "※このアプリは令和4年度岐阜県DX補助金事業で開発されました。",
|
"app_developed_by_gifu_dx": "※このアプリは令和4、6年度岐阜県DX補助金事業で開発されました。",
|
||||||
|
|
||||||
'location_permission_title': 'ロケーション許可',
|
'location_permission_title': 'ロケーション許可',
|
||||||
'location_permission_content': 'このアプリでは、位置情報の収集を行います。\n岐阜ナビアプリではチェックポイントの自動チェックインの機能を可能にするために、現在地のデータが収集されます。アプリを閉じている時や、使用していないときにも収集されます。位置情報は、個人を特定できない統計的な情報として、ユーザーの個人情報とは一切結びつかない形で送信されます。お知らせの配信、位置情報の利用を許可しない場合は、この後表示されるダイアログで「許可しない」を選択してください。',
|
'location_permission_content': 'このアプリでは、位置情報の収集を行います。\n岐阜ナビアプリではチェックポイントの自動チェックインの機能を可能にするために、現在地のデータが収集されます。アプリを閉じている時や、使用していないときにも収集されます。位置情報は、個人を特定できない統計的な情報として、ユーザーの個人情報とは一切結びつかない形で送信されます。お知らせの配信、位置情報の利用を許可しない場合は、この後表示されるダイアログで「許可しない」を選択してください。',
|
||||||
@ -299,7 +309,6 @@ class StringValues extends Translations{
|
|||||||
'already_have_account': 'すでにアカウントをお持ちですか?',
|
'already_have_account': 'すでにアカウントをお持ちですか?',
|
||||||
'sign_up': 'サインアップ',
|
'sign_up': 'サインアップ',
|
||||||
'create_account': 'アカウントを無料で作成します',
|
'create_account': 'アカウントを無料で作成します',
|
||||||
'email': 'ゼッケン番号',
|
|
||||||
'confirm_password': 'パスワードを認証する',
|
'confirm_password': 'パスワードを認証する',
|
||||||
'cancel_checkin': 'チェックイン取消',
|
'cancel_checkin': 'チェックイン取消',
|
||||||
'go_here': 'ルート表示',
|
'go_here': 'ルート表示',
|
||||||
@ -410,6 +419,11 @@ class StringValues extends Translations{
|
|||||||
'location_permission_required_message': 'このアプリを使用するには、位置情報へのアクセスが必要です。続行するには許可を付与してください。',
|
'location_permission_required_message': 'このアプリを使用するには、位置情報へのアクセスが必要です。続行するには許可を付与してください。',
|
||||||
'cancel': 'キャンセル',
|
'cancel': 'キャンセル',
|
||||||
'checkins': 'チェックイン',
|
'checkins': 'チェックイン',
|
||||||
|
'reset_button': 'リセット',
|
||||||
|
'reset_title': 'リセットしますがよろしいですか?',
|
||||||
|
'reset_message': 'これにより、すべてのゲーム データが削除され、すべての状態が削除されます',
|
||||||
|
'reset_done': 'リセット完了',
|
||||||
|
'reset_explain': 'すべてリセットされました。ロゲ開始から再開して下さい。',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,6 +12,9 @@ class LogManager {
|
|||||||
List<String> _logs = [];
|
List<String> _logs = [];
|
||||||
List<VoidCallback> _listeners = [];
|
List<VoidCallback> _listeners = [];
|
||||||
|
|
||||||
|
List<String> _operationLogs = [];
|
||||||
|
List<String> get operationLogs => _operationLogs;
|
||||||
|
|
||||||
List<String> get logs => _logs;
|
List<String> get logs => _logs;
|
||||||
|
|
||||||
void addLog(String log) {
|
void addLog(String log) {
|
||||||
@ -24,6 +27,16 @@ class LogManager {
|
|||||||
_notifyListeners(); // Notify all listeners
|
_notifyListeners(); // Notify all listeners
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addOperationLog(String log) {
|
||||||
|
_operationLogs.add(log);
|
||||||
|
_notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearOperationLogs() {
|
||||||
|
_operationLogs.clear();
|
||||||
|
_notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
void addListener(VoidCallback listener) {
|
void addListener(VoidCallback listener) {
|
||||||
_listeners.add(listener);
|
_listeners.add(listener);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
|||||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||||
# Read more about iOS versioning at
|
# Read more about iOS versioning at
|
||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
version: 4.8.0+480
|
version: 4.8.1+481
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.2.0 <4.0.0"
|
sdk: ">=3.2.0 <4.0.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user