added film picker

This commit is contained in:
Vadim 2023-04-01 19:15:43 +03:00
parent 0ff9249f8f
commit d0e847d25a
7 changed files with 115 additions and 45 deletions

View file

@ -7,6 +7,7 @@ import 'package:light_sensor/light_sensor.dart';
import 'package:lightmeter/data/caffeine_service.dart'; import 'package:lightmeter/data/caffeine_service.dart';
import 'package:lightmeter/data/haptics_service.dart'; import 'package:lightmeter/data/haptics_service.dart';
import 'package:lightmeter/data/models/supported_locale.dart'; import 'package:lightmeter/data/models/supported_locale.dart';
import 'package:lightmeter/providers/film_profile.dart';
import 'package:lightmeter/providers/supported_locale_provider.dart'; import 'package:lightmeter/providers/supported_locale_provider.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
@ -48,6 +49,7 @@ class Application extends StatelessWidget {
Provider(create: (_) => const LightSensorService()), Provider(create: (_) => const LightSensorService()),
], ],
child: StopTypeProvider( child: StopTypeProvider(
child: FilmProvider(
child: EquipmentProfileProvider( child: EquipmentProfileProvider(
child: EvSourceTypeProvider( child: EvSourceTypeProvider(
child: SupportedLocaleProvider( child: SupportedLocaleProvider(
@ -79,6 +81,7 @@ class Application extends StatelessWidget {
), ),
), ),
), ),
),
); );
} }
return const SizedBox(); return const SizedBox();

View file

@ -23,13 +23,13 @@ double log10polynomian(
/// do not have any reciprocity failure information, as these films are ment to be used in cinema /// do not have any reciprocity failure information, as these films are ment to be used in cinema
/// with appropriate light and pretty short shutter speeds. /// with appropriate light and pretty short shutter speeds.
/// ///
class Film { class FilmData {
final String name; final String name;
final int iso; final int iso;
const Film(this.name, this.iso); const FilmData(this.name, this.iso);
const Film.other() const FilmData.other()
: name = 'Other', : name = 'Other',
iso = 0; iso = 0;
@ -51,9 +51,8 @@ class Film {
@protected @protected
double reciprocityFormula(double t) => t; double reciprocityFormula(double t) => t;
static const List<Film> values = [ static const List<FilmData> values = [
Film.other(), FilmData.other(),
FomapanFilm.creative100(),
FomapanFilm.creative100(), FomapanFilm.creative100(),
FomapanFilm.creative200(), FomapanFilm.creative200(),
FomapanFilm.action400(), FomapanFilm.action400(),
@ -79,7 +78,7 @@ class Film {
/// https://www.tate.org.uk/documents/598/page_6_7_agfa_stocks_0.pdf /// https://www.tate.org.uk/documents/598/page_6_7_agfa_stocks_0.pdf
/// https://www.filmwasters.com/forum/index.php?topic=5298.0 /// https://www.filmwasters.com/forum/index.php?topic=5298.0
// {{1,1.87},{2,3.73},{3,8.06},{4,13.93},{5,21.28},{6,23.00},{7,30.12},{8,38.05},{9,44.75},{10,50.12},{20,117},{30,202},{40,293},{50,413},{60,547},{70,694},{80,853},{90,1022},{100,1202}}; // {{1,1.87},{2,3.73},{3,8.06},{4,13.93},{5,21.28},{6,23.00},{7,30.12},{8,38.05},{9,44.75},{10,50.12},{20,117},{30,202},{40,293},{50,413},{60,547},{70,694},{80,853},{90,1022},{100,1202}};
class AgfaFilm extends Film { class AgfaFilm extends FilmData {
final double a; final double a;
final double b; final double b;
final double c; final double c;
@ -100,7 +99,7 @@ class AgfaFilm extends Film {
double reciprocityFormula(double t) => t * log10polynomian(t, a, b, c); double reciprocityFormula(double t) => t * log10polynomian(t, a, b, c);
} }
class FomapanFilm extends Film { class FomapanFilm extends FilmData {
final double a; final double a;
final double b; final double b;
final double c; final double c;
@ -127,7 +126,7 @@ class FomapanFilm extends Film {
super('Fomapan ACTION 400', 400); super('Fomapan ACTION 400', 400);
} }
class IlfordFilm extends Film { class IlfordFilm extends FilmData {
final double reciprocityPower; final double reciprocityPower;
/// https://www.ilfordphoto.com/amfile/file/download/file/1948/product/1650/ /// https://www.ilfordphoto.com/amfile/file/download/file/1948/product/1650/
@ -189,7 +188,7 @@ class IlfordFilm extends Film {
double reciprocityFormula(double t) => pow(t, reciprocityPower).toDouble(); double reciprocityFormula(double t) => pow(t, reciprocityPower).toDouble();
} }
class KodakFilm extends Film { class KodakFilm extends FilmData {
final double a; final double a;
final double b; final double b;
final double c; final double c;

View file

@ -4,6 +4,7 @@ import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'models/ev_source_type.dart'; import 'models/ev_source_type.dart';
import 'models/film.dart';
import 'models/theme_type.dart'; import 'models/theme_type.dart';
class UserPreferencesService { class UserPreferencesService {
@ -13,6 +14,7 @@ class UserPreferencesService {
static const _evSourceTypeKey = "evSourceType"; static const _evSourceTypeKey = "evSourceType";
static const _cameraEvCalibrationKey = "cameraEvCalibration"; static const _cameraEvCalibrationKey = "cameraEvCalibration";
static const _lightSensorEvCalibrationKey = "lightSensorEvCalibration"; static const _lightSensorEvCalibrationKey = "lightSensorEvCalibration";
static const _filmKey = "film";
static const _caffeineKey = "caffeine"; static const _caffeineKey = "caffeine";
static const _hapticsKey = "haptics"; static const _hapticsKey = "haptics";
@ -63,16 +65,13 @@ class UserPreferencesService {
} }
} }
IsoValue get iso => IsoValue get iso => isoValues.firstWhere((v) => v.value == (_sharedPreferences.getInt(_isoKey) ?? 100));
isoValues.firstWhere((v) => v.value == (_sharedPreferences.getInt(_isoKey) ?? 100));
set iso(IsoValue value) => _sharedPreferences.setInt(_isoKey, value.value); set iso(IsoValue value) => _sharedPreferences.setInt(_isoKey, value.value);
NdValue get ndFilter => NdValue get ndFilter => ndValues.firstWhere((v) => v.value == (_sharedPreferences.getInt(_ndFilterKey) ?? 0));
ndValues.firstWhere((v) => v.value == (_sharedPreferences.getInt(_ndFilterKey) ?? 0));
set ndFilter(NdValue value) => _sharedPreferences.setInt(_ndFilterKey, value.value); set ndFilter(NdValue value) => _sharedPreferences.setInt(_ndFilterKey, value.value);
EvSourceType get evSourceType => EvSourceType get evSourceType => EvSourceType.values[_sharedPreferences.getInt(_evSourceTypeKey) ?? 0];
EvSourceType.values[_sharedPreferences.getInt(_evSourceTypeKey) ?? 0];
set evSourceType(EvSourceType value) => _sharedPreferences.setInt(_evSourceTypeKey, value.index); set evSourceType(EvSourceType value) => _sharedPreferences.setInt(_evSourceTypeKey, value.index);
bool get caffeine => _sharedPreferences.getBool(_caffeineKey) ?? false; bool get caffeine => _sharedPreferences.getBool(_caffeineKey) ?? false;
@ -88,13 +87,10 @@ class UserPreferencesService {
set locale(SupportedLocale value) => _sharedPreferences.setString(_localeKey, value.toString()); set locale(SupportedLocale value) => _sharedPreferences.setString(_localeKey, value.toString());
double get cameraEvCalibration => _sharedPreferences.getDouble(_cameraEvCalibrationKey) ?? 0.0; double get cameraEvCalibration => _sharedPreferences.getDouble(_cameraEvCalibrationKey) ?? 0.0;
set cameraEvCalibration(double value) => set cameraEvCalibration(double value) => _sharedPreferences.setDouble(_cameraEvCalibrationKey, value);
_sharedPreferences.setDouble(_cameraEvCalibrationKey, value);
double get lightSensorEvCalibration => double get lightSensorEvCalibration => _sharedPreferences.getDouble(_lightSensorEvCalibrationKey) ?? 0.0;
_sharedPreferences.getDouble(_lightSensorEvCalibrationKey) ?? 0.0; set lightSensorEvCalibration(double value) => _sharedPreferences.setDouble(_lightSensorEvCalibrationKey, value);
set lightSensorEvCalibration(double value) =>
_sharedPreferences.setDouble(_lightSensorEvCalibrationKey, value);
ThemeType get themeType => ThemeType.values[_sharedPreferences.getInt(_themeTypeKey) ?? 0]; ThemeType get themeType => ThemeType.values[_sharedPreferences.getInt(_themeTypeKey) ?? 0];
set themeType(ThemeType value) => _sharedPreferences.setInt(_themeTypeKey, value.index); set themeType(ThemeType value) => _sharedPreferences.setInt(_themeTypeKey, value.index);
@ -105,6 +101,12 @@ class UserPreferencesService {
bool get dynamicColor => _sharedPreferences.getBool(_dynamicColorKey) ?? false; bool get dynamicColor => _sharedPreferences.getBool(_dynamicColorKey) ?? false;
set dynamicColor(bool value) => _sharedPreferences.setBool(_dynamicColorKey, value); set dynamicColor(bool value) => _sharedPreferences.setBool(_dynamicColorKey, value);
FilmData get film => FilmData.values.firstWhere(
(e) => e.name == _sharedPreferences.getString(_filmKey),
orElse: () => FilmData.values.first,
);
set film(FilmData value) => _sharedPreferences.setString(_filmKey, value.name);
String get selectedEquipmentProfileId => ''; String get selectedEquipmentProfileId => '';
set selectedEquipmentProfileId(String id) {} set selectedEquipmentProfileId(String id) {}

View file

@ -34,6 +34,7 @@
"calibrationMessageCameraOnly": "The accuracy of the readings measured by this application depends entirely on the rear camera of the device. Therefore, consider testing this application and setting up an EV calibration value that will give you the desired measurement results.", "calibrationMessageCameraOnly": "The accuracy of the readings measured by this application depends entirely on the rear camera of the device. Therefore, consider testing this application and setting up an EV calibration value that will give you the desired measurement results.",
"camera": "Camera", "camera": "Camera",
"lightSensor": "Light sensor", "lightSensor": "Light sensor",
"film": "Film",
"equipment": "Equipment", "equipment": "Equipment",
"equipmentProfileName": "Equipment profile name", "equipmentProfileName": "Equipment profile name",
"equipmentProfileNameHint": "Praktica MTL5B", "equipmentProfileNameHint": "Praktica MTL5B",

View file

@ -34,6 +34,7 @@
"calibrationMessageCameraOnly": "La précision des lectures mesurées par cette application dépend entièrement de la caméra arrière de l'appareil. Par conséquent, envisagez de tester cette application et de configurer une valeur d'étalonnage EV qui vous donnera les résultats de mesure souhaités.", "calibrationMessageCameraOnly": "La précision des lectures mesurées par cette application dépend entièrement de la caméra arrière de l'appareil. Par conséquent, envisagez de tester cette application et de configurer une valeur d'étalonnage EV qui vous donnera les résultats de mesure souhaités.",
"camera": "Caméra", "camera": "Caméra",
"lightSensor": "Capteur de lumière", "lightSensor": "Capteur de lumière",
"film": "Pellicule",
"equipment": "Équipement", "equipment": "Équipement",
"equipmentProfileName": "Nom du profil de l'équipement", "equipmentProfileName": "Nom du profil de l'équipement",
"equipmentProfileNameHint": "Praktica MTL5B", "equipmentProfileNameHint": "Praktica MTL5B",

View file

@ -34,6 +34,7 @@
"calibrationMessageCameraOnly": "Точность измерений данного приложения полностью зависит от точности камеры вашего устройства. Поэтому рекомендуется самостоятельно подобрать калибровочное значение, которое даст желаемый результат измерений.", "calibrationMessageCameraOnly": "Точность измерений данного приложения полностью зависит от точности камеры вашего устройства. Поэтому рекомендуется самостоятельно подобрать калибровочное значение, которое даст желаемый результат измерений.",
"camera": "Камера", "camera": "Камера",
"lightSensor": "Датчик освещённости", "lightSensor": "Датчик освещённости",
"film": "Пленка",
"equipment": "Оборудование", "equipment": "Оборудование",
"equipmentProfileName": "Название профиля", "equipmentProfileName": "Название профиля",
"equipmentProfileNameHint": "Praktica MTL5B", "equipmentProfileNameHint": "Praktica MTL5B",

View file

@ -0,0 +1,63 @@
import 'package:flutter/material.dart';
import 'package:lightmeter/data/models/film.dart';
import 'package:lightmeter/data/shared_prefs_service.dart';
import 'package:provider/provider.dart';
class FilmProvider extends StatefulWidget {
final Widget child;
const FilmProvider({required this.child, super.key});
static FilmProviderState of(BuildContext context) {
return context.findAncestorStateOfType<FilmProviderState>()!;
}
@override
State<FilmProvider> createState() => FilmProviderState();
}
class FilmProviderState extends State<FilmProvider> {
late FilmData _selectedFilm;
@override
void initState() {
super.initState();
_selectedFilm = context.read<UserPreferencesService>().film;
}
@override
Widget build(BuildContext context) {
return Film(
data: _selectedFilm,
child: widget.child,
);
}
void setFilm(FilmData data) {
setState(() {
_selectedFilm = data;
});
context.read<UserPreferencesService>().film = _selectedFilm;
}
}
class Film extends InheritedWidget {
final FilmData data;
const Film({
required this.data,
required super.child,
super.key,
});
static FilmData of(BuildContext context, {bool listen = true}) {
if (listen) {
return context.dependOnInheritedWidgetOfExactType<Film>()!.data;
} else {
return context.findAncestorWidgetOfExactType<Film>()!.data;
}
}
@override
bool updateShouldNotify(Film oldWidget) => true;
}