diff --git a/lib/features/photo/camera/camera_controller.dart b/lib/features/photo/camera/camera_controller.dart index f2ec8ae..3c38ec5 100644 --- a/lib/features/photo/camera/camera_controller.dart +++ b/lib/features/photo/camera/camera_controller.dart @@ -49,12 +49,15 @@ class ClassifyLatestPhotoNotifier extends _$ClassifyLatestPhotoNotifier { final longitude = position?.longitude; if (latitude != null && longitude != null) { + logger.d('位置情報を取得しました: userId=$userId, photoId=$modifiedPhotoId, 緯度=$latitude, 経度=$longitude'); await ref.read(photoRepositoryProvider).registerStoreInfo( photoId: modifiedPhotoId, userId: userId, latitude: latitude, longitude: longitude, ); + } else { + logger.w('位置情報の取得に失敗しました: userId=$userId, photoId=$modifiedPhotoId'); } final photoFile = await latestPhoto.file; diff --git a/lib/features/photo/photo_picker/photo_picker_controller.dart b/lib/features/photo/photo_picker/photo_picker_controller.dart index 3d6b640..ab6d284 100644 --- a/lib/features/photo/photo_picker/photo_picker_controller.dart +++ b/lib/features/photo/photo_picker/photo_picker_controller.dart @@ -3,15 +3,16 @@ import 'dart:io'; import 'dart:typed_data'; import 'package:exif/exif.dart'; -import 'package:flutter_image_compress/flutter_image_compress.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:photo_manager/photo_manager.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import '../../../core/image_helper.dart'; import '../../../core/logger.dart'; +import '../../../core/timestamp_converter.dart'; import '../../auth/auth_controller.dart'; import '../local_photo_manager_service.dart'; +import '../local_photo_repository.dart'; import '../remote_photo_repository.dart'; part 'photo_picker_controller.g.dart'; @@ -85,10 +86,9 @@ class ClassifyLocalPhotoNotifier extends _$ClassifyLocalPhotoNotifier { } Future classifyPhotoAsFood({ - required XFile image, - bool isFood = true, + required AssetEntity photo, }) async { - final modifiedPhotoId = image.path.split('/').last.replaceAll('/', '-'); + final modifiedPhotoId = photo.id.replaceAll('/', '-'); final userId = ref.read(userIdProvider); if (userId == null) { @@ -97,41 +97,68 @@ class ClassifyLocalPhotoNotifier extends _$ClassifyLocalPhotoNotifier { } try { - final location = await _getImageLocation(image.path); - - if (isFood) { - if (location != null && location.isNotEmpty) { - // サーバーに位置情報を送信 - await ref.read(photoRepositoryProvider).registerStoreInfo( - photoId: modifiedPhotoId, - userId: userId, - latitude: location['latitude'], - longitude: location['longitude'], - ); - } - - // 画像ファイルの圧縮と送信 - final photoFile = File(image.path); - final compressedData = await ImageHelper.compress(photoFile); - - if (compressedData != null) { - await ref.read(photoRepositoryProvider).categorizeFood( - userId: userId, - photoId: modifiedPhotoId, - photoData: compressedData, - ); - } + final photoFile = await photo.file; + if (photoFile == null) { + logger.e('写真ファイルの取得に失敗しました'); + return; } - } on Exception catch (e, stackTrace) { - state = AsyncValue.error(e, stackTrace); - logger.e('Error in classifyPhotoAsFood: $e'); + + await ref.read(localPhotoRepositoryProvider).savePhoto( + photo: photo, + isFood: true, + ); + + logger.d('photo_managerパッケージ modifiedPhotoId: $modifiedPhotoId'); + logger.d('photo_managerパッケージ photo: $photo'); + logger.d('photo_managerパッケージ latitude: ${photo.latitude}'); + logger.d('photo_managerパッケージ longitude: ${photo.longitude}'); + + Map? location; + if (Platform.isIOS && photo.latitude != null && photo.longitude != null) { + location = { + 'latitude': photo.latitude!, + 'longitude': photo.longitude!, + }; + } else { + location = await _getImageLocation(photoFile.path); } + logger.d('位置情報: $location'); + + if (location != null && location.isNotEmpty) { + // サーバーに位置情報を送信 + await ref.read(photoRepositoryProvider).registerStoreInfo( + photoId: modifiedPhotoId, + userId: userId, + latitude: location['latitude'], + longitude: location['longitude'], + ); + + // 画像ファイルの圧縮と送信 + final compressedData = await ImageHelper.compress(photoFile); + + if (compressedData != null) { + await ref.read(photoRepositoryProvider).registerPhotoData( + userId: userId, + shotAt: UnionTimestamp.dateTime(photo.createDateTime), + photoId: modifiedPhotoId, + ); + await ref.read(photoRepositoryProvider).categorizeFood( + userId: userId, + photoId: modifiedPhotoId, + photoData: compressedData, + ); + } + } + } on Exception catch (e, stackTrace) { + state = AsyncValue.error(e, stackTrace); + logger.e('Error in classifyPhotoAsFood: $e'); } +} Future?> _getImageLocation(String imagePath) async { try { final file = File(imagePath); - final bytes = await file.readAsBytes(); + final bytes = file.readAsBytesSync(); // EXIFデータを解析 final data = await readExifFromBytes(bytes); diff --git a/lib/features/photo/photo_picker/photo_picker_controller.g.dart b/lib/features/photo/photo_picker/photo_picker_controller.g.dart index b9c898e..00d3fd5 100644 --- a/lib/features/photo/photo_picker/photo_picker_controller.g.dart +++ b/lib/features/photo/photo_picker/photo_picker_controller.g.dart @@ -196,7 +196,7 @@ final selectedLocalPhotosProvider = AutoDisposeNotifierProvider< typedef _$SelectedLocalPhotos = AutoDisposeNotifier>; String _$classifyLocalPhotoNotifierHash() => - r'0f08daa3b9571125b1e6bcf99eb7269f514c3aff'; + r'b9b94465a8cdbb7cb5a73d30fbfab640da6ebdf5'; /// 画像選択画面で選択された画像を用いて、画像分類APIを呼び出すProvider /// diff --git a/lib/features/photo/photo_picker/photo_picker_page.dart b/lib/features/photo/photo_picker/photo_picker_page.dart index 4d719b0..ee14bc0 100644 --- a/lib/features/photo/photo_picker/photo_picker_page.dart +++ b/lib/features/photo/photo_picker/photo_picker_page.dart @@ -5,10 +5,8 @@ import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:gap/gap.dart'; import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:image_picker/image_picker.dart'; import 'package:permission_handler/permission_handler.dart'; -import '../../../core/logger.dart'; import '../../../core/permission/permission_handler.dart'; import '../../../core/themes.dart'; @@ -243,26 +241,16 @@ class PhotoPickerPage extends HookConsumerWidget { // 非同期で分類処理を実行(バックグラウンド処理) await Future.microtask(() async { - final selectedPhotos = + final selectedPhotos = selectedLocalPhotos.toList(); final photoListNotifier = ref.read( classifyLocalPhotoNotifierProvider.notifier, ); final tasks = selectedPhotos.map((photo) async { - try { - final file = await photo.file; - - if (file != null) { - final xFile = XFile(file.path); - await photoListNotifier.classifyPhotoAsFood( - image: xFile, - ); - } - } on Exception catch (e) { - logger - .e('Error classify processing photo: $e'); - } + await photoListNotifier.classifyPhotoAsFood( + photo: photo, + ); }).toList(); unawaited(Future.wait(tasks));