mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-06-28 20:39:51 +00:00
add pin randomization
This commit is contained in:
parent
32e119e24f
commit
3e17d31435
9 changed files with 133 additions and 51 deletions
BIN
assets/images/shuffle.png
Normal file
BIN
assets/images/shuffle.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
|
@ -33,6 +33,7 @@ class PreferencesKey {
|
||||||
static const currentTheme = 'current_theme';
|
static const currentTheme = 'current_theme';
|
||||||
static const displayActionListModeKey = 'display_list_mode';
|
static const displayActionListModeKey = 'display_list_mode';
|
||||||
static const currentPinLength = 'current_pin_length';
|
static const currentPinLength = 'current_pin_length';
|
||||||
|
static const randomizePinCode = 'randomize_pin_code';
|
||||||
static const currentLanguageCode = 'language_code';
|
static const currentLanguageCode = 'language_code';
|
||||||
static const currentSeedPhraseLength = 'current_seed_phrase_length';
|
static const currentSeedPhraseLength = 'current_seed_phrase_length';
|
||||||
static const currentDefaultSettingsMigrationVersion =
|
static const currentDefaultSettingsMigrationVersion =
|
||||||
|
|
|
@ -19,9 +19,7 @@ abstract class AuthPageState<T extends StatefulWidget> extends State<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
class AuthPage extends StatefulWidget {
|
class AuthPage extends StatefulWidget {
|
||||||
AuthPage(this.authViewModel,
|
AuthPage(this.authViewModel, {required this.onAuthenticationFinished, this.closable = true});
|
||||||
{required this.onAuthenticationFinished,
|
|
||||||
this.closable = true});
|
|
||||||
|
|
||||||
final AuthViewModel authViewModel;
|
final AuthViewModel authViewModel;
|
||||||
final OnAuthenticationFinished onAuthenticationFinished;
|
final OnAuthenticationFinished onAuthenticationFinished;
|
||||||
|
@ -34,16 +32,14 @@ class AuthPage extends StatefulWidget {
|
||||||
class AuthPagePinCodeStateImpl extends AuthPageState<AuthPage> {
|
class AuthPagePinCodeStateImpl extends AuthPageState<AuthPage> {
|
||||||
final _key = GlobalKey<ScaffoldState>();
|
final _key = GlobalKey<ScaffoldState>();
|
||||||
final _pinCodeKey = GlobalKey<PinCodeState>();
|
final _pinCodeKey = GlobalKey<PinCodeState>();
|
||||||
final _backArrowImageDarkTheme =
|
final _backArrowImageDarkTheme = Image.asset('assets/images/close_button.png');
|
||||||
Image.asset('assets/images/close_button.png');
|
|
||||||
ReactionDisposer? _reaction;
|
ReactionDisposer? _reaction;
|
||||||
Flushbar<void>? _authBar;
|
Flushbar<void>? _authBar;
|
||||||
Flushbar<void>? _progressBar;
|
Flushbar<void>? _progressBar;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
_reaction ??=
|
_reaction ??= reaction((_) => widget.authViewModel.state, (ExecutionState state) {
|
||||||
reaction((_) => widget.authViewModel.state, (ExecutionState state) {
|
|
||||||
if (state is ExecutedSuccessfullyState) {
|
if (state is ExecutedSuccessfullyState) {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
widget.onAuthenticationFinished(true, this);
|
widget.onAuthenticationFinished(true, this);
|
||||||
|
@ -54,9 +50,7 @@ class AuthPagePinCodeStateImpl extends AuthPageState<AuthPage> {
|
||||||
if (state is IsExecutingState) {
|
if (state is IsExecutingState) {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
// null duration to make it indefinite until its disposed
|
// null duration to make it indefinite until its disposed
|
||||||
_authBar =
|
_authBar = createBar<void>(S.of(context).authentication, duration: null)..show(context);
|
||||||
createBar<void>(S.of(context).authentication, duration: null)
|
|
||||||
..show(context);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,8 +58,7 @@ class AuthPagePinCodeStateImpl extends AuthPageState<AuthPage> {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||||
_pinCodeKey.currentState?.clear();
|
_pinCodeKey.currentState?.clear();
|
||||||
dismissFlushBar(_authBar);
|
dismissFlushBar(_authBar);
|
||||||
showBar<void>(
|
showBar<void>(context, S.of(context).failed_authentication(state.error));
|
||||||
context, S.of(context).failed_authentication(state.error));
|
|
||||||
|
|
||||||
widget.onAuthenticationFinished(false, this);
|
widget.onAuthenticationFinished(false, this);
|
||||||
});
|
});
|
||||||
|
@ -75,8 +68,7 @@ class AuthPagePinCodeStateImpl extends AuthPageState<AuthPage> {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||||
_pinCodeKey.currentState?.clear();
|
_pinCodeKey.currentState?.clear();
|
||||||
dismissFlushBar(_authBar);
|
dismissFlushBar(_authBar);
|
||||||
showBar<void>(
|
showBar<void>(context, S.of(context).failed_authentication(state.error));
|
||||||
context, S.of(context).failed_authentication(state.error));
|
|
||||||
|
|
||||||
widget.onAuthenticationFinished(false, this);
|
widget.onAuthenticationFinished(false, this);
|
||||||
});
|
});
|
||||||
|
@ -102,8 +94,7 @@ class AuthPagePinCodeStateImpl extends AuthPageState<AuthPage> {
|
||||||
@override
|
@override
|
||||||
void changeProcessText(String text) {
|
void changeProcessText(String text) {
|
||||||
dismissFlushBar(_authBar);
|
dismissFlushBar(_authBar);
|
||||||
_progressBar = createBar<void>(text, duration: null)
|
_progressBar = createBar<void>(text, duration: null)..show(_key.currentContext!);
|
||||||
..show(_key.currentContext!);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -134,25 +125,33 @@ class AuthPagePinCodeStateImpl extends AuthPageState<AuthPage> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
key: _key,
|
key: _key,
|
||||||
appBar: CupertinoNavigationBar(
|
appBar: CupertinoNavigationBar(
|
||||||
leading: widget.closable
|
leading: widget.closable
|
||||||
? Container(
|
? Container(
|
||||||
padding: EdgeInsets.only(top: 10),
|
padding: EdgeInsets.only(top: 10),
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 37,
|
height: 37,
|
||||||
width: 37,
|
width: 37,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () => Navigator.of(context).pop(),
|
onTap: () => Navigator.of(context).pop(),
|
||||||
child: _backArrowImageDarkTheme,
|
child: _backArrowImageDarkTheme,
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
: Container(),
|
: Container(),
|
||||||
backgroundColor: Theme.of(context).colorScheme.background,
|
backgroundColor: Theme.of(context).colorScheme.background,
|
||||||
border: null),
|
border: null),
|
||||||
resizeToAvoidBottomInset: false,
|
resizeToAvoidBottomInset: false,
|
||||||
body: PinCode((pin, _) => widget.authViewModel.auth(password: pin),
|
body: PinCode(
|
||||||
(_) => null, widget.authViewModel.pinLength, false, _pinCodeKey));
|
(pin, _) => widget.authViewModel.auth(password: pin),
|
||||||
|
(_) => null,
|
||||||
|
widget.authViewModel.setPinRandomized,
|
||||||
|
widget.authViewModel.pinLength,
|
||||||
|
widget.authViewModel.pinRandomized,
|
||||||
|
false,
|
||||||
|
_pinCodeKey,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dismissFlushBar(Flushbar<dynamic>? bar) {
|
void dismissFlushBar(Flushbar<dynamic>? bar) {
|
||||||
|
|
|
@ -5,15 +5,20 @@ class PinCode extends PinCodeWidget {
|
||||||
PinCode(
|
PinCode(
|
||||||
void Function(String pin, PinCodeState state) onFullPin,
|
void Function(String pin, PinCodeState state) onFullPin,
|
||||||
void Function(String pin) onChangedPin,
|
void Function(String pin) onChangedPin,
|
||||||
|
void Function(bool) setPinRandomized,
|
||||||
int initialPinLength,
|
int initialPinLength,
|
||||||
|
bool initialPinRandomized,
|
||||||
bool hasLengthSwitcher,
|
bool hasLengthSwitcher,
|
||||||
Key key)
|
Key key)
|
||||||
: super(
|
: super(
|
||||||
key: key,
|
key: key,
|
||||||
onFullPin: onFullPin,
|
onFullPin: onFullPin,
|
||||||
onChangedPin: onChangedPin,
|
onChangedPin: onChangedPin,
|
||||||
hasLengthSwitcher: hasLengthSwitcher,
|
hasLengthSwitcher: hasLengthSwitcher,
|
||||||
initialPinLength: initialPinLength);
|
initialPinLength: initialPinLength,
|
||||||
|
initialPinRandomized: initialPinRandomized,
|
||||||
|
setPinRandomized: setPinRandomized,
|
||||||
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
PinCodeState createState() => PinCodeState();
|
PinCodeState createState() => PinCodeState();
|
||||||
|
|
|
@ -14,14 +14,18 @@ class PinCodeWidget extends StatefulWidget {
|
||||||
required this.initialPinLength,
|
required this.initialPinLength,
|
||||||
required this.onChangedPin,
|
required this.onChangedPin,
|
||||||
required this.hasLengthSwitcher,
|
required this.hasLengthSwitcher,
|
||||||
|
required this.setPinRandomized,
|
||||||
|
required this.initialPinRandomized,
|
||||||
this.onChangedPinLength,
|
this.onChangedPinLength,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
final void Function(String pin, PinCodeState state) onFullPin;
|
final void Function(String pin, PinCodeState state) onFullPin;
|
||||||
final void Function(String pin) onChangedPin;
|
final void Function(String pin) onChangedPin;
|
||||||
final void Function(int length)? onChangedPinLength;
|
final void Function(int length)? onChangedPinLength;
|
||||||
|
final void Function(bool) setPinRandomized;
|
||||||
final bool hasLengthSwitcher;
|
final bool hasLengthSwitcher;
|
||||||
final int initialPinLength;
|
final int initialPinLength;
|
||||||
|
final bool initialPinRandomized;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<StatefulWidget> createState() => PinCodeState();
|
State<StatefulWidget> createState() => PinCodeState();
|
||||||
|
@ -44,6 +48,8 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
|
||||||
String title;
|
String title;
|
||||||
double _aspectRatio;
|
double _aspectRatio;
|
||||||
Flushbar<void>? _progressBar;
|
Flushbar<void>? _progressBar;
|
||||||
|
late List<int> numbers = [];
|
||||||
|
bool randomizePin = false;
|
||||||
|
|
||||||
int currentPinLength() => pin.length;
|
int currentPinLength() => pin.length;
|
||||||
|
|
||||||
|
@ -54,6 +60,12 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
|
||||||
pin = '';
|
pin = '';
|
||||||
title = S.current.enter_your_pin;
|
title = S.current.enter_your_pin;
|
||||||
_aspectRatio = 0;
|
_aspectRatio = 0;
|
||||||
|
|
||||||
|
randomizePin = widget.initialPinRandomized;
|
||||||
|
numbers = List.generate(10, (index) => index);
|
||||||
|
if (randomizePin) {
|
||||||
|
numbers.shuffle();
|
||||||
|
}
|
||||||
WidgetsBinding.instance.addPostFrameCallback(_afterLayout);
|
WidgetsBinding.instance.addPostFrameCallback(_afterLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,6 +130,10 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
|
||||||
'assets/images/face.png',
|
'assets/images/face.png',
|
||||||
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
|
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
|
||||||
);
|
);
|
||||||
|
final shuffleImage = Image.asset(
|
||||||
|
'assets/images/shuffle.png',
|
||||||
|
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
|
||||||
|
);
|
||||||
|
|
||||||
return RawKeyboardListener(
|
return RawKeyboardListener(
|
||||||
focusNode: FocusNode(),
|
focusNode: FocusNode(),
|
||||||
|
@ -144,8 +160,7 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color:
|
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor)),
|
||||||
Theme.of(context).extension<CakeTextTheme>()!.titleColor)),
|
|
||||||
Spacer(flex: 3),
|
Spacer(flex: 3),
|
||||||
Container(
|
Container(
|
||||||
width: 180,
|
width: 180,
|
||||||
|
@ -162,7 +177,9 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
color: isFilled
|
color: isFilled
|
||||||
? Theme.of(context).extension<CakeTextTheme>()!.titleColor
|
? Theme.of(context).extension<CakeTextTheme>()!.titleColor
|
||||||
: Theme.of(context).extension<PinCodeTheme>()!.indicatorsColor
|
: Theme.of(context)
|
||||||
|
.extension<PinCodeTheme>()!
|
||||||
|
.indicatorsColor
|
||||||
.withOpacity(0.25),
|
.withOpacity(0.25),
|
||||||
));
|
));
|
||||||
}),
|
}),
|
||||||
|
@ -208,9 +225,26 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
|
||||||
const double marginLeft = 15;
|
const double marginLeft = 15;
|
||||||
|
|
||||||
if (index == 9) {
|
if (index == 9) {
|
||||||
// Empty container
|
// randomize button
|
||||||
return Container(
|
return MergeSemantics(
|
||||||
margin: EdgeInsets.only(left: marginLeft, right: marginRight),
|
child: Container(
|
||||||
|
margin: EdgeInsets.only(left: marginLeft, right: marginRight),
|
||||||
|
child: Semantics(
|
||||||
|
label: S.current.delete,
|
||||||
|
button: true,
|
||||||
|
onTap: () => _toggleRandomize(),
|
||||||
|
child: TextButton(
|
||||||
|
onPressed: () => _toggleRandomize(),
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
backgroundColor: randomizePin
|
||||||
|
? Theme.of(context).colorScheme.onBackground
|
||||||
|
: Theme.of(context).colorScheme.background,
|
||||||
|
shape: CircleBorder(),
|
||||||
|
),
|
||||||
|
child: shuffleImage,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
} else if (index == 10) {
|
} else if (index == 10) {
|
||||||
index = 0;
|
index = 0;
|
||||||
|
@ -225,7 +259,8 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
|
||||||
child: TextButton(
|
child: TextButton(
|
||||||
onPressed: () => _pop(),
|
onPressed: () => _pop(),
|
||||||
style: TextButton.styleFrom(
|
style: TextButton.styleFrom(
|
||||||
backgroundColor: Theme.of(context).colorScheme.background,
|
backgroundColor:
|
||||||
|
Theme.of(context).colorScheme.background,
|
||||||
shape: CircleBorder(),
|
shape: CircleBorder(),
|
||||||
),
|
),
|
||||||
child: deleteIconImage,
|
child: deleteIconImage,
|
||||||
|
@ -240,16 +275,18 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
|
||||||
return Container(
|
return Container(
|
||||||
margin: EdgeInsets.only(left: marginLeft, right: marginRight),
|
margin: EdgeInsets.only(left: marginLeft, right: marginRight),
|
||||||
child: TextButton(
|
child: TextButton(
|
||||||
onPressed: () => _push(index),
|
onPressed: () => _push(numbers[index]),
|
||||||
style: TextButton.styleFrom(
|
style: TextButton.styleFrom(
|
||||||
backgroundColor: Theme.of(context).colorScheme.background,
|
backgroundColor: Theme.of(context).colorScheme.background,
|
||||||
shape: CircleBorder(),
|
shape: CircleBorder(),
|
||||||
),
|
),
|
||||||
child: Text('$index',
|
child: Text('${numbers[index]}',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 30.0,
|
fontSize: 30.0,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor)),
|
color: Theme.of(context)
|
||||||
|
.extension<CakeTextTheme>()!
|
||||||
|
.titleColor)),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
@ -290,6 +327,18 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
|
||||||
setState(() => pin = pin.substring(0, pin.length - 1));
|
setState(() => pin = pin.substring(0, pin.length - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _toggleRandomize() {
|
||||||
|
setState(() {
|
||||||
|
randomizePin = !randomizePin;
|
||||||
|
widget.setPinRandomized(randomizePin);
|
||||||
|
if (!randomizePin) {
|
||||||
|
numbers = List.generate(10, (index) => index);
|
||||||
|
} else {
|
||||||
|
numbers.shuffle();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
String _changePinLengthText() {
|
String _changePinLengthText() {
|
||||||
return S.current.use +
|
return S.current.use +
|
||||||
(pinLength == PinCodeState.fourPinLength
|
(pinLength == PinCodeState.fourPinLength
|
||||||
|
|
|
@ -22,6 +22,8 @@ class SetupPinCodePage extends BasePage {
|
||||||
Widget body(BuildContext context) => PinCodeWidget(
|
Widget body(BuildContext context) => PinCodeWidget(
|
||||||
key: pinCodeStateKey,
|
key: pinCodeStateKey,
|
||||||
hasLengthSwitcher: true,
|
hasLengthSwitcher: true,
|
||||||
|
setPinRandomized: pinCodeViewModel.setPinRandomized,
|
||||||
|
initialPinRandomized: pinCodeViewModel.pinRandomized,
|
||||||
onFullPin: (String pin, PinCodeState<PinCodeWidget> state) async {
|
onFullPin: (String pin, PinCodeState<PinCodeWidget> state) async {
|
||||||
if (pinCodeViewModel.isOriginalPinCodeFull &&
|
if (pinCodeViewModel.isOriginalPinCodeFull &&
|
||||||
!pinCodeViewModel.isRepeatedPinCodeFull) {
|
!pinCodeViewModel.isRepeatedPinCodeFull) {
|
||||||
|
|
|
@ -73,6 +73,7 @@ abstract class SettingsStoreBase with Store {
|
||||||
required ExchangeApiMode initialExchangeStatus,
|
required ExchangeApiMode initialExchangeStatus,
|
||||||
required ThemeBase initialTheme,
|
required ThemeBase initialTheme,
|
||||||
required int initialPinLength,
|
required int initialPinLength,
|
||||||
|
required bool initialRandomizePinCode,
|
||||||
required String initialLanguageCode,
|
required String initialLanguageCode,
|
||||||
required SyncMode initialSyncMode,
|
required SyncMode initialSyncMode,
|
||||||
required bool initialSyncAll,
|
required bool initialSyncAll,
|
||||||
|
@ -150,6 +151,7 @@ abstract class SettingsStoreBase with Store {
|
||||||
exchangeStatus = initialExchangeStatus,
|
exchangeStatus = initialExchangeStatus,
|
||||||
currentTheme = initialTheme,
|
currentTheme = initialTheme,
|
||||||
pinCodeLength = initialPinLength,
|
pinCodeLength = initialPinLength,
|
||||||
|
randomizePinCode = initialRandomizePinCode,
|
||||||
languageCode = initialLanguageCode,
|
languageCode = initialLanguageCode,
|
||||||
shouldRequireTOTP2FAForAccessingWallet = initialShouldRequireTOTP2FAForAccessingWallet,
|
shouldRequireTOTP2FAForAccessingWallet = initialShouldRequireTOTP2FAForAccessingWallet,
|
||||||
shouldRequireTOTP2FAForSendsToContact = initialShouldRequireTOTP2FAForSendsToContact,
|
shouldRequireTOTP2FAForSendsToContact = initialShouldRequireTOTP2FAForSendsToContact,
|
||||||
|
@ -369,6 +371,9 @@ abstract class SettingsStoreBase with Store {
|
||||||
reaction((_) => pinCodeLength,
|
reaction((_) => pinCodeLength,
|
||||||
(int pinLength) => sharedPreferences.setInt(PreferencesKey.currentPinLength, pinLength));
|
(int pinLength) => sharedPreferences.setInt(PreferencesKey.currentPinLength, pinLength));
|
||||||
|
|
||||||
|
reaction((_) => randomizePinCode,
|
||||||
|
(bool randomizePinCode) => sharedPreferences.setBool(PreferencesKey.randomizePinCode, randomizePinCode));
|
||||||
|
|
||||||
reaction(
|
reaction(
|
||||||
(_) => languageCode,
|
(_) => languageCode,
|
||||||
(String languageCode) =>
|
(String languageCode) =>
|
||||||
|
@ -683,6 +688,9 @@ abstract class SettingsStoreBase with Store {
|
||||||
@observable
|
@observable
|
||||||
int pinCodeLength;
|
int pinCodeLength;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
bool randomizePinCode;
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
PinCodeRequiredDuration pinTimeOutDuration;
|
PinCodeRequiredDuration pinTimeOutDuration;
|
||||||
|
|
||||||
|
@ -931,6 +939,8 @@ abstract class SettingsStoreBase with Store {
|
||||||
pinLength = defaultPinLength;
|
pinLength = defaultPinLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final randomizePinCode = sharedPreferences.getBool(PreferencesKey.randomizePinCode) ?? false;
|
||||||
|
|
||||||
final savedLanguageCode = sharedPreferences.getString(PreferencesKey.currentLanguageCode) ??
|
final savedLanguageCode = sharedPreferences.getString(PreferencesKey.currentLanguageCode) ??
|
||||||
await LanguageService.localeDetection();
|
await LanguageService.localeDetection();
|
||||||
final nodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey);
|
final nodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey);
|
||||||
|
@ -1171,6 +1181,7 @@ abstract class SettingsStoreBase with Store {
|
||||||
initialTheme: savedTheme,
|
initialTheme: savedTheme,
|
||||||
actionlistDisplayMode: actionListDisplayMode,
|
actionlistDisplayMode: actionListDisplayMode,
|
||||||
initialPinLength: pinLength,
|
initialPinLength: pinLength,
|
||||||
|
initialRandomizePinCode: randomizePinCode,
|
||||||
pinTimeOutDuration: pinCodeTimeOutDuration,
|
pinTimeOutDuration: pinCodeTimeOutDuration,
|
||||||
seedPhraseLength: seedPhraseWordCount,
|
seedPhraseLength: seedPhraseWordCount,
|
||||||
initialLanguageCode: savedLanguageCode,
|
initialLanguageCode: savedLanguageCode,
|
||||||
|
@ -1327,6 +1338,8 @@ abstract class SettingsStoreBase with Store {
|
||||||
}
|
}
|
||||||
pinCodeLength = pinLength;
|
pinCodeLength = pinLength;
|
||||||
|
|
||||||
|
randomizePinCode = sharedPreferences.getBool(PreferencesKey.randomizePinCode) ?? false;
|
||||||
|
|
||||||
languageCode = sharedPreferences.getString(PreferencesKey.currentLanguageCode) ?? languageCode;
|
languageCode = sharedPreferences.getString(PreferencesKey.currentLanguageCode) ?? languageCode;
|
||||||
shouldShowYatPopup =
|
shouldShowYatPopup =
|
||||||
sharedPreferences.getBool(PreferencesKey.shouldShowYatPopup) ?? shouldShowYatPopup;
|
sharedPreferences.getBool(PreferencesKey.shouldShowYatPopup) ?? shouldShowYatPopup;
|
||||||
|
|
|
@ -30,8 +30,15 @@ abstract class AuthViewModelBase with Store {
|
||||||
|
|
||||||
int get pinLength => _settingsStore.pinCodeLength;
|
int get pinLength => _settingsStore.pinCodeLength;
|
||||||
|
|
||||||
|
bool get pinRandomized => _settingsStore.randomizePinCode;
|
||||||
|
|
||||||
bool get isBiometricalAuthenticationAllowed => _settingsStore.allowBiometricalAuthentication;
|
bool get isBiometricalAuthenticationAllowed => _settingsStore.allowBiometricalAuthentication;
|
||||||
|
|
||||||
|
@action
|
||||||
|
void setPinRandomized(bool randomized) {
|
||||||
|
_settingsStore.randomizePinCode = randomized;
|
||||||
|
}
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
int _failureCounter;
|
int _failureCounter;
|
||||||
|
|
||||||
|
@ -121,4 +128,4 @@ abstract class AuthViewModelBase with Store {
|
||||||
_authService.saveLastAuthTime();
|
_authService.saveLastAuthTime();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,4 +67,10 @@ class SetupPinCodeViewModel {
|
||||||
await _authService.setPassword(repeatedPinCode);
|
await _authService.setPassword(repeatedPinCode);
|
||||||
_settingsStore.pinCodeLength = pinCodeLength;
|
_settingsStore.pinCodeLength = pinCodeLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool get pinRandomized => _settingsStore.randomizePinCode;
|
||||||
|
|
||||||
|
void setPinRandomized(bool randomized) {
|
||||||
|
_settingsStore.randomizePinCode = randomized;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue