Add fingerprint (local_auth) session + 3-min inactivity timeout (default), activity resets timer, settings: biometric toggle + timeout picker

This commit is contained in:
cania
2026-08-12 20:13:57 +02:00
parent 9c3fe4f8e9
commit 68fca2c2c6
12 changed files with 305 additions and 52 deletions

View File

@@ -29,17 +29,25 @@ class _DashboardScreenState extends State<DashboardScreen> {
@override
void initState() {
super.initState();
_searchCtrl.addListener(_onSearchChanged);
_searchCtrl.addListener(() {
_touch(); // user activity
_onSearchChanged();
});
_refresh();
}
@override
void dispose() {
_searchCtrl.removeListener(_onSearchChanged);
_searchCtrl.dispose();
super.dispose();
}
/// Refresh the session timestamp — called on every user interaction so the
/// 3-minute inactivity timeout only fires when the user is truly idle.
void _touch() {
widget.auth.openSession();
}
void _onSearchChanged() => _refresh();
Future<void> _refresh() async {
@@ -66,6 +74,7 @@ class _DashboardScreenState extends State<DashboardScreen> {
}
Future<void> _editEntry(VaultEntry e) async {
_touch();
final result = await showEntryDialog(
context,
title: 'Edit konten',
@@ -80,6 +89,7 @@ class _DashboardScreenState extends State<DashboardScreen> {
}
Future<void> _addEntry() async {
_touch();
final result = await showEntryDialog(
context,
title: 'Tambah entri baru',
@@ -110,13 +120,16 @@ class _DashboardScreenState extends State<DashboardScreen> {
IconButton(
icon: const Icon(Icons.settings),
tooltip: 'Pengaturan',
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (_) => SettingsScreen(
auth: widget.auth, theme: widget.theme),
),
).then((_) => _refresh()),
onPressed: () {
_touch();
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => SettingsScreen(
auth: widget.auth, theme: widget.theme),
),
).then((_) => _refresh());
},
),
],
),
@@ -139,6 +152,7 @@ class _DashboardScreenState extends State<DashboardScreen> {
? IconButton(
icon: const Icon(Icons.clear),
onPressed: () {
_touch();
_searchCtrl.clear();
_refresh();
},
@@ -167,20 +181,20 @@ class _DashboardScreenState extends State<DashboardScreen> {
child: const Icon(Icons.delete, color: Colors.white),
),
confirmDismiss: (_) async {
// Use our own dialog for nicer copy.
_touch();
final c = await showConfirmDialog(
context,
title: 'Hapus entri?',
body:
'Yakin hapus "${e.id}"?',
body: 'Yakin hapus "${e.id}"?',
);
if (c == true) await _deleteEntry(e);
return false; // we handle deletion ourselves
return false;
},
child: Card(
margin: const EdgeInsets.symmetric(
horizontal: 12, vertical: 6),
child: ExpansionTile(
onExpansionChanged: (_) => _touch(),
title: Text(e.id,
style: const TextStyle(
fontWeight: FontWeight.bold)),