frontend: add OXC lint/format setup and apply semicolon fixes

This commit is contained in:
2026-05-25 02:54:30 +00:00
parent 836a563897
commit f6a40babc9
26 changed files with 3452 additions and 3130 deletions
@@ -1,16 +1,16 @@
type GamepadAction = 'up' | 'down' | 'left' | 'right' | 'select' | 'back' | 'menu';
type GamepadAction = "up" | "down" | "left" | "right" | "select" | "back" | "menu"
const GAMEPAD_AXIS_THRESHOLD = 0.55;
const GAMEPAD_REPEAT_MS = 180;
const GAMEPAD_AXIS_THRESHOLD = 0.55
const GAMEPAD_REPEAT_MS = 180
const KEY_BY_ACTION: Partial<Record<GamepadAction, string>> = {
up: 'ArrowUp',
down: 'ArrowDown',
left: 'ArrowLeft',
right: 'ArrowRight',
select: 'Enter',
back: 'Escape',
};
up: "ArrowUp",
down: "ArrowDown",
left: "ArrowLeft",
right: "ArrowRight",
select: "Enter",
back: "Escape",
}
const gamepadPressedState: Record<GamepadAction, boolean> = {
up: false,
@@ -20,7 +20,7 @@ const gamepadPressedState: Record<GamepadAction, boolean> = {
select: false,
back: false,
menu: false,
};
}
const gamepadLastTriggerAt: Record<GamepadAction, number> = {
up: 0,
@@ -30,111 +30,115 @@ const gamepadLastTriggerAt: Record<GamepadAction, number> = {
select: 0,
back: 0,
menu: 0,
};
}
let gamepadFrameId: number | null = null;
let gamepadInstalled = false;
let gamepadFrameId: number | null = null
let gamepadInstalled = false
function dispatchKey(key: string) {
const active = document.activeElement;
const target = active instanceof HTMLElement ? active : document;
target.dispatchEvent(new KeyboardEvent('keydown', {
key,
bubbles: true,
cancelable: true,
}));
const active = document.activeElement
const target = active instanceof HTMLElement ? active : document
target.dispatchEvent(
new KeyboardEvent("keydown", {
key,
bubbles: true,
cancelable: true,
}),
)
}
function applyGamepadAction(action: GamepadAction, isPressed: boolean, now: number) {
const wasPressed = gamepadPressedState[action];
gamepadPressedState[action] = isPressed;
const wasPressed = gamepadPressedState[action]
gamepadPressedState[action] = isPressed
if (!isPressed) return;
if (!isPressed) return
const shouldRepeat = action === 'up' || action === 'down' || action === 'left' || action === 'right';
const canTrigger = !wasPressed || (shouldRepeat && now - gamepadLastTriggerAt[action] >= GAMEPAD_REPEAT_MS);
if (!canTrigger) return;
const shouldRepeat =
action === "up" || action === "down" || action === "left" || action === "right"
const canTrigger =
!wasPressed || (shouldRepeat && now - gamepadLastTriggerAt[action] >= GAMEPAD_REPEAT_MS)
if (!canTrigger) return
gamepadLastTriggerAt[action] = now;
const actionEvent = new CustomEvent('mediahive:gamepad-action', {
gamepadLastTriggerAt[action] = now
const actionEvent = new CustomEvent("mediahive:gamepad-action", {
detail: { action },
cancelable: true,
});
const shouldContinueWithKeyboard = window.dispatchEvent(actionEvent);
if (!shouldContinueWithKeyboard) return;
})
const shouldContinueWithKeyboard = window.dispatchEvent(actionEvent)
if (!shouldContinueWithKeyboard) return
const key = KEY_BY_ACTION[action];
const key = KEY_BY_ACTION[action]
if (key) {
dispatchKey(key);
dispatchKey(key)
}
}
function resetPressedState() {
gamepadPressedState.up = false;
gamepadPressedState.down = false;
gamepadPressedState.left = false;
gamepadPressedState.right = false;
gamepadPressedState.select = false;
gamepadPressedState.back = false;
gamepadPressedState.menu = false;
gamepadPressedState.up = false
gamepadPressedState.down = false
gamepadPressedState.left = false
gamepadPressedState.right = false
gamepadPressedState.select = false
gamepadPressedState.back = false
gamepadPressedState.menu = false
}
function pollGamepad() {
const gamepads = navigator.getGamepads?.() ?? [];
const now = performance.now();
const connectedGamepads = gamepads.filter((gp): gp is Gamepad => Boolean(gp && gp.connected));
const gamepads = navigator.getGamepads?.() ?? []
const now = performance.now()
const connectedGamepads = gamepads.filter((gp): gp is Gamepad => Boolean(gp && gp.connected))
if (connectedGamepads.length > 0) {
let up = false;
let down = false;
let left = false;
let right = false;
let select = false;
let back = false;
let menu = false;
let up = false
let down = false
let left = false
let right = false
let select = false
let back = false
let menu = false
for (const gamepad of connectedGamepads) {
const axisX = gamepad.axes[0] ?? 0;
const axisY = gamepad.axes[1] ?? 0;
const axisX = gamepad.axes[0] ?? 0
const axisY = gamepad.axes[1] ?? 0
up = up || Boolean(gamepad.buttons[12]?.pressed) || axisY <= -GAMEPAD_AXIS_THRESHOLD;
down = down || Boolean(gamepad.buttons[13]?.pressed) || axisY >= GAMEPAD_AXIS_THRESHOLD;
left = left || Boolean(gamepad.buttons[14]?.pressed) || axisX <= -GAMEPAD_AXIS_THRESHOLD;
right = right || Boolean(gamepad.buttons[15]?.pressed) || axisX >= GAMEPAD_AXIS_THRESHOLD;
up = up || Boolean(gamepad.buttons[12]?.pressed) || axisY <= -GAMEPAD_AXIS_THRESHOLD
down = down || Boolean(gamepad.buttons[13]?.pressed) || axisY >= GAMEPAD_AXIS_THRESHOLD
left = left || Boolean(gamepad.buttons[14]?.pressed) || axisX <= -GAMEPAD_AXIS_THRESHOLD
right = right || Boolean(gamepad.buttons[15]?.pressed) || axisX >= GAMEPAD_AXIS_THRESHOLD
// Xbox mapping on standard gamepads: A=0, B=1
select = select || Boolean(gamepad.buttons[0]?.pressed);
back = back || Boolean(gamepad.buttons[1]?.pressed);
select = select || Boolean(gamepad.buttons[0]?.pressed)
back = back || Boolean(gamepad.buttons[1]?.pressed)
// Y/Triangle button opens contextual release list where supported.
menu = menu || Boolean(gamepad.buttons[3]?.pressed);
menu = menu || Boolean(gamepad.buttons[3]?.pressed)
}
applyGamepadAction('up', up, now);
applyGamepadAction('down', down, now);
applyGamepadAction('left', left, now);
applyGamepadAction('right', right, now);
applyGamepadAction('select', select, now);
applyGamepadAction('back', back, now);
applyGamepadAction('menu', menu, now);
applyGamepadAction("up", up, now)
applyGamepadAction("down", down, now)
applyGamepadAction("left", left, now)
applyGamepadAction("right", right, now)
applyGamepadAction("select", select, now)
applyGamepadAction("back", back, now)
applyGamepadAction("menu", menu, now)
} else {
resetPressedState();
resetPressedState()
}
gamepadFrameId = window.requestAnimationFrame(pollGamepad);
gamepadFrameId = window.requestAnimationFrame(pollGamepad)
}
export function installGamepadNavigation() {
if (gamepadInstalled) return;
gamepadInstalled = true;
gamepadFrameId = window.requestAnimationFrame(pollGamepad);
if (gamepadInstalled) return
gamepadInstalled = true
gamepadFrameId = window.requestAnimationFrame(pollGamepad)
}
export function uninstallGamepadNavigation() {
if (!gamepadInstalled) return;
gamepadInstalled = false;
if (!gamepadInstalled) return
gamepadInstalled = false
if (gamepadFrameId !== null) {
window.cancelAnimationFrame(gamepadFrameId);
gamepadFrameId = null;
window.cancelAnimationFrame(gamepadFrameId)
gamepadFrameId = null
}
resetPressedState();
resetPressedState()
}