Skip to content

Commit

Permalink
-Fix edge case with button animation
Browse files Browse the repository at this point in the history
- Handle not supported case during biometrics authentication
  • Loading branch information
DDavidPrime committed Sep 25, 2024
1 parent 9ff447c commit 3ff0936
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 28 deletions.
2 changes: 1 addition & 1 deletion packages/widget_toolkit_pin/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ class MyHomePage extends StatelessWidget {
return 'To use biometrics, you need to turn it on in your device settings!';

case BiometricsMessage.notSupported:
return 'You don\'t have biometric feature on your device!';
return 'Biometric features aren’t supported on this device!';

case BiometricsMessage.enabled:
return 'Your biometrics are enabled!';
Expand Down
8 changes: 4 additions & 4 deletions packages/widget_toolkit_pin/example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -883,10 +883,10 @@ packages:
dependency: transitive
description:
name: vm_service
sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc
sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
url: "https://pub.dev"
source: hosted
version: "14.2.4"
version: "14.2.5"
watcher:
dependency: transitive
description:
Expand Down Expand Up @@ -932,14 +932,14 @@ packages:
path: "../../widget_toolkit_biometrics"
relative: true
source: path
version: "0.0.3"
version: "0.1.0"
widget_toolkit_pin:
dependency: "direct main"
description:
path: ".."
relative: true
source: path
version: "0.1.1"
version: "0.2.0"
xdg_directories:
dependency: transitive
description:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import 'package:rx_bloc/rx_bloc.dart';
import 'package:rxdart/rxdart.dart';
import 'package:widget_toolkit/extensions.dart';
import 'package:widget_toolkit/models.dart';
import 'package:widget_toolkit_biometrics/widget_toolkit_biometrics.dart';

import '../models/error_enable_biometrics.dart';
import '../services/pin_biometrics_service.dart';
import '../services/pin_code_service.dart';

Expand Down Expand Up @@ -162,6 +164,9 @@ class PinCodeBloc extends $PinCodeBloc {
/// Authenticates the user with biometrics after which the pin code is
/// retrieved from the device and checked.
Future<bool> _authenticateWithBiometrics() async {
if (!await biometricAuthenticationService.isDeviceSupported) {
throw ErrorEnableBiometrics(BiometricsMessage.notSupported);
}
if (await biometricAuthenticationService.authenticate(localizedReason)) {
final pinCode = await pinCodeService.getPinCode();
if (pinCode != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import '../models/biometrics_authentication_type.dart';

class PinBiometricsRepository extends BiometricsRepository {
PinBiometricsRepository(
this.biometricAuthenticationDataSource, this.localDataSource);
this.biometricAuthenticationDataSource,
this.localDataSource,
);

@override
final PinBiometricsAuthDataSource biometricAuthenticationDataSource;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -391,9 +391,7 @@ class _PinCodeComponentState extends State<PinCodeComponent>
),
),
_buildPinCodeKey(context, 0, 0),
_buildBiometricsButton(context, pinLength
// pin
),
_buildBiometricsButton(context, pinLength),
],
),
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,31 @@ class PinCodeKey extends StatefulWidget {
this.isFaceScan = false,
this.isLoading = false,
this.showDefaultIcon = false,
this.tintDuration = const Duration(milliseconds: 300),
super.key,
});

/// The number to be displayed on the key
final int? number;

/// Shows the finger scan icon if it is set to true
final bool isFingerScan;

/// Shows the face scan icon if it is set to true
final bool isFaceScan;

/// Shows the loading state of the key
final bool isLoading;

/// Shows the face scan icon if it is set to true
final bool showDefaultIcon;

/// Callback executed once the key is pressed
final void Function(int?) onPressed;

/// The duration of the tint animation once a button is pressed/released
final Duration tintDuration;

@override
State<PinCodeKey> createState() => _PinCodeKeyState();
}
Expand All @@ -39,28 +52,14 @@ class _PinCodeKeyState extends State<PinCodeKey> {
isPressed = true;
});
if (widget.isFingerScan || widget.isFaceScan) {
await Future.delayed(const Duration(milliseconds: 300));
await Future.delayed(widget.tintDuration);
}
widget.onPressed(widget.number);
},
onTapUp: widget.isLoading
? null
: (_) async {
await Future.delayed(const Duration(milliseconds: 300));
setState(() {
isPressed = false;
});
},
onHorizontalDragEnd: (_) {
setState(() {
isPressed = false;
});
},
onVerticalDragEnd: (_) {
setState(() {
isPressed = false;
});
},
onTapUp: widget.isLoading ? null : (_) => _delayedButtonRelease(),
onTapCancel: widget.isLoading ? null : _delayedButtonRelease,
onHorizontalDragEnd: (_) => _cancelPress(),
onVerticalDragEnd: (_) => _cancelPress(),
child: widget.isFingerScan
? AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
Expand Down Expand Up @@ -108,4 +107,15 @@ class _PinCodeKeyState extends State<PinCodeKey> {

double _calculateSize(BuildContext context) =>
calculateKeyboardButtonSize(context);

void _cancelPress() {
setState(() {
isPressed = false;
});
}

void _delayedButtonRelease() async {
await Future.delayed(widget.tintDuration);
_cancelPress();
}
}

0 comments on commit 3ff0936

Please sign in to comment.