mirror of
https://github.com/vodemn/m3_lightmeter.git
synced 2024-12-04 05:10:40 +00:00
Compare commits
6 commits
8bc35633a7
...
2accf9f2b3
Author | SHA1 | Date | |
---|---|---|---|
|
2accf9f2b3 | ||
|
d1b96399bb | ||
|
ae2216ae3a | ||
|
e7512e47c2 | ||
|
e29920b757 | ||
|
f22086e578 |
4 changed files with 109 additions and 47 deletions
|
@ -39,7 +39,6 @@ class _ApplicationWrapperState extends State<ApplicationWrapper> {
|
||||||
late final bool hasLightSensor;
|
late final bool hasLightSensor;
|
||||||
|
|
||||||
final filmsStorageService = FilmsStorageService();
|
final filmsStorageService = FilmsStorageService();
|
||||||
final filmsProviderKey = GlobalKey<FilmsProviderState>();
|
|
||||||
|
|
||||||
late final Future<void> _initFuture;
|
late final Future<void> _initFuture;
|
||||||
|
|
||||||
|
@ -51,28 +50,28 @@ class _ApplicationWrapperState extends State<ApplicationWrapper> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return FilmsProvider(
|
return FutureBuilder(
|
||||||
key: filmsProviderKey,
|
future: _initFuture,
|
||||||
filmsStorageService: filmsStorageService,
|
builder: (context, snapshot) {
|
||||||
child: FutureBuilder(
|
if (snapshot.error != null) {
|
||||||
future: _initFuture,
|
return Center(child: Text(snapshot.error!.toString()));
|
||||||
builder: (context, snapshot) {
|
} else if (snapshot.connectionState == ConnectionState.done) {
|
||||||
if (snapshot.error != null) {
|
return ServicesProvider(
|
||||||
return Center(child: Text(snapshot.error!.toString()));
|
analytics: const LightmeterAnalytics(api: LightmeterAnalyticsFirebase()),
|
||||||
} else if (snapshot.connectionState == ConnectionState.done) {
|
caffeineService: const CaffeineService(),
|
||||||
return ServicesProvider(
|
environment: widget.env.copyWith(hasLightSensor: hasLightSensor),
|
||||||
analytics: const LightmeterAnalytics(api: LightmeterAnalyticsFirebase()),
|
hapticsService: const HapticsService(),
|
||||||
caffeineService: const CaffeineService(),
|
lightSensorService: const LightSensorService(LocalPlatform()),
|
||||||
environment: widget.env.copyWith(hasLightSensor: hasLightSensor),
|
permissionsService: const PermissionsService(),
|
||||||
hapticsService: const HapticsService(),
|
userPreferencesService: userPreferencesService,
|
||||||
lightSensorService: const LightSensorService(LocalPlatform()),
|
volumeEventsService: const VolumeEventsService(LocalPlatform()),
|
||||||
permissionsService: const PermissionsService(),
|
child: RemoteConfigProvider(
|
||||||
userPreferencesService: userPreferencesService,
|
remoteConfigService: remoteConfigService,
|
||||||
volumeEventsService: const VolumeEventsService(LocalPlatform()),
|
child: EquipmentProfileProvider(
|
||||||
child: RemoteConfigProvider(
|
storageService: iapStorageService,
|
||||||
remoteConfigService: remoteConfigService,
|
child: FilmsProvider(
|
||||||
child: EquipmentProfileProvider(
|
filmsStorageService: filmsStorageService,
|
||||||
storageService: iapStorageService,
|
onInitialized: _onFilmsProviderInitialized,
|
||||||
child: UserPreferencesProvider(
|
child: UserPreferencesProvider(
|
||||||
hasLightSensor: hasLightSensor,
|
hasLightSensor: hasLightSensor,
|
||||||
userPreferencesService: userPreferencesService,
|
userPreferencesService: userPreferencesService,
|
||||||
|
@ -80,12 +79,12 @@ class _ApplicationWrapperState extends State<ApplicationWrapper> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
}
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return const SizedBox();
|
return const SizedBox();
|
||||||
},
|
},
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,13 +93,16 @@ class _ApplicationWrapperState extends State<ApplicationWrapper> {
|
||||||
SharedPreferences.getInstance(),
|
SharedPreferences.getInstance(),
|
||||||
const LightSensorService(LocalPlatform()).hasSensor(),
|
const LightSensorService(LocalPlatform()).hasSensor(),
|
||||||
remoteConfigService.activeAndFetchFeatures(),
|
remoteConfigService.activeAndFetchFeatures(),
|
||||||
filmsStorageService.init().then((_) => filmsProviderKey.currentState?.init()),
|
filmsStorageService.init(),
|
||||||
]).then((value) {
|
]).then((value) {
|
||||||
final sharedPrefs = (value[0] as SharedPreferences?)!;
|
final sharedPrefs = (value[0] as SharedPreferences?)!;
|
||||||
iapStorageService = IAPStorageService(sharedPrefs);
|
iapStorageService = IAPStorageService(sharedPrefs);
|
||||||
userPreferencesService = UserPreferencesService(sharedPrefs);
|
userPreferencesService = UserPreferencesService(sharedPrefs);
|
||||||
hasLightSensor = value[1] as bool? ?? false;
|
hasLightSensor = value[1] as bool? ?? false;
|
||||||
FlutterNativeSplash.remove();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _onFilmsProviderInitialized() {
|
||||||
|
FlutterNativeSplash.remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:lightmeter/utils/context_utils.dart';
|
import 'package:lightmeter/utils/context_utils.dart';
|
||||||
import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart';
|
import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart';
|
||||||
|
@ -5,10 +6,12 @@ import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
|
||||||
|
|
||||||
class FilmsProvider extends StatefulWidget {
|
class FilmsProvider extends StatefulWidget {
|
||||||
final FilmsStorageService filmsStorageService;
|
final FilmsStorageService filmsStorageService;
|
||||||
|
final VoidCallback? onInitialized;
|
||||||
final Widget child;
|
final Widget child;
|
||||||
|
|
||||||
const FilmsProvider({
|
const FilmsProvider({
|
||||||
required this.filmsStorageService,
|
required this.filmsStorageService,
|
||||||
|
this.onInitialized,
|
||||||
required this.child,
|
required this.child,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
@ -28,6 +31,12 @@ class FilmsProviderState extends State<FilmsProvider> {
|
||||||
|
|
||||||
Film get _selectedFilm => customFilms[_selectedId]?.film ?? predefinedFilms[_selectedId]?.film ?? const FilmStub();
|
Film get _selectedFilm => customFilms[_selectedId]?.film ?? predefinedFilms[_selectedId]?.film ?? const FilmStub();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_init();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Films(
|
return Films(
|
||||||
|
@ -38,12 +47,13 @@ class FilmsProviderState extends State<FilmsProvider> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> init() async {
|
Future<void> _init() async {
|
||||||
_selectedId = widget.filmsStorageService.selectedFilmId;
|
_selectedId = widget.filmsStorageService.selectedFilmId;
|
||||||
predefinedFilms.addAll(await widget.filmsStorageService.getPredefinedFilms());
|
predefinedFilms.addAll(await widget.filmsStorageService.getPredefinedFilms());
|
||||||
customFilms.addAll(await widget.filmsStorageService.getCustomFilms());
|
customFilms.addAll(await widget.filmsStorageService.getCustomFilms());
|
||||||
_discardSelectedIfNotIncluded();
|
_discardSelectedIfNotIncluded();
|
||||||
if (mounted) setState(() {});
|
if (mounted) setState(() {});
|
||||||
|
widget.onInitialized?.call();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Both type of films **/
|
/* Both type of films **/
|
||||||
|
@ -104,8 +114,8 @@ class FilmsProviderState extends State<FilmsProvider> {
|
||||||
}
|
}
|
||||||
|
|
||||||
enum _FilmsModelAspect {
|
enum _FilmsModelAspect {
|
||||||
customFilmsList,
|
customFilms,
|
||||||
predefinedFilmsList,
|
predefinedFilms,
|
||||||
filmsInUse,
|
filmsInUse,
|
||||||
selected,
|
selected,
|
||||||
}
|
}
|
||||||
|
@ -125,7 +135,7 @@ class Films extends InheritedModel<_FilmsModelAspect> {
|
||||||
});
|
});
|
||||||
|
|
||||||
static List<Film> predefinedFilmsOf<T>(BuildContext context) {
|
static List<Film> predefinedFilmsOf<T>(BuildContext context) {
|
||||||
return InheritedModel.inheritFrom<Films>(context, aspect: _FilmsModelAspect.predefinedFilmsList)!
|
return InheritedModel.inheritFrom<Films>(context, aspect: _FilmsModelAspect.predefinedFilms)!
|
||||||
.predefinedFilms
|
.predefinedFilms
|
||||||
.values
|
.values
|
||||||
.map((value) => value.film)
|
.map((value) => value.film)
|
||||||
|
@ -133,7 +143,7 @@ class Films extends InheritedModel<_FilmsModelAspect> {
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<FilmExponential> customFilmsOf<T>(BuildContext context) {
|
static List<FilmExponential> customFilmsOf<T>(BuildContext context) {
|
||||||
return InheritedModel.inheritFrom<Films>(context, aspect: _FilmsModelAspect.customFilmsList)!
|
return InheritedModel.inheritFrom<Films>(context, aspect: _FilmsModelAspect.customFilms)!
|
||||||
.customFilms
|
.customFilms
|
||||||
.values
|
.values
|
||||||
.map((value) => value.film)
|
.map((value) => value.film)
|
||||||
|
@ -159,7 +169,12 @@ class Films extends InheritedModel<_FilmsModelAspect> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool updateShouldNotifyDependent(Films oldWidget, Set<_FilmsModelAspect> dependencies) {
|
bool updateShouldNotifyDependent(Films oldWidget, Set<_FilmsModelAspect> dependencies) {
|
||||||
// TODO: reduce unnecessary notifications
|
return (dependencies.contains(_FilmsModelAspect.selected) && oldWidget.selected != selected) ||
|
||||||
return true;
|
((dependencies.contains(_FilmsModelAspect.predefinedFilms) ||
|
||||||
|
dependencies.contains(_FilmsModelAspect.filmsInUse)) &&
|
||||||
|
const DeepCollectionEquality().equals(oldWidget.predefinedFilms, predefinedFilms)) ||
|
||||||
|
((dependencies.contains(_FilmsModelAspect.customFilms) ||
|
||||||
|
dependencies.contains(_FilmsModelAspect.filmsInUse)) &&
|
||||||
|
const DeepCollectionEquality().equals(oldWidget.customFilms, customFilms));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ dependencies:
|
||||||
camera: 0.10.5+2
|
camera: 0.10.5+2
|
||||||
camera_android_camerax: 0.6.1+1
|
camera_android_camerax: 0.6.1+1
|
||||||
clipboard: 0.1.3
|
clipboard: 0.1.3
|
||||||
|
collection: any
|
||||||
dynamic_color: 1.7.0
|
dynamic_color: 1.7.0
|
||||||
exif: 3.1.4
|
exif: 3.1.4
|
||||||
firebase_analytics: 10.6.2
|
firebase_analytics: 10.6.2
|
||||||
|
@ -31,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.0
|
ref: v1.1.1
|
||||||
m3_lightmeter_resources:
|
m3_lightmeter_resources:
|
||||||
git:
|
git:
|
||||||
url: "https://github.com/vodemn/m3_lightmeter_resources"
|
url: "https://github.com/vodemn/m3_lightmeter_resources"
|
||||||
|
|
|
@ -50,19 +50,19 @@ void main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void expectPredefinedFilmsCount(int count) {
|
void expectPredefinedFilmsCount(int count) {
|
||||||
expect(find.text('Predefined films count: $count'), findsOneWidget);
|
expect(find.text(_PredefinedFilmsCount.text(count)), findsOneWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
void expectCustomFilmsCount(int count) {
|
void expectCustomFilmsCount(int count) {
|
||||||
expect(find.text('Custom films count: $count'), findsOneWidget);
|
expect(find.text(_CustomFilmsCount.text(count)), findsOneWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
void expectFilmsInUseCount(int count) {
|
void expectFilmsInUseCount(int count) {
|
||||||
expect(find.text('Films in use count: $count'), findsOneWidget);
|
expect(find.text(_FilmsInUseCount.text(count)), findsOneWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
void expectSelectedFilmName(String name) {
|
void expectSelectedFilmName(String name) {
|
||||||
expect(find.text('Selected film: $name'), findsOneWidget);
|
expect(find.text(_SelectedFilm.text(name)), findsOneWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
group(
|
group(
|
||||||
|
@ -234,15 +234,15 @@ class _Application extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return const MaterialApp(
|
||||||
home: Scaffold(
|
home: Scaffold(
|
||||||
body: Center(
|
body: Center(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Text("Predefined films count: ${Films.predefinedFilmsOf(context).length}"),
|
_PredefinedFilmsCount(),
|
||||||
Text("Custom films count: ${Films.customFilmsOf(context).length}"),
|
_CustomFilmsCount(),
|
||||||
Text("Films in use count: ${Films.inUseOf(context).length}"),
|
_FilmsInUseCount(),
|
||||||
Text("Selected film: ${Films.selectedOf(context).name}"),
|
_SelectedFilm(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -251,6 +251,50 @@ class _Application extends StatelessWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _PredefinedFilmsCount extends StatelessWidget {
|
||||||
|
static String text(int count) => "Predefined films count: $count";
|
||||||
|
|
||||||
|
const _PredefinedFilmsCount();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Text(text(Films.predefinedFilmsOf(context).length));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CustomFilmsCount extends StatelessWidget {
|
||||||
|
static String text(int count) => "Custom films count: $count";
|
||||||
|
|
||||||
|
const _CustomFilmsCount();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Text(text(Films.customFilmsOf(context).length));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _FilmsInUseCount extends StatelessWidget {
|
||||||
|
static String text(int count) => "Films in use count: $count";
|
||||||
|
|
||||||
|
const _FilmsInUseCount();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Text(text(Films.inUseOf(context).length));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SelectedFilm extends StatelessWidget {
|
||||||
|
static String text(String name) => "Selected film: $name}";
|
||||||
|
|
||||||
|
const _SelectedFilm();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Text(text(Films.selectedOf(context).name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const mockPredefinedFilms = [
|
const mockPredefinedFilms = [
|
||||||
FilmExponential(id: '1', name: 'Mock film 2x', iso: 400, exponent: 1.34),
|
FilmExponential(id: '1', name: 'Mock film 2x', iso: 400, exponent: 1.34),
|
||||||
FilmExponential(id: '2', name: 'Mock film 3x', iso: 800, exponent: 1.34),
|
FilmExponential(id: '2', name: 'Mock film 3x', iso: 800, exponent: 1.34),
|
||||||
|
|
Loading…
Reference in a new issue