diff --git a/lib/app/data/models/character_settings.dart b/lib/app/data/models/character_settings.dart index 1b85f5ce..d5af9f1c 100644 --- a/lib/app/data/models/character_settings.dart +++ b/lib/app/data/models/character_settings.dart @@ -5,6 +5,8 @@ import 'package:flutter/material.dart'; enum RacePosition { start, end } +enum FavoritesView { cards, list } + @immutable class CharacterSettings { const CharacterSettings({ @@ -17,6 +19,7 @@ class CharacterSettings { this.racePosition = RacePosition.start, this.lightTheme, this.darkTheme, + this.favoritesView = FavoritesView.cards, }); final NoteCategoryList noteCategories; @@ -29,6 +32,7 @@ class CharacterSettings { final RacePosition racePosition; final int? lightTheme; final int? darkTheme; + final FavoritesView favoritesView; CharacterSettings copyWith({ int? sortOrder, @@ -40,18 +44,19 @@ class CharacterSettings { RacePosition? racePosition, int? lightTheme, int? darkTheme, - }) => - CharacterSettings( - sortOrder: sortOrder ?? this.sortOrder, - category: category ?? this.category, - rollButtons: rollButtons ?? this.rollButtons, - actionCategories: actionCategories ?? this.actionCategories, - noteCategories: noteCategories ?? this.noteCategories, - racePosition: racePosition ?? this.racePosition, - quickCategories: quickCategories ?? this.quickCategories, - lightTheme: lightTheme ?? this.lightTheme, - darkTheme: darkTheme ?? this.darkTheme, - ); + FavoritesView? favoritesView, + }) => CharacterSettings( + sortOrder: sortOrder ?? this.sortOrder, + category: category ?? this.category, + rollButtons: rollButtons ?? this.rollButtons, + actionCategories: actionCategories ?? this.actionCategories, + noteCategories: noteCategories ?? this.noteCategories, + racePosition: racePosition ?? this.racePosition, + quickCategories: quickCategories ?? this.quickCategories, + lightTheme: lightTheme ?? this.lightTheme, + darkTheme: darkTheme ?? this.darkTheme, + favoritesView: favoritesView ?? this.favoritesView, + ); factory CharacterSettings.fromRawJson(String str) => CharacterSettings.fromJson(json.decode(str)); @@ -60,57 +65,56 @@ class CharacterSettings { factory CharacterSettings.fromJson(Map json) => CharacterSettings( - noteCategories: json['noteCategories'] != null - ? NoteCategoryList.fromJson(json['noteCategories']) - : const NoteCategoryList(sortOrder: {}), - actionCategories: json['actionCategories'] != null - ? ActionCategoryList.fromJson(json['actionCategories']) - : const ActionCategoryList( - sortOrder: {}, - hidden: {}, - ), - quickCategories: json['actionCategories'] != null - ? ActionCategoryList.fromJson(json['actionCategories']) - : const ActionCategoryList( - sortOrder: {}, - hidden: {}, - ), + noteCategories: + json['noteCategories'] != null + ? NoteCategoryList.fromJson(json['noteCategories']) + : const NoteCategoryList(sortOrder: {}), + actionCategories: + json['actionCategories'] != null + ? ActionCategoryList.fromJson(json['actionCategories']) + : const ActionCategoryList(sortOrder: {}, hidden: {}), + quickCategories: + json['actionCategories'] != null + ? ActionCategoryList.fromJson(json['actionCategories']) + : const ActionCategoryList(sortOrder: {}, hidden: {}), sortOrder: json['sortOrder'], category: json['category'], - rollButtons: List.from((json['rollButtons'] ?? []) - .map((x) => x != null ? RollButton.fromJson(x) : null)), + rollButtons: List.from( + (json['rollButtons'] ?? []).map( + (x) => x != null ? RollButton.fromJson(x) : null, + ), + ), racePosition: RacePosition.values.firstWhere( (element) => element.name == json['racePosition'], orElse: () => RacePosition.start, ), lightTheme: json['lightTheme'], darkTheme: json['darkTheme'], + favoritesView: FavoritesView.values.firstWhere( + (element) => element.name == json['favoritesView'], + orElse: () => FavoritesView.cards, + ), ); factory CharacterSettings.empty() => const CharacterSettings( - rollButtons: [], - noteCategories: NoteCategoryList(sortOrder: {}), - actionCategories: ActionCategoryList( - sortOrder: {}, - hidden: {}, - ), - quickCategories: ActionCategoryList( - sortOrder: {}, - hidden: {}, - ), - ); + rollButtons: [], + noteCategories: NoteCategoryList(sortOrder: {}), + actionCategories: ActionCategoryList(sortOrder: {}, hidden: {}), + quickCategories: ActionCategoryList(sortOrder: {}, hidden: {}), + ); Map toJson() => { - 'sortOrder': sortOrder, - 'category': category, - 'rollButtons': List.from(rollButtons.map((x) => x?.toJson())), - 'noteCategories': noteCategories.toJson(), - 'actionCategories': actionCategories.toJson(), - 'quickCategories': quickCategories.toJson(), - 'racePosition': racePosition.name, - 'lightTheme': lightTheme, - 'darkTheme': darkTheme, - }; + 'sortOrder': sortOrder, + 'category': category, + 'rollButtons': List.from(rollButtons.map((x) => x?.toJson())), + 'noteCategories': noteCategories.toJson(), + 'actionCategories': actionCategories.toJson(), + 'quickCategories': quickCategories.toJson(), + 'racePosition': racePosition.name, + 'lightTheme': lightTheme, + 'darkTheme': darkTheme, + 'favoritesView': favoritesView.name, + }; CharacterSettings copyWithThemes({int? lightTheme, int? darkTheme}) => CharacterSettings( @@ -123,10 +127,11 @@ class CharacterSettings { noteCategories: noteCategories, racePosition: racePosition, quickCategories: quickCategories, + favoritesView: favoritesView, ); String get debugProperties => - 'sortOrder: $sortOrder, category: $category, rollButtons: $rollButtons, noteCategories: $noteCategories, actionCategories: $actionCategories, quickCategories: $quickCategories, racePosition: $racePosition, lightTheme: $lightTheme, darkTheme: $darkTheme'; + 'sortOrder: $sortOrder, category: $category, rollButtons: $rollButtons, noteCategories: $noteCategories, actionCategories: $actionCategories, quickCategories: $quickCategories, racePosition: $racePosition, lightTheme: $lightTheme, darkTheme: $darkTheme, favoritesView: $favoritesView'; @override String toString() => 'CharacterSettings($debugProperties)'; @@ -144,20 +149,22 @@ class CharacterSettings { quickCategories == other.quickCategories && racePosition == other.racePosition && lightTheme == other.lightTheme && - darkTheme == other.darkTheme; + darkTheme == other.darkTheme && + favoritesView == other.favoritesView; @override int get hashCode => Object.hashAll([ - sortOrder, - category, - rollButtons, - noteCategories, - actionCategories, - quickCategories, - racePosition, - lightTheme, - darkTheme, - ]); + sortOrder, + category, + rollButtons, + noteCategories, + actionCategories, + quickCategories, + racePosition, + lightTheme, + darkTheme, + favoritesView, + ]); } @immutable @@ -175,11 +182,11 @@ class OrderedCategoryList { final bool canHide; Map toJson() => { - // 'categories': List.from(categories), - 'hidden': List.from(hidden), - 'sortOrder': List.from(sortOrder), - 'canHide': canHide, - }; + // 'categories': List.from(categories), + 'hidden': List.from(hidden), + 'sortOrder': List.from(sortOrder), + 'canHide': canHide, + }; factory OrderedCategoryList.fromRawJson(String str) => OrderedCategoryList.fromJson(json.decode(str)); @@ -196,23 +203,18 @@ class OrderedCategoryList { Set? hidden, Set? sortOrder, bool? canHide, - }) => - OrderedCategoryList( - hidden: hidden ?? this.hidden, - sortOrder: sortOrder ?? this.sortOrder, - canHide: canHide ?? this.canHide, - ); + }) => OrderedCategoryList( + hidden: hidden ?? this.hidden, + sortOrder: sortOrder ?? this.sortOrder, + canHide: canHide ?? this.canHide, + ); - Set getSorted([Set all = const {}]) => { + Set getSorted([Set all = const {}]) => + { ...sortOrder, ...all, // .toList()..sort(stringSorter(order: SortOrder.asc)) - } - .where( - (cat) => !hidden.contains(cat), - ) - .toSet() - .cast(); + }.where((cat) => !hidden.contains(cat)).toSet().cast(); @override bool operator ==(Object other) => @@ -224,11 +226,7 @@ class OrderedCategoryList { canHide == other.canHide; @override - int get hashCode => Object.hashAll([ - hidden, - sortOrder, - canHide, - ]); + int get hashCode => Object.hashAll([hidden, sortOrder, canHide]); String get debugProperties => 'hidden: $hidden, sortOrder: $sortOrder, canHide: $canHide'; @@ -248,17 +246,12 @@ class NoteCategoryList extends OrderedCategoryList { NoteCategoryList.fromJson(json.decode(str)); factory NoteCategoryList.fromJson(Map json) => - NoteCategoryList( - sortOrder: Set.from(json['sortOrder']), - ); + NoteCategoryList(sortOrder: Set.from(json['sortOrder'])); NoteCategoryList copyWithInherited({ // Set? categories, Set? sortOrder, - }) => - NoteCategoryList( - sortOrder: sortOrder ?? this.sortOrder, - ); + }) => NoteCategoryList(sortOrder: sortOrder ?? this.sortOrder); @override String get debugProperties => 'sortOrder: $sortOrder'; @@ -288,11 +281,10 @@ class ActionCategoryList extends OrderedCategoryList { // Set? categories, Set? sortOrder, Set? hidden, - }) => - ActionCategoryList( - sortOrder: sortOrder ?? this.sortOrder, - hidden: hidden ?? this.hidden, - ); + }) => ActionCategoryList( + sortOrder: sortOrder ?? this.sortOrder, + hidden: hidden ?? this.hidden, + ); @override Map toJson() { diff --git a/lib/app/modules/Home/views/local_widgets/home_character_dynamic_cards.dart b/lib/app/modules/Home/views/local_widgets/home_character_dynamic_cards.dart index 79bac8ab..f373c13c 100644 --- a/lib/app/modules/Home/views/local_widgets/home_character_dynamic_cards.dart +++ b/lib/app/modules/Home/views/local_widgets/home_character_dynamic_cards.dart @@ -1,3 +1,4 @@ +import 'package:dungeon_paper/app/data/models/character_settings.dart'; import 'package:dungeon_paper/app/data/models/item.dart'; import 'package:dungeon_paper/app/data/models/meta.dart'; import 'package:dungeon_paper/app/data/models/move.dart'; @@ -25,6 +26,7 @@ import 'package:dungeon_paper/app/widgets/cards/spell_card.dart'; import 'package:dungeon_paper/app/widgets/cards/spell_card_mini.dart'; import 'package:dungeon_paper/app/widgets/dialogs/confirm_delete_dialog.dart'; import 'package:dungeon_paper/app/widgets/menus/entity_edit_menu.dart'; +import 'package:dungeon_paper/core/utils/list_utils.dart'; import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; @@ -58,14 +60,14 @@ class HomeCharacterDynamicCards extends StatelessWidget crossAxisAlignment: CrossAxisAlignment.start, children: [ ...{...controller.current.actionCategories, 'Note'} - .map((cat) => _buildList(context, controller, cat)) + .map((cat) => _buildListByType(context, controller, cat)) .reduce((value, element) => value + element), ], ), ); } - List _buildList( + List _buildListByType( BuildContext context, CharacterProvider controller, String cat, @@ -169,8 +171,9 @@ class HomeCharacterDynamicCards extends StatelessWidget List classActionCards( BuildContext context, - CharacterProvider charProvider, - ) { + CharacterProvider charProvider, { + required bool expandable, + }) { final raceCard = RaceCard( race: char.race, onSave: @@ -194,6 +197,8 @@ class HomeCharacterDynamicCards extends StatelessWidget ); final alignmentCard = AlignmentValueCard( alignment: char.bio.alignment, + expandable: expandable, + initiallyExpanded: !expandable, actions: [ EntityEditMenu( onDelete: null, @@ -225,376 +230,373 @@ class HomeCharacterDynamicCards extends StatelessWidget }, T); } - List _notesList(BuildContext context, CharacterProvider controller) { + List _listViewBuilder( + BuildContext context, + CharacterProvider controller, { + required List list, + required Widget Function(BuildContext, LibraryProvider, T) cardBuilder, + required Widget Function(BuildContext, LibraryProvider, T, VoidCallback) + cardMiniBuilder, + required Widget Function(BuildContext, LibraryProvider, T) + expandedCardBuilder, + required String title, + }) { + if (list.isEmpty) { + return []; + } return [ - if (notes.isNotEmpty) ...[ - const SizedBox(height: 10), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Text(tr.home.categories.notes), - ), - ], - HorizontalCardListView( - cardSize: cardSize, - items: notes, - cardBuilder: - (context, note, index, onTap) => NoteCardMini( - note: notes[index], - onTap: onTap, - onSave: - (note) => controller.updateCharacter( - CharacterUtils.updateNotes(controller.current, [note]), - ), - ), - expandedCardBuilder: - (context, note, index) => - notes.isNotEmpty && index < notes.length - ? NoteCard( - maxContentHeight: maxContentHeight(context), - expandable: false, - initiallyExpanded: true, - note: notes[index], - actions: [ - EntityEditMenu( - onEdit: - () => ModelPages.openNotePage( - context, - note: notes[index], - onSave: - (note) => controller.updateCharacter( - CharacterUtils.updateNotes( - controller.current, - [note], - ), - ), - ), - onDelete: _delete( - context, - note, - note.title, - tn(Note), - () => controller.updateCharacter( - CharacterUtils.removeNotes(controller.current, [ - note, - ]), - ), - ), - ), - ], - onSave: (note) { - controller.updateCharacter( - CharacterUtils.updateNotes(controller.current, [ - note, - ]), - ); - if (!note.favorite) { - Navigator.of(context).pop(); - } - }, - ) - : const SizedBox.shrink(), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16).copyWith(top: 10), + child: Text(title), ), - ]; - } - - List _movesList(BuildContext context, CharacterProvider controller) { - return [ - if (moves.isNotEmpty) - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Text(tr.home.categories.moves), - ), Builder( builder: (context) { - return HorizontalCardListView( + if (char.settings.favoritesView == FavoritesView.list) { + return Column( + children: [ + for (final item in list) + Padding( + padding: const EdgeInsets.only(top: 8, left: 8, right: 8), + child: LibraryProvider.consumer( + (context, library, _) => + cardBuilder(context, library, item), + ), + ), + ], + ); + } + return HorizontalCardListView( cardSize: cardSize, - items: moves, + items: list, cardBuilder: - (context, move, index, onTap) => MoveCardMini( - move: moves[index], - onTap: onTap, - onSave: - (move) => controller.updateCharacter( - CharacterUtils.updateMoves(controller.current, [move]), - ), - abilityScores: controller.current.abilityScores, + (context, item, index, onTap) => LibraryProvider.consumer( + (context, library, _) => + cardMiniBuilder(context, library, item, onTap), ), expandedCardBuilder: - (context, move, index) => - LibraryProvider.consumer((context, library, _) { - return moves.isNotEmpty && index < moves.length - ? MoveCard( - maxContentHeight: maxContentHeight(context), - expandable: false, - initiallyExpanded: true, - move: moves[index], - abilityScores: controller.current.abilityScores, - actions: [ - EntityEditMenu( - onEdit: - () => ModelPages.openMovePage( - context, - abilityScores: - controller.current.abilityScores, - move: moves[index], - onSave: - (move) => library.upsertToCharacter( - [move], - forkBehavior: - ForkBehavior.increaseVersion, - ), - ), - onDelete: _delete( - context, - move, - move.name, - tn(Move), - () => controller.updateCharacter( - CharacterUtils.removeMoves( - controller.current, - [move], - ), - ), - ), - ), - ], - onSave: (move) { - controller.updateCharacter( - CharacterUtils.updateMoves(controller.current, [ - move, - ]), - ); - if (!move.favorite) { - Navigator.of(context).pop(); - } - }, - ) - : const SizedBox.shrink(); - }), - // leading: raceCardMini != null && - // controller.current.settings.racePosition == - // RacePosition.start - // ? [raceCardMini] - // : [], - // trailing: raceCardMini != null && - // controller.current.settings.racePosition == - // RacePosition.end - // ? [raceCardMini] - // : [], + (context, item, index) => LibraryProvider.consumer( + (context, library, _) => + list.isNotEmpty && index < list.length + ? expandedCardBuilder(context, library, item) + : SizedBox.shrink(), + ), ); }, ), ]; } - List _spellsList(BuildContext context, CharacterProvider controller) { - return [ - if (spells.isNotEmpty) ...[ - const SizedBox(height: 10), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Text(tr.home.categories.spells), + List _notesList(BuildContext context, CharacterProvider controller) { + onSave(Note note) => controller.updateCharacter( + CharacterUtils.updateNotes(controller.current, [note]), + ); + actions(LibraryProvider library, Note note) => [ + EntityEditMenu( + onEdit: + () => ModelPages.openNotePage(context, note: note, onSave: onSave), + onDelete: _delete( + context, + note, + note.title, + tn(Note), + () => controller.updateCharacter( + CharacterUtils.removeNotes(controller.current, [note]), + ), ), - ], - HorizontalCardListView( - cardSize: cardSize, - items: spells, - cardBuilder: - (context, spell, index, onTap) => SpellCardMini( - spell: spells[index], - onTap: onTap, - onSave: - (spell) => controller.updateCharacter( - CharacterUtils.updateSpells(controller.current, [spell]), - ), - abilityScores: controller.current.abilityScores, - ), - expandedCardBuilder: - (context, spell, index) => - spells.isNotEmpty && index < spells.length - ? SpellCard( - maxContentHeight: maxContentHeight(context), - expandable: false, - initiallyExpanded: true, - spell: spells[index], - abilityScores: controller.current.abilityScores, - actions: [ - EntityEditMenu( - onEdit: - () => ModelPages.openSpellPage( - context, - abilityScores: controller.current.abilityScores, - classKeys: spells[index].classKeys, - spell: spells[index], - onSave: - (spell) => controller.updateCharacter( - CharacterUtils.updateSpells( - controller.current, - [spell], - ), - ), - ), - onDelete: _delete( - context, - spell, - spell.name, - tn(Spell), - () => controller.updateCharacter( - CharacterUtils.removeSpells(controller.current, [ - spell, - ]), - ), - ), - ), - ], - onSave: (spell) { - controller.updateCharacter( - CharacterUtils.updateSpells(controller.current, [ - spell, - ]), - ); - if (!spell.prepared) { - Navigator.of(context).pop(); - } - }, - ) - : const SizedBox.shrink(), ), ]; + + return _listViewBuilder( + context, + controller, + title: tr.home.categories.notes, + list: notes, + cardMiniBuilder: + (context, library, note, onTap) => + NoteCardMini(note: note, onTap: onTap, onSave: onSave), + cardBuilder: + (context, library, note) => NoteCard( + note: note, + onSave: onSave, + actions: actions(library, note), + ), + expandedCardBuilder: + (context, library, note) => NoteCard( + maxContentHeight: maxContentHeight(context), + expandable: false, + initiallyExpanded: true, + note: note, + actions: actions(library, note), + onSave: (note) { + onSave(note); + if (!note.favorite) { + Navigator.of(context).pop(); + } + }, + ), + ); + } + + List _movesList(BuildContext context, CharacterProvider controller) { + onSave(Move move) => controller.updateCharacter( + CharacterUtils.updateMoves(controller.current, [move]), + ); + actions(LibraryProvider library, Move move) => [ + EntityEditMenu( + onEdit: + () => ModelPages.openMovePage( + context, + abilityScores: controller.current.abilityScores, + move: move, + onSave: onSave, + ), + onDelete: _delete( + context, + move, + move.name, + tn(Move), + () => controller.updateCharacter( + CharacterUtils.removeMoves(controller.current, [move]), + ), + ), + ), + ]; + return _listViewBuilder( + context, + controller, + title: tr.home.categories.moves, + list: moves, + cardMiniBuilder: + (context, library, move, onTap) => MoveCardMini( + move: move, + onTap: onTap, + onSave: onSave, + abilityScores: controller.current.abilityScores, + ), + cardBuilder: + (context, library, move) => MoveCard( + move: move, + onSave: onSave, + abilityScores: controller.current.abilityScores, + actions: actions(library, move), + ), + expandedCardBuilder: + (context, library, move) => MoveCard( + maxContentHeight: maxContentHeight(context), + expandable: false, + initiallyExpanded: true, + move: move, + abilityScores: controller.current.abilityScores, + actions: actions(library, move), + onSave: (move) { + controller.updateCharacter( + CharacterUtils.updateMoves(controller.current, [move]), + ); + if (!move.favorite) { + Navigator.of(context).pop(); + } + }, + ), + ); + } + + List _spellsList(BuildContext context, CharacterProvider controller) { + onSave(Spell spell) => controller.updateCharacter( + CharacterUtils.updateSpells(controller.current, [spell]), + ); + actions(LibraryProvider library, Spell spell) => [ + EntityEditMenu( + onEdit: + () => ModelPages.openSpellPage( + context, + abilityScores: controller.current.abilityScores, + classKeys: spell.classKeys, + spell: spell, + onSave: onSave, + ), + onDelete: _delete( + context, + spell, + spell.name, + tn(Spell), + () => controller.updateCharacter( + CharacterUtils.removeSpells(controller.current, [spell]), + ), + ), + ), + ]; + return _listViewBuilder( + context, + controller, + title: tr.home.categories.spells, + list: spells, + cardMiniBuilder: + (context, library, spell, onTap) => SpellCardMini( + spell: spell, + onTap: onTap, + onSave: onSave, + abilityScores: controller.current.abilityScores, + ), + cardBuilder: + (context, library, spell) => SpellCard( + spell: spell, + onSave: onSave, + abilityScores: controller.current.abilityScores, + actions: actions(library, spell), + ), + expandedCardBuilder: + (context, library, spell) => SpellCard( + maxContentHeight: maxContentHeight(context), + expandable: false, + initiallyExpanded: true, + spell: spell, + abilityScores: controller.current.abilityScores, + actions: actions(library, spell), + onSave: (spell) { + onSave(spell); + if (!spell.prepared) { + Navigator.of(context).pop(); + } + }, + ), + ); } List _itemsList(BuildContext context, CharacterProvider controller) { - return [ - if (items.isNotEmpty) ...[ - const SizedBox(height: 10), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Text(tr.home.categories.items), - ), - ], - HorizontalCardListView( - cardSize: cardSize, - items: items, - cardBuilder: - (context, item, index, onTap) => ItemCardMini( - item: items[index], - onTap: onTap, + onSave(Item item) => controller.updateCharacter( + CharacterUtils.updateItems(controller.current, [item]), + ); + + actions(LibraryProvider library, Item item) => [ + EntityEditMenu( + onEdit: + () => ModelPages.openItemPage( + context, + item: item, onSave: - (item) => controller.updateCharacter( - CharacterUtils.updateItems(controller.current, [item]), - ), + (item) => library.upsertToCharacter([ + item, + ], forkBehavior: ForkBehavior.increaseVersion), ), - expandedCardBuilder: - (context, item, index) => - items.isNotEmpty && index < items.length - ? ItemCard( - maxContentHeight: maxContentHeight(context), - expandable: false, - initiallyExpanded: true, - item: items[index], - actions: [ - EntityEditMenu( - onEdit: - () => ModelPages.openItemPage( - context, - item: items[index], - onSave: - (item) => controller.updateCharacter( - CharacterUtils.updateItems( - controller.current, - [item], - ), - ), - ), - onDelete: _delete( - context, - item, - item.name, - tn(Item), - () => controller.updateCharacter( - CharacterUtils.removeItems(controller.current, [ - item, - ]), - ), - ), - leading: [ - ChecklistMenuEntry( - value: 'countArmor', - checked: item.settings.countArmor, - label: Text(tr.items.settings.countArmor), - onChanged: - (value) => controller.updateCharacter( - CharacterUtils.updateItems( - controller.current, - [ - item.copyWithInherited( - settings: item.settings.copyWith( - countArmor: value!, - ), - ), - ], - ), - ), - ), - ChecklistMenuEntry( - value: 'countDamage', - checked: item.settings.countDamage, - label: Text(tr.items.settings.countDamage), - onChanged: - (value) => controller.updateCharacter( - CharacterUtils.updateItems( - controller.current, - [ - item.copyWithInherited( - settings: item.settings.copyWith( - countDamage: value!, - ), - ), - ], - ), - ), - ), - ChecklistMenuEntry( - value: 'countWeight', - checked: item.settings.countWeight, - label: Text(tr.items.settings.countWeight), - onChanged: - (value) => controller.updateCharacter( - CharacterUtils.updateItems( - controller.current, - [ - item.copyWithInherited( - settings: item.settings.copyWith( - countWeight: value!, - ), - ), - ], - ), - ), - ), - ], - ), - ], - onSave: (item) { - controller.updateCharacter( - CharacterUtils.updateItems(controller.current, [ - item, - ]), - ); - if (!item.equipped) { - Navigator.of(context).pop(); - } - }, - ) - : const SizedBox.shrink(), + onDelete: _delete( + context, + item, + item.name, + tn(Item), + () => controller.updateCharacter( + CharacterUtils.removeItems(controller.current, [item]), + ), + ), + leading: [ + ChecklistMenuEntry( + value: 'countArmor', + checked: item.settings.countArmor, + label: Text(tr.items.settings.countArmor), + onChanged: + (value) => controller.updateCharacter( + CharacterUtils.updateItems(controller.current, [ + item.copyWithInherited( + settings: item.settings.copyWith(countArmor: value!), + ), + ]), + ), + ), + ChecklistMenuEntry( + value: 'countDamage', + checked: item.settings.countDamage, + label: Text(tr.items.settings.countDamage), + onChanged: + (value) => controller.updateCharacter( + CharacterUtils.updateItems(controller.current, [ + item.copyWithInherited( + settings: item.settings.copyWith(countDamage: value!), + ), + ]), + ), + ), + ChecklistMenuEntry( + value: 'countWeight', + checked: item.settings.countWeight, + label: Text(tr.items.settings.countWeight), + onChanged: + (value) => controller.updateCharacter( + CharacterUtils.updateItems(controller.current, [ + item.copyWithInherited( + settings: item.settings.copyWith(countWeight: value!), + ), + ]), + ), + ), + ], ), ]; + + return _listViewBuilder( + context, + controller, + title: tr.home.categories.items, + list: items, + cardMiniBuilder: + (context, library, item, onTap) => + ItemCardMini(item: item, onTap: onTap, onSave: onSave), + cardBuilder: + (context, library, item) => ItemCard( + item: item, + onSave: onSave, + actions: actions(library, item), + ), + expandedCardBuilder: + (context, library, item) => ItemCard( + maxContentHeight: maxContentHeight(context), + expandable: false, + initiallyExpanded: true, + item: item, + actions: actions(library, item), + onSave: (item) { + controller.updateCharacter( + CharacterUtils.updateItems(controller.current, [item]), + ); + if (!item.equipped) { + Navigator.of(context).pop(); + } + }, + ), + ); } List _classActionsList( BuildContext context, CharacterProvider controller, ) { + if (controller.current.classActions.isEmpty) { + return []; + } + if (controller.current.settings.favoritesView == FavoritesView.list) { + return [ + const SizedBox(height: 10), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Text(tr.home.categories.classActions), + ), + Column( + children: [ + for (final item in enumerate(classActions)) + Padding( + padding: const EdgeInsets.only(top: 8, left: 8, right: 8), + child: LibraryProvider.consumer( + (context, library, _) => + classActionCards( + context, + controller, + expandable: true, + )[item.index], + ), + ), + ], + ), + ]; + } + return [ const SizedBox(height: 10), Padding( @@ -609,7 +611,7 @@ class HomeCharacterDynamicCards extends StatelessWidget classActionCardsMini(context, controller)[index], expandedCardBuilder: (context, item, index) => - classActionCards(context, controller)[index], + classActionCards(context, controller, expandable: false)[index], ), ]; } diff --git a/lib/app/modules/Home/views/local_widgets/home_character_extras.dart b/lib/app/modules/Home/views/local_widgets/home_character_extras.dart index 8771b6b8..1ce879c8 100644 --- a/lib/app/modules/Home/views/local_widgets/home_character_extras.dart +++ b/lib/app/modules/Home/views/local_widgets/home_character_extras.dart @@ -10,6 +10,7 @@ import 'package:dungeon_paper/app/routes/app_pages.dart'; import 'package:dungeon_paper/app/widgets/atoms/menu_button.dart'; import 'package:dungeon_paper/app/widgets/dialogs/character_bio_dialog.dart'; import 'package:dungeon_paper/app/widgets/dialogs/character_bonds_flags_dialog.dart'; +import 'package:dungeon_paper/app/widgets/dialogs/character_favorites_view_select_dialog.dart'; import 'package:dungeon_paper/app/widgets/dialogs/custom_roll_buttons_dialog.dart'; import 'package:dungeon_paper/app/widgets/dialogs/debilities_dialog.dart'; import 'package:dungeon_paper/core/dw_icons.dart'; @@ -43,8 +44,9 @@ class HomeCharacterExtras extends StatelessWidget with CharacterProviderMixin { MenuEntry( value: 'class', icon: Icon(CharacterClass.genericIcon), - label: - Text(tr.generic.changeEntity(tr.entity(tn(CharacterClass)))), + label: Text( + tr.generic.changeEntity(tr.entity(tn(CharacterClass))), + ), onSelect: () => _openCharClass(context), ), MenuEntry( @@ -53,6 +55,35 @@ class HomeCharacterExtras extends StatelessWidget with CharacterProviderMixin { label: Text(tr.generic.changeEntity(tr.entity(tn(Race)))), onSelect: () => _openRace(context), ), + ], + ), + IconButton( + icon: const Icon(Icons.text_snippet), + tooltip: tr.home.menu.bio, + onPressed: () => _openBio(context), + ), + CharacterProvider.consumer( + (context, controller, _) => IconButton( + onPressed: () => _openBondsFlags(context), + icon: Transform.scale( + scaleX: -1, + child: const Icon(Icons.handshake), + ), + tooltip: SessionMark.categoryTitle( + bonds: controller.maybeCurrent?.bonds ?? [], + flags: controller.maybeCurrent?.flags ?? [], + ), + ), + ), + IconButton( + onPressed: () => _openDebilities(context), + icon: const Icon(Icons.personal_injury), + tooltip: tr.home.menu.debilities, + ), + MenuButton( + icon: const Icon(Icons.settings), + tooltip: tr.home.menu.character.settings, + items: [ MenuEntry( value: 'roll_buttons', icon: const Icon(DwIcons.dice_d6), @@ -65,34 +96,20 @@ class HomeCharacterExtras extends StatelessWidget with CharacterProviderMixin { label: Text(tr.home.menu.character.theme), onSelect: () => _openThemeSelect(context), ), + MenuEntry( + value: 'favorites_view', + icon: const Icon(Icons.grid_view), + label: Text(tr.home.menu.character.favoritesView), + onSelect: () => _openFavoritesViewSelect(context), + ), ], ), - IconButton( - icon: const Icon(Icons.text_snippet), - tooltip: tr.home.menu.bio, - onPressed: () => _openBio(context), - ), - CharacterProvider.consumer( - (context, controller, _) => IconButton( - onPressed: () => _openBondsFlags(context), - icon: - Transform.scale(scaleX: -1, child: const Icon(Icons.handshake)), - tooltip: SessionMark.categoryTitle( - bonds: controller.maybeCurrent?.bonds ?? [], - flags: controller.maybeCurrent?.flags ?? [], - ), - ), - ), - IconButton( - onPressed: () => _openDebilities(context), - icon: const Icon(Icons.personal_injury), - tooltip: tr.home.menu.debilities, - ), - IconButton( - onPressed: null, - icon: const Icon(Icons.groups), - tooltip: tr.entityPlural(tn(Campaign)), - ), + + // IconButton( + // onPressed: null, + // icon: const Icon(Icons.groups), + // tooltip: tr.entityPlural(tn(Campaign)), + // ), ], ); } @@ -102,8 +119,10 @@ class HomeCharacterExtras extends StatelessWidget with CharacterProviderMixin { Routes.abilityScores, arguments: AbilityScoresFormArguments( abilityScores: charProvider.current.abilityScores, - onChanged: (abilityScores) => charProvider.updateCharacter( - charProvider.current.copyWith(abilityScores: abilityScores)), + onChanged: + (abilityScores) => charProvider.updateCharacter( + charProvider.current.copyWith(abilityScores: abilityScores), + ), ), ); } @@ -112,9 +131,13 @@ class HomeCharacterExtras extends StatelessWidget with CharacterProviderMixin { Navigator.of(context).pushNamed( Routes.basicInfo, arguments: BasicInfoFormArguments( - onChanged: (name, avatar) => charProvider.updateCharacter( - charProvider.current.copyWith(displayName: name, avatarUrl: avatar), - ), + onChanged: + (name, avatar) => charProvider.updateCharacter( + charProvider.current.copyWith( + displayName: name, + avatarUrl: avatar, + ), + ), name: charProvider.current.displayName, avatarUrl: charProvider.current.avatarUrl, ), @@ -130,12 +153,14 @@ class HomeCharacterExtras extends StatelessWidget with CharacterProviderMixin { context, character: charProvider.current, preSelection: charProvider.current.race, - onSelected: (race) => charProvider.updateCharacter( - charProvider.current.copyWithInherited( - race: race.copyWithInherited( - favorite: charProvider.current.race.favorite), - ), - ), + onSelected: + (race) => charProvider.updateCharacter( + charProvider.current.copyWithInherited( + race: race.copyWithInherited( + favorite: charProvider.current.race.favorite, + ), + ), + ), ); } @@ -143,37 +168,50 @@ class HomeCharacterExtras extends StatelessWidget with CharacterProviderMixin { ModelPages.openCharacterClassesList( context, character: charProvider.current, - onSelected: (cls) => charProvider.updateCharacter( - // TODO add a reset dialog to confirm + ask what to reset: moves, spells, alignment, rac - charProvider.current.copyWithInherited( - characterClass: cls, - ), - ), + onSelected: + (cls) => charProvider.updateCharacter( + // TODO add a reset dialog to confirm + ask what to reset: moves, spells, alignment, rac + charProvider.current.copyWithInherited(characterClass: cls), + ), ); } void _openBondsFlags(BuildContext context) { showDialog( - context: context, builder: (_) => const CharacterBondsFlagsDialog()); + context: context, + builder: (_) => const CharacterBondsFlagsDialog(), + ); } void _openDebilities(BuildContext context) { showDialog( - context: context, builder: (_) => const CharacterDebilitiesDialog()); + context: context, + builder: (_) => const CharacterDebilitiesDialog(), + ); } void _openRollButtons(BuildContext context) { showDialog( context: context, - builder: (_) => CustomRollButtonsDialog( - character: charProvider.current, - onChanged: (rollButtons) => charProvider.updateCharacter( - charProvider.current.copyWith( - settings: charProvider.current.settings - .copyWith(rollButtons: rollButtons), + builder: + (_) => CustomRollButtonsDialog( + character: charProvider.current, + onChanged: + (rollButtons) => charProvider.updateCharacter( + charProvider.current.copyWith( + settings: charProvider.current.settings.copyWith( + rollButtons: rollButtons, + ), + ), + ), ), - ), - ), + ); + } + + void _openFavoritesViewSelect(BuildContext context) { + showDialog( + context: context, + builder: (_) => const CharacterFavoritesViewSelectDialog(), ); } diff --git a/lib/app/widgets/dialogs/character_favorites_view_select_dialog.dart b/lib/app/widgets/dialogs/character_favorites_view_select_dialog.dart new file mode 100644 index 00000000..d996ed65 --- /dev/null +++ b/lib/app/widgets/dialogs/character_favorites_view_select_dialog.dart @@ -0,0 +1,81 @@ +import 'package:dungeon_paper/app/data/models/character_settings.dart'; +import 'package:dungeon_paper/app/data/services/character_provider.dart'; +import 'package:dungeon_paper/app/widgets/molecules/dialog_controls.dart'; +import 'package:dungeon_paper/i18n.dart'; +import 'package:flutter/material.dart'; + +class CharacterFavoritesViewSelectDialog extends StatefulWidget { + const CharacterFavoritesViewSelectDialog({super.key}); + + @override + State createState() => + _CharacterFavoritesViewSelectDialogState(); +} + +class _CharacterFavoritesViewSelectDialogState + extends State + with CharacterProviderMixin { + late FavoritesView value; + + @override + void initState() { + super.initState(); + value = char.settings.favoritesView; + } + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Text('Select View'), + content: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + RadioListTile.adaptive( + value: FavoritesView.cards, + groupValue: value, + onChanged: _onSelect, + title: Row( + children: [ + Icon(Icons.grid_view), + const SizedBox(width: 8), + Expanded(child: Text(tr.character.favoritesView.cards)), + ], + ), + ), + RadioListTile.adaptive( + value: FavoritesView.list, + groupValue: value, + onChanged: _onSelect, + title: Row( + children: [ + Icon(Icons.list), + const SizedBox(width: 8), + Expanded(child: Text(tr.character.favoritesView.list)), + ], + ), + ), + ], + ), + ), + actions: DialogControls.save( + context, + onSave: () { + charProvider.updateCharacter( + char.copyWith( + settings: char.settings.copyWith(favoritesView: value), + ), + ); + Navigator.of(context).pop(); + }, + onCancel: () => Navigator.of(context).pop(), + ), + ); + } + + void _onSelect(FavoritesView? value) { + setState(() { + this.value = value!; + }); + } +} diff --git a/lib/i18n/messages.i18n.dart b/lib/i18n/messages.i18n.dart index 4edfeced..00a40cda 100644 --- a/lib/i18n/messages.i18n.dart +++ b/lib/i18n/messages.i18n.dart @@ -1239,6 +1239,16 @@ class CharacterMenuHomeMessages { /// "Character Theme" /// ``` String get theme => """Character Theme"""; + + /// ```dart + /// "View Settings" + /// ``` + String get settings => """View Settings"""; + + /// ```dart + /// "Change Favorites View" + /// ``` + String get favoritesView => """Change Favorites View"""; } class EmptyStateHomeMessages { @@ -1432,6 +1442,8 @@ class CharacterMessages { /// ``` String get noCategory => """No Category"""; ThemeCharacterMessages get theme => ThemeCharacterMessages(this); + FavoritesViewCharacterMessages get favoritesView => + FavoritesViewCharacterMessages(this); } class DataCharacterMessages { @@ -1536,6 +1548,21 @@ class ThemeCharacterMessages { String get defaultDark => """${_defaultTheme('dark')}"""; } +class FavoritesViewCharacterMessages { + final CharacterMessages _parent; + const FavoritesViewCharacterMessages(this._parent); + + /// ```dart + /// "Cards View" + /// ``` + String get cards => """Cards View"""; + + /// ```dart + /// "List View" + /// ``` + String get list => """List View"""; +} + class CharacterClassMessages { final Messages _parent; const CharacterClassMessages(this._parent); @@ -4145,6 +4172,8 @@ Map get messagesMap => { """home.menu.character.abilityScores""": """Ability Scores""", """home.menu.character.customRolls""": """Quick-Roll Buttons""", """home.menu.character.theme""": """Character Theme""", + """home.menu.character.settings""": """View Settings""", + """home.menu.character.favoritesView""": """Change Favorites View""", """home.menu.bio""": """Character Biography""", """home.menu.debilities""": """Debilities""", """home.emptyState.guest.title""": """Sign in to get more features""", @@ -4188,6 +4217,8 @@ Map get messagesMap => { """character.header.separator""": """ ∙ """, """character.noCategory""": """No Category""", """character.theme.title""": """Character Theme""", + """character.favoritesView.cards""": """Cards View""", + """character.favoritesView.list""": """List View""", """characterClass.baseLoad""": """Base Load""", """characterClass.baseHp""": """Base HP""", """characterClass.damageDice""": """Damage Dice""", diff --git a/lib/i18n/messages.i18n.yaml b/lib/i18n/messages.i18n.yaml index 673ea149..d7c87821 100644 --- a/lib/i18n/messages.i18n.yaml +++ b/lib/i18n/messages.i18n.yaml @@ -247,6 +247,8 @@ home: abilityScores: Ability Scores customRolls: Quick-Roll Buttons theme: Character Theme + settings: View Settings + favoritesView: Change Favorites View bio: Character Biography debilities: Debilities emptyState: @@ -307,6 +309,9 @@ character: _defaultTheme(String type): Default $type theme defaultLight: "${_defaultTheme('light')}" defaultDark: "${_defaultTheme('dark')}" + favoritesView: + cards: Cards View + list: List View characterClass: baseLoad: Base Load diff --git a/lib/i18n/messages_pl_PL.i18n.dart b/lib/i18n/messages_pl_PL.i18n.dart index d1a5c92c..0f759526 100644 --- a/lib/i18n/messages_pl_PL.i18n.dart +++ b/lib/i18n/messages_pl_PL.i18n.dart @@ -1251,6 +1251,16 @@ class CharacterMenuHomeMessagesPlPL extends CharacterMenuHomeMessages { /// "Character Theme" /// ``` String get theme => """Character Theme"""; + + /// ```dart + /// "View Settings" + /// ``` + String get settings => """View Settings"""; + + /// ```dart + /// "Change Favorites View" + /// ``` + String get favoritesView => """Change Favorites View"""; } class EmptyStateHomeMessagesPlPL extends EmptyStateHomeMessages { @@ -1445,6 +1455,8 @@ class CharacterMessagesPlPL extends CharacterMessages { /// ``` String get noCategory => """No Category"""; ThemeCharacterMessagesPlPL get theme => ThemeCharacterMessagesPlPL(this); + FavoritesViewCharacterMessagesPlPL get favoritesView => + FavoritesViewCharacterMessagesPlPL(this); } class DataCharacterMessagesPlPL extends DataCharacterMessages { @@ -1549,6 +1561,22 @@ class ThemeCharacterMessagesPlPL extends ThemeCharacterMessages { String get defaultDark => """${_defaultTheme('dark')}"""; } +class FavoritesViewCharacterMessagesPlPL + extends FavoritesViewCharacterMessages { + final CharacterMessagesPlPL _parent; + const FavoritesViewCharacterMessagesPlPL(this._parent) : super(_parent); + + /// ```dart + /// "Cards View" + /// ``` + String get cards => """Cards View"""; + + /// ```dart + /// "List View" + /// ``` + String get list => """List View"""; +} + class CharacterClassMessagesPlPL extends CharacterClassMessages { final MessagesPlPL _parent; const CharacterClassMessagesPlPL(this._parent) : super(_parent); @@ -4259,6 +4287,8 @@ Map get messagesPlPLMap => { """home.menu.character.abilityScores""": """Ability Scores""", """home.menu.character.customRolls""": """Quick-Roll Buttons""", """home.menu.character.theme""": """Character Theme""", + """home.menu.character.settings""": """View Settings""", + """home.menu.character.favoritesView""": """Change Favorites View""", """home.menu.bio""": """Character Biography""", """home.menu.debilities""": """Debilities""", """home.emptyState.guest.title""": """Sign in to get more features""", @@ -4302,6 +4332,8 @@ Map get messagesPlPLMap => { """character.header.separator""": """ ∙ """, """character.noCategory""": """No Category""", """character.theme.title""": """Character Theme""", + """character.favoritesView.cards""": """Cards View""", + """character.favoritesView.list""": """List View""", """characterClass.baseLoad""": """Base Load""", """characterClass.baseHp""": """Base HP""", """characterClass.damageDice""": """Damage Dice""", diff --git a/lib/i18n/messages_pl_PL.i18n.yaml b/lib/i18n/messages_pl_PL.i18n.yaml index 673ea149..d7c87821 100644 --- a/lib/i18n/messages_pl_PL.i18n.yaml +++ b/lib/i18n/messages_pl_PL.i18n.yaml @@ -247,6 +247,8 @@ home: abilityScores: Ability Scores customRolls: Quick-Roll Buttons theme: Character Theme + settings: View Settings + favoritesView: Change Favorites View bio: Character Biography debilities: Debilities emptyState: @@ -307,6 +309,9 @@ character: _defaultTheme(String type): Default $type theme defaultLight: "${_defaultTheme('light')}" defaultDark: "${_defaultTheme('dark')}" + favoritesView: + cards: Cards View + list: List View characterClass: baseLoad: Base Load diff --git a/lib/i18n/messages_pt_BR.i18n.dart b/lib/i18n/messages_pt_BR.i18n.dart index 514c044d..8018678c 100644 --- a/lib/i18n/messages_pt_BR.i18n.dart +++ b/lib/i18n/messages_pt_BR.i18n.dart @@ -1254,6 +1254,11 @@ class MenuHomeMessagesPtBR extends MenuHomeMessages { CharacterMenuHomeMessagesPtBR get character => CharacterMenuHomeMessagesPtBR(this); + /// ```dart + /// "Change Favorites View" + /// ``` + String get favoritesView => """Change Favorites View"""; + /// ```dart /// "Biografia do Personagem" /// ``` @@ -1293,6 +1298,11 @@ class CharacterMenuHomeMessagesPtBR extends CharacterMenuHomeMessages { /// "Tema do Personagem" /// ``` String get theme => """Tema do Personagem"""; + + /// ```dart + /// "View Settings" + /// ``` + String get settings => """View Settings"""; } class EmptyStateHomeMessagesPtBR extends EmptyStateHomeMessages { @@ -1488,6 +1498,8 @@ class CharacterMessagesPtBR extends CharacterMessages { /// ``` String get noCategory => """Sem Categoria"""; ThemeCharacterMessagesPtBR get theme => ThemeCharacterMessagesPtBR(this); + FavoritesViewCharacterMessagesPtBR get favoritesView => + FavoritesViewCharacterMessagesPtBR(this); } class DataCharacterMessagesPtBR extends DataCharacterMessages { @@ -1592,6 +1604,22 @@ class ThemeCharacterMessagesPtBR extends ThemeCharacterMessages { String get defaultDark => """${_defaultTheme('escuro')}"""; } +class FavoritesViewCharacterMessagesPtBR + extends FavoritesViewCharacterMessages { + final CharacterMessagesPtBR _parent; + const FavoritesViewCharacterMessagesPtBR(this._parent) : super(_parent); + + /// ```dart + /// "Cards View" + /// ``` + String get cards => """Cards View"""; + + /// ```dart + /// "List View" + /// ``` + String get list => """List View"""; +} + class CharacterClassMessagesPtBR extends CharacterClassMessages { final MessagesPtBR _parent; const CharacterClassMessagesPtBR(this._parent) : super(_parent); @@ -4302,6 +4330,8 @@ Map get messagesPtBRMap => { """home.menu.character.abilityScores""": """Pontuações de Habilidade""", """home.menu.character.customRolls""": """Botões de Rolagem Rápida""", """home.menu.character.theme""": """Tema do Personagem""", + """home.menu.character.settings""": """View Settings""", + """home.menu.favoritesView""": """Change Favorites View""", """home.menu.bio""": """Biografia do Personagem""", """home.menu.debilities""": """Debilidades""", """home.emptyState.guest.title""": """Entre para obter mais recursos""", @@ -4345,6 +4375,8 @@ Map get messagesPtBRMap => { """character.header.separator""": """ ∙ """, """character.noCategory""": """Sem Categoria""", """character.theme.title""": """Tema do Personagem""", + """character.favoritesView.cards""": """Cards View""", + """character.favoritesView.list""": """List View""", """characterClass.baseLoad""": """Carga Base""", """characterClass.baseHp""": """HP Base""", """characterClass.damageDice""": """Dados de Dano""", diff --git a/lib/i18n/messages_pt_BR.i18n.yaml b/lib/i18n/messages_pt_BR.i18n.yaml index 96ab791d..664ec33e 100644 --- a/lib/i18n/messages_pt_BR.i18n.yaml +++ b/lib/i18n/messages_pt_BR.i18n.yaml @@ -267,6 +267,9 @@ home: abilityScores: Pontuações de Habilidade customRolls: Botões de Rolagem Rápida theme: Tema do Personagem + # TODO translate + settings: View Settings + favoritesView: Change Favorites View bio: Biografia do Personagem debilities: Debilidades emptyState: @@ -327,6 +330,10 @@ character: _defaultTheme(String type): Tema padrão $type defaultLight: "${_defaultTheme('claro')}" defaultDark: "${_defaultTheme('escuro')}" + # TODO translate + favoritesView: + cards: Cards View + list: List View characterClass: baseLoad: Carga Base diff --git a/lib/main.dart b/lib/main.dart index 360b01a2..6879d32a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -37,6 +37,7 @@ void main() async { options.dsn = secrets.sentryDsn; options.tracesSampleRate = kDebugMode ? 1.0 : 0.0; options.environment = kDebugMode ? 'development' : 'release'; + options.debug = false; }, appRunner: _init, );