[local_auth] support localizedFallbackTitle in IOSAuthMessages (#5297)

diff --git a/packages/local_auth/local_auth_ios/CHANGELOG.md b/packages/local_auth/local_auth_ios/CHANGELOG.md
index d826cc8..ccacae9 100644
--- a/packages/local_auth/local_auth_ios/CHANGELOG.md
+++ b/packages/local_auth/local_auth_ios/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.2
+
+* Adds support `localizedFallbackTitle` in authenticateWithBiometrics on iOS.
+
 ## 1.0.1
 
 * BREAKING CHANGE: Changes `stopAuthentication` to always return false instead of throwing an error.
diff --git a/packages/local_auth/local_auth_ios/ios/Classes/FLTLocalAuthPlugin.m b/packages/local_auth/local_auth_ios/ios/Classes/FLTLocalAuthPlugin.m
index d4d0e0d..ffd1dd2 100644
--- a/packages/local_auth/local_auth_ios/ios/Classes/FLTLocalAuthPlugin.m
+++ b/packages/local_auth/local_auth_ios/ios/Classes/FLTLocalAuthPlugin.m
@@ -181,6 +181,7 @@
       case LAErrorTouchIDNotAvailable:
       case LAErrorTouchIDNotEnrolled:
       case LAErrorTouchIDLockout:
+      case LAErrorUserFallback:
         [self handleErrors:error flutterArguments:arguments withFlutterResult:result];
         return;
       case LAErrorSystemCancel:
diff --git a/packages/local_auth/local_auth_ios/lib/types/auth_messages_ios.dart b/packages/local_auth/local_auth_ios/lib/types/auth_messages_ios.dart
index 8a77624..b3236a7 100644
--- a/packages/local_auth/local_auth_ios/lib/types/auth_messages_ios.dart
+++ b/packages/local_auth/local_auth_ios/lib/types/auth_messages_ios.dart
@@ -16,6 +16,7 @@
     this.goToSettingsButton,
     this.goToSettingsDescription,
     this.cancelButton,
+    this.localizedFallbackTitle,
   });
 
   /// Message advising the user to re-enable biometrics on their device.
@@ -35,6 +36,10 @@
   /// Maximum 30 characters.
   final String? cancelButton;
 
+  /// The localized title for the fallback button in the dialog presented to
+  /// the user during authentication.
+  final String? localizedFallbackTitle;
+
   @override
   Map<String, String> get args {
     return <String, String>{
@@ -43,6 +48,8 @@
       'goToSettingDescriptionIOS':
           goToSettingsDescription ?? iOSGoToSettingsDescription,
       'okButton': cancelButton ?? iOSOkButton,
+      if (localizedFallbackTitle != null)
+        'localizedFallbackTitle': localizedFallbackTitle!,
     };
   }
 
@@ -54,14 +61,16 @@
           lockOut == other.lockOut &&
           goToSettingsButton == other.goToSettingsButton &&
           goToSettingsDescription == other.goToSettingsDescription &&
-          cancelButton == other.cancelButton;
+          cancelButton == other.cancelButton &&
+          localizedFallbackTitle == other.localizedFallbackTitle;
 
   @override
   int get hashCode =>
       lockOut.hashCode ^
       goToSettingsButton.hashCode ^
       goToSettingsDescription.hashCode ^
-      cancelButton.hashCode;
+      cancelButton.hashCode ^
+      localizedFallbackTitle.hashCode;
 }
 
 // Default Strings for IOSAuthMessages plugin. Currently supports English.
diff --git a/packages/local_auth/local_auth_ios/pubspec.yaml b/packages/local_auth/local_auth_ios/pubspec.yaml
index 537b1a6..9e69dc7 100644
--- a/packages/local_auth/local_auth_ios/pubspec.yaml
+++ b/packages/local_auth/local_auth_ios/pubspec.yaml
@@ -2,7 +2,7 @@
 description: iOS implementation of the local_auth plugin.
 repository: https://github.com/flutter/plugins/tree/master/packages/local_auth/local_auth_ios
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+local_auth%22
-version: 1.0.1
+version: 1.0.2
 
 environment:
   sdk: ">=2.14.0 <3.0.0"
diff --git a/packages/local_auth/local_auth_ios/test/local_auth_test.dart b/packages/local_auth/local_auth_ios/test/local_auth_test.dart
index 180383b..aa94b8a 100644
--- a/packages/local_auth/local_auth_ios/test/local_auth_test.dart
+++ b/packages/local_auth/local_auth_ios/test/local_auth_test.dart
@@ -135,6 +135,29 @@
         );
       });
 
+      test('authenticate with `localizedFallbackTitle`', () async {
+        await localAuthentication.authenticate(
+          authMessages: <AuthMessages>[
+            const IOSAuthMessages(localizedFallbackTitle: 'Enter PIN'),
+          ],
+          localizedReason: 'Needs secure',
+        );
+        expect(
+          log,
+          <Matcher>[
+            isMethodCall('authenticate',
+                arguments: <String, dynamic>{
+                  'localizedReason': 'Needs secure',
+                  'useErrorDialogs': true,
+                  'stickyAuth': false,
+                  'sensitiveTransaction': true,
+                  'biometricOnly': false,
+                  'localizedFallbackTitle': 'Enter PIN',
+                }..addAll(const IOSAuthMessages().args)),
+          ],
+        );
+      });
+
       test('authenticate with no sensitive transaction.', () async {
         await localAuthentication.authenticate(
           authMessages: <AuthMessages>[const IOSAuthMessages()],