From 905ed49245c9fb4ac18a123ab1f0b78e0fdb7eeb Mon Sep 17 00:00:00 2001 From: Chen Asraf Date: Sat, 9 Dec 2023 01:09:30 +0200 Subject: [PATCH] refactor: i18n (#30) * feat: intl poc * refactor: more translation migrations * refactor: move `tr` export to nicer path * refactor: more translation updates * feat: intl on many more files * feat: more i18n replacements * feat: more translation updates * feat: replace all left usages of S.current * chore: last forgotten cleanups * refactor: remove old intl files * chore: format all files * docs: update docs chore: use git version of i18n --- README.md | 20 +- lib/app/data/models/ability_scores.dart | 106 +- lib/app/data/models/alignment.dart | 31 +- lib/app/data/models/bio.dart | 3 +- lib/app/data/models/campaign.dart | 9 +- lib/app/data/models/character.dart | 71 +- lib/app/data/models/character_class.dart | 31 +- lib/app/data/models/character_settings.dart | 40 +- lib/app/data/models/character_stats.dart | 13 +- lib/app/data/models/gear_choice.dart | 25 +- lib/app/data/models/gear_selection.dart | 9 +- lib/app/data/models/item.dart | 19 +- lib/app/data/models/item_settings.dart | 6 +- lib/app/data/models/meta.dart | 65 +- lib/app/data/models/monster.dart | 6 +- lib/app/data/models/move.dart | 12 +- lib/app/data/models/move_templates.dart | 21 +- lib/app/data/models/note.dart | 9 +- lib/app/data/models/race.dart | 9 +- lib/app/data/models/roll_button.dart | 33 +- lib/app/data/models/session_marks.dart | 20 +- lib/app/data/models/spell.dart | 21 +- lib/app/data/models/user.dart | 14 +- lib/app/data/models/user_settings.dart | 17 +- lib/app/data/services/auth_service.dart | 6 +- lib/app/data/services/character_service.dart | 41 +- lib/app/data/services/intl_service.dart | 32 + lib/app/data/services/library_service.dart | 3 +- lib/app/data/services/repository_service.dart | 45 +- lib/app/data/services/services.dart | 2 + lib/app/data/services/user_service.dart | 20 +- lib/app/model_utils/character_utils.dart | 100 +- lib/app/model_utils/model_pages.dart | 16 +- lib/app/model_utils/model_search.dart | 6 +- lib/app/model_utils/tag_utils.dart | 6 +- .../ability_score_form_controller.dart | 35 +- .../views/ability_score_form_view.dart | 38 +- .../ability_scores_form_controller.dart | 27 +- .../views/ability_scores_form_view.dart | 46 +- lib/app/modules/About/views/about_view.dart | 48 +- .../controllers/account_controller.dart | 9 +- .../modules/Account/views/account_view.dart | 103 +- .../views/basic_info_form_view.dart | 73 +- .../controllers/bio_form_controller.dart | 7 +- .../modules/BioForm/views/bio_form_view.dart | 27 +- .../bonds_flags_form_controller.dart | 24 +- .../views/bonds_flags_form_view.dart | 17 +- .../campaigns_list_controller.dart | 3 +- .../views/campaigns_list_view.dart | 9 +- .../views/character_list_view.dart | 40 +- .../class_alignments_controller.dart | 9 +- .../views/class_alignments_view.dart | 43 +- .../select_moves_spells_controller.dart | 15 +- .../views/select_moves_spells_view.dart | 47 +- .../create_character_controller.dart | 17 +- .../views/create_character_view.dart | 150 +- lib/app/modules/Home/views/home_app_bar.dart | 8 +- .../views/home_character_actions_view.dart | 66 +- .../views/home_character_journal_view.dart | 46 +- .../Home/views/home_character_view.dart | 27 +- lib/app/modules/Home/views/home_fab.dart | 4 +- .../modules/Home/views/home_loader_view.dart | 25 +- lib/app/modules/Home/views/home_nav_bar.dart | 22 +- lib/app/modules/Home/views/home_view.dart | 35 +- .../home_character_actions_filters.dart | 12 +- .../home_character_actions_summary.dart | 21 +- .../home_character_dynamic_cards.dart | 661 +-- .../local_widgets/home_character_extras.dart | 54 +- .../horizontal_list_card_view.dart | 4 +- .../controllers/export_controller.dart | 29 +- .../controllers/import_controller.dart | 92 +- .../controllers/import_export_controller.dart | 3 +- .../local_widgets/import_progress_dialog.dart | 52 +- .../ImportExport/local_widgets/list_card.dart | 20 +- .../ImportExport/platforms/native_export.dart | 20 +- .../ImportExport/platforms/web_export.dart | 7 +- .../views/import_export_view.dart | 20 +- .../ImportExport/views/import_view.dart | 11 +- .../controllers/library_list_controller.dart | 52 +- .../character_classes_library_list_view.dart | 12 +- .../LibraryList/views/entity_filters.dart | 36 +- .../filters/character_class_filters.dart | 4 +- .../views/filters/item_filters.dart | 4 +- .../views/filters/move_filters.dart | 45 +- .../views/filters/note_filters.dart | 4 +- .../views/filters/race_filters.dart | 34 +- .../views/filters/spell_filters.dart | 33 +- .../views/items_library_list_view.dart | 6 +- .../LibraryList/views/library_card_list.dart | 24 +- .../views/library_collection_view.dart | 28 +- .../LibraryList/views/library_list_view.dart | 82 +- .../views/moves_library_list_view.dart | 16 +- .../views/notes_library_list_view.dart | 6 +- .../views/races_library_list_view.dart | 22 +- .../views/spells_library_list_view.dart | 9 +- .../Login/controllers/login_controller.dart | 7 +- .../views/login_progress_dialog_view.dart | 14 +- lib/app/modules/Login/views/login_view.dart | 80 +- .../Migration/views/migration_view.dart | 21 +- .../select_character_theme_controller.dart | 9 +- .../views/select_character_theme_view.dart | 29 +- .../controllers/send_feedback_controller.dart | 6 +- .../views/send_feedback_view.dart | 28 +- .../modules/Settings/views/settings_view.dart | 29 +- .../Settings/views/theme_selector.dart | 12 +- .../starting_gear_form_controller.dart | 9 +- .../views/starting_gear_form_view.dart | 19 +- .../universal_search_controller.dart | 75 +- .../views/universal_search_view.dart | 26 +- lib/app/routes/custom_transitions.dart | 13 +- lib/app/themes/button_themes.dart | 20 +- lib/app/themes/theme_utils.dart | 76 +- lib/app/themes/themes.dart | 12 +- .../advanced_floating_action_button.dart | 7 +- .../atoms/avatar_circular_progress.dart | 3 +- .../widgets/atoms/background_icon_button.dart | 4 +- .../widgets/atoms/buffer_progress_bar.dart | 6 +- lib/app/widgets/atoms/character_avatar.dart | 44 +- lib/app/widgets/atoms/confirm_exit_view.dart | 14 +- .../widgets/atoms/custom_expansion_tile.dart | 43 +- lib/app/widgets/atoms/debug_menu.dart | 3 +- lib/app/widgets/atoms/hp_bar.dart | 14 +- lib/app/widgets/atoms/hyperlink.dart | 6 +- .../widgets/atoms/labeled_icon_button.dart | 5 +- lib/app/widgets/atoms/lifecycle_builder.dart | 3 +- lib/app/widgets/atoms/number_text_field.dart | 27 +- lib/app/widgets/atoms/password_field.dart | 10 +- lib/app/widgets/atoms/rich_text_field.dart | 112 +- lib/app/widgets/atoms/round_icon_button.dart | 7 +- lib/app/widgets/atoms/round_roll_button.dart | 22 +- lib/app/widgets/atoms/search_field.dart | 11 +- lib/app/widgets/atoms/select_box.dart | 3 +- .../atoms/theme_brightness_switch.dart | 18 +- lib/app/widgets/atoms/xp_bar.dart | 11 +- .../widgets/cards/character_class_card.dart | 12 +- .../widgets/cards/dynamic_action_card.dart | 25 +- .../cards/dynamic_action_card_mini.dart | 23 +- lib/app/widgets/cards/item_card.dart | 3 +- lib/app/widgets/cards/item_card_mini.dart | 3 +- lib/app/widgets/cards/move_card.dart | 7 +- lib/app/widgets/cards/move_card_mini.dart | 3 +- lib/app/widgets/cards/note_card.dart | 3 +- lib/app/widgets/cards/note_card_mini.dart | 3 +- lib/app/widgets/cards/race_card.dart | 3 +- lib/app/widgets/cards/race_card_mini.dart | 3 +- lib/app/widgets/cards/spell_card.dart | 3 +- lib/app/widgets/cards/spell_card_mini.dart | 3 +- lib/app/widgets/chips/ability_score_chip.dart | 18 +- lib/app/widgets/chips/advanced_chip.dart | 6 +- lib/app/widgets/chips/item_amount_chip.dart | 10 +- lib/app/widgets/chips/item_damage_chip.dart | 3 +- lib/app/widgets/chips/move_category_chip.dart | 12 +- lib/app/widgets/chips/primary_chip.dart | 3 +- lib/app/widgets/chips/spell_level_chip.dart | 9 +- lib/app/widgets/dialogs/add_dice_dialog.dart | 19 +- lib/app/widgets/dialogs/add_tag_dialog.dart | 27 +- lib/app/widgets/dialogs/armor_dialog.dart | 18 +- .../widgets/dialogs/character_bio_dialog.dart | 27 +- .../dialogs/character_bonds_flags_dialog.dart | 18 +- lib/app/widgets/dialogs/coins_dialog.dart | 14 +- .../confirm_delete_account_dialog.dart | 24 +- .../dialogs/confirm_delete_dialog.dart | 17 +- .../confirm_unlink_provider_dialog.dart | 19 +- .../dialogs/custom_roll_buttons_dialog.dart | 70 +- .../widgets/dialogs/damage_dice_dialog.dart | 16 +- .../widgets/dialogs/debilities_dialog.dart | 24 +- lib/app/widgets/dialogs/hp_dialog.dart | 32 +- lib/app/widgets/dialogs/load_dialog.dart | 12 +- lib/app/widgets/dialogs/view_tag_dialog.dart | 28 +- lib/app/widgets/dialogs/xp_dialog.dart | 94 +- .../widgets/forms/character_class_form.dart | 20 +- lib/app/widgets/forms/dice_form.dart | 50 +- lib/app/widgets/forms/entity_share_form.dart | 11 +- lib/app/widgets/forms/item_form.dart | 13 +- .../widgets/forms/library_entity_form.dart | 27 +- lib/app/widgets/forms/move_form.dart | 48 +- lib/app/widgets/forms/note_form.dart | 20 +- lib/app/widgets/forms/race_form.dart | 46 +- lib/app/widgets/forms/spell_form.dart | 52 +- lib/app/widgets/menus/entity_edit_menu.dart | 18 +- lib/app/widgets/menus/group_sort_menu.dart | 10 +- .../widgets/molecules/character_subtitle.dart | 29 +- .../widgets/molecules/chip_list_input.dart | 40 +- .../widgets/molecules/dialog_controls.dart | 20 +- .../widgets/molecules/dice_list_input.dart | 19 +- .../molecules/special_dice_list_input.dart | 15 +- lib/app/widgets/molecules/tag_list_input.dart | 13 +- .../widgets/molecules/user_menu_popover.dart | 63 +- .../molecules/value_change_slider.dart | 10 +- lib/app/widgets/views/roll_dice_view.dart | 68 +- lib/core/dw_icons.dart | 120 +- lib/core/http/api.dart | 6 +- lib/core/http/api_requests/search.dart | 62 +- lib/core/http/requests.dart | 9 +- lib/core/localized_repository.dart | 6 +- lib/core/storage_handler/cache_handler.dart | 3 +- .../storage_handler/firestore_delegate.dart | 35 +- .../storage_handler/local_store_delegate.dart | 22 +- .../storage_handler/storage_handler_core.dart | 3 +- lib/core/task_runner/args.dart | 10 +- lib/core/task_runner/deploy.dart | 7 +- lib/core/task_runner/task.dart | 21 +- lib/core/task_runner/task_utils.dart | 16 +- lib/core/task_runner/tasks/android_tasks.dart | 6 +- lib/core/utils/builder_utils.dart | 16 +- lib/core/utils/dialog_utils.dart | 12 +- lib/core/utils/email_address_validator.dart | 4 +- lib/core/utils/filter_sort.dart | 3 +- lib/core/utils/list_utils.dart | 23 +- lib/core/utils/map_utils.dart | 3 +- lib/core/utils/markdown_highlight.dart | 62 +- lib/core/utils/markdown_styles.dart | 12 +- lib/core/utils/math_utils.dart | 3 +- lib/core/utils/password_validator.dart | 6 +- lib/core/utils/streams.dart | 8 +- lib/core/utils/string_utils.dart | 24 +- lib/core/utils/string_validator.dart | 18 +- lib/core/utils/upload_utils.dart | 20 +- lib/generated/intl/intl_messages.arb | 3696 ------------- lib/generated/intl/messages_all.dart | 64 - lib/generated/intl/messages_en.dart | 696 --- lib/generated/l10n.dart | 4811 ----------------- lib/i18n.dart | 4 + lib/i18n/messages.i18n.dart | 3020 +++++++++++ lib/i18n/messages.i18n.yaml | 700 +++ lib/main.dart | 11 +- pubspec.lock | 17 + pubspec.yaml | 9 +- script_runner.yaml | 4 + scripts/get_version.dart | 9 +- test/utils/string_utils_test.dart | 9 +- 231 files changed, 7420 insertions(+), 11564 deletions(-) create mode 100644 lib/app/data/services/intl_service.dart delete mode 100644 lib/generated/intl/intl_messages.arb delete mode 100644 lib/generated/intl/messages_all.dart delete mode 100644 lib/generated/intl/messages_en.dart delete mode 100644 lib/generated/l10n.dart create mode 100644 lib/i18n.dart create mode 100644 lib/i18n/messages.i18n.dart create mode 100644 lib/i18n/messages.i18n.yaml diff --git a/README.md b/README.md index 275a91b4..48285a5e 100644 --- a/README.md +++ b/README.md @@ -82,13 +82,29 @@ don't hesitate to open an appropriate issue and I will do my best to reply promp } ``` - Sentry DSN can remain empty to skip error reporting + Sentry DSN can remain empty to skip error reporting. 1. To run build scripts, install [script_runner](https://pub.dev/packages/script_runner) and use `scr -h` to see all available commands As mentioned above, Firebase secret keys must be your own, and so are the databases and services -related to them. This project uses Firebase auth, Firestore, and Crashlytics. +related to them. This project uses Firebase auth and Cloud Firestore. + +### Translations + +This app is currently only available in English. However, it's possible to contribute translations +if you wish to help localize the app to your language. The app should be fully-localizable easily by +just updating the translation files. + +- The current main translations file is at `lib/i18n/messages.i18n.dart` +- To add a new localization file, copy this file to `lib/i18n/messages_.i18n.dart` (for + example, for Hebrew you would use `messages_he.i18n.dart`) +- For help using the translation syntax, see the [i18n docs](https://github.com/MohiuddinM/i18n) +- To translate the playbook data (classes, items, moves, spells, etc) we must localize a separate + package containing all the Dungeon World base data. This package is + [available here](https://github.com/DungeonPaper/dungeon_world_data), see the localization docs + there for more help. +- The app and data may be translated separately and do not depend on each other. ### Help by bug reporting or requesting features diff --git a/lib/app/data/models/ability_scores.dart b/lib/app/data/models/ability_scores.dart index 6e2441d4..f4ac00e0 100644 --- a/lib/app/data/models/ability_scores.dart +++ b/lib/app/data/models/ability_scores.dart @@ -2,7 +2,7 @@ import 'dart:convert'; import 'package:dungeon_paper/app/data/models/meta.dart'; import 'package:dungeon_paper/core/utils/icon_utils.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import '../../../core/dw_icons.dart'; @@ -12,7 +12,8 @@ class AbilityScores { required Iterable stats, }) : stats = stats.toList(); - factory AbilityScores.dungeonWorldAll(int value) => AbilityScores.dungeonWorld( + factory AbilityScores.dungeonWorldAll(int value) => + AbilityScores.dungeonWorld( dex: value, str: value, wis: value, @@ -32,57 +33,58 @@ class AbilityScores { AbilityScores(stats: [ AbilityScore( key: 'STR', - name: S.current.abilityScoreStrName, - description: S.current.abilityScoreStrDescription, - debilityName: S.current.abilityScoreStrDebilityName, - debilityDescription: S.current.abilityScoreStrDebilityDescription, + name: tr.abilityScores.stats.str.name, + description: tr.abilityScores.stats.str.description, + debilityName: tr.abilityScores.stats.str.debility.name, + debilityDescription: tr.abilityScores.stats.str.debility.description, value: str, ), AbilityScore( key: 'DEX', - name: S.current.abilityScoreDexName, - description: S.current.abilityScoreDexDescription, - debilityName: S.current.abilityScoreDexDebilityName, - debilityDescription: S.current.abilityScoreDexDebilityDescription, + name: tr.abilityScores.stats.dex.name, + description: tr.abilityScores.stats.dex.description, + debilityName: tr.abilityScores.stats.dex.debility.name, + debilityDescription: tr.abilityScores.stats.dex.debility.description, value: dex, ), AbilityScore( key: 'CON', - name: S.current.abilityScoreConName, - description: S.current.abilityScoreConDescription, - debilityName: S.current.abilityScoreConDebilityName, - debilityDescription: S.current.abilityScoreConDebilityDescription, + name: tr.abilityScores.stats.con.name, + description: tr.abilityScores.stats.con.description, + debilityName: tr.abilityScores.stats.con.debility.name, + debilityDescription: tr.abilityScores.stats.con.debility.description, value: con, ), AbilityScore( key: 'INT', - name: S.current.abilityScoreIntName, - description: S.current.abilityScoreIntDescription, - debilityName: S.current.abilityScoreIntDebilityName, - debilityDescription: S.current.abilityScoreIntDebilityDescription, + name: tr.abilityScores.stats.intl.name, + description: tr.abilityScores.stats.intl.description, + debilityName: tr.abilityScores.stats.intl.debility.name, + debilityDescription: tr.abilityScores.stats.intl.debility.description, value: intl, ), AbilityScore( key: 'WIS', - name: S.current.abilityScoreWisName, - description: S.current.abilityScoreWisDescription, - debilityName: S.current.abilityScoreWisDebilityName, - debilityDescription: S.current.abilityScoreWisDebilityDescription, + name: tr.abilityScores.stats.wis.name, + description: tr.abilityScores.stats.wis.description, + debilityName: tr.abilityScores.stats.wis.debility.name, + debilityDescription: tr.abilityScores.stats.wis.debility.description, value: wis, ), AbilityScore( key: 'CHA', - name: S.current.abilityScoreChaName, - description: S.current.abilityScoreChaDescription, - debilityName: S.current.abilityScoreChaDebilityName, - debilityDescription: S.current.abilityScoreChaDebilityDescription, + name: tr.abilityScores.stats.cha.name, + description: tr.abilityScores.stats.cha.description, + debilityName: tr.abilityScores.stats.cha.debility.name, + debilityDescription: tr.abilityScores.stats.cha.debility.description, value: cha, ), ]); final List stats; - Map get statsMap => Map.fromIterable(stats, key: (s) => s.key); + Map get statsMap => + Map.fromIterable(stats, key: (s) => s.key); AbilityScores copyWith({ Iterable? stats, @@ -91,15 +93,22 @@ class AbilityScores { AbilityScores copyWithStatValues(Map map) => copyWith( stats: stats.map( - (stat) => map.containsKey(stat.key) ? stat.copyWith(value: map[stat.key]) : stat, + (stat) => map.containsKey(stat.key) + ? stat.copyWith(value: map[stat.key]) + : stat, ), ); - AbilityScores copyWithDebilities(Iterable keys, {required bool isDebilitated}) => copyWith( - stats: stats.map((e) => keys.contains(e.key) ? e.copyWith(isDebilitated: isDebilitated) : e), + AbilityScores copyWithDebilities(Iterable keys, + {required bool isDebilitated}) => + copyWith( + stats: stats.map((e) => keys.contains(e.key) + ? e.copyWith(isDebilitated: isDebilitated) + : e), ); - factory AbilityScores.fromRawJson(String str) => AbilityScores.fromJson(json.decode(str)); + factory AbilityScores.fromRawJson(String str) => + AbilityScores.fromJson(json.decode(str)); String toRawJson() => json.encode(toJson()); @@ -108,12 +117,12 @@ class AbilityScores { if (statKey == 'BOND') { return AbilityScore( key: 'BOND', - name: S.current.abilityScoreBondName, + name: tr.abilityScores.stats.bond.name, value: 10, isDebilitated: false, - description: S.current.abilityScoreBondDescription, - debilityName: S.current.abilityScoreBondDebilityName, - debilityDescription: S.current.abilityScoreBondDebilityDescription, + description: tr.abilityScores.stats.bond.description, + debilityName: tr.abilityScores.stats.bond.debility.name, + debilityDescription: tr.abilityScores.stats.bond.debility.description, ); } if (!statsMap.containsKey(statKey)) { @@ -147,7 +156,8 @@ class AbilityScores { int get loadBaseValue => str?.modifier ?? 0; factory AbilityScores.fromJson(Map json) => AbilityScores( - stats: List.from(json['stats'].map((x) => AbilityScore.fromJson(x))), + stats: List.from( + json['stats'].map((x) => AbilityScore.fromJson(x))), ); Map toJson() => { @@ -156,12 +166,16 @@ class AbilityScores { @override bool operator ==(Object? other) => - identical(this, other) || other is AbilityScores && runtimeType == other.runtimeType && stats == other.stats; + identical(this, other) || + other is AbilityScores && + runtimeType == other.runtimeType && + stats == other.stats; @override int get hashCode => Object.hashAll(stats); - String get debugProperties => stats.map((s) => '${s.key}: ${s.value}').join(', '); + String get debugProperties => + stats.map((s) => '${s.key}: ${s.value}').join(', '); @override String toString() => 'AbilityScores($debugProperties)'; @@ -244,12 +258,14 @@ class AbilityScore with WithIcon, WithKey { icon: icon ?? customIcon, ); - int get modifier => isDebilitated ? modifierForValue(value) - 1 : modifierForValue(value); + int get modifier => + isDebilitated ? modifierForValue(value) - 1 : modifierForValue(value); @override IconData get icon => customIcon ?? iconFor(key); - static IconData iconFor(String key) => _icons[key.toLowerCase()] ?? _icons['_other']!; + static IconData iconFor(String key) => + _icons[key.toLowerCase()] ?? _icons['_other']!; static int modifierForValue(int value) { var modifiers = {1: -3, 4: -2, 6: -1, 9: 0, 13: 1, 16: 2, 18: 3}; @@ -291,7 +307,15 @@ class AbilityScore with WithIcon, WithKey { debilityDescription == other.debilityDescription; @override - int get hashCode => Object.hashAll([key, name, description, value, isDebilitated, debilityName, debilityDescription]); + int get hashCode => Object.hashAll([ + key, + name, + description, + value, + isDebilitated, + debilityName, + debilityDescription + ]); String get debugProperties => 'key: $key, value: $value, name: $name, description: $description, isDebilitated: $isDebilitated, debilityName: $debilityName, debilityDescription: $debilityDescription'; diff --git a/lib/app/data/models/alignment.dart b/lib/app/data/models/alignment.dart index b52a455e..8a01ef18 100644 --- a/lib/app/data/models/alignment.dart +++ b/lib/app/data/models/alignment.dart @@ -17,16 +17,27 @@ class AlignmentValue extends dw.Alignment with WithIcon implements WithMeta { Meta get meta => _meta; final Meta _meta; - static final allKeys = ['good', 'lawful', 'neutral', 'chaotic', 'evil']; + static final allKeys = [ + 'good', + 'lawful', + 'neutral', + 'chaotic', + 'evil' + ]; - factory AlignmentValue.fromRawJson(String str) => AlignmentValue.fromJson(json.decode(str)); + factory AlignmentValue.fromRawJson(String str) => + AlignmentValue.fromJson(json.decode(str)); factory AlignmentValue.fromDwAlignmentValue(dw.Alignment original) => - AlignmentValue(meta: Meta.empty(createdBy: '__repo__'), type: original.type, description: original.description); + AlignmentValue( + meta: Meta.empty(createdBy: '__repo__'), + type: original.type, + description: original.description); factory AlignmentValue.fromJson(Map json) => AlignmentValue( meta: Meta.tryParse(json['_meta']), - type: dw.AlignmentType.values.firstWhere((element) => element.name == json['type']), + type: dw.AlignmentType.values + .firstWhere((element) => element.name == json['type']), description: json['description'], ); @@ -149,9 +160,11 @@ class AlignmentValues extends dw.AlignmentValues { chaotic: '', ); - factory AlignmentValues.fromRawJson(String str) => AlignmentValues.fromJson(json.decode(str)); + factory AlignmentValues.fromRawJson(String str) => + AlignmentValues.fromJson(json.decode(str)); - factory AlignmentValues.fromJson(Map json) => AlignmentValues( + factory AlignmentValues.fromJson(Map json) => + AlignmentValues( meta: Meta.tryParse(json['_meta']), good: json['good'], evil: json['evil'], @@ -177,7 +190,8 @@ class AlignmentValues extends dw.AlignmentValues { chaotic: chaotic ?? this.chaotic, ); - factory AlignmentValues.fromDwAlignmentValues(dw.AlignmentValues original) => AlignmentValues( + factory AlignmentValues.fromDwAlignmentValues(dw.AlignmentValues original) => + AlignmentValues( meta: Meta.empty(createdBy: '__repo__'), good: original.good, evil: original.evil, @@ -205,7 +219,8 @@ class AlignmentValues extends dw.AlignmentValues { chaotic == other.chaotic; @override - int get hashCode => Object.hashAll([meta, good, evil, lawful, neutral, chaotic]); + int get hashCode => + Object.hashAll([meta, good, evil, lawful, neutral, chaotic]); @override String get debugProperties => diff --git a/lib/app/data/models/bio.dart b/lib/app/data/models/bio.dart index abbb682b..1a244784 100644 --- a/lib/app/data/models/bio.dart +++ b/lib/app/data/models/bio.dart @@ -52,7 +52,8 @@ class Bio { 'alignment': alignment.toJson(), }; - String get debugProperties => 'looks: $looks, description: $description, alignment: $alignment'; + String get debugProperties => + 'looks: $looks, description: $description, alignment: $alignment'; @override String toString() => 'Bio($debugProperties)'; diff --git a/lib/app/data/models/campaign.dart b/lib/app/data/models/campaign.dart index c6e5f93b..2710d2f1 100644 --- a/lib/app/data/models/campaign.dart +++ b/lib/app/data/models/campaign.dart @@ -41,9 +41,12 @@ class Campaign with WithIcon implements WithMeta { key: json['key'], name: json['name'], description: json['description'], - owners: List.from(json['owners'].map((x) => dw.EntityReference.fromJson(x))), - moderators: List.from(json['moderators'].map((x) => dw.EntityReference.fromJson(x))), - participants: List.from(json['participants'].map((x) => dw.EntityReference.fromJson(x))), + owners: List.from( + json['owners'].map((x) => dw.EntityReference.fromJson(x))), + moderators: List.from( + json['moderators'].map((x) => dw.EntityReference.fromJson(x))), + participants: List.from( + json['participants'].map((x) => dw.EntityReference.fromJson(x))), ); @override diff --git a/lib/app/data/models/character.dart b/lib/app/data/models/character.dart index 0ce4760b..98ab711a 100644 --- a/lib/app/data/models/character.dart +++ b/lib/app/data/models/character.dart @@ -11,21 +11,21 @@ import 'package:dungeon_paper/core/utils/icon_utils.dart'; import 'package:dungeon_paper/core/utils/list_utils.dart'; import 'package:dungeon_paper/core/utils/math_utils.dart'; import 'package:dungeon_paper/core/utils/uuid.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; import 'package:flutter/material.dart'; +import 'ability_scores.dart'; import 'bio.dart'; -import 'session_marks.dart'; import 'character_class.dart'; import 'character_settings.dart'; -import 'item.dart'; import 'character_stats.dart'; +import 'item.dart'; import 'meta.dart'; import 'move.dart'; import 'note.dart'; import 'race.dart'; -import 'ability_scores.dart'; +import 'session_marks.dart'; import 'spell.dart'; class Character with WithIcon implements WithMeta { @@ -85,34 +85,38 @@ class Character with WithIcon implements WithMeta { int get defaultArmor => items.fold(0, (armor, item) => armor + item.armor); int get damageModifier => items.fold(0, (mod, item) => mod + item.damage); - int getLightTheme(User user) => settings.lightTheme ?? user.settings.defaultLightTheme; - int getDarkTheme(User user) => settings.darkTheme ?? user.settings.defaultDarkTheme; + int getLightTheme(User user) => + settings.lightTheme ?? user.settings.defaultLightTheme; + int getDarkTheme(User user) => + settings.darkTheme ?? user.settings.defaultDarkTheme; int getCurrentTheme(User user) => getThemeForUserBrightness(user); int getThemeForUserBrightness(User user) => - user.brightness == Brightness.light ? getLightTheme(user) : getDarkTheme(user); + user.brightness == Brightness.light + ? getLightTheme(user) + : getDarkTheme(user); static RollButton get basicActionRollButton => RollButton( - label: S.current.rollBasicActionButton, + label: tr.customRolls.presets.basicAction, dice: [dw.Dice.d6 * 2], specialDice: [], ); static RollButton get hackAndSlashRollButton => RollButton( - label: S.current.rollAttackDamageButton, + label: tr.customRolls.presets.hackAndSlash, dice: [dw.Dice.fromJson('2d6+STR')], specialDice: [SpecialDice.damage], ); static RollButton get volleyRollButton => RollButton( - label: S.current.rollVolleyButton, + label: tr.customRolls.presets.volley, dice: [dw.Dice.fromJson('2d6+DEX')], specialDice: [SpecialDice.damage], ); static RollButton get discernRealitiesRollButton => RollButton( - label: S.current.rollDiscernRealitiesButton, + label: tr.customRolls.presets.discernRealities, dice: [dw.Dice.fromJson('2d6+WIS')], specialDice: [], ); @@ -132,18 +136,22 @@ class Character with WithIcon implements WithMeta { rawRollButtons[1] ?? hackAndSlashRollButton, ]; - Set get noteCategories => - settings.noteCategories.getSorted(notes.map((note) => note.localizedCategory).toSet()); + Set get noteCategories => settings.noteCategories + .getSorted(notes.map((note) => note.localizedCategory).toSet()); - Set get actionCategories => settings.actionCategories.getSorted(allActionCategories); + Set get actionCategories => + settings.actionCategories.getSorted(allActionCategories); dw.Dice get damageDice => stats.damageDice ?? defaultDamageDice; - dw.Dice get defaultDamageDice => characterClass.damageDice.copyWithModifierValue(damageModifier); + dw.Dice get defaultDamageDice => + characterClass.damageDice.copyWithModifierValue(damageModifier); - List get bonds => sessionMarks.where((e) => e.type == dw.SessionMarkType.bond).toList(); + List get bonds => + sessionMarks.where((e) => e.type == dw.SessionMarkType.bond).toList(); - List get flags => sessionMarks.where((e) => e.type == dw.SessionMarkType.flag).toList(); + List get flags => + sessionMarks.where((e) => e.type == dw.SessionMarkType.flag).toList(); List get endOfSessionMarks => sessionMarks .where((e) => e.type == dw.SessionMarkType.endOfSession) @@ -154,19 +162,19 @@ class Character with WithIcon implements WithMeta { SessionMark( key: uuid(), type: dw.SessionMarkType.endOfSession, - description: S.current.endOfSessionQ1, + description: tr.sessionMarks.endOfSession.q1, completed: false, ), SessionMark( key: uuid(), type: dw.SessionMarkType.endOfSession, - description: S.current.endOfSessionQ2, + description: tr.sessionMarks.endOfSession.q2, completed: false, ), SessionMark( key: uuid(), type: dw.SessionMarkType.endOfSession, - description: S.current.endOfSessionQ3, + description: tr.sessionMarks.endOfSession.q3, completed: false, ), ]; @@ -262,7 +270,8 @@ class Character with WithIcon implements WithMeta { ], ); - factory Character.fromRawJson(String str) => Character.fromJson(json.decode(str)); + factory Character.fromRawJson(String str) => + Character.fromJson(json.decode(str)); factory Character.empty() { final rand = Random(); @@ -298,7 +307,8 @@ class Character with WithIcon implements WithMeta { ); } - factory Character.withClass({required CharacterClass characterClass, Race? race}) { + factory Character.withClass( + {required CharacterClass characterClass, Race? race}) { return Character.empty().copyWith( characterClass: characterClass, race: race ?? @@ -318,11 +328,14 @@ class Character with WithIcon implements WithMeta { String toRawJson() => json.encode(toJson()); factory Character.fromJson(Map json) => Character( - meta: Meta.tryParse(json['_meta'], parseData: (data) => CharacterMeta.fromJson(data)), + meta: Meta.tryParse(json['_meta'], + parseData: (data) => CharacterMeta.fromJson(data)), key: json['key'], displayName: json['displayName'], avatarUrl: json['avatarURL'], - settings: json['settings'] != null ? CharacterSettings.fromJson(json['settings']) : CharacterSettings.empty(), + settings: json['settings'] != null + ? CharacterSettings.fromJson(json['settings']) + : CharacterSettings.empty(), characterClass: CharacterClass.fromJson(json['class']), moves: List.from(json['moves'].map((x) => Move.fromJson(x))), spells: List.from(json['spells'].map((x) => Spell.fromJson(x))), @@ -331,7 +344,8 @@ class Character with WithIcon implements WithMeta { notes: List.from(json['notes'].map((x) => Note.fromJson(x))), stats: CharacterStats.fromJson(json['stats']), abilityScores: AbilityScores.fromJson(json['abilityScores']), - sessionMarks: List.from(json['sessionMarks'].map((x) => SessionMark.fromJson(x))), + sessionMarks: List.from( + json['sessionMarks'].map((x) => SessionMark.fromJson(x))), bio: Bio.fromJson(json['bio']), race: Race.fromJson(json['race']), ); @@ -421,7 +435,8 @@ class CharacterMeta { CharacterMeta({this.lastUsed}); factory CharacterMeta.fromJson(Map json) => CharacterMeta( - lastUsed: json['lastUsed'] != null ? DateTime.parse(json['lastUsed']) : null, + lastUsed: + json['lastUsed'] != null ? DateTime.parse(json['lastUsed']) : null, ); CharacterMeta copyWith({ @@ -438,7 +453,9 @@ class CharacterMeta { @override bool operator ==(Object other) => identical(this, other) || - other is CharacterMeta && runtimeType == other.runtimeType && lastUsed == other.lastUsed; + other is CharacterMeta && + runtimeType == other.runtimeType && + lastUsed == other.lastUsed; @override int get hashCode => Object.hashAll([lastUsed]); diff --git a/lib/app/data/models/character_class.dart b/lib/app/data/models/character_class.dart index eb9680cf..dbf16dfa 100644 --- a/lib/app/data/models/character_class.dart +++ b/lib/app/data/models/character_class.dart @@ -10,7 +10,9 @@ import 'gear_choice.dart'; import 'meta.dart'; import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; -class CharacterClass extends dw.CharacterClass with WithIcon implements WithMeta { +class CharacterClass extends dw.CharacterClass + with WithIcon + implements WithMeta { get isApp => true; CharacterClass({ @@ -86,7 +88,8 @@ class CharacterClass extends dw.CharacterClass with WithIcon implements WithMeta isSpellcaster: isSpellcaster ?? this.isSpellcaster, ); - factory CharacterClass.fromRawJson(String str) => CharacterClass.fromJson(json.decode(str)); + factory CharacterClass.fromRawJson(String str) => + CharacterClass.fromJson(json.decode(str)); factory CharacterClass.empty() => CharacterClass( meta: Meta.empty(), @@ -103,7 +106,8 @@ class CharacterClass extends dw.CharacterClass with WithIcon implements WithMeta isSpellcaster: false, ); - factory CharacterClass.fromDwCharacterClass(dw.CharacterClass cls) => CharacterClass( + factory CharacterClass.fromDwCharacterClass(dw.CharacterClass cls) => + CharacterClass( meta: Meta.tryParse(cls.meta), name: cls.name, key: cls.key, @@ -114,7 +118,8 @@ class CharacterClass extends dw.CharacterClass with WithIcon implements WithMeta alignments: AlignmentValues.fromDwAlignmentValues(cls.alignments), bonds: cls.bonds, flags: cls.flags, - gearChoices: cls.gearChoices.map((c) => GearChoice.fromDwGearChoice(c)).toList(), + gearChoices: + cls.gearChoices.map((c) => GearChoice.fromDwGearChoice(c)).toList(), isSpellcaster: cls.isSpellcaster, ); @@ -131,7 +136,8 @@ class CharacterClass extends dw.CharacterClass with WithIcon implements WithMeta IconData get icon => genericIcon; static IconData get genericIcon => Icons.person_outline; - static int Function(CharacterClass a, CharacterClass b) sorter(CharacterClassFilters filters) => + static int Function(CharacterClass a, CharacterClass b) sorter( + CharacterClassFilters filters) => (a, b) => a.name.toLowerCase().compareTo(b.name.toLowerCase()); @override @@ -159,8 +165,19 @@ class CharacterClass extends dw.CharacterClass with WithIcon implements WithMeta isSpellcaster == other.isSpellcaster; @override - int get hashCode => - Object.hashAll([meta, name, key, description, damageDice, load, hp, alignments, bonds, flags, gearChoices]); + int get hashCode => Object.hashAll([ + meta, + name, + key, + description, + damageDice, + load, + hp, + alignments, + bonds, + flags, + gearChoices + ]); @override String get debugProperties => diff --git a/lib/app/data/models/character_settings.dart b/lib/app/data/models/character_settings.dart index cc254df3..1eb0d60a 100644 --- a/lib/app/data/models/character_settings.dart +++ b/lib/app/data/models/character_settings.dart @@ -56,11 +56,13 @@ class CharacterSettings { darkTheme: darkTheme ?? this.darkTheme, ); - factory CharacterSettings.fromRawJson(String str) => CharacterSettings.fromJson(json.decode(str)); + factory CharacterSettings.fromRawJson(String str) => + CharacterSettings.fromJson(json.decode(str)); String toRawJson() => json.encode(toJson()); - factory CharacterSettings.fromJson(Map json) => CharacterSettings( + factory CharacterSettings.fromJson(Map json) => + CharacterSettings( noteCategories: json['noteCategories'] != null ? NoteCategoryList.fromJson(json['noteCategories']) : const NoteCategoryList(sortOrder: {}), @@ -78,8 +80,8 @@ class CharacterSettings { ), 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, @@ -113,7 +115,8 @@ class CharacterSettings { 'darkTheme': darkTheme, }; - CharacterSettings copyWithThemes({int? lightTheme, int? darkTheme}) => CharacterSettings( + CharacterSettings copyWithThemes({int? lightTheme, int? darkTheme}) => + CharacterSettings( lightTheme: lightTheme, darkTheme: darkTheme, sortOrder: sortOrder, @@ -181,9 +184,11 @@ class OrderedCategoryList { 'canHide': canHide, }; - factory OrderedCategoryList.fromRawJson(String str) => OrderedCategoryList.fromJson(json.decode(str)); + factory OrderedCategoryList.fromRawJson(String str) => + OrderedCategoryList.fromJson(json.decode(str)); - factory OrderedCategoryList.fromJson(Map json) => OrderedCategoryList( + factory OrderedCategoryList.fromJson(Map json) => + OrderedCategoryList( hidden: Set.from(json['hidden']), sortOrder: Set.from(json['sortOrder']), canHide: json['canHide'], @@ -228,7 +233,8 @@ class OrderedCategoryList { canHide, ]); - String get debugProperties => 'hidden: $hidden, sortOrder: $sortOrder, canHide: $canHide'; + String get debugProperties => + 'hidden: $hidden, sortOrder: $sortOrder, canHide: $canHide'; @override String toString() => 'OrderedCategoryList($debugProperties)'; @@ -241,9 +247,11 @@ class NoteCategoryList extends OrderedCategoryList { required super.sortOrder, }) : super(canHide: false, hidden: const {}); - factory NoteCategoryList.fromRawJson(String str) => NoteCategoryList.fromJson(json.decode(str)); + factory NoteCategoryList.fromRawJson(String str) => + NoteCategoryList.fromJson(json.decode(str)); - factory NoteCategoryList.fromJson(Map json) => NoteCategoryList( + factory NoteCategoryList.fromJson(Map json) => + NoteCategoryList( sortOrder: Set.from(json['sortOrder']), ); @@ -270,10 +278,13 @@ class ActionCategoryList extends OrderedCategoryList { required super.hidden, }) : super(canHide: true); - factory ActionCategoryList.fromRawJson(String str) => ActionCategoryList.fromJson(json.decode(str)); + factory ActionCategoryList.fromRawJson(String str) => + ActionCategoryList.fromJson(json.decode(str)); - factory ActionCategoryList.fromJson(Map json) => ActionCategoryList( - sortOrder: Set.from((json['sortOrder'] ?? []).map((x) => _toType(x))), + factory ActionCategoryList.fromJson(Map json) => + ActionCategoryList( + sortOrder: + Set.from((json['sortOrder'] ?? []).map((x) => _toType(x))), hidden: Set.from((json['hidden'] ?? []).map((x) => _toType(x))), ); @@ -297,7 +308,8 @@ class ActionCategoryList extends OrderedCategoryList { } @override - Set getSorted([Set all = const {}]) => super.getSorted(all).map((el) => _toType(el.toString())).toSet(); + Set getSorted([Set all = const {}]) => + super.getSorted(all).map((el) => _toType(el.toString())).toSet(); @override String get debugProperties => 'sortOrder: $sortOrder, hidden: $hidden'; diff --git a/lib/app/data/models/character_stats.dart b/lib/app/data/models/character_stats.dart index 1ec19f10..e7400478 100644 --- a/lib/app/data/models/character_stats.dart +++ b/lib/app/data/models/character_stats.dart @@ -26,7 +26,8 @@ class CharacterStats { static int maxExpForLevel(int level) => level + 7; int get totalMaxXp => totalMaxExpForLevel(level); - static int totalMaxExpForLevel(int level) => range(1, level).fold(8, (acc, l) => acc + maxExpForLevel(l + 1)); + static int totalMaxExpForLevel(int level) => + range(1, level).fold(8, (acc, l) => acc + maxExpForLevel(l + 1)); factory CharacterStats.empty() => CharacterStats( level: 1, @@ -66,7 +67,8 @@ class CharacterStats { load: load, ); - factory CharacterStats.fromRawJson(String str) => CharacterStats.fromJson(json.decode(str)); + factory CharacterStats.fromRawJson(String str) => + CharacterStats.fromJson(json.decode(str)); String toRawJson() => json.encode(toJson()); @@ -76,7 +78,9 @@ class CharacterStats { currentHp: json['currentHP'], currentXp: json['currentXP'], armor: json['armor'], - damageDice: json['damageDice'] != null ? Dice.fromJson(json['damageDice']) : null, + damageDice: json['damageDice'] != null + ? Dice.fromJson(json['damageDice']) + : null, load: json['load'], ); @@ -134,7 +138,8 @@ class CharacterStats { load == other.load; @override - int get hashCode => Object.hashAll([level, maxHp, currentHp, currentXp, armor, damageDice, load]); + int get hashCode => Object.hashAll( + [level, maxHp, currentHp, currentXp, armor, damageDice, load]); String get debugProperties => 'level: $level, maxHp: $maxHp, currentHp: $currentHp, currentXp: $currentXp, armor: $armor, damageDice: $damageDice, load: $load'; diff --git a/lib/app/data/models/gear_choice.dart b/lib/app/data/models/gear_choice.dart index 4b80d121..0d24601e 100644 --- a/lib/app/data/models/gear_choice.dart +++ b/lib/app/data/models/gear_choice.dart @@ -38,21 +38,27 @@ class GearChoice extends dw.GearChoice { maxSelections: maxSelections ?? this.maxSelections, ); - factory GearChoice.fromRawJson(String str) => GearChoice.fromJson(json.decode(str)); + factory GearChoice.fromRawJson(String str) => + GearChoice.fromJson(json.decode(str)); factory GearChoice.fromDwGearChoice(dw.GearChoice gearChoice) => GearChoice( key: gearChoice.key, description: gearChoice.description, - selections: gearChoice.selections.map((s) => GearSelection.fromDwGearSelection(s)).toList(), + selections: gearChoice.selections + .map((s) => GearSelection.fromDwGearSelection(s)) + .toList(), preselect: gearChoice.preselect, maxSelections: gearChoice.maxSelections, ); - factory GearChoice.fromJson(Map json) => GearChoice.fromDwGearChoice(dw.GearChoice.fromJson(json)); + factory GearChoice.fromJson(Map json) => + GearChoice.fromDwGearChoice(dw.GearChoice.fromJson(json)); @override - List get preselectedGearSelections => - super.preselectedGearSelections.map((e) => GearSelection.fromDwGearSelection(e)).toList(); + List get preselectedGearSelections => super + .preselectedGearSelections + .map((e) => GearSelection.fromDwGearSelection(e)) + .toList(); @override Map toJson() => { @@ -60,17 +66,20 @@ class GearChoice extends dw.GearChoice { 'selections': List.from(selections.map((x) => x.toJson())), }; - static List selectionToItems(List selections, {bool equipped = false}) => + static List selectionToItems(List selections, + {bool equipped = false}) => selections.fold>([], (acc, sel) { return Item.unifyItems([ ...acc, ...sel.options.map( - (e) => Item.fromDwItem(e.item, amount: e.amount, equipped: equipped), + (e) => + Item.fromDwItem(e.item, amount: e.amount, equipped: equipped), ) ]); }); - static double selectionToCoins(List selections) => selections.fold(0.0, (acc, sel) => acc + sel.coins); + static double selectionToCoins(List selections) => + selections.fold(0.0, (acc, sel) => acc + sel.coins); @override bool operator ==(Object? other) => diff --git a/lib/app/data/models/gear_selection.dart b/lib/app/data/models/gear_selection.dart index a3570102..40815b90 100644 --- a/lib/app/data/models/gear_selection.dart +++ b/lib/app/data/models/gear_selection.dart @@ -33,7 +33,8 @@ class GearSelection extends dw.GearSelection { coins: coins ?? this.coins, ); - factory GearSelection.fromRawJson(String str) => GearSelection.fromJson(json.decode(str)); + factory GearSelection.fromRawJson(String str) => + GearSelection.fromJson(json.decode(str)); factory GearSelection.fromDwGearSelection(dw.GearSelection gearSelection) => GearSelection.fromJson(gearSelection.toJson()); @@ -41,7 +42,8 @@ class GearSelection extends dw.GearSelection { factory GearSelection.fromJson(Map json) => GearSelection( key: json['key'], description: json['description'] ?? '', - options: List.from((json['options'] ?? []).map((x) => GearOption.fromJson(x))), + options: List.from( + (json['options'] ?? []).map((x) => GearOption.fromJson(x))), coins: json['coins'] ?? 0, ); @@ -59,7 +61,8 @@ class GearSelection extends dw.GearSelection { int get hashCode => Object.hashAll([key, description, options, coins]); @override - String get debugProperties => 'key: $key, description: $description, options: $options, coins: $coins'; + String get debugProperties => + 'key: $key, description: $description, options: $options, coins: $coins'; @override String toString() => 'GearSelection($debugProperties)'; diff --git a/lib/app/data/models/item.dart b/lib/app/data/models/item.dart index 6efbc392..4cd7378c 100644 --- a/lib/app/data/models/item.dart +++ b/lib/app/data/models/item.dart @@ -37,12 +37,16 @@ class Item extends dw.Item with WithIcon implements WithMeta { final double amount; final bool equipped; - dw.Tag? findTag(String name) => tags.cast().firstWhereOrNull((tag) => cleanStr(tag?.name ?? '') == name); + dw.Tag? findTag(String name) => tags + .cast() + .firstWhereOrNull((tag) => cleanStr(tag?.name ?? '') == name); bool get isWorn => findTag('worn') != null; int get weight => settings.countWeight ? tagIntValue('weight') ?? 0 : 0; - int get armor => settings.countArmor && isWorn && equipped ? tagIntValue('armor') ?? 0 : 0; - int get damage => settings.countDamage && equipped ? tagIntValue('damage') ?? 0 : 0; + int get armor => + settings.countArmor && isWorn && equipped ? tagIntValue('armor') ?? 0 : 0; + int get damage => + settings.countDamage && equipped ? tagIntValue('damage') ?? 0 : 0; int? tagIntValue(String name) { final tag = findTag(name); @@ -100,7 +104,8 @@ class Item extends dw.Item with WithIcon implements WithMeta { description: item.description, tags: item.tags, equipped: equipped ?? false, - settings: settings != null ? ItemSettings.fromJson(settings) : ItemSettings(), + settings: + settings != null ? ItemSettings.fromJson(settings) : ItemSettings(), ); factory Item.fromJson(Map json) => Item.fromDwItem( @@ -140,7 +145,8 @@ class Item extends dw.Item with WithIcon implements WithMeta { final map = {}; for (final item in items) { if (map[item.key] != null) { - map[item.key] = map[item.key]!.copyWithInherited(amount: map[item.key]!.amount + 1); + map[item.key] = + map[item.key]!.copyWithInherited(amount: map[item.key]!.amount + 1); } else { map[item.key] = item; } @@ -168,7 +174,8 @@ class Item extends dw.Item with WithIcon implements WithMeta { equipped == other.equipped; @override - int get hashCode => Object.hashAll([key, name, description, tags, settings, amount, equipped]); + int get hashCode => Object.hashAll( + [key, name, description, tags, settings, amount, equipped]); @override String get debugProperties => diff --git a/lib/app/data/models/item_settings.dart b/lib/app/data/models/item_settings.dart index 520a855d..923c735a 100644 --- a/lib/app/data/models/item_settings.dart +++ b/lib/app/data/models/item_settings.dart @@ -22,7 +22,8 @@ class ItemSettings { countWeight: countWeight ?? this.countWeight, ); - factory ItemSettings.fromRawJson(String str) => ItemSettings.fromJson(json.decode(str)); + factory ItemSettings.fromRawJson(String str) => + ItemSettings.fromJson(json.decode(str)); String toRawJson() => json.encode(toJson()); @@ -50,7 +51,8 @@ class ItemSettings { @override int get hashCode => Object.hashAll([countArmor, countDamage, countWeight]); - String get debugProperties => 'countArmor: $countArmor, countDamage: $countDamage, countWeight: $countWeight'; + String get debugProperties => + 'countArmor: $countArmor, countDamage: $countDamage, countWeight: $countWeight'; @override String toString() => 'ItemSettings($debugProperties)'; diff --git a/lib/app/data/models/meta.dart b/lib/app/data/models/meta.dart index 8a50944b..d48d20d2 100644 --- a/lib/app/data/models/meta.dart +++ b/lib/app/data/models/meta.dart @@ -44,8 +44,12 @@ class Meta with RepositoryServiceMixin { final MetaSharing? sharing; final DateTime? updated; - M? getLibraryCopy() => - repo.my.listByType().entries.toList().firstWhereOrNull((e) => e.value.key == sharing?.sourceKey)?.value; + M? getLibraryCopy() => repo.my + .listByType() + .entries + .toList() + .firstWhereOrNull((e) => e.value.key == sharing?.sourceKey) + ?.value; bool get isFork => sharing != null; bool get isSource => !isFork; @@ -53,7 +57,8 @@ class Meta with RepositoryServiceMixin { bool isForkOf(WithMeta parent) => isFork && sharing!.sourceKey == parent.key; bool isOwnedBy(User user) => createdBy == user.username; bool isSourceOf(WithMeta parent) => !isForkOf(parent); - bool isOutOfSyncWith(WithMeta parent) => isForkOf(parent) && sharing!.sourceVersion != version; + bool isOutOfSyncWith(WithMeta parent) => + isForkOf(parent) && sharing!.sourceVersion != version; factory Meta.empty({ String? version, @@ -65,7 +70,8 @@ class Meta with RepositoryServiceMixin { String? language, }) => Meta._( - createdBy: createdBy ?? '', // ?? Get.find().current.displayName, + createdBy: + createdBy ?? '', // ?? Get.find().current.displayName, version: version ?? uuid(), created: created ?? DateTime.now(), updated: updated, @@ -113,8 +119,12 @@ class Meta with RepositoryServiceMixin { String toRawJson() => json.encode(toJson()); - factory Meta.fromJson(Map json, [DataType Function(dynamic json)? parseData]) => Meta._( - created: json['created'] != null ? parseDate(json['created']) : DateTime.now(), + factory Meta.fromJson(Map json, + [DataType Function(dynamic json)? parseData]) => + Meta._( + created: json['created'] != null + ? parseDate(json['created']) + : DateTime.now(), createdBy: json['createdBy'], data: json['data'] != null ? parseData != null @@ -123,15 +133,19 @@ class Meta with RepositoryServiceMixin { : null, language: json['language'], version: json['version']?.toString() ?? uuid(), - sharing: json['sharing'] != null ? MetaSharing.fromJson(json['sharing']) : null, + sharing: json['sharing'] != null + ? MetaSharing.fromJson(json['sharing']) + : null, updated: json['updated'] != null ? parseDate(json['updated']) : null, ); - factory Meta.tryParse(dynamic meta, {String? owner, DataType Function(dynamic json)? parseData}) => meta != null - ? meta is Meta - ? meta - : Meta.fromJson(meta, parseData) - : Meta.empty(createdBy: owner); + factory Meta.tryParse(dynamic meta, + {String? owner, DataType Function(dynamic json)? parseData}) => + meta != null + ? meta is Meta + ? meta + : Meta.fromJson(meta, parseData) + : Meta.empty(createdBy: owner); Map toJson([dynamic Function(DataType? data)? dumpData]) => { 'created': created.toString(), @@ -155,7 +169,8 @@ class Meta with RepositoryServiceMixin { } /// Returns an item with forked meta, or the same meta if its by the same user - static T forkMeta(T object, User user, {Meta? meta, String? version}) { + static T forkMeta(T object, User user, + {Meta? meta, String? version}) { final Meta _m = (meta ?? object.meta); // final _o = // force || _m.createdBy != user.username ? object.copyWithInherited(key: uuid()) : object; @@ -252,7 +267,17 @@ class Meta with RepositoryServiceMixin { } static final allStorageKeys = { - for (final t in [CharacterClass, Character, Item, Monster, Move, Spell, Race, Note, dw.Tag]) + for (final t in [ + CharacterClass, + Character, + Item, + Monster, + Move, + Spell, + Race, + Note, + dw.Tag + ]) t: Meta.storageKeyFor(t), }; @@ -297,7 +322,8 @@ class Meta with RepositoryServiceMixin { language == other.language; @override - int get hashCode => Object.hashAll([created, createdBy, updated, version, sharing, data, language]); + int get hashCode => Object.hashAll( + [created, createdBy, updated, version, sharing, data, language]); String get debugProperties => 'created: $created, createdBy: $createdBy, updated: $updated, version: $version, sharing: $sharing, data: $data, language: $language'; @@ -352,7 +378,8 @@ class MetaSharing { sourceVersion: sourceVersion ?? this.sourceVersion, ); - factory MetaSharing.fromRawJson(String str) => MetaSharing.fromJson(json.decode(str)); + factory MetaSharing.fromRawJson(String str) => + MetaSharing.fromJson(json.decode(str)); String toRawJson() => json.encode(toJson()); @@ -401,7 +428,8 @@ class MetaSharing { sourceVersion == other.sourceVersion; @override - int get hashCode => Object.hashAll([shared, dirty, sourceKey, sourceOwner, sourceVersion]); + int get hashCode => + Object.hashAll([shared, dirty, sourceKey, sourceOwner, sourceVersion]); String get debugProperties => 'shared: $shared, dirty: $dirty, sourceKey: $sourceKey, sourceOwner: $sourceOwner, sourceVersion: $sourceVersion'; @@ -420,7 +448,8 @@ abstract class MetaInterface { dynamic toJson(); } -mixin WithMeta implements WithKey, MetaInterface { +mixin WithMeta + implements WithKey, MetaInterface { abstract final Meta meta; String get displayName; String get storageKey; diff --git a/lib/app/data/models/monster.dart b/lib/app/data/models/monster.dart index 1b8cb7e8..aed7e489 100644 --- a/lib/app/data/models/monster.dart +++ b/lib/app/data/models/monster.dart @@ -48,7 +48,8 @@ class Monster extends dw.Monster implements WithMeta { ); factory Monster.fromRawJson(String str) => Monster.fromJson(json.decode(str)); - factory Monster.fromDwMonster(dw.Monster monster) => Monster.fromJson(monster.toJson()); + factory Monster.fromDwMonster(dw.Monster monster) => + Monster.fromJson(monster.toJson()); factory Monster.fromJson(Map json) => Monster( meta: Meta.tryParse(json['_meta']), @@ -80,7 +81,8 @@ class Monster extends dw.Monster implements WithMeta { moves == other.moves; @override - int get hashCode => Object.hashAll([meta, key, name, description, instinct, tags, moves]); + int get hashCode => + Object.hashAll([meta, key, name, description, instinct, tags, moves]); @override String get debugProperties => diff --git a/lib/app/data/models/move.dart b/lib/app/data/models/move.dart index d5d5a396..7406dc5b 100644 --- a/lib/app/data/models/move.dart +++ b/lib/app/data/models/move.dart @@ -141,7 +141,17 @@ class Move extends dw.Move with WithIcon implements WithMeta { category == other.category; @override - int get hashCode => Object.hashAll([meta, key, name, description, explanation, dice, classKeys, tags, category]); + int get hashCode => Object.hashAll([ + meta, + key, + name, + description, + explanation, + dice, + classKeys, + tags, + category + ]); @override String get debugProperties => diff --git a/lib/app/data/models/move_templates.dart b/lib/app/data/models/move_templates.dart index e7774f1f..2a10ceae 100644 --- a/lib/app/data/models/move_templates.dart +++ b/lib/app/data/models/move_templates.dart @@ -24,19 +24,22 @@ class MoveTemplateList { MoveTemplate( shortLabel: 'Multi. choice', longLabel: 'Multiple choice success & trouble', - help: 'Template with multiple options for success,\nand multiple options for trouble.', + help: + 'Template with multiple options for success,\nand multiple options for trouble.', text: _multiBoth, ), MoveTemplate( shortLabel: 'Multi. success', longLabel: 'Multiple choice success', - help: 'Template with multiple options for success,\nbut only one outcome for trouble.', + help: + 'Template with multiple options for success,\nbut only one outcome for trouble.', text: _multiSuccess, ), MoveTemplate( shortLabel: 'Multi. trouble', longLabel: 'Multiple choice trouble', - help: 'Template with multiple options for trouble,\nbut only one outcome for success.', + help: + 'Template with multiple options for trouble,\nbut only one outcome for success.', text: _multiFail, ), ]; @@ -44,21 +47,25 @@ class MoveTemplateList { static const _blank = '_____'; // or '…'? static const _bullet = '-'; - static const _singleBoth = 'When you $_blank, roll+STAT. On a 10+, you succeed $_blank. ' + static const _singleBoth = + 'When you $_blank, roll+STAT. On a 10+, you succeed $_blank. ' 'On a 7-9, you fail $_blank.'; - static const _multiSuccess = 'When you $_blank, roll+STAT. On a 10+, you succeed and choose:\n' + static const _multiSuccess = + 'When you $_blank, roll+STAT. On a 10+, you succeed and choose:\n' ' $_bullet $_blank\n' ' $_bullet $_blank\n' ' $_bullet $_blank\n' 'On a 7-9, you fail $_blank.'; - static const _multiFail = 'When you $_blank, roll+STAT. On a 10+, you succeed $_blank. On a 7-9, choose one:\n' + static const _multiFail = + 'When you $_blank, roll+STAT. On a 10+, you succeed $_blank. On a 7-9, choose one:\n' ' $_bullet $_blank\n' ' $_bullet $_blank\n' ' $_bullet $_blank\n'; - static const _multiBoth = 'When you $_blank, roll+STAT. On a 10+, you succeed and choose:\n' + static const _multiBoth = + 'When you $_blank, roll+STAT. On a 10+, you succeed and choose:\n' ' $_bullet $_blank\n' ' $_bullet $_blank\n' ' $_bullet $_blank\n' diff --git a/lib/app/data/models/note.dart b/lib/app/data/models/note.dart index dddd16d4..19ee3b65 100644 --- a/lib/app/data/models/note.dart +++ b/lib/app/data/models/note.dart @@ -1,7 +1,8 @@ import 'dart:convert'; + import 'package:dungeon_paper/core/utils/icon_utils.dart'; import 'package:dungeon_paper/core/utils/uuid.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; import 'package:flutter/material.dart'; @@ -28,7 +29,8 @@ class Note with WithIcon implements WithMeta { final List tags; final bool favorite; - String get localizedCategory => category.isEmpty ? S.current.noteNoCategory : category; + String get localizedCategory => + category.isEmpty ? tr.notes.noCategory : category; @override Note copyWith({ @@ -128,7 +130,8 @@ class Note with WithIcon implements WithMeta { favorite == other.favorite; @override - int get hashCode => Object.hashAll([meta, key, title, description, category, tags, favorite]); + int get hashCode => + Object.hashAll([meta, key, title, description, category, tags, favorite]); String get debugProperties => 'meta: $meta, key: $key, title: $title, description: $description, category: $category, tags: $tags, favorite: $favorite'; diff --git a/lib/app/data/models/race.dart b/lib/app/data/models/race.dart index 4866d067..7cdde3d5 100644 --- a/lib/app/data/models/race.dart +++ b/lib/app/data/models/race.dart @@ -63,7 +63,8 @@ class Race extends dw.Race with WithIcon implements WithMeta { factory Race.fromRawJson(String str) => Race.fromJson(json.decode(str)); - factory Race.fromDwRace(dw.Race race, {Meta? meta, bool favorite = false}) => Race( + factory Race.fromDwRace(dw.Race race, {Meta? meta, bool favorite = false}) => + Race( meta: race.meta != null ? Meta.fromJson(race.meta) : Meta.empty(), key: race.key, name: race.name, @@ -81,7 +82,8 @@ class Race extends dw.Race with WithIcon implements WithMeta { name: json['name'], description: json['description'], explanation: json['explanation'], - classKeys: List.from(json['classKeys'].map((x) => dw.EntityReference.fromJson(x))), + classKeys: List.from( + json['classKeys'].map((x) => dw.EntityReference.fromJson(x))), tags: List.from(json['tags'].map((x) => dw.Tag.fromJson(x))), favorite: json['favorite'] ?? false, dice: List.from(json['dice'].map((x) => dw.Dice.fromJson(x))), @@ -149,7 +151,8 @@ class Race extends dw.Race with WithIcon implements WithMeta { dice == other.dice; @override - int get hashCode => Object.hashAll([meta, key, name, description, explanation, classKeys, tags, dice]); + int get hashCode => Object.hashAll( + [meta, key, name, description, explanation, classKeys, tags, dice]); @override String get debugProperties => diff --git a/lib/app/data/models/roll_button.dart b/lib/app/data/models/roll_button.dart index a893b2e2..17da915d 100644 --- a/lib/app/data/models/roll_button.dart +++ b/lib/app/data/models/roll_button.dart @@ -23,9 +23,11 @@ class RollButton { factory RollButton.fromJson(Map json) => RollButton( label: json['label'], - dice: List.from((json['dice'] ?? []).map((x) => dw.Dice.fromJson(x))), + dice: List.from( + (json['dice'] ?? []).map((x) => dw.Dice.fromJson(x))), specialDice: List.from( - (json['specialDice'] ?? []).map((x) => getEnumByName(SpecialDice.values, x)), + (json['specialDice'] ?? []) + .map((x) => getEnumByName(SpecialDice.values, x)), ), ); @@ -35,17 +37,19 @@ class RollButton { 'specialDice': specialDice.map((d) => d.name).toList(), }; - List specialDiceFor(Character character, List specialDice) => specialDice - .map((d) { - switch (d) { - case SpecialDice.damage: - return character.damageDice; - default: - return null; - } - }) - .whereType() - .toList(); + List specialDiceFor( + Character character, List specialDice) => + specialDice + .map((d) { + switch (d) { + case SpecialDice.damage: + return character.damageDice; + default: + return null; + } + }) + .whereType() + .toList(); @override bool operator ==(Object other) => @@ -59,7 +63,8 @@ class RollButton { @override int get hashCode => Object.hashAll([label, dice, specialDice]); - String get debugProperties => 'label: $label, dice: $dice, specialDice: $specialDice'; + String get debugProperties => + 'label: $label, dice: $dice, specialDice: $specialDice'; @override String toString() => 'RollButton($debugProperties)'; diff --git a/lib/app/data/models/session_marks.dart b/lib/app/data/models/session_marks.dart index 67213691..d5134730 100644 --- a/lib/app/data/models/session_marks.dart +++ b/lib/app/data/models/session_marks.dart @@ -1,5 +1,6 @@ import 'dart:convert'; -import 'package:dungeon_paper/generated/l10n.dart'; + +import 'package:dungeon_paper/i18n.dart'; import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; import 'meta.dart'; @@ -30,13 +31,15 @@ class SessionMark extends dw.SessionMark implements WithKey { required super.completed, }) : super(type: dw.SessionMarkType.endOfSession); - factory SessionMark.fromRawJson(String str) => SessionMark.fromJson(json.decode(str)); + factory SessionMark.fromRawJson(String str) => + SessionMark.fromJson(json.decode(str)); factory SessionMark.fromJson(Map json) => SessionMark( key: json['key'], completed: json['completed'], description: json['description'], - type: dw.SessionMarkType.values.firstWhere((e) => e.name == json['type']), + type: + dw.SessionMarkType.values.firstWhere((e) => e.name == json['type']), ); SessionMark copyWithInherited({ @@ -57,12 +60,12 @@ class SessionMark extends dw.SessionMark implements WithKey { required List flags, }) => bonds.isNotEmpty && flags.isNotEmpty - ? S.current.characterBondsFlagsDialogTitle + ? tr.sessionMarks.title : flags.isNotEmpty - ? S.current.characterBondsFlagsDialogFlags + ? tr.sessionMarks.flags : bonds.isNotEmpty - ? S.current.characterBondsFlagsDialogBonds - : S.current.characterBondsFlagsDialogTitle; + ? tr.sessionMarks.bonds + : tr.sessionMarks.title; @override bool operator ==(Object other) => @@ -78,7 +81,8 @@ class SessionMark extends dw.SessionMark implements WithKey { int get hashCode => Object.hashAll([key, description, completed, type]); @override - String get debugProperties => 'key: $key, description: $description, completed: $completed, type: $type'; + String get debugProperties => + 'key: $key, description: $description, completed: $completed, type: $type'; @override String toString() => 'SessionMark($debugProperties)'; diff --git a/lib/app/data/models/spell.dart b/lib/app/data/models/spell.dart index cc5b2b5d..0324523f 100644 --- a/lib/app/data/models/spell.dart +++ b/lib/app/data/models/spell.dart @@ -109,8 +109,13 @@ class Spell extends dw.Spell with WithIcon implements WithMeta { IconData get icon => DwIcons.book_cover; static IconData get genericIcon => DwIcons.book_cover; static int Function(Spell a, Spell b) sorter(SpellFilters filters) => (a, b) { - final levelOrder = ['cantrip', 'rote', ...List.generate(9, (i) => '${i + 1}')]; - final level = levelOrder.indexOf(a.level).compareTo(levelOrder.indexOf(b.level)); + final levelOrder = [ + 'cantrip', + 'rote', + ...List.generate(9, (i) => '${i + 1}') + ]; + final level = + levelOrder.indexOf(a.level).compareTo(levelOrder.indexOf(b.level)); if (level != 0) { return level; } @@ -141,7 +146,17 @@ class Spell extends dw.Spell with WithIcon implements WithMeta { tags == other.tags; @override - int get hashCode => Object.hashAll([meta, key, name, description, explanation, level, classKeys, dice, tags]); + int get hashCode => Object.hashAll([ + meta, + key, + name, + description, + explanation, + level, + classKeys, + dice, + tags + ]); @override String get debugProperties => diff --git a/lib/app/data/models/user.dart b/lib/app/data/models/user.dart index 9c8958ac..f3649e11 100644 --- a/lib/app/data/models/user.dart +++ b/lib/app/data/models/user.dart @@ -50,7 +50,9 @@ class User { displayName: json['displayName'], email: json['email'], photoUrl: json['photoURL'], - settings: json['settings'] != null ? UserSettings.fromJson(json['settings']) : UserSettings(), + settings: json['settings'] != null + ? UserSettings.fromJson(json['settings']) + : UserSettings(), flags: json['flags'] ?? {}, ); @@ -77,7 +79,8 @@ class User { bool get isSu => flags['su'] == true; bool get isDm => flags['dm_tools_preview'] == true; - Brightness get brightness => settings.brightnessOverride ?? getCurrentPlatformBrightness(); + Brightness get brightness => + settings.brightnessOverride ?? getCurrentPlatformBrightness(); void applySettings() => settings.apply(); @@ -85,7 +88,9 @@ class User { AppThemes.setTheme(getTheme()); } - int getTheme() => brightness == Brightness.light ? settings.defaultLightTheme : settings.defaultDarkTheme; + int getTheme() => brightness == Brightness.light + ? settings.defaultLightTheme + : settings.defaultDarkTheme; @override bool operator ==(Object other) => @@ -100,7 +105,8 @@ class User { flags == other.flags; @override - int get hashCode => Object.hashAll([username, displayName, email, photoUrl, settings, flags]); + int get hashCode => + Object.hashAll([username, displayName, email, photoUrl, settings, flags]); String get debugProperties => 'username: $username, displayName: $displayName, email: $email, photoUrl: $photoUrl, settings: $settings'; diff --git a/lib/app/data/models/user_settings.dart b/lib/app/data/models/user_settings.dart index 8e2834ae..d48e3117 100644 --- a/lib/app/data/models/user_settings.dart +++ b/lib/app/data/models/user_settings.dart @@ -32,15 +32,17 @@ class UserSettings with CharacterServiceMixin { brightnessOverride: brightnessOverride ?? this.brightnessOverride, ); - factory UserSettings.fromRawJson(String str) => UserSettings.fromJson(json.decode(str)); + factory UserSettings.fromRawJson(String str) => + UserSettings.fromJson(json.decode(str)); factory UserSettings.fromJson(Map json) => UserSettings( keepScreenAwake: json['keepScreenAwake'], defaultLightTheme: json['defaultLightTheme'], defaultDarkTheme: json['defaultDarkTheme'], - brightnessOverride: Brightness.values.cast().firstWhereOrNull( - (element) => element!.name == json['brightnessOverride'], - ), + brightnessOverride: + Brightness.values.cast().firstWhereOrNull( + (element) => element!.name == json['brightnessOverride'], + ), ); Map toJson() => { @@ -61,7 +63,12 @@ class UserSettings with CharacterServiceMixin { brightnessOverride == other.brightnessOverride; @override - int get hashCode => Object.hashAll([keepScreenAwake, defaultLightTheme, defaultDarkTheme, brightnessOverride]); + int get hashCode => Object.hashAll([ + keepScreenAwake, + defaultLightTheme, + defaultDarkTheme, + brightnessOverride + ]); String get debugProperties => 'keepScreenAwake: $keepScreenAwake, defaultLightTheme: $defaultLightTheme, defaultDarkTheme: $defaultDarkTheme, brightnessOverride: $brightnessOverride'; diff --git a/lib/app/data/services/auth_service.dart b/lib/app/data/services/auth_service.dart index 9fa695c9..7c60fdcf 100644 --- a/lib/app/data/services/auth_service.dart +++ b/lib/app/data/services/auth_service.dart @@ -12,7 +12,8 @@ import 'package:sign_in_with_apple/sign_in_with_apple.dart'; import '../../model_utils/user_utils.dart'; -class AuthService extends GetxService with UserServiceMixin, LoadingServiceMixin, RepositoryServiceMixin { +class AuthService extends GetxService + with UserServiceMixin, LoadingServiceMixin, RepositoryServiceMixin { StreamSubscription? _sub; FirebaseAuth get auth => FirebaseAuth.instance; @@ -157,7 +158,8 @@ class AuthService extends GetxService with UserServiceMixin, LoadingServiceMixin userService.loadGuestData(); } - Future signUp({required String email, required String password}) async => + Future signUp( + {required String email, required String password}) async => auth.createUserWithEmailAndPassword(email: email, password: password); void _clearAuthListener() { diff --git a/lib/app/data/services/character_service.dart b/lib/app/data/services/character_service.dart index e5af584e..803976c2 100644 --- a/lib/app/data/services/character_service.dart +++ b/lib/app/data/services/character_service.dart @@ -12,7 +12,8 @@ import 'package:get/get.dart'; import '../models/character.dart'; import 'loading_service.dart'; -class CharacterService extends GetxService with LoadingServiceMixin, UserServiceMixin { +class CharacterService extends GetxService + with LoadingServiceMixin, UserServiceMixin { static CharacterService find() => Get.find(); final all = {}.obs; @@ -34,9 +35,13 @@ class CharacterService extends GetxService with LoadingServiceMixin, UserService } PageController get pageController => _pageController; - double get page => pageController.hasClients && pageController.positions.length == 1 ? pageController.page ?? 0 : 0; + double get page => + pageController.hasClients && pageController.positions.length == 1 + ? pageController.page ?? 0 + : 0; - Character? get maybeCurrent => _currentKey.value != null ? all[_currentKey.value] : null; + Character? get maybeCurrent => + _currentKey.value != null ? all[_currentKey.value] : null; Character get current => maybeCurrent!; List get allAsList => all.values.toList(); @@ -48,22 +53,24 @@ class CharacterService extends GetxService with LoadingServiceMixin, UserService out[char.settings.category ?? '']!.add(char); } for (final key in out.keys) { - out[key]! - .sort((a, b) => (a.settings.sortOrder ?? double.infinity).compareTo(b.settings.sortOrder ?? double.infinity)); + out[key]!.sort((a, b) => (a.settings.sortOrder ?? double.infinity) + .compareTo(b.settings.sortOrder ?? double.infinity)); } return out; } Iterable get charsByLastUsed { final copy = [...all.values]; - copy.sort(createSortByDate(order: SortOrder.desc, parse: (char) => char?.meta.data?.lastUsed)); + copy.sort(createSortByDate( + order: SortOrder.desc, parse: (char) => char?.meta.data?.lastUsed)); return copy; } Future registerCharacterListener() async { _clearCharListener(); debugPrint('registering character listener'); - _sub = StorageHandler.instance.collectionListener('Characters', charsListener); + _sub = + StorageHandler.instance.collectionListener('Characters', charsListener); } void clear() { @@ -77,13 +84,16 @@ class CharacterService extends GetxService with LoadingServiceMixin, UserService switchToCharacterTheme(current); updateCharacter( current.copyWith( - meta: current.meta.copyWith(data: (current.meta.data ?? CharacterMeta()).copyWith(lastUsed: DateTime.now())), + meta: current.meta.copyWith( + data: (current.meta.data ?? CharacterMeta()) + .copyWith(lastUsed: DateTime.now())), ), ); } } - void switchToCharacterTheme(Character character) => switchToTheme(character.getCurrentTheme(user)); + void switchToCharacterTheme(Character character) => + switchToTheme(character.getCurrentTheme(user)); void switchToTheme(int themeId) { final dynamicTheme = DynamicTheme.of(Get.context!)!; @@ -125,21 +135,26 @@ class CharacterService extends GetxService with LoadingServiceMixin, UserService } } - Future updateCharacter(Character character, {bool switchToCharacter = false}) { + Future updateCharacter(Character character, + {bool switchToCharacter = false}) { // (StorageHandler.instance.delegate as LocalStorageDelegate).storage.collection('Characters'); character = character.copyWithInherited(meta: character.meta.stampUpdate()); all[character.key] = character; - if (switchToCharacter || _currentKey.value == null || !all.containsKey(_currentKey.value)) { + if (switchToCharacter || + _currentKey.value == null || + !all.containsKey(_currentKey.value)) { setCurrent(character.key); } debugPrint('Updated char: ${character.key} (${character.displayName})'); debugPrint(character.toRawJson()); - return StorageHandler.instance.update('Characters', character.key, character.toJson()); + return StorageHandler.instance + .update('Characters', character.key, character.toJson()); } void createCharacter(Character character, {bool switchToCharacter = false}) { all[character.key] = character; - StorageHandler.instance.create('Characters', character.key, character.toJson()); + StorageHandler.instance + .create('Characters', character.key, character.toJson()); if (switchToCharacter || _currentKey.value == null) { _currentKey.value = character.key; } diff --git a/lib/app/data/services/intl_service.dart b/lib/app/data/services/intl_service.dart new file mode 100644 index 00000000..d332f4e5 --- /dev/null +++ b/lib/app/data/services/intl_service.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../i18n/messages.i18n.dart'; + +class IntlService extends GetxService { + static final Map _m = {}; + static late Locale _locale; + + static Messages get m => _m[Get.locale] ?? _loadMessages(_locale); + List get supportedLocales => _m.keys.toList(); + + @override + void onInit() { + super.onInit(); + _loadMessages(Get.deviceLocale ?? const Locale('en')); + } + + static void changeLocale(Locale locale) { + _loadMessages(locale); + } + + static Messages _loadMessages(Locale locale) { + final map = { + const Locale('en'): () => const Messages(), + }; + + _m[locale] = map[locale]?.call() ?? const Messages(); + _locale = locale; + return _m[locale]!; + } +} diff --git a/lib/app/data/services/library_service.dart b/lib/app/data/services/library_service.dart index 5a70d1d6..ceb9a56c 100644 --- a/lib/app/data/services/library_service.dart +++ b/lib/app/data/services/library_service.dart @@ -66,7 +66,8 @@ class LibraryService extends GetxService { ); } - void removeFromCharacter(Iterable items, [Character? char]) async { + void removeFromCharacter(Iterable items, + [Character? char]) async { chars.updateCharacter( CharacterUtils.removeByType(char ?? chars.current, items), ); diff --git a/lib/app/data/services/repository_service.dart b/lib/app/data/services/repository_service.dart index 0fa5bae8..c61b9fc9 100644 --- a/lib/app/data/services/repository_service.dart +++ b/lib/app/data/services/repository_service.dart @@ -100,14 +100,17 @@ abstract class RepositoryCache { SearchResponse cacheRes; try { - cacheRes = ignoreCache ? SearchResponse.empty() : await getCacheResponse(); + cacheRes = + ignoreCache ? SearchResponse.empty() : await getCacheResponse(); } catch (e) { cacheRes = SearchResponse.empty(); } - final shouldLoadFromRemote = ignoreCache ? true : await shouldUseRemote(cacheRes); + final shouldLoadFromRemote = + ignoreCache ? true : await shouldUseRemote(cacheRes); if (shouldLoadFromRemote) { - debugPrint('[$id] Cache ${ignoreCache ? 'skipped' : 'invalid'}, loading from remote'); + debugPrint( + '[$id] Cache ${ignoreCache ? 'skipped' : 'invalid'}, loading from remote'); SearchResponse resp; try { resp = await getFromRemote; @@ -170,7 +173,8 @@ abstract class RepositoryCache { void registerListeners() { clearListeners(); - debugPrint('[$id] registering listeners, delegate: $storage, listener prefix: "${listenerKey('')}"'); + debugPrint( + '[$id] registering listeners, delegate: $storage, listener prefix: "${listenerKey('')}"'); subs.addAll([ storage.collectionListener( @@ -307,14 +311,23 @@ abstract class RepositoryCache { required bool saveIntoCache, }) async { await Future.wait([ - updateList(cacheKey('CharacterClasses'), classes, resp.classes, saveIntoCache: saveIntoCache), - updateList(cacheKey('Items'), items, resp.items, saveIntoCache: saveIntoCache), - updateList(cacheKey('Monsters'), monsters, resp.monsters, saveIntoCache: saveIntoCache), - updateList(cacheKey('Moves'), moves, resp.moves, saveIntoCache: saveIntoCache), - updateList(cacheKey('Races'), races, resp.races, saveIntoCache: saveIntoCache), - updateList(cacheKey('Spells'), spells, resp.spells, saveIntoCache: saveIntoCache), - updateList(cacheKey('Tags'), notes, resp.notes, saveIntoCache: saveIntoCache), - updateList(cacheKey('Tags'), tags, resp.tags, saveIntoCache: saveIntoCache), + updateList( + cacheKey('CharacterClasses'), classes, resp.classes, + saveIntoCache: saveIntoCache), + updateList(cacheKey('Items'), items, resp.items, + saveIntoCache: saveIntoCache), + updateList(cacheKey('Monsters'), monsters, resp.monsters, + saveIntoCache: saveIntoCache), + updateList(cacheKey('Moves'), moves, resp.moves, + saveIntoCache: saveIntoCache), + updateList(cacheKey('Races'), races, resp.races, + saveIntoCache: saveIntoCache), + updateList(cacheKey('Spells'), spells, resp.spells, + saveIntoCache: saveIntoCache), + updateList(cacheKey('Tags'), notes, resp.notes, + saveIntoCache: saveIntoCache), + updateList(cacheKey('Tags'), tags, resp.tags, + saveIntoCache: saveIntoCache), ]); } @@ -370,7 +383,8 @@ abstract class RepositoryCache { list.addAll(Map.fromIterable(resp, key: (x) => x.key)); if (saveIntoCache && list.isNotEmpty) { - for (final x in list.values) await cache.create(collectionName, Meta.keyFor(x), Meta.toJsonFor(x)); + for (final x in list.values) + await cache.create(collectionName, Meta.keyFor(x), Meta.toJsonFor(x)); } } } @@ -421,7 +435,10 @@ class PersonalRepository extends RepositoryCache { 'Notes': storage.getCollection('Notes'), }; return Future.wait(futures.values).then((v) async { - final map = {for (final e in enumerate(v)) futures.keys.elementAt(e.index): e.value}; + final map = { + for (final e in enumerate(v)) + futures.keys.elementAt(e.index): e.value + }; return SearchResponse.fromJson(map); }); }, diff --git a/lib/app/data/services/services.dart b/lib/app/data/services/services.dart index b8a4c0d1..c4563072 100644 --- a/lib/app/data/services/services.dart +++ b/lib/app/data/services/services.dart @@ -2,6 +2,7 @@ import 'package:flutter/foundation.dart'; import 'package:get/get.dart'; import 'character_service.dart'; +import 'intl_service.dart'; import 'library_service.dart'; import 'loading_service.dart'; import 'repository_service.dart'; @@ -13,6 +14,7 @@ Future initServices() async { /// Here is where you put get_storage, hive, shared_pref initialization. /// or moor connection, or whatever that's async. + await Get.putAsync(() => Future.value(IntlService())); await Get.putAsync(() => Future.value(LoadingService())); await Get.putAsync(() => Future.value(RepositoryService())); await Get.putAsync(() => Future.value(LibraryService())); diff --git a/lib/app/data/services/user_service.dart b/lib/app/data/services/user_service.dart index f645cbd6..34857ac5 100644 --- a/lib/app/data/services/user_service.dart +++ b/lib/app/data/services/user_service.dart @@ -11,7 +11,7 @@ import 'package:dungeon_paper/app/routes/app_pages.dart'; import 'package:dungeon_paper/core/http/api.dart'; import 'package:dungeon_paper/core/http/api_requests/migration.dart'; import 'package:dungeon_paper/core/storage_handler/storage_handler.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:email_validator/email_validator.dart'; import 'package:firebase_auth/firebase_auth.dart' as fba; import 'package:flutter/material.dart'; @@ -22,7 +22,11 @@ import 'package:sentry_flutter/sentry_flutter.dart'; import '../../../core/utils/secrets_base.dart'; class UserService extends GetxService - with RepositoryServiceMixin, AuthServiceMixin, CharacterServiceMixin, LoadingServiceMixin { + with + RepositoryServiceMixin, + AuthServiceMixin, + CharacterServiceMixin, + LoadingServiceMixin { final _current = User.guest().obs; User get current => _current.value; @@ -46,7 +50,8 @@ class UserService extends GetxService StorageHandler.instance.currentDelegate = 'firestore'; StorageHandler.instance.setCollectionPrefix('Data/$email'); final shouldLoadRepo = current.email != user.email; - final dbUser = await StorageHandler.instance.firestoreGlobal.getDocument('Data', email!); + final dbUser = await StorageHandler.instance.firestoreGlobal + .getDocument('Data', email!); await _setUserAfterMigration(user, dbUser); _registerUserListener(); charService.registerCharacterListener(); @@ -95,7 +100,8 @@ class UserService extends GetxService Future updateUser(User user) async { final email = user.email; debugPrint('updating user data for $email: ${user.toJson()}'); - await StorageHandler.instance.firestoreGlobal.update('Data', email, user.toJson()); + await StorageHandler.instance.firestoreGlobal + .update('Data', email, user.toJson()); return user; } @@ -127,7 +133,8 @@ class UserService extends GetxService void _registerUserListener() { _clearUserListener(); debugPrint('registering user listener'); - _userDataSub = StorageHandler.instance.firestoreGlobal.documentListener('Data', current.email, _updateUser); + _userDataSub = StorageHandler.instance.firestoreGlobal + .documentListener('Data', current.email, _updateUser); } void _updateUser(DocData? data) { @@ -165,7 +172,7 @@ class UserService extends GetxService if (needsMigration) { final resp = await _migrateUser(user); if (resp == null) { - Get.rawSnackbar(title: S.current.errorUserOperationCanceled); + Get.rawSnackbar(title: tr.errors.userOperationCanceled); loadingService.loadingUser = false; loadingService.afterFirstLoad = !loadingService.loadingCharacters; return; @@ -198,4 +205,3 @@ mixin UserServiceMixin { UserService get userService => Get.find(); User get user => userService.current; } - diff --git a/lib/app/model_utils/character_utils.dart b/lib/app/model_utils/character_utils.dart index 8dcc31e5..fce210e5 100644 --- a/lib/app/model_utils/character_utils.dart +++ b/lib/app/model_utils/character_utils.dart @@ -7,58 +7,74 @@ import 'package:dungeon_paper/core/utils/list_utils.dart'; class CharacterUtils { // Moves - static Character updateMoves(Character char, Iterable moves) => char.copyWith( + static Character updateMoves(Character char, Iterable moves) => + char.copyWith( moves: updateByKey(char.moves, moves), ); - static Character addMoves(Character char, Iterable moves) => char.copyWith( + static Character addMoves(Character char, Iterable moves) => + char.copyWith( moves: addByKey(char.moves, moves), ); - static Character removeMoves(Character char, Iterable move) => char.copyWith( + static Character removeMoves(Character char, Iterable move) => + char.copyWith( moves: removeByKey(char.moves, move), ); - static Character reorderMoves(Character char, int oldIndex, int newIndex) => char.copyWith( + static Character reorderMoves(Character char, int oldIndex, int newIndex) => + char.copyWith( moves: reorder(char.moves, oldIndex, newIndex), ); // Spells - static Character updateSpells(Character char, Iterable spells) => char.copyWith( + static Character updateSpells(Character char, Iterable spells) => + char.copyWith( spells: updateByKey(char.spells, spells), ); - static Character addSpells(Character char, Iterable spells) => char.copyWith( + static Character addSpells(Character char, Iterable spells) => + char.copyWith( spells: addByKey(char.spells, spells), ); - static Character removeSpells(Character char, Iterable spell) => char.copyWith( + static Character removeSpells(Character char, Iterable spell) => + char.copyWith( spells: removeByKey(char.spells, spell), ); - static Character reorderSpells(Character char, int oldIndex, int newIndex) => char.copyWith( + static Character reorderSpells(Character char, int oldIndex, int newIndex) => + char.copyWith( spells: reorder(char.spells, oldIndex, newIndex), ); // Items - static Character updateItems(Character char, Iterable items) => char.copyWith( + static Character updateItems(Character char, Iterable items) => + char.copyWith( items: updateByKey(char.items, items), ); - static Character addItems(Character char, Iterable items) => char.copyWith( + static Character addItems(Character char, Iterable items) => + char.copyWith( items: addByKey(char.items, items), ); - static Character removeItems(Character char, Iterable item) => char.copyWith( + static Character removeItems(Character char, Iterable item) => + char.copyWith( items: removeByKey(char.items, item), ); - static Character reorderItems(Character char, int oldIndex, int newIndex) => char.copyWith( + static Character reorderItems(Character char, int oldIndex, int newIndex) => + char.copyWith( items: reorder(char.items, oldIndex, newIndex), ); // Notes - static Character updateNotes(Character char, Iterable notes) => char.copyWith( + static Character updateNotes(Character char, Iterable notes) => + char.copyWith( notes: updateByKey(char.notes, notes), ); - static Character addNotes(Character char, Iterable notes) => char.copyWith( + static Character addNotes(Character char, Iterable notes) => + char.copyWith( notes: addByKey(char.notes, notes), ); - static Character removeNotes(Character char, Iterable note) => char.copyWith( + static Character removeNotes(Character char, Iterable note) => + char.copyWith( notes: removeByKey(char.notes, note), ); - static Character reorderNotes(Character char, int oldIndex, int newIndex) => char.copyWith( + static Character reorderNotes(Character char, int oldIndex, int newIndex) => + char.copyWith( notes: reorder(char.notes, oldIndex, newIndex), ); @@ -66,43 +82,58 @@ class CharacterUtils { // COMBINED - static Character updateByType(Character char, Iterable items) => char.copyWith( + static Character updateByType(Character char, Iterable items) => + char.copyWith( moves: T == Move ? updateByKey(char.moves, items.cast()) : null, - spells: T == Spell ? updateByKey(char.spells, items.cast()) : null, + spells: + T == Spell ? updateByKey(char.spells, items.cast()) : null, items: T == Item ? updateByKey(char.items, items.cast()) : null, notes: T == Note ? updateByKey(char.notes, items.cast()) : null, ); - static Character addByType(Character char, Iterable items) => char.copyWith( + static Character addByType(Character char, Iterable items) => + char.copyWith( moves: T == Move ? addByKey(char.moves, items.cast()) : null, spells: T == Spell ? addByKey(char.spells, items.cast()) : null, items: T == Item ? addByKey(char.items, items.cast()) : null, notes: T == Note ? addByKey(char.notes, items.cast()) : null, ); - static Character upsertByType(Character char, Iterable items) => char.copyWith( + static Character upsertByType(Character char, Iterable items) => + char.copyWith( moves: T == Move ? upsertByKey(char.moves, items.cast()) : null, - spells: T == Spell ? upsertByKey(char.spells, items.cast()) : null, + spells: + T == Spell ? upsertByKey(char.spells, items.cast()) : null, items: T == Item ? upsertByKey(char.items, items.cast()) : null, notes: T == Note ? upsertByKey(char.notes, items.cast()) : null, ); - static Character removeByType(Character char, Iterable items) => char.copyWith( + static Character removeByType(Character char, Iterable items) => + char.copyWith( moves: T == Move ? removeByKey(char.moves, items.cast()) : null, - spells: T == Spell ? removeByKey(char.spells, items.cast()) : null, + spells: + T == Spell ? removeByKey(char.spells, items.cast()) : null, items: T == Item ? removeByKey(char.items, items.cast()) : null, notes: T == Note ? removeByKey(char.notes, items.cast()) : null, ); - static Character reorderByType(Character char, int oldIndex, int newIndex, {dynamic extraData}) => char.copyWith( + static Character reorderByType(Character char, int oldIndex, int newIndex, + {dynamic extraData}) => + char.copyWith( moves: T == Move ? reorder(char.moves, oldIndex, newIndex) : null, spells: T == Spell ? reorder(char.spells, oldIndex, newIndex) : null, items: T == Item ? reorder(char.items, oldIndex, newIndex) : null, - notes: T == Note ? _reorderNotes(char.notes, oldIndex, newIndex, extraData as String) : null, + notes: T == Note + ? _reorderNotes(char.notes, oldIndex, newIndex, extraData as String) + : null, ); - static List _reorderNotes(List notes, int oldIndex, int newIndex, String category) { - final sortedInCat = reorder(notes.where((note) => note.localizedCategory == category).toList(), oldIndex, newIndex); + static List _reorderNotes( + List notes, int oldIndex, int newIndex, String category) { + final sortedInCat = reorder( + notes.where((note) => note.localizedCategory == category).toList(), + oldIndex, + newIndex); final otherCats = notes.where((note) => note.localizedCategory != category); return [...sortedInCat, ...otherCats]; @@ -119,12 +150,13 @@ class CharacterUtils { static List Function(int oldIndex, int newIndex) reorderCharacters( Iterable list, ) { - return (oldIndex, newIndex) => enumerate(reorder(list.toList(), oldIndex, newIndex)) - .map( - (e) => e.value.copyWith( - settings: e.value.settings.copyWith(sortOrder: e.index), - ), - ) - .toList(); + return (oldIndex, newIndex) => + enumerate(reorder(list.toList(), oldIndex, newIndex)) + .map( + (e) => e.value.copyWith( + settings: e.value.settings.copyWith(sortOrder: e.index), + ), + ) + .toList(); } } diff --git a/lib/app/model_utils/model_pages.dart b/lib/app/model_utils/model_pages.dart index 47e3b322..cb83075f 100644 --- a/lib/app/model_utils/model_pages.dart +++ b/lib/app/model_utils/model_pages.dart @@ -68,13 +68,17 @@ class ModelPages { ), CharacterClass: () => openCharacterClassesList( character: character, - onSelected: onSelected != null ? (x) => onSelected.call(asList(x)) : null, + onSelected: onSelected != null + ? (x) => onSelected.call(asList(x)) + : null, preSelection: preSelections?.first as CharacterClass?, initialTab: initialTab, ), Race: () => openRacesList( character: character, - onSelected: onSelected != null ? (x) => onSelected.call(asList(x)) : null, + onSelected: onSelected != null + ? (x) => onSelected.call(asList(x)) + : null, preSelection: preSelections?.first as Race?, initialTab: initialTab, ), @@ -274,7 +278,10 @@ class ModelPages { arguments: CharacterClassLibraryListArguments( initialTab: initialTab, onSelected: onSelected ?? - (char != null ? (cls) => controller.updateCharacter(char.copyWith(characterClass: cls)) : null), + (char != null + ? (cls) => controller + .updateCharacter(char.copyWith(characterClass: cls)) + : null), preSelections: asList(preSelection ?? char?.characterClass), ), ); @@ -289,7 +296,8 @@ class ModelPages { arguments: CharacterClassFormArguments( entity: characterClass, onSave: onSave, - formContext: characterClass == null ? FormContext.create : FormContext.edit, + formContext: + characterClass == null ? FormContext.create : FormContext.edit, ), ); } diff --git a/lib/app/model_utils/model_search.dart b/lib/app/model_utils/model_search.dart index 006c7af1..ec631563 100644 --- a/lib/app/model_utils/model_search.dart +++ b/lib/app/model_utils/model_search.dart @@ -20,7 +20,8 @@ bool searchFor(Type t, dynamic object, String search) { case Move: return MoveFilters(classKey: null, search: search).filter(object); case Spell: - return SpellFilters(classKey: null, search: search, level: null).filter(object); + return SpellFilters(classKey: null, search: search, level: null) + .filter(object); case Note: return NoteFilters(search: search).filter(object); // case AbilityScore: @@ -41,7 +42,8 @@ double getScoreFor(Type t, dynamic object, String search) { case Move: return MoveFilters(classKey: null, search: search).getScore(object); case Spell: - return SpellFilters(classKey: null, search: search, level: null).getScore(object); + return SpellFilters(classKey: null, search: search, level: null) + .getScore(object); case Note: return NoteFilters(search: search).getScore(object); // case AbilityScore: diff --git a/lib/app/model_utils/tag_utils.dart b/lib/app/model_utils/tag_utils.dart index 81367d6f..8efae391 100644 --- a/lib/app/model_utils/tag_utils.dart +++ b/lib/app/model_utils/tag_utils.dart @@ -3,8 +3,10 @@ import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; import 'package:flutter/material.dart'; class TagUtils { - static List excludeMetaTags(Iterable tags) => - tags.where((tag) => !['language', 'source'].contains(tag.name.toLowerCase().trim())).toList(); + static List excludeMetaTags(Iterable tags) => tags + .where((tag) => + !['language', 'source'].contains(tag.name.toLowerCase().trim())) + .toList(); static Widget iconOf(dw.Tag tag) => Transform.rotate( child: const Icon(Icons.label), diff --git a/lib/app/modules/AbilityScoreForm/controllers/ability_score_form_controller.dart b/lib/app/modules/AbilityScoreForm/controllers/ability_score_form_controller.dart index d52954c6..6810c795 100644 --- a/lib/app/modules/AbilityScoreForm/controllers/ability_score_form_controller.dart +++ b/lib/app/modules/AbilityScoreForm/controllers/ability_score_form_controller.dart @@ -1,7 +1,7 @@ import 'package:dungeon_paper/app/data/models/ability_scores.dart'; import 'package:dungeon_paper/core/utils/enums.dart'; import 'package:dungeon_paper/core/utils/string_validator.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -14,13 +14,16 @@ class AbilityScoreFormController extends GetxController { late final Rx _name = TextEditingController().obs; TextEditingController get name => _name.value; - late final Rx _description = TextEditingController().obs; + late final Rx _description = + TextEditingController().obs; TextEditingController get description => _description.value; - late final Rx _debilityName = TextEditingController().obs; + late final Rx _debilityName = + TextEditingController().obs; TextEditingController get debilityName => _debilityName.value; - late final Rx _debilityDescription = TextEditingController().obs; + late final Rx _debilityDescription = + TextEditingController().obs; TextEditingController get debilityDescription => _debilityDescription.value; late final Rx _icon = Rx(null); @@ -34,16 +37,23 @@ class AbilityScoreFormController extends GetxController { void onInit() { super.onInit(); final AbilityScoreFormArguments args = Get.arguments; - formContext = args.abilityScore != null ? FormContext.edit : FormContext.create; + formContext = + args.abilityScore != null ? FormContext.edit : FormContext.create; if (args.abilityScore != null) { entity.value = args.abilityScore!; } onSave = args.onSave; - _key.value = TextEditingController(text: entity.value.key)..addListener(_update); - _name.value = TextEditingController(text: entity.value.name)..addListener(_update); - _description.value = TextEditingController(text: entity.value.description)..addListener(_update); - _debilityName.value = TextEditingController(text: entity.value.debilityName)..addListener(_update); - _debilityDescription.value = TextEditingController(text: entity.value.debilityDescription)..addListener(_update); + _key.value = TextEditingController(text: entity.value.key) + ..addListener(_update); + _name.value = TextEditingController(text: entity.value.name) + ..addListener(_update); + _description.value = TextEditingController(text: entity.value.description) + ..addListener(_update); + _debilityName.value = TextEditingController(text: entity.value.debilityName) + ..addListener(_update); + _debilityDescription.value = + TextEditingController(text: entity.value.debilityDescription) + ..addListener(_update); _icon.value = entity.value.customIcon; } @@ -73,10 +83,11 @@ class AbilityScoreFormController extends GetxController { String? keyValidator(String? value) => StringValidator( exactLength: 3, notContainsPattern: RegExp(r'[^a-z]', caseSensitive: false), - patternMessage: S.current.errorOnlyLetters, + patternMessage: tr.errors.onlyLetters, ).validator(value); - String? requiredValidator(String? value) => StringValidator(minLength: 1).validator(value); + String? requiredValidator(String? value) => + StringValidator(minLength: 1).validator(value); void _update() { _key.refresh(); diff --git a/lib/app/modules/AbilityScoreForm/views/ability_score_form_view.dart b/lib/app/modules/AbilityScoreForm/views/ability_score_form_view.dart index 4e165053..3f58ab6c 100644 --- a/lib/app/modules/AbilityScoreForm/views/ability_score_form_view.dart +++ b/lib/app/modules/AbilityScoreForm/views/ability_score_form_view.dart @@ -2,15 +2,14 @@ import 'package:dungeon_paper/app/data/models/ability_scores.dart'; import 'package:dungeon_paper/app/widgets/atoms/advanced_floating_action_button.dart'; import 'package:dungeon_paper/app/widgets/atoms/help_text.dart'; import 'package:dungeon_paper/core/utils/enums.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; - import 'package:get/get.dart'; import '../controllers/ability_score_form_controller.dart'; class AbilityScoreFormView extends GetView { - const AbilityScoreFormView({Key? key}) : super(key: key); + const AbilityScoreFormView({super.key}); @override Widget build(BuildContext context) { const separator = SizedBox(height: 16); @@ -18,15 +17,15 @@ class AbilityScoreFormView extends GetView { appBar: AppBar( title: Text( controller.formContext == FormContext.create - ? S.current.addGeneric(S.current.entity(AbilityScore)) - : S.current.editGeneric(S.current.entity(AbilityScore)), + ? tr.generic.addEntity(tr.entity(AbilityScore)) + : tr.generic.editEntity(tr.entity(AbilityScore)), ), centerTitle: true, ), floatingActionButton: Obx( () => AdvancedFloatingActionButton.extended( onPressed: controller.isValid ? controller.save : null, - label: Text(S.current.save), + label: Text(tr.generic.save), icon: const Icon(Icons.save), ), ), @@ -38,20 +37,20 @@ class AbilityScoreFormView extends GetView { TextFormField( controller: controller.key, decoration: InputDecoration( - labelText: S.current.abilityScoreFormKeyLabel, + labelText: tr.abilityScores.form.key.label, ), validator: controller.keyValidator, ), Padding( padding: const EdgeInsets.only(top: 4), - child: HelpText(text: S.current.abilityScoreFormKeyDescription), + child: HelpText(text: tr.abilityScores.form.key.description), ), separator, TextFormField( controller: controller.name, decoration: InputDecoration( - labelText: S.current.abilityScoreFormNameLabel, - hintText: S.current.abilityScoreFormNameDescription, + labelText: tr.abilityScores.form.name.label, + hintText: tr.abilityScores.form.name.description, ), validator: controller.requiredValidator, ), @@ -61,8 +60,8 @@ class AbilityScoreFormView extends GetView { minLines: 3, maxLines: 3, decoration: InputDecoration( - labelText: S.current.abilityScoreFormDescriptionLabel, - hintText: S.current.abilityScoreFormDescriptionDescription, + labelText: tr.abilityScores.form.description.label, + hintText: tr.abilityScores.form.description.description, ), validator: controller.requiredValidator, ), @@ -70,8 +69,8 @@ class AbilityScoreFormView extends GetView { TextFormField( controller: controller.debilityName, decoration: InputDecoration( - labelText: S.current.abilityScoreFormDebilityNameLabel, - hintText: S.current.abilityScoreFormDebilityNameDescription, + labelText: tr.abilityScores.form.debilityName.label, + hintText: tr.abilityScores.form.debilityName.description, ), validator: controller.requiredValidator, ), @@ -81,25 +80,26 @@ class AbilityScoreFormView extends GetView { minLines: 3, maxLines: 3, decoration: InputDecoration( - labelText: S.current.abilityScoreFormDebilityDescriptionLabel, - hintText: S.current.abilityScoreFormDebilityDescriptionDescription, + labelText: tr.abilityScores.form.debilityDescription.label, + hintText: tr.abilityScores.form.debilityDescription.description, ), validator: controller.requiredValidator, ), separator, - Text(S.current.abilityScoreFormIconLabel), + Text(tr.abilityScores.form.icon.label), separator, Obx( () => Align( alignment: Alignment.centerLeft, - child: Icon(controller.icon ?? AbilityScore.iconFor(controller.key.text)), + child: Icon(controller.icon ?? + AbilityScore.iconFor(controller.key.text)), ), ), separator, ElevatedButton( onPressed: () => controller.pickIcon(context), child: Text( - S.current.abilityScoreFormPickIconLabel, + tr.abilityScores.form.icon.button, ), ), ], diff --git a/lib/app/modules/AbilityScoresForm/controllers/ability_scores_form_controller.dart b/lib/app/modules/AbilityScoresForm/controllers/ability_scores_form_controller.dart index 70db9db0..9582b7f1 100644 --- a/lib/app/modules/AbilityScoresForm/controllers/ability_scores_form_controller.dart +++ b/lib/app/modules/AbilityScoresForm/controllers/ability_scores_form_controller.dart @@ -6,8 +6,9 @@ import 'package:get/get.dart'; class AbilityScoresFormController extends GetxController { final dirty = false.obs; - final Rx abilityScores = - AbilityScores.dungeonWorld(dex: 10, str: 10, wis: 10, con: 10, intl: 10, cha: 10).obs; + final Rx abilityScores = AbilityScores.dungeonWorld( + dex: 10, str: 10, wis: 10, con: 10, intl: 10, cha: 10) + .obs; final textControllers = {}; late final void Function(AbilityScores abilityScores) onChanged; @@ -25,7 +26,9 @@ class AbilityScoresFormController extends GetxController { } textControllers.clear(); for (final stat in abilityScores.value.stats) { - textControllers[stat.key] = TextEditingController(text: stat.value.toString())..addListener(validate); + textControllers[stat.key] = + TextEditingController(text: stat.value.toString()) + ..addListener(validate); } onChanged = args.onChanged; } @@ -39,13 +42,17 @@ class AbilityScoresFormController extends GetxController { } void updateStat(AbilityScore stat) { - abilityScores.value = abilityScores.value.copyWith(stats: updateByKey(abilityScores.value.stats, [stat])); - textControllers[stat.key] ??= TextEditingController(text: stat.value.toString())..addListener(validate); + abilityScores.value = abilityScores.value + .copyWith(stats: updateByKey(abilityScores.value.stats, [stat])); + textControllers[stat.key] ??= + TextEditingController(text: stat.value.toString()) + ..addListener(validate); textControllers[stat.key]!.text = stat.value.toString(); } void removeStat(AbilityScore stat) { - abilityScores.value = abilityScores.value.copyWith(stats: removeByKey(abilityScores.value.stats, [stat])); + abilityScores.value = abilityScores.value + .copyWith(stats: removeByKey(abilityScores.value.stats, [stat])); textControllers.remove(stat.key); } @@ -53,9 +60,11 @@ class AbilityScoresFormController extends GetxController { if (textControllers.containsKey(abilityScore.key)) { return; } - abilityScores.value = abilityScores.value.copyWith(stats: [...abilityScores.value.stats, abilityScore]); - textControllers[abilityScore.key] = TextEditingController(text: abilityScore.value.toString()) - ..addListener(validate); + abilityScores.value = abilityScores.value + .copyWith(stats: [...abilityScores.value.stats, abilityScore]); + textControllers[abilityScore.key] = + TextEditingController(text: abilityScore.value.toString()) + ..addListener(validate); } } diff --git a/lib/app/modules/AbilityScoresForm/views/ability_scores_form_view.dart b/lib/app/modules/AbilityScoresForm/views/ability_scores_form_view.dart index b6b422d7..e63d005f 100644 --- a/lib/app/modules/AbilityScoresForm/views/ability_scores_form_view.dart +++ b/lib/app/modules/AbilityScoresForm/views/ability_scores_form_view.dart @@ -13,16 +13,15 @@ import 'package:dungeon_paper/app/widgets/atoms/round_icon_button.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/generated/l10n.dart'; -import 'package:flutter/material.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; - +import 'package:flutter/material.dart'; import 'package:get/get.dart'; class AbilityScoresFormView extends GetView { const AbilityScoresFormView({ - Key? key, - }) : super(key: key); + super.key, + }); @override Widget build(BuildContext context) { @@ -31,18 +30,18 @@ class AbilityScoresFormView extends GetView { dirty: controller.dirty.value, child: Scaffold( appBar: AppBar( - title: Text(S.current.entityPlural(AbilityScore)), + title: Text(tr.entityPlural(AbilityScore)), centerTitle: true, ), floatingActionButton: AdvancedFloatingActionButton.extended( onPressed: _save, - label: Text(S.current.save), + label: Text(tr.generic.save), icon: const Icon(Icons.save), ), body: ListView( padding: const EdgeInsets.all(16).copyWith(bottom: 80), children: [ - HelpText(text: S.current.abilityScoreInfo), + HelpText(text: tr.abilityScores.info), const SizedBox(height: 8), Form( child: ReorderableListView.builder( @@ -50,8 +49,10 @@ class AbilityScoresFormView extends GetView { physics: const NeverScrollableScrollPhysics(), itemCount: controller.abilityScores.value.stats.length, onReorder: (int oldIndex, int newIndex) { - controller.abilityScores.value = controller.abilityScores.value - .copyWith(stats: reorder(controller.abilityScores.value.stats, oldIndex, newIndex)); + controller.abilityScores.value = + controller.abilityScores.value.copyWith( + stats: reorder(controller.abilityScores.value.stats, + oldIndex, newIndex)); }, itemBuilder: (context, index) => _buildCard(context, index), ), @@ -64,8 +65,8 @@ class AbilityScoresFormView extends GetView { )), icon: const Icon(Icons.add), label: Text( - S.current.addGeneric( - S.current.entity(AbilityScore), + tr.generic.addEntity( + tr.entity(AbilityScore), ), ), ), @@ -81,9 +82,11 @@ class AbilityScoresFormView extends GetView { final textTheme = theme.textTheme; final statKey = sortByPredefined( controller.textControllers.keys.toList(), - order: controller.abilityScores.value.stats.map((stat) => stat.key).toList(), + order: + controller.abilityScores.value.stats.map((stat) => stat.key).toList(), ).elementAt(index); - final stat = controller.abilityScores.value.stats.firstWhere((stat) => stat.key == statKey); + final stat = controller.abilityScores.value.stats + .firstWhere((stat) => stat.key == statKey); return Padding( key: Key('stat-$statKey'), padding: const EdgeInsets.symmetric(vertical: 4), @@ -131,15 +134,18 @@ class AbilityScoresFormView extends GetView { ), ), Padding( - padding: const EdgeInsets.symmetric(horizontal: 8).copyWith(right: 16), + padding: const EdgeInsets.symmetric(horizontal: 8) + .copyWith(right: 16), child: Text( - S.current.abilityScoreModifierValueLabel(stat.modifier), + tr.abilityScores.form + .modifierValueLabel(stat.modifier.toString()), ), ), RoundIconButton( icon: DiceIcon.from(dw.Dice.d6), - onPressed: () => controller.textControllers[stat.key]!.text = Random().nextInt(21).toString(), - tooltip: S.current.abilityScoreRollButtonTooltip, + onPressed: () => controller.textControllers[stat.key]! + .text = Random().nextInt(21).toString(), + tooltip: tr.abilityScores.rollButton.randStat, ), Expanded(child: Container()), Padding( @@ -154,7 +160,9 @@ class AbilityScoresFormView extends GetView { ), onDelete: () => deleteDialog.confirm( context, - DeleteDialogOptions(entityName: stat.name, entityKind: S.current.entity(AbilityScore)), + DeleteDialogOptions( + entityName: stat.name, + entityKind: tr.entity(AbilityScore)), () => controller.removeStat(stat), ), ), diff --git a/lib/app/modules/About/views/about_view.dart b/lib/app/modules/About/views/about_view.dart index 51cd7f5b..89290b96 100644 --- a/lib/app/modules/About/views/about_view.dart +++ b/lib/app/modules/About/views/about_view.dart @@ -4,7 +4,7 @@ import 'package:dungeon_paper/app/routes/app_pages.dart'; import 'package:dungeon_paper/app/widgets/atoms/rainbow_text.dart'; import 'package:dungeon_paper/core/dw_icons.dart'; import 'package:dungeon_paper/core/utils/builder_utils.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -13,7 +13,7 @@ import '../../../model_utils/user_utils.dart'; import '../controllers/about_controller.dart'; class AboutView extends GetView { - const AboutView({Key? key}) : super(key: key); + const AboutView({super.key}); @override Widget build(BuildContext context) { @@ -22,19 +22,19 @@ class AboutView extends GetView { return Scaffold( appBar: AppBar( - title: Text(S.current.about), + title: Text(tr.about.title), centerTitle: true, ), body: ItemBuilder.lazyListView( children: [ () => Text( - S.current.appName, + tr.app.name, textAlign: TextAlign.center, style: textTheme.headlineMedium, ), () => Obx( () => Text( - S.current.aboutVersion(controller.version.value?.toString() ?? '-'), + tr.about.version(controller.version.value?.toString() ?? '-'), textAlign: TextAlign.center, style: textTheme.bodySmall, ), @@ -46,34 +46,38 @@ class AboutView extends GetView { ), () => const SizedBox(height: 16), () => Text( - S.current.aboutCopyright(DateTime.now().year), + tr.about.copyright(DateTime.now().year), textAlign: TextAlign.center, ), () => Text( - S.current.aboutAuthor, + tr.about.author, textAlign: TextAlign.center, ), () => const Divider(height: 48), () => ListTile( leading: const Icon(DwIcons.discord), - title: Text(S.current.aboutJoinDiscord), - subtitle: Text(S.current.aboutJoinDiscordSubtitle, style: textTheme.bodySmall), - onTap: () => launchUrl(Uri.parse('https://bit.ly/DungeonPaper-Discord')), + title: Text(tr.about.discord.title), + subtitle: + Text(tr.about.discord.subtitle, style: textTheme.bodySmall), + onTap: () => + launchUrl(Uri.parse('https://bit.ly/DungeonPaper-Discord')), isThreeLine: true, visualDensity: VisualDensity.compact, ), () => ListTile( leading: const Icon(Icons.send), - title: Text(S.current.aboutSendFeedback), - subtitle: Text(S.current.aboutSendFeedbackSubtitle, style: textTheme.bodySmall), + title: Text(tr.about.feedback.title), + subtitle: Text(tr.about.feedback.subtitle, + style: textTheme.bodySmall), onTap: () => Get.toNamed(Routes.sendFeedback), isThreeLine: true, visualDensity: VisualDensity.compact, ), () => const Divider(), () => Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - child: Text(S.current.aboutSocialLinks, style: textTheme.bodySmall), + padding: + const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: Text(tr.about.socials.title, style: textTheme.bodySmall), ), () => Padding( padding: const EdgeInsets.all(16.0).copyWith(top: 0), @@ -83,37 +87,37 @@ class AboutView extends GetView { children: [ _SocialButton( icon: Icon(DwIcons.providerIcon(ProviderName.twitter)), - label: Text(S.current.socialTwitter), + label: Text(tr.about.socials.twitter), url: 'https://bit.ly/DungeonPaper-Twitter', color: const Color.fromARGB(255, 28, 157, 236), ), _SocialButton( icon: Icon(DwIcons.providerIcon(ProviderName.facebook)), - label: Text(S.current.socialFacebook), + label: Text(tr.about.socials.facebook), url: 'https://bit.ly/DungeonPaper-Facebook', color: const Color.fromARGB(255, 22, 116, 236), ), _SocialButton( icon: Icon(DwIcons.providerIcon(ProviderName.discord)), - label: Text(S.current.socialDiscord), + label: Text(tr.about.socials.discord), url: 'https://bit.ly/DungeonPaper-Discord', color: const Color.fromARGB(255, 111, 133, 212), ), _SocialButton( icon: Icon(DwIcons.providerIcon(ProviderName.github)), - label: Text(S.current.socialGitHub), + label: Text(tr.about.socials.github), url: 'https://bit.ly/DungeonPaper-GitHub', color: const Color.fromARGB(255, 33, 32, 32), ), _SocialButton( icon: Icon(DwIcons.providerIcon(ProviderName.google)), - label: Text(S.current.socialGoogle), + label: Text(tr.about.socials.google), url: 'https://bit.ly/DungeonPaper-Android', color: const Color.fromARGB(255, 1, 135, 95), ), _SocialButton( icon: Icon(DwIcons.providerIcon(ProviderName.apple)), - label: Text(S.current.socialApple), + label: Text(tr.about.socials.apple), url: 'https://bit.ly/DungeonPaper-iOS', color: const Color.fromARGB(255, 30, 143, 232), ), @@ -124,7 +128,7 @@ class AboutView extends GetView { () => ListTile( minLeadingWidth: 36, leading: const Icon(Icons.favorite), - title: Text(S.current.aboutSpecialThanks), + title: Text(tr.about.specialThanks), subtitle: RainbowText( [ 'dekelts', @@ -146,7 +150,7 @@ class AboutView extends GetView { () => ListTile( minLeadingWidth: 36, leading: const Icon(Icons.code), - title: Text(S.current.aboutIconCredits), + title: Text(tr.about.icons), subtitle: Text(iconCredits), ), ], diff --git a/lib/app/modules/Account/controllers/account_controller.dart b/lib/app/modules/Account/controllers/account_controller.dart index b6cf1df8..b8c12233 100644 --- a/lib/app/modules/Account/controllers/account_controller.dart +++ b/lib/app/modules/Account/controllers/account_controller.dart @@ -2,24 +2,25 @@ import 'package:dungeon_paper/app/data/services/auth_service.dart'; import 'package:dungeon_paper/app/data/services/user_service.dart'; import 'package:dungeon_paper/core/utils/upload_utils.dart'; import 'package:dungeon_paper/core/utils/uuid.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:image_cropper/image_cropper.dart'; -class AccountController extends GetxController with UserServiceMixin, AuthServiceMixin { +class AccountController extends GetxController + with UserServiceMixin, AuthServiceMixin { final uploading = false.obs; void updateEmail(String email) async { await userService.updateEmail(email); - Get.rawSnackbar(message: S.current.accountChangeEmailSuccess); + Get.rawSnackbar(message: tr.account.details.email.success); } void uploadPhoto(BuildContext context) { cropAndUploadPhoto( context, UploadSettings( - uploadPath: '/UserPhoto/' + uuid(), + uploadPath: '/UserPhoto/${uuid()}', cropStyle: CropStyle.circle, onUploadFile: (_) => uploading.value = true, onSuccess: (url) { diff --git a/lib/app/modules/Account/views/account_view.dart b/lib/app/modules/Account/views/account_view.dart index fa7387cb..00c7ff16 100644 --- a/lib/app/modules/Account/views/account_view.dart +++ b/lib/app/modules/Account/views/account_view.dart @@ -9,9 +9,8 @@ import 'package:dungeon_paper/core/utils/builder_utils.dart'; import 'package:dungeon_paper/core/utils/email_address_validator.dart'; import 'package:dungeon_paper/core/utils/password_validator.dart'; import 'package:dungeon_paper/core/utils/string_validator.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; - import 'package:get/get.dart'; import '../../../../core/dw_icons.dart'; @@ -20,7 +19,7 @@ import '../../../model_utils/user_utils.dart'; import '../controllers/account_controller.dart'; class AccountView extends GetView { - const AccountView({Key? key}) : super(key: key); + const AccountView({super.key}); @override Widget build(BuildContext context) { final theme = Theme.of(context); @@ -39,15 +38,16 @@ class AccountView extends GetView { () => const SizedBox(height: 8), () => const Divider(), () => Padding( - padding: const EdgeInsets.symmetric(horizontal: 16).copyWith(top: 8), + padding: + const EdgeInsets.symmetric(horizontal: 16).copyWith(top: 8), child: Text( - S.current.accountCategoryDetails, + tr.account.details.title, style: textTheme.bodySmall, ), ), () => Obx( () => ListTile( - title: Text(S.current.accountChangeDisplayNameTitle), + title: Text(tr.account.details.displayName.title), subtitle: Text(controller.user.displayName), leading: const Icon(Icons.abc), onTap: _openNameDialog, @@ -55,8 +55,8 @@ class AccountView extends GetView { ), () => Obx( () => ListTile( - title: Text(S.current.accountChangeImageTitle), - subtitle: Text(S.current.accountChangeImageSubtitle), + title: Text(tr.account.details.image.title), + subtitle: Text(tr.account.details.image.subtitle), leading: controller.uploading.value ? const SizedBox.square( dimension: 24, @@ -66,28 +66,31 @@ class AccountView extends GetView { ) : const Icon(Icons.image), enabled: !controller.uploading.value, - onTap: !controller.uploading.value ? () => _uploadImage(context) : null, + onTap: !controller.uploading.value + ? () => _uploadImage(context) + : null, ), ), () => Obx( () => ListTile( - title: Text(S.current.accountChangeEmailTitle), + title: Text(tr.account.details.email.title), subtitle: Text(controller.user.email), onTap: _openEmailDialog, leading: const Icon(Icons.email), ), ), () => ListTile( - title: Text(S.current.accountChangePasswordTitle), - subtitle: Text(S.current.accountChangePasswordSubtitle), + title: Text(tr.account.details.password.title), + subtitle: Text(tr.account.details.password.subtitle), onTap: _openPasswordDialog, leading: const Icon(Icons.key), ), () => const Divider(), () => Padding( - padding: const EdgeInsets.symmetric(horizontal: 16).copyWith(top: 8), + padding: + const EdgeInsets.symmetric(horizontal: 16).copyWith(top: 8), child: Text( - S.current.accountCategorySocials, + tr.account.providers.title, style: textTheme.bodySmall, ), ), @@ -102,19 +105,17 @@ class AccountView extends GetView { (provider) { return () => Obx( () => ListTile( - title: Text(S.current.signinProvider(provider)), + title: Text(tr.auth.providers.name(provider.name)), // subtitle: Text(provider.), leading: Icon(DwIcons.providerIcon(provider)), subtitle: !PlatformHelper.canUseProvider(provider) ? Text( - S.current.signinCantUseProvider(S.current.signinProvider(provider)), + tr.auth.providers.unusable( + tr.auth.providers.name(provider.name)), textScaleFactor: 0.8, ) : null, trailing: ElevatedButton( - child: Text( - isProviderLinked(provider) ? S.current.signinProviderUnlink : S.current.signinProviderLink, - ), onPressed: providerCount > 1 ? isProviderLinked(provider) ? unlinkProvider(context, provider) @@ -122,6 +123,11 @@ class AccountView extends GetView { ? linkProvider(provider) : null : null, + child: Text( + isProviderLinked(provider) + ? tr.auth.providers.unlink + : tr.auth.providers.link, + ), ), ), ); @@ -129,7 +135,7 @@ class AccountView extends GetView { ), // delete account () => ListTile( - title: Text(S.current.accountDelete), + title: Text(tr.account.deleteAccount.title), leading: const Icon(Icons.delete_forever), onTap: () => awaitDeleteAccountConfirmation( context, @@ -137,12 +143,12 @@ class AccountView extends GetView { api.requests.sendFeedback( email: controller.user.email, subject: 'Account Deletion Request', - body: 'Automated: Request Account Deletion for ${controller.user.email}', + body: + 'Automated: Request Account Deletion for ${controller.user.email}', username: controller.user.username, ); - // A deletion request for your account was sent successfully - Get.rawSnackbar(message: 'A deletion request for your account was sent successfully'); - // Get.rawSnackbar(message: S.current.accountDeleteSuccess); + // A deletion request for your account was sent successfully + Get.rawSnackbar(message: tr.account.deleteAccount.success); }, ), ), @@ -158,7 +164,7 @@ class AccountView extends GetView { // Size(100, 28), // ), // ), - // child: Text(S.current.accountDelete), + // child: Text(tr.account.deleteAccount.title), // onPressed: () => // awaitDeleteAccountConfirmation(context, () => null), // ), @@ -176,21 +182,23 @@ class AccountView extends GetView { ); } - int get providerCount => controller.authService.fbUser?.providerData.length ?? 0; + int get providerCount => + controller.authService.fbUser?.providerData.length ?? 0; bool isProviderLinked(ProviderName provider) => - controller.authService.fbUser?.providerData.any((pr) => pr.providerId == domainFromProviderName(provider)) == + controller.authService.fbUser?.providerData + .any((pr) => pr.providerId == domainFromProviderName(provider)) == true; void _openNameDialog() { Get.dialog( SingleTextFieldDialog( - title: S.current.accountChangeDisplayNameTitle, - inputLabel: S.current.accountChangeDisplayNameLabel, - inputHint: S.current.accountChangeDisplayNameHint, + title: tr.account.details.displayName.title, + inputLabel: tr.account.details.displayName.label, + inputHint: tr.account.details.displayName.placeholder, value: controller.user.displayName, onSave: (displayName) { - Get.rawSnackbar(message: S.current.accountChangeDisplayNameSuccess); + Get.rawSnackbar(message: tr.account.details.displayName.success); controller.userService.updateUser( controller.user.copyWith(displayName: displayName), ); @@ -202,9 +210,9 @@ class AccountView extends GetView { void _openEmailDialog() { Get.dialog( SingleTextFieldDialog( - title: S.current.accountChangeEmailTitle, - inputLabel: S.current.accountChangeEmailLabel, - inputHint: S.current.accountChangeEmailHint, + title: tr.account.details.email.title, + inputLabel: tr.account.details.email.label, + inputHint: tr.account.details.email.placeholder, value: controller.user.email, validator: EmailAddressValidator().validator, onSave: controller.updateEmail, @@ -216,7 +224,7 @@ class AccountView extends GetView { Get.dialog( PasswordFieldDialog( onSave: (password) { - Get.rawSnackbar(message: S.current.accountChangePasswordSuccess); + Get.rawSnackbar(message: tr.account.details.password.success); controller.authService.fbUser!.updatePassword(password); }, ), @@ -227,18 +235,21 @@ class AccountView extends GetView { controller.uploadPhoto(context); } - Future Function() unlinkProvider(BuildContext context, ProviderName provider) => + Future Function() unlinkProvider( + BuildContext context, ProviderName provider) => () => awaitUnlinkProviderConfirmation( context, provider, () { controller.authService.logoutFromProvider(provider); - controller.authService.fbUser!.unlink(domainFromProviderName(provider)); + controller.authService.fbUser! + .unlink(domainFromProviderName(provider)); }, ); Future Function() linkProvider(ProviderName provider) => () async { - final cred = await controller.authService.getProviderCredential(provider); + final cred = + await controller.authService.getProviderCredential(provider); controller.authService.fbUser!.linkWithCredential(cred); }; } @@ -370,7 +381,7 @@ class _PasswordFieldDialogState extends State { @override Widget build(BuildContext context) { return AlertDialog( - title: Text(S.current.accountChangePasswordTitle), + title: Text(tr.account.details.password.title), content: SizedBox( width: 400, child: Form( @@ -382,8 +393,8 @@ class _PasswordFieldDialogState extends State { controller: password, validator: PasswordValidator().validator, decoration: InputDecoration( - labelText: S.current.accountChangePasswordLabel, - hintText: S.current.accountChangePasswordHint, + labelText: tr.account.details.password.label, + hintText: tr.account.details.password.placeholder, ), ), const SizedBox(height: 16), @@ -391,8 +402,8 @@ class _PasswordFieldDialogState extends State { controller: passwordConfirm, validator: _passwordValidator, decoration: InputDecoration( - labelText: S.current.accountChangePasswordConfirmLabel, - hintText: S.current.accountChangePasswordConfirmHint, + labelText: tr.account.details.password.confirm.label, + hintText: tr.account.details.password.confirm.placeholder, ), ), ], @@ -418,10 +429,10 @@ class _PasswordFieldDialogState extends State { }); } - String? _passwordValidator(String? _value) { + String? _passwordValidator(String? value) { if (password.text != passwordConfirm.text) { - return S.current.signupPasswordValidationMatch; + return tr.account.details.password.error; } - return PasswordValidator().validator(_value); + return PasswordValidator().validator(value); } } diff --git a/lib/app/modules/BasicInfoForm/views/basic_info_form_view.dart b/lib/app/modules/BasicInfoForm/views/basic_info_form_view.dart index 582730d5..3346af35 100644 --- a/lib/app/modules/BasicInfoForm/views/basic_info_form_view.dart +++ b/lib/app/modules/BasicInfoForm/views/basic_info_form_view.dart @@ -2,25 +2,25 @@ import 'package:dungeon_paper/app/data/models/character.dart'; import 'package:dungeon_paper/app/data/services/user_service.dart'; import 'package:dungeon_paper/app/routes/app_pages.dart'; import 'package:dungeon_paper/app/themes/colors.dart'; -import 'package:dungeon_paper/app/widgets/atoms/hyperlink.dart'; -import 'package:dungeon_paper/app/widgets/atoms/labeled_divider.dart'; import 'package:dungeon_paper/app/widgets/atoms/advanced_floating_action_button.dart'; import 'package:dungeon_paper/app/widgets/atoms/character_avatar.dart'; import 'package:dungeon_paper/app/widgets/atoms/confirm_exit_view.dart'; +import 'package:dungeon_paper/app/widgets/atoms/hyperlink.dart'; +import 'package:dungeon_paper/app/widgets/atoms/labeled_divider.dart'; import 'package:dungeon_paper/core/dw_icons.dart'; import 'package:dungeon_paper/core/platform_helper.dart'; import 'package:dungeon_paper/core/utils/content_generators/character_name_generator.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; - import 'package:get/get.dart'; import '../controllers/basic_info_form_controller.dart'; -class BasicInfoFormView extends GetView with UserServiceMixin { +class BasicInfoFormView extends GetView + with UserServiceMixin { const BasicInfoFormView({ - Key? key, - }) : super(key: key); + super.key, + }); @override Widget build(BuildContext context) { @@ -30,12 +30,12 @@ class BasicInfoFormView extends GetView with UserServic dirty: controller.dirty.value, child: Scaffold( appBar: AppBar( - title: Text(S.current.basicInformationTitle), + title: Text(tr.basicInfo.title), centerTitle: true, ), floatingActionButton: AdvancedFloatingActionButton.extended( onPressed: _save, - label: Text(S.current.save), + label: Text(tr.generic.save), icon: const Icon(Icons.save), ), body: Form( @@ -48,22 +48,24 @@ class BasicInfoFormView extends GetView with UserServic autovalidateMode: AutovalidateMode.onUserInteraction, controller: controller.name.value, textInputAction: TextInputAction.next, - validator: (val) => val == null || val.isEmpty ? 'Cannot be empty' : null, + validator: (val) => + val == null || val.isEmpty ? 'Cannot be empty' : null, // onChanged: (val) => updateControllers(), textCapitalization: TextCapitalization.words, decoration: InputDecoration( - labelText: S.current.createCharacterNameFieldLabel, - hintText: S.current.createCharacterNameFieldPlaceholder, + labelText: tr.basicInfo.form.name.label, + hintText: tr.basicInfo.form.name.placeholder, floatingLabelBehavior: FloatingLabelBehavior.always, suffixIcon: IconButton( tooltip: PlatformHelper.byInteractionType( context, - touch: S.current.createCharRandomizeNameTooltipTouch, - mouse: S.current.createCharRandomizeNameTooltipClick, + touch: tr.basicInfo.form.name.random.tooltip.touch, + mouse: tr.basicInfo.form.name.random.tooltip.click, ), icon: const Icon(DwIcons.dice_d6_numbered), onPressed: () { - controller.name.value.text = CharacterNameGenerator().generate(); + controller.name.value.text = + CharacterNameGenerator().generate(); }, ), ), @@ -86,17 +88,21 @@ class BasicInfoFormView extends GetView with UserServic children: [ Expanded( child: ElevatedButton.icon( - onPressed: controller.isUploading ? null : () => controller.startUploadFlow(context), + onPressed: controller.isUploading + ? null + : () => controller.startUploadFlow(context), icon: const Icon(Icons.upload_file), - label: Text(S.current.basicInfoImageChooseNew), + label: Text(tr.basicInfo.form.photo.change), ), ), const SizedBox(width: 16), Expanded( child: ElevatedButton.icon( - onPressed: controller.isUploading ? null : controller.resetPhoto, + onPressed: controller.isUploading + ? null + : controller.resetPhoto, icon: const Icon(Icons.close), - label: Text(S.current.basicInfoImageRemove), + label: Text(tr.basicInfo.form.photo.remove), ), ), ], @@ -106,11 +112,12 @@ class BasicInfoFormView extends GetView with UserServic SizedBox( height: 40, child: ElevatedButton.icon( - onPressed: !controller.isUploading && userService.isLoggedIn - ? () => controller.startUploadFlow(context) - : null, + onPressed: + !controller.isUploading && userService.isLoggedIn + ? () => controller.startUploadFlow(context) + : null, icon: const Icon(Icons.upload_file), - label: Text(S.current.basicInfoImageChoose), + label: Text(tr.basicInfo.form.photo.choose), ), ), if (userService.isGuest) ...[ @@ -122,16 +129,17 @@ class BasicInfoFormView extends GetView with UserServic const WidgetSpan( child: Padding( padding: EdgeInsets.only(right: 4), - child: Icon(Icons.warning, color: DwColors.warning, size: 16), + child: Icon(Icons.warning, + color: DwColors.warning, size: 16), ), ), - TextSpan(text: S.current.basicInfoImageNeedAccountPrefix + ' '), + TextSpan(text: tr.basicInfo.form.photo.guest.prefix), Hyperlink.textSpan( context, - S.current.basicInfoImageNeedAccountLinkLabel, + tr.basicInfo.form.photo.guest.label, onTap: () => Get.toNamed(Routes.login), ), - TextSpan(text: S.current.basicInfoImageNeedAccountSuffix), + TextSpan(text: tr.basicInfo.form.photo.guest.suffix), ], style: theme.textTheme.bodyMedium, ), @@ -148,10 +156,10 @@ class BasicInfoFormView extends GetView with UserServic child: CircularProgressIndicator(strokeWidth: 3), ), const SizedBox(width: 8), - Text(S.current.basicInfoImageUploading), + Text(tr.basicInfo.form.photo.uploading), ], ) - : Text(S.current.separatorOr), + : Text(tr.basicInfo.form.photo.orSeparator), ), TextFormField( controller: controller.avatarUrl.value, @@ -159,8 +167,8 @@ class BasicInfoFormView extends GetView with UserServic enabled: !controller.isUploading, // onChanged: (val) => updateControllers(), decoration: InputDecoration( - labelText: S.current.createCharacterAvatarFieldLabel, - hintText: S.current.createCharacterAvatarFieldPlaceholder, + labelText: tr.basicInfo.form.photo.url.label, + hintText: tr.basicInfo.form.photo.url.placeholder, floatingLabelBehavior: FloatingLabelBehavior.always, ), ), @@ -174,7 +182,8 @@ class BasicInfoFormView extends GetView with UserServic } _save() { - controller.onChanged(controller.name.value.text, controller.avatarUrl.value.text); + controller.onChanged( + controller.name.value.text, controller.avatarUrl.value.text); Get.back(); } } diff --git a/lib/app/modules/BioForm/controllers/bio_form_controller.dart b/lib/app/modules/BioForm/controllers/bio_form_controller.dart index 7ce9859b..ee52f171 100644 --- a/lib/app/modules/BioForm/controllers/bio_form_controller.dart +++ b/lib/app/modules/BioForm/controllers/bio_form_controller.dart @@ -21,8 +21,11 @@ class BioFormController extends GetxController with CharacterServiceMixin { bioDesc.value = TextEditingController(text: char.bio.description); looks.value = TextEditingController(text: char.bio.looks); alignmentName.value = char.bio.alignment.key; - alignmentValue.value = TextEditingController(text: char.bio.alignment.description); - bonds.value = char.sessionMarks.map((e) => TextEditingController(text: e.description)).toList(); + alignmentValue.value = + TextEditingController(text: char.bio.alignment.description); + bonds.value = char.sessionMarks + .map((e) => TextEditingController(text: e.description)) + .toList(); } void save() { diff --git a/lib/app/modules/BioForm/views/bio_form_view.dart b/lib/app/modules/BioForm/views/bio_form_view.dart index e92a3b32..1c8b71ce 100644 --- a/lib/app/modules/BioForm/views/bio_form_view.dart +++ b/lib/app/modules/BioForm/views/bio_form_view.dart @@ -5,12 +5,13 @@ import 'package:dungeon_paper/app/widgets/atoms/advanced_floating_action_button. import 'package:dungeon_paper/app/widgets/atoms/confirm_exit_view.dart'; import 'package:dungeon_paper/app/widgets/atoms/rich_text_field.dart'; import 'package:dungeon_paper/app/widgets/atoms/select_box.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -class BioFormView extends GetView with CharacterServiceMixin { - const BioFormView({Key? key}) : super(key: key); +class BioFormView extends GetView + with CharacterServiceMixin { + const BioFormView({super.key}); @override Widget build(BuildContext context) { @@ -19,11 +20,11 @@ class BioFormView extends GetView with CharacterServiceMixin dirty: controller.dirty.value, child: Scaffold( appBar: AppBar( - title: Text(S.current.characterBioDialogTitle), + title: Text(tr.bio.dialog.title), ), floatingActionButton: AdvancedFloatingActionButton.extended( onPressed: _save, - label: Text(S.current.save), + label: Text(tr.generic.save), icon: const Icon(Icons.save), ), body: ListView( @@ -36,8 +37,8 @@ class BioFormView extends GetView with CharacterServiceMixin textCapitalization: TextCapitalization.sentences, onChanged: controller.setDirty, decoration: InputDecoration( - label: Text(S.current.characterBioDialogDescLabel), - hintText: S.current.characterBioDialogDescPlaceholder, + label: Text(tr.bio.dialog.description.label), + hintText: tr.bio.dialog.description.placeholder, ), ), const SizedBox(height: 8), @@ -48,8 +49,8 @@ class BioFormView extends GetView with CharacterServiceMixin textCapitalization: TextCapitalization.sentences, onChanged: controller.setDirty, decoration: InputDecoration( - label: Text(S.current.characterBioDialogLooksLabel), - hintText: S.current.characterBioDialogLooksPlaceholder, + label: Text(tr.bio.dialog.looks.label), + hintText: tr.bio.dialog.looks.placeholder, ), ), const SizedBox(height: 24), @@ -63,7 +64,7 @@ class BioFormView extends GetView with CharacterServiceMixin children: [ Icon(AlignmentValue.iconMap[a]!), const SizedBox(width: 4), - Text(S.current.alignment(a)), + Text(tr.alignment.name(a)), ], ), ), @@ -74,7 +75,7 @@ class BioFormView extends GetView with CharacterServiceMixin controller.setDirty(); }, isExpanded: true, - label: Text(S.current.characterBioDialogAlignmentNameLabel), + label: Text(tr.bio.dialog.alignment.label), ), const SizedBox(height: 8), RichTextField( @@ -84,8 +85,8 @@ class BioFormView extends GetView with CharacterServiceMixin textCapitalization: TextCapitalization.sentences, onChanged: controller.setDirty, decoration: InputDecoration( - label: Text(S.current.characterBioDialogAlignmentDescriptionLabel), - hintText: S.current.characterBioDialogAlignmentDescriptionPlaceholder, + label: Text(tr.bio.dialog.alignmentDescription.label), + hintText: tr.bio.dialog.alignmentDescription.placeholder, ), ), const SizedBox(height: 80), diff --git a/lib/app/modules/BondsFlagsForm/controllers/bonds_flags_form_controller.dart b/lib/app/modules/BondsFlagsForm/controllers/bonds_flags_form_controller.dart index d63a237a..6dc41c3f 100644 --- a/lib/app/modules/BondsFlagsForm/controllers/bonds_flags_form_controller.dart +++ b/lib/app/modules/BondsFlagsForm/controllers/bonds_flags_form_controller.dart @@ -9,7 +9,8 @@ class BondsFlagsFormController extends GetxController { final flags = [].obs; final bondsDesc = [].obs; final flagsDesc = [].obs; - late final void Function(List bonds, List flags) onChanged; + late final void Function(List bonds, List flags) + onChanged; final dirty = false.obs; @override @@ -17,11 +18,15 @@ class BondsFlagsFormController extends GetxController { super.onReady(); final BondsFlagsFormArguments args = Get.arguments; bonds.value = args.bonds; - bondsDesc.value = - args.bonds.map((e) => TextEditingController(text: e.description)..addListener(_setDirty)).toList(); + bondsDesc.value = args.bonds + .map((e) => + TextEditingController(text: e.description)..addListener(_setDirty)) + .toList(); flags.value = args.flags; - flagsDesc.value = - args.flags.map((e) => TextEditingController(text: e.description)..addListener(_setDirty)).toList(); + flagsDesc.value = args.flags + .map((e) => + TextEditingController(text: e.description)..addListener(_setDirty)) + .toList(); onChanged = args.onChanged; } @@ -65,11 +70,13 @@ class BondsFlagsFormController extends GetxController { void save() { final newBonds = enumerate(bonds) - .map((e) => e.value.copyWithInherited(description: bondsDesc[e.index].text)) + .map((e) => + e.value.copyWithInherited(description: bondsDesc[e.index].text)) .where((e) => e.description.isNotEmpty) .toList(); final newFlags = enumerate(flags) - .map((e) => e.value.copyWithInherited(description: flagsDesc[e.index].text)) + .map((e) => + e.value.copyWithInherited(description: flagsDesc[e.index].text)) .where((e) => e.description.isNotEmpty) .toList(); @@ -87,7 +94,8 @@ class BondsFlagsFormController extends GetxController { class BondsFlagsFormArguments { final List bonds; final List flags; - final void Function(List bonds, List flags) onChanged; + final void Function(List bonds, List flags) + onChanged; BondsFlagsFormArguments({ required this.bonds, diff --git a/lib/app/modules/BondsFlagsForm/views/bonds_flags_form_view.dart b/lib/app/modules/BondsFlagsForm/views/bonds_flags_form_view.dart index 22f1dad2..1373ed13 100644 --- a/lib/app/modules/BondsFlagsForm/views/bonds_flags_form_view.dart +++ b/lib/app/modules/BondsFlagsForm/views/bonds_flags_form_view.dart @@ -1,15 +1,14 @@ import 'package:dungeon_paper/app/widgets/atoms/advanced_floating_action_button.dart'; import 'package:dungeon_paper/app/widgets/atoms/confirm_exit_view.dart'; import 'package:dungeon_paper/core/utils/list_utils.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; - import 'package:get/get.dart'; import '../controllers/bonds_flags_form_controller.dart'; class BondsFlagsFormView extends GetView { - const BondsFlagsFormView({Key? key}) : super(key: key); + const BondsFlagsFormView({super.key}); @override Widget build(BuildContext context) { @@ -19,18 +18,18 @@ class BondsFlagsFormView extends GetView { dirty: controller.dirty.value, child: Scaffold( appBar: AppBar( - title: Text(S.current.characterBondsFlagsDialogTitle), + title: Text(tr.sessionMarks.title), centerTitle: true, ), floatingActionButton: AdvancedFloatingActionButton.extended( onPressed: controller.save, icon: const Icon(Icons.save), - label: Text(S.current.save), + label: Text(tr.generic.save), ), body: ListView( padding: const EdgeInsets.all(16), children: [ - Text(S.current.characterBondsFlagsDialogBonds, style: textTheme.headlineSmall), + Text(tr.sessionMarks.bonds, style: textTheme.headlineSmall), for (final bond in enumerate(controller.bondsDesc)) ListTile( contentPadding: const EdgeInsets.all(0), @@ -47,11 +46,11 @@ class BondsFlagsFormView extends GetView { ), OutlinedButton.icon( onPressed: () => controller.addBond(), - label: Text(S.current.createGeneric(S.current.characterBondsFlagsDialogBond)), + label: Text(tr.generic.createEntity(tr.sessionMarks.bond)), icon: const Icon(Icons.add), ), const Divider(height: 24), - Text(S.current.characterBondsFlagsDialogFlags, style: textTheme.headlineSmall), + Text(tr.sessionMarks.flags, style: textTheme.headlineSmall), for (final flag in enumerate(controller.flagsDesc)) ListTile( contentPadding: const EdgeInsets.all(0), @@ -68,7 +67,7 @@ class BondsFlagsFormView extends GetView { ), OutlinedButton.icon( onPressed: () => controller.addFlag(), - label: Text(S.current.createGeneric(S.current.characterBondsFlagsDialogFlag)), + label: Text(tr.generic.createEntity(tr.sessionMarks.flag)), icon: const Icon(Icons.add), ), ], diff --git a/lib/app/modules/Campaign/CampaignsList/controllers/campaigns_list_controller.dart b/lib/app/modules/Campaign/CampaignsList/controllers/campaigns_list_controller.dart index 81a2158c..685dd64b 100644 --- a/lib/app/modules/Campaign/CampaignsList/controllers/campaigns_list_controller.dart +++ b/lib/app/modules/Campaign/CampaignsList/controllers/campaigns_list_controller.dart @@ -14,7 +14,8 @@ class CampaignsListController extends GetxController { @override void onInit() { super.onInit(); - _campaignsListenerSubscription = StorageHandler.instance.collectionListener('Campaigns', _campaignsListener); + _campaignsListenerSubscription = StorageHandler.instance + .collectionListener('Campaigns', _campaignsListener); } @override diff --git a/lib/app/modules/Campaign/CampaignsList/views/campaigns_list_view.dart b/lib/app/modules/Campaign/CampaignsList/views/campaigns_list_view.dart index 7d3f492c..4c4c8dce 100644 --- a/lib/app/modules/Campaign/CampaignsList/views/campaigns_list_view.dart +++ b/lib/app/modules/Campaign/CampaignsList/views/campaigns_list_view.dart @@ -1,24 +1,23 @@ import 'package:dungeon_paper/app/data/models/campaign.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; - import 'package:get/get.dart'; import '../controllers/campaigns_list_controller.dart'; class CampaignsListView extends GetView { - const CampaignsListView({Key? key}) : super(key: key); + const CampaignsListView({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text(S.current.myGeneric(S.current.entityPlural(Campaign))), + title: Text(tr.generic.myEntity(tr.entityPlural(Campaign))), centerTitle: true, ), body: Obx( () => controller.campaigns.isEmpty ? Center( - child: Text(S.current.noGeneric(S.current.entityPlural(Campaign))), + child: Text(tr.generic.noEntity(tr.entityPlural(Campaign))), ) : ListView.builder( itemCount: controller.campaigns.length, diff --git a/lib/app/modules/CharacterList/views/character_list_view.dart b/lib/app/modules/CharacterList/views/character_list_view.dart index e721e0e1..43ecce65 100644 --- a/lib/app/modules/CharacterList/views/character_list_view.dart +++ b/lib/app/modules/CharacterList/views/character_list_view.dart @@ -11,25 +11,24 @@ import 'package:dungeon_paper/app/widgets/menus/entity_edit_menu.dart'; import 'package:dungeon_paper/app/widgets/molecules/categorized_list.dart'; import 'package:dungeon_paper/app/widgets/molecules/character_subtitle.dart'; import 'package:dungeon_paper/core/utils/builder_utils.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; - import 'package:get/get.dart'; -import '../../../../generated/l10n.dart'; - -class CharacterListPageView extends GetView with UserServiceMixin { - const CharacterListPageView({Key? key}) : super(key: key); +class CharacterListPageView extends GetView + with UserServiceMixin { + const CharacterListPageView({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text(S.current.characterListTitle), + title: Text(tr.generic.allEntities(tr.entity(Character))), centerTitle: true, ), floatingActionButton: AdvancedFloatingActionButton.extended( onPressed: () => Get.toNamed(Routes.createCharacter), - label: Text(S.current.createCharacterAddButton), + label: Text(tr.generic.createEntity(tr.entity(Character))), icon: const Icon(Icons.add), ), body: Obx( @@ -38,18 +37,23 @@ class CharacterListPageView extends GetView with UserServiceMi children: [ for (final cat in controller.charsByCategory.keys) () => CategorizedList( - title: Text(cat.isNotEmpty ? cat : S.current.characterNoCategory), + title: + Text(cat.isNotEmpty ? cat : tr.character.noCategory), onReorder: (oldIndex, newIndex) => controller.updateAll( - CharacterUtils.reorderCharacters(controller.charsByCategory[cat]!).call(oldIndex, newIndex), + CharacterUtils.reorderCharacters( + controller.charsByCategory[cat]!) + .call(oldIndex, newIndex), ), children: [ for (var char in controller.charsByCategory[cat]!) Builder( key: Key(char.key), builder: (context) { - final charTheme = AppThemes.getTheme(char.getCurrentTheme(user)); + final charTheme = AppThemes.getTheme( + char.getCurrentTheme(user)); return Padding( - padding: const EdgeInsets.symmetric(vertical: 4), + padding: + const EdgeInsets.symmetric(vertical: 4), child: Card( margin: EdgeInsets.zero, color: charTheme.scaffoldBackgroundColor, @@ -57,17 +61,20 @@ class CharacterListPageView extends GetView with UserServiceMi minLeadingWidth: 48, minVerticalPadding: 16, horizontalTitleGap: 10, - textColor: charTheme.colorScheme.onBackground, + textColor: + charTheme.colorScheme.onBackground, // textColor: ThemeData.estimateBrightnessForColor(charTheme.scaffoldBackgroundColor) == Brightness.light ? Colors.black : Colors.white, child: InkWell( borderRadius: borderRadius, - splashColor: Theme.of(context).splashColor, + splashColor: + Theme.of(context).splashColor, onTap: () { controller.setCurrent(char.key); Get.offAllNamed(Routes.home); }, child: ListTile( - leading: CharacterAvatar.squircle(character: char, size: 48), + leading: CharacterAvatar.squircle( + character: char, size: 48), title: Text(char.displayName), subtitle: CharacterSubtitle( character: char, @@ -79,9 +86,10 @@ class CharacterListPageView extends GetView with UserServiceMi context, DeleteDialogOptions( entityName: char.displayName, - entityKind: S.current.entity(Character), + entityKind: tr.entity(Character), ), - () => controller.deleteCharacter(char), + () => controller + .deleteCharacter(char), ), ), ), diff --git a/lib/app/modules/ClassAlignments/controllers/class_alignments_controller.dart b/lib/app/modules/ClassAlignments/controllers/class_alignments_controller.dart index 990882db..2c211b0b 100644 --- a/lib/app/modules/ClassAlignments/controllers/class_alignments_controller.dart +++ b/lib/app/modules/ClassAlignments/controllers/class_alignments_controller.dart @@ -8,7 +8,8 @@ class ClassAlignmentsController extends GetxController { final selected = Rx(null); bool selectable = false; bool editable = false; - late final void Function(AlignmentValues alignments, dw.AlignmentType? selected)? onChanged; + late final void Function( + AlignmentValues alignments, dw.AlignmentType? selected)? onChanged; final sortedAlignmentTypes = dw.AlignmentType.values.toList(); final editing = {}.obs; final textControllers = {}.obs; @@ -46,7 +47,8 @@ class ClassAlignmentsController extends GetxController { } bool isEditing(dw.AlignmentType type) => editable && editing[type] == true; - bool isSelected(dw.AlignmentType type) => selectable && selected.value == type; + bool isSelected(dw.AlignmentType type) => + selectable && selected.value == type; void save() { final updated = alignments.value.copyWithInherited( @@ -64,7 +66,8 @@ class ClassAlignmentsController extends GetxController { class ClassAlignmentsArguments { final AlignmentValues? alignments; - final void Function(AlignmentValues alignments, dw.AlignmentType? selected)? onChanged; + final void Function(AlignmentValues alignments, dw.AlignmentType? selected)? + onChanged; final bool selectable; final dw.AlignmentType? preselected; final bool editable; diff --git a/lib/app/modules/ClassAlignments/views/class_alignments_view.dart b/lib/app/modules/ClassAlignments/views/class_alignments_view.dart index 35152a17..9c0c7a17 100644 --- a/lib/app/modules/ClassAlignments/views/class_alignments_view.dart +++ b/lib/app/modules/ClassAlignments/views/class_alignments_view.dart @@ -3,37 +3,38 @@ import 'package:dungeon_paper/app/themes/colors.dart'; import 'package:dungeon_paper/app/themes/themes.dart'; import 'package:dungeon_paper/app/widgets/atoms/advanced_floating_action_button.dart'; import 'package:dungeon_paper/app/widgets/molecules/dialog_controls.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; - import 'package:get/get.dart'; import '../controllers/class_alignments_controller.dart'; class ClassAlignmentsView extends GetView { - const ClassAlignmentsView({Key? key}) : super(key: key); + const ClassAlignmentsView({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text(S.current.selectGeneric(S.current.entity(AlignmentValue))), + title: Text(tr.generic.selectEntity(tr.entity(AlignmentValue))), centerTitle: true, ), floatingActionButton: controller.onChanged != null ? AdvancedFloatingActionButton.extended( onPressed: controller.save, - label: Text(S.current.save), + label: Text(tr.generic.save), icon: const Icon(Icons.save), ) : null, body: ListView( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 0).copyWith(bottom: 80), + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 0) + .copyWith(bottom: 80), children: [ for (final alignment in controller.sortedAlignmentTypes) Padding( padding: const EdgeInsets.only(bottom: 8), child: Obx(() { - final description = controller.alignments.value.byType(alignment); + final description = + controller.alignments.value.byType(alignment); final isEditing = controller.isEditing(alignment); final isSelected = controller.isSelected(alignment); @@ -47,7 +48,7 @@ class ClassAlignmentsView extends GetView { ListTile( minLeadingWidth: 16, leading: Icon(AlignmentValue.iconOf(alignment)), - title: Text(S.current.alignment(alignment)), + title: Text(tr.alignment.name(alignment.name)), trailing: Row( mainAxisSize: MainAxisSize.min, children: !isEditing @@ -55,25 +56,37 @@ class ClassAlignmentsView extends GetView { if (controller.editable) IconButton( icon: const Icon(Icons.edit), - onPressed: () => controller.toggleEdit(alignment, true), + onPressed: () => controller.toggleEdit( + alignment, true), iconSize: 16, ), if (controller.selectable) ElevatedButton.icon( icon: const Icon(Icons.check), - label: Text(!isSelected ? S.current.select : S.current.selected), - onPressed: !isSelected ? () => controller.select(alignment) : null, + label: Text(!isSelected + ? tr.generic.select + : tr.generic.selected), + onPressed: !isSelected + ? () => controller.select(alignment) + : null, ), ] - : DialogControls.done(context, () => controller.toggleEdit(alignment, false)), + : DialogControls.done( + context, + () => controller.toggleEdit( + alignment, false)), ), ), Padding( - padding: const EdgeInsets.all(8).copyWith(left: 56, top: 0), + padding: const EdgeInsets.all(8) + .copyWith(left: 56, top: 0), child: !isEditing - ? Text(description.isEmpty ? S.current.noDescription : description) + ? Text(description.isEmpty + ? tr.generic.noDescription + : description) : TextField( - controller: controller.textControllers[alignment]!, + controller: + controller.textControllers[alignment]!, ), ) ], diff --git a/lib/app/modules/CreateCharacter/SelectMovesSpells/controllers/select_moves_spells_controller.dart b/lib/app/modules/CreateCharacter/SelectMovesSpells/controllers/select_moves_spells_controller.dart index 2349dcd0..841f9ee0 100644 --- a/lib/app/modules/CreateCharacter/SelectMovesSpells/controllers/select_moves_spells_controller.dart +++ b/lib/app/modules/CreateCharacter/SelectMovesSpells/controllers/select_moves_spells_controller.dart @@ -27,13 +27,14 @@ class SelectMovesSpellsController extends GetxController { onChanged = args.onChanged; } - Iterable get sortedMoves => [...moves]..sort((a, b) => a.category == b.category - ? cleanStr(a.name).compareTo(cleanStr(b.name)) - : a.category == MoveCategory.basic - ? -1 - : b.category == MoveCategory.basic - ? 1 - : 0); + Iterable get sortedMoves => + [...moves]..sort((a, b) => a.category == b.category + ? cleanStr(a.name).compareTo(cleanStr(b.name)) + : a.category == MoveCategory.basic + ? -1 + : b.category == MoveCategory.basic + ? 1 + : 0); } class SelectMovesSpellsArguments { diff --git a/lib/app/modules/CreateCharacter/SelectMovesSpells/views/select_moves_spells_view.dart b/lib/app/modules/CreateCharacter/SelectMovesSpells/views/select_moves_spells_view.dart index 73f80794..9f5de75c 100644 --- a/lib/app/modules/CreateCharacter/SelectMovesSpells/views/select_moves_spells_view.dart +++ b/lib/app/modules/CreateCharacter/SelectMovesSpells/views/select_moves_spells_view.dart @@ -9,17 +9,16 @@ import 'package:dungeon_paper/app/widgets/cards/move_card.dart'; import 'package:dungeon_paper/app/widgets/cards/spell_card.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/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; - import 'package:get/get.dart'; import '../controllers/select_moves_spells_controller.dart'; class SelectMovesSpellsView extends GetView { const SelectMovesSpellsView({ - Key? key, - }) : super(key: key); + super.key, + }); @override Widget build(BuildContext context) { @@ -28,12 +27,13 @@ class SelectMovesSpellsView extends GetView { dirty: controller.dirty.value, child: Scaffold( appBar: AppBar( - title: Text(S.current.selectGeneric(S.current.createCharacterMovesSpells)), + title: Text( + tr.generic.selectEntity(tr.createCharacter.movesSpells.title)), centerTitle: true, ), floatingActionButton: AdvancedFloatingActionButton.extended( onPressed: _save, - label: Text(S.current.save), + label: Text(tr.generic.save), icon: const Icon(Icons.save), ), body: SingleChildScrollView( @@ -43,8 +43,11 @@ class SelectMovesSpellsView extends GetView { children: [ // MOVES TITLE Obx(() => Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - child: Text(S.current.movesWithCount(controller.moves.length), style: titleStyle), + padding: + const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: Text( + tr.entityCountNum(Move, controller.moves.length), + style: titleStyle), )), // MOVES CARDS Obx( @@ -62,11 +65,14 @@ class SelectMovesSpellsView extends GetView { actions: [ EntityEditMenu( onEdit: () => ModelPages.openMovePage( - abilityScores: controller.abilityScores.value, + abilityScores: + controller.abilityScores.value, move: move, - onSave: (_move) => controller.moves.value = updateByKey(controller.moves, [_move]), + onSave: (move) => controller.moves.value = + updateByKey(controller.moves, [move]), ), - onDelete: () => controller.moves.value = removeByKey(controller.moves, [move]), + onDelete: () => controller.moves.value = + removeByKey(controller.moves, [move]), ), ], ), @@ -95,15 +101,18 @@ class SelectMovesSpellsView extends GetView { ); }, ), - label: Text(S.current.addGeneric(S.current.entityPlural(Move))), + label: Text(tr.generic.addEntity(tr.entityPlural(Move))), icon: const Icon(Icons.add), ), ), ), // SPELLS TITLE Obx(() => Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8).copyWith(top: 24), - child: Text(S.current.spellsWithCount(controller.spells.length), style: titleStyle), + padding: + const EdgeInsets.symmetric(horizontal: 16, vertical: 8) + .copyWith(top: 24), + child: Text(tr.entityCount(Spell, controller.spells.length), + style: titleStyle), )), // SPELL CARDS Obx( @@ -122,9 +131,10 @@ class SelectMovesSpellsView extends GetView { ElevatedButton.icon( style: ButtonThemes.primaryElevated(context), onPressed: () { - controller.spells.value = removeByKey(controller.spells, [spell]); + controller.spells.value = + removeByKey(controller.spells, [spell]); }, - label: Text(S.current.remove), + label: Text(tr.generic.remove), icon: const Icon(Icons.remove), ) ], @@ -149,11 +159,12 @@ class SelectMovesSpellsView extends GetView { controller.dirty.value = true; controller.spells.value = addByKey( controller.spells, - spells.map((m) => m.copyWithInherited(prepared: true)), + spells + .map((m) => m.copyWithInherited(prepared: true)), ); }, ), - label: Text(S.current.addGeneric(S.current.entityPlural(Spell))), + label: Text(tr.generic.addEntity(tr.entityPlural(Spell))), icon: const Icon(Icons.add), ), ), diff --git a/lib/app/modules/CreateCharacter/controllers/create_character_controller.dart b/lib/app/modules/CreateCharacter/controllers/create_character_controller.dart index bbf74eba..6274962b 100644 --- a/lib/app/modules/CreateCharacter/controllers/create_character_controller.dart +++ b/lib/app/modules/CreateCharacter/controllers/create_character_controller.dart @@ -22,7 +22,9 @@ class CreateCharacterController extends GetxController { final name = ''.obs; final avatarUrl = ''.obs; final characterClass = Rx(null); - final abilityScores = AbilityScores.dungeonWorld(dex: 10, str: 10, wis: 10, con: 10, intl: 10, cha: 10).obs; + final abilityScores = AbilityScores.dungeonWorld( + dex: 10, str: 10, wis: 10, con: 10, intl: 10, cha: 10) + .obs; final startingGear = [].obs; final moves = [].obs; final spells = [].obs; @@ -41,7 +43,8 @@ class CreateCharacterController extends GetxController { race.value != null, ].every((element) => element == true); - List get items => GearChoice.selectionToItems(startingGear, equipped: true); + List get items => + GearChoice.selectionToItems(startingGear, equipped: true); double get coins => GearChoice.selectionToCoins(startingGear); @@ -54,7 +57,8 @@ class CreateCharacterController extends GetxController { void setClass(CharacterClass cls) { characterClass.value = cls; setStartingGear( - cls.gearChoices.fold([], (all, cur) => [...all, ...cur.preselectedGearSelections]), + cls.gearChoices + .fold([], (all, cur) => [...all, ...cur.preselectedGearSelections]), ); addStartingMoves(); setDirty(); @@ -95,7 +99,9 @@ class CreateCharacterController extends GetxController { moves.clear(); moves.addAll( [...repo.builtIn.moves.values, ...repo.my.moves.values] - .where((m) => (m.classKeys.contains(characterClass.value!.reference) && m.category == MoveCategory.starting)) + .where((m) => + (m.classKeys.contains(characterClass.value!.reference) && + m.category == MoveCategory.starting)) .map( // favorite: move.category != MoveCategory.basic (move) => Move.fromDwMove(move, favorite: true), @@ -121,7 +127,8 @@ class CreateCharacterController extends GetxController { ), sessionMarks: [ ...(characterClass.value?.bonds - .map((bond) => SessionMark.bond(description: bond, completed: false, key: uuid())) + .map((bond) => SessionMark.bond( + description: bond, completed: false, key: uuid())) .toList() ?? []), ...Character.defaultEndOfSessionMarks, diff --git a/lib/app/modules/CreateCharacter/views/create_character_view.dart b/lib/app/modules/CreateCharacter/views/create_character_view.dart index 8993109f..42763f11 100644 --- a/lib/app/modules/CreateCharacter/views/create_character_view.dart +++ b/lib/app/modules/CreateCharacter/views/create_character_view.dart @@ -20,9 +20,8 @@ import 'package:dungeon_paper/app/themes/colors.dart'; import 'package:dungeon_paper/app/widgets/atoms/advanced_floating_action_button.dart'; import 'package:dungeon_paper/app/widgets/atoms/character_avatar.dart'; import 'package:dungeon_paper/app/widgets/atoms/confirm_exit_view.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; - import 'package:get/get.dart'; import 'package:intl/intl.dart'; @@ -31,7 +30,7 @@ import '../../../widgets/chips/advanced_chip.dart'; import '../controllers/create_character_controller.dart'; class CreateCharacterView extends GetView { - const CreateCharacterView({Key? key}) : super(key: key); + const CreateCharacterView({super.key}); CharacterClass? get cls => controller.characterClass.value; @override @@ -62,7 +61,7 @@ class CreateCharacterView extends GetView { : null, icon: const Icon(Icons.person_add), label: Text( - S.current.createGeneric(Character), + tr.generic.createEntity(tr.entity(Character)), ), ), ), @@ -82,15 +81,21 @@ class CreateCharacterView extends GetView { _Card( leading: CharacterAvatar.squircle( size: 48, - character: Character.empty().copyWith(avatarUrl: controller.avatarUrl.value), + character: Character.empty().copyWith( + avatarUrl: controller.avatarUrl.value, + ), ), title: controller.name.isEmpty - ? Text(S.current.createCharacterTravelerBlankName) + ? Text( + tr.createCharacter.basicInfo.defaultName, + ) : Text(controller.name.value), subtitle: controller.name.isEmpty - ? Text(S.current.createCharacterTravelerHelpText) + ? Text(tr.createCharacter.basicInfo.helpText) : Text( - S.current.createCharacterTravelerDescription(cls?.name ?? ''), + tr.createCharacter.basicInfo.description( + cls?.name ?? '', + ), ), valid: controller.name.isNotEmpty, onTap: () => Get.toNamed( @@ -106,19 +111,28 @@ class CreateCharacterView extends GetView { // Class _Card( title: cls == null - ? Text(S.current.selectGeneric(S.current.entity(CharacterClass))) + ? Text(tr.generic + .selectEntity(tr.entity(CharacterClass))) : Text(cls!.name), subtitle: cls == null - ? Text(S.current.createCharacterClassHelpText) + ? Text(tr.createCharacter.characterClass + .noSelection) : Text( - S.current.createCharacterClassDescription(cls!.hp, cls!.load, cls!.damageDice), + tr.createCharacter.characterClass + .description( + cls!.hp, + cls!.load, + cls!.damageDice.toString(), + ), ), valid: cls != null, onTap: () => Get.toNamed( Routes.createCharacterSelectClass, arguments: CharacterClassLibraryListArguments( preSelections: - controller.characterClass.value != null ? [controller.characterClass.value!] : [], + controller.characterClass.value != null + ? [controller.characterClass.value!] + : [], onSelected: (cls) => controller.setClass(cls), ), preventDuplicates: false, @@ -127,10 +141,12 @@ class CreateCharacterView extends GetView { // Race _Card( title: controller.race.value == null - ? Text(S.current.selectGeneric(S.current.entity(Race))) + ? Text( + tr.generic.selectEntity(tr.entity(Race))) : Text(controller.race.value!.name), subtitle: controller.race.value == null - ? Text(S.current.errorNoSelectionGeneric(S.current.entity(Race))) + ? Text(tr.generic + .noEntitySelected(tr.entity(Race))) : Text( controller.race.value!.description, overflow: TextOverflow.ellipsis, @@ -139,27 +155,32 @@ class CreateCharacterView extends GetView { ? () => ModelPages.openRacesList( character: controller.getAsCharacter(), preSelection: controller.race.value, - onSelected: (race) => controller.race.value = race, + onSelected: (race) => + controller.race.value = race, ) : null, valid: controller.race.value != null, ), // Ability Scores _Card( - contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - title: Text(S.current.selectGeneric(S.current.entityPlural(AbilityScore))), + contentPadding: const EdgeInsets.symmetric( + horizontal: 16, vertical: 8), + title: Text(tr.generic + .selectEntity(tr.entityPlural(AbilityScore))), // subtitle: Text( // controller.abilityScores.value.stats // .map((stat) => '${stat.key}: ${stat.value}') // .join(', '), subtitle: Padding( padding: const EdgeInsets.only(top: 4.0), - child: _AbilityScoreChipList(controller: controller), + child: _AbilityScoreChipList( + controller: controller), ), onTap: () => Get.toNamed( Routes.createCharacterAbilityScores, arguments: AbilityScoresFormArguments( - onChanged: (abilityScores) => controller.setAbilityScores(abilityScores), + onChanged: (abilityScores) => controller + .setAbilityScores(abilityScores), abilityScores: controller.abilityScores.value, ), preventDuplicates: false, @@ -167,31 +188,43 @@ class CreateCharacterView extends GetView { ), // Alignment _Card( - contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 0), + contentPadding: const EdgeInsets.symmetric( + horizontal: 16, vertical: 0), valid: controller.alignment.value != null, - title: Text(controller.alignment.value != null - ? S.current.entity(AlignmentValue) + - ': ' + - S.current.alignment(controller.alignment.value!.type) - : S.current.selectGeneric(S.current.entity(AlignmentValue))), + title: Text( + controller.alignment.value != null + ? [ + tr.entity(AlignmentValue), + tr.alignment.name(controller + .alignment.value!.type.name) + ].join(': ') + : tr.generic.selectEntity( + tr.entity(AlignmentValue), + ), + ), subtitle: controller.alignment.value != null ? Text( - controller.alignment.value!.description.isNotEmpty - ? controller.alignment.value!.description - : S.current.noDescription, + controller.alignment.value!.description + .isNotEmpty + ? controller + .alignment.value!.description + : tr.generic.noDescription, overflow: TextOverflow.ellipsis, maxLines: 1, ) : Text( - S.current.errorNoSelectionGenericRequired(S.current.entity(AlignmentValue)), + tr.generic.noEntitySelectedRequired( + tr.entity(AlignmentValue)), ), onTap: cls != null ? () => Get.toNamed( Routes.classAlignments, arguments: ClassAlignmentsArguments( onChanged: controller.setAlignment, - alignments: controller.characterClass.value!.alignments, - preselected: controller.alignment.value?.type, + alignments: controller + .characterClass.value!.alignments, + preselected: + controller.alignment.value?.type, selectable: true, editable: true, ), @@ -202,19 +235,27 @@ class CreateCharacterView extends GetView { // Starting Gear _Card( - contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - title: Text(S.current.selectGeneric(S.current.entity(GearSelection))), - subtitle: Text(controller.items.isEmpty && controller.coins == 0 - ? S.current.createCharacterStartingGearHelpText + contentPadding: const EdgeInsets.symmetric( + horizontal: 16, vertical: 8), + title: Text(tr.generic + .selectEntity(tr.entity(GearSelection))), + subtitle: Text(controller.items.isEmpty && + controller.coins == 0 + ? tr.createCharacter.startingGear.helpText : [ controller.coins > 0 - ? S.current.createCharacterStartingGearDescriptionCoins( - NumberFormat('#0.#').format(controller.coins), + ? tr.createCharacter.startingGear + .coins( + NumberFormat('#0.#') + .format(controller.coins), ) : null, controller.items - .map((i) => S.current.createCharacterStartingGearDescriptionItem( - NumberFormat('#0.#').format(i.amount), + .map((i) => tr + .createCharacter.startingGear + .item( + NumberFormat('#0.#') + .format(i.amount), i.name, )) .join(', '), @@ -224,7 +265,8 @@ class CreateCharacterView extends GetView { Routes.createCharacterStartingGear, arguments: StartingGearFormArguments( onChanged: controller.setStartingGear, - selectedOptions: controller.startingGear, + selectedOptions: + controller.startingGear, characterClass: cls!, ), preventDuplicates: false, @@ -234,7 +276,9 @@ class CreateCharacterView extends GetView { ? false : cls!.gearChoices.every( (c) => c.selections.any( - (s) => controller.startingGear.map((x) => x.key).contains(s.key), + (s) => controller.startingGear + .map((x) => x.key) + .contains(s.key), ), ), ), @@ -242,19 +286,23 @@ class CreateCharacterView extends GetView { _Card( // contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 12), title: Text( - S.current.selectGeneric( + tr.generic.selectEntity( (cls?.isSpellcaster ?? false) - ? S.current.createCharacterMovesSpells - : S.current.entityPlural(Move), + ? tr.createCharacter.movesSpells.title + : tr.entityPlural(Move), ), ), subtitle: Text( (cls?.isSpellcaster ?? false) - ? S.current.createCharacterMovesSpellsDescription( + ? tr.createCharacter.movesSpells + .description( controller.moves.length, controller.spells.length, ) - : S.current.movesWithCount(controller.moves.length), + : tr.entityCountNum( + Move, + controller.moves.length, + ), ), onTap: cls != null ? () => Get.toNamed( @@ -263,8 +311,10 @@ class CreateCharacterView extends GetView { onChanged: controller.setMovesSpells, moves: controller.moves, spells: controller.spells, - abilityScores: controller.abilityScores.value, - characterClass: controller.characterClass.value!, + abilityScores: + controller.abilityScores.value, + characterClass: + controller.characterClass.value!, ), preventDuplicates: false, ) @@ -287,7 +337,6 @@ class CreateCharacterView extends GetView { class _AbilityScoreChipList extends StatelessWidget { const _AbilityScoreChipList({ - super.key, required this.controller, }); @@ -331,14 +380,13 @@ class _AbilityScoreChipList extends StatelessWidget { class _Card extends StatelessWidget { const _Card({ - Key? key, this.contentPadding, this.leading, required this.title, required this.subtitle, this.valid = true, required this.onTap, - }) : super(key: key); + }); final EdgeInsets? contentPadding; final Widget? leading; diff --git a/lib/app/modules/Home/views/home_app_bar.dart b/lib/app/modules/Home/views/home_app_bar.dart index ec5d988f..b17a03be 100644 --- a/lib/app/modules/Home/views/home_app_bar.dart +++ b/lib/app/modules/Home/views/home_app_bar.dart @@ -3,18 +3,20 @@ import 'package:dungeon_paper/app/data/services/user_service.dart'; import 'package:dungeon_paper/app/modules/Migration/controllers/migration_controller.dart'; import 'package:dungeon_paper/app/routes/app_pages.dart'; import 'package:dungeon_paper/app/widgets/atoms/user_menu.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -class HomeAppBar extends StatelessWidget with LoadingServiceMixin, UserServiceMixin implements PreferredSizeWidget { +class HomeAppBar extends StatelessWidget + with LoadingServiceMixin, UserServiceMixin + implements PreferredSizeWidget { const HomeAppBar({super.key}); @override Widget build(BuildContext context) { return Obx( () => AppBar( - title: Text(S.current.appName), + title: Text(tr.app.name), automaticallyImplyLeading: false, leading: IconButton( icon: const Icon(Icons.search), diff --git a/lib/app/modules/Home/views/home_character_actions_view.dart b/lib/app/modules/Home/views/home_character_actions_view.dart index 8df462d3..cf426882 100644 --- a/lib/app/modules/Home/views/home_character_actions_view.dart +++ b/lib/app/modules/Home/views/home_character_actions_view.dart @@ -28,15 +28,14 @@ import 'package:dungeon_paper/app/widgets/menus/group_sort_menu.dart'; import 'package:dungeon_paper/app/widgets/molecules/categorized_list.dart'; import 'package:dungeon_paper/core/utils/builder_utils.dart'; import 'package:dungeon_paper/core/utils/list_utils.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; - import 'package:get/get.dart'; import 'local_widgets/home_character_actions_summary.dart'; class HomeCharacterActionsView extends GetView { - const HomeCharacterActionsView({Key? key}) : super(key: key); + const HomeCharacterActionsView({super.key}); Character get char => controller.current; @@ -106,19 +105,19 @@ class HomeCharacterActionsView extends GetView { children: [ Expanded( child: ElevatedButton( - child: Text( - S.current.actionsBasicMoves, - ), onPressed: _openBasicMoves, + child: Text( + tr.actions.moves.basic, + ), ), ), const SizedBox(width: 16), Expanded( child: ElevatedButton( - child: Text( - S.current.actionsSpecialMoves, - ), onPressed: _openSpecialMoves, + child: Text( + tr.actions.moves.special, + ), ), ), ], @@ -128,16 +127,18 @@ class HomeCharacterActionsView extends GetView { const SizedBox(height: 4), if (char.settings.racePosition == RacePosition.start) raceCard, ], - trailing: char.settings.racePosition == RacePosition.end ? [raceCard] : [], + trailing: + char.settings.racePosition == RacePosition.end ? [raceCard] : [], menuTrailing: [ if (char.settings.racePosition != RacePosition.start) // Move to start of list MenuEntry( value: 'move_to_start', - label: Text(S.current.moveToStartGeneric(S.current.entity(Race))), + label: Text(tr.sort.moveEntityToTop(tr.entity(Race))), onSelect: () => controller.updateCharacter( char.copyWith( - settings: char.settings.copyWith(racePosition: RacePosition.start), + settings: + char.settings.copyWith(racePosition: RacePosition.start), ), ), ), @@ -145,10 +146,11 @@ class HomeCharacterActionsView extends GetView { // Move to end of list MenuEntry( value: 'move_to_end', - label: Text(S.current.moveToEndGeneric(S.current.entity(Race))), + label: Text(tr.sort.moveEntityToBottom(tr.entity(Race))), onSelect: () => controller.updateCharacter( char.copyWith( - settings: char.settings.copyWith(racePosition: RacePosition.end), + settings: + char.settings.copyWith(racePosition: RacePosition.end), ), ), ), @@ -225,7 +227,8 @@ class HomeCharacterActionsView extends GetView { onSelected: (items) => onSelected( items .map( - (x) => x.copyWithInherited(amount: x.amount == 0 ? 1 : x.amount), + (x) => + x.copyWithInherited(amount: x.amount == 0 ? 1 : x.amount), ) .toList(), ), @@ -245,7 +248,7 @@ class HomeCharacterActionsView extends GetView { ChecklistMenuEntry( value: 'countArmor', checked: item.settings.countArmor, - label: Text(S.current.itemSettingsCountArmor), + label: Text(tr.items.settings.countArmor), onChanged: (value) => onSave(false)( item.copyWithInherited( settings: item.settings.copyWith(countArmor: value!), @@ -255,7 +258,7 @@ class HomeCharacterActionsView extends GetView { ChecklistMenuEntry( value: 'countDamage', checked: item.settings.countDamage, - label: Text(S.current.itemSettingsCountDamage), + label: Text(tr.items.settings.countDamage), onChanged: (value) => onSave(false)( item.copyWithInherited( settings: item.settings.copyWith(countDamage: value!), @@ -265,7 +268,7 @@ class HomeCharacterActionsView extends GetView { ChecklistMenuEntry( value: 'countWeight', checked: item.settings.countWeight, - label: Text(S.current.itemSettingsCountWeight), + label: Text(tr.items.settings.countWeight), onChanged: (value) => onSave(false)( item.copyWithInherited( settings: item.settings.copyWith(countWeight: value!), @@ -319,7 +322,7 @@ class HomeCharacterActionsView extends GetView { class ActionsCardList extends GetView with LibraryServiceMixin, RepositoryServiceMixin { const ActionsCardList({ - Key? key, + super.key, required this.route, required this.addPageArguments, required this.cardBuilder, @@ -330,7 +333,7 @@ class ActionsCardList extends GetView this.menuTrailing = const [], this.leading = const [], this.trailing = const [], - }) : super(key: key); + }); final String route; final List leading; @@ -356,17 +359,18 @@ class ActionsCardList extends GetView Widget build(BuildContext context) { return CategorizedList( initiallyExpanded: true, - title: Text(S.current.entityPlural(T)), + title: Text(tr.entityPlural(T)), itemPadding: const EdgeInsets.only(bottom: 8), titleTrailing: [ TextButton.icon( onPressed: () => Get.toNamed( route, arguments: addPageArguments( - onSelected: (items) => library.upsertToCharacter(items, forkBehavior: ForkBehavior.fork), + onSelected: (items) => library.upsertToCharacter(items, + forkBehavior: ForkBehavior.fork), ), ), - label: Text(S.current.addGeneric(S.current.entityPlural(T))), + label: Text(tr.generic.addEntity(tr.entityPlural(T))), icon: const Icon(Icons.add), ), GroupSortMenu( @@ -382,19 +386,20 @@ class ActionsCardList extends GetView children: [ ...list.map( (obj) => _wrapChild( - key: PageStorageKey('type-$T-' + obj.key), + key: PageStorageKey('type-$T-${obj.key}'), child: cardBuilder( obj, onDelete: _confirmDeleteDlg(context, obj, obj.displayName), - onSave: (fork) => (_obj) { - library.upsertToCharacter([_obj], forkBehavior: ForkBehavior.none); + onSave: (fork) => (obj) { + library + .upsertToCharacter([obj], forkBehavior: ForkBehavior.none); }, ), ), ), ], - onReorder: (oldIndex, newIndex) => - controller.updateCharacter(CharacterUtils.reorderByType(char, oldIndex, newIndex)), + onReorder: (oldIndex, newIndex) => controller.updateCharacter( + CharacterUtils.reorderByType(char, oldIndex, newIndex)), ); } @@ -404,12 +409,13 @@ class ActionsCardList extends GetView child: child, ); - void Function() _confirmDeleteDlg(BuildContext context, T object, String name) { + void Function() _confirmDeleteDlg( + BuildContext context, T object, String name) { return () => deleteDialog.confirm( context, DeleteDialogOptions( entityName: name, - entityKind: S.current.entity(T), + entityKind: tr.entity(T), ), () => controller.updateCharacter( CharacterUtils.removeByType(char, [object]), diff --git a/lib/app/modules/Home/views/home_character_journal_view.dart b/lib/app/modules/Home/views/home_character_journal_view.dart index 43dc084a..62aafcfa 100644 --- a/lib/app/modules/Home/views/home_character_journal_view.dart +++ b/lib/app/modules/Home/views/home_character_journal_view.dart @@ -12,13 +12,12 @@ import 'package:dungeon_paper/app/widgets/menus/group_sort_menu.dart'; import 'package:dungeon_paper/app/widgets/molecules/categorized_list.dart'; import 'package:dungeon_paper/core/storage_handler/storage_handler.dart'; import 'package:dungeon_paper/core/utils/list_utils.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; - import 'package:get/get.dart'; class HomeCharacterJournalView extends GetView { - const HomeCharacterJournalView({Key? key}) : super(key: key); + const HomeCharacterJournalView({super.key}); Character get char => controller.current; @@ -47,9 +46,10 @@ class HomeCharacterJournalView extends GetView { children: [ for (final cat in enumerate(char.noteCategories)) CategorizedList( - key: Key('note-category-' + cat.value), + key: Key('note-category-${cat.value}'), initiallyExpanded: true, - title: Text(cat.value.isEmpty ? S.current.noteNoCategory : cat.value), + title: + Text(cat.value.isEmpty ? tr.notes.noCategory : cat.value), titleTrailing: [ GroupSortMenu( index: cat.index, @@ -58,33 +58,37 @@ class HomeCharacterJournalView extends GetView { ), ], onReorder: (oldIndex, newIndex) => controller.updateCharacter( - CharacterUtils.reorderByType(char, oldIndex, newIndex, extraData: cat.value), + CharacterUtils.reorderByType(char, oldIndex, newIndex, + extraData: cat.value), ), children: char.notes .where((note) => note.localizedCategory == cat.value) .map( (note) => Padding( - key: Key('note-' + note.key), + key: Key('note-${note.key}'), padding: const EdgeInsets.symmetric(vertical: 4), child: NoteCard( note: note, reorderablePadding: true, actions: [ EntityEditMenu( - onDelete: confirmDelete(context, note, note.title), + onDelete: + confirmDelete(context, note, note.title), onEdit: () => ModelPages.openNotePage( note: note, - onSave: (_note) { + onSave: (note) { controller.updateCharacter( - CharacterUtils.updateByType(char, [_note]), + CharacterUtils.updateByType( + char, [note]), ); - StorageHandler.instance.create('Notes', note.key, note.toJson()); + StorageHandler.instance + .create('Notes', note.key, note.toJson()); }, ), ), ], - onSave: (_note) => controller.updateCharacter( - CharacterUtils.updateNotes(char, [_note]), + onSave: (note) => controller.updateCharacter( + CharacterUtils.updateNotes(char, [note]), ), ), ), @@ -97,22 +101,25 @@ class HomeCharacterJournalView extends GetView { ); } - void Function() confirmDelete(BuildContext context, T object, String name) { + // TODO use existing confirmDelete + void Function() confirmDelete( + BuildContext context, T object, String name) { return () async { final result = await Get.dialog( AlertDialog( - title: Text(S.current.confirmDeleteTitle(S.current.entity(T))), - content: Text(S.current.confirmDeleteBody(S.current.entity(T), name)), + title: Text(tr.dialogs.confirmations.delete.title(tr.entity(T))), + content: + Text(tr.dialogs.confirmations.delete.body(tr.entity(T), name)), actions: [ ElevatedButton.icon( icon: const Icon(Icons.close), - label: Text(S.current.cancel), + label: Text(tr.generic.cancel), onPressed: () => Get.back(result: false), style: ButtonThemes.primaryElevated(context), ), ElevatedButton.icon( icon: const Icon(Icons.delete), - label: Text(S.current.remove), + label: Text(tr.generic.remove), onPressed: () => Get.back(result: true), style: ButtonThemes.errorElevated(context), ), @@ -130,7 +137,8 @@ class HomeCharacterJournalView extends GetView { break; case Spell: controller.updateCharacter( - char.copyWith(spells: removeByKey(char.spells, [object as Spell])), + char.copyWith( + spells: removeByKey(char.spells, [object as Spell])), ); break; case Item: diff --git a/lib/app/modules/Home/views/home_character_view.dart b/lib/app/modules/Home/views/home_character_view.dart index d1eeb2ea..1ad5ae82 100644 --- a/lib/app/modules/Home/views/home_character_view.dart +++ b/lib/app/modules/Home/views/home_character_view.dart @@ -10,15 +10,16 @@ import 'package:dungeon_paper/app/widgets/molecules/ability_scores_grid.dart'; import 'package:dungeon_paper/core/dw_icons.dart'; import 'package:dungeon_paper/core/utils/builder_utils.dart'; import 'package:dungeon_paper/core/utils/math_utils.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'local_widgets/home_character_dynamic_cards.dart'; import 'local_widgets/home_character_header_view.dart'; import 'local_widgets/home_character_hp_xp_view.dart'; -class HomeCharacterView extends GetView with HomeCharacterPaddingMixin { - const HomeCharacterView({Key? key}) : super(key: key); +class HomeCharacterView extends GetView + with HomeCharacterPaddingMixin { + const HomeCharacterView({super.key}); @override Widget build(BuildContext context) { @@ -45,7 +46,7 @@ class HomeCharacterView extends GetView with HomeCharacterPadd const SizedBox(height: 8), pad(Text( char.displayName, - textScaleFactor: 1.4, + textScaler: const TextScaler.linear(1.4), textAlign: TextAlign.center, )), CharacterSubtitle(character: char), @@ -69,7 +70,7 @@ class HomeCharacterView extends GetView with HomeCharacterPadd icon: const Icon(DwIcons.swords), // visualDensity: VisualDensity.compact, label: char.damageDice.toString(), - tooltip: S.current.damageDice, + tooltip: tr.character.data.damageDice, onPressed: () => Get.dialog( DamageDiceDialog( damage: char.stats.damageDice, @@ -85,7 +86,7 @@ class HomeCharacterView extends GetView with HomeCharacterPadd ), const SizedBox(width: 8), PrimaryChip( - tooltip: S.current.armor, + tooltip: tr.armor.title, icon: const Icon(DwIcons.armor), // visualDensity: VisualDensity.compact, label: char.armor.toString(), @@ -120,7 +121,8 @@ class HomeCharacterView extends GetView with HomeCharacterPadd children: [ Expanded( child: ElevatedButton.icon( - onPressed: () => DiceUtils.openRollDialog(char.rollButtons[0].diceFor(char)), + onPressed: () => DiceUtils.openRollDialog( + char.rollButtons[0].diceFor(char)), style: ButtonThemes.primaryElevated(context), label: Text(char.rollButtons[0].label), icon: const Icon(DwIcons.dice_d6), @@ -129,7 +131,8 @@ class HomeCharacterView extends GetView with HomeCharacterPadd const SizedBox(width: 16), Expanded( child: ElevatedButton.icon( - onPressed: () => DiceUtils.openRollDialog(char.rollButtons[1].diceFor(char)), + onPressed: () => DiceUtils.openRollDialog( + char.rollButtons[1].diceFor(char)), style: ButtonThemes.primaryElevated(context), label: Text(char.rollButtons[1].label), icon: const Icon(DwIcons.dice_d6), @@ -144,7 +147,8 @@ class HomeCharacterView extends GetView with HomeCharacterPadd } } -class HomeCharacterLayout extends StatelessWidget with HomeCharacterPaddingMixin { +class HomeCharacterLayout extends StatelessWidget + with HomeCharacterPaddingMixin { const HomeCharacterLayout({ super.key, required this.leftCol, @@ -194,7 +198,10 @@ class HomeCharacterLayout extends StatelessWidget with HomeCharacterPaddingMixin if (!scrollable) { return Column( - children: [for (final i in range(builder.itemCount)) builder.itemBuilder(context, i)], + children: [ + for (final i in range(builder.itemCount)) + builder.itemBuilder(context, i) + ], ); } diff --git a/lib/app/modules/Home/views/home_fab.dart b/lib/app/modules/Home/views/home_fab.dart index fa46e45d..5d8cf537 100644 --- a/lib/app/modules/Home/views/home_fab.dart +++ b/lib/app/modules/Home/views/home_fab.dart @@ -3,7 +3,7 @@ import 'package:dungeon_paper/app/data/services/character_service.dart'; import 'package:dungeon_paper/app/model_utils/character_utils.dart'; import 'package:dungeon_paper/app/model_utils/model_pages.dart'; import 'package:dungeon_paper/app/widgets/atoms/advanced_floating_action_button.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; class HomeFAB extends StatefulWidget { @@ -50,7 +50,7 @@ class _HomeFABState extends State with CharacterServiceMixin { scale: inPageRange ? 1.0 : 0.0, duration: duration, child: Text( - S.current.createGeneric(Note), + tr.generic.createEntity(tr.entity(Note)), ), ), icon: AnimatedScale( diff --git a/lib/app/modules/Home/views/home_loader_view.dart b/lib/app/modules/Home/views/home_loader_view.dart index 11254feb..b8553157 100644 --- a/lib/app/modules/Home/views/home_loader_view.dart +++ b/lib/app/modules/Home/views/home_loader_view.dart @@ -3,25 +3,24 @@ import 'package:dungeon_paper/app/modules/Home/views/home_character_view.dart'; import 'package:dungeon_paper/app/modules/Home/views/local_widgets/home_character_header_view.dart'; import 'package:dungeon_paper/app/widgets/atoms/character_avatar.dart'; import 'package:dungeon_paper/core/utils/math_utils.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; - import 'package:get/get.dart'; import 'package:skeleton_loader/skeleton_loader.dart'; class HomeLoaderView extends GetView with LoadingServiceMixin { - const HomeLoaderView({Key? key}) : super(key: key); + const HomeLoaderView({super.key}); String get title { if (loadingService.loadingUser) { - return S.current.loadingUser; + return tr.loading.user; } if (loadingService.loadingCharacters) { - return S.current.loadingCharacters; + return tr.loading.characters; } - return S.current.loadingGeneral; + return tr.loading.general; } @override @@ -29,11 +28,14 @@ class HomeLoaderView extends GetView with LoadingServiceMixin { final theme = Theme.of(context); final colorScheme = theme.colorScheme; final brightness = theme.brightness; - final skeletonColor = - brightness == Brightness.light ? theme.cardColor.withOpacity(0.65) : colorScheme.surfaceVariant; + final skeletonColor = brightness == Brightness.light + ? theme.cardColor.withOpacity(0.65) + : colorScheme.surfaceVariant; final skeletonHighlightColor = brightness == Brightness.light - ? Color.alphaBlend(theme.cardColor.withOpacity(0.65), colorScheme.surfaceTint.withOpacity(0.5)) - : Color.alphaBlend(theme.cardColor.withOpacity(0.65), colorScheme.surfaceTint); + ? Color.alphaBlend(theme.cardColor.withOpacity(0.65), + colorScheme.surfaceTint.withOpacity(0.5)) + : Color.alphaBlend( + theme.cardColor.withOpacity(0.65), colorScheme.surfaceTint); return SingleChildScrollView( child: SkeletonLoader( @@ -159,7 +161,8 @@ class HomeLoaderView extends GetView with LoadingServiceMixin { children: [ for (final _ in range(3)) Padding( - padding: const EdgeInsets.symmetric(horizontal: 2).copyWith(bottom: 4), + padding: const EdgeInsets.symmetric(horizontal: 2) + .copyWith(bottom: 4), child: Container( height: 56, width: 118, diff --git a/lib/app/modules/Home/views/home_nav_bar.dart b/lib/app/modules/Home/views/home_nav_bar.dart index 4cd3b32a..69309c41 100644 --- a/lib/app/modules/Home/views/home_nav_bar.dart +++ b/lib/app/modules/Home/views/home_nav_bar.dart @@ -1,13 +1,13 @@ import 'package:dungeon_paper/core/dw_icons.dart'; import 'package:dungeon_paper/core/utils/list_utils.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; class HomeNavBar extends StatefulWidget { const HomeNavBar({ - Key? key, + super.key, required this.pageController, - }) : super(key: key); + }); final PageController pageController; @@ -34,12 +34,14 @@ class _CharacterHomeNavBarState extends State { @override Widget build(BuildContext context) { - final currentIndex = widget.pageController.positions.length == 1 ? widget.pageController.page?.round() ?? 1 : 1; + final currentIndex = widget.pageController.positions.length == 1 + ? widget.pageController.page?.round() ?? 1 + : 1; final items = { - S.current.navActions: const Icon(DwIcons.hand_rock), - S.current.navCharacter: const Icon(Icons.person), - S.current.navJournal: const Icon(DwIcons.scroll_quill), + tr.nav.actions: const Icon(DwIcons.hand_rock), + tr.nav.character: const Icon(Icons.person), + tr.nav.journal: const Icon(DwIcons.scroll_quill), }; return Material( @@ -118,17 +120,17 @@ class _NavItem extends StatelessWidget { clipper: const ShapeBorderClipper(shape: StadiumBorder()), child: AnimatedContainer( duration: duration, + width: selected ? 60 : 40, + color: selected ? selectedColor : Colors.transparent, child: Padding( padding: const EdgeInsets.symmetric(vertical: 3), child: IconTheme( - child: icon, data: IconThemeData( color: selected ? selectedFgColor : unselectedFgColor, ), + child: icon, ), ), - width: selected ? 60 : 40, - color: selected ? selectedColor : Colors.transparent, ), ), const SizedBox(height: 2), diff --git a/lib/app/modules/Home/views/home_view.dart b/lib/app/modules/Home/views/home_view.dart index 4ecd2c1b..eec56acb 100644 --- a/lib/app/modules/Home/views/home_view.dart +++ b/lib/app/modules/Home/views/home_view.dart @@ -9,9 +9,8 @@ import 'package:dungeon_paper/app/routes/app_pages.dart'; import 'package:dungeon_paper/app/themes/button_themes.dart'; import 'package:dungeon_paper/app/widgets/atoms/icon_span.dart'; import 'package:dungeon_paper/app/widgets/atoms/page_controller_fractional_box.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; - import 'package:get/get.dart'; // import '../../../widgets/atoms/debug_menu.dart'; @@ -20,7 +19,8 @@ import 'home_character_view.dart'; import 'home_fab.dart'; import 'home_nav_bar.dart'; -class HomeView extends GetView with UserServiceMixin, LoadingServiceMixin, CharacterServiceMixin { +class HomeView extends GetView + with UserServiceMixin, LoadingServiceMixin, CharacterServiceMixin { const HomeView({super.key}); @override @@ -45,14 +45,18 @@ class HomeView extends GetView with UserServiceMixin, LoadingS : const HomeEmptyState(); }, ), - floatingActionButton: Obx(() => maybeChar != null ? const HomeFAB() : const SizedBox.shrink()), + floatingActionButton: Obx( + () => maybeChar != null ? const HomeFAB() : const SizedBox.shrink()), bottomNavigationBar: Obx( - () => maybeChar != null ? HomeNavBar(pageController: controller.pageController) : const SizedBox.shrink(), + () => maybeChar != null + ? HomeNavBar(pageController: controller.pageController) + : const SizedBox.shrink(), ), ); } - PageControllerFractionalBox _fractionalSizedBox(Widget child) => PageControllerFractionalBox( + PageControllerFractionalBox _fractionalSizedBox(Widget child) => + PageControllerFractionalBox( controller: controller.pageController, child: child, ); @@ -61,7 +65,8 @@ class HomeView extends GetView with UserServiceMixin, LoadingS debugPrint('afterFirstLoad: ${loadingService.afterFirstLoad}, ' 'loadingUser: ${loadingService.loadingUser}, ' 'loadingCharacters: ${loadingService.loadingCharacters}'); - return !loadingService.afterFirstLoad && (loadingService.loadingUser || loadingService.loadingCharacters); + return !loadingService.afterFirstLoad && + (loadingService.loadingUser || loadingService.loadingCharacters); } } @@ -83,7 +88,8 @@ class HomeEmptyState extends StatelessWidget with UserServiceMixin { child: Card( margin: const EdgeInsets.all(32), child: Padding( - padding: const EdgeInsets.symmetric(vertical: 24, horizontal: 16), + padding: const EdgeInsets.symmetric( + vertical: 24, horizontal: 16), child: Column( children: [ RichText( @@ -91,20 +97,21 @@ class HomeEmptyState extends StatelessWidget with UserServiceMixin { text: TextSpan( children: [ IconSpan(context, icon: Icons.person, size: 24), - TextSpan(text: ' ${S.current.homeEmptyStateLoginTitle}'), + TextSpan( + text: ' ${tr.home.emptyState.guest.title}'), ], style: textTheme.titleLarge, ), ), const SizedBox(height: 16), Text( - S.current.homeEmptyStateLoginSubtitle, + tr.home.emptyState.guest.subtitle, style: textTheme.titleMedium, textAlign: TextAlign.center, ), const SizedBox(height: 16), ElevatedButton.icon( - label: Text(S.current.signinButton), + label: Text(tr.auth.login.button), icon: const Icon(Icons.login), onPressed: () => Get.toNamed(Routes.login), style: ButtonThemes.primaryElevated(context), @@ -118,19 +125,19 @@ class HomeEmptyState extends StatelessWidget with UserServiceMixin { const SizedBox(height: 16), ], Text( - S.current.homeEmptyStateTitle, + tr.home.emptyState.title, style: textTheme.titleLarge, textAlign: TextAlign.center, ), const SizedBox(height: 16), Text( - S.current.homeEmptyStateSubtitle, + tr.home.emptyState.subtitle, style: textTheme.titleMedium, textAlign: TextAlign.center, ), const SizedBox(height: 16), ElevatedButton.icon( - label: Text(S.current.createGeneric(S.current.entity(Character))), + label: Text(tr.generic.createEntity(tr.entity(Character))), icon: const Icon(Icons.person_add), onPressed: () => Get.toNamed(Routes.createCharacter), ), diff --git a/lib/app/modules/Home/views/local_widgets/home_character_actions_filters.dart b/lib/app/modules/Home/views/local_widgets/home_character_actions_filters.dart index 5347039b..8778fda0 100644 --- a/lib/app/modules/Home/views/local_widgets/home_character_actions_filters.dart +++ b/lib/app/modules/Home/views/local_widgets/home_character_actions_filters.dart @@ -3,15 +3,15 @@ import 'package:dungeon_paper/app/data/models/move.dart'; import 'package:dungeon_paper/app/data/models/spell.dart'; import 'package:dungeon_paper/app/widgets/atoms/checklist_menu_entry.dart'; import 'package:dungeon_paper/app/widgets/atoms/menu_button.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; class HomeCharacterActionsFilters extends StatelessWidget { const HomeCharacterActionsFilters({ - Key? key, + super.key, required this.hidden, required this.onUpdateHidden, - }) : super(key: key); + }); final Set hidden; final void Function(Set filters) onUpdateHidden; @@ -27,10 +27,12 @@ class HomeCharacterActionsFilters extends StatelessWidget { checked: !hidden.contains(type), onChanged: (show) { onUpdateHidden( - !show! ? {...hidden, type} : {...hidden.where((element) => element != type)}, + !show! + ? {...hidden, type} + : {...hidden.where((element) => element != type)}, ); }, - label: Expanded(child: Text(S.current.entityPlural(type))), + label: Expanded(child: Text(tr.entityPlural(type))), ), ) .toList(), diff --git a/lib/app/modules/Home/views/local_widgets/home_character_actions_summary.dart b/lib/app/modules/Home/views/local_widgets/home_character_actions_summary.dart index 4fefba54..284c851c 100644 --- a/lib/app/modules/Home/views/local_widgets/home_character_actions_summary.dart +++ b/lib/app/modules/Home/views/local_widgets/home_character_actions_summary.dart @@ -4,7 +4,7 @@ import 'package:dungeon_paper/app/widgets/chips/primary_chip.dart'; import 'package:dungeon_paper/app/widgets/dialogs/coins_dialog.dart'; import 'package:dungeon_paper/app/widgets/dialogs/load_dialog.dart'; import 'package:dungeon_paper/core/dw_icons.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:intl/intl.dart'; @@ -13,8 +13,8 @@ import 'home_character_actions_filters.dart'; class HomeCharacterActionsSummary extends GetView { const HomeCharacterActionsSummary({ - Key? key, - }) : super(key: key); + super.key, + }); Character get char => controller.current; @@ -33,8 +33,9 @@ class HomeCharacterActionsSummary extends GetView { PrimaryChip( // visualDensity: VisualDensity.compact, icon: const Icon(DwIcons.dumbbell, size: 16), - label: S.current.actionSummaryChipLoad(char.currentLoad, char.maxLoad), - tooltip: S.current.maxLoad, + label: tr.home.summary.load + .label(char.currentLoad, char.maxLoad), + tooltip: tr.home.summary.load.tooltip, onPressed: () => Get.dialog( LoadDialog( load: char.stats.load, @@ -50,14 +51,15 @@ class HomeCharacterActionsSummary extends GetView { PrimaryChip( // visualDensity: VisualDensity.compact, icon: const Icon(DwIcons.coin_stack, size: 16), - label: S.current.actionSummaryChipCoins( + label: tr.home.summary.coins.label( NumberFormat.compact().format(char.coins), ), - tooltip: S.current.coins, + tooltip: tr.home.summary.coins.tooltip, onPressed: () => Get.dialog( CoinsDialog( coins: char.coins, - onChanged: (coins) => controller.updateCharacter(char.copyWith(coins: coins)), + onChanged: (coins) => controller + .updateCharacter(char.copyWith(coins: coins)), ), ), ), @@ -70,7 +72,8 @@ class HomeCharacterActionsSummary extends GetView { controller.updateCharacter( char.copyWith( settings: char.settings.copyWith( - actionCategories: char.settings.actionCategories.copyWithInherited( + actionCategories: + char.settings.actionCategories.copyWithInherited( hidden: filters, ), ), 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 73e942c5..6985d7e6 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 @@ -21,358 +21,397 @@ 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/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../expanded_card_dialog_view.dart'; import 'horizontal_list_card_view.dart'; -class HomeCharacterDynamicCards extends GetView with LibraryServiceMixin { - const HomeCharacterDynamicCards({Key? key}) : super(key: key); +class HomeCharacterDynamicCards extends GetView + with LibraryServiceMixin { + const HomeCharacterDynamicCards({super.key}); - List get moves => (controller.maybeCurrent?.moves ?? []).where((m) => m.favorite).toList(); - List get spells => (controller.maybeCurrent?.spells ?? []).where((m) => m.prepared).toList(); - List get items => (controller.maybeCurrent?.items ?? []).where((m) => m.equipped).toList(); - List get notes => (controller.maybeCurrent?.notes ?? []).where((n) => n.favorite).toList(); + List get moves => (controller.maybeCurrent?.moves ?? []) + .where((m) => m.favorite) + .toList(); + List get spells => (controller.maybeCurrent?.spells ?? []) + .where((m) => m.prepared) + .toList(); + List get items => (controller.maybeCurrent?.items ?? []) + .where((m) => m.equipped) + .toList(); + List get notes => (controller.maybeCurrent?.notes ?? []) + .where((n) => n.favorite) + .toList(); @override Widget build(BuildContext context) { const cardSize = Size(210, 151); final maxContentHeight = MediaQuery.of(context).size.height - 250; return Obx( - () => Column(mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - // - // NOTES - // - if (notes.isNotEmpty) ...[ - const SizedBox(height: 10), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Text(S.current.dynamicCategoriesNotes), - ), - ], - HorizontalCardListView( - cardSize: cardSize, - items: notes, - cardBuilder: (context, note, index, onTap) => Obx( - () => NoteCardMini( - note: notes[index], - onTap: onTap, - onSave: (_note) => controller.updateCharacter( - CharacterUtils.updateNotes(controller.current, [_note]), + () => Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // + // NOTES + // + 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) => Obx( + () => NoteCardMini( + note: notes[index], + onTap: onTap, + onSave: (note) => controller.updateCharacter( + CharacterUtils.updateNotes(controller.current, [note]), + ), + ), + ), + expandedCardBuilder: (context, note, index) => Obx( + () { + return notes.isNotEmpty && index < notes.length + ? NoteCard( + maxContentHeight: maxContentHeight, + expandable: false, + initiallyExpanded: true, + note: notes[index], + actions: [ + EntityEditMenu( + onEdit: () => ModelPages.openNotePage( + note: notes[index], + onSave: (note) => controller.updateCharacter( + CharacterUtils.updateNotes( + controller.current, [note]), + ), + ), + onDelete: _delete( + context, + note, + note.title, + () => controller.updateCharacter( + CharacterUtils.removeNotes( + controller.current, [note]), + ), + ), + ), + ], + onSave: (note) { + controller.updateCharacter( + CharacterUtils.updateNotes( + controller.current, [note]), + ); + if (!note.favorite) { + Get.back(); + } + }, + ) + : const SizedBox.shrink(); + }, ), ), - ), - expandedCardBuilder: (context, note, index) => Obx( - () { - return notes.isNotEmpty && index < notes.length - ? NoteCard( - maxContentHeight: maxContentHeight, - expandable: false, - initiallyExpanded: true, - note: notes[index], - actions: [ - EntityEditMenu( - onEdit: () => ModelPages.openNotePage( - note: notes[index], - onSave: (note) => controller.updateCharacter( - CharacterUtils.updateNotes(controller.current, [note]), - ), - ), - onDelete: _delete( - context, - note, - note.title, - () => controller.updateCharacter( - CharacterUtils.removeNotes(controller.current, [note]), + // + // MOVES + // + if (moves.isNotEmpty) + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Text(tr.home.categories.moves), + ), + Builder(builder: (context) { + final raceCardMini = controller.current.race.favorite + ? RaceCardMini( + race: controller.current.race, + onTap: () => Get.dialog( + ExpandedCardDialogView( + // heroTag: getKeyFor(item.value), + heroTag: null, + builder: (context) => RaceCard( + maxContentHeight: maxContentHeight, + expandable: false, + initiallyExpanded: true, + race: controller.current.race, + actions: [ + EntityEditMenu( + onEdit: () => ModelPages.openRacePage( + abilityScores: + controller.current.abilityScores, + race: controller.current.race, + onSave: (race) => controller.updateCharacter( + controller.current.copyWith(race: race), + ), + ), + onDelete: null, + ), + ], + onSave: (race) => controller.updateCharacter( + controller.current.copyWith(race: race), ), ), ), - ], - onSave: (_note) { - controller.updateCharacter( - CharacterUtils.updateNotes(controller.current, [_note]), - ); - if (!_note.favorite) { - Get.back(); - } - }, + ), + onSave: (race) => controller.updateCharacter( + controller.current.copyWith(race: race), + ), ) - : const SizedBox.shrink(); - }, - ), - ), - // - // MOVES - // - if (moves.isNotEmpty) - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Text(S.current.dynamicCategoriesMoves), - ), - Builder(builder: (context) { - final raceCardMini = controller.current.race.favorite - ? RaceCardMini( - race: controller.current.race, - onTap: () => Get.dialog( - ExpandedCardDialogView( - // heroTag: getKeyFor(item.value), - heroTag: null, - builder: (context) => RaceCard( + : null; + return HorizontalCardListView( + cardSize: cardSize, + items: moves, + cardBuilder: (context, move, index, onTap) => Obx( + () => MoveCardMini( + move: moves[index], + onTap: onTap, + onSave: (move) => controller.updateCharacter( + CharacterUtils.updateMoves(controller.current, [move]), + ), + abilityScores: controller.current.abilityScores, + ), + ), + expandedCardBuilder: (context, move, index) => Obx( + () => moves.isNotEmpty && index < moves.length + ? MoveCard( + maxContentHeight: maxContentHeight, + expandable: false, + initiallyExpanded: true, + move: moves[index], + abilityScores: controller.current.abilityScores, + actions: [ + EntityEditMenu( + onEdit: () => ModelPages.openMovePage( + abilityScores: controller.current.abilityScores, + move: moves[index], + onSave: (move) => library.upsertToCharacter( + [move], + forkBehavior: ForkBehavior.increaseVersion), + ), + onDelete: _delete( + context, + move, + move.name, + () => controller.updateCharacter( + CharacterUtils.removeMoves( + controller.current, [move]), + ), + ), + ), + ], + onSave: (move) { + controller.updateCharacter( + CharacterUtils.updateMoves( + controller.current, [move]), + ); + if (!move.favorite) { + Get.back(); + } + }, + ) + : const SizedBox.shrink(), + ), + leading: raceCardMini != null && + controller.current.settings.racePosition == + RacePosition.start + ? [raceCardMini] + : [], + trailing: raceCardMini != null && + controller.current.settings.racePosition == + RacePosition.end + ? [raceCardMini] + : [], + ); + }), + // + // SPELLS + // + if (spells.isNotEmpty) ...[ + const SizedBox(height: 10), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Text(tr.home.categories.spells), + ), + ], + HorizontalCardListView( + cardSize: cardSize, + items: spells, + cardBuilder: (context, spell, index, onTap) => Obx( + () => SpellCardMini( + spell: spells[index], + onTap: onTap, + onSave: (spell) => controller.updateCharacter( + CharacterUtils.updateSpells(controller.current, [spell]), + ), + abilityScores: controller.current.abilityScores, + ), + ), + expandedCardBuilder: (context, spell, index) => Obx( + () => spells.isNotEmpty && index < spells.length + ? SpellCard( maxContentHeight: maxContentHeight, expandable: false, initiallyExpanded: true, - race: controller.current.race, + spell: spells[index], + abilityScores: controller.current.abilityScores, actions: [ EntityEditMenu( - onEdit: () => ModelPages.openRacePage( + onEdit: () => ModelPages.openSpellPage( abilityScores: controller.current.abilityScores, - race: controller.current.race, - onSave: (_race) => controller.updateCharacter( - controller.current.copyWith(race: _race), + classKeys: spells[index].classKeys, + spell: spells[index], + onSave: (spell) => controller.updateCharacter( + CharacterUtils.updateSpells( + controller.current, [spell]), + ), + ), + onDelete: _delete( + context, + spell, + spell.name, + () => controller.updateCharacter( + CharacterUtils.removeSpells( + controller.current, [spell]), ), ), - onDelete: null, ), ], - onSave: (_race) => controller.updateCharacter( - controller.current.copyWith(race: _race), - ), - ), - ), + onSave: (spell) { + controller.updateCharacter( + CharacterUtils.updateSpells( + controller.current, [spell]), + ); + if (!spell.prepared) { + Get.back(); + } + }, + ) + : const SizedBox.shrink(), + ), + ), + // + // ITEMS + // + 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) => Obx( + () => ItemCardMini( + item: items[index], + onTap: onTap, + onSave: (item) => controller.updateCharacter( + CharacterUtils.updateItems(controller.current, [item]), ), - onSave: (_race) => controller.updateCharacter( - controller.current.copyWith(race: _race), - ), - ) - : null; - return HorizontalCardListView( - cardSize: cardSize, - items: moves, - cardBuilder: (context, move, index, onTap) => Obx( - () => MoveCardMini( - move: moves[index], - onTap: onTap, - onSave: (_move) => controller.updateCharacter( - CharacterUtils.updateMoves(controller.current, [_move]), ), - abilityScores: controller.current.abilityScores, ), - ), - expandedCardBuilder: (context, move, index) => Obx( - () => moves.isNotEmpty && index < moves.length - ? MoveCard( - maxContentHeight: maxContentHeight, - expandable: false, - initiallyExpanded: true, - move: moves[index], - abilityScores: controller.current.abilityScores, - actions: [ - EntityEditMenu( - onEdit: () => ModelPages.openMovePage( - abilityScores: controller.current.abilityScores, - move: moves[index], - onSave: (move) => - library.upsertToCharacter([move], forkBehavior: ForkBehavior.increaseVersion), - ), - onDelete: _delete( - context, - move, - move.name, - () => controller.updateCharacter( - CharacterUtils.removeMoves(controller.current, [move]), + expandedCardBuilder: (context, item, index) => Obx( + () => items.isNotEmpty && index < items.length + ? ItemCard( + maxContentHeight: maxContentHeight, + expandable: false, + initiallyExpanded: true, + item: items[index], + actions: [ + EntityEditMenu( + onEdit: () => ModelPages.openItemPage( + item: items[index], + onSave: (item) => controller.updateCharacter( + CharacterUtils.updateItems( + controller.current, [item]), + ), ), - ), - ), - ], - onSave: (_move) { - controller.updateCharacter( - CharacterUtils.updateMoves(controller.current, [_move]), - ); - if (!_move.favorite) { - Get.back(); - } - }, - ) - : const SizedBox.shrink(), - ), - leading: raceCardMini != null && controller.current.settings.racePosition == RacePosition.start - ? [raceCardMini] - : [], - trailing: raceCardMini != null && controller.current.settings.racePosition == RacePosition.end - ? [raceCardMini] - : [], - ); - }), - // - // SPELLS - // - if (spells.isNotEmpty) ...[ - const SizedBox(height: 10), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Text(S.current.dynamicCategoriesSpells), - ), - ], - HorizontalCardListView( - cardSize: cardSize, - items: spells, - cardBuilder: (context, spell, index, onTap) => Obx( - () => SpellCardMini( - spell: spells[index], - onTap: onTap, - onSave: (_spell) => controller.updateCharacter( - CharacterUtils.updateSpells(controller.current, [_spell]), - ), - abilityScores: controller.current.abilityScores, - ), - ), - expandedCardBuilder: (context, spell, index) => Obx( - () => spells.isNotEmpty && index < spells.length - ? SpellCard( - maxContentHeight: maxContentHeight, - expandable: false, - initiallyExpanded: true, - spell: spells[index], - abilityScores: controller.current.abilityScores, - actions: [ - EntityEditMenu( - onEdit: () => ModelPages.openSpellPage( - 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, - () => controller.updateCharacter( - CharacterUtils.removeSpells(controller.current, [spell]), - ), - ), - ), - ], - onSave: (_spell) { - controller.updateCharacter( - CharacterUtils.updateSpells(controller.current, [_spell]), - ); - if (!_spell.prepared) { - Get.back(); - } - }, - ) - : const SizedBox.shrink(), - ), - ), - // - // ITEMS - // - if (items.isNotEmpty) ...[ - const SizedBox(height: 10), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Text(S.current.dynamicCategoriesItems), - ), - ], - HorizontalCardListView( - cardSize: cardSize, - items: items, - cardBuilder: (context, item, index, onTap) => Obx( - () => ItemCardMini( - item: items[index], - onTap: onTap, - onSave: (_item) => controller.updateCharacter( - CharacterUtils.updateItems(controller.current, [_item]), - ), - ), - ), - expandedCardBuilder: (context, item, index) => Obx( - () => items.isNotEmpty && index < items.length - ? ItemCard( - maxContentHeight: maxContentHeight, - expandable: false, - initiallyExpanded: true, - item: items[index], - actions: [ - EntityEditMenu( - onEdit: () => ModelPages.openItemPage( - item: items[index], - onSave: (item) => controller.updateCharacter( - CharacterUtils.updateItems(controller.current, [item]), - ), - ), - onDelete: _delete( - context, - item, - item.name, - () => controller.updateCharacter( - CharacterUtils.removeItems(controller.current, [item]), - ), - ), - leading: [ - ChecklistMenuEntry( - value: 'countArmor', - checked: item.settings.countArmor, - label: Text(S.current.itemSettingsCountArmor), - 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(S.current.itemSettingsCountDamage), - 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(S.current.itemSettingsCountWeight), - onChanged: (value) => controller.updateCharacter( - CharacterUtils.updateItems(controller.current, [ - item.copyWithInherited( - settings: item.settings.copyWith(countWeight: value!), - ) - ]), + onDelete: _delete( + context, + item, + item.name, + () => 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) { - Get.back(); - } - }, - ) - : const SizedBox.shrink(), - ), - ), - ]), + onSave: (item) { + controller.updateCharacter( + CharacterUtils.updateItems( + controller.current, [item]), + ); + if (!item.equipped) { + Get.back(); + } + }, + ) + : const SizedBox.shrink(), + ), + ), + ]), ); } - void Function() _delete(BuildContext context, T item, String itemName, void Function() onRemove) { + void Function() _delete( + BuildContext context, T item, String itemName, void Function() onRemove) { return () => deleteDialog.confirm( context, - DeleteDialogOptions(entityName: itemName, entityKind: S.current.entity(T)), + DeleteDialogOptions(entityName: itemName, entityKind: tr.entity(T)), () { onRemove(); Get.back(); 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 810a1598..7b7ffab6 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 @@ -13,12 +13,12 @@ import 'package:dungeon_paper/app/widgets/dialogs/character_bonds_flags_dialog.d 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'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; class HomeCharacterExtras extends GetView { - const HomeCharacterExtras({Key? key}) : super(key: key); + const HomeCharacterExtras({super.key}); @override Widget build(BuildContext context) { @@ -27,66 +27,56 @@ class HomeCharacterExtras extends GetView { children: [ MenuButton( icon: const Icon(Icons.person), - tooltip: S.current.characterMenu, + tooltip: tr.home.menu.character.tooltip, items: [ MenuEntry( value: 'name_photo', icon: const Icon(Icons.photo), - label: Text(S.current.basicInformationTitle), + label: Text(tr.home.menu.character.basicInfo), onSelect: _openBasicInfo, ), - // MenuEntry( - // value: 'bio', - // icon: const Icon(Icons.text_snippet), - // label: Text(S.current.characterBioDialogTitle), - // onSelect: _openBio, - // ), MenuEntry( value: 'ability_scores', icon: const Icon(Icons.format_list_numbered_rtl), - label: Text(S.current.characterRollsTitle), + label: Text(tr.home.menu.character.abilityScores), onSelect: _openAbilityScores, ), MenuEntry( value: 'class', icon: Icon(CharacterClass.genericIcon), - label: Text(S.current.changeGeneric(S.current.entity(CharacterClass))), + label: Text(tr.generic.changeEntity(tr.entity(CharacterClass))), onSelect: _openCharClass, ), MenuEntry( value: 'race', icon: Icon(Race.genericIcon), - label: Text(S.current.changeGeneric(S.current.entity(Race))), + label: Text(tr.generic.changeEntity(tr.entity(Race))), onSelect: _openRace, ), MenuEntry( value: 'roll_buttons', icon: const Icon(DwIcons.dice_d6), - label: Text(S.current.customRollButtons), + label: Text(tr.home.menu.character.customRolls), onSelect: _openRollButtons, ), MenuEntry( value: 'theme', icon: const Icon(Icons.brush), - label: Text(S.current.characterSelectTheme), + label: Text(tr.home.menu.character.theme), onSelect: _openThemeSelect, ), ], ), - // IconButton( - // onPressed: _openAbilityScores, - // icon: const Icon(Icons.format_list_numbered_rtl), - // tooltip: S.current.characterRollsTitle, - // ), IconButton( icon: const Icon(Icons.text_snippet), - tooltip: S.current.characterBioDialogTitle, + tooltip: tr.home.menu.bio, onPressed: _openBio, ), Obx( () => IconButton( onPressed: _openBondsFlags, - icon: Transform.scale(child: const Icon(Icons.handshake), scaleX: -1), + icon: + Transform.scale(scaleX: -1, child: const Icon(Icons.handshake)), tooltip: SessionMark.categoryTitle( bonds: controller.maybeCurrent?.bonds ?? [], flags: controller.maybeCurrent?.flags ?? [], @@ -96,12 +86,12 @@ class HomeCharacterExtras extends GetView { IconButton( onPressed: _openDebilities, icon: const Icon(Icons.personal_injury), - tooltip: S.current.characterDebilitiesDialogTitle, + tooltip: tr.home.menu.debilities, ), IconButton( onPressed: null, icon: const Icon(Icons.groups), - tooltip: S.current.entity(S.current.entityPlural(Campaign)), + tooltip: tr.entityPlural(Campaign), ), ], ); @@ -111,8 +101,8 @@ class HomeCharacterExtras extends GetView { Routes.abilityScores, arguments: AbilityScoresFormArguments( abilityScores: controller.current.abilityScores, - onChanged: (abilityScores) => - controller.updateCharacter(controller.current.copyWith(abilityScores: abilityScores)), + onChanged: (abilityScores) => controller.updateCharacter( + controller.current.copyWith(abilityScores: abilityScores)), ), preventDuplicates: false, ); @@ -138,9 +128,10 @@ class HomeCharacterExtras extends GetView { ModelPages.openRacesList( character: controller.current, preSelection: controller.current.race, - onSelected: (_race) => controller.updateCharacter( + onSelected: (race) => controller.updateCharacter( controller.current.copyWithInherited( - race: _race.copyWithInherited(favorite: controller.current.race.favorite), + race: race.copyWithInherited( + favorite: controller.current.race.favorite), ), ), ); @@ -149,10 +140,10 @@ class HomeCharacterExtras extends GetView { void _openCharClass() { ModelPages.openCharacterClassesList( character: controller.current, - onSelected: (_cls) => controller.updateCharacter( + onSelected: (cls) => controller.updateCharacter( // TODO add a reset dialog to confirm + ask what to reset: moves, spells, alignment, rac controller.current.copyWithInherited( - characterClass: _cls, + characterClass: cls, ), ), ); @@ -172,7 +163,8 @@ class HomeCharacterExtras extends GetView { character: controller.current, onChanged: (rollButtons) => controller.updateCharacter( controller.current.copyWith( - settings: controller.current.settings.copyWith(rollButtons: rollButtons), + settings: + controller.current.settings.copyWith(rollButtons: rollButtons), ), ), ), diff --git a/lib/app/modules/Home/views/local_widgets/horizontal_list_card_view.dart b/lib/app/modules/Home/views/local_widgets/horizontal_list_card_view.dart index 104aac77..d8d6e7f3 100644 --- a/lib/app/modules/Home/views/local_widgets/horizontal_list_card_view.dart +++ b/lib/app/modules/Home/views/local_widgets/horizontal_list_card_view.dart @@ -17,7 +17,9 @@ class HorizontalCardListView extends StatelessWidget { }) : super(key: key); final Size cardSize; - final Widget Function(BuildContext context, T item, int index, void Function() onTap) cardBuilder; + final Widget Function( + BuildContext context, T item, int index, void Function() onTap) + cardBuilder; final Widget Function( BuildContext context, T item, diff --git a/lib/app/modules/ImportExport/controllers/export_controller.dart b/lib/app/modules/ImportExport/controllers/export_controller.dart index 497ffd74..7eec8f52 100644 --- a/lib/app/modules/ImportExport/controllers/export_controller.dart +++ b/lib/app/modules/ImportExport/controllers/export_controller.dart @@ -20,7 +20,10 @@ import 'package:dungeon_paper/app/modules/ImportExport/platforms/abstract_import if (dart.library.html) 'package:dungeon_paper/app/modules/ImportExport/platforms/web_export.dart'; class ExportController extends GetxController - with GetSingleTickerProviderStateMixin, CharacterServiceMixin, RepositoryServiceMixin + with + GetSingleTickerProviderStateMixin, + CharacterServiceMixin, + RepositoryServiceMixin implements ImportExportSelectionData { final toExport = ExportSelections().obs; @@ -43,30 +46,38 @@ class ExportController extends GetxController } @override - void toggle(T item, bool state) => _toggleExportList([item], state); + void toggle(T item, bool state) => + _toggleExportList([item], state); @override - void toggleAll(bool state) => _toggleExportList(listByType(), state); + void toggleAll(bool state) => + _toggleExportList(listByType(), state); void _toggleExportList(List items, bool state) { switch (T) { case Character: - toExport.value.characters = _toggleInList(toExport.value.characters, items.cast(), state); + toExport.value.characters = _toggleInList( + toExport.value.characters, items.cast(), state); break; case Move: - toExport.value.moves = _toggleInList(toExport.value.moves, items.cast(), state); + toExport.value.moves = + _toggleInList(toExport.value.moves, items.cast(), state); break; case Spell: - toExport.value.spells = _toggleInList(toExport.value.spells, items.cast(), state); + toExport.value.spells = + _toggleInList(toExport.value.spells, items.cast(), state); break; case Item: - toExport.value.items = _toggleInList(toExport.value.items, items.cast(), state); + toExport.value.items = + _toggleInList(toExport.value.items, items.cast(), state); break; case CharacterClass: - toExport.value.classes = _toggleInList(toExport.value.classes, items.cast(), state); + toExport.value.classes = _toggleInList( + toExport.value.classes, items.cast(), state); break; case Race: - toExport.value.races = _toggleInList(toExport.value.races, items.cast(), state); + toExport.value.races = + _toggleInList(toExport.value.races, items.cast(), state); break; } toExport.refresh(); diff --git a/lib/app/modules/ImportExport/controllers/import_controller.dart b/lib/app/modules/ImportExport/controllers/import_controller.dart index 6f924a92..1967c3ac 100644 --- a/lib/app/modules/ImportExport/controllers/import_controller.dart +++ b/lib/app/modules/ImportExport/controllers/import_controller.dart @@ -11,7 +11,7 @@ import 'package:dungeon_paper/app/data/models/spell.dart'; import 'package:dungeon_paper/app/modules/ImportExport/local_widgets/import_progress_dialog.dart'; import 'package:dungeon_paper/core/storage_handler/storage_handler.dart'; import 'package:dungeon_paper/core/utils/list_utils.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter_file_dialog/flutter_file_dialog.dart'; import 'package:get/get.dart'; @@ -29,7 +29,8 @@ class ImportController extends GetxController List get classes => toImport.value!.allClasses.toList(); List get races => toImport.value!.allRaces.toList(); - int get selectionsCount => [characters, moves, spells, items, classes].fold(0, (total, list) => total + list.length); + int get selectionsCount => [characters, moves, spells, items, classes] + .fold(0, (total, list) => total + list.length); bool get hasData => toImport.value != null; @@ -37,30 +38,38 @@ class ImportController extends GetxController final leftCount = 0.obs; @override - void toggle(T item, bool state) => _toggleImportList([item], state); + void toggle(T item, bool state) => + _toggleImportList([item], state); @override - void toggleAll(bool state) => _toggleImportList(listByType(), state); + void toggleAll(bool state) => + _toggleImportList(listByType(), state); void _toggleImportList(List items, bool state) { switch (T) { case Character: - toImport.value!.characters = _toggleInList(toImport.value!.characters, items.cast(), state); + toImport.value!.characters = _toggleInList( + toImport.value!.characters, items.cast(), state); break; case Move: - toImport.value!.moves = _toggleInList(toImport.value!.moves, items.cast(), state); + toImport.value!.moves = + _toggleInList(toImport.value!.moves, items.cast(), state); break; case Spell: - toImport.value!.spells = _toggleInList(toImport.value!.spells, items.cast(), state); + toImport.value!.spells = + _toggleInList(toImport.value!.spells, items.cast(), state); break; case Item: - toImport.value!.items = _toggleInList(toImport.value!.items, items.cast(), state); + toImport.value!.items = + _toggleInList(toImport.value!.items, items.cast(), state); break; case CharacterClass: - toImport.value!.classes = _toggleInList(toImport.value!.classes, items.cast(), state); + toImport.value!.classes = _toggleInList( + toImport.value!.classes, items.cast(), state); break; case Race: - toImport.value!.races = _toggleInList(toImport.value!.races, items.cast(), state); + toImport.value!.races = + _toggleInList(toImport.value!.races, items.cast(), state); break; } toImport.refresh(); @@ -68,7 +77,10 @@ class ImportController extends GetxController @override bool isSelected(T item) { - return toImport.value!.listByType(selected: true).map((x) => x.key).contains(item.key); + return toImport.value! + .listByType(selected: true) + .map((x) => x.key) + .contains(item.key); } List _toggleInList(List list, List items, bool state) { @@ -100,26 +112,27 @@ class ImportController extends GetxController void pickImportFile() async { try { - final _path = await FlutterFileDialog.pickFile( + final importPath = await FlutterFileDialog.pickFile( params: const OpenFileDialogParams( fileExtensionsFilter: ['json'], mimeTypesFilter: ['application/json'], ), ); - if (_path == null) { + if (importPath == null) { return; } - final js = json.decode(await File(_path).readAsString()) as Map; + final js = json.decode(await File(importPath).readAsString()) + as Map; toImport.value = ImportSelections.fromJson(js); } catch (e) { // unawaited(analytics.logEvent(name: Events.ImportFail, parameters: { // 'reason': e.toString(), // })); Get.rawSnackbar( - title: S.current.importFailedTitle, - message: S.current.importFailedMessage, + title: tr.backup.importing.error.title, + message: tr.backup.importing.error.message, ); rethrow; } @@ -139,12 +152,14 @@ class ImportController extends GetxController await Future.delayed(const Duration(milliseconds: 500)); for (final char in characters) { - await StorageHandler.instance.create('Characters', char.key, char.toJson()); + await StorageHandler.instance + .create('Characters', char.key, char.toJson()); leftCount.value -= 1; } importStep.value = CharacterClass; for (final cls in classes) { - await StorageHandler.instance.create('CharacterClasses', cls.key, cls.toJson()); + await StorageHandler.instance + .create('CharacterClasses', cls.key, cls.toJson()); leftCount.value -= 1; } importStep.value = Move; @@ -154,20 +169,22 @@ class ImportController extends GetxController } importStep.value = Spell; for (final spell in spells) { - await StorageHandler.instance.create('Spells', spell.key, spell.toJson()); + await StorageHandler.instance + .create('Spells', spell.key, spell.toJson()); leftCount.value -= 1; } importStep.value = Item; for (final items in items) { - await StorageHandler.instance.create('Items', items.key, items.toJson()); + await StorageHandler.instance + .create('Items', items.key, items.toJson()); leftCount.value -= 1; } await Future.delayed(const Duration(milliseconds: 500)); Get.back(); Get.rawSnackbar( - title: S.current.importSuccessTitle, - message: S.current.importSuccessMessage, + title: tr.backup.importing.success.title, + message: tr.backup.importing.success.message, ); }; } @@ -204,13 +221,30 @@ class ImportSelections { List races; factory ImportSelections.fromJson(Map json) { - final allClasses = (json['classes'] ?? []).map((x) => CharacterClass.fromJson(x)).toList().cast(); - final allCharacters = - List.from(json['characters'] ?? []).map((x) => Character.fromJson(x)).toList().cast(); - final allMoves = List.from(json['moves'] ?? []).map((x) => Move.fromJson(x)).toList().cast(); - final allSpells = List.from(json['spells'] ?? []).map((x) => Spell.fromJson(x)).toList().cast(); - final allItems = List.from(json['items'] ?? []).map((x) => Item.fromJson(x)).toList().cast(); - final allRaces = List.from(json['races'] ?? []).map((x) => Race.fromJson(x)).toList().cast(); + final allClasses = (json['classes'] ?? []) + .map((x) => CharacterClass.fromJson(x)) + .toList() + .cast(); + final allCharacters = List.from(json['characters'] ?? []) + .map((x) => Character.fromJson(x)) + .toList() + .cast(); + final allMoves = List.from(json['moves'] ?? []) + .map((x) => Move.fromJson(x)) + .toList() + .cast(); + final allSpells = List.from(json['spells'] ?? []) + .map((x) => Spell.fromJson(x)) + .toList() + .cast(); + final allItems = List.from(json['items'] ?? []) + .map((x) => Item.fromJson(x)) + .toList() + .cast(); + final allRaces = List.from(json['races'] ?? []) + .map((x) => Race.fromJson(x)) + .toList() + .cast(); return ImportSelections( allClasses: allClasses, diff --git a/lib/app/modules/ImportExport/controllers/import_export_controller.dart b/lib/app/modules/ImportExport/controllers/import_export_controller.dart index 8bd5218c..f58b20fd 100644 --- a/lib/app/modules/ImportExport/controllers/import_export_controller.dart +++ b/lib/app/modules/ImportExport/controllers/import_export_controller.dart @@ -5,7 +5,8 @@ import 'package:get/get.dart'; import 'import_controller.dart'; -class ImportExportController extends GetxController with GetSingleTickerProviderStateMixin { +class ImportExportController extends GetxController + with GetSingleTickerProviderStateMixin { late final Rx tab; @override diff --git a/lib/app/modules/ImportExport/local_widgets/import_progress_dialog.dart b/lib/app/modules/ImportExport/local_widgets/import_progress_dialog.dart index 4a1d7ce3..38a43b5f 100644 --- a/lib/app/modules/ImportExport/local_widgets/import_progress_dialog.dart +++ b/lib/app/modules/ImportExport/local_widgets/import_progress_dialog.dart @@ -1,33 +1,45 @@ import 'package:dungeon_paper/app/modules/ImportExport/controllers/import_controller.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; class ImportProgressDialog extends GetView { - const ImportProgressDialog({Key? key}) : super(key: key); + const ImportProgressDialog({super.key}); @override Widget build(BuildContext context) { return Obx( - () => SimpleDialog( - title: Text(S.current.importProgressTitle), - contentPadding: const EdgeInsets.symmetric(horizontal: 24, vertical: 32).copyWith(top: 8), - children: [ - Text(S.current.importProgressProcessing(S.current.entityPlural(controller.importStep.value!))), - const SizedBox(height: 8), - Row( - children: [ - Expanded( - child: LinearProgressIndicator( - value: 1 - controller.leftCount / controller.selectionsCount, - ), + () { + final completedCount = + controller.selectionsCount - controller.leftCount.value; + final totalCount = controller.selectionsCount; + return SimpleDialog( + title: Text(tr.backup.importing.progress.title), + contentPadding: + const EdgeInsets.symmetric(horizontal: 24, vertical: 32) + .copyWith(top: 8), + children: [ + Text( + tr.backup.importing.progress.processing( + tr.entityPlural(controller.importStep.value!), ), - const SizedBox(width: 16), - Text('${controller.selectionsCount - controller.leftCount.value} / ${controller.selectionsCount}'), - ], - ) - ], - ), + ), + const SizedBox(height: 8), + Row( + children: [ + Expanded( + child: LinearProgressIndicator( + value: + 1 - controller.leftCount / controller.selectionsCount, + ), + ), + const SizedBox(width: 16), + Text('$completedCount / $totalCount'), + ], + ) + ], + ); + }, ); } } diff --git a/lib/app/modules/ImportExport/local_widgets/list_card.dart b/lib/app/modules/ImportExport/local_widgets/list_card.dart index fbf61ffa..c2a6a76a 100644 --- a/lib/app/modules/ImportExport/local_widgets/list_card.dart +++ b/lib/app/modules/ImportExport/local_widgets/list_card.dart @@ -2,14 +2,15 @@ import 'package:dungeon_paper/app/data/models/meta.dart'; import 'package:dungeon_paper/app/modules/ImportExport/controllers/import_export_controller.dart'; import 'package:dungeon_paper/app/widgets/atoms/custom_expansion_panel.dart'; import 'package:dungeon_paper/app/widgets/atoms/menu_button.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -class ListCard extends GetView { +class ListCard + extends GetView { const ListCard({ - Key? key, - }) : super(key: key); + super.key, + }); List get list => controller.listByType(); @@ -31,7 +32,7 @@ class ListCard extends const SizedBox(width: 8), Expanded( child: Text( - S.current.myGeneric(S.current.entityPlural(T)), + tr.generic.myEntity(tr.entityPlural(T)), style: textTheme.titleLarge, ), ), @@ -43,13 +44,13 @@ class ListCard extends MenuEntry( value: true, icon: const Icon(Icons.select_all), - label: Text(S.current.selectAll), + label: Text(tr.generic.selectAll), onSelect: () => controller.toggleAll(true), ), MenuEntry( value: false, icon: const Icon(Icons.clear), - label: Text(S.current.selectNone), + label: Text(tr.generic.selectNone), onSelect: () => controller.toggleAll(false), ), ], @@ -58,7 +59,8 @@ class ListCard extends children: [ for (final item in list) ListTile( - onTap: () => controller.toggle(item, !controller.isSelected(item)), + onTap: () => + controller.toggle(item, !controller.isSelected(item)), title: Text(item.displayName), leading: Checkbox( value: controller.isSelected(item), @@ -69,7 +71,7 @@ class ListCard extends Padding( padding: const EdgeInsets.all(8), child: Text( - S.current.noGeneric(S.current.entityPlural(T)), + tr.generic.noEntity(tr.entityPlural(T)), textAlign: TextAlign.center, ), ), diff --git a/lib/app/modules/ImportExport/platforms/native_export.dart b/lib/app/modules/ImportExport/platforms/native_export.dart index 9ebf77f9..85fac6de 100644 --- a/lib/app/modules/ImportExport/platforms/native_export.dart +++ b/lib/app/modules/ImportExport/platforms/native_export.dart @@ -1,11 +1,11 @@ import 'dart:io'; import 'dart:typed_data'; -import 'package:flutter_file_dialog/flutter_file_dialog.dart'; -import 'package:path/path.dart' as path; -import 'package:get/get.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; import 'package:dungeon_paper/app/modules/ImportExport/platforms/abstract_import_export.dart'; +import 'package:dungeon_paper/i18n.dart'; +import 'package:flutter_file_dialog/flutter_file_dialog.dart'; +import 'package:get/get.dart'; +import 'package:path/path.dart' as path; import 'package:path_provider/path_provider.dart'; class Exporter extends AbstractExporter { @@ -21,19 +21,19 @@ class Exporter extends AbstractExporter { final path = await FlutterFileDialog.saveFile(params: params); if (path == null) { Get.rawSnackbar( - title: S.current.exportFailedTitle, - message: S.current.errorUserOperationCanceled, + title: tr.backup.exporting.error.title, + message: tr.errors.userOperationCanceled, ); } else { Get.rawSnackbar( - title: S.current.exportSuccessfulTitle, - message: S.current.exportSuccessfulMessage, + title: tr.backup.exporting.success.title, + message: tr.backup.exporting.success.message, ); } } catch (e) { Get.rawSnackbar( - title: S.current.exportFailedTitle, - message: S.current.exportFailedMessage, + title: tr.backup.exporting.error.title, + message: tr.backup.exporting.error.message, ); rethrow; } diff --git a/lib/app/modules/ImportExport/platforms/web_export.dart b/lib/app/modules/ImportExport/platforms/web_export.dart index af840df4..0fd3610f 100644 --- a/lib/app/modules/ImportExport/platforms/web_export.dart +++ b/lib/app/modules/ImportExport/platforms/web_export.dart @@ -4,9 +4,10 @@ import 'dart:html' as html; import 'package:dungeon_paper/app/modules/ImportExport/platforms/abstract_import_export.dart'; -void downloadFileFromDataURL(String dataURL, String fileName) => html.AnchorElement(href: dataURL) - ..setAttribute('download', fileName) - ..click(); +void downloadFileFromDataURL(String dataURL, String fileName) => + html.AnchorElement(href: dataURL) + ..setAttribute('download', fileName) + ..click(); class Exporter extends AbstractExporter { @override diff --git a/lib/app/modules/ImportExport/views/import_export_view.dart b/lib/app/modules/ImportExport/views/import_export_view.dart index 56350e6b..97085283 100644 --- a/lib/app/modules/ImportExport/views/import_export_view.dart +++ b/lib/app/modules/ImportExport/views/import_export_view.dart @@ -1,7 +1,6 @@ import 'package:dungeon_paper/app/widgets/atoms/advanced_floating_action_button.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; - import 'package:get/get.dart'; import '../controllers/import_export_controller.dart'; @@ -17,7 +16,7 @@ class ImportExportView extends GetView { return Scaffold( appBar: AppBar( - title: Text(S.current.importExportTitle), + title: Text(tr.backup.title), centerTitle: true, ), body: Column( @@ -25,8 +24,8 @@ class ImportExportView extends GetView { TabBar( controller: controller.tab.value, tabs: [ - Tab(child: Text(S.current.export, style: textStyle)), - Tab(child: Text(S.current.import, style: textStyle)), + Tab(child: Text(tr.backup.exporting.title, style: textStyle)), + Tab(child: Text(tr.backup.importing.title, style: textStyle)), ], ), Expanded( @@ -42,9 +41,14 @@ class ImportExportView extends GetView { ), floatingActionButton: Obx( () => AdvancedFloatingActionButton.extended( - label: Text(controller.tab.value.index == 0 ? S.current.export : S.current.import), - icon: Icon(controller.tab.value.index == 0 ? Icons.upload : Icons.download), - onPressed: controller.tab.value.index == 0 ? controller.doExport : controller.doImport, + label: Text(controller.tab.value.index == 0 + ? tr.backup.exporting.button + : tr.backup.importing.button), + icon: Icon( + controller.tab.value.index == 0 ? Icons.upload : Icons.download), + onPressed: controller.tab.value.index == 0 + ? controller.doExport + : controller.doImport, ), ), ); diff --git a/lib/app/modules/ImportExport/views/import_view.dart b/lib/app/modules/ImportExport/views/import_view.dart index 91a29e99..01959a5a 100644 --- a/lib/app/modules/ImportExport/views/import_view.dart +++ b/lib/app/modules/ImportExport/views/import_view.dart @@ -6,15 +6,14 @@ import 'package:dungeon_paper/app/data/models/race.dart'; import 'package:dungeon_paper/app/data/models/spell.dart'; import 'package:dungeon_paper/app/modules/ImportExport/controllers/import_controller.dart'; import 'package:dungeon_paper/core/utils/builder_utils.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; - import 'package:get/get.dart'; import '../local_widgets/list_card.dart'; class ImportView extends GetView { - const ImportView({Key? key}) : super(key: key); + const ImportView({super.key}); @override Widget build(BuildContext context) { @@ -28,7 +27,7 @@ class ImportView extends GetView { () => ElevatedButton.icon( onPressed: () => controller.toImport.value = null, icon: const Icon(Icons.clear), - label: Text(S.current.importClearFile), + label: Text(tr.backup.importing.file.clearFile), ), () => const ListCard(), () => const ListCard(), @@ -40,11 +39,11 @@ class ImportView extends GetView { ) : ItemBuilder.lazyChildren( children: [ - () => Text(S.current.importBrowseHelp), + () => Text(tr.backup.importing.file.info), () => ElevatedButton.icon( onPressed: controller.pickImportFile, icon: const Icon(Icons.file_open), - label: Text(S.current.importBrowseFile), + label: Text(tr.backup.importing.file.browse), ) ], ); diff --git a/lib/app/modules/LibraryList/controllers/library_list_controller.dart b/lib/app/modules/LibraryList/controllers/library_list_controller.dart index c08ebd7d..77abccbf 100644 --- a/lib/app/modules/LibraryList/controllers/library_list_controller.dart +++ b/lib/app/modules/LibraryList/controllers/library_list_controller.dart @@ -13,8 +13,12 @@ enum FiltersGroup { // online, } -class LibraryListController> extends GetxController - with GetSingleTickerProviderStateMixin, LibraryServiceMixin, CharacterServiceMixin { +class LibraryListController> + extends GetxController + with + GetSingleTickerProviderStateMixin, + LibraryServiceMixin, + CharacterServiceMixin { final repo = Get.find().obs; final chars = Get.find().obs; @@ -33,11 +37,14 @@ class LibraryListController> exte bool get selectable => onSelected != null; - Iterable get builtInList => filterList(builtInListRaw, FiltersGroup.playbook, filterFn, sortFn); + Iterable get builtInList => + filterList(builtInListRaw, FiltersGroup.playbook, filterFn, sortFn); - Iterable get builtInListRaw => repo.value.builtIn.listByType().values.toList(); + Iterable get builtInListRaw => + repo.value.builtIn.listByType().values.toList(); - Iterable get myList => filterList(myListRaw, FiltersGroup.my, filterFn, sortFn); + Iterable get myList => + filterList(myListRaw, FiltersGroup.my, filterFn, sortFn); Iterable get myListRaw => repo.value.my.listByType().values.toList(); String get storageKey => Meta.storageKeyFor(T); @@ -110,7 +117,8 @@ class LibraryListController> exte _compare(T item) { return (T element) { - return (element.meta.sharing?.sourceKey ?? element.key) == item.key || element.key == item.key; + return (element.meta.sharing?.sourceKey ?? element.key) == item.key || + element.key == item.key; }; } @@ -136,14 +144,18 @@ class LibraryListController> exte : // single: if is pre-selected, then only if it was not removed, // if not pre-selected, then only if nothing else is selected - (isPreSelected(item) && !isRemoved(item)) || isInCurrentSelectedList(item); + (isPreSelected(item) && !isRemoved(item)) || + isInCurrentSelectedList(item); bool isInCurrentSelectedList(T item) => - selected.firstWhereOrNull((element) => [element.meta.sharing?.sourceKey, element.key].contains(item.key)) != null; + selected.firstWhereOrNull((element) => + [element.meta.sharing?.sourceKey, element.key].contains(item.key)) != + null; bool isRemoved(T item) => removed.firstWhereOrNull(_compare(item)) != null; - bool isPreSelected(T item) => preSelections.toList().firstWhereOrNull(_compare(item)) != null; + bool isPreSelected(T item) => + preSelections.toList().firstWhereOrNull(_compare(item)) != null; bool isEnabled(T item) => multiple ? @@ -161,14 +173,20 @@ class LibraryListController> exte int Function(T a, T b) Function(F filters)? sortFn, F? initialFilters, ]) { - final filtered = filterFn != null && (filters[group] != null || initialFilters != null) - ? list.where((x) => filterFn(x, filters[group] ?? initialFilters!)).toList() - : list.toList(); - return sortFn != null ? (filtered..sort(sortFn(filters[group] ?? initialFilters!))) : filtered; + final filtered = + filterFn != null && (filters[group] != null || initialFilters != null) + ? list + .where((x) => filterFn(x, filters[group] ?? initialFilters!)) + .toList() + : list.toList(); + return sortFn != null + ? (filtered..sort(sortFn(filters[group] ?? initialFilters!))) + : filtered; } void _updatePlaybookSearch() { - filters[FiltersGroup.playbook]?.setSearch(search[FiltersGroup.playbook]!.text); + filters[FiltersGroup.playbook] + ?.setSearch(search[FiltersGroup.playbook]!.text); search.refresh(); repo.refresh(); } @@ -191,7 +209,8 @@ abstract class EntityFilters { List get filterActiveList; - int get activeFilterCount => filterActiveList.where((element) => element == true).length; + int get activeFilterCount => + filterActiveList.where((element) => element == true).length; int get totalFilterCount => filterActiveList.length; @@ -201,7 +220,8 @@ abstract class EntityFilters { int sortByScore(T a, T b) => getScore(b).compareTo(getScore(a)); } -abstract class LibraryListArguments> { +abstract class LibraryListArguments> { final Map filters; final void Function(Iterable items)? onSelected; diff --git a/lib/app/modules/LibraryList/views/character_classes_library_list_view.dart b/lib/app/modules/LibraryList/views/character_classes_library_list_view.dart index 947a483b..eefbf8dd 100644 --- a/lib/app/modules/LibraryList/views/character_classes_library_list_view.dart +++ b/lib/app/modules/LibraryList/views/character_classes_library_list_view.dart @@ -13,7 +13,8 @@ import 'package:get/get.dart'; import 'filters/character_class_filters.dart'; -class CharacterClassesLibraryListView extends GetView> { +class CharacterClassesLibraryListView extends GetView< + LibraryListController> { const CharacterClassesLibraryListView({ Key? key, }) : super(key: key); @@ -43,7 +44,8 @@ class CharacterClassesLibraryListView extends GetView data.onDelete!(data.item) : null, + onDelete: + data.onDelete != null ? () => data.onDelete!(data.item) : null, ), if (data.selectable) ElevatedButton.icon( @@ -58,7 +60,8 @@ class CharacterClassesLibraryListView extends GetView { +class CharacterClassLibraryListArguments + extends LibraryListArguments { CharacterClassLibraryListArguments({ required void Function(CharacterClass cls)? onSelected, required super.preSelections, @@ -70,7 +73,8 @@ class CharacterClassLibraryListArguments extends LibraryListArguments onSelected.call(cls.first) : null, + onSelected: + onSelected != null ? (cls) => onSelected.call(cls.first) : null, extraData: const {}, multiple: false, ); diff --git a/lib/app/modules/LibraryList/views/entity_filters.dart b/lib/app/modules/LibraryList/views/entity_filters.dart index 5aa11302..b6c3b765 100644 --- a/lib/app/modules/LibraryList/views/entity_filters.dart +++ b/lib/app/modules/LibraryList/views/entity_filters.dart @@ -5,14 +5,14 @@ import 'package:dungeon_paper/app/modules/LibraryList/controllers/library_list_c import 'package:dungeon_paper/app/widgets/atoms/search_field.dart'; import 'package:dungeon_paper/app/widgets/chips/primary_chip.dart'; import 'package:dungeon_paper/core/utils/list_utils.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:popover/popover.dart'; class EntityFiltersView> extends StatelessWidget { EntityFiltersView({ - Key? key, + super.key, required this.filters, required this.emptyFilters, required this.onChange, @@ -20,11 +20,12 @@ class EntityFiltersView> extends StatelessWidget { this.filterWidgetsBuilder, this.leading = const [], this.trailing = const [], - }) : super(key: key); + }); final F filters; final F emptyFilters; - final List Function(BuildContext context, F filters)? filterWidgetsBuilder; + final List Function(BuildContext context, F filters)? + filterWidgetsBuilder; final service = Get.find(); final void Function(F) onChange; final TextEditingController searchController; @@ -39,7 +40,7 @@ class EntityFiltersView> extends StatelessWidget { if (leading.isNotEmpty) const SizedBox(height: 8), SearchField( controller: searchController, - hintText: S.current.searchPlaceholderGeneric(S.current.entity(T)), + hintText: tr.search.placeholderEntity(tr.entity(T)), trailing: filterWidgetsBuilder != null ? [ _FiltersWidgetsBuilder( @@ -60,16 +61,17 @@ class EntityFiltersView> extends StatelessWidget { class _FiltersWidgetsBuilder extends StatelessWidget { const _FiltersWidgetsBuilder({ - Key? key, + super.key, required this.filters, required this.emptyFilters, required this.filterWidgetsBuilder, required this.onChange, - }) : super(key: key); + }); final F filters; final F emptyFilters; - final List Function(BuildContext context, F filters) filterWidgetsBuilder; + final List Function(BuildContext context, F filters) + filterWidgetsBuilder; final void Function(F) onChange; @override @@ -88,12 +90,14 @@ class _FiltersWidgetsBuilder extends StatelessWidget { filters.controller.add(emptyFilters); } : null, - deleteButtonTooltip: S.current.libraryListNoItemsFoundClearFiltersButton, + deleteButtonTooltip: tr.myLibrary.filters.clear, onPressed: () => showPopover( context: context, height: max( 96, - filters.totalFilterCount * 64 + 32 + (16 * (filters.totalFilterCount - 1)), + filters.totalFilterCount * 64 + + 32 + + (16 * (filters.totalFilterCount - 1)), ), width: 300, backgroundColor: Theme.of(context).cardColor, @@ -109,13 +113,14 @@ class _FiltersWidgetsBuilder extends StatelessWidget { class _FiltersPopover extends StatelessWidget { const _FiltersPopover({ - Key? key, + super.key, required this.filters, required this.filterWidgetsBuilder, - }) : super(key: key); + }); final F filters; - final List Function(BuildContext context, F filters) filterWidgetsBuilder; + final List Function(BuildContext context, F filters) + filterWidgetsBuilder; @override Widget build(BuildContext context) { @@ -131,8 +136,9 @@ class _FiltersPopover extends StatelessWidget { children: enumerate(filterWidgetsBuilder(context, filters)) .map( (e) => Container( - padding: - e.index == filters.totalFilterCount - 1 ? EdgeInsets.zero : const EdgeInsets.only(bottom: 16), + padding: e.index == filters.totalFilterCount - 1 + ? EdgeInsets.zero + : const EdgeInsets.only(bottom: 16), height: e.index == filters.totalFilterCount - 1 ? 64 : 80, child: e.value, ), diff --git a/lib/app/modules/LibraryList/views/filters/character_class_filters.dart b/lib/app/modules/LibraryList/views/filters/character_class_filters.dart index 512df11d..c3eb333d 100644 --- a/lib/app/modules/LibraryList/views/filters/character_class_filters.dart +++ b/lib/app/modules/LibraryList/views/filters/character_class_filters.dart @@ -70,7 +70,9 @@ class CharacterClassFilters extends EntityFilters { double getScore(CharacterClass cls) { return avg( [cls.name, cls.description].map( - (e) => (search?.isEmpty ?? true) || e.isEmpty ? 0.0 : StringSimilarity.compareTwoStrings(search!, e), + (e) => (search?.isEmpty ?? true) || e.isEmpty + ? 0.0 + : StringSimilarity.compareTwoStrings(search!, e), ), ); } diff --git a/lib/app/modules/LibraryList/views/filters/item_filters.dart b/lib/app/modules/LibraryList/views/filters/item_filters.dart index 7e3289c3..44450532 100644 --- a/lib/app/modules/LibraryList/views/filters/item_filters.dart +++ b/lib/app/modules/LibraryList/views/filters/item_filters.dart @@ -64,7 +64,9 @@ class ItemFilters extends EntityFilters { double getScore(Item item) { return avg( [item.name, item.description].map( - (e) => (search?.isEmpty ?? true) || e.isEmpty ? 0.0 : StringSimilarity.compareTwoStrings(search!, e), + (e) => (search?.isEmpty ?? true) || e.isEmpty + ? 0.0 + : StringSimilarity.compareTwoStrings(search!, e), ), ); } diff --git a/lib/app/modules/LibraryList/views/filters/move_filters.dart b/lib/app/modules/LibraryList/views/filters/move_filters.dart index 98342f32..121f44a9 100644 --- a/lib/app/modules/LibraryList/views/filters/move_filters.dart +++ b/lib/app/modules/LibraryList/views/filters/move_filters.dart @@ -6,20 +6,19 @@ import 'package:dungeon_paper/app/modules/LibraryList/views/entity_filters.dart' import 'package:dungeon_paper/app/widgets/atoms/select_box.dart'; import 'package:dungeon_paper/core/utils/math_utils.dart'; import 'package:dungeon_paper/core/utils/string_utils.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; - import 'package:get/get.dart'; import 'package:string_similarity/string_similarity.dart'; class MoveFiltersView extends StatelessWidget { MoveFiltersView({ - Key? key, + super.key, required this.filters, required this.group, required this.onChange, required this.searchController, - }) : super(key: key); + }); final MoveFilters filters; final FiltersGroup group; @@ -37,21 +36,18 @@ class MoveFiltersView extends StatelessWidget { filterWidgetsBuilder: (context, f) => [ SelectBox( isExpanded: true, - label: Text(S.current.entityPlural(MoveCategory)), + label: Text(tr.entityPlural(MoveCategory)), value: f.category, items: [ DropdownMenuItem( - child: Text(S.current.allGeneric(S.current.entityPlural(MoveCategory))), value: null, + child: + Text(tr.generic.allEntities(tr.entityPlural(MoveCategory))), ), ...MoveCategory.values.map( (cat) => DropdownMenuItem( - child: Text( - ![MoveCategory.advanced1, MoveCategory.advanced2].contains(cat) - ? S.current.moveCategory(cat) - : S.current.moveCategoryWithLevel(cat), - ), value: cat, + child: Text(tr.moves.category.longName(cat.name)), ), ), ], @@ -61,18 +57,22 @@ class MoveFiltersView extends StatelessWidget { }, ), SelectBox( - label: Text(S.current.entityPlural(CharacterClass)), + label: Text(tr.entityPlural(CharacterClass)), isExpanded: true, value: f.classKey, items: [ DropdownMenuItem( - child: Text(S.current.allGeneric(S.current.entityPlural(CharacterClass))), value: null, + child: + Text(tr.generic.allEntities(tr.entityPlural(CharacterClass))), ), - ...{...repo.builtIn.classes.values, ...repo.my.classes.values}.map( + ...{ + ...repo.builtIn.classes.values, + ...repo.my.classes.values + }.map( (cls) => DropdownMenuItem( - child: Text(cls.name), value: cls.key, + child: Text(cls.name), ), ), ], @@ -119,7 +119,9 @@ class MoveFilters extends EntityFilters { if (classKey != null) { if (![MoveCategory.basic, MoveCategory.special].contains(category) && - !move.classKeys.map((x) => cleanStr(x.key)).contains(cleanStr(classKey!))) { + !move.classKeys + .map((x) => cleanStr(x.key)) + .contains(cleanStr(classKey!))) { return false; } } @@ -139,11 +141,18 @@ class MoveFilters extends EntityFilters { return avg( [ category == move.category ? 1.0 : 0.0, - classKey != null && move.classKeys.map((x) => cleanStr(x.key)).contains(cleanStr(classKey!)) ? 1.0 : 0.0, + classKey != null && + move.classKeys + .map((x) => cleanStr(x.key)) + .contains(cleanStr(classKey!)) + ? 1.0 + : 0.0, ] + [move.name, move.description, move.explanation] .map( - (e) => (search?.isEmpty ?? true) || e.isEmpty ? 0.0 : StringSimilarity.compareTwoStrings(search!, e), + (e) => (search?.isEmpty ?? true) || e.isEmpty + ? 0.0 + : StringSimilarity.compareTwoStrings(search!, e), ) .toList(), ); diff --git a/lib/app/modules/LibraryList/views/filters/note_filters.dart b/lib/app/modules/LibraryList/views/filters/note_filters.dart index ba84793b..653085c5 100644 --- a/lib/app/modules/LibraryList/views/filters/note_filters.dart +++ b/lib/app/modules/LibraryList/views/filters/note_filters.dart @@ -64,7 +64,9 @@ class NoteFilters extends EntityFilters { double getScore(Note note) { return avg( [note.title, note.description].map( - (e) => (search?.isEmpty ?? true) || e.isEmpty ? 0.0 : StringSimilarity.compareTwoStrings(search!, e), + (e) => (search?.isEmpty ?? true) || e.isEmpty + ? 0.0 + : StringSimilarity.compareTwoStrings(search!, e), ), ); } diff --git a/lib/app/modules/LibraryList/views/filters/race_filters.dart b/lib/app/modules/LibraryList/views/filters/race_filters.dart index dfc51958..4c97f997 100644 --- a/lib/app/modules/LibraryList/views/filters/race_filters.dart +++ b/lib/app/modules/LibraryList/views/filters/race_filters.dart @@ -6,20 +6,19 @@ import 'package:dungeon_paper/app/modules/LibraryList/views/entity_filters.dart' import 'package:dungeon_paper/app/widgets/atoms/select_box.dart'; import 'package:dungeon_paper/core/utils/math_utils.dart'; import 'package:dungeon_paper/core/utils/string_utils.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; - import 'package:get/get.dart'; import 'package:string_similarity/string_similarity.dart'; class RaceFiltersView extends StatelessWidget { RaceFiltersView({ - Key? key, + super.key, required this.filters, required this.group, required this.onChange, required this.searchController, - }) : super(key: key); + }); final RaceFilters filters; final FiltersGroup group; @@ -36,18 +35,22 @@ class RaceFiltersView extends StatelessWidget { searchController: searchController, filterWidgetsBuilder: (context, f) => [ SelectBox( - label: Text(S.current.entityPlural(CharacterClass)), + label: Text(tr.entityPlural(CharacterClass)), isExpanded: true, value: f.classKey, items: [ DropdownMenuItem( - child: Text(S.current.allGeneric(S.current.entityPlural(CharacterClass))), value: null, + child: + Text(tr.generic.allEntities(tr.entityPlural(CharacterClass))), ), - ...{...repo.builtIn.classes.values, ...repo.my.classes.values}.map( + ...{ + ...repo.builtIn.classes.values, + ...repo.my.classes.values + }.map( (cls) => DropdownMenuItem( - child: Text(cls.name), value: cls.key, + child: Text(cls.name), ), ), ], @@ -85,7 +88,9 @@ class RaceFilters extends EntityFilters { } if (classKey != null) { - if (!race.classKeys.map((x) => cleanStr(x.key)).contains(cleanStr(classKey!))) { + if (!race.classKeys + .map((x) => cleanStr(x.key)) + .contains(cleanStr(classKey!))) { return false; } } @@ -104,11 +109,18 @@ class RaceFilters extends EntityFilters { double getScore(Race race) { return avg( [ - classKey != null && race.classKeys.map((x) => cleanStr(x.key)).contains(cleanStr(classKey!)) ? 1.0 : 0.0, + classKey != null && + race.classKeys + .map((x) => cleanStr(x.key)) + .contains(cleanStr(classKey!)) + ? 1.0 + : 0.0, ] + [race.name, race.description, race.explanation] .map( - (e) => (search?.isEmpty ?? true) || e.isEmpty ? 0.0 : StringSimilarity.compareTwoStrings(search!, e), + (e) => (search?.isEmpty ?? true) || e.isEmpty + ? 0.0 + : StringSimilarity.compareTwoStrings(search!, e), ) .toList(), ); diff --git a/lib/app/modules/LibraryList/views/filters/spell_filters.dart b/lib/app/modules/LibraryList/views/filters/spell_filters.dart index 955fe582..8705c15f 100644 --- a/lib/app/modules/LibraryList/views/filters/spell_filters.dart +++ b/lib/app/modules/LibraryList/views/filters/spell_filters.dart @@ -6,19 +6,19 @@ import 'package:dungeon_paper/app/modules/LibraryList/views/entity_filters.dart' import 'package:dungeon_paper/app/widgets/atoms/select_box.dart'; import 'package:dungeon_paper/core/utils/math_utils.dart'; import 'package:dungeon_paper/core/utils/string_utils.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:string_similarity/string_similarity.dart'; class SpellFiltersView extends StatelessWidget { SpellFiltersView({ - Key? key, + super.key, required this.group, required this.filters, required this.onChange, required this.searchController, - }) : super(key: key); + }); final SpellFilters filters; final FiltersGroup group; @@ -35,17 +35,21 @@ class SpellFiltersView extends StatelessWidget { searchController: searchController, filterWidgetsBuilder: (context, f) => [ SelectBox( - label: Text(S.current.entityPlural(Spell)), + label: Text(tr.entityPlural(Spell)), value: f.classKey, items: [ DropdownMenuItem( - child: Text(S.current.allGeneric(S.current.entityPlural(CharacterClass))), value: null, + child: + Text(tr.generic.allEntities(tr.entityPlural(CharacterClass))), ), - ...{...repo.builtIn.classes.values, ...repo.my.classes.values}.map( + ...{ + ...repo.builtIn.classes.values, + ...repo.my.classes.values + }.map( (cls) => DropdownMenuItem( - child: Text(cls.name), value: cls.key, + child: Text(cls.name), ), ), ], @@ -91,7 +95,9 @@ class SpellFilters extends EntityFilters { } if (classKey != null) { - if (!spell.classKeys.map((x) => cleanStr(x.key)).contains(cleanStr(classKey!))) { + if (!spell.classKeys + .map((x) => cleanStr(x.key)) + .contains(cleanStr(classKey!))) { return false; } } @@ -109,11 +115,18 @@ class SpellFilters extends EntityFilters { return avg( [ level == spell.level ? 1.0 : 0.0, - classKey != null && spell.classKeys.map((x) => cleanStr(x.key)).contains(cleanStr(classKey!)) ? 1.0 : 0.0, + classKey != null && + spell.classKeys + .map((x) => cleanStr(x.key)) + .contains(cleanStr(classKey!)) + ? 1.0 + : 0.0, ] + [spell.name, spell.description, spell.explanation] .map( - (e) => (search?.isEmpty ?? true) || e.isEmpty ? 0.0 : StringSimilarity.compareTwoStrings(search!, e), + (e) => (search?.isEmpty ?? true) || e.isEmpty + ? 0.0 + : StringSimilarity.compareTwoStrings(search!, e), ) .toList(), ); diff --git a/lib/app/modules/LibraryList/views/items_library_list_view.dart b/lib/app/modules/LibraryList/views/items_library_list_view.dart index 21887569..52cae09b 100644 --- a/lib/app/modules/LibraryList/views/items_library_list_view.dart +++ b/lib/app/modules/LibraryList/views/items_library_list_view.dart @@ -12,7 +12,8 @@ import 'package:get/get.dart'; import 'filters/item_filters.dart'; -class ItemsLibraryListView extends GetView> { +class ItemsLibraryListView + extends GetView> { const ItemsLibraryListView({ Key? key, }) : super(key: key); @@ -40,7 +41,8 @@ class ItemsLibraryListView extends GetView data.onDelete!(data.item) : null, + onDelete: + data.onDelete != null ? () => data.onDelete!(data.item) : null, ), if (data.selectable) ElevatedButton.icon( diff --git a/lib/app/modules/LibraryList/views/library_card_list.dart b/lib/app/modules/LibraryList/views/library_card_list.dart index cea57009..2411e3a2 100644 --- a/lib/app/modules/LibraryList/views/library_card_list.dart +++ b/lib/app/modules/LibraryList/views/library_card_list.dart @@ -16,13 +16,14 @@ import 'package:dungeon_paper/app/widgets/forms/race_form.dart'; import 'package:dungeon_paper/app/widgets/forms/spell_form.dart'; import 'package:dungeon_paper/core/utils/builder_utils.dart'; import 'package:dungeon_paper/core/utils/enums.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -class LibraryCardList> extends GetView> { +class LibraryCardList> + extends GetView> { LibraryCardList({ - Key? key, + super.key, required this.useFilters, required this.filtersBuilder, required this.filters, @@ -32,11 +33,10 @@ class LibraryCardList> extends Ge this.extraData = const {}, this.onSave, }) : itemBuilder = ((BuildContext context, int index) => children[index]), - itemCount = children.length, - super(key: key); + itemCount = children.length; const LibraryCardList.builder({ - Key? key, + super.key, required this.useFilters, required this.filtersBuilder, required this.filters, @@ -46,7 +46,7 @@ class LibraryCardList> extends Ge required this.itemCount, this.extraData = const {}, this.onSave, - }) : super(key: key); + }); final bool useFilters; final Widget Function( @@ -110,7 +110,7 @@ class LibraryCardList> extends Ge if (itemCount == 0) ...[ () => const SizedBox(height: 32), () => Text( - S.current.libraryListNoItemsFoundTitle(S.current.entityPlural(T)), + tr.myLibrary.emptyState.title(tr.entityPlural(T)), style: textTheme.titleLarge, textAlign: TextAlign.center, ), @@ -120,8 +120,10 @@ class LibraryCardList> extends Ge width: 300, child: Text( filters.isEmpty - ? S.current.libraryListNoItemsFoundSubtitleNoFilters(S.current.entityPlural(T)) - : S.current.libraryListNoItemsFoundSubtitleFilters(S.current.entityPlural(T)), + ? tr.myLibrary.emptyState.subtitle + .noFilters(tr.entityPlural(T)) + : tr.myLibrary.emptyState.subtitle + .filters(tr.entityPlural(T)), style: textTheme.titleMedium, textAlign: TextAlign.center, ), @@ -138,7 +140,7 @@ class LibraryCardList> extends Ge Routes.editByType(), arguments: createPageArgsByType(extraData), ), - label: Text(S.current.createGeneric(S.current.entity(T))), + label: Text(tr.generic.createEntity(tr.entity(T))), icon: const Icon(Icons.add), ), ), diff --git a/lib/app/modules/LibraryList/views/library_collection_view.dart b/lib/app/modules/LibraryList/views/library_collection_view.dart index 9bf882e2..92fb8732 100644 --- a/lib/app/modules/LibraryList/views/library_collection_view.dart +++ b/lib/app/modules/LibraryList/views/library_collection_view.dart @@ -10,9 +10,8 @@ import 'package:dungeon_paper/app/data/services/repository_service.dart'; import 'package:dungeon_paper/app/data/services/user_service.dart'; import 'package:dungeon_paper/app/model_utils/model_pages.dart'; import 'package:dungeon_paper/app/widgets/atoms/menu_button.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; - import 'package:get/get.dart'; import 'package:intl/intl.dart'; @@ -22,7 +21,7 @@ class LibraryCollectionView extends GetView with RepositoryServiceMixin, UserServiceMixin, CharacterServiceMixin { static const List types = [Move, Spell, Item, CharacterClass, Race]; - const LibraryCollectionView({Key? key}) : super(key: key); + const LibraryCollectionView({super.key}); @override Widget build(BuildContext context) { @@ -30,13 +29,13 @@ class LibraryCollectionView extends GetView final textTheme = theme.textTheme; return Scaffold( appBar: AppBar( - title: Text(S.current.libraryCollectionTitle), + title: Text(tr.myLibrary.title), centerTitle: true, actions: [ MenuButton( items: [ MenuEntry( - label: Text(S.current.reloadLibrary), + label: Text(tr.myLibrary.reload), icon: const Icon(Icons.refresh), disabled: repo.my.isLoading || repo.builtIn.isLoading, value: 'refresh', @@ -60,7 +59,8 @@ class LibraryCollectionView extends GetView child: ListTile( onTap: () => ModelPages.openLibraryList( type: type, - abilityScores: maybeChar?.abilityScores ?? AbilityScores.dungeonWorldAll(10), + abilityScores: maybeChar?.abilityScores ?? + AbilityScores.dungeonWorldAll(10), classKeys: [], moveCategory: null, // initialTab: charService.maybeCurrent != null @@ -79,18 +79,20 @@ class LibraryCollectionView extends GetView ), ), title: Text( - S.current.entityPlural(type), + tr.entityPlural(type), style: textTheme.titleLarge, ), subtitle: Text( [ - S.current.libraryCollectionListItemSubtitle( - NumberFormat('#,###,###').format(repo.builtIn.listByType(type).length), - S.current.libraryCollectionListItemSubtitleType('builtIn'), + tr.myLibrary.itemCount( + NumberFormat('#,###,###') + .format(repo.builtIn.listByType(type).length), + tr.myLibrary.libraryType('builtIn'), ), - S.current.libraryCollectionListItemSubtitle( - NumberFormat('#,###,###').format(repo.my.listByType(type).length), - S.current.libraryCollectionListItemSubtitleType('my'), + tr.myLibrary.itemCount( + NumberFormat('#,###,###') + .format(repo.my.listByType(type).length), + tr.myLibrary.libraryType('my'), ), ].join(' | '), ), diff --git a/lib/app/modules/LibraryList/views/library_list_view.dart b/lib/app/modules/LibraryList/views/library_list_view.dart index 11f997b5..6de04c98 100644 --- a/lib/app/modules/LibraryList/views/library_list_view.dart +++ b/lib/app/modules/LibraryList/views/library_list_view.dart @@ -4,14 +4,14 @@ import 'package:dungeon_paper/app/themes/colors.dart'; import 'package:dungeon_paper/app/themes/themes.dart'; import 'package:dungeon_paper/app/widgets/atoms/advanced_floating_action_button.dart'; import 'package:dungeon_paper/app/widgets/dialogs/confirm_delete_dialog.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; - import 'package:get/get.dart'; import 'library_card_list.dart'; -typedef CardBuilder = Widget Function(BuildContext context, CardBuilderData data); +typedef CardBuilder = Widget Function( + BuildContext context, CardBuilderData data); class CardBuilderData { final T item; @@ -37,19 +37,20 @@ class CardBuilderData { }); } -class LibraryListView> extends GetView> { +class LibraryListView> + extends GetView> { LibraryListView({ - Key? key, + super.key, this.title, required this.cardBuilder, required this.filtersBuilder, - }) : super(key: key); + }); final Widget? title; final CardBuilder cardBuilder; final pageStorageBucket = PageStorageBucket(); - final Widget Function(FiltersGroup group, F filters, void Function(FiltersGroup group, F filters) update)? - filtersBuilder; + final Widget Function(FiltersGroup group, F filters, + void Function(FiltersGroup group, F filters) update)? filtersBuilder; bool get useFilters => filtersBuilder != null; F get playbookFilters => controller.filters[FiltersGroup.playbook]!; @@ -57,14 +58,17 @@ class LibraryListView> extends Ge @override Widget build(BuildContext context) { - final entityTitleName = - controller.multiple || !controller.selectable ? S.current.entityPlural(T) : S.current.entity(T); + final entityTitleName = controller.multiple || !controller.selectable + ? tr.entityPlural(T) + : tr.entity(T); return Scaffold( appBar: AppBar( title: title ?? Text( - controller.selectable ? S.current.selectGeneric(entityTitleName) : S.current.viewGeneric(entityTitleName), + controller.selectable + ? tr.generic.selectEntity(entityTitleName) + : tr.generic.viewEntity(entityTitleName), ), centerTitle: true, ), @@ -79,9 +83,9 @@ class LibraryListView> extends Ge labelColor: Theme.of(context).colorScheme.onSurface, unselectedLabelColor: Theme.of(context).colorScheme.onSurface, tabs: [ - Tab(child: Text(S.current.addRepoItemTabPlaybook)), - Tab(child: Text(S.current.myGeneric(S.current.entityPlural(T)))), - // Tab(child: Text(S.current.addRepoItemTabOnline)), + Tab(child: Text(tr.myLibrary.itemTab.playbook)), + Tab(child: Text(tr.generic.myEntity(tr.entityPlural(T)))), + // Tab(child: Text(tr.myLibrary.itemTab.online)), ], ), Expanded( @@ -98,12 +102,14 @@ class LibraryListView> extends Ge itemCount: controller.builtInList.length, itemBuilder: (context, index) { final item = controller.builtInList.elementAt(index); - return _wrapWithSelection(context, item, FiltersGroup.playbook); + return _wrapWithSelection( + context, item, FiltersGroup.playbook); }, ), LibraryCardList.builder( group: FiltersGroup.my, - onSave: (item) => controller.saveCustomItem(controller.storageKey, item), + onSave: (item) => controller.saveCustomItem( + controller.storageKey, item), extraData: controller.extraData, useFilters: useFilters, filtersBuilder: filtersBuilder, @@ -112,7 +118,8 @@ class LibraryListView> extends Ge itemCount: controller.myList.length, itemBuilder: (context, index) { final item = controller.myList.elementAt(index); - return _wrapWithSelection(context, item, FiltersGroup.my); + return _wrapWithSelection( + context, item, FiltersGroup.my); }, ), // Container(), @@ -140,16 +147,15 @@ class LibraryListView> extends Ge label: Text( controller.selected.isNotEmpty ? controller.multiple - ? S.current.addGeneric( - S.current.pluralize( - controller.selected.length, - S.current.entity(T), - S.current.entityPlural(T), - ), + ? tr.generic.addEntity( + tr.entityCount(T, controller.selected.length), ) - : S.current.selectGeneric(controller.selected.first.displayName) - : S.current.selectToAdd( - controller.multiple ? S.current.entityPlural(T) : S.current.entity(T), + : tr.generic.selectEntity( + controller.selected.first.displayName) + : tr.generic.selectToAdd( + controller.multiple + ? tr.entityPlural(T) + : tr.entity(T), ), ), ) @@ -158,13 +164,15 @@ class LibraryListView> extends Ge ); } - Widget _wrapWithSelection(BuildContext context, T item, FiltersGroup group) => Obx( + Widget _wrapWithSelection(BuildContext context, T item, FiltersGroup group) => + Obx( () { final isPreSelected = controller.isPreSelected(item); final selected = controller.isSelected(item); final enabled = controller.isEnabled(item); final selectable = controller.selectable; - final onToggle = enabled ? () => controller.toggleItem(item, !selected) : null; + final onToggle = + enabled ? () => controller.toggleItem(item, !selected) : null; final cardData = CardBuilderData( item: item, selected: selected, @@ -173,13 +181,13 @@ class LibraryListView> extends Ge label: Text( enabled ? !selected - ? S.current.select + ? tr.generic.select : controller.multiple - ? S.current.remove - : S.current.unselect + ? tr.generic.remove + : tr.generic.unselect : controller.multiple - ? S.current.alreadyAdded - : S.current.select, + ? tr.myLibrary.alreadyAdded + : tr.generic.select, ), icon: Icon( enabled @@ -192,14 +200,16 @@ class LibraryListView> extends Ge ? Icons.add : Icons.check, ), - onUpdate: - group == FiltersGroup.my ? (item) => controller.saveCustomItem(controller.storageKey, item) : null, + onUpdate: group == FiltersGroup.my + ? (item) => + controller.saveCustomItem(controller.storageKey, item) + : null, onDelete: group == FiltersGroup.my ? (item) => deleteDialog.confirm( context, DeleteDialogOptions( entityName: item.displayName, - entityKind: S.current.entity(item.runtimeType), + entityKind: tr.entity(item.runtimeType), ), () => controller.deleteCustomItem( controller.storageKey, diff --git a/lib/app/modules/LibraryList/views/moves_library_list_view.dart b/lib/app/modules/LibraryList/views/moves_library_list_view.dart index 525cdbff..c06b1cf3 100644 --- a/lib/app/modules/LibraryList/views/moves_library_list_view.dart +++ b/lib/app/modules/LibraryList/views/moves_library_list_view.dart @@ -16,7 +16,9 @@ import 'package:get/get.dart'; import 'filters/move_filters.dart'; -class MovesLibraryListView extends GetView> with CharacterServiceMixin { +class MovesLibraryListView + extends GetView> + with CharacterServiceMixin { const MovesLibraryListView({ Key? key, }) : super(key: key); @@ -41,12 +43,14 @@ class MovesLibraryListView extends GetView ModelPages.openMovePage( - abilityScores: maybeChar?.abilityScores ?? AbilityScores.dungeonWorldAll(10), + abilityScores: maybeChar?.abilityScores ?? + AbilityScores.dungeonWorldAll(10), move: data.item, onSave: data.onUpdate!, ) : null, - onDelete: data.onDelete != null ? () => data.onDelete!(data.item) : null, + onDelete: + data.onDelete != null ? () => data.onDelete!(data.item) : null, ), if (data.selectable) ElevatedButton.icon( @@ -74,8 +78,10 @@ class MoveLibraryListArguments extends LibraryListArguments { sortFn: Move.sorter, filterFn: (move, filters) => filters.filter(move), filters: { - FiltersGroup.playbook: MoveFilters(classKey: character?.characterClass.key, category: category), - FiltersGroup.my: MoveFilters(classKey: character?.characterClass.key, category: category), + FiltersGroup.playbook: MoveFilters( + classKey: character?.characterClass.key, category: category), + FiltersGroup.my: MoveFilters( + classKey: character?.characterClass.key, category: category), }, extraData: { 'abilityScores': abilityScores ?? character?.abilityScores, diff --git a/lib/app/modules/LibraryList/views/notes_library_list_view.dart b/lib/app/modules/LibraryList/views/notes_library_list_view.dart index db25dee5..d9f2f67e 100644 --- a/lib/app/modules/LibraryList/views/notes_library_list_view.dart +++ b/lib/app/modules/LibraryList/views/notes_library_list_view.dart @@ -13,7 +13,8 @@ import 'package:get/get.dart'; import 'filters/note_filters.dart'; -class NotesLibraryListView extends GetView> { +class NotesLibraryListView + extends GetView> { const NotesLibraryListView({ Key? key, }) : super(key: key); @@ -41,7 +42,8 @@ class NotesLibraryListView extends GetView data.onDelete!(data.item) : null, + onDelete: + data.onDelete != null ? () => data.onDelete!(data.item) : null, ), if (data.selectable) ElevatedButton.icon( diff --git a/lib/app/modules/LibraryList/views/races_library_list_view.dart b/lib/app/modules/LibraryList/views/races_library_list_view.dart index 6ce19d30..7515252e 100644 --- a/lib/app/modules/LibraryList/views/races_library_list_view.dart +++ b/lib/app/modules/LibraryList/views/races_library_list_view.dart @@ -15,7 +15,9 @@ import 'package:get/get.dart'; import 'filters/race_filters.dart'; -class RacesLibraryListView extends GetView> with CharacterServiceMixin { +class RacesLibraryListView + extends GetView> + with CharacterServiceMixin { const RacesLibraryListView({ Key? key, }) : super(key: key); @@ -40,12 +42,14 @@ class RacesLibraryListView extends GetView ModelPages.openRacePage( - abilityScores: maybeChar?.abilityScores ?? AbilityScores.dungeonWorldAll(10), + abilityScores: maybeChar?.abilityScores ?? + AbilityScores.dungeonWorldAll(10), race: data.item, onSave: data.onUpdate!, ) : null, - onDelete: data.onDelete != null ? () => data.onDelete!(data.item) : null, + onDelete: + data.onDelete != null ? () => data.onDelete!(data.item) : null, ), if (data.selectable) ElevatedButton.icon( @@ -70,14 +74,18 @@ class RaceLibraryListArguments extends LibraryListArguments { sortFn: Race.sorter, filterFn: (race, filters) => filters.filter(race), filters: { - FiltersGroup.playbook: RaceFilters(classKey: character?.characterClass.key), - FiltersGroup.my: RaceFilters(classKey: character?.characterClass.key), + FiltersGroup.playbook: + RaceFilters(classKey: character?.characterClass.key), + FiltersGroup.my: + RaceFilters(classKey: character?.characterClass.key), }, extraData: { 'abilityScores': character?.abilityScores, - 'classKeys': character != null ? [character.characterClass.key] : null, + 'classKeys': + character != null ? [character.characterClass.key] : null, }, - onSelected: onSelected != null ? (race) => onSelected.call(race.first) : null, + onSelected: + onSelected != null ? (race) => onSelected.call(race.first) : null, multiple: false, ); } diff --git a/lib/app/modules/LibraryList/views/spells_library_list_view.dart b/lib/app/modules/LibraryList/views/spells_library_list_view.dart index 945852fd..a7e19029 100644 --- a/lib/app/modules/LibraryList/views/spells_library_list_view.dart +++ b/lib/app/modules/LibraryList/views/spells_library_list_view.dart @@ -13,7 +13,8 @@ import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; import 'filters/spell_filters.dart'; -class SpellsLibraryListView extends GetView> { +class SpellsLibraryListView + extends GetView> { const SpellsLibraryListView({ Key? key, }) : super(key: key); @@ -44,7 +45,8 @@ class SpellsLibraryListView extends GetView data.onDelete!(data.item) : null, + onDelete: + data.onDelete != null ? () => data.onDelete!(data.item) : null, ), if (data.selectable) ElevatedButton.icon( @@ -59,7 +61,8 @@ class SpellsLibraryListView extends GetView { +class SpellLibraryListArguments + extends LibraryListArguments { SpellLibraryListArguments({ required Character? character, required super.onSelected, diff --git a/lib/app/modules/Login/controllers/login_controller.dart b/lib/app/modules/Login/controllers/login_controller.dart index a078c38a..b5d2c8c4 100644 --- a/lib/app/modules/Login/controllers/login_controller.dart +++ b/lib/app/modules/Login/controllers/login_controller.dart @@ -7,7 +7,8 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; -class LoginController extends GetxController with AuthServiceMixin, LoadingServiceMixin, CharacterServiceMixin { +class LoginController extends GetxController + with AuthServiceMixin, LoadingServiceMixin, CharacterServiceMixin { final formKey = GlobalKey(debugLabel: 'loginForm'); final email = TextEditingController(); final password = TextEditingController(); @@ -41,7 +42,8 @@ class LoginController extends GetxController with AuthServiceMixin, LoadingServi void loginWithPassword() async { _loginWrapper( - () => authService.loginWithPassword(email: email.text, password: password.text), + () => authService.loginWithPassword( + email: email.text, password: password.text), ); } @@ -84,4 +86,3 @@ class LoginController extends GetxController with AuthServiceMixin, LoadingServi return _valid.value; } } - diff --git a/lib/app/modules/Login/views/login_progress_dialog_view.dart b/lib/app/modules/Login/views/login_progress_dialog_view.dart index 3df5212f..2b8db95e 100644 --- a/lib/app/modules/Login/views/login_progress_dialog_view.dart +++ b/lib/app/modules/Login/views/login_progress_dialog_view.dart @@ -1,8 +1,7 @@ import 'package:dungeon_paper/app/data/services/character_service.dart'; import 'package:dungeon_paper/app/data/services/loading_service.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; - import 'package:get/get.dart'; enum LoginProgressStep { @@ -10,19 +9,20 @@ enum LoginProgressStep { loadChars, } -class LoginProgressDialogView extends GetView with CharacterServiceMixin { - const LoginProgressDialogView({Key? key}) : super(key: key); +class LoginProgressDialogView extends GetView + with CharacterServiceMixin { + const LoginProgressDialogView({super.key}); String get title { if (controller.loadingUser) { - return S.current.loadingUser; + return tr.loading.user; } if (controller.loadingCharacters) { - return S.current.loadingCharacters; + return tr.loading.characters; } - return S.current.loadingGeneral; + return tr.loading.general; } @override diff --git a/lib/app/modules/Login/views/login_view.dart b/lib/app/modules/Login/views/login_view.dart index 5e9bb148..03b90d28 100644 --- a/lib/app/modules/Login/views/login_view.dart +++ b/lib/app/modules/Login/views/login_view.dart @@ -4,17 +4,16 @@ import 'package:dungeon_paper/core/dw_icons.dart'; import 'package:dungeon_paper/core/platform_helper.dart'; import 'package:dungeon_paper/core/utils/list_utils.dart'; import 'package:dungeon_paper/core/utils/password_validator.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:email_validator/email_validator.dart'; import 'package:flutter/material.dart'; - import 'package:get/get.dart'; import 'package:url_launcher/url_launcher.dart'; import '../controllers/login_controller.dart'; class LoginView extends GetView { - const LoginView({Key? key}) : super(key: key); + const LoginView({super.key}); @override Widget build(BuildContext context) { @@ -23,7 +22,7 @@ class LoginView extends GetView { return Scaffold( appBar: AppBar( - title: Text(S.current.appName), + title: Text(tr.app.name), ), body: Center( child: SingleChildScrollView( @@ -43,11 +42,15 @@ class LoginView extends GetView { onPressed: !controller.loadingService.loadingUser ? controller.loginWithGoogle : null, - label: Text(controller.isLogin - ? S.current.signinWithButton( - S.current.signinProvider('google')) - : S.current.signupWithButton( - S.current.signinProvider('google'))), + label: Text( + controller.isLogin + ? tr.auth.providers.loginWith( + tr.auth.providers.name('google'), + ) + : tr.auth.providers.signupWith( + tr.auth.providers.name('google'), + ), + ), icon: const Icon(DwIcons.google), ), ], @@ -56,11 +59,15 @@ class LoginView extends GetView { onPressed: !controller.loadingService.loadingUser ? controller.loginWithApple : null, - label: Text(controller.isLogin - ? S.current.signinWithButton( - S.current.signinProvider('apple')) - : S.current.signupWithButton( - S.current.signinProvider('apple'))), + label: Text( + controller.isLogin + ? tr.auth.providers.loginWith( + tr.auth.providers.name('apple'), + ) + : tr.auth.providers.signupWith( + tr.auth.providers.name('apple'), + ), + ), icon: const Icon(DwIcons.apple), ), ], @@ -69,16 +76,16 @@ class LoginView extends GetView { children: [ Text( controller.isLogin - ? S.current.signinTitle - : S.current.signupTitle, + ? tr.auth.login.title + : tr.auth.signup.title, style: textTheme.headlineMedium, textAlign: TextAlign.center, ), const SizedBox(height: 8), Text( controller.isLogin - ? S.current.signinSubtitle - : S.current.signupSubtitle, + ? tr.auth.login.subtitle + : tr.auth.signup.subtitle, style: textTheme.titleMedium, textAlign: TextAlign.center, ), @@ -87,7 +94,7 @@ class LoginView extends GetView { .joinObjects(const SizedBox(height: 8)), if (providerSignIns.isNotEmpty) ...[ const SizedBox(height: 16), - LabeledDivider(label: Text(S.current.separatorOr)), + LabeledDivider(label: Text(tr.auth.orSeparator)), ], TextFormField( controller: controller.email, @@ -95,15 +102,15 @@ class LoginView extends GetView { autofillHints: const [AutofillHints.email], decoration: InputDecoration( filled: true, - label: Text(S.current.signupEmail), + label: Text(tr.auth.signup.email.label), enabled: !controller.loadingService.loadingUser, // floatingLabelBehavior: FloatingLabelBehavior.auto, - hintText: S.current.signupEmailPlaceholder, + hintText: tr.auth.signup.email.placeholder, ), validator: (email) => email == null || EmailValidator.validate(email) ? null - : S.current.signupEmailValidation, + : tr.auth.signup.email.error, ), const SizedBox(height: 16), PasswordField( @@ -116,8 +123,8 @@ class LoginView extends GetView { ], decoration: InputDecoration( filled: true, - label: Text(S.current.signupPassword), - hintText: S.current.signupPasswordPlaceholder, + label: Text(tr.auth.signup.password.label), + hintText: tr.auth.signup.password.placeholder, enabled: !controller.loadingService.loadingUser, // floatingLabelBehavior: FloatingLabelBehavior.auto, ), @@ -131,9 +138,10 @@ class LoginView extends GetView { autofillHints: const [AutofillHints.newPassword], decoration: InputDecoration( filled: true, - label: Text(S.current.signupPasswordConfirm), + label: + Text(tr.auth.signup.password.confirm.label), hintText: - S.current.signupPasswordConfirmPlaceholder, + tr.auth.signup.password.confirm.placeholder, enabled: !controller.loadingService.loadingUser, // floatingLabelBehavior: FloatingLabelBehavior.auto, ), @@ -141,8 +149,7 @@ class LoginView extends GetView { PasswordValidator().validator(pwd) ?? (pwd == controller.password.text ? null - : S.current - .signupPasswordValidationMatch), + : tr.auth.signup.password.confirm.error), ), ], const SizedBox(height: 16), @@ -154,9 +161,9 @@ class LoginView extends GetView { : null, label: Text( controller.isLogin - ? S.current.signinButton - : S.current.signupButton, - textScaleFactor: 1.5, + ? tr.auth.login.button + : tr.auth.signup.button, + textScaler: const TextScaler.linear(1.5), ), style: ElevatedButton.styleFrom( padding: const EdgeInsets.symmetric( @@ -175,12 +182,10 @@ class LoginView extends GetView { runSpacing: 8, crossAxisAlignment: WrapCrossAlignment.center, children: [ - Text(S.current.signinGoToSignupLabel), + Text(tr.auth.login.noAccount.label), ElevatedButton( onPressed: controller.toggleSignup, - child: Text( - S.current.signinGoToSignupButton, - ), + child: Text(tr.auth.login.noAccount.button), ) ], ), @@ -191,7 +196,7 @@ class LoginView extends GetView { 'https://dungeonpaper.app/privacy-policy.html?utm_medium=app&utm_source=login', ), ), - label: Text(S.current.privacyPolicy), + label: Text(tr.auth.privacyPolicy), icon: const Icon(Icons.lock), ), const SizedBox(height: 8), @@ -202,7 +207,7 @@ class LoginView extends GetView { 'https://dungeonpaper.app/changelog.html', ), ), - label: Text(S.current.whatsNew), + label: Text(tr.auth.changelog), icon: const Icon(Icons.new_releases), ), ], @@ -218,4 +223,3 @@ class LoginView extends GetView { ); } } - diff --git a/lib/app/modules/Migration/views/migration_view.dart b/lib/app/modules/Migration/views/migration_view.dart index ddcfa23e..d1be6353 100644 --- a/lib/app/modules/Migration/views/migration_view.dart +++ b/lib/app/modules/Migration/views/migration_view.dart @@ -1,14 +1,13 @@ import 'package:dungeon_paper/app/widgets/atoms/advanced_floating_action_button.dart'; import 'package:dungeon_paper/app/widgets/atoms/select_box.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; - import 'package:get/get.dart'; import '../controllers/migration_controller.dart'; class MigrationView extends GetView { - const MigrationView({Key? key}) : super(key: key); + const MigrationView({super.key}); @override Widget build(BuildContext context) { @@ -20,7 +19,7 @@ class MigrationView extends GetView { floatingActionButton: Obx( () => AdvancedFloatingActionButton.extended( onPressed: controller.isValid ? controller.done : null, - label: Text(S.current.continueLabel), + label: Text(tr.generic.continue_), icon: const Icon(Icons.check), ), ), @@ -41,13 +40,13 @@ class MigrationView extends GetView { ), const SizedBox(height: 16), Text( - S.current.migrationTitle, + tr.migration.title, style: textTheme.headlineMedium, textAlign: TextAlign.center, ), const SizedBox(height: 16), Text( - S.current.migrationSubtitle, + tr.migration.subtitle, style: textTheme.titleMedium, textAlign: TextAlign.center, ), @@ -56,20 +55,20 @@ class MigrationView extends GetView { () => TextFormField( controller: controller.username, decoration: InputDecoration( - label: Text(S.current.signupUsername), - hintText: S.current.signupUsernamePlaceholder, + label: Text(tr.migration.username.label), + hintText: tr.migration.username.placeholder, ), ), ), const SizedBox(height: 8), - Text(S.current.migrationUsernameInfo, style: textTheme.bodySmall), + Text(tr.migration.username.info, style: textTheme.bodySmall), const SizedBox(height: 16), Obx( () => SelectBox( value: controller.language, - label: Text(S.current.signupDefaultDataLanguage), + label: Text(tr.migration.language.data), items: const [ - DropdownMenuItem(child: Text('English'), value: 'EN'), + DropdownMenuItem(value: 'EN', child: Text('English')), ], onChanged: null, ), diff --git a/lib/app/modules/SelectCharacterTheme/controllers/select_character_theme_controller.dart b/lib/app/modules/SelectCharacterTheme/controllers/select_character_theme_controller.dart index 3d870998..cacb5f51 100644 --- a/lib/app/modules/SelectCharacterTheme/controllers/select_character_theme_controller.dart +++ b/lib/app/modules/SelectCharacterTheme/controllers/select_character_theme_controller.dart @@ -4,7 +4,8 @@ import 'package:dungeon_paper/app/themes/themes.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -class SelectCharacterThemeController extends GetxController with CharacterServiceMixin, UserServiceMixin { +class SelectCharacterThemeController extends GetxController + with CharacterServiceMixin, UserServiceMixin { final seeAll = {Brightness.light: false, Brightness.dark: false}.obs; final lightTheme = Rx(AppThemes.parchment); final darkTheme = Rx(AppThemes.dark); @@ -14,10 +15,12 @@ class SelectCharacterThemeController extends GetxController with CharacterServic super.onReady(); lightTheme.value = char.settings.lightTheme; darkTheme.value = char.settings.darkTheme; - if (lightTheme.value != null && !AppThemes.allLightThemes.contains(lightTheme.value)) { + if (lightTheme.value != null && + !AppThemes.allLightThemes.contains(lightTheme.value)) { seeAll[Brightness.light] = true; } - if (darkTheme.value != null && !AppThemes.allDarkThemes.contains(darkTheme.value)) { + if (darkTheme.value != null && + !AppThemes.allDarkThemes.contains(darkTheme.value)) { seeAll[Brightness.dark] = true; } } diff --git a/lib/app/modules/SelectCharacterTheme/views/select_character_theme_view.dart b/lib/app/modules/SelectCharacterTheme/views/select_character_theme_view.dart index 0b620071..7ed5f219 100644 --- a/lib/app/modules/SelectCharacterTheme/views/select_character_theme_view.dart +++ b/lib/app/modules/SelectCharacterTheme/views/select_character_theme_view.dart @@ -1,19 +1,18 @@ import 'package:dungeon_paper/app/modules/Settings/views/theme_selector.dart'; import 'package:dungeon_paper/app/themes/themes.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; - import 'package:get/get.dart'; import '../controllers/select_character_theme_controller.dart'; class SelectCharacterThemeView extends GetView { - const SelectCharacterThemeView({Key? key}) : super(key: key); + const SelectCharacterThemeView({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text(S.current.characterSelectTheme), + title: Text(tr.character.theme.title), centerTitle: true, ), body: ListView( @@ -21,20 +20,23 @@ class SelectCharacterThemeView extends GetView { Obx( () => _sectionTitle( context, - S.current.settingsDefaultLightTheme, + tr.character.theme.defaultLight, onReset: () { controller.lightTheme.value = null; controller.save(); }, resetEnabled: controller.lightTheme.value != null, - onChangeSeeAll: (val) => controller.seeAll[Brightness.light] = val, + onChangeSeeAll: (val) => + controller.seeAll[Brightness.light] = val, seeAll: controller.seeAll[Brightness.light]!, ), ), _pad( Obx( () => ThemeSelector( - themes: controller.seeAll[Brightness.light]! ? AppThemes.allThemes : AppThemes.allLightThemes, + themes: controller.seeAll[Brightness.light]! + ? AppThemes.allThemes + : AppThemes.allLightThemes, selected: controller.lightTheme.value, onSelected: (theme) async { controller.lightTheme.value = theme; @@ -47,7 +49,7 @@ class SelectCharacterThemeView extends GetView { Obx( () => _sectionTitle( context, - S.current.settingsDefaultDarkTheme, + tr.character.theme.defaultDark, onReset: () { controller.darkTheme.value = null; controller.save(); @@ -60,7 +62,9 @@ class SelectCharacterThemeView extends GetView { _pad( Obx( () => ThemeSelector( - themes: controller.seeAll[Brightness.dark]! ? AppThemes.allThemes : AppThemes.allDarkThemes, + themes: controller.seeAll[Brightness.dark]! + ? AppThemes.allThemes + : AppThemes.allDarkThemes, selected: controller.darkTheme.value, onSelected: (theme) async { controller.darkTheme.value = theme; @@ -89,9 +93,12 @@ class SelectCharacterThemeView extends GetView { return _pad(Row( children: [ Expanded(child: Text(labelText, style: bodySmall)), - Text(S.current.seeAll), + Text(tr.generic.seeAll), Switch.adaptive(value: seeAll, onChanged: onChangeSeeAll), - ElevatedButton(onPressed: resetEnabled ? onReset : null, child: Text(S.current.useDefault)), + ElevatedButton( + onPressed: resetEnabled ? onReset : null, + child: Text(tr.generic.useDefault), + ), ], )); } diff --git a/lib/app/modules/SendFeedback/controllers/send_feedback_controller.dart b/lib/app/modules/SendFeedback/controllers/send_feedback_controller.dart index 98ae59e1..8366ff13 100644 --- a/lib/app/modules/SendFeedback/controllers/send_feedback_controller.dart +++ b/lib/app/modules/SendFeedback/controllers/send_feedback_controller.dart @@ -1,6 +1,6 @@ import 'package:dungeon_paper/app/data/services/user_service.dart'; import 'package:dungeon_paper/core/http/api.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -22,8 +22,8 @@ class SendFeedbackController extends GetxController with UserServiceMixin { ); Get.back(); Get.rawSnackbar( - title: S.current.sendFeedbackSuccessTitle, - message: S.current.sendFeedbackSuccessMessage, + title: tr.feedback.success.title, + message: tr.feedback.success.message, ); } diff --git a/lib/app/modules/SendFeedback/views/send_feedback_view.dart b/lib/app/modules/SendFeedback/views/send_feedback_view.dart index 277e5835..7b3dd619 100644 --- a/lib/app/modules/SendFeedback/views/send_feedback_view.dart +++ b/lib/app/modules/SendFeedback/views/send_feedback_view.dart @@ -2,28 +2,28 @@ import 'package:dungeon_paper/app/widgets/atoms/advanced_floating_action_button. import 'package:dungeon_paper/app/widgets/atoms/rich_text_field.dart'; import 'package:dungeon_paper/core/utils/email_address_validator.dart'; import 'package:dungeon_paper/core/utils/string_validator.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; - import 'package:get/get.dart'; import '../controllers/send_feedback_controller.dart'; class SendFeedbackView extends GetView { - const SendFeedbackView({Key? key}) : super(key: key); + const SendFeedbackView({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text(S.current.sendFeedbackTitle), + title: Text(tr.feedback.title), centerTitle: true, ), floatingActionButton: Obx( () => AdvancedFloatingActionButton.extended( onPressed: !controller.sending.value ? controller.send : null, - label: Text(S.current.sendFeedbackSendButton), + label: Text(tr.feedback.send), icon: controller.sending.value - ? const SizedBox.square(child: CircularProgressIndicator.adaptive(), dimension: 24) + ? const SizedBox.square( + dimension: 24, child: CircularProgressIndicator.adaptive()) : const Icon(Icons.send), ), ), @@ -37,9 +37,11 @@ class SendFeedbackView extends GetView { Obx( () => TextFormField( controller: controller.email.value, - validator: (email) => email?.isEmpty ?? true ? null : EmailAddressValidator().validator(email), + validator: (email) => email?.isEmpty ?? true + ? null + : EmailAddressValidator().validator(email), decoration: InputDecoration( - labelText: S.current.signupEmailPlaceholder, + labelText: tr.feedback.form.email.label, ), ), ), @@ -48,9 +50,10 @@ class SendFeedbackView extends GetView { TextFormField( controller: controller.title.value, textCapitalization: TextCapitalization.sentences, - validator: StringValidator(minLength: 1, maxLength: 100).validator, + validator: + StringValidator(minLength: 1, maxLength: 100).validator, decoration: InputDecoration( - labelText: S.current.sendFeedbackTitleLabel, + labelText: tr.feedback.form.title.label, ), ), const SizedBox(height: 16), @@ -59,9 +62,10 @@ class SendFeedbackView extends GetView { minLines: 10, maxLines: 10, textCapitalization: TextCapitalization.sentences, - validator: StringValidator(minLength: 1, maxLength: 100).validator, + validator: + StringValidator(minLength: 1, maxLength: 100).validator, decoration: InputDecoration( - labelText: S.current.sendFeedbackBodyLabel, + labelText: tr.feedback.form.body.label, ), ), ], diff --git a/lib/app/modules/Settings/views/settings_view.dart b/lib/app/modules/Settings/views/settings_view.dart index f8a12ab1..60d1e480 100644 --- a/lib/app/modules/Settings/views/settings_view.dart +++ b/lib/app/modules/Settings/views/settings_view.dart @@ -1,32 +1,32 @@ import 'package:dungeon_paper/app/data/services/character_service.dart'; import 'package:dungeon_paper/app/themes/themes.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; - import 'package:get/get.dart'; import '../controllers/settings_controller.dart'; import 'theme_selector.dart'; -class SettingsView extends GetView with CharacterServiceMixin { +class SettingsView extends GetView + with CharacterServiceMixin { const SettingsView({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text(S.current.settingsTitle), + title: Text(tr.settings.title), centerTitle: true, ), body: ListView( children: [ _sectionTitle( context, - S.current.settingsGeneral, + tr.settings.categories.general, ), Obx( () => SwitchListTile.adaptive( - title: Text(S.current.settingsKeepScreenAwake), + title: Text(tr.settings.keepAwake), value: controller.settings.keepScreenAwake, onChanged: (value) => controller.updateSettings( controller.settings.copyWith(keepScreenAwake: value), @@ -36,15 +36,18 @@ class SettingsView extends GetView with CharacterServiceMixi Obx( () => _sectionTitle( context, - S.current.settingsDefaultLightTheme, - onChangeSeeAll: (val) => controller.seeAll[Brightness.light] = val, + tr.settings.defaultTheme.light, + onChangeSeeAll: (val) => + controller.seeAll[Brightness.light] = val, seeAll: controller.seeAll[Brightness.light]!, ), ), _pad( Obx( () => ThemeSelector( - themes: controller.seeAll[Brightness.light]! ? AppThemes.allThemes : AppThemes.allLightThemes, + themes: controller.seeAll[Brightness.light]! + ? AppThemes.allThemes + : AppThemes.allLightThemes, selected: controller.settings.defaultLightTheme, onSelected: (theme) async { await controller.updateSettings( @@ -61,7 +64,7 @@ class SettingsView extends GetView with CharacterServiceMixi Obx( () => _sectionTitle( context, - S.current.settingsDefaultDarkTheme, + tr.settings.defaultTheme.dark, onChangeSeeAll: (val) => controller.seeAll[Brightness.dark] = val, seeAll: controller.seeAll[Brightness.dark]!, ), @@ -69,7 +72,9 @@ class SettingsView extends GetView with CharacterServiceMixi _pad( Obx( () => ThemeSelector( - themes: controller.seeAll[Brightness.dark]! ? AppThemes.allThemes : AppThemes.allDarkThemes, + themes: controller.seeAll[Brightness.dark]! + ? AppThemes.allThemes + : AppThemes.allDarkThemes, selected: controller.settings.defaultDarkTheme, onSelected: (theme) async { await controller.updateSettings( @@ -105,7 +110,7 @@ class SettingsView extends GetView with CharacterServiceMixi children: [ Expanded(child: Text(labelText, style: bodySmall)), if (seeAll != null && onChangeSeeAll != null) ...[ - Text(S.current.seeAll), + Text(tr.generic.seeAll), Switch.adaptive(value: seeAll, onChanged: onChangeSeeAll), ], ], diff --git a/lib/app/modules/Settings/views/theme_selector.dart b/lib/app/modules/Settings/views/theme_selector.dart index e3867d69..a86f4f95 100644 --- a/lib/app/modules/Settings/views/theme_selector.dart +++ b/lib/app/modules/Settings/views/theme_selector.dart @@ -58,12 +58,14 @@ class _ThemePreview extends StatelessWidget { height: size + 8, width: size + 8, child: Material( - shape: rRectShape.copyWith(borderRadius: rRectShape.borderRadius / 2), + shape: rRectShape.copyWith( + borderRadius: rRectShape.borderRadius / 2), color: Colors.black54, child: Padding( padding: const EdgeInsets.all(4), child: Material( - shape: rRectShape.copyWith(borderRadius: rRectShape.borderRadius / 2), + shape: rRectShape.copyWith( + borderRadius: rRectShape.borderRadius / 2), color: themeData.scaffoldBackgroundColor, clipBehavior: Clip.antiAlias, child: InkWell( @@ -107,9 +109,11 @@ class _ThemePreview extends StatelessWidget { margin: EdgeInsets.zero, elevation: 1, color: themeData.cardColor, - shape: rRectShape.copyWith(borderRadius: rRectShape.borderRadius / 2), + shape: rRectShape.copyWith( + borderRadius: rRectShape.borderRadius / 2), child: Padding( - padding: const EdgeInsets.all(8.0).copyWith(top: 22), + padding: + const EdgeInsets.all(8.0).copyWith(top: 22), child: Align( alignment: Alignment.bottomRight, child: SizedBox( diff --git a/lib/app/modules/StartingGearForm/controllers/starting_gear_form_controller.dart b/lib/app/modules/StartingGearForm/controllers/starting_gear_form_controller.dart index 450273fb..6eb1e71c 100644 --- a/lib/app/modules/StartingGearForm/controllers/starting_gear_form_controller.dart +++ b/lib/app/modules/StartingGearForm/controllers/starting_gear_form_controller.dart @@ -32,7 +32,8 @@ class StartingGearFormController extends GetxController { void toggleSelect(GearSelection selection) { dirty.value = true; - final found = selectedOptions.firstWhereOrNull((item) => item.key == selection.key); + final found = + selectedOptions.firstWhereOrNull((item) => item.key == selection.key); if (found == null) { selectedOptions.add(selection); } else { @@ -41,9 +42,11 @@ class StartingGearFormController extends GetxController { } bool isSelected(GearSelection selection) => - selectedOptions.firstWhereOrNull((item) => item.key == selection.key) != null; + selectedOptions.firstWhereOrNull((item) => item.key == selection.key) != + null; - int selectionCount(GearChoice choice) => choice.selections.where((item) => isSelected(item)).length; + int selectionCount(GearChoice choice) => + choice.selections.where((item) => isSelected(item)).length; } class StartingGearFormArguments { diff --git a/lib/app/modules/StartingGearForm/views/starting_gear_form_view.dart b/lib/app/modules/StartingGearForm/views/starting_gear_form_view.dart index 144f9237..fa1cabab 100644 --- a/lib/app/modules/StartingGearForm/views/starting_gear_form_view.dart +++ b/lib/app/modules/StartingGearForm/views/starting_gear_form_view.dart @@ -1,7 +1,7 @@ import 'package:dungeon_paper/app/data/models/gear_selection.dart'; import 'package:dungeon_paper/app/widgets/atoms/advanced_floating_action_button.dart'; import 'package:dungeon_paper/app/widgets/atoms/confirm_exit_view.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -11,8 +11,8 @@ import '../controllers/starting_gear_form_controller.dart'; class StartingGearFormView extends GetView { const StartingGearFormView({ - Key? key, - }) : super(key: key); + super.key, + }); @override Widget build(BuildContext context) { @@ -21,11 +21,11 @@ class StartingGearFormView extends GetView { dirty: controller.dirty.value, child: Scaffold( appBar: AppBar( - title: Text(S.current.selectGeneric(S.current.entity(GearSelection))), + title: Text(tr.generic.selectEntity(tr.entity(GearSelection))), ), floatingActionButton: AdvancedFloatingActionButton.extended( onPressed: _save, - label: Text(S.current.save), + label: Text(tr.generic.save), icon: const Icon(Icons.save), ), body: ListView( @@ -45,11 +45,13 @@ class StartingGearFormView extends GetView { title: Text(choice.description), subtitle: Text( choice.maxSelections != null - ? S.current.createCharacterStartingGearChoiceCountWithMax( + ? tr.createCharacter.startingGear.count + .withMax( controller.selectionCount(choice), choice.maxSelections!, ) - : S.current.createCharacterStartingGearChoiceCountNoMax( + : tr.createCharacter.startingGear.count + .noMax( controller.selectionCount(choice), ), ), @@ -68,7 +70,8 @@ class StartingGearFormView extends GetView { title: Text(sel.description, maxLines: 1), subtitle: Text( sel.options - .map((opt) => '${NumberFormat('#0.#').format(opt.amount)}x ${opt.item.name}') + .map((opt) => + '${NumberFormat('#0.#').format(opt.amount)}x ${opt.item.name}') .join(', '), ), dense: true, diff --git a/lib/app/modules/UniversalSearch/controllers/universal_search_controller.dart b/lib/app/modules/UniversalSearch/controllers/universal_search_controller.dart index 441c1a9a..df30d5f2 100644 --- a/lib/app/modules/UniversalSearch/controllers/universal_search_controller.dart +++ b/lib/app/modules/UniversalSearch/controllers/universal_search_controller.dart @@ -12,7 +12,7 @@ import 'package:dungeon_paper/app/modules/LibraryList/views/filters/move_filters import 'package:dungeon_paper/app/modules/LibraryList/views/filters/race_filters.dart'; import 'package:dungeon_paper/app/modules/LibraryList/views/filters/spell_filters.dart'; import 'package:dungeon_paper/core/utils/list_utils.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -22,44 +22,65 @@ enum SourceType { builtInLibrary, } -class UniversalSearchController extends GetxController with RepositoryServiceMixin, CharacterServiceMixin { +class UniversalSearchController extends GetxController + with RepositoryServiceMixin, CharacterServiceMixin { final _search = TextEditingController(text: '').obs; TextEditingController get search => _search.value; bool get hasCharacter => charService.all.isNotEmpty; - final enabledSources = {SourceType.character, SourceType.myLibrary, SourceType.builtInLibrary}.obs; + final enabledSources = { + SourceType.character, + SourceType.myLibrary, + SourceType.builtInLibrary + }.obs; Map> get sources => { Move: >[ - sourceEnabled(SourceType.character) ? charService.maybeCurrent?.moves ?? [] : [], + sourceEnabled(SourceType.character) + ? charService.maybeCurrent?.moves ?? [] + : [], sourceEnabled(SourceType.myLibrary) ? repo.my.moves.values : [], - sourceEnabled(SourceType.builtInLibrary) ? repo.builtIn.moves.values : [], + sourceEnabled(SourceType.builtInLibrary) + ? repo.builtIn.moves.values + : [], ], Spell: >[ - sourceEnabled(SourceType.character) ? charService.maybeCurrent?.spells ?? [] : [], + sourceEnabled(SourceType.character) + ? charService.maybeCurrent?.spells ?? [] + : [], sourceEnabled(SourceType.myLibrary) ? repo.my.spells.values : [], - sourceEnabled(SourceType.builtInLibrary) ? repo.builtIn.spells.values : [], + sourceEnabled(SourceType.builtInLibrary) + ? repo.builtIn.spells.values + : [], ], Item: >[ - sourceEnabled(SourceType.character) ? charService.maybeCurrent?.items ?? [] : [], + sourceEnabled(SourceType.character) + ? charService.maybeCurrent?.items ?? [] + : [], sourceEnabled(SourceType.myLibrary) ? repo.my.items.values : [], - sourceEnabled(SourceType.builtInLibrary) ? repo.builtIn.items.values : [], + sourceEnabled(SourceType.builtInLibrary) + ? repo.builtIn.items.values + : [], ], CharacterClass: >[ sourceEnabled(SourceType.myLibrary) ? repo.my.classes.values : [], - sourceEnabled(SourceType.builtInLibrary) ? repo.builtIn.classes.values : [], + sourceEnabled(SourceType.builtInLibrary) + ? repo.builtIn.classes.values + : [], ], Race: >[ sourceEnabled(SourceType.myLibrary) ? repo.my.races.values : [], - sourceEnabled(SourceType.builtInLibrary) ? repo.builtIn.races.values : [], + sourceEnabled(SourceType.builtInLibrary) + ? repo.builtIn.races.values + : [], ], }; void toggleSource(SourceType type, [bool? value]) { - final _value = value ?? !sourceEnabled(type); - if (_value) { + final value0 = value ?? !sourceEnabled(type); + if (value0) { enabledSources.add(type); } else { enabledSources.remove(type); @@ -76,7 +97,8 @@ class UniversalSearchController extends GetxController with RepositoryServiceMix List getSource() => flatten(sources[T] as List>); - List flatten(List> list) => list.fold([], (all, current) => all..addAll(current)); + List flatten(List> list) => + list.fold([], (all, current) => all..addAll(current)); Future> get results async { if (search.text.trim().isEmpty) { @@ -84,26 +106,34 @@ class UniversalSearchController extends GetxController with RepositoryServiceMix } final entries = sources.entries; final map = enumerate(entries).map((e) { - final list = flatten(e.value.value).where((e) => searchFor(e.runtimeType, e, search.text)).uniqueBy((e) => e.key); + final list = flatten(e.value.value) + .where((e) => searchFor(e.runtimeType, e, search.text)) + .uniqueBy((e) => e.key); if (list.isEmpty) { return []; } final sorters = { - Move: (a, b) => MoveFilters(search: search.text, classKey: null).sortByScore(a, b), - Spell: (a, b) => SpellFilters(search: search.text, classKey: null, level: null).sortByScore(a, b), + Move: (a, b) => + MoveFilters(search: search.text, classKey: null).sortByScore(a, b), + Spell: (a, b) => + SpellFilters(search: search.text, classKey: null, level: null) + .sortByScore(a, b), Item: (a, b) => ItemFilters(search: search.text).sortByScore(a, b), - CharacterClass: (a, b) => CharacterClassFilters(search: search.text).sortByScore(a, b), - Race: (a, b) => RaceFilters(search: search.text, classKey: null).sortByScore(a, b), + CharacterClass: (a, b) => + CharacterClassFilters(search: search.text).sortByScore(a, b), + Race: (a, b) => + RaceFilters(search: search.text, classKey: null).sortByScore(a, b), }; list.sort( (a, b) => sorters[a.runtimeType]!(a, b), ); - final result = - e.index < entries.length ? [SearchSeparator(S.current.entityPlural(list.first.runtimeType)), ...list] : list; + final result = e.index < entries.length + ? [SearchSeparator(tr.entityPlural(list.first.runtimeType)), ...list] + : list; return result; }); @@ -112,7 +142,8 @@ class UniversalSearchController extends GetxController with RepositoryServiceMix Future get flatResults async { final res = await results; - return res.fold>([], (all, current) => all + current); + return res + .fold>([], (all, current) => all + current); } @override diff --git a/lib/app/modules/UniversalSearch/views/universal_search_view.dart b/lib/app/modules/UniversalSearch/views/universal_search_view.dart index b8808d78..2980df6a 100644 --- a/lib/app/modules/UniversalSearch/views/universal_search_view.dart +++ b/lib/app/modules/UniversalSearch/views/universal_search_view.dart @@ -14,15 +14,14 @@ import 'package:dungeon_paper/app/widgets/cards/move_card.dart'; import 'package:dungeon_paper/app/widgets/cards/race_card.dart'; import 'package:dungeon_paper/app/widgets/cards/spell_card.dart'; import 'package:dungeon_paper/app/widgets/chips/primary_chip.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; - import 'package:get/get.dart'; import '../controllers/universal_search_controller.dart'; class UniversalSearchView extends GetView { - UniversalSearchView({Key? key}) : super(key: key); + UniversalSearchView({super.key}); final bucket = PageStorageBucket(); @@ -56,20 +55,23 @@ class UniversalSearchView extends GetView { crossAxisAlignment: WrapCrossAlignment.center, children: [ Text( - S.current.searchIn, - style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.white), + '${tr.search.searchIn}: ', + style: Theme.of(context) + .textTheme + .bodyMedium! + .copyWith(color: Colors.white), ), if (controller.hasCharacter) _FilterChip( - label: S.current.entity(Character), + label: tr.entity(Character), sourceType: SourceType.character, ), _FilterChip( - label: S.current.libraryCollectionTitle, + label: tr.myLibrary.title, sourceType: SourceType.myLibrary, ), _FilterChip( - label: S.current.addRepoItemTabPlaybook, + label: tr.playbook.title, sourceType: SourceType.builtInLibrary, ), ], @@ -99,7 +101,8 @@ class UniversalSearchView extends GetView { itemBuilder: (context, index) => _CardByType( value.data![index], highlightWords: [controller.search.text.trim()], - abilityScores: controller.maybeChar?.abilityScores ?? AbilityScores.dungeonWorldAll(10), + abilityScores: controller.maybeChar?.abilityScores ?? + AbilityScores.dungeonWorldAll(10), ), ), ); @@ -176,7 +179,10 @@ class _CardByType extends StatelessWidget { case SearchSeparator: return Text( result.text, - style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.white), + style: Theme.of(context) + .textTheme + .bodyMedium! + .copyWith(color: Colors.white), ); default: assert(false, 'Unknown type: ${result.runtimeType}'); diff --git a/lib/app/routes/custom_transitions.dart b/lib/app/routes/custom_transitions.dart index 73e39f18..f4f5e36e 100644 --- a/lib/app/routes/custom_transitions.dart +++ b/lib/app/routes/custom_transitions.dart @@ -21,7 +21,9 @@ class CustomCircularRevealClipper extends CustomClipper { @override Path getClip(Size size) { - final center = centerAlignment?.alongSize(size) ?? centerOffset ?? Offset(size.width / 2, size.height / 2); + final center = centerAlignment?.alongSize(size) ?? + centerOffset ?? + Offset(size.width / 2, size.height / 2); final minRadius = this.minRadius ?? 0; final maxRadius = this.maxRadius ?? calcMaxRadius(size, center); @@ -54,8 +56,13 @@ class CustomCircularRevealTransition extends CustomTransition { final Offset? offset; @override - Widget buildTransition(BuildContext context, Curve? curve, Alignment? alignment, Animation animation, - Animation secondaryAnimation, Widget child) { + Widget buildTransition( + BuildContext context, + Curve? curve, + Alignment? alignment, + Animation animation, + Animation secondaryAnimation, + Widget child) { return ClipPath( clipper: CustomCircularRevealClipper( fraction: animation.value, diff --git a/lib/app/themes/button_themes.dart b/lib/app/themes/button_themes.dart index ffad5d3d..c30cd223 100644 --- a/lib/app/themes/button_themes.dart +++ b/lib/app/themes/button_themes.dart @@ -4,19 +4,23 @@ import 'package:flutter/material.dart'; class ButtonThemes { static final rRectShape = t.rRectShape; - static ButtonStyle? primaryElevated(BuildContext context, {double? backgroundOpacity}) => ElevatedButton.styleFrom(); + static ButtonStyle? primaryElevated(BuildContext context, + {double? backgroundOpacity}) => + ElevatedButton.styleFrom(); // ElevatedButton.styleFrom( // primary: Theme.of(context).primaryColor.withOpacity(backgroundOpacity ?? 1), // shape: rRectShape, // ); - static ButtonStyle? errorElevated(BuildContext context) => ElevatedButton.styleFrom( + static ButtonStyle? errorElevated(BuildContext context) => + ElevatedButton.styleFrom( backgroundColor: Theme.of(context).colorScheme.error, foregroundColor: Theme.of(context).colorScheme.onError, shape: rRectShape, ); - static ButtonStyle? errorOutlined(BuildContext context) => OutlinedButton.styleFrom( + static ButtonStyle? errorOutlined(BuildContext context) => + OutlinedButton.styleFrom( foregroundColor: Theme.of(context).colorScheme.onError, side: BorderSide(color: Theme.of(context).colorScheme.error), shape: rRectShape, @@ -27,10 +31,12 @@ class ButtonThemes { shape: rRectShape, ); - static ButtonStyle? primaryOutlined(BuildContext context) => OutlinedButton.styleFrom( - foregroundColor: Theme.of(context).scaffoldBackgroundColor.computeLuminance() > 0.5 - ? Theme.of(context).primaryColor - : Theme.of(context).colorScheme.onSurface, + static ButtonStyle? primaryOutlined(BuildContext context) => + OutlinedButton.styleFrom( + foregroundColor: + Theme.of(context).scaffoldBackgroundColor.computeLuminance() > 0.5 + ? Theme.of(context).primaryColor + : Theme.of(context).colorScheme.onSurface, shape: rRectShape, ); } diff --git a/lib/app/themes/theme_utils.dart b/lib/app/themes/theme_utils.dart index 2d6fd4d4..cd2ab890 100644 --- a/lib/app/themes/theme_utils.dart +++ b/lib/app/themes/theme_utils.dart @@ -40,23 +40,39 @@ TextTheme copyTextThemeWith( Color? specialColor, }) => original.copyWith( - displayLarge: original.displayLarge?.copyWith(fontFamily: fontFamily, color: specialColor), - displayMedium: original.displayMedium?.copyWith(fontFamily: fontFamily, color: specialColor), - displaySmall: original.displaySmall?.copyWith(fontFamily: fontFamily, color: specialColor), - headlineMedium: original.headlineMedium?.copyWith(fontFamily: fontFamily, color: specialColor), - headlineSmall: original.headlineSmall?.copyWith(fontFamily: fontFamily, color: specialColor), - titleLarge: original.titleLarge?.copyWith(fontFamily: fontFamily, color: specialColor), - titleMedium: original.titleMedium?.copyWith(fontFamily: fontFamily, color: specialColor), - titleSmall: original.titleSmall?.copyWith(fontFamily: fontFamily, color: specialColor), - bodyLarge: original.bodyLarge?.copyWith(fontFamily: fontFamily, color: normalColor), - bodyMedium: original.bodyMedium?.copyWith(fontFamily: fontFamily, color: normalColor), - bodySmall: original.bodySmall?.copyWith(fontFamily: fontFamily, color: normalColor), - labelLarge: original.labelLarge?.copyWith(fontFamily: fontFamily, color: normalColor), - labelSmall: original.labelSmall?.copyWith(fontFamily: fontFamily, color: normalColor), + displayLarge: original.displayLarge + ?.copyWith(fontFamily: fontFamily, color: specialColor), + displayMedium: original.displayMedium + ?.copyWith(fontFamily: fontFamily, color: specialColor), + displaySmall: original.displaySmall + ?.copyWith(fontFamily: fontFamily, color: specialColor), + headlineMedium: original.headlineMedium + ?.copyWith(fontFamily: fontFamily, color: specialColor), + headlineSmall: original.headlineSmall + ?.copyWith(fontFamily: fontFamily, color: specialColor), + titleLarge: original.titleLarge + ?.copyWith(fontFamily: fontFamily, color: specialColor), + titleMedium: original.titleMedium + ?.copyWith(fontFamily: fontFamily, color: specialColor), + titleSmall: original.titleSmall + ?.copyWith(fontFamily: fontFamily, color: specialColor), + bodyLarge: original.bodyLarge + ?.copyWith(fontFamily: fontFamily, color: normalColor), + bodyMedium: original.bodyMedium + ?.copyWith(fontFamily: fontFamily, color: normalColor), + bodySmall: original.bodySmall + ?.copyWith(fontFamily: fontFamily, color: normalColor), + labelLarge: original.labelLarge + ?.copyWith(fontFamily: fontFamily, color: normalColor), + labelSmall: original.labelSmall + ?.copyWith(fontFamily: fontFamily, color: normalColor), ); ColorScheme createColorScheme(Color seedColor, - {required Brightness brightness, Color? secondary, Color? primary, bool highContrast = false}) { + {required Brightness brightness, + Color? secondary, + Color? primary, + bool highContrast = false}) { final defaultBase = brightness == Brightness.light ? !highContrast ? const ColorScheme.light() @@ -69,7 +85,9 @@ ColorScheme createColorScheme(Color seedColor, seedColor: seedColor, primary: primary, secondary: secondary, - onSecondary: ThemeData.estimateBrightnessForColor(secondary ?? defaultBase.secondary) == Brightness.light + onSecondary: ThemeData.estimateBrightnessForColor( + secondary ?? defaultBase.secondary) == + Brightness.light ? Colors.black : Colors.white, ); @@ -81,7 +99,8 @@ ThemeData createTheme( Color? surfaceColor, required Brightness brightness, }) { - final textTheme = brightness == Brightness.light ? lightM3.textTheme : darkM3.textTheme; + final textTheme = + brightness == Brightness.light ? lightM3.textTheme : darkM3.textTheme; final base = ThemeData.from( useMaterial3: true, colorScheme: colorScheme, @@ -97,15 +116,20 @@ ThemeData createTheme( foregroundColor: base.colorScheme.onSurface, elevation: 0, centerTitle: true, - systemOverlayStyle: getUiOverlayStyleFor(base).copyWith(statusBarColor: Colors.transparent), + systemOverlayStyle: getUiOverlayStyleFor(base) + .copyWith(statusBarColor: Colors.transparent), ), checkboxTheme: base.checkboxTheme.copyWith( - fillColor: MaterialStateProperty.resolveWith((states) => colorScheme.secondary), - checkColor: MaterialStateProperty.resolveWith((states) => colorScheme.onSecondary), + fillColor: + MaterialStateProperty.resolveWith((states) => colorScheme.secondary), + checkColor: MaterialStateProperty.resolveWith( + (states) => colorScheme.onSecondary), ), switchTheme: base.switchTheme.copyWith( - thumbColor: MaterialStateProperty.resolveWith((states) => colorScheme.secondary), - trackColor: MaterialStateProperty.resolveWith((states) => colorScheme.secondaryContainer), + thumbColor: + MaterialStateProperty.resolveWith((states) => colorScheme.secondary), + trackColor: MaterialStateProperty.resolveWith( + (states) => colorScheme.secondaryContainer), ), dialogTheme: base.dialogTheme.copyWith( shape: rRectShape, @@ -130,7 +154,8 @@ ThemeData createTheme( ), tabBarTheme: base.tabBarTheme.copyWith( labelStyle: base.textTheme.bodyMedium!.copyWith(fontFamily: 'Nunito'), - unselectedLabelStyle: base.textTheme.bodyMedium!.copyWith(fontFamily: 'Nunito'), + unselectedLabelStyle: + base.textTheme.bodyMedium!.copyWith(fontFamily: 'Nunito'), indicator: UnderlineTabIndicator( borderSide: BorderSide( color: colorScheme.secondary, @@ -142,7 +167,10 @@ ThemeData createTheme( } Brightness getCurrentPlatformBrightness() => - MediaQueryData.fromWindow(WidgetsBinding.instance.window).platformBrightness; + MediaQueryData.fromWindow(WidgetsBinding.instance.window) + .platformBrightness; SystemUiOverlayStyle getUiOverlayStyleFor(ThemeData theme) => - theme.brightness == Brightness.light ? SystemUiOverlayStyle.dark : SystemUiOverlayStyle.light; + theme.brightness == Brightness.light + ? SystemUiOverlayStyle.dark + : SystemUiOverlayStyle.light; diff --git a/lib/app/themes/themes.dart b/lib/app/themes/themes.dart index 8ddeee1d..8e442e3c 100644 --- a/lib/app/themes/themes.dart +++ b/lib/app/themes/themes.dart @@ -162,11 +162,15 @@ class AppThemes { static List allThemes = themes.keys.toList(); - static List allLightThemes = - themes.entries.where((e) => e.value.brightness == Brightness.light).map((e) => e.key).toList(); + static List allLightThemes = themes.entries + .where((e) => e.value.brightness == Brightness.light) + .map((e) => e.key) + .toList(); - static List allDarkThemes = - themes.entries.where((e) => e.value.brightness == Brightness.dark).map((e) => e.key).toList(); + static List allDarkThemes = themes.entries + .where((e) => e.value.brightness == Brightness.dark) + .map((e) => e.key) + .toList(); static ThemeData getTheme(int theme) => themeCollection[theme]; static String getThemeName(int theme) => _themeNames[theme]!; diff --git a/lib/app/widgets/atoms/advanced_floating_action_button.dart b/lib/app/widgets/atoms/advanced_floating_action_button.dart index b5bfff30..e0a675d1 100644 --- a/lib/app/widgets/atoms/advanced_floating_action_button.dart +++ b/lib/app/widgets/atoms/advanced_floating_action_button.dart @@ -43,7 +43,9 @@ class AdvancedFloatingActionButton extends StatelessWidget { assert(clipBehavior != null), assert(isExtended != null), assert(autofocus != null), - _floatingActionButtonType = mini ? _FloatingActionButtonType.small : _FloatingActionButtonType.regular, + _floatingActionButtonType = mini + ? _FloatingActionButtonType.small + : _FloatingActionButtonType.regular, _extendedLabel = null, extendedIconLabelSpacing = null, extendedPadding = null, @@ -423,7 +425,8 @@ class AdvancedFloatingActionButton extends StatelessWidget { @override Widget build(BuildContext context) { - final _fgColor = foregroundColor ?? (backgroundColor == DwColors.success ? Colors.white : null); + final _fgColor = foregroundColor ?? + (backgroundColor == DwColors.success ? Colors.white : null); final _bgColor = onPressed == null ? Theme.of(context).disabledColor.withOpacity(0.3) // ? Theme.of(context).brightness == Brightness.light diff --git a/lib/app/widgets/atoms/avatar_circular_progress.dart b/lib/app/widgets/atoms/avatar_circular_progress.dart index 8571b666..cc70a890 100644 --- a/lib/app/widgets/atoms/avatar_circular_progress.dart +++ b/lib/app/widgets/atoms/avatar_circular_progress.dart @@ -1,7 +1,8 @@ import 'package:flutter/material.dart'; class AvatarCircularProgress extends StatelessWidget { - const AvatarCircularProgress({Key? key, required this.size}) : super(key: key); + const AvatarCircularProgress({Key? key, required this.size}) + : super(key: key); final double size; diff --git a/lib/app/widgets/atoms/background_icon_button.dart b/lib/app/widgets/atoms/background_icon_button.dart index b5dd3443..970fb358 100644 --- a/lib/app/widgets/atoms/background_icon_button.dart +++ b/lib/app/widgets/atoms/background_icon_button.dart @@ -118,5 +118,7 @@ class BackgroundIconButton extends StatelessWidget { } Color bgColor(BuildContext context) => - color ?? ElevatedButtonTheme.of(context).style?.backgroundColor?.resolve({}) ?? Theme.of(context).primaryColor; + color ?? + ElevatedButtonTheme.of(context).style?.backgroundColor?.resolve({}) ?? + Theme.of(context).primaryColor; } diff --git a/lib/app/widgets/atoms/buffer_progress_bar.dart b/lib/app/widgets/atoms/buffer_progress_bar.dart index 541e499e..fc0c899d 100644 --- a/lib/app/widgets/atoms/buffer_progress_bar.dart +++ b/lib/app/widgets/atoms/buffer_progress_bar.dart @@ -35,14 +35,16 @@ class BufferProgressBar extends StatelessWidget { duration: _duration, height: height, width: constraints.maxWidth, - color: backgroundColor ?? Theme.of(context).colorScheme.primaryContainer, + color: backgroundColor ?? + Theme.of(context).colorScheme.primaryContainer, ), if (bufferValue != null) AnimatedContainer( duration: _duration, height: height, width: constraints.maxWidth * clamp(bufferValue!, 0, 1), - color: bufferColor ?? Theme.of(context).colorScheme.primary.withOpacity(0.3), + color: bufferColor ?? + Theme.of(context).colorScheme.primary.withOpacity(0.3), ), AnimatedContainer( duration: _duration, diff --git a/lib/app/widgets/atoms/character_avatar.dart b/lib/app/widgets/atoms/character_avatar.dart index 57084b9c..798c07c6 100644 --- a/lib/app/widgets/atoms/character_avatar.dart +++ b/lib/app/widgets/atoms/character_avatar.dart @@ -8,7 +8,8 @@ import 'package:get/get.dart'; class CharacterAvatar extends GetView { final Character? character; - final Widget Function(BuildContext context, String avatarUrl, double size) builder; + final Widget Function(BuildContext context, String avatarUrl, double size) + builder; final double size; const CharacterAvatar._({ @@ -22,30 +23,39 @@ class CharacterAvatar extends GetView { Key? key, Character? character, required double size, - required final Widget Function(BuildContext context, String avatarUrl, double size) builder, + required final Widget Function( + BuildContext context, String avatarUrl, double size) + builder, }) => - CharacterAvatar._(key: key, character: character, size: size, builder: builder); + CharacterAvatar._( + key: key, character: character, size: size, builder: builder); factory CharacterAvatar.roundedRect({ Key? key, Character? character, required double size, }) => - CharacterAvatar._(key: key, character: character, size: size, builder: _rRectBuilder); + CharacterAvatar._( + key: key, character: character, size: size, builder: _rRectBuilder); factory CharacterAvatar.circle({ Key? key, Character? character, required double size, }) => - CharacterAvatar._(key: key, character: character, size: size, builder: _circleBuilder); + CharacterAvatar._( + key: key, character: character, size: size, builder: _circleBuilder); factory CharacterAvatar.squircle({ Key? key, Character? character, required double size, }) => - CharacterAvatar._(key: key, character: character, size: size, builder: _squircleBuilder); + CharacterAvatar._( + key: key, + character: character, + size: size, + builder: _squircleBuilder); @override Widget build(BuildContext context) { @@ -58,12 +68,14 @@ class CharacterAvatar extends GetView { }); } - static Widget _rRectBuilder(BuildContext context, String url, double size) => ClipRRect( + static Widget _rRectBuilder(BuildContext context, String url, double size) => + ClipRRect( borderRadius: BorderRadius.circular(size / 8), child: _renderImage(context, url, size), ); - static Widget _circleBuilder(BuildContext context, String url, double size) => CircleAvatar( + static Widget _circleBuilder(BuildContext context, String url, double size) => + CircleAvatar( // clipBehavior: Clip.hardEdge, foregroundImage: _renderImageProvider(url), radius: size / 2, @@ -72,8 +84,11 @@ class CharacterAvatar extends GetView { static CachedNetworkImageProvider? _renderImageProvider(String url) => url.isNotEmpty ? CachedNetworkImageProvider(url) : null; - static Widget _squircleBuilder(BuildContext context, String url, double size) => Material( - shape: ContinuousRectangleBorder(borderRadius: BorderRadius.circular(size / 1.5)), + static Widget _squircleBuilder( + BuildContext context, String url, double size) => + Material( + shape: ContinuousRectangleBorder( + borderRadius: BorderRadius.circular(size / 1.5)), clipBehavior: Clip.antiAlias, child: _renderImage(context, url, size), ); @@ -87,7 +102,8 @@ class CharacterAvatar extends GetView { memCacheHeight: size.toInt(), memCacheWidth: size.toInt(), fit: BoxFit.cover, - progressIndicatorBuilder: (context, url, state) => AvatarCircularProgress(size: size), + progressIndicatorBuilder: (context, url, state) => + AvatarCircularProgress(size: size), errorWidget: (context, url, err) => Stack( children: [ _buildDefaultImage(context, size), @@ -111,12 +127,14 @@ class CharacterAvatar extends GetView { final theme = Theme.of(context); final textStyle = theme.primaryTextTheme.titleMedium!; return Container( - color: ThemeData.estimateBrightnessForColor(textStyle.color!) == Brightness.dark + color: ThemeData.estimateBrightnessForColor(textStyle.color!) == + Brightness.dark ? theme.primaryColorLight : theme.primaryColorDark, child: Icon(Icons.person, size: size), ); } - Widget _renderForChar(BuildContext context, Character? char) => builder(context, char?.avatarUrl ?? '', size); + Widget _renderForChar(BuildContext context, Character? char) => + builder(context, char?.avatarUrl ?? '', size); } diff --git a/lib/app/widgets/atoms/confirm_exit_view.dart b/lib/app/widgets/atoms/confirm_exit_view.dart index 9b63076e..5b3286d0 100644 --- a/lib/app/widgets/atoms/confirm_exit_view.dart +++ b/lib/app/widgets/atoms/confirm_exit_view.dart @@ -1,5 +1,5 @@ import 'package:dungeon_paper/app/widgets/molecules/dialog_controls.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -7,14 +7,14 @@ import '../../../core/utils/dialog_utils.dart'; class ConfirmExitView extends StatelessWidget { const ConfirmExitView({ - Key? key, + super.key, this.title, this.text, this.okLabel, this.cancelLabel, this.dirty = true, required this.child, - }) : super(key: key); + }); final Widget? title; final Widget? text; @@ -23,8 +23,8 @@ class ConfirmExitView extends StatelessWidget { final Widget child; final bool dirty; - static final _defaultTitle = Text(S.current.confirmExitDefaultTitle); - static final _defaultText = Text(S.current.confirmExitDefaultText); + static final _defaultTitle = Text(tr.dialogs.confirmations.exit.title); + static final _defaultText = Text(tr.dialogs.confirmations.exit.body); @override Widget build(BuildContext context) { @@ -63,12 +63,12 @@ class ConfirmExitDialog extends StatelessWidget { final String? cancelLabel; const ConfirmExitDialog({ - Key? key, + super.key, this.title, this.text, this.okLabel, this.cancelLabel, - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/app/widgets/atoms/custom_expansion_tile.dart b/lib/app/widgets/atoms/custom_expansion_tile.dart index 875e0427..1568f60f 100644 --- a/lib/app/widgets/atoms/custom_expansion_tile.dart +++ b/lib/app/widgets/atoms/custom_expansion_tile.dart @@ -273,10 +273,14 @@ class CustomExpansionTile extends StatefulWidget { State createState() => _CustomExpansionTileState(); } -class _CustomExpansionTileState extends State with SingleTickerProviderStateMixin { - static final Animatable _easeOutTween = CurveTween(curve: Curves.easeOut); - static final Animatable _easeInTween = CurveTween(curve: Curves.easeIn); - static final Animatable _halfTween = Tween(begin: 0.0, end: 0.5); +class _CustomExpansionTileState extends State + with SingleTickerProviderStateMixin { + static final Animatable _easeOutTween = + CurveTween(curve: Curves.easeOut); + static final Animatable _easeInTween = + CurveTween(curve: Curves.easeIn); + static final Animatable _halfTween = + Tween(begin: 0.0, end: 0.5); final ColorTween _headerColorTween = ColorTween(); final ColorTween _iconColorTween = ColorTween(); @@ -299,7 +303,8 @@ class _CustomExpansionTileState extends State with SingleTi _headerColor = _controller.drive(_headerColorTween.chain(_easeInTween)); _iconColor = _controller.drive(_iconColorTween.chain(_easeOutTween)); - _isExpanded = PageStorage.of(context).readState(context) as bool? ?? widget.initiallyExpanded; + _isExpanded = PageStorage.of(context).readState(context) as bool? ?? + widget.initiallyExpanded; if (_isExpanded) _controller.value = 1.0; } @@ -328,7 +333,8 @@ class _CustomExpansionTileState extends State with SingleTi } // Platform or null affinity defaults to trailing. - ListTileControlAffinity _effectiveAffinity(ListTileControlAffinity? affinity) { + ListTileControlAffinity _effectiveAffinity( + ListTileControlAffinity? affinity) { switch (affinity ?? ListTileControlAffinity.trailing) { case ListTileControlAffinity.leading: return ListTileControlAffinity.leading; @@ -346,15 +352,18 @@ class _CustomExpansionTileState extends State with SingleTi } Widget? _buildLeadingIcon(BuildContext context) { - if (!widget.expandable || _effectiveAffinity(widget.controlAffinity) != ListTileControlAffinity.leading) - return null; + if (!widget.expandable || + _effectiveAffinity(widget.controlAffinity) != + ListTileControlAffinity.leading) return null; return _buildIcon(context); } Widget? _buildTrailingIcon(BuildContext context) { - if (!widget.expandable || _effectiveAffinity(widget.controlAffinity) != ListTileControlAffinity.trailing) - return null; - if (widget.reorderablePadding && PlatformHelper.currentInteractionType == InteractionType.mouse) { + if (!widget.expandable || + _effectiveAffinity(widget.controlAffinity) != + ListTileControlAffinity.trailing) return null; + if (widget.reorderablePadding && + PlatformHelper.currentInteractionType == InteractionType.mouse) { return Padding( padding: const EdgeInsets.only(right: 24), child: _buildIcon(context), @@ -400,7 +409,10 @@ class _CustomExpansionTileState extends State with SingleTi ...widget.leading, Expanded( child: DefaultTextStyle( - style: Theme.of(context).textTheme.titleMedium!.copyWith(color: _headerColor.value), + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith(color: _headerColor.value), child: widget.title ?? widget.titleBuilder!.call( context, @@ -456,8 +468,11 @@ class _CustomExpansionTileState extends State with SingleTi child: Padding( padding: widget.childrenPadding ?? EdgeInsets.zero, child: Column( - crossAxisAlignment: widget.expandedCrossAxisAlignment ?? CrossAxisAlignment.center, - children: range(widget.itemCount).map((x) => widget.itemBuilder(context, x)).toList(), + crossAxisAlignment: + widget.expandedCrossAxisAlignment ?? CrossAxisAlignment.center, + children: range(widget.itemCount) + .map((x) => widget.itemBuilder(context, x)) + .toList(), ), // child: ListView.builder( // shrinkWrap: true, diff --git a/lib/app/widgets/atoms/debug_menu.dart b/lib/app/widgets/atoms/debug_menu.dart index 78395731..10dd8066 100644 --- a/lib/app/widgets/atoms/debug_menu.dart +++ b/lib/app/widgets/atoms/debug_menu.dart @@ -53,7 +53,8 @@ class DebugMenu extends StatelessWidget { void _toggleTheme() { var theme = DynamicTheme.of(Get.context!)!; - theme.setTheme(theme.themeId == AppThemes.dark ? AppThemes.parchment : AppThemes.dark); + theme.setTheme( + theme.themeId == AppThemes.dark ? AppThemes.parchment : AppThemes.dark); } void _clearChars() async { diff --git a/lib/app/widgets/atoms/hp_bar.dart b/lib/app/widgets/atoms/hp_bar.dart index 3f80f926..5c63311b 100644 --- a/lib/app/widgets/atoms/hp_bar.dart +++ b/lib/app/widgets/atoms/hp_bar.dart @@ -1,16 +1,15 @@ import 'package:dungeon_paper/app/data/services/character_service.dart'; import 'package:dungeon_paper/app/widgets/atoms/buffer_progress_bar.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import '../../../generated/l10n.dart'; - class HpBar extends StatelessWidget with CharacterServiceMixin { const HpBar({ - Key? key, + super.key, this.currentHp, this.maxHp, - }) : super(key: key); + }); final int? currentHp; final int? maxHp; @@ -21,7 +20,8 @@ class HpBar extends StatelessWidget with CharacterServiceMixin { final char = maybeChar; final curValue = currentHp ?? char?.currentHp; final maxValue = maxHp ?? char?.maxHp; - final curPercent = curValue != null && maxValue != null ? curValue / maxValue : 1.0; + final curPercent = + curValue != null && maxValue != null ? curValue / maxValue : 1.0; return Column( mainAxisSize: MainAxisSize.min, @@ -36,13 +36,13 @@ class HpBar extends StatelessWidget with CharacterServiceMixin { Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - Text(S.current.characterBarHp), + Text(tr.home.bars.hp), const SizedBox(width: 8), Text( curValue?.toString() ?? '-', style: const TextStyle(fontWeight: FontWeight.bold), ), - Text('/' + (maxValue?.toString() ?? '-')), + Text('/${maxValue?.toString() ?? '-'}'), ], ) ], diff --git a/lib/app/widgets/atoms/hyperlink.dart b/lib/app/widgets/atoms/hyperlink.dart index f01700a0..eef2c797 100644 --- a/lib/app/widgets/atoms/hyperlink.dart +++ b/lib/app/widgets/atoms/hyperlink.dart @@ -10,8 +10,10 @@ class Hyperlink extends StatelessWidget { Hyperlink.url(this.text, String url, {super.key}) : onTap = _urlTapper(url); - static textSpan(BuildContext context, String text, {void Function()? onTap, String? url}) { - assert(onTap != null || url != null, 'Either onTap or url must be provided'); + static textSpan(BuildContext context, String text, + {void Function()? onTap, String? url}) { + assert( + onTap != null || url != null, 'Either onTap or url must be provided'); onTap ??= _urlTapper(url!); return TextSpan( diff --git a/lib/app/widgets/atoms/labeled_icon_button.dart b/lib/app/widgets/atoms/labeled_icon_button.dart index 20d96843..9c163b85 100644 --- a/lib/app/widgets/atoms/labeled_icon_button.dart +++ b/lib/app/widgets/atoms/labeled_icon_button.dart @@ -25,7 +25,10 @@ class LabeledIconButton extends StatelessWidget { color: theme.primaryColor, onPressed: onPressed, shadows: [ - BoxShadow(offset: shadowOffset, blurRadius: 4, color: Colors.black.withOpacity(0.2)), + BoxShadow( + offset: shadowOffset, + blurRadius: 4, + color: Colors.black.withOpacity(0.2)), ], icon: Column( mainAxisSize: MainAxisSize.min, diff --git a/lib/app/widgets/atoms/lifecycle_builder.dart b/lib/app/widgets/atoms/lifecycle_builder.dart index 337b1ea2..d26d3dd2 100644 --- a/lib/app/widgets/atoms/lifecycle_builder.dart +++ b/lib/app/widgets/atoms/lifecycle_builder.dart @@ -23,7 +23,8 @@ class LifecycleView extends StatefulWidget { }) : child = null, super(key: key); - static Widget Function(BuildContext context) childBuilder(Widget child) => (_) => child; + static Widget Function(BuildContext context) childBuilder(Widget child) => + (_) => child; @override _LifecycleBuilderState createState() => _LifecycleBuilderState(); diff --git a/lib/app/widgets/atoms/number_text_field.dart b/lib/app/widgets/atoms/number_text_field.dart index b906b867..6f47645b 100644 --- a/lib/app/widgets/atoms/number_text_field.dart +++ b/lib/app/widgets/atoms/number_text_field.dart @@ -153,7 +153,9 @@ class NumberTextField extends StatelessWidget { onPressed: _incr, ), ), - keyboardType: keyboardType ?? TextInputType.numberWithOptions(decimal: numberType == NumberType.double), + keyboardType: keyboardType ?? + TextInputType.numberWithOptions( + decimal: numberType == NumberType.double), textCapitalization: textCapitalization, textInputAction: textInputAction, style: style, @@ -183,7 +185,8 @@ class NumberTextField extends StatelessWidget { onSaved: onSaved, validator: validator, inputFormatters: [ - NumberInputFormatter(min: minValue, max: maxValue, numberType: numberType), + NumberInputFormatter( + min: minValue, max: maxValue, numberType: numberType), ...?inputFormatters, ], enabled: enabled, @@ -216,12 +219,16 @@ class NumberTextField extends StatelessWidget { } void _decr() { - controller?.text = max((_parse(controller?.text ?? '') ?? 1) - 1, minValue ?? -double.infinity).toString(); + controller?.text = max((_parse(controller?.text ?? '') ?? 1) - 1, + minValue ?? -double.infinity) + .toString(); onChanged?.call(controller?.text ?? ''); } void _incr() { - controller?.text = min((_parse(controller?.text ?? '') ?? 0) + 1, maxValue ?? double.infinity).toString(); + controller?.text = min((_parse(controller?.text ?? '') ?? 0) + 1, + maxValue ?? double.infinity) + .toString(); onChanged?.call(controller?.text ?? ''); } } @@ -243,14 +250,16 @@ class NumberInputFormatter extends TextInputFormatter { final NumberType numberType; @override - TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) { + TextEditingValue formatEditUpdate( + TextEditingValue oldValue, TextEditingValue newValue) { if (newValue.text.isEmpty) { return newValue; } final value = double.tryParse(newValue.text); - if (value != null && ((max != null && value > max!) || (min != null && value < min!))) { + if (value != null && + ((max != null && value > max!) || (min != null && value < min!))) { return oldValue; } @@ -262,7 +271,8 @@ class NumberInputFormatter extends TextInputFormatter { } } - TextEditingValue _doubleFormat(TextEditingValue oldValue, TextEditingValue newValue) { + TextEditingValue _doubleFormat( + TextEditingValue oldValue, TextEditingValue newValue) { if (newValue.text.endsWith('.')) { return newValue; } @@ -274,7 +284,8 @@ class NumberInputFormatter extends TextInputFormatter { return oldValue; } - TextEditingValue _intFormat(TextEditingValue oldValue, TextEditingValue newValue) { + TextEditingValue _intFormat( + TextEditingValue oldValue, TextEditingValue newValue) { if (int.tryParse(newValue.text) != null) { return newValue; } diff --git a/lib/app/widgets/atoms/password_field.dart b/lib/app/widgets/atoms/password_field.dart index 93688e78..5fe5bb9c 100644 --- a/lib/app/widgets/atoms/password_field.dart +++ b/lib/app/widgets/atoms/password_field.dart @@ -1,4 +1,4 @@ -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -136,11 +136,15 @@ class _PasswordFieldState extends State { decoration: (widget.decoration ?? const InputDecoration()).copyWith( suffix: widget.decoration?.suffixIcon ?? IconButton( - icon: obscured ? const Icon(Icons.visibility) : const Icon(Icons.visibility_off), + icon: obscured + ? const Icon(Icons.visibility) + : const Icon(Icons.visibility_off), iconSize: 16, splashColor: Colors.green.withOpacity(0.2), onPressed: _toggleObscureText, - tooltip: obscured ? S.current.passwordShowTooltip : S.current.passwordHideTooltip, + tooltip: obscured + ? tr.account.details.password.visibility.show + : tr.account.details.password.visibility.hide, ), ), keyboardType: widget.keyboardType, diff --git a/lib/app/widgets/atoms/rich_text_field.dart b/lib/app/widgets/atoms/rich_text_field.dart index 19ac653c..ac308361 100644 --- a/lib/app/widgets/atoms/rich_text_field.dart +++ b/lib/app/widgets/atoms/rich_text_field.dart @@ -1,7 +1,7 @@ import 'package:dungeon_paper/app/widgets/atoms/menu_button.dart'; import 'package:dungeon_paper/core/utils/builder_utils.dart'; import 'package:dungeon_paper/core/utils/markdown_styles.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_markdown/flutter_markdown.dart'; @@ -10,7 +10,7 @@ import 'package:url_launcher/url_launcher.dart'; class RichTextField extends StatelessWidget { RichTextField({ - Key? key, + super.key, this.controller, this.label, this.rich = true, @@ -29,7 +29,7 @@ class RichTextField extends StatelessWidget { this.textAlignVertical, this.autofocus = false, this.readOnly = false, - this.toolbarOptions, + // this.toolbarOptions, this.showCursor, this.obscuringCharacter = '•', this.obscureText = false, @@ -67,7 +67,7 @@ class RichTextField extends StatelessWidget { this.enableIMEPersonalizedLearning = true, // this.customButtons, - }) : super(key: key); + }); final String? label; final String text; @@ -88,7 +88,7 @@ class RichTextField extends StatelessWidget { final TextAlignVertical? textAlignVertical; final bool autofocus; final bool readOnly; - final ToolbarOptions? toolbarOptions; + // final ToolbarOptions? toolbarOptions; final bool? showCursor; final String obscuringCharacter; final bool obscureText; @@ -125,7 +125,8 @@ class RichTextField extends StatelessWidget { final String? restorationId; final bool enableIMEPersonalizedLearning; final _defaultController = TextEditingController().obs; - TextEditingController get _controller => controller ?? _defaultController.value; + TextEditingController get _controller => + controller ?? _defaultController.value; final List? customButtons; @override @@ -146,7 +147,7 @@ class RichTextField extends StatelessWidget { } Widget _buildInput(BuildContext context) { - final _label = label != null ? Text(label!) : null; + final effectiveLabel = label != null ? Text(label!) : null; return TextFormField( controller: controller, @@ -154,12 +155,12 @@ class RichTextField extends StatelessWidget { focusNode: focusNode, decoration: decoration?.copyWith( hintText: hintText, - label: _label, + label: effectiveLabel, ) ?? InputDecoration( filled: true, hintText: hintText, - label: _label, + label: effectiveLabel, ), keyboardType: keyboardType, textCapitalization: textCapitalization, @@ -171,7 +172,7 @@ class RichTextField extends StatelessWidget { textAlignVertical: textAlignVertical, autofocus: autofocus, readOnly: readOnly, - toolbarOptions: toolbarOptions, + // toolbarOptions: toolbarOptions, showCursor: showCursor, obscuringCharacter: obscuringCharacter, obscureText: obscureText, @@ -212,7 +213,8 @@ class RichTextField extends StatelessWidget { SizedBox _buildRichControls(BuildContext context) { final mdTheme = MarkdownStyles.of(context); - const divider = Padding(padding: EdgeInsets.symmetric(vertical: 8), child: VerticalDivider()); + const divider = Padding( + padding: EdgeInsets.symmetric(vertical: 8), child: VerticalDivider()); const thinDivider = Padding( padding: EdgeInsets.symmetric(vertical: 8), child: VerticalDivider(width: 4), @@ -222,14 +224,15 @@ class RichTextField extends StatelessWidget { () => _RichButton( color: Theme.of(context).colorScheme.secondary, icon: const Icon(Icons.preview_outlined), - tooltip: S.current.formatPreview, + tooltip: tr.richText.preview, onTap: () => _openPreview(context), ), () => _RichButton( color: Theme.of(context).colorScheme.secondary, icon: const Icon(Icons.help), - tooltip: S.current.formatHelp, - onTap: () => launchUrl(Uri.parse('https://www.markdownguide.org/basic-syntax')), + tooltip: tr.richText.help, + onTap: () => launchUrl( + Uri.parse('https://www.markdownguide.org/basic-syntax')), ), if (customButtons?.isNotEmpty == true) () => thinDivider, if (customButtons?.isNotEmpty == true) @@ -239,7 +242,7 @@ class RichTextField extends StatelessWidget { () => thinDivider, () => RichButton( icon: Icons.format_bold, - tooltip: S.current.formatBold, + tooltip: tr.richText.bold, defaultContent: '**bold**', prefix: '**', selectionStartOffset: 2, @@ -247,7 +250,7 @@ class RichTextField extends StatelessWidget { ).buildButton(context, _controller), () => RichButton( icon: Icons.format_italic, - tooltip: S.current.formatItalic, + tooltip: tr.richText.italic, defaultContent: '*italic*', prefix: '*', selectionStartOffset: 1, @@ -255,12 +258,12 @@ class RichTextField extends StatelessWidget { ).buildButton(context, _controller), () => RichButton.dropdown( icon: Icons.format_size, - tooltip: S.current.formatHeadings, + tooltip: tr.richText.headings, actions: List.generate(6, (i) => i + 1) .map( (i) => RichButtonAction.dropdownItem( text: Text( - S.current.formatHeading(i), + tr.richText.heading(i), style: { 'h1': mdTheme.h1, 'h2': mdTheme.h2, @@ -270,7 +273,8 @@ class RichTextField extends StatelessWidget { 'h6': mdTheme.h6, }['h$i']!, ), - defaultContent: '\n${List.filled(i, "#").join("")} ${S.current.formatHeading(i)}\n', + defaultContent: + '\n${List.filled(i, "#").join("")} ${tr.richText.heading(i)}\n', prefix: '\n${List.filled(i, "#").join("")} ', suffix: '\n', selectionStartOffset: 2 + i, @@ -282,26 +286,26 @@ class RichTextField extends StatelessWidget { () => divider, () => RichButton( icon: Icons.format_list_bulleted, - tooltip: S.current.formatBulletList, + tooltip: tr.richText.bulletList, defaultContent: '\n- ', prefix: '\n- ', ).buildButton(context, _controller), () => RichButton( icon: Icons.format_list_numbered, - tooltip: S.current.formatNumberedList, + tooltip: tr.richText.numberedList, defaultContent: '\n1. ', prefix: '\n1. ', ).buildButton(context, _controller), () => RichButton( icon: Icons.check_box_outline_blank, - tooltip: S.current.formatCheckboxListUnchecked, + tooltip: tr.richText.checkList.unchecked, defaultContent: '\n- [ ] ', prefix: '\n- [ ] ', selectionStartOffset: 7, ).buildButton(context, _controller), () => RichButton( icon: Icons.check_box_outlined, - tooltip: S.current.formatCheckboxList, + tooltip: tr.richText.checkList.checked, defaultContent: '\n- [x] ', prefix: '\n- [x] ', selectionStartOffset: 7, @@ -309,7 +313,7 @@ class RichTextField extends StatelessWidget { () => divider, () => RichButton( icon: Icons.link, - tooltip: S.current.formatURL, + tooltip: tr.richText.url, defaultContent: '[text](url)', prefix: '[', suffix: '](url)', @@ -318,7 +322,7 @@ class RichTextField extends StatelessWidget { ).buildButton(context, _controller), () => RichButton( icon: Icons.image, - tooltip: S.current.formatImageURL, + tooltip: tr.richText.imageURL, defaultContent: '![alt](url)', prefix: '![alt][', suffix: ']', @@ -327,13 +331,13 @@ class RichTextField extends StatelessWidget { ).buildButton(context, _controller), () => RichButton( icon: Icons.table_chart_outlined, - tooltip: S.current.formatTable, - defaultContent: '| ${S.current.formatHeader(1)} ' - '| ${S.current.formatHeader(2)} ' + tooltip: tr.richText.table, + defaultContent: '| ${tr.richText.header(1)} ' + '| ${tr.richText.header(2)} ' '|\n|---|---|\n' - '| ${S.current.formatCell(1)} ' - '| ${S.current.formatCell(2)} |', - prefix: '| ${S.current.formatHeader(' ')}|\n|---|\n| ', + '| ${tr.richText.cell(1)} ' + '| ${tr.richText.cell(2)} |', + prefix: '| ${tr.richText.header(' ')}|\n|---|\n| ', suffix: ' |', selectionStartOffset: 2, selectionEndOffset: -43, @@ -360,12 +364,11 @@ class RichTextField extends StatelessWidget { class _RichButton extends StatelessWidget { const _RichButton({ - Key? key, required this.icon, required this.tooltip, this.onTap, this.color, - }) : super(key: key); + }); final Widget icon; final String tooltip; @@ -395,9 +398,9 @@ class _RichButton extends StatelessWidget { class MarkdownPreviewDialog extends StatelessWidget { const MarkdownPreviewDialog({ - Key? key, + super.key, required this.text, - }) : super(key: key); + }); final String text; @@ -405,7 +408,7 @@ class MarkdownPreviewDialog extends StatelessWidget { Widget build(BuildContext context) { return OrientationBuilder(builder: (context, orient) { return AlertDialog( - title: Text(S.current.markdownPreview), + title: Text(tr.richText.markdownPreview), content: ConstrainedBox( constraints: BoxConstraints( minWidth: MediaQuery.of(context).size.width - 100, @@ -414,7 +417,7 @@ class MarkdownPreviewDialog extends StatelessWidget { minHeight: 10, ), child: Markdown( - data: text.trim().isNotEmpty ? text : S.current.noDescription, + data: text.trim().isNotEmpty ? text : tr.generic.noDescription, padding: const EdgeInsets.all(0), onTapLink: (text, href, title) => launchUrl(Uri.parse(href!)), shrinkWrap: true, @@ -525,7 +528,8 @@ class RichButton { ); } - void _wrapWith(TextEditingController controller, String prefix, [String? suffix]) { + void _wrapWith(TextEditingController controller, String prefix, + [String? suffix]) { if (controller.selection.isValid) { // has selection - wrap current cursor positions final selection = controller.selection.copyWith( @@ -533,12 +537,15 @@ class RichButton { extentOffset: controller.selection.extentOffset + prefix.length, ); controller.text = [ - if (controller.selection.start > 0) controller.text.substring(0, controller.selection.start), + if (controller.selection.start > 0) + controller.text.substring(0, controller.selection.start), prefix, - controller.text.substring(controller.selection.start, controller.selection.end), + controller.text + .substring(controller.selection.start, controller.selection.end), suffix ?? prefix, if (controller.selection.end < controller.text.length) - controller.text.substring(controller.selection.end, controller.text.length), + controller.text + .substring(controller.selection.end, controller.text.length), ].join(''); try { controller.selection = selection; @@ -548,17 +555,22 @@ class RichButton { } } - void _append(TextEditingController controller, String text, [int? selectionStartOffset, int? selectionEndOffset]) { + void _append(TextEditingController controller, String text, + [int? selectionStartOffset, int? selectionEndOffset]) { if (controller.selection.isValid) { // has cursor - append at cursor position final selection = controller.selection.copyWith( - baseOffset: controller.selection.baseOffset + (selectionStartOffset ?? 0), - extentOffset: controller.selection.extentOffset + text.length + (selectionEndOffset ?? 0), + baseOffset: + controller.selection.baseOffset + (selectionStartOffset ?? 0), + extentOffset: controller.selection.extentOffset + + text.length + + (selectionEndOffset ?? 0), ); controller.text = [ controller.text.substring(0, controller.selection.start), text, - controller.text.substring(controller.selection.start, controller.text.length), + controller.text + .substring(controller.selection.start, controller.text.length), ].join(''); try { controller.selection = selection; @@ -580,9 +592,10 @@ class RichButton { } } - void Function() _wrapOrAppendCb(TextEditingController controller, String defaultContent, String prefix, + void Function() _wrapOrAppendCb( + TextEditingController controller, String defaultContent, String prefix, [String? suffix, int? selectionStartOffset, int? selectionEndOffset]) { - var _suffix = suffix ?? prefix; + var suffix0 = suffix ?? prefix; // if text is empty, or selection starts directly after newline - remove prefix newlines // if (controller.text.trim().isEmpty || @@ -603,9 +616,10 @@ class RichButton { // } return () { if (!controller.selection.isCollapsed) { - _wrapWith(controller, prefix, _suffix); + _wrapWith(controller, prefix, suffix0); } else { - _append(controller, defaultContent, selectionStartOffset, selectionEndOffset); + _append(controller, defaultContent, selectionStartOffset, + selectionEndOffset); } }; } diff --git a/lib/app/widgets/atoms/round_icon_button.dart b/lib/app/widgets/atoms/round_icon_button.dart index 73302261..e23a26b4 100644 --- a/lib/app/widgets/atoms/round_icon_button.dart +++ b/lib/app/widgets/atoms/round_icon_button.dart @@ -35,10 +35,13 @@ class RoundIconButton extends StatelessWidget { Widget _buildButton(BuildContext context) { final theme = Theme.of(context); final colorScheme = theme.colorScheme; - final bgColor = Color.alphaBlend(backgroundColor ?? Colors.transparent, colorScheme.primary); + final bgColor = Color.alphaBlend( + backgroundColor ?? Colors.transparent, colorScheme.primary); final fgColor = Color.alphaBlend( foregroundColor ?? Colors.transparent, - (ThemeData.estimateBrightnessForColor(bgColor) == Brightness.light ? Colors.black : Colors.white), + (ThemeData.estimateBrightnessForColor(bgColor) == Brightness.light + ? Colors.black + : Colors.white), ); return ElevatedButton( child: IconTheme.merge( diff --git a/lib/app/widgets/atoms/round_roll_button.dart b/lib/app/widgets/atoms/round_roll_button.dart index b6b6dd38..f8d6bbab 100644 --- a/lib/app/widgets/atoms/round_roll_button.dart +++ b/lib/app/widgets/atoms/round_roll_button.dart @@ -3,17 +3,17 @@ import 'package:dungeon_paper/app/model_utils/dice_utils.dart'; import 'package:dungeon_paper/app/themes/colors.dart'; import 'package:dungeon_paper/app/widgets/atoms/round_icon_button.dart'; import 'package:dungeon_paper/core/dw_icons.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:dungeon_world_data/dice.dart'; import 'package:flutter/material.dart'; class RoundRollButton extends StatelessWidget { const RoundRollButton({ - Key? key, + super.key, required this.dice, required this.abilityScores, this.size = 50, - }) : super(key: key); + }); final List dice; final double size; @@ -24,16 +24,22 @@ class RoundRollButton extends StatelessWidget { final isRollingWithDebility = dice.any( (d) => isDebilitated(d), ); - final diceStr = dice.map((d) => d.toString() + (isDebilitated(d) ? ' (-1)*' : '')).join(', '); + final diceStr = dice + .map((d) => d.toString() + (isDebilitated(d) ? ' (-1)*' : '')) + .join(', '); return RoundIconButton( icon: const Icon(DwIcons.dice_d6), - backgroundColor: abilityScores != null && isRollingWithDebility ? DwColors.error.withOpacity(0.5) : null, + backgroundColor: abilityScores != null && isRollingWithDebility + ? DwColors.error.withOpacity(0.5) + : null, onPressed: () => DiceUtils.openRollDialog(dice), tooltip: isRollingWithDebility - ? S.current.rollButtonTooltipWithDebility(diceStr) - : S.current.rollButtonTooltip(diceStr), + ? tr.customRolls.tooltip.rollWithDebility(diceStr) + : tr.customRolls.tooltip.rollNormal(diceStr), ); } - bool isDebilitated(Dice d) => d.modifierStat != null && abilityScores!.getStat(d.modifierStat!).isDebilitated; + bool isDebilitated(Dice d) => + d.modifierStat != null && + abilityScores!.getStat(d.modifierStat!).isDebilitated; } diff --git a/lib/app/widgets/atoms/search_field.dart b/lib/app/widgets/atoms/search_field.dart index 83507cc6..2186e906 100644 --- a/lib/app/widgets/atoms/search_field.dart +++ b/lib/app/widgets/atoms/search_field.dart @@ -1,9 +1,9 @@ -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; class SearchField extends StatelessWidget { const SearchField({ - Key? key, + super.key, required this.controller, this.hintText, this.trailing = const [], @@ -11,7 +11,7 @@ class SearchField extends StatelessWidget { this.elevation, this.enabled, this.autofocus, - }) : super(key: key); + }); final String? hintText; final Widget? suffix; @@ -27,7 +27,8 @@ class SearchField extends StatelessWidget { return Material( elevation: elevation ?? 5, - color: Color.alphaBlend(_getFillColor(theme), theme.scaffoldBackgroundColor), + color: + Color.alphaBlend(_getFillColor(theme), theme.scaffoldBackgroundColor), shape: const StadiumBorder(), shadowColor: Colors.black87, child: Padding( @@ -43,7 +44,7 @@ class SearchField extends StatelessWidget { enabled: enabled, decoration: InputDecoration( filled: false, - hintText: hintText ?? S.current.searchPlaceholder, + hintText: hintText ?? tr.search.placeholder, prefixIcon: const Icon(Icons.search), ), ), diff --git a/lib/app/widgets/atoms/select_box.dart b/lib/app/widgets/atoms/select_box.dart index 2f92209a..14e154bc 100644 --- a/lib/app/widgets/atoms/select_box.dart +++ b/lib/app/widgets/atoms/select_box.dart @@ -88,7 +88,8 @@ class SelectBox extends StatelessWidget { return DropdownButton( alignment: alignment, autofocus: autofocus, - borderRadius: borderRadius ?? rRectShape.borderRadius.resolve(TextDirection.ltr), + borderRadius: + borderRadius ?? rRectShape.borderRadius.resolve(TextDirection.ltr), disabledHint: disabledHint, dropdownColor: dropdownColor, elevation: elevation, diff --git a/lib/app/widgets/atoms/theme_brightness_switch.dart b/lib/app/widgets/atoms/theme_brightness_switch.dart index 1ffd02f6..40ef2bd5 100644 --- a/lib/app/widgets/atoms/theme_brightness_switch.dart +++ b/lib/app/widgets/atoms/theme_brightness_switch.dart @@ -2,11 +2,12 @@ import 'package:dungeon_paper/app/data/models/character.dart'; import 'package:dungeon_paper/app/data/models/user.dart'; import 'package:dungeon_paper/app/data/services/character_service.dart'; import 'package:dungeon_paper/app/data/services/user_service.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -class ThemeBrightnessSwitch extends StatelessWidget with UserServiceMixin, CharacterServiceMixin { +class ThemeBrightnessSwitch extends StatelessWidget + with UserServiceMixin, CharacterServiceMixin { const ThemeBrightnessSwitch({ super.key, required this.builder, @@ -47,11 +48,13 @@ class ThemeBrightnessSwitch extends StatelessWidget with UserServiceMixin, Chara static Brightness brightnessOf(User user) => user.brightness; - static IconData icon(User user) => - brightnessOf(user) == Brightness.light ? Icons.light_mode : Icons.light_mode_outlined; + static IconData icon(User user) => brightnessOf(user) == Brightness.light + ? Icons.light_mode + : Icons.light_mode_outlined; - static String title(User user) => - brightnessOf(user) == Brightness.light ? S.current.themeTurnDark : S.current.themeTurnLight; + static String title(User user) => brightnessOf(user) == Brightness.light + ? tr.settings.switchToDark + : tr.settings.switchToLight; static Widget _listTileBuilder( BuildContext context, { @@ -78,7 +81,8 @@ class ThemeBrightnessSwitch extends StatelessWidget with UserServiceMixin, Chara onPressed: onChanged, ); - static Brightness _toggleTheme(BuildContext context, User user, Character? character) { + static Brightness _toggleTheme( + BuildContext context, User user, Character? character) { final currentIsDark = user.brightness == Brightness.dark; final brightness = currentIsDark ? Brightness.light : Brightness.dark; _updateThemeOnUser(user, character); diff --git a/lib/app/widgets/atoms/xp_bar.dart b/lib/app/widgets/atoms/xp_bar.dart index 2c7e0a6a..7183dab1 100644 --- a/lib/app/widgets/atoms/xp_bar.dart +++ b/lib/app/widgets/atoms/xp_bar.dart @@ -1,17 +1,16 @@ import 'package:dungeon_paper/app/data/services/character_service.dart'; import 'package:dungeon_paper/app/widgets/atoms/buffer_progress_bar.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import '../../../generated/l10n.dart'; - class ExpBar extends StatelessWidget with CharacterServiceMixin { const ExpBar({ - Key? key, + super.key, this.currentXp, this.maxXp, this.pendingXp, - }) : super(key: key); + }); final int? currentXp; final int? maxXp; @@ -45,13 +44,13 @@ class ExpBar extends StatelessWidget with CharacterServiceMixin { Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - Text(S.current.characterBarXp), + Text(tr.home.bars.xp), const SizedBox(width: 8), Text( curValue.toString(), style: const TextStyle(fontWeight: FontWeight.bold), ), - Text('/' + (maxValue?.toString() ?? '-')), + Text('/${maxValue?.toString() ?? '-'}'), if (curPending > 0) Text( '(+$curPending)', diff --git a/lib/app/widgets/cards/character_class_card.dart b/lib/app/widgets/cards/character_class_card.dart index 6ff3e0d6..787333e1 100644 --- a/lib/app/widgets/cards/character_class_card.dart +++ b/lib/app/widgets/cards/character_class_card.dart @@ -1,4 +1,4 @@ -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import '../../data/models/character_class.dart'; @@ -6,7 +6,7 @@ import 'dynamic_action_card.dart'; class CharacterClassCard extends StatelessWidget { const CharacterClassCard({ - Key? key, + super.key, required this.characterClass, this.onSave, this.showDice = true, @@ -18,7 +18,7 @@ class CharacterClassCard extends StatelessWidget { this.maxContentHeight, this.expandable = true, this.highlightWords = const [], - }) : super(key: key); + }); final CharacterClass characterClass; final void Function(CharacterClass characterClass)? onSave; @@ -49,13 +49,13 @@ class CharacterClassCard extends StatelessWidget { } String get _buildMarkdownDescription { - final baseLoadLabel = S.current.formCharacterClassBaseLoad; - final baseHpLabel = S.current.formCharacterClassBaseHp; + final baseLoadLabel = tr.characterClass.baseLoad; + final baseHpLabel = tr.characterClass.baseHp; final table = [ '| $baseHpLabel | $baseLoadLabel |', '| --- | --- |', '| ${characterClass.hp} | ${characterClass.load} |', ].join('\n'); - return characterClass.description + '\n\n' + table; + return '${characterClass.description}\n\n$table'; } } diff --git a/lib/app/widgets/cards/dynamic_action_card.dart b/lib/app/widgets/cards/dynamic_action_card.dart index 2dc122b4..e858c16d 100644 --- a/lib/app/widgets/cards/dynamic_action_card.dart +++ b/lib/app/widgets/cards/dynamic_action_card.dart @@ -4,7 +4,7 @@ import 'package:dungeon_paper/app/widgets/atoms/round_roll_button.dart'; import 'package:dungeon_paper/app/widgets/menus/entity_edit_menu.dart'; import 'package:dungeon_paper/core/utils/markdown_highlight.dart'; import 'package:dungeon_paper/core/utils/markdown_styles.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:dungeon_world_data/dice.dart'; import 'package:flutter/material.dart'; import 'package:flutter_markdown/flutter_markdown.dart'; @@ -12,7 +12,7 @@ import 'package:url_launcher/url_launcher.dart'; class DynamicActionCard extends StatefulWidget { const DynamicActionCard({ - Key? key, + super.key, this.expansionKey, required this.title, required this.icon, @@ -36,8 +36,7 @@ class DynamicActionCard extends StatefulWidget { this.highlightWords = const [], this.abilityScores, this.reorderablePadding = false, - }) : assert(dice.length == 0 || abilityScores != null), - super(key: key); + }) : assert(dice.length == 0 || abilityScores != null); final bool expandable; final double? maxContentHeight; @@ -98,7 +97,8 @@ class _DynamicActionCardState extends State { ), child: widget.starred ? widget.starredIcon ?? const Icon(Icons.star_rounded) - : widget.unstarredIcon ?? const Icon(Icons.star_border_rounded), + : widget.unstarredIcon ?? + const Icon(Icons.star_border_rounded), ), onPressed: () => widget.onStarChanged?.call(!widget.starred), ), @@ -151,7 +151,8 @@ class _DynamicActionCardState extends State { ? children : [ ConstrainedBox( - constraints: BoxConstraints.loose(Size.fromHeight(widget.maxContentHeight!)), + constraints: BoxConstraints.loose( + Size.fromHeight(widget.maxContentHeight!)), child: ListView( shrinkWrap: true, children: children.sublist(0, children.length - 1), @@ -168,7 +169,9 @@ class _DynamicActionCardState extends State { List _buildChildren(BuildContext context) { final bottomHasContent = widget.chips.isNotEmpty || widget.actions - .where((el) => (el is! EntityEditMenu) || (el.onDelete != null || el.onEdit != null)) + .where((el) => + (el is! EntityEditMenu) || + (el.onDelete != null || el.onEdit != null)) .isNotEmpty || widget.dice.isNotEmpty; return [ @@ -180,14 +183,15 @@ class _DynamicActionCardState extends State { // style: Theme.of(context).textTheme.bodyLarge, ) : Text( - S.current.noDescription, + tr.generic.noDescription, style: Theme.of(context).textTheme.bodyLarge, ), // Divider(height: 32, color: dividerColor), if (widget.explanation != null && widget.explanation!.isNotEmpty) ...[ Padding( padding: const EdgeInsets.only(top: 16, bottom: 4), - child: Text(S.current.explanation, style: Theme.of(context).textTheme.bodySmall), + child: Text(tr.generic.explanation, + style: Theme.of(context).textTheme.bodySmall), ), _renderMarkdown(context, widget.explanation!), ], @@ -205,7 +209,8 @@ class _DynamicActionCardState extends State { ), ), ...widget.actions, - if (widget.actions.isNotEmpty && widget.dice.isNotEmpty) const SizedBox(width: 8), + if (widget.actions.isNotEmpty && widget.dice.isNotEmpty) + const SizedBox(width: 8), if (widget.dice.isNotEmpty) Padding( padding: const EdgeInsets.only(bottom: 2.5), diff --git a/lib/app/widgets/cards/dynamic_action_card_mini.dart b/lib/app/widgets/cards/dynamic_action_card_mini.dart index 5c104dbf..587f1144 100644 --- a/lib/app/widgets/cards/dynamic_action_card_mini.dart +++ b/lib/app/widgets/cards/dynamic_action_card_mini.dart @@ -2,7 +2,7 @@ import 'package:dungeon_paper/app/data/models/ability_scores.dart'; import 'package:dungeon_paper/app/themes/themes.dart'; import 'package:dungeon_paper/app/widgets/atoms/round_roll_button.dart'; import 'package:dungeon_paper/core/utils/markdown_styles.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:dungeon_world_data/dice.dart'; import 'package:flutter/material.dart'; import 'package:flutter_markdown/flutter_markdown.dart'; @@ -10,7 +10,7 @@ import 'package:url_launcher/url_launcher.dart'; class DynamicActionCardMini extends StatelessWidget { const DynamicActionCardMini({ - Key? key, + super.key, required this.title, required this.icon, required this.starred, @@ -23,8 +23,7 @@ class DynamicActionCardMini extends StatelessWidget { required this.onStarChanged, this.onTap, this.abilityScores, - }) : assert(dice.length == 0 || abilityScores != null), - super(key: key); + }) : assert(dice.length == 0 || abilityScores != null); final String title; final Widget? icon; @@ -107,7 +106,9 @@ class DynamicActionCardMini extends StatelessWidget { padding: EdgeInsets.zero, iconSize: 16, icon: Icon( - starred ? Icons.star_rounded : Icons.star_border_rounded, + starred + ? Icons.star_rounded + : Icons.star_border_rounded, color: colorScheme.onSurface.withOpacity(0.3), ), onPressed: () => onStarChanged(!starred), @@ -125,18 +126,21 @@ class DynamicActionCardMini extends StatelessWidget { // clipper: RectClipper(constraints.maxWidth, constraints.maxHeight), child: Markdown( padding: EdgeInsets.zero, - data: description.isNotEmpty ? description : S.current.noDescription, + data: description.isNotEmpty + ? description + : tr.generic.noDescription, // fitContent: true, // shrinkWrap: true, // fitContent: true, - styleSheet: MarkdownStyles.of(context).copyWith(textScaleFactor: 0.9), + styleSheet: + MarkdownStyles.of(context).copyWith(textScaleFactor: 0.9), physics: const NeverScrollableScrollPhysics(), onTapLink: (text, href, title) => launchUrl(Uri.parse(href!)), ), ); }), // child: Text( - // description.isNotEmpty ? description : S.current.noDescription, + // description.isNotEmpty ? description : tr.playbook.data.noDescription, // overflow: TextOverflow.ellipsis, // maxLines: dice.isNotEmpty // ? 3 @@ -183,5 +187,6 @@ class RectClipper extends CustomClipper { @override bool shouldReclip(covariant RectClipper oldClipper) => - oldClipper.size.width != size.width || oldClipper.size.height != size.height; + oldClipper.size.width != size.width || + oldClipper.size.height != size.height; } diff --git a/lib/app/widgets/cards/item_card.dart b/lib/app/widgets/cards/item_card.dart index b992ddf6..6b890f43 100644 --- a/lib/app/widgets/cards/item_card.dart +++ b/lib/app/widgets/cards/item_card.dart @@ -68,7 +68,8 @@ class ItemCard extends StatelessWidget { icon: showIcon ? Icon(item.icon, size: 16) : null, starred: item.equipped, showStar: showStar, - onStarChanged: (equipped) => onSave?.call(item.copyWithInherited(equipped: equipped)), + onStarChanged: (equipped) => + onSave?.call(item.copyWithInherited(equipped: equipped)), actions: actions, expansionKey: expansionKey ?? PageStorageKey(item.key), highlightWords: highlightWords, diff --git a/lib/app/widgets/cards/item_card_mini.dart b/lib/app/widgets/cards/item_card_mini.dart index 74e73335..9495fa32 100644 --- a/lib/app/widgets/cards/item_card_mini.dart +++ b/lib/app/widgets/cards/item_card_mini.dart @@ -47,7 +47,8 @@ class ItemCardMini extends StatelessWidget { icon: showIcon ? Icon(item.icon, size: 16) : null, starred: item.equipped, showStar: showStar, - onStarChanged: (equipped) => onSave?.call(item.copyWithInherited(equipped: equipped)), + onStarChanged: (equipped) => + onSave?.call(item.copyWithInherited(equipped: equipped)), onTap: onTap, ); } diff --git a/lib/app/widgets/cards/move_card.dart b/lib/app/widgets/cards/move_card.dart index 4fa1f5a1..0a74f98b 100644 --- a/lib/app/widgets/cards/move_card.dart +++ b/lib/app/widgets/cards/move_card.dart @@ -55,12 +55,15 @@ class MoveCard extends StatelessWidget { icon: showIcon ? Icon(move.icon, size: 16) : null, starred: move.favorite, showStar: showStar, - onStarChanged: (favorite) => onSave?.call(move.copyWithInherited(favorite: favorite)), + onStarChanged: (favorite) => + onSave?.call(move.copyWithInherited(favorite: favorite)), initiallyExpanded: initiallyExpanded, actions: actions, highlightWords: highlightWords, leading: [ - MoveCategoryChip(category: move.category, advancedLevelDisplay: advancedLevelDisplay), + MoveCategoryChip( + category: move.category, + advancedLevelDisplay: advancedLevelDisplay), ], abilityScores: abilityScores, ); diff --git a/lib/app/widgets/cards/move_card_mini.dart b/lib/app/widgets/cards/move_card_mini.dart index e6469251..a2b1c362 100644 --- a/lib/app/widgets/cards/move_card_mini.dart +++ b/lib/app/widgets/cards/move_card_mini.dart @@ -40,7 +40,8 @@ class MoveCardMini extends StatelessWidget { icon: showIcon ? Icon(move.icon, size: 16) : null, starred: move.favorite, showStar: showStar, - onStarChanged: (favorite) => onSave?.call(move.copyWithInherited(favorite: favorite)), + onStarChanged: (favorite) => + onSave?.call(move.copyWithInherited(favorite: favorite)), onTap: onTap, abilityScores: abilityScores, ); diff --git a/lib/app/widgets/cards/note_card.dart b/lib/app/widgets/cards/note_card.dart index 658c7fc1..90a8b627 100644 --- a/lib/app/widgets/cards/note_card.dart +++ b/lib/app/widgets/cards/note_card.dart @@ -47,7 +47,8 @@ class NoteCard extends StatelessWidget { icon: showIcon ? Icon(note.icon, size: 16) : null, starred: note.favorite, showStar: showStar, - onStarChanged: (favorite) => onSave?.call(note.copyWith(favorite: favorite)), + onStarChanged: (favorite) => + onSave?.call(note.copyWith(favorite: favorite)), actions: actions, expansionKey: expansionKey ?? PageStorageKey(note.key), highlightWords: highlightWords, diff --git a/lib/app/widgets/cards/note_card_mini.dart b/lib/app/widgets/cards/note_card_mini.dart index b42ec764..4a14178b 100644 --- a/lib/app/widgets/cards/note_card_mini.dart +++ b/lib/app/widgets/cards/note_card_mini.dart @@ -29,7 +29,8 @@ class NoteCardMini extends StatelessWidget { icon: showIcon ? Icon(note.icon, size: 16) : null, starred: note.favorite, showStar: showStar, - onStarChanged: (favorite) => onSave?.call(note.copyWith(favorite: favorite)), + onStarChanged: (favorite) => + onSave?.call(note.copyWith(favorite: favorite)), onTap: onTap, ); } diff --git a/lib/app/widgets/cards/race_card.dart b/lib/app/widgets/cards/race_card.dart index 13a5cb88..13471e2f 100644 --- a/lib/app/widgets/cards/race_card.dart +++ b/lib/app/widgets/cards/race_card.dart @@ -50,7 +50,8 @@ class RaceCard extends StatelessWidget { icon: showIcon ? Icon(race.icon, size: 16) : null, starred: race.favorite, showStar: showStar, - onStarChanged: (favorite) => onSave?.call(race.copyWithInherited(favorite: favorite)), + onStarChanged: (favorite) => + onSave?.call(race.copyWithInherited(favorite: favorite)), initiallyExpanded: initiallyExpanded, actions: actions, highlightWords: highlightWords, diff --git a/lib/app/widgets/cards/race_card_mini.dart b/lib/app/widgets/cards/race_card_mini.dart index 10d8e6cf..814d6e96 100644 --- a/lib/app/widgets/cards/race_card_mini.dart +++ b/lib/app/widgets/cards/race_card_mini.dart @@ -29,7 +29,8 @@ class RaceCardMini extends StatelessWidget { icon: showIcon ? Icon(race.icon, size: 16) : null, starred: race.favorite, showStar: showStar, - onStarChanged: (favorite) => onSave?.call(race.copyWithInherited(favorite: favorite)), + onStarChanged: (favorite) => + onSave?.call(race.copyWithInherited(favorite: favorite)), onTap: onTap, ); } diff --git a/lib/app/widgets/cards/spell_card.dart b/lib/app/widgets/cards/spell_card.dart index f23c9c10..2d361d7d 100644 --- a/lib/app/widgets/cards/spell_card.dart +++ b/lib/app/widgets/cards/spell_card.dart @@ -52,7 +52,8 @@ class SpellCard extends StatelessWidget { icon: showIcon ? Icon(spell.icon, size: 16) : null, starred: spell.prepared, showStar: showStar, - onStarChanged: (prepared) => onSave?.call(spell.copyWithInherited(prepared: prepared)), + onStarChanged: (prepared) => + onSave?.call(spell.copyWithInherited(prepared: prepared)), initiallyExpanded: initiallyExpanded, actions: actions, expansionKey: expansionKey ?? PageStorageKey(spell.key), diff --git a/lib/app/widgets/cards/spell_card_mini.dart b/lib/app/widgets/cards/spell_card_mini.dart index 6c2a480d..323d407f 100644 --- a/lib/app/widgets/cards/spell_card_mini.dart +++ b/lib/app/widgets/cards/spell_card_mini.dart @@ -35,7 +35,8 @@ class SpellCardMini extends StatelessWidget { icon: showIcon ? Icon(spell.icon, size: 16) : null, starred: spell.prepared, showStar: showStar, - onStarChanged: (prepared) => onSave?.call(spell.copyWithInherited(prepared: prepared)), + onStarChanged: (prepared) => + onSave?.call(spell.copyWithInherited(prepared: prepared)), onTap: onTap, abilityScores: abilityScores, ); diff --git a/lib/app/widgets/chips/ability_score_chip.dart b/lib/app/widgets/chips/ability_score_chip.dart index 568351f4..f8c4454c 100644 --- a/lib/app/widgets/chips/ability_score_chip.dart +++ b/lib/app/widgets/chips/ability_score_chip.dart @@ -10,7 +10,8 @@ class AbilityScoreChip extends StatelessWidget { final AbilityScore stat; final bool showDice; - const AbilityScoreChip({Key? key, required this.stat, this.showDice = true}) : super(key: key); + const AbilityScoreChip({Key? key, required this.stat, this.showDice = true}) + : super(key: key); @override Widget build(BuildContext context) { @@ -24,7 +25,8 @@ class AbilityScoreChip extends StatelessWidget { final rollBadgeModifierOpacity = isDark ? 0.5 : 0.4; final isLight = theme.brightness == Brightness.light; final cardColor = stat.isDebilitated - ? Color.alphaBlend(DwColors.error.withOpacity(isLight ? 0.4 : 0.2), theme.scaffoldBackgroundColor) + ? Color.alphaBlend(DwColors.error.withOpacity(isLight ? 0.4 : 0.2), + theme.scaffoldBackgroundColor) // : Color.alphaBlend(theme.cardColor.withOpacity(0.5), theme.scaffoldBackgroundColor); : theme.cardColor; @@ -33,7 +35,8 @@ class AbilityScoreChip extends StatelessWidget { color: cardColor, child: InkWell( splashColor: Theme.of(context).splashColor, - onTap: () => DiceUtils.openRollDialog([dw.Dice(amount: 2, sides: 6, modifierStat: stat.key)]), + onTap: () => DiceUtils.openRollDialog( + [dw.Dice(amount: 2, sides: 6, modifierStat: stat.key)]), borderRadius: borderRadius, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8), @@ -46,7 +49,8 @@ class AbilityScoreChip extends StatelessWidget { children: [ IconTheme( child: Icon(stat.icon), - data: IconThemeData(size: 18, color: theme.colorScheme.onSurface), + data: IconThemeData( + size: 18, color: theme.colorScheme.onSurface), ), const SizedBox(width: 4), SizedBox( @@ -73,14 +77,16 @@ class AbilityScoreChip extends StatelessWidget { child: const Icon(DwIcons.dice_d6), data: IconTheme.of(context).copyWith( size: 12, - color: theme.colorScheme.onSurface.withOpacity(rollBadgeModifierOpacity), + color: theme.colorScheme.onSurface + .withOpacity(rollBadgeModifierOpacity), ), ), const SizedBox(width: 2), Text( '$modSign$modStr', // textScaleFactor: 0.8, - style: TextStyle(color: theme.colorScheme.onSurface), + style: TextStyle( + color: theme.colorScheme.onSurface), //.withOpacity(rollBadgeModifierOpacity), ), ], diff --git a/lib/app/widgets/chips/advanced_chip.dart b/lib/app/widgets/chips/advanced_chip.dart index b83cf1bf..bea9d5fe 100644 --- a/lib/app/widgets/chips/advanced_chip.dart +++ b/lib/app/widgets/chips/advanced_chip.dart @@ -147,7 +147,8 @@ class AdvancedChip extends StatelessWidget selectedShadowColor: selectedShadowColor, showCheckmark: showCheckmark, checkmarkColor: checkmarkColor, - isEnabled: isEnabled, // && (onSelected != null || onDeleted != null || onPressed != null), + isEnabled: + isEnabled, // && (onSelected != null || onDeleted != null || onPressed != null), avatarBorder: avatarBorder, iconTheme: iconTheme, surfaceTintColor: surfaceTintColor, @@ -155,5 +156,6 @@ class AdvancedChip extends StatelessWidget } @override - MaterialStateProperty? get color => MaterialStatePropertyAll(backgroundColor); + MaterialStateProperty? get color => + MaterialStatePropertyAll(backgroundColor); } diff --git a/lib/app/widgets/chips/item_amount_chip.dart b/lib/app/widgets/chips/item_amount_chip.dart index 70d3f3ca..9dd4e7a5 100644 --- a/lib/app/widgets/chips/item_amount_chip.dart +++ b/lib/app/widgets/chips/item_amount_chip.dart @@ -1,15 +1,15 @@ import 'package:dungeon_paper/app/data/models/item.dart'; import 'package:dungeon_paper/app/widgets/chips/primary_chip.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; -import '../../../generated/l10n.dart'; class ItemAmountChip extends StatelessWidget { const ItemAmountChip({ - Key? key, + super.key, required this.item, this.visualDensity, - }) : super(key: key); + }); final Item item; final VisualDensity? visualDensity; @@ -17,8 +17,8 @@ class ItemAmountChip extends StatelessWidget { @override Widget build(BuildContext context) { return PrimaryChip( - label: S.current.itemAmountX(NumberFormat('#.##').format(item.amount)), - tooltip: S.current.amount, + label: tr.items.amount(NumberFormat('#.##').format(item.amount)), + tooltip: tr.items.amountTooltip, visualDensity: visualDensity ?? VisualDensity.compact, ); } diff --git a/lib/app/widgets/chips/item_damage_chip.dart b/lib/app/widgets/chips/item_damage_chip.dart index 3a29575f..e3720d7c 100644 --- a/lib/app/widgets/chips/item_damage_chip.dart +++ b/lib/app/widgets/chips/item_damage_chip.dart @@ -19,7 +19,8 @@ class ItemDamageChip extends StatelessWidget { Widget build(BuildContext context) { return PrimaryChip( icon: const Icon(DwIcons.dice_d6_numbered), - label: (item.damage.isNegative ? '-' : '+') + NumberFormat('#.#').format(item.damage.abs()), + label: (item.damage.isNegative ? '-' : '+') + + NumberFormat('#.#').format(item.damage.abs()), tooltip: dw.dungeonWorldData.tags['Damage']!.description, visualDensity: visualDensity ?? VisualDensity.compact, ); diff --git a/lib/app/widgets/chips/move_category_chip.dart b/lib/app/widgets/chips/move_category_chip.dart index 9f77a005..58798303 100644 --- a/lib/app/widgets/chips/move_category_chip.dart +++ b/lib/app/widgets/chips/move_category_chip.dart @@ -1,16 +1,16 @@ import 'package:dungeon_paper/app/widgets/chips/primary_chip.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; -import '../../../generated/l10n.dart'; import '../../data/models/move.dart'; class MoveCategoryChip extends StatelessWidget { const MoveCategoryChip({ - Key? key, + super.key, required this.category, this.visualDensity, this.advancedLevelDisplay = AdvancedLevelDisplay.none, - }) : super(key: key); + }); final MoveCategory category; final AdvancedLevelDisplay advancedLevelDisplay; @@ -27,11 +27,11 @@ class MoveCategoryChip extends StatelessWidget { String get _text { switch (advancedLevelDisplay) { case AdvancedLevelDisplay.none: - return S.current.moveCategory(category); + return tr.moves.category.shortName(category.name); case AdvancedLevelDisplay.short: - return S.current.moveCategoryWithLevelShort(category); + return tr.moves.category.mediumName(category.name); case AdvancedLevelDisplay.full: - return S.current.moveCategoryWithLevel(category); + return tr.moves.category.longName(category.name); } } } diff --git a/lib/app/widgets/chips/primary_chip.dart b/lib/app/widgets/chips/primary_chip.dart index bdcc0040..6de40483 100644 --- a/lib/app/widgets/chips/primary_chip.dart +++ b/lib/app/widgets/chips/primary_chip.dart @@ -31,7 +31,8 @@ class PrimaryChip extends StatelessWidget { final colorScheme = theme.colorScheme; final isLight = theme.brightness == Brightness.light; final fgColor = isLight ? colorScheme.onPrimary : colorScheme.onSecondary; - final bgColor = backgroundColor ?? (isLight ? colorScheme.primary : colorScheme.secondary); + final bgColor = backgroundColor ?? + (isLight ? colorScheme.primary : colorScheme.secondary); final isCompact = visualDensity == VisualDensity.compact; final hasIcon = icon != null; diff --git a/lib/app/widgets/chips/spell_level_chip.dart b/lib/app/widgets/chips/spell_level_chip.dart index 6b766969..058f50ac 100644 --- a/lib/app/widgets/chips/spell_level_chip.dart +++ b/lib/app/widgets/chips/spell_level_chip.dart @@ -1,14 +1,13 @@ import 'package:dungeon_paper/app/widgets/chips/primary_chip.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; -import '../../../generated/l10n.dart'; - class SpellLevelChip extends StatelessWidget { const SpellLevelChip({ - Key? key, + super.key, required this.level, this.visualDensity, - }) : super(key: key); + }); final String level; final VisualDensity? visualDensity; @@ -16,7 +15,7 @@ class SpellLevelChip extends StatelessWidget { @override Widget build(BuildContext context) { return PrimaryChip( - label: S.current.spellLevel(level), + label: tr.spells.spellLevel(level), visualDensity: visualDensity ?? VisualDensity.compact, ); } diff --git a/lib/app/widgets/dialogs/add_dice_dialog.dart b/lib/app/widgets/dialogs/add_dice_dialog.dart index b0e0390f..9188772e 100644 --- a/lib/app/widgets/dialogs/add_dice_dialog.dart +++ b/lib/app/widgets/dialogs/add_dice_dialog.dart @@ -1,20 +1,20 @@ import 'package:dungeon_paper/app/data/models/ability_scores.dart'; import 'package:dungeon_paper/app/data/services/repository_service.dart'; import 'package:dungeon_paper/app/widgets/forms/dice_form.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; -import 'package:flutter/material.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; +import 'package:flutter/material.dart'; import 'package:get/get.dart'; enum ModifierType { stat, fixed } class AddDiceDialog extends StatefulWidget { const AddDiceDialog({ - Key? key, + super.key, this.dice, this.onSave, required this.abilityScores, - }) : super(key: key); + }); final dw.Dice? dice; final void Function(dw.Dice dice)? onSave; @@ -24,7 +24,8 @@ class AddDiceDialog extends StatefulWidget { State createState() => _AddDiceDialogState(); } -class _AddDiceDialogState extends State with RepositoryServiceMixin { +class _AddDiceDialogState extends State + with RepositoryServiceMixin { late dw.Dice dice; @override @@ -37,12 +38,14 @@ class _AddDiceDialogState extends State with RepositoryServiceMix Widget build(BuildContext context) { return AlertDialog( title: Text( - widget.dice == null ? S.current.addGeneric(dw.Dice) : S.current.editGeneric(dw.Dice), + widget.dice == null + ? tr.generic.addEntity(tr.entity(dw.Dice)) + : tr.generic.editEntity(tr.entity(dw.Dice)), ), content: SingleChildScrollView( child: DiceForm( dice: dice, - onChanged: (dw.Dice _dice) => setState(() => dice = _dice), + onChanged: (dw.Dice dice) => setState(() => dice = dice), abilityScores: widget.abilityScores, ), ), @@ -52,7 +55,7 @@ class _AddDiceDialogState extends State with RepositoryServiceMix widget.onSave?.call(dice); Get.back(); }, - child: Text(S.current.save), + child: Text(tr.generic.save), ), ], ); diff --git a/lib/app/widgets/dialogs/add_tag_dialog.dart b/lib/app/widgets/dialogs/add_tag_dialog.dart index 40c46c75..26ad64c2 100644 --- a/lib/app/widgets/dialogs/add_tag_dialog.dart +++ b/lib/app/widgets/dialogs/add_tag_dialog.dart @@ -1,17 +1,17 @@ import 'package:dungeon_paper/app/data/services/repository_service.dart'; import 'package:dungeon_paper/app/widgets/atoms/menu_button.dart'; import 'package:dungeon_paper/core/utils/string_utils.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; -import 'package:flutter/material.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; +import 'package:flutter/material.dart'; import 'package:get/get.dart'; class AddTagDialog extends StatefulWidget { const AddTagDialog({ - Key? key, + super.key, this.tag, this.onSave, - }) : super(key: key); + }); final dw.Tag? tag; final void Function(dw.Tag tag)? onSave; @@ -39,13 +39,12 @@ class _AddTagDialogState extends State { return AlertDialog( title: Row( children: [ - Expanded(child: Text(S.current.createGeneric(dw.Tag))), + Expanded(child: Text(tr.generic.createEntity(tr.entity(dw.Tag)))), MenuButton( - child: const Icon(Icons.list), items: [ for (final tag in allTags) MenuEntry( - label: Text(S.current.tagCopyFrom(toTitleCase(tag.name))), + label: Text(tr.tags.copyFrom(toTitleCase(tag.name))), value: tag, onSelect: () { setState(() { @@ -56,6 +55,7 @@ class _AddTagDialogState extends State { }, ) ], + child: const Icon(Icons.list), ) ], ), @@ -68,7 +68,7 @@ class _AddTagDialogState extends State { decoration: InputDecoration( filled: true, label: Text( - S.current.genericNameField(S.current.entity(dw.Tag)), + tr.generic.entityName(tr.entity(dw.Tag)), ), ), ), @@ -81,7 +81,7 @@ class _AddTagDialogState extends State { decoration: InputDecoration( filled: true, label: Text( - S.current.genericValueField(S.current.entity(dw.Tag)), + tr.generic.entityValue(tr.entity(dw.Tag)), ), ), ), @@ -94,7 +94,7 @@ class _AddTagDialogState extends State { decoration: InputDecoration( filled: true, label: Text( - S.current.genericDescriptionField(S.current.entity(dw.Tag)), + tr.generic.entityDescription(tr.entity(dw.Tag)), ), ), ), @@ -106,7 +106,7 @@ class _AddTagDialogState extends State { widget.onSave?.call(createTag()); Get.back(); }, - child: Text(S.current.save), + child: Text(tr.generic.save), ), ], ); @@ -118,8 +118,9 @@ class _AddTagDialogState extends State { value: tryParse(value.text), ); - List get allTags => {...repo.my.tags.values, ...repo.builtIn.tags.values}.toList() - ..sort((a, b) => a.name.toLowerCase().compareTo(b.name.toLowerCase())); + List get allTags => + {...repo.my.tags.values, ...repo.builtIn.tags.values}.toList() + ..sort((a, b) => a.name.toLowerCase().compareTo(b.name.toLowerCase())); dynamic tryParse(String text) { if (RegExp(r'[a-z]').hasMatch(text)) { diff --git a/lib/app/widgets/dialogs/armor_dialog.dart b/lib/app/widgets/dialogs/armor_dialog.dart index 4b031975..3781cad7 100644 --- a/lib/app/widgets/dialogs/armor_dialog.dart +++ b/lib/app/widgets/dialogs/armor_dialog.dart @@ -1,7 +1,7 @@ import 'package:dungeon_paper/app/widgets/atoms/number_text_field.dart'; import 'package:dungeon_paper/app/widgets/molecules/dialog_controls.dart'; import 'package:dungeon_paper/core/dw_icons.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -29,7 +29,8 @@ class _ArmorDialogState extends State { void initState() { super.initState(); useDefault = widget.armor == null; - controller = TextEditingController(text: widget.armor?.toString() ?? widget.defaultArmor.toString()); + controller = TextEditingController( + text: widget.armor?.toString() ?? widget.defaultArmor.toString()); controller.addListener(_listener); } @@ -40,7 +41,7 @@ class _ArmorDialogState extends State { children: [ const Icon(DwIcons.armor, size: 32), const SizedBox(width: 12), - Expanded(child: Text(S.current.armor)), + Expanded(child: Text(tr.armor.dialog.title)), ], ), content: SingleChildScrollView( @@ -48,15 +49,15 @@ class _ArmorDialogState extends State { children: [ CheckboxListTile( // minLeadingWidth: 20, - title: Text(S.current.characterAutoArmor), + title: Text(tr.armor.dialog.title), dense: true, visualDensity: VisualDensity.compact, controlAffinity: ListTileControlAffinity.leading, value: useDefault, onChanged: (value) => setState(() { - final _value = value ?? !useDefault; - useDefault = _value; - if (_value) { + final newValue = value ?? !useDefault; + useDefault = newValue; + if (newValue) { controller.text = '${widget.defaultArmor}'; } }), @@ -65,7 +66,8 @@ class _ArmorDialogState extends State { NumberTextField( controller: controller, numberType: NumberType.int, - decoration: InputDecoration(hintText: '0', label: Text(S.current.armor)), + decoration: InputDecoration( + hintText: '0', label: Text(tr.armor.dialog.title)), minValue: 0, enabled: !useDefault, ) diff --git a/lib/app/widgets/dialogs/character_bio_dialog.dart b/lib/app/widgets/dialogs/character_bio_dialog.dart index c4f99ebe..c8a02d8b 100644 --- a/lib/app/widgets/dialogs/character_bio_dialog.dart +++ b/lib/app/widgets/dialogs/character_bio_dialog.dart @@ -3,14 +3,14 @@ import 'package:dungeon_paper/app/modules/BioForm/controllers/bio_form_controlle import 'package:dungeon_paper/app/routes/app_pages.dart'; import 'package:dungeon_paper/app/widgets/molecules/dialog_controls.dart'; import 'package:dungeon_paper/core/utils/markdown_styles.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:flutter_markdown/flutter_markdown.dart'; import 'package:get/get.dart'; import 'package:url_launcher/url_launcher.dart'; class CharacterBioDialog extends GetView with CharacterServiceMixin { - const CharacterBioDialog({Key? key}) : super(key: key); + const CharacterBioDialog({super.key}); @override Widget build(BuildContext context) { @@ -21,10 +21,11 @@ class CharacterBioDialog extends GetView with CharacterServiceMixin { title: Row( mainAxisSize: MainAxisSize.max, children: [ - Expanded(child: Text(S.current.characterBioDialogTitle)), + Expanded(child: Text(tr.bio.dialog.title)), IconButton( onPressed: () { - Get.toNamed(Routes.bio, arguments: BioFormArguments(character: character)); + Get.toNamed(Routes.bio, + arguments: BioFormArguments(character: character)); }, icon: const Icon(Icons.edit, size: 20), ) @@ -41,16 +42,17 @@ class CharacterBioDialog extends GetView with CharacterServiceMixin { crossAxisAlignment: CrossAxisAlignment.start, // shrinkWrap: true, children: [ - Text(S.current.characterBioDialogDescLabel, style: textTheme.bodySmall), + Text(tr.bio.dialog.description.label, + style: textTheme.bodySmall), char.bio.description.isNotEmpty ? MarkdownBody( data: char.bio.description, onTapLink: (_, url, __) => launchUrl(Uri.parse(url!)), styleSheet: MarkdownStyles.of(context), ) - : Text(S.current.noDescription), + : Text(tr.generic.noDescription), const SizedBox(height: 16), - Text(S.current.characterBioDialogLooksLabel, style: textTheme.bodySmall), + Text(tr.bio.dialog.looks.label, style: textTheme.bodySmall), char.bio.looks.isNotEmpty ? Text(char.bio.looks, style: textTheme.bodyLarge) // TODO broken...?! @@ -71,22 +73,23 @@ class CharacterBioDialog extends GetView with CharacterServiceMixin { // , // ) // ) - : Text(S.current.noDescription), + : Text(tr.generic.noDescription), const SizedBox(height: 16), Row( children: [ Text( - S.current.characterBioDialogAlignmentNameDisplayLabel, + '${tr.bio.dialog.alignment.label}: ', style: textTheme.bodySmall, ), const SizedBox(width: 4), IconTheme.merge( - data: IconThemeData(size: 14, color: textTheme.bodySmall!.color!), + data: IconThemeData( + size: 14, color: textTheme.bodySmall!.color!), child: Icon(char.bio.alignment.icon), ), const SizedBox(width: 4), Text( - S.current.alignment(char.bio.alignment.key), + tr.alignment.name(char.bio.alignment.key), style: textTheme.bodySmall, ), ], @@ -96,7 +99,7 @@ class CharacterBioDialog extends GetView with CharacterServiceMixin { data: char.bio.alignment.description, onTapLink: (_, url, __) => launchUrl(Uri.parse(url!)), ) - : Text(S.current.noDescription), + : Text(tr.generic.noDescription), ], ), ), diff --git a/lib/app/widgets/dialogs/character_bonds_flags_dialog.dart b/lib/app/widgets/dialogs/character_bonds_flags_dialog.dart index 97dc94f9..3cddf9c7 100644 --- a/lib/app/widgets/dialogs/character_bonds_flags_dialog.dart +++ b/lib/app/widgets/dialogs/character_bonds_flags_dialog.dart @@ -5,12 +5,13 @@ import 'package:dungeon_paper/app/routes/app_pages.dart'; import 'package:dungeon_paper/app/widgets/atoms/help_text.dart'; import 'package:dungeon_paper/app/widgets/molecules/dialog_controls.dart'; import 'package:dungeon_paper/core/utils/list_utils.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -class CharacterBondsFlagsDialog extends GetView with CharacterServiceMixin { - const CharacterBondsFlagsDialog({Key? key}) : super(key: key); +class CharacterBondsFlagsDialog extends GetView + with CharacterServiceMixin { + const CharacterBondsFlagsDialog({super.key}); List get bonds => char.bonds; List get flags => char.flags; @@ -26,7 +27,8 @@ class CharacterBondsFlagsDialog extends GetView with Character mainAxisSize: MainAxisSize.max, children: [ Expanded( - child: Obx(() => Text(SessionMark.categoryTitle(bonds: bonds, flags: flags))), + child: Obx(() => + Text(SessionMark.categoryTitle(bonds: bonds, flags: flags))), ), IconButton( onPressed: () { @@ -64,20 +66,20 @@ class CharacterBondsFlagsDialog extends GetView with Character Padding( padding: const EdgeInsets.symmetric(horizontal: 8), child: HelpText( - text: S.current.characterBondsFlagsDialogNoData, + text: tr.sessionMarks.noData, ), ), if (bonds.isNotEmpty || flags.isNotEmpty) ...[ Padding( padding: const EdgeInsets.symmetric(horizontal: 8), child: HelpText( - text: S.current.characterBondsFlagsDialogInfoText, + text: tr.sessionMarks.info, ), ), const Divider(height: 32), ], if (bonds.isNotEmpty && flags.isNotEmpty) - Text(S.current.characterBondsFlagsDialogBonds, style: textTheme.bodySmall), + Text(tr.sessionMarks.bond, style: textTheme.bodySmall), for (final bond in bonds) ...[ CheckboxListTile( title: Text(bond.description), @@ -90,7 +92,7 @@ class CharacterBondsFlagsDialog extends GetView with Character ], if (bonds.isNotEmpty && flags.isNotEmpty) ...[ const Divider(height: 32), - Text(S.current.characterBondsFlagsDialogFlags, style: textTheme.bodySmall), + Text(tr.sessionMarks.flags, style: textTheme.bodySmall), ], for (final flag in flags) ...[ CheckboxListTile( diff --git a/lib/app/widgets/dialogs/coins_dialog.dart b/lib/app/widgets/dialogs/coins_dialog.dart index a0125090..bc0245dd 100644 --- a/lib/app/widgets/dialogs/coins_dialog.dart +++ b/lib/app/widgets/dialogs/coins_dialog.dart @@ -1,10 +1,11 @@ -import 'package:dungeon_paper/app/widgets/atoms/number_text_field.dart'; -import 'package:dungeon_paper/app/widgets/molecules/dialog_controls.dart'; -import 'package:dungeon_paper/core/dw_icons.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import '../../../core/dw_icons.dart'; +import '../atoms/number_text_field.dart'; +import '../molecules/dialog_controls.dart'; + class CoinsDialog extends StatefulWidget { const CoinsDialog({ super.key, @@ -35,7 +36,7 @@ class _CoinsDialogState extends State { children: [ const Icon(DwIcons.coin_stack, size: 32), const SizedBox(width: 12), - Expanded(child: Text(S.current.coins)), + Expanded(child: Text(tr.character.data.coins)), ], ), content: SingleChildScrollView( @@ -43,7 +44,8 @@ class _CoinsDialogState extends State { children: [ NumberTextField( controller: controller, - decoration: InputDecoration(hintText: '0', label: Text(S.current.coins)), + decoration: InputDecoration( + hintText: '0', label: Text(tr.character.data.coins)), numberType: NumberType.double, minValue: 0.0, ) diff --git a/lib/app/widgets/dialogs/confirm_delete_account_dialog.dart b/lib/app/widgets/dialogs/confirm_delete_account_dialog.dart index 9ab7ab39..0847d209 100644 --- a/lib/app/widgets/dialogs/confirm_delete_account_dialog.dart +++ b/lib/app/widgets/dialogs/confirm_delete_account_dialog.dart @@ -1,5 +1,5 @@ import 'package:dungeon_paper/app/widgets/molecules/dialog_controls.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -8,10 +8,11 @@ import '../../../core/utils/dialog_utils.dart'; Future confirmDeleteAccount1(BuildContext context) { return Get.dialog( AlertDialog( - title: Text(S.current.confirmDeleteAccount1Title), - content: Text(S.current.confirmDeleteAccount1Body), + title: Text(tr.dialogs.confirmations.deleteAccount.step1.title), + content: Text(tr.dialogs.confirmations.deleteAccount.step1.body), actions: DialogControls.delete(context, - onDelete: () => Get.back(result: true), onCancel: () => Get.back(result: false)), + onDelete: () => Get.back(result: true), + onCancel: () => Get.back(result: false)), ), ).then((res) => res == true); } @@ -19,13 +20,18 @@ Future confirmDeleteAccount1(BuildContext context) { Future confirmDeleteAccount2(BuildContext context) { return Get.dialog( AlertDialog( - title: Text(S.current.confirmDeleteAccount2Title), - content: Text(S.current.confirmDeleteAccount2Body), + title: Text(tr.dialogs.confirmations.deleteAccount.step2.title), + content: Text(tr.dialogs.confirmations.deleteAccount.step2.body), actions: DialogControls.delete(context, - onDelete: () => Get.back(result: true), onCancel: () => Get.back(result: false)), + onDelete: () => Get.back(result: true), + onCancel: () => Get.back(result: false)), ), ).then((res) => res == true); } -Future awaitDeleteAccountConfirmation(BuildContext context, void Function() onConfirmed) => awaitConfirmation( - confirmDeleteAccount1(context), () => awaitConfirmation(confirmDeleteAccount2(context), onConfirmed)); +Future awaitDeleteAccountConfirmation( + BuildContext context, void Function() onConfirmed) => + awaitConfirmation( + confirmDeleteAccount1(context), + () => + awaitConfirmation(confirmDeleteAccount2(context), onConfirmed)); diff --git a/lib/app/widgets/dialogs/confirm_delete_dialog.dart b/lib/app/widgets/dialogs/confirm_delete_dialog.dart index da971029..7ea140b5 100644 --- a/lib/app/widgets/dialogs/confirm_delete_dialog.dart +++ b/lib/app/widgets/dialogs/confirm_delete_dialog.dart @@ -1,5 +1,5 @@ import 'package:dungeon_paper/app/widgets/molecules/dialog_controls.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -7,14 +7,19 @@ import '../../../core/utils/dialog_utils.dart'; class _DeleteDialog extends ConfirmationDialog { @override - Widget createConfirmation(BuildContext context, DeleteDialogOptions options) { + Widget createConfirmation( + BuildContext context, DeleteDialogOptions options) { return AlertDialog( - title: Text(S.current.confirmDeleteTitle(options.entityKind)), + title: Text(tr.dialogs.confirmations.delete.title(options.entityKind)), content: Text( - S.current.confirmDeleteBody(options.entityKind, options.entityName), + tr.dialogs.confirmations.delete + .body(options.entityKind, options.entityName), + ), + actions: DialogControls.delete( + context, + onDelete: () => Get.back(result: true), + onCancel: () => Get.back(result: false), ), - actions: DialogControls.delete(context, - onDelete: () => Get.back(result: true), onCancel: () => Get.back(result: false)), ); } } diff --git a/lib/app/widgets/dialogs/confirm_unlink_provider_dialog.dart b/lib/app/widgets/dialogs/confirm_unlink_provider_dialog.dart index f82975c5..c1f0050c 100644 --- a/lib/app/widgets/dialogs/confirm_unlink_provider_dialog.dart +++ b/lib/app/widgets/dialogs/confirm_unlink_provider_dialog.dart @@ -1,20 +1,23 @@ import 'package:dungeon_paper/app/widgets/molecules/dialog_controls.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../../core/utils/dialog_utils.dart'; import '../../model_utils/user_utils.dart'; -Future confirmUnlinkProvider(BuildContext context, ProviderName provider) { +Future confirmUnlinkProvider( + BuildContext context, ProviderName provider) { return Get.dialog( AlertDialog( - title: Text(S.current.confirmUnlinkProviderTitle(S.current.signinProvider(provider))), - content: Text(S.current.confirmUnlinkProviderBody(S.current.signinProvider(provider))), + title: Text( + tr.auth.confirmUnlink.title(tr.auth.providers.name(provider.name))), + content: Text( + tr.auth.confirmUnlink.body(tr.auth.providers.name(provider.name))), actions: DialogControls.negative( context, - confirmLabel: S.current.signinProviderUnlink, - cancelLabel: S.current.cancel, + confirmLabel: tr.auth.providers.unlink, + cancelLabel: tr.generic.cancel, onConfirm: () => Get.back(result: true), onCancel: () => Get.back(result: false), ), @@ -22,6 +25,6 @@ Future confirmUnlinkProvider(BuildContext context, ProviderName provide ).then((res) => res == true); } -Future awaitUnlinkProviderConfirmation( - BuildContext context, ProviderName provider, void Function() onConfirmed) => +Future awaitUnlinkProviderConfirmation(BuildContext context, + ProviderName provider, void Function() onConfirmed) => awaitConfirmation(confirmUnlinkProvider(context, provider), onConfirmed); diff --git a/lib/app/widgets/dialogs/custom_roll_buttons_dialog.dart b/lib/app/widgets/dialogs/custom_roll_buttons_dialog.dart index 22d051cb..883e1a56 100644 --- a/lib/app/widgets/dialogs/custom_roll_buttons_dialog.dart +++ b/lib/app/widgets/dialogs/custom_roll_buttons_dialog.dart @@ -5,15 +5,15 @@ import 'package:dungeon_paper/app/data/models/move.dart'; import 'package:dungeon_paper/app/data/models/roll_button.dart'; import 'package:dungeon_paper/app/data/services/repository_service.dart'; import 'package:dungeon_paper/app/widgets/atoms/select_box.dart'; -import 'package:dungeon_paper/app/widgets/molecules/dice_list_input.dart'; import 'package:dungeon_paper/app/widgets/molecules/dialog_controls.dart'; +import 'package:dungeon_paper/app/widgets/molecules/dice_list_input.dart'; import 'package:dungeon_paper/app/widgets/molecules/special_dice_list_input.dart'; import 'package:dungeon_paper/core/dw_icons.dart'; import 'package:dungeon_paper/core/utils/list_utils.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; +import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; class CustomRollButtonsDialog extends StatefulWidget { const CustomRollButtonsDialog({ @@ -26,16 +26,21 @@ class CustomRollButtonsDialog extends StatefulWidget { final void Function(List rollButtons) onChanged; @override - State createState() => _CustomRollButtonsDialogState(); + State createState() => + _CustomRollButtonsDialogState(); } -class _CustomRollButtonsDialogState extends State with SingleTickerProviderStateMixin { +class _CustomRollButtonsDialogState extends State + with SingleTickerProviderStateMixin { late List rollButtons; late TabController tabController; @override void initState() { - rollButtons = [widget.character.rawRollButtons[0], widget.character.rawRollButtons[1]]; + rollButtons = [ + widget.character.rawRollButtons[0], + widget.character.rawRollButtons[1] + ]; tabController = TabController(length: rollButtons.length, vsync: this); super.initState(); } @@ -47,7 +52,7 @@ class _CustomRollButtonsDialogState extends State with children: [ const Icon(DwIcons.dice_d6_numbered, size: 24), const SizedBox(width: 8), - Text(S.current.customRollButtons), + Text(tr.customRolls.title), ], ), content: Column( @@ -58,14 +63,16 @@ class _CustomRollButtonsDialogState extends State with controller: tabController, labelColor: Theme.of(context).colorScheme.onSurface, tabs: [ - Tab(text: S.current.customButtonLeft), - Tab(text: S.current.customButtonRight), + Tab(text: tr.customRolls.left), + Tab(text: tr.customRolls.right), ], ), SizedBox( width: 400, height: min( - MediaQuery.of(context).size.height - MediaQuery.of(context).viewInsets.bottom - 310, + MediaQuery.of(context).size.height - + MediaQuery.of(context).viewInsets.bottom - + 310, 300, ), child: TabBarView( @@ -79,8 +86,10 @@ class _CustomRollButtonsDialogState extends State with child: _RollButtonListTile( rollButton: button.value, character: widget.character, - defaultButton: Character.defaultRollButtons[button.index], - onChanged: (val) => setState(() => rollButtons[button.index] = val), + defaultButton: + Character.defaultRollButtons[button.index], + onChanged: (val) => + setState(() => rollButtons[button.index] = val), ), ), ), @@ -122,7 +131,8 @@ class _RollButtonListTile extends StatefulWidget { State<_RollButtonListTile> createState() => _RollButtonListTileState(); } -class _RollButtonListTileState extends State<_RollButtonListTile> with RepositoryServiceMixin { +class _RollButtonListTileState extends State<_RollButtonListTile> + with RepositoryServiceMixin { late TextEditingController label; late ValueNotifier> dice; late ValueNotifier> specialDice; @@ -131,7 +141,8 @@ class _RollButtonListTileState extends State<_RollButtonListTile> with Repositor @override void initState() { super.initState(); - initFields(widget.rollButton ?? widget.defaultButton, widget.rollButton == null); + initFields( + widget.rollButton ?? widget.defaultButton, widget.rollButton == null); label.addListener(listener); dice.addListener(listener); specialDice.addListener(listener); @@ -167,16 +178,20 @@ class _RollButtonListTileState extends State<_RollButtonListTile> with Repositor Expanded( child: SelectBox( isExpanded: true, - hint: Text(S.current.customRollButtonsUsePreset), + hint: Text(tr.customRolls.presets.title), items: [ for (final button in [ Character.basicActionRollButton, Character.hackAndSlashRollButton, Character.volleyRollButton, Character.discernRealitiesRollButton, - for (final move in moves) RollButton(label: move.name, dice: move.dice, specialDice: []), - for (final spell in widget.character.spells.where((spell) => spell.dice.isNotEmpty)) - RollButton(label: spell.name, dice: spell.dice, specialDice: []), + for (final move in moves) + RollButton( + label: move.name, dice: move.dice, specialDice: []), + for (final spell in widget.character.spells + .where((spell) => spell.dice.isNotEmpty)) + RollButton( + label: spell.name, dice: spell.dice, specialDice: []), ].uniqueBy((item) => item.label)) DropdownMenuItem( value: button, @@ -201,8 +216,11 @@ class _RollButtonListTileState extends State<_RollButtonListTile> with Repositor child: SizedBox( height: 48, child: ElevatedButton( - onPressed: isDefault ? null : () => setState(() => updateFields(widget.defaultButton, true)), - child: Text(S.current.customRollButtonsUseDefault), + onPressed: isDefault + ? null + : () => setState( + () => updateFields(widget.defaultButton, true)), + child: Text(tr.generic.useDefault), ), ), ), @@ -212,7 +230,7 @@ class _RollButtonListTileState extends State<_RollButtonListTile> with Repositor TextFormField( controller: label, decoration: InputDecoration( - labelText: S.current.rollButtonLabel, + labelText: tr.customRolls.buttonLabel, ), ), const SizedBox(height: 16), @@ -229,8 +247,8 @@ class _RollButtonListTileState extends State<_RollButtonListTile> with Repositor Iterable get moves => [ ...widget.character.moves, - ...repo.builtIn.moves.values - .where((move) => [MoveCategory.basic, MoveCategory.special].contains(move.category)), + ...repo.builtIn.moves.values.where((move) => + [MoveCategory.basic, MoveCategory.special].contains(move.category)), ].where((move) => move.dice.isNotEmpty).toList() ..sort((a, b) => a.name.compareTo(b.name)); @@ -265,8 +283,10 @@ class _RollButtonListTileState extends State<_RollButtonListTile> with Repositor return defaultDice.length == dice.length && enumerate(dice).every( (element) { - debugPrint('index: ${element.index} value ${element.value} == ${defaultDice[element.index]}'); - return defaultDice[element.index].toString() == element.value.toString(); + debugPrint( + 'index: ${element.index} value ${element.value} == ${defaultDice[element.index]}'); + return defaultDice[element.index].toString() == + element.value.toString(); }, ); } diff --git a/lib/app/widgets/dialogs/damage_dice_dialog.dart b/lib/app/widgets/dialogs/damage_dice_dialog.dart index 40caf023..28fad1d3 100644 --- a/lib/app/widgets/dialogs/damage_dice_dialog.dart +++ b/lib/app/widgets/dialogs/damage_dice_dialog.dart @@ -2,10 +2,10 @@ import 'package:dungeon_paper/app/data/models/ability_scores.dart'; import 'package:dungeon_paper/app/widgets/forms/dice_form.dart'; import 'package:dungeon_paper/app/widgets/molecules/dialog_controls.dart'; import 'package:dungeon_paper/core/dw_icons.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; +import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; class DamageDiceDialog extends StatefulWidget { const DamageDiceDialog({ @@ -43,22 +43,22 @@ class _DamageDiceDialogState extends State { children: [ const Icon(DwIcons.dumbbell, size: 32), const SizedBox(width: 12), - Expanded(child: Text(S.current.damageDice)), + Expanded(child: Text(tr.character.data.damageDice)), ], ), content: SingleChildScrollView( child: Column( children: [ CheckboxListTile( - title: Text(S.current.characterAutoDamage), + title: Text(tr.character.data.calculateDamage), dense: true, visualDensity: VisualDensity.compact, controlAffinity: ListTileControlAffinity.leading, value: useDefault, onChanged: (value) => setState(() { - final _value = value ?? !useDefault; - useDefault = _value; - if (_value) { + final rValue = value ?? !useDefault; + useDefault = rValue; + if (rValue) { damage = widget.defaultDamage; } }), @@ -66,7 +66,7 @@ class _DamageDiceDialogState extends State { const SizedBox(height: 8), DiceForm( dice: damage, - onChanged: (dw.Dice _dice) => setState(() => damage = _dice), + onChanged: (dw.Dice dice) => setState(() => damage = dice), abilityScores: widget.abilityScores, enabled: !useDefault, ), diff --git a/lib/app/widgets/dialogs/debilities_dialog.dart b/lib/app/widgets/dialogs/debilities_dialog.dart index b70010f0..e02e630a 100644 --- a/lib/app/widgets/dialogs/debilities_dialog.dart +++ b/lib/app/widgets/dialogs/debilities_dialog.dart @@ -2,12 +2,13 @@ import 'package:dungeon_paper/app/data/models/session_marks.dart'; import 'package:dungeon_paper/app/data/services/character_service.dart'; import 'package:dungeon_paper/app/widgets/atoms/help_text.dart'; import 'package:dungeon_paper/app/widgets/molecules/dialog_controls.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -class CharacterDebilitiesDialog extends GetView with CharacterServiceMixin { - const CharacterDebilitiesDialog({Key? key}) : super(key: key); +class CharacterDebilitiesDialog extends GetView + with CharacterServiceMixin { + const CharacterDebilitiesDialog({super.key}); List get bonds => char.bonds; List get flags => char.flags; @@ -18,7 +19,7 @@ class CharacterDebilitiesDialog extends GetView with Character // final textTheme = Theme.of(context).textTheme; return AlertDialog( - title: Text(S.current.characterDebilitiesDialogTitle), + title: Text(tr.debilities.dialog.title), contentPadding: const EdgeInsets.all(16), actions: DialogControls.done(context, () => Get.back()), content: Obx( @@ -33,13 +34,14 @@ class CharacterDebilitiesDialog extends GetView with Character mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - HelpText(text: S.current.characterDebilitiesDialogInfoText), + HelpText(text: tr.debilities.dialog.info), const SizedBox(height: 6), const Divider(), for (final ability in char.abilityScores.stats) ListTile( contentPadding: const EdgeInsets.all(0), - title: Text(S.current.debilityLabel(ability.debilityName, ability.key)), + title: Text(tr.debilities + .label(ability.debilityName, ability.key)), subtitle: Text(ability.debilityDescription), dense: true, leading: Icon(ability.icon, size: 20), @@ -47,7 +49,9 @@ class CharacterDebilitiesDialog extends GetView with Character char.copyWith( abilityScores: char.abilityScores.copyWith( stats: char.abilityScores.stats.map( - (e) => e.key == ability.key ? e.copyWith(isDebilitated: !e.isDebilitated) : e, + (e) => e.key == ability.key + ? e.copyWith(isDebilitated: !e.isDebilitated) + : e, ), ), ), @@ -57,8 +61,10 @@ class CharacterDebilitiesDialog extends GetView with Character onChanged: (checked) => charService.updateCharacter( char.copyWith( abilityScores: char.abilityScores.copyWith( - stats: char.abilityScores.stats - .map((e) => e.key == ability.key ? e.copyWith(isDebilitated: checked) : e), + stats: char.abilityScores.stats.map((e) => + e.key == ability.key + ? e.copyWith(isDebilitated: checked) + : e), ), ), ), diff --git a/lib/app/widgets/dialogs/hp_dialog.dart b/lib/app/widgets/dialogs/hp_dialog.dart index 15477158..68b30b97 100644 --- a/lib/app/widgets/dialogs/hp_dialog.dart +++ b/lib/app/widgets/dialogs/hp_dialog.dart @@ -5,15 +5,14 @@ import 'package:dungeon_paper/app/widgets/atoms/hp_bar.dart'; import 'package:dungeon_paper/app/widgets/atoms/number_text_field.dart'; import 'package:dungeon_paper/app/widgets/molecules/dialog_controls.dart'; import 'package:dungeon_paper/app/widgets/molecules/value_change_slider.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; - import 'package:get/get.dart'; enum ValueChange { positive, neutral, negative } class HPDialog extends StatefulWidget { - const HPDialog({Key? key}) : super(key: key); + const HPDialog({super.key}); @override State createState() => _HPDialogState(); @@ -28,7 +27,8 @@ class _HPDialogState extends State with CharacterServiceMixin { void initState() { overrideHP = char.currentHp; shouldOverrideMaxHP = char.stats.maxHp != null; - overrideMaxHp = TextEditingController(text: char.maxHp.toString())..addListener(clampCurrentHP); + overrideMaxHp = TextEditingController(text: char.maxHp.toString()) + ..addListener(clampCurrentHP); super.initState(); } @@ -37,7 +37,7 @@ class _HPDialogState extends State with CharacterServiceMixin { const dlgWidth = 400.0; return AlertDialog( - title: Text(S.current.hpDialogTitle), + title: Text(tr.hp.dialog.title), content: SingleChildScrollView( child: Obx( () => Column( @@ -61,9 +61,9 @@ class _HPDialogState extends State with CharacterServiceMixin { maxValue: maxHP, updatedValue: overrideHP, onChange: (val) => setState(() => overrideHP = val.round()), - positiveText: S.current.hpDialogChangeAdd, - neutralText: (_) => S.current.hpDialogChangeNeutral, - negativeText: S.current.hpDialogChangeRemove, + positiveText: tr.hp.dialog.change.add, + neutralText: (_) => tr.hp.dialog.change.neutral, + negativeText: tr.hp.dialog.change.remove, ), ), ), @@ -71,8 +71,9 @@ class _HPDialogState extends State with CharacterServiceMixin { const Divider(height: 32), CheckboxListTile( value: shouldOverrideMaxHP, - onChanged: (value) => setState(() => shouldOverrideMaxHP = value!), - title: Text(S.current.hpDialogChangeOverrideMax), + onChanged: (value) => + setState(() => shouldOverrideMaxHP = value!), + title: Text(tr.hp.dialog.overrideMax), controlAffinity: ListTileControlAffinity.leading, dense: true, visualDensity: VisualDensity.compact, @@ -86,7 +87,8 @@ class _HPDialogState extends State with CharacterServiceMixin { const SizedBox(height: 24), Row( mainAxisAlignment: MainAxisAlignment.end, - children: DialogControls.save(context, onSave: save, onCancel: close, spacing: 8), + children: DialogControls.save(context, + onSave: save, onCancel: close, spacing: 8), ), ], ), @@ -96,7 +98,9 @@ class _HPDialogState extends State with CharacterServiceMixin { } int get currentHP => char.currentHp; - int get maxHP => shouldOverrideMaxHP ? int.tryParse(overrideMaxHp.text) ?? char.defaultMaxHp : char.defaultMaxHp; + int get maxHP => shouldOverrideMaxHP + ? int.tryParse(overrideMaxHp.text) ?? char.defaultMaxHp + : char.defaultMaxHp; ValueChange get change => currentHP == overrideHP ? ValueChange.neutral @@ -117,7 +121,9 @@ class _HPDialogState extends State with CharacterServiceMixin { void save() { charService.updateCharacter( char.copyWith( - stats: char.stats.copyWith(currentHp: overrideHP).copyWithMaxHp(shouldOverrideMaxHP ? maxHP : null), + stats: char.stats + .copyWith(currentHp: overrideHP) + .copyWithMaxHp(shouldOverrideMaxHP ? maxHP : null), ), ); close(); diff --git a/lib/app/widgets/dialogs/load_dialog.dart b/lib/app/widgets/dialogs/load_dialog.dart index 4d84a595..75a33f0e 100644 --- a/lib/app/widgets/dialogs/load_dialog.dart +++ b/lib/app/widgets/dialogs/load_dialog.dart @@ -1,7 +1,7 @@ import 'package:dungeon_paper/app/widgets/atoms/number_text_field.dart'; import 'package:dungeon_paper/app/widgets/molecules/dialog_controls.dart'; import 'package:dungeon_paper/core/dw_icons.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -29,7 +29,8 @@ class _LoadDialogState extends State { void initState() { super.initState(); useDefault = widget.load == null; - controller = TextEditingController(text: (widget.load ?? widget.defaultLoad).toString()); + controller = TextEditingController( + text: (widget.load ?? widget.defaultLoad).toString()); controller.addListener(_listener); } @@ -40,7 +41,7 @@ class _LoadDialogState extends State { children: [ const Icon(DwIcons.dumbbell, size: 32), const SizedBox(width: 12), - Expanded(child: Text(S.current.maxLoad)), + Expanded(child: Text(tr.character.data.load.maxLoad)), ], ), content: SingleChildScrollView( @@ -57,7 +58,7 @@ class _LoadDialogState extends State { controller.text = widget.defaultLoad.toString(); } }), - title: Text(S.current.characterAutoMaxLoad), + title: Text(tr.character.data.load.autoMaxLoad), ), NumberTextField( controller: controller, @@ -69,7 +70,8 @@ class _LoadDialogState extends State { ), ), actions: DialogControls.save(context, - onSave: useDefault || controller.text.isNotEmpty ? save : null, onCancel: cancel), + onSave: useDefault || controller.text.isNotEmpty ? save : null, + onCancel: cancel), ); } diff --git a/lib/app/widgets/dialogs/view_tag_dialog.dart b/lib/app/widgets/dialogs/view_tag_dialog.dart index 089cd7b9..c225521e 100644 --- a/lib/app/widgets/dialogs/view_tag_dialog.dart +++ b/lib/app/widgets/dialogs/view_tag_dialog.dart @@ -1,15 +1,15 @@ import 'package:dungeon_paper/app/widgets/molecules/dialog_controls.dart'; import 'package:dungeon_paper/core/utils/string_utils.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; -import 'package:flutter/material.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; +import 'package:flutter/material.dart'; import 'package:get/get.dart'; class ViewTagDialog extends StatelessWidget { const ViewTagDialog({ - Key? key, + super.key, required this.tag, - }) : super(key: key); + }); final dw.Tag tag; @@ -18,7 +18,7 @@ class ViewTagDialog extends StatelessWidget { final textTheme = Theme.of(context).textTheme; return AlertDialog( - title: Text(S.current.tagDetails), + title: Text(tr.tags.dialog.title), content: SizedBox( width: 500, child: Column( @@ -32,14 +32,14 @@ class ViewTagDialog extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - S.current.genericNameField( - S.current.entity(dw.Tag), + tr.generic.entityName( + tr.entity(dw.Tag), ), style: textTheme.bodySmall, ), Text( toTitleCase(tag.name), - textScaleFactor: 1.8, + textScaler: const TextScaler.linear(1.8), ), ], ), @@ -51,14 +51,14 @@ class ViewTagDialog extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - S.current.genericValueField( - S.current.entity(dw.Tag), + tr.generic.entityValue( + tr.entity(dw.Tag), ), style: textTheme.bodySmall, ), Text( tag.value.toString(), - textScaleFactor: 1.8, + textScaler: const TextScaler.linear(1.8), ), ], ), @@ -69,14 +69,14 @@ class ViewTagDialog extends StatelessWidget { if (tag.description.isNotEmpty) ...[ const SizedBox(height: 8), Text( - S.current.genericDescriptionField( - S.current.entity(dw.Tag), + tr.generic.entityDescription( + tr.entity(dw.Tag), ), style: textTheme.bodySmall, ), Text( tag.description, - textScaleFactor: 0.9, + textScaler: const TextScaler.linear(0.9), ), ], ], diff --git a/lib/app/widgets/dialogs/xp_dialog.dart b/lib/app/widgets/dialogs/xp_dialog.dart index f35ffff1..cfbae6b1 100644 --- a/lib/app/widgets/dialogs/xp_dialog.dart +++ b/lib/app/widgets/dialogs/xp_dialog.dart @@ -3,22 +3,21 @@ import 'package:dungeon_paper/app/data/models/session_marks.dart'; import 'package:dungeon_paper/app/data/services/character_service.dart'; import 'package:dungeon_paper/app/widgets/atoms/custom_expansion_panel.dart'; import 'package:dungeon_paper/app/widgets/atoms/help_text.dart'; -import 'package:dungeon_paper/app/widgets/atoms/xp_bar.dart'; import 'package:dungeon_paper/app/widgets/atoms/number_text_field.dart'; +import 'package:dungeon_paper/app/widgets/atoms/xp_bar.dart'; import 'package:dungeon_paper/app/widgets/molecules/dialog_controls.dart'; import 'package:dungeon_paper/core/platform_helper.dart'; import 'package:dungeon_paper/core/utils/list_utils.dart'; import 'package:dungeon_paper/core/utils/math_utils.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; -import 'package:flutter/material.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; - +import 'package:flutter/material.dart'; import 'package:get/get.dart'; enum ValueChange { positive, neutral, negative } class EXPDialog extends StatefulWidget { - const EXPDialog({Key? key}) : super(key: key); + const EXPDialog({super.key}); @override State createState() => _EXPDialogState(); @@ -33,9 +32,11 @@ class _EXPDialogState extends State with CharacterServiceMixin { @override void initState() { - overrideXp = TextEditingController(text: char.currentXp.toString())..addListener(() => setState(() {})); + overrideXp = TextEditingController(text: char.currentXp.toString()) + ..addListener(() => setState(() {})); manualExpExpanded = false; - overrideLevel = TextEditingController(text: currentLevel.toString())..addListener(() => setState(() {})); + overrideLevel = TextEditingController(text: currentLevel.toString()) + ..addListener(() => setState(() {})); shouldResetSessionMarks = true; eosMarks = char.endOfSessionMarks; super.initState(); @@ -53,7 +54,8 @@ class _EXPDialogState extends State with CharacterServiceMixin { const dlgWidth = 400.0; return AlertDialog( - title: Text(!hasOverrides ? S.current.xpDialogTitle : S.current.xpDialogTitleOverriding), + title: Text( + !hasOverrides ? tr.xp.dialog.title : tr.xp.dialog.overridingTitle), content: SingleChildScrollView( child: Obx( () { @@ -66,10 +68,13 @@ class _EXPDialogState extends State with CharacterServiceMixin { SizedBox( width: dlgWidth, child: ExpBar( - currentXp: clamp(int.tryParse(overrideXp.text) ?? currentXp, 0, maxXp), + currentXp: clamp( + int.tryParse(overrideXp.text) ?? currentXp, 0, maxXp), maxXp: maxXp, - pendingXp: - !shouldResetSessionMarks || (!shouldOverrideXp && !shouldOverrideLevel) ? totalPendingXp : 0, + pendingXp: !shouldResetSessionMarks || + (!shouldOverrideXp && !shouldOverrideLevel) + ? totalPendingXp + : 0, ), ), const SizedBox(height: 24), @@ -77,10 +82,10 @@ class _EXPDialogState extends State with CharacterServiceMixin { width: dlgWidth, child: ListTile( title: Text( - S.current.endOfSessionQuestions, + tr.xp.dialog.endOfSession.questions.title, ), subtitle: Text( - S.current.endOfSessionQuestionsSubtitle, + tr.xp.dialog.endOfSession.questions.subtitle, ), ), ), @@ -100,10 +105,15 @@ class _EXPDialogState extends State with CharacterServiceMixin { AnimatedContainer( duration: const Duration(milliseconds: 250), width: dlgWidth, - height: manualExpExpanded ? (332 + (PlatformHelper.isIOS || PlatformHelper.isAndroid ? 32 : 0)) : 48, + height: manualExpExpanded + ? (332 + + (PlatformHelper.isIOS || PlatformHelper.isAndroid + ? 32 + : 0)) + : 48, child: CustomExpansionPanel( title: Text( - S.current.xpDialogChangeOverride + (hasOverrides ? '*' : ''), + tr.xp.dialog.override.title + (hasOverrides ? '*' : ''), ), expanded: manualExpExpanded, onExpansion: (value) { @@ -112,14 +122,15 @@ class _EXPDialogState extends State with CharacterServiceMixin { }); }, children: [ - HelpText(text: S.current.xpDialogOverrideInfoText), + HelpText(text: tr.xp.dialog.override.info), const SizedBox(height: 8), CheckboxListTile( value: shouldResetSessionMarks, onChanged: (val) => setState( - () => shouldResetSessionMarks = val ?? !shouldResetSessionMarks, + () => shouldResetSessionMarks = + val ?? !shouldResetSessionMarks, ), - title: Text(S.current.xpDialogResetSessionMarks), + title: Text(tr.xp.dialog.override.resetCheckbox), dense: true, visualDensity: VisualDensity.compact, controlAffinity: ListTileControlAffinity.leading, @@ -129,7 +140,8 @@ class _EXPDialogState extends State with CharacterServiceMixin { controller: overrideXp, numberType: NumberType.int, decoration: InputDecoration( - labelText: S.current.xpDialogOverrideXp + (shouldOverrideXp ? '*' : ''), + labelText: tr.xp.dialog.override.xp + + (shouldOverrideXp ? '*' : ''), ), minValue: 0, maxValue: CharacterStats.maxExpForLevel(level), @@ -137,7 +149,8 @@ class _EXPDialogState extends State with CharacterServiceMixin { const SizedBox(height: 16), NumberTextField( decoration: InputDecoration( - labelText: S.current.xpDialogOverrideLevel + (shouldOverrideLevel ? '*' : ''), + labelText: tr.xp.dialog.override.level + + (shouldOverrideLevel ? '*' : ''), ), numberType: NumberType.int, controller: overrideLevel, @@ -154,7 +167,9 @@ class _EXPDialogState extends State with CharacterServiceMixin { children: DialogControls.save( context, onSave: save, - saveLabel: shouldResetSessionMarks ? S.current.xpDialogEndSession : null, + saveLabel: shouldResetSessionMarks + ? tr.xp.dialog.endOfSession.button + : null, onCancel: close, spacing: 8, ), @@ -170,23 +185,34 @@ class _EXPDialogState extends State with CharacterServiceMixin { int get currentXp => char.currentXp; int get currentLevel => char.stats.level; int get maxXp => shouldOverrideLevel - ? CharacterStats.maxExpForLevel(int.tryParse(overrideLevel.text) ?? currentLevel) + ? CharacterStats.maxExpForLevel( + int.tryParse(overrideLevel.text) ?? currentLevel) : char.maxXp; int get eosPendingXp => eosMarks.where((mark) => mark.completed).length; int get totalPendingXp => - char.sessionMarks.where((mark) => mark.type != dw.SessionMarkType.endOfSession && mark.completed).length + + char.sessionMarks + .where((mark) => + mark.type != dw.SessionMarkType.endOfSession && mark.completed) + .length + eosPendingXp; - int get effectiveXp => shouldOverrideXp ? int.parse(overrideXp.text) : currentXp; - int get effectiveLevel => shouldOverrideLevel ? int.parse(overrideLevel.text) : currentLevel; - bool get shouldOverrideXp => int.tryParse(overrideXp.text) != null && int.parse(overrideXp.text) != currentXp; + int get effectiveXp => + shouldOverrideXp ? int.parse(overrideXp.text) : currentXp; + int get effectiveLevel => + shouldOverrideLevel ? int.parse(overrideLevel.text) : currentLevel; + bool get shouldOverrideXp => + int.tryParse(overrideXp.text) != null && + int.parse(overrideXp.text) != currentXp; bool get shouldOverrideLevel => - int.tryParse(overrideLevel.text) != null && int.parse(overrideLevel.text) != currentLevel; + int.tryParse(overrideLevel.text) != null && + int.parse(overrideLevel.text) != currentLevel; - bool get hasOverrides => shouldOverrideLevel || shouldOverrideXp || !shouldResetSessionMarks; + bool get hasOverrides => + shouldOverrideLevel || shouldOverrideXp || !shouldResetSessionMarks; void save() { - final beforeLevelXp = effectiveXp + (shouldResetSessionMarks ? totalPendingXp : 0); + final beforeLevelXp = + effectiveXp + (shouldResetSessionMarks ? totalPendingXp : 0); int updatedLevel = effectiveLevel; int updatedXp = beforeLevelXp; @@ -205,7 +231,9 @@ class _EXPDialogState extends State with CharacterServiceMixin { ), // reset all session marks completion sessionMarks: shouldResetSessionMarks - ? char.sessionMarks.map((e) => e.copyWithInherited(completed: false)).toList() + ? char.sessionMarks + .map((e) => e.copyWithInherited(completed: false)) + .toList() : upsertByKey(char.sessionMarks, eosMarks), ), ); @@ -221,8 +249,10 @@ class _EXPDialogState extends State with CharacterServiceMixin { void _toggleEosMark(SessionMark eos, bool? val) { setState(() { - eosMarks = updateByKey(eosMarks, [eos.copyWithInherited(completed: val ?? !eos.completed)]); - charService.updateCharacter(char.copyWith(sessionMarks: upsertByKey(char.sessionMarks, eosMarks))); + eosMarks = updateByKey( + eosMarks, [eos.copyWithInherited(completed: val ?? !eos.completed)]); + charService.updateCharacter(char.copyWith( + sessionMarks: upsertByKey(char.sessionMarks, eosMarks))); }); } } diff --git a/lib/app/widgets/forms/character_class_form.dart b/lib/app/widgets/forms/character_class_form.dart index 424fb3cb..a9350446 100644 --- a/lib/app/widgets/forms/character_class_form.dart +++ b/lib/app/widgets/forms/character_class_form.dart @@ -5,13 +5,13 @@ import 'package:dungeon_paper/app/widgets/atoms/rich_text_field.dart'; import 'package:dungeon_paper/app/widgets/forms/library_entity_form.dart'; import 'package:dungeon_paper/app/widgets/molecules/dice_list_input.dart'; import 'package:dungeon_paper/core/utils/list_utils.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; import 'package:flutter/material.dart'; import 'package:get/get.dart'; class CharacterClassForm extends GetView { - const CharacterClassForm({Key? key}) : super(key: key); + const CharacterClassForm({super.key}); @override Widget build(BuildContext context) { @@ -21,20 +21,20 @@ class CharacterClassForm extends GetView { controller: controller.name, textCapitalization: TextCapitalization.words, decoration: InputDecoration( - label: Text(S.current.formGeneralNameGeneric(S.current.entity(CharacterClass))), + label: Text(tr.generic.entityName(tr.entity(CharacterClass))), ), ), () => const SizedBox(height: 16), () => RichTextField( controller: controller.description, - label: S.current.formGeneralDescriptionGeneric(S.current.entity(CharacterClass)), + label: tr.generic.entityDescription(tr.entity(CharacterClass)), maxLines: 10, minLines: 5, textCapitalization: TextCapitalization.sentences, ), () => DiceListInput( controller: controller.damageDice, - label: Text(S.current.formCharacterClassDamage), + label: Text(tr.characterClass.damageDice), abilityScores: AbilityScores.dungeonWorld( cha: 12, con: 12, @@ -53,7 +53,7 @@ class CharacterClassForm extends GetView { numberType: NumberType.int, controller: controller.hp, decoration: InputDecoration( - label: Text(S.current.formCharacterClassBaseHp), + label: Text(tr.characterClass.baseHp), ), ), ), @@ -63,7 +63,7 @@ class CharacterClassForm extends GetView { numberType: NumberType.int, controller: controller.load, decoration: InputDecoration( - label: Text(S.current.formCharacterClassBaseLoad), + label: Text(tr.characterClass.baseLoad), ), ), ), @@ -74,7 +74,8 @@ class CharacterClassForm extends GetView { } } -class CharacterClassFormController extends LibraryEntityFormController { +class CharacterClassFormController extends LibraryEntityFormController< + CharacterClass, CharacterClassFormArguments> { final _name = TextEditingController().obs; final _description = TextEditingController().obs; final _damageDice = ValueNotifier>([dw.Dice.d4]).obs; @@ -123,7 +124,8 @@ class CharacterClassFormController extends LibraryEntityFormController { +class CharacterClassFormArguments + extends LibraryEntityFormArguments { CharacterClassFormArguments({ required super.entity, required super.onSave, diff --git a/lib/app/widgets/forms/dice_form.dart b/lib/app/widgets/forms/dice_form.dart index f0d86ae1..def6ce61 100644 --- a/lib/app/widgets/forms/dice_form.dart +++ b/lib/app/widgets/forms/dice_form.dart @@ -4,7 +4,7 @@ import 'package:dungeon_paper/app/themes/button_themes.dart'; import 'package:dungeon_paper/app/themes/themes.dart'; import 'package:dungeon_paper/app/widgets/atoms/number_text_field.dart'; import 'package:dungeon_paper/app/widgets/atoms/select_box.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; import 'package:get/get.dart'; @@ -13,12 +13,12 @@ enum ModifierType { stat, fixed } class DiceForm extends StatefulWidget { const DiceForm({ - Key? key, + super.key, this.dice, this.onChanged, required this.abilityScores, this.enabled = true, - }) : super(key: key); + }); final dw.Dice? dice; final void Function(dw.Dice dice)? onChanged; @@ -42,11 +42,16 @@ class _DiceFormState extends State { void initState() { super.initState(); // amount = widget.dice?.amount ?? 2; - amount = TextEditingController(text: widget.dice?.amount.toString() ?? '2')..addListener(_onChanged); + amount = TextEditingController(text: widget.dice?.amount.toString() ?? '2') + ..addListener(_onChanged); sides = widget.dice?.sides ?? 6; - modifierNum = TextEditingController(text: (widget.dice?.modifierValue ?? 0).toString())..addListener(_onChanged); + modifierNum = TextEditingController( + text: (widget.dice?.modifierValue ?? 0).toString()) + ..addListener(_onChanged); modifierStat = widget.dice?.modifierStat; - modifierType = widget.dice?.modifierStat != null ? ModifierType.stat : ModifierType.fixed; + modifierType = widget.dice?.modifierStat != null + ? ModifierType.stat + : ModifierType.fixed; } @override @@ -65,22 +70,23 @@ class _DiceFormState extends State { enabled: widget.enabled, minValue: 1, decoration: InputDecoration( - label: Text(S.current.diceAmount), + label: Text(tr.dice.form.amount), alignLabelWithHint: true, ), ), ), const SizedBox(width: 8), - Text(S.current.diceSeparator), + Text(tr.dice.form.diceSeparator), const SizedBox(width: 8), SizedBox( width: 100, child: SelectBox( value: sides, - label: Text(S.current.diceSides), + label: Text(tr.dice.form.sides), isExpanded: true, items: [ - for (final i in [4, 6, 8, 10, 12, 20, 100]) DropdownMenuItem(child: Text(i.toString()), value: i) + for (final i in [4, 6, 8, 10, 12, 20, 100]) + DropdownMenuItem(value: i, child: Text(i.toString())) ], onChanged: widget.enabled ? (value) => setState(() { @@ -101,7 +107,8 @@ class _DiceFormState extends State { child: ElevatedButton( style: (ButtonThemes.primaryElevated( context, - backgroundOpacity: modifierType == ModifierType.fixed ? 1 : 0.4, + backgroundOpacity: + modifierType == ModifierType.fixed ? 1 : 0.4, ) ?? ElevatedButton.styleFrom()) .copyWith( @@ -121,14 +128,15 @@ class _DiceFormState extends State { modifierType = ModifierType.fixed; _onChanged(); }), - child: Text(S.current.diceUseValue), + child: Text(tr.dice.form.modifierType.fixed), ), ), Expanded( child: ElevatedButton( style: (ButtonThemes.primaryElevated( context, - backgroundOpacity: modifierType == ModifierType.stat ? 1 : 0.4, + backgroundOpacity: + modifierType == ModifierType.stat ? 1 : 0.4, ) ?? ElevatedButton.styleFrom()) .copyWith( @@ -148,7 +156,7 @@ class _DiceFormState extends State { modifierType = ModifierType.stat; _onChanged(); }), - child: Text(S.current.diceUseStat), + child: Text(tr.dice.form.modifierType.modifier), ), ), ], @@ -161,8 +169,8 @@ class _DiceFormState extends State { controller: modifierNum, enabled: widget.enabled, decoration: InputDecoration( - hintText: S.current.diceUseValuePlaceholder, - label: Text(S.current.diceUseValueLabel), + hintText: tr.dice.form.value.placeholder, + label: Text(tr.dice.form.value.label), ), ), ), @@ -172,8 +180,8 @@ class _DiceFormState extends State { child: SelectBox( value: modifierStat, isExpanded: true, - label: Text(S.current.diceUseStatPlaceholder), - hint: Text(S.current.diceUseStatLabel), + label: Text(tr.dice.form.modifier.placeholder), + hint: Text(tr.dice.form.modifier.label), onChanged: widget.enabled ? (value) => setState(() { modifierStat = value; @@ -183,8 +191,8 @@ class _DiceFormState extends State { items: [ for (final stat in widget.abilityScores.stats) DropdownMenuItem( - child: Text(S.current.diceUseStatValue(stat.name, stat.key)), value: stat.key, + child: Text(tr.dice.form.statValue(stat.name, stat.key)), ) ], ), @@ -197,7 +205,9 @@ class _DiceFormState extends State { amount: int.tryParse(amount.text) ?? 1, sides: sides, modifierStat: modifierType == ModifierType.stat ? modifierStat : null, - modifierValue: modifierType == ModifierType.fixed ? int.tryParse(modifierNum.text) ?? 0 : null, + modifierValue: modifierType == ModifierType.fixed + ? int.tryParse(modifierNum.text) ?? 0 + : null, ); void _onChanged() { diff --git a/lib/app/widgets/forms/entity_share_form.dart b/lib/app/widgets/forms/entity_share_form.dart index a51c13b5..1e417e4b 100644 --- a/lib/app/widgets/forms/entity_share_form.dart +++ b/lib/app/widgets/forms/entity_share_form.dart @@ -1,7 +1,7 @@ import 'package:dungeon_paper/app/data/models/meta.dart'; import 'package:dungeon_paper/app/data/services/repository_service.dart'; import 'package:dungeon_paper/app/data/services/user_service.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; class EntityShareForm extends StatefulWidget { @@ -34,9 +34,12 @@ class _EntityShareFormState extends State }[syncStatus]; String get syncStatusText => { - SyncStatus.inSync: S.current.entityShareStatusInSync(S.current.entity(widget.entity.runtimeType)), - SyncStatus.outOfSync: S.current.entityShareStatusOutOfSync(S.current.entity(widget.entity.runtimeType)), - SyncStatus.detached: S.current.entityShareStatusDetached(S.current.entity(widget.entity.runtimeType)), + SyncStatus.inSync: + tr.sync.entity.status.inSync(tr.entity(widget.entity.runtimeType)), + SyncStatus.outOfSync: tr.sync.entity.status + .outOfSync(tr.entity(widget.entity.runtimeType)), + SyncStatus.detached: tr.sync.entity.status + .detached(tr.entity(widget.entity.runtimeType)), }[syncStatus]!; Color? syncStatusColor(BuildContext context) => { diff --git a/lib/app/widgets/forms/item_form.dart b/lib/app/widgets/forms/item_form.dart index 84a90bed..a678b3df 100644 --- a/lib/app/widgets/forms/item_form.dart +++ b/lib/app/widgets/forms/item_form.dart @@ -2,13 +2,13 @@ import 'package:dungeon_paper/app/data/models/item.dart'; import 'package:dungeon_paper/app/widgets/atoms/rich_text_field.dart'; import 'package:dungeon_paper/app/widgets/forms/library_entity_form.dart'; import 'package:dungeon_paper/app/widgets/molecules/tag_list_input.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; +import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; class ItemForm extends GetView { - const ItemForm({Key? key}) : super(key: key); + const ItemForm({super.key}); @override Widget build(BuildContext context) { @@ -19,14 +19,14 @@ class ItemForm extends GetView { controller: controller.name, textCapitalization: TextCapitalization.words, decoration: InputDecoration( - label: Text(S.current.formGeneralNameGeneric(S.current.entity(Item))), + label: Text(tr.generic.entityName(tr.entity(Item))), ), ), ), () => Obx( () => RichTextField( controller: controller.description, - label: S.current.formGeneralDescriptionGeneric(S.current.entity(Item)), + label: tr.generic.entityDescription(tr.entity(Item)), maxLines: 10, minLines: 5, textCapitalization: TextCapitalization.sentences, @@ -42,7 +42,8 @@ class ItemForm extends GetView { } } -class ItemFormController extends LibraryEntityFormController { +class ItemFormController + extends LibraryEntityFormController { final _name = TextEditingController().obs; final _description = TextEditingController().obs; final _tags = ValueNotifier>([]).obs; diff --git a/lib/app/widgets/forms/library_entity_form.dart b/lib/app/widgets/forms/library_entity_form.dart index 38e2ee3e..9ebf54b8 100644 --- a/lib/app/widgets/forms/library_entity_form.dart +++ b/lib/app/widgets/forms/library_entity_form.dart @@ -7,16 +7,18 @@ import 'package:dungeon_paper/app/widgets/forms/entity_share_form.dart'; import 'package:dungeon_paper/core/utils/builder_utils.dart'; import 'package:dungeon_paper/core/utils/enums.dart'; import 'package:dungeon_paper/core/utils/list_utils.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -class LibraryEntityForm>> - extends GetView { +class LibraryEntityForm< + T extends WithMeta, + Ctrl extends LibraryEntityFormController>> extends GetView { const LibraryEntityForm({ - Key? key, + super.key, required this.children, - }) : super(key: key); + }); final List children; @@ -31,7 +33,8 @@ class LibraryEntityForm const SizedBox(height: 16)).toList(), + children: + children.joinObjects(() => const SizedBox(height: 16)).toList(), trailing: [ () => const Divider(height: 64), () => Obx( @@ -44,7 +47,7 @@ class LibraryEntityForm Text( controller.args.formContext == FormContext.create - ? S.current.addGeneric(S.current.entity(controller.empty().runtimeType)) - : S.current.editGeneric(S.current.entity(controller.empty().runtimeType)), + ? tr.generic.addEntity(tr.entity(controller.empty().runtimeType)) + : tr.generic.editEntity(tr.entity(controller.empty().runtimeType)), ); } -abstract class LibraryEntityFormController> - extends GetxController { +abstract class LibraryEntityFormController> extends GetxController { final dirty = false.obs; late final Args args; bool afterInit = false; @@ -113,7 +116,7 @@ abstract class LibraryEntityFormController _toString(e)).join(',') + ']'; + return '[${object.map((e) => _toString(e)).join(',')}]'; } return object.toString(); } diff --git a/lib/app/widgets/forms/move_form.dart b/lib/app/widgets/forms/move_form.dart index f395e9e2..ecb5fb0d 100644 --- a/lib/app/widgets/forms/move_form.dart +++ b/lib/app/widgets/forms/move_form.dart @@ -1,6 +1,6 @@ +import 'package:dungeon_paper/app/data/models/ability_scores.dart'; import 'package:dungeon_paper/app/data/models/character_class.dart'; import 'package:dungeon_paper/app/data/models/move.dart'; -import 'package:dungeon_paper/app/data/models/ability_scores.dart'; import 'package:dungeon_paper/app/data/models/move_templates.dart'; import 'package:dungeon_paper/app/data/services/repository_service.dart'; import 'package:dungeon_paper/app/widgets/atoms/rich_text_field.dart'; @@ -8,13 +8,13 @@ import 'package:dungeon_paper/app/widgets/atoms/select_box.dart'; import 'package:dungeon_paper/app/widgets/forms/library_entity_form.dart'; import 'package:dungeon_paper/app/widgets/molecules/dice_list_input.dart'; import 'package:dungeon_paper/app/widgets/molecules/tag_list_input.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; +import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; class MoveForm extends GetView with RepositoryServiceMixin { - const MoveForm({Key? key}) : super(key: key); + const MoveForm({super.key}); @override Widget build(BuildContext context) { @@ -23,7 +23,7 @@ class MoveForm extends GetView with RepositoryServiceMixin { () => Obx( () => TextFormField( decoration: InputDecoration( - label: Text(S.current.formGeneralNameGeneric(S.current.entity(Move))), + label: Text(tr.generic.entityName(tr.entity(Move))), ), textCapitalization: TextCapitalization.words, controller: controller.name, @@ -35,13 +35,14 @@ class MoveForm extends GetView with RepositoryServiceMixin { Expanded( child: SelectBox( value: controller.category.value, - label: Text(S.current.entity(MoveCategory)), + label: Text(tr.entity(MoveCategory)), isExpanded: true, items: MoveCategory.values .map( (cat) => DropdownMenuItem( - child: Text(S.current.moveCategoryWithLevelShort(cat.name)), value: cat, + child: + Text(tr.moves.category.shortName(cat.name)), ), ) .toList(), @@ -51,15 +52,21 @@ class MoveForm extends GetView with RepositoryServiceMixin { const SizedBox(width: 16), Expanded( child: SelectBox( - value: controller.classKeys.value.isNotEmpty ? controller.classKeys.value.first : null, - onChanged: (value) => controller.classKeys.value = [value!], + value: controller.classKeys.value.isNotEmpty + ? controller.classKeys.value.first + : null, + onChanged: (value) => + controller.classKeys.value = [value!], isExpanded: true, - label: Text(S.current.entity(CharacterClass)), - items: {...repo.builtIn.classes.values, ...repo.my.classes.values} + label: Text(tr.entity(CharacterClass)), + items: { + ...repo.builtIn.classes.values, + ...repo.my.classes.values + } .map( (cls) => DropdownMenuItem( - child: Text(cls.name), value: cls.reference, + child: Text(cls.name), ), ) .toList(), @@ -71,7 +78,9 @@ class MoveForm extends GetView with RepositoryServiceMixin { () => Obx( () => RichTextField( decoration: InputDecoration( - label: Text(S.current.formGeneralDescriptionGeneric(S.current.entity(Move))), + label: Text( + tr.generic.entityDescription(tr.entity(Move)), + ), ), maxLines: 10, minLines: 5, @@ -108,7 +117,9 @@ class MoveForm extends GetView with RepositoryServiceMixin { () => Obx( () => RichTextField( decoration: InputDecoration( - label: Text(S.current.formGeneralExplanationGeneric(S.current.entity(Move))), + label: Text( + tr.generic.entityExplanation(tr.entity(Move)), + ), ), maxLines: 10, minLines: 5, @@ -120,7 +131,8 @@ class MoveForm extends GetView with RepositoryServiceMixin { () => Obx( () => DiceListInput( controller: controller.dice, - abilityScores: controller.args.abilityScores ?? AbilityScores.dungeonWorldAll(10), + abilityScores: controller.args.abilityScores ?? + AbilityScores.dungeonWorldAll(10), guessFrom: [controller.description, controller.explanation], ), ), @@ -134,7 +146,8 @@ class MoveForm extends GetView with RepositoryServiceMixin { } } -class MoveFormController extends LibraryEntityFormController { +class MoveFormController + extends LibraryEntityFormController { final _name = TextEditingController().obs; final _description = TextEditingController().obs; final _explanation = TextEditingController().obs; @@ -152,7 +165,8 @@ class MoveFormController extends LibraryEntityFormController> get classKeys => _classKeys.value; @override - List> get fields => [_name, _description, _explanation, _dice, _tags, _category, _classKeys]; + List> get fields => + [_name, _description, _explanation, _dice, _tags, _category, _classKeys]; @override void onInit() { diff --git a/lib/app/widgets/forms/note_form.dart b/lib/app/widgets/forms/note_form.dart index afd79ec2..bd0adcb8 100644 --- a/lib/app/widgets/forms/note_form.dart +++ b/lib/app/widgets/forms/note_form.dart @@ -3,13 +3,13 @@ import 'package:dungeon_paper/app/data/services/repository_service.dart'; import 'package:dungeon_paper/app/widgets/atoms/rich_text_field.dart'; import 'package:dungeon_paper/app/widgets/forms/library_entity_form.dart'; import 'package:dungeon_paper/app/widgets/molecules/tag_list_input.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; +import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; class NoteForm extends GetView with RepositoryServiceMixin { - const NoteForm({Key? key}) : super(key: key); + const NoteForm({super.key}); @override Widget build(BuildContext context) { @@ -18,7 +18,9 @@ class NoteForm extends GetView with RepositoryServiceMixin { () => Obx( () => TextFormField( decoration: InputDecoration( - label: Text(S.current.formGeneralNameGeneric(S.current.entity(Note))), + label: Text( + tr.generic.entityName(tr.entity(Note)), + ), ), textCapitalization: TextCapitalization.words, controller: controller.title, @@ -27,7 +29,9 @@ class NoteForm extends GetView with RepositoryServiceMixin { () => Obx( () => RichTextField( decoration: InputDecoration( - label: Text(S.current.formGeneralDescriptionGeneric(S.current.entity(Note))), + label: Text( + tr.generic.entityDescription(tr.entity(Note)), + ), ), maxLines: 10, minLines: 5, @@ -46,7 +50,8 @@ class NoteForm extends GetView with RepositoryServiceMixin { } } -class NoteFormController extends LibraryEntityFormController { +class NoteFormController + extends LibraryEntityFormController { final _title = TextEditingController().obs; final _description = TextEditingController().obs; final _category = TextEditingController().obs; @@ -59,7 +64,8 @@ class NoteFormController extends LibraryEntityFormController> get tags => _tags.value; @override - List> get fields => [_title, _description, _category, _dice, _tags]; + List> get fields => + [_title, _description, _category, _dice, _tags]; @override void onInit() { diff --git a/lib/app/widgets/forms/race_form.dart b/lib/app/widgets/forms/race_form.dart index e6329c00..36f708cb 100644 --- a/lib/app/widgets/forms/race_form.dart +++ b/lib/app/widgets/forms/race_form.dart @@ -1,19 +1,19 @@ +import 'package:dungeon_paper/app/data/models/ability_scores.dart'; import 'package:dungeon_paper/app/data/models/character_class.dart'; import 'package:dungeon_paper/app/data/models/race.dart'; -import 'package:dungeon_paper/app/data/models/ability_scores.dart'; import 'package:dungeon_paper/app/data/services/repository_service.dart'; import 'package:dungeon_paper/app/widgets/atoms/rich_text_field.dart'; import 'package:dungeon_paper/app/widgets/atoms/select_box.dart'; import 'package:dungeon_paper/app/widgets/forms/library_entity_form.dart'; import 'package:dungeon_paper/app/widgets/molecules/dice_list_input.dart'; import 'package:dungeon_paper/app/widgets/molecules/tag_list_input.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; +import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; class RaceForm extends GetView with RepositoryServiceMixin { - const RaceForm({Key? key}) : super(key: key); + const RaceForm({super.key}); @override Widget build(BuildContext context) { @@ -22,7 +22,7 @@ class RaceForm extends GetView with RepositoryServiceMixin { () => Obx( () => TextFormField( decoration: InputDecoration( - label: Text(S.current.formGeneralNameGeneric(S.current.entity(Race))), + label: Text(tr.generic.entityName(tr.entity(Race))), ), textCapitalization: TextCapitalization.words, controller: controller.name, @@ -30,24 +30,27 @@ class RaceForm extends GetView with RepositoryServiceMixin { ), () => Obx( () => SelectBox( - value: controller.classKeys.value.isNotEmpty ? controller.classKeys.value.first : null, + value: controller.classKeys.value.isNotEmpty + ? controller.classKeys.value.first + : null, onChanged: (value) => controller.classKeys.value = [value!], isExpanded: true, - label: Text(S.current.entity(CharacterClass)), - items: {...repo.builtIn.classes.values, ...repo.my.classes.values} - .map( - (cls) => DropdownMenuItem( - child: Text(cls.name), - value: cls.reference, - ), - ) - .toList(), + label: Text(tr.entity(CharacterClass)), + items: + {...repo.builtIn.classes.values, ...repo.my.classes.values} + .map( + (cls) => DropdownMenuItem( + value: cls.reference, + child: Text(cls.name), + ), + ) + .toList(), ), ), () => Obx( () => RichTextField( decoration: InputDecoration( - label: Text(S.current.formGeneralDescriptionGeneric(S.current.entity(Race))), + label: Text(tr.generic.entityDescription(tr.entity(Race))), ), maxLines: 10, minLines: 5, @@ -59,7 +62,7 @@ class RaceForm extends GetView with RepositoryServiceMixin { () => Obx( () => RichTextField( decoration: InputDecoration( - label: Text(S.current.formGeneralExplanationGeneric(S.current.entity(Race))), + label: Text(tr.generic.entityExplanation(tr.entity(Race))), ), maxLines: 10, minLines: 5, @@ -71,7 +74,8 @@ class RaceForm extends GetView with RepositoryServiceMixin { () => Obx( () => DiceListInput( controller: controller.dice, - abilityScores: controller.args.abilityScores ?? AbilityScores.dungeonWorldAll(10), + abilityScores: controller.args.abilityScores ?? + AbilityScores.dungeonWorldAll(10), guessFrom: [controller.description, controller.explanation], ), ), @@ -85,7 +89,8 @@ class RaceForm extends GetView with RepositoryServiceMixin { } } -class RaceFormController extends LibraryEntityFormController { +class RaceFormController + extends LibraryEntityFormController { final _name = TextEditingController().obs; final _description = TextEditingController().obs; final _explanation = TextEditingController().obs; @@ -101,7 +106,8 @@ class RaceFormController extends LibraryEntityFormController> get classKeys => _classKeys.value; @override - List> get fields => [_name, _description, _explanation, _dice, _tags, _classKeys]; + List> get fields => + [_name, _description, _explanation, _dice, _tags, _classKeys]; @override void onInit() { diff --git a/lib/app/widgets/forms/spell_form.dart b/lib/app/widgets/forms/spell_form.dart index f3b13a1c..ca519145 100644 --- a/lib/app/widgets/forms/spell_form.dart +++ b/lib/app/widgets/forms/spell_form.dart @@ -1,6 +1,6 @@ +import 'package:dungeon_paper/app/data/models/ability_scores.dart'; import 'package:dungeon_paper/app/data/models/character_class.dart'; import 'package:dungeon_paper/app/data/models/spell.dart'; -import 'package:dungeon_paper/app/data/models/ability_scores.dart'; import 'package:dungeon_paper/app/data/services/repository_service.dart'; import 'package:dungeon_paper/app/widgets/atoms/rich_text_field.dart'; import 'package:dungeon_paper/app/widgets/atoms/select_box.dart'; @@ -8,13 +8,14 @@ import 'package:dungeon_paper/app/widgets/forms/library_entity_form.dart'; import 'package:dungeon_paper/app/widgets/molecules/dice_list_input.dart'; import 'package:dungeon_paper/app/widgets/molecules/tag_list_input.dart'; import 'package:dungeon_paper/core/utils/math_utils.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; +import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; -class SpellForm extends GetView with RepositoryServiceMixin { - const SpellForm({Key? key}) : super(key: key); +class SpellForm extends GetView + with RepositoryServiceMixin { + const SpellForm({super.key}); @override Widget build(BuildContext context) { @@ -23,7 +24,7 @@ class SpellForm extends GetView with RepositoryServiceMixin () => Obx( () => TextFormField( decoration: InputDecoration( - label: Text(S.current.formGeneralNameGeneric(S.current.entity(Spell))), + label: Text(tr.generic.entityName(tr.entity(Spell))), ), textCapitalization: TextCapitalization.words, controller: controller.name, @@ -35,13 +36,17 @@ class SpellForm extends GetView with RepositoryServiceMixin child: Obx( () => SelectBox( value: controller.level.value, - label: Text(S.current.entity(S.current.level)), + label: Text(tr.character.data.level), isExpanded: true, - items: {'cantrip', 'rote', ...range(9).map((i) => (i + 1).toString())} + items: { + 'cantrip', + 'rote', + ...range(9).map((i) => (i + 1).toString()) + } .map( (lv) => DropdownMenuItem( - child: Text(S.current.spellLevel(lv)), value: lv, + child: Text(tr.spells.spellLevel(lv)), ), ) .toList(), @@ -53,15 +58,21 @@ class SpellForm extends GetView with RepositoryServiceMixin Expanded( child: Obx( () => SelectBox( - value: controller.classKeys.value.isNotEmpty ? controller.classKeys.value.first : null, - onChanged: (value) => controller.classKeys.value = [value!], + value: controller.classKeys.value.isNotEmpty + ? controller.classKeys.value.first + : null, + onChanged: (value) => + controller.classKeys.value = [value!], isExpanded: true, - label: Text(S.current.entity(CharacterClass)), - items: {...repo.builtIn.classes.values, ...repo.my.classes.values} + label: Text(tr.entity(CharacterClass)), + items: { + ...repo.builtIn.classes.values, + ...repo.my.classes.values + } .map( (cls) => DropdownMenuItem( - child: Text(cls.name), value: cls.reference, + child: Text(cls.name), ), ) .toList(), @@ -73,7 +84,7 @@ class SpellForm extends GetView with RepositoryServiceMixin () => Obx( () => RichTextField( decoration: InputDecoration( - label: Text(S.current.formGeneralDescriptionGeneric(S.current.entity(Spell))), + label: Text(tr.generic.entityDescription(tr.entity(Spell))), ), maxLines: 10, minLines: 5, @@ -85,7 +96,7 @@ class SpellForm extends GetView with RepositoryServiceMixin () => Obx( () => RichTextField( decoration: InputDecoration( - label: Text(S.current.formGeneralExplanationGeneric(S.current.entity(Spell))), + label: Text(tr.generic.entityExplanation(tr.entity(Spell))), ), maxLines: 10, minLines: 5, @@ -97,7 +108,8 @@ class SpellForm extends GetView with RepositoryServiceMixin () => Obx( () => DiceListInput( controller: controller.dice, - abilityScores: controller.args.abilityScores ?? AbilityScores.dungeonWorldAll(10), + abilityScores: controller.args.abilityScores ?? + AbilityScores.dungeonWorldAll(10), guessFrom: [controller.description, controller.explanation], ), ), @@ -111,7 +123,8 @@ class SpellForm extends GetView with RepositoryServiceMixin } } -class SpellFormController extends LibraryEntityFormController { +class SpellFormController + extends LibraryEntityFormController { final _name = TextEditingController().obs; final _description = TextEditingController().obs; final _explanation = TextEditingController().obs; @@ -129,7 +142,8 @@ class SpellFormController extends LibraryEntityFormController> get classKeys => _classKeys.value; @override - List> get fields => [_name, _description, _explanation, _dice, _tags, _category, _classKeys]; + List> get fields => + [_name, _description, _explanation, _dice, _tags, _category, _classKeys]; @override void onInit() { diff --git a/lib/app/widgets/menus/entity_edit_menu.dart b/lib/app/widgets/menus/entity_edit_menu.dart index 73f3be8e..79ce704e 100644 --- a/lib/app/widgets/menus/entity_edit_menu.dart +++ b/lib/app/widgets/menus/entity_edit_menu.dart @@ -1,15 +1,15 @@ import 'package:dungeon_paper/app/widgets/atoms/menu_button.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; class EntityEditMenu extends StatelessWidget { const EntityEditMenu({ - Key? key, + super.key, required this.onEdit, required this.onDelete, this.leading = const [], this.trailing = const [], - }) : super(key: key); + }); final void Function()? onEdit; final void Function()? onDelete; @@ -27,10 +27,6 @@ class EntityEditMenu extends StatelessWidget { shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), clipBehavior: Clip.antiAlias, child: MenuButton( - child: const Padding( - padding: EdgeInsets.all(8), - child: Icon(Icons.more_vert), - ), items: [ ...leading, if (leading.isNotEmpty) @@ -43,7 +39,7 @@ class EntityEditMenu extends StatelessWidget { MenuEntry( value: 'edit', icon: const Icon(Icons.edit), - label: Text(S.current.edit), + label: Text(tr.generic.edit), onSelect: onEdit!, ), if (onDelete != null) @@ -55,7 +51,7 @@ class EntityEditMenu extends StatelessWidget { ), label: DefaultTextStyle.merge( style: TextStyle(color: Theme.of(context).colorScheme.error), - child: Text(S.current.remove), + child: Text(tr.generic.remove), ), onSelect: onDelete!, ), @@ -67,6 +63,10 @@ class EntityEditMenu extends StatelessWidget { ), ...trailing, ], + child: const Padding( + padding: EdgeInsets.all(8), + child: Icon(Icons.more_vert), + ), ), ); } diff --git a/lib/app/widgets/menus/group_sort_menu.dart b/lib/app/widgets/menus/group_sort_menu.dart index 5ac39ccf..695f2d1c 100644 --- a/lib/app/widgets/menus/group_sort_menu.dart +++ b/lib/app/widgets/menus/group_sort_menu.dart @@ -1,16 +1,16 @@ import 'package:dungeon_paper/app/widgets/atoms/menu_button.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; class GroupSortMenu extends StatelessWidget { const GroupSortMenu({ - Key? key, + super.key, required this.index, required this.totalItemCount, required this.onReorder, this.leading = const [], this.trailing = const [], - }) : super(key: key); + }); final int index; final int totalItemCount; @@ -28,14 +28,14 @@ class GroupSortMenu extends StatelessWidget { disabled: index <= 0, value: 'up', icon: const Icon(Icons.move_up), - label: Text(S.current.sortMoveUp), + label: Text(tr.sort.moveUp), onSelect: () => onReorder(index, index - 1), ), MenuEntry( disabled: index >= totalItemCount - 1, value: 'down', icon: const Icon(Icons.move_down), - label: Text(S.current.sortMoveDown), + label: Text(tr.sort.moveDown), onSelect: () => onReorder(index, index + 1), ), ...trailing, diff --git a/lib/app/widgets/molecules/character_subtitle.dart b/lib/app/widgets/molecules/character_subtitle.dart index 676db5a3..90aa852d 100644 --- a/lib/app/widgets/molecules/character_subtitle.dart +++ b/lib/app/widgets/molecules/character_subtitle.dart @@ -1,15 +1,15 @@ import 'package:dungeon_paper/app/data/models/character.dart'; import 'package:dungeon_paper/app/widgets/atoms/icon_span.dart'; import 'package:dungeon_paper/core/utils/list_utils.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; class CharacterSubtitle extends StatelessWidget { const CharacterSubtitle({ - Key? key, + super.key, required this.character, this.textAlign = TextAlign.center, - }) : super(key: key); + }); final Character character; final TextAlign textAlign; @@ -21,9 +21,11 @@ class CharacterSubtitle extends StatelessWidget { text: TextSpan( style: Theme.of(context).textTheme.bodyMedium, children: [ - TextSpan(text: S.current.characterHeaderSubtitleLevel(character.stats.level)), - TextSpan(text: S.current.characterHeaderSubtitleClass(character.characterClass.name)), - TextSpan(text: S.current.characterHeaderSubtitleRace(character.race.name)), + TextSpan(text: tr.character.header.level(character.stats.level)), + TextSpan( + text: tr.character.header + .characterClass(character.characterClass.name)), + TextSpan(text: tr.character.header.race(character.race.name)), TextSpan( children: [ IconSpan( @@ -31,16 +33,17 @@ class CharacterSubtitle extends StatelessWidget { icon: character.bio.alignment.icon, ), TextSpan( + // ignore: prefer_interpolation_to_compose_strings text: ' ' + - S.current.characterHeaderSubtitleAlignment( - S.current.alignment(character.bio.alignment.type), + tr.character.header.alignment( + tr.alignment.name(character.bio.alignment.key), ), ), ], ), ] .joinObjects( - TextSpan(text: S.current.characterHeaderSubtitleSeparator), + TextSpan(text: tr.character.header.separator), ) .toList(), ), @@ -51,13 +54,13 @@ class CharacterSubtitle extends StatelessWidget { // spacing: 4, // children: [ // Text( - // S.current.characterHeaderSubtitle( + // tr.character.header.( // character.stats.level, // character.characterClass.name, // character.race.name, // // "test", // // char.bio.toRawJson() ?? 'test', - // // S.current.alignment(char.bio.alignment.key), + // // tr.alignment.name(char.bio.alignment.key), // ), // ), // Row( @@ -70,12 +73,12 @@ class CharacterSubtitle extends StatelessWidget { // ), // const SizedBox(width: 4), // Text( - // // S.current.characterHeaderSubtitle( + // // tr.character.header.( // // char.stats.level, // // char.characterClass.name, // // "test", // // char.bio.toRawJson() ?? 'test', - // S.current.alignment(character.bio.alignment.key), + // tr.alignment.name(character.bio.alignment.key), // // ), // ), // ], diff --git a/lib/app/widgets/molecules/chip_list_input.dart b/lib/app/widgets/molecules/chip_list_input.dart index c7da9815..b57dff68 100644 --- a/lib/app/widgets/molecules/chip_list_input.dart +++ b/lib/app/widgets/molecules/chip_list_input.dart @@ -1,9 +1,8 @@ import 'package:dungeon_paper/core/utils/list_utils.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import '../../../generated/l10n.dart'; - class ChipListInput extends StatefulWidget { const ChipListInput({ super.key, @@ -47,7 +46,8 @@ class _ChipListInputState extends State> { @override void initState() { - controller = (widget.controller ?? ValueNotifier([]))..addListener(_listener); + controller = (widget.controller ?? ValueNotifier([])) + ..addListener(_listener); super.initState(); } @@ -63,13 +63,17 @@ class _ChipListInputState extends State> { @override Widget build(BuildContext context) { - final isNotAtMax = widget.maxCount == null || controller.value.length < widget.maxCount!; + final isNotAtMax = + widget.maxCount == null || controller.value.length < widget.maxCount!; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ DefaultTextStyle( - child: widget.label ?? Text(S.current.entityPlural(T)), - style: Theme.of(context).textTheme.bodySmall!.copyWith(color: widget.labelColor), + style: Theme.of(context) + .textTheme + .bodySmall! + .copyWith(color: widget.labelColor), + child: widget.label ?? Text(tr.entityPlural(T)), ), const SizedBox(height: 6), Wrap( @@ -82,14 +86,17 @@ class _ChipListInputState extends State> { widget.chipBuilder( context, dice, - onDeleteChip: () => setState(() => controller.value = [...controller.value..removeAt(dice.index)]), + onDeleteChip: () => setState(() => controller.value = [ + ...controller.value..removeAt(dice.index) + ]), onTapChip: widget.dialogBuilder != null ? () => Get.dialog( widget.dialogBuilder!( context, dice, - onSave: (_value) { - setState(() => controller.value = updateByIndex(controller.value, _value, dice.index)); + onSave: (value) { + setState(() => controller.value = updateByIndex( + controller.value, value, dice.index)); }, ), ) @@ -105,12 +112,18 @@ class _ChipListInputState extends State> { widget.dialogBuilder!( context, null, - onSave: (_value) { - setState(() => controller.value = [...controller.value, _value]); + onSave: (value) { + setState(() => controller.value = [ + ...controller.value, + value + ]); }, ), ) - : () => setState(() => controller.value = [...controller.value, widget.addValue!]), + : () => setState(() => controller.value = [ + ...controller.value, + widget.addValue as T + ]), ), ...widget.trailing, ], @@ -131,8 +144,7 @@ Widget Function( Enumerated? value, { void Function()? onDeleteChip, required void Function() onTapChip, - }) - chipBuilder, + }) chipBuilder, ) { return (context, value, {onDeleteChip, required onTapChip}) => chipBuilder( context, diff --git a/lib/app/widgets/molecules/dialog_controls.dart b/lib/app/widgets/molecules/dialog_controls.dart index 56a7c46e..db8bd5b9 100644 --- a/lib/app/widgets/molecules/dialog_controls.dart +++ b/lib/app/widgets/molecules/dialog_controls.dart @@ -1,5 +1,5 @@ import 'package:dungeon_paper/app/themes/button_themes.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; class DialogControls { @@ -24,8 +24,8 @@ class DialogControls { if (cancelIcon == null) TextButton( onPressed: onCancel, - child: Text(cancelLabel), style: ButtonThemes.errorText(context), + child: Text(cancelLabel), ), if (spacing != null && spacing > 0) SizedBox(width: spacing), if (confirmIcon != null) @@ -74,8 +74,8 @@ class DialogControls { if (confirmIcon == null) ElevatedButton( onPressed: onConfirm, - child: Text(confirmLabel), style: ButtonThemes.errorElevated(context), + child: Text(confirmLabel), ), ]; @@ -89,10 +89,10 @@ class DialogControls { }) => negative( context, - confirmLabel: exitLabel ?? S.current.confirmExitDefaultOkLabel, + confirmLabel: exitLabel ?? tr.dialogs.confirmations.exit.ok, confirmIcon: const Icon(Icons.close), onConfirm: onExit, - cancelLabel: continueLabel ?? S.current.confirmExitDefaultCancelLabel, + cancelLabel: continueLabel ?? tr.dialogs.confirmations.exit.cancel, // cancelIcon: const Icon(Icons.close), onCancel: onContinue, spacing: spacing, @@ -109,10 +109,10 @@ class DialogControls { custom( context, confirmIcon: const Icon(Icons.check), - confirmLabel: saveLabel ?? S.current.save, + confirmLabel: saveLabel ?? tr.generic.save, onConfirm: onSave, cancelIcon: const Icon(Icons.close), - cancelLabel: cancelLabel ?? S.current.cancel, + cancelLabel: cancelLabel ?? tr.generic.cancel, onCancel: onCancel, spacing: spacing, ); @@ -126,10 +126,10 @@ class DialogControls { negative( context, confirmIcon: const Icon(Icons.delete), - confirmLabel: S.current.remove, + confirmLabel: tr.generic.remove, onConfirm: onDelete, cancelIcon: const Icon(Icons.close), - cancelLabel: S.current.cancel, + cancelLabel: tr.generic.cancel, onCancel: onCancel, spacing: spacing, ); @@ -138,7 +138,7 @@ class DialogControls { ElevatedButton.icon( onPressed: onDone, icon: const Icon(Icons.check), - label: Text(S.current.done), + label: Text(tr.generic.done), ), ]; } diff --git a/lib/app/widgets/molecules/dice_list_input.dart b/lib/app/widgets/molecules/dice_list_input.dart index e2374e63..b86ed98b 100644 --- a/lib/app/widgets/molecules/dice_list_input.dart +++ b/lib/app/widgets/molecules/dice_list_input.dart @@ -2,10 +2,9 @@ import 'package:dungeon_paper/app/data/models/ability_scores.dart'; import 'package:dungeon_paper/app/widgets/chips/dice_chip.dart'; import 'package:dungeon_paper/app/widgets/dialogs/add_dice_dialog.dart'; import 'package:dungeon_paper/app/widgets/molecules/chip_list_input.dart'; -import 'package:flutter/material.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; - -import '../../../generated/l10n.dart'; +import 'package:flutter/material.dart'; class DiceListInput extends StatefulWidget { const DiceListInput({ @@ -46,7 +45,8 @@ class _DiceListInputState extends State { @override Widget build(BuildContext context) { - bool isNotAtMax = widget.maxCount == null || controller.value.length < widget.maxCount!; + bool isNotAtMax = + widget.maxCount == null || controller.value.length < widget.maxCount!; return ChipListInput( label: widget.label, @@ -56,9 +56,10 @@ class _DiceListInputState extends State { abilityScores: widget.abilityScores, onSave: onSave, ), - chipBuilder: (context, dice, {onDeleteChip, required onTapChip}) => DiceChip( + chipBuilder: (context, dice, {onDeleteChip, required onTapChip}) => + DiceChip( dice: dice != null ? dice.value : dw.Dice.d6, - label: dice != null ? null : S.current.addGeneric(dw.Dice), + label: dice != null ? null : tr.generic.addEntity(tr.entity(dw.Dice)), icon: dice != null ? null : const Icon(Icons.add), onPressed: onTapChip, onDeleted: onDeleteChip, @@ -68,11 +69,13 @@ class _DiceListInputState extends State { trailing: [ if (isNotAtMax) for (final dice in guesses.where( - (guess) => !controller.value.map((d) => d.toString()).contains(guess.toString()), + (guess) => !controller.value + .map((d) => d.toString()) + .contains(guess.toString()), )) DiceChip( dice: dice, - label: S.current.diceSuggestion(dice.toString()), + label: tr.dice.suggestion(dice.toString()), onPressed: () => controller.value = [...controller.value, dice], ), ], diff --git a/lib/app/widgets/molecules/special_dice_list_input.dart b/lib/app/widgets/molecules/special_dice_list_input.dart index 9bfcd9f2..b5acf8e0 100644 --- a/lib/app/widgets/molecules/special_dice_list_input.dart +++ b/lib/app/widgets/molecules/special_dice_list_input.dart @@ -2,10 +2,9 @@ import 'package:dungeon_paper/app/data/models/roll_button.dart'; import 'package:dungeon_paper/app/themes/colors.dart'; import 'package:dungeon_paper/app/widgets/chips/dice_chip.dart'; import 'package:dungeon_paper/app/widgets/molecules/chip_list_input.dart'; -import 'package:flutter/material.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; - -import '../../../generated/l10n.dart'; +import 'package:flutter/material.dart'; class SpecialDiceListInput extends StatefulWidget { const SpecialDiceListInput({ @@ -32,14 +31,16 @@ class _SpecialDiceListInputState extends State { Widget build(BuildContext context) { return ChipListInput( controller: controller, - label: Text(S.current.specialDice), + label: Text(tr.customRolls.specialDice.title), addValue: SpecialDice.damage, - chipBuilder: (context, dice, {onDeleteChip, required onTapChip}) => DiceChip( + chipBuilder: (context, dice, {onDeleteChip, required onTapChip}) => + DiceChip( dice: dw.Dice.d6, backgroundColor: DwColors.warning, label: dice != null - ? S.current.specialRollButton(dice.value) - : S.current.addGeneric(S.current.specialRollButton(SpecialDice.damage)), + ? tr.customRolls.specialDice.button(dice.value.name) + : tr.generic.addEntity( + tr.customRolls.specialDice.button(SpecialDice.damage.name)), icon: dice != null ? null : const Icon(Icons.add), onPressed: onTapChip, onDeleted: onDeleteChip, diff --git a/lib/app/widgets/molecules/tag_list_input.dart b/lib/app/widgets/molecules/tag_list_input.dart index 0092870c..d65f5825 100644 --- a/lib/app/widgets/molecules/tag_list_input.dart +++ b/lib/app/widgets/molecules/tag_list_input.dart @@ -1,10 +1,9 @@ import 'package:dungeon_paper/app/widgets/chips/tag_chip.dart'; import 'package:dungeon_paper/app/widgets/dialogs/add_tag_dialog.dart'; import 'package:dungeon_paper/app/widgets/molecules/chip_list_input.dart'; -import 'package:flutter/material.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; - -import '../../../generated/l10n.dart'; +import 'package:flutter/material.dart'; class TagListInput extends StatelessWidget { const TagListInput({ @@ -27,8 +26,12 @@ class TagListInput extends StatelessWidget { tag: tag?.value, onSave: onSave, ), - chipBuilder: (context, tag, {onDeleteChip, required onTapChip}) => TagChip( - tag: tag != null ? tag.value : dw.Tag(name: S.current.addGeneric(dw.Tag), value: null), + chipBuilder: (context, tag, {onDeleteChip, required onTapChip}) => + TagChip( + tag: tag != null + ? tag.value + : dw.Tag( + name: tr.generic.addEntity(tr.entity(dw.Tag)), value: null), icon: tag != null ? null : const Icon(Icons.add), onPressed: onTapChip, onDeleted: onDeleteChip, diff --git a/lib/app/widgets/molecules/user_menu_popover.dart b/lib/app/widgets/molecules/user_menu_popover.dart index b275b29e..49bba62a 100644 --- a/lib/app/widgets/molecules/user_menu_popover.dart +++ b/lib/app/widgets/molecules/user_menu_popover.dart @@ -9,14 +9,15 @@ import 'package:dungeon_paper/app/data/services/user_service.dart'; import 'package:dungeon_paper/app/routes/app_pages.dart'; import 'package:dungeon_paper/app/themes/themes.dart'; import 'package:dungeon_paper/app/widgets/atoms/theme_brightness_switch.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../atoms/character_avatar.dart'; import '../atoms/user_avatar.dart'; -class UserMenuPopover extends GetView with AuthServiceMixin, UserServiceMixin { +class UserMenuPopover extends GetView + with AuthServiceMixin, UserServiceMixin { UserMenuPopover({super.key}); @override @@ -46,19 +47,23 @@ class UserMenuPopover extends GetView with AuthServiceMixin, U child: Card( clipBehavior: Clip.antiAlias, child: ConstrainedBox( - constraints: BoxConstraints(maxWidth: maxW, maxHeight: maxH), + constraints: + BoxConstraints(maxWidth: maxW, maxHeight: maxH), child: GestureDetector( behavior: HitTestBehavior.opaque, // ignore: avoid_returning_null_for_void onTap: () => null, child: Obx( () => ListView( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + padding: const EdgeInsets.symmetric( + horizontal: 16, vertical: 8), shrinkWrap: true, children: [ // User details ListTile( - onTap: userService.isLoggedIn ? () => Get.toNamed(Routes.account) : null, + onTap: userService.isLoggedIn + ? () => Get.toNamed(Routes.account) + : null, visualDensity: VisualDensity.compact, title: Text( '${userService.current.displayName} (@${userService.current.username})', @@ -67,7 +72,7 @@ class UserMenuPopover extends GetView with AuthServiceMixin, U subtitle: Text( userService.current.email.isNotEmpty ? userService.current.email - : S.current.userUnregistered, + : tr.auth.signup.notLoggedIn.label, ), trailing: userService.isGuest ? Row( @@ -79,7 +84,7 @@ class UserMenuPopover extends GetView with AuthServiceMixin, U Get.toNamed(Routes.login); }, icon: const Icon(Icons.login), - label: Text(S.current.userLoginButton), + label: Text(tr.auth.login.button), ), const SizedBox(width: 16), UserAvatar(user: user), @@ -92,8 +97,9 @@ class UserMenuPopover extends GetView with AuthServiceMixin, U if (controller.charsByLastUsed.isNotEmpty) ...[ const SizedBox(height: 8), Text( - S.current.userMenuRecentCharacters, - style: Theme.of(context).textTheme.bodySmall, + tr.user.recentCharacters, + style: + Theme.of(context).textTheme.bodySmall, ), Padding( padding: const EdgeInsets.only(top: 8), @@ -101,9 +107,12 @@ class UserMenuPopover extends GetView with AuthServiceMixin, U spacing: 4, runSpacing: 4, children: [ - for (final char in controller.charsByLastUsed.take(4)) + for (final char in controller + .charsByLastUsed + .take(4)) InkWell( - splashColor: Theme.of(context).splashColor, + splashColor: + Theme.of(context).splashColor, borderRadius: borderRadius, onTap: () { controller.setCurrent(char.key); @@ -113,15 +122,21 @@ class UserMenuPopover extends GetView with AuthServiceMixin, U padding: const EdgeInsets.all(4), child: Column( children: [ - CharacterAvatar.squircle(character: char, size: avatarSize), + CharacterAvatar.squircle( + character: char, + size: avatarSize), const SizedBox(height: 4), SizedBox( width: 60, child: Text( char.displayName, - overflow: TextOverflow.ellipsis, - textScaleFactor: 0.8, - textAlign: TextAlign.center, + overflow: + TextOverflow.ellipsis, + textScaler: + const TextScaler + .linear(0.8), + textAlign: + TextAlign.center, style: textStyle, ), ), @@ -139,7 +154,8 @@ class UserMenuPopover extends GetView with AuthServiceMixin, U ListTile( visualDensity: VisualDensity.compact, dense: true, - title: Text(S.current.allGeneric(S.current.entityPlural(Character))), + title: Text(tr.generic + .allEntities(tr.entityPlural(Character))), leading: const Icon(Icons.group), onTap: () { Get.back(); @@ -149,7 +165,8 @@ class UserMenuPopover extends GetView with AuthServiceMixin, U // Create Character ListTile( visualDensity: VisualDensity.compact, - title: Text(S.current.createGeneric(S.current.entity(Character))), + title: Text(tr.generic + .createEntity(tr.entity(Character))), leading: const Icon(Icons.person_add), onTap: () { Get.back(); @@ -160,7 +177,7 @@ class UserMenuPopover extends GetView with AuthServiceMixin, U // My Library ListTile( visualDensity: VisualDensity.compact, - title: Text(S.current.libraryCollectionTitle), + title: Text(tr.playbook.myLibrary), leading: const Icon(Icons.local_library), onTap: () { Get.back(); @@ -171,7 +188,7 @@ class UserMenuPopover extends GetView with AuthServiceMixin, U // My Campaigns ListTile( visualDensity: VisualDensity.compact, - title: Text(S.current.myGeneric(S.current.entityPlural(Campaign))), + title: Text(tr.playbook.myCampaigns), leading: Icon(Campaign.genericIcon), onTap: () { Get.back(); @@ -181,7 +198,7 @@ class UserMenuPopover extends GetView with AuthServiceMixin, U // Export/Import ListTile( visualDensity: VisualDensity.compact, - title: Text(S.current.importExportTitle), + title: Text(tr.settings.importExport), leading: const Icon(Icons.import_export), onTap: () { Get.back(); @@ -195,7 +212,7 @@ class UserMenuPopover extends GetView with AuthServiceMixin, U // Settings ListTile( visualDensity: VisualDensity.compact, - title: Text(S.current.settingsTitle), + title: Text(tr.settings.title), leading: const Icon(Icons.settings), onTap: () { Get.back(); @@ -205,7 +222,7 @@ class UserMenuPopover extends GetView with AuthServiceMixin, U // About ListTile( visualDensity: VisualDensity.compact, - title: Text(S.current.aboutTitle), + title: Text(tr.about.title), leading: const Icon(Icons.info), onTap: () { Get.back(); @@ -217,7 +234,7 @@ class UserMenuPopover extends GetView with AuthServiceMixin, U const Divider(), ListTile( visualDensity: VisualDensity.compact, - title: Text(S.current.userLogoutButton), + title: Text(tr.auth.logout.button), leading: const Icon(Icons.logout), onTap: () { Get.back(); diff --git a/lib/app/widgets/molecules/value_change_slider.dart b/lib/app/widgets/molecules/value_change_slider.dart index 8cc20dbc..18ccf051 100644 --- a/lib/app/widgets/molecules/value_change_slider.dart +++ b/lib/app/widgets/molecules/value_change_slider.dart @@ -76,12 +76,14 @@ class ValueChangeSlider extends StatelessWidget { value: updatedValue.toDouble(), min: minValue?.toDouble() ?? -double.infinity, max: maxValue?.toDouble() ?? double.infinity, - theme: - (theme.brightness == Brightness.light ? WheelSpinnerThemeData.light() : WheelSpinnerThemeData.dark()) - .copyWith( + theme: (theme.brightness == Brightness.light + ? WheelSpinnerThemeData.light() + : WheelSpinnerThemeData.dark()) + .copyWith( borderRadius: borderRadius, ), - onSlideUpdate: (val) => onChange((N == int ? val.toInt() : val.toDouble()) as N), + onSlideUpdate: (val) => + onChange((N == int ? val.toInt() : val.toDouble()) as N), ), ), ), diff --git a/lib/app/widgets/views/roll_dice_view.dart b/lib/app/widgets/views/roll_dice_view.dart index 9fc49f27..c3f786ea 100644 --- a/lib/app/widgets/views/roll_dice_view.dart +++ b/lib/app/widgets/views/roll_dice_view.dart @@ -9,18 +9,18 @@ import 'package:dungeon_paper/app/widgets/atoms/dice_icon.dart'; import 'package:dungeon_paper/app/widgets/molecules/dice_list_input.dart'; import 'package:dungeon_paper/core/utils/list_utils.dart'; import 'package:dungeon_paper/core/utils/math_utils.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; -import 'package:flutter/material.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:dungeon_world_data/dungeon_world_data.dart' as dw; +import 'package:flutter/material.dart'; import 'package:get/get.dart'; class RollDiceView extends StatefulWidget { final List dice; const RollDiceView({ - Key? key, + super.key, required this.dice, - }) : super(key: key); + }); static const rollAnimDuration = Duration(milliseconds: 1500); static const rollAnimResetDuration = Duration(milliseconds: 700); @@ -29,7 +29,8 @@ class RollDiceView extends StatefulWidget { State createState() => _RollDiceViewState(); } -class _RollDiceViewState extends State with TickerProviderStateMixin { +class _RollDiceViewState extends State + with TickerProviderStateMixin { final diceSize = 56.0; final diceSpacing = 24.0; late AnimationStatus rollStatus; @@ -40,7 +41,8 @@ class _RollDiceViewState extends State with TickerProviderStateMix var results = []; CharacterService get charService => Get.find(); - int get totalResult => results.fold(0, (previousValue, element) => previousValue + element.total); + int get totalResult => results.fold( + 0, (previousValue, element) => previousValue + element.total); List get flat => dw.Dice.flatten(dice.value); @override @@ -65,8 +67,8 @@ class _RollDiceViewState extends State with TickerProviderStateMix appBar: AppBar( title: Text( rollStatus == AnimationStatus.completed - ? S.current.rollDialogTitleRolled(totalResult) - : S.current.rollDialogTitleRolling(flat.length), + ? tr.dice.roll.title.rolled(totalResult) + : tr.dice.roll.title.rolling(flat.length), ), centerTitle: true, backgroundColor: Colors.transparent, @@ -101,7 +103,8 @@ class _RollDiceViewState extends State with TickerProviderStateMix // mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - for (final group in enumerate(dice.value)) _groupBuilder(group), + for (final group in enumerate(dice.value)) + _groupBuilder(group), ], ), ), @@ -114,7 +117,7 @@ class _RollDiceViewState extends State with TickerProviderStateMix ), ), floatingActionButton: AdvancedFloatingActionButton.extended( - label: Text(S.current.diceRollAgain), + label: Text(tr.dice.roll.action), icon: const Icon(Icons.refresh), onPressed: _reRoll, ), @@ -131,9 +134,12 @@ class _RollDiceViewState extends State with TickerProviderStateMix final textTheme = Theme.of(context).textTheme; final currentAnimGroup = animations[group.index]; return Padding( - padding: group.index != dice.value.length - 1 ? const EdgeInsets.only(bottom: 24) : EdgeInsets.zero, + padding: group.index != dice.value.length - 1 + ? const EdgeInsets.only(bottom: 24) + : EdgeInsets.zero, child: Material( - color: cardColor.withOpacity(cardColor.opacity * currentAnimGroup.first.opacity.value), + color: cardColor.withOpacity( + cardColor.opacity * currentAnimGroup.first.opacity.value), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), child: Padding( padding: const EdgeInsets.all(8), @@ -152,15 +158,21 @@ class _RollDiceViewState extends State with TickerProviderStateMix crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - S.current.rollDialogResultTotal(results.isNotEmpty ? results[group.index].total : 0), - style: textTheme.titleLarge!.copyWith(color: Colors.white), + tr.dice.roll.total(results.isNotEmpty + ? results[group.index].total + : 0), + style: + textTheme.titleLarge!.copyWith(color: Colors.white), ), Text( - S.current.rollDialogResultBreakdown( + tr.dice.roll.resultBreakdown( (withoutModDice.value[group.index]).toString(), - (group.value.modifierWithSign.isEmpty ? '+0' : group.value.modifierWithSign), + (group.value.modifierWithSign.isEmpty + ? '+0' + : group.value.modifierWithSign), ), - style: textTheme.bodyMedium!.copyWith(color: Colors.white.withOpacity(0.75)), + style: textTheme.bodyMedium! + .copyWith(color: Colors.white.withOpacity(0.75)), ), ], ), @@ -173,7 +185,8 @@ class _RollDiceViewState extends State with TickerProviderStateMix runSpacing: diceSpacing, spacing: diceSpacing, children: [ - for (final d in enumerate(dw.Dice.flatten([group.value]))) Builder(builder: _diceBuilder(group, d)), + for (final d in enumerate(dw.Dice.flatten([group.value]))) + Builder(builder: _diceBuilder(group, d)), ], ), ], @@ -191,7 +204,8 @@ class _RollDiceViewState extends State with TickerProviderStateMix final maxHeight = _getMaxHeight(context); final isDark = Theme.of(context).brightness == Brightness.dark; final currentAnim = animations[group.index][d.index]; - final currentResult = results.isNotEmpty ? results[group.index].results[d.index] : null; + final currentResult = + results.isNotEmpty ? results[group.index].results[d.index] : null; final colorScheme = Theme.of(context).colorScheme; final textContainerColor = currentResult == group.value.sides @@ -234,7 +248,8 @@ class _RollDiceViewState extends State with TickerProviderStateMix style: const TextStyle( color: Colors.white, ), - textScaleFactor: resultStr.length > 2 ? 1 : 1.5, + textScaler: TextScaler.linear( + resultStr.length > 2 ? 1 : 1.5), ), ), ), @@ -266,7 +281,9 @@ class _RollDiceViewState extends State with TickerProviderStateMix .map( (d) => d.needsModifier ? d.copyWithModifierValue( - charService.current.abilityScores.getStat(d.modifierStat!).modifier, + charService.current.abilityScores + .getStat(d.modifierStat!) + .modifier, ) : d, ) @@ -310,7 +327,8 @@ class _RollDiceViewState extends State with TickerProviderStateMix } Future _walkAnimations( - FutureOr Function(_AnimSet animation, int groupIndex, int animIndex) cb, + FutureOr Function(_AnimSet animation, int groupIndex, int animIndex) + cb, ) async { for (final group in enumerate(animations)) { for (final anim in enumerate(group.value)) { @@ -342,7 +360,8 @@ class _RollDiceViewState extends State with TickerProviderStateMix ); rollStatus = AnimationStatus.forward; _walkAnimations( - ((animation, groupIndex, animIndex) => animation.controller.addListener(_updateAnimStatus)), + ((animation, groupIndex, animIndex) => + animation.controller.addListener(_updateAnimStatus)), ); if (animations.isNotEmpty && animations.last.isNotEmpty) { animations.last.last.controller.addListener(_updateAnimStatus); @@ -396,7 +415,8 @@ class _AnimSet { final forwardTween = Tween(begin: 0, end: 1); final reverseTween = Tween(begin: 1, end: 0); - controller = AnimationController(vsync: vsync, duration: RollDiceView.rollAnimDuration); + controller = AnimationController( + vsync: vsync, duration: RollDiceView.rollAnimDuration); angle = reverseTween.animate(CurvedAnimation( parent: controller, curve: const Interval(0, 0.75, curve: Curves.easeOutQuad), diff --git a/lib/core/dw_icons.dart b/lib/core/dw_icons.dart index 787af51a..87328636 100644 --- a/lib/core/dw_icons.dart +++ b/lib/core/dw_icons.dart @@ -23,51 +23,90 @@ class DwIcons { static const String? _kFontPkg = null; // General - static const IconData armor = IconData(0xe800, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData book_cover = IconData(0xe801, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData coin_stack = IconData(0xe805, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData dumbbell = IconData(0xe803, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData exclamation = IconData(0xe804, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData hand_rock = IconData(0xe806, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData knapsack = IconData(0xe807, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData quill = IconData(0xe808, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData riposte = IconData(0xe809, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData scroll_quill = IconData(0xe80a, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData swap_bag = IconData(0xe80b, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData swords = IconData(0xe80c, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData armor = + IconData(0xe800, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData book_cover = + IconData(0xe801, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData coin_stack = + IconData(0xe805, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData dumbbell = + IconData(0xe803, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData exclamation = + IconData(0xe804, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData hand_rock = + IconData(0xe806, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData knapsack = + IconData(0xe807, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData quill = + IconData(0xe808, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData riposte = + IconData(0xe809, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData scroll_quill = + IconData(0xe80a, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData swap_bag = + IconData(0xe80b, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData swords = + IconData(0xe80c, fontFamily: _kFontFam, fontPackage: _kFontPkg); // Stats - static const IconData stat_cha = IconData(0xe80d, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData stat_con = IconData(0xe80e, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData stat_dex = IconData(0xe80f, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData stat_int = IconData(0xe810, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData stat_str = IconData(0xe811, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData stat_wis = IconData(0xe812, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData stat_cha = + IconData(0xe80d, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData stat_con = + IconData(0xe80e, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData stat_dex = + IconData(0xe80f, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData stat_int = + IconData(0xe810, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData stat_str = + IconData(0xe811, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData stat_wis = + IconData(0xe812, fontFamily: _kFontFam, fontPackage: _kFontPkg); // Dice - static const IconData dice_d10 = IconData(0xe816, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData dice_d12 = IconData(0xe817, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData dice_d20 = IconData(0xe818, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData dice_d4 = IconData(0xe813, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData dice_d6 = IconData(0xe814, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData dice_d6_numbered = IconData(0xe802, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData dice_d8 = IconData(0xe815, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData dice_d10 = + IconData(0xe816, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData dice_d12 = + IconData(0xe817, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData dice_d20 = + IconData(0xe818, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData dice_d4 = + IconData(0xe813, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData dice_d6 = + IconData(0xe814, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData dice_d6_numbered = + IconData(0xe802, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData dice_d8 = + IconData(0xe815, fontFamily: _kFontFam, fontPackage: _kFontPkg); // Social - static const IconData app_store = IconData(0xf36f, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData app_store_ios = IconData(0xf370, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData apple = IconData(0xf179, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData discord = IconData(0xf392, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData facebook = IconData(0xf09a, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData facebook_squared = IconData(0xf308, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData github_circled = IconData(0xf09b, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData google = IconData(0xf1a0, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData google_drive = IconData(0xf3aa, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData google_play = IconData(0xf3ab, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData linkedin = IconData(0xf0e1, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData linkedin_squared = IconData(0xf30c, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData twitter = IconData(0xf099, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData twitter_squared = IconData(0xf304, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData app_store = + IconData(0xf36f, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData app_store_ios = + IconData(0xf370, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData apple = + IconData(0xf179, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData discord = + IconData(0xf392, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData facebook = + IconData(0xf09a, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData facebook_squared = + IconData(0xf308, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData github_circled = + IconData(0xf09b, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData google = + IconData(0xf1a0, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData google_drive = + IconData(0xf3aa, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData google_play = + IconData(0xf3ab, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData linkedin = + IconData(0xf0e1, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData linkedin_squared = + IconData(0xf30c, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData twitter = + IconData(0xf099, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData twitter_squared = + IconData(0xf304, fontFamily: _kFontFam, fontPackage: _kFontPkg); static IconData statIcon(String stat) => { 'cha': DwIcons.stat_cha, @@ -99,5 +138,6 @@ class DwIcons { ProviderName.password: Icons.key, }[provider]!; - static IconData providerIconFromDomain(String domain) => providerIcon(providerNameFromDomain(domain)); + static IconData providerIconFromDomain(String domain) => + providerIcon(providerNameFromDomain(domain)); } diff --git a/lib/core/http/api.dart b/lib/core/http/api.dart index 40e8a9d2..5924bf93 100644 --- a/lib/core/http/api.dart +++ b/lib/core/http/api.dart @@ -8,7 +8,8 @@ import 'api_requests/migration.dart'; part 'requests.dart'; class Api { - static const baseUrl = 'https://us-central1-dw-sheet.cloudfunctions.net/main/api'; + static const baseUrl = + 'https://us-central1-dw-sheet.cloudfunctions.net/main/api'; final requests = Requests(); Future get( @@ -27,7 +28,8 @@ class Api { Object? body, Encoding? encoding, }) async { - final resp = await http.post(Uri.parse(baseUrl + url), headers: headers, body: body, encoding: encoding); + final resp = await http.post(Uri.parse(baseUrl + url), + headers: headers, body: body, encoding: encoding); return Response.fromHttp(resp); } } diff --git a/lib/core/http/api_requests/search.dart b/lib/core/http/api_requests/search.dart index 26dafd38..8597a48d 100644 --- a/lib/core/http/api_requests/search.dart +++ b/lib/core/http/api_requests/search.dart @@ -68,21 +68,38 @@ class SearchResponse { this.tags, }); - static List values(dynamic object) => object is List ? object : (object as Map).values.toList(); + static List values(dynamic object) => + object is List ? object : (object as Map).values.toList(); factory SearchResponse.fromJson(Map json) { - debugPrint('Parsing response: ${json.map((k, v) => MapEntry(k, v.length))}'); + debugPrint( + 'Parsing response: ${json.map((k, v) => MapEntry(k, v.length))}'); return SearchResponse( classes: json['CharacterClasses'] != null - ? List.from(values(json['CharacterClasses']).map((x) => CharacterClass.fromJson(x))) + ? List.from(values(json['CharacterClasses']) + .map((x) => CharacterClass.fromJson(x))) + : null, + items: json['Items'] != null + ? List.from(values(json['Items']).map((x) => Item.fromJson(x))) + : null, + monsters: json['Monsters'] != null + ? List.from(values(json['Monsters']).map((x) => Monster.fromJson(x))) + : null, + moves: json['Moves'] != null + ? List.from(values(json['Moves']).map((x) => Move.fromJson(x))) + : null, + races: json['Races'] != null + ? List.from(values(json['Races']).map((x) => Race.fromJson(x))) + : null, + spells: json['Spells'] != null + ? List.from(values(json['Spells']).map((x) => Spell.fromJson(x))) + : null, + notes: json['Notes'] != null + ? List.from(values(json['Notes']).map((x) => Note.fromJson(x))) + : null, + tags: json['Tags'] != null + ? List.from(values(json['Tags']).map((x) => dw.Tag.fromJson(x))) : null, - items: json['Items'] != null ? List.from(values(json['Items']).map((x) => Item.fromJson(x))) : null, - monsters: json['Monsters'] != null ? List.from(values(json['Monsters']).map((x) => Monster.fromJson(x))) : null, - moves: json['Moves'] != null ? List.from(values(json['Moves']).map((x) => Move.fromJson(x))) : null, - races: json['Races'] != null ? List.from(values(json['Races']).map((x) => Race.fromJson(x))) : null, - spells: json['Spells'] != null ? List.from(values(json['Spells']).map((x) => Spell.fromJson(x))) : null, - notes: json['Notes'] != null ? List.from(values(json['Notes']).map((x) => Note.fromJson(x))) : null, - tags: json['Tags'] != null ? List.from(values(json['Tags']).map((x) => dw.Tag.fromJson(x))) : null, ); } @@ -97,13 +114,24 @@ class SearchResponse { notes = []; factory SearchResponse.fromPackageRepo() => SearchResponse( - classes: - dw.dungeonWorldData.characterClasses.values.map((e) => CharacterClass.fromDwCharacterClass(e)).toList(), - items: dw.dungeonWorldData.items.values.map((e) => Item.fromDwItem(e)).toList(), - monsters: dw.dungeonWorldData.monsters.values.map((e) => Monster.fromDwMonster(e)).toList(), - moves: dw.dungeonWorldData.moves.values.map((e) => Move.fromDwMove(e)).toList(), - spells: dw.dungeonWorldData.spells.values.map((e) => Spell.fromDwSpell(e)).toList(), - races: dw.dungeonWorldData.races.values.map((e) => Race.fromDwRace(e)).toList(), + classes: dw.dungeonWorldData.characterClasses.values + .map((e) => CharacterClass.fromDwCharacterClass(e)) + .toList(), + items: dw.dungeonWorldData.items.values + .map((e) => Item.fromDwItem(e)) + .toList(), + monsters: dw.dungeonWorldData.monsters.values + .map((e) => Monster.fromDwMonster(e)) + .toList(), + moves: dw.dungeonWorldData.moves.values + .map((e) => Move.fromDwMove(e)) + .toList(), + spells: dw.dungeonWorldData.spells.values + .map((e) => Spell.fromDwSpell(e)) + .toList(), + races: dw.dungeonWorldData.races.values + .map((e) => Race.fromDwRace(e)) + .toList(), tags: dw.dungeonWorldData.tags.values.toList(), // notes: [], ); diff --git a/lib/core/http/requests.dart b/lib/core/http/requests.dart index 1003ae2c..47d6c46b 100644 --- a/lib/core/http/requests.dart +++ b/lib/core/http/requests.dart @@ -8,14 +8,17 @@ class Requests { return {'Authorization': 'Bearer $idToken'}; } - Future getDefaultRepository({bool ignoreCache = false}) async { - final Map headers = ignoreCache ? {'Cache-Control': 'no-cache'} : {}; + Future getDefaultRepository( + {bool ignoreCache = false}) async { + final Map headers = + ignoreCache ? {'Cache-Control': 'no-cache'} : {}; final resp = await api.get('/library/default', headers: headers); return SearchResponse.fromJson(resp.json); } Future migrateUser(MigrationDetails details) => - api.get('/user/migrate?${details.toString()}', headers: authorizationHeaders); + api.get('/user/migrate?${details.toString()}', + headers: authorizationHeaders); Future sendFeedback({ required String email, diff --git a/lib/core/localized_repository.dart b/lib/core/localized_repository.dart index ac8b3b2b..9aa04d94 100644 --- a/lib/core/localized_repository.dart +++ b/lib/core/localized_repository.dart @@ -10,7 +10,8 @@ class LocalizedRepository { LocalizedItem operator [](String key) => forLocale(currentLocale, key); - LocalizedItem forLocale(Locale locale, String key, {bool throwOnMissing = false}) { + LocalizedItem forLocale(Locale locale, String key, + {bool throwOnMissing = false}) { if (throwOnMissing && collections[key] == null) { throw StateError('Key $key not found'); } @@ -41,7 +42,8 @@ class LocalizedRepository { class LocalizedCollection { final locales = >{}; - LocalizedItem operator [](Locale locale) => locales[locale] ??= LocalizedItem(); + LocalizedItem operator [](Locale locale) => + locales[locale] ??= LocalizedItem(); void operator []=(String key, T item) => locales[key] ??= LocalizedItem(); bool localeExists(Locale locale) => locales.containsKey(locale); diff --git a/lib/core/storage_handler/cache_handler.dart b/lib/core/storage_handler/cache_handler.dart index 2d0c9e2f..ede07873 100644 --- a/lib/core/storage_handler/cache_handler.dart +++ b/lib/core/storage_handler/cache_handler.dart @@ -2,7 +2,8 @@ part of 'storage_handler.dart'; class CacheHandler extends StorageHandler { static LocalStorageDelegate? _instance; - static LocalStorageDelegate get instance => _instance ??= LocalStorageDelegate(); + static LocalStorageDelegate get instance => + _instance ??= LocalStorageDelegate(); @override String get currentDelegate => 'local'; diff --git a/lib/core/storage_handler/firestore_delegate.dart b/lib/core/storage_handler/firestore_delegate.dart index 10ec2686..a386ed9f 100644 --- a/lib/core/storage_handler/firestore_delegate.dart +++ b/lib/core/storage_handler/firestore_delegate.dart @@ -3,19 +3,28 @@ part of 'storage_handler.dart'; class FirestoreDelegate extends StorageDelegate { final storage = FirebaseFirestore.instance; - String get prefix => _collectionPrefix != null ? _collectionPrefix! + '/' : ''; + String get prefix => + _collectionPrefix != null ? _collectionPrefix! + '/' : ''; @override - Future> getCollection(String collection) => - storage.collection(prefix + collection).get().then((list) => list.docs.map((snap) => snap.data()).toList()); + Future> getCollection(String collection) => storage + .collection(prefix + collection) + .get() + .then((list) => list.docs.map((snap) => snap.data()).toList()); @override - Future getDocument(String collection, String document) => - storage.collection(prefix + collection).doc(document).get().then((snap) => snap.data()); + Future getDocument(String collection, String document) => storage + .collection(prefix + collection) + .doc(document) + .get() + .then((snap) => snap.data()); @override Future create(String collection, String document, DocData value) => - storage.collection(prefix + collection).doc(document).set(value, fs.SetOptions(merge: true)); + storage + .collection(prefix + collection) + .doc(document) + .set(value, fs.SetOptions(merge: true)); @override Future delete(String collection, String document) => @@ -33,7 +42,9 @@ class FirestoreDelegate extends StorageDelegate { void Function()? onDone, bool? cancelOnError, }) { - return asCollectionStream(storage.collection(prefix + collection).snapshots()).listen( + return asCollectionStream( + storage.collection(prefix + collection).snapshots()) + .listen( onData, onError: onError, onDone: onDone, @@ -50,7 +61,9 @@ class FirestoreDelegate extends StorageDelegate { void Function()? onDone, bool? cancelOnError, }) { - return asDocumentStream(storage.collection(prefix + collection).doc(document).snapshots()).listen( + return asDocumentStream( + storage.collection(prefix + collection).doc(document).snapshots()) + .listen( onData, onError: onError, onDone: onDone, @@ -58,7 +71,8 @@ class FirestoreDelegate extends StorageDelegate { ); } - Stream asDocumentStream(Stream> source) async* { + Stream asDocumentStream( + Stream> source) async* { try { await for (final snap in source) { yield snap.data(); @@ -68,7 +82,8 @@ class FirestoreDelegate extends StorageDelegate { } } - Stream> asCollectionStream(Stream> source) async* { + Stream> asCollectionStream( + Stream> source) async* { try { await for (final query in source) { yield query.docs.map((doc) => doc.data()).toList(); diff --git a/lib/core/storage_handler/local_store_delegate.dart b/lib/core/storage_handler/local_store_delegate.dart index fb76d5ad..09af7e4c 100644 --- a/lib/core/storage_handler/local_store_delegate.dart +++ b/lib/core/storage_handler/local_store_delegate.dart @@ -6,8 +6,10 @@ class LocalStorageDelegate extends StorageDelegate { final colStreams = >>{}; @override - Future> getCollection(String collection) => - storage.collection(collection).get().then((map) => map?.values.toList().cast() ?? []); + Future> getCollection(String collection) => storage + .collection(collection) + .get() + .then((map) => map?.values.toList().cast() ?? []); @override Future getDocument(String collection, String document) => @@ -16,24 +18,28 @@ class LocalStorageDelegate extends StorageDelegate { @override Future update(String collection, String document, DocData value) async { docStreams['$collection/$document']?.add(value); - colStreams[collection] - ?.add((await getCollection(collection)).map((e) => (e['key'] ?? e['name']) == document ? value : e).toList()); + colStreams[collection]?.add((await getCollection(collection)) + .map((e) => (e['key'] ?? e['name']) == document ? value : e) + .toList()); return storage.collection(collection).doc(document).set(value); } @override Future delete(String collection, String document) async { docStreams['$collection/$document']?.add(null); - colStreams[collection] - ?.add((await getCollection(collection)).where((e) => (e['key'] ?? e['name']) != document).toList()); + colStreams[collection]?.add((await getCollection(collection)) + .where((e) => (e['key'] ?? e['name']) != document) + .toList()); return storage.collection(collection).doc(document).delete(); } @override Future create(String collection, String document, DocData value) async { docStreams['$collection/$document']?.add(value); - colStreams[collection] - ?.add((await getCollection(collection)).where((e) => (e['key'] ?? e['name']) != document).toList()..add(value)); + colStreams[collection]?.add((await getCollection(collection)) + .where((e) => (e['key'] ?? e['name']) != document) + .toList() + ..add(value)); return storage.collection(collection).doc(document).set(value); } diff --git a/lib/core/storage_handler/storage_handler_core.dart b/lib/core/storage_handler/storage_handler_core.dart index 16d3f8e1..3e1a7858 100644 --- a/lib/core/storage_handler/storage_handler_core.dart +++ b/lib/core/storage_handler/storage_handler_core.dart @@ -46,7 +46,8 @@ class StorageHandler implements StorageDelegate { String? _collectionPrefix; @override - void setCollectionPrefix(String? prefix) => delegate.setCollectionPrefix(prefix); + void setCollectionPrefix(String? prefix) => + delegate.setCollectionPrefix(prefix); @override String? get collectionPrefix => delegate.collectionPrefix; diff --git a/lib/core/task_runner/args.dart b/lib/core/task_runner/args.dart index 0c8f38dd..796458fd 100644 --- a/lib/core/task_runner/args.dart +++ b/lib/core/task_runner/args.dart @@ -57,7 +57,9 @@ class ArgOptions { bump: bump, install: res['install'], platform: Device.values.firstWhere( - (device) => enumName(device).toLowerCase() == res['platform'].toString().toLowerCase(), + (device) => + enumName(device).toLowerCase() == + res['platform'].toString().toLowerCase(), orElse: () => Device.android, ), outputFilePrefix: getAppName(), @@ -78,9 +80,11 @@ class ArgOptions { Version version; Device platform = Device.android; - String get deviceFilePath => '/sdcard/Download/$outputFilePrefix-$version.apk'; + String get deviceFilePath => + '/sdcard/Download/$outputFilePrefix-$version.apk'; - String get localOutputPath => 'build/app/outputs/apk/release/app-arm64-v8a-release.apk'; + String get localOutputPath => + 'build/app/outputs/apk/release/app-arm64-v8a-release.apk'; List get deviceArgs => device != null ? ['-s', device!] : []; diff --git a/lib/core/task_runner/deploy.dart b/lib/core/task_runner/deploy.dart index 242347cc..81323c5c 100644 --- a/lib/core/task_runner/deploy.dart +++ b/lib/core/task_runner/deploy.dart @@ -26,9 +26,12 @@ void main(List args) { } throw Exception('No actions to perform'); } - final lst = o.mapLabels.keys.where((k) => o.mapLabels[k] == true).toList(); + final lst = + o.mapLabels.keys.where((k) => o.mapLabels[k] == true).toList(); final msg = [ - [lst.getRange(0, lst.length - 1).join(', '), lst.last].where((i) => i.isNotEmpty).join(' & ') + + [lst.getRange(0, lst.length - 1).join(', '), lst.last] + .where((i) => i.isNotEmpty) + .join(' & ') + (lst.length == 1 ? ' Only' : ''), if (o.build == true) 'Platform: ${enumName(o.platform)}', 'Version: ${o.version}', diff --git a/lib/core/task_runner/task.dart b/lib/core/task_runner/task.dart index 942684ba..1f98fa4a 100644 --- a/lib/core/task_runner/task.dart +++ b/lib/core/task_runner/task.dart @@ -29,7 +29,8 @@ class Task { FutureOr dispose() {} FutureOr run([T? options]) async { - assert(options != null || this.options != null, 'Options must be passed either in constructor or to run options.'); + assert(options != null || this.options != null, + 'Options must be passed either in constructor or to run options.'); await _run(options ?? this.options!); dispose(); } @@ -64,8 +65,10 @@ class TaskGroup extends Task { @override FutureOr run([ArgOptions? options]) { - assert(options != null || this.options != null, 'Options must be passed either in constructor or to run options.'); - return _runTasks(tasks, options ?? this.options!, condition).call(options ?? this.options!); + assert(options != null || this.options != null, + 'Options must be passed either in constructor or to run options.'); + return _runTasks(tasks, options ?? this.options!, condition) + .call(options ?? this.options!); } static Future Function(ArgOptions?) _runTasks( @@ -104,7 +107,8 @@ class DeviceTaskGroup extends TaskGroup { ArgOptions? options, }) : super( condition: condition != null - ? (o) => condition.call(o) != false && _isDeviceIncluded(o, device) + ? (o) => + condition.call(o) != false && _isDeviceIncluded(o, device) : (o) => _isDeviceIncluded(o, device), tasks: tasks, options: options, @@ -121,7 +125,8 @@ class DeviceTaskGroup extends TaskGroup { options: options, ); - static bool _isDeviceIncluded(ArgOptions o, Device device) => o.platform == Device.all || o.platform == device; + static bool _isDeviceIncluded(ArgOptions o, Device device) => + o.platform == Device.all || o.platform == device; } class ProcessTask extends Task { @@ -165,7 +170,8 @@ class ProcessTask extends Task { (o) async { final _process = await process(o); final _args = await (args?.call(o) ?? []); - final _argsStr = _args.map((a) => a.contains(' ') ? '"$a"' : a).join(' '); + final _argsStr = + _args.map((a) => a.contains(' ') ? '"$a"' : a).join(' '); print('\n\nRunning process: $_process $_argsStr\n\n'); try { final result = await Process.run(_process, _args); @@ -174,7 +180,8 @@ class ProcessTask extends Task { final exitCode = result.exitCode; if (exitCode != 0) { final stack = StackTrace.current; - final e = ProcessException(_process, _args, 'Process exited with error code: $exitCode', exitCode); + final e = ProcessException(_process, _args, + 'Process exited with error code: $exitCode', exitCode); _handleError(o, e, stack, onError); } } catch (e, stack) { diff --git a/lib/core/task_runner/task_utils.dart b/lib/core/task_runner/task_utils.dart index 622fb928..653b929b 100644 --- a/lib/core/task_runner/task_utils.dart +++ b/lib/core/task_runner/task_utils.dart @@ -45,10 +45,14 @@ Version getBumpedVersion(ArgOptions o) { o.version.major, o.version.minor, o.version.patch, - pre: o.version.preRelease.isEmpty ? null : o.version.preRelease.join('.'), + pre: o.version.preRelease.isEmpty + ? null + : o.version.preRelease.join('.'), build: o.version.build.isEmpty ? null - : o.version.build.map((part) => part is String ? part : (part as num) + 1).join('.'), + : o.version.build + .map((part) => part is String ? part : (part as num) + 1) + .join('.'), ); break; case BumpType.major: @@ -67,10 +71,14 @@ Version getBumpedVersion(ArgOptions o) { o.version.patch, pre: o.version.preRelease.isEmpty ? null - : o.version.preRelease.map((part) => part is String ? part : (part as num) + 1).join('-'), + : o.version.preRelease + .map((part) => part is String ? part : (part as num) + 1) + .join('-'), build: o.version.build.isEmpty ? null - : o.version.build.map((part) => part is String ? part : (part as num) + 1).join('-'), + : o.version.build + .map((part) => part is String ? part : (part as num) + 1) + .join('-'), ); break; } diff --git a/lib/core/task_runner/tasks/android_tasks.dart b/lib/core/task_runner/tasks/android_tasks.dart index 8f10f744..f26ce595 100644 --- a/lib/core/task_runner/tasks/android_tasks.dart +++ b/lib/core/task_runner/tasks/android_tasks.dart @@ -11,7 +11,8 @@ final installAndroid = TaskGroup( onError: (o, e, stack) async { TaskGroup( tasks: [ - LogTask.staticArgs('Failed to install. Uninstalling old version...'), + LogTask.staticArgs( + 'Failed to install. Uninstalling old version...'), ProcessTask.staticArgs( 'adb', args: [...o.deviceArgs, 'uninstall', 'app.dungeonpaper'], @@ -34,7 +35,8 @@ final pushAndroid = TaskGroup( LogTask((o) => 'Pushing to ${o.deviceFilePath}'), ProcessTask( (_) => 'adb', - args: (o) => [...o.deviceArgs, 'push', o.localOutputPath, o.deviceFilePath], + args: (o) => + [...o.deviceArgs, 'push', o.localOutputPath, o.deviceFilePath], ), ], ); diff --git a/lib/core/utils/builder_utils.dart b/lib/core/utils/builder_utils.dart index 95b4351b..0fe3c579 100644 --- a/lib/core/utils/builder_utils.dart +++ b/lib/core/utils/builder_utils.dart @@ -27,7 +27,9 @@ class ItemBuilder { return ItemBuilder._( itemBuilder: (context, index) { - if (leadingBuilder != null && leadingCount > 0 && index < leadingCount) { + if (leadingBuilder != null && + leadingCount > 0 && + index < leadingCount) { return leadingBuilder(context, index); } if (index >= childrenStartIndex && index < trailingStartIndex) { @@ -85,7 +87,8 @@ class ItemBuilder { double? cacheExtent, int? semanticChildCount, DragStartBehavior dragStartBehavior = DragStartBehavior.start, - ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual, + ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = + ScrollViewKeyboardDismissBehavior.manual, String? restorationId, Clip clipBehavior = Clip.hardEdge, ChildIndexGetter? findChildIndexCallback, @@ -135,7 +138,8 @@ class ItemBuilder { double? cacheExtent, int? semanticChildCount, DragStartBehavior dragStartBehavior = DragStartBehavior.start, - ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual, + ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = + ScrollViewKeyboardDismissBehavior.manual, String? restorationId, Clip clipBehavior = Clip.hardEdge, ChildIndexGetter? findChildIndexCallback, @@ -188,7 +192,8 @@ class ItemBuilder { double? cacheExtent, int? semanticChildCount, DragStartBehavior dragStartBehavior = DragStartBehavior.start, - ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual, + ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = + ScrollViewKeyboardDismissBehavior.manual, String? restorationId, Clip clipBehavior = Clip.hardEdge, ChildIndexGetter? findChildIndexCallback, @@ -236,7 +241,8 @@ class ItemBuilder { double? cacheExtent, int? semanticChildCount, DragStartBehavior dragStartBehavior = DragStartBehavior.start, - ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual, + ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = + ScrollViewKeyboardDismissBehavior.manual, String? restorationId, Clip clipBehavior = Clip.hardEdge, ChildIndexGetter? findChildIndexCallback, diff --git a/lib/core/utils/dialog_utils.dart b/lib/core/utils/dialog_utils.dart index 89343d4f..3143669f 100644 --- a/lib/core/utils/dialog_utils.dart +++ b/lib/core/utils/dialog_utils.dart @@ -1,18 +1,22 @@ import 'package:flutter/material.dart'; -Future awaitConfirmation(Future confirmation, void Function() callback) async { +Future awaitConfirmation( + Future confirmation, void Function() callback) async { final res = await confirmation; if (res) callback(); } abstract class ConfirmationDialog { - Future _awaitConfirmation(Future confirmation, void Function() callback) async { + Future _awaitConfirmation( + Future confirmation, void Function() callback) async { final res = await confirmation; if (res) callback(); } - Future confirm(BuildContext context, Options options, void Function() onSuccess) { - return _awaitConfirmation(_createConfirmation(context, options), onSuccess); + Future confirm( + BuildContext context, Options options, void Function() onSuccess) { + return _awaitConfirmation( + _createConfirmation(context, options), onSuccess); } Widget createConfirmation(BuildContext context, Options options); diff --git a/lib/core/utils/email_address_validator.dart b/lib/core/utils/email_address_validator.dart index 0c2d669b..07e83b7c 100644 --- a/lib/core/utils/email_address_validator.dart +++ b/lib/core/utils/email_address_validator.dart @@ -1,9 +1,9 @@ import 'package:dungeon_paper/core/utils/string_validator.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:email_validator/email_validator.dart'; class EmailAddressValidator extends Validation { - EmailAddressValidator() : super(S.current.errorInvalidEmail); + EmailAddressValidator() : super(tr.errors.invalidEmail); @override bool isValid(String? string) { diff --git a/lib/core/utils/filter_sort.dart b/lib/core/utils/filter_sort.dart index d00f58f3..b154c3e4 100644 --- a/lib/core/utils/filter_sort.dart +++ b/lib/core/utils/filter_sort.dart @@ -3,7 +3,8 @@ import 'enums.dart'; int Function(T1? date1, T1? date2) Function({ SortOrder order, T2? Function(T1? object)? parse, -}) createSorter([T2 Function(T2? object)? postParse]) { +}) createSorter( + [T2 Function(T2? object)? postParse]) { T2 _postParse(T2? x) => postParse != null ? postParse(x) : x as T2; return ({order = SortOrder.asc, parse}) { diff --git a/lib/core/utils/list_utils.dart b/lib/core/utils/list_utils.dart index d3e2a80f..34ece733 100644 --- a/lib/core/utils/list_utils.dart +++ b/lib/core/utils/list_utils.dart @@ -91,7 +91,8 @@ class Enumerated { List> enumerate(Iterable list) => Enumerated.listFrom(list); -List reorder(List list, int oldIndex, int newIndex, {bool useReorderableOffset = true}) { +List reorder(List list, int oldIndex, int newIndex, + {bool useReorderableOffset = true}) { if (useReorderableOffset && newIndex > oldIndex) { newIndex = newIndex - 1; } @@ -120,31 +121,38 @@ List sortByPredefined( return out; } -List updateByKey(List original, Iterable itemsToUpdate, {dynamic Function(T item)? key}) { +List updateByKey(List original, Iterable itemsToUpdate, + {dynamic Function(T item)? key}) { final keyGetter = key ?? Meta.keyFor; final keys = itemsToUpdate.map(keyGetter); return original - .map((x) => keys.contains(keyGetter(x)) ? itemsToUpdate.firstWhere((y) => keyGetter(x) == keyGetter(y)) : x) + .map((x) => keys.contains(keyGetter(x)) + ? itemsToUpdate.firstWhere((y) => keyGetter(x) == keyGetter(y)) + : x) .toList(); } List updateByIndex(List list, T item, int index) => enumerate(list).map((x) => x.index == index ? item : x.value).toList(); -List addByKey(List list, Iterable items, {dynamic Function(T item)? key}) { +List addByKey(List list, Iterable items, + {dynamic Function(T item)? key}) { final keyGetter = key ?? Meta.keyFor; final keys = items.map(keyGetter); return [...list.where((x) => !keys.contains(keyGetter(x))), ...items]; } -List upsertByKey(List list, Iterable items, {dynamic Function(T item)? key}) { +List upsertByKey(List list, Iterable items, + {dynamic Function(T item)? key}) { final keyGetter = key ?? Meta.keyFor; final keys = items.map(keyGetter); final existingKeys = list.map(keyGetter); return [ ...list - .map((x) => keys.contains(keyGetter(x)) ? items.firstWhere((y) => keyGetter(x) == keyGetter(y)) : x) + .map((x) => keys.contains(keyGetter(x)) + ? items.firstWhere((y) => keyGetter(x) == keyGetter(y)) + : x) .toList(), ...items.where((x) { return !existingKeys.contains(keyGetter(x)); @@ -152,7 +160,8 @@ List upsertByKey(List list, Iterable items, {dynamic Function(T item ]; } -List removeByKey(List list, Iterable items, {dynamic Function(T item)? key}) { +List removeByKey(List list, Iterable items, + {dynamic Function(T item)? key}) { final keyGetter = key ?? Meta.keyFor; final keys = items.map(keyGetter); return [...list]..removeWhere((x) => keys.contains(keyGetter(x))); diff --git a/lib/core/utils/map_utils.dart b/lib/core/utils/map_utils.dart index a81e1b7a..e1aab594 100644 --- a/lib/core/utils/map_utils.dart +++ b/lib/core/utils/map_utils.dart @@ -1,3 +1,4 @@ extension MapUtils on Map { - Map get inverse => Map.fromEntries(entries.map((ent) => MapEntry(ent.value, ent.key))); + Map get inverse => + Map.fromEntries(entries.map((ent) => MapEntry(ent.value, ent.key))); } diff --git a/lib/core/utils/markdown_highlight.dart b/lib/core/utils/markdown_highlight.dart index 2e8df1fe..583ead1a 100644 --- a/lib/core/utils/markdown_highlight.dart +++ b/lib/core/utils/markdown_highlight.dart @@ -9,8 +9,10 @@ class HighlightSyntax extends markdown.InlineSyntax { @override bool onMatch(markdown.InlineParser parser, Match match) { - final element = markdown.Element( - 'mark', [markdown.Element.text('span', match.input.substring(match.start + 2, match.end - 2))]); + final element = markdown.Element('mark', [ + markdown.Element.text( + 'span', match.input.substring(match.start + 2, match.end - 2)) + ]); parser.addNode(element); return true; } @@ -37,7 +39,8 @@ class HighlightBuilder extends flutter_markdown.MarkdownElementBuilder { final BuildContext context; @override - Widget? visitElementAfter(markdown.Element element, TextStyle? preferredStyle) { + Widget? visitElementAfter( + markdown.Element element, TextStyle? preferredStyle) { final highlightStyle = getHighlightStyle( context, override: getDefaultHighlightStyle(context), @@ -52,11 +55,12 @@ class HighlightBuilder extends flutter_markdown.MarkdownElementBuilder { ); } - static TextStyle getDefaultHighlightStyle(BuildContext context) => Theme.of(context).textTheme.bodyMedium!.copyWith( - color: Colors.black, - backgroundColor: Colors.yellow[200], - fontStyle: FontStyle.italic, - ); + static TextStyle getDefaultHighlightStyle(BuildContext context) => + Theme.of(context).textTheme.bodyMedium!.copyWith( + color: Colors.black, + backgroundColor: Colors.yellow[200], + fontStyle: FontStyle.italic, + ); static TextStyle getNormalStyle(BuildContext context, TextStyle? override) => override ?? Theme.of(context).textTheme.bodyMedium!; @@ -67,22 +71,33 @@ class HighlightBuilder extends flutter_markdown.MarkdownElementBuilder { required TextStyle normalStyle, }) { final defaultHighlightStyle = getDefaultHighlightStyle(context); - final normalColorBrightness = - ThemeData.estimateBrightnessForColor(normalStyle.color ?? defaultHighlightStyle.color!); - final backgroundColor = - override?.backgroundColor ?? normalStyle.backgroundColor ?? defaultHighlightStyle.backgroundColor!; - final highlightBackgroundColorBrightness = ThemeData.estimateBrightnessForColor(backgroundColor); - final brightnessHighlightColor = normalColorBrightness == highlightBackgroundColorBrightness - ? normalColorBrightness == Brightness.dark - ? Colors.white - : Colors.black - : null; + final normalColorBrightness = ThemeData.estimateBrightnessForColor( + normalStyle.color ?? defaultHighlightStyle.color!); + final backgroundColor = override?.backgroundColor ?? + normalStyle.backgroundColor ?? + defaultHighlightStyle.backgroundColor!; + final highlightBackgroundColorBrightness = + ThemeData.estimateBrightnessForColor(backgroundColor); + final brightnessHighlightColor = + normalColorBrightness == highlightBackgroundColorBrightness + ? normalColorBrightness == Brightness.dark + ? Colors.white + : Colors.black + : null; return normalStyle.copyWith( - fontFamily: override?.fontFamily ?? normalStyle.fontFamily ?? defaultHighlightStyle.fontFamily, - color: override?.color ?? brightnessHighlightColor ?? defaultHighlightStyle.color, + fontFamily: override?.fontFamily ?? + normalStyle.fontFamily ?? + defaultHighlightStyle.fontFamily, + color: override?.color ?? + brightnessHighlightColor ?? + defaultHighlightStyle.color, backgroundColor: backgroundColor, - fontStyle: override?.fontStyle ?? normalStyle.fontStyle ?? defaultHighlightStyle.fontStyle, - fontWeight: override?.fontWeight ?? normalStyle.fontWeight ?? defaultHighlightStyle.fontWeight, + fontStyle: override?.fontStyle ?? + normalStyle.fontStyle ?? + defaultHighlightStyle.fontStyle, + fontWeight: override?.fontWeight ?? + normalStyle.fontWeight ?? + defaultHighlightStyle.fontWeight, ); } } @@ -110,7 +125,8 @@ class HighlightText extends StatelessWidget { @override Widget build(BuildContext context) { final _text = highlight(text, highlightWords).split('=='); - final normalStyle = HighlightBuilder.getNormalStyle(context, normalTextStyle); + final normalStyle = + HighlightBuilder.getNormalStyle(context, normalTextStyle); final hlStyle = HighlightBuilder.getHighlightStyle( context, normalStyle: normalStyle, diff --git a/lib/core/utils/markdown_styles.dart b/lib/core/utils/markdown_styles.dart index 72735504..cd95b5c2 100644 --- a/lib/core/utils/markdown_styles.dart +++ b/lib/core/utils/markdown_styles.dart @@ -10,10 +10,14 @@ class MarkdownStyles { h1: _headingTheme(textTheme.displayLarge!, mdTheme.h1!), h2: _headingTheme(textTheme.displayMedium!, mdTheme.h2!), h3: _headingTheme(textTheme.displaySmall!, mdTheme.h3!), - h4: _headingTheme(textTheme.headlineMedium!, mdTheme.h4!, textScaleFactor: 0.93), - h5: _headingTheme(textTheme.headlineSmall!, mdTheme.h5!, textScaleFactor: 0.88), - h6: _headingTheme(textTheme.titleLarge!, mdTheme.h6!, textScaleFactor: 0.8), - blockquotePadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 2), + h4: _headingTheme(textTheme.headlineMedium!, mdTheme.h4!, + textScaleFactor: 0.93), + h5: _headingTheme(textTheme.headlineSmall!, mdTheme.h5!, + textScaleFactor: 0.88), + h6: _headingTheme(textTheme.titleLarge!, mdTheme.h6!, + textScaleFactor: 0.8), + blockquotePadding: + const EdgeInsets.symmetric(horizontal: 16, vertical: 2), blockquoteDecoration: BoxDecoration( border: Border( left: BorderSide( diff --git a/lib/core/utils/math_utils.dart b/lib/core/utils/math_utils.dart index 72c5d45b..a3f4b99d 100644 --- a/lib/core/utils/math_utils.dart +++ b/lib/core/utils/math_utils.dart @@ -12,7 +12,8 @@ Iterable range(int start, [int? end]) { return Iterable.generate((_max - min).toInt(), (i) => min + i); } -T avg(Iterable values) => values.reduce((a, b) => a + b as T) / values.length as T; +T avg(Iterable values) => + values.reduce((a, b) => a + b as T) / values.length as T; T sum(Iterable values) => values.reduce((a, b) => a + b as T); diff --git a/lib/core/utils/password_validator.dart b/lib/core/utils/password_validator.dart index 22ef3af4..e0cb26f6 100644 --- a/lib/core/utils/password_validator.dart +++ b/lib/core/utils/password_validator.dart @@ -1,5 +1,5 @@ import 'package:dungeon_paper/core/utils/string_validator.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; class PasswordValidator extends CompoundStringValidator { static const minLength = 8; @@ -9,11 +9,11 @@ class PasswordValidator extends CompoundStringValidator { StringMinLengthValidation(minLength: minLength), StringContainsValidation( pattern: RegExp('[A-Z]'), - message: S.current.signupPasswordValidationPatternLetter, + message: tr.errors.invalidPassword.letter, ), StringContainsValidation( pattern: RegExp('[0-9]'), - message: S.current.signupPasswordValidationPatternNumber, + message: tr.errors.invalidPassword.number, ), ]; } diff --git a/lib/core/utils/streams.dart b/lib/core/utils/streams.dart index fc8071bd..bf9fbe9c 100644 --- a/lib/core/utils/streams.dart +++ b/lib/core/utils/streams.dart @@ -29,9 +29,8 @@ class ValueNotifierStream extends Stream { void Function()? onDone, bool? cancelOnError, }) => - controller.stream - .asBroadcastStream() - .listen(onData, onError: onError, onDone: onDone, cancelOnError: cancelOnError); + controller.stream.asBroadcastStream().listen(onData, + onError: onError, onDone: onDone, cancelOnError: cancelOnError); } class TextEditingControllerStream extends Stream { @@ -50,7 +49,8 @@ class TextEditingControllerStream extends Stream { void Function()? onDone, bool? cancelOnError, }) { - return stream.listen(onData, onError: onError, onDone: onDone, cancelOnError: cancelOnError); + return stream.listen(onData, + onError: onError, onDone: onDone, cancelOnError: cancelOnError); } void init() { diff --git a/lib/core/utils/string_utils.dart b/lib/core/utils/string_utils.dart index fdb64ca9..55e974ac 100644 --- a/lib/core/utils/string_utils.dart +++ b/lib/core/utils/string_utils.dart @@ -1,7 +1,8 @@ import 'package:dungeon_paper/core/utils/filter_sort.dart'; List splitIntoWords(String string, {bool? lowerCase, bool? upperCase}) { - assert(lowerCase == null || upperCase == null, "Can't apply both uppercase and lowercase"); + assert(lowerCase == null || upperCase == null, + "Can't apply both uppercase and lowercase"); final pattern = RegExp(r'[^a-zA-Z0-9]|(?=[A-Z])'); final words = string.split(pattern).where((s) => s.isNotEmpty).toList(); if (lowerCase == true) return words.map((e) => e.toLowerCase()).toList(); @@ -9,23 +10,29 @@ List splitIntoWords(String string, {bool? lowerCase, bool? upperCase}) { return words; } -String wordToCapital(String string) => string.substring(0, 1).toUpperCase() + string.substring(1).toLowerCase(); +String wordToCapital(String string) => + string.substring(0, 1).toUpperCase() + string.substring(1).toLowerCase(); String toCamelCase(String string) { final words = splitIntoWords(string); if (words.isEmpty) { return ''; } - return [words.first.toLowerCase(), ...words.sublist(1).map(wordToCapital)].join(''); + return [words.first.toLowerCase(), ...words.sublist(1).map(wordToCapital)] + .join(''); } -String toPascalCase(String string) => splitIntoWords(string).map(wordToCapital).join(''); +String toPascalCase(String string) => + splitIntoWords(string).map(wordToCapital).join(''); -String toTitleCase(String string) => splitIntoWords(string).map(wordToCapital).join(' '); +String toTitleCase(String string) => + splitIntoWords(string).map(wordToCapital).join(' '); -String toSnakeCase(String string) => splitIntoWords(string).map((s) => s.toLowerCase()).join('_'); +String toSnakeCase(String string) => + splitIntoWords(string).map((s) => s.toLowerCase()).join('_'); -String toKebabCase(String string) => splitIntoWords(string).map((s) => s.toLowerCase()).join('-'); +String toKebabCase(String string) => + splitIntoWords(string).map((s) => s.toLowerCase()).join('-'); // int Function(T? date1, T? date2) dateComparator({ // SortOrder order = SortOrder.asc, @@ -48,4 +55,5 @@ final stringSorter = createSorter( String cleanStr(String str) => str.toLowerCase(); -bool Function(String) stringFilter(String search) => (str) => cleanStr(str).contains(cleanStr(search)); +bool Function(String) stringFilter(String search) => + (str) => cleanStr(str).contains(cleanStr(search)); diff --git a/lib/core/utils/string_validator.dart b/lib/core/utils/string_validator.dart index 7dbc7e65..02501a50 100644 --- a/lib/core/utils/string_validator.dart +++ b/lib/core/utils/string_validator.dart @@ -1,4 +1,4 @@ -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:get/get.dart'; abstract class Validation { @@ -15,7 +15,7 @@ class StringMinLengthValidation extends Validation { StringMinLengthValidation({ required this.minLength, - }) : super(S.current.errorMinLength(minLength)); + }) : super(tr.errors.minLength(minLength)); @override bool isValid(String? string) => string == null || string.length >= minLength; @@ -26,7 +26,7 @@ class StringExactLengthValidation extends Validation { StringExactLengthValidation({ required this.length, - }) : super(S.current.errorExactLength(length)); + }) : super(tr.errors.exactLength(length)); @override bool isValid(String? string) => string == null || string.length == length; @@ -37,7 +37,7 @@ class StringMaxLengthValidation extends Validation { StringMaxLengthValidation({ required this.maxLength, - }) : super(S.current.errorMaxLength(maxLength)); + }) : super(tr.errors.maxLength(maxLength)); @override bool isValid(String? string) => string == null || string.length <= maxLength; @@ -51,7 +51,8 @@ class StringContainsValidation extends Validation { required this.pattern, this.userFriendlyPattern, String? message, - }) : super(message ?? S.current.errorMustContain(userFriendlyPattern ?? pattern)); + }) : super(message ?? + tr.errors.mustContain((userFriendlyPattern ?? pattern).toString())); @override bool isValid(String? string) => string == null || string.contains(pattern); @@ -65,7 +66,9 @@ class StringNotContainsValidation extends Validation { required this.pattern, this.userFriendlyPattern, String? message, - }) : super(message ?? S.current.errorMustNotContain(userFriendlyPattern ?? pattern)); + }) : super(message ?? + tr.errors + .mustNotContain((userFriendlyPattern ?? pattern).toString())); @override bool isValid(String? string) => string == null || !string.contains(pattern); @@ -110,7 +113,8 @@ class StringValidator extends CompoundStringValidator { List get validators => [ if (minLength != null) StringMinLengthValidation(minLength: minLength!), if (maxLength != null) StringMaxLengthValidation(maxLength: maxLength!), - if (exactLength != null) StringExactLengthValidation(length: exactLength!), + if (exactLength != null) + StringExactLengthValidation(length: exactLength!), if (containsPattern != null) StringContainsValidation( pattern: containsPattern!, diff --git a/lib/core/utils/upload_utils.dart b/lib/core/utils/upload_utils.dart index bfbb9907..a007f977 100644 --- a/lib/core/utils/upload_utils.dart +++ b/lib/core/utils/upload_utils.dart @@ -1,12 +1,11 @@ import 'package:dungeon_paper/app/data/services/user_service.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:firebase_storage/firebase_storage.dart'; -import 'package:path/path.dart' as path; - import 'package:flutter/material.dart'; import 'package:flutter_file_dialog/flutter_file_dialog.dart'; import 'package:get/get.dart'; import 'package:image_cropper/image_cropper.dart'; +import 'package:path/path.dart' as path; class UploadSettings { final void Function(String downloadURL)? onSuccess; @@ -44,6 +43,7 @@ Future _pickAndCrop( BuildContext context, { CropStyle? cropStyle, }) async { + final theme = Theme.of(context); final res = await FlutterFileDialog.pickFile( params: const OpenFileDialogParams( dialogType: OpenFileDialogType.image, @@ -56,7 +56,6 @@ Future _pickAndCrop( return null; } - final theme = Theme.of(context); final colorScheme = theme.colorScheme; final cropped = await ImageCropper().cropImage( sourcePath: res, @@ -80,23 +79,25 @@ Future _uploadPhoto(CroppedFile file, String uploadPath) async { if (!uploadPath.startsWith('/')) { uploadPath = '/$uploadPath'; } - final ref = FirebaseStorage.instance.ref(userService.current.fileStoragePath! + uploadPath + ext); + final ref = FirebaseStorage.instance + .ref(userService.current.fileStoragePath! + uploadPath + ext); await ref.putData(await file.readAsBytes()); return ref; } -Future cropAndUploadPhoto(BuildContext context, UploadSettings settings) async { +Future cropAndUploadPhoto( + BuildContext context, UploadSettings settings) async { CroppedFile? file; try { file = await _pickAndCrop(context); if (file == null) { - Get.rawSnackbar(message: S.current.errorUserOperationCanceled); + Get.rawSnackbar(message: tr.errors.userOperationCanceled); settings.onCancel?.call(); return null; } settings.onUploadFile?.call(file); } catch (e) { - Get.rawSnackbar(message: S.current.errorUpload); + Get.rawSnackbar(message: tr.errors.uploadError); settings.onError?.call(e); return null; } @@ -110,7 +111,8 @@ Future cropAndUploadPhoto(BuildContext context, UploadSettings settings.onSuccess?.call(downloadURL); } catch (e) { Get.rawSnackbar( - message: 'Error while uploading photo. Try again later, or contact support using the "About" page.', + message: + 'Error while uploading photo. Try again later, or contact support using the "About" page.', ); settings.onError?.call(e); diff --git a/lib/generated/intl/intl_messages.arb b/lib/generated/intl/intl_messages.arb deleted file mode 100644 index 75e9c894..00000000 --- a/lib/generated/intl/intl_messages.arb +++ /dev/null @@ -1,3696 +0,0 @@ -{ - "@@last_modified": "2023-05-14T01:29:24.684390", - "abilityScoreBondDebilityDescription": "", - "@abilityScoreBondDebilityDescription": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreBondDebilityName": "Lonely", - "@abilityScoreBondDebilityName": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreBondDescription": "When a move has you roll+BOND you'll count the number of bonds you have with the character in question and add that to the roll.", - "@abilityScoreBondDescription": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreBondName": "Charisma", - "@abilityScoreBondName": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreButtonTooltip": "Roll +{stat}", - "@abilityScoreButtonTooltip": { - "description": "", - "type": "text", - "placeholders_order": [ - "stat" - ], - "placeholders": { - "stat": {} - } - }, - "abilityScoreChaDebilityDescription": "It may not be permanent, but for now you don't look so good.", - "@abilityScoreChaDebilityDescription": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreChaDebilityName": "Scarred", - "@abilityScoreChaDebilityName": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreChaDescription": "Measures a character's personality, personal magnetism, ability to lead, and appearance.", - "@abilityScoreChaDescription": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreChaName": "Charisma", - "@abilityScoreChaName": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreConDebilityDescription": "Something just isn't right inside. Maybe you've got a disease or a wasting illness. Maybe you just drank too much ale last night and it's coming back to haunt you.", - "@abilityScoreConDebilityDescription": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreConDebilityName": "Sick", - "@abilityScoreConDebilityName": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreConDescription": "Represents your character's health and stamina.", - "@abilityScoreConDescription": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreConName": "Constitution", - "@abilityScoreConName": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreDexDebilityDescription": "You're unsteady on your feet and you've got a shake in your hands.", - "@abilityScoreDexDebilityDescription": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreDexDebilityName": "Shaky", - "@abilityScoreDexDebilityName": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreDexDescription": "Measures agility, reflexes and balance.", - "@abilityScoreDexDescription": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreDexName": "Dexterity", - "@abilityScoreDexName": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreFormDebilityDescriptionDescription": "A description of the effect causing the debility and/or how it affects your character", - "@abilityScoreFormDebilityDescriptionDescription": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreFormDebilityDescriptionLabel": "Debility Description", - "@abilityScoreFormDebilityDescriptionLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreFormDebilityNameDescription": "The name for the debility that occurs when this stat is debilitated (takes -1 until recovered).", - "@abilityScoreFormDebilityNameDescription": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreFormDebilityNameLabel": "Debility Name", - "@abilityScoreFormDebilityNameLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreFormDescriptionDescription": "A description of what this ability score represents", - "@abilityScoreFormDescriptionDescription": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreFormDescriptionLabel": "Ability Score Description", - "@abilityScoreFormDescriptionLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreFormIconLabel": "Icon", - "@abilityScoreFormIconLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreFormKeyDescription": "A 3-letter unique key that identifies this ability score in dice and is used as the short label for the modifier value (and not the actual score)", - "@abilityScoreFormKeyDescription": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreFormKeyLabel": "Ability Score Key", - "@abilityScoreFormKeyLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreFormNameDescription": "The name of this ability score", - "@abilityScoreFormNameDescription": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreFormNameLabel": "Ability Score Name", - "@abilityScoreFormNameLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreFormPickIconLabel": "Change Icon", - "@abilityScoreFormPickIconLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreInfo": "You can drag & drop the stat cards to change the order in which they appear throughout this character's screens.", - "@abilityScoreInfo": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreIntDebilityDescription": "That last knock to the head shook something loose. Brain not work so good.", - "@abilityScoreIntDebilityDescription": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreIntDebilityName": "Stunned", - "@abilityScoreIntDebilityName": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreIntDescription": "Determines how well your character learns and reasons.", - "@abilityScoreIntDescription": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreIntName": "Intelligence", - "@abilityScoreIntName": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreModifierValueLabel": "Modifier:\n{modifier}", - "@abilityScoreModifierValueLabel": { - "description": "", - "type": "text", - "placeholders_order": [ - "modifier" - ], - "placeholders": { - "modifier": {} - } - }, - "abilityScoreRollButtonTooltip": "Roll random stat", - "@abilityScoreRollButtonTooltip": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreStrDebilityDescription": "You can't exert much force. Maybe it's just fatigue and injury, or maybe your strength was drained by magic.", - "@abilityScoreStrDebilityDescription": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreStrDebilityName": "Weak", - "@abilityScoreStrDebilityName": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreStrDescription": "Measures muscle and physical power.", - "@abilityScoreStrDescription": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreStrName": "Strength", - "@abilityScoreStrName": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreWisDebilityDescription": "Ears ringing. Vision blurred. You're more than a little out of it.", - "@abilityScoreWisDebilityDescription": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreWisDebilityName": "Confused", - "@abilityScoreWisDebilityName": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreWisDescription": "Describes a character's willpower, common sense, awareness, and intuition.", - "@abilityScoreWisDescription": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "abilityScoreWisName": "Wisdom", - "@abilityScoreWisName": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "about": "About", - "@about": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "aboutAuthor": "Chen Asraf", - "@aboutAuthor": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "aboutCopyright": "Copyright © 2018-{year}", - "@aboutCopyright": { - "description": "", - "type": "text", - "placeholders_order": [ - "year" - ], - "placeholders": { - "year": {} - } - }, - "aboutIconCredits": "Icon Credits", - "@aboutIconCredits": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "aboutJoinDiscord": "Join Our Discord", - "@aboutJoinDiscord": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "aboutJoinDiscordSubtitle": "Join the Discord community to ask questions, get help, send feedback, or just chat with other players.", - "@aboutJoinDiscordSubtitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "aboutSendFeedback": "Send Feedback", - "@aboutSendFeedback": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "aboutSendFeedbackSubtitle": "We reply more promptly through Discord, but you can send us feedback, bug reports or suggestions about the app directly here as an alternative.", - "@aboutSendFeedbackSubtitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "aboutSocialLinks": "Links", - "@aboutSocialLinks": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "aboutSpecialThanks": "Special Thanks", - "@aboutSpecialThanks": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "aboutTitle": "About", - "@aboutTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "aboutVersion": "Version {version}", - "@aboutVersion": { - "description": "", - "type": "text", - "placeholders_order": [ - "version" - ], - "placeholders": { - "version": {} - } - }, - "account": "Account", - "@account": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "accountCategoryDetails": "Account Details", - "@accountCategoryDetails": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "accountCategorySocials": "Connected Logins", - "@accountCategorySocials": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "accountChangeDisplayNameHint": "Enter your public display name", - "@accountChangeDisplayNameHint": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "accountChangeDisplayNameLabel": "Display Name", - "@accountChangeDisplayNameLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "accountChangeDisplayNameSuccess": "Display name changed successfully", - "@accountChangeDisplayNameSuccess": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "accountChangeDisplayNameTitle": "Change Display Name", - "@accountChangeDisplayNameTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "accountChangeEmailHint": "Enter your new email address", - "@accountChangeEmailHint": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "accountChangeEmailLabel": "Email Address", - "@accountChangeEmailLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "accountChangeEmailSuccess": "Email address changed successfully", - "@accountChangeEmailSuccess": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "accountChangeEmailTitle": "Change Email Address", - "@accountChangeEmailTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "accountChangeImageSubtitle": "Change your profile picture", - "@accountChangeImageSubtitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "accountChangeImageTitle": "Change Profile Picture", - "@accountChangeImageTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "accountChangePasswordConfirmHint": "Enter the same password again", - "@accountChangePasswordConfirmHint": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "accountChangePasswordConfirmLabel": "Confirm New Password", - "@accountChangePasswordConfirmLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "accountChangePasswordHint": "Enter your new password", - "@accountChangePasswordHint": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "accountChangePasswordLabel": "New Password", - "@accountChangePasswordLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "accountChangePasswordSubtitle": "Change your password", - "@accountChangePasswordSubtitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "accountChangePasswordSuccess": "Password changed successfully", - "@accountChangePasswordSuccess": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "accountChangePasswordTitle": "Change Password", - "@accountChangePasswordTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "accountDelete": "Delete Your Account", - "@accountDelete": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "actionsBasicMoves": "Basic Moves", - "@actionsBasicMoves": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "actionsSpecialMoves": "Special Moves", - "@actionsSpecialMoves": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "actionSummaryChipCoins": "{coins} G", - "@actionSummaryChipCoins": { - "description": "", - "type": "text", - "placeholders_order": [ - "coins" - ], - "placeholders": { - "coins": {} - } - }, - "actionSummaryChipLoad": "Load: {load}/{maxLoad}", - "@actionSummaryChipLoad": { - "description": "", - "type": "text", - "placeholders_order": [ - "load", - "maxLoad" - ], - "placeholders": { - "load": {}, - "maxLoad": {} - } - }, - "actionsViewVisibleLabel": "Show", - "@actionsViewVisibleLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "addCustomGeneric": "Add New {entity}", - "@addCustomGeneric": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "addExistingGeneric": "Add Existing {entity}", - "@addExistingGeneric": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "addGeneric": "Add {entity}", - "@addGeneric": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "addRepoItemTabOnline": "Online", - "@addRepoItemTabOnline": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "addRepoItemTabPlaybook": "Playbook", - "@addRepoItemTabPlaybook": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "alignment": "{alignment,select, chaotic{Chaotic}evil{Evil}good{Good}lawful{Lawful}neutral{Neutral}other{{alignment}}}", - "@alignment": { - "description": "", - "type": "text", - "placeholders_order": [ - "alignment" - ], - "placeholders": { - "alignment": {} - } - }, - "alignmentLabel": "Alignment", - "@alignmentLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "all": "All", - "@all": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "allGeneric": "All {entity}", - "@allGeneric": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "alreadyAdded": "Already added", - "@alreadyAdded": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "amount": "Amount", - "@amount": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "appName": "Dungeon Paper", - "@appName": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "armor": "Armor", - "@armor": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "basicInfoImageChoose": "Choose Photo...", - "@basicInfoImageChoose": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "basicInfoImageChooseNew": "Change Photo...", - "@basicInfoImageChooseNew": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "basicInfoImageNeedAccountLinkLabel": "Sign in or create an account", - "@basicInfoImageNeedAccountLinkLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "basicInfoImageNeedAccountPrefix": "You need to be signed in to upload images.", - "@basicInfoImageNeedAccountPrefix": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "basicInfoImageNeedAccountSuffix": ", or upload using your own URL below.", - "@basicInfoImageNeedAccountSuffix": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "basicInfoImageRemove": "Remove Photo", - "@basicInfoImageRemove": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "basicInfoImageUploading": "UPLOADING...", - "@basicInfoImageUploading": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "basicInformationTitle": "Basic Information", - "@basicInformationTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "cancel": "Cancel", - "@cancel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "changeGeneric": "Change {entity}", - "@changeGeneric": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "characterAutoArmor": "Use armor from class & equipped items", - "@characterAutoArmor": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "characterAutoDamage": "Use damage dice from class & equipped items", - "@characterAutoDamage": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "characterAutoMaxLoad": "Use class base load + STR mod", - "@characterAutoMaxLoad": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "characterBarHp": "HP", - "@characterBarHp": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "characterBarXp": "XP", - "@characterBarXp": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "characterBioDialogAlignmentDescriptionLabel": "Alignment Description", - "@characterBioDialogAlignmentDescriptionLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "characterBioDialogAlignmentDescriptionPlaceholder": "Alignment is your character's way of thinking and moral compass. This can center on an ethical ideal, religious strictures or early life events. It reflects what your character values and aspires to protect or create.", - "@characterBioDialogAlignmentDescriptionPlaceholder": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "characterBioDialogAlignmentNameDisplayLabel": "Alignment:", - "@characterBioDialogAlignmentNameDisplayLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "characterBioDialogAlignmentNameLabel": "Alignment", - "@characterBioDialogAlignmentNameLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "characterBioDialogAlignmentNamePlaceholder": "Select alignment", - "@characterBioDialogAlignmentNamePlaceholder": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "characterBioDialogDescLabel": "Character & background description", - "@characterBioDialogDescLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "characterBioDialogDescPlaceholder": "Describe your character's background, personality, goals, etc.", - "@characterBioDialogDescPlaceholder": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "characterBioDialogLooksLabel": "Looks", - "@characterBioDialogLooksLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "characterBioDialogLooksPlaceholder": "Describe your character's appearance. You may use the presets from the buttons above.", - "@characterBioDialogLooksPlaceholder": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "characterBioDialogTitle": "Character Biography", - "@characterBioDialogTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "characterBondsFlagsDialogBond": "Bond", - "@characterBondsFlagsDialogBond": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "characterBondsFlagsDialogBonds": "Bonds", - "@characterBondsFlagsDialogBonds": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "characterBondsFlagsDialogFlag": "Flag", - "@characterBondsFlagsDialogFlag": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "characterBondsFlagsDialogFlags": "Flags", - "@characterBondsFlagsDialogFlags": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "characterBondsFlagsDialogInfoText": "You can add, update or remove bonds & flags using the edit icon above.", - "@characterBondsFlagsDialogInfoText": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "characterBondsFlagsDialogNoData": "You have no bonds or flags. You can add some using the edit button above, then mark them off as completed as you go along your adventure.", - "@characterBondsFlagsDialogNoData": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "characterBondsFlagsDialogTitle": "Bonds & Flags", - "@characterBondsFlagsDialogTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "characterDebilitiesDialogInfoText": "Debilities are temporary, negative conditions or states in which your character is in. When a stat is debilitated, it causes its modifier to be reduced by 1 until recovered.", - "@characterDebilitiesDialogInfoText": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "characterDebilitiesDialogTitle": "Debilities", - "@characterDebilitiesDialogTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "characterHeaderSubtitle": "Level {level} ∙ {charClass} ∙ {race} ∙", - "@characterHeaderSubtitle": { - "description": "", - "type": "text", - "placeholders_order": [ - "level", - "charClass", - "race" - ], - "placeholders": { - "level": {}, - "charClass": {}, - "race": {} - } - }, - "characterHeaderSubtitleAlignment": "{alignment}", - "@characterHeaderSubtitleAlignment": { - "description": "", - "type": "text", - "placeholders_order": [ - "alignment" - ], - "placeholders": { - "alignment": {} - } - }, - "characterHeaderSubtitleClass": "{charClass}", - "@characterHeaderSubtitleClass": { - "description": "", - "type": "text", - "placeholders_order": [ - "charClass" - ], - "placeholders": { - "charClass": {} - } - }, - "characterHeaderSubtitleLevel": "Level {level}", - "@characterHeaderSubtitleLevel": { - "description": "", - "type": "text", - "placeholders_order": [ - "level" - ], - "placeholders": { - "level": {} - } - }, - "characterHeaderSubtitleRace": "{race}", - "@characterHeaderSubtitleRace": { - "description": "", - "type": "text", - "placeholders_order": [ - "race" - ], - "placeholders": { - "race": {} - } - }, - "characterHeaderSubtitleSeparator": " ∙ ", - "@characterHeaderSubtitleSeparator": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "characterListTitle": "All Characters", - "@characterListTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "characterMenu": "Character Menu", - "@characterMenu": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "characterNoCategory": "No Category", - "@characterNoCategory": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "characterRollsTitle": "Ability Scores", - "@characterRollsTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "characterSelectTheme": "Character Theme", - "@characterSelectTheme": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "coins": "Coins", - "@coins": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "coinsWithCount": "{count,plural, =0{No coins}=1{One coin}other{{fmtCount} coins}}", - "@coinsWithCount": { - "description": "", - "type": "text", - "placeholders_order": [ - "count", - "fmtCount" - ], - "placeholders": { - "count": {}, - "fmtCount": {} - } - }, - "confirm": "Confirm", - "@confirm": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "confirmDeleteBody": "Are you sure you want to remove the {entity} \"{name}\" from the list?", - "@confirmDeleteBody": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity", - "name" - ], - "placeholders": { - "entity": {}, - "name": {} - } - }, - "confirmDeleteTitle": "Delete {entity}?", - "@confirmDeleteTitle": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "confirmDeleteAccount1Body": "Are you sure you want to delete your account?\n\nThis action cannot be undone.", - "@confirmDeleteAccount1Body": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "confirmDeleteAccount1Title": "Delete Your Account?", - "@confirmDeleteAccount1Title": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "confirmDeleteAccount2Body": "We do not save any data for deleted accounts. All your data will be permanently deleted.\n\nAre you sure you want to delete your account?\n\nPlease confirm this one last time.", - "@confirmDeleteAccount2Body": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "confirmDeleteAccount2Title": "Are you really sure?", - "@confirmDeleteAccount2Title": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "confirmUnlinkProviderBody": "Are you sure you want to unlink your account from {provider}?\nBy clicking \"Unlink\", you will no longer be able to sign in with {provider}.\n\nYou will be able to re-link your account at any time by going to your account settings.", - "@confirmUnlinkProviderBody": { - "description": "", - "type": "text", - "placeholders_order": [ - "provider" - ], - "placeholders": { - "provider": {} - } - }, - "confirmUnlinkProviderTitle": "Unlink from {entity}?", - "@confirmUnlinkProviderTitle": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "confirmExitDefaultCancelLabel": "Continue editing", - "@confirmExitDefaultCancelLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "confirmExitDefaultOkLabel": "Exit & Discard", - "@confirmExitDefaultOkLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "confirmExitDefaultText": "Going back will lose any unsaved changes.\nAre you sure you want to go back?", - "@confirmExitDefaultText": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "confirmExitDefaultTitle": "Are you sure?", - "@confirmExitDefaultTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "continueLabel": "Continue", - "@continueLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "createCharacterAddButton": "Create Character", - "@createCharacterAddButton": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "createCharacterAvatarFieldLabel": "Photo URL", - "@createCharacterAvatarFieldLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "createCharacterAvatarFieldPlaceholder": "Paste an image URL", - "@createCharacterAvatarFieldPlaceholder": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "createCharacterBioFieldLabel": "Biography", - "@createCharacterBioFieldLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "createCharacterBioFieldPlaceholder": "Describe your character as shortly or thoroughly as you want here.\nPut your backstory, a visual description, some personality traits, etc. to help you keep in character.", - "@createCharacterBioFieldPlaceholder": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "createCharacterClassDescription": "Base HP: {hp}, Load: {load}, Damage Dice: {damageDice}", - "@createCharacterClassDescription": { - "description": "", - "type": "text", - "placeholders_order": [ - "hp", - "load", - "damageDice" - ], - "placeholders": { - "hp": {}, - "load": {}, - "damageDice": {} - } - }, - "createCharacterClassHelpText": "No class selected (required)", - "@createCharacterClassHelpText": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "createCharacterDescFieldLabel": "Biography/description", - "@createCharacterDescFieldLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "createCharacterDescFieldPlaceholder": "Enter general information about your character - backstory, goals & ambitions, behavior descriptions, etc", - "@createCharacterDescFieldPlaceholder": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "createCharacterFinishButton": "Review", - "@createCharacterFinishButton": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "createCharacterMovesSpells": "Moves & Spells", - "@createCharacterMovesSpells": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "createCharacterMovesSpellsDescription": "{moves} Moves, {spells} Spells selected", - "@createCharacterMovesSpellsDescription": { - "description": "", - "type": "text", - "placeholders_order": [ - "moves", - "spells" - ], - "placeholders": { - "moves": {}, - "spells": {} - } - }, - "createCharacterNameFieldLabel": "Character Name", - "@createCharacterNameFieldLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "createCharacterNameFieldPlaceholder": "Enter your character's name", - "@createCharacterNameFieldPlaceholder": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "createCharacterPreviewPageMaxHp": "Max HP: {hp}", - "@createCharacterPreviewPageMaxHp": { - "description": "", - "type": "text", - "placeholders_order": [ - "hp" - ], - "placeholders": { - "hp": {} - } - }, - "createCharacterPreviewPageTitle": "Preview Character", - "@createCharacterPreviewPageTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "createCharacterProceedTooltip": "Continue", - "@createCharacterProceedTooltip": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "createCharacterRaceDescFieldLabel": "Race description", - "@createCharacterRaceDescFieldLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "createCharacterRaceDescFieldPlaceholder": "Describe a special move usable by your race. It will appear alongside the rest of the moves.", - "@createCharacterRaceDescFieldPlaceholder": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "createCharacterRaceNameFieldLabel": "Race", - "@createCharacterRaceNameFieldLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "createCharacterRaceNameFieldPlaceholder": "Race name", - "@createCharacterRaceNameFieldPlaceholder": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "createCharacterSaveButton": "Create Character", - "@createCharacterSaveButton": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "createCharacterStartingGearChoiceCountNoMax": "{count} selected", - "@createCharacterStartingGearChoiceCountNoMax": { - "description": "", - "type": "text", - "placeholders_order": [ - "count" - ], - "placeholders": { - "count": {} - } - }, - "createCharacterStartingGearChoiceCountWithMax": "{count} selected (class allowance: {max})", - "@createCharacterStartingGearChoiceCountWithMax": { - "description": "", - "type": "text", - "placeholders_order": [ - "count", - "max" - ], - "placeholders": { - "count": {}, - "max": {} - } - }, - "createCharacterStartingGearDescriptionCoins": "{amount} coins", - "@createCharacterStartingGearDescriptionCoins": { - "description": "", - "type": "text", - "placeholders_order": [ - "amount" - ], - "placeholders": { - "amount": {} - } - }, - "createCharacterStartingGearDescriptionItem": "{amount} × {name}", - "@createCharacterStartingGearDescriptionItem": { - "description": "", - "type": "text", - "placeholders_order": [ - "amount", - "name" - ], - "placeholders": { - "amount": {}, - "name": {} - } - }, - "createCharacterStartingGearHelpText": "Select your starting gear determined by class (optional)", - "@createCharacterStartingGearHelpText": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "createCharacterStepInvalidTooltip": "{step} - Changes Required", - "@createCharacterStepInvalidTooltip": { - "description": "", - "type": "text", - "placeholders_order": [ - "step" - ], - "placeholders": { - "step": {} - } - }, - "createCharacterTitle": "Create Character", - "@createCharacterTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "createCharacterTravelerBlankName": "Unnamed Traveler", - "@createCharacterTravelerBlankName": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "createCharacterTravelerDescription": "Level 1 {cls}", - "@createCharacterTravelerDescription": { - "description": "", - "type": "text", - "placeholders_order": [ - "cls" - ], - "placeholders": { - "cls": {} - } - }, - "createCharacterTravelerHelpText": "Select name & picture (required)", - "@createCharacterTravelerHelpText": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "createCharRandomizeNameTooltipClick": "Click to generate a random name", - "@createCharRandomizeNameTooltipClick": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "createCharRandomizeNameTooltipTouch": "Tap to generate a random name", - "@createCharRandomizeNameTooltipTouch": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "createGeneric": "Create {entity}", - "@createGeneric": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "customButtonLeft": "Left Button", - "@customButtonLeft": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "customButtonRight": "Right Button", - "@customButtonRight": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "customRollButtons": "Quick Roll Buttons", - "@customRollButtons": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "customRollButtonsUseDefault": "Use Default", - "@customRollButtonsUseDefault": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "customRollButtonsUsePreset": "Presets", - "@customRollButtonsUsePreset": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "damage": "Damage", - "@damage": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "damageDice": "Damage Dice", - "@damageDice": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "debilityLabel": "{name} ({key})", - "@debilityLabel": { - "description": "", - "type": "text", - "placeholders_order": [ - "name", - "key" - ], - "placeholders": { - "name": {}, - "key": {} - } - }, - "diceAmount": "Amount", - "@diceAmount": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "diceRollAgain": "Roll", - "@diceRollAgain": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "diceSeparator": "d", - "@diceSeparator": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "diceSides": "Sides", - "@diceSides": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "diceSuggestion": "Suggested: {dice}", - "@diceSuggestion": { - "description": "", - "type": "text", - "placeholders_order": [ - "dice" - ], - "placeholders": { - "dice": {} - } - }, - "diceUseStat": "Roll Stat", - "@diceUseStat": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "diceUseStatLabel": "Stat", - "@diceUseStatLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "diceUseStatPlaceholder": "Select Stat", - "@diceUseStatPlaceholder": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "diceUseStatValue": "{name} ({key})", - "@diceUseStatValue": { - "description": "", - "type": "text", - "placeholders_order": [ - "name", - "key" - ], - "placeholders": { - "name": {}, - "key": {} - } - }, - "diceUseValue": "Fixed Value", - "@diceUseValue": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "diceUseValueLabel": "Modifier value", - "@diceUseValueLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "diceUseValuePlaceholder": "Number, e.g. 2 or -1", - "@diceUseValuePlaceholder": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "done": "Done", - "@done": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "dynamicCategoriesItems": "Equipped Items", - "@dynamicCategoriesItems": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "dynamicCategoriesMoves": "Favorite Moves", - "@dynamicCategoriesMoves": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "dynamicCategoriesNotes": "Bookmarked Notes", - "@dynamicCategoriesNotes": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "dynamicCategoriesSpells": "Prepared Spells", - "@dynamicCategoriesSpells": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "edit": "Edit", - "@edit": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "editGeneric": "Edit {entity}", - "@editGeneric": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "endOfSessionQ1": "Did we learn something new and important about the world?", - "@endOfSessionQ1": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "endOfSessionQ2": "Did we overcome a notable monster or enemy?", - "@endOfSessionQ2": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "endOfSessionQ3": "Did we loot a memorable treasure?", - "@endOfSessionQ3": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "endOfSessionQuestions": "End of Session Questions", - "@endOfSessionQuestions": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "endOfSessionQuestionsSubtitle": "Answer these questions as a group. For each \"yes\" answer, XP is marked.", - "@endOfSessionQuestionsSubtitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "entity": "{runtimeType,select, CharacterClass{Class}Item{Item}Monster{Monster}Move{Move}Race{Race}Spell{Spell}Tag{Tag}MoveCategory{Category}GearSelection{Starting Gear}Dice{Dice}AbilityScore{Ability Score}AlignmentValue{Alignment}Playbook{Playbook}other{{runtimeType}}}", - "@entity": { - "description": "", - "type": "text", - "placeholders_order": [ - "runtimeType" - ], - "placeholders": { - "runtimeType": {} - } - }, - "entityPlural": "{runtimeType,select, CharacterClass{Classes}Item{Items}Monster{Monsters}Move{Moves}Race{Races}Spell{Spells}Tag{Tags}MoveCategory{Categories}Dice{Dice}GearSelection{Starting Gear}AbilityScore{Ability Scores}AlignmentValue{Alignment}Playbook{Playbooks}other{{runtimeType}s}}", - "@entityPlural": { - "description": "", - "type": "text", - "placeholders_order": [ - "runtimeType" - ], - "placeholders": { - "runtimeType": {} - } - }, - "entityShareStatusDetached": "This {entity} is not linked to any library item", - "@entityShareStatusDetached": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "entityShareStatusInSync": "This {entity} is In Sync with its linked library item", - "@entityShareStatusInSync": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "entityShareStatusOutOfSync": "This {entity} is Out of Sync with its linked library item", - "@entityShareStatusOutOfSync": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "entityWithCount": "{count,plural, =0{No {entPlural}}=1{One {ent}}other{{count} {entPlural}}}", - "@entityWithCount": { - "description": "", - "type": "text", - "placeholders_order": [ - "count", - "entPlural", - "ent" - ], - "placeholders": { - "count": {}, - "entPlural": {}, - "ent": {} - } - }, - "errorExactLength": "Must be exactly {length} {length,plural, =1{character}other{characters}}", - "@errorExactLength": { - "description": "", - "type": "text", - "placeholders_order": [ - "length" - ], - "placeholders": { - "length": {} - } - }, - "errorInvalidEmail": "Invalid email address", - "@errorInvalidEmail": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "errorMaxLength": "Must be no more than {length} {length,plural, =1{character}other{characters}}", - "@errorMaxLength": { - "description": "", - "type": "text", - "placeholders_order": [ - "length" - ], - "placeholders": { - "length": {} - } - }, - "errorMinLength": "Must be at least {length} {length,plural, =1{character}other{characters}}", - "@errorMinLength": { - "description": "", - "type": "text", - "placeholders_order": [ - "length" - ], - "placeholders": { - "length": {} - } - }, - "errorMustContain": "Must contain {pattern}", - "@errorMustContain": { - "description": "", - "type": "text", - "placeholders_order": [ - "pattern" - ], - "placeholders": { - "pattern": {} - } - }, - "errorMustNotContain": "Must not contain {pattern}", - "@errorMustNotContain": { - "description": "", - "type": "text", - "placeholders_order": [ - "pattern" - ], - "placeholders": { - "pattern": {} - } - }, - "errorNoSelection": "None selected", - "@errorNoSelection": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "errorNoSelectionGeneric": "No {entity} selected", - "@errorNoSelectionGeneric": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "errorNoSelectionGenericRequired": "No {entity} selected (required)", - "@errorNoSelectionGenericRequired": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "errorOnlyLetters": "Must contain letters only", - "@errorOnlyLetters": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "errorUpload": "Error while uploading photo. Try again later, or contact support using the \"About\" page.", - "@errorUpload": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "errorUserOperationCanceled": "Operation canceled", - "@errorUserOperationCanceled": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "explanation": "Further details", - "@explanation": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "export": "Export", - "@export": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "exportFailedMessage": "Something went wrong.\nTry again or contact support if this persists", - "@exportFailedMessage": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "exportFailedTitle": "Export Failed", - "@exportFailedTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "exportSuccessfulMessage": "Your data was exported to file successfully", - "@exportSuccessfulMessage": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "exportSuccessfulTitle": "Export Successful", - "@exportSuccessfulTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "formatBold": "Bold", - "@formatBold": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "formatBulletList": "Bullet List", - "@formatBulletList": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "formatCell": "Cell {n}", - "@formatCell": { - "description": "", - "type": "text", - "placeholders_order": [ - "n" - ], - "placeholders": { - "n": {} - } - }, - "formatCheckboxList": "Check List (Checked)", - "@formatCheckboxList": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "formatCheckboxListUnchecked": "Check List (Unchecked)", - "@formatCheckboxListUnchecked": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "formatHeader": "Header {n}", - "@formatHeader": { - "description": "", - "type": "text", - "placeholders_order": [ - "n" - ], - "placeholders": { - "n": {} - } - }, - "formatHeaderNoNum": "Header {n}", - "@formatHeaderNoNum": { - "description": "", - "type": "text", - "placeholders_order": [ - "n" - ], - "placeholders": { - "n": {} - } - }, - "formatHeading": "Heading {n}", - "@formatHeading": { - "description": "", - "type": "text", - "placeholders_order": [ - "n" - ], - "placeholders": { - "n": {} - } - }, - "formatHeadings": "Headings", - "@formatHeadings": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "formatHelp": "Formatting Help", - "@formatHelp": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "formatImageURL": "Image URL", - "@formatImageURL": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "formatItalic": "Italic", - "@formatItalic": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "formatNumberedList": "Numbered List", - "@formatNumberedList": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "formatPreview": "Preview", - "@formatPreview": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "formatTable": "Table", - "@formatTable": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "formatURL": "URL", - "@formatURL": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "formCharacterClassBaseHp": "Base HP", - "@formCharacterClassBaseHp": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "formCharacterClassBaseLoad": "Base Load", - "@formCharacterClassBaseLoad": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "formCharacterClassDamage": "Damage Dice", - "@formCharacterClassDamage": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "formCharacterClassDescriptionPlaceholder": "Give a general description of your class. Describe a calling for the type of person or creature that would choose or be raised in to this adventuring profession.", - "@formCharacterClassDescriptionPlaceholder": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "formCharacterClassNamePlaceholder": "Enter the class name", - "@formCharacterClassNamePlaceholder": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "formGeneralCategory": "Category", - "@formGeneralCategory": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "formGeneralCategoryGeneric": "{entity} category", - "@formGeneralCategoryGeneric": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "formGeneralDescription": "Description", - "@formGeneralDescription": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "formGeneralDescriptionGeneric": "{entity} description", - "@formGeneralDescriptionGeneric": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "formGeneralExplanation": "Explanation", - "@formGeneralExplanation": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "formGeneralExplanationGeneric": "{entity} explanation", - "@formGeneralExplanationGeneric": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "formGeneralName": "Name", - "@formGeneralName": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "formGeneralNameGeneric": "{entity} name", - "@formGeneralNameGeneric": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "formGeneralTitle": "Title", - "@formGeneralTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "formGeneralTitleGeneric": "{entity} title", - "@formGeneralTitleGeneric": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "genericDescriptionField": "{entity} description", - "@genericDescriptionField": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "genericNameField": "{entity} name", - "@genericNameField": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "genericValueField": "{entity} value", - "@genericValueField": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "homeEmptyStateLoginSubtitle": "Online data sync, library sharing, campaigns and more!", - "@homeEmptyStateLoginSubtitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "homeEmptyStateLoginTitle": "Sign in to get more features", - "@homeEmptyStateLoginTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "homeEmptyStateSubtitle": "Create a Character to get started", - "@homeEmptyStateSubtitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "homeEmptyStateTitle": "No Characters", - "@homeEmptyStateTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "hp": "HP", - "@hp": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "hpDialogChangeAdd": "Heal\n+{amount}", - "@hpDialogChangeAdd": { - "description": "", - "type": "text", - "placeholders_order": [ - "amount" - ], - "placeholders": { - "amount": {} - } - }, - "hpDialogChangeNeutral": "No Change", - "@hpDialogChangeNeutral": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "hpDialogChangeOverrideMax": "Override Max HP", - "@hpDialogChangeOverrideMax": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "hpDialogChangeRemove": "Damage\n-{amount}", - "@hpDialogChangeRemove": { - "description": "", - "type": "text", - "placeholders_order": [ - "amount" - ], - "placeholders": { - "amount": {} - } - }, - "hpDialogCurrentHP": "Current HP", - "@hpDialogCurrentHP": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "hpDialogTitle": "Modify HP", - "@hpDialogTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "import": "Import", - "@import": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "importBrowseFile": "Browse...", - "@importBrowseFile": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "importBrowseHelp": "To start importing, pick the file you want to import from.\nYou will then be able to select what to save and what to leave out.", - "@importBrowseHelp": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "importClearFile": "Clear selected file", - "@importClearFile": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "importExportTitle": "Export/Import", - "@importExportTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "importFailedMessage": "Something went wrong.\nTry again or contact support if this persists", - "@importFailedMessage": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "importFailedTitle": "Import Failed", - "@importFailedTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "importProgressProcessing": "Processing {entity}...", - "@importProgressProcessing": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "importProgressTitle": "Importing...", - "@importProgressTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "importSuccessMessage": "Your data was imported from file successfully", - "@importSuccessMessage": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "importSuccessTitle": "Successful", - "@importSuccessTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "itemAmountX": "× {amount}", - "@itemAmountX": { - "description": "", - "type": "text", - "placeholders_order": [ - "amount" - ], - "placeholders": { - "amount": {} - } - }, - "itemSettingsCountArmor": "Count Armor", - "@itemSettingsCountArmor": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "itemSettingsCountDamage": "Count Damage", - "@itemSettingsCountDamage": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "itemSettingsCountWeight": "Count Weight", - "@itemSettingsCountWeight": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "items": "Items", - "@items": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "itemsWithCount": "{count,plural, =0{No items}=1{One item}other{{count} items}}", - "@itemsWithCount": { - "description": "", - "type": "text", - "placeholders_order": [ - "count" - ], - "placeholders": { - "count": {} - } - }, - "level": "Level", - "@level": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "libraryCollectionListItemSubtitle": "{count} in {type}", - "@libraryCollectionListItemSubtitle": { - "description": "", - "type": "text", - "placeholders_order": [ - "count", - "type" - ], - "placeholders": { - "count": {}, - "type": {} - } - }, - "libraryCollectionListItemSubtitleType": "{type,select, builtIn{Playbook}my{My Library}other{{type}}}", - "@libraryCollectionListItemSubtitleType": { - "description": "", - "type": "text", - "placeholders_order": [ - "type" - ], - "placeholders": { - "type": {} - } - }, - "libraryCollectionTitle": "My Library", - "@libraryCollectionTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "libraryListNoItemsFoundClearFiltersButton": "Clear Filters", - "@libraryListNoItemsFoundClearFiltersButton": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "libraryListNoItemsFoundSubtitleFilters": "Try changing the search or filters to find more {entities}.", - "@libraryListNoItemsFoundSubtitleFilters": { - "description": "", - "type": "text", - "placeholders_order": [ - "entities" - ], - "placeholders": { - "entities": {} - } - }, - "libraryListNoItemsFoundSubtitleNoFilters": "No {entities} found in this list.", - "@libraryListNoItemsFoundSubtitleNoFilters": { - "description": "", - "type": "text", - "placeholders_order": [ - "entities" - ], - "placeholders": { - "entities": {} - } - }, - "libraryListNoItemsFoundTitle": "No {entities} found", - "@libraryListNoItemsFoundTitle": { - "description": "", - "type": "text", - "placeholders_order": [ - "entities" - ], - "placeholders": { - "entities": {} - } - }, - "loadingCharacters": "Getting characters...", - "@loadingCharacters": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "loadingGeneral": "Loading...", - "@loadingGeneral": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "loadingUser": "Signing in...", - "@loadingUser": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "markdownPreview": "Content Preview", - "@markdownPreview": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "maxLoad": "Max Load", - "@maxLoad": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "migrationTitle": "Welcome to\nDungeon Paper 2!", - "@migrationTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "migrationSubtitle": "To get started, pick a username and the language for the rulebook & app. If you already have an existing Dungeon Paper account your data might take a few seconds to migrate.", - "@migrationSubtitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "migrationUsernameInfo": "Your username is unique and can not be changed later, so think carefully! It will be used to identify all your library items when publishing.", - "@migrationUsernameInfo": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "moveCategory": "{category,select, starting{Starting}basic{Basic}special{Special}advanced1{Advanced}advanced2{Advanced}other{Other}}", - "@moveCategory": { - "description": "", - "type": "text", - "placeholders_order": [ - "category" - ], - "placeholders": { - "category": {} - } - }, - "moveCategoryWithLevel": "{category,select, starting{Starting}basic{Basic}special{Special}advanced1{Advanced (level 1-5)}advanced2{Advanced (level 6-10)}other{Other}}", - "@moveCategoryWithLevel": { - "description": "", - "type": "text", - "placeholders_order": [ - "category" - ], - "placeholders": { - "category": {} - } - }, - "moveCategoryWithLevelShort": "{category,select, starting{Starting}basic{Basic}special{Special}advanced1{Advanced (1-5)}advanced2{Advanced (6-10)}other{Other}}", - "@moveCategoryWithLevelShort": { - "description": "", - "type": "text", - "placeholders_order": [ - "category" - ], - "placeholders": { - "category": {} - } - }, - "moves": "Moves", - "@moves": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "movesWithCount": "{count,plural, =0{No moves}=1{One move}other{{count} moves}}", - "@movesWithCount": { - "description": "", - "type": "text", - "placeholders_order": [ - "count" - ], - "placeholders": { - "count": {} - } - }, - "moveToEnd": "Move to bottom", - "@moveToEnd": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "moveToEndGeneric": "Move {entity} to bottom", - "@moveToEndGeneric": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "moveToStart": "Move to top", - "@moveToStart": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "moveToStartGeneric": "Move {entity} to top", - "@moveToStartGeneric": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "myGeneric": "My {entity}", - "@myGeneric": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "navActions": "Use", - "@navActions": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "navCharacter": "Character", - "@navCharacter": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "navJournal": "Journal", - "@navJournal": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "noDescription": "‹No description provided›", - "@noDescription": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "noGeneric": "No {entity}", - "@noGeneric": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "noteNoCategory": "General", - "@noteNoCategory": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "notes": "Notes", - "@notes": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "notesWithCount": "{count,plural, =0{No notes}=1{One note}other{{count} notes}}", - "@notesWithCount": { - "description": "", - "type": "text", - "placeholders_order": [ - "count" - ], - "placeholders": { - "count": {} - } - }, - "ok": "OK", - "@ok": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "passwordHideTooltip": "Hide password", - "@passwordHideTooltip": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "passwordShowTooltip": "Show password", - "@passwordShowTooltip": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "pluralize": "{count,plural, =1{One {singular}}other{{count} {plural}}}", - "@pluralize": { - "description": "", - "type": "text", - "placeholders_order": [ - "count", - "singular", - "plural" - ], - "placeholders": { - "count": {}, - "singular": {}, - "plural": {} - } - }, - "privacyPolicy": "Privacy Policy", - "@privacyPolicy": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "quickIconsItems": "Items", - "@quickIconsItems": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "quickIconsMoves": "Moves", - "@quickIconsMoves": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "quickIconsNote": "+ Note", - "@quickIconsNote": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "quickIconsSpells": "Spells", - "@quickIconsSpells": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "reloadLibrary": "Reload Library", - "@reloadLibrary": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "remove": "Remove", - "@remove": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "resetToDefault": "Reset to default", - "@resetToDefault": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "rollAttackDamageButton": "Hack & Slash", - "@rollAttackDamageButton": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "rollBasicActionButton": "Basic Action", - "@rollBasicActionButton": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "rollButtonLabel": "Button Text", - "@rollButtonLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "rollButtonTooltip": "Roll {dice}", - "@rollButtonTooltip": { - "description": "", - "type": "text", - "placeholders_order": [ - "dice" - ], - "placeholders": { - "dice": {} - } - }, - "rollButtonTooltipWithDebility": "Roll {dice}\n* Rolling with debility", - "@rollButtonTooltipWithDebility": { - "description": "", - "type": "text", - "placeholders_order": [ - "dice" - ], - "placeholders": { - "dice": {} - } - }, - "rollDialogResultBreakdown": "Dice: {dice} | Modifier: {mod}", - "@rollDialogResultBreakdown": { - "description": "", - "type": "text", - "placeholders_order": [ - "dice", - "mod" - ], - "placeholders": { - "dice": {}, - "mod": {} - } - }, - "rollDialogResultTotal": "Total: {total}", - "@rollDialogResultTotal": { - "description": "", - "type": "text", - "placeholders_order": [ - "total" - ], - "placeholders": { - "total": {} - } - }, - "rollDialogTitleRolled": "Total: {total}", - "@rollDialogTitleRolled": { - "description": "", - "type": "text", - "placeholders_order": [ - "total" - ], - "placeholders": { - "total": {} - } - }, - "rollDialogTitleRolling": "Rolling {count} dice", - "@rollDialogTitleRolling": { - "description": "", - "type": "text", - "placeholders_order": [ - "count" - ], - "placeholders": { - "count": {} - } - }, - "rollDiscernRealitiesButton": "Discern Realities", - "@rollDiscernRealitiesButton": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "rollVolleyButton": "Volley", - "@rollVolleyButton": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "save": "Save", - "@save": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "saveGeneric": "Save {entity}", - "@saveGeneric": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "searchIn": "Search in: ", - "@searchIn": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "searchPlaceholder": "Type to search", - "@searchPlaceholder": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "searchPlaceholderGeneric": "Type to search {entity}", - "@searchPlaceholderGeneric": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "seeAll": "See all", - "@seeAll": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "select": "Select", - "@select": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "selectAll": "Select All", - "@selectAll": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "selected": "Selected", - "@selected": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "selectGeneric": "Select {entity}", - "@selectGeneric": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "selectNone": "Select None", - "@selectNone": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "selectToAdd": "Select {string} to add", - "@selectToAdd": { - "description": "", - "type": "text", - "placeholders_order": [ - "string" - ], - "placeholders": { - "string": {} - } - }, - "sendFeedbackBodyLabel": "Problem description", - "@sendFeedbackBodyLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "sendFeedbackSendButton": "Feedback title", - "@sendFeedbackSendButton": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "sendFeedbackSuccessMessage": "Thank you for your feedback! We will review your feedback as soon as we can.", - "@sendFeedbackSuccessMessage": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "sendFeedbackSuccessTitle": "Feedback sent!", - "@sendFeedbackSuccessTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "sendFeedbackTitle": "Send App Feedback", - "@sendFeedbackTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "sendFeedbackTitleLabel": "Feedback title", - "@sendFeedbackTitleLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "separatorOr": "OR", - "@separatorOr": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "settingsDefaultDarkTheme": "Default dark theme", - "@settingsDefaultDarkTheme": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "settingsDefaultLightTheme": "Default light theme", - "@settingsDefaultLightTheme": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "settingsGeneral": "General", - "@settingsGeneral": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "settingsKeepScreenAwake": "Keep screen awake while using the app", - "@settingsKeepScreenAwake": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "settingsTitle": "Settings", - "@settingsTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signinTitle": "Sign In", - "@signinTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signinGoToSignupLabel": "Don't have an account?", - "@signinGoToSignupLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signinGoToSignupButton": "Sign up", - "@signinGoToSignupButton": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signinGoToSigninLabel": "Already have an account?", - "@signinGoToSigninLabel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signinGoToSigninButton": "Sign in", - "@signinGoToSigninButton": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signinSubtitle": "Sign in to your account to sync your data online, and get access to many more features.", - "@signinSubtitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signupTitle": "Sign Up", - "@signupTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signupSubtitle": "Enter the required details below to create your Dungeon Paper account.", - "@signupSubtitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signinButton": "Sign in", - "@signinButton": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signupButton": "Sign up", - "@signupButton": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signinWithButton": "Sign in with {provider}", - "@signinWithButton": { - "description": "", - "type": "text", - "placeholders_order": [ - "provider" - ], - "placeholders": { - "provider": {} - } - }, - "signupWithButton": "Sign up with {provider}", - "@signupWithButton": { - "description": "", - "type": "text", - "placeholders_order": [ - "provider" - ], - "placeholders": { - "provider": {} - } - }, - "signinProvider": "{provider,select, facebook{Facebook}google{Google}apple{Apple}password{Dungeon Paper}other{Other}}", - "@signinProvider": { - "description": "", - "type": "text", - "placeholders_order": [ - "provider" - ], - "placeholders": { - "provider": {} - } - }, - "signinProviderFacebook": "Facebook", - "@signinProviderFacebook": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signinProviderGoogle": "Google", - "@signinProviderGoogle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signinProviderApple": "Apple", - "@signinProviderApple": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signinProviderLink": "Link", - "@signinProviderLink": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signinProviderUnlink": "Unlink", - "@signinProviderUnlink": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signinCantUseProvider": "This device only supports unlinking {provider} accounts.", - "@signinCantUseProvider": { - "description": "", - "type": "text", - "placeholders_order": [ - "provider" - ], - "placeholders": { - "provider": {} - } - }, - "signinCantUseProviderTooltip": "You may only unlink {provider} from this device.\nTo link accounts using the {provider} provider is only available from supported devices.", - "@signinCantUseProviderTooltip": { - "description": "", - "type": "text", - "placeholders_order": [ - "provider" - ], - "placeholders": { - "provider": {} - } - }, - "signoutButton": "Sign out", - "@signoutButton": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signupDefaultDataLanguage": "Default data language", - "@signupDefaultDataLanguage": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signupEmail": "Email", - "@signupEmail": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signupEmailPlaceholder": "Enter your email", - "@signupEmailPlaceholder": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signupEmailValidation": "Please enter a valid email", - "@signupEmailValidation": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signupPassword": "Password", - "@signupPassword": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signupPasswordPlaceholder": "Enter your password", - "@signupPasswordPlaceholder": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signupPasswordConfirm": "Confirm Password", - "@signupPasswordConfirm": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signupPasswordConfirmPlaceholder": "Enter the same password again", - "@signupPasswordConfirmPlaceholder": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signupPasswordValidationLength": "Password must be at least {length} characters", - "@signupPasswordValidationLength": { - "description": "", - "type": "text", - "placeholders_order": [ - "length" - ], - "placeholders": { - "length": {} - } - }, - "signupPasswordValidationMatch": "Passwords do not match", - "@signupPasswordValidationMatch": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signupPasswordValidationPatternGeneric": "Password must contain {pattern}", - "@signupPasswordValidationPatternGeneric": { - "description": "", - "type": "text", - "placeholders_order": [ - "pattern" - ], - "placeholders": { - "pattern": {} - } - }, - "signupPasswordValidationPatternLetter": "Password must contain at least one capital letter", - "@signupPasswordValidationPatternLetter": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signupPasswordValidationPatternNumber": "Password must contain at least one number", - "@signupPasswordValidationPatternNumber": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signupUsername": "Username", - "@signupUsername": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signupUsernamePlaceholder": "Pick a unique username", - "@signupUsernamePlaceholder": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "signupUsernameValidation": "Username must be at least {length} characters", - "@signupUsernameValidation": { - "description": "", - "type": "text", - "placeholders_order": [ - "length" - ], - "placeholders": { - "length": {} - } - }, - "signupUsernameValidationPattern": "Username must only contain letters, numbers, dashes and underscores", - "@signupUsernameValidationPattern": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "socialTwitter": "Twitter", - "@socialTwitter": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "socialFacebook": "Facebook", - "@socialFacebook": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "socialDiscord": "Discord", - "@socialDiscord": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "socialGitHub": "GitHub", - "@socialGitHub": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "socialGoogle": "Play Store", - "@socialGoogle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "socialApple": "App Store", - "@socialApple": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "sortMoveDown": "Move down", - "@sortMoveDown": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "sortMoveUp": "Move up", - "@sortMoveUp": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "specialDice": "Special Dice", - "@specialDice": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "specialRollButton": "{button,select, damage{Damage}other{{button}}}", - "@specialRollButton": { - "description": "", - "type": "text", - "placeholders_order": [ - "button" - ], - "placeholders": { - "button": {} - } - }, - "spellLevel": "{level,select, cantrip{Cantrip}rote{Rote}other{Level {level}}}", - "@spellLevel": { - "description": "", - "type": "text", - "placeholders_order": [ - "level" - ], - "placeholders": { - "level": {} - } - }, - "spells": "Spells", - "@spells": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "spellsWithCount": "{count,plural, =0{No spells}=1{One spell}other{{count} spells}}", - "@spellsWithCount": { - "description": "", - "type": "text", - "placeholders_order": [ - "count" - ], - "placeholders": { - "count": {} - } - }, - "tagCopyFrom": "Copy from: {tag}", - "@tagCopyFrom": { - "description": "", - "type": "text", - "placeholders_order": [ - "tag" - ], - "placeholders": { - "tag": {} - } - }, - "tagDetails": "Tag Information", - "@tagDetails": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "themeTurnDark": "Switch to Dark Mode", - "@themeTurnDark": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "themeTurnLight": "Switch to Light Mode", - "@themeTurnLight": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "unselect": "Unselect", - "@unselect": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "useDefault": "Use default", - "@useDefault": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "userLoginButton": "Sign in", - "@userLoginButton": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "userLogoutButton": "Sign out", - "@userLogoutButton": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "userMenuMoreChars": "More", - "@userMenuMoreChars": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "userMenuRecentCharacters": "Recent Characters", - "@userMenuRecentCharacters": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "userUnregistered": "Not registered", - "@userUnregistered": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "view": "View", - "@view": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "viewGeneric": "View {entity}", - "@viewGeneric": { - "description": "", - "type": "text", - "placeholders_order": [ - "entity" - ], - "placeholders": { - "entity": {} - } - }, - "whatsNew": "What's new?", - "@whatsNew": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "xpDialogChangeOverride": "Update manually", - "@xpDialogChangeOverride": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "xpDialogEndSession": "End Session", - "@xpDialogEndSession": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "xpDialogOverrideInfoText": "Changing the current XP or level manually will cause the pending XP to be discarded unless this is unchecked.", - "@xpDialogOverrideInfoText": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "xpDialogOverrideLevel": "Override Level", - "@xpDialogOverrideLevel": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "xpDialogOverrideXp": "Override XP", - "@xpDialogOverrideXp": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "xpDialogResetSessionMarks": "Reset bonds, flags & end of session questions after saving", - "@xpDialogResetSessionMarks": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "xpDialogTitle": "Mark Session XP", - "@xpDialogTitle": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - }, - "xpDialogTitleOverriding": "Update XP & Level", - "@xpDialogTitleOverriding": { - "description": "", - "type": "text", - "placeholders_order": [], - "placeholders": {} - } -} \ No newline at end of file diff --git a/lib/generated/intl/messages_all.dart b/lib/generated/intl/messages_all.dart deleted file mode 100644 index 58d913ab..00000000 --- a/lib/generated/intl/messages_all.dart +++ /dev/null @@ -1,64 +0,0 @@ -// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart -// This is a library that looks up messages for specific locales by -// delegating to the appropriate library. - -// Ignore issues from commonly used lints in this file. -// ignore_for_file:implementation_imports, file_names -// ignore_for_file:unnecessary_brace_in_string_interps, directives_ordering -// ignore_for_file:argument_type_not_assignable, invalid_assignment -// ignore_for_file:prefer_single_quotes, prefer_generic_function_type_aliases -// ignore_for_file:comment_references -// ignore_for_file:avoid_catches_without_on_clauses - -import 'dart:async'; - -import 'package:intl/intl.dart'; -import 'package:intl/message_lookup_by_library.dart'; -import 'package:intl/src/intl_helpers.dart'; - -import 'messages_en.dart' as messages_en; - -typedef Future LibraryLoader(); -Map _deferredLibraries = { - 'en': () => Future.value(null), -}; - -MessageLookupByLibrary? _findExact(String localeName) { - switch (localeName) { - case 'en': - return messages_en.messages; - default: - return null; - } -} - -/// User programs should call this before using [localeName] for messages. -Future initializeMessages(String localeName) async { - final availableLocale = Intl.verifiedLocale( - localeName, - (locale) => _deferredLibraries[locale] != null, - onFailure: (_) => null); - if (availableLocale == null) { - return Future.value(false); - } - final lib = _deferredLibraries[availableLocale]; - await (lib == null ? Future.value(false) : lib()); - initializeInternalMessageLookup(() => CompositeMessageLookup()); - messageLookup.addLocale(availableLocale, _findGeneratedMessagesFor); - return Future.value(true); -} - -bool _messagesExistFor(String locale) { - try { - return _findExact(locale) != null; - } catch (e) { - return false; - } -} - -MessageLookupByLibrary? _findGeneratedMessagesFor(String locale) { - final actualLocale = Intl.verifiedLocale(locale, _messagesExistFor, - onFailure: (_) => null); - if (actualLocale == null) return null; - return _findExact(actualLocale); -} diff --git a/lib/generated/intl/messages_en.dart b/lib/generated/intl/messages_en.dart deleted file mode 100644 index c8fbacaf..00000000 --- a/lib/generated/intl/messages_en.dart +++ /dev/null @@ -1,696 +0,0 @@ -// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart -// This is a library that provides messages for a en locale. All the -// messages from the main program should be duplicated here with the same -// function name. - -// Ignore issues from commonly used lints in this file. -// ignore_for_file:unnecessary_brace_in_string_interps -// ignore_for_file:prefer_single_quotes,comment_references, directives_ordering -// ignore_for_file:annotate_overrides,prefer_generic_function_type_aliases -// ignore_for_file:unused_import, file_names, always_declare_return_types - -import 'package:intl/intl.dart'; -import 'package:intl/message_lookup_by_library.dart'; - -final messages = MessageLookup(); - -typedef String MessageIfAbsent(String? messageStr, List? args); - -class MessageLookup extends MessageLookupByLibrary { - String get localeName => 'en'; - - static m0(stat) => "Roll +${stat}"; - - static m1(modifier) => "Modifier:\n${modifier}"; - - static m2(year) => "Copyright © 2018-${year}"; - - static m3(version) => "Version ${version}"; - - static m4(coins) => "${coins} G"; - - static m5(load, maxLoad) => "Load: ${load}/${maxLoad}"; - - static m6(entity) => "Add New ${entity}"; - - static m7(entity) => "Add Existing ${entity}"; - - static m8(entity) => "Add ${entity}"; - - static m9(alignment) => "${Intl.select(alignment, {'chaotic': 'Chaotic', 'evil': 'Evil', 'good': 'Good', 'lawful': 'Lawful', 'neutral': 'Neutral', 'other': '${alignment}', })}"; - - static m10(entity) => "All ${entity}"; - - static m11(entity) => "Change ${entity}"; - - static m12(level, charClass, race) => "Level ${level} ∙ ${charClass} ∙ ${race} ∙"; - - static m13(alignment) => "${alignment}"; - - static m14(charClass) => "${charClass}"; - - static m15(level) => "Level ${level}"; - - static m16(race) => "${race}"; - - static m17(count, fmtCount) => "${Intl.plural(count, zero: 'No coins', one: 'One coin', other: '${fmtCount} coins')}"; - - static m18(entity, name) => "Are you sure you want to remove the ${entity} \"${name}\" from the list?"; - - static m19(entity) => "Delete ${entity}?"; - - static m20(provider) => "Are you sure you want to unlink your account from ${provider}?\nBy clicking \"Unlink\", you will no longer be able to sign in with ${provider}.\n\nYou will be able to re-link your account at any time by going to your account settings."; - - static m21(entity) => "Unlink from ${entity}?"; - - static m22(hp, load, damageDice) => "Base HP: ${hp}, Load: ${load}, Damage Dice: ${damageDice}"; - - static m23(moves, spells) => "${moves} Moves, ${spells} Spells selected"; - - static m24(hp) => "Max HP: ${hp}"; - - static m25(count) => "${count} selected"; - - static m26(count, max) => "${count} selected (class allowance: ${max})"; - - static m27(amount) => "${amount} coins"; - - static m28(amount, name) => "${amount} × ${name}"; - - static m29(step) => "${step} - Changes Required"; - - static m30(cls) => "Level 1 ${cls}"; - - static m31(entity) => "Create ${entity}"; - - static m32(name, key) => "${name} (${key})"; - - static m33(dice) => "Suggested: ${dice}"; - - static m34(name, key) => "${name} (${key})"; - - static m35(entity) => "Edit ${entity}"; - - static m36(runtimeType) => "${Intl.select(runtimeType, {'CharacterClass': 'Class', 'Item': 'Item', 'Monster': 'Monster', 'Move': 'Move', 'Race': 'Race', 'Spell': 'Spell', 'Tag': 'Tag', 'MoveCategory': 'Category', 'GearSelection': 'Starting Gear', 'Dice': 'Dice', 'AbilityScore': 'Ability Score', 'AlignmentValue': 'Alignment', 'Playbook': 'Playbook', 'other': '${runtimeType}', })}"; - - static m37(runtimeType) => "${Intl.select(runtimeType, {'CharacterClass': 'Classes', 'Item': 'Items', 'Monster': 'Monsters', 'Move': 'Moves', 'Race': 'Races', 'Spell': 'Spells', 'Tag': 'Tags', 'MoveCategory': 'Categories', 'Dice': 'Dice', 'GearSelection': 'Starting Gear', 'AbilityScore': 'Ability Scores', 'AlignmentValue': 'Alignment', 'Playbook': 'Playbooks', 'other': '${runtimeType}s', })}"; - - static m38(entity) => "This ${entity} is not linked to any library item"; - - static m39(entity) => "This ${entity} is In Sync with its linked library item"; - - static m40(entity) => "This ${entity} is Out of Sync with its linked library item"; - - static m41(count, entPlural, ent) => "${Intl.plural(count, zero: 'No ${entPlural}', one: 'One ${ent}', other: '${count} ${entPlural}')}"; - - static m42(length) => "Must be exactly ${length} {length, plural, one character other characters}"; - - static m43(length) => "Must be no more than ${length} {length, plural, one character other characters}"; - - static m44(length) => "Must be at least ${length} {length, plural, one character other characters}"; - - static m45(pattern) => "Must contain ${pattern}"; - - static m46(pattern) => "Must not contain ${pattern}"; - - static m47(entity) => "No ${entity} selected"; - - static m48(entity) => "No ${entity} selected (required)"; - - static m49(entity) => "${entity} category"; - - static m50(entity) => "${entity} description"; - - static m51(entity) => "${entity} explanation"; - - static m52(entity) => "${entity} name"; - - static m53(entity) => "${entity} title"; - - static m54(n) => "Cell ${n}"; - - static m55(n) => "Header ${n}"; - - static m56(n) => "Header ${n}"; - - static m57(n) => "Heading ${n}"; - - static m58(entity) => "${entity} description"; - - static m59(entity) => "${entity} name"; - - static m60(entity) => "${entity} value"; - - static m61(amount) => "Heal\n+${amount}"; - - static m62(amount) => "Damage\n-${amount}"; - - static m63(entity) => "Processing ${entity}..."; - - static m64(amount) => "× ${amount}"; - - static m65(count) => "${Intl.plural(count, zero: 'No items', one: 'One item', other: '${count} items')}"; - - static m66(count, type) => "${count} in ${type}"; - - static m67(type) => "${Intl.select(type, {'builtIn': 'Playbook', 'my': 'My Library', 'other': '${type}', })}"; - - static m68(entities) => "Try changing the search or filters to find more ${entities}."; - - static m69(entities) => "No ${entities} found in this list."; - - static m70(entities) => "No ${entities} found"; - - static m71(category) => "${Intl.select(category, {'starting': 'Starting', 'basic': 'Basic', 'special': 'Special', 'advanced1': 'Advanced', 'advanced2': 'Advanced', 'other': 'Other', })}"; - - static m72(category) => "${Intl.select(category, {'starting': 'Starting', 'basic': 'Basic', 'special': 'Special', 'advanced1': 'Advanced (level 1-5)', 'advanced2': 'Advanced (level 6-10)', 'other': 'Other', })}"; - - static m73(category) => "${Intl.select(category, {'starting': 'Starting', 'basic': 'Basic', 'special': 'Special', 'advanced1': 'Advanced (1-5)', 'advanced2': 'Advanced (6-10)', 'other': 'Other', })}"; - - static m74(entity) => "Move ${entity} to bottom"; - - static m75(entity) => "Move ${entity} to top"; - - static m76(count) => "${Intl.plural(count, zero: 'No moves', one: 'One move', other: '${count} moves')}"; - - static m77(entity) => "My ${entity}"; - - static m78(entity) => "No ${entity}"; - - static m79(count) => "${Intl.plural(count, zero: 'No notes', one: 'One note', other: '${count} notes')}"; - - static m80(count, singular, plural) => "${Intl.plural(count, one: 'One ${singular}', other: '${count} ${plural}')}"; - - static m81(dice) => "Roll ${dice}"; - - static m82(dice) => "Roll ${dice}\n* Rolling with debility"; - - static m83(dice, mod) => "Dice: ${dice} | Modifier: ${mod}"; - - static m84(total) => "Total: ${total}"; - - static m85(total) => "Total: ${total}"; - - static m86(count) => "Rolling ${count} dice"; - - static m87(entity) => "Save ${entity}"; - - static m88(entity) => "Type to search ${entity}"; - - static m89(entity) => "Select ${entity}"; - - static m90(string) => "Select ${string} to add"; - - static m91(provider) => "This device only supports unlinking ${provider} accounts."; - - static m92(provider) => "You may only unlink ${provider} from this device.\nTo link accounts using the ${provider} provider is only available from supported devices."; - - static m93(provider) => "${Intl.select(provider, {'facebook': 'Facebook', 'google': 'Google', 'apple': 'Apple', 'password': 'Dungeon Paper', 'other': 'Other', })}"; - - static m94(provider) => "Sign in with ${provider}"; - - static m95(length) => "Password must be at least ${length} characters"; - - static m96(pattern) => "Password must contain ${pattern}"; - - static m97(length) => "Username must be at least ${length} characters"; - - static m98(provider) => "Sign up with ${provider}"; - - static m99(button) => "${Intl.select(button, {'damage': 'Damage', 'other': '${button}', })}"; - - static m100(level) => "${Intl.select(level, {'cantrip': 'Cantrip', 'rote': 'Rote', 'other': 'Level ${level}', })}"; - - static m101(count) => "${Intl.plural(count, zero: 'No spells', one: 'One spell', other: '${count} spells')}"; - - static m102(tag) => "Copy from: ${tag}"; - - static m103(entity) => "View ${entity}"; - - final messages = _notInlinedMessages(_notInlinedMessages); - static Map _notInlinedMessages(_) => { - "abilityScoreBondDebilityDescription" : MessageLookupByLibrary.simpleMessage(""), - "abilityScoreBondDebilityName" : MessageLookupByLibrary.simpleMessage("Lonely"), - "abilityScoreBondDescription" : MessageLookupByLibrary.simpleMessage("When a move has you roll+BOND you\'ll count the number of bonds you have with the character in question and add that to the roll."), - "abilityScoreBondName" : MessageLookupByLibrary.simpleMessage("Charisma"), - "abilityScoreButtonTooltip" : m0, - "abilityScoreChaDebilityDescription" : MessageLookupByLibrary.simpleMessage("It may not be permanent, but for now you don\'t look so good."), - "abilityScoreChaDebilityName" : MessageLookupByLibrary.simpleMessage("Scarred"), - "abilityScoreChaDescription" : MessageLookupByLibrary.simpleMessage("Measures a character\'s personality, personal magnetism, ability to lead, and appearance."), - "abilityScoreChaName" : MessageLookupByLibrary.simpleMessage("Charisma"), - "abilityScoreConDebilityDescription" : MessageLookupByLibrary.simpleMessage("Something just isn\'t right inside. Maybe you\'ve got a disease or a wasting illness. Maybe you just drank too much ale last night and it\'s coming back to haunt you."), - "abilityScoreConDebilityName" : MessageLookupByLibrary.simpleMessage("Sick"), - "abilityScoreConDescription" : MessageLookupByLibrary.simpleMessage("Represents your character\'s health and stamina."), - "abilityScoreConName" : MessageLookupByLibrary.simpleMessage("Constitution"), - "abilityScoreDexDebilityDescription" : MessageLookupByLibrary.simpleMessage("You\'re unsteady on your feet and you\'ve got a shake in your hands."), - "abilityScoreDexDebilityName" : MessageLookupByLibrary.simpleMessage("Shaky"), - "abilityScoreDexDescription" : MessageLookupByLibrary.simpleMessage("Measures agility, reflexes and balance."), - "abilityScoreDexName" : MessageLookupByLibrary.simpleMessage("Dexterity"), - "abilityScoreFormDebilityDescriptionDescription" : MessageLookupByLibrary.simpleMessage("A description of the effect causing the debility and/or how it affects your character"), - "abilityScoreFormDebilityDescriptionLabel" : MessageLookupByLibrary.simpleMessage("Debility Description"), - "abilityScoreFormDebilityNameDescription" : MessageLookupByLibrary.simpleMessage("The name for the debility that occurs when this stat is debilitated (takes -1 until recovered)."), - "abilityScoreFormDebilityNameLabel" : MessageLookupByLibrary.simpleMessage("Debility Name"), - "abilityScoreFormDescriptionDescription" : MessageLookupByLibrary.simpleMessage("A description of what this ability score represents"), - "abilityScoreFormDescriptionLabel" : MessageLookupByLibrary.simpleMessage("Ability Score Description"), - "abilityScoreFormIconLabel" : MessageLookupByLibrary.simpleMessage("Icon"), - "abilityScoreFormKeyDescription" : MessageLookupByLibrary.simpleMessage("A 3-letter unique key that identifies this ability score in dice and is used as the short label for the modifier value (and not the actual score)"), - "abilityScoreFormKeyLabel" : MessageLookupByLibrary.simpleMessage("Ability Score Key"), - "abilityScoreFormNameDescription" : MessageLookupByLibrary.simpleMessage("The name of this ability score"), - "abilityScoreFormNameLabel" : MessageLookupByLibrary.simpleMessage("Ability Score Name"), - "abilityScoreFormPickIconLabel" : MessageLookupByLibrary.simpleMessage("Change Icon"), - "abilityScoreInfo" : MessageLookupByLibrary.simpleMessage("You can drag & drop the stat cards to change the order in which they appear throughout this character\'s screens."), - "abilityScoreIntDebilityDescription" : MessageLookupByLibrary.simpleMessage("That last knock to the head shook something loose. Brain not work so good."), - "abilityScoreIntDebilityName" : MessageLookupByLibrary.simpleMessage("Stunned"), - "abilityScoreIntDescription" : MessageLookupByLibrary.simpleMessage("Determines how well your character learns and reasons."), - "abilityScoreIntName" : MessageLookupByLibrary.simpleMessage("Intelligence"), - "abilityScoreModifierValueLabel" : m1, - "abilityScoreRollButtonTooltip" : MessageLookupByLibrary.simpleMessage("Roll random stat"), - "abilityScoreStrDebilityDescription" : MessageLookupByLibrary.simpleMessage("You can\'t exert much force. Maybe it\'s just fatigue and injury, or maybe your strength was drained by magic."), - "abilityScoreStrDebilityName" : MessageLookupByLibrary.simpleMessage("Weak"), - "abilityScoreStrDescription" : MessageLookupByLibrary.simpleMessage("Measures muscle and physical power."), - "abilityScoreStrName" : MessageLookupByLibrary.simpleMessage("Strength"), - "abilityScoreWisDebilityDescription" : MessageLookupByLibrary.simpleMessage("Ears ringing. Vision blurred. You\'re more than a little out of it."), - "abilityScoreWisDebilityName" : MessageLookupByLibrary.simpleMessage("Confused"), - "abilityScoreWisDescription" : MessageLookupByLibrary.simpleMessage("Describes a character\'s willpower, common sense, awareness, and intuition."), - "abilityScoreWisName" : MessageLookupByLibrary.simpleMessage("Wisdom"), - "about" : MessageLookupByLibrary.simpleMessage("About"), - "aboutAuthor" : MessageLookupByLibrary.simpleMessage("Chen Asraf"), - "aboutCopyright" : m2, - "aboutIconCredits" : MessageLookupByLibrary.simpleMessage("Icon Credits"), - "aboutJoinDiscord" : MessageLookupByLibrary.simpleMessage("Join Our Discord"), - "aboutJoinDiscordSubtitle" : MessageLookupByLibrary.simpleMessage("Join the Discord community to ask questions, get help, send feedback, or just chat with other players."), - "aboutSendFeedback" : MessageLookupByLibrary.simpleMessage("Send Feedback"), - "aboutSendFeedbackSubtitle" : MessageLookupByLibrary.simpleMessage("We reply more promptly through Discord, but you can send us feedback, bug reports or suggestions about the app directly here as an alternative."), - "aboutSocialLinks" : MessageLookupByLibrary.simpleMessage("Links"), - "aboutSpecialThanks" : MessageLookupByLibrary.simpleMessage("Special Thanks"), - "aboutTitle" : MessageLookupByLibrary.simpleMessage("About"), - "aboutVersion" : m3, - "account" : MessageLookupByLibrary.simpleMessage("Account"), - "accountCategoryDetails" : MessageLookupByLibrary.simpleMessage("Account Details"), - "accountCategorySocials" : MessageLookupByLibrary.simpleMessage("Connected Logins"), - "accountChangeDisplayNameHint" : MessageLookupByLibrary.simpleMessage("Enter your public display name"), - "accountChangeDisplayNameLabel" : MessageLookupByLibrary.simpleMessage("Display Name"), - "accountChangeDisplayNameSuccess" : MessageLookupByLibrary.simpleMessage("Display name changed successfully"), - "accountChangeDisplayNameTitle" : MessageLookupByLibrary.simpleMessage("Change Display Name"), - "accountChangeEmailHint" : MessageLookupByLibrary.simpleMessage("Enter your new email address"), - "accountChangeEmailLabel" : MessageLookupByLibrary.simpleMessage("Email Address"), - "accountChangeEmailSuccess" : MessageLookupByLibrary.simpleMessage("Email address changed successfully"), - "accountChangeEmailTitle" : MessageLookupByLibrary.simpleMessage("Change Email Address"), - "accountChangeImageSubtitle" : MessageLookupByLibrary.simpleMessage("Change your profile picture"), - "accountChangeImageTitle" : MessageLookupByLibrary.simpleMessage("Change Profile Picture"), - "accountChangePasswordConfirmHint" : MessageLookupByLibrary.simpleMessage("Enter the same password again"), - "accountChangePasswordConfirmLabel" : MessageLookupByLibrary.simpleMessage("Confirm New Password"), - "accountChangePasswordHint" : MessageLookupByLibrary.simpleMessage("Enter your new password"), - "accountChangePasswordLabel" : MessageLookupByLibrary.simpleMessage("New Password"), - "accountChangePasswordSubtitle" : MessageLookupByLibrary.simpleMessage("Change your password"), - "accountChangePasswordSuccess" : MessageLookupByLibrary.simpleMessage("Password changed successfully"), - "accountChangePasswordTitle" : MessageLookupByLibrary.simpleMessage("Change Password"), - "accountDelete" : MessageLookupByLibrary.simpleMessage("Delete Your Account"), - "actionSummaryChipCoins" : m4, - "actionSummaryChipLoad" : m5, - "actionsBasicMoves" : MessageLookupByLibrary.simpleMessage("Basic Moves"), - "actionsSpecialMoves" : MessageLookupByLibrary.simpleMessage("Special Moves"), - "actionsViewVisibleLabel" : MessageLookupByLibrary.simpleMessage("Show"), - "addCustomGeneric" : m6, - "addExistingGeneric" : m7, - "addGeneric" : m8, - "addRepoItemTabOnline" : MessageLookupByLibrary.simpleMessage("Online"), - "addRepoItemTabPlaybook" : MessageLookupByLibrary.simpleMessage("Playbook"), - "alignment" : m9, - "alignmentLabel" : MessageLookupByLibrary.simpleMessage("Alignment"), - "all" : MessageLookupByLibrary.simpleMessage("All"), - "allGeneric" : m10, - "alreadyAdded" : MessageLookupByLibrary.simpleMessage("Already added"), - "amount" : MessageLookupByLibrary.simpleMessage("Amount"), - "appName" : MessageLookupByLibrary.simpleMessage("Dungeon Paper"), - "armor" : MessageLookupByLibrary.simpleMessage("Armor"), - "basicInfoImageChoose" : MessageLookupByLibrary.simpleMessage("Choose Photo..."), - "basicInfoImageChooseNew" : MessageLookupByLibrary.simpleMessage("Change Photo..."), - "basicInfoImageNeedAccountLinkLabel" : MessageLookupByLibrary.simpleMessage("Sign in or create an account"), - "basicInfoImageNeedAccountPrefix" : MessageLookupByLibrary.simpleMessage("You need to be signed in to upload images."), - "basicInfoImageNeedAccountSuffix" : MessageLookupByLibrary.simpleMessage(", or upload using your own URL below."), - "basicInfoImageRemove" : MessageLookupByLibrary.simpleMessage("Remove Photo"), - "basicInfoImageUploading" : MessageLookupByLibrary.simpleMessage("UPLOADING..."), - "basicInformationTitle" : MessageLookupByLibrary.simpleMessage("Basic Information"), - "cancel" : MessageLookupByLibrary.simpleMessage("Cancel"), - "changeGeneric" : m11, - "characterAutoArmor" : MessageLookupByLibrary.simpleMessage("Use armor from class & equipped items"), - "characterAutoDamage" : MessageLookupByLibrary.simpleMessage("Use damage dice from class & equipped items"), - "characterAutoMaxLoad" : MessageLookupByLibrary.simpleMessage("Use class base load + STR mod"), - "characterBarHp" : MessageLookupByLibrary.simpleMessage("HP"), - "characterBarXp" : MessageLookupByLibrary.simpleMessage("XP"), - "characterBioDialogAlignmentDescriptionLabel" : MessageLookupByLibrary.simpleMessage("Alignment Description"), - "characterBioDialogAlignmentDescriptionPlaceholder" : MessageLookupByLibrary.simpleMessage("Alignment is your character\'s way of thinking and moral compass. This can center on an ethical ideal, religious strictures or early life events. It reflects what your character values and aspires to protect or create."), - "characterBioDialogAlignmentNameDisplayLabel" : MessageLookupByLibrary.simpleMessage("Alignment:"), - "characterBioDialogAlignmentNameLabel" : MessageLookupByLibrary.simpleMessage("Alignment"), - "characterBioDialogAlignmentNamePlaceholder" : MessageLookupByLibrary.simpleMessage("Select alignment"), - "characterBioDialogDescLabel" : MessageLookupByLibrary.simpleMessage("Character & background description"), - "characterBioDialogDescPlaceholder" : MessageLookupByLibrary.simpleMessage("Describe your character\'s background, personality, goals, etc."), - "characterBioDialogLooksLabel" : MessageLookupByLibrary.simpleMessage("Looks"), - "characterBioDialogLooksPlaceholder" : MessageLookupByLibrary.simpleMessage("Describe your character\'s appearance. You may use the presets from the buttons above."), - "characterBioDialogTitle" : MessageLookupByLibrary.simpleMessage("Character Biography"), - "characterBondsFlagsDialogBond" : MessageLookupByLibrary.simpleMessage("Bond"), - "characterBondsFlagsDialogBonds" : MessageLookupByLibrary.simpleMessage("Bonds"), - "characterBondsFlagsDialogFlag" : MessageLookupByLibrary.simpleMessage("Flag"), - "characterBondsFlagsDialogFlags" : MessageLookupByLibrary.simpleMessage("Flags"), - "characterBondsFlagsDialogInfoText" : MessageLookupByLibrary.simpleMessage("You can add, update or remove bonds & flags using the edit icon above."), - "characterBondsFlagsDialogNoData" : MessageLookupByLibrary.simpleMessage("You have no bonds or flags. You can add some using the edit button above, then mark them off as completed as you go along your adventure."), - "characterBondsFlagsDialogTitle" : MessageLookupByLibrary.simpleMessage("Bonds & Flags"), - "characterDebilitiesDialogInfoText" : MessageLookupByLibrary.simpleMessage("Debilities are temporary, negative conditions or states in which your character is in. When a stat is debilitated, it causes its modifier to be reduced by 1 until recovered."), - "characterDebilitiesDialogTitle" : MessageLookupByLibrary.simpleMessage("Debilities"), - "characterHeaderSubtitle" : m12, - "characterHeaderSubtitleAlignment" : m13, - "characterHeaderSubtitleClass" : m14, - "characterHeaderSubtitleLevel" : m15, - "characterHeaderSubtitleRace" : m16, - "characterHeaderSubtitleSeparator" : MessageLookupByLibrary.simpleMessage(" ∙ "), - "characterListTitle" : MessageLookupByLibrary.simpleMessage("All Characters"), - "characterMenu" : MessageLookupByLibrary.simpleMessage("Character Menu"), - "characterNoCategory" : MessageLookupByLibrary.simpleMessage("No Category"), - "characterRollsTitle" : MessageLookupByLibrary.simpleMessage("Ability Scores"), - "characterSelectTheme" : MessageLookupByLibrary.simpleMessage("Character Theme"), - "coins" : MessageLookupByLibrary.simpleMessage("Coins"), - "coinsWithCount" : m17, - "confirm" : MessageLookupByLibrary.simpleMessage("Confirm"), - "confirmDeleteAccount1Body" : MessageLookupByLibrary.simpleMessage("Are you sure you want to delete your account?\n\nThis action cannot be undone."), - "confirmDeleteAccount1Title" : MessageLookupByLibrary.simpleMessage("Delete Your Account?"), - "confirmDeleteAccount2Body" : MessageLookupByLibrary.simpleMessage("We do not save any data for deleted accounts. All your data will be permanently deleted.\n\nAre you sure you want to delete your account?\n\nPlease confirm this one last time."), - "confirmDeleteAccount2Title" : MessageLookupByLibrary.simpleMessage("Are you really sure?"), - "confirmDeleteBody" : m18, - "confirmDeleteTitle" : m19, - "confirmExitDefaultCancelLabel" : MessageLookupByLibrary.simpleMessage("Continue editing"), - "confirmExitDefaultOkLabel" : MessageLookupByLibrary.simpleMessage("Exit & Discard"), - "confirmExitDefaultText" : MessageLookupByLibrary.simpleMessage("Going back will lose any unsaved changes.\nAre you sure you want to go back?"), - "confirmExitDefaultTitle" : MessageLookupByLibrary.simpleMessage("Are you sure?"), - "confirmUnlinkProviderBody" : m20, - "confirmUnlinkProviderTitle" : m21, - "continueLabel" : MessageLookupByLibrary.simpleMessage("Continue"), - "createCharRandomizeNameTooltipClick" : MessageLookupByLibrary.simpleMessage("Click to generate a random name"), - "createCharRandomizeNameTooltipTouch" : MessageLookupByLibrary.simpleMessage("Tap to generate a random name"), - "createCharacterAddButton" : MessageLookupByLibrary.simpleMessage("Create Character"), - "createCharacterAvatarFieldLabel" : MessageLookupByLibrary.simpleMessage("Photo URL"), - "createCharacterAvatarFieldPlaceholder" : MessageLookupByLibrary.simpleMessage("Paste an image URL"), - "createCharacterBioFieldLabel" : MessageLookupByLibrary.simpleMessage("Biography"), - "createCharacterBioFieldPlaceholder" : MessageLookupByLibrary.simpleMessage("Describe your character as shortly or thoroughly as you want here.\nPut your backstory, a visual description, some personality traits, etc. to help you keep in character."), - "createCharacterClassDescription" : m22, - "createCharacterClassHelpText" : MessageLookupByLibrary.simpleMessage("No class selected (required)"), - "createCharacterDescFieldLabel" : MessageLookupByLibrary.simpleMessage("Biography/description"), - "createCharacterDescFieldPlaceholder" : MessageLookupByLibrary.simpleMessage("Enter general information about your character - backstory, goals & ambitions, behavior descriptions, etc"), - "createCharacterFinishButton" : MessageLookupByLibrary.simpleMessage("Review"), - "createCharacterMovesSpells" : MessageLookupByLibrary.simpleMessage("Moves & Spells"), - "createCharacterMovesSpellsDescription" : m23, - "createCharacterNameFieldLabel" : MessageLookupByLibrary.simpleMessage("Character Name"), - "createCharacterNameFieldPlaceholder" : MessageLookupByLibrary.simpleMessage("Enter your character\'s name"), - "createCharacterPreviewPageMaxHp" : m24, - "createCharacterPreviewPageTitle" : MessageLookupByLibrary.simpleMessage("Preview Character"), - "createCharacterProceedTooltip" : MessageLookupByLibrary.simpleMessage("Continue"), - "createCharacterRaceDescFieldLabel" : MessageLookupByLibrary.simpleMessage("Race description"), - "createCharacterRaceDescFieldPlaceholder" : MessageLookupByLibrary.simpleMessage("Describe a special move usable by your race. It will appear alongside the rest of the moves."), - "createCharacterRaceNameFieldLabel" : MessageLookupByLibrary.simpleMessage("Race"), - "createCharacterRaceNameFieldPlaceholder" : MessageLookupByLibrary.simpleMessage("Race name"), - "createCharacterSaveButton" : MessageLookupByLibrary.simpleMessage("Create Character"), - "createCharacterStartingGearChoiceCountNoMax" : m25, - "createCharacterStartingGearChoiceCountWithMax" : m26, - "createCharacterStartingGearDescriptionCoins" : m27, - "createCharacterStartingGearDescriptionItem" : m28, - "createCharacterStartingGearHelpText" : MessageLookupByLibrary.simpleMessage("Select your starting gear determined by class (optional)"), - "createCharacterStepInvalidTooltip" : m29, - "createCharacterTitle" : MessageLookupByLibrary.simpleMessage("Create Character"), - "createCharacterTravelerBlankName" : MessageLookupByLibrary.simpleMessage("Unnamed Traveler"), - "createCharacterTravelerDescription" : m30, - "createCharacterTravelerHelpText" : MessageLookupByLibrary.simpleMessage("Select name & picture (required)"), - "createGeneric" : m31, - "customButtonLeft" : MessageLookupByLibrary.simpleMessage("Left Button"), - "customButtonRight" : MessageLookupByLibrary.simpleMessage("Right Button"), - "customRollButtons" : MessageLookupByLibrary.simpleMessage("Quick Roll Buttons"), - "customRollButtonsUseDefault" : MessageLookupByLibrary.simpleMessage("Use Default"), - "customRollButtonsUsePreset" : MessageLookupByLibrary.simpleMessage("Presets"), - "damage" : MessageLookupByLibrary.simpleMessage("Damage"), - "damageDice" : MessageLookupByLibrary.simpleMessage("Damage Dice"), - "debilityLabel" : m32, - "diceAmount" : MessageLookupByLibrary.simpleMessage("Amount"), - "diceRollAgain" : MessageLookupByLibrary.simpleMessage("Roll"), - "diceSeparator" : MessageLookupByLibrary.simpleMessage("d"), - "diceSides" : MessageLookupByLibrary.simpleMessage("Sides"), - "diceSuggestion" : m33, - "diceUseStat" : MessageLookupByLibrary.simpleMessage("Roll Stat"), - "diceUseStatLabel" : MessageLookupByLibrary.simpleMessage("Stat"), - "diceUseStatPlaceholder" : MessageLookupByLibrary.simpleMessage("Select Stat"), - "diceUseStatValue" : m34, - "diceUseValue" : MessageLookupByLibrary.simpleMessage("Fixed Value"), - "diceUseValueLabel" : MessageLookupByLibrary.simpleMessage("Modifier value"), - "diceUseValuePlaceholder" : MessageLookupByLibrary.simpleMessage("Number, e.g. 2 or -1"), - "done" : MessageLookupByLibrary.simpleMessage("Done"), - "dynamicCategoriesItems" : MessageLookupByLibrary.simpleMessage("Equipped Items"), - "dynamicCategoriesMoves" : MessageLookupByLibrary.simpleMessage("Favorite Moves"), - "dynamicCategoriesNotes" : MessageLookupByLibrary.simpleMessage("Bookmarked Notes"), - "dynamicCategoriesSpells" : MessageLookupByLibrary.simpleMessage("Prepared Spells"), - "edit" : MessageLookupByLibrary.simpleMessage("Edit"), - "editGeneric" : m35, - "endOfSessionQ1" : MessageLookupByLibrary.simpleMessage("Did we learn something new and important about the world?"), - "endOfSessionQ2" : MessageLookupByLibrary.simpleMessage("Did we overcome a notable monster or enemy?"), - "endOfSessionQ3" : MessageLookupByLibrary.simpleMessage("Did we loot a memorable treasure?"), - "endOfSessionQuestions" : MessageLookupByLibrary.simpleMessage("End of Session Questions"), - "endOfSessionQuestionsSubtitle" : MessageLookupByLibrary.simpleMessage("Answer these questions as a group. For each \"yes\" answer, XP is marked."), - "entity" : m36, - "entityPlural" : m37, - "entityShareStatusDetached" : m38, - "entityShareStatusInSync" : m39, - "entityShareStatusOutOfSync" : m40, - "entityWithCount" : m41, - "errorExactLength" : m42, - "errorInvalidEmail" : MessageLookupByLibrary.simpleMessage("Invalid email address"), - "errorMaxLength" : m43, - "errorMinLength" : m44, - "errorMustContain" : m45, - "errorMustNotContain" : m46, - "errorNoSelection" : MessageLookupByLibrary.simpleMessage("None selected"), - "errorNoSelectionGeneric" : m47, - "errorNoSelectionGenericRequired" : m48, - "errorOnlyLetters" : MessageLookupByLibrary.simpleMessage("Must contain letters only"), - "errorUpload" : MessageLookupByLibrary.simpleMessage("Error while uploading photo. Try again later, or contact support using the \"About\" page."), - "errorUserOperationCanceled" : MessageLookupByLibrary.simpleMessage("Operation canceled"), - "explanation" : MessageLookupByLibrary.simpleMessage("Further details"), - "export" : MessageLookupByLibrary.simpleMessage("Export"), - "exportFailedMessage" : MessageLookupByLibrary.simpleMessage("Something went wrong.\nTry again or contact support if this persists"), - "exportFailedTitle" : MessageLookupByLibrary.simpleMessage("Export Failed"), - "exportSuccessfulMessage" : MessageLookupByLibrary.simpleMessage("Your data was exported to file successfully"), - "exportSuccessfulTitle" : MessageLookupByLibrary.simpleMessage("Export Successful"), - "formCharacterClassBaseHp" : MessageLookupByLibrary.simpleMessage("Base HP"), - "formCharacterClassBaseLoad" : MessageLookupByLibrary.simpleMessage("Base Load"), - "formCharacterClassDamage" : MessageLookupByLibrary.simpleMessage("Damage Dice"), - "formCharacterClassDescriptionPlaceholder" : MessageLookupByLibrary.simpleMessage("Give a general description of your class. Describe a calling for the type of person or creature that would choose or be raised in to this adventuring profession."), - "formCharacterClassNamePlaceholder" : MessageLookupByLibrary.simpleMessage("Enter the class name"), - "formGeneralCategory" : MessageLookupByLibrary.simpleMessage("Category"), - "formGeneralCategoryGeneric" : m49, - "formGeneralDescription" : MessageLookupByLibrary.simpleMessage("Description"), - "formGeneralDescriptionGeneric" : m50, - "formGeneralExplanation" : MessageLookupByLibrary.simpleMessage("Explanation"), - "formGeneralExplanationGeneric" : m51, - "formGeneralName" : MessageLookupByLibrary.simpleMessage("Name"), - "formGeneralNameGeneric" : m52, - "formGeneralTitle" : MessageLookupByLibrary.simpleMessage("Title"), - "formGeneralTitleGeneric" : m53, - "formatBold" : MessageLookupByLibrary.simpleMessage("Bold"), - "formatBulletList" : MessageLookupByLibrary.simpleMessage("Bullet List"), - "formatCell" : m54, - "formatCheckboxList" : MessageLookupByLibrary.simpleMessage("Check List (Checked)"), - "formatCheckboxListUnchecked" : MessageLookupByLibrary.simpleMessage("Check List (Unchecked)"), - "formatHeader" : m55, - "formatHeaderNoNum" : m56, - "formatHeading" : m57, - "formatHeadings" : MessageLookupByLibrary.simpleMessage("Headings"), - "formatHelp" : MessageLookupByLibrary.simpleMessage("Formatting Help"), - "formatImageURL" : MessageLookupByLibrary.simpleMessage("Image URL"), - "formatItalic" : MessageLookupByLibrary.simpleMessage("Italic"), - "formatNumberedList" : MessageLookupByLibrary.simpleMessage("Numbered List"), - "formatPreview" : MessageLookupByLibrary.simpleMessage("Preview"), - "formatTable" : MessageLookupByLibrary.simpleMessage("Table"), - "formatURL" : MessageLookupByLibrary.simpleMessage("URL"), - "genericDescriptionField" : m58, - "genericNameField" : m59, - "genericValueField" : m60, - "homeEmptyStateLoginSubtitle" : MessageLookupByLibrary.simpleMessage("Online data sync, library sharing, campaigns and more!"), - "homeEmptyStateLoginTitle" : MessageLookupByLibrary.simpleMessage("Sign in to get more features"), - "homeEmptyStateSubtitle" : MessageLookupByLibrary.simpleMessage("Create a Character to get started"), - "homeEmptyStateTitle" : MessageLookupByLibrary.simpleMessage("No Characters"), - "hp" : MessageLookupByLibrary.simpleMessage("HP"), - "hpDialogChangeAdd" : m61, - "hpDialogChangeNeutral" : MessageLookupByLibrary.simpleMessage("No Change"), - "hpDialogChangeOverrideMax" : MessageLookupByLibrary.simpleMessage("Override Max HP"), - "hpDialogChangeRemove" : m62, - "hpDialogCurrentHP" : MessageLookupByLibrary.simpleMessage("Current HP"), - "hpDialogTitle" : MessageLookupByLibrary.simpleMessage("Modify HP"), - "import" : MessageLookupByLibrary.simpleMessage("Import"), - "importBrowseFile" : MessageLookupByLibrary.simpleMessage("Browse..."), - "importBrowseHelp" : MessageLookupByLibrary.simpleMessage("To start importing, pick the file you want to import from.\nYou will then be able to select what to save and what to leave out."), - "importClearFile" : MessageLookupByLibrary.simpleMessage("Clear selected file"), - "importExportTitle" : MessageLookupByLibrary.simpleMessage("Export/Import"), - "importFailedMessage" : MessageLookupByLibrary.simpleMessage("Something went wrong.\nTry again or contact support if this persists"), - "importFailedTitle" : MessageLookupByLibrary.simpleMessage("Import Failed"), - "importProgressProcessing" : m63, - "importProgressTitle" : MessageLookupByLibrary.simpleMessage("Importing..."), - "importSuccessMessage" : MessageLookupByLibrary.simpleMessage("Your data was imported from file successfully"), - "importSuccessTitle" : MessageLookupByLibrary.simpleMessage("Successful"), - "itemAmountX" : m64, - "itemSettingsCountArmor" : MessageLookupByLibrary.simpleMessage("Count Armor"), - "itemSettingsCountDamage" : MessageLookupByLibrary.simpleMessage("Count Damage"), - "itemSettingsCountWeight" : MessageLookupByLibrary.simpleMessage("Count Weight"), - "items" : MessageLookupByLibrary.simpleMessage("Items"), - "itemsWithCount" : m65, - "level" : MessageLookupByLibrary.simpleMessage("Level"), - "libraryCollectionListItemSubtitle" : m66, - "libraryCollectionListItemSubtitleType" : m67, - "libraryCollectionTitle" : MessageLookupByLibrary.simpleMessage("My Library"), - "libraryListNoItemsFoundClearFiltersButton" : MessageLookupByLibrary.simpleMessage("Clear Filters"), - "libraryListNoItemsFoundSubtitleFilters" : m68, - "libraryListNoItemsFoundSubtitleNoFilters" : m69, - "libraryListNoItemsFoundTitle" : m70, - "loadingCharacters" : MessageLookupByLibrary.simpleMessage("Getting characters..."), - "loadingGeneral" : MessageLookupByLibrary.simpleMessage("Loading..."), - "loadingUser" : MessageLookupByLibrary.simpleMessage("Signing in..."), - "markdownPreview" : MessageLookupByLibrary.simpleMessage("Content Preview"), - "maxLoad" : MessageLookupByLibrary.simpleMessage("Max Load"), - "migrationSubtitle" : MessageLookupByLibrary.simpleMessage("To get started, pick a username and the language for the rulebook & app. If you already have an existing Dungeon Paper account your data might take a few seconds to migrate."), - "migrationTitle" : MessageLookupByLibrary.simpleMessage("Welcome to\nDungeon Paper 2!"), - "migrationUsernameInfo" : MessageLookupByLibrary.simpleMessage("Your username is unique and can not be changed later, so think carefully! It will be used to identify all your library items when publishing."), - "moveCategory" : m71, - "moveCategoryWithLevel" : m72, - "moveCategoryWithLevelShort" : m73, - "moveToEnd" : MessageLookupByLibrary.simpleMessage("Move to bottom"), - "moveToEndGeneric" : m74, - "moveToStart" : MessageLookupByLibrary.simpleMessage("Move to top"), - "moveToStartGeneric" : m75, - "moves" : MessageLookupByLibrary.simpleMessage("Moves"), - "movesWithCount" : m76, - "myGeneric" : m77, - "navActions" : MessageLookupByLibrary.simpleMessage("Use"), - "navCharacter" : MessageLookupByLibrary.simpleMessage("Character"), - "navJournal" : MessageLookupByLibrary.simpleMessage("Journal"), - "noDescription" : MessageLookupByLibrary.simpleMessage("‹No description provided›"), - "noGeneric" : m78, - "noteNoCategory" : MessageLookupByLibrary.simpleMessage("General"), - "notes" : MessageLookupByLibrary.simpleMessage("Notes"), - "notesWithCount" : m79, - "ok" : MessageLookupByLibrary.simpleMessage("OK"), - "passwordHideTooltip" : MessageLookupByLibrary.simpleMessage("Hide password"), - "passwordShowTooltip" : MessageLookupByLibrary.simpleMessage("Show password"), - "pluralize" : m80, - "privacyPolicy" : MessageLookupByLibrary.simpleMessage("Privacy Policy"), - "quickIconsItems" : MessageLookupByLibrary.simpleMessage("Items"), - "quickIconsMoves" : MessageLookupByLibrary.simpleMessage("Moves"), - "quickIconsNote" : MessageLookupByLibrary.simpleMessage("+ Note"), - "quickIconsSpells" : MessageLookupByLibrary.simpleMessage("Spells"), - "reloadLibrary" : MessageLookupByLibrary.simpleMessage("Reload Library"), - "remove" : MessageLookupByLibrary.simpleMessage("Remove"), - "resetToDefault" : MessageLookupByLibrary.simpleMessage("Reset to default"), - "rollAttackDamageButton" : MessageLookupByLibrary.simpleMessage("Hack & Slash"), - "rollBasicActionButton" : MessageLookupByLibrary.simpleMessage("Basic Action"), - "rollButtonLabel" : MessageLookupByLibrary.simpleMessage("Button Text"), - "rollButtonTooltip" : m81, - "rollButtonTooltipWithDebility" : m82, - "rollDialogResultBreakdown" : m83, - "rollDialogResultTotal" : m84, - "rollDialogTitleRolled" : m85, - "rollDialogTitleRolling" : m86, - "rollDiscernRealitiesButton" : MessageLookupByLibrary.simpleMessage("Discern Realities"), - "rollVolleyButton" : MessageLookupByLibrary.simpleMessage("Volley"), - "save" : MessageLookupByLibrary.simpleMessage("Save"), - "saveGeneric" : m87, - "searchIn" : MessageLookupByLibrary.simpleMessage("Search in: "), - "searchPlaceholder" : MessageLookupByLibrary.simpleMessage("Type to search"), - "searchPlaceholderGeneric" : m88, - "seeAll" : MessageLookupByLibrary.simpleMessage("See all"), - "select" : MessageLookupByLibrary.simpleMessage("Select"), - "selectAll" : MessageLookupByLibrary.simpleMessage("Select All"), - "selectGeneric" : m89, - "selectNone" : MessageLookupByLibrary.simpleMessage("Select None"), - "selectToAdd" : m90, - "selected" : MessageLookupByLibrary.simpleMessage("Selected"), - "sendFeedbackBodyLabel" : MessageLookupByLibrary.simpleMessage("Problem description"), - "sendFeedbackSendButton" : MessageLookupByLibrary.simpleMessage("Feedback title"), - "sendFeedbackSuccessMessage" : MessageLookupByLibrary.simpleMessage("Thank you for your feedback! We will review your feedback as soon as we can."), - "sendFeedbackSuccessTitle" : MessageLookupByLibrary.simpleMessage("Feedback sent!"), - "sendFeedbackTitle" : MessageLookupByLibrary.simpleMessage("Send App Feedback"), - "sendFeedbackTitleLabel" : MessageLookupByLibrary.simpleMessage("Feedback title"), - "separatorOr" : MessageLookupByLibrary.simpleMessage("OR"), - "settingsDefaultDarkTheme" : MessageLookupByLibrary.simpleMessage("Default dark theme"), - "settingsDefaultLightTheme" : MessageLookupByLibrary.simpleMessage("Default light theme"), - "settingsGeneral" : MessageLookupByLibrary.simpleMessage("General"), - "settingsKeepScreenAwake" : MessageLookupByLibrary.simpleMessage("Keep screen awake while using the app"), - "settingsTitle" : MessageLookupByLibrary.simpleMessage("Settings"), - "signinButton" : MessageLookupByLibrary.simpleMessage("Sign in"), - "signinCantUseProvider" : m91, - "signinCantUseProviderTooltip" : m92, - "signinGoToSigninButton" : MessageLookupByLibrary.simpleMessage("Sign in"), - "signinGoToSigninLabel" : MessageLookupByLibrary.simpleMessage("Already have an account?"), - "signinGoToSignupButton" : MessageLookupByLibrary.simpleMessage("Sign up"), - "signinGoToSignupLabel" : MessageLookupByLibrary.simpleMessage("Don\'t have an account?"), - "signinProvider" : m93, - "signinProviderApple" : MessageLookupByLibrary.simpleMessage("Apple"), - "signinProviderFacebook" : MessageLookupByLibrary.simpleMessage("Facebook"), - "signinProviderGoogle" : MessageLookupByLibrary.simpleMessage("Google"), - "signinProviderLink" : MessageLookupByLibrary.simpleMessage("Link"), - "signinProviderUnlink" : MessageLookupByLibrary.simpleMessage("Unlink"), - "signinSubtitle" : MessageLookupByLibrary.simpleMessage("Sign in to your account to sync your data online, and get access to many more features."), - "signinTitle" : MessageLookupByLibrary.simpleMessage("Sign In"), - "signinWithButton" : m94, - "signoutButton" : MessageLookupByLibrary.simpleMessage("Sign out"), - "signupButton" : MessageLookupByLibrary.simpleMessage("Sign up"), - "signupDefaultDataLanguage" : MessageLookupByLibrary.simpleMessage("Default data language"), - "signupEmail" : MessageLookupByLibrary.simpleMessage("Email"), - "signupEmailPlaceholder" : MessageLookupByLibrary.simpleMessage("Enter your email"), - "signupEmailValidation" : MessageLookupByLibrary.simpleMessage("Please enter a valid email"), - "signupPassword" : MessageLookupByLibrary.simpleMessage("Password"), - "signupPasswordConfirm" : MessageLookupByLibrary.simpleMessage("Confirm Password"), - "signupPasswordConfirmPlaceholder" : MessageLookupByLibrary.simpleMessage("Enter the same password again"), - "signupPasswordPlaceholder" : MessageLookupByLibrary.simpleMessage("Enter your password"), - "signupPasswordValidationLength" : m95, - "signupPasswordValidationMatch" : MessageLookupByLibrary.simpleMessage("Passwords do not match"), - "signupPasswordValidationPatternGeneric" : m96, - "signupPasswordValidationPatternLetter" : MessageLookupByLibrary.simpleMessage("Password must contain at least one capital letter"), - "signupPasswordValidationPatternNumber" : MessageLookupByLibrary.simpleMessage("Password must contain at least one number"), - "signupSubtitle" : MessageLookupByLibrary.simpleMessage("Enter the required details below to create your Dungeon Paper account."), - "signupTitle" : MessageLookupByLibrary.simpleMessage("Sign Up"), - "signupUsername" : MessageLookupByLibrary.simpleMessage("Username"), - "signupUsernamePlaceholder" : MessageLookupByLibrary.simpleMessage("Pick a unique username"), - "signupUsernameValidation" : m97, - "signupUsernameValidationPattern" : MessageLookupByLibrary.simpleMessage("Username must only contain letters, numbers, dashes and underscores"), - "signupWithButton" : m98, - "socialApple" : MessageLookupByLibrary.simpleMessage("App Store"), - "socialDiscord" : MessageLookupByLibrary.simpleMessage("Discord"), - "socialFacebook" : MessageLookupByLibrary.simpleMessage("Facebook"), - "socialGitHub" : MessageLookupByLibrary.simpleMessage("GitHub"), - "socialGoogle" : MessageLookupByLibrary.simpleMessage("Play Store"), - "socialTwitter" : MessageLookupByLibrary.simpleMessage("Twitter"), - "sortMoveDown" : MessageLookupByLibrary.simpleMessage("Move down"), - "sortMoveUp" : MessageLookupByLibrary.simpleMessage("Move up"), - "specialDice" : MessageLookupByLibrary.simpleMessage("Special Dice"), - "specialRollButton" : m99, - "spellLevel" : m100, - "spells" : MessageLookupByLibrary.simpleMessage("Spells"), - "spellsWithCount" : m101, - "tagCopyFrom" : m102, - "tagDetails" : MessageLookupByLibrary.simpleMessage("Tag Information"), - "themeTurnDark" : MessageLookupByLibrary.simpleMessage("Switch to Dark Mode"), - "themeTurnLight" : MessageLookupByLibrary.simpleMessage("Switch to Light Mode"), - "unselect" : MessageLookupByLibrary.simpleMessage("Unselect"), - "useDefault" : MessageLookupByLibrary.simpleMessage("Use default"), - "userLoginButton" : MessageLookupByLibrary.simpleMessage("Sign in"), - "userLogoutButton" : MessageLookupByLibrary.simpleMessage("Sign out"), - "userMenuMoreChars" : MessageLookupByLibrary.simpleMessage("More"), - "userMenuRecentCharacters" : MessageLookupByLibrary.simpleMessage("Recent Characters"), - "userUnregistered" : MessageLookupByLibrary.simpleMessage("Not registered"), - "view" : MessageLookupByLibrary.simpleMessage("View"), - "viewGeneric" : m103, - "whatsNew" : MessageLookupByLibrary.simpleMessage("What\'s new?"), - "xpDialogChangeOverride" : MessageLookupByLibrary.simpleMessage("Update manually"), - "xpDialogEndSession" : MessageLookupByLibrary.simpleMessage("End Session"), - "xpDialogOverrideInfoText" : MessageLookupByLibrary.simpleMessage("Changing the current XP or level manually will cause the pending XP to be discarded unless this is unchecked."), - "xpDialogOverrideLevel" : MessageLookupByLibrary.simpleMessage("Override Level"), - "xpDialogOverrideXp" : MessageLookupByLibrary.simpleMessage("Override XP"), - "xpDialogResetSessionMarks" : MessageLookupByLibrary.simpleMessage("Reset bonds, flags & end of session questions after saving"), - "xpDialogTitle" : MessageLookupByLibrary.simpleMessage("Mark Session XP"), - "xpDialogTitleOverriding" : MessageLookupByLibrary.simpleMessage("Update XP & Level") - }; -} diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart deleted file mode 100644 index c80450d6..00000000 --- a/lib/generated/l10n.dart +++ /dev/null @@ -1,4811 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'intl/messages_all.dart'; - -// ************************************************************************** -// Generator: Flutter Intl IDE plugin -// Made by Localizely -// ************************************************************************** - -// ignore_for_file: non_constant_identifier_names, lines_longer_than_80_chars -// ignore_for_file: join_return_with_assignment, prefer_final_in_for_each -// ignore_for_file: avoid_redundant_argument_values, avoid_escaping_inner_quotes - -class S { - S(); - - static S? _current; - - static S get current { - assert( - _current != null, 'No instance of S was loaded. Try to initialize the S delegate before accessing S.current.'); - return _current!; - } - - static const AppLocalizationDelegate delegate = AppLocalizationDelegate(); - - static Future load(Locale locale) { - final name = (locale.countryCode?.isEmpty ?? false) ? locale.languageCode : locale.toString(); - final localeName = Intl.canonicalizedLocale(name); - return initializeMessages(localeName).then((_) { - Intl.defaultLocale = localeName; - final instance = S(); - S._current = instance; - - return instance; - }); - } - - static S of(BuildContext context) { - final instance = S.maybeOf(context); - assert(instance != null, - 'No instance of S present in the widget tree. Did you add S.delegate in localizationsDelegates?'); - return instance!; - } - - static S? maybeOf(BuildContext context) { - return Localizations.of(context, S); - } - - /// `` - String get abilityScoreBondDebilityDescription { - return Intl.message( - '', - name: 'abilityScoreBondDebilityDescription', - desc: '', - args: [], - ); - } - - /// `Lonely` - String get abilityScoreBondDebilityName { - return Intl.message( - 'Lonely', - name: 'abilityScoreBondDebilityName', - desc: '', - args: [], - ); - } - - /// `When a move has you roll+BOND you'll count the number of bonds you have with the character in question and add that to the roll.` - String get abilityScoreBondDescription { - return Intl.message( - 'When a move has you roll+BOND you\'ll count the number of bonds you have with the character in question and add that to the roll.', - name: 'abilityScoreBondDescription', - desc: '', - args: [], - ); - } - - /// `Charisma` - String get abilityScoreBondName { - return Intl.message( - 'Charisma', - name: 'abilityScoreBondName', - desc: '', - args: [], - ); - } - - /// `Roll +{stat}` - String abilityScoreButtonTooltip(Object stat) { - return Intl.message( - 'Roll +$stat', - name: 'abilityScoreButtonTooltip', - desc: '', - args: [stat], - ); - } - - /// `It may not be permanent, but for now you don't look so good.` - String get abilityScoreChaDebilityDescription { - return Intl.message( - 'It may not be permanent, but for now you don\'t look so good.', - name: 'abilityScoreChaDebilityDescription', - desc: '', - args: [], - ); - } - - /// `Scarred` - String get abilityScoreChaDebilityName { - return Intl.message( - 'Scarred', - name: 'abilityScoreChaDebilityName', - desc: '', - args: [], - ); - } - - /// `Measures a character's personality, personal magnetism, ability to lead, and appearance.` - String get abilityScoreChaDescription { - return Intl.message( - 'Measures a character\'s personality, personal magnetism, ability to lead, and appearance.', - name: 'abilityScoreChaDescription', - desc: '', - args: [], - ); - } - - /// `Charisma` - String get abilityScoreChaName { - return Intl.message( - 'Charisma', - name: 'abilityScoreChaName', - desc: '', - args: [], - ); - } - - /// `Something just isn't right inside. Maybe you've got a disease or a wasting illness. Maybe you just drank too much ale last night and it's coming back to haunt you.` - String get abilityScoreConDebilityDescription { - return Intl.message( - 'Something just isn\'t right inside. Maybe you\'ve got a disease or a wasting illness. Maybe you just drank too much ale last night and it\'s coming back to haunt you.', - name: 'abilityScoreConDebilityDescription', - desc: '', - args: [], - ); - } - - /// `Sick` - String get abilityScoreConDebilityName { - return Intl.message( - 'Sick', - name: 'abilityScoreConDebilityName', - desc: '', - args: [], - ); - } - - /// `Represents your character's health and stamina.` - String get abilityScoreConDescription { - return Intl.message( - 'Represents your character\'s health and stamina.', - name: 'abilityScoreConDescription', - desc: '', - args: [], - ); - } - - /// `Constitution` - String get abilityScoreConName { - return Intl.message( - 'Constitution', - name: 'abilityScoreConName', - desc: '', - args: [], - ); - } - - /// `You're unsteady on your feet and you've got a shake in your hands.` - String get abilityScoreDexDebilityDescription { - return Intl.message( - 'You\'re unsteady on your feet and you\'ve got a shake in your hands.', - name: 'abilityScoreDexDebilityDescription', - desc: '', - args: [], - ); - } - - /// `Shaky` - String get abilityScoreDexDebilityName { - return Intl.message( - 'Shaky', - name: 'abilityScoreDexDebilityName', - desc: '', - args: [], - ); - } - - /// `Measures agility, reflexes and balance.` - String get abilityScoreDexDescription { - return Intl.message( - 'Measures agility, reflexes and balance.', - name: 'abilityScoreDexDescription', - desc: '', - args: [], - ); - } - - /// `Dexterity` - String get abilityScoreDexName { - return Intl.message( - 'Dexterity', - name: 'abilityScoreDexName', - desc: '', - args: [], - ); - } - - /// `A description of the effect causing the debility and/or how it affects your character` - String get abilityScoreFormDebilityDescriptionDescription { - return Intl.message( - 'A description of the effect causing the debility and/or how it affects your character', - name: 'abilityScoreFormDebilityDescriptionDescription', - desc: '', - args: [], - ); - } - - /// `Debility Description` - String get abilityScoreFormDebilityDescriptionLabel { - return Intl.message( - 'Debility Description', - name: 'abilityScoreFormDebilityDescriptionLabel', - desc: '', - args: [], - ); - } - - /// `The name for the debility that occurs when this stat is debilitated (takes -1 until recovered).` - String get abilityScoreFormDebilityNameDescription { - return Intl.message( - 'The name for the debility that occurs when this stat is debilitated (takes -1 until recovered).', - name: 'abilityScoreFormDebilityNameDescription', - desc: '', - args: [], - ); - } - - /// `Debility Name` - String get abilityScoreFormDebilityNameLabel { - return Intl.message( - 'Debility Name', - name: 'abilityScoreFormDebilityNameLabel', - desc: '', - args: [], - ); - } - - /// `A description of what this ability score represents` - String get abilityScoreFormDescriptionDescription { - return Intl.message( - 'A description of what this ability score represents', - name: 'abilityScoreFormDescriptionDescription', - desc: '', - args: [], - ); - } - - /// `Ability Score Description` - String get abilityScoreFormDescriptionLabel { - return Intl.message( - 'Ability Score Description', - name: 'abilityScoreFormDescriptionLabel', - desc: '', - args: [], - ); - } - - /// `Icon` - String get abilityScoreFormIconLabel { - return Intl.message( - 'Icon', - name: 'abilityScoreFormIconLabel', - desc: '', - args: [], - ); - } - - /// `A 3-letter unique key that identifies this ability score in dice and is used as the short label for the modifier value (and not the actual score)` - String get abilityScoreFormKeyDescription { - return Intl.message( - 'A 3-letter unique key that identifies this ability score in dice and is used as the short label for the modifier value (and not the actual score)', - name: 'abilityScoreFormKeyDescription', - desc: '', - args: [], - ); - } - - /// `Ability Score Key` - String get abilityScoreFormKeyLabel { - return Intl.message( - 'Ability Score Key', - name: 'abilityScoreFormKeyLabel', - desc: '', - args: [], - ); - } - - /// `The name of this ability score` - String get abilityScoreFormNameDescription { - return Intl.message( - 'The name of this ability score', - name: 'abilityScoreFormNameDescription', - desc: '', - args: [], - ); - } - - /// `Ability Score Name` - String get abilityScoreFormNameLabel { - return Intl.message( - 'Ability Score Name', - name: 'abilityScoreFormNameLabel', - desc: '', - args: [], - ); - } - - /// `Change Icon` - String get abilityScoreFormPickIconLabel { - return Intl.message( - 'Change Icon', - name: 'abilityScoreFormPickIconLabel', - desc: '', - args: [], - ); - } - - /// `You can drag & drop the stat cards to change the order in which they appear throughout this character's screens.` - String get abilityScoreInfo { - return Intl.message( - 'You can drag & drop the stat cards to change the order in which they appear throughout this character\'s screens.', - name: 'abilityScoreInfo', - desc: '', - args: [], - ); - } - - /// `That last knock to the head shook something loose. Brain not work so good.` - String get abilityScoreIntDebilityDescription { - return Intl.message( - 'That last knock to the head shook something loose. Brain not work so good.', - name: 'abilityScoreIntDebilityDescription', - desc: '', - args: [], - ); - } - - /// `Stunned` - String get abilityScoreIntDebilityName { - return Intl.message( - 'Stunned', - name: 'abilityScoreIntDebilityName', - desc: '', - args: [], - ); - } - - /// `Determines how well your character learns and reasons.` - String get abilityScoreIntDescription { - return Intl.message( - 'Determines how well your character learns and reasons.', - name: 'abilityScoreIntDescription', - desc: '', - args: [], - ); - } - - /// `Intelligence` - String get abilityScoreIntName { - return Intl.message( - 'Intelligence', - name: 'abilityScoreIntName', - desc: '', - args: [], - ); - } - - /// `Modifier:\n{modifier}` - String abilityScoreModifierValueLabel(Object modifier) { - return Intl.message( - 'Modifier:\n$modifier', - name: 'abilityScoreModifierValueLabel', - desc: '', - args: [modifier], - ); - } - - /// `Roll random stat` - String get abilityScoreRollButtonTooltip { - return Intl.message( - 'Roll random stat', - name: 'abilityScoreRollButtonTooltip', - desc: '', - args: [], - ); - } - - /// `You can't exert much force. Maybe it's just fatigue and injury, or maybe your strength was drained by magic.` - String get abilityScoreStrDebilityDescription { - return Intl.message( - 'You can\'t exert much force. Maybe it\'s just fatigue and injury, or maybe your strength was drained by magic.', - name: 'abilityScoreStrDebilityDescription', - desc: '', - args: [], - ); - } - - /// `Weak` - String get abilityScoreStrDebilityName { - return Intl.message( - 'Weak', - name: 'abilityScoreStrDebilityName', - desc: '', - args: [], - ); - } - - /// `Measures muscle and physical power.` - String get abilityScoreStrDescription { - return Intl.message( - 'Measures muscle and physical power.', - name: 'abilityScoreStrDescription', - desc: '', - args: [], - ); - } - - /// `Strength` - String get abilityScoreStrName { - return Intl.message( - 'Strength', - name: 'abilityScoreStrName', - desc: '', - args: [], - ); - } - - /// `Ears ringing. Vision blurred. You're more than a little out of it.` - String get abilityScoreWisDebilityDescription { - return Intl.message( - 'Ears ringing. Vision blurred. You\'re more than a little out of it.', - name: 'abilityScoreWisDebilityDescription', - desc: '', - args: [], - ); - } - - /// `Confused` - String get abilityScoreWisDebilityName { - return Intl.message( - 'Confused', - name: 'abilityScoreWisDebilityName', - desc: '', - args: [], - ); - } - - /// `Describes a character's willpower, common sense, awareness, and intuition.` - String get abilityScoreWisDescription { - return Intl.message( - 'Describes a character\'s willpower, common sense, awareness, and intuition.', - name: 'abilityScoreWisDescription', - desc: '', - args: [], - ); - } - - /// `Wisdom` - String get abilityScoreWisName { - return Intl.message( - 'Wisdom', - name: 'abilityScoreWisName', - desc: '', - args: [], - ); - } - - /// `About` - String get about { - return Intl.message( - 'About', - name: 'about', - desc: '', - args: [], - ); - } - - /// `Chen Asraf` - String get aboutAuthor { - return Intl.message( - 'Chen Asraf', - name: 'aboutAuthor', - desc: '', - args: [], - ); - } - - /// `Copyright © 2018-{year}` - String aboutCopyright(Object year) { - return Intl.message( - 'Copyright © 2018-$year', - name: 'aboutCopyright', - desc: '', - args: [year], - ); - } - - /// `Icon Credits` - String get aboutIconCredits { - return Intl.message( - 'Icon Credits', - name: 'aboutIconCredits', - desc: '', - args: [], - ); - } - - /// `Join Our Discord` - String get aboutJoinDiscord { - return Intl.message( - 'Join Our Discord', - name: 'aboutJoinDiscord', - desc: '', - args: [], - ); - } - - /// `Join the Discord community to ask questions, get help, send feedback, or just chat with other players.` - String get aboutJoinDiscordSubtitle { - return Intl.message( - 'Join the Discord community to ask questions, get help, send feedback, or just chat with other players.', - name: 'aboutJoinDiscordSubtitle', - desc: '', - args: [], - ); - } - - /// `Send Feedback` - String get aboutSendFeedback { - return Intl.message( - 'Send Feedback', - name: 'aboutSendFeedback', - desc: '', - args: [], - ); - } - - /// `We reply more promptly through Discord, but you can send us feedback, bug reports or suggestions about the app directly here as an alternative.` - String get aboutSendFeedbackSubtitle { - return Intl.message( - 'We reply more promptly through Discord, but you can send us feedback, bug reports or suggestions about the app directly here as an alternative.', - name: 'aboutSendFeedbackSubtitle', - desc: '', - args: [], - ); - } - - /// `Links` - String get aboutSocialLinks { - return Intl.message( - 'Links', - name: 'aboutSocialLinks', - desc: '', - args: [], - ); - } - - /// `Special Thanks` - String get aboutSpecialThanks { - return Intl.message( - 'Special Thanks', - name: 'aboutSpecialThanks', - desc: '', - args: [], - ); - } - - /// `About` - String get aboutTitle { - return Intl.message( - 'About', - name: 'aboutTitle', - desc: '', - args: [], - ); - } - - /// `Version {version}` - String aboutVersion(Object version) { - return Intl.message( - 'Version $version', - name: 'aboutVersion', - desc: '', - args: [version], - ); - } - - /// `Account` - String get account { - return Intl.message( - 'Account', - name: 'account', - desc: '', - args: [], - ); - } - - /// `Account Details` - String get accountCategoryDetails { - return Intl.message( - 'Account Details', - name: 'accountCategoryDetails', - desc: '', - args: [], - ); - } - - /// `Connected Logins` - String get accountCategorySocials { - return Intl.message( - 'Connected Logins', - name: 'accountCategorySocials', - desc: '', - args: [], - ); - } - - /// `Enter your public display name` - String get accountChangeDisplayNameHint { - return Intl.message( - 'Enter your public display name', - name: 'accountChangeDisplayNameHint', - desc: '', - args: [], - ); - } - - /// `Display Name` - String get accountChangeDisplayNameLabel { - return Intl.message( - 'Display Name', - name: 'accountChangeDisplayNameLabel', - desc: '', - args: [], - ); - } - - /// `Display name changed successfully` - String get accountChangeDisplayNameSuccess { - return Intl.message( - 'Display name changed successfully', - name: 'accountChangeDisplayNameSuccess', - desc: '', - args: [], - ); - } - - /// `Change Display Name` - String get accountChangeDisplayNameTitle { - return Intl.message( - 'Change Display Name', - name: 'accountChangeDisplayNameTitle', - desc: '', - args: [], - ); - } - - /// `Enter your new email address` - String get accountChangeEmailHint { - return Intl.message( - 'Enter your new email address', - name: 'accountChangeEmailHint', - desc: '', - args: [], - ); - } - - /// `Email Address` - String get accountChangeEmailLabel { - return Intl.message( - 'Email Address', - name: 'accountChangeEmailLabel', - desc: '', - args: [], - ); - } - - /// `Email address changed successfully` - String get accountChangeEmailSuccess { - return Intl.message( - 'Email address changed successfully', - name: 'accountChangeEmailSuccess', - desc: '', - args: [], - ); - } - - /// `Change Email Address` - String get accountChangeEmailTitle { - return Intl.message( - 'Change Email Address', - name: 'accountChangeEmailTitle', - desc: '', - args: [], - ); - } - - /// `Change your profile picture` - String get accountChangeImageSubtitle { - return Intl.message( - 'Change your profile picture', - name: 'accountChangeImageSubtitle', - desc: '', - args: [], - ); - } - - /// `Change Profile Picture` - String get accountChangeImageTitle { - return Intl.message( - 'Change Profile Picture', - name: 'accountChangeImageTitle', - desc: '', - args: [], - ); - } - - /// `Enter the same password again` - String get accountChangePasswordConfirmHint { - return Intl.message( - 'Enter the same password again', - name: 'accountChangePasswordConfirmHint', - desc: '', - args: [], - ); - } - - /// `Confirm New Password` - String get accountChangePasswordConfirmLabel { - return Intl.message( - 'Confirm New Password', - name: 'accountChangePasswordConfirmLabel', - desc: '', - args: [], - ); - } - - /// `Enter your new password` - String get accountChangePasswordHint { - return Intl.message( - 'Enter your new password', - name: 'accountChangePasswordHint', - desc: '', - args: [], - ); - } - - /// `New Password` - String get accountChangePasswordLabel { - return Intl.message( - 'New Password', - name: 'accountChangePasswordLabel', - desc: '', - args: [], - ); - } - - /// `Change your password` - String get accountChangePasswordSubtitle { - return Intl.message( - 'Change your password', - name: 'accountChangePasswordSubtitle', - desc: '', - args: [], - ); - } - - /// `Password changed successfully` - String get accountChangePasswordSuccess { - return Intl.message( - 'Password changed successfully', - name: 'accountChangePasswordSuccess', - desc: '', - args: [], - ); - } - - /// `Change Password` - String get accountChangePasswordTitle { - return Intl.message( - 'Change Password', - name: 'accountChangePasswordTitle', - desc: '', - args: [], - ); - } - - /// `Delete Your Account` - String get accountDelete { - return Intl.message( - 'Delete Your Account', - name: 'accountDelete', - desc: '', - args: [], - ); - } - - /// `Basic Moves` - String get actionsBasicMoves { - return Intl.message( - 'Basic Moves', - name: 'actionsBasicMoves', - desc: '', - args: [], - ); - } - - /// `Special Moves` - String get actionsSpecialMoves { - return Intl.message( - 'Special Moves', - name: 'actionsSpecialMoves', - desc: '', - args: [], - ); - } - - /// `{coins} G` - String actionSummaryChipCoins(Object coins) { - return Intl.message( - '$coins G', - name: 'actionSummaryChipCoins', - desc: '', - args: [coins], - ); - } - - /// `Load: {load}/{maxLoad}` - String actionSummaryChipLoad(Object load, Object maxLoad) { - return Intl.message( - 'Load: $load/$maxLoad', - name: 'actionSummaryChipLoad', - desc: '', - args: [load, maxLoad], - ); - } - - /// `Show` - String get actionsViewVisibleLabel { - return Intl.message( - 'Show', - name: 'actionsViewVisibleLabel', - desc: '', - args: [], - ); - } - - /// `Add New {entity}` - String addCustomGeneric(Object entity) { - return Intl.message( - 'Add New $entity', - name: 'addCustomGeneric', - desc: '', - args: [entity], - ); - } - - /// `Add Existing {entity}` - String addExistingGeneric(Object entity) { - return Intl.message( - 'Add Existing $entity', - name: 'addExistingGeneric', - desc: '', - args: [entity], - ); - } - - /// `Add {entity}` - String addGeneric(Object entity) { - return Intl.message( - 'Add $entity', - name: 'addGeneric', - desc: '', - args: [entity], - ); - } - - /// `Online` - String get addRepoItemTabOnline { - return Intl.message( - 'Online', - name: 'addRepoItemTabOnline', - desc: '', - args: [], - ); - } - - /// `Playbook` - String get addRepoItemTabPlaybook { - return Intl.message( - 'Playbook', - name: 'addRepoItemTabPlaybook', - desc: '', - args: [], - ); - } - - /// `{alignment, select, chaotic {Chaotic} evil {Evil} good {Good} lawful {Lawful} neutral {Neutral} other {{alignment}}}` - String alignment(Object alignment) { - return Intl.select( - alignment, - { - 'chaotic': 'Chaotic', - 'evil': 'Evil', - 'good': 'Good', - 'lawful': 'Lawful', - 'neutral': 'Neutral', - 'other': '$alignment', - }, - name: 'alignment', - desc: '', - args: [alignment], - ); - } - - /// `Alignment` - String get alignmentLabel { - return Intl.message( - 'Alignment', - name: 'alignmentLabel', - desc: '', - args: [], - ); - } - - /// `All` - String get all { - return Intl.message( - 'All', - name: 'all', - desc: '', - args: [], - ); - } - - /// `All {entity}` - String allGeneric(Object entity) { - return Intl.message( - 'All $entity', - name: 'allGeneric', - desc: '', - args: [entity], - ); - } - - /// `Already added` - String get alreadyAdded { - return Intl.message( - 'Already added', - name: 'alreadyAdded', - desc: '', - args: [], - ); - } - - /// `Amount` - String get amount { - return Intl.message( - 'Amount', - name: 'amount', - desc: '', - args: [], - ); - } - - /// `Dungeon Paper` - String get appName { - return Intl.message( - 'Dungeon Paper', - name: 'appName', - desc: '', - args: [], - ); - } - - /// `Armor` - String get armor { - return Intl.message( - 'Armor', - name: 'armor', - desc: '', - args: [], - ); - } - - /// `Choose Photo...` - String get basicInfoImageChoose { - return Intl.message( - 'Choose Photo...', - name: 'basicInfoImageChoose', - desc: '', - args: [], - ); - } - - /// `Change Photo...` - String get basicInfoImageChooseNew { - return Intl.message( - 'Change Photo...', - name: 'basicInfoImageChooseNew', - desc: '', - args: [], - ); - } - - /// `Sign in or create an account` - String get basicInfoImageNeedAccountLinkLabel { - return Intl.message( - 'Sign in or create an account', - name: 'basicInfoImageNeedAccountLinkLabel', - desc: '', - args: [], - ); - } - - /// `You need to be signed in to upload images.` - String get basicInfoImageNeedAccountPrefix { - return Intl.message( - 'You need to be signed in to upload images.', - name: 'basicInfoImageNeedAccountPrefix', - desc: '', - args: [], - ); - } - - /// `, or upload using your own URL below.` - String get basicInfoImageNeedAccountSuffix { - return Intl.message( - ', or upload using your own URL below.', - name: 'basicInfoImageNeedAccountSuffix', - desc: '', - args: [], - ); - } - - /// `Remove Photo` - String get basicInfoImageRemove { - return Intl.message( - 'Remove Photo', - name: 'basicInfoImageRemove', - desc: '', - args: [], - ); - } - - /// `UPLOADING...` - String get basicInfoImageUploading { - return Intl.message( - 'UPLOADING...', - name: 'basicInfoImageUploading', - desc: '', - args: [], - ); - } - - /// `Basic Information` - String get basicInformationTitle { - return Intl.message( - 'Basic Information', - name: 'basicInformationTitle', - desc: '', - args: [], - ); - } - - /// `Cancel` - String get cancel { - return Intl.message( - 'Cancel', - name: 'cancel', - desc: '', - args: [], - ); - } - - /// `Change {entity}` - String changeGeneric(Object entity) { - return Intl.message( - 'Change $entity', - name: 'changeGeneric', - desc: '', - args: [entity], - ); - } - - /// `Use armor from class & equipped items` - String get characterAutoArmor { - return Intl.message( - 'Use armor from class & equipped items', - name: 'characterAutoArmor', - desc: '', - args: [], - ); - } - - /// `Use damage dice from class & equipped items` - String get characterAutoDamage { - return Intl.message( - 'Use damage dice from class & equipped items', - name: 'characterAutoDamage', - desc: '', - args: [], - ); - } - - /// `Use class base load + STR mod` - String get characterAutoMaxLoad { - return Intl.message( - 'Use class base load + STR mod', - name: 'characterAutoMaxLoad', - desc: '', - args: [], - ); - } - - /// `HP` - String get characterBarHp { - return Intl.message( - 'HP', - name: 'characterBarHp', - desc: '', - args: [], - ); - } - - /// `XP` - String get characterBarXp { - return Intl.message( - 'XP', - name: 'characterBarXp', - desc: '', - args: [], - ); - } - - /// `Alignment Description` - String get characterBioDialogAlignmentDescriptionLabel { - return Intl.message( - 'Alignment Description', - name: 'characterBioDialogAlignmentDescriptionLabel', - desc: '', - args: [], - ); - } - - /// `Alignment is your character's way of thinking and moral compass. This can center on an ethical ideal, religious strictures or early life events. It reflects what your character values and aspires to protect or create.` - String get characterBioDialogAlignmentDescriptionPlaceholder { - return Intl.message( - 'Alignment is your character\'s way of thinking and moral compass. This can center on an ethical ideal, religious strictures or early life events. It reflects what your character values and aspires to protect or create.', - name: 'characterBioDialogAlignmentDescriptionPlaceholder', - desc: '', - args: [], - ); - } - - /// `Alignment:` - String get characterBioDialogAlignmentNameDisplayLabel { - return Intl.message( - 'Alignment:', - name: 'characterBioDialogAlignmentNameDisplayLabel', - desc: '', - args: [], - ); - } - - /// `Alignment` - String get characterBioDialogAlignmentNameLabel { - return Intl.message( - 'Alignment', - name: 'characterBioDialogAlignmentNameLabel', - desc: '', - args: [], - ); - } - - /// `Select alignment` - String get characterBioDialogAlignmentNamePlaceholder { - return Intl.message( - 'Select alignment', - name: 'characterBioDialogAlignmentNamePlaceholder', - desc: '', - args: [], - ); - } - - /// `Character & background description` - String get characterBioDialogDescLabel { - return Intl.message( - 'Character & background description', - name: 'characterBioDialogDescLabel', - desc: '', - args: [], - ); - } - - /// `Describe your character's background, personality, goals, etc.` - String get characterBioDialogDescPlaceholder { - return Intl.message( - 'Describe your character\'s background, personality, goals, etc.', - name: 'characterBioDialogDescPlaceholder', - desc: '', - args: [], - ); - } - - /// `Looks` - String get characterBioDialogLooksLabel { - return Intl.message( - 'Looks', - name: 'characterBioDialogLooksLabel', - desc: '', - args: [], - ); - } - - /// `Describe your character's appearance. You may use the presets from the buttons above.` - String get characterBioDialogLooksPlaceholder { - return Intl.message( - 'Describe your character\'s appearance. You may use the presets from the buttons above.', - name: 'characterBioDialogLooksPlaceholder', - desc: '', - args: [], - ); - } - - /// `Character Biography` - String get characterBioDialogTitle { - return Intl.message( - 'Character Biography', - name: 'characterBioDialogTitle', - desc: '', - args: [], - ); - } - - /// `Bond` - String get characterBondsFlagsDialogBond { - return Intl.message( - 'Bond', - name: 'characterBondsFlagsDialogBond', - desc: '', - args: [], - ); - } - - /// `Bonds` - String get characterBondsFlagsDialogBonds { - return Intl.message( - 'Bonds', - name: 'characterBondsFlagsDialogBonds', - desc: '', - args: [], - ); - } - - /// `Flag` - String get characterBondsFlagsDialogFlag { - return Intl.message( - 'Flag', - name: 'characterBondsFlagsDialogFlag', - desc: '', - args: [], - ); - } - - /// `Flags` - String get characterBondsFlagsDialogFlags { - return Intl.message( - 'Flags', - name: 'characterBondsFlagsDialogFlags', - desc: '', - args: [], - ); - } - - /// `You can add, update or remove bonds & flags using the edit icon above.` - String get characterBondsFlagsDialogInfoText { - return Intl.message( - 'You can add, update or remove bonds & flags using the edit icon above.', - name: 'characterBondsFlagsDialogInfoText', - desc: '', - args: [], - ); - } - - /// `You have no bonds or flags. You can add some using the edit button above, then mark them off as completed as you go along your adventure.` - String get characterBondsFlagsDialogNoData { - return Intl.message( - 'You have no bonds or flags. You can add some using the edit button above, then mark them off as completed as you go along your adventure.', - name: 'characterBondsFlagsDialogNoData', - desc: '', - args: [], - ); - } - - /// `Bonds & Flags` - String get characterBondsFlagsDialogTitle { - return Intl.message( - 'Bonds & Flags', - name: 'characterBondsFlagsDialogTitle', - desc: '', - args: [], - ); - } - - /// `Debilities are temporary, negative conditions or states in which your character is in. When a stat is debilitated, it causes its modifier to be reduced by 1 until recovered.` - String get characterDebilitiesDialogInfoText { - return Intl.message( - 'Debilities are temporary, negative conditions or states in which your character is in. When a stat is debilitated, it causes its modifier to be reduced by 1 until recovered.', - name: 'characterDebilitiesDialogInfoText', - desc: '', - args: [], - ); - } - - /// `Debilities` - String get characterDebilitiesDialogTitle { - return Intl.message( - 'Debilities', - name: 'characterDebilitiesDialogTitle', - desc: '', - args: [], - ); - } - - /// `Level {level} ∙ {charClass} ∙ {race} ∙` - String characterHeaderSubtitle(Object level, Object charClass, Object race) { - return Intl.message( - 'Level $level ∙ $charClass ∙ $race ∙', - name: 'characterHeaderSubtitle', - desc: '', - args: [level, charClass, race], - ); - } - - /// `{alignment}` - String characterHeaderSubtitleAlignment(Object alignment) { - return Intl.message( - '$alignment', - name: 'characterHeaderSubtitleAlignment', - desc: '', - args: [alignment], - ); - } - - /// `{charClass}` - String characterHeaderSubtitleClass(Object charClass) { - return Intl.message( - '$charClass', - name: 'characterHeaderSubtitleClass', - desc: '', - args: [charClass], - ); - } - - /// `Level {level}` - String characterHeaderSubtitleLevel(Object level) { - return Intl.message( - 'Level $level', - name: 'characterHeaderSubtitleLevel', - desc: '', - args: [level], - ); - } - - /// `{race}` - String characterHeaderSubtitleRace(Object race) { - return Intl.message( - '$race', - name: 'characterHeaderSubtitleRace', - desc: '', - args: [race], - ); - } - - /// ` ∙ ` - String get characterHeaderSubtitleSeparator { - return Intl.message( - ' ∙ ', - name: 'characterHeaderSubtitleSeparator', - desc: '', - args: [], - ); - } - - /// `All Characters` - String get characterListTitle { - return Intl.message( - 'All Characters', - name: 'characterListTitle', - desc: '', - args: [], - ); - } - - /// `Character Menu` - String get characterMenu { - return Intl.message( - 'Character Menu', - name: 'characterMenu', - desc: '', - args: [], - ); - } - - /// `No Category` - String get characterNoCategory { - return Intl.message( - 'No Category', - name: 'characterNoCategory', - desc: '', - args: [], - ); - } - - /// `Ability Scores` - String get characterRollsTitle { - return Intl.message( - 'Ability Scores', - name: 'characterRollsTitle', - desc: '', - args: [], - ); - } - - /// `Character Theme` - String get characterSelectTheme { - return Intl.message( - 'Character Theme', - name: 'characterSelectTheme', - desc: '', - args: [], - ); - } - - /// `Coins` - String get coins { - return Intl.message( - 'Coins', - name: 'coins', - desc: '', - args: [], - ); - } - - /// `{count, plural, =0 {No coins} one {One coin} other {{fmtCount} coins}}` - String coinsWithCount(num count, Object fmtCount) { - return Intl.plural( - count, - zero: 'No coins', - one: 'One coin', - other: '$fmtCount coins', - name: 'coinsWithCount', - desc: '', - args: [count, fmtCount], - ); - } - - /// `Confirm` - String get confirm { - return Intl.message( - 'Confirm', - name: 'confirm', - desc: '', - args: [], - ); - } - - /// `Are you sure you want to remove the {entity} "{name}" from the list?` - String confirmDeleteBody(Object entity, Object name) { - return Intl.message( - 'Are you sure you want to remove the $entity "$name" from the list?', - name: 'confirmDeleteBody', - desc: '', - args: [entity, name], - ); - } - - /// `Delete {entity}?` - String confirmDeleteTitle(Object entity) { - return Intl.message( - 'Delete $entity?', - name: 'confirmDeleteTitle', - desc: '', - args: [entity], - ); - } - - /// `Are you sure you want to delete your account?\n\nThis action cannot be undone.` - String get confirmDeleteAccount1Body { - return Intl.message( - 'Are you sure you want to delete your account?\n\nThis action cannot be undone.', - name: 'confirmDeleteAccount1Body', - desc: '', - args: [], - ); - } - - /// `Delete Your Account?` - String get confirmDeleteAccount1Title { - return Intl.message( - 'Delete Your Account?', - name: 'confirmDeleteAccount1Title', - desc: '', - args: [], - ); - } - - /// `We do not save any data for deleted accounts. All your data will be permanently deleted.\n\nAre you sure you want to delete your account?\n\nPlease confirm this one last time.` - String get confirmDeleteAccount2Body { - return Intl.message( - 'We do not save any data for deleted accounts. All your data will be permanently deleted.\n\nAre you sure you want to delete your account?\n\nPlease confirm this one last time.', - name: 'confirmDeleteAccount2Body', - desc: '', - args: [], - ); - } - - /// `Are you really sure?` - String get confirmDeleteAccount2Title { - return Intl.message( - 'Are you really sure?', - name: 'confirmDeleteAccount2Title', - desc: '', - args: [], - ); - } - - /// `Are you sure you want to unlink your account from {provider}?\nBy clicking "Unlink", you will no longer be able to sign in with {provider}.\n\nYou will be able to re-link your account at any time by going to your account settings.` - String confirmUnlinkProviderBody(Object provider) { - return Intl.message( - 'Are you sure you want to unlink your account from $provider?\nBy clicking "Unlink", you will no longer be able to sign in with $provider.\n\nYou will be able to re-link your account at any time by going to your account settings.', - name: 'confirmUnlinkProviderBody', - desc: '', - args: [provider], - ); - } - - /// `Unlink from {entity}?` - String confirmUnlinkProviderTitle(Object entity) { - return Intl.message( - 'Unlink from $entity?', - name: 'confirmUnlinkProviderTitle', - desc: '', - args: [entity], - ); - } - - /// `Continue editing` - String get confirmExitDefaultCancelLabel { - return Intl.message( - 'Continue editing', - name: 'confirmExitDefaultCancelLabel', - desc: '', - args: [], - ); - } - - /// `Exit & Discard` - String get confirmExitDefaultOkLabel { - return Intl.message( - 'Exit & Discard', - name: 'confirmExitDefaultOkLabel', - desc: '', - args: [], - ); - } - - /// `Going back will lose any unsaved changes.\nAre you sure you want to go back?` - String get confirmExitDefaultText { - return Intl.message( - 'Going back will lose any unsaved changes.\nAre you sure you want to go back?', - name: 'confirmExitDefaultText', - desc: '', - args: [], - ); - } - - /// `Are you sure?` - String get confirmExitDefaultTitle { - return Intl.message( - 'Are you sure?', - name: 'confirmExitDefaultTitle', - desc: '', - args: [], - ); - } - - /// `Continue` - String get continueLabel { - return Intl.message( - 'Continue', - name: 'continueLabel', - desc: '', - args: [], - ); - } - - /// `Create Character` - String get createCharacterAddButton { - return Intl.message( - 'Create Character', - name: 'createCharacterAddButton', - desc: '', - args: [], - ); - } - - /// `Photo URL` - String get createCharacterAvatarFieldLabel { - return Intl.message( - 'Photo URL', - name: 'createCharacterAvatarFieldLabel', - desc: '', - args: [], - ); - } - - /// `Paste an image URL` - String get createCharacterAvatarFieldPlaceholder { - return Intl.message( - 'Paste an image URL', - name: 'createCharacterAvatarFieldPlaceholder', - desc: '', - args: [], - ); - } - - /// `Biography` - String get createCharacterBioFieldLabel { - return Intl.message( - 'Biography', - name: 'createCharacterBioFieldLabel', - desc: '', - args: [], - ); - } - - /// `Describe your character as shortly or thoroughly as you want here.\nPut your backstory, a visual description, some personality traits, etc. to help you keep in character.` - String get createCharacterBioFieldPlaceholder { - return Intl.message( - 'Describe your character as shortly or thoroughly as you want here.\nPut your backstory, a visual description, some personality traits, etc. to help you keep in character.', - name: 'createCharacterBioFieldPlaceholder', - desc: '', - args: [], - ); - } - - /// `Base HP: {hp}, Load: {load}, Damage Dice: {damageDice}` - String createCharacterClassDescription(Object hp, Object load, Object damageDice) { - return Intl.message( - 'Base HP: $hp, Load: $load, Damage Dice: $damageDice', - name: 'createCharacterClassDescription', - desc: '', - args: [hp, load, damageDice], - ); - } - - /// `No class selected (required)` - String get createCharacterClassHelpText { - return Intl.message( - 'No class selected (required)', - name: 'createCharacterClassHelpText', - desc: '', - args: [], - ); - } - - /// `Biography/description` - String get createCharacterDescFieldLabel { - return Intl.message( - 'Biography/description', - name: 'createCharacterDescFieldLabel', - desc: '', - args: [], - ); - } - - /// `Enter general information about your character - backstory, goals & ambitions, behavior descriptions, etc` - String get createCharacterDescFieldPlaceholder { - return Intl.message( - 'Enter general information about your character - backstory, goals & ambitions, behavior descriptions, etc', - name: 'createCharacterDescFieldPlaceholder', - desc: '', - args: [], - ); - } - - /// `Review` - String get createCharacterFinishButton { - return Intl.message( - 'Review', - name: 'createCharacterFinishButton', - desc: '', - args: [], - ); - } - - /// `Moves & Spells` - String get createCharacterMovesSpells { - return Intl.message( - 'Moves & Spells', - name: 'createCharacterMovesSpells', - desc: '', - args: [], - ); - } - - /// `{moves} Moves, {spells} Spells selected` - String createCharacterMovesSpellsDescription(Object moves, Object spells) { - return Intl.message( - '$moves Moves, $spells Spells selected', - name: 'createCharacterMovesSpellsDescription', - desc: '', - args: [moves, spells], - ); - } - - /// `Character Name` - String get createCharacterNameFieldLabel { - return Intl.message( - 'Character Name', - name: 'createCharacterNameFieldLabel', - desc: '', - args: [], - ); - } - - /// `Enter your character's name` - String get createCharacterNameFieldPlaceholder { - return Intl.message( - 'Enter your character\'s name', - name: 'createCharacterNameFieldPlaceholder', - desc: '', - args: [], - ); - } - - /// `Max HP: {hp}` - String createCharacterPreviewPageMaxHp(Object hp) { - return Intl.message( - 'Max HP: $hp', - name: 'createCharacterPreviewPageMaxHp', - desc: '', - args: [hp], - ); - } - - /// `Preview Character` - String get createCharacterPreviewPageTitle { - return Intl.message( - 'Preview Character', - name: 'createCharacterPreviewPageTitle', - desc: '', - args: [], - ); - } - - /// `Continue` - String get createCharacterProceedTooltip { - return Intl.message( - 'Continue', - name: 'createCharacterProceedTooltip', - desc: '', - args: [], - ); - } - - /// `Race description` - String get createCharacterRaceDescFieldLabel { - return Intl.message( - 'Race description', - name: 'createCharacterRaceDescFieldLabel', - desc: '', - args: [], - ); - } - - /// `Describe a special move usable by your race. It will appear alongside the rest of the moves.` - String get createCharacterRaceDescFieldPlaceholder { - return Intl.message( - 'Describe a special move usable by your race. It will appear alongside the rest of the moves.', - name: 'createCharacterRaceDescFieldPlaceholder', - desc: '', - args: [], - ); - } - - /// `Race` - String get createCharacterRaceNameFieldLabel { - return Intl.message( - 'Race', - name: 'createCharacterRaceNameFieldLabel', - desc: '', - args: [], - ); - } - - /// `Race name` - String get createCharacterRaceNameFieldPlaceholder { - return Intl.message( - 'Race name', - name: 'createCharacterRaceNameFieldPlaceholder', - desc: '', - args: [], - ); - } - - /// `Create Character` - String get createCharacterSaveButton { - return Intl.message( - 'Create Character', - name: 'createCharacterSaveButton', - desc: '', - args: [], - ); - } - - /// `{count} selected` - String createCharacterStartingGearChoiceCountNoMax(Object count) { - return Intl.message( - '$count selected', - name: 'createCharacterStartingGearChoiceCountNoMax', - desc: '', - args: [count], - ); - } - - /// `{count} selected (class allowance: {max})` - String createCharacterStartingGearChoiceCountWithMax(Object count, Object max) { - return Intl.message( - '$count selected (class allowance: $max)', - name: 'createCharacterStartingGearChoiceCountWithMax', - desc: '', - args: [count, max], - ); - } - - /// `{amount} coins` - String createCharacterStartingGearDescriptionCoins(Object amount) { - return Intl.message( - '$amount coins', - name: 'createCharacterStartingGearDescriptionCoins', - desc: '', - args: [amount], - ); - } - - /// `{amount} × {name}` - String createCharacterStartingGearDescriptionItem(Object amount, Object name) { - return Intl.message( - '$amount × $name', - name: 'createCharacterStartingGearDescriptionItem', - desc: '', - args: [amount, name], - ); - } - - /// `Select your starting gear determined by class (optional)` - String get createCharacterStartingGearHelpText { - return Intl.message( - 'Select your starting gear determined by class (optional)', - name: 'createCharacterStartingGearHelpText', - desc: '', - args: [], - ); - } - - /// `{step} - Changes Required` - String createCharacterStepInvalidTooltip(Object step) { - return Intl.message( - '$step - Changes Required', - name: 'createCharacterStepInvalidTooltip', - desc: '', - args: [step], - ); - } - - /// `Create Character` - String get createCharacterTitle { - return Intl.message( - 'Create Character', - name: 'createCharacterTitle', - desc: '', - args: [], - ); - } - - /// `Unnamed Traveler` - String get createCharacterTravelerBlankName { - return Intl.message( - 'Unnamed Traveler', - name: 'createCharacterTravelerBlankName', - desc: '', - args: [], - ); - } - - /// `Level 1 {cls}` - String createCharacterTravelerDescription(Object cls) { - return Intl.message( - 'Level 1 $cls', - name: 'createCharacterTravelerDescription', - desc: '', - args: [cls], - ); - } - - /// `Select name & picture (required)` - String get createCharacterTravelerHelpText { - return Intl.message( - 'Select name & picture (required)', - name: 'createCharacterTravelerHelpText', - desc: '', - args: [], - ); - } - - /// `Click to generate a random name` - String get createCharRandomizeNameTooltipClick { - return Intl.message( - 'Click to generate a random name', - name: 'createCharRandomizeNameTooltipClick', - desc: '', - args: [], - ); - } - - /// `Tap to generate a random name` - String get createCharRandomizeNameTooltipTouch { - return Intl.message( - 'Tap to generate a random name', - name: 'createCharRandomizeNameTooltipTouch', - desc: '', - args: [], - ); - } - - /// `Create {entity}` - String createGeneric(Object entity) { - return Intl.message( - 'Create $entity', - name: 'createGeneric', - desc: '', - args: [entity], - ); - } - - /// `Left Button` - String get customButtonLeft { - return Intl.message( - 'Left Button', - name: 'customButtonLeft', - desc: '', - args: [], - ); - } - - /// `Right Button` - String get customButtonRight { - return Intl.message( - 'Right Button', - name: 'customButtonRight', - desc: '', - args: [], - ); - } - - /// `Quick Roll Buttons` - String get customRollButtons { - return Intl.message( - 'Quick Roll Buttons', - name: 'customRollButtons', - desc: '', - args: [], - ); - } - - /// `Use Default` - String get customRollButtonsUseDefault { - return Intl.message( - 'Use Default', - name: 'customRollButtonsUseDefault', - desc: '', - args: [], - ); - } - - /// `Presets` - String get customRollButtonsUsePreset { - return Intl.message( - 'Presets', - name: 'customRollButtonsUsePreset', - desc: '', - args: [], - ); - } - - /// `Damage` - String get damage { - return Intl.message( - 'Damage', - name: 'damage', - desc: '', - args: [], - ); - } - - /// `Damage Dice` - String get damageDice { - return Intl.message( - 'Damage Dice', - name: 'damageDice', - desc: '', - args: [], - ); - } - - /// `{name} ({key})` - String debilityLabel(Object name, Object key) { - return Intl.message( - '$name ($key)', - name: 'debilityLabel', - desc: '', - args: [name, key], - ); - } - - /// `Amount` - String get diceAmount { - return Intl.message( - 'Amount', - name: 'diceAmount', - desc: '', - args: [], - ); - } - - /// `Roll` - String get diceRollAgain { - return Intl.message( - 'Roll', - name: 'diceRollAgain', - desc: '', - args: [], - ); - } - - /// `d` - String get diceSeparator { - return Intl.message( - 'd', - name: 'diceSeparator', - desc: '', - args: [], - ); - } - - /// `Sides` - String get diceSides { - return Intl.message( - 'Sides', - name: 'diceSides', - desc: '', - args: [], - ); - } - - /// `Suggested: {dice}` - String diceSuggestion(Object dice) { - return Intl.message( - 'Suggested: $dice', - name: 'diceSuggestion', - desc: '', - args: [dice], - ); - } - - /// `Roll Stat` - String get diceUseStat { - return Intl.message( - 'Roll Stat', - name: 'diceUseStat', - desc: '', - args: [], - ); - } - - /// `Stat` - String get diceUseStatLabel { - return Intl.message( - 'Stat', - name: 'diceUseStatLabel', - desc: '', - args: [], - ); - } - - /// `Select Stat` - String get diceUseStatPlaceholder { - return Intl.message( - 'Select Stat', - name: 'diceUseStatPlaceholder', - desc: '', - args: [], - ); - } - - /// `{name} ({key})` - String diceUseStatValue(Object name, Object key) { - return Intl.message( - '$name ($key)', - name: 'diceUseStatValue', - desc: '', - args: [name, key], - ); - } - - /// `Fixed Value` - String get diceUseValue { - return Intl.message( - 'Fixed Value', - name: 'diceUseValue', - desc: '', - args: [], - ); - } - - /// `Modifier value` - String get diceUseValueLabel { - return Intl.message( - 'Modifier value', - name: 'diceUseValueLabel', - desc: '', - args: [], - ); - } - - /// `Number, e.g. 2 or -1` - String get diceUseValuePlaceholder { - return Intl.message( - 'Number, e.g. 2 or -1', - name: 'diceUseValuePlaceholder', - desc: '', - args: [], - ); - } - - /// `Done` - String get done { - return Intl.message( - 'Done', - name: 'done', - desc: '', - args: [], - ); - } - - /// `Equipped Items` - String get dynamicCategoriesItems { - return Intl.message( - 'Equipped Items', - name: 'dynamicCategoriesItems', - desc: '', - args: [], - ); - } - - /// `Favorite Moves` - String get dynamicCategoriesMoves { - return Intl.message( - 'Favorite Moves', - name: 'dynamicCategoriesMoves', - desc: '', - args: [], - ); - } - - /// `Bookmarked Notes` - String get dynamicCategoriesNotes { - return Intl.message( - 'Bookmarked Notes', - name: 'dynamicCategoriesNotes', - desc: '', - args: [], - ); - } - - /// `Prepared Spells` - String get dynamicCategoriesSpells { - return Intl.message( - 'Prepared Spells', - name: 'dynamicCategoriesSpells', - desc: '', - args: [], - ); - } - - /// `Edit` - String get edit { - return Intl.message( - 'Edit', - name: 'edit', - desc: '', - args: [], - ); - } - - /// `Edit {entity}` - String editGeneric(Object entity) { - return Intl.message( - 'Edit $entity', - name: 'editGeneric', - desc: '', - args: [entity], - ); - } - - /// `Did we learn something new and important about the world?` - String get endOfSessionQ1 { - return Intl.message( - 'Did we learn something new and important about the world?', - name: 'endOfSessionQ1', - desc: '', - args: [], - ); - } - - /// `Did we overcome a notable monster or enemy?` - String get endOfSessionQ2 { - return Intl.message( - 'Did we overcome a notable monster or enemy?', - name: 'endOfSessionQ2', - desc: '', - args: [], - ); - } - - /// `Did we loot a memorable treasure?` - String get endOfSessionQ3 { - return Intl.message( - 'Did we loot a memorable treasure?', - name: 'endOfSessionQ3', - desc: '', - args: [], - ); - } - - /// `End of Session Questions` - String get endOfSessionQuestions { - return Intl.message( - 'End of Session Questions', - name: 'endOfSessionQuestions', - desc: '', - args: [], - ); - } - - /// `Answer these questions as a group. For each "yes" answer, XP is marked.` - String get endOfSessionQuestionsSubtitle { - return Intl.message( - 'Answer these questions as a group. For each "yes" answer, XP is marked.', - name: 'endOfSessionQuestionsSubtitle', - desc: '', - args: [], - ); - } - - /// `{runtimeType, select, CharacterClass {Class} Item {Item} Monster {Monster} Move {Move} Race {Race} Spell {Spell} Tag {Tag} MoveCategory {Category} GearSelection {Starting Gear} Dice {Dice} AbilityScore {Ability Score} AlignmentValue {Alignment} Playbook {Playbook} other {{runtimeType}}}` - String entity(Object runtimeType) { - return Intl.select( - runtimeType, - { - 'CharacterClass': 'Class', - 'Item': 'Item', - 'Monster': 'Monster', - 'Move': 'Move', - 'Race': 'Race', - 'Spell': 'Spell', - 'Tag': 'Tag', - 'MoveCategory': 'Category', - 'GearSelection': 'Starting Gear', - 'Dice': 'Dice', - 'AbilityScore': 'Ability Score', - 'AlignmentValue': 'Alignment', - 'Playbook': 'Playbook', - 'other': '$runtimeType', - }, - name: 'entity', - desc: '', - args: [runtimeType], - ); - } - - /// `{runtimeType, select, CharacterClass {Classes} Item {Items} Monster {Monsters} Move {Moves} Race {Races} Spell {Spells} Tag {Tags} MoveCategory {Categories} Dice {Dice} GearSelection {Starting Gear} AbilityScore {Ability Scores} AlignmentValue {Alignment} Playbook {Playbooks} other {{runtimeType}s}}` - String entityPlural(Object runtimeType) { - return Intl.select( - runtimeType, - { - 'CharacterClass': 'Classes', - 'Item': 'Items', - 'Monster': 'Monsters', - 'Move': 'Moves', - 'Race': 'Races', - 'Spell': 'Spells', - 'Tag': 'Tags', - 'MoveCategory': 'Categories', - 'Dice': 'Dice', - 'GearSelection': 'Starting Gear', - 'AbilityScore': 'Ability Scores', - 'AlignmentValue': 'Alignment', - 'Playbook': 'Playbooks', - 'other': '${runtimeType}s', - }, - name: 'entityPlural', - desc: '', - args: [runtimeType], - ); - } - - /// `This {entity} is not linked to any library item` - String entityShareStatusDetached(Object entity) { - return Intl.message( - 'This $entity is not linked to any library item', - name: 'entityShareStatusDetached', - desc: '', - args: [entity], - ); - } - - /// `This {entity} is In Sync with its linked library item` - String entityShareStatusInSync(Object entity) { - return Intl.message( - 'This $entity is In Sync with its linked library item', - name: 'entityShareStatusInSync', - desc: '', - args: [entity], - ); - } - - /// `This {entity} is Out of Sync with its linked library item` - String entityShareStatusOutOfSync(Object entity) { - return Intl.message( - 'This $entity is Out of Sync with its linked library item', - name: 'entityShareStatusOutOfSync', - desc: '', - args: [entity], - ); - } - - /// `{count, plural, =0 {No {entPlural}} one {One {ent}} other {{count} {entPlural}}}` - String entityWithCount(num count, Object entPlural, Object ent) { - return Intl.plural( - count, - zero: 'No $entPlural', - one: 'One $ent', - other: '$count $entPlural', - name: 'entityWithCount', - desc: '', - args: [count, entPlural, ent], - ); - } - - /// `Must be exactly {length} {length, plural, one {character} other {characters}}` - String errorExactLength(num length) { - return Intl.message( - 'Must be exactly $length ${Intl.plural(length, one: 'character', other: 'characters')}', - name: 'errorExactLength', - desc: '', - args: [length], - ); - } - - /// `Invalid email address` - String get errorInvalidEmail { - return Intl.message( - 'Invalid email address', - name: 'errorInvalidEmail', - desc: '', - args: [], - ); - } - - /// `Must be no more than {length} {length, plural, one {character} other {characters}}` - String errorMaxLength(num length) { - return Intl.message( - 'Must be no more than $length ${Intl.plural(length, one: 'character', other: 'characters')}', - name: 'errorMaxLength', - desc: '', - args: [length], - ); - } - - /// `Must be at least {length} {length, plural, one {character} other {characters}}` - String errorMinLength(num length) { - return Intl.message( - 'Must be at least $length ${Intl.plural(length, one: 'character', other: 'characters')}', - name: 'errorMinLength', - desc: '', - args: [length], - ); - } - - /// `Must contain {pattern}` - String errorMustContain(Object pattern) { - return Intl.message( - 'Must contain $pattern', - name: 'errorMustContain', - desc: '', - args: [pattern], - ); - } - - /// `Must not contain {pattern}` - String errorMustNotContain(Object pattern) { - return Intl.message( - 'Must not contain $pattern', - name: 'errorMustNotContain', - desc: '', - args: [pattern], - ); - } - - /// `None selected` - String get errorNoSelection { - return Intl.message( - 'None selected', - name: 'errorNoSelection', - desc: '', - args: [], - ); - } - - /// `No {entity} selected` - String errorNoSelectionGeneric(Object entity) { - return Intl.message( - 'No $entity selected', - name: 'errorNoSelectionGeneric', - desc: '', - args: [entity], - ); - } - - /// `No {entity} selected (required)` - String errorNoSelectionGenericRequired(Object entity) { - return Intl.message( - 'No $entity selected (required)', - name: 'errorNoSelectionGenericRequired', - desc: '', - args: [entity], - ); - } - - /// `Must contain letters only` - String get errorOnlyLetters { - return Intl.message( - 'Must contain letters only', - name: 'errorOnlyLetters', - desc: '', - args: [], - ); - } - - /// `Error while uploading photo. Try again later, or contact support using the "About" page.` - String get errorUpload { - return Intl.message( - 'Error while uploading photo. Try again later, or contact support using the "About" page.', - name: 'errorUpload', - desc: '', - args: [], - ); - } - - /// `Operation canceled` - String get errorUserOperationCanceled { - return Intl.message( - 'Operation canceled', - name: 'errorUserOperationCanceled', - desc: '', - args: [], - ); - } - - /// `Further details` - String get explanation { - return Intl.message( - 'Further details', - name: 'explanation', - desc: '', - args: [], - ); - } - - /// `Export` - String get export { - return Intl.message( - 'Export', - name: 'export', - desc: '', - args: [], - ); - } - - /// `Something went wrong.\nTry again or contact support if this persists` - String get exportFailedMessage { - return Intl.message( - 'Something went wrong.\nTry again or contact support if this persists', - name: 'exportFailedMessage', - desc: '', - args: [], - ); - } - - /// `Export Failed` - String get exportFailedTitle { - return Intl.message( - 'Export Failed', - name: 'exportFailedTitle', - desc: '', - args: [], - ); - } - - /// `Your data was exported to file successfully` - String get exportSuccessfulMessage { - return Intl.message( - 'Your data was exported to file successfully', - name: 'exportSuccessfulMessage', - desc: '', - args: [], - ); - } - - /// `Export Successful` - String get exportSuccessfulTitle { - return Intl.message( - 'Export Successful', - name: 'exportSuccessfulTitle', - desc: '', - args: [], - ); - } - - /// `Bold` - String get formatBold { - return Intl.message( - 'Bold', - name: 'formatBold', - desc: '', - args: [], - ); - } - - /// `Bullet List` - String get formatBulletList { - return Intl.message( - 'Bullet List', - name: 'formatBulletList', - desc: '', - args: [], - ); - } - - /// `Cell {n}` - String formatCell(Object n) { - return Intl.message( - 'Cell $n', - name: 'formatCell', - desc: '', - args: [n], - ); - } - - /// `Check List (Checked)` - String get formatCheckboxList { - return Intl.message( - 'Check List (Checked)', - name: 'formatCheckboxList', - desc: '', - args: [], - ); - } - - /// `Check List (Unchecked)` - String get formatCheckboxListUnchecked { - return Intl.message( - 'Check List (Unchecked)', - name: 'formatCheckboxListUnchecked', - desc: '', - args: [], - ); - } - - /// `Header {n}` - String formatHeader(Object n) { - return Intl.message( - 'Header $n', - name: 'formatHeader', - desc: '', - args: [n], - ); - } - - /// `Header {n}` - String formatHeaderNoNum(Object n) { - return Intl.message( - 'Header $n', - name: 'formatHeaderNoNum', - desc: '', - args: [n], - ); - } - - /// `Heading {n}` - String formatHeading(Object n) { - return Intl.message( - 'Heading $n', - name: 'formatHeading', - desc: '', - args: [n], - ); - } - - /// `Headings` - String get formatHeadings { - return Intl.message( - 'Headings', - name: 'formatHeadings', - desc: '', - args: [], - ); - } - - /// `Formatting Help` - String get formatHelp { - return Intl.message( - 'Formatting Help', - name: 'formatHelp', - desc: '', - args: [], - ); - } - - /// `Image URL` - String get formatImageURL { - return Intl.message( - 'Image URL', - name: 'formatImageURL', - desc: '', - args: [], - ); - } - - /// `Italic` - String get formatItalic { - return Intl.message( - 'Italic', - name: 'formatItalic', - desc: '', - args: [], - ); - } - - /// `Numbered List` - String get formatNumberedList { - return Intl.message( - 'Numbered List', - name: 'formatNumberedList', - desc: '', - args: [], - ); - } - - /// `Preview` - String get formatPreview { - return Intl.message( - 'Preview', - name: 'formatPreview', - desc: '', - args: [], - ); - } - - /// `Table` - String get formatTable { - return Intl.message( - 'Table', - name: 'formatTable', - desc: '', - args: [], - ); - } - - /// `URL` - String get formatURL { - return Intl.message( - 'URL', - name: 'formatURL', - desc: '', - args: [], - ); - } - - /// `Base HP` - String get formCharacterClassBaseHp { - return Intl.message( - 'Base HP', - name: 'formCharacterClassBaseHp', - desc: '', - args: [], - ); - } - - /// `Base Load` - String get formCharacterClassBaseLoad { - return Intl.message( - 'Base Load', - name: 'formCharacterClassBaseLoad', - desc: '', - args: [], - ); - } - - /// `Damage Dice` - String get formCharacterClassDamage { - return Intl.message( - 'Damage Dice', - name: 'formCharacterClassDamage', - desc: '', - args: [], - ); - } - - /// `Give a general description of your class. Describe a calling for the type of person or creature that would choose or be raised in to this adventuring profession.` - String get formCharacterClassDescriptionPlaceholder { - return Intl.message( - 'Give a general description of your class. Describe a calling for the type of person or creature that would choose or be raised in to this adventuring profession.', - name: 'formCharacterClassDescriptionPlaceholder', - desc: '', - args: [], - ); - } - - /// `Enter the class name` - String get formCharacterClassNamePlaceholder { - return Intl.message( - 'Enter the class name', - name: 'formCharacterClassNamePlaceholder', - desc: '', - args: [], - ); - } - - /// `Category` - String get formGeneralCategory { - return Intl.message( - 'Category', - name: 'formGeneralCategory', - desc: '', - args: [], - ); - } - - /// `{entity} category` - String formGeneralCategoryGeneric(Object entity) { - return Intl.message( - '$entity category', - name: 'formGeneralCategoryGeneric', - desc: '', - args: [entity], - ); - } - - /// `Description` - String get formGeneralDescription { - return Intl.message( - 'Description', - name: 'formGeneralDescription', - desc: '', - args: [], - ); - } - - /// `{entity} description` - String formGeneralDescriptionGeneric(Object entity) { - return Intl.message( - '$entity description', - name: 'formGeneralDescriptionGeneric', - desc: '', - args: [entity], - ); - } - - /// `Explanation` - String get formGeneralExplanation { - return Intl.message( - 'Explanation', - name: 'formGeneralExplanation', - desc: '', - args: [], - ); - } - - /// `{entity} explanation` - String formGeneralExplanationGeneric(Object entity) { - return Intl.message( - '$entity explanation', - name: 'formGeneralExplanationGeneric', - desc: '', - args: [entity], - ); - } - - /// `Name` - String get formGeneralName { - return Intl.message( - 'Name', - name: 'formGeneralName', - desc: '', - args: [], - ); - } - - /// `{entity} name` - String formGeneralNameGeneric(Object entity) { - return Intl.message( - '$entity name', - name: 'formGeneralNameGeneric', - desc: '', - args: [entity], - ); - } - - /// `Title` - String get formGeneralTitle { - return Intl.message( - 'Title', - name: 'formGeneralTitle', - desc: '', - args: [], - ); - } - - /// `{entity} title` - String formGeneralTitleGeneric(Object entity) { - return Intl.message( - '$entity title', - name: 'formGeneralTitleGeneric', - desc: '', - args: [entity], - ); - } - - /// `{entity} description` - String genericDescriptionField(Object entity) { - return Intl.message( - '$entity description', - name: 'genericDescriptionField', - desc: '', - args: [entity], - ); - } - - /// `{entity} name` - String genericNameField(Object entity) { - return Intl.message( - '$entity name', - name: 'genericNameField', - desc: '', - args: [entity], - ); - } - - /// `{entity} value` - String genericValueField(Object entity) { - return Intl.message( - '$entity value', - name: 'genericValueField', - desc: '', - args: [entity], - ); - } - - /// `Online data sync, library sharing, campaigns and more!` - String get homeEmptyStateLoginSubtitle { - return Intl.message( - 'Online data sync, library sharing, campaigns and more!', - name: 'homeEmptyStateLoginSubtitle', - desc: '', - args: [], - ); - } - - /// `Sign in to get more features` - String get homeEmptyStateLoginTitle { - return Intl.message( - 'Sign in to get more features', - name: 'homeEmptyStateLoginTitle', - desc: '', - args: [], - ); - } - - /// `Create a Character to get started` - String get homeEmptyStateSubtitle { - return Intl.message( - 'Create a Character to get started', - name: 'homeEmptyStateSubtitle', - desc: '', - args: [], - ); - } - - /// `No Characters` - String get homeEmptyStateTitle { - return Intl.message( - 'No Characters', - name: 'homeEmptyStateTitle', - desc: '', - args: [], - ); - } - - /// `HP` - String get hp { - return Intl.message( - 'HP', - name: 'hp', - desc: '', - args: [], - ); - } - - /// `Heal\n+{amount}` - String hpDialogChangeAdd(Object amount) { - return Intl.message( - 'Heal\n+$amount', - name: 'hpDialogChangeAdd', - desc: '', - args: [amount], - ); - } - - /// `No Change` - String get hpDialogChangeNeutral { - return Intl.message( - 'No Change', - name: 'hpDialogChangeNeutral', - desc: '', - args: [], - ); - } - - /// `Override Max HP` - String get hpDialogChangeOverrideMax { - return Intl.message( - 'Override Max HP', - name: 'hpDialogChangeOverrideMax', - desc: '', - args: [], - ); - } - - /// `Damage\n-{amount}` - String hpDialogChangeRemove(Object amount) { - return Intl.message( - 'Damage\n-$amount', - name: 'hpDialogChangeRemove', - desc: '', - args: [amount], - ); - } - - /// `Current HP` - String get hpDialogCurrentHP { - return Intl.message( - 'Current HP', - name: 'hpDialogCurrentHP', - desc: '', - args: [], - ); - } - - /// `Modify HP` - String get hpDialogTitle { - return Intl.message( - 'Modify HP', - name: 'hpDialogTitle', - desc: '', - args: [], - ); - } - - /// `Import` - String get import { - return Intl.message( - 'Import', - name: 'import', - desc: '', - args: [], - ); - } - - /// `Browse...` - String get importBrowseFile { - return Intl.message( - 'Browse...', - name: 'importBrowseFile', - desc: '', - args: [], - ); - } - - /// `To start importing, pick the file you want to import from.\nYou will then be able to select what to save and what to leave out.` - String get importBrowseHelp { - return Intl.message( - 'To start importing, pick the file you want to import from.\nYou will then be able to select what to save and what to leave out.', - name: 'importBrowseHelp', - desc: '', - args: [], - ); - } - - /// `Clear selected file` - String get importClearFile { - return Intl.message( - 'Clear selected file', - name: 'importClearFile', - desc: '', - args: [], - ); - } - - /// `Export/Import` - String get importExportTitle { - return Intl.message( - 'Export/Import', - name: 'importExportTitle', - desc: '', - args: [], - ); - } - - /// `Something went wrong.\nTry again or contact support if this persists` - String get importFailedMessage { - return Intl.message( - 'Something went wrong.\nTry again or contact support if this persists', - name: 'importFailedMessage', - desc: '', - args: [], - ); - } - - /// `Import Failed` - String get importFailedTitle { - return Intl.message( - 'Import Failed', - name: 'importFailedTitle', - desc: '', - args: [], - ); - } - - /// `Processing {entity}...` - String importProgressProcessing(Object entity) { - return Intl.message( - 'Processing $entity...', - name: 'importProgressProcessing', - desc: '', - args: [entity], - ); - } - - /// `Importing...` - String get importProgressTitle { - return Intl.message( - 'Importing...', - name: 'importProgressTitle', - desc: '', - args: [], - ); - } - - /// `Your data was imported from file successfully` - String get importSuccessMessage { - return Intl.message( - 'Your data was imported from file successfully', - name: 'importSuccessMessage', - desc: '', - args: [], - ); - } - - /// `Successful` - String get importSuccessTitle { - return Intl.message( - 'Successful', - name: 'importSuccessTitle', - desc: '', - args: [], - ); - } - - /// `× {amount}` - String itemAmountX(Object amount) { - return Intl.message( - '× $amount', - name: 'itemAmountX', - desc: '', - args: [amount], - ); - } - - /// `Count Armor` - String get itemSettingsCountArmor { - return Intl.message( - 'Count Armor', - name: 'itemSettingsCountArmor', - desc: '', - args: [], - ); - } - - /// `Count Damage` - String get itemSettingsCountDamage { - return Intl.message( - 'Count Damage', - name: 'itemSettingsCountDamage', - desc: '', - args: [], - ); - } - - /// `Count Weight` - String get itemSettingsCountWeight { - return Intl.message( - 'Count Weight', - name: 'itemSettingsCountWeight', - desc: '', - args: [], - ); - } - - /// `Items` - String get items { - return Intl.message( - 'Items', - name: 'items', - desc: '', - args: [], - ); - } - - /// `{count, plural, =0 {No items} one {One item} other {{count} items}}` - String itemsWithCount(num count) { - return Intl.plural( - count, - zero: 'No items', - one: 'One item', - other: '$count items', - name: 'itemsWithCount', - desc: '', - args: [count], - ); - } - - /// `Level` - String get level { - return Intl.message( - 'Level', - name: 'level', - desc: '', - args: [], - ); - } - - /// `{count} in {type}` - String libraryCollectionListItemSubtitle(Object count, Object type) { - return Intl.message( - '$count in $type', - name: 'libraryCollectionListItemSubtitle', - desc: '', - args: [count, type], - ); - } - - /// `{type, select, builtIn {Playbook} my {My Library} other {{type}}}` - String libraryCollectionListItemSubtitleType(Object type) { - return Intl.select( - type, - { - 'builtIn': 'Playbook', - 'my': 'My Library', - 'other': '$type', - }, - name: 'libraryCollectionListItemSubtitleType', - desc: '', - args: [type], - ); - } - - /// `My Library` - String get libraryCollectionTitle { - return Intl.message( - 'My Library', - name: 'libraryCollectionTitle', - desc: '', - args: [], - ); - } - - /// `Clear Filters` - String get libraryListNoItemsFoundClearFiltersButton { - return Intl.message( - 'Clear Filters', - name: 'libraryListNoItemsFoundClearFiltersButton', - desc: '', - args: [], - ); - } - - /// `Try changing the search or filters to find more {entities}.` - String libraryListNoItemsFoundSubtitleFilters(Object entities) { - return Intl.message( - 'Try changing the search or filters to find more $entities.', - name: 'libraryListNoItemsFoundSubtitleFilters', - desc: '', - args: [entities], - ); - } - - /// `No {entities} found in this list.` - String libraryListNoItemsFoundSubtitleNoFilters(Object entities) { - return Intl.message( - 'No $entities found in this list.', - name: 'libraryListNoItemsFoundSubtitleNoFilters', - desc: '', - args: [entities], - ); - } - - /// `No {entities} found` - String libraryListNoItemsFoundTitle(Object entities) { - return Intl.message( - 'No $entities found', - name: 'libraryListNoItemsFoundTitle', - desc: '', - args: [entities], - ); - } - - /// `Getting characters...` - String get loadingCharacters { - return Intl.message( - 'Getting characters...', - name: 'loadingCharacters', - desc: '', - args: [], - ); - } - - /// `Loading...` - String get loadingGeneral { - return Intl.message( - 'Loading...', - name: 'loadingGeneral', - desc: '', - args: [], - ); - } - - /// `Signing in...` - String get loadingUser { - return Intl.message( - 'Signing in...', - name: 'loadingUser', - desc: '', - args: [], - ); - } - - /// `Content Preview` - String get markdownPreview { - return Intl.message( - 'Content Preview', - name: 'markdownPreview', - desc: '', - args: [], - ); - } - - /// `Max Load` - String get maxLoad { - return Intl.message( - 'Max Load', - name: 'maxLoad', - desc: '', - args: [], - ); - } - - /// `Welcome to\nDungeon Paper 2!` - String get migrationTitle { - return Intl.message( - 'Welcome to\nDungeon Paper 2!', - name: 'migrationTitle', - desc: '', - args: [], - ); - } - - /// `To get started, pick a username and the language for the rulebook & app. If you already have an existing Dungeon Paper account your data might take a few seconds to migrate.` - String get migrationSubtitle { - return Intl.message( - 'To get started, pick a username and the language for the rulebook & app. If you already have an existing Dungeon Paper account your data might take a few seconds to migrate.', - name: 'migrationSubtitle', - desc: '', - args: [], - ); - } - - /// `Your username is unique and can not be changed later, so think carefully! It will be used to identify all your library items when publishing.` - String get migrationUsernameInfo { - return Intl.message( - 'Your username is unique and can not be changed later, so think carefully! It will be used to identify all your library items when publishing.', - name: 'migrationUsernameInfo', - desc: '', - args: [], - ); - } - - /// `{category, select, starting {Starting} basic {Basic} special {Special} advanced1 {Advanced} advanced2 {Advanced} other {Other}}` - String moveCategory(Object category) { - return Intl.select( - category, - { - 'starting': 'Starting', - 'basic': 'Basic', - 'special': 'Special', - 'advanced1': 'Advanced', - 'advanced2': 'Advanced', - 'other': 'Other', - }, - name: 'moveCategory', - desc: '', - args: [category], - ); - } - - /// `{category, select, starting {Starting} basic {Basic} special {Special} advanced1 {Advanced (level 1-5)} advanced2 {Advanced (level 6-10)} other {Other}}` - String moveCategoryWithLevel(Object category) { - return Intl.select( - category, - { - 'starting': 'Starting', - 'basic': 'Basic', - 'special': 'Special', - 'advanced1': 'Advanced (level 1-5)', - 'advanced2': 'Advanced (level 6-10)', - 'other': 'Other', - }, - name: 'moveCategoryWithLevel', - desc: '', - args: [category], - ); - } - - /// `{category, select, starting {Starting} basic {Basic} special {Special} advanced1 {Advanced (1-5)} advanced2 {Advanced (6-10)} other {Other}}` - String moveCategoryWithLevelShort(Object category) { - return Intl.select( - category, - { - 'starting': 'Starting', - 'basic': 'Basic', - 'special': 'Special', - 'advanced1': 'Advanced (1-5)', - 'advanced2': 'Advanced (6-10)', - 'other': 'Other', - }, - name: 'moveCategoryWithLevelShort', - desc: '', - args: [category], - ); - } - - /// `Moves` - String get moves { - return Intl.message( - 'Moves', - name: 'moves', - desc: '', - args: [], - ); - } - - /// `{count, plural, =0 {No moves} one {One move} other {{count} moves}}` - String movesWithCount(num count) { - return Intl.plural( - count, - zero: 'No moves', - one: 'One move', - other: '$count moves', - name: 'movesWithCount', - desc: '', - args: [count], - ); - } - - /// `Move to bottom` - String get moveToEnd { - return Intl.message( - 'Move to bottom', - name: 'moveToEnd', - desc: '', - args: [], - ); - } - - /// `Move {entity} to bottom` - String moveToEndGeneric(Object entity) { - return Intl.message( - 'Move $entity to bottom', - name: 'moveToEndGeneric', - desc: '', - args: [entity], - ); - } - - /// `Move to top` - String get moveToStart { - return Intl.message( - 'Move to top', - name: 'moveToStart', - desc: '', - args: [], - ); - } - - /// `Move {entity} to top` - String moveToStartGeneric(Object entity) { - return Intl.message( - 'Move $entity to top', - name: 'moveToStartGeneric', - desc: '', - args: [entity], - ); - } - - /// `My {entity}` - String myGeneric(Object entity) { - return Intl.message( - 'My $entity', - name: 'myGeneric', - desc: '', - args: [entity], - ); - } - - /// `Use` - String get navActions { - return Intl.message( - 'Use', - name: 'navActions', - desc: '', - args: [], - ); - } - - /// `Character` - String get navCharacter { - return Intl.message( - 'Character', - name: 'navCharacter', - desc: '', - args: [], - ); - } - - /// `Journal` - String get navJournal { - return Intl.message( - 'Journal', - name: 'navJournal', - desc: '', - args: [], - ); - } - - /// `‹No description provided›` - String get noDescription { - return Intl.message( - '‹No description provided›', - name: 'noDescription', - desc: '', - args: [], - ); - } - - /// `No {entity}` - String noGeneric(Object entity) { - return Intl.message( - 'No $entity', - name: 'noGeneric', - desc: '', - args: [entity], - ); - } - - /// `General` - String get noteNoCategory { - return Intl.message( - 'General', - name: 'noteNoCategory', - desc: '', - args: [], - ); - } - - /// `Notes` - String get notes { - return Intl.message( - 'Notes', - name: 'notes', - desc: '', - args: [], - ); - } - - /// `{count, plural, =0 {No notes} one {One note} other {{count} notes}}` - String notesWithCount(num count) { - return Intl.plural( - count, - zero: 'No notes', - one: 'One note', - other: '$count notes', - name: 'notesWithCount', - desc: '', - args: [count], - ); - } - - /// `OK` - String get ok { - return Intl.message( - 'OK', - name: 'ok', - desc: '', - args: [], - ); - } - - /// `Hide password` - String get passwordHideTooltip { - return Intl.message( - 'Hide password', - name: 'passwordHideTooltip', - desc: '', - args: [], - ); - } - - /// `Show password` - String get passwordShowTooltip { - return Intl.message( - 'Show password', - name: 'passwordShowTooltip', - desc: '', - args: [], - ); - } - - /// `{count, plural, one {One {singular}} other {{count} {plural}}}` - String pluralize(num count, Object singular, Object plural) { - return Intl.plural( - count, - one: 'One $singular', - other: '$count $plural', - name: 'pluralize', - desc: '', - args: [count, singular, plural], - ); - } - - /// `Privacy Policy` - String get privacyPolicy { - return Intl.message( - 'Privacy Policy', - name: 'privacyPolicy', - desc: '', - args: [], - ); - } - - /// `Items` - String get quickIconsItems { - return Intl.message( - 'Items', - name: 'quickIconsItems', - desc: '', - args: [], - ); - } - - /// `Moves` - String get quickIconsMoves { - return Intl.message( - 'Moves', - name: 'quickIconsMoves', - desc: '', - args: [], - ); - } - - /// `+ Note` - String get quickIconsNote { - return Intl.message( - '+ Note', - name: 'quickIconsNote', - desc: '', - args: [], - ); - } - - /// `Spells` - String get quickIconsSpells { - return Intl.message( - 'Spells', - name: 'quickIconsSpells', - desc: '', - args: [], - ); - } - - /// `Reload Library` - String get reloadLibrary { - return Intl.message( - 'Reload Library', - name: 'reloadLibrary', - desc: '', - args: [], - ); - } - - /// `Remove` - String get remove { - return Intl.message( - 'Remove', - name: 'remove', - desc: '', - args: [], - ); - } - - /// `Reset to default` - String get resetToDefault { - return Intl.message( - 'Reset to default', - name: 'resetToDefault', - desc: '', - args: [], - ); - } - - /// `Hack & Slash` - String get rollAttackDamageButton { - return Intl.message( - 'Hack & Slash', - name: 'rollAttackDamageButton', - desc: '', - args: [], - ); - } - - /// `Basic Action` - String get rollBasicActionButton { - return Intl.message( - 'Basic Action', - name: 'rollBasicActionButton', - desc: '', - args: [], - ); - } - - /// `Button Text` - String get rollButtonLabel { - return Intl.message( - 'Button Text', - name: 'rollButtonLabel', - desc: '', - args: [], - ); - } - - /// `Roll {dice}` - String rollButtonTooltip(Object dice) { - return Intl.message( - 'Roll $dice', - name: 'rollButtonTooltip', - desc: '', - args: [dice], - ); - } - - /// `Roll {dice}\n* Rolling with debility` - String rollButtonTooltipWithDebility(Object dice) { - return Intl.message( - 'Roll $dice\n* Rolling with debility', - name: 'rollButtonTooltipWithDebility', - desc: '', - args: [dice], - ); - } - - /// `Dice: {dice} | Modifier: {mod}` - String rollDialogResultBreakdown(Object dice, Object mod) { - return Intl.message( - 'Dice: $dice | Modifier: $mod', - name: 'rollDialogResultBreakdown', - desc: '', - args: [dice, mod], - ); - } - - /// `Total: {total}` - String rollDialogResultTotal(Object total) { - return Intl.message( - 'Total: $total', - name: 'rollDialogResultTotal', - desc: '', - args: [total], - ); - } - - /// `Total: {total}` - String rollDialogTitleRolled(Object total) { - return Intl.message( - 'Total: $total', - name: 'rollDialogTitleRolled', - desc: '', - args: [total], - ); - } - - /// `Rolling {count} dice` - String rollDialogTitleRolling(Object count) { - return Intl.message( - 'Rolling $count dice', - name: 'rollDialogTitleRolling', - desc: '', - args: [count], - ); - } - - /// `Discern Realities` - String get rollDiscernRealitiesButton { - return Intl.message( - 'Discern Realities', - name: 'rollDiscernRealitiesButton', - desc: '', - args: [], - ); - } - - /// `Volley` - String get rollVolleyButton { - return Intl.message( - 'Volley', - name: 'rollVolleyButton', - desc: '', - args: [], - ); - } - - /// `Save` - String get save { - return Intl.message( - 'Save', - name: 'save', - desc: '', - args: [], - ); - } - - /// `Save {entity}` - String saveGeneric(Object entity) { - return Intl.message( - 'Save $entity', - name: 'saveGeneric', - desc: '', - args: [entity], - ); - } - - /// `Search in: ` - String get searchIn { - return Intl.message( - 'Search in: ', - name: 'searchIn', - desc: '', - args: [], - ); - } - - /// `Type to search` - String get searchPlaceholder { - return Intl.message( - 'Type to search', - name: 'searchPlaceholder', - desc: '', - args: [], - ); - } - - /// `Type to search {entity}` - String searchPlaceholderGeneric(Object entity) { - return Intl.message( - 'Type to search $entity', - name: 'searchPlaceholderGeneric', - desc: '', - args: [entity], - ); - } - - /// `See all` - String get seeAll { - return Intl.message( - 'See all', - name: 'seeAll', - desc: '', - args: [], - ); - } - - /// `Select` - String get select { - return Intl.message( - 'Select', - name: 'select', - desc: '', - args: [], - ); - } - - /// `Select All` - String get selectAll { - return Intl.message( - 'Select All', - name: 'selectAll', - desc: '', - args: [], - ); - } - - /// `Selected` - String get selected { - return Intl.message( - 'Selected', - name: 'selected', - desc: '', - args: [], - ); - } - - /// `Select {entity}` - String selectGeneric(Object entity) { - return Intl.message( - 'Select $entity', - name: 'selectGeneric', - desc: '', - args: [entity], - ); - } - - /// `Select None` - String get selectNone { - return Intl.message( - 'Select None', - name: 'selectNone', - desc: '', - args: [], - ); - } - - /// `Select {string} to add` - String selectToAdd(Object string) { - return Intl.message( - 'Select $string to add', - name: 'selectToAdd', - desc: '', - args: [string], - ); - } - - /// `Problem description` - String get sendFeedbackBodyLabel { - return Intl.message( - 'Problem description', - name: 'sendFeedbackBodyLabel', - desc: '', - args: [], - ); - } - - /// `Feedback title` - String get sendFeedbackSendButton { - return Intl.message( - 'Feedback title', - name: 'sendFeedbackSendButton', - desc: '', - args: [], - ); - } - - /// `Thank you for your feedback! We will review your feedback as soon as we can.` - String get sendFeedbackSuccessMessage { - return Intl.message( - 'Thank you for your feedback! We will review your feedback as soon as we can.', - name: 'sendFeedbackSuccessMessage', - desc: '', - args: [], - ); - } - - /// `Feedback sent!` - String get sendFeedbackSuccessTitle { - return Intl.message( - 'Feedback sent!', - name: 'sendFeedbackSuccessTitle', - desc: '', - args: [], - ); - } - - /// `Send App Feedback` - String get sendFeedbackTitle { - return Intl.message( - 'Send App Feedback', - name: 'sendFeedbackTitle', - desc: '', - args: [], - ); - } - - /// `Feedback title` - String get sendFeedbackTitleLabel { - return Intl.message( - 'Feedback title', - name: 'sendFeedbackTitleLabel', - desc: '', - args: [], - ); - } - - /// `OR` - String get separatorOr { - return Intl.message( - 'OR', - name: 'separatorOr', - desc: '', - args: [], - ); - } - - /// `Default dark theme` - String get settingsDefaultDarkTheme { - return Intl.message( - 'Default dark theme', - name: 'settingsDefaultDarkTheme', - desc: '', - args: [], - ); - } - - /// `Default light theme` - String get settingsDefaultLightTheme { - return Intl.message( - 'Default light theme', - name: 'settingsDefaultLightTheme', - desc: '', - args: [], - ); - } - - /// `General` - String get settingsGeneral { - return Intl.message( - 'General', - name: 'settingsGeneral', - desc: '', - args: [], - ); - } - - /// `Keep screen awake while using the app` - String get settingsKeepScreenAwake { - return Intl.message( - 'Keep screen awake while using the app', - name: 'settingsKeepScreenAwake', - desc: '', - args: [], - ); - } - - /// `Settings` - String get settingsTitle { - return Intl.message( - 'Settings', - name: 'settingsTitle', - desc: '', - args: [], - ); - } - - /// `Sign In` - String get signinTitle { - return Intl.message( - 'Sign In', - name: 'signinTitle', - desc: '', - args: [], - ); - } - - /// `Don't have an account?` - String get signinGoToSignupLabel { - return Intl.message( - 'Don\'t have an account?', - name: 'signinGoToSignupLabel', - desc: '', - args: [], - ); - } - - /// `Sign up` - String get signinGoToSignupButton { - return Intl.message( - 'Sign up', - name: 'signinGoToSignupButton', - desc: '', - args: [], - ); - } - - /// `Already have an account?` - String get signinGoToSigninLabel { - return Intl.message( - 'Already have an account?', - name: 'signinGoToSigninLabel', - desc: '', - args: [], - ); - } - - /// `Sign in` - String get signinGoToSigninButton { - return Intl.message( - 'Sign in', - name: 'signinGoToSigninButton', - desc: '', - args: [], - ); - } - - /// `Sign in to your account to sync your data online, and get access to many more features.` - String get signinSubtitle { - return Intl.message( - 'Sign in to your account to sync your data online, and get access to many more features.', - name: 'signinSubtitle', - desc: '', - args: [], - ); - } - - /// `Sign Up` - String get signupTitle { - return Intl.message( - 'Sign Up', - name: 'signupTitle', - desc: '', - args: [], - ); - } - - /// `Enter the required details below to create your Dungeon Paper account.` - String get signupSubtitle { - return Intl.message( - 'Enter the required details below to create your Dungeon Paper account.', - name: 'signupSubtitle', - desc: '', - args: [], - ); - } - - /// `Sign in` - String get signinButton { - return Intl.message( - 'Sign in', - name: 'signinButton', - desc: '', - args: [], - ); - } - - /// `Sign up` - String get signupButton { - return Intl.message( - 'Sign up', - name: 'signupButton', - desc: '', - args: [], - ); - } - - /// `Sign in with {provider}` - String signinWithButton(Object provider) { - return Intl.message( - 'Sign in with $provider', - name: 'signinWithButton', - desc: '', - args: [provider], - ); - } - - /// `Sign up with {provider}` - String signupWithButton(Object provider) { - return Intl.message( - 'Sign up with $provider', - name: 'signupWithButton', - desc: '', - args: [provider], - ); - } - - /// `{provider, select, facebook {Facebook} google {Google} apple {Apple} password {Dungeon Paper} other {Other}}` - String signinProvider(Object provider) { - return Intl.select( - provider, - { - 'facebook': 'Facebook', - 'google': 'Google', - 'apple': 'Apple', - 'password': 'Dungeon Paper', - 'other': 'Other', - }, - name: 'signinProvider', - desc: '', - args: [provider], - ); - } - - /// `Facebook` - String get signinProviderFacebook { - return Intl.message( - 'Facebook', - name: 'signinProviderFacebook', - desc: '', - args: [], - ); - } - - /// `Google` - String get signinProviderGoogle { - return Intl.message( - 'Google', - name: 'signinProviderGoogle', - desc: '', - args: [], - ); - } - - /// `Apple` - String get signinProviderApple { - return Intl.message( - 'Apple', - name: 'signinProviderApple', - desc: '', - args: [], - ); - } - - /// `Link` - String get signinProviderLink { - return Intl.message( - 'Link', - name: 'signinProviderLink', - desc: '', - args: [], - ); - } - - /// `Unlink` - String get signinProviderUnlink { - return Intl.message( - 'Unlink', - name: 'signinProviderUnlink', - desc: '', - args: [], - ); - } - - /// `This device only supports unlinking {provider} accounts.` - String signinCantUseProvider(Object provider) { - return Intl.message( - 'This device only supports unlinking $provider accounts.', - name: 'signinCantUseProvider', - desc: '', - args: [provider], - ); - } - - /// `You may only unlink {provider} from this device.\nTo link accounts using the {provider} provider is only available from supported devices.` - String signinCantUseProviderTooltip(Object provider) { - return Intl.message( - 'You may only unlink $provider from this device.\nTo link accounts using the $provider provider is only available from supported devices.', - name: 'signinCantUseProviderTooltip', - desc: '', - args: [provider], - ); - } - - /// `Sign out` - String get signoutButton { - return Intl.message( - 'Sign out', - name: 'signoutButton', - desc: '', - args: [], - ); - } - - /// `Default data language` - String get signupDefaultDataLanguage { - return Intl.message( - 'Default data language', - name: 'signupDefaultDataLanguage', - desc: '', - args: [], - ); - } - - /// `Email` - String get signupEmail { - return Intl.message( - 'Email', - name: 'signupEmail', - desc: '', - args: [], - ); - } - - /// `Enter your email` - String get signupEmailPlaceholder { - return Intl.message( - 'Enter your email', - name: 'signupEmailPlaceholder', - desc: '', - args: [], - ); - } - - /// `Please enter a valid email` - String get signupEmailValidation { - return Intl.message( - 'Please enter a valid email', - name: 'signupEmailValidation', - desc: '', - args: [], - ); - } - - /// `Password` - String get signupPassword { - return Intl.message( - 'Password', - name: 'signupPassword', - desc: '', - args: [], - ); - } - - /// `Enter your password` - String get signupPasswordPlaceholder { - return Intl.message( - 'Enter your password', - name: 'signupPasswordPlaceholder', - desc: '', - args: [], - ); - } - - /// `Confirm Password` - String get signupPasswordConfirm { - return Intl.message( - 'Confirm Password', - name: 'signupPasswordConfirm', - desc: '', - args: [], - ); - } - - /// `Enter the same password again` - String get signupPasswordConfirmPlaceholder { - return Intl.message( - 'Enter the same password again', - name: 'signupPasswordConfirmPlaceholder', - desc: '', - args: [], - ); - } - - /// `Password must be at least {length} characters` - String signupPasswordValidationLength(Object length) { - return Intl.message( - 'Password must be at least $length characters', - name: 'signupPasswordValidationLength', - desc: '', - args: [length], - ); - } - - /// `Passwords do not match` - String get signupPasswordValidationMatch { - return Intl.message( - 'Passwords do not match', - name: 'signupPasswordValidationMatch', - desc: '', - args: [], - ); - } - - /// `Password must contain {pattern}` - String signupPasswordValidationPatternGeneric(Object pattern) { - return Intl.message( - 'Password must contain $pattern', - name: 'signupPasswordValidationPatternGeneric', - desc: '', - args: [pattern], - ); - } - - /// `Password must contain at least one capital letter` - String get signupPasswordValidationPatternLetter { - return Intl.message( - 'Password must contain at least one capital letter', - name: 'signupPasswordValidationPatternLetter', - desc: '', - args: [], - ); - } - - /// `Password must contain at least one number` - String get signupPasswordValidationPatternNumber { - return Intl.message( - 'Password must contain at least one number', - name: 'signupPasswordValidationPatternNumber', - desc: '', - args: [], - ); - } - - /// `Username` - String get signupUsername { - return Intl.message( - 'Username', - name: 'signupUsername', - desc: '', - args: [], - ); - } - - /// `Pick a unique username` - String get signupUsernamePlaceholder { - return Intl.message( - 'Pick a unique username', - name: 'signupUsernamePlaceholder', - desc: '', - args: [], - ); - } - - /// `Username must be at least {length} characters` - String signupUsernameValidation(Object length) { - return Intl.message( - 'Username must be at least $length characters', - name: 'signupUsernameValidation', - desc: '', - args: [length], - ); - } - - /// `Username must only contain letters, numbers, dashes and underscores` - String get signupUsernameValidationPattern { - return Intl.message( - 'Username must only contain letters, numbers, dashes and underscores', - name: 'signupUsernameValidationPattern', - desc: '', - args: [], - ); - } - - /// `Twitter` - String get socialTwitter { - return Intl.message( - 'Twitter', - name: 'socialTwitter', - desc: '', - args: [], - ); - } - - /// `Facebook` - String get socialFacebook { - return Intl.message( - 'Facebook', - name: 'socialFacebook', - desc: '', - args: [], - ); - } - - /// `Discord` - String get socialDiscord { - return Intl.message( - 'Discord', - name: 'socialDiscord', - desc: '', - args: [], - ); - } - - /// `GitHub` - String get socialGitHub { - return Intl.message( - 'GitHub', - name: 'socialGitHub', - desc: '', - args: [], - ); - } - - /// `Play Store` - String get socialGoogle { - return Intl.message( - 'Play Store', - name: 'socialGoogle', - desc: '', - args: [], - ); - } - - /// `App Store` - String get socialApple { - return Intl.message( - 'App Store', - name: 'socialApple', - desc: '', - args: [], - ); - } - - /// `Move down` - String get sortMoveDown { - return Intl.message( - 'Move down', - name: 'sortMoveDown', - desc: '', - args: [], - ); - } - - /// `Move up` - String get sortMoveUp { - return Intl.message( - 'Move up', - name: 'sortMoveUp', - desc: '', - args: [], - ); - } - - /// `Special Dice` - String get specialDice { - return Intl.message( - 'Special Dice', - name: 'specialDice', - desc: '', - args: [], - ); - } - - /// `{button, select, damage {Damage} other {{button}}}` - String specialRollButton(Object button) { - return Intl.select( - button, - { - 'damage': 'Damage', - 'other': '$button', - }, - name: 'specialRollButton', - desc: '', - args: [button], - ); - } - - /// `{level, select, cantrip {Cantrip} rote {Rote} other {Level {level}}}` - String spellLevel(Object level) { - return Intl.select( - level, - { - 'cantrip': 'Cantrip', - 'rote': 'Rote', - 'other': 'Level $level', - }, - name: 'spellLevel', - desc: '', - args: [level], - ); - } - - /// `Spells` - String get spells { - return Intl.message( - 'Spells', - name: 'spells', - desc: '', - args: [], - ); - } - - /// `{count, plural, =0 {No spells} one {One spell} other {{count} spells}}` - String spellsWithCount(num count) { - return Intl.plural( - count, - zero: 'No spells', - one: 'One spell', - other: '$count spells', - name: 'spellsWithCount', - desc: '', - args: [count], - ); - } - - /// `Copy from: {tag}` - String tagCopyFrom(Object tag) { - return Intl.message( - 'Copy from: $tag', - name: 'tagCopyFrom', - desc: '', - args: [tag], - ); - } - - /// `Tag Information` - String get tagDetails { - return Intl.message( - 'Tag Information', - name: 'tagDetails', - desc: '', - args: [], - ); - } - - /// `Switch to Dark Mode` - String get themeTurnDark { - return Intl.message( - 'Switch to Dark Mode', - name: 'themeTurnDark', - desc: '', - args: [], - ); - } - - /// `Switch to Light Mode` - String get themeTurnLight { - return Intl.message( - 'Switch to Light Mode', - name: 'themeTurnLight', - desc: '', - args: [], - ); - } - - /// `Unselect` - String get unselect { - return Intl.message( - 'Unselect', - name: 'unselect', - desc: '', - args: [], - ); - } - - /// `Use default` - String get useDefault { - return Intl.message( - 'Use default', - name: 'useDefault', - desc: '', - args: [], - ); - } - - /// `Sign in` - String get userLoginButton { - return Intl.message( - 'Sign in', - name: 'userLoginButton', - desc: '', - args: [], - ); - } - - /// `Sign out` - String get userLogoutButton { - return Intl.message( - 'Sign out', - name: 'userLogoutButton', - desc: '', - args: [], - ); - } - - /// `More` - String get userMenuMoreChars { - return Intl.message( - 'More', - name: 'userMenuMoreChars', - desc: '', - args: [], - ); - } - - /// `Recent Characters` - String get userMenuRecentCharacters { - return Intl.message( - 'Recent Characters', - name: 'userMenuRecentCharacters', - desc: '', - args: [], - ); - } - - /// `Not registered` - String get userUnregistered { - return Intl.message( - 'Not registered', - name: 'userUnregistered', - desc: '', - args: [], - ); - } - - /// `View` - String get view { - return Intl.message( - 'View', - name: 'view', - desc: '', - args: [], - ); - } - - /// `View {entity}` - String viewGeneric(Object entity) { - return Intl.message( - 'View $entity', - name: 'viewGeneric', - desc: '', - args: [entity], - ); - } - - /// `What's new?` - String get whatsNew { - return Intl.message( - 'What\'s new?', - name: 'whatsNew', - desc: '', - args: [], - ); - } - - /// `Update manually` - String get xpDialogChangeOverride { - return Intl.message( - 'Update manually', - name: 'xpDialogChangeOverride', - desc: '', - args: [], - ); - } - - /// `End Session` - String get xpDialogEndSession { - return Intl.message( - 'End Session', - name: 'xpDialogEndSession', - desc: '', - args: [], - ); - } - - /// `Changing the current XP or level manually will cause the pending XP to be discarded unless this is unchecked.` - String get xpDialogOverrideInfoText { - return Intl.message( - 'Changing the current XP or level manually will cause the pending XP to be discarded unless this is unchecked.', - name: 'xpDialogOverrideInfoText', - desc: '', - args: [], - ); - } - - /// `Override Level` - String get xpDialogOverrideLevel { - return Intl.message( - 'Override Level', - name: 'xpDialogOverrideLevel', - desc: '', - args: [], - ); - } - - /// `Override XP` - String get xpDialogOverrideXp { - return Intl.message( - 'Override XP', - name: 'xpDialogOverrideXp', - desc: '', - args: [], - ); - } - - /// `Reset bonds, flags & end of session questions after saving` - String get xpDialogResetSessionMarks { - return Intl.message( - 'Reset bonds, flags & end of session questions after saving', - name: 'xpDialogResetSessionMarks', - desc: '', - args: [], - ); - } - - /// `Mark Session XP` - String get xpDialogTitle { - return Intl.message( - 'Mark Session XP', - name: 'xpDialogTitle', - desc: '', - args: [], - ); - } - - /// `Update XP & Level` - String get xpDialogTitleOverriding { - return Intl.message( - 'Update XP & Level', - name: 'xpDialogTitleOverriding', - desc: '', - args: [], - ); - } -} - -class AppLocalizationDelegate extends LocalizationsDelegate { - const AppLocalizationDelegate(); - - List get supportedLocales { - return const [ - Locale.fromSubtags(languageCode: 'en'), - ]; - } - - @override - bool isSupported(Locale locale) => _isSupported(locale); - @override - Future load(Locale locale) => S.load(locale); - @override - bool shouldReload(AppLocalizationDelegate old) => false; - - bool _isSupported(Locale locale) { - for (var supportedLocale in supportedLocales) { - if (supportedLocale.languageCode == locale.languageCode) { - return true; - } - } - return false; - } -} diff --git a/lib/i18n.dart b/lib/i18n.dart new file mode 100644 index 00000000..b85cdccc --- /dev/null +++ b/lib/i18n.dart @@ -0,0 +1,4 @@ +import 'app/data/services/intl_service.dart'; +import 'i18n/messages.i18n.dart'; + +Messages get tr => IntlService.m; diff --git a/lib/i18n/messages.i18n.dart b/lib/i18n/messages.i18n.dart new file mode 100644 index 00000000..fd31ce76 --- /dev/null +++ b/lib/i18n/messages.i18n.dart @@ -0,0 +1,3020 @@ +// GENERATED FILE, do not edit! +// ignore_for_file: annotate_overrides, non_constant_identifier_names, prefer_single_quotes, unused_element, unused_field, unnecessary_string_interpolations +import 'package:i18n/i18n.dart' as i18n; + +String get _languageCode => 'en'; +String _plural( + int count, { + String? zero, + String? one, + String? two, + String? few, + String? many, + String? other, +}) => + i18n.plural( + count, + _languageCode, + zero: zero, + one: one, + two: two, + few: few, + many: many, + other: other, + ); +String _ordinal( + int count, { + String? zero, + String? one, + String? two, + String? few, + String? many, + String? other, +}) => + i18n.ordinal( + count, + _languageCode, + zero: zero, + one: one, + two: two, + few: few, + many: many, + other: other, + ); +String _cardinal( + int count, { + String? zero, + String? one, + String? two, + String? few, + String? many, + String? other, +}) => + i18n.cardinal( + count, + _languageCode, + zero: zero, + one: one, + two: two, + few: few, + many: many, + other: other, + ); +String _select( + String key, + Map cases, { + String? other, +}) => + i18n.select(key, cases, other: other); + +class Messages { + const Messages(); + String get locale => "en"; + String get languageCode => "en"; + + /// ```dart + /// """ + /// ${_select(type, { + /// 'Dice': 'Die', + /// 'CharacterClass': 'Class', + /// 'MoveCategory': 'Category', + /// 'GearSelection': 'Starting Gear', + /// 'AbilityScore': 'Ability Score', + /// 'AlignmentValue': 'Alignment' + /// })} + /// """ + /// ``` + String _entSingle(String type) => """${_select(type, { + 'Dice': 'Die', + 'CharacterClass': 'Class', + 'MoveCategory': 'Category', + 'GearSelection': 'Starting Gear', + 'AbilityScore': 'Ability Score', + 'AlignmentValue': 'Alignment' + })}"""; + + /// ```dart + /// """ + /// ${_select(type, { + /// 'MoveCategory': 'Categories', + /// 'CharacterClass': 'Classes', + /// }, other: '${_entSingle(type)}s')} + /// """ + /// ``` + String _entPlural(String type) => """${_select(type, { + 'MoveCategory': 'Categories', + 'CharacterClass': 'Classes', + }, other: '${_entSingle(type)}s')}"""; + + /// `${_entSingle(ent.toString())}` + String entity(Type ent) => """${_entSingle(ent.toString())}"""; + + /// `${_entPlural(ent.toString())}` + String entityPlural(Type ent) => """${_entPlural(ent.toString())}"""; + + /// `${cnt == 1 ? _entSingle(ent.toString()) : _entPlural(ent.toString())}` + String entityCount(Type ent, int cnt) => + """${cnt == 1 ? _entSingle(ent.toString()) : _entPlural(ent.toString())}"""; + + /// `$cnt ${entityCount(ent, cnt)}` + String entityCountNum(Type ent, int cnt) => + """$cnt ${entityCount(ent, cnt)}"""; + AppMessages get app => AppMessages(this); + GenericMessages get generic => GenericMessages(this); + LoadingMessages get loading => LoadingMessages(this); + ErrorsMessages get errors => ErrorsMessages(this); + SortMessages get sort => SortMessages(this); + PlaybookMessages get playbook => PlaybookMessages(this); + MyLibraryMessages get myLibrary => MyLibraryMessages(this); + NavMessages get nav => NavMessages(this); + SyncMessages get sync => SyncMessages(this); + SettingsMessages get settings => SettingsMessages(this); + UserMessages get user => UserMessages(this); + AuthMessages get auth => AuthMessages(this); + HomeMessages get home => HomeMessages(this); + AboutMessages get about => AboutMessages(this); + CharacterMessages get character => CharacterMessages(this); + CharacterClassMessages get characterClass => CharacterClassMessages(this); + DiceMessages get dice => DiceMessages(this); + BasicInfoMessages get basicInfo => BasicInfoMessages(this); + DebilitiesMessages get debilities => DebilitiesMessages(this); + TagsMessages get tags => TagsMessages(this); + DialogsMessages get dialogs => DialogsMessages(this); + MovesMessages get moves => MovesMessages(this); + SpellsMessages get spells => SpellsMessages(this); + ItemsMessages get items => ItemsMessages(this); + NotesMessages get notes => NotesMessages(this); + AlignmentMessages get alignment => AlignmentMessages(this); + BioMessages get bio => BioMessages(this); + SearchMessages get search => SearchMessages(this); + HpMessages get hp => HpMessages(this); + XpMessages get xp => XpMessages(this); + ArmorMessages get armor => ArmorMessages(this); + RichTextMessages get richText => RichTextMessages(this); + CustomRollsMessages get customRolls => CustomRollsMessages(this); + SessionMarksMessages get sessionMarks => SessionMarksMessages(this); + CreateCharacterMessages get createCharacter => CreateCharacterMessages(this); + AccountMessages get account => AccountMessages(this); + ActionsMessages get actions => ActionsMessages(this); + AbilityScoresMessages get abilityScores => AbilityScoresMessages(this); + FeedbackMessages get feedback => FeedbackMessages(this); + MigrationMessages get migration => MigrationMessages(this); + BackupMessages get backup => BackupMessages(this); +} + +class AppMessages { + final Messages _parent; + const AppMessages(this._parent); + + /// `Dungeon Paper` + String get name => """Dungeon Paper"""; +} + +class GenericMessages { + final Messages _parent; + const GenericMessages(this._parent); + + /// `Save` + String get save => """Save"""; + + /// `Save $ent` + String saveEntity(String ent) => """Save $ent"""; + + /// `Cancel` + String get cancel => """Cancel"""; + + /// `Close` + String get close => """Close"""; + + /// `Done` + String get done => """Done"""; + + /// `View` + String get view => """View"""; + + /// `Continue` + String get continue_ => """Continue"""; + + /// `View $ent` + String viewEntity(String ent) => """View $ent"""; + + /// `All` + String get all => """All"""; + + /// `All $ent` + String allEntities(String ent) => """All $ent"""; + + /// `Create` + String get create => """Create"""; + + /// `Create $ent` + String createEntity(String ent) => """Create $ent"""; + + /// `Add` + String get add => """Add"""; + + /// `Add $ent` + String addEntity(String ent) => """Add $ent"""; + + /// `Remove` + String get remove => """Remove"""; + + /// `Remove $ent` + String removeEntity(String ent) => """Remove $ent"""; + + /// `Unselect` + String get unselect => """Unselect"""; + + /// `Unselect $ent` + String unselectEntity(String ent) => """Unselect $ent"""; + + /// `Delete` + String get delete => """Delete"""; + + /// `Delete $ent` + String deleteEntity(String ent) => """Delete $ent"""; + + /// `Edit` + String get edit => """Edit"""; + + /// `Edit $ent` + String editEntity(String ent) => """Edit $ent"""; + + /// `Yes` + String get yes => """Yes"""; + + /// `No` + String get no => """No"""; + + /// `No $ent` + String noEntity(String ent) => """No $ent"""; + + /// `Select` + String get select => """Select"""; + + /// `Select $ent` + String selectEntity(String ent) => """Select $ent"""; + + /// `Selected` + String get selected => """Selected"""; + + /// `Select All` + String get selectAll => """Select All"""; + + /// `Select None` + String get selectNone => """Select None"""; + + /// `My` + String get my => """My"""; + + /// `My $ent` + String myEntity(String ent) => """My $ent"""; + + /// `Change` + String get change => """Change"""; + + /// `Change $ent` + String changeEntity(String ent) => """Change $ent"""; + + /// `See All` + String get seeAll => """See All"""; + + /// `Select $ent to add` + String selectToAdd(String ent) => """Select $ent to add"""; + + /// `Name` + String get name => """Name"""; + + /// `$ent name` + String entityName(String ent) => """$ent name"""; + + /// `Value` + String get value => """Value"""; + + /// `$ent value` + String entityValue(String ent) => """$ent value"""; + + /// `Description` + String get description => """Description"""; + + /// `$ent description` + String entityDescription(String ent) => """$ent description"""; + + /// `Explanation` + String get explanation => """Explanation"""; + + /// `$ent explanation` + String entityExplanation(String ent) => """$ent explanation"""; + + /// `‹No description provided›` + String get noDescription => """‹No description provided›"""; + + /// `No $ent selected` + String noEntitySelected(String ent) => """No $ent selected"""; + + /// `No $ent selected (required)` + String noEntitySelectedRequired(String ent) => + """No $ent selected (required)"""; + + /// `Use Default` + String get useDefault => """Use Default"""; +} + +class LoadingMessages { + final Messages _parent; + const LoadingMessages(this._parent); + + /// `Signing in...` + String get user => """Signing in..."""; + + /// `Getting characters...` + String get characters => """Getting characters..."""; + + /// `Loading...` + String get general => """Loading..."""; +} + +class ErrorsMessages { + final Messages _parent; + const ErrorsMessages(this._parent); + + /// `Operation canceled` + String get userOperationCanceled => """Operation canceled"""; + + /// `Error while uploading photo. Try again later, or contact support using the "About" page.` + String get uploadError => + """Error while uploading photo. Try again later, or contact support using the "About" page."""; + + /// `Invalid email address` + String get invalidEmail => """Invalid email address"""; + InvalidPasswordErrorsMessages get invalidPassword => + InvalidPasswordErrorsMessages(this); + + /// `Must be at least $cnt ${_plural(cnt, one: 'character', many: 'characters')}` + String minLength(int cnt) => + """Must be at least $cnt ${_plural(cnt, one: 'character', many: 'characters')}"""; + + /// `Must be no more than $cnt ${_plural(cnt, one: 'character', many: 'characters')}` + String maxLength(int cnt) => + """Must be no more than $cnt ${_plural(cnt, one: 'character', many: 'characters')}"""; + + /// `Must be exactly $cnt ${_plural(cnt, one: 'character', many: 'characters')}` + String exactLength(int cnt) => + """Must be exactly $cnt ${_plural(cnt, one: 'character', many: 'characters')}"""; + + /// `Must contain $pattern` + String mustContain(String pattern) => """Must contain $pattern"""; + + /// `Must not contain $pattern` + String mustNotContain(String pattern) => """Must not contain $pattern"""; + + /// `Must contain letters only` + String get onlyLetters => """Must contain letters only"""; +} + +class InvalidPasswordErrorsMessages { + final ErrorsMessages _parent; + const InvalidPasswordErrorsMessages(this._parent); + + /// `Password must contain at least one capital letter` + String get letter => """Password must contain at least one capital letter"""; + + /// `Password must contain at least one number` + String get number => """Password must contain at least one number"""; +} + +class SortMessages { + final Messages _parent; + const SortMessages(this._parent); + + /// `Move up` + String get moveUp => """Move up"""; + + /// `Move down` + String get moveDown => """Move down"""; + + /// `Move $ent to top` + String moveEntityToTop(String ent) => """Move $ent to top"""; + + /// `Move $ent to bottom` + String moveEntityToBottom(String ent) => """Move $ent to bottom"""; +} + +class PlaybookMessages { + final Messages _parent; + const PlaybookMessages(this._parent); + + /// `Playbook` + String get title => """Playbook"""; + + /// `My Library` + String get myLibrary => """My Library"""; + + /// `My Campaigns` + String get myCampaigns => """My Campaigns"""; +} + +class MyLibraryMessages { + final Messages _parent; + const MyLibraryMessages(this._parent); + + /// `My Library` + String get title => """My Library"""; + + /// `Reload Library` + String get reload => """Reload Library"""; + + /// `$cnt in $type` + String itemCount(String cnt, String type) => """$cnt in $type"""; + + /// ```dart + /// """ + /// ${_select(type, { + /// 'builtIn': 'Playbook', + /// 'my': 'My Library' + /// })} + /// """ + /// ``` + String libraryType(String type) => + """${_select(type, {'builtIn': 'Playbook', 'my': 'My Library'})}"""; + + /// `Already added` + String get alreadyAdded => """Already added"""; + ItemTabMyLibraryMessages get itemTab => ItemTabMyLibraryMessages(this); + EmptyStateMyLibraryMessages get emptyState => + EmptyStateMyLibraryMessages(this); + FiltersMyLibraryMessages get filters => FiltersMyLibraryMessages(this); +} + +class ItemTabMyLibraryMessages { + final MyLibraryMessages _parent; + const ItemTabMyLibraryMessages(this._parent); + + /// `Playbook` + String get playbook => """Playbook"""; + + /// `Online` + String get online => """Online"""; +} + +class EmptyStateMyLibraryMessages { + final MyLibraryMessages _parent; + const EmptyStateMyLibraryMessages(this._parent); + + /// `No $ent found` + String title(String ent) => """No $ent found"""; + SubtitleEmptyStateMyLibraryMessages get subtitle => + SubtitleEmptyStateMyLibraryMessages(this); +} + +class SubtitleEmptyStateMyLibraryMessages { + final EmptyStateMyLibraryMessages _parent; + const SubtitleEmptyStateMyLibraryMessages(this._parent); + + /// `No $ent found in this list.` + String filters(String ent) => """No $ent found in this list."""; + + /// `Try changing the search or filters to find more $ent.` + String noFilters(String ent) => + """Try changing the search or filters to find more $ent."""; +} + +class FiltersMyLibraryMessages { + final MyLibraryMessages _parent; + const FiltersMyLibraryMessages(this._parent); + + /// `Clear Filters` + String get clear => """Clear Filters"""; +} + +class NavMessages { + final Messages _parent; + const NavMessages(this._parent); + + /// `Use` + String get actions => """Use"""; + + /// `Character` + String get character => """Character"""; + + /// `Journal` + String get journal => """Journal"""; +} + +class SyncMessages { + final Messages _parent; + const SyncMessages(this._parent); + EntitySyncMessages get entity => EntitySyncMessages(this); +} + +class EntitySyncMessages { + final SyncMessages _parent; + const EntitySyncMessages(this._parent); + StatusEntitySyncMessages get status => StatusEntitySyncMessages(this); +} + +class StatusEntitySyncMessages { + final EntitySyncMessages _parent; + const StatusEntitySyncMessages(this._parent); + + /// `This $ent is In Sync with its linked library item` + String inSync(String ent) => + """This $ent is In Sync with its linked library item"""; + + /// `This $ent is Out of Sync with its linked library item` + String outOfSync(String ent) => + """This $ent is Out of Sync with its linked library item"""; + + /// `This $ent is not linked to any library item` + String detached(String ent) => + """This $ent is not linked to any library item"""; +} + +class SettingsMessages { + final Messages _parent; + const SettingsMessages(this._parent); + + /// `Settings` + String get title => """Settings"""; + + /// `Export/Import` + String get importExport => """Export/Import"""; + + /// `Switch to ${mode} Mode` + String _switchMode(String mode) => """Switch to ${mode} Mode"""; + + /// `${_switchMode('Dark')}` + String get switchToDark => """${_switchMode('Dark')}"""; + + /// `${_switchMode('Light')}` + String get switchToLight => """${_switchMode('Light')}"""; + CategoriesSettingsMessages get categories => CategoriesSettingsMessages(this); + + /// `Keep screen awake while using the app` + String get keepAwake => """Keep screen awake while using the app"""; + DefaultThemeSettingsMessages get defaultTheme => + DefaultThemeSettingsMessages(this); +} + +class CategoriesSettingsMessages { + final SettingsMessages _parent; + const CategoriesSettingsMessages(this._parent); + + /// `General` + String get general => """General"""; +} + +class DefaultThemeSettingsMessages { + final SettingsMessages _parent; + const DefaultThemeSettingsMessages(this._parent); + + /// `Default $type theme` + String _p(String type) => """Default $type theme"""; + + /// `${_p('light')}` + String get light => """${_p('light')}"""; + + /// `${_p('dark')}` + String get dark => """${_p('dark')}"""; +} + +class UserMessages { + final Messages _parent; + const UserMessages(this._parent); + + /// `Recent Characters` + String get recentCharacters => """Recent Characters"""; +} + +class AuthMessages { + final Messages _parent; + const AuthMessages(this._parent); + + /// `OR` + String get orSeparator => """OR"""; + + /// `Privacy Policy` + String get privacyPolicy => """Privacy Policy"""; + + /// `What's new?` + String get changelog => """What's new?"""; + ProvidersAuthMessages get providers => ProvidersAuthMessages(this); + ConfirmUnlinkAuthMessages get confirmUnlink => + ConfirmUnlinkAuthMessages(this); + LoginAuthMessages get login => LoginAuthMessages(this); + LogoutAuthMessages get logout => LogoutAuthMessages(this); + SignupAuthMessages get signup => SignupAuthMessages(this); +} + +class ProvidersAuthMessages { + final AuthMessages _parent; + const ProvidersAuthMessages(this._parent); + + /// `Sign in with $provider` + String loginWith(String provider) => """Sign in with $provider"""; + + /// `Sign up with $provider` + String signupWith(String provider) => """Sign up with $provider"""; + + /// `This device only supports unlinking $provider accounts.` + String unusable(String provider) => + """This device only supports unlinking $provider accounts."""; + + /// ```dart + /// """ + /// ${_select(provider, { + /// 'facebook': 'Facebook', + /// 'google': 'Google', + /// 'apple': 'Apple', + /// 'password': 'Dungeon Paper', + /// }, other: 'Other')} + /// """ + /// ``` + String name(String provider) => """${_select(provider, { + 'facebook': 'Facebook', + 'google': 'Google', + 'apple': 'Apple', + 'password': 'Dungeon Paper', + }, other: 'Other')}"""; + + /// `Unlink` + String get unlink => """Unlink"""; + + /// `Link` + String get link => """Link"""; +} + +class ConfirmUnlinkAuthMessages { + final AuthMessages _parent; + const ConfirmUnlinkAuthMessages(this._parent); + + /// `Unlink from $ent` + String title(String ent) => """Unlink from $ent"""; + + /// `Are you sure you want to unlink your account from $ent?\nBy clicking "Unlink", you will no longer be able to sign in with $ent.\n\nYou will be able to re-link your account at any time by going to your account settings.` + String body(String ent) => + """Are you sure you want to unlink your account from $ent?\nBy clicking "Unlink", you will no longer be able to sign in with $ent.\n\nYou will be able to re-link your account at any time by going to your account settings."""; +} + +class LoginAuthMessages { + final AuthMessages _parent; + const LoginAuthMessages(this._parent); + + /// `Sign In` + String get title => """Sign In"""; + + /// `Sign in to your account to sync your data online, and get access to many more features.` + String get subtitle => + """Sign in to your account to sync your data online, and get access to many more features."""; + + /// `Sign in` + String get button => """Sign in"""; + NoAccountLoginAuthMessages get noAccount => NoAccountLoginAuthMessages(this); +} + +class NoAccountLoginAuthMessages { + final LoginAuthMessages _parent; + const NoAccountLoginAuthMessages(this._parent); + + /// `Don't have an account?` + String get label => """Don't have an account?"""; + + /// `Sign up` + String get button => """Sign up"""; +} + +class LogoutAuthMessages { + final AuthMessages _parent; + const LogoutAuthMessages(this._parent); + + /// `Sign out` + String get button => """Sign out"""; +} + +class SignupAuthMessages { + final AuthMessages _parent; + const SignupAuthMessages(this._parent); + + /// `Sign Up` + String get title => """Sign Up"""; + + /// `Enter the required details below to create your Dungeon Paper account.` + String get subtitle => + """Enter the required details below to create your Dungeon Paper account."""; + + /// `Sign up` + String get button => """Sign up"""; + NotLoggedInSignupAuthMessages get notLoggedIn => + NotLoggedInSignupAuthMessages(this); + EmailSignupAuthMessages get email => EmailSignupAuthMessages(this); + PasswordSignupAuthMessages get password => PasswordSignupAuthMessages(this); +} + +class NotLoggedInSignupAuthMessages { + final SignupAuthMessages _parent; + const NotLoggedInSignupAuthMessages(this._parent); + + /// `Not logged in` + String get label => """Not logged in"""; +} + +class EmailSignupAuthMessages { + final SignupAuthMessages _parent; + const EmailSignupAuthMessages(this._parent); + + /// `Email` + String get label => """Email"""; + + /// `Enter your email` + String get placeholder => """Enter your email"""; + + /// `Please enter a valid email address` + String get error => """Please enter a valid email address"""; +} + +class PasswordSignupAuthMessages { + final SignupAuthMessages _parent; + const PasswordSignupAuthMessages(this._parent); + + /// `Password` + String get label => """Password"""; + + /// `Enter a password` + String get placeholder => """Enter a password"""; + ConfirmPasswordSignupAuthMessages get confirm => + ConfirmPasswordSignupAuthMessages(this); +} + +class ConfirmPasswordSignupAuthMessages { + final PasswordSignupAuthMessages _parent; + const ConfirmPasswordSignupAuthMessages(this._parent); + + /// `Confirm Password` + String get label => """Confirm Password"""; + + /// `Enter the same password again` + String get placeholder => """Enter the same password again"""; + + /// `Passwords do not match` + String get error => """Passwords do not match"""; +} + +class HomeMessages { + final Messages _parent; + const HomeMessages(this._parent); + BarsHomeMessages get bars => BarsHomeMessages(this); + CategoriesHomeMessages get categories => CategoriesHomeMessages(this); + SummaryHomeMessages get summary => SummaryHomeMessages(this); + MenuHomeMessages get menu => MenuHomeMessages(this); + EmptyStateHomeMessages get emptyState => EmptyStateHomeMessages(this); +} + +class BarsHomeMessages { + final HomeMessages _parent; + const BarsHomeMessages(this._parent); + + /// `XP` + String get xp => """XP"""; + + /// `HP` + String get hp => """HP"""; +} + +class CategoriesHomeMessages { + final HomeMessages _parent; + const CategoriesHomeMessages(this._parent); + + /// `Bookmarked Notes` + String get notes => """Bookmarked Notes"""; + + /// `Favorite Moves` + String get moves => """Favorite Moves"""; + + /// `Prepared Spells` + String get spells => """Prepared Spells"""; + + /// `Equipped Items` + String get items => """Equipped Items"""; +} + +class SummaryHomeMessages { + final HomeMessages _parent; + const SummaryHomeMessages(this._parent); + LoadSummaryHomeMessages get load => LoadSummaryHomeMessages(this); + CoinsSummaryHomeMessages get coins => CoinsSummaryHomeMessages(this); +} + +class LoadSummaryHomeMessages { + final SummaryHomeMessages _parent; + const LoadSummaryHomeMessages(this._parent); + + /// `Load: $cur/$max` + String label(int cur, int max) => """Load: $cur/$max"""; + + /// `Max Load` + String get tooltip => """Max Load"""; +} + +class CoinsSummaryHomeMessages { + final SummaryHomeMessages _parent; + const CoinsSummaryHomeMessages(this._parent); + + /// `$amt G` + String label(String amt) => """$amt G"""; + + /// `Coins` + String get tooltip => """Coins"""; +} + +class MenuHomeMessages { + final HomeMessages _parent; + const MenuHomeMessages(this._parent); + CharacterMenuHomeMessages get character => CharacterMenuHomeMessages(this); + + /// `Character Biography` + String get bio => """Character Biography"""; + + /// `Debilities` + String get debilities => """Debilities"""; +} + +class CharacterMenuHomeMessages { + final MenuHomeMessages _parent; + const CharacterMenuHomeMessages(this._parent); + + /// `Character Menu` + String get tooltip => """Character Menu"""; + + /// `Basic Information` + String get basicInfo => """Basic Information"""; + + /// `Ability Scores` + String get abilityScores => """Ability Scores"""; + + /// `Quick-Roll Buttons` + String get customRolls => """Quick-Roll Buttons"""; + + /// `Character Theme` + String get theme => """Character Theme"""; +} + +class EmptyStateHomeMessages { + final HomeMessages _parent; + const EmptyStateHomeMessages(this._parent); + GuestEmptyStateHomeMessages get guest => GuestEmptyStateHomeMessages(this); + + /// `No Characters` + String get title => """No Characters"""; + + /// `Create a Character to get started` + String get subtitle => """Create a Character to get started"""; +} + +class GuestEmptyStateHomeMessages { + final EmptyStateHomeMessages _parent; + const GuestEmptyStateHomeMessages(this._parent); + + /// `Sign in to get more features` + String get title => """Sign in to get more features"""; + + /// `Online data sync, library sharing, campaigns and more!` + String get subtitle => + """Online data sync, library sharing, campaigns and more!"""; +} + +class AboutMessages { + final Messages _parent; + const AboutMessages(this._parent); + + /// `About` + String get title => """About"""; + + /// `Version $version` + String version(String version) => """Version $version"""; + + /// `Copyright © 2018-$year` + String copyright(int year) => """Copyright © 2018-$year"""; + + /// `Chen Asraf` + String get author => """Chen Asraf"""; + DiscordAboutMessages get discord => DiscordAboutMessages(this); + FeedbackAboutMessages get feedback => FeedbackAboutMessages(this); + SocialsAboutMessages get socials => SocialsAboutMessages(this); + + /// `Special Thanks` + String get specialThanks => """Special Thanks"""; + + /// `Contributors` + String get contributors => """Contributors"""; + + /// `Icon Credits` + String get icons => """Icon Credits"""; +} + +class DiscordAboutMessages { + final AboutMessages _parent; + const DiscordAboutMessages(this._parent); + + /// `Join Our Discord` + String get title => """Join Our Discord"""; + + /// `Join the Discord community to ask questions, get help, send feedback, or just chat with other players.` + String get subtitle => + """Join the Discord community to ask questions, get help, send feedback, or just chat with other players."""; +} + +class FeedbackAboutMessages { + final AboutMessages _parent; + const FeedbackAboutMessages(this._parent); + + /// `Send Feedback` + String get title => """Send Feedback"""; + + /// `We reply more promptly through Discord, but you can send us feedback, bug reports or suggestions about the app directly here as an alternative.` + String get subtitle => + """We reply more promptly through Discord, but you can send us feedback, bug reports or suggestions about the app directly here as an alternative."""; +} + +class SocialsAboutMessages { + final AboutMessages _parent; + const SocialsAboutMessages(this._parent); + + /// `Links` + String get title => """Links"""; + + /// `Twitter` + String get twitter => """Twitter"""; + + /// `Facebook` + String get facebook => """Facebook"""; + + /// `Discord` + String get discord => """Discord"""; + + /// `GitHub` + String get github => """GitHub"""; + + /// `Play Store` + String get google => """Play Store"""; + + /// `App Store` + String get apple => """App Store"""; +} + +class CharacterMessages { + final Messages _parent; + const CharacterMessages(this._parent); + DataCharacterMessages get data => DataCharacterMessages(this); + HeaderCharacterMessages get header => HeaderCharacterMessages(this); + + /// `No Category` + String get noCategory => """No Category"""; + ThemeCharacterMessages get theme => ThemeCharacterMessages(this); +} + +class DataCharacterMessages { + final CharacterMessages _parent; + const DataCharacterMessages(this._parent); + + /// `Coins` + String get coins => """Coins"""; + LoadDataCharacterMessages get load => LoadDataCharacterMessages(this); + + /// `Level` + String get level => """Level"""; + + /// `Damage Dice` + String get damageDice => """Damage Dice"""; + + /// `Use damage dice from class & equipped items` + String get calculateDamage => + """Use damage dice from class & equipped items"""; +} + +class LoadDataCharacterMessages { + final DataCharacterMessages _parent; + const LoadDataCharacterMessages(this._parent); + + /// `Load` + String get load => """Load"""; + + /// `Max Load` + String get maxLoad => """Max Load"""; + + /// `Use class base load + STR mod` + String get autoMaxLoad => """Use class base load + STR mod"""; +} + +class HeaderCharacterMessages { + final CharacterMessages _parent; + const HeaderCharacterMessages(this._parent); + + /// `Level $lv` + String level(int lv) => """Level $lv"""; + + /// `$name` + String characterClass(String name) => """$name"""; + + /// `$name` + String race(String name) => """$name"""; + + /// `$alignment` + String alignment(String alignment) => """$alignment"""; + + /// ` ∙ ` + String get separator => """ ∙ """; +} + +class ThemeCharacterMessages { + final CharacterMessages _parent; + const ThemeCharacterMessages(this._parent); + + /// `Character Theme` + String get title => """Character Theme"""; + + /// `Default $type theme` + String _defaultTheme(String type) => """Default $type theme"""; + + /// `${_defaultTheme('light')}` + String get defaultLight => """${_defaultTheme('light')}"""; + + /// `${_defaultTheme('dark')}` + String get defaultDark => """${_defaultTheme('dark')}"""; +} + +class CharacterClassMessages { + final Messages _parent; + const CharacterClassMessages(this._parent); + + /// `Base Load` + String get baseLoad => """Base Load"""; + + /// `Base HP` + String get baseHp => """Base HP"""; + + /// `Damage Dice` + String get damageDice => """Damage Dice"""; +} + +class DiceMessages { + final Messages _parent; + const DiceMessages(this._parent); + + /// `Suggested: $dice` + String suggestion(String dice) => """Suggested: $dice"""; + FormDiceMessages get form => FormDiceMessages(this); + RollDiceMessages get roll => RollDiceMessages(this); +} + +class FormDiceMessages { + final DiceMessages _parent; + const FormDiceMessages(this._parent); + + /// `Amount` + String get amount => """Amount"""; + + /// `Sides` + String get sides => """Sides"""; + + /// `d` + String get diceSeparator => """d"""; + ModifierTypeFormDiceMessages get modifierType => + ModifierTypeFormDiceMessages(this); + ValueFormDiceMessages get value => ValueFormDiceMessages(this); + ModifierFormDiceMessages get modifier => ModifierFormDiceMessages(this); + + /// `$name ($key)` + String statValue(String name, String key) => """$name ($key)"""; +} + +class ModifierTypeFormDiceMessages { + final FormDiceMessages _parent; + const ModifierTypeFormDiceMessages(this._parent); + + /// `Fixed Value` + String get fixed => """Fixed Value"""; + + /// `Stat Mod.` + String get modifier => """Stat Mod."""; +} + +class ValueFormDiceMessages { + final FormDiceMessages _parent; + const ValueFormDiceMessages(this._parent); + + /// `Number, e.g. 2 or -1` + String get placeholder => """Number, e.g. 2 or -1"""; + + /// `Modifier value` + String get label => """Modifier value"""; +} + +class ModifierFormDiceMessages { + final FormDiceMessages _parent; + const ModifierFormDiceMessages(this._parent); + + /// `Select stat` + String get placeholder => """Select stat"""; + + /// `Stat` + String get label => """Stat"""; +} + +class RollDiceMessages { + final DiceMessages _parent; + const RollDiceMessages(this._parent); + TitleRollDiceMessages get title => TitleRollDiceMessages(this); + + /// `Roll` + String get action => """Roll"""; + + /// `Total $amt` + String total(int amt) => """Total $amt"""; + + /// `Dice: $dice | Modifier: $mod` + String resultBreakdown(String dice, String mod) => + """Dice: $dice | Modifier: $mod"""; +} + +class TitleRollDiceMessages { + final RollDiceMessages _parent; + const TitleRollDiceMessages(this._parent); + + /// `Rolled $total` + String rolled(int total) => """Rolled $total"""; + + /// `Rolling $amt ${_plural(amt, one: 'die', many: 'dice')}` + String rolling(int amt) => + """Rolling $amt ${_plural(amt, one: 'die', many: 'dice')}"""; +} + +class BasicInfoMessages { + final Messages _parent; + const BasicInfoMessages(this._parent); + + /// `Basic Information` + String get title => """Basic Information"""; + FormBasicInfoMessages get form => FormBasicInfoMessages(this); +} + +class FormBasicInfoMessages { + final BasicInfoMessages _parent; + const FormBasicInfoMessages(this._parent); + NameFormBasicInfoMessages get name => NameFormBasicInfoMessages(this); + PhotoFormBasicInfoMessages get photo => PhotoFormBasicInfoMessages(this); +} + +class NameFormBasicInfoMessages { + final FormBasicInfoMessages _parent; + const NameFormBasicInfoMessages(this._parent); + + /// `Character Name` + String get label => """Character Name"""; + + /// `Enter your character's name` + String get placeholder => """Enter your character's name"""; + RandomNameFormBasicInfoMessages get random => + RandomNameFormBasicInfoMessages(this); +} + +class RandomNameFormBasicInfoMessages { + final NameFormBasicInfoMessages _parent; + const RandomNameFormBasicInfoMessages(this._parent); + TooltipRandomNameFormBasicInfoMessages get tooltip => + TooltipRandomNameFormBasicInfoMessages(this); +} + +class TooltipRandomNameFormBasicInfoMessages { + final RandomNameFormBasicInfoMessages _parent; + const TooltipRandomNameFormBasicInfoMessages(this._parent); + + /// `$act to generate a random name` + String _p(String act) => """$act to generate a random name"""; + + /// `${_p('Tap')}` + String get touch => """${_p('Tap')}"""; + + /// `${_p('Click')}` + String get click => """${_p('Click')}"""; +} + +class PhotoFormBasicInfoMessages { + final FormBasicInfoMessages _parent; + const PhotoFormBasicInfoMessages(this._parent); + + /// `Change Photo...` + String get change => """Change Photo..."""; + + /// `Remove Photo` + String get remove => """Remove Photo"""; + + /// `Choose Photo...` + String get choose => """Choose Photo..."""; + GuestPhotoFormBasicInfoMessages get guest => + GuestPhotoFormBasicInfoMessages(this); + + /// `UPLOADING...` + String get uploading => """UPLOADING..."""; + + /// `OR` + String get orSeparator => """OR"""; + UrlPhotoFormBasicInfoMessages get url => UrlPhotoFormBasicInfoMessages(this); +} + +class GuestPhotoFormBasicInfoMessages { + final PhotoFormBasicInfoMessages _parent; + const GuestPhotoFormBasicInfoMessages(this._parent); + + /// `You need to be signed in to upload images. ` + String get prefix => """You need to be signed in to upload images. """; + + /// `Sign in or create an account` + String get label => """Sign in or create an account"""; + + /// `, or upload using your own URL below.` + String get suffix => """, or upload using your own URL below."""; +} + +class UrlPhotoFormBasicInfoMessages { + final PhotoFormBasicInfoMessages _parent; + const UrlPhotoFormBasicInfoMessages(this._parent); + + /// `Image URL` + String get label => """Image URL"""; + + /// `Paste an image URL` + String get placeholder => """Paste an image URL"""; +} + +class DebilitiesMessages { + final Messages _parent; + const DebilitiesMessages(this._parent); + + /// `$name ($key)` + String label(String name, String key) => """$name ($key)"""; + DialogDebilitiesMessages get dialog => DialogDebilitiesMessages(this); +} + +class DialogDebilitiesMessages { + final DebilitiesMessages _parent; + const DialogDebilitiesMessages(this._parent); + + /// `Debilities` + String get title => """Debilities"""; + + /// `Debilities are temporary, negative conditions or states in which your character is in. When a stat is debilitated, it causes its modifier to be reduced by 1 until recovered.` + String get info => + """Debilities are temporary, negative conditions or states in which your character is in. When a stat is debilitated, it causes its modifier to be reduced by 1 until recovered."""; +} + +class TagsMessages { + final Messages _parent; + const TagsMessages(this._parent); + + /// `Copy from: $name` + String copyFrom(String name) => """Copy from: $name"""; + DialogTagsMessages get dialog => DialogTagsMessages(this); +} + +class DialogTagsMessages { + final TagsMessages _parent; + const DialogTagsMessages(this._parent); + + /// `Tag Information` + String get title => """Tag Information"""; +} + +class DialogsMessages { + final Messages _parent; + const DialogsMessages(this._parent); + ConfirmationsDialogsMessages get confirmations => + ConfirmationsDialogsMessages(this); +} + +class ConfirmationsDialogsMessages { + final DialogsMessages _parent; + const ConfirmationsDialogsMessages(this._parent); + DeleteConfirmationsDialogsMessages get delete => + DeleteConfirmationsDialogsMessages(this); + ExitConfirmationsDialogsMessages get exit => + ExitConfirmationsDialogsMessages(this); + DeleteAccountConfirmationsDialogsMessages get deleteAccount => + DeleteAccountConfirmationsDialogsMessages(this); +} + +class DeleteConfirmationsDialogsMessages { + final ConfirmationsDialogsMessages _parent; + const DeleteConfirmationsDialogsMessages(this._parent); + + /// `Delete $ent?` + String title(String ent) => """Delete $ent?"""; + + /// `Are you sure you want to remove the $ent "$name" from the list?` + String body(String ent, String name) => + """Are you sure you want to remove the $ent "$name" from the list?"""; +} + +class ExitConfirmationsDialogsMessages { + final ConfirmationsDialogsMessages _parent; + const ExitConfirmationsDialogsMessages(this._parent); + + /// `Are you sure?` + String get title => """Are you sure?"""; + + /// `Going back will lose any unsaved changes.\nAre you sure you want to go back?` + String get body => + """Going back will lose any unsaved changes.\nAre you sure you want to go back?"""; + + /// `Exit & Discard` + String get ok => """Exit & Discard"""; + + /// `Continue editing` + String get cancel => """Continue editing"""; +} + +class DeleteAccountConfirmationsDialogsMessages { + final ConfirmationsDialogsMessages _parent; + const DeleteAccountConfirmationsDialogsMessages(this._parent); + Step1DeleteAccountConfirmationsDialogsMessages get step1 => + Step1DeleteAccountConfirmationsDialogsMessages(this); + Step2DeleteAccountConfirmationsDialogsMessages get step2 => + Step2DeleteAccountConfirmationsDialogsMessages(this); +} + +class Step1DeleteAccountConfirmationsDialogsMessages { + final DeleteAccountConfirmationsDialogsMessages _parent; + const Step1DeleteAccountConfirmationsDialogsMessages(this._parent); + + /// `Delete Your Account?` + String get title => """Delete Your Account?"""; + + /// `Are you sure you want to delete your account?\n\nThis action cannot be undone.` + String get body => + """Are you sure you want to delete your account?\n\nThis action cannot be undone."""; +} + +class Step2DeleteAccountConfirmationsDialogsMessages { + final DeleteAccountConfirmationsDialogsMessages _parent; + const Step2DeleteAccountConfirmationsDialogsMessages(this._parent); + + /// `Are you really sure?` + String get title => """Are you really sure?"""; + + /// `We do not save any data for deleted accounts. All your data will be permanently deleted.\n\nAre you sure you want to delete your account?\n\nPlease confirm this one last time.` + String get body => + """We do not save any data for deleted accounts. All your data will be permanently deleted.\n\nAre you sure you want to delete your account?\n\nPlease confirm this one last time."""; +} + +class MovesMessages { + final Messages _parent; + const MovesMessages(this._parent); + CategoryMovesMessages get category => CategoryMovesMessages(this); +} + +class CategoryMovesMessages { + final MovesMessages _parent; + const CategoryMovesMessages(this._parent); + + /// ```dart + /// """ + /// ${_select(cat, { + /// 'starting': 'Starting', + /// 'basic': 'Basic', + /// 'special': 'Special', + /// 'advanced1': 'Advanced', + /// 'advanced2': 'Advanced', + /// }, other: 'Other')} + /// """ + /// ``` + String shortName(String cat) => """${_select(cat, { + 'starting': 'Starting', + 'basic': 'Basic', + 'special': 'Special', + 'advanced1': 'Advanced', + 'advanced2': 'Advanced', + }, other: 'Other')}"""; + + /// ```dart + /// """ + /// ${_select(cat, { + /// 'starting': 'Starting', + /// 'basic': 'Basic', + /// 'special': 'Special', + /// 'advanced1': 'Advanced (1-5)', + /// 'advanced2': 'Advanced (6-10)', + /// }, other: 'Other')} + /// """ + /// ``` + String mediumName(String cat) => """${_select(cat, { + 'starting': 'Starting', + 'basic': 'Basic', + 'special': 'Special', + 'advanced1': 'Advanced (1-5)', + 'advanced2': 'Advanced (6-10)', + }, other: 'Other')}"""; + + /// ```dart + /// """ + /// ${_select(cat, { + /// 'starting': 'Starting', + /// 'basic': 'Basic', + /// 'special': 'Special', + /// 'advanced1': 'Advanced (level 1-5)', + /// 'advanced2': 'Advanced (level 6-10)', + /// }, other: 'Other')} + /// """ + /// ``` + String longName(String cat) => """${_select(cat, { + 'starting': 'Starting', + 'basic': 'Basic', + 'special': 'Special', + 'advanced1': 'Advanced (level 1-5)', + 'advanced2': 'Advanced (level 6-10)', + }, other: 'Other')}"""; +} + +class SpellsMessages { + final Messages _parent; + const SpellsMessages(this._parent); + + /// ```dart + /// """ + /// ${_select(level, { + /// 'rote': 'Rote', + /// 'cantrip': 'Cantrip', + /// }, other: 'Level $level')} + /// """ + /// ``` + String spellLevel(String level) => """${_select(level, { + 'rote': 'Rote', + 'cantrip': 'Cantrip', + }, other: 'Level $level')}"""; +} + +class ItemsMessages { + final Messages _parent; + const ItemsMessages(this._parent); + + /// `× $amt` + String amount(String amt) => """× $amt"""; + + /// `Amount` + String get amountTooltip => """Amount"""; + SettingsItemsMessages get settings => SettingsItemsMessages(this); +} + +class SettingsItemsMessages { + final ItemsMessages _parent; + const SettingsItemsMessages(this._parent); + + /// `Count Armor` + String get countArmor => """Count Armor"""; + + /// `Count Damage` + String get countDamage => """Count Damage"""; + + /// `Count Weight` + String get countWeight => """Count Weight"""; +} + +class NotesMessages { + final Messages _parent; + const NotesMessages(this._parent); + + /// `General` + String get noCategory => """General"""; +} + +class AlignmentMessages { + final Messages _parent; + const AlignmentMessages(this._parent); + + /// ```dart + /// """ + /// ${_select(key, { + /// 'chaotic': 'Chaotic', + /// 'evil': 'Evil', + /// 'good': 'Good', + /// 'lawful': 'Lawful', + /// 'neutral': 'Neutral', + /// })} + /// """ + /// ``` + String name(String key) => """${_select(key, { + 'chaotic': 'Chaotic', + 'evil': 'Evil', + 'good': 'Good', + 'lawful': 'Lawful', + 'neutral': 'Neutral', + })}"""; +} + +class BioMessages { + final Messages _parent; + const BioMessages(this._parent); + DialogBioMessages get dialog => DialogBioMessages(this); +} + +class DialogBioMessages { + final BioMessages _parent; + const DialogBioMessages(this._parent); + + /// `Character Biography` + String get title => """Character Biography"""; + DescriptionDialogBioMessages get description => + DescriptionDialogBioMessages(this); + LooksDialogBioMessages get looks => LooksDialogBioMessages(this); + AlignmentDialogBioMessages get alignment => AlignmentDialogBioMessages(this); + AlignmentDescriptionDialogBioMessages get alignmentDescription => + AlignmentDescriptionDialogBioMessages(this); +} + +class DescriptionDialogBioMessages { + final DialogBioMessages _parent; + const DescriptionDialogBioMessages(this._parent); + + /// `Character & background description` + String get label => """Character & background description"""; + + /// `Describe your character's background, personality, goals, etc.` + String get placeholder => + """Describe your character's background, personality, goals, etc."""; +} + +class LooksDialogBioMessages { + final DialogBioMessages _parent; + const LooksDialogBioMessages(this._parent); + + /// `Appearance` + String get label => """Appearance"""; + + /// `Describe your character's appearance. You may use the presets from the buttons above.` + String get placeholder => + """Describe your character's appearance. You may use the presets from the buttons above."""; +} + +class AlignmentDialogBioMessages { + final DialogBioMessages _parent; + const AlignmentDialogBioMessages(this._parent); + + /// `Alignment` + String get label => """Alignment"""; +} + +class AlignmentDescriptionDialogBioMessages { + final DialogBioMessages _parent; + const AlignmentDescriptionDialogBioMessages(this._parent); + + /// `Alignment Description` + String get label => """Alignment Description"""; + + /// `Alignment is your character's way of thinking and moral compass. This can center on an ethical ideal, religious strictures or early life events. It reflects what your character values and aspires to protect or create.` + String get placeholder => + """Alignment is your character's way of thinking and moral compass. This can center on an ethical ideal, religious strictures or early life events. It reflects what your character values and aspires to protect or create."""; +} + +class SearchMessages { + final Messages _parent; + const SearchMessages(this._parent); + + /// `Type to search` + String get placeholder => """Type to search"""; + + /// `Type to search $ent` + String placeholderEntity(String ent) => """Type to search $ent"""; + + /// `Search in` + String get searchIn => """Search in"""; +} + +class HpMessages { + final Messages _parent; + const HpMessages(this._parent); + DialogHpMessages get dialog => DialogHpMessages(this); +} + +class DialogHpMessages { + final HpMessages _parent; + const DialogHpMessages(this._parent); + + /// `Modify HP` + String get title => """Modify HP"""; + ChangeDialogHpMessages get change => ChangeDialogHpMessages(this); + + /// `Override Max HP` + String get overrideMax => """Override Max HP"""; +} + +class ChangeDialogHpMessages { + final DialogHpMessages _parent; + const ChangeDialogHpMessages(this._parent); + + /// `Heal\n+$amt` + String add(int amt) => """Heal\n+$amt"""; + + /// `Damage\n-$amt` + String remove(int amt) => """Damage\n-$amt"""; + + /// `No Change` + String get neutral => """No Change"""; +} + +class XpMessages { + final Messages _parent; + const XpMessages(this._parent); + DialogXpMessages get dialog => DialogXpMessages(this); +} + +class DialogXpMessages { + final XpMessages _parent; + const DialogXpMessages(this._parent); + + /// `Mark Session XP` + String get title => """Mark Session XP"""; + + /// `Update XP & Level` + String get overridingTitle => """Update XP & Level"""; + EndOfSessionDialogXpMessages get endOfSession => + EndOfSessionDialogXpMessages(this); + OverrideDialogXpMessages get override => OverrideDialogXpMessages(this); +} + +class EndOfSessionDialogXpMessages { + final DialogXpMessages _parent; + const EndOfSessionDialogXpMessages(this._parent); + + /// `End Session` + String get button => """End Session"""; + QuestionsEndOfSessionDialogXpMessages get questions => + QuestionsEndOfSessionDialogXpMessages(this); +} + +class QuestionsEndOfSessionDialogXpMessages { + final EndOfSessionDialogXpMessages _parent; + const QuestionsEndOfSessionDialogXpMessages(this._parent); + + /// `End of Session Questions` + String get title => """End of Session Questions"""; + + /// `Answer these questions as a group. For each "yes" answer, XP is marked.` + String get subtitle => + """Answer these questions as a group. For each "yes" answer, XP is marked."""; +} + +class OverrideDialogXpMessages { + final DialogXpMessages _parent; + const OverrideDialogXpMessages(this._parent); + + /// `Update Manually` + String get title => """Update Manually"""; + + /// `Changing the current XP or level manually will cause the pending XP to be discarded unless this is unchecked.` + String get info => + """Changing the current XP or level manually will cause the pending XP to be discarded unless this is unchecked."""; + + /// `Reset bonds, flags & end of session questions after saving` + String get resetCheckbox => + """Reset bonds, flags & end of session questions after saving"""; + + /// `Override XP` + String get xp => """Override XP"""; + + /// `Override Level` + String get level => """Override Level"""; +} + +class ArmorMessages { + final Messages _parent; + const ArmorMessages(this._parent); + + /// `Armor` + String get title => """Armor"""; + DialogArmorMessages get dialog => DialogArmorMessages(this); +} + +class DialogArmorMessages { + final ArmorMessages _parent; + const DialogArmorMessages(this._parent); + + /// `Armor` + String get title => """Armor"""; + + /// `Use armor from class & equipped items` + String get autoArmor => """Use armor from class & equipped items"""; +} + +class RichTextMessages { + final Messages _parent; + const RichTextMessages(this._parent); + + /// `Preview` + String get preview => """Preview"""; + + /// `Formatting Help` + String get help => """Formatting Help"""; + + /// `Bold` + String get bold => """Bold"""; + + /// `Italic` + String get italic => """Italic"""; + + /// `Headings` + String get headings => """Headings"""; + + /// `Heading $depth` + String heading(int depth) => """Heading $depth"""; + + /// `Bullet List` + String get bulletList => """Bullet List"""; + + /// `Numbered List` + String get numberedList => """Numbered List"""; + CheckListRichTextMessages get checkList => CheckListRichTextMessages(this); + + /// `URL` + String get url => """URL"""; + + /// `Image URL` + String get imageURL => """Image URL"""; + + /// `Table` + String get table => """Table"""; + + /// `Header $n` + String header(Object n) => """Header $n"""; + + /// `Cell $n` + String cell(int n) => """Cell $n"""; + + /// `Markdown Preview` + String get markdownPreview => """Markdown Preview"""; +} + +class CheckListRichTextMessages { + final RichTextMessages _parent; + const CheckListRichTextMessages(this._parent); + + /// `Checklist (Unchecked)` + String get unchecked => """Checklist (Unchecked)"""; + + /// `Checklist (Checked)` + String get checked => """Checklist (Checked)"""; +} + +class CustomRollsMessages { + final Messages _parent; + const CustomRollsMessages(this._parent); + + /// `Quick Roll Buttons` + String get title => """Quick Roll Buttons"""; + + /// `Left Button` + String get left => """Left Button"""; + + /// `Right Button` + String get right => """Right Button"""; + + /// `Button Label` + String get buttonLabel => """Button Label"""; + SpecialDiceCustomRollsMessages get specialDice => + SpecialDiceCustomRollsMessages(this); + TooltipCustomRollsMessages get tooltip => TooltipCustomRollsMessages(this); + PresetsCustomRollsMessages get presets => PresetsCustomRollsMessages(this); +} + +class SpecialDiceCustomRollsMessages { + final CustomRollsMessages _parent; + const SpecialDiceCustomRollsMessages(this._parent); + + /// `Special Dice` + String get title => """Special Dice"""; + + /// `${_select(btn, {'damage': 'Damage'}, other: btn)}` + String button(String btn) => + """${_select(btn, {'damage': 'Damage'}, other: btn)}"""; +} + +class TooltipCustomRollsMessages { + final CustomRollsMessages _parent; + const TooltipCustomRollsMessages(this._parent); + + /// `Roll $dice\n* Rolling with debility` + String rollNormal(String dice) => """Roll $dice\n* Rolling with debility"""; + + /// `Roll $dice` + String rollWithDebility(String dice) => """Roll $dice"""; +} + +class PresetsCustomRollsMessages { + final CustomRollsMessages _parent; + const PresetsCustomRollsMessages(this._parent); + + /// `Presets` + String get title => """Presets"""; + + /// `Basic Action` + String get basicAction => """Basic Action"""; + + /// `Hack & Slash` + String get hackAndSlash => """Hack & Slash"""; + + /// `Volley` + String get volley => """Volley"""; + + /// `Discern Realities` + String get discernRealities => """Discern Realities"""; +} + +class SessionMarksMessages { + final Messages _parent; + const SessionMarksMessages(this._parent); + + /// `Bonds & Flags` + String get title => """Bonds & Flags"""; + + /// `Bond` + String get bond => """Bond"""; + + /// `Bonds` + String get bonds => """Bonds"""; + + /// `Flag` + String get flag => """Flag"""; + + /// `Flags` + String get flags => """Flags"""; + + /// `You have no bonds or flags. You can add some using the edit button above, then mark them off as completed as you go along your adventure.` + String get noData => + """You have no bonds or flags. You can add some using the edit button above, then mark them off as completed as you go along your adventure."""; + + /// `You can add, update or remove bonds & flags using the edit icon above.` + String get info => + """You can add, update or remove bonds & flags using the edit icon above."""; + EndOfSessionSessionMarksMessages get endOfSession => + EndOfSessionSessionMarksMessages(this); +} + +class EndOfSessionSessionMarksMessages { + final SessionMarksMessages _parent; + const EndOfSessionSessionMarksMessages(this._parent); + + /// `Did we learn something new and important about the world?` + String get q1 => + """Did we learn something new and important about the world?"""; + + /// `Did we overcome a notable monster or enemy?` + String get q2 => """Did we overcome a notable monster or enemy?"""; + + /// `Did we loot a memorable treasure?` + String get q3 => """Did we loot a memorable treasure?"""; +} + +class CreateCharacterMessages { + final Messages _parent; + const CreateCharacterMessages(this._parent); + CharacterClassCreateCharacterMessages get characterClass => + CharacterClassCreateCharacterMessages(this); + BasicInfoCreateCharacterMessages get basicInfo => + BasicInfoCreateCharacterMessages(this); + StartingGearCreateCharacterMessages get startingGear => + StartingGearCreateCharacterMessages(this); + MovesSpellsCreateCharacterMessages get movesSpells => + MovesSpellsCreateCharacterMessages(this); +} + +class CharacterClassCreateCharacterMessages { + final CreateCharacterMessages _parent; + const CharacterClassCreateCharacterMessages(this._parent); + + /// `No class selected (required)` + String get noSelection => """No class selected (required)"""; + + /// `Base HP: $hp, Load: $load, Damage Dice: $damageDice` + String description(int hp, int load, String damageDice) => + """Base HP: $hp, Load: $load, Damage Dice: $damageDice"""; +} + +class BasicInfoCreateCharacterMessages { + final CreateCharacterMessages _parent; + const BasicInfoCreateCharacterMessages(this._parent); + + /// `Unnamed Traveler` + String get defaultName => """Unnamed Traveler"""; + + /// `Select name & picture (required)` + String get helpText => """Select name & picture (required)"""; + + /// `Level 1 $cls` + String description(String cls) => """Level 1 $cls"""; +} + +class StartingGearCreateCharacterMessages { + final CreateCharacterMessages _parent; + const StartingGearCreateCharacterMessages(this._parent); + + /// `Select your starting gear determined by class (optional)` + String get helpText => + """Select your starting gear determined by class (optional)"""; + + /// `$amt ${_plural(double.tryParse(amt)?.ceil() ?? 0, one: 'coin', many: 'coins')}` + String coins(String amt) => + """$amt ${_plural(double.tryParse(amt)?.ceil() ?? 0, one: 'coin', many: 'coins')}"""; + + /// `$amt × $name` + String item(String amt, String name) => """$amt × $name"""; + CountStartingGearCreateCharacterMessages get count => + CountStartingGearCreateCharacterMessages(this); +} + +class CountStartingGearCreateCharacterMessages { + final StartingGearCreateCharacterMessages _parent; + const CountStartingGearCreateCharacterMessages(this._parent); + + /// `$cnt selected (class allowance: $max)` + String withMax(int cnt, int max) => + """$cnt selected (class allowance: $max)"""; + + /// `$cnt selected` + String noMax(int cnt) => """$cnt selected"""; +} + +class MovesSpellsCreateCharacterMessages { + final CreateCharacterMessages _parent; + const MovesSpellsCreateCharacterMessages(this._parent); + + /// `Moves & Spells` + String get title => """Moves & Spells"""; + + /// `$moves Moves, $spells Spells selected` + String description(int moves, int spells) => + """$moves Moves, $spells Spells selected"""; +} + +class AccountMessages { + final Messages _parent; + const AccountMessages(this._parent); + DetailsAccountMessages get details => DetailsAccountMessages(this); + ProvidersAccountMessages get providers => ProvidersAccountMessages(this); + DeleteAccountAccountMessages get deleteAccount => + DeleteAccountAccountMessages(this); +} + +class DetailsAccountMessages { + final AccountMessages _parent; + const DetailsAccountMessages(this._parent); + + /// `Account details` + String get title => """Account details"""; + DisplayNameDetailsAccountMessages get displayName => + DisplayNameDetailsAccountMessages(this); + ImageDetailsAccountMessages get image => ImageDetailsAccountMessages(this); + EmailDetailsAccountMessages get email => EmailDetailsAccountMessages(this); + PasswordDetailsAccountMessages get password => + PasswordDetailsAccountMessages(this); +} + +class DisplayNameDetailsAccountMessages { + final DetailsAccountMessages _parent; + const DisplayNameDetailsAccountMessages(this._parent); + + /// `Change Display Name` + String get title => """Change Display Name"""; + + /// `Display name` + String get label => """Display name"""; + + /// `Enter your public display name` + String get placeholder => """Enter your public display name"""; + + /// `Display name changed successfully` + String get success => """Display name changed successfully"""; +} + +class ImageDetailsAccountMessages { + final DetailsAccountMessages _parent; + const ImageDetailsAccountMessages(this._parent); + + /// `Change Profile Picture` + String get title => """Change Profile Picture"""; + + /// `Change your profile picture` + String get subtitle => """Change your profile picture"""; +} + +class EmailDetailsAccountMessages { + final DetailsAccountMessages _parent; + const EmailDetailsAccountMessages(this._parent); + + /// `Change Email Address` + String get title => """Change Email Address"""; + + /// `Email address` + String get label => """Email address"""; + + /// `Enter a new email address` + String get placeholder => """Enter a new email address"""; + + /// `Email changed successfully` + String get success => """Email changed successfully"""; +} + +class PasswordDetailsAccountMessages { + final DetailsAccountMessages _parent; + const PasswordDetailsAccountMessages(this._parent); + + /// `Change Password` + String get title => """Change Password"""; + + /// `Change your password` + String get subtitle => """Change your password"""; + + /// `Password changed successfully` + String get success => """Password changed successfully"""; + + /// `New password` + String get label => """New password"""; + + /// `Enter your new password` + String get placeholder => """Enter your new password"""; + VisibilityPasswordDetailsAccountMessages get visibility => + VisibilityPasswordDetailsAccountMessages(this); + ConfirmPasswordDetailsAccountMessages get confirm => + ConfirmPasswordDetailsAccountMessages(this); + + /// `Passwords do not match` + String get error => """Passwords do not match"""; +} + +class VisibilityPasswordDetailsAccountMessages { + final PasswordDetailsAccountMessages _parent; + const VisibilityPasswordDetailsAccountMessages(this._parent); + + /// `Show password` + String get show => """Show password"""; + + /// `Hide password` + String get hide => """Hide password"""; +} + +class ConfirmPasswordDetailsAccountMessages { + final PasswordDetailsAccountMessages _parent; + const ConfirmPasswordDetailsAccountMessages(this._parent); + + /// `Confirm New Password` + String get label => """Confirm New Password"""; + + /// `Enter the same password again` + String get placeholder => """Enter the same password again"""; +} + +class ProvidersAccountMessages { + final AccountMessages _parent; + const ProvidersAccountMessages(this._parent); + + /// `Connected logins` + String get title => """Connected logins"""; +} + +class DeleteAccountAccountMessages { + final AccountMessages _parent; + const DeleteAccountAccountMessages(this._parent); + + /// `Delete Your Account` + String get title => """Delete Your Account"""; + + /// `A deletion request for your account was sent successfully` + String get success => + """A deletion request for your account was sent successfully"""; +} + +class ActionsMessages { + final Messages _parent; + const ActionsMessages(this._parent); + MovesActionsMessages get moves => MovesActionsMessages(this); +} + +class MovesActionsMessages { + final ActionsMessages _parent; + const MovesActionsMessages(this._parent); + + /// `Basic Moves` + String get basic => """Basic Moves"""; + + /// `Special Moves` + String get special => """Special Moves"""; +} + +class AbilityScoresMessages { + final Messages _parent; + const AbilityScoresMessages(this._parent); + + /// `You can drag & drop the stat cards to change the order in which they appear throughout this character's screens.` + String get info => + """You can drag & drop the stat cards to change the order in which they appear throughout this character's screens."""; + RollButtonAbilityScoresMessages get rollButton => + RollButtonAbilityScoresMessages(this); + StatsAbilityScoresMessages get stats => StatsAbilityScoresMessages(this); + FormAbilityScoresMessages get form => FormAbilityScoresMessages(this); +} + +class RollButtonAbilityScoresMessages { + final AbilityScoresMessages _parent; + const RollButtonAbilityScoresMessages(this._parent); + + /// `Roll +{stat}` + String get stat => """Roll +{stat}"""; + + /// `Roll random stat` + String get randStat => """Roll random stat"""; +} + +class StatsAbilityScoresMessages { + final AbilityScoresMessages _parent; + const StatsAbilityScoresMessages(this._parent); + BondStatsAbilityScoresMessages get bond => + BondStatsAbilityScoresMessages(this); + ChaStatsAbilityScoresMessages get cha => ChaStatsAbilityScoresMessages(this); + ConStatsAbilityScoresMessages get con => ConStatsAbilityScoresMessages(this); + DexStatsAbilityScoresMessages get dex => DexStatsAbilityScoresMessages(this); + StrStatsAbilityScoresMessages get str => StrStatsAbilityScoresMessages(this); + WisStatsAbilityScoresMessages get wis => WisStatsAbilityScoresMessages(this); + IntlStatsAbilityScoresMessages get intl => + IntlStatsAbilityScoresMessages(this); +} + +class BondStatsAbilityScoresMessages { + final StatsAbilityScoresMessages _parent; + const BondStatsAbilityScoresMessages(this._parent); + + /// `Bond` + String get name => """Bond"""; + + /// `When a move has you roll+bond you'll count the number of bonds you have with the character in question and add that to the roll.` + String get description => + """When a move has you roll+bond you'll count the number of bonds you have with the character in question and add that to the roll."""; + DebilityBondStatsAbilityScoresMessages get debility => + DebilityBondStatsAbilityScoresMessages(this); +} + +class DebilityBondStatsAbilityScoresMessages { + final BondStatsAbilityScoresMessages _parent; + const DebilityBondStatsAbilityScoresMessages(this._parent); + + /// `Lonely` + String get name => """Lonely"""; + + String get description => """null"""; +} + +class ChaStatsAbilityScoresMessages { + final StatsAbilityScoresMessages _parent; + const ChaStatsAbilityScoresMessages(this._parent); + + /// `Measures a character's personality, personal magnetism, ability to lead, and appearance.` + String get description => + """Measures a character's personality, personal magnetism, ability to lead, and appearance."""; + + /// `Charisma` + String get name => """Charisma"""; + DebilityChaStatsAbilityScoresMessages get debility => + DebilityChaStatsAbilityScoresMessages(this); +} + +class DebilityChaStatsAbilityScoresMessages { + final ChaStatsAbilityScoresMessages _parent; + const DebilityChaStatsAbilityScoresMessages(this._parent); + + /// `Scarred` + String get name => """Scarred"""; + + /// `It may not be permanent, but for now you don't look so good.` + String get description => + """It may not be permanent, but for now you don't look so good."""; +} + +class ConStatsAbilityScoresMessages { + final StatsAbilityScoresMessages _parent; + const ConStatsAbilityScoresMessages(this._parent); + + /// `Represents your character's health and stamina.` + String get description => + """Represents your character's health and stamina."""; + + /// `Constitution` + String get name => """Constitution"""; + DebilityConStatsAbilityScoresMessages get debility => + DebilityConStatsAbilityScoresMessages(this); +} + +class DebilityConStatsAbilityScoresMessages { + final ConStatsAbilityScoresMessages _parent; + const DebilityConStatsAbilityScoresMessages(this._parent); + + /// `Sick` + String get name => """Sick"""; + + /// `Something just isn't right inside. Maybe you've got a disease or a wasting illness. Maybe you just drank too much ale last night and it's coming back to haunt you.` + String get description => + """Something just isn't right inside. Maybe you've got a disease or a wasting illness. Maybe you just drank too much ale last night and it's coming back to haunt you."""; +} + +class DexStatsAbilityScoresMessages { + final StatsAbilityScoresMessages _parent; + const DexStatsAbilityScoresMessages(this._parent); + + /// `Measures agility, reflexes and balance.` + String get description => """Measures agility, reflexes and balance."""; + + /// `Dexterity` + String get name => """Dexterity"""; + DebilityDexStatsAbilityScoresMessages get debility => + DebilityDexStatsAbilityScoresMessages(this); +} + +class DebilityDexStatsAbilityScoresMessages { + final DexStatsAbilityScoresMessages _parent; + const DebilityDexStatsAbilityScoresMessages(this._parent); + + /// `Shaky` + String get name => """Shaky"""; + + /// `You're unsteady on your feet and you've got a shake in your hands.` + String get description => + """You're unsteady on your feet and you've got a shake in your hands."""; +} + +class StrStatsAbilityScoresMessages { + final StatsAbilityScoresMessages _parent; + const StrStatsAbilityScoresMessages(this._parent); + + /// `Measures muscle and physical power.` + String get description => """Measures muscle and physical power."""; + + /// `Strength` + String get name => """Strength"""; + DebilityStrStatsAbilityScoresMessages get debility => + DebilityStrStatsAbilityScoresMessages(this); +} + +class DebilityStrStatsAbilityScoresMessages { + final StrStatsAbilityScoresMessages _parent; + const DebilityStrStatsAbilityScoresMessages(this._parent); + + /// `Weak` + String get name => """Weak"""; + + /// `You can't exert much force. Maybe it's just fatigue and injury, or maybe your strength was drained by magic.` + String get description => + """You can't exert much force. Maybe it's just fatigue and injury, or maybe your strength was drained by magic."""; +} + +class WisStatsAbilityScoresMessages { + final StatsAbilityScoresMessages _parent; + const WisStatsAbilityScoresMessages(this._parent); + + /// `Describes a character's willpower, common sense, awareness, and intuition.` + String get description => + """Describes a character's willpower, common sense, awareness, and intuition."""; + + /// `Wisdom` + String get name => """Wisdom"""; + DebilityWisStatsAbilityScoresMessages get debility => + DebilityWisStatsAbilityScoresMessages(this); +} + +class DebilityWisStatsAbilityScoresMessages { + final WisStatsAbilityScoresMessages _parent; + const DebilityWisStatsAbilityScoresMessages(this._parent); + + /// `Confused` + String get name => """Confused"""; + + /// `Ears ringing. Vision blurred. You're more than a little out of it.` + String get description => + """Ears ringing. Vision blurred. You're more than a little out of it."""; +} + +class IntlStatsAbilityScoresMessages { + final StatsAbilityScoresMessages _parent; + const IntlStatsAbilityScoresMessages(this._parent); + + /// `Determines how well your character learns and reasons.` + String get description => + """Determines how well your character learns and reasons."""; + + /// `Intelligence` + String get name => """Intelligence"""; + DebilityIntlStatsAbilityScoresMessages get debility => + DebilityIntlStatsAbilityScoresMessages(this); +} + +class DebilityIntlStatsAbilityScoresMessages { + final IntlStatsAbilityScoresMessages _parent; + const DebilityIntlStatsAbilityScoresMessages(this._parent); + + /// `Stunned` + String get name => """Stunned"""; + + /// `That last knock to the head shook something loose. Brain not work so good.` + String get description => + """That last knock to the head shook something loose. Brain not work so good."""; +} + +class FormAbilityScoresMessages { + final AbilityScoresMessages _parent; + const FormAbilityScoresMessages(this._parent); + + /// `Modifier:\n$mod` + String modifierValueLabel(String mod) => """Modifier:\n$mod"""; + DebilityDescriptionFormAbilityScoresMessages get debilityDescription => + DebilityDescriptionFormAbilityScoresMessages(this); + DebilityNameFormAbilityScoresMessages get debilityName => + DebilityNameFormAbilityScoresMessages(this); + DescriptionFormAbilityScoresMessages get description => + DescriptionFormAbilityScoresMessages(this); + KeyFormAbilityScoresMessages get key => KeyFormAbilityScoresMessages(this); + NameFormAbilityScoresMessages get name => NameFormAbilityScoresMessages(this); + IconFormAbilityScoresMessages get icon => IconFormAbilityScoresMessages(this); +} + +class DebilityDescriptionFormAbilityScoresMessages { + final FormAbilityScoresMessages _parent; + const DebilityDescriptionFormAbilityScoresMessages(this._parent); + + /// `Debility Description` + String get label => """Debility Description"""; + + /// `A description of the effect causing the debility and/or how it affects your character` + String get description => + """A description of the effect causing the debility and/or how it affects your character"""; +} + +class DebilityNameFormAbilityScoresMessages { + final FormAbilityScoresMessages _parent; + const DebilityNameFormAbilityScoresMessages(this._parent); + + /// `Debility Name` + String get label => """Debility Name"""; + + /// `The name for the debility that occurs when this stat is debilitated (takes -1 until recovered).` + String get description => + """The name for the debility that occurs when this stat is debilitated (takes -1 until recovered)."""; +} + +class DescriptionFormAbilityScoresMessages { + final FormAbilityScoresMessages _parent; + const DescriptionFormAbilityScoresMessages(this._parent); + + /// `Ability Score Description` + String get label => """Ability Score Description"""; + + /// `A description of what this ability score represents` + String get description => + """A description of what this ability score represents"""; +} + +class KeyFormAbilityScoresMessages { + final FormAbilityScoresMessages _parent; + const KeyFormAbilityScoresMessages(this._parent); + + /// `Ability Score Key` + String get label => """Ability Score Key"""; + + /// `A 3-letter unique key that identifies this ability score in dice and is used as the short label for the modifier value (and not the actual score)` + String get description => + """A 3-letter unique key that identifies this ability score in dice and is used as the short label for the modifier value (and not the actual score)"""; +} + +class NameFormAbilityScoresMessages { + final FormAbilityScoresMessages _parent; + const NameFormAbilityScoresMessages(this._parent); + + /// `Ability Score Name` + String get label => """Ability Score Name"""; + + /// `The name of this ability score` + String get description => """The name of this ability score"""; +} + +class IconFormAbilityScoresMessages { + final FormAbilityScoresMessages _parent; + const IconFormAbilityScoresMessages(this._parent); + + /// `Icon` + String get label => """Icon"""; + + /// `Change Icon` + String get button => """Change Icon"""; +} + +class FeedbackMessages { + final Messages _parent; + const FeedbackMessages(this._parent); + + /// `Send App Feedback` + String get title => """Send App Feedback"""; + + /// `Send` + String get send => """Send"""; + FormFeedbackMessages get form => FormFeedbackMessages(this); + SuccessFeedbackMessages get success => SuccessFeedbackMessages(this); +} + +class FormFeedbackMessages { + final FeedbackMessages _parent; + const FormFeedbackMessages(this._parent); + TitleFormFeedbackMessages get title => TitleFormFeedbackMessages(this); + BodyFormFeedbackMessages get body => BodyFormFeedbackMessages(this); + EmailFormFeedbackMessages get email => EmailFormFeedbackMessages(this); +} + +class TitleFormFeedbackMessages { + final FormFeedbackMessages _parent; + const TitleFormFeedbackMessages(this._parent); + + /// `Feedback title` + String get label => """Feedback title"""; +} + +class BodyFormFeedbackMessages { + final FormFeedbackMessages _parent; + const BodyFormFeedbackMessages(this._parent); + + /// `Problem, idea or feedback description` + String get label => """Problem, idea or feedback description"""; +} + +class EmailFormFeedbackMessages { + final FormFeedbackMessages _parent; + const EmailFormFeedbackMessages(this._parent); + + /// `Enter your email` + String get label => """Enter your email"""; +} + +class SuccessFeedbackMessages { + final FeedbackMessages _parent; + const SuccessFeedbackMessages(this._parent); + + /// `Feedback sent!` + String get title => """Feedback sent!"""; + + /// `Thank you for your feedback! We will review your feedback as soon as we can.` + String get message => + """Thank you for your feedback! We will review your feedback as soon as we can."""; +} + +class MigrationMessages { + final Messages _parent; + const MigrationMessages(this._parent); + + /// `Welcome to\nDungeon Paper 2!` + String get title => """Welcome to\nDungeon Paper 2!"""; + + /// `To get started, pick a username and the language for the rulebook & app. If you already have an existing Dungeon Paper account your data might take a few seconds to migrate.` + String get subtitle => + """To get started, pick a username and the language for the rulebook & app. If you already have an existing Dungeon Paper account your data might take a few seconds to migrate."""; + UsernameMigrationMessages get username => UsernameMigrationMessages(this); + LanguageMigrationMessages get language => LanguageMigrationMessages(this); +} + +class UsernameMigrationMessages { + final MigrationMessages _parent; + const UsernameMigrationMessages(this._parent); + + /// `Username` + String get label => """Username"""; + + /// `Pick a unique username` + String get placeholder => """Pick a unique username"""; + + /// `Your username is unique and can not be changed later, so think carefully! It will be used to identify all your library items when publishing.` + String get info => + """Your username is unique and can not be changed later, so think carefully! It will be used to identify all your library items when publishing."""; +} + +class LanguageMigrationMessages { + final MigrationMessages _parent; + const LanguageMigrationMessages(this._parent); + + /// `Default data language` + String get data => """Default data language"""; +} + +class BackupMessages { + final Messages _parent; + const BackupMessages(this._parent); + + /// `Export/Import` + String get title => """Export/Import"""; + ImportingBackupMessages get importing => ImportingBackupMessages(this); + ExportingBackupMessages get exporting => ExportingBackupMessages(this); +} + +class ImportingBackupMessages { + final BackupMessages _parent; + const ImportingBackupMessages(this._parent); + + /// `Import` + String get title => """Import"""; + + /// `Import` + String get button => """Import"""; + ProgressImportingBackupMessages get progress => + ProgressImportingBackupMessages(this); + FileImportingBackupMessages get file => FileImportingBackupMessages(this); + SuccessImportingBackupMessages get success => + SuccessImportingBackupMessages(this); + ErrorImportingBackupMessages get error => ErrorImportingBackupMessages(this); +} + +class ProgressImportingBackupMessages { + final ImportingBackupMessages _parent; + const ProgressImportingBackupMessages(this._parent); + + /// `Importing...` + String get title => """Importing..."""; + + /// `Processing $ent...` + String processing(String ent) => """Processing $ent..."""; +} + +class FileImportingBackupMessages { + final ImportingBackupMessages _parent; + const FileImportingBackupMessages(this._parent); + + /// `Browse...` + String get browse => """Browse..."""; + + /// `Clear selected file` + String get clearFile => """Clear selected file"""; + + /// `To start importing, pick the file you want to import from.\nYou will then be able to select what to save and what to leave out.` + String get info => + """To start importing, pick the file you want to import from.\nYou will then be able to select what to save and what to leave out."""; +} + +class SuccessImportingBackupMessages { + final ImportingBackupMessages _parent; + const SuccessImportingBackupMessages(this._parent); + + /// `Import Successful` + String get title => """Import Successful"""; + + /// `Your data was imported from file successfully` + String get message => """Your data was imported from file successfully"""; +} + +class ErrorImportingBackupMessages { + final ImportingBackupMessages _parent; + const ErrorImportingBackupMessages(this._parent); + + /// `Import Failed` + String get title => """Import Failed"""; + + /// `Something went wrong.\nTry again or contact support if this persists` + String get message => + """Something went wrong.\nTry again or contact support if this persists"""; +} + +class ExportingBackupMessages { + final BackupMessages _parent; + const ExportingBackupMessages(this._parent); + + /// `Export` + String get title => """Export"""; + + /// `Export` + String get button => """Export"""; + ErrorExportingBackupMessages get error => ErrorExportingBackupMessages(this); + SuccessExportingBackupMessages get success => + SuccessExportingBackupMessages(this); +} + +class ErrorExportingBackupMessages { + final ExportingBackupMessages _parent; + const ErrorExportingBackupMessages(this._parent); + + /// `Export Failed` + String get title => """Export Failed"""; + + /// `Something went wrong.\nTry again or contact support if this persists` + String get message => + """Something went wrong.\nTry again or contact support if this persists"""; +} + +class SuccessExportingBackupMessages { + final ExportingBackupMessages _parent; + const SuccessExportingBackupMessages(this._parent); + + /// `Export Successful` + String get title => """Export Successful"""; + + /// `Your data was exported to file successfully` + String get message => """Your data was exported to file successfully"""; +} + +Map get messagesMap => { + """app.name""": """Dungeon Paper""", + """generic.save""": """Save""", + """generic.cancel""": """Cancel""", + """generic.close""": """Close""", + """generic.done""": """Done""", + """generic.view""": """View""", + """generic.continue_""": """Continue""", + """generic.all""": """All""", + """generic.create""": """Create""", + """generic.add""": """Add""", + """generic.remove""": """Remove""", + """generic.unselect""": """Unselect""", + """generic.delete""": """Delete""", + """generic.edit""": """Edit""", + """generic.yes""": """Yes""", + """generic.no""": """No""", + """generic.select""": """Select""", + """generic.selected""": """Selected""", + """generic.selectAll""": """Select All""", + """generic.selectNone""": """Select None""", + """generic.my""": """My""", + """generic.change""": """Change""", + """generic.seeAll""": """See All""", + """generic.name""": """Name""", + """generic.value""": """Value""", + """generic.description""": """Description""", + """generic.explanation""": """Explanation""", + """generic.noDescription""": """‹No description provided›""", + """generic.useDefault""": """Use Default""", + """loading.user""": """Signing in...""", + """loading.characters""": """Getting characters...""", + """loading.general""": """Loading...""", + """errors.userOperationCanceled""": """Operation canceled""", + """errors.uploadError""": + """Error while uploading photo. Try again later, or contact support using the "About" page.""", + """errors.invalidEmail""": """Invalid email address""", + """errors.invalidPassword.letter""": + """Password must contain at least one capital letter""", + """errors.invalidPassword.number""": + """Password must contain at least one number""", + """errors.onlyLetters""": """Must contain letters only""", + """sort.moveUp""": """Move up""", + """sort.moveDown""": """Move down""", + """playbook.title""": """Playbook""", + """playbook.myLibrary""": """My Library""", + """playbook.myCampaigns""": """My Campaigns""", + """myLibrary.title""": """My Library""", + """myLibrary.reload""": """Reload Library""", + """myLibrary.alreadyAdded""": """Already added""", + """myLibrary.itemTab.playbook""": """Playbook""", + """myLibrary.itemTab.online""": """Online""", + """myLibrary.filters.clear""": """Clear Filters""", + """nav.actions""": """Use""", + """nav.character""": """Character""", + """nav.journal""": """Journal""", + """settings.title""": """Settings""", + """settings.importExport""": """Export/Import""", + """settings.categories.general""": """General""", + """settings.keepAwake""": """Keep screen awake while using the app""", + """user.recentCharacters""": """Recent Characters""", + """auth.orSeparator""": """OR""", + """auth.privacyPolicy""": """Privacy Policy""", + """auth.changelog""": """What's new?""", + """auth.providers.unlink""": """Unlink""", + """auth.providers.link""": """Link""", + """auth.login.title""": """Sign In""", + """auth.login.subtitle""": + """Sign in to your account to sync your data online, and get access to many more features.""", + """auth.login.button""": """Sign in""", + """auth.login.noAccount.label""": """Don't have an account?""", + """auth.login.noAccount.button""": """Sign up""", + """auth.logout.button""": """Sign out""", + """auth.signup.title""": """Sign Up""", + """auth.signup.subtitle""": + """Enter the required details below to create your Dungeon Paper account.""", + """auth.signup.button""": """Sign up""", + """auth.signup.notLoggedIn.label""": """Not logged in""", + """auth.signup.email.label""": """Email""", + """auth.signup.email.placeholder""": """Enter your email""", + """auth.signup.email.error""": """Please enter a valid email address""", + """auth.signup.password.label""": """Password""", + """auth.signup.password.placeholder""": """Enter a password""", + """auth.signup.password.confirm.label""": """Confirm Password""", + """auth.signup.password.confirm.placeholder""": + """Enter the same password again""", + """auth.signup.password.confirm.error""": """Passwords do not match""", + """home.bars.xp""": """XP""", + """home.bars.hp""": """HP""", + """home.categories.notes""": """Bookmarked Notes""", + """home.categories.moves""": """Favorite Moves""", + """home.categories.spells""": """Prepared Spells""", + """home.categories.items""": """Equipped Items""", + """home.summary.load.tooltip""": """Max Load""", + """home.summary.coins.tooltip""": """Coins""", + """home.menu.character.tooltip""": """Character Menu""", + """home.menu.character.basicInfo""": """Basic Information""", + """home.menu.character.abilityScores""": """Ability Scores""", + """home.menu.character.customRolls""": """Quick-Roll Buttons""", + """home.menu.character.theme""": """Character Theme""", + """home.menu.bio""": """Character Biography""", + """home.menu.debilities""": """Debilities""", + """home.emptyState.guest.title""": """Sign in to get more features""", + """home.emptyState.guest.subtitle""": + """Online data sync, library sharing, campaigns and more!""", + """home.emptyState.title""": """No Characters""", + """home.emptyState.subtitle""": """Create a Character to get started""", + """about.title""": """About""", + """about.author""": """Chen Asraf""", + """about.discord.title""": """Join Our Discord""", + """about.discord.subtitle""": + """Join the Discord community to ask questions, get help, send feedback, or just chat with other players.""", + """about.feedback.title""": """Send Feedback""", + """about.feedback.subtitle""": + """We reply more promptly through Discord, but you can send us feedback, bug reports or suggestions about the app directly here as an alternative.""", + """about.socials.title""": """Links""", + """about.socials.twitter""": """Twitter""", + """about.socials.facebook""": """Facebook""", + """about.socials.discord""": """Discord""", + """about.socials.github""": """GitHub""", + """about.socials.google""": """Play Store""", + """about.socials.apple""": """App Store""", + """about.specialThanks""": """Special Thanks""", + """about.contributors""": """Contributors""", + """about.icons""": """Icon Credits""", + """character.data.coins""": """Coins""", + """character.data.load.load""": """Load""", + """character.data.load.maxLoad""": """Max Load""", + """character.data.load.autoMaxLoad""": + """Use class base load + STR mod""", + """character.data.level""": """Level""", + """character.data.damageDice""": """Damage Dice""", + """character.data.calculateDamage""": + """Use damage dice from class & equipped items""", + """character.header.separator""": """ ∙ """, + """character.noCategory""": """No Category""", + """character.theme.title""": """Character Theme""", + """characterClass.baseLoad""": """Base Load""", + """characterClass.baseHp""": """Base HP""", + """characterClass.damageDice""": """Damage Dice""", + """dice.form.amount""": """Amount""", + """dice.form.sides""": """Sides""", + """dice.form.diceSeparator""": """d""", + """dice.form.modifierType.fixed""": """Fixed Value""", + """dice.form.modifierType.modifier""": """Stat Mod.""", + """dice.form.value.placeholder""": """Number, e.g. 2 or -1""", + """dice.form.value.label""": """Modifier value""", + """dice.form.modifier.placeholder""": """Select stat""", + """dice.form.modifier.label""": """Stat""", + """dice.roll.action""": """Roll""", + """basicInfo.title""": """Basic Information""", + """basicInfo.form.name.label""": """Character Name""", + """basicInfo.form.name.placeholder""": """Enter your character's name""", + """basicInfo.form.photo.change""": """Change Photo...""", + """basicInfo.form.photo.remove""": """Remove Photo""", + """basicInfo.form.photo.choose""": """Choose Photo...""", + """basicInfo.form.photo.guest.prefix""": + """You need to be signed in to upload images. """, + """basicInfo.form.photo.guest.label""": + """Sign in or create an account""", + """basicInfo.form.photo.guest.suffix""": + """, or upload using your own URL below.""", + """basicInfo.form.photo.uploading""": """UPLOADING...""", + """basicInfo.form.photo.orSeparator""": """OR""", + """basicInfo.form.photo.url.label""": """Image URL""", + """basicInfo.form.photo.url.placeholder""": """Paste an image URL""", + """debilities.dialog.title""": """Debilities""", + """debilities.dialog.info""": + """Debilities are temporary, negative conditions or states in which your character is in. When a stat is debilitated, it causes its modifier to be reduced by 1 until recovered.""", + """tags.dialog.title""": """Tag Information""", + """dialogs.confirmations.exit.title""": """Are you sure?""", + """dialogs.confirmations.exit.body""": + """Going back will lose any unsaved changes.\nAre you sure you want to go back?""", + """dialogs.confirmations.exit.ok""": """Exit & Discard""", + """dialogs.confirmations.exit.cancel""": """Continue editing""", + """dialogs.confirmations.deleteAccount.step1.title""": + """Delete Your Account?""", + """dialogs.confirmations.deleteAccount.step1.body""": + """Are you sure you want to delete your account?\n\nThis action cannot be undone.""", + """dialogs.confirmations.deleteAccount.step2.title""": + """Are you really sure?""", + """dialogs.confirmations.deleteAccount.step2.body""": + """We do not save any data for deleted accounts. All your data will be permanently deleted.\n\nAre you sure you want to delete your account?\n\nPlease confirm this one last time.""", + """items.amountTooltip""": """Amount""", + """items.settings.countArmor""": """Count Armor""", + """items.settings.countDamage""": """Count Damage""", + """items.settings.countWeight""": """Count Weight""", + """notes.noCategory""": """General""", + """bio.dialog.title""": """Character Biography""", + """bio.dialog.description.label""": + """Character & background description""", + """bio.dialog.description.placeholder""": + """Describe your character's background, personality, goals, etc.""", + """bio.dialog.looks.label""": """Appearance""", + """bio.dialog.looks.placeholder""": + """Describe your character's appearance. You may use the presets from the buttons above.""", + """bio.dialog.alignment.label""": """Alignment""", + """bio.dialog.alignmentDescription.label""": """Alignment Description""", + """bio.dialog.alignmentDescription.placeholder""": + """Alignment is your character's way of thinking and moral compass. This can center on an ethical ideal, religious strictures or early life events. It reflects what your character values and aspires to protect or create.""", + """search.placeholder""": """Type to search""", + """search.searchIn""": """Search in""", + """hp.dialog.title""": """Modify HP""", + """hp.dialog.change.neutral""": """No Change""", + """hp.dialog.overrideMax""": """Override Max HP""", + """xp.dialog.title""": """Mark Session XP""", + """xp.dialog.overridingTitle""": """Update XP & Level""", + """xp.dialog.endOfSession.button""": """End Session""", + """xp.dialog.endOfSession.questions.title""": + """End of Session Questions""", + """xp.dialog.endOfSession.questions.subtitle""": + """Answer these questions as a group. For each "yes" answer, XP is marked.""", + """xp.dialog.override.title""": """Update Manually""", + """xp.dialog.override.info""": + """Changing the current XP or level manually will cause the pending XP to be discarded unless this is unchecked.""", + """xp.dialog.override.resetCheckbox""": + """Reset bonds, flags & end of session questions after saving""", + """xp.dialog.override.xp""": """Override XP""", + """xp.dialog.override.level""": """Override Level""", + """armor.title""": """Armor""", + """armor.dialog.title""": """Armor""", + """armor.dialog.autoArmor""": """Use armor from class & equipped items""", + """richText.preview""": """Preview""", + """richText.help""": """Formatting Help""", + """richText.bold""": """Bold""", + """richText.italic""": """Italic""", + """richText.headings""": """Headings""", + """richText.bulletList""": """Bullet List""", + """richText.numberedList""": """Numbered List""", + """richText.checkList.unchecked""": """Checklist (Unchecked)""", + """richText.checkList.checked""": """Checklist (Checked)""", + """richText.url""": """URL""", + """richText.imageURL""": """Image URL""", + """richText.table""": """Table""", + """richText.markdownPreview""": """Markdown Preview""", + """customRolls.title""": """Quick Roll Buttons""", + """customRolls.left""": """Left Button""", + """customRolls.right""": """Right Button""", + """customRolls.buttonLabel""": """Button Label""", + """customRolls.specialDice.title""": """Special Dice""", + """customRolls.presets.title""": """Presets""", + """customRolls.presets.basicAction""": """Basic Action""", + """customRolls.presets.hackAndSlash""": """Hack & Slash""", + """customRolls.presets.volley""": """Volley""", + """customRolls.presets.discernRealities""": """Discern Realities""", + """sessionMarks.title""": """Bonds & Flags""", + """sessionMarks.bond""": """Bond""", + """sessionMarks.bonds""": """Bonds""", + """sessionMarks.flag""": """Flag""", + """sessionMarks.flags""": """Flags""", + """sessionMarks.noData""": + """You have no bonds or flags. You can add some using the edit button above, then mark them off as completed as you go along your adventure.""", + """sessionMarks.info""": + """You can add, update or remove bonds & flags using the edit icon above.""", + """sessionMarks.endOfSession.q1""": + """Did we learn something new and important about the world?""", + """sessionMarks.endOfSession.q2""": + """Did we overcome a notable monster or enemy?""", + """sessionMarks.endOfSession.q3""": + """Did we loot a memorable treasure?""", + """createCharacter.characterClass.noSelection""": + """No class selected (required)""", + """createCharacter.basicInfo.defaultName""": """Unnamed Traveler""", + """createCharacter.basicInfo.helpText""": + """Select name & picture (required)""", + """createCharacter.startingGear.helpText""": + """Select your starting gear determined by class (optional)""", + """createCharacter.movesSpells.title""": """Moves & Spells""", + """account.details.title""": """Account details""", + """account.details.displayName.title""": """Change Display Name""", + """account.details.displayName.label""": """Display name""", + """account.details.displayName.placeholder""": + """Enter your public display name""", + """account.details.displayName.success""": + """Display name changed successfully""", + """account.details.image.title""": """Change Profile Picture""", + """account.details.image.subtitle""": """Change your profile picture""", + """account.details.email.title""": """Change Email Address""", + """account.details.email.label""": """Email address""", + """account.details.email.placeholder""": """Enter a new email address""", + """account.details.email.success""": """Email changed successfully""", + """account.details.password.title""": """Change Password""", + """account.details.password.subtitle""": """Change your password""", + """account.details.password.success""": + """Password changed successfully""", + """account.details.password.label""": """New password""", + """account.details.password.placeholder""": """Enter your new password""", + """account.details.password.visibility.show""": """Show password""", + """account.details.password.visibility.hide""": """Hide password""", + """account.details.password.confirm.label""": """Confirm New Password""", + """account.details.password.confirm.placeholder""": + """Enter the same password again""", + """account.details.password.error""": """Passwords do not match""", + """account.providers.title""": """Connected logins""", + """account.deleteAccount.title""": """Delete Your Account""", + """account.deleteAccount.success""": + """A deletion request for your account was sent successfully""", + """actions.moves.basic""": """Basic Moves""", + """actions.moves.special""": """Special Moves""", + """abilityScores.info""": + """You can drag & drop the stat cards to change the order in which they appear throughout this character's screens.""", + """abilityScores.rollButton.stat""": """Roll +{stat}""", + """abilityScores.rollButton.randStat""": """Roll random stat""", + """abilityScores.stats.bond.name""": """Bond""", + """abilityScores.stats.bond.description""": + """When a move has you roll+bond you'll count the number of bonds you have with the character in question and add that to the roll.""", + """abilityScores.stats.bond.debility.name""": """Lonely""", + """abilityScores.stats.cha.description""": + """Measures a character's personality, personal magnetism, ability to lead, and appearance.""", + """abilityScores.stats.cha.name""": """Charisma""", + """abilityScores.stats.cha.debility.name""": """Scarred""", + """abilityScores.stats.cha.debility.description""": + """It may not be permanent, but for now you don't look so good.""", + """abilityScores.stats.con.description""": + """Represents your character's health and stamina.""", + """abilityScores.stats.con.name""": """Constitution""", + """abilityScores.stats.con.debility.name""": """Sick""", + """abilityScores.stats.con.debility.description""": + """Something just isn't right inside. Maybe you've got a disease or a wasting illness. Maybe you just drank too much ale last night and it's coming back to haunt you.""", + """abilityScores.stats.dex.description""": + """Measures agility, reflexes and balance.""", + """abilityScores.stats.dex.name""": """Dexterity""", + """abilityScores.stats.dex.debility.name""": """Shaky""", + """abilityScores.stats.dex.debility.description""": + """You're unsteady on your feet and you've got a shake in your hands.""", + """abilityScores.stats.str.description""": + """Measures muscle and physical power.""", + """abilityScores.stats.str.name""": """Strength""", + """abilityScores.stats.str.debility.name""": """Weak""", + """abilityScores.stats.str.debility.description""": + """You can't exert much force. Maybe it's just fatigue and injury, or maybe your strength was drained by magic.""", + """abilityScores.stats.wis.description""": + """Describes a character's willpower, common sense, awareness, and intuition.""", + """abilityScores.stats.wis.name""": """Wisdom""", + """abilityScores.stats.wis.debility.name""": """Confused""", + """abilityScores.stats.wis.debility.description""": + """Ears ringing. Vision blurred. You're more than a little out of it.""", + """abilityScores.stats.intl.description""": + """Determines how well your character learns and reasons.""", + """abilityScores.stats.intl.name""": """Intelligence""", + """abilityScores.stats.intl.debility.name""": """Stunned""", + """abilityScores.stats.intl.debility.description""": + """That last knock to the head shook something loose. Brain not work so good.""", + """abilityScores.form.debilityDescription.label""": + """Debility Description""", + """abilityScores.form.debilityDescription.description""": + """A description of the effect causing the debility and/or how it affects your character""", + """abilityScores.form.debilityName.label""": """Debility Name""", + """abilityScores.form.debilityName.description""": + """The name for the debility that occurs when this stat is debilitated (takes -1 until recovered).""", + """abilityScores.form.description.label""": + """Ability Score Description""", + """abilityScores.form.description.description""": + """A description of what this ability score represents""", + """abilityScores.form.key.label""": """Ability Score Key""", + """abilityScores.form.key.description""": + """A 3-letter unique key that identifies this ability score in dice and is used as the short label for the modifier value (and not the actual score)""", + """abilityScores.form.name.label""": """Ability Score Name""", + """abilityScores.form.name.description""": + """The name of this ability score""", + """abilityScores.form.icon.label""": """Icon""", + """abilityScores.form.icon.button""": """Change Icon""", + """feedback.title""": """Send App Feedback""", + """feedback.send""": """Send""", + """feedback.form.title.label""": """Feedback title""", + """feedback.form.body.label""": + """Problem, idea or feedback description""", + """feedback.form.email.label""": """Enter your email""", + """feedback.success.title""": """Feedback sent!""", + """feedback.success.message""": + """Thank you for your feedback! We will review your feedback as soon as we can.""", + """migration.title""": """Welcome to\nDungeon Paper 2!""", + """migration.subtitle""": + """To get started, pick a username and the language for the rulebook & app. If you already have an existing Dungeon Paper account your data might take a few seconds to migrate.""", + """migration.username.label""": """Username""", + """migration.username.placeholder""": """Pick a unique username""", + """migration.username.info""": + """Your username is unique and can not be changed later, so think carefully! It will be used to identify all your library items when publishing.""", + """migration.language.data""": """Default data language""", + """backup.title""": """Export/Import""", + """backup.importing.title""": """Import""", + """backup.importing.button""": """Import""", + """backup.importing.progress.title""": """Importing...""", + """backup.importing.file.browse""": """Browse...""", + """backup.importing.file.clearFile""": """Clear selected file""", + """backup.importing.file.info""": + """To start importing, pick the file you want to import from.\nYou will then be able to select what to save and what to leave out.""", + """backup.importing.success.title""": """Import Successful""", + """backup.importing.success.message""": + """Your data was imported from file successfully""", + """backup.importing.error.title""": """Import Failed""", + """backup.importing.error.message""": + """Something went wrong.\nTry again or contact support if this persists""", + """backup.exporting.title""": """Export""", + """backup.exporting.button""": """Export""", + """backup.exporting.error.title""": """Export Failed""", + """backup.exporting.error.message""": + """Something went wrong.\nTry again or contact support if this persists""", + """backup.exporting.success.title""": """Export Successful""", + """backup.exporting.success.message""": + """Your data was exported to file successfully""", + }; diff --git a/lib/i18n/messages.i18n.yaml b/lib/i18n/messages.i18n.yaml new file mode 100644 index 00000000..ca6d0c45 --- /dev/null +++ b/lib/i18n/messages.i18n.yaml @@ -0,0 +1,700 @@ +# generic name mappings +_entSingle(String type): |- + ${_select(type, { + 'Dice': 'Die', + 'CharacterClass': 'Class', + 'MoveCategory': 'Category', + 'GearSelection': 'Starting Gear', + 'AbilityScore': 'Ability Score', + 'AlignmentValue': 'Alignment' + })} +_entPlural(String type): |- + ${_select(type, { + 'MoveCategory': 'Categories', + 'CharacterClass': 'Classes', + }, other: '${_entSingle(type)}s')} + +entity(Type ent): '${_entSingle(ent.toString())}' +entityPlural(Type ent): '${_entPlural(ent.toString())}' +entityCount(Type ent, int cnt): '${cnt == 1 ? _entSingle(ent.toString()) : _entPlural(ent.toString())}' +entityCountNum(Type ent, int cnt): '$cnt ${entityCount(ent, cnt)}' + +app: + name: Dungeon Paper + +generic: + save: Save + saveEntity(String ent): Save $ent + cancel: Cancel + close: Close + done: Done + view: View + continue_: Continue + viewEntity(String ent): View $ent + all: All + allEntities(String ent): All $ent + create: Create + createEntity(String ent): Create $ent + add: Add + addEntity(String ent): Add $ent + remove: Remove + removeEntity(String ent): Remove $ent + unselect: Unselect + unselectEntity(String ent): Unselect $ent + delete: Delete + deleteEntity(String ent): Delete $ent + edit: Edit + editEntity(String ent): Edit $ent + yes: Yes + no: No + noEntity(String ent): No $ent + select: Select + selectEntity(String ent): Select $ent + selected: Selected + selectAll: Select All + selectNone: Select None + my: My + myEntity(String ent): My $ent + change: Change + changeEntity(String ent): Change $ent + seeAll: See All + selectToAdd(String ent): Select $ent to add + name: Name + entityName(String ent): $ent name + value: Value + entityValue(String ent): $ent value + description: Description + entityDescription(String ent): $ent description + explanation: Explanation + entityExplanation(String ent): $ent explanation + noDescription: ‹No description provided› + noEntitySelected(String ent): No $ent selected + noEntitySelectedRequired(String ent): No $ent selected (required) + useDefault: Use Default + +loading: + user: Signing in... + characters: Getting characters... + general: Loading... + +errors: + userOperationCanceled: Operation canceled + uploadError: Error while uploading photo. Try again later, or contact support using the "About" page. + invalidEmail: Invalid email address + invalidPassword: + letter: Password must contain at least one capital letter + number: Password must contain at least one number + minLength(int cnt): "Must be at least $cnt ${_plural(cnt, one: 'character', many: 'characters')}" + maxLength(int cnt): "Must be no more than $cnt ${_plural(cnt, one: 'character', many: 'characters')}" + exactLength(int cnt): "Must be exactly $cnt ${_plural(cnt, one: 'character', many: 'characters')}" + mustContain(String pattern): Must contain $pattern + mustNotContain(String pattern): Must not contain $pattern + onlyLetters: Must contain letters only + +sort: + moveUp: Move up + moveDown: Move down + moveEntityToTop(String ent): Move $ent to top + moveEntityToBottom(String ent): Move $ent to bottom + +playbook: + title: Playbook + myLibrary: My Library + myCampaigns: My Campaigns + +myLibrary: + title: My Library + reload: Reload Library + itemCount(String cnt, String type): $cnt in $type + libraryType(String type): |- + ${_select(type, { + 'builtIn': 'Playbook', + 'my': 'My Library' + })} + alreadyAdded: Already added + itemTab: + playbook: Playbook + online: Online + emptyState: + title(String ent): No $ent found + subtitle: + filters(String ent): No $ent found in this list. + noFilters(String ent): Try changing the search or filters to find more $ent. + filters: + clear: Clear Filters + +nav: + actions: Use + character: Character + journal: Journal + +sync: + entity: + status: + inSync(String ent): This $ent is In Sync with its linked library item + outOfSync(String ent): This $ent is Out of Sync with its linked library item + detached(String ent): This $ent is not linked to any library item + +settings: + title: Settings + importExport: Export/Import + _switchMode(String mode): 'Switch to ${mode} Mode' + switchToDark: "${_switchMode('Dark')}" + switchToLight: "${_switchMode('Light')}" + categories: + general: General + keepAwake: Keep screen awake while using the app + defaultTheme: + _p(String type): Default $type theme + light: "${_p('light')}" + dark: "${_p('dark')}" + +user: + recentCharacters: Recent Characters + +auth: + orSeparator: OR + privacyPolicy: Privacy Policy + changelog: What's new? + providers: + loginWith(String provider): Sign in with $provider + signupWith(String provider): Sign up with $provider + unusable(String provider): This device only supports unlinking $provider accounts. + # `{provider, select, facebook {Facebook} google {Google} apple {Apple} password {Dungeon Paper} other {Other}}` + name(String provider): |- + ${_select(provider, { + 'facebook': 'Facebook', + 'google': 'Google', + 'apple': 'Apple', + 'password': 'Dungeon Paper', + }, other: 'Other')} + unlink: Unlink + link: Link + confirmUnlink: + title(String ent): Unlink from $ent + body(String ent): Are you sure you want to unlink your account from $ent?\nBy clicking "Unlink", you will no longer be able to sign in with $ent.\n\nYou will be able to re-link your account at any time by going to your account settings. + login: + title: Sign In + subtitle: Sign in to your account to sync your data online, and get access to many more features. + button: Sign in + noAccount: + label: Don't have an account? + button: Sign up + logout: + button: Sign out + signup: + title: Sign Up + subtitle: Enter the required details below to create your Dungeon Paper account. + button: Sign up + notLoggedIn: + label: Not logged in + email: + label: Email + placeholder: Enter your email + error: Please enter a valid email address + password: + label: Password + placeholder: Enter a password + confirm: + label: Confirm Password + placeholder: Enter the same password again + error: Passwords do not match + +home: + bars: + xp: XP + hp: HP + categories: + notes: Bookmarked Notes + moves: Favorite Moves + spells: Prepared Spells + items: Equipped Items + summary: + load: + label(int cur, int max): 'Load: $cur/$max' + tooltip: Max Load + coins: + label(String amt): $amt G + tooltip: Coins + menu: + character: + tooltip: Character Menu + basicInfo: Basic Information + abilityScores: Ability Scores + customRolls: Quick-Roll Buttons + theme: Character Theme + bio: Character Biography + debilities: Debilities + emptyState: + guest: + title: Sign in to get more features + subtitle: Online data sync, library sharing, campaigns and more! + title: No Characters + subtitle: Create a Character to get started + +about: + title: About + version(String version): Version $version + copyright(int year): Copyright © 2018-$year + author: Chen Asraf + discord: + title: Join Our Discord + subtitle: Join the Discord community to ask questions, get help, send feedback, or just chat with other players. + feedback: + title: Send Feedback + subtitle: We reply more promptly through Discord, but you can send us feedback, bug reports or suggestions about the app directly here as an alternative. + socials: + title: Links + twitter: Twitter + facebook: Facebook + discord: Discord + github: GitHub + google: Play Store + apple: App Store + specialThanks: Special Thanks + contributors: Contributors + icons: Icon Credits + +character: + data: + coins: Coins + load: + load: Load + maxLoad: Max Load + autoMaxLoad: Use class base load + STR mod + level: Level + damageDice: Damage Dice + calculateDamage: Use damage dice from class & equipped items + header: + level(int lv): Level $lv + characterClass(String name): $name + race(String name): $name + alignment(String alignment): $alignment + separator: ' ∙ ' + noCategory: No Category + theme: + title: Character Theme + _defaultTheme(String type): Default $type theme + defaultLight: "${_defaultTheme('light')}" + defaultDark: "${_defaultTheme('dark')}" + +characterClass: + baseLoad: Base Load + baseHp: Base HP + damageDice: Damage Dice + +dice: + suggestion(String dice): 'Suggested: $dice' + form: + amount: Amount + sides: Sides + diceSeparator: d + modifierType: + fixed: Fixed Value + modifier: Stat Mod. + value: + placeholder: Number, e.g. 2 or -1 + label: Modifier value + modifier: + placeholder: Select stat + label: Stat + statValue(String name, String key): $name ($key) + + roll: + title: + rolled(int total): Rolled $total + rolling(int amt): "Rolling $amt ${_plural(amt, one: 'die', many: 'dice')}" + action: Roll + total(int amt): Total $amt + resultBreakdown(String dice, String mod): 'Dice: $dice | Modifier: $mod' + +basicInfo: + title: Basic Information + form: + name: + label: Character Name + placeholder: Enter your character's name + random: + tooltip: + _p(String act): $act to generate a random name + touch: "${_p('Tap')}" + click: "${_p('Click')}" + photo: + change: Change Photo... + remove: Remove Photo + choose: Choose Photo... + guest: + prefix: 'You need to be signed in to upload images. ' + label: Sign in or create an account + suffix: ', or upload using your own URL below.' + uploading: UPLOADING... + orSeparator: OR + url: + label: Image URL + placeholder: Paste an image URL + +debilities: + label(String name, String key): $name ($key) + dialog: + title: Debilities + info: Debilities are temporary, negative conditions or states in which your character is in. When a stat is debilitated, it causes its modifier to be reduced by 1 until recovered. + +tags: + copyFrom(String name): 'Copy from: $name' + dialog: + title: Tag Information + +dialogs: + confirmations: + delete: + title(String ent): Delete $ent? + body(String ent, String name): Are you sure you want to remove the $ent "$name" from the list? + exit: + title: Are you sure? + body: Going back will lose any unsaved changes.\nAre you sure you want to go back? + ok: Exit & Discard + cancel: Continue editing + deleteAccount: + step1: + title: Delete Your Account? + body: Are you sure you want to delete your account?\n\nThis action cannot be undone. + step2: + title: Are you really sure? + body: We do not save any data for deleted accounts. All your data will be permanently deleted.\n\nAre you sure you want to delete your account?\n\nPlease confirm this one last time. + +moves: + category: + shortName(String cat): |- + ${_select(cat, { + 'starting': 'Starting', + 'basic': 'Basic', + 'special': 'Special', + 'advanced1': 'Advanced', + 'advanced2': 'Advanced', + }, other: 'Other')} + mediumName(String cat): |- + ${_select(cat, { + 'starting': 'Starting', + 'basic': 'Basic', + 'special': 'Special', + 'advanced1': 'Advanced (1-5)', + 'advanced2': 'Advanced (6-10)', + }, other: 'Other')} + longName(String cat): |- + ${_select(cat, { + 'starting': 'Starting', + 'basic': 'Basic', + 'special': 'Special', + 'advanced1': 'Advanced (level 1-5)', + 'advanced2': 'Advanced (level 6-10)', + }, other: 'Other')} + +spells: + spellLevel(String level): |- + ${_select(level, { + 'rote': 'Rote', + 'cantrip': 'Cantrip', + }, other: 'Level $level')} + +items: + amount(String amt): × $amt + amountTooltip: Amount + settings: + countArmor: Count Armor + countDamage: Count Damage + countWeight: Count Weight + +notes: + noCategory: General + +# `{alignment, select, chaotic {Chaotic} evil {Evil} good {Good} lawful {Lawful} neutral {Neutral} other {{alignment}}}` +alignment: + name(String key): |- + ${_select(key, { + 'chaotic': 'Chaotic', + 'evil': 'Evil', + 'good': 'Good', + 'lawful': 'Lawful', + 'neutral': 'Neutral', + })} + +bio: + dialog: + title: Character Biography + description: + label: Character & background description + placeholder: Describe your character's background, personality, goals, etc. + looks: + label: Appearance + placeholder: Describe your character's appearance. You may use the presets from the buttons above. + alignment: + label: Alignment + alignmentDescription: + label: Alignment Description + placeholder: Alignment is your character's way of thinking and moral compass. This can center on an ethical ideal, religious strictures or early life events. It reflects what your character values and aspires to protect or create. + +search: + placeholder: Type to search + placeholderEntity(String ent): Type to search $ent + searchIn: Search in + +hp: + dialog: + title: Modify HP + change: + add(int amt): Heal\n+$amt + remove(int amt): Damage\n-$amt + neutral: No Change + overrideMax: Override Max HP + +xp: + dialog: + title: Mark Session XP + overridingTitle: Update XP & Level + endOfSession: + button: End Session + questions: + title: End of Session Questions + subtitle: 'Answer these questions as a group. For each "yes" answer, XP is marked.' + override: + title: Update Manually + info: Changing the current XP or level manually will cause the pending XP to be discarded unless this is unchecked. + resetCheckbox: Reset bonds, flags & end of session questions after saving + xp: Override XP + level: Override Level + +armor: + title: Armor + dialog: + title: Armor + autoArmor: Use armor from class & equipped items + +richText: + preview: Preview + help: Formatting Help + bold: Bold + italic: Italic + headings: Headings + heading(int depth): Heading $depth + bulletList: Bullet List + numberedList: Numbered List + checkList: + unchecked: Checklist (Unchecked) + checked: Checklist (Checked) + url: URL + imageURL: Image URL + table: Table + header(Object n): Header $n + cell(int n): Cell $n + markdownPreview: Markdown Preview + +customRolls: + title: Quick Roll Buttons + left: Left Button + right: Right Button + buttonLabel: Button Label + specialDice: + title: Special Dice + button(String btn): "${_select(btn, {'damage': 'Damage'}, other: btn)}" + tooltip: + rollNormal(String dice): Roll $dice\n* Rolling with debility + rollWithDebility(String dice): Roll $dice + presets: + title: Presets + basicAction: Basic Action + hackAndSlash: Hack & Slash + volley: Volley + discernRealities: Discern Realities + +sessionMarks: + title: Bonds & Flags + bond: Bond + bonds: Bonds + flag: Flag + flags: Flags + noData: You have no bonds or flags. You can add some using the edit button above, then mark them off as completed as you go along your adventure. + info: You can add, update or remove bonds & flags using the edit icon above. + endOfSession: + q1: Did we learn something new and important about the world? + q2: Did we overcome a notable monster or enemy? + q3: Did we loot a memorable treasure? + +createCharacter: + characterClass: + noSelection: No class selected (required) + description(int hp, int load, String damageDice): 'Base HP: $hp, Load: $load, Damage Dice: $damageDice' + basicInfo: + defaultName: Unnamed Traveler + helpText: Select name & picture (required) + description(String cls): Level 1 $cls + startingGear: + helpText: Select your starting gear determined by class (optional) + coins(String amt): "$amt ${_plural(double.tryParse(amt)?.ceil() ?? 0, one: 'coin', many: 'coins')}" + item(String amt, String name): $amt × $name + count: + withMax(int cnt, int max): '$cnt selected (class allowance: $max)' + noMax(int cnt): $cnt selected + movesSpells: + title: Moves & Spells + description(int moves, int spells): $moves Moves, $spells Spells selected + +account: + details: + title: Account details + displayName: + title: Change Display Name + label: Display name + placeholder: Enter your public display name + success: Display name changed successfully + image: + title: Change Profile Picture + subtitle: Change your profile picture + email: + title: Change Email Address + label: Email address + placeholder: Enter a new email address + success: Email changed successfully + password: + title: Change Password + subtitle: Change your password + success: Password changed successfully + label: New password + placeholder: Enter your new password + visibility: + show: Show password + hide: Hide password + confirm: + label: Confirm New Password + placeholder: Enter the same password again + error: Passwords do not match + providers: + title: Connected logins + deleteAccount: + title: Delete Your Account + success: A deletion request for your account was sent successfully + +actions: + moves: + basic: Basic Moves + special: Special Moves + +abilityScores: + info: You can drag & drop the stat cards to change the order in which they appear throughout this character's screens. + rollButton: + stat: Roll +{stat} + randStat: Roll random stat + stats: + bond: + name: Bond + description: When a move has you roll+bond you'll count the number of bonds you have with the character in question and add that to the roll. + debility: + name: Lonely + description: + cha: + description: Measures a character's personality, personal magnetism, ability to lead, and appearance. + name: Charisma + debility: + name: Scarred + description: It may not be permanent, but for now you don't look so good. + con: + description: Represents your character's health and stamina. + name: Constitution + debility: + name: Sick + description: Something just isn't right inside. Maybe you've got a disease or a wasting illness. Maybe you just drank too much ale last night and it's coming back to haunt you. + dex: + description: Measures agility, reflexes and balance. + name: Dexterity + debility: + name: Shaky + description: You're unsteady on your feet and you've got a shake in your hands. + str: + description: Measures muscle and physical power. + name: Strength + debility: + name: Weak + description: You can't exert much force. Maybe it's just fatigue and injury, or maybe your strength was drained by magic. + wis: + description: Describes a character's willpower, common sense, awareness, and intuition. + name: Wisdom + debility: + name: Confused + description: Ears ringing. Vision blurred. You're more than a little out of it. + intl: + description: Determines how well your character learns and reasons. + name: Intelligence + debility: + name: Stunned + description: That last knock to the head shook something loose. Brain not work so good. + form: + modifierValueLabel(String mod): Modifier:\n$mod + debilityDescription: + label: Debility Description + description: A description of the effect causing the debility and/or how it affects your character + debilityName: + label: Debility Name + description: The name for the debility that occurs when this stat is debilitated (takes -1 until recovered). + description: + label: Ability Score Description + description: A description of what this ability score represents + key: + label: Ability Score Key + description: A 3-letter unique key that identifies this ability score in dice and is used as the short label for the modifier value (and not the actual score) + name: + label: Ability Score Name + description: The name of this ability score + icon: + label: Icon + button: Change Icon + +feedback: + title: Send App Feedback + send: Send + form: + title: + label: Feedback title + body: + label: Problem, idea or feedback description + email: + label: Enter your email + success: + title: Feedback sent! + message: Thank you for your feedback! We will review your feedback as soon as we can. + +migration: + title: Welcome to\nDungeon Paper 2! + subtitle: To get started, pick a username and the language for the rulebook & app. If you already have an existing Dungeon Paper account your data might take a few seconds to migrate. + username: + label: Username + placeholder: Pick a unique username + info: Your username is unique and can not be changed later, so think carefully! It will be used to identify all your library items when publishing. + language: + data: Default data language + +backup: + title: Export/Import + importing: + title: Import + button: Import + progress: + title: Importing... + processing(String ent): Processing $ent... + file: + browse: Browse... + clearFile: Clear selected file + info: To start importing, pick the file you want to import from.\nYou will then be able to select what to save and what to leave out. + success: + title: Import Successful + message: Your data was imported from file successfully + error: + title: Import Failed + message: Something went wrong.\nTry again or contact support if this persists + exporting: + title: Export + button: Export + error: + title: Export Failed + message: Something went wrong.\nTry again or contact support if this persists + success: + title: Export Successful + message: Your data was exported to file successfully diff --git a/lib/main.dart b/lib/main.dart index b8cebde5..4e2cfb48 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -5,8 +5,7 @@ import 'package:dungeon_paper/core/pref_keys.dart'; import 'package:dungeon_paper/core/remote_config.dart'; import 'package:dungeon_paper/core/shared_preferences.dart'; import 'package:dungeon_paper/core/utils/secrets_base.dart'; -import 'package:dungeon_paper/generated/intl/messages_all.dart'; -import 'package:dungeon_paper/generated/l10n.dart'; +import 'package:dungeon_paper/i18n.dart'; import 'package:dynamic_themes/dynamic_themes.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -22,8 +21,6 @@ void main() async { final widgetsBinding = WidgetsFlutterBinding.ensureInitialized(); FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding); - await initializeMessages('en'); - await S.load(const Locale('en', 'US')); await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); await loadSharedPrefs(); await initRemoteConfig(); @@ -53,7 +50,9 @@ class DungeonPaperApp extends StatelessWidget { @override Widget build(BuildContext context) { final platformBrightness = getCurrentPlatformBrightness(); - final defaultTheme = platformBrightness == Brightness.light ? AppThemes.parchment : AppThemes.dark; + final defaultTheme = platformBrightness == Brightness.light + ? AppThemes.parchment + : AppThemes.dark; return DynamicTheme( themeCollection: themeCollection, @@ -61,7 +60,7 @@ class DungeonPaperApp extends StatelessWidget { builder: (context, value) { return GetMaterialApp( scrollBehavior: MultiPlatformScrollBehavior(), - title: S.current.appName, + title: tr.app.name, theme: value, initialRoute: AppPages.initial, getPages: AppPages.routes, diff --git a/pubspec.lock b/pubspec.lock index 2ca28cef..7044ffcd 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -624,6 +624,15 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" + i18n: + dependency: "direct main" + description: + path: "." + ref: next + resolved-ref: "8b5c9110c6e87773b91a5b0f3505f99279212da6" + url: "https://github.com/chenasraf/i18n.git" + source: git + version: "4.0.8" icons_launcher: dependency: "direct main" description: @@ -936,6 +945,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.3" + quick_log: + dependency: transitive + description: + name: quick_log + sha256: b684b8ac632a12059412116fed3081260dc2a5e4b6dcf00dbfd0744cc57e3d96 + url: "https://pub.dev" + source: hosted + version: "5.3.1" quiver: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index f4d1f54b..5781ffe8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -30,7 +30,7 @@ dependencies: cloud_firestore: ^4.13.3 cupertino_icons: ^1.0.2 # dungeon_world_data: - # path: ../dungeon_world_data + # path: ../dungeon_world_data dungeon_world_data: ^3.0.1 dynamic_themes: ^1.1.0 email_validator: ^2.0.1 @@ -49,6 +49,13 @@ dependencies: get: ^4.6.1 google_sign_in: ^5.3.3 http: ^0.13.4 + # i18n: ^4.0.8 + # i18n: + # path: ../i18n + i18n: + git: + url: https://github.com/chenasraf/i18n.git + ref: next icons_launcher: ^2.0.2 image_cropper: ^2.0.2 intl: ^0.17.0 diff --git a/script_runner.yaml b/script_runner.yaml index 89b757a8..2cdaee5c 100644 --- a/script_runner.yaml +++ b/script_runner.yaml @@ -1,5 +1,9 @@ shell: /bin/zsh scripts: + # Developer + - name: runner + cmd: dart run build_runner watch + description: Run Build Runner in watch mode # Android - name: build:android:apk cmd: flutter build apk diff --git a/scripts/get_version.dart b/scripts/get_version.dart index 7a3891b0..81c8cc6a 100644 --- a/scripts/get_version.dart +++ b/scripts/get_version.dart @@ -3,8 +3,13 @@ import 'dart:io'; void main() { // get version from pubspec.yaml final pubspecFile = File('pubspec.yaml'); - final version = - pubspecFile.readAsStringSync().split('\n').firstWhere((x) => x.startsWith('version:')).split(':').last.trim(); + final version = pubspecFile + .readAsStringSync() + .split('\n') + .firstWhere((x) => x.startsWith('version:')) + .split(':') + .last + .trim(); // ignore: avoid_print print(version); } diff --git a/test/utils/string_utils_test.dart b/test/utils/string_utils_test.dart index c92d7571..361369fb 100644 --- a/test/utils/string_utils_test.dart +++ b/test/utils/string_utils_test.dart @@ -5,13 +5,16 @@ void main() { group('String Utils', () { group('splitIntoWords', () { test('should work with spaces', () { - expect(splitIntoWords('one two three'), equals(['one', 'two', 'three'])); + expect( + splitIntoWords('one two three'), equals(['one', 'two', 'three'])); }); test('should work with underscores', () { - expect(splitIntoWords('one_two_three'), equals(['one', 'two', 'three'])); + expect( + splitIntoWords('one_two_three'), equals(['one', 'two', 'three'])); }); test('should work with numbers', () { - expect(splitIntoWords('one_2_two_three'), equals(['one', '2', 'two', 'three'])); + expect(splitIntoWords('one_2_two_three'), + equals(['one', '2', 'two', 'three'])); }); test('should work with pascalCase', () { expect(splitIntoWords('OneTwoThree'), equals(['One', 'Two', 'Three']));