feat: Implement menu open/close functionality in HomeScreen for improved user interaction

This commit is contained in:
2026-05-19 20:24:03 +02:00
parent 4912316845
commit 6035e3bc18
+91 -45
View File
@@ -50,6 +50,26 @@ class _HomeScreenState extends State<HomeScreen> {
bool _showDeletedNotes = false;
PointerDeviceKind _lastPointerKind = PointerDeviceKind.mouse;
void _openMenu() {
if (_isMenuOpen) {
return;
}
setState(() {
_isMenuOpen = true;
});
}
void _closeMenu() {
if (!_isMenuOpen) {
return;
}
setState(() {
_isMenuOpen = false;
});
}
bool _requiresLongPressToDrag(PointerDeviceKind kind) {
return kind == PointerDeviceKind.touch ||
kind == PointerDeviceKind.stylus ||
@@ -172,9 +192,7 @@ class _HomeScreenState extends State<HomeScreen> {
}
Future<void> _handleMenuItemTapped(String item) async {
setState(() {
_isMenuOpen = false;
});
_closeMenu();
if (item == 'settings') {
widget.onOpenSettings();
@@ -209,8 +227,8 @@ class _HomeScreenState extends State<HomeScreen> {
final Widget body = _isLoading
? const Center(child: CircularProgressIndicator())
: _notes.isEmpty
? _EmptyState(showDeletedNotes: _showDeletedNotes)
: RefreshIndicator(
? _EmptyState(showDeletedNotes: _showDeletedNotes)
: RefreshIndicator(
onRefresh: () async {
await widget.onRequestSync();
},
@@ -546,53 +564,81 @@ class _HomeScreenState extends State<HomeScreen> {
},
),
Expanded(
child: Stack(
children: [
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 12.0,
vertical: 8.0,
child: Listener(
onPointerDown: (PointerDownEvent event) {
if (_lastPointerKind == event.kind) {
return;
}
setState(() {
_lastPointerKind = event.kind;
});
},
child: Stack(
children: [
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 12.0,
vertical: 8.0,
),
child: body,
),
child: body,
),
Positioned.fill(
child: IgnorePointer(
ignoring: !_isMenuOpen,
child: AnimatedOpacity(
duration: const Duration(milliseconds: 300),
opacity: _isMenuOpen ? 0.5 : 0.0,
curve: Curves.easeOutCubic,
Positioned(
left: 0,
top: 0,
bottom: 0,
width: 28,
child: IgnorePointer(
ignoring:
_isMenuOpen ||
!_requiresLongPressToDrag(_lastPointerKind),
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
setState(() {
_isMenuOpen = false;
});
},
child: Container(color: Colors.black),
behavior: HitTestBehavior.translucent,
onHorizontalDragUpdate:
(DragUpdateDetails details) {
if ((details.primaryDelta ?? 0) > 6) {
_openMenu();
}
},
child: const SizedBox.expand(),
),
),
),
),
AnimatedPositioned(
duration: const Duration(milliseconds: 300),
curve: Curves.easeOutCubic,
left: _isMenuOpen ? 0 : -280,
top: 0,
bottom: 0,
width: 280,
child: Material(
color: const Color.fromRGBO(24, 25, 26, 1),
elevation: 8,
child: MenuDrawer(
onMenuItemTapped: _handleMenuItemTapped,
selectedItem: _showDeletedNotes
? 'deleted_notes'
: 'all_notes',
Positioned.fill(
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: _closeMenu,
child: Container(color: Colors.black),
),
),
),
),
),
],
AnimatedPositioned(
duration: const Duration(milliseconds: 300),
curve: Curves.easeOutCubic,
left: _isMenuOpen ? 0 : -280,
top: 0,
bottom: 0,
width: 280,
child: Material(
color: const Color.fromRGBO(24, 25, 26, 1),
elevation: 8,
child: MenuDrawer(
onMenuItemTapped: _handleMenuItemTapped,
selectedItem: _showDeletedNotes
? 'deleted_notes'
: 'all_notes',
),
),
),
],
),
),
),
],