Refactor SettingsScreen and SearchAppBar: remove unused menu logic and enhance navigation features

This commit is contained in:
2026-05-14 16:39:48 +02:00
parent 94fdfe51eb
commit ca8399dbc9
2 changed files with 35 additions and 122 deletions
+26 -118
View File
@@ -1,6 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:notas/widgets/app_title_bar.dart'; import 'package:notas/widgets/app_title_bar.dart';
import 'package:notas/widgets/menu_drawer.dart';
import 'package:notas/widgets/search_app_bar.dart'; import 'package:notas/widgets/search_app_bar.dart';
class SettingsScreen extends StatefulWidget { class SettingsScreen extends StatefulWidget {
@@ -17,38 +16,6 @@ class SettingsScreen extends StatefulWidget {
class _SettingsScreenState extends State<SettingsScreen> { class _SettingsScreenState extends State<SettingsScreen> {
bool _isBusy = false; bool _isBusy = false;
bool _isMenuOpen = false;
final GlobalKey _headerKey = GlobalKey();
double _menuTopInset = 0;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
_updateMenuTopInset();
});
}
void _updateMenuTopInset() {
final BuildContext? headerContext = _headerKey.currentContext;
if (headerContext == null) {
return;
}
final RenderObject? renderObject = headerContext.findRenderObject();
if (renderObject is! RenderBox) {
return;
}
final double newInset = renderObject.size.height;
if ((newInset - _menuTopInset).abs() < 0.5) {
return;
}
setState(() {
_menuTopInset = newInset;
});
}
Future<void> _confirmAndDeleteAll() async { Future<void> _confirmAndDeleteAll() async {
final bool? confirmed = await showDialog<bool>( final bool? confirmed = await showDialog<bool>(
@@ -92,22 +59,8 @@ class _SettingsScreenState extends State<SettingsScreen> {
} }
} }
void _handleMenuItemTapped(String item) {
setState(() {
_isMenuOpen = false;
});
if (item == 'all_notes') {
Navigator.of(context).pop();
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
WidgetsBinding.instance.addPostFrameCallback((_) {
_updateMenuTopInset();
});
return Scaffold( return Scaffold(
body: Container( body: Container(
decoration: const BoxDecoration( decoration: const BoxDecoration(
@@ -122,80 +75,35 @@ class _SettingsScreenState extends State<SettingsScreen> {
), ),
), ),
child: SafeArea( child: SafeArea(
child: Stack( child: Column(
children: [ children: [
Column( const AppTitleBar(),
children: [ SearchAppBar(
Column( onLeadingPressed: () => Navigator.of(context).pop(),
key: _headerKey, leadingIcon: Icons.arrow_back,
mainAxisSize: MainAxisSize.min, leadingTooltip: 'Atrás',
children: [ showSearch: false,
const AppTitleBar(), titleText: 'Configuración',
SearchAppBar( ),
onMenuPressed: () { Expanded(
setState(() { child: Padding(
_isMenuOpen = !_isMenuOpen; padding: const EdgeInsets.all(16.0),
}); child: Column(
}, crossAxisAlignment: CrossAxisAlignment.start,
showSearch: false, children: [
titleText: 'Configuración', ElevatedButton.icon(
), style: ElevatedButton.styleFrom(backgroundColor: Colors.redAccent),
], onPressed: _isBusy ? null : _confirmAndDeleteAll,
), icon: _isBusy ? const SizedBox(width: 16, height: 16, child: CircularProgressIndicator(strokeWidth: 2)) : const Icon(Icons.delete_forever),
Expanded( label: const Text('Borrar todos los datos'),
child: Padding( ),
padding: const EdgeInsets.all(16.0), const SizedBox(height: 16),
child: Column( const Text('Esto cerrará el vault actual y eliminará la base de datos local junto con la clave de cifrado.'),
crossAxisAlignment: CrossAxisAlignment.start, ],
children: [
ElevatedButton.icon(
style: ElevatedButton.styleFrom(backgroundColor: Colors.redAccent),
onPressed: _isBusy ? null : _confirmAndDeleteAll,
icon: _isBusy ? const SizedBox(width: 16, height: 16, child: CircularProgressIndicator(strokeWidth: 2)) : const Icon(Icons.delete_forever),
label: const Text('Borrar todos los datos'),
),
const SizedBox(height: 16),
const Text('Esto cerrará el vault actual y eliminará la base de datos local junto con la clave de cifrado.'),
],
),
),
),
],
),
Positioned.fill(
top: _menuTopInset,
child: IgnorePointer(
ignoring: !_isMenuOpen,
child: AnimatedOpacity(
duration: const Duration(milliseconds: 300),
opacity: _isMenuOpen ? 0.5 : 0.0,
curve: Curves.easeOutCubic,
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
setState(() {
_isMenuOpen = false;
});
},
child: Container(color: Colors.black),
), ),
), ),
), ),
), ],
AnimatedPositioned(
duration: const Duration(milliseconds: 300),
curve: Curves.easeOutCubic,
left: _isMenuOpen ? 0 : -280,
top: _menuTopInset,
bottom: 0,
width: 280,
child: Material(
color: const Color.fromRGBO(24, 25, 26, 1),
elevation: 8,
child: MenuDrawer(onMenuItemTapped: _handleMenuItemTapped),
),
),
],
), ),
), ),
), ),
+9 -4
View File
@@ -4,6 +4,9 @@ class SearchAppBar extends StatefulWidget {
const SearchAppBar({ const SearchAppBar({
super.key, super.key,
this.onMenuPressed, this.onMenuPressed,
this.onLeadingPressed,
this.leadingIcon = Icons.menu,
this.leadingTooltip = 'Menú',
this.onSearchChanged, this.onSearchChanged,
this.searchHint = 'Buscar notas...', this.searchHint = 'Buscar notas...',
this.showSearch = true, this.showSearch = true,
@@ -11,6 +14,9 @@ class SearchAppBar extends StatefulWidget {
}); });
final VoidCallback? onMenuPressed; final VoidCallback? onMenuPressed;
final VoidCallback? onLeadingPressed;
final IconData leadingIcon;
final String leadingTooltip;
final ValueChanged<String>? onSearchChanged; final ValueChanged<String>? onSearchChanged;
final String searchHint; final String searchHint;
final bool showSearch; final bool showSearch;
@@ -50,11 +56,10 @@ class _SearchAppBarState extends State<SearchAppBar> {
padding: const EdgeInsets.only(left: 16, right: 16, top: 7, bottom: 7), padding: const EdgeInsets.only(left: 16, right: 16, top: 7, bottom: 7),
child: Row( child: Row(
children: [ children: [
// Menu button (fixed on left)
IconButton( IconButton(
onPressed: widget.onMenuPressed, onPressed: widget.onLeadingPressed ?? widget.onMenuPressed,
icon: const Icon(Icons.menu, color: Colors.white70, size: 20), icon: Icon(widget.leadingIcon, color: Colors.white70, size: 20),
tooltip: 'Menú', tooltip: widget.leadingTooltip,
splashRadius: 18, splashRadius: 18,
constraints: const BoxConstraints(minWidth: 40, minHeight: 40), constraints: const BoxConstraints(minWidth: 40, minHeight: 40),
), ),