mirror of
https://github.com/vodemn/m3_lightmeter.git
synced 2024-11-22 07:20:39 +00:00
implemented CRUD for custom films
This commit is contained in:
parent
9884a6147f
commit
68cecf5391
12 changed files with 207 additions and 59 deletions
|
@ -50,6 +50,7 @@ class Application extends StatelessWidget {
|
||||||
NavigationRoutes.meteringScreen.name: (_) => const ReleaseNotesFlow(child: MeteringFlow()),
|
NavigationRoutes.meteringScreen.name: (_) => const ReleaseNotesFlow(child: MeteringFlow()),
|
||||||
NavigationRoutes.settingsScreen.name: (_) => const SettingsFlow(),
|
NavigationRoutes.settingsScreen.name: (_) => const SettingsFlow(),
|
||||||
NavigationRoutes.filmsListScreen.name: (_) => const FilmsScreen(),
|
NavigationRoutes.filmsListScreen.name: (_) => const FilmsScreen(),
|
||||||
|
NavigationRoutes.filmAddScreen.name: (_) => const FilmEditFlow(args: FilmEditArgs()),
|
||||||
NavigationRoutes.filmEditScreen.name: (context) => FilmEditFlow(args: context.routeArgs<FilmEditArgs>()),
|
NavigationRoutes.filmEditScreen.name: (context) => FilmEditFlow(args: context.routeArgs<FilmEditArgs>()),
|
||||||
NavigationRoutes.proFeaturesScreen.name: (_) => LightmeterProScreen(),
|
NavigationRoutes.proFeaturesScreen.name: (_) => LightmeterProScreen(),
|
||||||
NavigationRoutes.timerScreen.name: (context) => TimerFlow(args: context.routeArgs<TimerFlowArgs>()),
|
NavigationRoutes.timerScreen.name: (context) => TimerFlow(args: context.routeArgs<TimerFlowArgs>()),
|
||||||
|
|
|
@ -2,6 +2,7 @@ enum NavigationRoutes {
|
||||||
meteringScreen,
|
meteringScreen,
|
||||||
settingsScreen,
|
settingsScreen,
|
||||||
filmsListScreen,
|
filmsListScreen,
|
||||||
|
filmAddScreen,
|
||||||
filmEditScreen,
|
filmEditScreen,
|
||||||
proFeaturesScreen,
|
proFeaturesScreen,
|
||||||
timerScreen,
|
timerScreen,
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
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: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';
|
||||||
|
|
||||||
|
@ -25,13 +24,23 @@ class FilmsProvider extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class FilmsProviderState extends State<FilmsProvider> {
|
class FilmsProviderState extends State<FilmsProvider> {
|
||||||
late List<Film> _filmsInUse;
|
late final Map<String, _SelectableFilm<Film>> predefinedFilms = Map.fromEntries(
|
||||||
|
(widget.availableFilms ?? films).map(
|
||||||
|
(film) => MapEntry(
|
||||||
|
film.id,
|
||||||
|
(
|
||||||
|
film: film,
|
||||||
|
selected: widget.storageService.filmsInUse.contains(film),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
final Map<String, _SelectableFilm<FilmExponential>> customFilms = {};
|
||||||
late Film _selected;
|
late Film _selected;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_filmsInUse = widget.storageService.filmsInUse;
|
|
||||||
_selected = widget.storageService.selectedFilm;
|
_selected = widget.storageService.selectedFilm;
|
||||||
_discardSelectedIfNotIncluded();
|
_discardSelectedIfNotIncluded();
|
||||||
}
|
}
|
||||||
|
@ -39,20 +48,34 @@ class FilmsProviderState extends State<FilmsProvider> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Films(
|
return Films(
|
||||||
values: [
|
predefinedFilms: predefinedFilms,
|
||||||
const FilmStub(),
|
customFilms: customFilms,
|
||||||
...widget.availableFilms ?? films,
|
|
||||||
],
|
|
||||||
filmsInUse: [
|
|
||||||
const FilmStub(),
|
|
||||||
if (context.isPro) ..._filmsInUse,
|
|
||||||
],
|
|
||||||
selected: context.isPro ? _selected : const FilmStub(),
|
selected: context.isPro ? _selected : const FilmStub(),
|
||||||
child: widget.child,
|
child: widget.child,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setFilm(Film film) {
|
/* Both type of films **/
|
||||||
|
|
||||||
|
void toggleFilm(Film film, bool enabled) {
|
||||||
|
Film? targetFilm = predefinedFilms[film.id]?.film;
|
||||||
|
if (targetFilm != null) {
|
||||||
|
predefinedFilms[film.id] = (film: film, selected: enabled);
|
||||||
|
_discardSelectedIfNotIncluded();
|
||||||
|
setState(() {});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
targetFilm = customFilms[film.id]?.film;
|
||||||
|
if (targetFilm != null) {
|
||||||
|
customFilms[film.id] = (film: film as FilmExponential, selected: enabled);
|
||||||
|
_discardSelectedIfNotIncluded();
|
||||||
|
setState(() {});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void selectFilm(Film film) {
|
||||||
if (_selected != film) {
|
if (_selected != film) {
|
||||||
_selected = film;
|
_selected = film;
|
||||||
widget.storageService.selectedFilm = film;
|
widget.storageService.selectedFilm = film;
|
||||||
|
@ -60,47 +83,99 @@ class FilmsProviderState extends State<FilmsProvider> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void saveFilms(List<Film> films) {
|
/* Custom films **/
|
||||||
_filmsInUse = films;
|
|
||||||
widget.storageService.filmsInUse = films;
|
void addCustomFilm(FilmExponential film) {
|
||||||
|
customFilms[film.id] = (film: film, selected: false);
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateCustomFilm(FilmExponential film) {
|
||||||
|
customFilms[film.id] = (film: film, selected: customFilms[film.id]!.selected);
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: add delete button to UI
|
||||||
|
void deleteCustomFilm(FilmExponential film) {
|
||||||
|
customFilms.remove(film.id);
|
||||||
_discardSelectedIfNotIncluded();
|
_discardSelectedIfNotIncluded();
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
|
|
||||||
void _discardSelectedIfNotIncluded() {
|
void _discardSelectedIfNotIncluded() {
|
||||||
if (_selected != const FilmStub() && !_filmsInUse.contains(_selected)) {
|
if (_selected != const FilmStub() &&
|
||||||
|
!predefinedFilms.values.any((e) => e.film == _selected) &&
|
||||||
|
!customFilms.values.any((e) => e.film == _selected)) {
|
||||||
_selected = const FilmStub();
|
_selected = const FilmStub();
|
||||||
widget.storageService.selectedFilm = const FilmStub();
|
widget.storageService.selectedFilm = const FilmStub();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Films extends SelectableInheritedModel<Film> {
|
typedef _SelectableFilm<T extends Film> = ({T film, bool selected});
|
||||||
final List<Film> filmsInUse;
|
|
||||||
|
enum _FilmsModelAspect {
|
||||||
|
customFilmsList,
|
||||||
|
predefinedFilmsList,
|
||||||
|
filmsInUse,
|
||||||
|
selected,
|
||||||
|
}
|
||||||
|
|
||||||
|
class Films extends InheritedModel<_FilmsModelAspect> {
|
||||||
|
final Map<String, _SelectableFilm<Film>> predefinedFilms;
|
||||||
|
|
||||||
|
@protected
|
||||||
|
final Map<String, _SelectableFilm<FilmExponential>> customFilms;
|
||||||
|
final Film selected;
|
||||||
|
|
||||||
const Films({
|
const Films({
|
||||||
super.key,
|
required this.predefinedFilms,
|
||||||
required super.values,
|
required this.customFilms,
|
||||||
required this.filmsInUse,
|
required this.selected,
|
||||||
required super.selected,
|
|
||||||
required super.child,
|
required super.child,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// [FilmStub()] + all the custom fields with actual reciprocity formulas
|
static List<Film> predefinedFilmsOf<T>(BuildContext context) {
|
||||||
static List<Film> of(BuildContext context) {
|
return InheritedModel.inheritFrom<Films>(context, aspect: _FilmsModelAspect.predefinedFilmsList)!
|
||||||
return InheritedModel.inheritFrom<Films>(context)!.values;
|
.predefinedFilms
|
||||||
|
.values
|
||||||
|
.map((value) => value.film)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<FilmExponential> customFilmsOf<T>(BuildContext context) {
|
||||||
|
return InheritedModel.inheritFrom<Films>(context, aspect: _FilmsModelAspect.customFilmsList)!
|
||||||
|
.customFilms
|
||||||
|
.values
|
||||||
|
.map((value) => value.film)
|
||||||
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [FilmStub()] + films in use selected by user
|
/// [FilmStub()] + films in use selected by user
|
||||||
static List<Film> inUseOf<T>(BuildContext context) {
|
static List<Film> inUseOf<T>(BuildContext context) {
|
||||||
return InheritedModel.inheritFrom<Films>(
|
final model = InheritedModel.inheritFrom<Films>(context, aspect: _FilmsModelAspect.filmsInUse)!;
|
||||||
context,
|
return [
|
||||||
aspect: SelectableAspect.list,
|
const FilmStub(),
|
||||||
)!
|
...model.customFilms.values.where((e) => e.selected).map((e) => e.film),
|
||||||
.filmsInUse;
|
...model.predefinedFilms.values.where((e) => e.selected).map((e) => e.film),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
static Film selectedOf(BuildContext context) {
|
static Film selectedOf(BuildContext context) {
|
||||||
return InheritedModel.inheritFrom<Films>(context, aspect: SelectableAspect.selected)!.selected;
|
return InheritedModel.inheritFrom<Films>(context, aspect: _FilmsModelAspect.selected)!.selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool updateShouldNotify(Films _) => true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool updateShouldNotifyDependent(Films oldWidget, Set<_FilmsModelAspect> dependencies) {
|
||||||
|
if (dependencies.contains(_FilmsModelAspect.customFilmsList)) {}
|
||||||
|
if (dependencies.contains(_FilmsModelAspect.selected)) {
|
||||||
|
return selected != oldWidget.selected;
|
||||||
|
} else {
|
||||||
|
// TODO: reduce unnecessary notifications
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,40 @@
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:lightmeter/providers/films_provider.dart';
|
||||||
import 'package:lightmeter/screens/film_edit/event_film_edit.dart';
|
import 'package:lightmeter/screens/film_edit/event_film_edit.dart';
|
||||||
import 'package:lightmeter/screens/film_edit/state_film_edit.dart';
|
import 'package:lightmeter/screens/film_edit/state_film_edit.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 FilmEditBloc extends Bloc<FilmEditEvent, FilmEditState> {
|
class FilmEditBloc extends Bloc<FilmEditEvent, FilmEditState> {
|
||||||
static const _defaultFilm = FilmExponential(name: '', iso: 100, exponent: 1.3);
|
static const _defaultFilm = FilmExponential(name: '', iso: 100, exponent: 1.3);
|
||||||
|
|
||||||
|
final FilmsProviderState filmsProvider;
|
||||||
final FilmExponential _originalFilm;
|
final FilmExponential _originalFilm;
|
||||||
FilmExponential _newFilm;
|
FilmExponential _newFilm;
|
||||||
|
final bool _isEdit;
|
||||||
|
|
||||||
factory FilmEditBloc(FilmExponential? film) => film != null ? FilmEditBloc._(film) : FilmEditBloc._(_defaultFilm);
|
factory FilmEditBloc(
|
||||||
|
FilmsProviderState filmsProvider, {
|
||||||
|
required FilmExponential? film,
|
||||||
|
required bool isEdit,
|
||||||
|
}) =>
|
||||||
|
film != null
|
||||||
|
? FilmEditBloc._(
|
||||||
|
filmsProvider,
|
||||||
|
film,
|
||||||
|
isEdit,
|
||||||
|
)
|
||||||
|
: FilmEditBloc._(
|
||||||
|
filmsProvider,
|
||||||
|
_defaultFilm,
|
||||||
|
isEdit,
|
||||||
|
);
|
||||||
|
|
||||||
FilmEditBloc._(FilmExponential film)
|
FilmEditBloc._(
|
||||||
: _originalFilm = film,
|
this.filmsProvider,
|
||||||
|
FilmExponential film,
|
||||||
|
this._isEdit,
|
||||||
|
) : _originalFilm = film,
|
||||||
_newFilm = film,
|
_newFilm = film,
|
||||||
super(
|
super(
|
||||||
FilmEditState(
|
FilmEditState(
|
||||||
|
@ -19,7 +42,6 @@ class FilmEditBloc extends Bloc<FilmEditEvent, FilmEditState> {
|
||||||
isoValue: IsoValue.values.firstWhere((element) => element.value == film.iso),
|
isoValue: IsoValue.values.firstWhere((element) => element.value == film.iso),
|
||||||
exponent: film.exponent,
|
exponent: film.exponent,
|
||||||
canSave: false,
|
canSave: false,
|
||||||
isEdit: film != _defaultFilm,
|
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
on<FilmEditEvent>(
|
on<FilmEditEvent>(
|
||||||
|
@ -33,6 +55,8 @@ class FilmEditBloc extends Bloc<FilmEditEvent, FilmEditState> {
|
||||||
_onExpChanged(e, emit);
|
_onExpChanged(e, emit);
|
||||||
case FilmEditSaveEvent():
|
case FilmEditSaveEvent():
|
||||||
_onSave(event, emit);
|
_onSave(event, emit);
|
||||||
|
case FilmEditDeleteEvent():
|
||||||
|
_onDelete(event, emit);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -46,7 +70,6 @@ class FilmEditBloc extends Bloc<FilmEditEvent, FilmEditState> {
|
||||||
isoValue: state.isoValue,
|
isoValue: state.isoValue,
|
||||||
exponent: state.exponent,
|
exponent: state.exponent,
|
||||||
canSave: _canSave(event.name, state.exponent),
|
canSave: _canSave(event.name, state.exponent),
|
||||||
isEdit: state.isEdit,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -59,7 +82,6 @@ class FilmEditBloc extends Bloc<FilmEditEvent, FilmEditState> {
|
||||||
isoValue: event.iso,
|
isoValue: event.iso,
|
||||||
exponent: state.exponent,
|
exponent: state.exponent,
|
||||||
canSave: _canSave(state.name, state.exponent),
|
canSave: _canSave(state.name, state.exponent),
|
||||||
isEdit: state.isEdit,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -74,12 +96,35 @@ class FilmEditBloc extends Bloc<FilmEditEvent, FilmEditState> {
|
||||||
isoValue: state.isoValue,
|
isoValue: state.isoValue,
|
||||||
exponent: event.exponent,
|
exponent: event.exponent,
|
||||||
canSave: _canSave(state.name, event.exponent),
|
canSave: _canSave(state.name, event.exponent),
|
||||||
isEdit: state.isEdit,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onSave(FilmEditSaveEvent _, Emitter emit) async {}
|
Future<void> _onSave(FilmEditSaveEvent _, Emitter emit) async {
|
||||||
|
if (_isEdit) {
|
||||||
|
filmsProvider.updateCustomFilm(
|
||||||
|
FilmExponential(
|
||||||
|
id: _originalFilm.id,
|
||||||
|
name: state.name,
|
||||||
|
iso: state.isoValue.value,
|
||||||
|
exponent: state.exponent!,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
filmsProvider.addCustomFilm(
|
||||||
|
FilmExponential(
|
||||||
|
id: const Uuid().v1(),
|
||||||
|
name: state.name,
|
||||||
|
iso: state.isoValue.value,
|
||||||
|
exponent: state.exponent!,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onDelete(FilmEditDeleteEvent _, Emitter emit) async {
|
||||||
|
filmsProvider.deleteCustomFilm(_originalFilm);
|
||||||
|
}
|
||||||
|
|
||||||
bool _canSave(String name, double? exponent) {
|
bool _canSave(String name, double? exponent) {
|
||||||
return name.isNotEmpty && exponent != null && _newFilm != _originalFilm;
|
return name.isNotEmpty && exponent != null && _newFilm != _originalFilm;
|
||||||
|
|
|
@ -25,3 +25,7 @@ class FilmEditExpChangedEvent extends FilmEditEvent {
|
||||||
class FilmEditSaveEvent extends FilmEditEvent {
|
class FilmEditSaveEvent extends FilmEditEvent {
|
||||||
const FilmEditSaveEvent();
|
const FilmEditSaveEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class FilmEditDeleteEvent extends FilmEditEvent {
|
||||||
|
const FilmEditDeleteEvent();
|
||||||
|
}
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:lightmeter/providers/films_provider.dart';
|
||||||
import 'package:lightmeter/screens/film_edit/bloc_film_edit.dart';
|
import 'package:lightmeter/screens/film_edit/bloc_film_edit.dart';
|
||||||
import 'package:lightmeter/screens/film_edit/screen_film_edit.dart';
|
import 'package:lightmeter/screens/film_edit/screen_film_edit.dart';
|
||||||
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
|
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
|
||||||
|
|
||||||
class FilmEditArgs {
|
class FilmEditArgs {
|
||||||
final FilmExponential film;
|
final FilmExponential? film;
|
||||||
|
|
||||||
const FilmEditArgs({required this.film});
|
const FilmEditArgs({this.film});
|
||||||
}
|
}
|
||||||
|
|
||||||
class FilmEditFlow extends StatelessWidget {
|
class FilmEditFlow extends StatelessWidget {
|
||||||
|
@ -18,8 +19,12 @@ class FilmEditFlow extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (_) => FilmEditBloc(args.film),
|
create: (_) => FilmEditBloc(
|
||||||
child: const FilmEditScreen(),
|
FilmsProvider.of(context),
|
||||||
|
film: args.film,
|
||||||
|
isEdit: args.film != null,
|
||||||
|
),
|
||||||
|
child: FilmEditScreen(isEdit: args.film != null),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,12 @@ import 'package:lightmeter/screens/film_edit/state_film_edit.dart';
|
||||||
import 'package:lightmeter/screens/shared/sliver_screen/screen_sliver.dart';
|
import 'package:lightmeter/screens/shared/sliver_screen/screen_sliver.dart';
|
||||||
|
|
||||||
class FilmEditScreen extends StatefulWidget {
|
class FilmEditScreen extends StatefulWidget {
|
||||||
const FilmEditScreen({super.key});
|
final bool isEdit;
|
||||||
|
|
||||||
|
const FilmEditScreen({
|
||||||
|
required this.isEdit,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<FilmEditScreen> createState() => _FilmEditScreenState();
|
State<FilmEditScreen> createState() => _FilmEditScreenState();
|
||||||
|
@ -21,18 +26,28 @@ class _FilmEditScreenState extends State<FilmEditScreen> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SliverScreen(
|
return SliverScreen(
|
||||||
title: BlocBuilder<FilmEditBloc, FilmEditState>(
|
title: Text(widget.isEdit ? S.of(context).editFilmTitle : S.of(context).addFilmTitle),
|
||||||
buildWhen: (previous, current) => false,
|
|
||||||
builder: (context, state) => Text(state.isEdit ? S.of(context).editFilmTitle : S.of(context).addFilmTitle),
|
|
||||||
),
|
|
||||||
appBarActions: [
|
appBarActions: [
|
||||||
BlocBuilder<FilmEditBloc, FilmEditState>(
|
BlocBuilder<FilmEditBloc, FilmEditState>(
|
||||||
buildWhen: (previous, current) => previous.canSave != current.canSave,
|
buildWhen: (previous, current) => previous.canSave != current.canSave,
|
||||||
builder: (context, state) => IconButton(
|
builder: (context, state) => IconButton(
|
||||||
onPressed: state.canSave ? () {} : null,
|
onPressed: state.canSave
|
||||||
|
? () {
|
||||||
|
context.read<FilmEditBloc>().add(const FilmEditSaveEvent());
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
}
|
||||||
|
: null,
|
||||||
icon: const Icon(Icons.save),
|
icon: const Icon(Icons.save),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (widget.isEdit)
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
context.read<FilmEditBloc>().add(const FilmEditDeleteEvent());
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.delete),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
slivers: [
|
slivers: [
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
|
|
|
@ -5,13 +5,13 @@ class FilmEditState {
|
||||||
final IsoValue isoValue;
|
final IsoValue isoValue;
|
||||||
final double? exponent;
|
final double? exponent;
|
||||||
final bool canSave;
|
final bool canSave;
|
||||||
final bool isEdit;
|
final FilmExponential? filmToSave;
|
||||||
|
|
||||||
const FilmEditState({
|
const FilmEditState({
|
||||||
required this.name,
|
required this.name,
|
||||||
required this.isoValue,
|
required this.isoValue,
|
||||||
required this.exponent,
|
required this.exponent,
|
||||||
required this.canSave,
|
required this.canSave,
|
||||||
required this.isEdit,
|
this.filmToSave,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,12 +55,12 @@ class _FilmsScreenState extends State<FilmsScreen> with SingleTickerProviderStat
|
||||||
controller: tabController,
|
controller: tabController,
|
||||||
children: [
|
children: [
|
||||||
_FilmsListBuilder(
|
_FilmsListBuilder(
|
||||||
films: Films.of(context).skip(1).toList(),
|
films: Films.predefinedFilmsOf(context).toList(),
|
||||||
onFilmSelected: (film, value) {},
|
onFilmSelected: FilmsProvider.of(context).toggleFilm,
|
||||||
),
|
),
|
||||||
_FilmsListBuilder<FilmExponential>(
|
_FilmsListBuilder<FilmExponential>(
|
||||||
films: Films.of(context).skip(1).whereType<FilmExponential>().toList(),
|
films: Films.customFilmsOf(context).toList(),
|
||||||
onFilmSelected: (film, value) {},
|
onFilmSelected: FilmsProvider.of(context).toggleFilm,
|
||||||
onFilmEdit: _editFilm,
|
onFilmEdit: _editFilm,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -72,8 +72,8 @@ class _FilmsScreenState extends State<FilmsScreen> with SingleTickerProviderStat
|
||||||
|
|
||||||
void _addFilm() {
|
void _addFilm() {
|
||||||
Navigator.of(context).pushNamed(
|
Navigator.of(context).pushNamed(
|
||||||
NavigationRoutes.filmEditScreen.name,
|
NavigationRoutes.filmAddScreen.name,
|
||||||
arguments: const FilmEditArgs(film: FilmExponential(name: '', iso: 100, exponent: 1.3)),
|
arguments: const FilmEditArgs(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ class FilmPicker extends StatelessWidget {
|
||||||
selectedValue: Films.selectedOf(context),
|
selectedValue: Films.selectedOf(context),
|
||||||
values: Films.inUseOf(context),
|
values: Films.inUseOf(context),
|
||||||
itemTitleBuilder: (_, value) => Text(value.name.isEmpty ? S.of(context).none : value.name),
|
itemTitleBuilder: (_, value) => Text(value.name.isEmpty ? S.of(context).none : value.name),
|
||||||
onChanged: FilmsProvider.of(context).setFilm,
|
onChanged: FilmsProvider.of(context).selectFilm,
|
||||||
closedChild: ReadingValueContainer.singleValue(
|
closedChild: ReadingValueContainer.singleValue(
|
||||||
value: ReadingValue(
|
value: ReadingValue(
|
||||||
label: _label(context),
|
label: _label(context),
|
||||||
|
|
|
@ -39,7 +39,7 @@ class MeteringScreenLayoutListTile extends StatelessWidget {
|
||||||
EquipmentProfileProvider.of(context).setProfile(EquipmentProfiles.of(context).first);
|
EquipmentProfileProvider.of(context).setProfile(EquipmentProfiles.of(context).first);
|
||||||
}
|
}
|
||||||
if (!value[MeteringScreenLayoutFeature.filmPicker]!) {
|
if (!value[MeteringScreenLayoutFeature.filmPicker]!) {
|
||||||
FilmsProvider.of(context).setFilm(const FilmStub());
|
FilmsProvider.of(context).selectFilm(const FilmStub());
|
||||||
}
|
}
|
||||||
UserPreferencesProvider.of(context).setMeteringScreenLayout(value);
|
UserPreferencesProvider.of(context).setMeteringScreenLayout(value);
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
|
||||||
|
|
||||||
enum SelectableAspect { list, selected }
|
enum SelectableAspect { list, selected }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class SelectableInheritedModel<T> extends InheritedModel<SelectableAspect> {
|
class SelectableInheritedModel<T> extends InheritedModel<SelectableAspect> {
|
||||||
const SelectableInheritedModel({
|
const SelectableInheritedModel({
|
||||||
super.key,
|
super.key,
|
||||||
|
|
Loading…
Reference in a new issue