From 73c1c0d66ebd1db7aa42f4f485b27464f3285998 Mon Sep 17 00:00:00 2001 From: Vadim <44135514+vodemn@users.noreply.github.com> Date: Fri, 13 Jun 2025 22:54:02 +0200 Subject: [PATCH] added `LogbookPhotosProvider` --- lib/application_wrapper.dart | 18 +++- lib/providers/logbook_photos_provider.dart | 97 ++++++++++++++++++++++ 2 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 lib/providers/logbook_photos_provider.dart diff --git a/lib/application_wrapper.dart b/lib/application_wrapper.dart index 4e95f40..62fbe83 100644 --- a/lib/application_wrapper.dart +++ b/lib/application_wrapper.dart @@ -15,6 +15,7 @@ import 'package:lightmeter/data/volume_events_service.dart'; import 'package:lightmeter/environment.dart'; import 'package:lightmeter/providers/equipment_profile_provider.dart'; import 'package:lightmeter/providers/films_provider.dart'; +import 'package:lightmeter/providers/logbook_photos_provider.dart'; import 'package:lightmeter/providers/remote_config_provider.dart'; import 'package:lightmeter/providers/services_provider.dart'; import 'package:lightmeter/providers/user_preferences_provider.dart'; @@ -46,6 +47,9 @@ class _ApplicationWrapperState extends State { final filmsStorageService = FilmsStorageService(); final filmsStorageServiceCompleter = Completer(); + final logbookPhotosStorageService = LogbookPhotosStorageService(); + final logbookPhotosStorageServiceCompleter = Completer(); + late final Future _initFuture; @override @@ -80,10 +84,14 @@ class _ApplicationWrapperState extends State { child: FilmsProvider( storageService: filmsStorageService, onInitialized: filmsStorageServiceCompleter.complete, - child: UserPreferencesProvider( - hasLightSensor: hasLightSensor, - userPreferencesService: userPreferencesService, - child: widget.child, + child: LogbookPhotosProvider( + storageService: logbookPhotosStorageService, + onInitialized: logbookPhotosStorageServiceCompleter.complete, + child: UserPreferencesProvider( + hasLightSensor: hasLightSensor, + userPreferencesService: userPreferencesService, + child: widget.child, + ), ), ), ), @@ -104,6 +112,7 @@ class _ApplicationWrapperState extends State { remoteConfigService.activeAndFetchFeatures(), equipmentProfilesStorageService.init(), filmsStorageService.init(), + logbookPhotosStorageService.init(), ]).then((value) { userPreferencesService = UserPreferencesService((value[0] as SharedPreferences?)!) ..cameraFocalLength = value[2] as int?; @@ -115,6 +124,7 @@ class _ApplicationWrapperState extends State { Future.wait([ equipmentProfilesStorageServiceCompleter.future, filmsStorageServiceCompleter.future, + logbookPhotosStorageServiceCompleter.future, ]).then((_) { FlutterNativeSplash.remove(); }); diff --git a/lib/providers/logbook_photos_provider.dart b/lib/providers/logbook_photos_provider.dart new file mode 100644 index 0000000..4d1890f --- /dev/null +++ b/lib/providers/logbook_photos_provider.dart @@ -0,0 +1,97 @@ +import 'package:collection/collection.dart'; +import 'package:flutter/material.dart'; +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'; + +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()!; + } + + @override + State createState() => LogbookPhotosProviderState(); +} + +class LogbookPhotosProviderState extends State { + final Map _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 _init() async { + _photos.addAll( + Map.fromIterable( + await widget.storageService.getPhotos(), + key: (photo) => (photo as LogbookPhoto).id, + ), + ); + if (mounted) setState(() {}); + widget.onInitialized?.call(); + } + + Future addPhoto(LogbookPhoto photo) async { + await widget.storageService.addPhoto(photo); + _photos[photo.id] = photo; + setState(() {}); + } + + Future updateProfile(LogbookPhoto photo) async { + final oldProfile = _photos[photo.id]!; + if (oldProfile.note != photo.note) { + await widget.storageService.updatePhoto( + id: photo.id, + note: photo.note, + ); + _photos[photo.id] = photo; + setState(() {}); + } + } + + Future deleteProfile(LogbookPhoto photo) async { + await widget.storageService.deletePhoto(photo.id); + _photos.remove(photo.id); + setState(() {}); + } +} + +class LogbookPhotos extends InheritedWidget { + final List photos; + + const LogbookPhotos({ + required this.photos, + required super.child, + }); + + static List of(BuildContext context, {bool listen = false}) { + return (listen + ? context.dependOnInheritedWidgetOfExactType() + : context.getInheritedWidgetOfExactType())! + .photos; + } + + @override + bool updateShouldNotify(LogbookPhotos oldWidget) => const DeepCollectionEquality().equals(oldWidget.photos, photos); +}