refactor: util for keyboard activation

This commit is contained in:
edde746
2025-12-04 07:52:37 +01:00
parent 87dd16d322
commit ac7b867f54
8 changed files with 25 additions and 59 deletions
+2 -9
View File
@@ -2,6 +2,7 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import '../utils/keyboard_utils.dart';
/// A mixin that provides keyboard long-press detection for focusable widgets.
///
@@ -42,19 +43,11 @@ mixin KeyboardLongPressMixin<T extends StatefulWidget> on State<T> {
/// Override to handle long press action (e.g., show context menu)
void onKeyboardLongPress();
/// Check if the given key is an activation key
bool _isActivationKey(LogicalKeyboardKey key) {
return key == LogicalKeyboardKey.enter ||
key == LogicalKeyboardKey.space ||
key == LogicalKeyboardKey.select ||
key == LogicalKeyboardKey.gameButtonA;
}
/// Call this from your onKeyEvent handler to enable long-press detection.
/// Returns [KeyEventResult.handled] if the event was an activation key,
/// [KeyEventResult.ignored] otherwise.
KeyEventResult handleKeyboardLongPress(KeyEvent event) {
if (!_isActivationKey(event.logicalKey)) {
if (!isKeyboardActivationKey(event.logicalKey)) {
return KeyEventResult.ignored;
}
+1 -4
View File
@@ -133,10 +133,7 @@ class _DiscoverScreenState extends State<DiscoverScreen>
KeyEventResult _handleHeroKeyEvent(FocusNode node, KeyEvent event) {
if (event is KeyDownEvent) {
// Enter/Space to play current hero item
if (event.logicalKey == LogicalKeyboardKey.enter ||
event.logicalKey == LogicalKeyboardKey.space ||
event.logicalKey == LogicalKeyboardKey.select ||
event.logicalKey == LogicalKeyboardKey.gameButtonA) {
if (isKeyboardActivationKey(event.logicalKey)) {
if (_onDeck.isNotEmpty && _currentHeroIndex < _onDeck.length) {
navigateToVideoPlayer(context, metadata: _onDeck[_currentHeroIndex]);
return KeyEventResult.handled;
+6 -22
View File
@@ -1028,10 +1028,7 @@ class _LibrariesScreenState extends State<LibrariesScreen>
focusNode: _libraryDropdownFocusNode,
onKeyEvent: (node, event) {
if (event is KeyDownEvent) {
if (event.logicalKey == LogicalKeyboardKey.enter ||
event.logicalKey == LogicalKeyboardKey.space ||
event.logicalKey == LogicalKeyboardKey.select ||
event.logicalKey == LogicalKeyboardKey.gameButtonA) {
if (isKeyboardActivationKey(event.logicalKey)) {
_libraryDropdownKey.currentState?.showButtonMenu();
return KeyEventResult.handled;
}
@@ -1133,10 +1130,7 @@ class _LibrariesScreenState extends State<LibrariesScreen>
onKeyEvent: (node, event) {
if (event is KeyDownEvent) {
// Activation keys
if (event.logicalKey == LogicalKeyboardKey.enter ||
event.logicalKey == LogicalKeyboardKey.space ||
event.logicalKey == LogicalKeyboardKey.select ||
event.logicalKey == LogicalKeyboardKey.gameButtonA) {
if (isKeyboardActivationKey(event.logicalKey)) {
onPressed();
return KeyEventResult.handled;
}
@@ -1668,24 +1662,17 @@ class _LibraryManagementSheetState extends State<_LibraryManagementSheet> {
if (index < maxIndex) onMove(1);
return KeyEventResult.handled;
}
if (event.logicalKey == LogicalKeyboardKey.enter ||
event.logicalKey == LogicalKeyboardKey.space ||
event.logicalKey == LogicalKeyboardKey.select ||
event.logicalKey == LogicalKeyboardKey.gameButtonA) {
if (isKeyboardActivationKey(event.logicalKey)) {
onEndMove();
return KeyEventResult.handled;
}
if (event.logicalKey == LogicalKeyboardKey.escape ||
event.logicalKey == LogicalKeyboardKey.gameButtonB) {
if (isBackKey(event.logicalKey)) {
onCancelMove();
return KeyEventResult.handled;
}
} else {
// Not moving - Enter/Space starts move
if (event.logicalKey == LogicalKeyboardKey.enter ||
event.logicalKey == LogicalKeyboardKey.space ||
event.logicalKey == LogicalKeyboardKey.select ||
event.logicalKey == LogicalKeyboardKey.gameButtonA) {
if (isKeyboardActivationKey(event.logicalKey)) {
onStartMove();
return KeyEventResult.handled;
}
@@ -1749,10 +1736,7 @@ class _LibraryManagementSheetState extends State<_LibraryManagementSheet> {
if (event is! KeyDownEvent) return KeyEventResult.ignored;
// Handle activation
if (event.logicalKey == LogicalKeyboardKey.enter ||
event.logicalKey == LogicalKeyboardKey.space ||
event.logicalKey == LogicalKeyboardKey.select ||
event.logicalKey == LogicalKeyboardKey.gameButtonA) {
if (isKeyboardActivationKey(event.logicalKey)) {
onPressed();
return KeyEventResult.handled;
}
@@ -438,10 +438,7 @@ class _LibraryBrowseTabState extends State<LibraryBrowseTab>
return Focus(
onKeyEvent: (node, event) {
if (event is KeyDownEvent) {
if (event.logicalKey == LogicalKeyboardKey.enter ||
event.logicalKey == LogicalKeyboardKey.space ||
event.logicalKey == LogicalKeyboardKey.select ||
event.logicalKey == LogicalKeyboardKey.gameButtonA) {
if (isKeyboardActivationKey(event.logicalKey)) {
onPressed();
return KeyEventResult.handled;
}
+8
View File
@@ -13,3 +13,11 @@ bool isBackKeyEvent(KeyEvent event) {
if (event is! KeyDownEvent) return false;
return isBackKey(event.logicalKey);
}
/// Check if the given key should activate/select an item
bool isKeyboardActivationKey(LogicalKeyboardKey key) {
return key == LogicalKeyboardKey.enter ||
key == LogicalKeyboardKey.space ||
key == LogicalKeyboardKey.select ||
key == LogicalKeyboardKey.gameButtonA;
}
+3 -8
View File
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import '../models/plex_metadata.dart';
import '../utils/keyboard_utils.dart';
/// Individual item in the folder tree
/// Can be either a folder (expandable) or a file (tappable)
@@ -54,15 +55,9 @@ class _FolderTreeItemState extends State<FolderTreeItem> {
}
}
bool _isActivationKey(LogicalKeyboardKey key) {
return key == LogicalKeyboardKey.enter ||
key == LogicalKeyboardKey.space ||
key == LogicalKeyboardKey.select ||
key == LogicalKeyboardKey.gameButtonA;
}
KeyEventResult _handleKeyEvent(FocusNode node, KeyEvent event) {
if (event is KeyDownEvent && _isActivationKey(event.logicalKey)) {
if (event is KeyDownEvent &&
isKeyboardActivationKey(event.logicalKey)) {
_isKeyboardActivation = true;
return KeyEventResult.ignored; // Let InkWell handle the activation
}
+2 -4
View File
@@ -7,6 +7,7 @@ import 'horizontal_scroll_with_arrows.dart';
import 'hub_navigation_controller.dart';
import '../i18n/strings.g.dart';
import 'focus/focus_indicator.dart';
import '../utils/keyboard_utils.dart';
/// Shared hub section widget used in both discover and library screens
/// Displays a hub title with icon and a horizontal scrollable list of items
@@ -162,10 +163,7 @@ class _HubSectionState extends State<HubSection> {
KeyEventResult _handleHeaderKeyEvent(FocusNode node, KeyEvent event) {
if (event is KeyDownEvent && widget.hub.more) {
if (event.logicalKey == LogicalKeyboardKey.enter ||
event.logicalKey == LogicalKeyboardKey.space ||
event.logicalKey == LogicalKeyboardKey.select ||
event.logicalKey == LogicalKeyboardKey.gameButtonA) {
if (isKeyboardActivationKey(event.logicalKey)) {
_navigateToHubDetail();
return KeyEventResult.handled;
}
+2 -8
View File
@@ -1498,10 +1498,7 @@ class _FocusableContextMenuSheetState
}
// Select with Enter/Space
if (event.logicalKey == LogicalKeyboardKey.enter ||
event.logicalKey == LogicalKeyboardKey.space ||
event.logicalKey == LogicalKeyboardKey.select ||
event.logicalKey == LogicalKeyboardKey.gameButtonA) {
if (isKeyboardActivationKey(event.logicalKey)) {
Navigator.pop(context, widget.actions[_focusedIndex].value);
return KeyEventResult.handled;
}
@@ -1628,10 +1625,7 @@ class _FocusablePopupMenuState extends State<_FocusablePopupMenu> {
}
// Select with Enter/Space
if (event.logicalKey == LogicalKeyboardKey.enter ||
event.logicalKey == LogicalKeyboardKey.space ||
event.logicalKey == LogicalKeyboardKey.select ||
event.logicalKey == LogicalKeyboardKey.gameButtonA) {
if (isKeyboardActivationKey(event.logicalKey)) {
Navigator.pop(context, widget.actions[_focusedIndex].value);
return KeyEventResult.handled;
}