mirror of
https://github.com/vodemn/m3_lightmeter.git
synced 2024-11-24 00:10:47 +00:00
wip
This commit is contained in:
parent
a0eb641cf3
commit
6f094d6432
5 changed files with 158 additions and 40 deletions
|
@ -1,11 +1,11 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:lightmeter/utils/inherited_generics.dart';
|
||||||
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
|
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
|
|
||||||
class StopTypeProvider extends StatefulWidget {
|
class StopTypeProvider extends StatefulWidget {
|
||||||
final Widget? child;
|
final Widget child;
|
||||||
|
|
||||||
const StopTypeProvider({this.child, super.key});
|
const StopTypeProvider({required this.child, super.key});
|
||||||
|
|
||||||
static StopTypeProviderState of(BuildContext context) {
|
static StopTypeProviderState of(BuildContext context) {
|
||||||
return context.findAncestorStateOfType<StopTypeProviderState>()!;
|
return context.findAncestorStateOfType<StopTypeProviderState>()!;
|
||||||
|
@ -28,8 +28,8 @@ class StopTypeProviderState extends State<StopTypeProvider> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Provider.value(
|
return InheritedWidgetBase<StopType>(
|
||||||
value: _stopType,
|
data: _stopType,
|
||||||
child: widget.child,
|
child: widget.child,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import 'package:lightmeter/providers/equipment_profile_provider.dart';
|
||||||
import 'package:lightmeter/screens/metering/bloc_metering.dart';
|
import 'package:lightmeter/screens/metering/bloc_metering.dart';
|
||||||
import 'package:lightmeter/screens/metering/communication/bloc_communication_metering.dart';
|
import 'package:lightmeter/screens/metering/communication/bloc_communication_metering.dart';
|
||||||
import 'package:lightmeter/screens/metering/screen_metering.dart';
|
import 'package:lightmeter/screens/metering/screen_metering.dart';
|
||||||
|
import 'package:lightmeter/utils/inherited_generics.dart';
|
||||||
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
|
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
@ -39,7 +40,7 @@ class _MeteringFlowState extends State<MeteringFlow> {
|
||||||
context.read<MeteringCommunicationBloc>(),
|
context.read<MeteringCommunicationBloc>(),
|
||||||
context.read<MeteringInteractor>(),
|
context.read<MeteringInteractor>(),
|
||||||
EquipmentProfile.of(context, listen: false),
|
EquipmentProfile.of(context, listen: false),
|
||||||
context.read<StopType>(),
|
context.get<StopType>(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -14,6 +14,7 @@ import 'package:lightmeter/screens/metering/components/camera_container/provider
|
||||||
import 'package:lightmeter/screens/metering/components/light_sensor_container/provider_container_light_sensor.dart';
|
import 'package:lightmeter/screens/metering/components/light_sensor_container/provider_container_light_sensor.dart';
|
||||||
import 'package:lightmeter/screens/metering/event_metering.dart';
|
import 'package:lightmeter/screens/metering/event_metering.dart';
|
||||||
import 'package:lightmeter/screens/metering/state_metering.dart';
|
import 'package:lightmeter/screens/metering/state_metering.dart';
|
||||||
|
import 'package:lightmeter/utils/inherited_generics.dart';
|
||||||
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
|
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
|
||||||
|
|
||||||
class MeteringScreen extends StatefulWidget {
|
class MeteringScreen extends StatefulWidget {
|
||||||
|
@ -30,7 +31,6 @@ class _MeteringScreenState extends State<MeteringScreen> {
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
_bloc.add(EquipmentProfileChangedEvent(EquipmentProfile.of(context)));
|
_bloc.add(EquipmentProfileChangedEvent(EquipmentProfile.of(context)));
|
||||||
_bloc.add(StopTypeChangedEvent(context.watch<StopType>()));
|
|
||||||
if (!MeteringScreenLayout.featureStatusOf(context, MeteringScreenLayoutFeature.filmPicker)) {
|
if (!MeteringScreenLayout.featureStatusOf(context, MeteringScreenLayoutFeature.filmPicker)) {
|
||||||
_bloc.add(const FilmChangedEvent(Film.other()));
|
_bloc.add(const FilmChangedEvent(Film.other()));
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,11 @@ class _MeteringScreenState extends State<MeteringScreen> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return InheritedWidgetListener<StopType>(
|
||||||
|
onDidChangeDependencies: (value) {
|
||||||
|
context.read<MeteringBloc>().add(StopTypeChangedEvent(value));
|
||||||
|
},
|
||||||
|
child: Scaffold(
|
||||||
backgroundColor: Theme.of(context).colorScheme.background,
|
backgroundColor: Theme.of(context).colorScheme.background,
|
||||||
body: Column(
|
body: Column(
|
||||||
children: [
|
children: [
|
||||||
|
@ -72,6 +76,7 @@ class _MeteringScreenState extends State<MeteringScreen> {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:lightmeter/generated/l10n.dart';
|
import 'package:lightmeter/generated/l10n.dart';
|
||||||
import 'package:lightmeter/providers/stop_type_provider.dart';
|
import 'package:lightmeter/providers/stop_type_provider.dart';
|
||||||
import 'package:lightmeter/screens/settings/components/shared/dialog_picker.dart/widget_dialog_picker.dart';
|
import 'package:lightmeter/screens/settings/components/shared/dialog_picker.dart/widget_dialog_picker.dart';
|
||||||
|
import 'package:lightmeter/utils/inherited_generics.dart';
|
||||||
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
|
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
|
|
||||||
class StopTypeListTile extends StatelessWidget {
|
class StopTypeListTile extends StatelessWidget {
|
||||||
const StopTypeListTile({super.key});
|
const StopTypeListTile({super.key});
|
||||||
|
@ -13,14 +13,14 @@ class StopTypeListTile extends StatelessWidget {
|
||||||
return ListTile(
|
return ListTile(
|
||||||
leading: const Icon(Icons.straighten),
|
leading: const Icon(Icons.straighten),
|
||||||
title: Text(S.of(context).fractionalStops),
|
title: Text(S.of(context).fractionalStops),
|
||||||
trailing: Text(_typeToString(context, context.watch<StopType>())),
|
trailing: Text(_typeToString(context, context.listen<StopType>())),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
showDialog<StopType>(
|
showDialog<StopType>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (_) => DialogPicker<StopType>(
|
builder: (_) => DialogPicker<StopType>(
|
||||||
icon: Icons.straighten,
|
icon: Icons.straighten,
|
||||||
title: S.of(context).showFractionalStops,
|
title: S.of(context).showFractionalStops,
|
||||||
selectedValue: context.read<StopType>(),
|
selectedValue: context.get<StopType>(),
|
||||||
values: StopType.values,
|
values: StopType.values,
|
||||||
titleAdapter: _typeToString,
|
titleAdapter: _typeToString,
|
||||||
),
|
),
|
||||||
|
|
112
lib/utils/inherited_generics.dart
Normal file
112
lib/utils/inherited_generics.dart
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
|
/// Listening to multiple dependencies at the same time causes firing an event for all dependencies
|
||||||
|
/// even though some of them didn't change:
|
||||||
|
/// ```dart
|
||||||
|
/// @override
|
||||||
|
/// void didChangeDependencies() {
|
||||||
|
/// super.didChangeDependencies();
|
||||||
|
/// _bloc.add(EquipmentProfileChangedEvent(EquipmentProfile.of(context)));
|
||||||
|
/// if (!MeteringScreenLayout.featureStatusOf(context, MeteringScreenLayoutFeature.filmPicker)) {
|
||||||
|
/// _bloc.add(const FilmChangedEvent(Film.other()));
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
/// To overcome this issue I've decided to create a generic listener,
|
||||||
|
/// that will listen to each dependency separately.
|
||||||
|
class InheritedWidgetListener<T> extends StatefulWidget {
|
||||||
|
final ValueChanged<T> onDidChangeDependencies;
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
const InheritedWidgetListener({
|
||||||
|
required this.onDidChangeDependencies,
|
||||||
|
required this.child,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<InheritedWidgetListener<T>> createState() => _InheritedWidgetListenerState<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _InheritedWidgetListenerState<T> extends State<InheritedWidgetListener<T>> {
|
||||||
|
@override
|
||||||
|
void didChangeDependencies() {
|
||||||
|
super.didChangeDependencies();
|
||||||
|
widget.onDidChangeDependencies(context.listen<T>());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return widget.child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class InheritedWidgetBase<T> extends InheritedWidget {
|
||||||
|
final T data;
|
||||||
|
|
||||||
|
const InheritedWidgetBase({
|
||||||
|
required this.data,
|
||||||
|
required super.child,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
static T of<T>(BuildContext context, {bool listen = true}) {
|
||||||
|
if (listen) {
|
||||||
|
return context.dependOnInheritedWidgetOfExactType<InheritedWidgetBase<T>>()!.data;
|
||||||
|
} else {
|
||||||
|
return context.findAncestorWidgetOfExactType<InheritedWidgetBase<T>>()!.data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool updateShouldNotify(InheritedWidgetBase<T> oldWidget) => true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// class InheritedModelBase<A, R> extends InheritedModel<A> {
|
||||||
|
// final Map<A, R> data;
|
||||||
|
|
||||||
|
// const InheritedModelBase({
|
||||||
|
// required this.data,
|
||||||
|
// required super.child,
|
||||||
|
// super.key,
|
||||||
|
// });
|
||||||
|
|
||||||
|
// static Map<A, R> of<R, A>(BuildContext context, {bool listen = true}) {
|
||||||
|
// if (listen) {
|
||||||
|
// return context.dependOnInheritedWidgetOfExactType<InheritedModelBase<A, R>>()!.data;
|
||||||
|
// } else {
|
||||||
|
// return context.findAncestorWidgetOfExactType<InheritedModelBase<A, R>>()!.data;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// static R featureStatusOf<A, R>(BuildContext context, A aspect) {
|
||||||
|
// return InheritedModel.inheritFrom<InheritedModelBase<A, R>>(context, aspect: aspect)!
|
||||||
|
// .data[aspect]!;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @override
|
||||||
|
// bool updateShouldNotify(InheritedModelBase oldWidget) => true;
|
||||||
|
|
||||||
|
// @override
|
||||||
|
// bool updateShouldNotifyDependent(
|
||||||
|
// InheritedModelBase<A, R> oldWidget,
|
||||||
|
// Set<A> dependencies,
|
||||||
|
// ) {
|
||||||
|
// for (final dependecy in dependencies) {
|
||||||
|
// if (oldWidget.data[dependecy] != data[dependecy]) {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
extension InheritedWidgetBaseContext on BuildContext {
|
||||||
|
T get<T>() {
|
||||||
|
return InheritedWidgetBase.of<T>(this, listen: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
T listen<T>() {
|
||||||
|
return InheritedWidgetBase.of<T>(this);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue