From f3b80be47523447ec50d92f71c789204d0764601 Mon Sep 17 00:00:00 2001 From: Chen Asraf Date: Tue, 23 Jun 2020 23:10:27 +0300 Subject: [PATCH] update roll dice display + prevent accidental leave with dialogs --- lib/src/dialogs/roll_dice_dialog.dart | 53 ++++++---- .../character_wizard_view.dart | 24 ++++- .../pages/character_wizard/edit_looks.dart | 6 +- lib/src/scaffolds/class_select_scaffold.dart | 6 +- .../custom_class_wizard.dart | 99 ++++++++++++------- 5 files changed, 124 insertions(+), 64 deletions(-) diff --git a/lib/src/dialogs/roll_dice_dialog.dart b/lib/src/dialogs/roll_dice_dialog.dart index a2b020f7..3f4c0b10 100644 --- a/lib/src/dialogs/roll_dice_dialog.dart +++ b/lib/src/dialogs/roll_dice_dialog.dart @@ -31,27 +31,44 @@ class _RollDiceDialogState extends State { @override Widget build(BuildContext context) { - return SimpleDialog( - title: Text('Roll Dice'), - titlePadding: EdgeInsets.all(16).copyWith(bottom: 0), + return Column( children: [ - for (var list in enumerate(controllers)) - Padding( - padding: list.index > 0 - ? const EdgeInsets.symmetric(vertical: 16) - : EdgeInsets.only(bottom: 16), - child: DiceRollBox( - key: Key('dice-${list.value.hash}'), - diceList: list.value.value, - controller: controllers[list.index], - onRemove: () => _removeAt(list.index), + Container( + height: 52, + child: Center( + child: Text( + 'Roll Dice', + style: Theme.of(context).textTheme.headline4.copyWith( + color: Theme.of(context).canvasColor, + ), ), ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: DiceRollBuilder( - character: widget.character, - onChanged: _add, + ), + Expanded( + child: SingleChildScrollView( + child: Column( + children: [ + for (var list in enumerate(controllers)) + Padding( + padding: list.index > 0 + ? const EdgeInsets.symmetric(vertical: 16) + : EdgeInsets.only(bottom: 16), + child: DiceRollBox( + key: Key('dice-${list.value.hash}'), + diceList: list.value.value, + controller: controllers[list.index], + onRemove: () => _removeAt(list.index), + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: DiceRollBuilder( + character: widget.character, + onChanged: _add, + ), + ), + ], + ), ), ), ], diff --git a/lib/src/pages/character_wizard/character_wizard_view.dart b/lib/src/pages/character_wizard/character_wizard_view.dart index b11fb4f8..f4f8cf71 100644 --- a/lib/src/pages/character_wizard/character_wizard_view.dart +++ b/lib/src/pages/character_wizard/character_wizard_view.dart @@ -48,6 +48,7 @@ class _CharacterWizardViewState extends State ValueNotifier raceValid; ValueNotifier looksValid; ValueNotifier statsValid; + bool dirty; static const Map TAB_TITLES = { CreateCharacterTab.BasicInfo: 'General', @@ -77,6 +78,7 @@ class _CharacterWizardViewState extends State raceValid = ValueNotifier(character.race != null); looksValid = ValueNotifier(true); statsValid = ValueNotifier(true); + dirty = false; tabController = TabController(length: _tabs.keys.length, vsync: this); @@ -158,13 +160,15 @@ class _CharacterWizardViewState extends State character: character, mode: DialogMode.Create, onUpdate: (char) => setState(() { + dirty = true; character = char; }), ), CreateCharacterTab.MainClass: ClassSelectView( character: character, mode: DialogMode.Create, - onSave: (char) => setState(() { + onUpdate: (char) => setState(() { + dirty = true; character = char; }), ), @@ -172,6 +176,7 @@ class _CharacterWizardViewState extends State character: character, mode: DialogMode.Create, onUpdate: (char) => setState(() { + dirty = true; character = char; }), ), @@ -179,19 +184,22 @@ class _CharacterWizardViewState extends State character: character, mode: DialogMode.Create, onUpdate: (char) => setState(() { + dirty = true; character = char; }), ), CreateCharacterTab.Looks: ChangeLooksDialog( character: character, mode: DialogMode.Create, - onSave: (char) => setState(() { + onUpdate: (char) => setState(() { + dirty = true; character = char; }), ), CreateCharacterTab.Stats: EditStats( character: character, onUpdate: (char) => setState(() { + dirty = true; character = char; }), ), @@ -234,16 +242,22 @@ class _CharacterWizardViewState extends State Navigator.pop(context); } - void _confirmExit() async { + Future _confirmExit() async { var verb = widget.mode == DialogMode.Edit ? 'edit' : 'creation'; - if (await await showDialog( + if (!dirty) { + return true; + } + if (await showDialog( context: context, builder: (ctx) => ConfirmationDialog( - text: Text('Are you sure you want to quit character $verb?')), + text: Text( + 'Are you sure you want to quit character $verb?\nYour changes will not be saved.')), ) == true) { Navigator.pop(context, true); + return true; } + return false; } } diff --git a/lib/src/pages/character_wizard/edit_looks.dart b/lib/src/pages/character_wizard/edit_looks.dart index 1aa55373..ee03efb8 100644 --- a/lib/src/pages/character_wizard/edit_looks.dart +++ b/lib/src/pages/character_wizard/edit_looks.dart @@ -10,12 +10,12 @@ import 'package:flutter/material.dart'; class ChangeLooksDialog extends StatefulWidget { final Character character; final DialogMode mode; - final VoidCallbackDelegate onSave; + final VoidCallbackDelegate onUpdate; const ChangeLooksDialog({ Key key, @required this.character, - @required this.onSave, + @required this.onUpdate, this.mode = DialogMode.Edit, }) : super(key: key); @@ -146,7 +146,7 @@ class _ChangeLooksDialogState extends State { void changeLooks(List def) async { var char = widget.character; char.looks = def; - widget.onSave?.call(char); + widget.onUpdate?.call(char); } void _setValue(int i, String val) { diff --git a/lib/src/scaffolds/class_select_scaffold.dart b/lib/src/scaffolds/class_select_scaffold.dart index 559a805a..3b318735 100644 --- a/lib/src/scaffolds/class_select_scaffold.dart +++ b/lib/src/scaffolds/class_select_scaffold.dart @@ -12,12 +12,12 @@ import 'package:flutter/material.dart'; class ClassSelectView extends StatelessWidget { final Character character; final DialogMode mode; - final VoidCallbackDelegate onSave; + final VoidCallbackDelegate onUpdate; const ClassSelectView({ Key key, @required this.character, - @required this.onSave, + @required this.onUpdate, this.mode = DialogMode.Edit, }) : super(key: key); @@ -74,7 +74,7 @@ class ClassSelectView extends StatelessWidget { ChangeClassConfirmationOptions options) { var result = options.applyToCharacter(character, def); character.mainClass = def; - onSave?.call(result.character); + onUpdate?.call(result.character); } Function() previewClass(BuildContext context, PlayerClass def) { diff --git a/lib/src/scaffolds/custom_class_wizard/custom_class_wizard.dart b/lib/src/scaffolds/custom_class_wizard/custom_class_wizard.dart index 78bc5032..ac41ef2e 100644 --- a/lib/src/scaffolds/custom_class_wizard/custom_class_wizard.dart +++ b/lib/src/scaffolds/custom_class_wizard/custom_class_wizard.dart @@ -1,4 +1,5 @@ import 'package:dungeon_paper/db/models/custom_class.dart'; +import 'package:dungeon_paper/src/dialogs/confirmation_dialog.dart'; import 'package:dungeon_paper/src/dialogs/dialogs.dart'; import 'package:dungeon_paper/src/lists/custom_class_moves_list.dart'; import 'package:dungeon_paper/src/molecules/custom_class_alignments.dart'; @@ -36,6 +37,7 @@ class _CustomClassWizardState extends State ValueNotifier racesValid; ValueNotifier looksValid; ValueNotifier alignmentsValid; + bool dirty; static const Map TAB_TITLES = { CustomClassWizardTab.BasicInfo: 'General', @@ -63,6 +65,7 @@ class _CustomClassWizardState extends State movesValid = ValueNotifier(true); looksValid = ValueNotifier(true); alignmentsValid = ValueNotifier(true); + dirty = false; tabController = TabController(length: _tabs.keys.length, vsync: this); @@ -71,46 +74,49 @@ class _CustomClassWizardState extends State @override Widget build(BuildContext context) { - return ScaffoldWithElevation.primaryBackground( - title: Text(def.name.isEmpty - ? 'Custom Class' - : '${widget.mode == DialogMode.Create ? 'Creat' : 'Edit'}ing: ${def.name}'), - actions: [ - IconButton( - icon: Icon(Icons.save), - tooltip: 'Save', - onPressed: _isClsValid ? _save : null, - ) - ], - wrapWithScrollable: false, - useElevation: false, - elevation: 0, - body: Column( - children: [ - Row( - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Container( - color: Theme.of(context).primaryColor, - child: TabBar( - isScrollable: true, - controller: tabController, - tabs: _tabs.keys.map(_mapTab).toList(), + return WillPopScope( + onWillPop: _confirmExit, + child: ScaffoldWithElevation.primaryBackground( + title: Text(def.name.isEmpty + ? 'Custom Class' + : '${widget.mode == DialogMode.Create ? 'Creat' : 'Edit'}ing: ${def.name}'), + actions: [ + IconButton( + icon: Icon(Icons.save), + tooltip: 'Save', + onPressed: _isClsValid ? _save : null, + ) + ], + wrapWithScrollable: false, + useElevation: false, + elevation: 0, + body: Column( + children: [ + Row( + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Container( + color: Theme.of(context).primaryColor, + child: TabBar( + isScrollable: true, + controller: tabController, + tabs: _tabs.keys.map(_mapTab).toList(), + ), ), ), ), + ], + ), + Expanded( + child: TabBarView( + controller: tabController, + children: _tabs.values.toList(), ), - ], - ), - Expanded( - child: TabBarView( - controller: tabController, - children: _tabs.values.toList(), ), - ), - ], + ], + ), ), ); } @@ -142,6 +148,7 @@ class _CustomClassWizardState extends State customClass: def, validityNotifier: basicInfoValid, onUpdate: (cls) => setState(() { + dirty = true; def = cls; }), ), @@ -151,6 +158,7 @@ class _CustomClassWizardState extends State validityNotifier: racesValid, raceMoveMode: true, onUpdate: (cls) => setState(() { + dirty = true; def = cls; }), ), @@ -160,6 +168,7 @@ class _CustomClassWizardState extends State validityNotifier: movesValid, raceMoveMode: false, onUpdate: (cls) => setState(() { + dirty = true; def = cls; }), ), @@ -168,6 +177,7 @@ class _CustomClassWizardState extends State looks: def.looks, validityNotifier: looksValid, onUpdate: (looks) => setState(() { + dirty = true; def.looks = Map>.from( looks.asMap().map( (k, v) => MapEntry(k.toString(), v), @@ -179,6 +189,7 @@ class _CustomClassWizardState extends State mode: widget.mode, alignments: def.alignments, onUpdate: (alignments) => setState(() { + dirty = true; def.alignments = alignments; }), ), @@ -217,4 +228,22 @@ class _CustomClassWizardState extends State } Navigator.pop(context); } + + Future _confirmExit() async { + var verb = widget.mode == DialogMode.Edit ? 'edit' : 'creation'; + if (!dirty) { + return true; + } + if (await showDialog( + context: context, + builder: (ctx) => ConfirmationDialog( + text: Text( + 'Are you sure you want to quit custom class $verb?\nYour changes will not be saved.')), + ) == + true) { + Navigator.pop(context, true); + return true; + } + return false; + } }