diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index de50dd9d..8bbdd468 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -1,20 +1,19 @@ -name: Publish plugin +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +name: Publish to pub.dev on: push: - tags: - - v* + tags: + - '[0-9]+.[0-9]+.[0-9]+*' jobs: publish: - - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v1 - - name: Publish - uses: sakebook/actions-flutter-pub-publisher@v1.2.1 - with: - credential: ${{ secrets.CREDENTIALS }} - skip_test: true + permissions: + id-token: write # Required for authentication using OIDC + uses: dart-lang/setup-dart/.github/workflows/publish.yml@v1 + # with: + # working-directory: path/to/package/within/repository \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ecec8ce..70e39f3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,17 @@ +## 3.4.1 - October 08 2025 +- Fix French country translations +- Removed Netherlands Antilles from country codes list + +## 3.4.0 - August 19 2025 +- Fix China translation +- Adding flag autofocus + +## 3.3.1 - August 19 2025 +- Fix French translation accent display issue +- Correct French country name translations (Biélorussie, Koweït, Grenade, etc.) +- Preserve accents in displayed names while maintaining search functionality +- Update search logic to handle both accented and non-accented input + ## 3.3.0 - March 26 2025 - Fix localization, typo, and flag issue #51 thanks to @MrRoy121 diff --git a/lib/country_code_picker.dart b/lib/country_code_picker.dart index c4b52603..9456ddb5 100644 --- a/lib/country_code_picker.dart +++ b/lib/country_code_picker.dart @@ -9,12 +9,12 @@ import 'src/country_code.dart'; import 'src/country_codes.dart'; import 'src/selection_dialog.dart'; +export 'src/bottom_sheet.dart'; +export 'src/constants.dart'; export 'src/country_code.dart'; export 'src/country_codes.dart'; export 'src/country_localizations.dart'; export 'src/selection_dialog.dart'; -export 'src/bottom_sheet.dart'; -export 'src/constants.dart'; class CountryCodePicker extends StatefulWidget { final ValueChanged? onChanged; @@ -27,6 +27,7 @@ class CountryCodePicker extends StatefulWidget { final bool showCountryOnly; final InputDecoration searchDecoration; final TextStyle? searchStyle; + final bool? isFocused; final TextStyle? dialogTextStyle; final WidgetBuilder? emptySearchBuilder; final Function(CountryCode?)? builder; @@ -115,6 +116,20 @@ class CountryCodePicker extends StatefulWidget { ///Header Text Alignment final MainAxisAlignment headerAlignment; + /// space after dropdown icon if shown + final double? spaceAfterDropdownIcon; + + /// This function will receive the child and show a custom + /// dialog based on the function implementation + /// Note: You have to return this function to back to the package to select the country + final Function? showDialogCustomFunction; + + /// This function will receive the child and show a custom + /// modal bottom sheet based on the function implementation + /// Note: You have to return this function to back to the package to select the country + + final Function? showBottomSheetCustomFunction; + const CountryCodePicker({ this.onChanged, this.onInit, @@ -125,6 +140,7 @@ class CountryCodePicker extends StatefulWidget { this.margin, this.showCountryOnly = false, this.searchDecoration = const InputDecoration(), + this.isFocused = false, this.searchStyle, this.dialogTextStyle, this.emptySearchBuilder, @@ -152,13 +168,19 @@ class CountryCodePicker extends StatefulWidget { this.closeIcon = const Icon(Icons.close), this.countryList = codes, this.pickerStyle = PickerStyle.dialog, - this.dialogItemPadding = const EdgeInsets.symmetric(horizontal: 24, vertical: 8), + this.dialogItemPadding = + const EdgeInsets.symmetric(horizontal: 24, vertical: 8), this.searchPadding = const EdgeInsets.symmetric(horizontal: 24), this.headerAlignment = MainAxisAlignment.spaceBetween, this.headerText = "Select Country", - this.headerTextStyle = const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + this.headerTextStyle = + const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), this.hideHeaderText = false, - this.topBarPadding = const EdgeInsets.symmetric(vertical: 5.0, horizontal: 20), + this.topBarPadding = + const EdgeInsets.symmetric(vertical: 5.0, horizontal: 20), + this.spaceAfterDropdownIcon, + this.showDialogCustomFunction, + this.showBottomSheetCustomFunction, Key? key, }) : super(key: key); @@ -167,14 +189,16 @@ class CountryCodePicker extends StatefulWidget { State createState() { List> jsonList = countryList; - List elements = jsonList.map((json) => CountryCode.fromJson(json)).toList(); + List elements = + jsonList.map((json) => CountryCode.fromJson(json)).toList(); if (comparator != null) { elements.sort(comparator); } if (countryFilter != null && countryFilter!.isNotEmpty) { - final uppercaseCustomList = countryFilter!.map((criteria) => criteria.toUpperCase()).toList(); + final uppercaseCustomList = + countryFilter!.map((criteria) => criteria.toUpperCase()).toList(); elements = elements .where((criteria) => uppercaseCustomList.contains(criteria.code) || @@ -200,15 +224,20 @@ class CountryCodePickerState extends State { Widget internalWidget; if (widget.builder != null) { internalWidget = InkWell( - onTap: pickerStyle == PickerStyle.dialog ? showCountryCodePickerDialog : showCountryCodePickerBottomSheet, + onTap: pickerStyle == PickerStyle.dialog + ? () => showCountryCodePickerDialog(widget.showDialogCustomFunction) + : () => showCountryCodePickerBottomSheet( + widget.showBottomSheetCustomFunction), child: widget.builder!(selectedItem), ); } else { internalWidget = TextButton( onPressed: widget.enabled ? pickerStyle == PickerStyle.dialog - ? showCountryCodePickerDialog - : showCountryCodePickerBottomSheet + ? () => + showCountryCodePickerDialog(widget.showDialogCustomFunction) + : () => showCountryCodePickerBottomSheet( + widget.showBottomSheetCustomFunction) : null, child: Padding( padding: widget.padding, @@ -216,12 +245,16 @@ class CountryCodePickerState extends State { direction: Axis.horizontal, mainAxisSize: MainAxisSize.min, children: [ - if (widget.showFlagMain != null ? widget.showFlagMain! : widget.showFlag) + if (widget.showFlagMain != null + ? widget.showFlagMain! + : widget.showFlag) Flexible( flex: widget.alignLeft ? 0 : 1, fit: widget.alignLeft ? FlexFit.tight : FlexFit.loose, child: Container( - clipBehavior: widget.flagDecoration == null ? Clip.none : Clip.hardEdge, + clipBehavior: widget.flagDecoration == null + ? Clip.none + : Clip.hardEdge, decoration: widget.flagDecoration, margin: widget.margin ?? (widget.alignLeft @@ -238,8 +271,11 @@ class CountryCodePickerState extends State { Flexible( fit: widget.alignLeft ? FlexFit.tight : FlexFit.loose, child: Text( - widget.showOnlyCountryWhenClosed ? selectedItem!.toCountryStringOnly() : selectedItem.toString(), - style: widget.textStyle ?? Theme.of(context).textTheme.labelLarge, + widget.showOnlyCountryWhenClosed + ? selectedItem!.toCountryStringOnly() + : selectedItem.toString(), + style: widget.textStyle ?? + Theme.of(context).textTheme.labelLarge, overflow: widget.textOverflow, ), ), @@ -249,8 +285,11 @@ class CountryCodePickerState extends State { fit: widget.alignLeft ? FlexFit.tight : FlexFit.loose, child: Padding( padding: (widget.alignLeft - ? const EdgeInsets.only(right: 16.0, left: 8.0) - : const EdgeInsets.only(right: 16.0)), + ? EdgeInsets.only( + right: widget.spaceAfterDropdownIcon ?? 16.0, + left: 8.0) + : EdgeInsets.only( + right: widget.spaceAfterDropdownIcon ?? 16.0)), child: Icon( Icons.arrow_drop_down, color: Colors.grey, @@ -281,9 +320,11 @@ class CountryCodePickerState extends State { if (widget.initialSelection != null) { selectedItem = elements.firstWhere( (criteria) => - (criteria.code!.toUpperCase() == widget.initialSelection!.toUpperCase()) || + (criteria.code!.toUpperCase() == + widget.initialSelection!.toUpperCase()) || (criteria.dialCode == widget.initialSelection) || - (criteria.name!.toUpperCase() == widget.initialSelection!.toUpperCase()), + (criteria.name!.toUpperCase() == + widget.initialSelection!.toUpperCase()), orElse: () => elements[0]); } else { selectedItem = elements[0]; @@ -299,9 +340,11 @@ class CountryCodePickerState extends State { if (widget.initialSelection != null) { selectedItem = elements.firstWhere( (item) => - (item.code!.toUpperCase() == widget.initialSelection!.toUpperCase()) || + (item.code!.toUpperCase() == + widget.initialSelection!.toUpperCase()) || (item.dialCode == widget.initialSelection) || - (item.name!.toUpperCase() == widget.initialSelection!.toUpperCase()), + (item.name!.toUpperCase() == + widget.initialSelection!.toUpperCase()), orElse: () => elements[0]); } else { selectedItem = elements[0]; @@ -317,41 +360,45 @@ class CountryCodePickerState extends State { .toList(); } - void showCountryCodePickerDialog() async { - final item = await showDialog( - barrierColor: widget.barrierColor ?? Colors.grey.withAlpha(128), - context: context, - builder: (context) => Center( - child: Dialog( - child: SelectionDialog( - elements, - favoriteElements, - showCountryOnly: widget.showCountryOnly, - emptySearchBuilder: widget.emptySearchBuilder, - searchDecoration: widget.searchDecoration, - searchStyle: widget.searchStyle, - textStyle: widget.dialogTextStyle, - boxDecoration: widget.boxDecoration, - showFlag: widget.showFlagDialog ?? widget.showFlag, - flagWidth: widget.flagWidth, - size: widget.dialogSize, - headerAlignment: widget.headerAlignment, - headerText: widget.headerText, - headerTextStyle: widget.headerTextStyle, - hideHeaderText: widget.hideHeaderText, - topBarPadding: widget.topBarPadding, - backgroundColor: widget.dialogBackgroundColor, - barrierColor: widget.barrierColor, - hideSearch: widget.hideSearch, - hideCloseIcon: widget.hideCloseIcon, - closeIcon: widget.closeIcon, - flagDecoration: widget.flagDecoration, - dialogItemPadding: widget.dialogItemPadding, - searchPadding: widget.searchPadding, - ), - ), - ), + void showCountryCodePickerDialog(Function? showDialogCustomFunction) async { + late final childWidget = SelectionDialog( + elements, + favoriteElements, + showCountryOnly: widget.showCountryOnly, + emptySearchBuilder: widget.emptySearchBuilder, + searchDecoration: widget.searchDecoration, + searchStyle: widget.searchStyle, + isFocused: widget.isFocused, + textStyle: widget.dialogTextStyle, + boxDecoration: widget.boxDecoration, + showFlag: widget.showFlagDialog ?? widget.showFlag, + flagWidth: widget.flagWidth, + size: widget.dialogSize, + headerAlignment: widget.headerAlignment, + headerText: widget.headerText, + headerTextStyle: widget.headerTextStyle, + hideHeaderText: widget.hideHeaderText, + topBarPadding: widget.topBarPadding, + backgroundColor: widget.dialogBackgroundColor, + barrierColor: widget.barrierColor, + hideSearch: widget.hideSearch, + hideCloseIcon: widget.hideCloseIcon, + closeIcon: widget.closeIcon, + flagDecoration: widget.flagDecoration, + dialogItemPadding: widget.dialogItemPadding, + searchPadding: widget.searchPadding, ); + final item = showDialogCustomFunction == null + ? await showDialog( + barrierColor: widget.barrierColor ?? Colors.grey.withAlpha(128), + context: context, + builder: (context) => Center( + child: Dialog( + child: childWidget, + ), + ), + ) + : await showDialogCustomFunction(context, childWidget); if (item != null) { setState(() { @@ -362,33 +409,39 @@ class CountryCodePickerState extends State { } } - void showCountryCodePickerBottomSheet() async { - final item = await showModalBottomSheet( - isScrollControlled: true, - context: context, - backgroundColor: Colors.transparent, - elevation: 0, - builder: (ctx) { - return SelectionBottomSheet( - elements, - favoriteElements, - showCountryOnly: widget.showCountryOnly, - emptySearchBuilder: widget.emptySearchBuilder, - searchDecoration: widget.searchDecoration, - searchStyle: widget.searchStyle, - textStyle: widget.dialogTextStyle, - boxDecoration: widget.boxDecoration, - showFlag: widget.showFlagDialog ?? widget.showFlag, - flagWidth: widget.flagWidth, - size: widget.dialogSize, - backgroundColor: widget.dialogBackgroundColor, - barrierColor: widget.barrierColor, - hideSearch: widget.hideSearch, - closeIcon: widget.closeIcon, - flagDecoration: widget.flagDecoration, - ); - }, + void showCountryCodePickerBottomSheet( + Function? showBottomSheetCustomFunction) async { + // + late final sheetWidget = SelectionBottomSheet( + elements, + favoriteElements, + showCountryOnly: widget.showCountryOnly, + emptySearchBuilder: widget.emptySearchBuilder, + searchDecoration: widget.searchDecoration, + searchStyle: widget.searchStyle, + textStyle: widget.dialogTextStyle, + boxDecoration: widget.boxDecoration, + showFlag: widget.showFlagDialog ?? widget.showFlag, + flagWidth: widget.flagWidth, + size: widget.dialogSize, + backgroundColor: widget.dialogBackgroundColor, + barrierColor: widget.barrierColor, + hideSearch: widget.hideSearch, + closeIcon: widget.closeIcon, + flagDecoration: widget.flagDecoration, ); + // + final item = showBottomSheetCustomFunction == null + ? await showModalBottomSheet( + isScrollControlled: true, + context: context, + backgroundColor: Colors.transparent, + elevation: 0, + builder: (ctx) { + return sheetWidget; + }, + ) + : await showBottomSheetCustomFunction(context, sheetWidget); if (item == null) return; diff --git a/lib/src/country_code.dart b/lib/src/country_code.dart index cf10c9a0..069f0e88 100644 --- a/lib/src/country_code.dart +++ b/lib/src/country_code.dart @@ -1,5 +1,4 @@ import 'package:collection/collection.dart' show IterableExtension; -import 'package:diacritic/diacritic.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart' show kDebugMode; @@ -45,7 +44,9 @@ class CountryCode { try { return CountryCode.fromCountryCode(countryCode); } catch (e) { - if (kDebugMode) print('Failed to recognize country from countryCode: $countryCode'); + if (kDebugMode) { + print('Failed to recognize country from countryCode: $countryCode'); + } return null; } } @@ -61,20 +62,21 @@ class CountryCode { try { return CountryCode.fromDialCode(dialCode); } catch (e) { - if (kDebugMode) print('Failed to recognize country from dialCode: $dialCode'); + if (kDebugMode) { + print('Failed to recognize country from dialCode: $dialCode'); + } return null; } } CountryCode localize(BuildContext context) { final nam = CountryLocalizations.of(context)?.translate(code) ?? name; - return this - ..name = nam == null? name : removeDiacritics(nam); + return this..name = nam ?? name; } factory CountryCode.fromJson(Map json) { return CountryCode( - name: removeDiacritics(json['name']), + name: json['name'], code: json['code'], dialCode: json['dial_code'], flagUri: 'flags/${json['code'].toLowerCase()}.png', diff --git a/lib/src/country_codes.dart b/lib/src/country_codes.dart index 6d33a850..e35a0dd0 100644 --- a/lib/src/country_codes.dart +++ b/lib/src/country_codes.dart @@ -83,7 +83,7 @@ const List> codes = [ }, {"name": "Tchad", "code": "TD", "iso3Code": "TCD", "dial_code": "+235"}, {"name": "Chile", "code": "CL", "iso3Code": "CHL", "dial_code": "+56"}, - {"name": "中国", "code": "CN", "iso3Code": "CHN", "dial_code": "+86"}, + {"name": "中国大陆", "code": "CN", "iso3Code": "CHN", "dial_code": "+86"}, { "name": "Christmas Island", "code": "CX", @@ -216,7 +216,7 @@ const List> codes = [ }, {"name": "Vaticano", "code": "VA", "iso3Code": "VAT", "dial_code": "+379"}, {"name": "Honduras", "code": "HN", "iso3Code": "HND", "dial_code": "+504"}, - {"name": "香港", "code": "HK", "iso3Code": "HKG", "dial_code": "+852"}, + {"name": "中國香港", "code": "HK", "iso3Code": "HKG", "dial_code": "+852"}, {"name": "Magyarország", "code": "HU", "iso3Code": "HUN", "dial_code": "+36"}, {"name": "Ísland", "code": "IS", "iso3Code": "ISL", "dial_code": "+354"}, {"name": "भारत", "code": "IN", "iso3Code": "IND", "dial_code": "+91"}, @@ -258,7 +258,7 @@ const List> codes = [ }, {"name": "Lietuva", "code": "LT", "iso3Code": "LTU", "dial_code": "+370"}, {"name": "Luxembourg", "code": "LU", "iso3Code": "LUX", "dial_code": "+352"}, - {"name": "澳門", "code": "MO", "iso3Code": "MAC", "dial_code": "+853"}, + {"name": "中國澳門", "code": "MO", "iso3Code": "MAC", "dial_code": "+853"}, {"name": "Македонија", "code": "MK", "iso3Code": "MKD", "dial_code": "+389"}, { "name": "Madagasikara", @@ -290,12 +290,6 @@ const List> codes = [ {"name": "Nauru", "code": "NR", "iso3Code": "NRU", "dial_code": "+674"}, {"name": "नेपाल", "code": "NP", "iso3Code": "NPL", "dial_code": "+977"}, {"name": "Nederland", "code": "NL", "iso3Code": "NLD", "dial_code": "+31"}, - { - "name": "Netherlands Antilles", - "code": "AN", - "iso3Code": "AN", - "dial_code": "+599" - }, { "name": "Nouvelle-Calédonie", "code": "NC", @@ -456,7 +450,7 @@ const List> codes = [ {"name": "Sverige", "code": "SE", "iso3Code": "SWE", "dial_code": "+46"}, {"name": "Schweiz", "code": "CH", "iso3Code": "CHE", "dial_code": "+41"}, {"name": "سوريا", "code": "SY", "iso3Code": "SYR", "dial_code": "+963"}, - {"name": "臺灣", "code": "TW", "iso3Code": "TWN", "dial_code": "+886"}, + {"name": "中國臺灣", "code": "TW", "iso3Code": "TWN", "dial_code": "+886"}, {"name": "Тоҷикистон", "code": "TJ", "iso3Code": "TJK", "dial_code": "+992"}, {"name": "Tanzania", "code": "TZ", "iso3Code": "TZA", "dial_code": "+255"}, {"name": "ประเทศไทย", "code": "TH", "iso3Code": "THA", "dial_code": "+66"}, diff --git a/lib/src/i18n/en.json b/lib/src/i18n/en.json index 68e89d86..62f6b855 100644 --- a/lib/src/i18n/en.json +++ b/lib/src/i18n/en.json @@ -42,7 +42,7 @@ "CF": "Central African Republic", "TD": "Chad", "CL": "Chile", - "CN": "China", + "CN": "China's Mainland", "CX": "Christmas Island", "CC": "Cocos (Keeling) Islands", "CO": "Colombia", @@ -94,7 +94,7 @@ "HM": "Heard Island and McDonald Islands", "VA": "Holy See (Vatican City State)", "HN": "Honduras", - "HK": "Hong Kong", + "HK": "Hong Kong China", "HU": "Hungary", "IS": "Iceland", "IN": "India", @@ -123,7 +123,7 @@ "LI": "Liechtenstein", "LT": "Lithuania", "LU": "Luxembourg", - "MO": "Macao", + "MO": "Macao China", "MG": "Madagascar", "MW": "Malawi", "MY": "Malaysia", @@ -210,10 +210,7 @@ "SE": "Sweden", "CH": "Switzerland", "SY": "Syrian Arab Republic", - "TW": [ - "Taiwan, Province of China", - "Taiwan" - ], + "TW": "Taiwan China", "TJ": "Tajikistan", "TZ": "Tanzania, United Republic of", "TH": "Thailand", diff --git a/lib/src/i18n/fr.json b/lib/src/i18n/fr.json index e7ea4d02..d1a919be 100644 --- a/lib/src/i18n/fr.json +++ b/lib/src/i18n/fr.json @@ -18,7 +18,7 @@ "BH": "Bahrein", "BD": "Bangladesh", "BB": "Barbade", - "BY": "Bielorussie", + "BY": "Biélorussie", "BE": "Belgique", "BZ": "Belize", "BJ": "Bénin", @@ -38,8 +38,8 @@ "CM": "Cameroun", "CA": "Canada", "CV": "Cap-Vert", - "KY": "Caïmanes", - "CF": "Centrafricaine, République", + "KY": "Îles Caïmans", + "CF": "République Centrafricaine", "TD": "Tchad", "CL": "Chili", "CN": "Chine", @@ -83,7 +83,7 @@ "GI": "Gibraltar", "GR": "Grèce", "GL": "Groenland", - "GD": "Grenada", + "GD": "Grenade", "GP": "Guadeloupe", "GU": "Guam", "GT": "Guatemala", @@ -92,7 +92,7 @@ "GY": "Guyana", "HT": "Haïti", "HM": "Îles Heard-et-MacDonald", - "VA": "Saint-Siège", + "VA": "Vatican", "HN": "Honduras", "HK": "Hong Kong", "HU": "Hongrie", @@ -110,10 +110,10 @@ "KZ": "Kazakhstan", "KE": "Kenya", "KI": "Kiribati", - "KP": "Corée du Nord, République populaire démocratique", - "KR": "Corée du Sud, République", - "KW": "Koweit", - "KG": "Kirghistan", + "KP": "Corée du Nord", + "KR": "Corée du Sud", + "KW": "Koweït", + "KG": "Kirghizistan", "LA": "Laos", "LV": "Lettonie", "LB": "Liban", @@ -179,7 +179,7 @@ "SH": "Sainte-Hélène", "KN": "Saint-Christophe-et-Niévès", "LC": "Sainte-Lucie", - "PM": "Saint Pierre and Miquelon", + "PM": "Saint-Pierre-et-Miquelon", "VC": "Saint-Vincent et les Grenadines", "WS": "Samoa", "SM": "Saint-Marin", @@ -200,19 +200,19 @@ "SD": "Soudan", "SR": "Suriname", "SJ": "Svalbard et Île Jan Mayen", - "SZ": "Ngwane, Royaume d'Eswatini", + "SZ": "Eswatini", "SE": "Suède", "CH": "Suisse", "SY": "Syrie", "TW": "Taïwan", "TJ": "Tadjikistan", - "TZ": "Tanzanie, République unie", + "TZ": "Tanzanie", "TH": "Thaïlande", - "TL": "Timor Leste", + "TL": "Timor-Leste", "TG": "Togo", "TK": "Tokelau", "TO": "Tonga", - "TT": "Trinidad et Tobago", + "TT": "Trinité-et-Tobago", "TN": "Tunisie", "TR": "Turquie", "TM": "Turkménistan", diff --git a/lib/src/i18n/zh.json b/lib/src/i18n/zh.json index 93abba2a..2f1c941f 100644 --- a/lib/src/i18n/zh.json +++ b/lib/src/i18n/zh.json @@ -46,7 +46,7 @@ "CK": "库克群岛", "CL": "智利", "CM": "喀麦隆", - "CN": "中国", + "CN": "中国大陆", "CO": "哥伦比亚", "CR": "哥斯达黎加", "CU": "古巴", @@ -93,7 +93,7 @@ "GU": "关岛", "GW": "几内亚比绍", "GY": "圭亚那", - "HK": "香港", + "HK": "中国香港", "HM": "赫德岛和麦克唐纳群岛", "HN": "洪都拉斯", "HR": "克罗地亚", @@ -146,7 +146,7 @@ "ML": "马里", "MM": "缅甸", "MN": "蒙古", - "MO": "澳门", + "MO": "中国澳门", "MP": "北马里亚纳群岛", "MQ": "马提尼克", "MR": "毛里塔尼亚", @@ -226,7 +226,7 @@ "TR": "土耳其", "TT": "特立尼达和多巴哥", "TV": "图瓦卢", - "TW": "中国台湾省", + "TW": "中国台湾", "TZ": "坦桑尼亚", "UA": "乌克兰", "UG": "乌干达", diff --git a/lib/src/selection_dialog.dart b/lib/src/selection_dialog.dart index 46cc466f..6a12d6dd 100644 --- a/lib/src/selection_dialog.dart +++ b/lib/src/selection_dialog.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:diacritic/diacritic.dart'; import 'country_code.dart'; import 'country_localizations.dart'; @@ -9,6 +10,7 @@ class SelectionDialog extends StatefulWidget { final bool? showCountryOnly; final InputDecoration searchDecoration; final TextStyle? searchStyle; + final bool? isFocused; final TextStyle? textStyle; final TextStyle headerTextStyle; final BoxDecoration? boxDecoration; @@ -49,8 +51,9 @@ class SelectionDialog extends StatefulWidget { required this.headerTextStyle, InputDecoration searchDecoration = const InputDecoration(), this.searchStyle, + this.isFocused, this.textStyle, - required this.topBarPadding, + required this.topBarPadding, this.headerText, this.boxDecoration, this.showFlag, @@ -62,9 +65,12 @@ class SelectionDialog extends StatefulWidget { this.hideSearch = false, this.hideCloseIcon = false, this.closeIcon, - this.dialogItemPadding = const EdgeInsets.symmetric(horizontal: 24, vertical: 8), + this.dialogItemPadding = + const EdgeInsets.symmetric(horizontal: 24, vertical: 8), this.searchPadding = const EdgeInsets.symmetric(horizontal: 24), - }) : searchDecoration = searchDecoration.prefixIcon == null ? searchDecoration.copyWith(prefixIcon: const Icon(Icons.search)) : searchDecoration, + }) : searchDecoration = searchDecoration.prefixIcon == null + ? searchDecoration.copyWith(prefixIcon: const Icon(Icons.search)) + : searchDecoration, super(key: key); @override @@ -81,7 +87,8 @@ class _SelectionDialogState extends State { child: Container( clipBehavior: Clip.hardEdge, width: widget.size?.width ?? MediaQuery.of(context).size.width, - height: widget.size?.height ?? MediaQuery.of(context).size.height * 0.85, + height: + widget.size?.height ?? MediaQuery.of(context).size.height * 0.85, decoration: widget.boxDecoration ?? BoxDecoration( color: widget.backgroundColor ?? Colors.white, @@ -100,7 +107,9 @@ class _SelectionDialogState extends State { crossAxisAlignment: CrossAxisAlignment.end, children: [ Padding( - padding:!widget.hideHeaderText? widget.topBarPadding: EdgeInsets.zero, + padding: !widget.hideHeaderText + ? widget.topBarPadding + : EdgeInsets.zero, child: Row( mainAxisAlignment: widget.headerAlignment, children: [ @@ -125,6 +134,7 @@ class _SelectionDialogState extends State { Padding( padding: widget.searchPadding, child: TextField( + autofocus: widget.isFocused ?? false, style: widget.searchStyle, decoration: widget.searchDecoration, onChanged: _filterElements, @@ -177,11 +187,14 @@ class _SelectionDialogState extends State { if (widget.showFlag!) Flexible( child: Container( - margin: Directionality.of(context) == TextDirection.ltr // Here Adding padding depending on the locale language direction + margin: Directionality.of(context) == + TextDirection + .ltr // Here Adding padding depending on the locale language direction ? const EdgeInsets.only(right: 16.0) : const EdgeInsets.only(left: 16.0), decoration: widget.flagDecoration, - clipBehavior: widget.flagDecoration == null ? Clip.none : Clip.hardEdge, + clipBehavior: + widget.flagDecoration == null ? Clip.none : Clip.hardEdge, child: Image.asset( e.flagUri!, package: 'country_code_picker', @@ -192,7 +205,9 @@ class _SelectionDialogState extends State { Expanded( flex: 4, child: Text( - widget.showCountryOnly! ? e.toCountryStringOnly() : e.toLongString(), + widget.showCountryOnly! + ? e.toCountryStringOnly() + : e.toLongString(), overflow: TextOverflow.fade, style: widget.textStyle, ), @@ -208,7 +223,8 @@ class _SelectionDialogState extends State { } return Center( - child: Text(CountryLocalizations.of(context)?.translate('no_country') ?? 'No country found'), + child: Text(CountryLocalizations.of(context)?.translate('no_country') ?? + 'No country found'), ); } @@ -219,9 +235,15 @@ class _SelectionDialogState extends State { } void _filterElements(String s) { - s = s.toUpperCase(); + final normalizedSearch = removeDiacritics(s.toUpperCase()); setState(() { - filteredElements = widget.elements.where((e) => e.code!.contains(s) || e.dialCode!.contains(s) || e.name!.toUpperCase().contains(s)).toList(); + filteredElements = widget.elements + .where((e) => + e.code!.contains(normalizedSearch) || + e.dialCode!.contains(normalizedSearch) || + removeDiacritics(e.name!.toUpperCase()) + .contains(normalizedSearch)) + .toList(); }); } diff --git a/pubspec.yaml b/pubspec.yaml index c274e60f..f474c187 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: country_code_picker description: A flutter package for showing a country code selector. In addition it gives the possibility to select a list of favorites countries, as well as to search using a simple searchbox -version: 3.3.0 +version: 3.4.1 homepage: https://github.com/chandrabezzo/CountryCodePicker repository: https://github.com/chandrabezzo/CountryCodePicker issue_tracker: https://github.com/imtoori/CountryCodePicker/issues