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