2 Commits

18 changed files with 518 additions and 148 deletions

View File

@ -156,7 +156,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1430;
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -30,6 +30,8 @@ class Destination {
int recipt_times = 0;
String? tags;
bool use_qr_code = false; // QR code を使用するかどうか。default=false
Destination(
{this.name,
this.address,
@ -57,13 +59,14 @@ class Destination {
this.buypoint_image,
this.forced_checkin = false,
this.recipt_times = 0,
this.tags});
this.tags,
this.use_qr_code = false});
factory Destination.fromMap(Map<String, dynamic> 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<String, dynamic> 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
};
}
}

View File

@ -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<String> tts = tags.split(" ");
List<String> 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<DestinationController>() を使用して取得されます。
// これは、GetXというFlutterの状態管理ライブラリの機能を使用して、
// 現在のアプリケーションコンテキストから DestinationController タイプのインスタンスを取得するものです。
// これにより、アプリケーションの他の部分で共有されている DestinationController の現在のインスタンスにアクセスします。
//
DestinationController destinationController =
Get.find<DestinationController>();
// 画像の決定:
// 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<DestinationController>();
@ -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<QRCodeScannerPage> {
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,
),
);
}
}

View File

@ -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<void> 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<void> 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<Destination> 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で、最後にゴールしてから時間経過していれば、");
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<void> 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, "");
@ -692,7 +763,7 @@ class DestinationController extends GetxController {
rogainingCounted.value = true;
chekcs = 0;
isInCheckin.value = false;
Get.back();
//Get.back();
});
} else {
skipGps = false;
@ -717,20 +788,22 @@ class DestinationController extends GetxController {
// GPSデータをデータベースに追加する関数です。
//
Future<void> 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 &&

View File

@ -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!,

View File

@ -40,7 +40,7 @@ class _HistoryPageState extends State<HistoryPage> {
} 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,

View File

@ -109,7 +109,7 @@ class IndexPage extends GetView<IndexController> {
return DropdownButton<String>(
value: locationController.getSimulatedSignalStrength(),
onChanged: (value) {
debugPrint("DropDown changed!");
//debugPrint("DropDown changed!");
locationController.setSimulatedSignalStrength(value!);
},
items: ['low', 'medium', 'high', 'real']

View File

@ -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)),

View File

@ -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"),

View File

@ -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<DestinationController>();
// ロゲ開始前、終了後、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(

View File

@ -128,14 +128,13 @@ class BottomSheetNew extends GetView<BottomSheetController> {
// ボタンがタップされたときの処理も含まれています。
//
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<BottomSheetController> {
}
: null,
child: const Text(
"ロゲイニングを終える",
"ロゲゴール",
style: TextStyle(color: Colors.white),
));
} else if (distanceToDest <=
@ -186,7 +185,26 @@ class BottomSheetNew extends GetView<BottomSheetController> {
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<BottomSheetController> {
return;
}
},
*/
child: Text(
destination.cp == -1 &&
destinationController.isInRog.value == false &&
@ -251,7 +270,7 @@ class BottomSheetNew extends GetView<BottomSheetController> {
? "ゲーム中"
: destinationController.isInRog.value == true
? "チェックイン"
: "始まっていない",
: "ロゲは始まっていません",
style: TextStyle(color: Theme.of(context).colorScheme.onSecondary),
),
);

View File

@ -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(

View File

@ -20,7 +20,7 @@ class GpsSignalStrengthIndicator extends StatelessWidget {
// final LocationController locationController = Get.find<LocationController>();
return Obx(() {
String signalStrength = locationController.latestSignalStrength.value;
debugPrint("GpsSignalStrengthIndicator : signalStrength=${signalStrength}");
//debugPrint("GpsSignalStrengthIndicator : signalStrength=${signalStrength}");
IconData iconData;
Color backgroundColor;
String text;

View File

@ -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<ListWidget> {
@override
Widget build(BuildContext context) {
debugPrint("_ListWidgetState");
return Obx(
() => indexController.locations.isNotEmpty
? RefreshIndicator(
@ -130,7 +132,8 @@ class _ListWidgetState extends State<ListWidget> {
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<ListWidget> {
} else {
bottomSheet = BottomSheetNormalPoint(destination: des);
}
*/
showModalBottomSheet(
constraints: BoxConstraints.loose(

View File

@ -25,7 +25,8 @@ class MapWidget extends StatefulWidget {
State<MapWidget> createState() => _MapWidgetState();
}
class _MapWidgetState extends State<MapWidget> {
class _MapWidgetState extends State<MapWidget> with WidgetsBindingObserver {
//class _MapWidgetState extends State<MapWidget> {
final IndexController indexController = Get.find<IndexController>();
final DestinationController destinationController =
Get.find<DestinationController>();
@ -46,6 +47,11 @@ class _MapWidgetState extends State<MapWidget> {
_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<MapWidget> {
@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<void> _initMarkers() async {
@ -172,8 +193,7 @@ class _MapWidgetState extends State<MapWidget> {
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<MapWidget> {
stream: locationController.locationMarkerPositionStream,
builder: (context, snapshot) {
if (!snapshot.hasData) {
print("====== Not display current marker");
debugPrint("====== Not display current marker");
}
return Container();
},

View File

@ -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:

View File

@ -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