Fixed Cameraでクラッシュ、日付ズレ、遠くのチェックポイント表示、1日1回のプロテクト
This commit is contained in:
@ -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 = "";
|
||||
|
||||
@ -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で、最後にゴールしてから24時間経過していれば、");
|
||||
|
||||
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
|
||||
|
||||
@ -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 ------");
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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(
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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"
|
||||
|
||||
Reference in New Issue
Block a user