Files
plezy/lib/focus/dpad_select_long_press_controller.dart
T

64 lines
1.9 KiB
Dart

import 'dart:async';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart' show KeyEventResult, VoidCallback;
import 'dpad_navigator.dart';
/// Tracks the timer and physical key state for a D-pad SELECT long press.
///
/// Focus loss, context-menu dispatch, and transferred/touch gesture suppression
/// stay with the caller because their behavior differs between widgets. The TV
/// guide program selector also stays local: it captures a program at key-down
/// and resets its state before opening program details.
class DpadSelectLongPressController {
static const defaultDuration = Duration(milliseconds: 500);
Timer? _timer;
bool _isKeyDown = false;
KeyEventResult handleKeyEvent(
KeyEvent event, {
Duration duration = defaultDuration,
required bool Function() isOwnerActive,
required VoidCallback onShortPress,
required VoidCallback onLongPress,
}) {
if (!event.logicalKey.isSelectKey) return KeyEventResult.ignored;
if (event is KeyDownEvent) {
// Some platforms report another down instead of a repeat. Only the
// transition from up to down may start (or restart) the timer.
if (!_isKeyDown) {
_isKeyDown = true;
_timer?.cancel();
_timer = Timer(duration, () {
if (!isOwnerActive() || !_isKeyDown) return;
SelectKeyUpSuppressor.suppressSelectUntilKeyUp();
onLongPress();
});
}
return KeyEventResult.handled;
}
if (event is KeyRepeatEvent) return KeyEventResult.handled;
if (event is KeyUpEvent) {
final timerWasActive = _timer?.isActive ?? false;
_timer?.cancel();
if (timerWasActive && _isKeyDown) onShortPress();
_isKeyDown = false;
return KeyEventResult.handled;
}
return KeyEventResult.ignored;
}
void reset() {
_timer?.cancel();
_isKeyDown = false;
}
void dispose() => reset();
}