Skip to content

Commit

Permalink
[Draft] Split calculator model
Browse files Browse the repository at this point in the history
  • Loading branch information
duddu committed Oct 22, 2023
1 parent d5be08d commit f3e5b7d
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 66 deletions.
2 changes: 1 addition & 1 deletion lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import 'package:window_size/window_size.dart';
void _setupWindow() async {
if (!kIsWeb && (Platform.isWindows || Platform.isLinux || Platform.isMacOS)) {
const double windowWidth = style.mobileMaxScreenWidth;
const double windowHeight = 730;
const double windowHeight = 735;

WidgetsFlutterBinding.ensureInitialized();
setWindowMinSize(const Size(windowWidth, windowHeight));
Expand Down
36 changes: 36 additions & 0 deletions lib/models/fermentation_model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import 'package:flutter/material.dart';
import 'package:sourdoc/methods/temperature_unit_helpers.dart';
import 'package:sourdoc/methods/get_fermentation_values.dart';

class FermentationModel extends ChangeNotifier {
double _inoculation = 0;
double _bulkRise = 0;

double get inoculation => _inoculation;
double get bulkRise => _bulkRise;

TextEditingController temperatureController = TextEditingController();

double _parseValue(TextEditingController controller) {
if (controller.value.text.isEmpty) {
return 0;
}
return double.parse(controller.value.text);
}

void updateFermentationValues() {
final double temperature = _parseValue(temperatureController);

_inoculation = getInoculationValue(temperature, _temperatureUnit);
_bulkRise = getBulkRiseValue(temperature, _temperatureUnit);

notifyListeners();
}

late TemperatureUnit _temperatureUnit;

void updateTemperatureUnit(TemperatureUnit temperatureUnit) {
_temperatureUnit = temperatureUnit;
updateFermentationValues();
}
}
45 changes: 45 additions & 0 deletions lib/models/ingredients_model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import 'package:flutter/material.dart';
import 'package:sourdoc/methods/get_ingredients_values.dart';

class IngredientsModel extends ChangeNotifier {
double _flour = 0;
double _water = 0;
double _levain = 0;
double _salt = 0;

double get flour => _flour;
double get water => _water;
double get levain => _levain;
double get salt => _salt;

TextEditingController totalWeightController = TextEditingController();
TextEditingController hydrationController = TextEditingController();
TextEditingController saltController = TextEditingController();

double _parseValue(TextEditingController controller) {
if (controller.value.text.isEmpty) {
return 0;
}
return double.parse(controller.value.text);
}

void updateIngredientsValues() {
final double totalWeight = _parseValue(totalWeightController);
final double hydration = _parseValue(hydrationController);
final double saltLevel = _parseValue(saltController);

_flour = getFlourValue(totalWeight, hydration, saltLevel, _inoculation);
_water = getNonFlourIngredientValue(_flour, hydration);
_levain = getNonFlourIngredientValue(_flour, _inoculation);
_salt = getNonFlourIngredientValue(_flour, saltLevel);

notifyListeners();
}

late double _inoculation;

void updateInoculation(double inoculation) {
_inoculation = inoculation;
updateIngredientsValues();
}
}
140 changes: 82 additions & 58 deletions lib/widgets/home_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import 'package:sourdoc/constants/routes.dart';
import 'package:sourdoc/constants/style.dart' as style;
import 'package:sourdoc/methods/temperature_unit_helpers.dart';
import 'package:sourdoc/methods/persist_initial_values.dart';
import 'package:sourdoc/models/calculator_model.dart';
import 'package:sourdoc/models/fermentation_model.dart';
import 'package:sourdoc/models/ingredients_model.dart';
import 'package:sourdoc/models/temperature_unit_model.dart';
import 'package:sourdoc/widgets/app_bar_with_actions.dart';
import 'package:sourdoc/widgets/centered_container.dart';
Expand Down Expand Up @@ -46,9 +47,28 @@ class HomePage extends StatelessWidget {
onPressed: () {
Navigator.pushNamed(context, helpPagePath);
})))),
body: ChangeNotifierProvider(
create: (context) => CalculatorModel(),
child: const HomePageListView()),
body: MultiProvider(providers: [
ChangeNotifierProvider(create: (context) => TemperatureUnitModel()),
ChangeNotifierProxyProvider<TemperatureUnitModel, FermentationModel>(
create: (context) => FermentationModel(),
update: (context, temperatureUnitModel, fermentationModel) {
if (fermentationModel == null) {
throw ArgumentError.notNull('fermentationModel');
}
fermentationModel
.updateTemperatureUnit(temperatureUnitModel.temperatureUnit);
return fermentationModel;
}),
ChangeNotifierProxyProvider<FermentationModel, IngredientsModel>(
create: (context) => IngredientsModel(),
update: (context, fermentationModel, ingredientsModel) {
if (ingredientsModel == null) {
throw ArgumentError.notNull('ingredientsModel');
}
ingredientsModel.updateInoculation(fermentationModel.inoculation);
return ingredientsModel;
}),
], child: const HomePageListView()),
);
}
}
Expand All @@ -60,7 +80,7 @@ class HomePageListView extends StatelessWidget {
Widget build(BuildContext context) {
return ListView(
primary: true,
padding: const EdgeInsets.only(bottom: 35),
padding: const EdgeInsets.only(bottom: 25),
children: [
CenteredContainer(
decoration: BoxDecoration(
Expand All @@ -76,15 +96,13 @@ class HomePageListView extends StatelessWidget {
textAlign: TextAlign.start,
style: Theme.of(context).textTheme.bodyMedium,
)),
Card(
const Card(
margin: EdgeInsets.zero,
semanticContainer: false,
shape: const RoundedRectangleBorder(),
shape: RoundedRectangleBorder(),
child: CenteredContainer(
padding: const EdgeInsets.symmetric(vertical: 12),
child: ChangeNotifierProvider(
create: (context) => TemperatureUnitModel(),
child: const CalculatorForm()))),
padding: EdgeInsets.symmetric(vertical: 12),
child: CalculatorForm())),
const CenteredContainer(child: IngredientsValues()),
const CenteredContainer(child: FermentationValues()),
],
Expand All @@ -100,10 +118,10 @@ class CalculatorForm extends StatefulWidget {
}

class _CalculatorFormState extends State<CalculatorForm> {
final temperatureController = TextEditingController();
final totalWeightController = TextEditingController();
final hydrationController = TextEditingController();
final saltController = TextEditingController();
TextEditingController? temperatureController;
TextEditingController? totalWeightController;
TextEditingController? hydrationController;
TextEditingController? saltController;

final unitChoiceList = temperatureUnitSet
.map((element) => UnitSingleChoiceDescriptor(
Expand All @@ -119,50 +137,41 @@ class _CalculatorFormState extends State<CalculatorForm> {
return double.parse(controller.value.text);
}

void _updateFermentationValues(TemperatureUnit temperatureUnit) {
Provider.of<CalculatorModel>(context, listen: false)
.updateFermentationValues(
_parseValue(temperatureController), temperatureUnit);
}

void _updateIngredientsValues() {
Provider.of<CalculatorModel>(context, listen: false)
.updateIngredientsValues(_parseValue(totalWeightController),
_parseValue(hydrationController), _parseValue(saltController));
}

void _onTemperatureUnitSelectionChanged(TemperatureUnit selection) {
Provider.of<TemperatureUnitModel>(context, listen: false)
.updateTemperatureUnit(selection);
storeInitialValue(temperatureUnitKey, getTemperatureUnitSymbol(selection));
if (temperatureController.text.isNotEmpty) {
temperatureController.text = convertTemperatureToUnit(
_parseValue(temperatureController), selection)
if (temperatureController!.text.isNotEmpty) {
temperatureController?.text = convertTemperatureToUnit(
_parseValue(temperatureController!), selection)
.toStringAsFixed(1)
.replaceFirst('.0', '');
storeInitialValue(temperatureKey, temperatureController.text);
storeInitialValue(temperatureKey, temperatureController!.text);
}
}

void _onTemperatureChanged(TemperatureUnit temperatureUnit) {
_updateFermentationValues(temperatureUnit);
_updateIngredientsValues();
storeInitialValue(temperatureKey, temperatureController.text);
Provider.of<FermentationModel>(context, listen: false)
.updateFermentationValues();
storeInitialValue(temperatureKey, temperatureController!.text);
}

void _onTotalWeightChanged() {
_updateIngredientsValues();
storeInitialValue(totalWeightKey, totalWeightController.text);
Provider.of<IngredientsModel>(context, listen: false)
.updateIngredientsValues();
storeInitialValue(totalWeightKey, totalWeightController!.text);
}

void _onHydrationChanged() {
_updateIngredientsValues();
storeInitialValue(hydrationKey, hydrationController.text);
Provider.of<IngredientsModel>(context, listen: false)
.updateIngredientsValues();
storeInitialValue(hydrationKey, hydrationController!.text);
}

void _onSaltChanged() {
_updateIngredientsValues();
storeInitialValue(saltLevelKey, saltController.text);
Provider.of<IngredientsModel>(context, listen: false)
.updateIngredientsValues();
storeInitialValue(saltLevelKey, saltController!.text);
}

Future<TemperatureUnit> _getInitialTemperatureSymbol() async {
Expand All @@ -171,25 +180,40 @@ class _CalculatorFormState extends State<CalculatorForm> {
return getTemperatureUnitName(initialValueUnit);
}

Future<void> _loadInitialValues() async {
final TemperatureUnit initialTemperatureUnit =
await _getInitialTemperatureSymbol();
temperatureController.text = await getInitialOrDefaultValue(
temperatureKey, form.getDefaultTemperature(initialTemperatureUnit));
totalWeightController.text =
await getInitialOrDefaultValue(totalWeightKey, form.defaultTotalWeight);
hydrationController.text =
await getInitialOrDefaultValue(hydrationKey, form.defaultHydration);
saltController.text =
await getInitialOrDefaultValue(saltLevelKey, form.defaultSaltLevel);
_updateFermentationValues(initialTemperatureUnit);
_updateIngredientsValues();
}

@override
initState() {
super.initState();
_loadInitialValues();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
final fermentationProvider =
Provider.of<FermentationModel>(context, listen: false);
final ingredientsProvider =
Provider.of<IngredientsModel>(context, listen: false);
temperatureController = fermentationProvider.temperatureController;
totalWeightController = ingredientsProvider.totalWeightController;
hydrationController = ingredientsProvider.hydrationController;
saltController = ingredientsProvider.saltController;
final TemperatureUnit initialTemperatureUnit =
await _getInitialTemperatureSymbol();
temperatureController?.text = await getInitialOrDefaultValue(
temperatureKey, form.getDefaultTemperature(initialTemperatureUnit));
totalWeightController?.text = await getInitialOrDefaultValue(
totalWeightKey, form.defaultTotalWeight);
hydrationController?.text =
await getInitialOrDefaultValue(hydrationKey, form.defaultHydration);
saltController?.text =
await getInitialOrDefaultValue(saltLevelKey, form.defaultSaltLevel);
setState(() {});
// fermentationProvider.updateFermentationValues();
});
}

@override
void dispose() {
temperatureController?.dispose();
totalWeightController?.dispose();
hydrationController?.dispose();
saltController?.dispose();
super.dispose();
}

@override
Expand Down Expand Up @@ -272,7 +296,7 @@ class IngredientsValues extends StatelessWidget {

@override
Widget build(BuildContext context) {
return Consumer<CalculatorModel>(builder: (context, model, child) {
return Consumer<IngredientsModel>(builder: (context, model, child) {
return Column(children: <Row>[
const Row(children: <Header>[
Header(
Expand Down Expand Up @@ -314,7 +338,7 @@ class FermentationValues extends StatelessWidget {

@override
Widget build(BuildContext context) {
return Consumer<CalculatorModel>(builder: (context, model, child) {
return Consumer<FermentationModel>(builder: (context, model, child) {
return Column(children: <Row>[
const Row(children: <Header>[Header(text: locale.headerFermentation)]),
Row(children: <VariableWithLabel>[
Expand Down
20 changes: 13 additions & 7 deletions lib/widgets/text_field_with_affixes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import 'package:sourdoc/constants/style.dart' as style;
class TextFieldWithAffixes extends StatelessWidget {
const TextFieldWithAffixes({
super.key,
required this.controller,
this.controller,
required this.prefixText,
required this.suffixText,
required this.tooltip,
Expand All @@ -15,7 +15,7 @@ class TextFieldWithAffixes extends StatelessWidget {
this.paddingTop = 5,
});

final TextEditingController controller;
final TextEditingController? controller;
final String prefixText;
final String suffixText;
final String tooltip;
Expand Down Expand Up @@ -43,20 +43,26 @@ class TextFieldWithAffixes extends StatelessWidget {
}

void _onChanged(String text, BuildContext context) {
if (controller == null) {
return;
}
if (text.isEmpty) {
controller.text = '0';
controller?.text = '0';
_selectAll();
} else if (double.parse(text) > maxValue) {
controller.text = maxValue.toStringAsFixed(0);
controller?.text = maxValue.toStringAsFixed(0);
_selectAll();
_showErrorSnackBar(context);
}
onChangedCallback();
}

void _selectAll() {
controller.selection = TextSelection(
baseOffset: 0, extentOffset: controller.value.text.length);
if (controller == null || controller!.value.text.isEmpty) {
return;
}
controller?.selection = TextSelection(
baseOffset: 0, extentOffset: controller!.value.text.length);
}

@override
Expand All @@ -70,7 +76,7 @@ class TextFieldWithAffixes extends StatelessWidget {
textField: true,
focusable: true,
label: tooltip,
value: '${controller.text} $suffixText',
value: '${controller?.text} $suffixText',
hint: locale.a11yTextFieldHint,
child: TextField(
controller: controller,
Expand Down

0 comments on commit f3e5b7d

Please sign in to comment.