Fixed Location & Storage issues

This commit is contained in:
2024-05-25 11:05:02 +09:00
parent e55674e1b9
commit 6a49aed98d
861 changed files with 80074 additions and 402 deletions

View File

@ -218,45 +218,53 @@ class CameraPage extends StatelessWidget {
// 要修正:エラーハンドリングが不十分です。例外が発生した場合の処理を追加することをお勧めします。
//
Widget getAction(BuildContext context) {
//print("----cccheckin is --- ${dbDest?.checkedin} ----");
if (manulaCheckin == true) {
// manulaCheckinがtrueの場合は、撮影ボタンとチェックインボタンを表示します。
return Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
ElevatedButton(
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Wrap(
spacing: 16.0,
runSpacing: 8.0,
children: [
Obx(() => ElevatedButton(
onPressed: () {
destinationController.openCamera(context, destination);
},
child: const Text("撮影")),
Obx(() => destinationController.photos.isNotEmpty
? ElevatedButton(
style: ElevatedButton.styleFrom(backgroundColor: Colors.red),
onPressed: () async {
await destinationController.makeCheckin(destination, true,
destinationController.photos[0].path);
//Get.back();
destinationController.rogainingCounted.value = true;
destinationController.skipGps = false;
destinationController.isPhotoShoot.value = false;
style: ElevatedButton.styleFrom(
shape: const CircleBorder(),
padding: const EdgeInsets.all(20),
backgroundColor: destinationController.photos.isEmpty
? Colors.red
: Colors.grey[300],
),
child: destinationController.photos.isEmpty
? const Text("撮影", style: TextStyle(color: Colors.white))
: const Text("再撮影", style: TextStyle(color: Colors.black)),
)),
Obx(() => destinationController.photos.isNotEmpty
? ElevatedButton(
style: ElevatedButton.styleFrom(backgroundColor: Colors.red),
onPressed: () async {
await destinationController.makeCheckin(destination, true,
destinationController.photos[0].path);
destinationController.rogainingCounted.value = true;
destinationController.skipGps = false;
destinationController.isPhotoShoot.value = false;
Get.snackbar("チェックインしました。",
"${destination.sub_loc_id} : ${destination.name}",
backgroundColor: Colors.green,
colorText: Colors.white,
duration: const Duration(seconds: 2), // 表示時間を1秒に設定
);
// SnackBarの表示が終了するのを待ってからCameraPageを閉じる
await Future.delayed(const Duration(seconds: 2));
Get.snackbar("チェックインしました。",
"${destination.sub_loc_id} : ${destination.name}",
backgroundColor: Colors.green,
colorText: Colors.white,
duration: const Duration(seconds: 2),
);
await Future.delayed(const Duration(seconds: 2));
Navigator.of(context).pop(true); // ここを修正
},
child: const Text("チェックイン"))
: Container())
],
Navigator.of(context).pop(true);
},
child: const Text("チェックイン", style: TextStyle(color: Colors.white)),
)
: Container())
],
),
);
}
@ -610,6 +618,114 @@ class BuyPointCamera extends StatelessWidget {
Destination destination;
DestinationController destinationController =
Get.find<DestinationController>();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
title: Text(
"${destination.sub_loc_id} : ${destination.name}",
),
),
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: Obx(
() => Container(
width: MediaQuery.of(context).size.width,
height: 370,
decoration: BoxDecoration(
image: DecorationImage(
// 要修正getReceiptImage関数の戻り値がnullの場合のエラーハンドリングが不十分です。適切なデフォルト画像を表示するなどの処理を追加してください。
//
image: getReceiptImage(), fit: BoxFit.cover)),
),
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(getTagText(true, destination.tags)),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Wrap(
spacing: 16.0,
runSpacing: 8.0,
children: [
Obx(() => ElevatedButton(
onPressed: () {
destinationController.openCamera(context, destination);
},
style: ElevatedButton.styleFrom(
shape: const CircleBorder(),
padding: const EdgeInsets.all(20),
backgroundColor: destinationController.photos.isEmpty
? Colors.red
: Colors.grey[300],
),
child: destinationController.photos.isEmpty
? const Text("撮影",
style: TextStyle(color: Colors.white))
: const Text("再撮影",
style: TextStyle(color: Colors.black)),
)),
ElevatedButton(
onPressed: () async {
await destinationController.cancelBuyPoint(destination);
Navigator.of(Get.context!).pop();
destinationController.rogainingCounted.value = true;
destinationController.skipGps = false;
destinationController.isPhotoShoot.value = false;
},
child: const Text("買い物なし")),
Obx(() => destinationController.photos.isNotEmpty
? ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.red),
onPressed: () async {
await destinationController.makeBuyPoint(
destination,
destinationController.photos[0].path);
Get.back();
destinationController.rogainingCounted.value = true;
destinationController.skipGps = false;
destinationController.isPhotoShoot.value = false;
Get.snackbar("お買い物加点を行いました",
"${destination.sub_loc_id} : ${destination.name}",
backgroundColor: Colors.green,
colorText: Colors.white);
},
child: const Text("完了",
style: TextStyle(color: Colors.white)))
: Container())
],
),
),
],
),
),
);
}
}
/*
class BuyPointCamera extends StatelessWidget {
BuyPointCamera({Key? key, required this.destination}) : super(key: key);
Destination destination;
DestinationController destinationController =
Get.find<DestinationController>();
@ -725,7 +841,7 @@ class BuyPointCamera extends StatelessWidget {
);
}
}
*/
class QRCodeScannerPage extends StatefulWidget {

View File

@ -0,0 +1,163 @@
import 'dart:io';
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart';
class CustomCameraView extends StatefulWidget {
final Function(String) onImageCaptured;
const CustomCameraView({Key? key, required this.onImageCaptured}) : super(key: key);
@override
_CustomCameraViewState createState() => _CustomCameraViewState();
}
class _CustomCameraViewState extends State<CustomCameraView> {
CameraController? _controller;
late List<CameraDescription> _cameras;
int _selectedCameraIndex = 0;
double _currentScale = 1.0;
FlashMode _currentFlashMode = FlashMode.off;
@override
void initState() {
super.initState();
_initializeCamera();
}
Future<void> _initializeCamera() async {
_cameras = await availableCameras();
_controller = CameraController(_cameras[_selectedCameraIndex], ResolutionPreset.medium);
await _controller!.initialize();
setState(() {});
}
@override
void dispose() {
_controller?.dispose();
super.dispose();
}
Future<void> _toggleCameraLens() async {
final newIndex = (_selectedCameraIndex + 1) % _cameras.length;
await _controller!.dispose();
setState(() {
_controller = null;
_selectedCameraIndex = newIndex;
});
_controller = CameraController(_cameras[_selectedCameraIndex], ResolutionPreset.medium);
await _controller!.initialize();
setState(() {});
}
void _toggleFlashMode() {
setState(() {
_currentFlashMode = (_currentFlashMode == FlashMode.off) ? FlashMode.torch : FlashMode.off;
});
_controller!.setFlashMode(_currentFlashMode);
}
void _zoomIn() {
setState(() {
_currentScale += 0.1;
if (_currentScale > 5.0) _currentScale = 5.0;
});
_controller!.setZoomLevel(_currentScale);
}
void _zoomOut() {
setState(() {
_currentScale -= 0.1;
if (_currentScale < 1.0) _currentScale = 1.0;
});
_controller!.setZoomLevel(_currentScale);
}
void _captureImage() async {
if (_controller!.value.isInitialized) {
final Directory appDirectory = await getApplicationDocumentsDirectory();
final String imagePath = path.join(appDirectory.path, '${DateTime.now()}.jpg');
final XFile imageFile = await _controller!.takePicture();
await imageFile.saveTo(imagePath);
widget.onImageCaptured(imagePath);
Navigator.pop(context);
}
}
@override
Widget build(BuildContext context) {
if (_controller == null || !_controller!.value.isInitialized) {
return Container();
}
return Stack(
children: [
CameraPreview(_controller!),
Positioned(
bottom: 16.0,
left: 16.0,
right: 16.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
IconButton(
onPressed: _toggleFlashMode,
icon: Icon(
(_currentFlashMode == FlashMode.off) ? Icons.flash_off : Icons.flash_on,
color: Colors.white,
),
iconSize: 32,
color: Colors.orange,
),
GestureDetector(
onTap: _captureImage,
child: Container(
height: 80,
width: 80,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.white,
border: Border.all(color: Colors.red, width: 4),
),
child: const Icon(Icons.camera_alt, color: Colors.red, size: 40),
),
),
IconButton(
onPressed: _toggleCameraLens,
icon: const Icon(Icons.flip_camera_ios, color: Colors.white),
iconSize: 32,
color: Colors.blue,
),
],
),
),
Positioned(
top: 16.0,
right: 16.0,
child: Column(
children: [
IconButton(
onPressed: _zoomIn,
icon: const Icon(Icons.zoom_in, color: Colors.white),
iconSize: 32,
color: Colors.green,
),
IconButton(
onPressed: _zoomOut,
icon: const Icon(Icons.zoom_out, color: Colors.white),
iconSize: 32,
color: Colors.green,
),
],
),
),
],
);
}
}

View File

@ -14,6 +14,7 @@ import 'package:rogapp/main.dart';
import 'package:rogapp/model/destination.dart';
import 'package:rogapp/model/gps_data.dart';
import 'package:rogapp/pages/camera/camera_page.dart';
import 'package:rogapp/pages/camera/custom_camera_view.dart';
import 'package:rogapp/pages/index/index_controller.dart';
import 'package:rogapp/routes/app_pages.dart';
import 'package:rogapp/services/DatabaseService.dart';
@ -119,6 +120,7 @@ class DestinationController extends GetxController {
var isCheckingIn = false.obs; // チェックイン操作中はtrueになり、重複してポップアップが出ないようにするもの。
var isRouteShowing = false.obs; // ルートが表示されているかどうかを示すReactive変数
/*
//==== Akira .. GPS信号シミュレーション用 ===== ここから、2024-4-5
//
@ -159,10 +161,18 @@ class DestinationController extends GetxController {
}
}
//
//==== Akira .. GPS信号シミュレーション用 ======= ここまで
*/
// ルートをクリアする関数です。
void clearRoute() {
indexController.routePoints.clear();
indexController.routePointLenght.value = 0;
isRouteShowing.value = false;
}
void showGPSDataNotReceivedPopup() {
if (Get.context != null) {
Get.dialog(
@ -750,6 +760,12 @@ class DestinationController extends GetxController {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => CustomCameraView(
onImageCaptured: (imagePath) {
photos.add(File(imagePath));
},
),
/*
builder: (_) => CameraCamera(
resolutionPreset: ResolutionPreset.medium,
onFile: (file) {
@ -758,7 +774,10 @@ class DestinationController extends GetxController {
//print("----image file is : $file----");
//setState(() {});
},
)));
)
*/
),
);
}
// ルートポイントを取得する関数です。
@ -1075,6 +1094,12 @@ class DestinationController extends GetxController {
}
Future<void> _saveImageToGallery(String imagePath) async {
final status = await PermissionController.checkStoragePermission();
if(!status){
await PermissionController.requestStoragePermission();
}
/*
final status = await Permission.storage.status;
if (!status.isGranted) {
final result = await Permission.storage.request();
@ -1105,9 +1130,11 @@ class DestinationController extends GetxController {
);
}
);
return;
}
}
*/
try {
final result = await ImageGallerySaver.saveFile(imagePath);
@ -1873,11 +1900,13 @@ class DestinationController extends GetxController {
//Get.toNamed(AppPages.TRAVEL);
});
destinationCount.value = destinations.length;
} catch (_) {
skipGps = false;
return;
} finally {
//Get.back();
isRouteShowing.value = true;
}
});
}

View File

@ -8,6 +8,7 @@ import 'dart:developer' as developer;
class PermissionController {
/*
static Future<bool> checkLocationPermissions() async {
debugPrint("(gifunavi)== checkLocationPermissions ==");
final alwaysPermission = await Permission.locationAlways.status;
@ -16,6 +17,29 @@ class PermissionController {
return (alwaysPermission == PermissionStatus.granted || whenInUsePermission == PermissionStatus.granted) &&
(locationPermission == PermissionStatus.granted);
}
*/
static Future<bool> checkStoragePermission() async {
debugPrint("(gifunavi)== checkStoragePermission ==");
final storagePermission = await Permission.storage.status;
return storagePermission == PermissionStatus.granted;
}
static Future<void> requestStoragePermission() async {
debugPrint("(gifunavi)== requestStoragePermission ==");
final storagePermission = await Permission.storage.request();
if (storagePermission == PermissionStatus.granted) {
return;
}
if (storagePermission == PermissionStatus.permanentlyDenied) {
// リクエストが完了するまで待機
await Future.delayed(Duration(milliseconds: 500));
showPermissionDeniedDialog('storage_permission_needed_title','storage_permission_needed_main');
}
}
static Future<bool> checkLocationBasicPermission() async {
@ -45,7 +69,7 @@ class PermissionController {
final locationStatus = await Permission.location.request();
if (locationStatus != PermissionStatus.granted) {
showPermissionDeniedDialog();
showPermissionDeniedDialog('location_permission_needed_title','location_permission_needed_main');
}
}
}catch (e, stackTrace){
@ -68,7 +92,7 @@ class PermissionController {
final whenInUseStatus = await Permission.locationWhenInUse.request();
if (whenInUseStatus != PermissionStatus.granted) {
showPermissionDeniedDialog();
showPermissionDeniedDialog('location_permission_needed_title','location_permission_needed_main');
}else{
if( !isLocationServiceRunning ){
isLocationServiceRunning=true;
@ -100,7 +124,7 @@ class PermissionController {
final alwaysStatus = await Permission.locationAlways.request();
if (alwaysStatus != PermissionStatus.granted) {
showPermissionDeniedDialog();
showPermissionDeniedDialog('location_permission_needed_title','location_permission_needed_main');
}
}
}catch (e, stackTrace){
@ -128,12 +152,14 @@ class PermissionController {
}
}
static void showPermissionDeniedDialog() {
static void showPermissionDeniedDialog(String title,String message) {
Get.dialog(
AlertDialog(
title: Text('location_permission_needed_title'.tr),
//title: Text('location_permission_needed_title'.tr),
title: Text(title.tr),
// 位置情報への許可が必要です
content: Text('location_permission_needed_main'.tr),
//content: Text('location_permission_needed_main'.tr),
content: Text(message.tr),
// 岐阜ロゲでは、位置情報を使用してスタート・チェックイン・ゴール等の通過照明及び移動手段の記録のために、位置情報のトラッキングを行なっています。このためバックグラウンドでもトラッキングができるように位置情報の権限が必要です。
// 設定画面で、「岐阜ナビ」に対して、常に位置情報を許可するように設定してください。
actions: [

View File

@ -99,13 +99,13 @@ class LocationController extends GetxController {
}
if (position == null) {
gpsDebugMode ? debugPrint("getGpsSignalStrength position is null.") : null;
//gpsDebugMode ? debugPrint("getGpsSignalStrength position is null.") : null;
latestSignalStrength.value = "low";
isGpsSignalWeak = true;
return 'low';
}
final accuracy = position.accuracy;
gpsDebugMode ? debugPrint("getGpsSignalStrength : ${accuracy}") : null;
//gpsDebugMode ? debugPrint("getGpsSignalStrength : ${accuracy}") : null;
/*
if(isSimulationMode){
return _simulatedSignalStrength.value; // GPS信号強度シミュレーション
@ -289,14 +289,14 @@ class LocationController extends GetxController {
//
positionStream = Geolocator.getPositionStream(locationSettings: locationOptions).listen(
(Position? position) {
gpsDebugMode ? debugPrint("Position = ${position}"):null;
//gpsDebugMode ? debugPrint("Position = ${position}"):null;
final signalStrength = getGpsSignalStrength(position);
if (signalStrength == 'low') {
isGpsSignalWeak = true;
gpsDebugMode ? debugPrint("LocationController.getPositionStream : isGpsSignalWeak = ${isGpsSignalWeak}"):null;
//gpsDebugMode ? debugPrint("LocationController.getPositionStream : isGpsSignalWeak = ${isGpsSignalWeak}"):null;
} else {
isGpsSignalWeak = false;
gpsDebugMode ? debugPrint("LocationController.getPositionStream : isGpsSignalWeak = ${isGpsSignalWeak}"):null;
//gpsDebugMode ? debugPrint("LocationController.getPositionStream : isGpsSignalWeak = ${isGpsSignalWeak}"):null;
}
final DestinationController destinationController = Get.find<DestinationController>();

View File

@ -98,7 +98,8 @@ class StringValues extends Translations{
'email': 'Email',
'confirm_password': 'Confirm Password',
'cancel_checkin': 'Cancel Check-in',
'go_here': 'Go Here',
'go_here': 'Show route',
'cancel_route':'Clear route',
'start_rogaining': 'Start Rogaining',
'in_game': 'In Game',
'finish_rogaining': 'Finish Rogaining',
@ -301,7 +302,8 @@ class StringValues extends Translations{
'email': 'ゼッケン番号',
'confirm_password': 'パスワードを認証する',
'cancel_checkin': 'チェックイン取消',
'go_here': 'ここへ行く',
'go_here': 'ルート表示',
'cancel_route':'ルート消去',
'start_rogaining': 'ロゲ開始',
'in_game': '競技中',
'finish_rogaining': 'ロゲゴール',
@ -359,7 +361,7 @@ class StringValues extends Translations{
'could_not_communicate_with_server': 'サーバーと通信できませんでした',
'communication_error_occurred': '通信エラーがおきました',
'checked_in': 'チェックインしました。',
'cancel_checkin': 'チェックイン取り消し',
'cancel_checkin': 'チェックイン取',
'checkin_canceled_for': 'のチェックインは取り消されました',
'error': 'エラー',
'failed_to_cancel_checkin': 'チェックイン取り消しに失敗しました。',
@ -390,6 +392,8 @@ class StringValues extends Translations{
'location_permission_permanently_denied_title': '位置情報の許可が永久に拒否されました',
'location_permission_permanently_denied_message': '位置情報の許可が永久に拒否されました。位置情報の許可を付与するには、アプリ設定を開いてください。',
'open_settings': '設定を開く',
'storage_permission_needed_title': '写真ライブラリへの許可が必要です',
'storage_permission_needed_main': '岐阜ロゲでは、写真ライブラリを使用してスタート・チェックイン・ゴール等の通過照明写真の記録のために、写真ライブラリへの書き込みを行なっています。このためチェックイン時に写真をライブラリに保存する権限が必要です。設定画面で、「岐阜ナビ」に対して、ライブラリに写真の保存を許可するように設定してください。',
'location_permission_needed_title': '位置情報への許可が必要です',
'location_permission_needed_main': '岐阜ロゲでは、位置情報を使用してスタート・チェックイン・ゴール等の通過照明及び移動手段の記録のために、位置情報のトラッキングを行なっています。このためバックグラウンドでもトラッキングができるように位置情報の権限が必要です。設定画面で、「岐阜ナビ」に対して、常に位置情報を許可するように設定してください。',
'open_settings': '設定を開く',

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:rogapp/widgets/GameState/Colors.dart';
class GameStatusIndicator extends StatelessWidget {
@ -15,7 +16,7 @@ class GameStatusIndicator extends StatelessWidget {
IconData iconData =
gameStarted ? Icons.stop_circle : Icons.play_circle_filled;
// Text to show based on the game status
String text = gameStarted ? 'ゲーム中' : 'ゲーム前';
String text = gameStarted ? 'in_game'.tr : 'start_game'.tr;
// Layout for minimized view
if (minimized) {

View File

@ -36,6 +36,8 @@ class BottomSheetNew extends GetView<BottomSheetController> {
final Destination destination; // 目的地オブジェクト
final bool isAlreadyCheckedIn; // すでにチェックイン済みかどうかのフラグ
final RxBool isButtonDisabled = false.obs;
// 目的地の画像を取得するためのメソッドです。
// indexController.rogModeの値に基づいて、適切な画像を返します。画像が見つからない場合は、デフォルトの画像を返します。
//
@ -139,7 +141,6 @@ class BottomSheetNew extends GetView<BottomSheetController> {
destinationController.photos.add(tempFile);
}
// アクションボタン(チェックイン、ゴールなど)を表示するためのメソッドです。
// 現在の状態に基づいて、適切なボタンを返します。
// ボタンがタップされたときの処理も含まれています。
@ -153,6 +154,7 @@ class BottomSheetNew extends GetView<BottomSheetController> {
// ...2024-04-03 Akira デバッグモードのみ出力するようにした。
*/
// bool isInRog=false;
Destination cdest = destinationController
.festuretoDestination(indexController.currentFeature[0]);
var distance = const Distance();
@ -164,66 +166,70 @@ class BottomSheetNew extends GetView<BottomSheetController> {
// Check conditions to show confirmation dialog
if (destinationController.isInRog.value == false &&
(destinationController.distanceToStart() <= 500 || destinationController.isGpsSignalWeak() ) && //追加 Akira 2024-4-5
(destinationController.distanceToStart() <= 100 || destinationController.isGpsSignalWeak() ) && //追加 Akira 2024-4-5
(destination.cp == -1 || destination.cp == 0 ) &&
destinationController.rogainingCounted.value == false) {
// ゲームが始まってなければ
return ElevatedButton(
return Obx(() {
final isInRog = destinationController.isInRog.value;
return ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.secondary,
),
onPressed: destinationController.isInRog.value == false &&
(destinationController.distanceToStart() <= 100 || destinationController.isGpsSignalWeak() ) && //追加 Akira 2024-4-5
(destination.cp == -1 || destination.cp == 0 ) &&
destinationController.rogainingCounted.value == false ? () async {
// Show confirmation dialog
Get.dialog(
AlertDialog(
title: Text("confirm".tr), //confirm
content: Text(
"clear_rog_data_message".tr), //are you sure
actions: <Widget>[
TextButton(
child: Text("no".tr), //no
onPressed: () {
Get.back(); // Close the dialog
},
),
TextButton(
child: Text("yes".tr), //yes
onPressed: () async {
onPressed: destinationController.isInRog.value
? null
: () async {
destinationController.isInRog.value = true;
await saveTemporaryImage(destination);
// Clear data and start game logic here
destinationController.isInRog.value = true;
destinationController.resetRogaining();
// Show confirmation dialog
Get.dialog(
AlertDialog(
title: Text("confirm".tr), //confirm
content: Text(
"clear_rog_data_message".tr), //are you sure
actions: <Widget>[
TextButton(
child: Text("no".tr), //no
onPressed: () {
// ダイアログをキャンセルした場合はボタンを再度有効化
destinationController.isInRog.value = false;
Get.back(); // Close the dialog
},
),
TextButton(
child: Text("yes".tr), //yes
onPressed: () async {
destinationController.isInRog.value = true;
await saveTemporaryImage(destination);
destinationController.addToRogaining(
destinationController.currentLat,
destinationController.currentLon,
destination.location_id!,
);
// Clear data and start game logic here
destinationController.resetRogaining();
saveGameState();
await ExternalService().startRogaining();
Get.back(); // Close the dialog and potentially navigate away
},
),
],
),
barrierDismissible:
false, // User must tap a button to close the dialog
);
}
: null,
child: Obx(
()=> Text(
destinationController.isInRog.value ? 'in_game'.tr : 'start_rogaining'.tr,
style: TextStyle(color: Colors.white),
),
destinationController.addToRogaining(
destinationController.currentLat,
destinationController.currentLon,
destination.location_id!,
);
saveGameState();
await ExternalService().startRogaining();
Get.back(); // Close the dialog and potentially navigate away
},
),
],
),
barrierDismissible: false, // User must tap a button to close the dialog
);
},
child: Text(
isInRog ? 'in_game'.tr : 'start_rogaining'.tr,
style: TextStyle(color: Colors.white),
),
);
});
//print("counted ${destinationController.rogainingCounted.value}");
@ -418,11 +424,9 @@ class BottomSheetNew extends GetView<BottomSheetController> {
LogManager().addLog(
"current point : ${destinationController.currentLat}, ${destinationController.currentLon} - ${DateTime.now().hour}:${DateTime.now().minute}:${DateTime.now().second}:${DateTime.now().microsecond}");
//LogManager().addLog("is already checked in : $isAlreadyCheckedIn");
LogManager().addLog("Checkin radius : ${destination.checkin_radious}");
LogManager().addLog("--${destination.cp}--");
return SingleChildScrollView(
child: Column(
children: [
@ -433,7 +437,6 @@ class BottomSheetNew extends GetView<BottomSheetController> {
MaterialButton(
onPressed: () {
Get.back();
//indexController.makePrevious(indexController.currentFeature[0]);
},
color: Colors.blue,
textColor: Colors.white,
@ -441,7 +444,6 @@ class BottomSheetNew extends GetView<BottomSheetController> {
shape: const CircleBorder(),
child: const Icon(
Icons.arrow_back_ios,
//Icons.arrow_back_ios,
size: 14,
),
),
@ -449,14 +451,12 @@ class BottomSheetNew extends GetView<BottomSheetController> {
child: Container(
alignment: Alignment.centerLeft,
child: Obx(() => Text(
"${TextUtils.getDisplayTextFeture(indexController.currentFeature[0])} : ${indexController.currentFeature[0].properties!["location_name"]}",
// indexController
// .currentFeature[0].properties!["location_name"],
style: const TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.bold,
),
)),
"${TextUtils.getDisplayTextFeture(indexController.currentFeature[0])} : ${indexController.currentFeature[0].properties!["location_name"]}",
style: const TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.bold,
),
)),
),
),
],
@ -466,287 +466,306 @@ class BottomSheetNew extends GetView<BottomSheetController> {
children: [
Expanded(
child: SizedBox(
height: 260.0,
child: Obx(() => getImage()),
)),
height: 260.0,
child: Obx(() => getImage()),
)),
],
),
Obx(() => Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
// Finish or Goal
getActionButton(context, destination),
//remove checkin
isAlreadyCheckedIn == true && destination.cp != 0 && destination.cp != -1 && destination.cp != -2
? ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blueAccent),
onPressed: () async {
try {
await destinationController
.removeCheckin(destination.cp!.toInt());
destinationController
.deleteDestination(destination);
Get.back();
Get.snackbar(
'チェックイン取り消し',
'${destination
.name}のチェックインは取り消されました',
backgroundColor: Colors.green,
colorText: Colors.white,
duration: Duration(seconds: 3),
);
} catch (e ) {
// エラーハンドリング
Get.snackbar(
'Error',
'An error occurred while canceling check-in.',
backgroundColor: Colors.red,
colorText: Colors.white,
duration: Duration(seconds: 3),
);
// 必要に応じてエラーログを記録
print('Error canceling check-in: $e');
}
},
child: Text(
"cancel_checkin".tr,
style: TextStyle(color: Colors.white),
)) //remove checkin
: Container(),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Theme.of(context)
.colorScheme
.onPrimaryContainer),
onPressed: () async {
// print(
// "dist to start ${destinationController.distanceToStart()}");
Get.back();
//print("---- go to ----");
// GeoJSONMultiPoint mp = indexController
// .currentFeature[0] as GeoJSONMultiPoint;
Position position =
await Geolocator.getCurrentPosition(
desiredAccuracy:
LocationAccuracy.bestForNavigation,
forceAndroidLocationManager: true);
//print("------- position -------- $position");
Destination ds = Destination(
lat: position.latitude,
lon: position.longitude);
Destination tp = Destination(
lat: destination.lat, lon: destination.lon);
destinationController
.destinationMatrixFromCurrentPoint([ds, tp]);
},
//go here
child: Text(
"go_here".tr,
style: TextStyle(
color:
Theme.of(context).colorScheme.onPrimary),
)),
const SizedBox(
width: 10,
),
// forced start / checkin
],
),
Row(
children: [
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
indexController.currentDestinationFeature
.isNotEmpty &&
destinationController.isInCheckin.value ==
true
? Container()
: FutureBuilder<Widget>(
future: wantToGo(context),
builder: (context, snapshot) {
return Container(
child: snapshot.data,
);
},
),
indexController.currentFeature[0]
.properties!["location_name"] !=
null &&
(indexController.currentFeature[0]
.properties!["location_name"]
as String)
.isNotEmpty
? Flexible(
child: Text(indexController
.currentFeature[0]
.properties!["location_name"]))
: const SizedBox(
width: 0.0,
height: 0,
),
],
),
),
],
),
const SizedBox(
height: 8.0,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
const Icon(Icons.roundabout_left),
const SizedBox(
width: 8.0,
),
indexController.currentFeature[0]
.properties!["address"] !=
null &&
(indexController.currentFeature[0]
.properties!["address"] as String)
.isNotEmpty
? getDetails(
context,
"address".tr,
indexController.currentFeature[0]
.properties!["address"] ??
'')
: const SizedBox(
width: 0.0,
height: 0,
),
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
const Icon(Icons.phone),
const SizedBox(
width: 8.0,
),
indexController.currentFeature[0]
.properties!["phone"] !=
null &&
(indexController.currentFeature[0]
.properties!["phone"] as String)
.isNotEmpty
? getDetails(
context,
"telephone".tr,
indexController.currentFeature[0]
.properties!["phone"] ??
'')
: const SizedBox(
width: 0.0,
height: 0,
),
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
const Icon(Icons.email),
const SizedBox(
width: 8.0,
),
indexController.currentFeature[0]
.properties!["email"] !=
null &&
(indexController.currentFeature[0]
.properties!["email"] as String)
.isNotEmpty
? getDetails(
context,
"email".tr,
indexController.currentFeature[0]
.properties!["email"] ??
'')
: const SizedBox(
width: 0.0,
height: 0,
),
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
const Icon(Icons.language),
const SizedBox(
width: 8.0,
),
indexController.currentFeature[0]
.properties!["webcontents"] !=
null &&
(indexController.currentFeature[0]
.properties!["webcontents"] as String)
.isNotEmpty
? getDetails(
context,
"web".tr,
indexController.currentFeature[0]
.properties!["webcontents"] ??
'',
isurl: true)
: const SizedBox(
width: 0.0,
height: 0,
),
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
const SizedBox(
width: 8.0,
),
indexController.currentFeature[0]
.properties!["remark"] !=
null &&
(indexController.currentFeature[0]
.properties!["remark"] as String)
.isNotEmpty
? getDetails(
context,
"remarks".tr,
indexController.currentFeature[0]
.properties!["remark"] ??
'',
isurl: false)
: const SizedBox(
width: 0.0,
height: 0,
),
],
),
),
// Text('${TextUtils.getDisplayText(indexController.currentFeature[0].properties!["cp"].toString())} - id: ${TextUtils.getDisplayText(indexController.currentFeature[0].properties!["checkin_point"].toString())}'),
// Finish or Goal
(destination.cp == -1 || destination.cp == 0)
? getActionButton(context, destination)
: Container(),
],
),
)),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
//checkin or remove checkin
destinationController.isInRog.value == true && destination.cp != 0 && destination.cp != -1 && destination.cp != -2
? (isAlreadyCheckedIn == false
? ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.red),
onPressed: () async {
try {
await destinationController.callforCheckin(destination);
} catch (e) {
// エラーハンドリング
Get.snackbar(
'Error',
'An error occurred while processing check-in.',
backgroundColor: Colors.red,
colorText: Colors.white,
duration: Duration(seconds: 3),
);
// 必要に応じてエラーログを記録
print('Error processing check-in: $e');
}
},
child: Text(
"checkin".tr,
style: TextStyle(color: Colors.white),
))
: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.grey[300]),
onPressed: () async {
try {
await destinationController
.removeCheckin(destination.cp!.toInt());
destinationController
.deleteDestination(destination);
Get.back();
Get.snackbar(
'チェックイン取り消し',
'${destination.name}のチェックインは取り消されました',
backgroundColor: Colors.green,
colorText: Colors.white,
duration: Duration(seconds: 3),
);
} catch (e) {
// エラーハンドリング
Get.snackbar(
'Error',
'An error occurred while canceling check-in.',
backgroundColor: Colors.red,
colorText: Colors.white,
duration: Duration(seconds: 3),
);
// 必要に応じてエラーログを記録
print('Error canceling check-in: $e');
}
},
child: Text(
"cancel_checkin".tr,
style: TextStyle(color: Colors.black),
)))
: Container(),
// go here or cancel route
Obx(() => ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Theme.of(context)
.colorScheme
.onPrimaryContainer),
onPressed: () async {
if (destinationController.isRouteShowing.value) {
destinationController.clearRoute();
} else {
Get.back();
Position position =
await Geolocator.getCurrentPosition(
desiredAccuracy:
LocationAccuracy.bestForNavigation,
forceAndroidLocationManager: true);
Destination ds = Destination(
lat: position.latitude,
lon: position.longitude);
Destination tp = Destination(
lat: destination.lat, lon: destination.lon);
destinationController
.destinationMatrixFromCurrentPoint([ds, tp]);
}
},
child: Text(
destinationController.isRouteShowing.value
? "cancel_route".tr
: "go_here".tr,
style: TextStyle(
color:
Theme.of(context).colorScheme.onPrimary),
))),
],
),
Row(
children: [
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
indexController.currentDestinationFeature
.isNotEmpty &&
destinationController.isInCheckin.value ==
true
? Container()
: FutureBuilder<Widget>(
future: wantToGo(context),
builder: (context, snapshot) {
return Container(
child: snapshot.data,
);
},
),
indexController.currentFeature[0]
.properties!["location_name"] !=
null &&
(indexController.currentFeature[0]
.properties!["location_name"]
as String)
.isNotEmpty
? Flexible(
child: Text(indexController
.currentFeature[0]
.properties!["location_name"]))
: const SizedBox(
width: 0.0,
height: 0,
),
],
),
),
],
),
const SizedBox(
height: 8.0,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
const Icon(Icons.roundabout_left),
const SizedBox(
width: 8.0,
),
indexController.currentFeature[0]
.properties!["address"] !=
null &&
(indexController.currentFeature[0]
.properties!["address"] as String)
.isNotEmpty
? getDetails(
context,
"address".tr,
indexController.currentFeature[0]
.properties!["address"] ??
'')
: const SizedBox(
width: 0.0,
height: 0,
),
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
const Icon(Icons.phone),
const SizedBox(
width: 8.0,
),
indexController.currentFeature[0]
.properties!["phone"] !=
null &&
(indexController.currentFeature[0]
.properties!["phone"] as String)
.isNotEmpty
? getDetails(
context,
"telephone".tr,
indexController.currentFeature[0]
.properties!["phone"] ??
'')
: const SizedBox(
width: 0.0,
height: 0,
),
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
const Icon(Icons.email),
const SizedBox(
width: 8.0,
),
indexController.currentFeature[0]
.properties!["email"] !=
null &&
(indexController.currentFeature[0]
.properties!["email"] as String)
.isNotEmpty
? getDetails(
context,
"email".tr,
indexController.currentFeature[0]
.properties!["email"] ??
'')
: const SizedBox(
width: 0.0,
height: 0,
),
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
const Icon(Icons.language),
const SizedBox(
width: 8.0,
),
indexController.currentFeature[0]
.properties!["webcontents"] !=
null &&
(indexController.currentFeature[0]
.properties!["webcontents"] as String)
.isNotEmpty
? getDetails(
context,
"web".tr,
indexController.currentFeature[0]
.properties!["webcontents"] ??
'',
isurl: true)
: const SizedBox(
width: 0.0,
height: 0,
),
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
const SizedBox(
width: 8.0,
),
indexController.currentFeature[0]
.properties!["remark"] !=
null &&
(indexController.currentFeature[0]
.properties!["remark"] as String)
.isNotEmpty
? getDetails(
context,
"remarks".tr,
indexController.currentFeature[0]
.properties!["remark"] ??
'',
isurl: false)
: const SizedBox(
width: 0.0,
height: 0,
),
],
),
),
],
),
)),
const SizedBox(
height: 60.0,
)