From 33bd2b97a118bb9a98bfb642b0ff49720effb575 Mon Sep 17 00:00:00 2001 From: Akira Date: Sat, 20 Apr 2024 12:34:49 +0900 Subject: [PATCH] =?UTF-8?q?#2832=20=E3=81=BE=E3=81=A7=E8=A7=A3=E6=B1=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ios/Runner.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- lib/model/destination.dart | 13 +- lib/pages/camera/camera_page.dart | 219 ++++++++++++++- .../destination/destination_controller.dart | 252 ++++++++++++------ .../destination_map/destination_map_page.dart | 12 +- lib/pages/history/history_page.dart | 2 +- lib/pages/index/index_page.dart | 2 +- lib/pages/search/search_page.dart | 11 +- lib/pages/subperf/subperf_page.dart | 1 + lib/utils/location_controller.dart | 41 +-- lib/widgets/bottom_sheet_new.dart | 39 ++- lib/widgets/destination_widget.dart | 15 +- lib/widgets/gps_status.dart | 2 +- lib/widgets/list_widget.dart | 12 +- lib/widgets/map_widget.dart | 30 ++- pubspec.lock | 8 + pubspec.yaml | 1 + 18 files changed, 517 insertions(+), 147 deletions(-) diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 2ed4b50..8af03db 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -156,7 +156,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1430; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index a6b826d..5e31d3d 100644 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ json) { bool selec = json['selected'] == 0 ? false : true; bool checkin = json['checkedin'] == 0 ? false : true; bool forcedCheckin = json['forced_checkin'] == 0 ? false : true; - + bool useQrCode = json['use_qr_code'] == 1 ? true : false; //print("-----tags model----- ${json}"); return Destination( @@ -93,7 +96,8 @@ class Destination { buypoint_image: json["buypoint_image"], forced_checkin: forcedCheckin, recipt_times: json["recipt_times"], - tags: json["tags"]); + tags: json["tags"], + use_qr_code: useQrCode); } Map toMap() { @@ -127,7 +131,8 @@ class Destination { 'buypoint_image': buypoint_image, 'forced_checkin': forcedCheckin, 'recipt_times': recipt_times, - 'tags': tags + 'tags': tags, + 'use_qr_code': use_qr_code }; } } diff --git a/lib/pages/camera/camera_page.dart b/lib/pages/camera/camera_page.dart index 8e015b5..7ad678f 100644 --- a/lib/pages/camera/camera_page.dart +++ b/lib/pages/camera/camera_page.dart @@ -8,39 +8,103 @@ import 'package:rogapp/pages/destination/destination_controller.dart'; import 'package:rogapp/pages/index/index_controller.dart'; import 'package:rogapp/services/external_service.dart'; import 'package:rogapp/utils/const.dart'; +import 'package:qr_code_scanner/qr_code_scanner.dart'; +// 関数 getTagText は、特定の条件に基づいて文字列から特定の部分を抽出し、返却するためのものです。 +// 関数は2つのパラメータを受け取り、条件分岐を通じて結果を返します。 +// +// この関数は、タグのリスト(空白を含む文字列)を適切に解析し、条件に応じて特定のタグを抽出するために設計されています。 +// 異なる種類の空白文字(半角、全角)で異なる分割を行い、与えられた条件(isRecept)に応じて適切なタグを選択して返却します。 +// String getTagText(bool isRecept, String? tags) { + // bool isRecept: 真偽値を受け取り、この値によって処理の分岐が行われます。 + // String? tags: オプショナルな文字列(null が許容される)。空白文字を含む可能性のあるタグのリストを表します。 + + // 空のチェック: + // tags が null または空文字列 ("") の場合、何も含まれていないことを意味し、関数はただちに空文字列を返します。 + // if (tags == null || tags.isEmpty) { return ""; } + + // タグの分割: + // tags が空ではない場合、文字列を空白文字で分割します。 + // ここで2種類の空白文字(半角 " " と全角 " ")に対応するため、2回分割を行っています。 + // tts: 半角スペース " " で分割した結果のリスト。 + // ttt: 全角スペース " " で分割した結果のリスト。 + // List tts = tags.split(" "); List ttt = tags.split(" "); + + // 条件分岐: + // isRecept の値によって、処理が分岐します。 + // if (isRecept) { + // isRecept が true の場合: + // 全角スペースで分割した結果 (ttt) の長さが半角スペースで分割した結果 (tts) の長さより大きく、 + // かつ ttt が1つ以上の要素を持つ場合、ttt[1] (全角スペースで分割後の2番目の要素)を返します。 if (ttt.length > tts.length && ttt.length > 1) { return ttt[1]; } } if (!isRecept) { + // isRecept が false の場合: + // 全角スペースで分割したリストが半角スペースで分割したリストよりも長い場合、ttt[0] (全角スペースで分割後の最初の要素)を返します。 + // 上記の条件に当てはまらない場合、半角スペースで分割したリストの最初の要素 tts[0] を返します。 + // if (ttt.length > tts.length && ttt.length > 1) { return ttt[0]; } } if (!isRecept) { + // 最終的な返却: + // 上記の条件に何も該当しない場合(主に isRecept が true であり、全角スペースの条件に該当しない場合)、空文字列 "" を返します。 return tts[0]; } return ""; } // 要修正:画像の読み込みエラーが発生した場合のエラーハンドリングが不十分です。エラーメッセージを表示するなどの処理を追加してください。 +// getDisplayImage は、Destination オブジェクトを受け取り、特定の条件に基づいて表示する画像を返す機能を持っています。 +// Flutterの Image ウィジェットを使用して、適切な画像を表示します。 +// +// この関数は、提供された Destination オブジェクトに基づいて適切な画像を動的に選択し、 +// その画像を表示するための Image ウィジェットを生成します。 +// デフォルトの画像、完全なURL、またはサーバーURLと組み合わされた画像パスを使用して、条件に応じた画像の取得を試みます。 +// また、エラー発生時にはデフォルト画像にフォールバックすることでユーザー体験を向上させます。 // Image getDisplayImage(Destination destination) { + // Destination destination: これは Destination クラスのインスタンスで、 + // CheckPointのデータを持っているオブジェクトです。 + // このクラスには少なくとも phone と photos というプロパティが含まれている + // + + // サーバーURLの取得: + // serverUrl 変数には ConstValues.currentServer() メソッドから現在のサーバーのURLが取得されます。 + // これは画像を取得する際の基本URLとして使用される可能性があります。 + // String serverUrl = ConstValues.currentServer(); + // デフォルト画像の設定: + // img 変数にはデフォルトの画像が設定されます。 + // これは、アセットから "assets/images/empty_image.png" をロードするための Image.asset コンストラクタを使用しています。 + // Image img = Image.asset("assets/images/empty_image.png"); + + // 電話番号のチェック: + // destination.phone が null の場合、関数は img(デフォルト画像)を返します。 + // これは、phone プロパティが画像URLの代用として何らかの形で使用されることを示唆していますが、 + // それが null であればデフォルト画像を使用するという意味です。 + // if (destination.phone == null) { return img; } + // 画像URLの構築と画像の返却: + // destination.photos が http を含む場合、これはすでに完全なURLとして提供されていることを意味します。 + // このURLを NetworkImage コンストラクタに渡し、Image ウィジェットを生成して返します。 + // そうでない場合は、serverUrl と destination.photos を組み合わせたURLを生成して NetworkImage に渡し、画像を取得します。 + // if (destination.photos!.contains('http')) { return Image( image: NetworkImage( @@ -64,16 +128,51 @@ Image getDisplayImage(Destination destination) { } } +// getFinishImage は、ImageProvider 型のオブジェクトを返す関数で、Flutterアプリケーションで使用される画像を提供します。 +// この関数は、DestinationController というクラスのインスタンスに依存しており、特定の状態に基づいて適切な画像を返します。 +// +// この関数は、アプリケーションの現在の状態に依存して動的に画像を提供します。 +// DestinationController の photos リストに基づいて画像を選択し、リストが空の場合はデフォルトの画像を提供します。 +// これにより、画像の動的な管理が可能になり、ユーザーインターフェースの柔軟性が向上します。 +// また、ImageProvider クラスを使用することで、 +// 画像の具体的な取得方法(ファイルからの読み込みやアセットからのロードなど)を抽象化し、 +// Flutterの Image ウィジェットで直接使用できる形式で画像を返します。 +// ImageProvider getFinishImage() { + + // DestinationControllerの取得: + // destinationController は Get.find() を使用して取得されます。 + // これは、GetXというFlutterの状態管理ライブラリの機能を使用して、 + // 現在のアプリケーションコンテキストから DestinationController タイプのインスタンスを取得するものです。 + // これにより、アプリケーションの他の部分で共有されている DestinationController の現在のインスタンスにアクセスします。 + // DestinationController destinationController = Get.find(); + + // 画像の決定: + // destinationController.photos リストが空でないかどうかをチェックします。 + // このリストは、ファイルパスまたは画像リソースへの参照を含む可能性があります。 + // if (destinationController.photos.isNotEmpty) { + // リストが空でない場合、最初の要素 (destinationController.photos[0]) が使用されます。 + // FileImage コンストラクタを使用して、このパスから ImageProvider を生成します。 + // これは、ローカルファイルシステム上の画像ファイルを参照するためのものです。 + // return FileImage(destinationController.photos[0]); + } else { + // destinationController.photos が空の場合、 + // AssetImage を使用してアプリケーションのアセットからデフォルトの画像('assets/images/empty_image.png')を + // ロードします。これはビルド時にアプリケーションに組み込まれる静的なリソースです。 + // return const AssetImage('assets/images/empty_image.png'); } } +// getReceiptImage は、ImageProvider 型を返す関数です。 +// この関数は DestinationController オブジェクトに依存しており、条件に応じて特定の画像を返します。 +// この関数は getFinishImage 関数と非常に似ており、ほぼ同じロジックを使用していますが、返されるデフォルトの画像が異なります。 +// ImageProvider getReceiptImage() { DestinationController destinationController = Get.find(); @@ -84,12 +183,21 @@ ImageProvider getReceiptImage() { } } +// CameraPageクラスは、目的地に応じて適切なカメラ機能とアクションボタンを提供します。 +// 手動チェックイン、ゴール撮影、購入ポイント撮影など、様々なシナリオに対応しています。 +// また、ロゲイニングが開始されていない場合は、StartRogainingウィジェットを表示して、ユーザーにロゲイニングの開始を促します。 +// CameraPageクラスは、IndexControllerとDestinationControllerを使用して、 +// 現在の状態や目的地の情報を取得し、適切なUIを構築します。 +// また、写真の撮影や購入ポイントの処理など、様々な機能を提供しています。 +// class CameraPage extends StatelessWidget { - bool? manulaCheckin = false; - bool? buyPointPhoto = false; - Destination destination; - Destination? dbDest; - String? initImage; + bool? manulaCheckin = false; // 手動チェックインを示すブール値(デフォルトはfalse) + bool? buyPointPhoto = false; // 購入ポイントの写真を示すブール値(デフォルトはfalse) + Destination destination; // 目的地オブジェクト + Destination? dbDest; // データベースから取得した目的地オブジェクト(オプショナル) + String? initImage; // 初期画像のパス(オプショナル) + bool? buyQrCode = false; + CameraPage( {Key? key, required this.destination, @@ -106,11 +214,15 @@ class CameraPage extends StatelessWidget { Timer? timer; + // 現在の状態に基づいて、適切なアクションボタンを返します。 // 要修正:エラーハンドリングが不十分です。例外が発生した場合の処理を追加することをお勧めします。 // Widget getAction(BuildContext context) { + //print("----cccheckin is --- ${dbDest?.checkedin} ----"); + if (manulaCheckin == true) { + // manulaCheckinがtrueの場合は、撮影ボタンとチェックインボタンを表示します。 return Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.spaceAround, @@ -142,6 +254,7 @@ class CameraPage extends StatelessWidget { if (destinationController.isAtGoal.value && destinationController.isInRog.value && destination.cp == -1) { + // isAtGoalがtrueで、isInRogがtrue、destination.cpが-1の場合は、ゴール用の撮影ボタンとゴール完了ボタンを表示します。 //goal return Row( mainAxisAlignment: MainAxisAlignment.spaceAround, @@ -215,10 +328,12 @@ class CameraPage extends StatelessWidget { : Container()) ], ); + } else if (destinationController.isInRog.value && dbDest?.checkedin != null && destination.cp != -1 && dbDest?.checkedin == true) { + // isInRogがtrueで、dbDest?.checkedinがtrue、destination.cpが-1以外の場合は、購入ポイントの撮影ボタンと完了ボタンを表示します。 //make buypoint image return Row( mainAxisAlignment: MainAxisAlignment.spaceAround, @@ -245,11 +360,49 @@ class CameraPage extends StatelessWidget { Get.snackbar("お買い物加点を行いました。", "${destination.sub_loc_id} : ${destination.name}"); }, - child: const Text("レシートの写真を撮る")) + child: const Text("レシートの写真を撮ってください")) + : Container()) + ], + ); + + } else if (destinationController.isInRog.value && + dbDest?.checkedin != null && + destination.cp != -1 && + destination.use_qr_code == true && + dbDest?.checkedin == true) { + // isInRogがtrueで、dbDest?.checkedinがtrue、destination.cpが-1以外、qrCode == true の場合は、 + // QRCode 撮影ボタンを表示 + return Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Obx(() => ElevatedButton( + onPressed: () { + destinationController.openCamera(context, destination); + }, + child: destinationController.photos.isNotEmpty + ? const Text("再QR読込") + : const Text("QR読込"))), + Obx(() => destinationController.photos.isNotEmpty + ? ElevatedButton( + style: ElevatedButton.styleFrom(backgroundColor: Colors.red), + onPressed: () async { + // print( + // "##### current destination ${indexController.currentDestinationFeature[0].sub_loc_id} #######"); + 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}"); + }, + child: const Text("QRコードを読み取ってください")) : Container()) ], ); } else { + // それ以外の場合は、撮影ボタンとチェックインボタンを表示します。 return Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ @@ -294,9 +447,15 @@ class CameraPage extends StatelessWidget { Widget build(BuildContext context) { //print("---- photos ${destination.photos} ----"); if (buyPointPhoto == true) { + // buyPointPhotoがtrueの場合は、BuyPointCameraウィジェットを返します。 //print("--- buy point camera ${destination.toString()}"); return BuyPointCamera(destination: destination); + }else if(destination.use_qr_code){ + return QRCodeScannerPage(destination: destination); } else if (destinationController.isInRog.value) { + // isInRogがtrueの場合は、カメラページのUIを構築します。 + // AppBarには、目的地の情報を表示します。 + // ボディには、目的地の画像、タグ、アクションボタンを表示します。 //print("-----tags camera page----- ${destination.tags}"); //print("--- in normal camera ${destination.toString()}"); return Scaffold( @@ -361,11 +520,15 @@ class CameraPage extends StatelessWidget { ), ); } else { + // isInRogがfalseの場合は、StartRogainingウィジェットを返します。 return StartRogaining(); } } } +// ロゲイニングが開始されていない場合に表示されるウィジェットです。 +// "You have not started rogaining yet."というメッセージと、戻るボタンを表示します。 +// class StartRogaining extends StatelessWidget { StartRogaining({Key? key}) : super(key: key); @@ -404,6 +567,12 @@ class StartRogaining extends StatelessWidget { } } +// 購入ポイントの写真撮影用のウィジェットです。 +// 目的地の画像、タグ、撮影ボタン、完了ボタン、購入なしボタンを表示します。 +// 撮影ボタンをタップすると、カメラが起動します。 +// 完了ボタンをタップすると、購入ポイントの処理が行われます。 +// 購入なしボタンをタップすると、購入ポイントがキャンセルされます。 +// class BuyPointCamera extends StatelessWidget { BuyPointCamera({Key? key, required this.destination}) : super(key: key); @@ -521,3 +690,41 @@ class BuyPointCamera extends StatelessWidget { ); } } + + +class QRCodeScannerPage extends StatefulWidget { + @override + _QRCodeScannerPageState createState() => _QRCodeScannerPageState(); +} + +class _QRCodeScannerPageState extends State { + final GlobalKey qrKey = GlobalKey(debugLabel: 'QR'); + QRViewController? controller; + + @override + void dispose() { + controller?.dispose(); + super.dispose(); + } + + void _onQRViewCreated(QRViewController controller) { + this.controller = controller; + controller.scannedDataStream.listen((scanData) { + // QRコードのデータを処理する + debugPrint("scan data = ${scanData}"); + String? qrCodeData = scanData.code; + // qrCodeDataを使用してチェックポイントの処理を行う + // 例えば、qrCodeDataからCPのIDと店名を取得し、加点処理を行う + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: QRView( + key: qrKey, + onQRViewCreated: _onQRViewCreated, + ), + ); + } +} \ No newline at end of file diff --git a/lib/pages/destination/destination_controller.dart b/lib/pages/destination/destination_controller.dart index 1eaa2ac..d35f6b1 100644 --- a/lib/pages/destination/destination_controller.dart +++ b/lib/pages/destination/destination_controller.dart @@ -24,7 +24,7 @@ import 'package:rogapp/services/perfecture_service.dart'; import 'package:rogapp/utils/database_gps.dart'; import 'package:rogapp/utils/database_helper.dart'; import 'package:rogapp/utils/location_controller.dart'; -import 'package:rogapp/widgets/bottom_sheets/bottom_sheet_normal_point.dart'; +import 'package:rogapp/widgets/bottom_sheet_new.dart'; import 'dart:async'; import 'package:modal_bottom_sheet/modal_bottom_sheet.dart'; @@ -201,18 +201,33 @@ class DestinationController extends GetxController { } // 指定された目的地の位置情報に基づいてタイマーを開始する関数です。 + // CP情報(fs)と現在位置からCPまでの距離distance を引数として渡します。 // Future startTimerLocation(GeoJSONFeature fs, double distance) async { //print("---- in startTimer ----"); // print("---- is in rog is $is_in_rog ----"); + double checkinRadious = fs.properties!['checkin_radius'] ?? double.infinity; + // CPのcheckin_radiusを取得し、checkinRadius に代入。値がなければinfinityとする。 + if (checkinRadious >= distance) { + // checkinRadious以内に入ったら、 + indexController.currentFeature.clear(); + // indexController.currentFeatureを空にします。 + Destination d = festuretoDestination(fs); + // festuretoDestination(fs)を呼び出し、GeoJSONFeatureオブジェクトfsからDestinationオブジェクトdを作成します。 + // print("----- destination lenght is ${destinations.length} -----"); + indexController.currentFeature.add(fs); + // indexController.currentFeatureにfsを追加します。 + //print("---- before calling startTimer ----"); await startTimer(d, distance); + // startTimer(d, distance)を非同期で呼び出し、その完了を待機します。 + return; } } @@ -227,43 +242,51 @@ class DestinationController extends GetxController { // // 要検討:エラーが発生した場合のエラーハンドリングを追加し、適切なメッセージを表示することを検討してください。 // + // 引数:CPオブジェクトと現在地からCPまでの距離を渡す。 + // Future startTimer(Destination d, double distance) async { //print("=== passed dest is ${d.location_id} ${d.checkedin} ===="); skipGps = true; - //print("---- in startTimer ----"); + //debugPrint("---- in startTimer ----"); DatabaseHelper db = DatabaseHelper.instance; List ds = await db.getDestinationByLatLon(d.lat!, d.lon!); + //指定位置のオブジェクトのリストを取得。 Destination? dss; if (ds.isNotEmpty) { - dss = ds.first; + dss = ds.first; // 取得したリストが空でない場合、dss変数に最初の要素を代入します。 } - double checkinRadious = d.checkin_radious ?? double.infinity; - bool autoCheckin = d.auto_checkin == 0 ? false : true; - bool buyPoint = dss != null && dss.buy_point != null && dss.buy_point! > 0 + // 変数を計算 + double checkinRadious = d.checkin_radious ?? double.infinity; // 反応半径 + bool autoCheckin = d.auto_checkin == 0 ? false : true; // 自動チェックイン + bool buyPoint = dss != null && dss.buy_point != null && dss.buy_point! > 0 // 買い物ポイント ? true : false; - bool buyPointImageAdded = + bool buyPointImageAdded = // 買い物画像 dss != null && dss.buypoint_image != null ? true : false; - bool buyPointCanceled = + bool buyPointCanceled = // 買い物キャンセル dss != null && dss.buy_point != null && dss.buy_point == 0 ? true : false; - bool locationAlreadyCheckedIn = + bool locationAlreadyCheckedIn = // チェックイン済みか ds.isNotEmpty && ds[0].checkedin == true ? true : false; - bool isuserLoggedIn = indexController.currentUser.isNotEmpty ? true : false; - //make current destination - // print("---- checkin_radious $checkinRadious ----"); - // print("---- distance $distance ----"); - if (checkinRadious >= distance || checkinRadious == -1) { + bool isuserLoggedIn = indexController.currentUser.isNotEmpty ? true : false; // ログイン済みか + + // 初期化。GPS信号が強くても弱くても + if (checkinRadious >= distance || checkinRadious == -1) { // 反応半径内か、-1(=距離を無視) //currentSelectedDestinations.add(d); + // 目的地として登録する。 + //debugPrint("目的地の初期化"); indexController.currentDestinationFeature.clear(); indexController.currentDestinationFeature.add(d); // print( // "---- checked in as ${indexController.currentDestinationFeature[0].checkedin.toString()} ----"); } else { + // ここには来ないのでは? + debugPrint("検出範囲外..."); + // GPS信号が弱い場合でも、チェックインやゴールの処理を続行する // comment out by Akira, 2024-4-5 // skipGps = false; @@ -282,7 +305,7 @@ class DestinationController extends GetxController { ); */ - if (checkinRadious >= lastValidDistance || checkinRadious == -1) { + if (checkinRadious >= lastValidDistance || checkinRadious == -1) { // 反応半径内か、距離無視CPなら indexController.currentDestinationFeature.clear(); indexController.currentDestinationFeature.add(d); } else { @@ -295,11 +318,14 @@ class DestinationController extends GetxController { } } - if (isPhotoShoot.value == true) { - photos.clear(); - if (shouldShowBottomSheet) { + if (isPhotoShoot.value == true) { // 写真撮影するなら ... isPhotoShoot=True にしてる場所がない。 + debugPrint("isPhotoShoot.value == true ... will camera popup"); + photos.clear(); // まず既存の写真をクリア + if (shouldShowBottomSheet) { // ボトムシートを使うべきなら shouldShowBottomSheet = false; - if (d.cp == -1) return; + if (d.cp == -1) return; // CPは開始点なら戻る。 + + // カメラページをポップアップ await showModalBottomSheet( constraints: BoxConstraints.loose(Size(Get.width, Get.height * 0.75)), @@ -316,21 +342,28 @@ class DestinationController extends GetxController { return; } + // 写真撮影モードでない場合 + if (ds.isEmpty) { + debugPrint("* 目的地がない場合 ==> 検知半径=-1の場合"); + // print("----- in location popup cp - ${d.cp}----"); - if (d.cp == -1 && DateTime.now().difference(lastGoalAt).inHours >= 24) { + if ((d.cp == -1 || d.cp==0 ) && DateTime.now().difference(lastGoalAt).inHours >= 24) { + debugPrint("**1: 開始CPで、最後にゴールしてから24時間経過していれば、"); + chekcs = 1; //start // print("~~~~ calling start ~~~~"); - // print("---- in start -----"); - chekcs = 1; + print("---- in start -----"); + + chekcs = 1; // スタート地点で前のゴールから24時間経過 + isInCheckin.value = true; isAtStart.value = true; if (shouldShowBottomSheet) { - shouldShowBottomSheet = false; + shouldShowBottomSheet = false; // bottom_sheet を起動させない。 - if (d.cp == -1||d.cp==-2||d.cp==0) return; - Widget bottomSheet = BottomSheetNormalPoint(destination: d); + Widget bottomSheet = BottomSheetNew(destination: d); await showModalBottomSheet( constraints: @@ -339,25 +372,30 @@ class DestinationController extends GetxController { isScrollControlled: true, builder: ((context) => bottomSheet) ).whenComplete(() { - shouldShowBottomSheet = true; + shouldShowBottomSheet = true; // bottom_sheet 起動許可 skipGps = false; - chekcs = 0; + chekcs = 0; // ボトムシートモード=1, isAtStart.value = false; isInCheckin.value = false; }); } return; + } else if (isInRog.value == true && indexController.rogMode.value == 1 && - d.cp != -1) { + (locationAlreadyCheckedIn==null || locationAlreadyCheckedIn==false) && + d.cp != -1 && d.cp != 0 && d.cp != -2) { + + debugPrint("**2: 標準CP まだチェックインしていない。"); + // print("----- in location popup checkin cp - ${d.cp}----"); - chekcs = 2; + chekcs = 2; // 標準CP + isInCheckin.value = true; if (shouldShowBottomSheet) { shouldShowBottomSheet = false; - if (d.cp == -1||d.cp==-2||d.cp==0) return; - Widget bottomSheet = BottomSheetNormalPoint(destination: d); + Widget bottomSheet = BottomSheetNew(destination: d); await showModalBottomSheet( constraints: @@ -376,36 +414,49 @@ class DestinationController extends GetxController { } } + // 以降、検知範囲にある場合。 + //debugPrint("検知範囲にある場合"); + // print("---- location checkin radious ${d.checkin_radious} ----"); // print("---- already checked in $locationAlreadyCheckedIn ----"); if ((checkinRadious >= distance || checkinRadious == -1) && locationAlreadyCheckedIn == false && isInRog.value == true) { - if (autoCheckin) { + + debugPrint("* 検知範囲または距離無視CPで、ゲーム中でまだチェックインしていない。"); + + if (autoCheckin) { // 自動チェックインなら if (!checkingIn) { + debugPrint("** 自動チェックインの場合"); //print( // "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ make checkin ${d.sub_loc_id}@@@@@@@@@@@"); - makeCheckin(d, true, ""); - if (d.cp != -1) { - rogainingCounted.value = true; + makeCheckin(d, true, ""); // チェックインして + if (d.cp != -1 && d.cp != -2 && d.cp != 0 ) { + rogainingCounted.value = true; // ゴール用チェックイン済み } skipGps = false; } - return; + return; // 戻る + } else { + // それ以外 + debugPrint("* 自動チェックイン以外の場合"); + // print("--- hidden loc ${d.hidden_location} ----"); // ask for checkin if (d.hidden_location != null && - d.hidden_location == 0 && + d.hidden_location == 0 && // 隠しCPフラグ==0 ... 通常CP isInRog.value == true && - d.cp != -1) { + d.cp != -1 && d.cp != -2 && d.cp != 0) { + // 隠しCPの場合、 + debugPrint("**3 通常CPの場合"); + chekcs = 3; isInCheckin.value = true; photos.clear(); // print("--- calling checkin ---"); if (shouldShowBottomSheet) { shouldShowBottomSheet = false; - if (d.cp == -1) return; await showModalBottomSheet( constraints: BoxConstraints.loose(Size(Get.width, Get.height * 0.75)), @@ -422,14 +473,20 @@ class DestinationController extends GetxController { }); } return; - } else if (isInRog.value == true && d.cp != -1) { + + } else if (isInRog.value == true && + (locationAlreadyCheckedIn==null || locationAlreadyCheckedIn==false) && + d.cp != -1 && d.cp != -2 && d.cp != 0) { + // 通常CP + + debugPrint("**4 通常CP以外の場合....どんな場合?"); + chekcs = 4; isInCheckin.value = true; if (shouldShowBottomSheet) { shouldShowBottomSheet = false; - if (d.cp == -1||d.cp==-2||d.cp==0) return; - Widget bottomSheet = BottomSheetNormalPoint(destination: d); + Widget bottomSheet = BottomSheetNew(destination: d); await showMaterialModalBottomSheet( expand: true, @@ -453,13 +510,18 @@ class DestinationController extends GetxController { buyPoint == true && buyPointCanceled == false && isInRog.value == true) { + // チェックイン後で買い物ポイントの場合。 + + debugPrint("**5 チェックイン後で買い物ポイントの場合"); + + chekcs = 5; isInCheckin.value = true; photos.clear(); //print("--- open buy point $buyPointImageAdded ${d.buypoint_image} ----"); if (shouldShowBottomSheet) { shouldShowBottomSheet = false; - if (d.cp == -1) return; + if (d.cp == -1 && d.cp != -2 && d.cp != 0) return; await showModalBottomSheet( constraints: BoxConstraints.loose(Size(Get.width, Get.height * 0.75)), @@ -486,14 +548,17 @@ class DestinationController extends GetxController { // print( // "==== date diff is ${DateTime.now().difference(last_goal_at).inHours} ===="); if (isuserLoggedIn && - d.cp == -1 && + (d.cp == -2 || d.cp == 0 ) && // Goal CP locationAlreadyCheckedIn && skip_10s == false) { //check for rogaining if (isAtGoal.value == false && rogainingCounted.value) { //goal //print("---- in goal -----"); - chekcs = 5; + + debugPrint("**5 ゴールで時計撮影の場合"); + + chekcs = 5; // Goal 時計撮影 isAtGoal.value = true; photos.clear(); if (shouldShowBottomSheet) { @@ -514,18 +579,23 @@ class DestinationController extends GetxController { }); } return; + } else if (isInRog.value == false && indexController.rogMode.value == 1 && DateTime.now().difference(lastGoalAt).inHours >= 24) { //start //print("---- in start -----"); - chekcs = 6; + + debugPrint("**5 スタートの場合で最後のゴールから24時間経過している場合"); + + + chekcs = 6; // start point isAtStart.value = true; if (shouldShowBottomSheet) { shouldShowBottomSheet = false; - if (d.cp == -1||d.cp==-2||d.cp==0) return; - Widget bottomSheet = BottomSheetNormalPoint(destination: d); + if (d.cp != -1 && d.cp != 0) return; + Widget bottomSheet = BottomSheetNew(destination: d); await showModalBottomSheet( constraints: @@ -546,6 +616,7 @@ class DestinationController extends GetxController { } //print("==== _chekcs $chekcs ===="); if (chekcs == 0) { + //debugPrint("いずれにも当てはまらないので、処理スキップ"); skipGps = false; } return; @@ -639,7 +710,7 @@ class DestinationController extends GetxController { // Future callforCheckin(Destination d) async { bool autoCheckin = d.auto_checkin == 0 ? false : true; - //print("---- f- checkin ${d.sub_loc_id} ----"); + print("---- f- checkin ${d.sub_loc_id} ----"); if (autoCheckin) { if (!checkingIn) { makeCheckin(d, true, ""); @@ -717,20 +788,22 @@ class DestinationController extends GetxController { // GPSデータをデータベースに追加する関数です。 // Future addGPStoDB(double la, double ln, {isCheckin = 0}) async { - //print("in addGPStoDB ${indexController.currentUser}"); + //debugPrint("in addGPStoDB ${indexController.currentUser}"); try { GpsDatabaseHelper db = GpsDatabaseHelper.instance; - final team_name = indexController.currentUser[0]["user"]['team_name']; - final event_code = indexController.currentUser[0]["user"]["event_code"]; - GpsData gps_data = GpsData( - id: 0, - team_name: team_name, - event_code: event_code, - lat: la, - lon: ln, - is_checkin: isCheckin, - created_at: DateTime.now().millisecondsSinceEpoch); - var res = await db.insertGps(gps_data); + if(indexController.currentUser.length>0){ + final team_name = indexController.currentUser[0]["user"]['team_name']; + final event_code = indexController.currentUser[0]["user"]["event_code"]; + GpsData gps_data = GpsData( + id: 0, + team_name: team_name, + event_code: event_code, + lat: la, + lon: ln, + is_checkin: isCheckin, + created_at: DateTime.now().millisecondsSinceEpoch); + var res = await db.insertGps(gps_data); + } } catch (err) { print("errr ready gps ${err}"); return; @@ -752,25 +825,28 @@ class DestinationController extends GetxController { game_started = true; try { - indexController.locations[0].features.forEach((fs) async { - GeoJSONMultiPoint mp = fs!.geometry as GeoJSONMultiPoint; - LatLng pt = LatLng(mp.coordinates[0][1], mp.coordinates[0][0]); + // ここで、エラー + if( indexController.locations.length>0 ) { + indexController.locations[0].features.forEach((fs) async { + GeoJSONMultiPoint mp = fs!.geometry as GeoJSONMultiPoint; + LatLng pt = LatLng(mp.coordinates[0][1], mp.coordinates[0][0]); - double latFs = pt.latitude; - double lonFs = pt.longitude; - var distanceFs = const Distance(); - double distFs = distanceFs.as(LengthUnit.Meter, LatLng(latFs, lonFs), - LatLng(currentLat, currentLon)); - Destination des = festuretoDestination(fs); + double latFs = pt.latitude; + double lonFs = pt.longitude; + var distanceFs = const Distance(); + double distFs = distanceFs.as(LengthUnit.Meter, LatLng(latFs, lonFs), + LatLng(currentLat, currentLon)); + Destination des = festuretoDestination(fs); - if (distFs <= des.checkin_radious! && skipGps == false) { - await startTimerLocation(fs, distFs); - // Note: You cannot break out of forEach. If you need to stop processing, you might have to reconsider using forEach. + if (distFs <= des.checkin_radious! && skipGps == false) { + await startTimerLocation(fs, distFs); + // Note: You cannot break out of forEach. If you need to stop processing, you might have to reconsider using forEach. + } + }); + + if (gps_push_started == false) { + unawaited(pushGPStoServer()); } - }); - - if (gps_push_started == false) { - unawaited( pushGPStoServer() ); } //print("--- 123 ---- $skip_gps----"); } catch (e) { @@ -980,14 +1056,13 @@ class DestinationController extends GetxController { //final signalStrength = locationController.getGpsSignalStrength(); okToUseGPS = false; - double prevLat = currentLat; // 直前の位置 + double prevLat = currentLat; // 直前の位置 double prevLon = currentLon; - if (position!=null){ + if (position != null) { currentLat = position.latitude; currentLon = position.longitude; okToUseGPS = true; - } else { // 信号強度が低い場合、最後に取得した高いまたは中程度の位置情報を使用 // 但し、最初から高精度のものがない場合、どうするか? @@ -1012,7 +1087,7 @@ class DestinationController extends GetxController { } } - if (okToUseGPS && position!=null) { + if (okToUseGPS && position != null) { // スタート位置から150m離れたら、ready_for_goal if (distanceToStart() >= 150) { ready_for_goal = true; @@ -1025,20 +1100,31 @@ class DestinationController extends GetxController { LatLng(prevLat, prevLon) ); - Duration difference = lastGPSCollectedTime.difference(DateTime.now()).abs(); + Duration difference = lastGPSCollectedTime.difference(DateTime.now()) + .abs(); // 最後にGPS信号を取得した時刻から10秒以上経過、かつ10m以上経過(普通に歩くスピード) if (difference.inSeconds >= 10 || distanceToDest >= 10) { // print( // "^^^^^^^^ GPS data collected ${DateFormat('kk:mm:ss \n EEE d MMM').format(DateTime.now())}, ^^^ ${position.latitude}, ${position.longitude}"); LogManager().addLog( - "GPS : $currentLat, $currentLon - ${DateTime.now().hour}:${DateTime.now().minute}:${DateTime.now().second}:${DateTime.now().microsecond}"); + "GPS : $currentLat, $currentLon - ${DateTime + .now() + .hour}:${DateTime + .now() + .minute}:${DateTime + .now() + .second}:${DateTime + .now() + .microsecond}"); if (isInRog.value) { await addGPStoDB(position.latitude, position.longitude); lastGPSCollectedTime = DateTime.now(); } } } + } catch(e) { + debugPrint("Error: ${e}"); } finally { /* Akira , 2024-4-5 if (position != null && diff --git a/lib/pages/destination_map/destination_map_page.dart b/lib/pages/destination_map/destination_map_page.dart index ca7e594..fbd5118 100644 --- a/lib/pages/destination_map/destination_map_page.dart +++ b/lib/pages/destination_map/destination_map_page.dart @@ -12,10 +12,10 @@ import 'package:rogapp/pages/destination/destination_controller.dart'; import 'package:rogapp/pages/index/index_controller.dart'; import 'package:rogapp/utils/text_util.dart'; import 'package:rogapp/widgets/base_layer_widget.dart'; -//import 'package:rogapp/widgets/bottom_sheet_new.dart'; -import 'package:rogapp/widgets/bottom_sheets/bottom_sheet_start.dart'; -import 'package:rogapp/widgets/bottom_sheets/bottom_sheet_goal.dart'; -import 'package:rogapp/widgets/bottom_sheets/bottom_sheet_normal_point.dart'; +import 'package:rogapp/widgets/bottom_sheet_new.dart'; +//import 'package:rogapp/widgets/bottom_sheets/bottom_sheet_start.dart'; +//import 'package:rogapp/widgets/bottom_sheets/bottom_sheet_goal.dart'; +//import 'package:rogapp/widgets/bottom_sheets/bottom_sheet_normal_point.dart'; // FlutterMapウィジェットを使用して、地図を表示します。 // IndexControllerから目的地のリストを取得し、マーカーとしてマップ上に表示します。 @@ -70,7 +70,8 @@ class DestinationMapPage extends StatelessWidget { indexController.currentDestinationFeature.add(d); //indexController.getAction(); - Widget bottomSheet; + Widget bottomSheet = BottomSheetNew(destination: d); + /* if (d.cp == -1 || d.cp == 0) { bottomSheet = BottomSheetStart(destination: d); } else if (d.cp == -2 || d.cp == 0) { @@ -78,6 +79,7 @@ class DestinationMapPage extends StatelessWidget { } else { bottomSheet = BottomSheetNormalPoint(destination: d); } + */ showModalBottomSheet( context: Get.context!, diff --git a/lib/pages/history/history_page.dart b/lib/pages/history/history_page.dart index 31ca1c7..26da97d 100644 --- a/lib/pages/history/history_page.dart +++ b/lib/pages/history/history_page.dart @@ -40,7 +40,7 @@ class _HistoryPageState extends State { } else if (snapshot.hasData) { final dests = snapshot.data; if (dests!.isNotEmpty) { - //print("----- history -----"); + debugPrint("----- history -----"); return SizedBox( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height, diff --git a/lib/pages/index/index_page.dart b/lib/pages/index/index_page.dart index b026b48..bf55333 100644 --- a/lib/pages/index/index_page.dart +++ b/lib/pages/index/index_page.dart @@ -109,7 +109,7 @@ class IndexPage extends GetView { return DropdownButton( value: locationController.getSimulatedSignalStrength(), onChanged: (value) { - debugPrint("DropDown changed!"); + //debugPrint("DropDown changed!"); locationController.setSimulatedSignalStrength(value!); }, items: ['low', 'medium', 'high', 'real'] diff --git a/lib/pages/search/search_page.dart b/lib/pages/search/search_page.dart index 406c6f6..a839817 100644 --- a/lib/pages/search/search_page.dart +++ b/lib/pages/search/search_page.dart @@ -6,9 +6,10 @@ import 'package:rogapp/model/destination.dart'; import 'package:rogapp/pages/destination/destination_controller.dart'; import 'package:rogapp/pages/index/index_controller.dart'; import 'package:rogapp/pages/search/search_controller.dart'; -import 'package:rogapp/widgets/bottom_sheets/bottom_sheet_start.dart'; -import 'package:rogapp/widgets/bottom_sheets/bottom_sheet_goal.dart'; -import 'package:rogapp/widgets/bottom_sheets/bottom_sheet_normal_point.dart'; +//import 'package:rogapp/widgets/bottom_sheets/bottom_sheet_start.dart'; +//import 'package:rogapp/widgets/bottom_sheets/bottom_sheet_goal.dart'; +//import 'package:rogapp/widgets/bottom_sheets/bottom_sheet_normal_point.dart'; +import 'package:rogapp/widgets/bottom_sheet_new.dart'; class SearchPage extends StatelessWidget { SearchPage({Key? key}) : super(key: key); @@ -78,7 +79,8 @@ class SearchPage extends StatelessWidget { destinationController.festuretoDestination(suggestion); Get.back(); - Widget bottomSheet; + Widget bottomSheet = BottomSheetNew(destination: des); + /* if (des.cp == -1 || des.cp == 0) { bottomSheet = BottomSheetStart(destination: des); } else if (des.cp == -2 || des.cp == 0) { @@ -86,6 +88,7 @@ class SearchPage extends StatelessWidget { } else { bottomSheet = BottomSheetNormalPoint(destination: des); } + */ showModalBottomSheet( constraints: BoxConstraints.loose(Size(Get.width, Get.height * 0.75)), diff --git a/lib/pages/subperf/subperf_page.dart b/lib/pages/subperf/subperf_page.dart index a1fe067..29dadca 100644 --- a/lib/pages/subperf/subperf_page.dart +++ b/lib/pages/subperf/subperf_page.dart @@ -9,6 +9,7 @@ class SubPerfPage extends StatelessWidget { @override Widget build(BuildContext context) { + debugPrint("SubPerfPage ---->"); return Scaffold( appBar: AppBar( title: const Text("Select Sub Perfecture"), diff --git a/lib/utils/location_controller.dart b/lib/utils/location_controller.dart index 7e79ca1..27da7c9 100644 --- a/lib/utils/location_controller.dart +++ b/lib/utils/location_controller.dart @@ -5,6 +5,7 @@ import 'package:geolocator/geolocator.dart'; import 'package:latlong2/latlong.dart'; //import 'package:rogapp/widgets/debug_widget.dart'; import 'package:flutter_map_location_marker/flutter_map_location_marker.dart'; +import 'package:rogapp/pages/destination/destination_controller.dart'; // LocationControllerクラスは、GetxControllerを継承したクラスであり、位置情報の管理を担当しています。 // LocationControllerは以下の機能を提供しています。 @@ -66,7 +67,7 @@ class LocationController extends GetxController { // シミュレートされた信号強度を取得するための関数 String getSimulatedSignalStrength() { - debugPrint("strength : ${_simulatedSignalStrength.value}"); + //debugPrint("strength : ${_simulatedSignalStrength.value}"); return _simulatedSignalStrength.value; } @@ -269,22 +270,31 @@ class LocationController extends GetxController { isGpsSignalWeak = false; } - final adjustedLocation = adjustCurrentLocation(position); - if (adjustedLocation != null) { - final locationMarkerPosition = LocationMarkerPosition( - latitude: adjustedLocation.latitude, - longitude: adjustedLocation.longitude, - accuracy: position?.accuracy ?? 0, - ); - handleLocationUpdate(locationMarkerPosition); - //locationMarkerPositionStreamController.add(locationMarkerPosition); // 位置データ送信 - } else { - // 位置情報が取得できなかった場合、 - // locationMarkerPositionStreamControllerにnullを追加します。 - locationMarkerPositionStreamController.add(null); // null 送信? - //forceUpdateLocation(Position? position); + final DestinationController destinationController = Get.find(); + // ロゲ開始前、終了後、GPS=low の場合は更新しない。 + // + if (destinationController.isInRog.value && isGpsSignalWeak == false) { + final adjustedLocation = adjustCurrentLocation(position); + if (adjustedLocation != null) { + final locationMarkerPosition = LocationMarkerPosition( + latitude: adjustedLocation.latitude, + longitude: adjustedLocation.longitude, + accuracy: position?.accuracy ?? 0, + ); + handleLocationUpdate(locationMarkerPosition); + //locationMarkerPositionStreamController.add(locationMarkerPosition); // 位置データ送信 + } else { + // 位置情報が取得できなかった場合、 + // locationMarkerPositionStreamControllerにnullを追加します。 + locationMarkerPositionStreamController.add(null); // null 送信? + //forceUpdateLocation(Position? position); + + } + //}else{ + // debugPrint("GPS処理対象外"); } + }, onError: (e) { // エラーが発生した場合、locationMarkerPositionStreamControllerにエラーを追加します。 @@ -335,6 +345,7 @@ class LocationController extends GetxController { void handleLocationUpdate(LocationMarkerPosition? position) async { if (position != null) { + //debugPrint("position = ${position}"); /* currentPosition.value = position; final locationMarkerPosition = LocationMarkerPosition( diff --git a/lib/widgets/bottom_sheet_new.dart b/lib/widgets/bottom_sheet_new.dart index 77507c1..b228b8d 100644 --- a/lib/widgets/bottom_sheet_new.dart +++ b/lib/widgets/bottom_sheet_new.dart @@ -128,14 +128,13 @@ class BottomSheetNew extends GetView { // ボタンがタップされたときの処理も含まれています。 // Widget getActionButton(BuildContext context, Destination destination) { - assert(() { - print("getActionButton ${destinationController.rogainingCounted.value}"); - print("getActionButton ${destinationController.distanceToStart()}"); - print("getActionButton ${destination.cp}"); - print("getActionButton ${DestinationController.ready_for_goal}"); - return true; - }()); + /* + debugPrint("getActionButton ${destinationController.rogainingCounted.value}"); + debugPrint("getActionButton ${destinationController.distanceToStart()}"); + debugPrint("getActionButton ${destination.cp}"); + debugPrint("getActionButton ${DestinationController.ready_for_goal}"); // ...2024-04-03 Akira デバッグモードのみ出力するようにした。 + */ Destination cdest = destinationController .festuretoDestination(indexController.currentFeature[0]); @@ -176,7 +175,7 @@ class BottomSheetNew extends GetView { } : null, child: const Text( - "ロゲイニングを終える", + "ロゲゴール", style: TextStyle(color: Colors.white), )); } else if (distanceToDest <= @@ -186,7 +185,26 @@ class BottomSheetNew extends GetView { style: ElevatedButton.styleFrom( backgroundColor: Theme.of(context).colorScheme.secondary, ), - onPressed: () async { + onPressed: isAlreadyCheckedIn == true + ? null + : () 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'); + } + }, + /* // Check conditions to show confirmation dialog if (destinationController.isInRog.value == false && (destinationController.distanceToStart() <= 500 || destinationController.isGpsSignalWeak() ) && //追加 Akira 2024-4-5 @@ -239,6 +257,7 @@ class BottomSheetNew extends GetView { return; } }, + */ child: Text( destination.cp == -1 && destinationController.isInRog.value == false && @@ -251,7 +270,7 @@ class BottomSheetNew extends GetView { ? "ゲーム中" : destinationController.isInRog.value == true ? "チェックイン" - : "始まっていない", + : "ロゲは始まっていません", style: TextStyle(color: Theme.of(context).colorScheme.onSecondary), ), ); diff --git a/lib/widgets/destination_widget.dart b/lib/widgets/destination_widget.dart index ee72818..481d4c6 100644 --- a/lib/widgets/destination_widget.dart +++ b/lib/widgets/destination_widget.dart @@ -5,9 +5,10 @@ import 'package:rogapp/pages/destination/destination_controller.dart'; import 'package:rogapp/pages/index/index_controller.dart'; import 'package:rogapp/utils/const.dart'; import 'package:rogapp/utils/database_helper.dart'; -import 'package:rogapp/widgets/bottom_sheets/bottom_sheet_start.dart'; -import 'package:rogapp/widgets/bottom_sheets/bottom_sheet_goal.dart'; -import 'package:rogapp/widgets/bottom_sheets/bottom_sheet_normal_point.dart'; +//import 'package:rogapp/widgets/bottom_sheets/bottom_sheet_start.dart'; +//import 'package:rogapp/widgets/bottom_sheets/bottom_sheet_goal.dart'; +//import 'package:rogapp/widgets/bottom_sheets/bottom_sheet_normal_point.dart'; +import 'package:rogapp/widgets/bottom_sheet_new.dart'; import 'package:timeline_tile/timeline_tile.dart'; class DestinationWidget extends StatelessWidget { @@ -147,8 +148,8 @@ class DestinationWidget extends StatelessWidget { @override Widget build(BuildContext context) { - //print( - // "------ destination widget------ ${destinationController.destinationCount.value} ----------"); + print( + "------ destination widget------ ${destinationController.destinationCount.value} ----------"); return Obx(() => Stack( children: [ @@ -194,7 +195,8 @@ class DestinationWidget extends StatelessWidget { // "--- ndexController.currentDestinationFeature ----- ${indexController.currentDestinationFeature[0].name} ----"); //indexController.getAction(); - Widget bottomSheet; + Widget bottomSheet = BottomSheetNew(destination: fs); + /* if (fs.cp == -1 || fs.cp == 0) { bottomSheet = BottomSheetStart(destination: fs); } else if (fs.cp == -2 || fs.cp == 0) { @@ -202,6 +204,7 @@ class DestinationWidget extends StatelessWidget { } else { bottomSheet = BottomSheetNormalPoint(destination: fs); } + */ showModalBottomSheet( constraints: BoxConstraints.loose( diff --git a/lib/widgets/gps_status.dart b/lib/widgets/gps_status.dart index 45dd6cd..a5ea00d 100644 --- a/lib/widgets/gps_status.dart +++ b/lib/widgets/gps_status.dart @@ -20,7 +20,7 @@ class GpsSignalStrengthIndicator extends StatelessWidget { // final LocationController locationController = Get.find(); return Obx(() { String signalStrength = locationController.latestSignalStrength.value; - debugPrint("GpsSignalStrengthIndicator : signalStrength=${signalStrength}"); + //debugPrint("GpsSignalStrengthIndicator : signalStrength=${signalStrength}"); IconData iconData; Color backgroundColor; String text; diff --git a/lib/widgets/list_widget.dart b/lib/widgets/list_widget.dart index a371252..061942e 100644 --- a/lib/widgets/list_widget.dart +++ b/lib/widgets/list_widget.dart @@ -6,9 +6,10 @@ import 'package:rogapp/pages/destination/destination_controller.dart'; import 'package:rogapp/pages/index/index_controller.dart'; import 'package:rogapp/services/maxtrix_service.dart'; import 'package:rogapp/utils/const.dart'; -import 'package:rogapp/widgets/bottom_sheets/bottom_sheet_start.dart'; -import 'package:rogapp/widgets/bottom_sheets/bottom_sheet_goal.dart'; -import 'package:rogapp/widgets/bottom_sheets/bottom_sheet_normal_point.dart'; +//import 'package:rogapp/widgets/bottom_sheets/bottom_sheet_start.dart'; +//import 'package:rogapp/widgets/bottom_sheets/bottom_sheet_goal.dart'; +//import 'package:rogapp/widgets/bottom_sheets/bottom_sheet_normal_point.dart'; +import 'package:rogapp/widgets/bottom_sheet_new.dart'; class ListWidget extends StatefulWidget { const ListWidget({Key? key}) : super(key: key); @@ -102,6 +103,7 @@ class _ListWidgetState extends State { @override Widget build(BuildContext context) { + debugPrint("_ListWidgetState"); return Obx( () => indexController.locations.isNotEmpty ? RefreshIndicator( @@ -130,7 +132,8 @@ class _ListWidgetState extends State { destinationController.festuretoDestination(gf); changeCurrentFeature(gf); - Widget bottomSheet; + Widget bottomSheet = BottomSheetNew(destination: des); + /* if (des.cp == -1 || des.cp == 0) { bottomSheet = BottomSheetStart(destination: des); } else if (des.cp == -2 || des.cp == 0) { @@ -138,6 +141,7 @@ class _ListWidgetState extends State { } else { bottomSheet = BottomSheetNormalPoint(destination: des); } + */ showModalBottomSheet( constraints: BoxConstraints.loose( diff --git a/lib/widgets/map_widget.dart b/lib/widgets/map_widget.dart index 2465e6f..873adfb 100644 --- a/lib/widgets/map_widget.dart +++ b/lib/widgets/map_widget.dart @@ -25,7 +25,8 @@ class MapWidget extends StatefulWidget { State createState() => _MapWidgetState(); } -class _MapWidgetState extends State { +class _MapWidgetState extends State with WidgetsBindingObserver { +//class _MapWidgetState extends State { final IndexController indexController = Get.find(); final DestinationController destinationController = Get.find(); @@ -46,6 +47,11 @@ class _MapWidgetState extends State { _startIdleTimer(); mapController = MapController(); indexController.mapController = mapController; + + // added by Akira + WidgetsBinding.instance.addObserver(this); + _startIdleTimer(); + //_initMarkers(); // indexController.mapController = MapController(initCompleter: mapControllerCompleter); @@ -54,22 +60,37 @@ class _MapWidgetState extends State { @override void dispose() { + WidgetsBinding.instance.removeObserver(this); // added + mapController?.dispose(); _timer?.cancel(); super.dispose(); } + // added by Akira + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + if (state == AppLifecycleState.resumed) { + _resetTimer(); + } + } + + // _centerMapOnUser を10秒間でコール void _startIdleTimer() { _timer = Timer(const Duration(milliseconds: (1000 * 10)), _centerMapOnUser); } + // タイマーをリセットして_startIdleTimer をコール void _resetTimer() { _timer?.cancel(); _startIdleTimer(); } + // マッぷを現在位置を中心にする。 void _centerMapOnUser() { - destinationController.centerMapToCurrentLocation(); + if (mounted) { + destinationController.centerMapToCurrentLocation(); + } } Future _initMarkers() async { @@ -172,8 +193,7 @@ class _MapWidgetState extends State { context: context, isScrollControlled: true, isDismissible: true, - builder: ((context) => BottomSheetNew( - destination: des, isAlreadyCheckedIn: value.isNotEmpty)), + builder: ((context) => BottomSheetNew(destination: des, isAlreadyCheckedIn: value.isNotEmpty)), ).whenComplete(() { destinationController.shouldShowBottomSheet = true; destinationController.skipGps = false; @@ -378,7 +398,7 @@ class _MapWidgetState extends State { stream: locationController.locationMarkerPositionStream, builder: (context, snapshot) { if (!snapshot.hasData) { - print("====== Not display current marker"); + debugPrint("====== Not display current marker"); } return Container(); }, diff --git a/pubspec.lock b/pubspec.lock index 10df839..3170325 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1056,6 +1056,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.1.1" + qr_code_scanner: + dependency: "direct main" + description: + name: qr_code_scanner + sha256: f23b68d893505a424f0bd2e324ebea71ed88465d572d26bb8d2e78a4749591fd + url: "https://pub.dev" + source: hosted + version: "1.0.1" queue: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index c128997..47eceab 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -86,6 +86,7 @@ dependencies: image_gallery_saver: ^2.0.3 flutter_riverpod: ^2.5.1 http: ^1.1.0 + qr_code_scanner: ^1.0.1 flutter_icons: android: true