diff --git a/CHANGELOG.md b/CHANGELOG.md index e28dcb6..0e3e323 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## [10.0.2] + +- Fix fixes issue where area codes wrapped in parentheses cannot be deleted + ## [10.0.0] - Add missing countries and favorites params to CountrySelectorNavigator.page factory diff --git a/example/pubspec.lock b/example/pubspec.lock index beea6ba..80b9fef 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -53,10 +53,10 @@ packages: dependency: transitive description: name: collection - sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.19.0" + version: "1.18.0" diacritic: dependency: transitive description: @@ -140,18 +140,18 @@ packages: dependency: transitive description: name: leak_tracker - sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" url: "https://pub.dev" source: hosted - version: "10.0.8" + version: "10.0.5" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" url: "https://pub.dev" source: hosted - version: "3.0.9" + version: "3.0.5" leak_tracker_testing: dependency: transitive description: @@ -222,7 +222,7 @@ packages: path: ".." relative: true source: path - version: "10.0.0" + version: "10.0.2" phone_numbers_parser: dependency: transitive description: @@ -235,7 +235,7 @@ packages: dependency: transitive description: flutter source: sdk - version: "0.0.0" + version: "0.0.99" source_span: dependency: transitive description: @@ -248,10 +248,10 @@ packages: dependency: transitive description: name: stack_trace - sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.11.1" stream_channel: dependency: transitive description: @@ -264,10 +264,10 @@ packages: dependency: transitive description: name: string_scanner - sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.2.0" term_glyph: dependency: transitive description: @@ -280,10 +280,10 @@ packages: dependency: transitive description: name: test_api - sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" + sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" url: "https://pub.dev" source: hosted - version: "0.7.3" + version: "0.7.2" typed_data: dependency: transitive description: @@ -328,10 +328,10 @@ packages: dependency: transitive description: name: vm_service - sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b + sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" url: "https://pub.dev" source: hosted - version: "14.3.0" + version: "14.2.5" web: dependency: transitive description: @@ -349,5 +349,5 @@ packages: source: hosted version: "6.5.0" sdks: - dart: ">=3.4.0 <4.0.0" + dart: ">=3.3.0 <4.0.0" flutter: ">=3.18.0-18.0.pre.54" diff --git a/lib/src/phone_controller.dart b/lib/src/phone_controller.dart index f7d4659..6143dec 100644 --- a/lib/src/phone_controller.dart +++ b/lib/src/phone_controller.dart @@ -37,8 +37,11 @@ class PhoneController extends ChangeNotifier { changeNationalNumber(String? text) { text = text ?? ''; + final oldFormattedText = _value.formatNsn(); var newFormattedText = text; + bool isDeleting = text.length < oldFormattedText.length; + // if starts with + then we parse the whole number final startsWithPlus = text.startsWith(RegExp('[${AllowedCharacters.plus}]')); @@ -51,6 +54,11 @@ class PhoneController extends ChangeNotifier { _value = phoneNumber; newFormattedText = _value.formatNsn(); } + } else if (isDeleting && + text.startsWith( + RegExp('^\\([${AllowedCharacters.digits}]+(?!.*\\))'))) { + // Handle case where the phone number contains an area code such as (416), and user has begun to delete it, i.e. the text input is now (416. + // We need to skip parsing/formatting here, else the parentheses will be added back } else { final phoneNumber = PhoneNumber.parse( text, diff --git a/pubspec.yaml b/pubspec.yaml index 0577c86..51abd0c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: phone_form_field description: Flutter phone input integrated with flutter internationalization -version: 10.0.0 +version: 10.0.2 homepage: https://github.com/cedvdb/phone_form_field environment: diff --git a/test/phone_form_field_test.dart b/test/phone_form_field_test.dart index 599b476..5c04b71 100644 --- a/test/phone_form_field_test.dart +++ b/test/phone_form_field_test.dart @@ -1,5 +1,6 @@ import 'package:circle_flags/circle_flags.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_country_selector/flutter_country_selector.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:phone_form_field/phone_form_field.dart'; @@ -112,6 +113,86 @@ void main() { expect(find.text('6 77 77 77 77'), findsOneWidget); }); + testWidgets('Can delete phone number', (tester) async { + final controller = PhoneController( + initialValue: PhoneNumber.parse('+64'), + ); + + await tester.pumpWidget(getWidget(controller: controller)); + await tester.pump(const Duration(seconds: 1)); + final phoneField = find.byType(PhoneFormField); + await tester.enterText(phoneField, '+64210000000'); + await tester.pump(const Duration(seconds: 1)); + expect(find.text('+ 64'), findsOneWidget); + expect(find.text('210 000 000'), findsOneWidget); + + await tester.sendKeyEvent(LogicalKeyboardKey.backspace); + await tester.sendKeyEvent(LogicalKeyboardKey.backspace); + await tester.sendKeyEvent(LogicalKeyboardKey.backspace); + await tester.sendKeyEvent(LogicalKeyboardKey.backspace); + await tester.sendKeyEvent(LogicalKeyboardKey.backspace); + await tester.sendKeyEvent(LogicalKeyboardKey.backspace); + await tester.sendKeyEvent(LogicalKeyboardKey.backspace); + await tester.sendKeyEvent(LogicalKeyboardKey.backspace); + await tester.sendKeyEvent(LogicalKeyboardKey.backspace); + await tester.pump(); + + expect(controller.value.nsn, equals('')); + }); + + testWidgets('Can delete phone number with area code in parentheses', + (tester) async { + final controller = PhoneController( + initialValue: PhoneNumber.parse('+1'), + ); + + await tester.pumpWidget(getWidget(controller: controller)); + await tester.pump(const Duration(seconds: 1)); + final phoneField = find.byType(PhoneFormField); + await tester.enterText(phoneField, '+14165555555'); + await tester.pump(const Duration(seconds: 1)); + expect(find.text('+ 1'), findsOneWidget); + expect(find.text('(416) 555-5555'), findsOneWidget); + + // delete all digits up to the area code (416) + await tester.sendKeyEvent(LogicalKeyboardKey.backspace); + await tester.sendKeyEvent(LogicalKeyboardKey.backspace); + await tester.sendKeyEvent(LogicalKeyboardKey.backspace); + await tester.sendKeyEvent(LogicalKeyboardKey.backspace); + await tester.sendKeyEvent(LogicalKeyboardKey.backspace); + await tester.sendKeyEvent(LogicalKeyboardKey.backspace); + await tester.sendKeyEvent(LogicalKeyboardKey.backspace); + + // attempt to delete area code + await tester.sendKeyEvent(LogicalKeyboardKey.backspace); + + expect(find.text('(416'), findsOneWidget); + + await tester.sendKeyEvent(LogicalKeyboardKey.backspace); + await tester.sendKeyEvent(LogicalKeyboardKey.backspace); + await tester.sendKeyEvent(LogicalKeyboardKey.backspace); + + expect(find.text('(416)'), findsNothing); + expect(controller.value.nsn, equals('')); + }); + + testWidgets('Can enter phone number with area code', (tester) async { + final controller = PhoneController( + initialValue: PhoneNumber.parse('+1'), + ); + + await tester.pumpWidget(getWidget(controller: controller)); + await tester.pump(const Duration(seconds: 1)); + final phoneField = find.byType(PhoneFormField); + + await tester.enterText(phoneField, '(416'); + + await tester.pump(const Duration(seconds: 1)); + + expect(find.text('+ 1'), findsOneWidget); + expect(find.text('(416)'), findsOneWidget); + }); + testWidgets('Should show dial code when showDialCode is true', (tester) async { PhoneNumber phoneNumber = PhoneNumber.parse('+33'); @@ -250,10 +331,11 @@ void main() { ); }); - testWidgets('Should call onChange when countryCode updated', (tester) async { + testWidgets('Should call onChange when countryCode updated', + (tester) async { bool changed = false; PhoneNumber? phoneNumber = - PhoneNumber.parse('', destinationCountry: IsoCode.FR); + PhoneNumber.parse('', destinationCountry: IsoCode.FR); void onChanged(PhoneNumber? p) { changed = true; phoneNumber = p;