mirror of
https://github.com/ente-io/ente.git
synced 2025-08-09 07:48:52 +00:00
[mob][photos] implemeted custom keyboard
This commit is contained in:
parent
89e7cfb357
commit
aeb3e2be24
@ -46,6 +46,7 @@ class TextInputWidget extends StatefulWidget {
|
|||||||
final ValueNotifier? isEmptyNotifier;
|
final ValueNotifier? isEmptyNotifier;
|
||||||
final List<TextInputFormatter>? textInputFormatter;
|
final List<TextInputFormatter>? textInputFormatter;
|
||||||
final TextInputType? textInputType;
|
final TextInputType? textInputType;
|
||||||
|
final bool? fillColor;
|
||||||
const TextInputWidget({
|
const TextInputWidget({
|
||||||
this.onSubmit,
|
this.onSubmit,
|
||||||
this.onChange,
|
this.onChange,
|
||||||
@ -74,6 +75,7 @@ class TextInputWidget extends StatefulWidget {
|
|||||||
this.isEmptyNotifier,
|
this.isEmptyNotifier,
|
||||||
this.textInputFormatter,
|
this.textInputFormatter,
|
||||||
this.textInputType,
|
this.textInputType,
|
||||||
|
this.fillColor = true,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -161,7 +163,7 @@ class _TextInputWidgetState extends State<TextInputWidget> {
|
|||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: widget.hintText,
|
hintText: widget.hintText,
|
||||||
hintStyle: textTheme.body.copyWith(color: colorScheme.textMuted),
|
hintStyle: textTheme.body.copyWith(color: colorScheme.textMuted),
|
||||||
filled: true,
|
filled: widget.fillColor,
|
||||||
fillColor: colorScheme.fillFaint,
|
fillColor: colorScheme.fillFaint,
|
||||||
contentPadding: const EdgeInsets.fromLTRB(
|
contentPadding: const EdgeInsets.fromLTRB(
|
||||||
12,
|
12,
|
||||||
|
@ -141,10 +141,16 @@ class _LockScreenOptionState extends State<LockScreenOption> {
|
|||||||
),
|
),
|
||||||
appLock!
|
appLock!
|
||||||
? Container()
|
? Container()
|
||||||
: Text(
|
: Padding(
|
||||||
'Choose between your device\'s default lock screen and a custom lock screen with a PIN or password.',
|
padding: const EdgeInsets.only(
|
||||||
style: textTheme.smallFaint,
|
left: 14,
|
||||||
textAlign: TextAlign.center,
|
right: 12,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
'Choose between your device\'s default lock screen and a custom lock screen with a PIN or password.',
|
||||||
|
style: textTheme.miniFaint,
|
||||||
|
textAlign: TextAlign.left,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -31,7 +31,6 @@ class _LockScreenOptionConfirmPasswordState
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||||
await Future.delayed(const Duration(milliseconds: 500));
|
|
||||||
_focusNode.requestFocus();
|
_focusNode.requestFocus();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -51,7 +50,7 @@ class _LockScreenOptionConfirmPasswordState
|
|||||||
Navigator.of(context).pop(true);
|
Navigator.of(context).pop(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_confirmPasswordController.clear();
|
await HapticFeedback.vibrate();
|
||||||
throw Exception("Incorrect password");
|
throw Exception("Incorrect password");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,6 +144,7 @@ class _LockScreenOptionConfirmPasswordState
|
|||||||
child: TextInputWidget(
|
child: TextInputWidget(
|
||||||
hintText: S.of(context).confirmPassword,
|
hintText: S.of(context).confirmPassword,
|
||||||
focusNode: _focusNode,
|
focusNode: _focusNode,
|
||||||
|
fillColor: false,
|
||||||
textCapitalization: TextCapitalization.none,
|
textCapitalization: TextCapitalization.none,
|
||||||
textEditingController: _confirmPasswordController,
|
textEditingController: _confirmPasswordController,
|
||||||
isPasswordInput: true,
|
isPasswordInput: true,
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter/services.dart";
|
import "package:flutter/services.dart";
|
||||||
import "package:photos/core/configuration.dart";
|
import "package:photos/core/configuration.dart";
|
||||||
import "package:photos/generated/l10n.dart";
|
|
||||||
import "package:photos/theme/ente_theme.dart";
|
import "package:photos/theme/ente_theme.dart";
|
||||||
import "package:photos/ui/common/dynamic_fab.dart";
|
|
||||||
import "package:photos/ui/components/buttons/icon_button_widget.dart";
|
import "package:photos/ui/components/buttons/icon_button_widget.dart";
|
||||||
import "package:pinput/pinput.dart";
|
import "package:pinput/pinput.dart";
|
||||||
|
|
||||||
@ -19,10 +17,10 @@ class _LockScreenOptionConfirmPinState
|
|||||||
extends State<LockScreenOptionConfirmPin> {
|
extends State<LockScreenOptionConfirmPin> {
|
||||||
final _confirmPinController = TextEditingController(text: null);
|
final _confirmPinController = TextEditingController(text: null);
|
||||||
final Configuration _configuration = Configuration.instance;
|
final Configuration _configuration = Configuration.instance;
|
||||||
final _focusNode = FocusNode();
|
Key _pinputKey = UniqueKey();
|
||||||
final _pinPutDecoration = PinTheme(
|
final _pinPutDecoration = PinTheme(
|
||||||
height: 50,
|
height: 48,
|
||||||
width: 50,
|
width: 48,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
border: Border.all(color: const Color.fromRGBO(45, 194, 98, 1.0)),
|
border: Border.all(color: const Color.fromRGBO(45, 194, 98, 1.0)),
|
||||||
borderRadius: BorderRadius.circular(15.0),
|
borderRadius: BorderRadius.circular(15.0),
|
||||||
@ -31,19 +29,29 @@ class _LockScreenOptionConfirmPinState
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
|
||||||
await Future.delayed(const Duration(milliseconds: 500));
|
|
||||||
_focusNode.requestFocus();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
_focusNode.dispose();
|
|
||||||
_confirmPinController.dispose();
|
_confirmPinController.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String _pin = "";
|
||||||
|
|
||||||
|
void onClick(String number) {
|
||||||
|
_pin += number;
|
||||||
|
_confirmPinController.text = _pin;
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeNum() {
|
||||||
|
if (_pin.isNotEmpty) {
|
||||||
|
_pin = _pin.substring(0, _pin.length - 1);
|
||||||
|
_confirmPinController.text = _pin;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _confirmPinMatch() async {
|
Future<void> _confirmPinMatch() async {
|
||||||
if (widget.pin == _confirmPinController.text) {
|
if (widget.pin == _confirmPinController.text) {
|
||||||
await _configuration.setPin(_confirmPinController.text);
|
await _configuration.setPin(_confirmPinController.text);
|
||||||
@ -54,29 +62,20 @@ class _LockScreenOptionConfirmPinState
|
|||||||
}
|
}
|
||||||
await HapticFeedback.vibrate();
|
await HapticFeedback.vibrate();
|
||||||
_confirmPinController.clear();
|
_confirmPinController.clear();
|
||||||
|
_pin = "";
|
||||||
|
_pinputKey = UniqueKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final colorTheme = getEnteColorScheme(context);
|
final colorTheme = getEnteColorScheme(context);
|
||||||
final textTheme = getEnteTextTheme(context);
|
final textTheme = getEnteTextTheme(context);
|
||||||
final isKeypadOpen = MediaQuery.of(context).viewInsets.bottom > 100;
|
|
||||||
|
|
||||||
FloatingActionButtonLocation? fabLocation() {
|
|
||||||
if (isKeypadOpen) {
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
return FloatingActionButtonLocation.centerFloat;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
resizeToAvoidBottomInset: isKeypadOpen,
|
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
FocusScope.of(context).unfocus();
|
|
||||||
Navigator.of(context).pop(false);
|
Navigator.of(context).pop(false);
|
||||||
},
|
},
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
@ -85,17 +84,6 @@ class _LockScreenOptionConfirmPinState
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
floatingActionButton: DynamicFAB(
|
|
||||||
isKeypadOpen: isKeypadOpen,
|
|
||||||
buttonText: S.of(context).confirm,
|
|
||||||
isFormValid: _confirmPinController.text.isNotEmpty,
|
|
||||||
onPressedFunction: () async {
|
|
||||||
await _confirmPinMatch();
|
|
||||||
FocusScope.of(context).unfocus();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
floatingActionButtonLocation: fabLocation(),
|
|
||||||
floatingActionButtonAnimator: NoScalingAnimation(),
|
|
||||||
body: Center(
|
body: Center(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
@ -154,11 +142,12 @@ class _LockScreenOptionConfirmPinState
|
|||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(70, 0, 70, 0),
|
padding: const EdgeInsets.fromLTRB(70, 0, 70, 0),
|
||||||
child: Pinput(
|
child: Pinput(
|
||||||
|
key: _pinputKey,
|
||||||
length: 4,
|
length: 4,
|
||||||
|
useNativeKeyboard: false,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
controller: _confirmPinController,
|
controller: _confirmPinController,
|
||||||
focusNode: _focusNode,
|
|
||||||
defaultPinTheme: _pinPutDecoration,
|
defaultPinTheme: _pinPutDecoration,
|
||||||
submittedPinTheme: _pinPutDecoration.copyWith(
|
submittedPinTheme: _pinPutDecoration.copyWith(
|
||||||
textStyle: textTheme.h3Bold,
|
textStyle: textTheme.h3Bold,
|
||||||
@ -195,18 +184,203 @@ class _LockScreenOptionConfirmPinState
|
|||||||
if (value == widget.pin) {
|
if (value == widget.pin) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
|
value = null;
|
||||||
return 'PIN does not match';
|
return 'PIN does not match';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onSubmitted: (value) {
|
onCompleted: (value) async {
|
||||||
_confirmPinMatch();
|
await Future.delayed(const Duration(milliseconds: 250));
|
||||||
FocusScope.of(context).unfocus();
|
await _confirmPinMatch();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
const Spacer(),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(2),
|
||||||
|
color: colorTheme.strokeFainter,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
buttonWidget(
|
||||||
|
colorTheme: colorTheme,
|
||||||
|
textTheme: textTheme,
|
||||||
|
text: '',
|
||||||
|
number: '1',
|
||||||
|
onTap: () {
|
||||||
|
onClick('1');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
buttonWidget(
|
||||||
|
colorTheme: colorTheme,
|
||||||
|
textTheme: textTheme,
|
||||||
|
text: "ABC",
|
||||||
|
number: '2',
|
||||||
|
onTap: () {
|
||||||
|
onClick('2');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
buttonWidget(
|
||||||
|
colorTheme: colorTheme,
|
||||||
|
textTheme: textTheme,
|
||||||
|
text: "DEF",
|
||||||
|
number: '3',
|
||||||
|
onTap: () {
|
||||||
|
onClick('3');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
buttonWidget(
|
||||||
|
colorTheme: colorTheme,
|
||||||
|
textTheme: textTheme,
|
||||||
|
number: '4',
|
||||||
|
text: "GHI",
|
||||||
|
onTap: () {
|
||||||
|
onClick('4');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
buttonWidget(
|
||||||
|
colorTheme: colorTheme,
|
||||||
|
textTheme: textTheme,
|
||||||
|
number: '5',
|
||||||
|
text: 'JKL',
|
||||||
|
onTap: () {
|
||||||
|
onClick('5');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
buttonWidget(
|
||||||
|
colorTheme: colorTheme,
|
||||||
|
textTheme: textTheme,
|
||||||
|
number: '6',
|
||||||
|
text: 'MNO',
|
||||||
|
onTap: () {
|
||||||
|
onClick('6');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
buttonWidget(
|
||||||
|
colorTheme: colorTheme,
|
||||||
|
textTheme: textTheme,
|
||||||
|
number: '7',
|
||||||
|
text: 'PQRS',
|
||||||
|
onTap: () {
|
||||||
|
onClick('7');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
buttonWidget(
|
||||||
|
colorTheme: colorTheme,
|
||||||
|
textTheme: textTheme,
|
||||||
|
number: '8',
|
||||||
|
text: 'TUV',
|
||||||
|
onTap: () {
|
||||||
|
onClick('8');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
buttonWidget(
|
||||||
|
colorTheme: colorTheme,
|
||||||
|
textTheme: textTheme,
|
||||||
|
number: '9',
|
||||||
|
text: 'WXYZ',
|
||||||
|
onTap: () {
|
||||||
|
onClick('9');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
buttonWidget(
|
||||||
|
colorTheme: colorTheme,
|
||||||
|
textTheme: textTheme,
|
||||||
|
number: '',
|
||||||
|
text: '',
|
||||||
|
muteButton: true,
|
||||||
|
),
|
||||||
|
buttonWidget(
|
||||||
|
colorTheme: colorTheme,
|
||||||
|
textTheme: textTheme,
|
||||||
|
number: '0',
|
||||||
|
text: '',
|
||||||
|
onTap: () {
|
||||||
|
onClick('0');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
buttonWidget(
|
||||||
|
colorTheme: colorTheme,
|
||||||
|
textTheme: textTheme,
|
||||||
|
number: '',
|
||||||
|
text: '',
|
||||||
|
icons: const Icon(Icons.backspace_outlined),
|
||||||
|
onTap: () {
|
||||||
|
removeNum();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget buttonWidget({
|
||||||
|
colorTheme,
|
||||||
|
textTheme,
|
||||||
|
text,
|
||||||
|
number,
|
||||||
|
muteButton = false,
|
||||||
|
icons,
|
||||||
|
onTap,
|
||||||
|
}) {
|
||||||
|
return Expanded(
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: onTap,
|
||||||
|
child: Container(
|
||||||
|
margin: const EdgeInsets.all(4),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
shape: BoxShape.rectangle,
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
color: muteButton
|
||||||
|
? colorTheme.fillFaintPressed
|
||||||
|
: icons == null
|
||||||
|
? colorTheme.backgroundElevated2
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: muteButton
|
||||||
|
? Container()
|
||||||
|
: icons != null
|
||||||
|
? Container(
|
||||||
|
child: icons,
|
||||||
|
)
|
||||||
|
: Container(
|
||||||
|
padding: const EdgeInsets.all(4),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
number,
|
||||||
|
style: textTheme.h3,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
text,
|
||||||
|
style: textTheme.small,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,6 @@ class _LockScreenOptionPasswordState extends State<LockScreenOptionPassword> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||||
await Future.delayed(const Duration(milliseconds: 500));
|
|
||||||
_focusNode.requestFocus();
|
_focusNode.requestFocus();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -159,6 +158,7 @@ class _LockScreenOptionPasswordState extends State<LockScreenOptionPassword> {
|
|||||||
child: TextInputWidget(
|
child: TextInputWidget(
|
||||||
hintText: S.of(context).password,
|
hintText: S.of(context).password,
|
||||||
focusNode: _focusNode,
|
focusNode: _focusNode,
|
||||||
|
fillColor: false,
|
||||||
textCapitalization: TextCapitalization.none,
|
textCapitalization: TextCapitalization.none,
|
||||||
textEditingController: _passwordController,
|
textEditingController: _passwordController,
|
||||||
isPasswordInput: true,
|
isPasswordInput: true,
|
||||||
|
@ -20,22 +20,31 @@ class LockScreenOptionPin extends StatefulWidget {
|
|||||||
|
|
||||||
class _LockScreenOptionPinState extends State<LockScreenOptionPin> {
|
class _LockScreenOptionPinState extends State<LockScreenOptionPin> {
|
||||||
final _pinController = TextEditingController(text: null);
|
final _pinController = TextEditingController(text: null);
|
||||||
final _focusNode = FocusNode();
|
Key _pinputKey = UniqueKey();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
|
||||||
await Future.delayed(const Duration(milliseconds: 500));
|
|
||||||
_focusNode.requestFocus();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
_pinController.dispose();
|
_pinController.dispose();
|
||||||
_focusNode.dispose();
|
}
|
||||||
|
|
||||||
|
String _pin = "";
|
||||||
|
|
||||||
|
void onClick(String number) {
|
||||||
|
_pin += number;
|
||||||
|
_pinController.text = _pin;
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeNum() {
|
||||||
|
if (_pin.isNotEmpty) {
|
||||||
|
_pin = _pin.substring(0, _pin.length - 1);
|
||||||
|
_pinController.text = _pin;
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> confirmPinAuth(String code) async {
|
Future<bool> confirmPinAuth(String code) async {
|
||||||
@ -43,6 +52,9 @@ class _LockScreenOptionPinState extends State<LockScreenOptionPin> {
|
|||||||
Navigator.of(context).pop(true);
|
Navigator.of(context).pop(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
_pinController.clear();
|
||||||
|
_pin = "";
|
||||||
|
_pinputKey = UniqueKey();
|
||||||
await HapticFeedback.vibrate();
|
await HapticFeedback.vibrate();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -59,6 +71,7 @@ class _LockScreenOptionPinState extends State<LockScreenOptionPin> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
_pinController.clear();
|
_pinController.clear();
|
||||||
|
_pin = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,6 +83,7 @@ class _LockScreenOptionPinState extends State<LockScreenOptionPin> {
|
|||||||
borderRadius: BorderRadius.circular(15.0),
|
borderRadius: BorderRadius.circular(15.0),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final colorTheme = getEnteColorScheme(context);
|
final colorTheme = getEnteColorScheme(context);
|
||||||
@ -79,7 +93,6 @@ class _LockScreenOptionPinState extends State<LockScreenOptionPin> {
|
|||||||
elevation: 0,
|
elevation: 0,
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
FocusScope.of(context).unfocus();
|
|
||||||
Navigator.of(context).pop(false);
|
Navigator.of(context).pop(false);
|
||||||
},
|
},
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
@ -149,10 +162,11 @@ class _LockScreenOptionPinState extends State<LockScreenOptionPin> {
|
|||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(70, 0, 70, 0),
|
padding: const EdgeInsets.fromLTRB(70, 0, 70, 0),
|
||||||
child: Pinput(
|
child: Pinput(
|
||||||
|
key: _pinputKey,
|
||||||
length: 4,
|
length: 4,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
focusNode: _focusNode,
|
useNativeKeyboard: false,
|
||||||
controller: _pinController,
|
controller: _pinController,
|
||||||
defaultPinTheme: _pinPutDecoration,
|
defaultPinTheme: _pinPutDecoration,
|
||||||
submittedPinTheme: _pinPutDecoration.copyWith(
|
submittedPinTheme: _pinPutDecoration.copyWith(
|
||||||
@ -191,12 +205,10 @@ class _LockScreenOptionPinState extends State<LockScreenOptionPin> {
|
|||||||
return 'Invalid PIN';
|
return 'Invalid PIN';
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
autofocus: true,
|
|
||||||
errorText: '',
|
errorText: '',
|
||||||
obscureText: true,
|
obscureText: true,
|
||||||
obscuringCharacter: '*',
|
obscuringCharacter: '*',
|
||||||
onCompleted: (value) async {
|
onCompleted: (value) async {
|
||||||
FocusScope.of(context).unfocus();
|
|
||||||
await Future.delayed(const Duration(milliseconds: 250));
|
await Future.delayed(const Duration(milliseconds: 250));
|
||||||
await _confirmPin(_pinController.text);
|
await _confirmPin(_pinController.text);
|
||||||
},
|
},
|
||||||
@ -204,9 +216,193 @@ class _LockScreenOptionPinState extends State<LockScreenOptionPin> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
const Spacer(),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(2),
|
||||||
|
color: colorTheme.strokeFainter,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
buttonWidget(
|
||||||
|
colorTheme: colorTheme,
|
||||||
|
textTheme: textTheme,
|
||||||
|
text: '',
|
||||||
|
number: '1',
|
||||||
|
onTap: () {
|
||||||
|
onClick('1');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
buttonWidget(
|
||||||
|
colorTheme: colorTheme,
|
||||||
|
textTheme: textTheme,
|
||||||
|
text: "ABC",
|
||||||
|
number: '2',
|
||||||
|
onTap: () {
|
||||||
|
onClick('2');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
buttonWidget(
|
||||||
|
colorTheme: colorTheme,
|
||||||
|
textTheme: textTheme,
|
||||||
|
text: "DEF",
|
||||||
|
number: '3',
|
||||||
|
onTap: () {
|
||||||
|
onClick('3');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
buttonWidget(
|
||||||
|
colorTheme: colorTheme,
|
||||||
|
textTheme: textTheme,
|
||||||
|
number: '4',
|
||||||
|
text: "GHI",
|
||||||
|
onTap: () {
|
||||||
|
onClick('4');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
buttonWidget(
|
||||||
|
colorTheme: colorTheme,
|
||||||
|
textTheme: textTheme,
|
||||||
|
number: '5',
|
||||||
|
text: 'JKL',
|
||||||
|
onTap: () {
|
||||||
|
onClick('5');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
buttonWidget(
|
||||||
|
colorTheme: colorTheme,
|
||||||
|
textTheme: textTheme,
|
||||||
|
number: '6',
|
||||||
|
text: 'MNO',
|
||||||
|
onTap: () {
|
||||||
|
onClick('6');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
buttonWidget(
|
||||||
|
colorTheme: colorTheme,
|
||||||
|
textTheme: textTheme,
|
||||||
|
number: '7',
|
||||||
|
text: 'PQRS',
|
||||||
|
onTap: () {
|
||||||
|
onClick('7');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
buttonWidget(
|
||||||
|
colorTheme: colorTheme,
|
||||||
|
textTheme: textTheme,
|
||||||
|
number: '8',
|
||||||
|
text: 'TUV',
|
||||||
|
onTap: () {
|
||||||
|
onClick('8');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
buttonWidget(
|
||||||
|
colorTheme: colorTheme,
|
||||||
|
textTheme: textTheme,
|
||||||
|
number: '9',
|
||||||
|
text: 'WXYZ',
|
||||||
|
onTap: () {
|
||||||
|
onClick('9');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
buttonWidget(
|
||||||
|
colorTheme: colorTheme,
|
||||||
|
textTheme: textTheme,
|
||||||
|
number: '',
|
||||||
|
text: '',
|
||||||
|
muteButton: true,
|
||||||
|
),
|
||||||
|
buttonWidget(
|
||||||
|
colorTheme: colorTheme,
|
||||||
|
textTheme: textTheme,
|
||||||
|
number: '0',
|
||||||
|
text: '',
|
||||||
|
onTap: () {
|
||||||
|
onClick('0');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
buttonWidget(
|
||||||
|
colorTheme: colorTheme,
|
||||||
|
textTheme: textTheme,
|
||||||
|
number: '',
|
||||||
|
text: '',
|
||||||
|
icons: const Icon(Icons.backspace_outlined),
|
||||||
|
onTap: () {
|
||||||
|
removeNum();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget buttonWidget({
|
||||||
|
colorTheme,
|
||||||
|
textTheme,
|
||||||
|
text,
|
||||||
|
number,
|
||||||
|
muteButton = false,
|
||||||
|
icons,
|
||||||
|
onTap,
|
||||||
|
}) {
|
||||||
|
return Expanded(
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: onTap,
|
||||||
|
child: Container(
|
||||||
|
margin: const EdgeInsets.all(4),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
shape: BoxShape.rectangle,
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
color: muteButton
|
||||||
|
? colorTheme.fillFaintPressed
|
||||||
|
: icons == null
|
||||||
|
? colorTheme.backgroundElevated2
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: muteButton
|
||||||
|
? Container()
|
||||||
|
: icons != null
|
||||||
|
? Container(
|
||||||
|
child: icons,
|
||||||
|
)
|
||||||
|
: Container(
|
||||||
|
padding: const EdgeInsets.all(4),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
number,
|
||||||
|
style: textTheme.h3,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
text,
|
||||||
|
style: textTheme.small,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,6 +143,8 @@ class _SecuritySectionWidgetState extends State<SecuritySectionWidget> {
|
|||||||
captionedTextWidget: const CaptionedTextWidget(
|
captionedTextWidget: const CaptionedTextWidget(
|
||||||
title: 'App lock',
|
title: 'App lock',
|
||||||
),
|
),
|
||||||
|
trailingIcon: Icons.chevron_right_outlined,
|
||||||
|
trailingIconIsMuted: true,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
final bool result = await requestAuthentication(
|
final bool result = await requestAuthentication(
|
||||||
context,
|
context,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user