mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-22 07:15:47 +00:00
fix(shortcuts): keep shortcut contract in config/ (Rust include_str! path)
The shortcut contract (shortcutActions.ts + shortcutTypes.ts) is NOT a
pure-frontend file: src-tauri/src/cli/parse.rs include_str!s
'/../src/config/shortcutActions.ts' at compile time, so moving it to
lib/shortcuts/ (slice 7ad19671) broke the Rust build (couldn't read the file ->
dev build won't start). Revert the contract back to src/config/ — it has a
build-time backend path contract and belongs where Rust anchors it, not in lib/.
No Rust file touched (fix = restore the frontend path the backend expects).
cargo check green (13s), tsc 0, lint 0/0, frontend suite 319/2353 green.
Lesson: grep src-tauri for include_str!/include_bytes! '../src/...' before
moving ANY frontend file — Rust can pin a TS file by path.
This commit is contained in:
@@ -8,7 +8,7 @@ import { usePlayerStore } from '../store/playerStore';
|
||||
import { usePreviewStore } from '../store/previewStore';
|
||||
import { useLyricsStore } from '../store/lyricsStore';
|
||||
import { showToast } from '../utils/ui/toast';
|
||||
import type { ActionContext, ShortcutSlot, ShortcutActionMeta } from '@/lib/shortcuts/shortcutTypes';
|
||||
import type { ActionContext, ShortcutSlot, ShortcutActionMeta } from '@/config/shortcutTypes';
|
||||
|
||||
let cliPremuteVolume: number | null = null;
|
||||
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
// ─── Shortcut-action subsystem ───────────────────────────────────────────────
|
||||
//
|
||||
// Barrel + contract reference. Split into:
|
||||
// shortcutTypes.ts — shared types
|
||||
// shortcutActionRegistry.ts — SHORTCUT_ACTION_REGISTRY + action id types
|
||||
// shortcutDispatch.ts — runtime + CLI dispatch
|
||||
// shortcutBindings.ts — derived in-app / global binding tables
|
||||
// Existing call sites import from this module unchanged.
|
||||
//
|
||||
// ── The contract ─────────────────────────────────────────────────────────────
|
||||
//
|
||||
// Every shortcut action is one entry in `SHORTCUT_ACTION_REGISTRY`, keyed by a
|
||||
// stable id (`ShortcutAction`). Its `ShortcutActionMeta` declares which of three
|
||||
// independent *trigger surfaces* the action is exposed on — an action may opt
|
||||
// into any combination:
|
||||
//
|
||||
// • inApp? — bindable to a keyboard chord while the MAIN window is focused.
|
||||
// Presence of the `inApp` slot makes the id a `KeyAction`; the
|
||||
// slot's `defaultBinding` is the out-of-box chord (or null =
|
||||
// unbound), `hidden` keeps it out of the Settings UI list.
|
||||
// Surfaced via IN_APP_SHORTCUT_ACTIONS / DEFAULT_IN_APP_BINDINGS;
|
||||
// matched at runtime by `shortcuts/runtime.ts`.
|
||||
// • global? — registrable as an OS-LEVEL global hotkey (fires even when the
|
||||
// app is unfocused). Presence makes the id a `GlobalAction`;
|
||||
// surfaced via GLOBAL_SHORTCUT_ACTIONS / DEFAULT_GLOBAL_SHORTCUTS.
|
||||
// `isGlobalShortcutActionId` is the runtime guard.
|
||||
// • runInMiniWindow — whether the action may run when triggered FROM the
|
||||
// mini-player window. `canRunShortcutActionInMiniWindow` gates
|
||||
// cross-window `shortcut:run-action` events.
|
||||
//
|
||||
// Two extra, surface-independent fields:
|
||||
// • cli? — exposes the action to `psysonic --player <verb>`. No-arg CLI
|
||||
// verbs are auto-collected and dispatched by
|
||||
// `executeCliPlayerCommand`; arg-carrying commands (play-id,
|
||||
// seek-relative, set-volume, set-repeat, set-rating-current)
|
||||
// are handled explicitly there.
|
||||
// • run(ctx) — the handler. `ctx.previewPolicy` ('stop' | 'ignore') decides
|
||||
// whether an active track-preview is interrupted: media keys
|
||||
// pass 'ignore', explicit UI / in-app keys pass 'stop'.
|
||||
//
|
||||
// Dispatch entry points: `executeRuntimeAction` (any trigger surface) and
|
||||
// `executeCliPlayerCommand` (CLI). `isShortcutAction` validates an arbitrary
|
||||
// string against the registry.
|
||||
|
||||
export type {
|
||||
TranslateLike,
|
||||
ShortcutSlot,
|
||||
ActionContext,
|
||||
CliContext,
|
||||
ShortcutActionMeta,
|
||||
} from '@/config/shortcutTypes';
|
||||
|
||||
export {
|
||||
SHORTCUT_ACTION_REGISTRY,
|
||||
type ShortcutAction,
|
||||
type KeyAction,
|
||||
type GlobalAction,
|
||||
} from '@/config/shortcutActionRegistry';
|
||||
|
||||
export {
|
||||
isShortcutAction,
|
||||
isGlobalShortcutActionId,
|
||||
canRunShortcutActionInMiniWindow,
|
||||
executeRuntimeAction,
|
||||
executeCliPlayerCommand,
|
||||
type RuntimeAction,
|
||||
} from '@/config/shortcutDispatch';
|
||||
|
||||
export {
|
||||
IN_APP_SHORTCUT_ACTIONS,
|
||||
GLOBAL_SHORTCUT_ACTIONS,
|
||||
DEFAULT_IN_APP_BINDINGS,
|
||||
DEFAULT_GLOBAL_SHORTCUTS,
|
||||
} from '@/config/shortcutBindings';
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ShortcutSlot } from '@/lib/shortcuts/shortcutTypes';
|
||||
import type { ShortcutSlot } from '@/config/shortcutTypes';
|
||||
import {
|
||||
SHORTCUT_ACTION_REGISTRY,
|
||||
type ShortcutAction,
|
||||
|
||||
@@ -3,7 +3,7 @@ import i18n from '@/lib/i18n';
|
||||
import { usePlayerStore } from '../store/playerStore';
|
||||
import { showToast } from '../utils/ui/toast';
|
||||
import { playByOpaqueId } from '../utils/playback/playByOpaqueId';
|
||||
import type { ActionContext, CliContext } from '@/lib/shortcuts/shortcutTypes';
|
||||
import type { ActionContext, CliContext } from '@/config/shortcutTypes';
|
||||
import {
|
||||
SHORTCUT_ACTION_REGISTRY,
|
||||
type ShortcutAction,
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
// Shared types for the shortcut-action subsystem. The contract overview lives
|
||||
// in the barrel, `shortcutActions.ts`.
|
||||
|
||||
import type { NavigateOptions } from 'react-router-dom';
|
||||
|
||||
export type TranslateLike = (key: string, options?: Record<string, unknown>) => string;
|
||||
|
||||
/** One bindable slot (in-app OR global). `defaultBinding` is the out-of-box
|
||||
* chord, or `null` for "unbound by default". `hidden` keeps the action out of
|
||||
* the Settings shortcut-list UI (still bindable / dispatchable). */
|
||||
export type ShortcutSlot = { defaultBinding: string | null; hidden?: boolean };
|
||||
|
||||
/** Passed to an action's `run`. `previewPolicy` decides whether an active
|
||||
* track-preview is interrupted: 'stop' for explicit UI / in-app keys, 'ignore'
|
||||
* for hardware media keys. */
|
||||
export type ActionContext = {
|
||||
navigate: (to: string, options?: NavigateOptions) => void;
|
||||
previewPolicy: 'stop' | 'ignore';
|
||||
};
|
||||
|
||||
/** Passed to `executeCliPlayerCommand` — the raw `cli:player-command` payload
|
||||
* plus a navigate fn. */
|
||||
export type CliContext = {
|
||||
navigate: (to: string, options?: NavigateOptions) => void;
|
||||
payload: Record<string, unknown>;
|
||||
};
|
||||
|
||||
/** Registry entry for one shortcut action. `inApp` / `global` /
|
||||
* `runInMiniWindow` are the three independent trigger surfaces; `cli` and
|
||||
* `run` are surface-independent. See the contract block in `shortcutActions.ts`. */
|
||||
export type ShortcutActionMeta = {
|
||||
/** Localized display label for the Settings UI. */
|
||||
getLabel: (t: TranslateLike) => string;
|
||||
/** Present ⇒ bindable to a main-window keyboard chord (id becomes a `KeyAction`). */
|
||||
inApp?: ShortcutSlot;
|
||||
/** Present ⇒ registrable as an OS-level global hotkey (id becomes a `GlobalAction`). */
|
||||
global?: ShortcutSlot;
|
||||
/** Whether the action may run when triggered from the mini-player window. */
|
||||
runInMiniWindow: boolean;
|
||||
/** The handler. */
|
||||
run: (ctx: ActionContext) => void;
|
||||
/** Present ⇒ exposed to `psysonic --player <verb>`. `command` overrides the
|
||||
* CLI verb used for no-arg dispatch (defaults to the action id). */
|
||||
cli?: { verb: string; description: string; command?: string };
|
||||
};
|
||||
Reference in New Issue
Block a user