審査用に文言などを修正 ver.4.5.1 467

This commit is contained in:
2024-05-15 17:59:25 +09:00
parent dd9343bef7
commit df4405aedf
28 changed files with 843 additions and 227 deletions

View File

@ -117,8 +117,8 @@ class ChangePasswordPage extends StatelessWidget {
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(40)),
child: const Text(
"ログイン",
child: Text(
"login".tr,
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 16,

View File

@ -0,0 +1,9 @@
import 'package:get/get.dart';
import 'package:rogapp/pages/debug/debug_controller.dart';
class DebugBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut<DebugController>(() => DebugController());
}
}

View File

@ -0,0 +1,47 @@
import 'package:geolocator/geolocator.dart';
import 'package:get/get.dart';
import 'package:rogapp/utils/location_controller.dart';
class DebugController extends GetxController {
final LocationController locationController = Get.find<LocationController>();
final gpsSignalStrength = 'high'.obs;
final currentPosition = Rx<Position?>(null);
final isSimulationMode = false.obs;
@override
void onInit() {
super.onInit();
// 位置情報の更新を監視
locationController.locationMarkerPositionStream.listen((position) {
if (position != null) {
currentPosition.value = Position(
latitude: position.latitude,
longitude: position.longitude,
accuracy: position.accuracy,
altitudeAccuracy: 30,
headingAccuracy: 30,
heading: 0,
altitude: 0,
speed: 0,
speedAccuracy: 0,
timestamp: DateTime.now(),
);
}
});
}
void setGpsSignalStrength(String value) {
gpsSignalStrength.value = value;
locationController.setSimulatedSignalStrength(value);
}
void toggleSimulationMode() {
isSimulationMode.value = !isSimulationMode.value;
locationController.setSimulationMode(isSimulationMode.value);
if (!isSimulationMode.value) {
// 標準モードに切り替えた場合は、シミュレートされた信号強度をリセット
locationController.setSimulatedSignalStrength('low');
gpsSignalStrength.value = 'low';
}
}
}

View File

@ -0,0 +1,63 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:rogapp/pages/debug/debug_controller.dart';
class DebugPage extends GetView<DebugController> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('デバッグモード'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('GPS信号強度'),
const SizedBox(height: 20),
Obx(
() => DropdownButton<String>(
value: controller.gpsSignalStrength.value,
onChanged: (value) {
controller.setGpsSignalStrength(value!);
},
items: ['high', 'medium', 'low']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
),
const SizedBox(height: 20),
const Text('現在のGPS座標'),
const SizedBox(height: 10),
Obx(
() => Text(
'緯度: ${controller.currentPosition.value?.latitude ?? '-'}, 経度: ${controller.currentPosition.value?.longitude ?? '-'}',
),
),
const SizedBox(height: 20),
const Text('現在のGPS精度'),
const SizedBox(height: 10),
Obx(
() => Text(
'精度: ${controller.currentPosition.value?.accuracy.toStringAsFixed(2) ?? '-'} m',
),
),
const SizedBox(height: 20),
Obx(
() => ElevatedButton(
onPressed: controller.toggleSimulationMode,
child: Text(controller.isSimulationMode.value
? 'シミュレーションモード'
: '標準モード'),
),
),
],
),
),
);
}
}

View File

@ -221,7 +221,7 @@ class DestinationController extends GetxController {
if (accuracy == null) {
return true; // 位置情報が取得できていない場合、GPS信号が弱いと見なす
}
return accuracy > 50;
return accuracy > 60;
//return locationController.currentPosition.value?.accuracy ?? double.infinity > 50;
}
@ -1335,11 +1335,14 @@ class DestinationController extends GetxController {
prevLon = currentLon;
}
lastValidGPSLocation = LatLng(currentLat, currentLon);
lastValidLat = currentLat;
lastValidLon = currentLon;
okToUseGPS = true;
lastGPSDataReceivedTime = DateTime.now();
hasReceivedGPSData = true;
} else {
debugPrint("....position is null....");
checkGPSDataReceived();
// 信号強度が低い場合、最後に取得した高いまたは中程度の位置情報を使用
@ -1351,6 +1354,9 @@ class DestinationController extends GetxController {
longitude: lastValidGPSLocation.longitude,
accuracy: 0,
);
currentLat = position.latitude;
currentLon = position.longitude;
okToUseGPS = false;
/*
if (lastValidLat != 0.0 && lastValidLon != 0.0) {

View File

@ -281,7 +281,15 @@ class DrawerPage extends StatelessWidget {
Get.toNamed(Routes.SETTINGS);
},
)
),
ListTile(
leading: const Icon(Icons.developer_mode),
title: const Text('開発者メニュー'),
onTap: () {
Get.back(); // ドロワーを閉じる
Get.toNamed('/debug'); // デバッグ画面に遷移
},
),
// ListTile(
// leading: const Icon(Icons.router),
// title: Text("my_route".tr),

View File

@ -104,7 +104,7 @@ class _GpsPageState extends State<GpsPage> {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("移動履歴"),
title: Text("movement_history".tr),
),
body: Container(
child: Obx(

View File

@ -3,6 +3,7 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:rogapp/model/destination.dart';
import 'package:rogapp/utils/database_helper.dart';
import 'package:get/get.dart';
class HistoryPage extends StatefulWidget {
const HistoryPage({super.key});
@ -18,7 +19,7 @@ class _HistoryPageState extends State<HistoryPage> {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("通過履歴"),
title: Text("pass_history".tr),
),
body: SingleChildScrollView(
child: Column(
@ -68,7 +69,7 @@ class _HistoryPageState extends State<HistoryPage> {
);
}));
} else {
return const Center(child: Text("No checkin yet"));
return Center(child: Text("no_checkin_yet".tr));
}
}
} else if (snapshot.connectionState ==

View File

@ -1,46 +1,76 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:rogapp/pages/search/search_page.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:rogapp/routes/app_pages.dart';
import 'package:rogapp/utils/string_values.dart';
// 要検討SearchPageへのナビゲーションにNavigator.pushを使用していますが、一貫性のためにGet.toやGet.toNamedを使用することを検討してください。
//
class HomePage extends GetView{
const HomePage({Key? key}) : super(key: key);
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
bool _isLocationServiceEnabled = true;
@override
void initState() {
super.initState();
_checkLocationService();
}
Future<void> _checkLocationService() async {
final serviceEnabled = await Permission.location.serviceStatus.isEnabled;
setState(() {
_isLocationServiceEnabled = serviceEnabled;
});
}
void _showLocationDisabledDialog() {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('location_disabled_title'.tr),
content: Text('location_disabled_message'.tr),
actions: [
TextButton(
child: Text('ok'.tr),
onPressed: () => Navigator.of(context).pop(),
),
TextButton(
child: Text('open_settings'.tr),
onPressed: () {
Navigator.of(context).pop();
openAppSettings();
},
),
],
);
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.white,
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("app_title".tr,
style: const TextStyle(
color: Colors.blue
),
),
InkWell(
onTap: (){
Navigator.push(context, MaterialPageRoute(builder: (context) => SearchPage()));
},
child: Container(
height: 32,
width: 75,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(25),
),
child: const Center(child: Icon(Icons.search),),
),
),
],
),
title: Text('home'.tr),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('welcome'.tr),
SizedBox(height: 20),
ElevatedButton(
onPressed: _isLocationServiceEnabled
? () => Get.offNamed(AppPages.INDEX)
: () => _showLocationDisabledDialog(),
child: Text('start_app'.tr),
),
],
),
body: Container(),
),
);
}
}

View File

@ -120,8 +120,8 @@ class LoginPage extends StatelessWidget {
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(40)),
child: const Text(
"ログイン",
child: Text(
"login".tr,
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 16,
@ -133,7 +133,7 @@ class LoginPage extends StatelessWidget {
),
MaterialButton(
minWidth: double.infinity,
height: 40,
height: 36,
onPressed: () {
Get.toNamed(AppPages.REGISTER);
},
@ -154,7 +154,7 @@ class LoginPage extends StatelessWidget {
),
MaterialButton(
minWidth: double.infinity,
height: 40,
height: 36,
onPressed: () {
Get.back();
},
@ -187,6 +187,7 @@ class LoginPage extends StatelessWidget {
"rogaining_user_need_tosign_up".tr,
style: const TextStyle(
overflow: TextOverflow.ellipsis,
fontSize: 10.0
),
),
),

View File

@ -2,13 +2,12 @@ import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:rogapp/routes/app_pages.dart';
import 'dart:io';
class PermissionHandlerScreen extends StatefulWidget {
const PermissionHandlerScreen({Key? key}) : super(key: key);
@override
State<PermissionHandlerScreen> createState() =>
_PermissionHandlerScreenState createState() =>
_PermissionHandlerScreenState();
}
@ -21,116 +20,59 @@ class _PermissionHandlerScreenState extends State<PermissionHandlerScreen> {
});
}
_checkPermissionStatus() async {
Future<void> _checkPermissionStatus() async {
PermissionStatus status = await Permission.location.status;
if (status.isGranted == false) {
if (status.isGranted) {
if (context.mounted) {
showAlert(context);
Get.offNamed(AppPages.LOGIN);
}
} else if (status.isPermanentlyDenied) {
await requestPermission();
} else {
if (mounted) {
Get.toNamed(AppPages.LOGIN);
if (context.mounted) {
_showPermissionRequestDialog();
}
}
}
void showAlert(BuildContext context) {
void _showPermissionRequestDialog() {
showDialog(
context: context,
builder: (_) => AlertDialog(
title: const Text('ロケーション許可'),
content: const SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text('ぎふナビ "アプリへようこそ!\n'),
Text('収集データ:\n'),
Text(
'岐阜ナビアプリをより快適にご利用いただくために、チェックポイントでの自動チェックインのための位置情報を収集しています。また、撮影した画像やチェックインした時間を収集し、チャレンジの勝者を決定します。\n'),
Text('お客様のデータの使用方法:\n'),
Text(
'お客様のデータは、アプリを改善し、競争力のある魅力的な体験を提供するのに役立ちます。お客様の位置情報と画像は、個人を特定できない統計データとして処理され、いかなる個人情報にもリンクされないようにしています\n'),
Text('お客様の管理:\n'),
Text(
'お客様はご自身のデータを完全に管理することができます。アプリの設定でいつでも同意を撤回することができます。位置情報の収集に同意しなくても、ぎふナビを楽しむことはできますが、自動チェックインや競技への参加など、一部の機能が制限されることを覚えておいてください。位置情報、画像、時刻情報の利用に同意する場合は「許可」を選択してください。許可しない場合は、「許可しない」を選択してください。あなたの選択は、アプリの他の機能を使用することに影響しません。\n'),
],
),
),
actions: <Widget>[
ElevatedButton(
child: const Text('OK'),
onPressed: () {
Get.back();
requestPermission();
},
),
],
));
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('location_permission_required_title'.tr),
content: Text('location_permission_required_message'.tr),
actions: [
TextButton(
child: Text('cancel'.tr),
onPressed: () {
Navigator.of(context).pop();
Get.offNamed(AppPages.HOME);
},
),
TextButton(
child: Text('ok'.tr),
onPressed: () {
Navigator.of(context).pop();
_requestLocationPermission();
},
),
],
);
},
);
}
// 要検討:位置情報の許可が拒否された場合、適切なエラーメッセージを表示することを検討してください。
//
Future<void> requestPermission() async {
PermissionStatus permission = await Permission.location.status;
if (permission == PermissionStatus.permanentlyDenied) {
showPermanentAlert();
void _requestLocationPermission() async {
final status = await Permission.location.request();
if (status.isGranted) {
Get.offNamed(AppPages.LOGIN);
} else {
PermissionStatus newPermission = await Permission.location.request();
if (newPermission != PermissionStatus.granted) {
exit(0);
} else {
if (context.mounted) {
Get.toNamed(AppPages.LOGIN);
}
}
Get.offNamed(AppPages.HOME);
}
}
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Text(""),
);
return Scaffold(body: Container());
}
// 要検討:ユーザーが位置情報の許可を拒否し続けた場合の対処方法を明確にすることをお勧めします。
//
void showPermanentAlert() {
showDialog(
context: context,
builder: (_) => AlertDialog(
title: const Text('無効'),
content: const SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text('位置情報が無効になっています'),
Text(
'このアプリケーションへの位置情報アクセスが無効になっています。続行するには設定>プライバシーとセキュリティ>位置情報サービス>岐阜ナビ で有効にしてください。'),
],
),
),
actions: <Widget>[
ElevatedButton(
child: const Text('OK'),
onPressed: () async {
await openAppSettings().then(
(value) async {
if (value) {
if (await Permission
.location.status.isPermanentlyDenied ==
true &&
await Permission.location.status.isGranted ==
false) {
requestPermission(); /* opens app settings until permission is granted */
}
}
},
);
},
),
],
));
}
}
}

View File

@ -0,0 +1,188 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:rogapp/routes/app_pages.dart';
import 'dart:io';
class PermissionHandlerScreen extends StatefulWidget {
const PermissionHandlerScreen({Key? key}) : super(key: key);
@override
State<PermissionHandlerScreen> createState() =>
_PermissionHandlerScreenState();
}
class _PermissionHandlerScreenState extends State<PermissionHandlerScreen> {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
_checkPermissionStatus();
});
}
Future<void> _checkPermissionStatus() async {
PermissionStatus status = await Permission.location.status;
if (status.isGranted) {
if (context.mounted) {
Get.toNamed(AppPages.LOGIN);
}
} else {
if (context.mounted) {
Get.toNamed(AppPages.HOME);
}
}
}
/*
_checkPermissionStatus() async {
PermissionStatus status = await Permission.location.status;
if (status.isGranted == false) {
if (context.mounted) {
showAlert(context);
}
} else if (status.isPermanentlyDenied) {
await requestPermission();
} else {
if (mounted) {
Get.toNamed(AppPages.LOGIN);
}
}
}
*/
void showAlert(BuildContext context) {
showDialog(
context: context,
builder: (_) => AlertDialog(
title: Text('location_permission_title'.tr),
content: SingleChildScrollView(
child: Text('location_permission_content'.tr),
),
actions: <Widget>[
ElevatedButton(
child: const Text('OK'),
onPressed: () {
Get.back();
requestPermission();
},
),
],
));
}
// 要検討:位置情報の許可が拒否された場合、適切なエラーメッセージを表示することを検討してください。
//
/*
Future<void> requestPermission() async {
PermissionStatus permission = await Permission.location.status;
if (permission == PermissionStatus.permanentlyDenied) {
showPermanentAlert();
} else {
PermissionStatus newPermission = await Permission.location.request();
if (newPermission != PermissionStatus.granted) {
exit(0);
} else {
if (context.mounted) {
Get.toNamed(AppPages.LOGIN);
}
}
}
}
*/
Future<void> requestPermission() async {
PermissionStatus permission = await Permission.location.request();
if (permission == PermissionStatus.granted) {
if (context.mounted) {
Get.toNamed(AppPages.LOGIN);
}
} else if (permission == PermissionStatus.denied) {
await showLocationPermissionDeniedDialog();
} else if (permission == PermissionStatus.permanentlyDenied) {
await showPermanentlyDeniedDialog();
}
}
Future<void> showLocationPermissionDeniedDialog() async {
await showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('location_permission_denied_title'.tr),
content: Text('location_permission_denied_message'.tr),
actions: [
TextButton(
child: Text('ok'.tr),
onPressed: () => Navigator.of(context).pop(),
),
],
);
},
);
}
Future<void> showPermanentlyDeniedDialog() async {
await showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('location_permission_permanently_denied_title'.tr),
content: Text('location_permission_permanently_denied_message'.tr),
actions: [
TextButton(
child: Text('open_settings'.tr),
onPressed: () {
Navigator.of(context).pop();
openAppSettings();
},
),
],
);
},
);
}
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Text(""),
);
}
// 要検討:ユーザーが位置情報の許可を拒否し続けた場合の対処方法を明確にすることをお勧めします。
//
void showPermanentAlert() {
showDialog(
context: context,
builder: (_) => AlertDialog(
title: Text('location_disabled_title'.tr),
content: SingleChildScrollView(
child: Text('location_disabled_content'.tr),
),
actions: <Widget>[
ElevatedButton(
child: const Text('OK'),
onPressed: () async {
await openAppSettings().then(
(value) async {
if (value) {
if (await Permission
.location.status.isPermanentlyDenied ==
true &&
await Permission.location.status.isGranted ==
false) {
requestPermission(); /* opens app settings until permission is granted */
}
}
},
);
},
),
],
));
}
}

View File

@ -43,8 +43,8 @@ class RegisterPage extends StatelessWidget {
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
const Text(
"サインアップ",
Text(
"sign_up".tr,
style: TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
@ -54,7 +54,7 @@ class RegisterPage extends StatelessWidget {
height: 20,
),
Text(
"アカウントを作成し、無料です",
"create_account".tr,
style: TextStyle(
fontSize: 15,
color: Colors.grey[700],
@ -69,13 +69,13 @@ class RegisterPage extends StatelessWidget {
padding: const EdgeInsets.symmetric(horizontal: 40),
child: Column(
children: [
makeInput(label: "Eメール", controller: emailController),
makeInput(label: "email".tr, controller: emailController),
makeInput(
label: "パスワード",
label: "password".tr,
controller: passwordController,
obsureText: true),
makeInput(
label: "パスワードを認証する",
label: "confirm_password".tr,
controller: confirmPasswordController,
obsureText: true)
],
@ -150,13 +150,13 @@ class RegisterPage extends StatelessWidget {
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Flexible(child: Text("すでにアカウントをお持ちですか?")),
Flexible(child: Text("already_have_account".tr)),
TextButton(
onPressed: () {
Get.toNamed(AppPages.LOGIN);
},
child: const Text(
"ログイン",
child: Text(
"login".tr,
style: TextStyle(
fontWeight: FontWeight.w600, fontSize: 18),
),

View File

@ -18,8 +18,8 @@ class SettingsPage extends GetView<SettingsController> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'タイマーの長さ',
Text(
'timer_duration'.tr,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,