diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 55cc87e..0f4625d 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -398,11 +398,11 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 469; + CURRENT_PROJECT_VERSION = 480; DEVELOPMENT_TEAM = UMNEWT25JR; ENABLE_BITCODE = NO; - FLUTTER_BUILD_NAME = 4.5.3; - FLUTTER_BUILD_NUMBER = 469; + FLUTTER_BUILD_NAME = 4.8.0; + FLUTTER_BUILD_NUMBER = 480; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "岐阜ナビ"; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.healthcare-fitness"; @@ -411,7 +411,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 4.5.3; + MARKETING_VERSION = 4.8.0; PRODUCT_BUNDLE_IDENTIFIER = com.dvox.gifunavi; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -539,11 +539,11 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 469; + CURRENT_PROJECT_VERSION = 480; DEVELOPMENT_TEAM = UMNEWT25JR; ENABLE_BITCODE = NO; - FLUTTER_BUILD_NAME = 4.5.3; - FLUTTER_BUILD_NUMBER = 469; + FLUTTER_BUILD_NAME = 4.8.0; + FLUTTER_BUILD_NUMBER = 480; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "岐阜ナビ"; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.healthcare-fitness"; @@ -552,7 +552,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 4.5.3; + MARKETING_VERSION = 4.8.0; PRODUCT_BUNDLE_IDENTIFIER = com.dvox.gifunavi; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -571,11 +571,11 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 469; + CURRENT_PROJECT_VERSION = 480; DEVELOPMENT_TEAM = UMNEWT25JR; ENABLE_BITCODE = NO; - FLUTTER_BUILD_NAME = 4.5.3; - FLUTTER_BUILD_NUMBER = 469; + FLUTTER_BUILD_NAME = 4.8.0; + FLUTTER_BUILD_NUMBER = 480; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "岐阜ナビ"; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.healthcare-fitness"; @@ -584,7 +584,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 4.5.3; + MARKETING_VERSION = 4.8.0; PRODUCT_BUNDLE_IDENTIFIER = com.dvox.gifunavi; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 498aa0d..89993c9 100644 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -59,6 +59,13 @@ ReferencedContainer = "container:Runner.xcodeproj"> + + + + Void in if call.method == "isLocationServiceRunning" { result(self.isLocationServiceRunning()) @@ -19,6 +22,18 @@ import Flutter result(FlutterMethodNotImplemented) } } + */ + + locationServiceChannel.setMethodCallHandler { [weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in + if call.method == "startLocationService" { + //self?.startLocationService() + result(nil) + } else if call.method == "isLocationServiceRunning" { + result(self?.isLocationServiceRunning() ?? false) + } else { + result(FlutterMethodNotImplemented) + } + } locationManager = CLLocationManager() locationManager?.delegate = self diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index cea64eb..e1e9c1f 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -24,8 +24,6 @@ ???? CFBundleVersion $(FLUTTER_BUILD_NUMBER) - FLTEnableImpeller - LSRequiresIPhoneOS NSCameraUsageDescription @@ -38,6 +36,8 @@ このアプリはチェックポイントへのチェックインや走行履歴を記録するために、位置情報にアクセスします。 NSPhotoLibraryUsageDescription 撮影した写真はデバイスのアルバムに保存されます。これにより、不具合時の通過記録を安全に担保することができます。 + NSMicrophoneUsageDescription + このアプリではカメラは使用しますが、マイクの使用は当面行いません。 UIApplicationSupportsIndirectInputEvents LSApplicationCategoryType diff --git a/lib/pages/camera/custom_camera_view.dart b/lib/pages/camera/custom_camera_view.dart index 2f75855..9ac1f05 100644 --- a/lib/pages/camera/custom_camera_view.dart +++ b/lib/pages/camera/custom_camera_view.dart @@ -3,11 +3,13 @@ import 'package:camera/camera.dart'; import 'package:flutter/material.dart'; import 'package:path/path.dart' as path; import 'package:path_provider/path_provider.dart'; +import 'package:rogapp/model/destination.dart'; class CustomCameraView extends StatefulWidget { final Function(String) onImageCaptured; + final Destination? destination; - const CustomCameraView({Key? key, required this.onImageCaptured}) : super(key: key); + const CustomCameraView({Key? key, required this.onImageCaptured, required this.destination}) : super(key: key); @override _CustomCameraViewState createState() => _CustomCameraViewState(); @@ -19,11 +21,13 @@ class _CustomCameraViewState extends State { int _selectedCameraIndex = 0; double _currentScale = 1.0; FlashMode _currentFlashMode = FlashMode.off; + Destination? destination; @override void initState() { super.initState(); _initializeCamera(); + destination = widget.destination; } Future _initializeCamera() async { @@ -98,7 +102,25 @@ class _CustomCameraViewState extends State { return Stack( children: [ - CameraPreview(_controller!), + Padding( + padding: const EdgeInsets.only(top: 60.0), // 上部に60ピクセルのパディングを追加 + child: CameraPreview(_controller!), + ), + Positioned( + bottom: 120.0, + left: 16.0, + right: 16.0, + child: Center( + child: Text( + destination?.tags ?? '', + style: const TextStyle( + color: Colors.white, + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + ), + ), Positioned( bottom: 16.0, left: 16.0, diff --git a/lib/pages/destination/destination_controller.dart b/lib/pages/destination/destination_controller.dart index 9a553d4..33884a0 100644 --- a/lib/pages/destination/destination_controller.dart +++ b/lib/pages/destination/destination_controller.dart @@ -764,6 +764,7 @@ class DestinationController extends GetxController { onImageCaptured: (imagePath) { photos.add(File(imagePath)); }, + destination: destination, ), /* builder: (_) => CameraCamera( @@ -973,7 +974,7 @@ class DestinationController extends GetxController { is_checkin: isCheckin, created_at: DateTime.now().millisecondsSinceEpoch); var res = await db.insertGps(gps_data); - debugPrint("Saved GPS data into DB...:${gps_data}"); + //debugPrint("Saved GPS data into DB...:${gps_data}"); } } catch (err) { print("errr ready gps ${err}"); diff --git a/lib/pages/history/history_page.dart b/lib/pages/history/history_page.dart index d01b872..df05902 100644 --- a/lib/pages/history/history_page.dart +++ b/lib/pages/history/history_page.dart @@ -41,7 +41,7 @@ class _HistoryPageState extends State { } else if (snapshot.hasData) { final dests = snapshot.data; if (dests!.isNotEmpty) { - debugPrint("----- history -----"); + debugPrint("----- 通過履歴表示 -----"); return SizedBox( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height, diff --git a/lib/pages/permission/permission.dart b/lib/pages/permission/permission.dart index b1baed8..190689f 100644 --- a/lib/pages/permission/permission.dart +++ b/lib/pages/permission/permission.dart @@ -21,13 +21,13 @@ class PermissionController { */ static Future checkStoragePermission() async { - debugPrint("(gifunavi)== checkStoragePermission =="); + //debugPrint("(gifunavi)== checkStoragePermission =="); final storagePermission = await Permission.storage.status; return storagePermission == PermissionStatus.granted; } static Future requestStoragePermission() async { - debugPrint("(gifunavi)== requestStoragePermission =="); + //debugPrint("(gifunavi)== requestStoragePermission =="); final storagePermission = await Permission.storage.request(); if (storagePermission == PermissionStatus.granted) { @@ -43,26 +43,26 @@ class PermissionController { } static Future checkLocationBasicPermission() async { - debugPrint("(gifunavi)== checkLocationBasicPermission =="); + //debugPrint("(gifunavi)== checkLocationBasicPermission =="); final locationPermission = await Permission.location.status; return locationPermission == PermissionStatus.granted; } static Future checkLocationWhenInUsePermission() async { - debugPrint("(gifunavi)== checkLocationWhenInUsePermission =="); + //debugPrint("(gifunavi)== checkLocationWhenInUsePermission =="); final whenInUsePermission = await Permission.locationWhenInUse.status; return whenInUsePermission == PermissionStatus.granted; } static Future checkLocationAlwaysPermission() async { - debugPrint("(gifunavi)== checkLocationAlwaysPermission =="); + //debugPrint("(gifunavi)== checkLocationAlwaysPermission =="); final alwaysPermission = await Permission.locationAlways.status; return alwaysPermission == PermissionStatus.granted; } static bool isBasicPermission=false; static Future requestLocationBasicPermissions() async { - debugPrint("(gifunavi)== requestLocationBasicPermissions =="); + //debugPrint("(gifunavi)== requestLocationBasicPermissions =="); try{ if(!isBasicPermission){ isBasicPermission=true; @@ -84,7 +84,7 @@ class PermissionController { static bool isRequestedWhenInUsePermission = false; static Future requestLocationWhenInUsePermissions() async { - debugPrint("(gifunavi)== requestLocationWhenInUsePermissions =="); + //debugPrint("(gifunavi)== requestLocationWhenInUsePermissions =="); try{ if(!isRequestedWhenInUsePermission){ @@ -116,7 +116,7 @@ class PermissionController { static bool isRequestedAlwaysPermission = false; static Future requestLocationAlwaysPermissions() async { - debugPrint("(gifunavi)== requestLocationAlwaysPermissions =="); + //debugPrint("(gifunavi)== requestLocationAlwaysPermissions =="); try { if( !isRequestedAlwaysPermission ){ diff --git a/lib/widgets/bottom_sheet_new.dart b/lib/widgets/bottom_sheet_new.dart index b4f33f5..e9b9804 100644 --- a/lib/widgets/bottom_sheet_new.dart +++ b/lib/widgets/bottom_sheet_new.dart @@ -75,7 +75,7 @@ class BottomSheetNew extends GetView { } } else { GeoJSONFeature gf = indexController.currentFeature[0]; - print("=== photo sss ${gf.properties!["photos"]}"); + //print("=== photo sss ${gf.properties!["photos"]}"); if (gf.properties!["photos"] == null || gf.properties!["photos"] == "") { return const Image(image: AssetImage('assets/images/empty_image.png')); } else { @@ -170,6 +170,7 @@ class BottomSheetNew extends GetView { (destination.cp == -1 || destination.cp == 0 ) && destinationController.rogainingCounted.value == false) { // ゲームが始まってなければ + // ロゲ開始している && (開始地点から100m以内 又は 電波が弱い) && CP番号が 1 or 0 && rogainingCounted==false(どこにもチェックインしていない) なら return Obx(() { final isInRog = destinationController.isInRog.value; @@ -196,6 +197,7 @@ class BottomSheetNew extends GetView { // ダイアログをキャンセルした場合はボタンを再度有効化 destinationController.isInRog.value = false; Get.back(); // Close the dialog + Get.back(); // Close the bottom sheet }, ), TextButton( @@ -215,7 +217,8 @@ class BottomSheetNew extends GetView { saveGameState(); await ExternalService().startRogaining(); - Get.back(); // Close the dialog and potentially navigate away + Get.back(); + Get.back();// Close the dialog and potentially navigate away }, ), ], @@ -240,7 +243,11 @@ class BottomSheetNew extends GetView { (destination.cp == 0 || destination.cp == -2 || destination.cp == -1) && // (destination.cp == 0 || destination.cp == -2 ) && DestinationController.ready_for_goal == true) { + + // ready_for_goal && (開始地点から500m以内 又は 電波が弱い) && CP番号が -1 or -2 or 0 && rogainingCounted==true なら + // Goal ボタン //goal + return ElevatedButton( style: ElevatedButton.styleFrom(backgroundColor: Colors.red), onPressed: destinationController.rogainingCounted.value == true && @@ -268,8 +275,10 @@ class BottomSheetNew extends GetView { "finish_rogaining".tr, style: TextStyle(color: Colors.white), )); + } else if (distanceToDest <= destinationController.getForcedChckinDistance(destination)) { + // cpごとの強制チェックイン以内にいれば //start return ElevatedButton( style: ElevatedButton.styleFrom( @@ -281,6 +290,8 @@ class BottomSheetNew extends GetView { try{ destinationController.isCheckingIn.value = true; // ここを追加 Get.back(); + Get.back(); + await Future.delayed(Duration(milliseconds: 500)); await destinationController.callforCheckin(destination); destinationController.isCheckingIn.value = false; } catch (e) { @@ -296,62 +307,6 @@ class BottomSheetNew extends GetView { print('Error processing check-in: $e'); } }, -/* - // Check conditions to show confirmation dialog - if (destinationController.isInRog.value == false && - (destinationController.distanceToStart() <= 500 || destinationController.isGpsSignalWeak() ) && //追加 Akira 2024-4-5 - destination.cp == -1 && - destinationController.rogainingCounted.value == false) { - print("counted ${destinationController.rogainingCounted.value}"); - - // Show confirmation dialog - Get.dialog( - AlertDialog( - title: const Text("確認"), //confirm - content: const Text( - "ロゲを開始すると、今までのロゲデータが全てクリアされます。本当に開始しますか?"), //are you sure - actions: [ - TextButton( - child: const Text("いいえ"), //no - onPressed: () { - Get.back(); // Close the dialog - }, - ), - TextButton( - child: const Text("はい"), //yes - onPressed: () async { - // Clear data and start game logic here - destinationController.isInRog.value = true; - destinationController.resetRogaining(); - 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 - ); - } else if (destinationController.isInRog.value == true && - destination.cp != -1) { - //print("counted ${destinationController.rogainingCounted.value}"); - // Existing logic for other conditions - - Get.back(); - await destinationController.callforCheckin(destination); - } else { - return; - } - }, - - */ - child: Text( destination.cp == -1 && destinationController.isInRog.value == false && @@ -418,23 +373,23 @@ class BottomSheetNew extends GetView { destinationController.currentLat, destinationController.currentLon), LatLng(cdest.lat!, cdest.lon!)); - LogManager().addLog("Distance from current point : $distanceToDest"); - LogManager().addLog( + debugPrint("Distance from current point : $distanceToDest"); + debugPrint( "forced distance for point : ${destinationController.getForcedChckinDistance(destination)}"); - LogManager().addLog( + debugPrint( "current point : ${destinationController.currentLat}, ${destinationController.currentLon} - ${DateTime.now().hour}:${DateTime.now().minute}:${DateTime.now().second}:${DateTime.now().microsecond}"); - LogManager().addLog("Checkin radius : ${destination.checkin_radious}"); - LogManager().addLog("--${destination.cp}--"); + debugPrint("Checkin radius : ${destination.checkin_radious}"); + debugPrint("--${destination.cp}--"); return SingleChildScrollView( child: Column( children: [ - Padding( + Padding( // 1行目 padding: const EdgeInsets.all(8.0), child: Row( children: [ - MaterialButton( + MaterialButton( // キャンセルボタン onPressed: () { Get.back(); }, @@ -447,7 +402,7 @@ class BottomSheetNew extends GetView { size: 14, ), ), - Expanded( + Expanded( // チェックポイント番号+ポイント名 child: Container( alignment: Alignment.centerLeft, child: Obx(() => Text( @@ -462,7 +417,7 @@ class BottomSheetNew extends GetView { ], ), ), - Row( + Row( // 2行目 チェックポイント写真 children: [ Expanded( child: SizedBox( @@ -471,84 +426,89 @@ class BottomSheetNew extends GetView { )), ], ), - Obx(() => Padding( + Obx(() => Padding( // 3行め ボタン類 padding: const EdgeInsets.all(8.0), child: Column( children: [ - Row( + Row( // 開始・ゴールボタン mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ // Finish or Goal - (destination.cp == -1 || destination.cp == 0) + (destination.cp == -1 || destination.cp == 0 || destination.cp == -2) ? getActionButton(context, destination) - : Container(), + : Container(), // 一般CPは空 ], ), - Row( + Row( // 2列目 チェックインボタン mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ //checkin or remove checkin - destinationController.isInRog.value == true && destination.cp != 0 && destination.cp != -1 && destination.cp != -2 + destinationController.isInRog.value == true + && (distanceToDest <= + destinationController.getForcedChckinDistance(destination) || destination.checkin_radious==-1 ) + && 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 + ? ElevatedButton( // まだチェックインしていなければ、チェックインボタンを表示 + style: ElevatedButton.styleFrom( + backgroundColor: Colors.red), + onPressed: () async { + try { + Get.back(); + + 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) @@ -557,6 +517,7 @@ class BottomSheetNew extends GetView { onPressed: () async { if (destinationController.isRouteShowing.value) { destinationController.clearRoute(); + Get.back(); } else { Get.back(); Position position = @@ -575,14 +536,16 @@ class BottomSheetNew extends GetView { .destinationMatrixFromCurrentPoint([ds, tp]); } }, - child: Text( + child: Text( //ルート表示 or ルート消去 destinationController.isRouteShowing.value ? "cancel_route".tr : "go_here".tr, style: TextStyle( color: Theme.of(context).colorScheme.onPrimary), - ))), + ) + ) + ), ], ), Row( diff --git a/pubspec.yaml b/pubspec.yaml index 4d7478f..fcaf28a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -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. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 4.5.3+469 +version: 4.8.0+480 environment: sdk: ">=3.2.0 <4.0.0"