mirror of
https://github.com/vodemn/m3_lightmeter.git
synced 2024-11-25 08:50:40 +00:00
wip
This commit is contained in:
parent
57fbeeb88f
commit
7d1c1ebc9f
13 changed files with 47 additions and 51 deletions
|
@ -1,7 +1,7 @@
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
|
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
|
||||||
|
|
||||||
typedef SelectableFilm<T extends Film> = ({T film, bool isUsed});
|
typedef SelectableValue<T extends Film> = ({T film, bool isUsed});
|
||||||
|
|
||||||
class FilmsStorageService {
|
class FilmsStorageService {
|
||||||
FilmsStorageService();
|
FilmsStorageService();
|
||||||
|
@ -22,11 +22,11 @@ class FilmsStorageService {
|
||||||
|
|
||||||
Future<void> deleteFilm(FilmExponential _) async {}
|
Future<void> deleteFilm(FilmExponential _) async {}
|
||||||
|
|
||||||
Future<Map<String, SelectableFilm<Film>>> getPredefinedFilms() async {
|
Future<Map<String, SelectableValue<Film>>> getPredefinedFilms() async {
|
||||||
return const {};
|
return const {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Map<String, SelectableFilm<FilmExponential>>> getCustomFilms() async {
|
Future<Map<String, SelectableValue<FilmExponential>>> getCustomFilms() async {
|
||||||
return const {};
|
return const {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import 'package:lightmeter/screens/settings/components/shared/dialog_range_picke
|
||||||
import 'package:lightmeter/screens/settings/screen_settings.dart';
|
import 'package:lightmeter/screens/settings/screen_settings.dart';
|
||||||
import 'package:lightmeter/utils/double_to_zoom.dart';
|
import 'package:lightmeter/utils/double_to_zoom.dart';
|
||||||
import 'package:lightmeter/utils/platform_utils.dart';
|
import 'package:lightmeter/utils/platform_utils.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:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
@ -49,7 +50,7 @@ void testE2E(String description) {
|
||||||
(tester) async {
|
(tester) async {
|
||||||
await tester.pumpApplication(
|
await tester.pumpApplication(
|
||||||
equipmentProfiles: {},
|
equipmentProfiles: {},
|
||||||
predefinedFilms: mockFilms.toFilmsMap(isUsed: true),
|
predefinedFilms: mockFilms.toSelectableMap(),
|
||||||
customFilms: {},
|
customFilms: {},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -10,24 +10,24 @@ class _MockEquipmentProfilesStorageService extends Mock implements EquipmentProf
|
||||||
class _MockFilmsStorageService extends Mock implements FilmsStorageService {}
|
class _MockFilmsStorageService extends Mock implements FilmsStorageService {}
|
||||||
|
|
||||||
class MockIAPProviders extends StatefulWidget {
|
class MockIAPProviders extends StatefulWidget {
|
||||||
final Map<String, EquipmentProfile> equipmentProfiles;
|
final SelectableMap<EquipmentProfile> equipmentProfiles;
|
||||||
final String selectedEquipmentProfileId;
|
final String selectedEquipmentProfileId;
|
||||||
final Map<String, SelectableFilm<Film>> predefinedFilms;
|
final Map<String, SelectableValue<Film>> predefinedFilms;
|
||||||
final Map<String, SelectableFilm<FilmExponential>> customFilms;
|
final Map<String, SelectableValue<FilmExponential>> customFilms;
|
||||||
final String selectedFilmId;
|
final String selectedFilmId;
|
||||||
final Widget child;
|
final Widget child;
|
||||||
|
|
||||||
MockIAPProviders({
|
MockIAPProviders({
|
||||||
Map<String, EquipmentProfile>? equipmentProfiles,
|
SelectableMap<EquipmentProfile>? equipmentProfiles,
|
||||||
this.selectedEquipmentProfileId = '',
|
this.selectedEquipmentProfileId = '',
|
||||||
Map<String, SelectableFilm<Film>>? predefinedFilms,
|
Map<String, SelectableValue<Film>>? predefinedFilms,
|
||||||
Map<String, SelectableFilm<FilmExponential>>? customFilms,
|
Map<String, SelectableValue<FilmExponential>>? customFilms,
|
||||||
String? selectedFilmId,
|
String? selectedFilmId,
|
||||||
required this.child,
|
required this.child,
|
||||||
super.key,
|
super.key,
|
||||||
}) : equipmentProfiles = equipmentProfiles ?? mockEquipmentProfiles.toProfilesMap(),
|
}) : equipmentProfiles = equipmentProfiles ?? mockEquipmentProfiles.toSelectableMap(),
|
||||||
predefinedFilms = predefinedFilms ?? mockFilms.toFilmsMap(),
|
predefinedFilms = predefinedFilms ?? mockFilms.toSelectableMap(),
|
||||||
customFilms = customFilms ?? mockFilms.toFilmsMap(),
|
customFilms = customFilms ?? mockFilms.toSelectableMap(),
|
||||||
selectedFilmId = selectedFilmId ?? const FilmStub().id;
|
selectedFilmId = selectedFilmId ?? const FilmStub().id;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -155,15 +155,6 @@ const mockFilms = [
|
||||||
_FilmMultiplying(id: '4', name: 'Mock film 4', iso: 1200, reciprocityMultiplier: 1.5),
|
_FilmMultiplying(id: '4', name: 'Mock film 4', iso: 1200, reciprocityMultiplier: 1.5),
|
||||||
];
|
];
|
||||||
|
|
||||||
extension EquipmentProfileMapper on List<EquipmentProfile> {
|
|
||||||
Map<String, EquipmentProfile> toProfilesMap() => Map.fromEntries(map((e) => MapEntry(e.id, e)));
|
|
||||||
}
|
|
||||||
|
|
||||||
extension FilmMapper on List<Film> {
|
|
||||||
Map<String, ({T film, bool isUsed})> toFilmsMap<T extends Film>({bool isUsed = true}) =>
|
|
||||||
Map.fromEntries(map((e) => MapEntry(e.id, (film: e as T, isUsed: isUsed))));
|
|
||||||
}
|
|
||||||
|
|
||||||
class _FilmMultiplying extends FilmExponential {
|
class _FilmMultiplying extends FilmExponential {
|
||||||
final double reciprocityMultiplier;
|
final double reciprocityMultiplier;
|
||||||
|
|
||||||
|
|
|
@ -20,10 +20,10 @@ const mockPhotoEv100 = 8.3;
|
||||||
extension WidgetTesterCommonActions on WidgetTester {
|
extension WidgetTesterCommonActions on WidgetTester {
|
||||||
Future<void> pumpApplication({
|
Future<void> pumpApplication({
|
||||||
IAPProductStatus productStatus = IAPProductStatus.purchased,
|
IAPProductStatus productStatus = IAPProductStatus.purchased,
|
||||||
Map<String, EquipmentProfile>? equipmentProfiles,
|
SelectableMap<EquipmentProfile>? equipmentProfiles,
|
||||||
String selectedEquipmentProfileId = '',
|
String selectedEquipmentProfileId = '',
|
||||||
Map<String, SelectableFilm<Film>>? predefinedFilms,
|
Map<String, SelectableValue<Film>>? predefinedFilms,
|
||||||
Map<String, SelectableFilm<FilmExponential>>? customFilms,
|
Map<String, SelectableValue<FilmExponential>>? customFilms,
|
||||||
String selectedFilmId = '',
|
String selectedFilmId = '',
|
||||||
}) async {
|
}) async {
|
||||||
await pumpWidget(
|
await pumpWidget(
|
||||||
|
|
|
@ -34,7 +34,7 @@ class EquipmentProfilesProvider extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class EquipmentProfilesProviderState extends State<EquipmentProfilesProvider> {
|
class EquipmentProfilesProviderState extends State<EquipmentProfilesProvider> {
|
||||||
final Map<String, EquipmentProfile> _customProfiles = {};
|
final SelectableMap<EquipmentProfile> _customProfiles = {};
|
||||||
String _selectedId = '';
|
String _selectedId = '';
|
||||||
|
|
||||||
EquipmentProfile get _selectedProfile => _customProfiles[_selectedId] ?? EquipmentProfilesProvider.defaultProfile;
|
EquipmentProfile get _selectedProfile => _customProfiles[_selectedId] ?? EquipmentProfilesProvider.defaultProfile;
|
||||||
|
|
|
@ -25,11 +25,11 @@ class FilmsProvider extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class FilmsProviderState extends State<FilmsProvider> {
|
class FilmsProviderState extends State<FilmsProvider> {
|
||||||
final Map<String, SelectableFilm<Film>> predefinedFilms = {};
|
final Map<String, SelectableValue<Film>> predefinedFilms = {};
|
||||||
final Map<String, SelectableFilm<FilmExponential>> customFilms = {};
|
final Map<String, SelectableValue<FilmExponential>> customFilms = {};
|
||||||
String _selectedId = '';
|
String _selectedId = '';
|
||||||
|
|
||||||
Film get _selectedFilm => customFilms[_selectedId]?.film ?? predefinedFilms[_selectedId]?.film ?? const FilmStub();
|
Film get _selectedFilm => customFilms[_selectedId]?.value ?? predefinedFilms[_selectedId]?.value ?? const FilmStub();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
@ -60,9 +60,9 @@ class FilmsProviderState extends State<FilmsProvider> {
|
||||||
|
|
||||||
Future<void> toggleFilm(Film film, bool enabled) async {
|
Future<void> toggleFilm(Film film, bool enabled) async {
|
||||||
if (predefinedFilms.containsKey(film.id)) {
|
if (predefinedFilms.containsKey(film.id)) {
|
||||||
predefinedFilms[film.id] = (film: film, isUsed: enabled);
|
predefinedFilms[film.id] = (value: film, isUsed: enabled);
|
||||||
} else if (customFilms.containsKey(film.id)) {
|
} else if (customFilms.containsKey(film.id)) {
|
||||||
customFilms[film.id] = (film: film as FilmExponential, isUsed: enabled);
|
customFilms[film.id] = (value: film as FilmExponential, isUsed: enabled);
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -84,13 +84,13 @@ 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.storageService.addFilm(film, isUsed: true);
|
await widget.storageService.addFilm(film, isUsed: true);
|
||||||
customFilms[film.id] = (film: film, isUsed: true);
|
customFilms[film.id] = (value: film, isUsed: true);
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updateCustomFilm(FilmExponential film) async {
|
Future<void> updateCustomFilm(FilmExponential film) async {
|
||||||
await widget.storageService.updateFilm(film);
|
await widget.storageService.updateFilm(film);
|
||||||
customFilms[film.id] = (film: film, isUsed: customFilms[film.id]!.isUsed);
|
customFilms[film.id] = (value: film, isUsed: customFilms[film.id]!.isUsed);
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,10 +121,10 @@ enum _FilmsModelAspect {
|
||||||
}
|
}
|
||||||
|
|
||||||
class Films extends InheritedModel<_FilmsModelAspect> {
|
class Films extends InheritedModel<_FilmsModelAspect> {
|
||||||
final Map<String, SelectableFilm<Film>> predefinedFilms;
|
final Map<String, SelectableValue<Film>> predefinedFilms;
|
||||||
|
|
||||||
@protected
|
@protected
|
||||||
final Map<String, SelectableFilm<FilmExponential>> customFilms;
|
final Map<String, SelectableValue<FilmExponential>> customFilms;
|
||||||
final Film selected;
|
final Film selected;
|
||||||
|
|
||||||
const Films({
|
const Films({
|
||||||
|
@ -138,7 +138,7 @@ class Films extends InheritedModel<_FilmsModelAspect> {
|
||||||
return InheritedModel.inheritFrom<Films>(context, aspect: _FilmsModelAspect.predefinedFilms)!
|
return InheritedModel.inheritFrom<Films>(context, aspect: _FilmsModelAspect.predefinedFilms)!
|
||||||
.predefinedFilms
|
.predefinedFilms
|
||||||
.values
|
.values
|
||||||
.map((value) => value.film)
|
.map((value) => value.value)
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ class Films extends InheritedModel<_FilmsModelAspect> {
|
||||||
return InheritedModel.inheritFrom<Films>(context, aspect: _FilmsModelAspect.customFilms)!
|
return InheritedModel.inheritFrom<Films>(context, aspect: _FilmsModelAspect.customFilms)!
|
||||||
.customFilms
|
.customFilms
|
||||||
.values
|
.values
|
||||||
.map((value) => value.film)
|
.map((value) => value.value)
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,8 +155,8 @@ class Films extends InheritedModel<_FilmsModelAspect> {
|
||||||
final model = InheritedModel.inheritFrom<Films>(context, aspect: _FilmsModelAspect.filmsInUse)!;
|
final model = InheritedModel.inheritFrom<Films>(context, aspect: _FilmsModelAspect.filmsInUse)!;
|
||||||
return [
|
return [
|
||||||
const FilmStub(),
|
const FilmStub(),
|
||||||
...model.customFilms.values.where((e) => e.isUsed).map((e) => e.film),
|
...model.customFilms.values.where((e) => e.isUsed).map((e) => e.value),
|
||||||
...model.predefinedFilms.values.where((e) => e.isUsed).map((e) => e.film),
|
...model.predefinedFilms.values.where((e) => e.isUsed).map((e) => e.value),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,9 +89,12 @@ class _EquipmentProfilesListBuilder extends StatelessWidget {
|
||||||
top: index == 0 ? Dimens.paddingM : 0.0,
|
top: index == 0 ? Dimens.paddingM : 0.0,
|
||||||
bottom: index == values.length - 1 ? Dimens.paddingM : 0.0,
|
bottom: index == values.length - 1 ? Dimens.paddingM : 0.0,
|
||||||
),
|
),
|
||||||
child: ListTile(
|
child: CheckboxListTile(
|
||||||
title: Text(values[index].name),
|
title: Text(values[index].name),
|
||||||
trailing: IconButton(
|
controlAffinity: ListTileControlAffinity.leading,
|
||||||
|
value: false,
|
||||||
|
onChanged: (value) {},
|
||||||
|
secondary: IconButton(
|
||||||
onPressed: () => onEdit(values[index]),
|
onPressed: () => onEdit(values[index]),
|
||||||
icon: const Icon(Icons.edit),
|
icon: const Icon(Icons.edit),
|
||||||
),
|
),
|
||||||
|
|
|
@ -23,6 +23,7 @@ import 'package:lightmeter/screens/settings/screen_settings.dart';
|
||||||
import 'package:lightmeter/screens/shared/animated_circular_button/widget_button_circular_animated.dart';
|
import 'package:lightmeter/screens/shared/animated_circular_button/widget_button_circular_animated.dart';
|
||||||
import 'package:lightmeter/screens/timer/screen_timer.dart';
|
import 'package:lightmeter/screens/timer/screen_timer.dart';
|
||||||
import 'package:lightmeter/utils/platform_utils.dart';
|
import 'package:lightmeter/utils/platform_utils.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:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
@ -92,7 +93,7 @@ void main() {
|
||||||
testWidgets('Generate light theme screenshots', (tester) async {
|
testWidgets('Generate light theme screenshots', (tester) async {
|
||||||
await mockSharedPrefs(theme: ThemeType.light, color: _lightThemeColor);
|
await mockSharedPrefs(theme: ThemeType.light, color: _lightThemeColor);
|
||||||
await tester.pumpApplication(
|
await tester.pumpApplication(
|
||||||
predefinedFilms: [_mockFilm].toFilmsMap(),
|
predefinedFilms: [_mockFilm].toSelectableMap(),
|
||||||
customFilms: {},
|
customFilms: {},
|
||||||
selectedFilmId: _mockFilm.id,
|
selectedFilmId: _mockFilm.id,
|
||||||
);
|
);
|
||||||
|
@ -132,7 +133,7 @@ void main() {
|
||||||
(tester) async {
|
(tester) async {
|
||||||
await mockSharedPrefs(theme: ThemeType.dark, color: _darkThemeColor);
|
await mockSharedPrefs(theme: ThemeType.dark, color: _darkThemeColor);
|
||||||
await tester.pumpApplication(
|
await tester.pumpApplication(
|
||||||
predefinedFilms: [_mockFilm].toFilmsMap(),
|
predefinedFilms: [_mockFilm].toSelectableMap(),
|
||||||
customFilms: {},
|
customFilms: {},
|
||||||
selectedFilmId: _mockFilm.id,
|
selectedFilmId: _mockFilm.id,
|
||||||
);
|
);
|
||||||
|
@ -157,7 +158,7 @@ void main() {
|
||||||
color: _lightThemeColor,
|
color: _lightThemeColor,
|
||||||
);
|
);
|
||||||
await tester.pumpApplication(
|
await tester.pumpApplication(
|
||||||
predefinedFilms: [_mockFilm].toFilmsMap(),
|
predefinedFilms: [_mockFilm].toSelectableMap(),
|
||||||
customFilms: {},
|
customFilms: {},
|
||||||
selectedFilmId: _mockFilm.id,
|
selectedFilmId: _mockFilm.id,
|
||||||
);
|
);
|
||||||
|
|
|
@ -27,7 +27,7 @@ void main() {
|
||||||
),
|
),
|
||||||
).thenAnswer((_) async {});
|
).thenAnswer((_) async {});
|
||||||
when(() => storageService.deleteProfile(any<String>())).thenAnswer((_) async {});
|
when(() => storageService.deleteProfile(any<String>())).thenAnswer((_) async {});
|
||||||
when(() => storageService.getProfiles()).thenAnswer((_) => Future.value(_customProfiles.toProfilesMap()));
|
when(() => storageService.getProfiles()).thenAnswer((_) => Future.value(_customProfiles.toSelectableMap()));
|
||||||
});
|
});
|
||||||
|
|
||||||
tearDown(() {
|
tearDown(() {
|
||||||
|
@ -66,7 +66,7 @@ void main() {
|
||||||
() {
|
() {
|
||||||
setUp(() {
|
setUp(() {
|
||||||
when(() => storageService.selectedEquipmentProfileId).thenReturn(_customProfiles.first.id);
|
when(() => storageService.selectedEquipmentProfileId).thenReturn(_customProfiles.first.id);
|
||||||
when(() => storageService.getProfiles()).thenAnswer((_) => Future.value(_customProfiles.toProfilesMap()));
|
when(() => storageService.getProfiles()).thenAnswer((_) => Future.value(_customProfiles.toSelectableMap()));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets(
|
testWidgets(
|
||||||
|
|
|
@ -305,6 +305,6 @@ const mockCustomFilms = [
|
||||||
];
|
];
|
||||||
|
|
||||||
extension on List<Film> {
|
extension on List<Film> {
|
||||||
Map<String, ({T film, bool isUsed})> toFilmsMap<T extends Film>() =>
|
Map<String, ({T value, bool isUsed})> toFilmsMap<T extends Film>() =>
|
||||||
Map.fromEntries(map((e) => MapEntry(e.id, (film: e as T, isUsed: true))));
|
Map.fromEntries(map((e) => MapEntry(e.id, (value: e as T, isUsed: true))));
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ void main() {
|
||||||
|
|
||||||
setUpAll(() {
|
setUpAll(() {
|
||||||
storageService = _MockEquipmentProfilesStorageService();
|
storageService = _MockEquipmentProfilesStorageService();
|
||||||
when(() => storageService.getProfiles()).thenAnswer((_) async => _mockEquipmentProfiles.toProfilesMap());
|
when(() => storageService.getProfiles()).thenAnswer((_) async => _mockEquipmentProfiles.toSelectableMap());
|
||||||
when(() => storageService.selectedEquipmentProfileId).thenReturn('');
|
when(() => storageService.selectedEquipmentProfileId).thenReturn('');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ void main() {
|
||||||
setUpAll(() {
|
setUpAll(() {
|
||||||
mockFilmsStorageService = _MockFilmsStorageService();
|
mockFilmsStorageService = _MockFilmsStorageService();
|
||||||
when(() => mockFilmsStorageService.getPredefinedFilms()).thenAnswer(
|
when(() => mockFilmsStorageService.getPredefinedFilms()).thenAnswer(
|
||||||
(_) => Future.value(Map.fromEntries(_films.map((e) => MapEntry(e.id, (film: e, isUsed: true))))),
|
(_) => Future.value(Map.fromEntries(_films.map((e) => MapEntry(e.id, (value: e, isUsed: true))))),
|
||||||
);
|
);
|
||||||
when(() => mockFilmsStorageService.getCustomFilms()).thenAnswer(
|
when(() => mockFilmsStorageService.getCustomFilms()).thenAnswer(
|
||||||
(_) => Future.value({}),
|
(_) => Future.value({}),
|
||||||
|
|
|
@ -26,7 +26,7 @@ void main() {
|
||||||
),
|
),
|
||||||
).thenAnswer((_) async {});
|
).thenAnswer((_) async {});
|
||||||
when(() => storageService.deleteProfile(any<String>())).thenAnswer((_) async {});
|
when(() => storageService.deleteProfile(any<String>())).thenAnswer((_) async {});
|
||||||
when(() => storageService.getProfiles()).thenAnswer((_) => Future.value(_customProfiles.toProfilesMap()));
|
when(() => storageService.getProfiles()).thenAnswer((_) => Future.value(_customProfiles.toSelectableMap()));
|
||||||
});
|
});
|
||||||
|
|
||||||
tearDown(() {
|
tearDown(() {
|
||||||
|
|
Loading…
Reference in a new issue