integrated EquipmentProfilesStorageService

This commit is contained in:
Vadim 2024-11-06 14:04:11 +01:00
parent c66381f813
commit 5ddaed8dfb
5 changed files with 65 additions and 62 deletions

View file

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_native_splash/flutter_native_splash.dart'; import 'package:flutter_native_splash/flutter_native_splash.dart';
import 'package:lightmeter/data/analytics/analytics.dart'; import 'package:lightmeter/data/analytics/analytics.dart';
@ -34,11 +36,14 @@ class _ApplicationWrapperState extends State<ApplicationWrapper> {
? const RemoteConfigService(LightmeterAnalytics(api: LightmeterAnalyticsFirebase())) ? const RemoteConfigService(LightmeterAnalytics(api: LightmeterAnalyticsFirebase()))
: const MockRemoteConfigService(); : const MockRemoteConfigService();
late final IAPStorageService iapStorageService;
late final UserPreferencesService userPreferencesService; late final UserPreferencesService userPreferencesService;
late final bool hasLightSensor; late final bool hasLightSensor;
final equipmentProfilesStorageService = EquipmentProfilesStorageService();
final equipmentProfilesStorageServiceCompleter = Completer<void>();
final filmsStorageService = FilmsStorageService(); final filmsStorageService = FilmsStorageService();
final filmsStorageServiceCompleter = Completer<void>();
late final Future<void> _initFuture; late final Future<void> _initFuture;
@ -68,10 +73,11 @@ class _ApplicationWrapperState extends State<ApplicationWrapper> {
child: RemoteConfigProvider( child: RemoteConfigProvider(
remoteConfigService: remoteConfigService, remoteConfigService: remoteConfigService,
child: EquipmentProfileProvider( child: EquipmentProfileProvider(
storageService: iapStorageService, storageService: equipmentProfilesStorageService,
onInitialized: equipmentProfilesStorageServiceCompleter.complete,
child: FilmsProvider( child: FilmsProvider(
filmsStorageService: filmsStorageService, storageService: filmsStorageService,
onInitialized: _onFilmsProviderInitialized, onInitialized: filmsStorageServiceCompleter.complete,
child: UserPreferencesProvider( child: UserPreferencesProvider(
hasLightSensor: hasLightSensor, hasLightSensor: hasLightSensor,
userPreferencesService: userPreferencesService, userPreferencesService: userPreferencesService,
@ -95,14 +101,12 @@ class _ApplicationWrapperState extends State<ApplicationWrapper> {
remoteConfigService.activeAndFetchFeatures(), remoteConfigService.activeAndFetchFeatures(),
filmsStorageService.init(), filmsStorageService.init(),
]).then((value) { ]).then((value) {
final sharedPrefs = (value[0] as SharedPreferences?)!; userPreferencesService = UserPreferencesService((value[0] as SharedPreferences?)!);
iapStorageService = IAPStorageService(sharedPrefs);
userPreferencesService = UserPreferencesService(sharedPrefs);
hasLightSensor = value[1] as bool? ?? false; hasLightSensor = value[1] as bool? ?? false;
}); });
} await Future.wait([
equipmentProfilesStorageServiceCompleter.future,
void _onFilmsProviderInitialized() { filmsStorageServiceCompleter.future,
FlutterNativeSplash.remove(); ]).then((_) => FlutterNativeSplash.remove());
} }
} }

View file

@ -3,14 +3,15 @@ import 'package:lightmeter/utils/context_utils.dart';
import 'package:lightmeter/utils/selectable_provider.dart'; import 'package:lightmeter/utils/selectable_provider.dart';
import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart'; import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
import 'package:uuid/uuid.dart';
class EquipmentProfileProvider extends StatefulWidget { class EquipmentProfileProvider extends StatefulWidget {
final IAPStorageService storageService; final EquipmentProfilesStorageService storageService;
final VoidCallback? onInitialized;
final Widget child; final Widget child;
const EquipmentProfileProvider({ const EquipmentProfileProvider({
required this.storageService, required this.storageService,
this.onInitialized,
required this.child, required this.child,
super.key, super.key,
}); });
@ -33,19 +34,15 @@ class EquipmentProfileProviderState extends State<EquipmentProfileProvider> {
isoValues: IsoValue.values, isoValues: IsoValue.values,
); );
List<EquipmentProfile> _customProfiles = []; final Map<String, EquipmentProfile> _customProfiles = {};
String _selectedId = ''; String _selectedId = '';
EquipmentProfile get _selectedProfile => _customProfiles.firstWhere( EquipmentProfile get _selectedProfile => _customProfiles[_selectedId] ?? _defaultProfile;
(e) => e.id == _selectedId,
orElse: () => _defaultProfile,
);
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_selectedId = widget.storageService.selectedEquipmentProfileId; _init();
_customProfiles = widget.storageService.equipmentProfiles;
} }
@override @override
@ -53,13 +50,20 @@ class EquipmentProfileProviderState extends State<EquipmentProfileProvider> {
return EquipmentProfiles( return EquipmentProfiles(
values: [ values: [
_defaultProfile, _defaultProfile,
if (context.isPro) ..._customProfiles, if (context.isPro) ..._customProfiles.values,
], ],
selected: context.isPro ? _selectedProfile : _defaultProfile, selected: context.isPro ? _selectedProfile : _defaultProfile,
child: widget.child, child: widget.child,
); );
} }
Future<void> _init() async {
_selectedId = widget.storageService.selectedEquipmentProfileId;
_customProfiles.addAll(await widget.storageService.getProfiles());
if (mounted) setState(() {});
widget.onInitialized?.call();
}
void setProfile(EquipmentProfile data) { void setProfile(EquipmentProfile data) {
if (_selectedId != data.id) { if (_selectedId != data.id) {
setState(() { setState(() {
@ -69,40 +73,35 @@ class EquipmentProfileProviderState extends State<EquipmentProfileProvider> {
} }
} }
/// Creates a default equipment profile Future<void> addProfile(EquipmentProfile profile) async {
void addProfile(String name, [EquipmentProfile? copyFrom]) { await widget.storageService.addProfile(profile);
_customProfiles.add( _customProfiles[profile.id] = profile;
EquipmentProfile( setState(() {});
id: const Uuid().v1(), }
name: name,
apertureValues: copyFrom?.apertureValues ?? ApertureValue.values, Future<void> updateProfile(EquipmentProfile profile) async {
ndValues: copyFrom?.ndValues ?? NdValue.values, final oldProfile = _customProfiles[profile.id]!;
shutterSpeedValues: copyFrom?.shutterSpeedValues ?? ShutterSpeedValue.values, await widget.storageService.updateProfile(
isoValues: copyFrom?.isoValues ?? IsoValue.values, id: profile.id,
), name: oldProfile.name != profile.name ? profile.name : null,
apertureValues: oldProfile.apertureValues != profile.apertureValues ? profile.apertureValues : null,
shutterSpeedValues:
oldProfile.shutterSpeedValues != profile.shutterSpeedValues ? profile.shutterSpeedValues : null,
isoValues: oldProfile.isoValues != profile.isoValues ? profile.isoValues : null,
ndValues: oldProfile.ndValues != profile.ndValues ? profile.ndValues : null,
lensZoom: oldProfile.lensZoom != profile.lensZoom ? profile.lensZoom : null,
); );
_refreshSavedProfiles(); _customProfiles[profile.id] = profile;
setState(() {});
} }
void updateProfile(EquipmentProfile data) { Future<void> deleteProfile(EquipmentProfile profile) async {
final indexToUpdate = _customProfiles.indexWhere((element) => element.id == data.id); await widget.storageService.deleteProfile(profile.id);
if (indexToUpdate >= 0) { if (profile.id == _selectedId) {
_customProfiles[indexToUpdate] = data;
_refreshSavedProfiles();
}
}
void deleteProfile(EquipmentProfile data) {
if (data.id == _selectedId) {
_selectedId = _defaultProfile.id; _selectedId = _defaultProfile.id;
widget.storageService.selectedEquipmentProfileId = _defaultProfile.id; widget.storageService.selectedEquipmentProfileId = _defaultProfile.id;
} }
_customProfiles.remove(data); _customProfiles.remove(profile.id);
_refreshSavedProfiles();
}
void _refreshSavedProfiles() {
widget.storageService.equipmentProfiles = _customProfiles;
setState(() {}); setState(() {});
} }
} }

View file

@ -5,12 +5,12 @@ import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
class FilmsProvider extends StatefulWidget { class FilmsProvider extends StatefulWidget {
final FilmsStorageService filmsStorageService; final FilmsStorageService storageService;
final VoidCallback? onInitialized; final VoidCallback? onInitialized;
final Widget child; final Widget child;
const FilmsProvider({ const FilmsProvider({
required this.filmsStorageService, required this.storageService,
this.onInitialized, this.onInitialized,
required this.child, required this.child,
super.key, super.key,
@ -48,9 +48,9 @@ class FilmsProviderState extends State<FilmsProvider> {
} }
Future<void> _init() async { Future<void> _init() async {
_selectedId = widget.filmsStorageService.selectedFilmId; _selectedId = widget.storageService.selectedFilmId;
predefinedFilms.addAll(await widget.filmsStorageService.getPredefinedFilms()); predefinedFilms.addAll(await widget.storageService.getPredefinedFilms());
customFilms.addAll(await widget.filmsStorageService.getCustomFilms()); customFilms.addAll(await widget.storageService.getCustomFilms());
_discardSelectedIfNotIncluded(); _discardSelectedIfNotIncluded();
if (mounted) setState(() {}); if (mounted) setState(() {});
widget.onInitialized?.call(); widget.onInitialized?.call();
@ -66,7 +66,7 @@ class FilmsProviderState extends State<FilmsProvider> {
} else { } else {
return; return;
} }
await widget.filmsStorageService.toggleFilm(film, enabled); await widget.storageService.toggleFilm(film, enabled);
_discardSelectedIfNotIncluded(); _discardSelectedIfNotIncluded();
setState(() {}); setState(() {});
} }
@ -74,7 +74,7 @@ class FilmsProviderState extends State<FilmsProvider> {
void selectFilm(Film film) { void selectFilm(Film film) {
if (_selectedFilm != film) { if (_selectedFilm != film) {
_selectedId = film.id; _selectedId = film.id;
widget.filmsStorageService.selectedFilmId = _selectedId; widget.storageService.selectedFilmId = _selectedId;
setState(() {}); setState(() {});
} }
} }
@ -83,19 +83,19 @@ class FilmsProviderState extends State<FilmsProvider> {
Future<void> addCustomFilm(FilmExponential film) async { Future<void> addCustomFilm(FilmExponential film) async {
// ignore: avoid_redundant_argument_values // ignore: avoid_redundant_argument_values
await widget.filmsStorageService.addFilm(film, isUsed: true); await widget.storageService.addFilm(film, isUsed: true);
customFilms[film.id] = (film: film, isUsed: true); customFilms[film.id] = (film: film, isUsed: true);
setState(() {}); setState(() {});
} }
Future<void> updateCustomFilm(FilmExponential film) async { Future<void> updateCustomFilm(FilmExponential film) async {
await widget.filmsStorageService.updateFilm(film); await widget.storageService.updateFilm(film);
customFilms[film.id] = (film: film, isUsed: customFilms[film.id]!.isUsed); customFilms[film.id] = (film: film, isUsed: customFilms[film.id]!.isUsed);
setState(() {}); setState(() {});
} }
Future<void> deleteCustomFilm(FilmExponential film) async { Future<void> deleteCustomFilm(FilmExponential film) async {
await widget.filmsStorageService.deleteFilm(film); await widget.storageService.deleteFilm(film);
customFilms.remove(film.id); customFilms.remove(film.id);
_discardSelectedIfNotIncluded(); _discardSelectedIfNotIncluded();
setState(() {}); setState(() {});
@ -108,7 +108,7 @@ class FilmsProviderState extends State<FilmsProvider> {
final isSelectedUsed = predefinedFilms[_selectedId]?.isUsed ?? customFilms[_selectedId]?.isUsed ?? false; final isSelectedUsed = predefinedFilms[_selectedId]?.isUsed ?? customFilms[_selectedId]?.isUsed ?? false;
if (!isSelectedUsed) { if (!isSelectedUsed) {
_selectedId = const FilmStub().id; _selectedId = const FilmStub().id;
widget.filmsStorageService.selectedFilmId = _selectedId; widget.storageService.selectedFilmId = _selectedId;
} }
} }
} }

View file

@ -79,7 +79,7 @@ class _EquipmentProfilesScreenState extends State<EquipmentProfilesScreen> {
builder: (_) => const EquipmentProfileNameDialog(), builder: (_) => const EquipmentProfileNameDialog(),
).then((name) { ).then((name) {
if (name != null) { if (name != null) {
EquipmentProfileProvider.of(context).addProfile(name, copyFrom); //EquipmentProfileProvider.of(context).addProfile(name, copyFrom);
} }
}); });
} }

View file

@ -32,7 +32,7 @@ dependencies:
m3_lightmeter_iap: m3_lightmeter_iap:
git: git:
url: "https://github.com/vodemn/m3_lightmeter_iap" url: "https://github.com/vodemn/m3_lightmeter_iap"
ref: v1.1.1 ref: feature/MLI-15
m3_lightmeter_resources: m3_lightmeter_resources:
git: git:
url: "https://github.com/vodemn/m3_lightmeter_resources" url: "https://github.com/vodemn/m3_lightmeter_resources"