feat: update country dropdown to match style of language dropdown (#1756)
This commit is contained in:
parent
3e72ee8088
commit
ee72460aba
4 changed files with 200 additions and 60 deletions
|
|
@ -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,
|
||||
) ??
|
||||
'';
|
||||
|
||||
final String flag = CountryDisplayUtil.flagEmoji(
|
||||
learningController.country,
|
||||
);
|
||||
|
||||
return ListTile(
|
||||
title: Text(
|
||||
"${L10n.of(context).countryInformation}: $displayName $flag",
|
||||
return DropdownButtonFormField2<Country>(
|
||||
customButton: widget.learningController.country != null
|
||||
? CountryPickerTile(
|
||||
widget.learningController.country!,
|
||||
isDropdown: true,
|
||||
)
|
||||
: null,
|
||||
decoration: InputDecoration(
|
||||
labelText: L10n.of(context).countryInformation,
|
||||
),
|
||||
trailing: const Icon(Icons.edit_outlined),
|
||||
onTap: () => showCountryPicker(
|
||||
context: context,
|
||||
showPhoneCode: false,
|
||||
onSelect: learningController.changeCountry,
|
||||
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 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,
|
||||
});
|
||||
|
||||
@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,
|
||||
),
|
||||
),
|
||||
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,
|
||||
children: [
|
||||
LanguageFlag(
|
||||
language: languageModel,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Flexible(
|
||||
child: Text(
|
||||
languageModel.getDisplayName(context) ?? "",
|
||||
style: const TextStyle().copyWith(
|
||||
color: Theme.of(context).textTheme.bodyLarge!.color,
|
||||
fontSize: 14,
|
||||
return Row(
|
||||
children: [
|
||||
LanguageFlag(
|
||||
language: languageModel,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
languageModel.getDisplayName(context) ?? "",
|
||||
style: const TextStyle().copyWith(
|
||||
color: Theme.of(context).textTheme.bodyLarge!.color,
|
||||
fontSize: 14,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
if (isL2List && languageModel.l2Support != L2SupportEnum.full)
|
||||
languageModel.l2Support.toBadge(context),
|
||||
],
|
||||
),
|
||||
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…
Add table
Reference in a new issue