From 0762c6d9f80e95f7b170004bbe996a4848ec1c65 Mon Sep 17 00:00:00 2001 From: Riccardo Baldassa Date: Wed, 14 May 2025 08:55:31 +0200 Subject: [PATCH 01/12] upgrade libraries in `pubspec.yaml` - @rickypid @RichiB20 --- example/pubspec.lock | 134 +++++++++++++++++++++++++++---------------- pubspec.yaml | 20 +++---- 2 files changed, 93 insertions(+), 61 deletions(-) diff --git a/example/pubspec.lock b/example/pubspec.lock index 88d3db72..c91e850b 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -21,42 +21,42 @@ packages: dependency: transitive description: name: async - sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63 url: "https://pub.dev" source: hosted - version: "2.11.0" + version: "2.12.0" boolean_selector: dependency: transitive description: name: boolean_selector - sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" characters: dependency: transitive description: name: characters - sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.0" clock: dependency: transitive description: name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" collection: dependency: transitive description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.19.1" cupertino_icons: dependency: "direct main" description: @@ -77,10 +77,10 @@ packages: dependency: transitive description: name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.2" flutter: dependency: "direct main" description: flutter @@ -107,10 +107,10 @@ packages: dependency: "direct main" description: name: font_awesome_flutter - sha256: "52671aea66da73b58d42ec6d0912b727a42248dd9a7c76d6c20f275783c48c08" + sha256: d3a89184101baec7f4600d58840a764d2ef760fe1c5a20ef9e6b0e9b24a07a3a url: "https://pub.dev" source: hosted - version: "10.6.0" + version: "10.8.0" intl: dependency: "direct main" description: @@ -135,6 +135,30 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.7" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec + url: "https://pub.dev" + source: hosted + version: "10.0.8" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 + url: "https://pub.dev" + source: hosted + version: "3.0.9" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" libphonenumber_platform_interface: dependency: transitive description: @@ -171,26 +195,26 @@ packages: dependency: transitive description: name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 url: "https://pub.dev" source: hosted - version: "0.12.16" + version: "0.12.17" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.11.1" meta: dependency: transitive description: name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.16.0" nested: dependency: transitive description: @@ -203,18 +227,18 @@ packages: dependency: transitive description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.1" phone_numbers_parser: dependency: transitive description: name: phone_numbers_parser - sha256: "17a6686350c574a08f7beb839c5f908cc19b9c0eabd6e97029b517527a49da02" + sha256: "8aaa49708c9314d450d80767753c6512402e848138e5a91bf59ed3e0d3ac5d9b" url: "https://pub.dev" source: hosted - version: "8.1.0" + version: "9.0.3" plugin_platform_interface: dependency: transitive description: @@ -227,18 +251,18 @@ packages: dependency: transitive description: name: provider - sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096" + sha256: "4abbd070a04e9ddc287673bf5a030c7ca8b685ff70218720abab8b092f53dd84" url: "https://pub.dev" source: hosted - version: "6.1.1" + version: "6.1.5" quiver: dependency: transitive description: name: quiver - sha256: b1c1ac5ce6688d77f65f3375a9abb9319b3cb32486bdc7a1e0fdf004d7ba4e47 + sha256: ea0b925899e64ecdfbf9c7becb60d5b50e706ade44a85b2363be2a22d88117d2 url: "https://pub.dev" source: hosted - version: "3.2.1" + version: "3.2.2" sign_in_button: dependency: transitive description: @@ -251,79 +275,79 @@ packages: dependency: transitive description: flutter source: sdk - version: "0.0.99" + version: "0.0.0" source_span: dependency: transitive description: name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.10.1" stack_trace: dependency: transitive description: name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.12.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" string_scanner: dependency: transitive description: name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.4.1" term_glyph: dependency: transitive description: name: term_glyph - sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.2" test_api: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.7.4" url_launcher: dependency: transitive description: name: url_launcher - sha256: e9aa5ea75c84cf46b3db4eea212523591211c3cf2e13099ee4ec147f54201c86 + sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603" url: "https://pub.dev" source: hosted - version: "6.2.2" + version: "6.3.1" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "31222ffb0063171b526d3e569079cf1f8b294075ba323443fdc690842bfd4def" + sha256: "8582d7f6fe14d2652b4c45c9b6c14c0b678c2af2d083a11b604caeba51930d79" url: "https://pub.dev" source: hosted - version: "6.2.0" + version: "6.3.16" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: bba3373219b7abb6b5e0d071b0fe66dfbe005d07517a68e38d4fc3638f35c6d3 + sha256: "7f2022359d4c099eea7df3fdf739f7d3d3b9faf3166fb1dd390775176e0b76cb" url: "https://pub.dev" source: hosted - version: "6.2.1" + version: "6.3.3" url_launcher_linux: dependency: transitive description: @@ -344,10 +368,10 @@ packages: dependency: transitive description: name: url_launcher_platform_interface - sha256: "980e8d9af422f477be6948bdfb68df8433be71f5743a188968b0c1b887807e50" + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.2" url_launcher_web: dependency: transitive description: @@ -372,6 +396,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14" + url: "https://pub.dev" + source: hosted + version: "14.3.1" web: dependency: transitive description: @@ -381,5 +413,5 @@ packages: source: hosted version: "0.3.0" sdks: - dart: ">=3.2.0 <4.0.0" - flutter: ">=3.16.0" + dart: ">=3.7.0-0 <4.0.0" + flutter: ">=3.27.0" diff --git a/pubspec.yaml b/pubspec.yaml index 37200442..80cad04c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -8,23 +8,23 @@ environment: flutter: ">=3.16.0" dependencies: - another_flushbar: ^1.10.29 - another_transformer_page_view: ^2.0.0 + another_flushbar: ^1.12.30 + another_transformer_page_view: ^2.0.1 flutter: sdk: flutter - font_awesome_flutter: ^10.0.0 + font_awesome_flutter: ^10.8.0 intl_phone_number_input: ^0.7.4 - phone_numbers_parser: ^8.0.0 - provider: ^6.0.1 - quiver: ^3.0.1 - sign_in_button: ^3.0.0 - url_launcher: ^6.1.3 + phone_numbers_parser: ^9.0.3 + provider: ^6.1.5 + quiver: ^3.2.2 + sign_in_button: ^3.2.0 + url_launcher: ^6.3.1 dev_dependencies: flutter_test: sdk: flutter - lint: ^2.1.2 - mockito: ^5.0.16 + lint: ^2.8.0 + mockito: ^5.4.6 flutter: uses-material-design: true From 750141a2492bd4ca05745e2226c8e89715c71b3c Mon Sep 17 00:00:00 2001 From: riccardocucia Date: Wed, 14 May 2025 15:32:48 +0200 Subject: [PATCH 02/12] Remove intl_phone_number_input --- example/pubspec.lock | 48 ------------------- lib/src/widgets/animated_text_form_field.dart | 14 ++++-- 2 files changed, 9 insertions(+), 53 deletions(-) diff --git a/example/pubspec.lock b/example/pubspec.lock index c91e850b..a5820df2 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -65,14 +65,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.6" - equatable: - dependency: transitive - description: - name: equatable - sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 - url: "https://pub.dev" - source: hosted - version: "2.0.5" fake_async: dependency: transitive description: @@ -119,22 +111,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.19.0" - intl_phone_number_input: - dependency: transitive - description: - name: intl_phone_number_input - sha256: "1c4328713a9503ab26a1fdbb6b00b4cada68c18aac922b35bedbc72eff1297c3" - url: "https://pub.dev" - source: hosted - version: "0.7.4" - js: - dependency: transitive - description: - name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 - url: "https://pub.dev" - source: hosted - version: "0.6.7" leak_tracker: dependency: transitive description: @@ -159,30 +135,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.1" - libphonenumber_platform_interface: - dependency: transitive - description: - name: libphonenumber_platform_interface - sha256: f801f6c65523f56504b83f0890e6dad584ab3a7507dca65fec0eed640afea40f - url: "https://pub.dev" - source: hosted - version: "0.4.2" - libphonenumber_plugin: - dependency: transitive - description: - name: libphonenumber_plugin - sha256: c615021d9816fbda2b2587881019ed595ecdf54d999652d7e4cce0e1f026368c - url: "https://pub.dev" - source: hosted - version: "0.3.3" - libphonenumber_web: - dependency: transitive - description: - name: libphonenumber_web - sha256: "8186f420dbe97c3132283e52819daff1e55d60d6db46f7ea5ac42f42a28cc2ef" - url: "https://pub.dev" - source: hosted - version: "0.3.2" lint: dependency: "direct dev" description: diff --git a/lib/src/widgets/animated_text_form_field.dart b/lib/src/widgets/animated_text_form_field.dart index b2613008..0fef84d5 100644 --- a/lib/src/widgets/animated_text_form_field.dart +++ b/lib/src/widgets/animated_text_form_field.dart @@ -5,8 +5,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_login/flutter_login.dart'; import 'package:flutter_login/src/widgets/term_of_service_checkbox.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:intl_phone_number_input/intl_phone_number_input.dart'; -import 'package:phone_numbers_parser/phone_numbers_parser.dart' as pnp; +//import 'package:intl_phone_number_input/intl_phone_number_input.dart'; +//import 'package:phone_numbers_parser/phone_numbers_parser.dart' as pnp; import 'package:url_launcher/url_launcher.dart'; enum TextFieldInertiaDirection { @@ -98,7 +98,7 @@ class _AnimatedTextFormFieldState extends State { late Animation iconRotationAnimation; late Animation iconTranslateAnimation; - PhoneNumber? _phoneNumberInitialValue; + //PhoneNumber? _phoneNumberInitialValue; final TextEditingController _phoneNumberController = TextEditingController(); @override @@ -167,6 +167,7 @@ class _AnimatedTextFormFieldState extends State { ); } + /* if (widget.userType == LoginUserType.intlPhone) { _phoneNumberInitialValue = PhoneNumber( isoCode: widget.initialIsoCode ?? 'US', @@ -189,6 +190,8 @@ class _AnimatedTextFormFieldState extends State { } } } + + */ } void _updateSizeAnimation() { @@ -271,7 +274,7 @@ class _AnimatedTextFormFieldState extends State { Widget build(BuildContext context) { final theme = Theme.of(context); Widget inputField; - if (widget.userType == LoginUserType.intlPhone) { + /*if (widget.userType == LoginUserType.intlPhone) { inputField = Padding( padding: const EdgeInsets.only(left: 8), child: InternationalPhoneNumberInput( @@ -327,7 +330,8 @@ class _AnimatedTextFormFieldState extends State { initialValue: _phoneNumberInitialValue, ), ); - } else if (widget.userType == LoginUserType.checkbox) { + } else*/ + if (widget.userType == LoginUserType.checkbox) { inputField = CheckboxFormField( initialValue: widget.controller?.text == 'true', validator: (value) => From 5bebee4689fc05004ddcc883371c14dfd6b50179 Mon Sep 17 00:00:00 2001 From: riccardocucia Date: Wed, 14 May 2025 16:00:02 +0200 Subject: [PATCH 03/12] Remove intl_phone_number_input --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 80cad04c..7e30d154 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -13,7 +13,7 @@ dependencies: flutter: sdk: flutter font_awesome_flutter: ^10.8.0 - intl_phone_number_input: ^0.7.4 + #intl_phone_number_input: ^0.7.4 phone_numbers_parser: ^9.0.3 provider: ^6.1.5 quiver: ^3.2.2 From 2bef000311bf30616caaef8df6fe63461ed22a42 Mon Sep 17 00:00:00 2001 From: Riccardo Baldassa Date: Tue, 10 Jun 2025 19:30:11 +0200 Subject: [PATCH 04/12] Center text title - @RichiB20 --- lib/flutter_login.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/flutter_login.dart b/lib/flutter_login.dart index c2f37063..d46411f1 100644 --- a/lib/flutter_login.dart +++ b/lib/flutter_login.dart @@ -239,6 +239,7 @@ class __HeaderState extends State<_Header> { widget.title!, key: kTitleKey, style: theme.textTheme.displaySmall, + textAlign: TextAlign.center, ); } else { title = null; From 4f3a9e2cdd630d1edfd9f6af9347a47f46b558e8 Mon Sep 17 00:00:00 2001 From: Riccardo Baldassa Date: Wed, 11 Jun 2025 08:52:28 +0200 Subject: [PATCH 05/12] Change `kMaxLogoHeight` - @RichiB20 --- lib/src/utils/constants.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/utils/constants.dart b/lib/src/utils/constants.dart index 0f5af7b0..d109b4ec 100644 --- a/lib/src/utils/constants.dart +++ b/lib/src/utils/constants.dart @@ -6,4 +6,4 @@ const kRecoverPasswordDescriptionKey = Key('RECOVER_PASSWORD_DESCRIPTION'); const kDebugToolbarKey = Key('DEBUG_TOOLBAR'); const kMinLogoHeight = 50.0; // hide logo if less than this -const kMaxLogoHeight = 125.0; +const kMaxLogoHeight = 250.0; From cb8265b210bf03028afbd10bc0a06e1447f47d46 Mon Sep 17 00:00:00 2001 From: Riccardo Baldassa Date: Tue, 29 Jul 2025 11:09:17 +0200 Subject: [PATCH 06/12] Upgrade with v5.1.0 - @RichiB20 @alato --- lib/flutter_login.dart | 1 + lib/src/utils/constants.dart | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/flutter_login.dart b/lib/flutter_login.dart index 5af46cd7..09911dcf 100644 --- a/lib/flutter_login.dart +++ b/lib/flutter_login.dart @@ -243,6 +243,7 @@ class __HeaderState extends State<_Header> { widget.title!, key: kTitleKey, style: theme.textTheme.displaySmall, + textAlign: TextAlign.center, ); } else { title = null; diff --git a/lib/src/utils/constants.dart b/lib/src/utils/constants.dart index 18e6326b..abc98cc2 100644 --- a/lib/src/utils/constants.dart +++ b/lib/src/utils/constants.dart @@ -20,4 +20,4 @@ const kMinLogoHeight = 50.0; /// The maximum height at which the logo will be displayed. /// /// Used to limit scaling of the logo in larger layouts. -const kMaxLogoHeight = 125.0; +const kMaxLogoHeight = 250.0; From bd25d7a87236defb8a14682e6c4ac71624f274fb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Aug 2025 05:45:30 +0000 Subject: [PATCH 07/12] build(deps): bump androidx.test.ext:junit in /example/android Bumps androidx.test.ext:junit from 1.2.1 to 1.3.0. --- updated-dependencies: - dependency-name: androidx.test.ext:junit dependency-version: 1.3.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- example/android/app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 50250b4a..836a6752 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -67,6 +67,6 @@ flutter { dependencies { testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.2.1' + androidTestImplementation 'androidx.test.ext:junit:1.3.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1' } From 653cc52f3358f52eec7a9e67a08941918e75f44f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Aug 2025 06:27:20 +0000 Subject: [PATCH 08/12] build(deps): bump actions/checkout from 4 to 5 Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/flutter.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index 9b187dd5..e80cc9ca 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -16,7 +16,7 @@ jobs: steps: - name: 📥 Checkout Code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: ⚡ Set Up Flutter uses: subosito/flutter-action@v2 @@ -50,7 +50,7 @@ jobs: steps: - name: 📥 Checkout Code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: ⚡ Set Up Flutter uses: subosito/flutter-action@v2 @@ -70,7 +70,7 @@ jobs: runs-on: ubuntu-latest steps: - name: 📥 Checkout Code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: ⚡ Set Up Flutter uses: subosito/flutter-action@v2 From 0685627f42561ab6ce246f0dec710314fb1118d5 Mon Sep 17 00:00:00 2001 From: Julian Steenbakker Date: Wed, 17 Sep 2025 12:29:09 +0200 Subject: [PATCH 09/12] imp: update dependencies, migrate from intl_phone_number to form_builder_phone_field to remove local sdk usage --- example/android/app/build.gradle | 8 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- example/android/settings.gradle | 4 +- example/lib/login_screen.dart | 5 + example/pubspec.lock | 103 +++++++---------- example/pubspec.yaml | 2 +- lib/src/widgets/animated_text_form_field.dart | 105 +++++++----------- pubspec.yaml | 7 +- 8 files changed, 98 insertions(+), 138 deletions(-) diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 50250b4a..7c298183 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -23,7 +23,7 @@ if (flutterVersionName == null) { } android { - compileSdk 35 + compileSdk 36 compileOptions { sourceCompatibility = JavaVersion.VERSION_17 @@ -41,7 +41,7 @@ android { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.example.example" minSdkVersion flutter.minSdkVersion - targetSdkVersion 35 + targetSdkVersion 36 versionCode flutterVersionCode.toInteger() versionName flutterVersionName testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' @@ -67,6 +67,6 @@ flutter { dependencies { testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.2.1' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1' + androidTestImplementation 'androidx.test.ext:junit:1.3.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.7.0' } diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties index c0aacdb2..e03ab7cb 100644 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Tue Aug 29 15:49:40 CEST 2023 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/example/android/settings.gradle b/example/android/settings.gradle index 641f9339..ca751158 100644 --- a/example/android/settings.gradle +++ b/example/android/settings.gradle @@ -18,8 +18,8 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" // apply true - id "com.android.application" version '8.10.1' apply false - id "org.jetbrains.kotlin.android" version "1.9.10" apply false + id "com.android.application" version '8.13.0' apply false + id "org.jetbrains.kotlin.android" version "2.2.20" apply false } include ":app" \ No newline at end of file diff --git a/example/lib/login_screen.dart b/example/lib/login_screen.dart index aef0f3de..055f4404 100644 --- a/example/lib/login_screen.dart +++ b/example/lib/login_screen.dart @@ -125,6 +125,11 @@ class LoginScreen extends StatelessWidget { return null; }, ), + const UserFormField( + keyName: 'int_phone_number', + displayName: 'Int Phone Number', + userType: LoginUserType.intlPhone, + ), ], // scrollable: true, // hideProvidersTitle: false, diff --git a/example/pubspec.lock b/example/pubspec.lock index 861ec668..4818bd59 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -57,6 +57,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.19.1" + country_pickers: + dependency: transitive + description: + name: country_pickers + sha256: b10f6618fa64fbba02ffc4ad1b84dc0ca071cc206e5376de1698bddd980b355a + url: "https://pub.dev" + source: hosted + version: "3.0.1" cupertino_icons: dependency: "direct main" description: @@ -65,14 +73,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.8" - equatable: - dependency: transitive - description: - name: equatable - sha256: "567c64b3cb4cf82397aac55f4f0cbd3ca20d77c6c03bedbc4ceaddc08904aef7" - url: "https://pub.dev" - source: hosted - version: "2.0.7" fake_async: dependency: transitive description: @@ -86,6 +86,19 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_form_builder: + dependency: transitive + description: + name: flutter_form_builder + sha256: ec74389c4af2361a5e9fe9a36fcfe722698be3f681d713cb3ebe099ae15ed863 + url: "https://pub.dev" + source: hosted + version: "10.2.0" + flutter_localizations: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" flutter_login: dependency: "direct main" description: @@ -111,78 +124,46 @@ packages: url: "https://pub.dev" source: hosted version: "10.8.0" - intl: - dependency: "direct main" - description: - name: intl - sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf - url: "https://pub.dev" - source: hosted - version: "0.19.0" - intl_phone_number_input: + form_builder_phone_field: dependency: transitive description: - name: intl_phone_number_input - sha256: "1c4328713a9503ab26a1fdbb6b00b4cada68c18aac922b35bedbc72eff1297c3" + name: form_builder_phone_field + sha256: c89ea400428bb22707a8d76e433070bef4a74de15a085060e1d75f9e3b660cab url: "https://pub.dev" source: hosted - version: "0.7.4" - js: - dependency: transitive + version: "3.0.0" + intl: + dependency: "direct main" description: - name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + name: intl + sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" url: "https://pub.dev" source: hosted - version: "0.6.7" + version: "0.20.2" leak_tracker: dependency: transitive description: name: leak_tracker - sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" url: "https://pub.dev" source: hosted - version: "10.0.9" + version: "11.0.2" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" url: "https://pub.dev" source: hosted - version: "3.0.9" + version: "3.0.10" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" - url: "https://pub.dev" - source: hosted - version: "3.0.1" - libphonenumber_platform_interface: - dependency: transitive - description: - name: libphonenumber_platform_interface - sha256: f801f6c65523f56504b83f0890e6dad584ab3a7507dca65fec0eed640afea40f - url: "https://pub.dev" - source: hosted - version: "0.4.2" - libphonenumber_plugin: - dependency: transitive - description: - name: libphonenumber_plugin - sha256: c615021d9816fbda2b2587881019ed595ecdf54d999652d7e4cce0e1f026368c + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" url: "https://pub.dev" source: hosted - version: "0.3.3" - libphonenumber_web: - dependency: transitive - description: - name: libphonenumber_web - sha256: "8186f420dbe97c3132283e52819daff1e55d60d6db46f7ea5ac42f42a28cc2ef" - url: "https://pub.dev" - source: hosted - version: "0.3.2" + version: "3.0.2" matcher: dependency: transitive description: @@ -312,10 +293,10 @@ packages: dependency: transitive description: name: test_api - sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd + sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" url: "https://pub.dev" source: hosted - version: "0.7.4" + version: "0.7.6" url_launcher: dependency: transitive description: @@ -384,10 +365,10 @@ packages: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" very_good_analysis: dependency: "direct dev" description: @@ -413,5 +394,5 @@ packages: source: hosted version: "1.1.1" sdks: - dart: ">=3.7.0 <4.0.0" - flutter: ">=3.27.0" + dart: ">=3.9.0 <4.0.0" + flutter: ">=3.35.0" diff --git a/example/pubspec.yaml b/example/pubspec.yaml index f0ba5ac2..054e8da6 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -14,7 +14,7 @@ dependencies: flutter_login: path: ../ font_awesome_flutter: ^10.0.0 - intl: ^0.19.0 + intl: ^0.20.0 dev_dependencies: flutter_test: diff --git a/lib/src/widgets/animated_text_form_field.dart b/lib/src/widgets/animated_text_form_field.dart index 732fc807..ea59829b 100644 --- a/lib/src/widgets/animated_text_form_field.dart +++ b/lib/src/widgets/animated_text_form_field.dart @@ -2,10 +2,11 @@ import 'dart:math'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; import 'package:flutter_login/flutter_login.dart'; import 'package:flutter_login/src/widgets/term_of_service_checkbox.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:intl_phone_number_input/intl_phone_number_input.dart'; +import 'package:form_builder_phone_field/form_builder_phone_field.dart'; import 'package:phone_numbers_parser/phone_numbers_parser.dart' as pnp; import 'package:url_launcher/url_launcher.dart'; @@ -171,7 +172,6 @@ class _AnimatedTextFormFieldState extends State { late Animation iconRotationAnimation; late Animation iconTranslateAnimation; - PhoneNumber? _phoneNumberInitialValue; final TextEditingController _phoneNumberController = TextEditingController(); @override @@ -241,19 +241,18 @@ class _AnimatedTextFormFieldState extends State { } if (widget.userType == LoginUserType.intlPhone) { - _phoneNumberInitialValue = PhoneNumber( - isoCode: widget.initialIsoCode ?? 'US', - dialCode: '+1', - ); + _phoneNumberController.text = pnp.PhoneNumber( + isoCode: pnp.IsoCode.fromJson(widget.initialIsoCode ?? 'US'), + nsn: '', + ).nsn; if (widget.controller?.value.text != null) { try { final parsed = pnp.PhoneNumber.parse(widget.controller!.value.text); if (parsed.isValid()) { - _phoneNumberInitialValue = PhoneNumber( - phoneNumber: parsed.nsn, - isoCode: parsed.isoCode.name, - dialCode: parsed.countryCode, - ); + _phoneNumberController.text = pnp.PhoneNumber( + nsn: parsed.nsn, + isoCode: pnp.IsoCode.fromJson(parsed.isoCode.name), + ).nsn; } } on pnp.PhoneNumberException { // ignore @@ -329,75 +328,47 @@ class _AnimatedTextFormFieldState extends State { return InputDecoration( labelText: widget.labelText, prefixIcon: _buildInertiaAnimation(widget.prefixIcon), - suffixIcon: _buildInertiaAnimation( - widget.loadingController != null - ? FadeTransition( - opacity: suffixIconOpacityAnimation, - child: widget.suffixIcon, - ) - : widget.suffixIcon, - ), + suffixIcon: widget.userType == LoginUserType.intlPhone + ? null + : _buildInertiaAnimation( + widget.loadingController != null + ? FadeTransition( + opacity: suffixIconOpacityAnimation, + child: widget.suffixIcon, + ) + : widget.suffixIcon, + ), ); } + final _formKey = GlobalKey(); + @override Widget build(BuildContext context) { final theme = Theme.of(context); Widget inputField; if (widget.userType == LoginUserType.intlPhone) { - inputField = Padding( - padding: const EdgeInsets.only(left: 8), - child: InternationalPhoneNumberInput( + _phoneNumberController.addListener(() { + final phoneNumber = (_formKey.currentState?.fields['phone_number_intl'] + as FormBuilderPhoneFieldState?) + ?.fullNumber; + if (phoneNumber == null) return; + widget.controller?.text = phoneNumber; + }); + + inputField = FormBuilder( + key: _formKey, + child: FormBuilderPhoneField( + name: 'phone_number_intl', + iconSelector: const SizedBox.shrink(), cursorColor: theme.primaryColor, focusNode: widget.focusNode, - inputDecoration: _getInputDecoration(theme), - searchBoxDecoration: const InputDecoration( - contentPadding: EdgeInsets.only(left: 20), - labelText: 'Search by country name or dial code', - ), + decoration: _getInputDecoration(theme), keyboardType: widget.keyboardType ?? TextInputType.phone, onFieldSubmitted: widget.onFieldSubmitted, - onSaved: (phoneNumber) { - if (phoneNumber.phoneNumber == phoneNumber.dialCode) { - widget.controller?.text = ''; - } else { - widget.controller?.text = phoneNumber.phoneNumber ?? ''; - } - _phoneNumberController.selection = TextSelection.collapsed( - offset: _phoneNumberController.text.length, - ); - widget.onSaved?.call(phoneNumber.phoneNumber); - }, validator: widget.validator, - autofillHints: widget.autofillHints, - onInputChanged: (phoneNumber) { - if (phoneNumber.phoneNumber != null && - phoneNumber.dialCode != null && - phoneNumber.phoneNumber!.startsWith('+')) { - _phoneNumberController.text = - _phoneNumberController.text.replaceAll( - RegExp( - '^([\\+]${phoneNumber.dialCode!.replaceAll('+', '')}[\\s]?)', - ), - '', - ); - } - _phoneNumberController.selection = TextSelection.collapsed( - offset: _phoneNumberController.text.length, - ); - }, - textFieldController: _phoneNumberController, - isEnabled: widget.enabled, - selectorConfig: SelectorConfig( - selectorType: PhoneInputSelectorType.DIALOG, - trailingSpace: false, - countryComparator: (c1, c2) => - int.parse(c1.dialCode!.substring(1)).compareTo( - int.parse(c2.dialCode!.substring(1)), - ), - ), - spaceBetweenSelectorAndTextField: 0, - initialValue: _phoneNumberInitialValue, + controller: _phoneNumberController, + enabled: widget.enabled, ), ); } else if (widget.userType == LoginUserType.checkbox) { diff --git a/pubspec.yaml b/pubspec.yaml index 3ca9e0bf..4e574161 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,8 +15,11 @@ dependencies: another_transformer_page_view: ^2.0.0 flutter: sdk: flutter + flutter_form_builder: ^10.1.0 + flutter_localizations: + sdk: flutter font_awesome_flutter: ^10.0.0 - intl_phone_number_input: ^0.7.4 + form_builder_phone_field: ^3.0.0 phone_numbers_parser: ^9.0.0 provider: ^6.0.1 quiver: ^3.0.1 @@ -27,7 +30,7 @@ dev_dependencies: flutter_test: sdk: flutter mockito: ^5.0.16 - very_good_analysis: ^8.0.0 + very_good_analysis: ^9.0.0 flutter: uses-material-design: true From c71373302184c8a2839ef4ecdf311c7f0e1c685a Mon Sep 17 00:00:00 2001 From: Julian Steenbakker Date: Wed, 17 Sep 2025 12:40:02 +0200 Subject: [PATCH 10/12] fix: deprecated members --- lib/src/widgets/animated_text.dart | 20 +++++++++++-------- lib/src/widgets/animated_text_form_field.dart | 2 +- lib/src/widgets/cards/auth_card_builder.dart | 6 ++++-- lib/src/widgets/custom_page_transformer.dart | 7 +++++-- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/lib/src/widgets/animated_text.dart b/lib/src/widgets/animated_text.dart index 548ce6f0..8cd48cb0 100644 --- a/lib/src/widgets/animated_text.dart +++ b/lib/src/widgets/animated_text.dart @@ -120,40 +120,44 @@ class _AnimatedTextState extends State Matrix4 _getFrontSideUp(double value) { return _matrix - ..translate( - 0.0, + ..translateByDouble( + 0, -radius * sin(_animation.value), -radius * cos(_animation.value), + 1, ) ..rotateX(-_animation.value); // 0 -> -pi/2 } Matrix4 _getBackSideUp(double value) { return _matrix - ..translate( - 0.0, + ..translateByDouble( + 0, radius * cos(_animation.value), -radius * sin(_animation.value), + 1, ) ..rotateX((pi / 2) - _animation.value); // pi/2 -> 0 } Matrix4 _getFrontSideDown(double value) { return _matrix - ..translate( - 0.0, + ..translateByDouble( + 0, radius * sin(_animation.value), -radius * cos(_animation.value), + 1, ) ..rotateX(_animation.value); // 0 -> pi/2 } Matrix4 _getBackSideDown(double value) { return _matrix - ..translate( - 0.0, + ..translateByDouble( + 0, -radius * cos(_animation.value), -radius * sin(_animation.value), + 1, ) ..rotateX(_animation.value - pi / 2); // -pi/2 -> 0 } diff --git a/lib/src/widgets/animated_text_form_field.dart b/lib/src/widgets/animated_text_form_field.dart index ea59829b..e390e322 100644 --- a/lib/src/widgets/animated_text_form_field.dart +++ b/lib/src/widgets/animated_text_form_field.dart @@ -316,7 +316,7 @@ class _AnimatedTextFormFieldState extends State { builder: (context, child) => Transform( alignment: Alignment.center, transform: Matrix4.identity() - ..translate(iconTranslateAnimation.value) + ..translateByDouble(iconTranslateAnimation.value, 0, 0, 1) ..rotateZ(iconRotationAnimation.value), child: child, ), diff --git a/lib/src/widgets/cards/auth_card_builder.dart b/lib/src/widgets/cards/auth_card_builder.dart index 9c8485f3..3f293dd8 100644 --- a/lib/src/widgets/cards/auth_card_builder.dart +++ b/lib/src/widgets/cards/auth_card_builder.dart @@ -606,8 +606,10 @@ class AuthCardState extends State with TickerProviderStateMixin { alignment: Alignment.center, transform: Matrix4.identity() ..rotateZ(_cardRotationAnimation.value) - ..scale(_cardSizeAnimation.value, _cardSizeAnimation.value) - ..scale(_cardSize2AnimationX.value, _cardSize2AnimationY.value), + ..scaleByDouble(_cardSizeAnimation.value, _cardSizeAnimation.value, + _cardSizeAnimation.value, 1) + ..scaleByDouble(_cardSize2AnimationX.value, + _cardSize2AnimationY.value, _cardSize2AnimationX.value, 1), child: current, ); }, diff --git a/lib/src/widgets/custom_page_transformer.dart b/lib/src/widgets/custom_page_transformer.dart index cf8941d6..757d9ec7 100644 --- a/lib/src/widgets/custom_page_transformer.dart +++ b/lib/src/widgets/custom_page_transformer.dart @@ -20,13 +20,16 @@ class CustomPageTransformer extends PageTransformer { final pageDt = 1 - position.abs(); // Apply scale and Y-axis rotation based on the page's position. + final scale = lerp(0.6, 1, pageDt); if (position > 0) { transform - ..scale(lerp(0.6, 1, pageDt)) // Scale up as it approaches center + ..scaleByDouble( + scale, scale, scale, 1) // Scale up as it approaches center ..rotateY(position * -1.5); // Rotate left for right-side pages } else { transform - ..scale(lerp(0.6, 1, pageDt)) // Scale up as it approaches center + ..scaleByDouble( + scale, scale, scale, 1) // Scale up as it approaches center ..rotateY(position * 1.5); // Rotate right for left-side pages } From f7315eb9a63fbf7d6a66cd5c666f2682cd77f4e1 Mon Sep 17 00:00:00 2001 From: Julian Steenbakker Date: Wed, 17 Sep 2025 12:53:54 +0200 Subject: [PATCH 11/12] release of v6.0.0 --- CHANGELOG.md | 8 +++++++ .../flutter/generated_plugin_registrant.cc | 15 ------------ .../flutter/generated_plugin_registrant.h | 15 ------------ example/linux/flutter/generated_plugins.cmake | 24 ------------------- .../flutter/generated_plugin_registrant.cc | 14 ----------- .../flutter/generated_plugin_registrant.h | 15 ------------ .../windows/flutter/generated_plugins.cmake | 24 ------------------- pubspec.yaml | 2 +- 8 files changed, 9 insertions(+), 108 deletions(-) delete mode 100644 example/linux/flutter/generated_plugin_registrant.cc delete mode 100644 example/linux/flutter/generated_plugin_registrant.h delete mode 100644 example/linux/flutter/generated_plugins.cmake delete mode 100644 example/windows/flutter/generated_plugin_registrant.cc delete mode 100644 example/windows/flutter/generated_plugin_registrant.h delete mode 100644 example/windows/flutter/generated_plugins.cmake diff --git a/CHANGELOG.md b/CHANGELOG.md index fadf955d..f47c5a75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## 6.0.0 +Breaking Changes: +- Replaced intl_phone_number_input with form_builder_phone_field, removing need for platform specific code. +This change makes the plugin WASM compatible & fixes build errors on Android. + +Other changes: +- Updated dependencies, fixed deprecated member usages + ## 5.1.0 Features: - Added background image (thanks @alenas !) diff --git a/example/linux/flutter/generated_plugin_registrant.cc b/example/linux/flutter/generated_plugin_registrant.cc deleted file mode 100644 index f6f23bfe..00000000 --- a/example/linux/flutter/generated_plugin_registrant.cc +++ /dev/null @@ -1,15 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#include "generated_plugin_registrant.h" - -#include - -void fl_register_plugins(FlPluginRegistry* registry) { - g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = - fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); - url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); -} diff --git a/example/linux/flutter/generated_plugin_registrant.h b/example/linux/flutter/generated_plugin_registrant.h deleted file mode 100644 index e0f0a47b..00000000 --- a/example/linux/flutter/generated_plugin_registrant.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#ifndef GENERATED_PLUGIN_REGISTRANT_ -#define GENERATED_PLUGIN_REGISTRANT_ - -#include - -// Registers Flutter plugins. -void fl_register_plugins(FlPluginRegistry* registry); - -#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/example/linux/flutter/generated_plugins.cmake b/example/linux/flutter/generated_plugins.cmake deleted file mode 100644 index f16b4c34..00000000 --- a/example/linux/flutter/generated_plugins.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# -# Generated file, do not edit. -# - -list(APPEND FLUTTER_PLUGIN_LIST - url_launcher_linux -) - -list(APPEND FLUTTER_FFI_PLUGIN_LIST -) - -set(PLUGIN_BUNDLED_LIBRARIES) - -foreach(plugin ${FLUTTER_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) - target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) - list(APPEND PLUGIN_BUNDLED_LIBRARIES $) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) -endforeach(plugin) - -foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) -endforeach(ffi_plugin) diff --git a/example/windows/flutter/generated_plugin_registrant.cc b/example/windows/flutter/generated_plugin_registrant.cc deleted file mode 100644 index 4f788487..00000000 --- a/example/windows/flutter/generated_plugin_registrant.cc +++ /dev/null @@ -1,14 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#include "generated_plugin_registrant.h" - -#include - -void RegisterPlugins(flutter::PluginRegistry* registry) { - UrlLauncherWindowsRegisterWithRegistrar( - registry->GetRegistrarForPlugin("UrlLauncherWindows")); -} diff --git a/example/windows/flutter/generated_plugin_registrant.h b/example/windows/flutter/generated_plugin_registrant.h deleted file mode 100644 index dc139d85..00000000 --- a/example/windows/flutter/generated_plugin_registrant.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#ifndef GENERATED_PLUGIN_REGISTRANT_ -#define GENERATED_PLUGIN_REGISTRANT_ - -#include - -// Registers Flutter plugins. -void RegisterPlugins(flutter::PluginRegistry* registry); - -#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/example/windows/flutter/generated_plugins.cmake b/example/windows/flutter/generated_plugins.cmake deleted file mode 100644 index 88b22e5c..00000000 --- a/example/windows/flutter/generated_plugins.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# -# Generated file, do not edit. -# - -list(APPEND FLUTTER_PLUGIN_LIST - url_launcher_windows -) - -list(APPEND FLUTTER_FFI_PLUGIN_LIST -) - -set(PLUGIN_BUNDLED_LIBRARIES) - -foreach(plugin ${FLUTTER_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) - target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) - list(APPEND PLUGIN_BUNDLED_LIBRARIES $) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) -endforeach(plugin) - -foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) -endforeach(ffi_plugin) diff --git a/pubspec.yaml b/pubspec.yaml index 4e574161..d1e924b2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_login description: A login widget with login/signup functionalities to help speed up development -version: 5.1.0 +version: 6.0.0 repository: https://github.com/NearHuscarl/flutter_login screenshots: - description: 'This screenshot shows the default themed login screen..' From 183fe56ca14384741c777e1430f6e21eeecb057a Mon Sep 17 00:00:00 2001 From: sebastiano-ia Date: Thu, 26 Mar 2026 11:42:14 +0100 Subject: [PATCH 12/12] Introduce `AuthModeAwareValidator` for enhanced context-aware validation for separated login and signup forms. --- example/lib/login_screen.dart | 4 +- lib/flutter_login.dart | 8 +- lib/src/providers/auth.dart | 12 +++ lib/src/widgets/cards/auth_card_builder.dart | 7 +- lib/src/widgets/cards/login_card.dart | 9 +- lib/src/widgets/cards/recover_card.dart | 4 +- test/flutter_login_test.dart | 98 ++++++++++++-------- test/utils.dart | 26 ++++-- 8 files changed, 105 insertions(+), 63 deletions(-) diff --git a/example/lib/login_screen.dart b/example/lib/login_screen.dart index aef0f3de..cda7dd72 100644 --- a/example/lib/login_screen.dart +++ b/example/lib/login_screen.dart @@ -226,13 +226,13 @@ class LoginScreen extends StatelessWidget { // // shape: ContinuousRectangleBorder(borderRadius: BorderRadius.circular(55.0)), // ), // ), - userValidator: (value) { + userValidator: (value, _) { if (!value!.contains('@') || !value.endsWith('.com')) { return "Email must contain '@' and end with '.com'"; } return null; }, - passwordValidator: (value) { + passwordValidator: (value, _) { if (value!.isEmpty) { return 'Password is empty'; } diff --git a/lib/flutter_login.dart b/lib/flutter_login.dart index 09911dcf..5918f987 100644 --- a/lib/flutter_login.dart +++ b/lib/flutter_login.dart @@ -410,14 +410,14 @@ class FlutterLogin extends StatefulWidget { /// Email validating logic, Returns an error string to display if the input is /// invalid, or null otherwise - final FormFieldValidator? userValidator; + final AuthModeAwareValidator? userValidator; /// Should email be validated after losing focus true or after form /// submissions false. Default: false final bool? validateUserImmediately; /// Same as [userValidator] but for password - final FormFieldValidator? passwordValidator; + final AuthModeAwareValidator? passwordValidator; /// Called after the submit animation's completed. Put your route transition /// logic here. Recommend to use with [logoTag] and [titleTag] @@ -541,7 +541,7 @@ class FlutterLogin extends StatefulWidget { /// Default email validator used when none is supplied. /// /// Returns `'Invalid email!'` if the value is null, empty, or doesn't match a basic email regex. - static String? defaultEmailValidator(String? value) { + static String? defaultEmailValidator(String? value, AuthMode authMode) { if (value == null || value.isEmpty || !email.hasMatch(value)) { return 'Invalid email!'; } @@ -551,7 +551,7 @@ class FlutterLogin extends StatefulWidget { /// Default password validator used when none is supplied. /// /// Returns `'Password is too short!'` if the value is null, empty, or shorter than 3 characters. - static String? defaultPasswordValidator(String? value) { + static String? defaultPasswordValidator(String? value, AuthMode authMode) { if (value == null || value.isEmpty || value.length <= 2) { return 'Password is too short!'; } diff --git a/lib/src/providers/auth.dart b/lib/src/providers/auth.dart index 1458a86e..0eb41ff2 100644 --- a/lib/src/providers/auth.dart +++ b/lib/src/providers/auth.dart @@ -61,6 +61,13 @@ typedef ConfirmSignupRequiredCallback = Future Function(LoginData); /// The result is an error message; callback succeeds if the message is null. typedef ConfirmRecoverCallback = Future? Function(String, LoginData); +/// Validator that also provides auth mode to the function, so that client code +/// can execute different validation for login/signup +typedef AuthModeAwareValidator = String? Function( + T? value, + AuthMode authMode, + ); + /// Provides and manages authentication state and callbacks. class Auth with ChangeNotifier { /// Creates an instance of [Auth] to manage the login/signup state and related callbacks. @@ -118,6 +125,7 @@ class Auth with ChangeNotifier { /// The type of authentication being used (password or provider). AuthType get authType => _authType; + set authType(AuthType authType) { _authType = authType; notifyListeners(); @@ -127,6 +135,7 @@ class Auth with ChangeNotifier { /// Current authentication mode (login or signup). AuthMode get mode => _mode; + set mode(AuthMode value) { _mode = value; notifyListeners(); @@ -160,6 +169,7 @@ class Auth with ChangeNotifier { /// Email or username entered by the user. String get email => _email; + set email(String email) { _email = email; notifyListeners(); @@ -169,6 +179,7 @@ class Auth with ChangeNotifier { /// Password entered by the user. String get password => _password; + set password(String password) { _password = password; notifyListeners(); @@ -178,6 +189,7 @@ class Auth with ChangeNotifier { /// Confirmation password entered by the user during sign up. String get confirmPassword => _confirmPassword; + set confirmPassword(String confirmPassword) { _confirmPassword = confirmPassword; notifyListeners(); diff --git a/lib/src/widgets/cards/auth_card_builder.dart b/lib/src/widgets/cards/auth_card_builder.dart index 9c8485f3..24a8aaaf 100644 --- a/lib/src/widgets/cards/auth_card_builder.dart +++ b/lib/src/widgets/cards/auth_card_builder.dart @@ -76,13 +76,13 @@ class AuthCard extends StatefulWidget { final AnimationController loadingController; /// Validator for the user input field (email/username/etc). - final FormFieldValidator? userValidator; + final AuthModeAwareValidator? userValidator; /// Whether to validate the user field immediately on blur. final bool? validateUserImmediately; /// Validator for the password input field. - final FormFieldValidator? passwordValidator; + final AuthModeAwareValidator? passwordValidator; /// Called when the form is submitted (e.g., login/signup). final VoidCallback? onSubmit; @@ -524,7 +524,8 @@ class AuthCardState extends State with TickerProviderStateMixin { case _confirmRecover: return _ConfirmRecoverCard( key: _confirmRecoverCardKey, - passwordValidator: widget.passwordValidator!, + passwordValidator: (s) => + widget.passwordValidator!.call(s, AuthMode.signup), onBack: () => _changeCard(_loginPageIndex), onSubmitCompleted: () => _changeCard(_loginPageIndex), initialIsoCode: widget.initialIsoCode, diff --git a/lib/src/widgets/cards/login_card.dart b/lib/src/widgets/cards/login_card.dart index b59ee0b8..96d16bbf 100644 --- a/lib/src/widgets/cards/login_card.dart +++ b/lib/src/widgets/cards/login_card.dart @@ -33,9 +33,9 @@ class _LoginCard extends StatefulWidget { }); final AnimationController loadingController; - final FormFieldValidator? userValidator; + final AuthModeAwareValidator? userValidator; final bool? validateUserImmediately; - final FormFieldValidator? passwordValidator; + final AuthModeAwareValidator? passwordValidator; final VoidCallback onSwitchRecoveryPassword; final VoidCallback onSwitchSignUpAdditionalData; final VoidCallback onSwitchConfirmSignup; @@ -401,7 +401,7 @@ class _LoginCardState extends State<_LoginCard> with TickerProviderStateMixin { onFieldSubmitted: (value) { FocusScope.of(context).requestFocus(_passwordFocusNode); }, - validator: widget.userValidator, + validator: (s) => widget.userValidator?.call(s, auth.mode), onSaved: (value) => auth.email = value!, enabled: !_isSubmitting, initialIsoCode: widget.initialIsoCode, @@ -431,7 +431,8 @@ class _LoginCardState extends State<_LoginCard> with TickerProviderStateMixin { FocusScope.of(context).requestFocus(_confirmPasswordFocusNode); } }, - validator: widget.passwordValidator, + validator: (String? value) => + widget.passwordValidator?.call(value, auth.mode), onSaved: (value) => auth.password = value!, enabled: !_isSubmitting, initialIsoCode: widget.initialIsoCode, diff --git a/lib/src/widgets/cards/recover_card.dart b/lib/src/widgets/cards/recover_card.dart index a8298d82..a1e8f251 100644 --- a/lib/src/widgets/cards/recover_card.dart +++ b/lib/src/widgets/cards/recover_card.dart @@ -13,7 +13,7 @@ class _RecoverCard extends StatefulWidget { this.loginTheme, }); - final FormFieldValidator? userValidator; + final AuthModeAwareValidator? userValidator; final VoidCallback onBack; final LoginUserType userType; final LoginTheme? loginTheme; @@ -109,7 +109,7 @@ class _RecoverCardState extends State<_RecoverCard> autofillHints: [getAutofillHints(widget.userType)], textInputAction: TextInputAction.done, onFieldSubmitted: (value) => _submit(), - validator: widget.userValidator, + validator: (s) => widget.userValidator?.call(s, AuthMode.login), onSaved: (value) => auth.email = value!, initialIsoCode: widget.initialIsoCode, autofocus: widget.autofocusName, diff --git a/test/flutter_login_test.dart b/test/flutter_login_test.dart index 827f434d..317503e8 100644 --- a/test/flutter_login_test.dart +++ b/test/flutter_login_test.dart @@ -183,8 +183,8 @@ void main() { onSignup: (data) => null, onLogin: (data) => null, onRecoverPassword: (data) => null, - userValidator: (value) => - value!.endsWith('.com') ? null : 'Invalid!', + userValidator: (value, authMode) => + value!.endsWith('.com') ? null : 'Invalid!', ), ); await tester.pumpWidget(loginBuilder()); @@ -216,8 +216,8 @@ void main() { onSignup: (data) => null, onLogin: (data) => null, onRecoverPassword: (data) => null, - passwordValidator: (value) => - value!.length == 5 ? null : 'Invalid!', + passwordValidator: (value, authMode) => + value!.length == 5 ? null : 'Invalid!', ), ); await tester.pumpWidget(loginBuilder()); @@ -532,8 +532,8 @@ void main() { await tester.pumpAndSettle(); verifyInOrder([ - mockCallback.userValidator('invalid-name'), - mockCallback.passwordValidator(user.password), + mockCallback.userValidator('invalid-name', AuthMode.login), + mockCallback.passwordValidator(user.password, AuthMode.login), ]); verifyNever(mockCallback.onLogin(any)); verifyNever(mockCallback.onSubmitAnimationCompleted()); @@ -550,8 +550,8 @@ void main() { await tester.pumpAndSettle(); verifyInOrder([ - mockCallback.userValidator(invalidUser.name), - mockCallback.passwordValidator(invalidUser.password), + mockCallback.userValidator(invalidUser.name, AuthMode.login), + mockCallback.passwordValidator(invalidUser.password, AuthMode.login), mockCallback.onLogin(any), ]); verifyNever(mockCallback.onSubmitAnimationCompleted()); @@ -568,8 +568,8 @@ void main() { await tester.pumpAndSettle(); verifyInOrder([ - mockCallback.userValidator(user.name), - mockCallback.passwordValidator(user.password), + mockCallback.userValidator(user.name, AuthMode.login), + mockCallback.passwordValidator(user.password, AuthMode.login), mockCallback.onLogin(any), mockCallback.onSubmitAnimationCompleted(), ]); @@ -612,8 +612,18 @@ void main() { clickSubmitButton(); await tester.pumpAndSettle(); - verifyNever(mockCallback.userValidator(invalidUser.name)); - verifyNever(mockCallback.passwordValidator(invalidUser.password)); + verifyNever( + mockCallback.userValidator( + invalidUser.name, + AuthMode.signup, + ), + ); + verifyNever( + mockCallback.passwordValidator( + invalidUser.password, + AuthMode.signup, + ), + ); verifyNever(mockCallback.onSignup(any)); verifyNever(mockCallback.onSubmitAnimationCompleted()); @@ -631,8 +641,8 @@ void main() { await tester.pumpAndSettle(); verifyInOrder([ - mockCallback.userValidator('invalid-name'), - mockCallback.passwordValidator(user.password), + mockCallback.userValidator('invalid-name', AuthMode.signup), + mockCallback.passwordValidator(user.password, AuthMode.signup), ]); verifyNever(mockCallback.onSignup(any)); verifyNever(mockCallback.onSubmitAnimationCompleted()); @@ -654,8 +664,8 @@ void main() { await tester.pumpAndSettle(); verifyInOrder([ - mockCallback.userValidator(invalidUser.name), - mockCallback.passwordValidator(invalidUser.password), + mockCallback.userValidator(invalidUser.name, AuthMode.signup), + mockCallback.passwordValidator(invalidUser.password, AuthMode.signup), mockCallback.onSignup(any), ]); verifyNever(mockCallback.onSubmitAnimationCompleted()); @@ -674,8 +684,8 @@ void main() { await tester.pumpAndSettle(); verifyInOrder([ - mockCallback.userValidator(user.name), - mockCallback.passwordValidator(user.password), + mockCallback.userValidator(user.name, AuthMode.signup), + mockCallback.passwordValidator(user.password, AuthMode.signup), mockCallback.onSignup(any), mockCallback.onSubmitAnimationCompleted(), ]); @@ -697,11 +707,13 @@ void main() { additionalSignupFields: [ UserFormField( keyName: 'Name', - fieldValidator: mockCallback.userValidator, + fieldValidator: (s) => + mockCallback.userValidator(s, AuthMode.signup), ), UserFormField( keyName: 'Surname', - fieldValidator: mockCallback.userValidator, + fieldValidator: (s) => + mockCallback.userValidator(s, AuthMode.signup), ), ], ), @@ -728,8 +740,18 @@ void main() { clickSubmitButton(); await tester.pumpAndSettle(); - verifyNever(mockCallback.userValidator(invalidUser.name)); - verifyNever(mockCallback.passwordValidator(invalidUser.password)); + verifyNever( + mockCallback.userValidator( + invalidUser.name, + AuthMode.signup, + ), + ); + verifyNever( + mockCallback.passwordValidator( + invalidUser.password, + AuthMode.signup, + ), + ); verifyNever(mockCallback.onSignup(any)); verifyNever(mockCallback.onSubmitAnimationCompleted()); @@ -747,8 +769,8 @@ void main() { await tester.pumpAndSettle(); verifyInOrder([ - mockCallback.userValidator('invalid-name'), - mockCallback.passwordValidator(user.password), + mockCallback.userValidator('invalid-name', AuthMode.signup), + mockCallback.passwordValidator(user.password, AuthMode.signup), ]); verifyNever(mockCallback.onSignup(any)); verifyNever(mockCallback.onSubmitAnimationCompleted()); @@ -770,8 +792,8 @@ void main() { await tester.pumpAndSettle(); verifyInOrder([ - mockCallback.userValidator(invalidUser.name), - mockCallback.passwordValidator(invalidUser.password), + mockCallback.userValidator(invalidUser.name, AuthMode.signup), + mockCallback.passwordValidator(invalidUser.password, AuthMode.signup), ]); verifyNever(mockCallback.onSignup(any)); verifyNever(mockCallback.onSubmitAnimationCompleted()); @@ -796,8 +818,8 @@ void main() { await tester.pumpAndSettle(); verifyInOrder([ - mockCallback.userValidator('foo'), - mockCallback.userValidator('bar'), + mockCallback.userValidator('foo', AuthMode.signup), + mockCallback.userValidator('bar', AuthMode.signup), mockCallback.onSignup(any), mockCallback.onSubmitAnimationCompleted(), ]); @@ -899,7 +921,7 @@ void main() { FlutterLogin( onLogin: (data) => null, onRecoverPassword: (data) => null, - passwordValidator: (value) => + passwordValidator: (value, authMode) => value!.length == 5 ? null : 'Invalid!', hideForgotPasswordButton: true, messages: LoginMessages( @@ -921,7 +943,7 @@ void main() { onSignup: (data) => null, onLogin: (data) => null, onRecoverPassword: (data) => null, - passwordValidator: (value) => + passwordValidator: (value, authMode) => value!.length == 5 ? null : 'Invalid!', loginProviders: [ LoginProvider( @@ -949,8 +971,8 @@ void main() { onSignup: (data) => null, onLogin: (data) => null, onRecoverPassword: (data) => null, - passwordValidator: (value) => - value!.length == 5 ? null : 'Invalid!', + passwordValidator: (value, authMode) => + value!.length == 5 ? null : 'Invalid!', messages: LoginMessages( signupButton: 'REGISTER', forgotPasswordButton: 'Forgot huh?', @@ -968,7 +990,7 @@ void main() { onSignup: (data) => null, onLogin: (data) => null, onRecoverPassword: (data) => null, - passwordValidator: (value) => + passwordValidator: (value, authMode) => value!.length == 5 ? null : 'Invalid!', hideProvidersTitle: true, loginProviders: [ @@ -1056,7 +1078,7 @@ void main() { onSignup: (data) => null, onLogin: (data) => null, onRecoverPassword: (data) => null, - passwordValidator: (value) => null, + passwordValidator: (value, authMode) => null, ), ); await tester.pumpWidget(loginBuilder()); @@ -1092,7 +1114,7 @@ void main() { }, onLogin: (data) => null, onRecoverPassword: (data) => null, - passwordValidator: (value) => null, + passwordValidator: (value, authMode) => null, additionalSignupFields: const [ UserFormField(keyName: 'Name'), UserFormField(keyName: 'Surname'), @@ -1146,7 +1168,7 @@ void main() { onSignup: (data) => null, onLogin: (data) => null, onRecoverPassword: (data) => null, - passwordValidator: (value) => null, + passwordValidator: (value, authMode) => null, additionalSignupFields: const [ UserFormField(keyName: 'Name'), UserFormField(keyName: 'Surname'), @@ -1192,7 +1214,7 @@ void main() { onSignup: (data) => null, onLogin: (data) => null, onRecoverPassword: (data) => null, - passwordValidator: (value) => null, + passwordValidator: (value, authMode) => null, additionalSignupFields: const [ UserFormField(keyName: 'Name'), UserFormField(keyName: 'Surname'), @@ -1238,7 +1260,7 @@ void main() { onSignup: (data) => null, onLogin: (data) => null, onRecoverPassword: (data) => null, - passwordValidator: (value) => null, + passwordValidator: (value, authMode) => null, footer: 'Copyright flutter_login', ), ); diff --git a/test/utils.dart b/test/utils.dart index c083ce8b..a5336760 100644 --- a/test/utils.dart +++ b/test/utils.dart @@ -12,8 +12,8 @@ class LoginCallback { Future? onLogin(LoginData? data) => null; Future? onSignup(SignupData? data) => null; Future? onRecoverPassword(String? data) => null; - String? userValidator(String? value) => null; - String? passwordValidator(String? value) => null; + String? userValidator(String? value, AuthMode authMode) => null; + String? passwordValidator(String? value, AuthMode authMode) => null; void onSubmitAnimationCompleted() {} } @@ -27,11 +27,14 @@ List loginStubCallback(MockCallback mockCallback) { const user = LoginData(name: 'near@gmail.com', password: '12345'); const invalidUser = LoginData(name: 'not.exists@gmail.com', password: ''); - when(mockCallback.userValidator(user.name)).thenReturn(null); - when(mockCallback.userValidator('invalid-name')).thenReturn('Invalid!'); + when(mockCallback.userValidator(user.name, AuthMode.login)).thenReturn(null); + when(mockCallback.userValidator('invalid-name', AuthMode.login)) + .thenReturn('Invalid!'); - when(mockCallback.passwordValidator(user.password)).thenReturn(null); - when(mockCallback.passwordValidator('invalid-name')).thenReturn('Invalid!'); + when(mockCallback.passwordValidator(user.password, AuthMode.login)) + .thenReturn(null); + when(mockCallback.passwordValidator('invalid-name', AuthMode.login)) + .thenReturn('Invalid!'); when(mockCallback.onLogin(user)).thenAnswer((_) => null); when(mockCallback.onLogin(invalidUser)) @@ -48,11 +51,14 @@ List signupStubCallback(MockCallback mockCallback) { const invalidUser = SignupData.fromSignupForm(name: 'not.exists@gmail.com', password: ''); - when(mockCallback.userValidator(user.name)).thenReturn(null); - when(mockCallback.userValidator('invalid-name')).thenReturn('Invalid!'); + when(mockCallback.userValidator(user.name, AuthMode.signup)).thenReturn(null); + when(mockCallback.userValidator('invalid-name', AuthMode.signup)) + .thenReturn('Invalid!'); - when(mockCallback.passwordValidator(user.password)).thenReturn(null); - when(mockCallback.passwordValidator('invalid-name')).thenReturn('Invalid!'); + when(mockCallback.passwordValidator(user.password, AuthMode.signup)) + .thenReturn(null); + when(mockCallback.passwordValidator('invalid-name', AuthMode.signup)) + .thenReturn('Invalid!'); when(mockCallback.onSignup(user)).thenAnswer((_) => null); when(mockCallback.onSignup(invalidUser))