m3_lightmeter/lib/providers/logbook_photos_provider.dart

127 lines
3.7 KiB
Dart
Raw Normal View History

2025-07-09 19:48:24 +00:00
import 'dart:io';
2025-06-13 20:54:02 +00:00
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
2025-07-10 13:18:47 +00:00
import 'package:lightmeter/providers/services_provider.dart';
2025-06-13 20:54:02 +00:00
import 'package:lightmeter/utils/context_utils.dart';
import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
2025-07-09 19:48:24 +00:00
import 'package:uuid/v8.dart';
2025-06-13 20:54:02 +00:00
class LogbookPhotosProvider extends StatefulWidget {
final LogbookPhotosStorageService storageService;
final VoidCallback? onInitialized;
final Widget child;
const LogbookPhotosProvider({
required this.storageService,
this.onInitialized,
required this.child,
super.key,
});
static LogbookPhotosProviderState of(BuildContext context) {
return context.findAncestorStateOfType<LogbookPhotosProviderState>()!;
}
@override
State<LogbookPhotosProvider> createState() => LogbookPhotosProviderState();
}
class LogbookPhotosProviderState extends State<LogbookPhotosProvider> {
final Map<String, LogbookPhoto> _photos = {};
@override
void initState() {
super.initState();
_init();
}
@override
Widget build(BuildContext context) {
return LogbookPhotos(
photos: context.isPro ? _photos.values.toList(growable: false) : [],
child: widget.child,
);
}
Future<void> _init() async {
_photos.addAll(
Map.fromIterable(
await widget.storageService.getPhotos(),
key: (photo) => (photo as LogbookPhoto).id,
),
);
if (mounted) setState(() {});
widget.onInitialized?.call();
}
2025-07-09 19:48:24 +00:00
Future<void> addPhotoIfPossible(
String path, {
required double ev100,
required int iso,
required int nd,
}) async {
if (context.isPro) {
2025-07-10 13:18:47 +00:00
// Get coordinates from geolocation service
final geolocationService = ServicesProvider.of(context).geolocationService;
final coordinates = await geolocationService.getCurrentPosition();
2025-07-09 19:48:24 +00:00
final photo = LogbookPhoto(
id: const UuidV8().generate(),
name: path,
timestamp: DateTime.timestamp(),
ev: ev100,
iso: iso,
nd: nd,
2025-07-10 13:18:47 +00:00
coordinates: coordinates,
2025-07-09 19:48:24 +00:00
);
2025-07-10 13:18:47 +00:00
await widget.storageService.addPhoto(photo);
2025-07-09 19:48:24 +00:00
_photos[photo.id] = photo;
setState(() {});
} else {
Directory(path).deleteSync(recursive: true);
}
2025-06-13 20:54:02 +00:00
}
Future<void> updateProfile(LogbookPhoto photo) async {
final oldProfile = _photos[photo.id]!;
2025-07-10 11:52:48 +00:00
await widget.storageService.updatePhoto(
id: photo.id,
note: oldProfile.note != photo.note ? photo.note : null,
apertureValue: oldProfile.apertureValue != photo.apertureValue ? photo.apertureValue : null,
removeApertureValue: photo.apertureValue == null,
shutterSpeedValue: oldProfile.shutterSpeedValue != photo.shutterSpeedValue ? photo.shutterSpeedValue : null,
removeShutterSpeedValue: photo.shutterSpeedValue == null,
);
_photos[photo.id] = photo;
setState(() {});
2025-06-13 20:54:02 +00:00
}
Future<void> deleteProfile(LogbookPhoto photo) async {
await widget.storageService.deletePhoto(photo.id);
_photos.remove(photo.id);
2025-07-09 19:48:24 +00:00
Directory(photo.name).deleteSync(recursive: true);
2025-06-13 20:54:02 +00:00
setState(() {});
}
}
class LogbookPhotos extends InheritedWidget {
final List<LogbookPhoto> photos;
const LogbookPhotos({
required this.photos,
required super.child,
});
static List<LogbookPhoto> of(BuildContext context, {bool listen = false}) {
return (listen
? context.dependOnInheritedWidgetOfExactType<LogbookPhotos>()
: context.getInheritedWidgetOfExactType<LogbookPhotos>())!
.photos;
}
@override
2025-07-10 14:18:12 +00:00
bool updateShouldNotify(LogbookPhotos oldWidget) => !const DeepCollectionEquality().equals(oldWidget.photos, photos);
2025-06-13 20:54:02 +00:00
}