Fixed Cameraでクラッシュ、日付ズレ、遠くのチェックポイント表示、1日1回のプロテクト

This commit is contained in:
2024-08-07 21:17:13 +09:00
parent 347861e5a1
commit bdf6dd3c04
7 changed files with 227 additions and 21 deletions

View File

@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objectVersion = 60;
objects = {
/* Begin PBXBuildFile section */
@ -398,11 +398,11 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 493;
CURRENT_PROJECT_VERSION = 494;
DEVELOPMENT_TEAM = UMNEWT25JR;
ENABLE_BITCODE = NO;
FLUTTER_BUILD_NAME = 4.8.13;
FLUTTER_BUILD_NUMBER = 493;
FLUTTER_BUILD_NAME = 4.8.14;
FLUTTER_BUILD_NUMBER = 494;
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.8.13;
MARKETING_VERSION = 4.8.14;
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 = 493;
CURRENT_PROJECT_VERSION = 494;
DEVELOPMENT_TEAM = UMNEWT25JR;
ENABLE_BITCODE = NO;
FLUTTER_BUILD_NAME = 4.8.13;
FLUTTER_BUILD_NUMBER = 493;
FLUTTER_BUILD_NAME = 4.8.14;
FLUTTER_BUILD_NUMBER = 494;
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.8.13;
MARKETING_VERSION = 4.8.14;
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 = 493;
CURRENT_PROJECT_VERSION = 494;
DEVELOPMENT_TEAM = UMNEWT25JR;
ENABLE_BITCODE = NO;
FLUTTER_BUILD_NAME = 4.8.13;
FLUTTER_BUILD_NUMBER = 493;
FLUTTER_BUILD_NAME = 4.8.14;
FLUTTER_BUILD_NUMBER = 494;
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.8.13;
MARKETING_VERSION = 4.8.14;
PRODUCT_BUNDLE_IDENTIFIER = com.dvox.gifunavi;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";

View File

@ -431,7 +431,7 @@ class DestinationController extends GetxController {
debugPrint("* 目的地がない場合 ==> 検知半径=-1の場合");
// print("----- in location popup cp - ${d.cp}----");
if ((d.cp == -1 || d.cp==0 ) && DateTime.now().difference(lastGoalAt).inHours >= 24) {
if ((d.cp == -1 || d.cp==0 ) && DateTime.now().difference(lastGoalAt).inHours >= 10) {
debugPrint("**1: 開始CPで、最後にゴールしてから時間経過していれば、");
chekcs = 1;
@ -673,11 +673,11 @@ class DestinationController extends GetxController {
} else if (isInRog.value == false &&
indexController.rogMode.value == 1 &&
DateTime.now().difference(lastGoalAt).inHours >= 24) {
DateTime.now().difference(lastGoalAt).inHours >= 10) {
//start
//print("---- in start -----");
debugPrint("**5 スタートの場合で最後のゴールから24時間経過している場合");
debugPrint("**5 スタートの場合で最後のゴールから10時間経過している場合");
chekcs = 6; // start point

View File

@ -23,10 +23,14 @@ import 'package:shared_preferences/shared_preferences.dart';
import 'package:rogapp/services/api_service.dart';
import 'package:rogapp/model/user.dart';
import 'package:rogapp/model/rog.dart';
import 'package:rogapp/main.dart';
import 'package:rogapp/widgets/helper_dialog.dart';
import 'package:timezone/timezone.dart' as tz;
import 'package:timezone/data/latest.dart' as tz;
class IndexController extends GetxController with WidgetsBindingObserver {
List<GeoJSONFeatureCollection> locations = <GeoJSONFeatureCollection>[].obs;
@ -66,6 +70,7 @@ class IndexController extends GetxController with WidgetsBindingObserver {
//late final ApiService _apiService;
final ApiService _apiService = Get.find<ApiService>();
final DatabaseHelper _dbHelper = DatabaseHelper.instance;
// mode = 0 is map mode, mode = 1 list mode
var mode = 0.obs;
@ -237,6 +242,7 @@ class IndexController extends GetxController with WidgetsBindingObserver {
print('IndexController onInit called'); // デバッグ用の出力を追加
tz.initializeTimeZones();
//teamController = Get.find<TeamController>();
}
@ -562,6 +568,10 @@ class IndexController extends GetxController with WidgetsBindingObserver {
saveToDevice(currentUser[0]["token"]);
}
isLoading.value = false;
// ユーザーのイベント情報を取得
await fetchUserEventInfo();
loadLocationsBound( currentUser[0]["user"]["event_code"]);
if (currentUser.isNotEmpty) {
rogMode.value = 0;
@ -575,6 +585,58 @@ class IndexController extends GetxController with WidgetsBindingObserver {
Get.toNamed(AppPages.INDEX);
}
Future<void> fetchUserEventInfo() async {
try {
final List<Entry> entries = await _apiService.getEntries();
if (entries.isNotEmpty) {
final Entry latestEntry = entries.last;
final tokyo = tz.getLocation('Asia/Tokyo');
final eventDate = latestEntry.date!.toUtc();
//final eventDate = tz.TZDateTime.from(utcDate, tokyo);
final eventDateOnly = tz.TZDateTime(tokyo, eventDate.year, eventDate.month, eventDate.day);
currentUser[0]['user']['event_date'] = eventDateOnly.toIso8601String().split('T')[0];
currentUser[0]['user']['event_code'] = latestEntry.event.eventName;
currentUser[0]['user']['team_name'] = latestEntry.team.teamName;
currentUser[0]['user']['group'] = latestEntry.team.category.categoryName;
currentUser[0]['user']['zekken_number'] = latestEntry.zekkenNumber;
// 最後のゴール日時を取得
final lastGoalTime = await getLastGoalTime();
currentUser[0]['user']['last_goal_time'] = lastGoalTime?.toIso8601String();
print('Updated user event info: ${currentUser[0]['user']}');
} else {
print('No entries found for the user');
_clearUserEventInfo();
}
} catch (e) {
print('Error fetching user event info: $e');
_clearUserEventInfo();
}
}
Future<DateTime?> getLastGoalTime() async {
try {
final userId = currentUser[0]['user']['id'];
return await _apiService.getLastGoalTime(userId);
} catch (e) {
print('Error getting last goal time: $e');
}
return null;
}
void _clearUserEventInfo() {
currentUser[0]['user']['event_date'] = null;
currentUser[0]['user']['event_code'] = null;
currentUser[0]['user']['team_name'] = null;
currentUser[0]['user']['group'] = null;
currentUser[0]['user']['zekken_number'] = null;
}
Future<void> fetchTeamData() async {
try {
Get.put(TeamController());
@ -589,6 +651,8 @@ class IndexController extends GetxController with WidgetsBindingObserver {
}
}
loadUserDetailsForToken(String token) async {
AuthService.userForToken(token).then((value) {
print("----token val-- $value ------");

View File

@ -665,4 +665,29 @@ class ApiService extends GetxService{
return false;
}
}
Future<DateTime?> getLastGoalTime(int userId) async {
try {
final response = await http.get(
Uri.parse('$baseUrl/users/$userId/last-goal/'),
headers: {
'Authorization': 'Token $token',
'Content-Type': 'application/json; charset=UTF-8',
},
);
if (response.statusCode == 200) {
final decodedResponse = json.decode(utf8.decode(response.bodyBytes));
if (decodedResponse['last_goal_time'] != null) {
return DateTime.parse(decodedResponse['last_goal_time']).toLocal();
}
} else {
print('Failed to get last goal time. Status code: ${response.statusCode}');
}
} catch (e) {
print('Error in getLastGoalTime: $e');
}
return null;
}
}

View File

@ -122,10 +122,10 @@ class LocationService {
var grp = event_code; //indexController.currentUser[0]['user']['event_code'];
print("Group=$grp");
url =
'$serverUrl/api/inbound?rog=$r&grp=$grp&ln1=$lon1&la1=$lat1&ln2=$lon2&la2=$lat2&ln3=$lon3&la3=$lat3&ln4=$lon4&la4=$lat4&cat=$cat';
'$serverUrl/api/inbound2?rog=$r&grp=$grp&ln1=$lon1&la1=$lat1&ln2=$lon2&la2=$lat2&ln3=$lon3&la3=$lat3&ln4=$lon4&la4=$lat4&cat=$cat';
} else {
url =
'$serverUrl/api/inbound?ln1=$lon1&la1=$lat1&ln2=$lon2&la2=$lat2&ln3=$lon3&la3=$lat3&ln4=$lon4&la4=$lat4&cat=$cat';
'$serverUrl/api/inbound2?ln1=$lon1&la1=$lat1&ln2=$lon2&la2=$lat2&ln3=$lon3&la3=$lat3&ln4=$lon4&la4=$lat4&cat=$cat';
}
} else {
if (indexController.currentUser.isNotEmpty) {
@ -134,10 +134,10 @@ class LocationService {
var grp = indexController.currentUser[0]['user']['event_code'];
print("-------- requested user group $grp -------------");
url =
'$serverUrl/api/inbound?rog=$r&grp=$grp&ln1=$lon1&la1=$lat1&ln2=$lon2&la2=$lat2&ln3=$lon3&la3=$lat3&ln4=$lon4&la4=$lat4';
'$serverUrl/api/inbound2?rog=$r&grp=$grp&ln1=$lon1&la1=$lat1&ln2=$lon2&la2=$lat2&ln3=$lon3&la3=$lat3&ln4=$lon4&la4=$lat4';
} else {
url =
'$serverUrl/api/inbound?ln1=$lon1&la1=$lat1&ln2=$lon2&la2=$lat2&ln3=$lon3&la3=$lat3&ln4=$lon4&la4=$lat4';
'$serverUrl/api/inbound2?ln1=$lon1&la1=$lat1&ln2=$lon2&la2=$lat2&ln3=$lon3&la3=$lat3&ln4=$lon4&la4=$lat4';
}
print('++++++++$url');
final response = await http.get(

View File

@ -21,6 +21,10 @@ import 'package:rogapp/widgets/bottom_sheet_controller.dart';
import 'package:rogapp/widgets/debug_widget.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:timezone/timezone.dart' as tz;
import 'package:timezone/data/latest.dart' as tz;
import 'package:get/get.dart';
// BottomSheetNewは、StatelessWidgetを継承したクラスで、目的地の詳細情報を表示するボトムシートのUIを構築します。
// コンストラクタでは、destination目的地オブジェクトとisAlreadyCheckedInすでにチェックイン済みかどうかのフラグを受け取ります。
// buildメソッドでは、detailsSheetメソッドを呼び出して、目的地の詳細情報を表示します。
@ -38,6 +42,15 @@ class BottomSheetNew extends GetView<BottomSheetController> {
final RxBool isButtonDisabled = false.obs;
static bool _timezoneInitialized = false;
void _initializeTimezone() {
if (!_timezoneInitialized) {
tz.initializeTimeZones();
_timezoneInitialized = true;
}
}
// 目的地の画像を取得するためのメソッドです。
// indexController.rogModeの値に基づいて、適切な画像を返します。画像が見つからない場合は、デフォルトの画像を返します。
//
@ -146,6 +159,7 @@ class BottomSheetNew extends GetView<BottomSheetController> {
// ボタンがタップされたときの処理も含まれています。
//
Widget getActionButton(BuildContext context, Destination destination) {
_initializeTimezone(); // タイムゾーンの初期化
/*
debugPrint("getActionButton ${destinationController.rogainingCounted.value}");
debugPrint("getActionButton ${destinationController.distanceToStart()}");
@ -181,6 +195,51 @@ class BottomSheetNew extends GetView<BottomSheetController> {
onPressed: destinationController.isInRog.value
? null
: () async {
// Check if the event is for today
bool isEventToday = await checkIfEventIsToday();
if (!isEventToday) {
Get.dialog(
AlertDialog(
title: Text("警告"),
content: Text("参加したエントリーは別日のものですので、ロゲの開始はできません。当日のエントリーを選択するか、エントリーを今日に変更してからロゲ開始を行ってください。"),
actions: <Widget>[
TextButton(
child: Text("OK"),
onPressed: () {
Get.back(); // Close the dialog
Get.back(); // Close the bottom sheet
},
),
],
),
);
return;
}
// Check if user has already completed a rogaining event today
bool hasCompletedToday = await checkIfCompletedToday();
if (hasCompletedToday) {
Get.dialog(
AlertDialog(
title: Text("警告"),
content: Text("すでにロゲの参加を行いゴールをしています。ロゲは1日1回に制限されています。ご了承ください。"),
actions: <Widget>[
TextButton(
child: Text("OK"),
onPressed: () {
Get.back(); // Close the dialog
Get.back(); // Close the bottom sheet
},
),
],
),
);
return;
}
destinationController.isInRog.value = true;
@ -259,6 +318,8 @@ class BottomSheetNew extends GetView<BottomSheetController> {
(destination.cp == 0 || destination.cp == -2|| destination.cp == -1) &&
DestinationController.ready_for_goal == true
? () async {
destinationController.isAtGoal.value = true;
destinationController.photos.clear();
await showModalBottomSheet(
@ -331,6 +392,62 @@ class BottomSheetNew extends GetView<BottomSheetController> {
return Container();
}
// Add these new methods to check event date and completion status
Future<bool> checkIfEventIsToday() async {
try {
final now = tz.TZDateTime.now(tz.getLocation('Asia/Tokyo'));
// Null チェックと安全な操作を追加
final userEventDate = indexController.currentUser.isNotEmpty &&
indexController.currentUser[0] != null &&
indexController.currentUser[0]["user"] != null
? indexController.currentUser[0]["user"]["event_date"]
: null;
if (userEventDate == null || userEventDate.toString().isEmpty) {
print('Event date is null or empty');
return false; // イベント日付が設定されていない場合は false を返す
}
final eventDate = tz.TZDateTime.from(
DateTime.parse(userEventDate.toString()),
tz.getLocation('Asia/Tokyo')
);
return eventDate.year == now.year &&
eventDate.month == now.month &&
eventDate.day == now.day;
} catch (e) {
print('Error in checkIfEventIsToday: $e');
// エラーが発生した場合はダイアログを表示
Get.dialog(
AlertDialog(
title: Text('エラー'),
content: Text('イベント日付の確認中にエラーが発生しました。\nアプリを再起動するか、管理者にお問い合わせください。'),
actions: <Widget>[
TextButton(
child: Text('OK'),
onPressed: () => Get.back(),
),
],
),
);
return false; // エラーが発生した場合は false を返す
}
}
Future<bool> checkIfCompletedToday() async {
final IndexController indexController = Get.find<IndexController>();
final lastGoalTime = await indexController.getLastGoalTime();
if (lastGoalTime == null) return false;
final now = DateTime.now();
return lastGoalTime.year == now.year &&
lastGoalTime.month == now.month &&
lastGoalTime.day == now.day;
}
// 継承元のbuild をオーバーライドし、detailsSheetメソッドを呼び出して、目的地の詳細情報を表示します。
@override
Widget build(BuildContext context) {

View File

@ -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.8.13+493
version: 4.8.14+494
environment:
sdk: ">=3.2.0 <4.0.0"