fix: pincode functionality
This commit is contained in:
@@ -62,14 +62,16 @@ class _BarScreenViewState extends State<BarScreenView> {
|
||||
onPressed: () => context.go('/settings'),
|
||||
icon: const Icon(Icons.settings),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
IconButton(
|
||||
tooltip: 'logout',
|
||||
onPressed: () {
|
||||
Provider.of<PinLockViewModel>(context, listen: false).lock();
|
||||
},
|
||||
icon: const Icon(Icons.logout),
|
||||
),
|
||||
if (context.watch<PinLockViewModel>().isPinSet) ...[
|
||||
const SizedBox(width: 6),
|
||||
IconButton(
|
||||
tooltip: 'Logout',
|
||||
onPressed: () {
|
||||
Provider.of<PinLockViewModel>(context, listen: false).lock();
|
||||
},
|
||||
icon: const Icon(Icons.logout),
|
||||
),
|
||||
],
|
||||
],
|
||||
actionsPadding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
),
|
||||
|
||||
@@ -242,30 +242,32 @@ class _PinKeypad extends StatelessWidget {
|
||||
children: [
|
||||
for (final row in _rows)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 6),
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Row(
|
||||
spacing: 16,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
for (final digit in row)
|
||||
for (final digit in row) ...[
|
||||
_KeypadButton(
|
||||
label: digit,
|
||||
onTap: enabled ? () => onDigit(digit) : null,
|
||||
),
|
||||
const SizedBox(width: 20),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 6),
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Row(
|
||||
spacing: 16,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const _KeypadButton(isSpacer: true, onTap: null),
|
||||
const SizedBox(width: 20),
|
||||
_KeypadButton(
|
||||
label: '0',
|
||||
onTap: enabled ? () => onDigit('0') : null,
|
||||
),
|
||||
const SizedBox(width: 20),
|
||||
_KeypadButton(
|
||||
icon: Icons.backspace_outlined,
|
||||
onTap: enabled ? onBackspace : null,
|
||||
@@ -294,14 +296,14 @@ class _KeypadButton extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (isSpacer) {
|
||||
return const SizedBox(width: 72, height: 72);
|
||||
return const SizedBox(width: 80, height: 80);
|
||||
}
|
||||
|
||||
final scheme = Theme.of(context).colorScheme;
|
||||
|
||||
return SizedBox(
|
||||
width: 72,
|
||||
height: 72,
|
||||
width: 80,
|
||||
height: 80,
|
||||
child: Material(
|
||||
color: scheme.onSurface.withValues(alpha: 0.04),
|
||||
shape: const CircleBorder(),
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
@@ -55,32 +57,37 @@ class _SettingsScreenViewState extends State<SettingsScreenView> {
|
||||
});
|
||||
}
|
||||
|
||||
Future<String?> _promptPin(String title, {String hint = 'Enter PIN'}) {
|
||||
Future<String?> _promptPin(String title, {String hint = 'Enter PIN (4 digits)'}) {
|
||||
final controller = TextEditingController();
|
||||
|
||||
return showDialog<String>(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(title),
|
||||
content: TextField(
|
||||
controller: controller,
|
||||
autofocus: true,
|
||||
obscureText: true,
|
||||
keyboardType: TextInputType.number,
|
||||
maxLength: 6,
|
||||
decoration: InputDecoration(hintText: hint),
|
||||
contentPadding: const EdgeInsets.fromLTRB(24, 20, 24, 0),
|
||||
content: SizedBox(
|
||||
width: 320,
|
||||
child: TextField(
|
||||
controller: controller,
|
||||
autofocus: true,
|
||||
obscureText: true,
|
||||
keyboardType: TextInputType.number,
|
||||
maxLength: 4,
|
||||
decoration: InputDecoration(hintText: hint),
|
||||
),
|
||||
),
|
||||
actionsPadding: const EdgeInsets.fromLTRB(16, 8, 16, 12),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: const Text('Cancel'),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
FilledButton(
|
||||
onPressed: () => Navigator.pop(context, controller.text),
|
||||
child: const Text('Confirm'),
|
||||
),
|
||||
],
|
||||
actionsPadding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -93,11 +100,11 @@ class _SettingsScreenViewState extends State<SettingsScreenView> {
|
||||
}
|
||||
|
||||
Future<void> _enablePin() async {
|
||||
final pin = await _promptPin('Set PIN Code', hint: '4–6 digits');
|
||||
final pin = await _promptPin('Set PIN Code', hint: '4 digits');
|
||||
if (pin == null) return;
|
||||
|
||||
if (pin.length < 4) {
|
||||
_showError('PIN must be at least 4 digits');
|
||||
if (pin.length != 4) {
|
||||
_showError('PIN must be exactly 4 digits');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -109,6 +116,7 @@ class _SettingsScreenViewState extends State<SettingsScreenView> {
|
||||
return;
|
||||
}
|
||||
|
||||
pinLockViewModel.setPinRequired(true);
|
||||
await context.read<SettingsViewModel>().updatePinRequired(true);
|
||||
}
|
||||
|
||||
@@ -116,11 +124,11 @@ class _SettingsScreenViewState extends State<SettingsScreenView> {
|
||||
final current = await _promptPin('Enter Current PIN');
|
||||
if (current == null) return;
|
||||
|
||||
final newPin = await _promptPin('Enter New PIN', hint: '4–6 digits');
|
||||
final newPin = await _promptPin('Enter New PIN', hint: '4 digits');
|
||||
if (newPin == null) return;
|
||||
|
||||
if (newPin.length < 4) {
|
||||
_showError('PIN must be at least 4 digits');
|
||||
if (newPin.length != 4) {
|
||||
_showError('PIN must be exactly 4 digits');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -147,6 +155,7 @@ class _SettingsScreenViewState extends State<SettingsScreenView> {
|
||||
return;
|
||||
}
|
||||
|
||||
pinLockViewModel.setPinRequired(false);
|
||||
await context.read<SettingsViewModel>().updatePinRequired(false);
|
||||
}
|
||||
|
||||
@@ -252,20 +261,21 @@ class _SettingsScreenViewState extends State<SettingsScreenView> {
|
||||
),
|
||||
],
|
||||
),
|
||||
_SettingsSection(
|
||||
title: 'Updates',
|
||||
children: [
|
||||
_SettingsTile(
|
||||
icon: Icons.system_update_alt_rounded,
|
||||
title: settingsViewModel.checkingForUpdates
|
||||
? 'Checking for updates...'
|
||||
: 'Check for updates',
|
||||
onTap: settingsViewModel.checkingForUpdates
|
||||
? null
|
||||
: _checkForUpdates,
|
||||
),
|
||||
],
|
||||
),
|
||||
if (Platform.isAndroid)
|
||||
_SettingsSection(
|
||||
title: 'Updates',
|
||||
children: [
|
||||
_SettingsTile(
|
||||
icon: Icons.system_update_alt_rounded,
|
||||
title: settingsViewModel.checkingForUpdates
|
||||
? 'Checking for updates...'
|
||||
: 'Check for updates',
|
||||
onTap: settingsViewModel.checkingForUpdates
|
||||
? null
|
||||
: _checkForUpdates,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 40),
|
||||
GestureDetector(
|
||||
onTap: _onVersionTap,
|
||||
@@ -289,6 +299,7 @@ class _SettingsScreenViewState extends State<SettingsScreenView> {
|
||||
}
|
||||
|
||||
Future<void> _checkForUpdates() async {
|
||||
if (!Platform.isAndroid) return;
|
||||
final vm = context.read<SettingsViewModel>();
|
||||
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user