This repository has been archived by the owner on Sep 17, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: Passcode UI/UX audits & Added Animations
- Loading branch information
Showing
7 changed files
with
264 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 2 additions & 0 deletions
2
lib/features/security/presentation/passcode_base/passcode_base_page_state.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
119 changes: 119 additions & 0 deletions
119
lib/features/security/presentation/passcode_base/widget/numbers_row_widget.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import 'dart:math'; | ||
|
||
import 'package:datadashwallet/common/color_filter.dart'; | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter_svg/flutter_svg.dart'; | ||
import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||
import 'package:mxc_ui/mxc_ui.dart'; | ||
|
||
import '../../passcode_require/widgets/circle_animation.dart'; | ||
|
||
class NumbersRowWidget extends StatefulWidget { | ||
const NumbersRowWidget( | ||
{super.key, | ||
required this.expectedNumbersLength, | ||
required this.enteredNumbers, | ||
required this.shakeAnimationInt}); | ||
|
||
final int expectedNumbersLength; | ||
final int enteredNumbers; | ||
final void Function(AnimationController) shakeAnimationInt; | ||
|
||
@override | ||
State<NumbersRowWidget> createState() => _NumbersRowWidgetState(); | ||
} | ||
|
||
class _NumbersRowWidgetState extends State<NumbersRowWidget> | ||
with SingleTickerProviderStateMixin { | ||
late AnimationController _animationController; | ||
late Animation<double> _animationRotation; | ||
int shakeOffset = 10; | ||
int shakeCount = 4; | ||
|
||
@override | ||
void initState() { | ||
super.initState(); | ||
_animationController = AnimationController( | ||
vsync: this, | ||
duration: const Duration(milliseconds: 400), | ||
); | ||
|
||
final tweenSequenceList = [ | ||
TweenSequenceItem<double>( | ||
tween: Tween(begin: 0, end: 2 * pi / 360), | ||
weight: 1, | ||
), | ||
for (int i = 0; i < 6; i++) | ||
TweenSequenceItem<double>( | ||
tween: Tween(begin: 2 * pi / 360, end: -2 * pi / 360) | ||
.chain(CurveTween(curve: Curves.easeInOut)), | ||
weight: 1, | ||
), | ||
TweenSequenceItem<double>( | ||
tween: Tween(begin: 0, end: 0), | ||
weight: 1, | ||
), | ||
]; | ||
|
||
_animationRotation = TweenSequence<double>(tweenSequenceList).animate( | ||
CurvedAnimation(parent: _animationController, curve: Curves.linear), | ||
); | ||
|
||
_animationController.addStatusListener(_updateStatus); | ||
|
||
widget.shakeAnimationInt(_animationController); | ||
} | ||
|
||
@override | ||
void dispose() { | ||
_animationController.removeStatusListener(_updateStatus); | ||
_animationController.dispose(); | ||
super.dispose(); | ||
} | ||
|
||
void _updateStatus(AnimationStatus status) { | ||
if (status == AnimationStatus.completed) { | ||
_animationController.reset(); | ||
} | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Expanded( | ||
child: AnimatedBuilder( | ||
animation: _animationController, | ||
builder: (context, child) { | ||
return Transform.rotate( | ||
angle: _animationRotation.value, | ||
child: child, | ||
); | ||
}, | ||
child: Padding( | ||
padding: const EdgeInsets.symmetric(horizontal: 16), | ||
child: Row( | ||
mainAxisSize: MainAxisSize.max, | ||
mainAxisAlignment: MainAxisAlignment.spaceEvenly, | ||
children: [ | ||
for (var i = 0; i < widget.expectedNumbersLength; i++) ...[ | ||
widget.enteredNumbers > i | ||
? const Expanded(child: CircleAnimation()) | ||
: Expanded( | ||
child: SvgPicture.asset( | ||
'assets/svg/security/ic_ring.svg', | ||
height: 32, | ||
width: 32, | ||
colorFilter: filterFor( | ||
ColorsTheme.of(context).iconWhite, | ||
), | ||
), | ||
), | ||
// if (i != ref.watch(state).expectedNumbersLength - 1) | ||
// const SizedBox(width: 16), | ||
], | ||
], | ||
), | ||
), | ||
), | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
86 changes: 86 additions & 0 deletions
86
lib/features/security/presentation/passcode_require/widgets/circle_animation.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:mxc_ui/mxc_ui.dart'; | ||
|
||
class CircleAnimation extends StatefulWidget { | ||
const CircleAnimation({super.key}); | ||
|
||
@override | ||
State<CircleAnimation> createState() => _CircleAnimationState(); | ||
} | ||
|
||
class _CircleAnimationState extends State<CircleAnimation> | ||
with SingleTickerProviderStateMixin { | ||
late AnimationController _controller; | ||
late Animation<double> _animationSize; | ||
late Animation<double> _animationOpacity; | ||
|
||
@override | ||
void initState() { | ||
super.initState(); | ||
_controller = AnimationController( | ||
vsync: this, | ||
duration: const Duration(milliseconds: 200), | ||
); | ||
_animationSize = Tween<double>(begin: 57.5, end: 32.0).animate( | ||
CurvedAnimation( | ||
parent: _controller, | ||
curve: Curves.easeOut, | ||
), | ||
); | ||
_animationOpacity = Tween<double>(begin: 0.0, end: 1.0).animate( | ||
CurvedAnimation( | ||
parent: _controller, | ||
curve: Curves.easeOut, | ||
), | ||
); | ||
_controller.forward(); | ||
} | ||
|
||
@override | ||
void dispose() { | ||
_controller.dispose(); | ||
super.dispose(); | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return SizedBox( | ||
height: 57.5, | ||
child: Stack( | ||
fit: StackFit.passthrough, | ||
children: [ | ||
Center( | ||
child: Container( | ||
height: 32, | ||
width: 32, | ||
decoration: BoxDecoration( | ||
border: Border.all( | ||
color: ColorsTheme.of(context).iconWhite, width: 2), | ||
shape: BoxShape.circle, | ||
), | ||
), | ||
), | ||
AnimatedBuilder( | ||
animation: _controller, | ||
builder: (BuildContext context, Widget? child) { | ||
return Center( | ||
child: Opacity( | ||
opacity: _animationOpacity.value, | ||
child: Container( | ||
height: _animationSize.value, | ||
width: _animationSize.value, | ||
decoration: BoxDecoration( | ||
color: ColorsTheme.of(context).iconWhite, | ||
shape: BoxShape.circle, | ||
), | ||
), | ||
), | ||
); | ||
}, | ||
// child: , | ||
), | ||
], | ||
), | ||
); | ||
} | ||
} |