Skip to content

Commit 1e40e1d

Browse files
authored
feat: move language dropdowns into learning settings dialog (#1695)
1 parent 75a0d1e commit 1e40e1d

File tree

3 files changed

+176
-95
lines changed

3 files changed

+176
-95
lines changed

lib/pangea/learning_settings/pages/settings_learning.dart

+46
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@ import 'package:country_picker/country_picker.dart';
44

55
import 'package:fluffychat/pangea/common/controllers/pangea_controller.dart';
66
import 'package:fluffychat/pangea/learning_settings/enums/language_level_type_enum.dart';
7+
import 'package:fluffychat/pangea/learning_settings/models/language_model.dart';
78
import 'package:fluffychat/pangea/learning_settings/pages/settings_learning_view.dart';
9+
import 'package:fluffychat/pangea/learning_settings/utils/language_list_util.dart';
810
import 'package:fluffychat/pangea/learning_settings/widgets/p_language_dialog.dart';
911
import 'package:fluffychat/pangea/spaces/models/space_model.dart';
1012
import 'package:fluffychat/pangea/toolbar/controllers/tts_controller.dart';
1113
import 'package:fluffychat/pangea/user/models/user_model.dart';
14+
import 'package:fluffychat/widgets/future_loading_dialog.dart';
1215
import 'package:fluffychat/widgets/matrix.dart';
1316

1417
class SettingsLearning extends StatefulWidget {
@@ -22,6 +25,22 @@ class SettingsLearningController extends State<SettingsLearning> {
2225
PangeaController pangeaController = MatrixState.pangeaController;
2326
final tts = TtsController();
2427

28+
LanguageModel? get selectedSourceLanguage {
29+
return userL1 ?? pangeaController.languageController.systemLanguage;
30+
}
31+
32+
LanguageModel? get selectedTargetLanguage {
33+
return userL2 ??
34+
((selectedSourceLanguage?.langCode != 'en')
35+
? PangeaLanguage.byLangCode('en')!
36+
: PangeaLanguage.byLangCode('es')!);
37+
}
38+
39+
LanguageModel? get userL1 => pangeaController.languageController.userL1;
40+
LanguageModel? get userL2 => pangeaController.languageController.userL2;
41+
42+
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
43+
2544
@override
2645
void initState() {
2746
super.initState();
@@ -34,6 +53,33 @@ class SettingsLearningController extends State<SettingsLearning> {
3453
super.dispose();
3554
}
3655

56+
Future<void> setSelectedLanguage({
57+
LanguageModel? sourceLanguage,
58+
LanguageModel? targetLanguage,
59+
}) async {
60+
if (targetLanguage == null && sourceLanguage == null) return;
61+
if (!formKey.currentState!.validate()) return;
62+
63+
await showFutureLoadingDialog(
64+
context: context,
65+
future: () async {
66+
pangeaController.userController.updateProfile(
67+
(profile) {
68+
if (sourceLanguage != null) {
69+
profile.userSettings.sourceLanguage = sourceLanguage.langCode;
70+
}
71+
if (targetLanguage != null) {
72+
profile.userSettings.targetLanguage = targetLanguage.langCode;
73+
}
74+
return profile;
75+
},
76+
waitForDataInSync: true,
77+
);
78+
},
79+
);
80+
if (mounted) setState(() {});
81+
}
82+
3783
void setPublicProfile(bool isPublic) {
3884
pangeaController.userController.updateProfile(
3985
(profile) {

lib/pangea/learning_settings/pages/settings_learning_view.dart

+116-77
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ import 'package:fluffychat/config/app_config.dart';
88
import 'package:fluffychat/pangea/chat_settings/widgets/language_level_dropdown.dart';
99
import 'package:fluffychat/pangea/common/constants/model_keys.dart';
1010
import 'package:fluffychat/pangea/common/widgets/full_width_dialog.dart';
11+
import 'package:fluffychat/pangea/learning_settings/models/language_model.dart';
1112
import 'package:fluffychat/pangea/learning_settings/pages/settings_learning.dart';
1213
import 'package:fluffychat/pangea/learning_settings/widgets/country_picker_tile.dart';
13-
import 'package:fluffychat/pangea/learning_settings/widgets/language_tile.dart';
14+
import 'package:fluffychat/pangea/learning_settings/widgets/p_language_dropdown.dart';
1415
import 'package:fluffychat/pangea/learning_settings/widgets/p_settings_switch_list_tile.dart';
1516
import 'package:fluffychat/pangea/spaces/models/space_model.dart';
1617
import 'package:fluffychat/utils/platform_infos.dart';
@@ -46,88 +47,126 @@ class SettingsLearningView extends StatelessWidget {
4647
iconColor: Theme.of(context).textTheme.bodyLarge!.color,
4748
child: MaxWidthBody(
4849
withScrolling: true,
49-
child: Column(
50-
children: [
51-
LanguageTile(controller),
52-
CountryPickerTile(controller),
53-
Padding(
54-
padding: const EdgeInsets.only(top: 16.0, bottom: 24.0),
55-
child: LanguageLevelDropdown(
56-
initialLevel: controller.cefrLevel,
57-
onChanged: controller.setCefrLevel,
50+
child: Form(
51+
key: controller.formKey,
52+
child: Column(
53+
children: [
54+
const SizedBox(height: 8.0),
55+
PLanguageDropdown(
56+
onChange: (lang) =>
57+
controller.setSelectedLanguage(sourceLanguage: lang),
58+
initialLanguage: controller.selectedSourceLanguage ??
59+
LanguageModel.unknown,
60+
languages: MatrixState
61+
.pangeaController.pLanguageStore.baseOptions,
62+
isL2List: false,
63+
decorationText: L10n.of(context).myBaseLanguage,
64+
validator: (lang) {
65+
if (lang == controller.selectedTargetLanguage) {
66+
return L10n.of(context).noIdenticalLanguages;
67+
}
68+
return null;
69+
},
5870
),
59-
),
60-
const Divider(height: 1),
61-
ListTile(
62-
title: Text(L10n.of(context).toggleToolSettingsDescription),
63-
),
64-
for (final toolSetting in ToolSetting.values
65-
.where((tool) => tool.isAvailableSetting))
66-
Column(
67-
children: [
68-
ProfileSettingsSwitchListTile.adaptive(
69-
defaultValue: controller.getToolSetting(toolSetting),
70-
title: toolSetting.toolName(context),
71-
subtitle: toolSetting == ToolSetting.enableTTS &&
72-
!controller.tts.isLanguageFullySupported
73-
? null
74-
: toolSetting.toolDescription(context),
75-
onChange: (bool value) =>
76-
controller.updateToolSetting(
77-
toolSetting,
78-
value,
79-
),
80-
enabled: toolSetting == ToolSetting.enableTTS
81-
? controller.tts.isLanguageFullySupported
82-
: true,
83-
),
84-
if (toolSetting == ToolSetting.enableTTS &&
85-
!controller.tts.isLanguageFullySupported)
86-
ListTile(
87-
trailing: const Padding(
88-
padding: EdgeInsets.symmetric(horizontal: 16.0),
89-
child: Icon(Icons.info_outlined),
71+
const SizedBox(height: 24.0),
72+
PLanguageDropdown(
73+
onChange: (lang) =>
74+
controller.setSelectedLanguage(targetLanguage: lang),
75+
initialLanguage: controller.selectedTargetLanguage,
76+
languages: MatrixState
77+
.pangeaController.pLanguageStore.targetOptions,
78+
isL2List: true,
79+
decorationText: L10n.of(context).iWantToLearn,
80+
validator: (lang) {
81+
if (lang == controller.selectedSourceLanguage) {
82+
return L10n.of(context).noIdenticalLanguages;
83+
}
84+
return null;
85+
},
86+
),
87+
const SizedBox(height: 16.0),
88+
CountryPickerTile(controller),
89+
Padding(
90+
padding: const EdgeInsets.only(top: 16.0, bottom: 24.0),
91+
child: LanguageLevelDropdown(
92+
initialLevel: controller.cefrLevel,
93+
onChanged: controller.setCefrLevel,
94+
),
95+
),
96+
const Divider(height: 1),
97+
ListTile(
98+
title:
99+
Text(L10n.of(context).toggleToolSettingsDescription),
100+
),
101+
for (final toolSetting in ToolSetting.values
102+
.where((tool) => tool.isAvailableSetting))
103+
Column(
104+
children: [
105+
ProfileSettingsSwitchListTile.adaptive(
106+
defaultValue:
107+
controller.getToolSetting(toolSetting),
108+
title: toolSetting.toolName(context),
109+
subtitle: toolSetting == ToolSetting.enableTTS &&
110+
!controller.tts.isLanguageFullySupported
111+
? null
112+
: toolSetting.toolDescription(context),
113+
onChange: (bool value) =>
114+
controller.updateToolSetting(
115+
toolSetting,
116+
value,
90117
),
91-
subtitle: RichText(
92-
text: TextSpan(
93-
text: L10n.of(context).couldNotFindTTS,
94-
style: DefaultTextStyle.of(context).style,
95-
children: [
96-
if (PlatformInfos.isWindows ||
97-
PlatformInfos.isAndroid)
98-
TextSpan(
99-
text: L10n.of(context)
100-
.ttsInstructionsHyperlink,
101-
style: const TextStyle(
102-
color: Colors.blue,
103-
fontWeight: FontWeight.bold,
104-
decoration: TextDecoration.underline,
118+
enabled: toolSetting == ToolSetting.enableTTS
119+
? controller.tts.isLanguageFullySupported
120+
: true,
121+
),
122+
if (toolSetting == ToolSetting.enableTTS &&
123+
!controller.tts.isLanguageFullySupported)
124+
ListTile(
125+
trailing: const Padding(
126+
padding: EdgeInsets.symmetric(horizontal: 16.0),
127+
child: Icon(Icons.info_outlined),
128+
),
129+
subtitle: RichText(
130+
text: TextSpan(
131+
text: L10n.of(context).couldNotFindTTS,
132+
style: DefaultTextStyle.of(context).style,
133+
children: [
134+
if (PlatformInfos.isWindows ||
135+
PlatformInfos.isAndroid)
136+
TextSpan(
137+
text: L10n.of(context)
138+
.ttsInstructionsHyperlink,
139+
style: const TextStyle(
140+
color: Colors.blue,
141+
fontWeight: FontWeight.bold,
142+
decoration: TextDecoration.underline,
143+
),
144+
recognizer: TapGestureRecognizer()
145+
..onTap = () {
146+
launchUrlString(
147+
PlatformInfos.isWindows
148+
? AppConfig
149+
.windowsTTSDownloadInstructions
150+
: AppConfig
151+
.androidTTSDownloadInstructions,
152+
);
153+
},
105154
),
106-
recognizer: TapGestureRecognizer()
107-
..onTap = () {
108-
launchUrlString(
109-
PlatformInfos.isWindows
110-
? AppConfig
111-
.windowsTTSDownloadInstructions
112-
: AppConfig
113-
.androidTTSDownloadInstructions,
114-
);
115-
},
116-
),
117-
],
155+
],
156+
),
118157
),
119158
),
120-
),
121-
],
159+
],
160+
),
161+
SwitchListTile.adaptive(
162+
value: controller.publicProfile,
163+
onChanged: controller.setPublicProfile,
164+
title: Text(L10n.of(context).publicProfileTitle),
165+
subtitle: Text(L10n.of(context).publicProfileDesc),
166+
activeColor: AppConfig.activeToggleColor,
122167
),
123-
SwitchListTile.adaptive(
124-
value: controller.publicProfile,
125-
onChanged: controller.setPublicProfile,
126-
title: Text(L10n.of(context).publicProfileTitle),
127-
subtitle: Text(L10n.of(context).publicProfileDesc),
128-
activeColor: AppConfig.activeToggleColor,
129-
),
130-
],
168+
],
169+
),
131170
),
132171
),
133172
),

lib/pangea/learning_settings/widgets/p_language_dropdown.dart

+14-18
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,20 @@
22

33
import 'package:flutter/material.dart';
44

5-
import 'package:dropdown_button2/dropdown_button2.dart';
6-
75
import 'package:fluffychat/config/themes.dart';
86
import 'package:fluffychat/pangea/learning_settings/enums/l2_support_enum.dart';
97
import 'package:fluffychat/pangea/learning_settings/models/language_model.dart';
108
import 'flag.dart';
119

12-
class PLanguageDropdown extends StatefulWidget {
10+
class PLanguageDropdown extends StatelessWidget {
1311
final List<LanguageModel> languages;
1412
final LanguageModel? initialLanguage;
1513
final Function(LanguageModel) onChange;
1614
final bool showMultilingual;
1715
final bool isL2List;
1816
final String decorationText;
1917
final String? error;
18+
final String? Function(LanguageModel?)? validator;
2019

2120
const PLanguageDropdown({
2221
super.key,
@@ -27,16 +26,12 @@ class PLanguageDropdown extends StatefulWidget {
2726
required this.decorationText,
2827
this.isL2List = false,
2928
this.error,
29+
this.validator,
3030
});
3131

32-
@override
33-
State<PLanguageDropdown> createState() => _PLanguageDropdownState();
34-
}
35-
36-
class _PLanguageDropdownState extends State<PLanguageDropdown> {
3732
@override
3833
Widget build(BuildContext context) {
39-
final List<LanguageModel> sortedLanguages = widget.languages;
34+
final List<LanguageModel> sortedLanguages = languages;
4035
final String systemLang = Localizations.localeOf(context).languageCode;
4136
final List<String> languagePriority = [systemLang, 'en', 'es'];
4237

@@ -65,42 +60,43 @@ class _PLanguageDropdownState extends State<PLanguageDropdown> {
6560
return Column(
6661
crossAxisAlignment: CrossAxisAlignment.start,
6762
children: [
68-
DropdownButtonFormField2<LanguageModel>(
69-
decoration: InputDecoration(labelText: widget.decorationText),
63+
DropdownButtonFormField<LanguageModel>(
64+
decoration: InputDecoration(labelText: decorationText),
7065
isExpanded: true,
7166
items: [
72-
if (widget.showMultilingual)
67+
if (showMultilingual)
7368
DropdownMenuItem(
7469
value: LanguageModel.multiLingual(context),
7570
child: LanguageDropDownEntry(
7671
languageModel: LanguageModel.multiLingual(context),
77-
isL2List: widget.isL2List,
72+
isL2List: isL2List,
7873
),
7974
),
8075
...sortedLanguages.map(
8176
(languageModel) => DropdownMenuItem(
8277
value: languageModel,
8378
child: LanguageDropDownEntry(
8479
languageModel: languageModel,
85-
isL2List: widget.isL2List,
80+
isL2List: isL2List,
8681
),
8782
),
8883
),
8984
],
90-
onChanged: (value) => widget.onChange(value!),
91-
value: widget.initialLanguage,
85+
onChanged: (value) => onChange(value!),
86+
value: initialLanguage,
87+
validator: (value) => validator?.call(value),
9288
),
9389
AnimatedSize(
9490
duration: FluffyThemes.animationDuration,
95-
child: widget.error == null
91+
child: error == null
9692
? const SizedBox.shrink()
9793
: Padding(
9894
padding: const EdgeInsets.symmetric(
9995
horizontal: 30,
10096
vertical: 5,
10197
),
10298
child: Text(
103-
widget.error!,
99+
error!,
104100
style: TextStyle(
105101
color: Theme.of(context).colorScheme.error,
106102
fontSize: 12,

0 commit comments

Comments
 (0)