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

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

@ -1,6 +1,7 @@
import 'package:flutter/material.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: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/widgets/matrix.dart';
class CountryPickerTile extends StatelessWidget {
class CountryPickerDropdown extends StatefulWidget {
final SettingsLearningController learningController;
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
Widget build(BuildContext context) {
final String displayName = CountryDisplayUtil.countryDisplayName(
learningController.country,
context,
) ??
'';
return DropdownButtonFormField2<Country>(
customButton: widget.learningController.country != null
? 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(
learningController.country,
final search = searchValue.toLowerCase();
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(
title: Text(
"${L10n.of(context).countryInformation}: $displayName $flag",
@override
Widget build(BuildContext context) {
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),
onTap: () => showCountryPicker(
context: context,
showPhoneCode: false,
onSelect: learningController.changeCountry,
if (isDropdown)
Icon(
Icons.arrow_drop_down,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
],
);
}
}

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

Loading…
Cancel
Save