feat: Customizable shortcuts/hotkeys (#439)

This implements the logic for allowing hotkeys with modifiers.
Implemented globalhotkeys and videocontrol hotkeys
Also implements saving the forward backwards seconds to the user.

Co-authored-by: PartyDonut <PartyDonut@users.noreply.github.com>
This commit is contained in:
PartyDonut 2025-08-08 16:36:50 +02:00 committed by GitHub
parent 23385d8e62
commit fa30e634b4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
29 changed files with 1360 additions and 162 deletions

View file

@ -1,27 +1,36 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class InputHandler extends StatefulWidget {
import 'package:fladder/models/settings/key_combinations.dart';
class InputHandler<T> extends StatefulWidget {
final bool autoFocus;
final KeyEventResult Function(FocusNode node, KeyEvent event)? onKeyEvent;
final bool Function(T result)? keyMapResult;
final Map<T, KeyCombination>? keyMap;
final Widget child;
const InputHandler({
required this.child,
this.autoFocus = true,
this.onKeyEvent,
this.keyMapResult,
this.keyMap,
super.key,
});
@override
State<InputHandler> createState() => _InputHandlerState();
State<InputHandler> createState() => _InputHandlerState<T>();
}
class _InputHandlerState extends State<InputHandler> {
class _InputHandlerState<T> extends State<InputHandler<T>> {
final focusNode = FocusNode();
LogicalKeyboardKey? pressedModifier;
@override
void initState() {
super.initState();
//Focus on start
// Focus on start
focusNode.requestFocus();
}
@ -35,8 +44,38 @@ class _InputHandlerState extends State<InputHandler> {
focusNode.requestFocus();
}
},
onKeyEvent: widget.onKeyEvent,
onKeyEvent: (node, event) => _onKey(event),
child: widget.child,
);
}
KeyEventResult _onKey(KeyEvent value) {
final keyMap = widget.keyMap?.entries.nonNulls.toList() ?? [];
if (value is KeyDownEvent || value is KeyRepeatEvent) {
if (KeyCombination.modifierKeys.contains(value.logicalKey)) {
pressedModifier = value.logicalKey;
}
for (var entry in keyMap) {
final hotKey = entry.key;
final keyCombination = entry.value;
bool isMainKeyPressed = value.logicalKey == keyCombination.key;
bool isModifierKeyPressed = pressedModifier == keyCombination.modifier;
if (isMainKeyPressed && isModifierKeyPressed) {
if (widget.keyMapResult?.call(hotKey) ?? false) {
return KeyEventResult.handled;
} else {
return KeyEventResult.ignored;
}
}
}
} else if (value is KeyUpEvent) {
if (KeyCombination.modifierKeys.contains(value.logicalKey)) {
pressedModifier = null;
}
}
return KeyEventResult.ignored;
}
}