feat: update country dropdown to match style of language dropdown (#1756)

pull/1605/head
ggurdin 9 months ago committed by GitHub
parent 3e72ee8088
commit ee72460aba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -77,8 +77,8 @@ class SettingsLearningController extends State<SettingsLearning> {
if (mounted) setState(() {}); if (mounted) setState(() {});
} }
void changeCountry(Country country) { void changeCountry(Country? country) {
_profile.userSettings.country = country.displayNameNoCountryCode; _profile.userSettings.country = country?.name;
if (mounted) setState(() {}); if (mounted) setState(() {});
} }
@ -146,7 +146,8 @@ class SettingsLearningController extends State<SettingsLearning> {
LanguageLevelTypeEnum get cefrLevel => _profile.userSettings.cefrLevel; LanguageLevelTypeEnum get cefrLevel => _profile.userSettings.cefrLevel;
String? get country => _profile.userSettings.country; Country? get country =>
CountryService().findByName(_profile.userSettings.country);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

@ -98,7 +98,7 @@ class SettingsLearningView extends StatelessWidget {
return null; return null;
}, },
), ),
CountryPickerTile(controller), CountryPickerDropdown(controller),
LanguageLevelDropdown( LanguageLevelDropdown(
initialLevel: controller.cefrLevel, initialLevel: controller.cefrLevel,
onChanged: controller.setCefrLevel, onChanged: controller.setCefrLevel,

@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:country_picker/country_picker.dart'; import 'package:country_picker/country_picker.dart';
import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:fluffychat/pangea/common/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/common/controllers/pangea_controller.dart';
@ -8,34 +9,117 @@ import 'package:fluffychat/pangea/learning_settings/pages/settings_learning.dart
import 'package:fluffychat/pangea/learning_settings/utils/country_display.dart'; import 'package:fluffychat/pangea/learning_settings/utils/country_display.dart';
import 'package:fluffychat/widgets/matrix.dart'; import 'package:fluffychat/widgets/matrix.dart';
class CountryPickerTile extends StatelessWidget { class CountryPickerDropdown extends StatefulWidget {
final SettingsLearningController learningController; final SettingsLearningController learningController;
final PangeaController pangeaController = MatrixState.pangeaController; final PangeaController pangeaController = MatrixState.pangeaController;
CountryPickerTile(this.learningController, {super.key}); CountryPickerDropdown(this.learningController, {super.key});
@override
CountryPickerDropdownState createState() => CountryPickerDropdownState();
}
class CountryPickerDropdownState extends State<CountryPickerDropdown> {
final TextEditingController _searchController = TextEditingController();
@override
void dispose() {
_searchController.dispose();
super.dispose();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final String displayName = CountryDisplayUtil.countryDisplayName( return DropdownButtonFormField2<Country>(
learningController.country, customButton: widget.learningController.country != null
context, ? CountryPickerTile(
) ?? widget.learningController.country!,
''; isDropdown: true,
)
: null,
decoration: InputDecoration(
labelText: L10n.of(context).countryInformation,
),
dropdownStyleData: const DropdownStyleData(
maxHeight: 300,
),
items: [
...CountryService().getAll().map(
(country) => DropdownMenuItem(
value: country,
child: CountryPickerTile(country),
),
),
],
onChanged: widget.learningController.changeCountry,
value: widget.learningController.country,
dropdownSearchData: DropdownSearchData(
searchController: _searchController,
searchInnerWidgetHeight: 50,
searchInnerWidget: Padding(
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
child: TextField(
autofocus: true,
controller: _searchController,
decoration: const InputDecoration(
prefixIcon: Icon(Icons.search),
),
),
),
searchMatchFn: (item, searchValue) {
final countryName = item.value?.name.toLowerCase();
if (countryName == null) return false;
final String flag = CountryDisplayUtil.flagEmoji( final search = searchValue.toLowerCase();
learningController.country, return countryName.startsWith(search);
},
),
onMenuStateChange: (isOpen) {
if (!isOpen) _searchController.clear();
},
); );
}
}
class CountryPickerTile extends StatelessWidget {
final Country country;
final bool isDropdown;
const CountryPickerTile(
this.country, {
super.key,
this.isDropdown = false,
});
return ListTile( @override
title: Text( Widget build(BuildContext context) {
"${L10n.of(context).countryInformation}: $displayName $flag", return Row(
children: [
Text(
CountryDisplayUtil.flagEmoji(country.name),
style: const TextStyle(fontSize: 25),
),
const SizedBox(width: 10),
Expanded(
child: Text(
CountryDisplayUtil.countryDisplayName(
country.name,
context,
) ??
'',
style: const TextStyle().copyWith(
color: Theme.of(context).textTheme.bodyLarge!.color,
fontSize: 14,
),
overflow: TextOverflow.ellipsis,
),
), ),
trailing: const Icon(Icons.edit_outlined), if (isDropdown)
onTap: () => showCountryPicker( Icon(
context: context, Icons.arrow_drop_down,
showPhoneCode: false, color: Theme.of(context).colorScheme.onSurfaceVariant,
onSelect: learningController.changeCountry,
), ),
],
); );
} }
} }

@ -2,12 +2,14 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:fluffychat/config/themes.dart'; import 'package:fluffychat/config/themes.dart';
import 'package:fluffychat/pangea/learning_settings/enums/l2_support_enum.dart'; import 'package:fluffychat/pangea/learning_settings/enums/l2_support_enum.dart';
import 'package:fluffychat/pangea/learning_settings/models/language_model.dart'; import 'package:fluffychat/pangea/learning_settings/models/language_model.dart';
import 'flag.dart'; import 'flag.dart';
class PLanguageDropdown extends StatelessWidget { class PLanguageDropdown extends StatefulWidget {
final List<LanguageModel> languages; final List<LanguageModel> languages;
final LanguageModel? initialLanguage; final LanguageModel? initialLanguage;
final Function(LanguageModel) onChange; final Function(LanguageModel) onChange;
@ -29,9 +31,22 @@ class PLanguageDropdown extends StatelessWidget {
this.validator, this.validator,
}); });
@override
PLanguageDropdownState createState() => PLanguageDropdownState();
}
class PLanguageDropdownState extends State<PLanguageDropdown> {
final TextEditingController _searchController = TextEditingController();
@override
void dispose() {
_searchController.dispose();
super.dispose();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final List<LanguageModel> sortedLanguages = languages; final List<LanguageModel> sortedLanguages = widget.languages;
final String systemLang = Localizations.localeOf(context).languageCode; final String systemLang = Localizations.localeOf(context).languageCode;
final List<String> languagePriority = [systemLang, 'en', 'es']; final List<String> languagePriority = [systemLang, 'en', 'es'];
@ -60,16 +75,26 @@ class PLanguageDropdown extends StatelessWidget {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
DropdownButtonFormField<LanguageModel>( DropdownButtonFormField2<LanguageModel>(
decoration: InputDecoration(labelText: decorationText), customButton: widget.initialLanguage != null
? LanguageDropDownEntry(
languageModel: widget.initialLanguage!,
isL2List: widget.isL2List,
isDropdown: true,
)
: null,
decoration: InputDecoration(labelText: widget.decorationText),
isExpanded: true, isExpanded: true,
dropdownStyleData: const DropdownStyleData(
maxHeight: 400,
),
items: [ items: [
if (showMultilingual) if (widget.showMultilingual)
DropdownMenuItem( DropdownMenuItem(
value: LanguageModel.multiLingual(context), value: LanguageModel.multiLingual(context),
child: LanguageDropDownEntry( child: LanguageDropDownEntry(
languageModel: LanguageModel.multiLingual(context), languageModel: LanguageModel.multiLingual(context),
isL2List: isL2List, isL2List: widget.isL2List,
), ),
), ),
...sortedLanguages.map( ...sortedLanguages.map(
@ -77,18 +102,42 @@ class PLanguageDropdown extends StatelessWidget {
value: languageModel, value: languageModel,
child: LanguageDropDownEntry( child: LanguageDropDownEntry(
languageModel: languageModel, languageModel: languageModel,
isL2List: isL2List, isL2List: widget.isL2List,
), ),
), ),
), ),
], ],
onChanged: (value) => onChange(value!), onChanged: (value) => widget.onChange(value!),
value: initialLanguage, value: widget.initialLanguage,
validator: (value) => validator?.call(value), validator: (value) => widget.validator?.call(value),
dropdownSearchData: DropdownSearchData(
searchController: _searchController,
searchInnerWidgetHeight: 50,
searchInnerWidget: Padding(
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
child: TextField(
autofocus: true,
controller: _searchController,
decoration: const InputDecoration(
prefixIcon: Icon(Icons.search),
),
),
),
searchMatchFn: (item, searchValue) {
final displayName = item.value?.displayName.toLowerCase();
if (displayName == null) return false;
final search = searchValue.toLowerCase();
return displayName.startsWith(search);
},
),
onMenuStateChange: (isOpen) {
if (!isOpen) _searchController.clear();
},
), ),
AnimatedSize( AnimatedSize(
duration: FluffyThemes.animationDuration, duration: FluffyThemes.animationDuration,
child: error == null child: widget.error == null
? const SizedBox.shrink() ? const SizedBox.shrink()
: Padding( : Padding(
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
@ -96,7 +145,7 @@ class PLanguageDropdown extends StatelessWidget {
vertical: 5, vertical: 5,
), ),
child: Text( child: Text(
error!, widget.error!,
style: TextStyle( style: TextStyle(
color: Theme.of(context).colorScheme.error, color: Theme.of(context).colorScheme.error,
fontSize: 12, fontSize: 12,
@ -112,40 +161,46 @@ class PLanguageDropdown extends StatelessWidget {
class LanguageDropDownEntry extends StatelessWidget { class LanguageDropDownEntry extends StatelessWidget {
final LanguageModel languageModel; final LanguageModel languageModel;
final bool isL2List; final bool isL2List;
final bool isDropdown;
const LanguageDropDownEntry({ const LanguageDropDownEntry({
super.key, super.key,
required this.languageModel, required this.languageModel,
required this.isL2List, required this.isL2List,
this.isDropdown = false,
}); });
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Padding( return Row(
padding: const EdgeInsets.only(left: 12),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
LanguageFlag( LanguageFlag(
language: languageModel, language: languageModel,
), ),
const SizedBox(width: 10), const SizedBox(width: 10),
Flexible( Expanded(
child: Text( child: Row(
children: [
Text(
languageModel.getDisplayName(context) ?? "", languageModel.getDisplayName(context) ?? "",
style: const TextStyle().copyWith( style: const TextStyle().copyWith(
color: Theme.of(context).textTheme.bodyLarge!.color, color: Theme.of(context).textTheme.bodyLarge!.color,
fontSize: 14, fontSize: 14,
), ),
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
),
), ),
const SizedBox(width: 10), const SizedBox(width: 10),
if (isL2List && languageModel.l2Support != L2SupportEnum.full) if (isL2List && languageModel.l2Support != L2SupportEnum.full)
languageModel.l2Support.toBadge(context), languageModel.l2Support.toBadge(context),
], ],
), ),
),
if (isDropdown)
Icon(
Icons.arrow_drop_down,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
],
); );
} }
} }

Loading…
Cancel
Save