From 6ac2e4543bacded9b1bd0fe5a60b1c6521fad585 Mon Sep 17 00:00:00 2001 From: Sandi Milohanic Date: Mon, 17 Oct 2022 17:03:53 +0200 Subject: [PATCH 1/8] issues#208 - Translate exercise filter headers https://github.com/wger-project/flutter/issues/208 --- lib/helpers/i18n.dart | 6 ++++++ lib/widgets/exercises/filter_modal.dart | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/helpers/i18n.dart b/lib/helpers/i18n.dart index ad6fa731..7da7ad62 100644 --- a/lib/helpers/i18n.dart +++ b/lib/helpers/i18n.dart @@ -99,6 +99,12 @@ String getTranslation(String value, BuildContext context) { case 'Legs': return AppLocalizations.of(context).legs; + + case 'Category': + return AppLocalizations.of(context).category; + + case 'Equipment': + return AppLocalizations.of(context).equipment; default: return 'NOT TRANSLATED'; } diff --git a/lib/widgets/exercises/filter_modal.dart b/lib/widgets/exercises/filter_modal.dart index 27ce3997..29a97d99 100644 --- a/lib/widgets/exercises/filter_modal.dart +++ b/lib/widgets/exercises/filter_modal.dart @@ -61,7 +61,7 @@ class _ExerciseFilterModalBodyState extends State { headerBuilder: (context, isExpanded) { return Container( child: Text( - filterCategory.title, + getTranslation(filterCategory.title, context), style: theme.textTheme.headline5, ), ); From 9aa480c0dc96c67fd3bb5eab63d3deff9ac6d772 Mon Sep 17 00:00:00 2001 From: Sandi Milohanic Date: Fri, 28 Oct 2022 12:12:36 +0200 Subject: [PATCH 2/8] Translate exercise filter headers #208 --- lib/providers/exercises.dart | 14 ++++++++------ lib/screens/home_tabs_screen.dart | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/providers/exercises.dart b/lib/providers/exercises.dart index b8850333..5f641dbe 100644 --- a/lib/providers/exercises.dart +++ b/lib/providers/exercises.dart @@ -25,6 +25,7 @@ import 'package:json_annotation/json_annotation.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:wger/exceptions/no_such_entry_exception.dart'; import 'package:wger/helpers/consts.dart'; +import 'package:wger/main.dart'; import 'package:wger/models/exercises/alias.dart'; import 'package:wger/models/exercises/base.dart'; import 'package:wger/models/exercises/category.dart'; @@ -37,6 +38,7 @@ import 'package:wger/models/exercises/muscle.dart'; import 'package:wger/models/exercises/variation.dart'; import 'package:wger/models/exercises/video.dart'; import 'package:wger/providers/base_provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class ExercisesProvider with ChangeNotifier { final WgerBaseProvider baseProvider; @@ -104,7 +106,7 @@ class ExercisesProvider with ChangeNotifier { } // Initialize filters for exercises search in exercises list - void _initFilters() { + void _initFilters(BuildContext context) { if (_muscles.isEmpty || _equipment.isEmpty || _filters != null) { return; } @@ -112,7 +114,7 @@ class ExercisesProvider with ChangeNotifier { setFilters( Filters( exerciseCategories: FilterCategory( - title: 'Category', + title: AppLocalizations.of(context).category, items: Map.fromEntries( _categories.map( (category) => MapEntry(category, false), @@ -120,7 +122,7 @@ class ExercisesProvider with ChangeNotifier { ), ), equipment: FilterCategory( - title: 'Equipment', + title: AppLocalizations.of(context).equipment, items: Map.fromEntries( _equipment.map( (singleEquipment) => MapEntry(singleEquipment, false), @@ -367,7 +369,7 @@ class ExercisesProvider with ChangeNotifier { } } - Future fetchAndSetExercises() async { + Future fetchAndSetExercises(BuildContext context) async { clear(); // Load exercises from cache, if available @@ -384,7 +386,7 @@ class ExercisesProvider with ChangeNotifier { cacheData['variations'].forEach((e) => _variations.add(Variation.fromJson(e))); cacheData['bases'].forEach((e) => _exerciseBases.add(readExerciseBaseFromBaseInfo(e))); - _initFilters(); + _initFilters(context); log("Read ${_exerciseBases.length} exercises from cache. Valid till ${cacheData['expiresIn']}"); return; } @@ -420,7 +422,7 @@ class ExercisesProvider with ChangeNotifier { log("Saved ${_exerciseBases.length} exercises to cache. Valid till ${cacheData['expiresIn']}"); await prefs.setString(PREFS_EXERCISES, json.encode(cacheData)); - _initFilters(); + _initFilters(context); notifyListeners(); } on MissingRequiredKeysException catch (error) { log(error.missingKeys.toString()); diff --git a/lib/screens/home_tabs_screen.dart b/lib/screens/home_tabs_screen.dart index 3012770a..0dc3ca29 100644 --- a/lib/screens/home_tabs_screen.dart +++ b/lib/screens/home_tabs_screen.dart @@ -89,7 +89,7 @@ class _HomeTabsScreenState extends State with SingleTickerProvid userProvider.fetchAndSetProfile(), workoutPlansProvider.fetchAndSetUnits(), nutritionPlansProvider.fetchIngredientsFromCache(), - exercisesProvider.fetchAndSetExercises(), + exercisesProvider.fetchAndSetExercises(context), ]); // Plans, weight and gallery From 1606191893de683af2d21f24b3a3b7ec3607acbb Mon Sep 17 00:00:00 2001 From: Sandi Milohanic Date: Fri, 28 Oct 2022 12:16:19 +0200 Subject: [PATCH 3/8] removed added translations --- lib/helpers/i18n.dart | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/helpers/i18n.dart b/lib/helpers/i18n.dart index 7da7ad62..537cb883 100644 --- a/lib/helpers/i18n.dart +++ b/lib/helpers/i18n.dart @@ -99,12 +99,7 @@ String getTranslation(String value, BuildContext context) { case 'Legs': return AppLocalizations.of(context).legs; - - case 'Category': - return AppLocalizations.of(context).category; - - case 'Equipment': - return AppLocalizations.of(context).equipment; + default: return 'NOT TRANSLATED'; } From adf91a230f3c5dbaa353808217bbf493ffb2caa4 Mon Sep 17 00:00:00 2001 From: Sandi Milohanic Date: Fri, 28 Oct 2022 16:26:39 +0200 Subject: [PATCH 4/8] update test cases --- test/workout/gym_mode_screen_test.mocks.dart | 2 +- test/workout/workout_set_form_test.mocks.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/workout/gym_mode_screen_test.mocks.dart b/test/workout/gym_mode_screen_test.mocks.dart index 63fb4e2f..8f737717 100644 --- a/test/workout/gym_mode_screen_test.mocks.dart +++ b/test/workout/gym_mode_screen_test.mocks.dart @@ -358,7 +358,7 @@ class MockExercisesProvider extends _i1.Mock implements _i8.ExercisesProvider { returnValueForMissingStub: _i9.Future.value(), ) as _i9.Future); @override - _i9.Future fetchAndSetExercises() => (super.noSuchMethod( + _i9.Future fetchAndSetExercises(context) => (super.noSuchMethod( Invocation.method( #fetchAndSetExercises, [], diff --git a/test/workout/workout_set_form_test.mocks.dart b/test/workout/workout_set_form_test.mocks.dart index a87bd4e3..b8865320 100644 --- a/test/workout/workout_set_form_test.mocks.dart +++ b/test/workout/workout_set_form_test.mocks.dart @@ -358,7 +358,7 @@ class MockExercisesProvider extends _i1.Mock implements _i8.ExercisesProvider { returnValueForMissingStub: _i9.Future.value(), ) as _i9.Future); @override - _i9.Future fetchAndSetExercises() => (super.noSuchMethod( + _i9.Future fetchAndSetExercises(context) => (super.noSuchMethod( Invocation.method( #fetchAndSetExercises, [], From 40905d254f548b8a9d4673d97a4bec285f700a9e Mon Sep 17 00:00:00 2001 From: Sandi Milohanic Date: Sat, 29 Oct 2022 21:22:08 +0200 Subject: [PATCH 5/8] Add simple WYSIWYG editor for exercise descriptions #189 --- .../add_exercise_html_editor.dart | 81 +++++++++++++++++++ .../add_exercise/steps/step3description.dart | 12 +-- pubspec.yaml | 1 + 3 files changed, 85 insertions(+), 9 deletions(-) create mode 100644 lib/widgets/add_exercise/add_exercise_html_editor.dart diff --git a/lib/widgets/add_exercise/add_exercise_html_editor.dart b/lib/widgets/add_exercise/add_exercise_html_editor.dart new file mode 100644 index 00000000..5933f3b6 --- /dev/null +++ b/lib/widgets/add_exercise/add_exercise_html_editor.dart @@ -0,0 +1,81 @@ +import 'dart:async'; +import 'dart:ffi'; +import 'package:flutter/material.dart'; +import 'package:html_editor_enhanced/html_editor.dart'; +import 'package:provider/provider.dart'; +import 'package:wger/providers/add_exercise.dart'; + +class AddExerciseHtmlEditor extends StatefulWidget { + const AddExerciseHtmlEditor({ + Key? key, + this.helperText = '', + }) : super(key: key); + + final String helperText; + + @override + _AddExerciseHtmlEditorState createState() => _AddExerciseHtmlEditorState(); +} + +class _AddExerciseHtmlEditorState extends State { + @override + Widget build(BuildContext context) { + final addExerciseProvider = context.read(); + final HtmlEditorController editorController = HtmlEditorController( + processInputHtml: true, + processNewLineAsBr: false, + processOutputHtml: true + ); + return Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + HtmlEditor( + controller: editorController, + htmlToolbarOptions: const HtmlToolbarOptions( + toolbarPosition: ToolbarPosition.belowEditor, + toolbarType: ToolbarType.nativeScrollable, + defaultToolbarButtons: [ + FontButtons(bold: true, + underline: true, + italic: true, + strikethrough: false, + superscript: false, + subscript: false, + clearAll: false + ), + ListButtons( + ol: true, + ul: true, + listStyles: false + ), + ParagraphButtons( + textDirection: false, + lineHeight: false, + caseConverter: false, + increaseIndent: false, + decreaseIndent: false, + alignLeft: false, + alignCenter: false, + alignRight: false, + alignJustify: false + ), + ] + ), + htmlEditorOptions: HtmlEditorOptions( + hint: widget.helperText, + shouldEnsureVisible: true, + ), + otherOptions: const OtherOptions( + height: 200, + ), + callbacks: Callbacks(onChangeContent: (String? currentHtml) { + addExerciseProvider.descriptionEn = currentHtml!; + }, + ), + ), + ], + ), + ); + } +} diff --git a/lib/widgets/add_exercise/steps/step3description.dart b/lib/widgets/add_exercise/steps/step3description.dart index fad46ba8..806222be 100644 --- a/lib/widgets/add_exercise/steps/step3description.dart +++ b/lib/widgets/add_exercise/steps/step3description.dart @@ -1,9 +1,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; -import 'package:wger/helpers/exercises/forms.dart'; import 'package:wger/providers/add_exercise.dart'; -import 'package:wger/widgets/add_exercise/add_exercise_text_area.dart'; +import 'package:wger/widgets/add_exercise/add_exercise_html_editor.dart'; class Step3Description extends StatelessWidget { final GlobalKey formkey; @@ -17,13 +16,8 @@ class Step3Description extends StatelessWidget { key: formkey, child: Column( children: [ - AddExerciseTextArea( - onChange: (value) => {}, - title: '${AppLocalizations.of(context).description}*', - isRequired: true, - isMultiline: true, - validator: (name) => validateDescription(name, context), - onSaved: (String? description) => addExerciseProvider.descriptionEn = description!, + AddExerciseHtmlEditor( + helperText: AppLocalizations.of(context).description, ), ], ), diff --git a/pubspec.yaml b/pubspec.yaml index 4bb31098..3e9fddf5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -58,6 +58,7 @@ dependencies: carousel_slider: ^4.1.1 multi_select_flutter: ^4.1.2 flutter_svg: ^0.23.0+1 + html_editor_enhanced: ^2.5.0 dev_dependencies: flutter_test: From e0615c2c42d808099fa85263c03300c4825393c2 Mon Sep 17 00:00:00 2001 From: Sandi Milohanic Date: Sat, 29 Oct 2022 21:46:07 +0200 Subject: [PATCH 6/8] Add simple WYSIWYG editor for exercise descriptions #189 remove column --- .../add_exercise_html_editor.dart | 90 +++++++++---------- 1 file changed, 43 insertions(+), 47 deletions(-) diff --git a/lib/widgets/add_exercise/add_exercise_html_editor.dart b/lib/widgets/add_exercise/add_exercise_html_editor.dart index 5933f3b6..098dffd5 100644 --- a/lib/widgets/add_exercise/add_exercise_html_editor.dart +++ b/lib/widgets/add_exercise/add_exercise_html_editor.dart @@ -28,53 +28,49 @@ class _AddExerciseHtmlEditorState extends State { ); return Padding( padding: const EdgeInsets.all(8.0), - child: Column( - children: [ - HtmlEditor( - controller: editorController, - htmlToolbarOptions: const HtmlToolbarOptions( - toolbarPosition: ToolbarPosition.belowEditor, - toolbarType: ToolbarType.nativeScrollable, - defaultToolbarButtons: [ - FontButtons(bold: true, - underline: true, - italic: true, - strikethrough: false, - superscript: false, - subscript: false, - clearAll: false - ), - ListButtons( - ol: true, - ul: true, - listStyles: false - ), - ParagraphButtons( - textDirection: false, - lineHeight: false, - caseConverter: false, - increaseIndent: false, - decreaseIndent: false, - alignLeft: false, - alignCenter: false, - alignRight: false, - alignJustify: false - ), - ] - ), - htmlEditorOptions: HtmlEditorOptions( - hint: widget.helperText, - shouldEnsureVisible: true, - ), - otherOptions: const OtherOptions( - height: 200, - ), - callbacks: Callbacks(onChangeContent: (String? currentHtml) { - addExerciseProvider.descriptionEn = currentHtml!; - }, - ), - ), - ], + child: HtmlEditor( + controller: editorController, + htmlToolbarOptions: const HtmlToolbarOptions( + toolbarPosition: ToolbarPosition.belowEditor, + toolbarType: ToolbarType.nativeScrollable, + defaultToolbarButtons: [ + FontButtons(bold: true, + underline: true, + italic: true, + strikethrough: false, + superscript: false, + subscript: false, + clearAll: false + ), + ListButtons( + ol: true, + ul: true, + listStyles: false + ), + ParagraphButtons( + textDirection: false, + lineHeight: false, + caseConverter: false, + increaseIndent: false, + decreaseIndent: false, + alignLeft: false, + alignCenter: false, + alignRight: false, + alignJustify: false + ), + ] + ), + htmlEditorOptions: HtmlEditorOptions( + hint: widget.helperText, + shouldEnsureVisible: true, + ), + otherOptions: const OtherOptions( + height: 200, + ), + callbacks: Callbacks(onChangeContent: (String? currentHtml) { + addExerciseProvider.descriptionEn = currentHtml!; + }, + ), ), ); } From 0c082bc14b297f6fb94b4cad1c2bbe813de8b92e Mon Sep 17 00:00:00 2001 From: Sandi Milohanic Date: Sun, 30 Oct 2022 07:26:59 +0100 Subject: [PATCH 7/8] Text on exercise not gets text well, fixed --- lib/widgets/exercises/filter_modal.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/widgets/exercises/filter_modal.dart b/lib/widgets/exercises/filter_modal.dart index 29a97d99..27ce3997 100644 --- a/lib/widgets/exercises/filter_modal.dart +++ b/lib/widgets/exercises/filter_modal.dart @@ -61,7 +61,7 @@ class _ExerciseFilterModalBodyState extends State { headerBuilder: (context, isExpanded) { return Container( child: Text( - getTranslation(filterCategory.title, context), + filterCategory.title, style: theme.textTheme.headline5, ), ); From c958251104fb296a57ae36c0ca7941ad06662a2d Mon Sep 17 00:00:00 2001 From: Sandi Milohanic Date: Sun, 30 Oct 2022 09:30:42 +0100 Subject: [PATCH 8/8] Improvements - Added localization for loading text --- lib/screens/splash_screen.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/screens/splash_screen.dart b/lib/screens/splash_screen.dart index c3b4df92..9dc14a7e 100644 --- a/lib/screens/splash_screen.dart +++ b/lib/screens/splash_screen.dart @@ -17,13 +17,14 @@ */ import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class SplashScreen extends StatelessWidget { @override Widget build(BuildContext context) { - return const Scaffold( + return Scaffold( body: Center( - child: Text('Loading...'), + child: Text(AppLocalizations.of(context).loadingText), ), ); }