entangled-worlds-orbiters-shared 4.2.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/dist/shortcuts/catalogue.d.ts +72 -0
- package/dist/shortcuts/catalogue.js +118 -0
- package/dist/shortcuts/index.d.ts +3 -7
- package/dist/shortcuts/index.js +6 -10
- package/dist/shortcuts/match.d.ts +11 -5
- package/dist/shortcuts/source.d.ts +62 -0
- package/dist/shortcuts/source.js +139 -0
- package/package.json +1 -1
- package/src/shortcuts/catalogue.ts +172 -0
- package/src/shortcuts/index.ts +26 -28
- package/src/shortcuts/match.ts +12 -5
- package/src/shortcuts/source.ts +204 -0
- package/dist/shortcuts/entangledWorlds.d.ts +0 -21
- package/dist/shortcuts/entangledWorlds.js +0 -40
- package/dist/shortcuts/labels.d.ts +0 -10
- package/dist/shortcuts/labels.js +0 -130
- package/dist/shortcuts/orbiters.d.ts +0 -55
- package/dist/shortcuts/orbiters.js +0 -109
- package/dist/shortcuts/overrides.d.ts +0 -30
- package/dist/shortcuts/overrides.js +0 -81
- package/dist/shortcuts/sections.d.ts +0 -23
- package/dist/shortcuts/sections.js +0 -19
- package/dist/shortcuts/site.d.ts +0 -9
- package/dist/shortcuts/site.js +0 -25
- package/src/shortcuts/entangledWorlds.ts +0 -51
- package/src/shortcuts/labels.ts +0 -139
- package/src/shortcuts/orbiters.ts +0 -132
- package/src/shortcuts/overrides.ts +0 -110
- package/src/shortcuts/sections.ts +0 -36
- package/src/shortcuts/site.ts +0 -33
package/dist/shortcuts/labels.js
DELETED
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
// What the actions and sections are called in each language the platform speaks, beside the
|
|
2
|
-
// English in the catalogues. One table, read by every app and the settings page, so a name is
|
|
3
|
-
// translated once.
|
|
4
|
-
const ES = Object.freeze({
|
|
5
|
-
"ew.player.playPause": "Reproducir o pausar",
|
|
6
|
-
"ew.studio.commands": "Comandos",
|
|
7
|
-
"ew.studio.copy": "Copiar la selección",
|
|
8
|
-
"ew.studio.duplicate": "Duplicar la selección",
|
|
9
|
-
"ew.studio.help": "Atajos de teclado",
|
|
10
|
-
"ew.studio.paste": "Pegar",
|
|
11
|
-
"ew.studio.playPause": "Reproducir o pausar",
|
|
12
|
-
"ew.studio.redo": "Rehacer",
|
|
13
|
-
"ew.studio.remove": "Quitar la selección",
|
|
14
|
-
"ew.studio.step.animations": "Paso de animaciones",
|
|
15
|
-
"ew.studio.step.audio": "Paso de audio",
|
|
16
|
-
"ew.studio.step.release": "Paso de publicación",
|
|
17
|
-
"ew.studio.step.third": "Paso de exportación (Publicación donde no hay exportación)",
|
|
18
|
-
"ew.studio.undo": "Deshacer",
|
|
19
|
-
"orbiters.play.body.moon": "Luna",
|
|
20
|
-
"orbiters.play.body.star": "Estrella",
|
|
21
|
-
"orbiters.play.body.world": "Mundo",
|
|
22
|
-
"orbiters.play.dimension.1": "Primera dimensión",
|
|
23
|
-
"orbiters.play.dimension.2": "Segunda dimensión",
|
|
24
|
-
"orbiters.play.dimension.3": "Tercera dimensión",
|
|
25
|
-
"orbiters.play.help": "Atajos de teclado",
|
|
26
|
-
"orbiters.play.history.redo": "Rehacer",
|
|
27
|
-
"orbiters.play.history.undo": "Deshacer",
|
|
28
|
-
"orbiters.play.midiLearn": "MIDI learn",
|
|
29
|
-
"orbiters.play.panel.cosmicLfo": "Cosmic LFO",
|
|
30
|
-
"orbiters.play.panel.jamming": "Jamming",
|
|
31
|
-
"orbiters.play.panel.playback": "Reproducción",
|
|
32
|
-
"orbiters.play.panel.sensors": "Sensores",
|
|
33
|
-
"orbiters.play.performanceMode": "Modo rendimiento",
|
|
34
|
-
"orbiters.play.rec.hold": "Grabar mientras se mantiene",
|
|
35
|
-
"orbiters.play.rec.toggle": "Activar o desactivar Rec",
|
|
36
|
-
"orbiters.play.snapshot.recall.0": "Recuperar instantánea 0",
|
|
37
|
-
"orbiters.play.snapshot.recall.1": "Recuperar instantánea 1",
|
|
38
|
-
"orbiters.play.snapshot.recall.2": "Recuperar instantánea 2",
|
|
39
|
-
"orbiters.play.snapshot.recall.3": "Recuperar instantánea 3",
|
|
40
|
-
"orbiters.play.snapshot.recall.4": "Recuperar instantánea 4",
|
|
41
|
-
"orbiters.play.snapshot.recall.5": "Recuperar instantánea 5",
|
|
42
|
-
"orbiters.play.snapshot.recall.6": "Recuperar instantánea 6",
|
|
43
|
-
"orbiters.play.snapshot.recall.7": "Recuperar instantánea 7",
|
|
44
|
-
"orbiters.play.snapshot.recall.8": "Recuperar instantánea 8",
|
|
45
|
-
"orbiters.play.snapshot.recall.9": "Recuperar instantánea 9",
|
|
46
|
-
"orbiters.play.snapshot.store.0": "Guardar instantánea 0",
|
|
47
|
-
"orbiters.play.snapshot.store.1": "Guardar instantánea 1",
|
|
48
|
-
"orbiters.play.snapshot.store.2": "Guardar instantánea 2",
|
|
49
|
-
"orbiters.play.snapshot.store.3": "Guardar instantánea 3",
|
|
50
|
-
"orbiters.play.snapshot.store.4": "Guardar instantánea 4",
|
|
51
|
-
"orbiters.play.snapshot.store.5": "Guardar instantánea 5",
|
|
52
|
-
"orbiters.play.snapshot.store.6": "Guardar instantánea 6",
|
|
53
|
-
"orbiters.play.snapshot.store.7": "Guardar instantánea 7",
|
|
54
|
-
"orbiters.play.snapshot.store.8": "Guardar instantánea 8",
|
|
55
|
-
"orbiters.play.snapshot.store.9": "Guardar instantánea 9",
|
|
56
|
-
"orbiters.play.transport.restart": "Reproducir desde el principio",
|
|
57
|
-
"orbiters.play.transport.toggle": "Reproducir o pausar",
|
|
58
|
-
"orbiters.studio.map": "Mapear",
|
|
59
|
-
"orbiters.studio.redo": "Rehacer",
|
|
60
|
-
"orbiters.studio.undo": "Deshacer",
|
|
61
|
-
"site.commands": "Comandos",
|
|
62
|
-
"site.search": "Buscar",
|
|
63
|
-
"site.go.home": "Inicio",
|
|
64
|
-
"site.go.playground": "Playground",
|
|
65
|
-
"site.go.notifications": "Notificaciones",
|
|
66
|
-
"site.go.audios": "Mis audios",
|
|
67
|
-
"site.go.orbiters": "Mis Orbiters",
|
|
68
|
-
"site.go.worlds": "Mis Entangled Worlds",
|
|
69
|
-
"site.go.collections": "Mis colecciones",
|
|
70
|
-
"site.go.stars": "Mis estrellas",
|
|
71
|
-
"site.new.orbiter": "Nuevo Orbiter",
|
|
72
|
-
"site.new.audio": "Nuevo audio",
|
|
73
|
-
"site.new.world": "Nuevo Entangled World",
|
|
74
|
-
"site.settings": "Abrir la configuración",
|
|
75
|
-
"section:site": "Plantasia Space",
|
|
76
|
-
"app:plantasia-space": "Plantasia Space",
|
|
77
|
-
"app:orbiters": "Orbiters",
|
|
78
|
-
"app:entangled-worlds": "Entangled Worlds",
|
|
79
|
-
"part:orbiters-play": "Tocar",
|
|
80
|
-
"part:orbiters-studio": "Estudio",
|
|
81
|
-
"part:ew-studio": "Estudio",
|
|
82
|
-
"part:ew-player": "Reproductor",
|
|
83
|
-
"section:orbiters-play": "Orbiters: tocar",
|
|
84
|
-
"section:orbiters-studio": "Orbiter Studio",
|
|
85
|
-
"section:ew-studio": "Estudio de Entangled Worlds",
|
|
86
|
-
"section:ew-player": "Reproductor de Entangled Worlds",
|
|
87
|
-
"orbiters.play.screenCapture": "Captura de pantalla",
|
|
88
|
-
"orbiters.play.share": "Compartir",
|
|
89
|
-
"orbiters.play.fullscreen": "Pantalla completa",
|
|
90
|
-
"orbiters.play.commands": "Comandos",
|
|
91
|
-
"group:edit": "Edición",
|
|
92
|
-
"group:playback": "Reproducción",
|
|
93
|
-
"group:steps": "Pasos",
|
|
94
|
-
"group:help": "Ayuda",
|
|
95
|
-
"group:transport": "Transporte",
|
|
96
|
-
"group:view": "Vista",
|
|
97
|
-
"group:snapshots": "Instantáneas",
|
|
98
|
-
"group:panels": "Paneles",
|
|
99
|
-
"group:orbiter": "Orbiter",
|
|
100
|
-
"group:studio": "Estudio",
|
|
101
|
-
"row:playPause": "Reproducir / pausar",
|
|
102
|
-
"row:playFromStart": "Reproducir desde el inicio",
|
|
103
|
-
"row:recHeld": "REC mientras se mantiene",
|
|
104
|
-
"row:recLatch": "REC fijo",
|
|
105
|
-
"row:undo": "Deshacer",
|
|
106
|
-
"row:redo": "Rehacer",
|
|
107
|
-
"row:dimensions": "Dimensión I · II · III",
|
|
108
|
-
"row:bodies": "Mundo · Luna · Estrella",
|
|
109
|
-
"row:snapshotRecall": "Recuperar instantánea",
|
|
110
|
-
"row:snapshotStore": "Guardar instantánea",
|
|
111
|
-
"row:jamming": "Jamming",
|
|
112
|
-
"row:playback": "Reproducción",
|
|
113
|
-
"row:cosmicLfo": "Cosmic LFO",
|
|
114
|
-
"row:sensors": "Sensores",
|
|
115
|
-
"row:midiLearn": "MIDI learn",
|
|
116
|
-
"row:performanceMode": "Modo rendimiento",
|
|
117
|
-
});
|
|
118
|
-
const NAMES = Object.freeze({ es: ES });
|
|
119
|
-
/** An action's name in a language (`es`, `es-AR`), falling back to the catalogue's English. */
|
|
120
|
-
export function shortcutLabel(action, locale) {
|
|
121
|
-
return NAMES[(locale ?? '').slice(0, 2).toLowerCase()]?.[action.id] ?? action.label;
|
|
122
|
-
}
|
|
123
|
-
/** A section's name in a language, falling back to the English. */
|
|
124
|
-
export function shortcutSectionLabel(section, locale) {
|
|
125
|
-
return NAMES[(locale ?? '').slice(0, 2).toLowerCase()]?.[`section:${section.id}`] ?? section.label;
|
|
126
|
-
}
|
|
127
|
-
/** Any other named thing of the shortcuts (a command group `group:<id>`, a sheet row `row:<id>`). */
|
|
128
|
-
export function shortcutName(key, english, locale) {
|
|
129
|
-
return NAMES[(locale ?? '').slice(0, 2).toLowerCase()]?.[key] ?? english;
|
|
130
|
-
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import type { ShortcutAction } from './match.js';
|
|
2
|
-
export type OrbitersShortcutScope = 'voice' | 'client';
|
|
3
|
-
export type OrbitersShortcut = ShortcutAction<OrbitersShortcutScope>;
|
|
4
|
-
export declare const ORBITERS_PLAY_SECTION = "orbiters-play";
|
|
5
|
-
export declare const ORBITERS_STUDIO_SECTION = "orbiters-studio";
|
|
6
|
-
/** How a command menu groups the actions, in its order. */
|
|
7
|
-
export declare const ORBITERS_COMMAND_GROUPS: readonly [{
|
|
8
|
-
readonly id: "transport";
|
|
9
|
-
readonly label: "Transport";
|
|
10
|
-
}, {
|
|
11
|
-
readonly id: "view";
|
|
12
|
-
readonly label: "View";
|
|
13
|
-
}, {
|
|
14
|
-
readonly id: "snapshots";
|
|
15
|
-
readonly label: "Snapshots";
|
|
16
|
-
}, {
|
|
17
|
-
readonly id: "panels";
|
|
18
|
-
readonly label: "Panels";
|
|
19
|
-
}, {
|
|
20
|
-
readonly id: "orbiter";
|
|
21
|
-
readonly label: "Orbiter";
|
|
22
|
-
}, {
|
|
23
|
-
readonly id: "studio";
|
|
24
|
-
readonly label: "Studio";
|
|
25
|
-
}];
|
|
26
|
-
/**
|
|
27
|
-
* Playing an Orbiter. Shift is free on most keys (`Shift?`): it is held to select several decks,
|
|
28
|
-
* and a key pressed while selecting means what it means alone.
|
|
29
|
-
*/
|
|
30
|
-
export declare const ORBITERS_PLAY_SHORTCUTS: readonly OrbitersShortcut[];
|
|
31
|
-
/**
|
|
32
|
-
* The keys sheet (`?`): what to look up at a glance, in three columns. A row may stand for several
|
|
33
|
-
* actions whose keys differ only in the last key ("Dimension I · II · III — 1 2 3"); the keys
|
|
34
|
-
* shown are always this person's (`mergedKeyParts`).
|
|
35
|
-
*/
|
|
36
|
-
export declare const ORBITERS_PLAY_SHEET: readonly Readonly<{
|
|
37
|
-
rows: readonly Readonly<{
|
|
38
|
-
actions: readonly string[];
|
|
39
|
-
id: string;
|
|
40
|
-
label: string;
|
|
41
|
-
}>[];
|
|
42
|
-
id: string;
|
|
43
|
-
label: string;
|
|
44
|
-
}>[];
|
|
45
|
-
/**
|
|
46
|
-
* The Studio. It is open over play, so the play keys above still work there; where both name a key,
|
|
47
|
-
* the Studio's action is the one.
|
|
48
|
-
*/
|
|
49
|
-
export declare const ORBITERS_STUDIO_SHORTCUTS: readonly OrbitersShortcut[];
|
|
50
|
-
/**
|
|
51
|
-
* The letters the on-screen keyboard plays while it is open (`event.key`, lower-case): the piano row,
|
|
52
|
-
* then Z and X for the octave and C and V for velocity. While it is up they are its notes, and the
|
|
53
|
-
* shortcuts on them wait (`claimKeys`); a settings page says so beside those keys.
|
|
54
|
-
*/
|
|
55
|
-
export declare const ORBITERS_KEYBOARD_SURFACE_KEYS: readonly string[];
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
// The Orbiters catalogues: every key Orbiters answers, with the keys it has by default.
|
|
2
|
-
//
|
|
3
|
-
// `voice` acts on the focused deck(s), so in a shared session it only reaches a deck this person
|
|
4
|
-
// holds; `client` is about this machine and no deck (MIDI learn, performance mode, the Studio).
|
|
5
|
-
export const ORBITERS_PLAY_SECTION = 'orbiters-play';
|
|
6
|
-
export const ORBITERS_STUDIO_SECTION = 'orbiters-studio';
|
|
7
|
-
const play = (id, label, defaultKeys, { scope = 'voice', group, command } = {}) => Object.freeze({
|
|
8
|
-
id: `orbiters.play.${id}`, section: ORBITERS_PLAY_SECTION, label, defaultKeys: Object.freeze([...defaultKeys]), scope,
|
|
9
|
-
...(group ? { group } : {}), ...(command === false ? { command } : {}),
|
|
10
|
-
});
|
|
11
|
-
const studio = (id, label, defaultKeys) => Object.freeze({ id: `orbiters.studio.${id}`, section: ORBITERS_STUDIO_SECTION, label, defaultKeys: Object.freeze([...defaultKeys]), scope: 'client', group: 'studio' });
|
|
12
|
-
/** How a command menu groups the actions, in its order. */
|
|
13
|
-
export const ORBITERS_COMMAND_GROUPS = Object.freeze([
|
|
14
|
-
{ id: 'transport', label: 'Transport' },
|
|
15
|
-
{ id: 'view', label: 'View' },
|
|
16
|
-
{ id: 'snapshots', label: 'Snapshots' },
|
|
17
|
-
{ id: 'panels', label: 'Panels' },
|
|
18
|
-
{ id: 'orbiter', label: 'Orbiter' },
|
|
19
|
-
{ id: 'studio', label: 'Studio' },
|
|
20
|
-
]);
|
|
21
|
-
/** The snapshot slots, by the number each shows: the number row, 1 to 9, then 0. */
|
|
22
|
-
const SLOT_NUMBERS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
|
|
23
|
-
/** Undo and redo, the same keys wherever an edit can be taken back. */
|
|
24
|
-
const UNDO_KEYS = ['Mod+KeyZ'];
|
|
25
|
-
const REDO_KEYS = ['Mod+Shift+KeyZ', 'Ctrl+Shift?+KeyY'];
|
|
26
|
-
/**
|
|
27
|
-
* Playing an Orbiter. Shift is free on most keys (`Shift?`): it is held to select several decks,
|
|
28
|
-
* and a key pressed while selecting means what it means alone.
|
|
29
|
-
*/
|
|
30
|
-
export const ORBITERS_PLAY_SHORTCUTS = Object.freeze([
|
|
31
|
-
// Space takes Ctrl, Option and ⌘ as it comes: only Shift changes what it does.
|
|
32
|
-
play('transport.toggle', 'Play or pause', ['Alt?+Ctrl?+Meta?+Space'], { group: 'transport' }),
|
|
33
|
-
play('transport.restart', 'Play from the beginning', ['Shift+Alt?+Ctrl?+Meta?+Space'], { group: 'transport' }),
|
|
34
|
-
play('rec.hold', 'Record while held', ['KeyR'], { group: 'transport', command: false }),
|
|
35
|
-
play('rec.toggle', 'Rec on or off', ['Shift+KeyR'], { group: 'transport' }),
|
|
36
|
-
play('history.undo', 'Undo', UNDO_KEYS, { group: 'transport' }),
|
|
37
|
-
play('history.redo', 'Redo', REDO_KEYS, { group: 'transport' }),
|
|
38
|
-
play('dimension.1', 'First dimension', ['Shift?+Digit1'], { group: 'view' }),
|
|
39
|
-
play('dimension.2', 'Second dimension', ['Shift?+Digit2'], { group: 'view' }),
|
|
40
|
-
play('dimension.3', 'Third dimension', ['Shift?+Digit3'], { group: 'view' }),
|
|
41
|
-
play('body.world', 'World', ['Shift?+KeyQ'], { group: 'view' }),
|
|
42
|
-
play('body.moon', 'Moon', ['Shift?+KeyW'], { group: 'view' }),
|
|
43
|
-
play('body.star', 'Star', ['Shift?+KeyE'], { group: 'view' }),
|
|
44
|
-
...SLOT_NUMBERS.map((n) => play(`snapshot.recall.${n}`, `Recall snapshot ${n}`, [`Alt+Digit${n}`], { group: 'snapshots' })),
|
|
45
|
-
...SLOT_NUMBERS.map((n) => play(`snapshot.store.${n}`, `Store snapshot ${n}`, [`Alt+Shift+Digit${n}`], { group: 'snapshots' })),
|
|
46
|
-
// The panels, from the bottom of the rail up.
|
|
47
|
-
play('panel.jamming', 'Jamming', ['KeyA'], { group: 'panels' }),
|
|
48
|
-
play('panel.playback', 'Playback', ['KeyS'], { group: 'panels' }),
|
|
49
|
-
play('panel.cosmicLfo', 'Cosmic LFO', ['KeyD'], { group: 'panels' }),
|
|
50
|
-
play('panel.sensors', 'Sensors', ['KeyF'], { group: 'panels' }),
|
|
51
|
-
// The More menu, and this machine's switches.
|
|
52
|
-
play('midiLearn', 'MIDI learn', ['Shift?+KeyM'], { scope: 'client', group: 'orbiter' }),
|
|
53
|
-
play('performanceMode', 'Performance mode', ['Shift?+KeyP'], { scope: 'client', group: 'orbiter' }),
|
|
54
|
-
play('screenCapture', 'Screen capture', [], { scope: 'client', group: 'orbiter' }),
|
|
55
|
-
play('share', 'Share', [], { scope: 'client', group: 'orbiter' }),
|
|
56
|
-
play('fullscreen', 'Fullscreen', [], { scope: 'client', group: 'orbiter' }),
|
|
57
|
-
// `?` on a US keyboard: the key's place, whatever this keyboard prints there.
|
|
58
|
-
play('help', 'Keyboard shortcuts', ['Shift?+Slash'], { scope: 'client', group: 'orbiter', command: false }),
|
|
59
|
-
play('commands', 'Commands', ['Mod+KeyK'], { scope: 'client', group: 'orbiter', command: false }),
|
|
60
|
-
]);
|
|
61
|
-
/**
|
|
62
|
-
* The keys sheet (`?`): what to look up at a glance, in three columns. A row may stand for several
|
|
63
|
-
* actions whose keys differ only in the last key ("Dimension I · II · III — 1 2 3"); the keys
|
|
64
|
-
* shown are always this person's (`mergedKeyParts`).
|
|
65
|
-
*/
|
|
66
|
-
export const ORBITERS_PLAY_SHEET = Object.freeze([
|
|
67
|
-
{ id: 'transport', label: 'Transport', rows: [
|
|
68
|
-
{ id: 'playPause', label: 'Play / pause', actions: ['transport.toggle'] },
|
|
69
|
-
{ id: 'playFromStart', label: 'Play from start', actions: ['transport.restart'] },
|
|
70
|
-
{ id: 'recHeld', label: 'REC while held', actions: ['rec.hold'] },
|
|
71
|
-
{ id: 'recLatch', label: 'REC latch', actions: ['rec.toggle'] },
|
|
72
|
-
{ id: 'undo', label: 'Undo', actions: ['history.undo'] },
|
|
73
|
-
{ id: 'redo', label: 'Redo', actions: ['history.redo'] },
|
|
74
|
-
] },
|
|
75
|
-
{ id: 'view', label: 'View', rows: [
|
|
76
|
-
{ id: 'dimensions', label: 'Dimension I · II · III', actions: ['dimension.1', 'dimension.2', 'dimension.3'] },
|
|
77
|
-
{ id: 'bodies', label: 'World · Moon · Star', actions: ['body.world', 'body.moon', 'body.star'] },
|
|
78
|
-
{ id: 'snapshotRecall', label: 'Snapshot recall', actions: SLOT_NUMBERS.map((n) => `snapshot.recall.${n}`) },
|
|
79
|
-
{ id: 'snapshotStore', label: 'Snapshot store', actions: SLOT_NUMBERS.map((n) => `snapshot.store.${n}`) },
|
|
80
|
-
] },
|
|
81
|
-
{ id: 'panels', label: 'Panels', rows: [
|
|
82
|
-
{ id: 'jamming', label: 'Jamming', actions: ['panel.jamming'] },
|
|
83
|
-
{ id: 'playback', label: 'Playback', actions: ['panel.playback'] },
|
|
84
|
-
{ id: 'cosmicLfo', label: 'Cosmic LFO', actions: ['panel.cosmicLfo'] },
|
|
85
|
-
{ id: 'sensors', label: 'Sensors', actions: ['panel.sensors'] },
|
|
86
|
-
{ id: 'midiLearn', label: 'MIDI learn', actions: ['midiLearn'] },
|
|
87
|
-
{ id: 'performanceMode', label: 'Performance mode', actions: ['performanceMode'] },
|
|
88
|
-
] },
|
|
89
|
-
].map((column) => Object.freeze({
|
|
90
|
-
...column,
|
|
91
|
-
rows: Object.freeze(column.rows.map((row) => Object.freeze({ ...row, actions: Object.freeze(row.actions.map((a) => `orbiters.play.${a}`)) }))),
|
|
92
|
-
})));
|
|
93
|
-
/**
|
|
94
|
-
* The Studio. It is open over play, so the play keys above still work there; where both name a key,
|
|
95
|
-
* the Studio's action is the one.
|
|
96
|
-
*/
|
|
97
|
-
export const ORBITERS_STUDIO_SHORTCUTS = Object.freeze([
|
|
98
|
-
studio('undo', 'Undo', UNDO_KEYS),
|
|
99
|
-
studio('redo', 'Redo', REDO_KEYS),
|
|
100
|
-
studio('map', 'Map', ['Shift+KeyM']),
|
|
101
|
-
]);
|
|
102
|
-
/**
|
|
103
|
-
* The letters the on-screen keyboard plays while it is open (`event.key`, lower-case): the piano row,
|
|
104
|
-
* then Z and X for the octave and C and V for velocity. While it is up they are its notes, and the
|
|
105
|
-
* shortcuts on them wait (`claimKeys`); a settings page says so beside those keys.
|
|
106
|
-
*/
|
|
107
|
-
export const ORBITERS_KEYBOARD_SURFACE_KEYS = Object.freeze([
|
|
108
|
-
'a', 'w', 's', 'e', 'd', 'f', 't', 'g', 'y', 'h', 'u', 'j', 'k', 'o', 'l', 'p', ';', "'", 'z', 'x', 'c', 'v',
|
|
109
|
-
]);
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { type ShortcutAction, type ShortcutOverrides } from './match.js';
|
|
2
|
-
/** The overrides in a stored value, or `null` when it is not a list of `{ id, keys }`. */
|
|
3
|
-
export declare function parseOverrides(value: unknown): ShortcutOverrides | null;
|
|
4
|
-
/**
|
|
5
|
-
* How the app reads the signed-in person's settings: `null` when no one is signed in (the
|
|
6
|
-
* default keys); `undefined` when the read failed (the overrides in force are kept: a blip must not
|
|
7
|
-
* swap someone's keys for the defaults).
|
|
8
|
-
*/
|
|
9
|
-
export type ReadAccountSettings = (options: {
|
|
10
|
-
fresh: boolean;
|
|
11
|
-
}) => Promise<{
|
|
12
|
-
shortcuts?: unknown;
|
|
13
|
-
} | null | undefined>;
|
|
14
|
-
export interface ShortcutOverridesSource {
|
|
15
|
-
/** The overrides in force. */
|
|
16
|
-
get(): ShortcutOverrides;
|
|
17
|
-
/** A catalogue's actions with their keys now (kept until the overrides change). */
|
|
18
|
-
bindings(catalogue: readonly ShortcutAction[]): Map<string, readonly string[]>;
|
|
19
|
-
/** Called whenever the overrides change; returns the unsubscribe. */
|
|
20
|
-
subscribe(listener: () => void): () => void;
|
|
21
|
-
/** Read again (`fresh`: past the app's own cached read). The newest read wins, whatever order they end in. */
|
|
22
|
-
refresh(options?: {
|
|
23
|
-
fresh?: boolean;
|
|
24
|
-
}): Promise<void>;
|
|
25
|
-
/** Read now, and again whenever the page comes back to the front; once per source. */
|
|
26
|
-
bind(): void;
|
|
27
|
-
/** For tests: set the overrides directly. */
|
|
28
|
-
set(overrides: ShortcutOverrides): void;
|
|
29
|
-
}
|
|
30
|
-
export declare function createShortcutOverridesSource(readAccount: ReadAccountSettings): ShortcutOverridesSource;
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
// A person's shortcut overrides, read the same way by every app: from their account when signed in
|
|
2
|
-
// (someone signed out has the default keys), and again whenever the page comes back to the front (a key changed
|
|
3
|
-
// on the settings page applies on return, without a reload).
|
|
4
|
-
//
|
|
5
|
-
// Framework-free: the app hands in how it reads the account (its own API client) and gets the
|
|
6
|
-
// overrides and each catalogue's resolved keys back, kept until the overrides change.
|
|
7
|
-
import { resolveBindings } from './match.js';
|
|
8
|
-
/** The overrides in a stored value, or `null` when it is not a list of `{ id, keys }`. */
|
|
9
|
-
export function parseOverrides(value) {
|
|
10
|
-
if (!Array.isArray(value))
|
|
11
|
-
return null;
|
|
12
|
-
return value.filter((entry) => !!entry && typeof entry.id === 'string' && Array.isArray(entry.keys) && entry.keys.every((k) => typeof k === 'string'));
|
|
13
|
-
}
|
|
14
|
-
/** Coming back to the front twice in a row (visible, then focus) asks the account once. */
|
|
15
|
-
const REFRESH_GAP_MS = 2000;
|
|
16
|
-
export function createShortcutOverridesSource(readAccount) {
|
|
17
|
-
let overrides = [];
|
|
18
|
-
let resolved = new WeakMap();
|
|
19
|
-
let latest = 0;
|
|
20
|
-
let applied = 0;
|
|
21
|
-
let lastRefreshAt = -Infinity;
|
|
22
|
-
let bound = false;
|
|
23
|
-
const listeners = new Set();
|
|
24
|
-
const apply = (next) => {
|
|
25
|
-
if (JSON.stringify(next) === JSON.stringify(overrides))
|
|
26
|
-
return;
|
|
27
|
-
overrides = next;
|
|
28
|
-
resolved = new WeakMap();
|
|
29
|
-
listeners.forEach((listener) => listener());
|
|
30
|
-
};
|
|
31
|
-
const refresh = async ({ fresh = false } = {}) => {
|
|
32
|
-
const ticket = ++latest;
|
|
33
|
-
lastRefreshAt = Date.now();
|
|
34
|
-
let settings;
|
|
35
|
-
try {
|
|
36
|
-
settings = await readAccount({ fresh });
|
|
37
|
-
}
|
|
38
|
-
catch {
|
|
39
|
-
settings = undefined;
|
|
40
|
-
}
|
|
41
|
-
// The newest read that answered wins: an older one ending after it says nothing new, and a newer
|
|
42
|
-
// one that failed does not throw away an older one's answer.
|
|
43
|
-
if (settings === undefined || ticket < applied)
|
|
44
|
-
return;
|
|
45
|
-
applied = ticket;
|
|
46
|
-
apply(settings === null ? [] : (parseOverrides(settings.shortcuts) ?? []));
|
|
47
|
-
};
|
|
48
|
-
return {
|
|
49
|
-
get: () => overrides,
|
|
50
|
-
bindings(catalogue) {
|
|
51
|
-
let map = resolved.get(catalogue);
|
|
52
|
-
if (!map) {
|
|
53
|
-
map = resolveBindings(catalogue, overrides);
|
|
54
|
-
resolved.set(catalogue, map);
|
|
55
|
-
}
|
|
56
|
-
return map;
|
|
57
|
-
},
|
|
58
|
-
subscribe(listener) {
|
|
59
|
-
listeners.add(listener);
|
|
60
|
-
return () => {
|
|
61
|
-
listeners.delete(listener);
|
|
62
|
-
};
|
|
63
|
-
},
|
|
64
|
-
refresh,
|
|
65
|
-
bind() {
|
|
66
|
-
const win = globalThis;
|
|
67
|
-
if (bound || typeof win.addEventListener !== 'function' || !win.document?.addEventListener)
|
|
68
|
-
return;
|
|
69
|
-
bound = true;
|
|
70
|
-
void refresh();
|
|
71
|
-
const onFront = () => {
|
|
72
|
-
if (win.document?.visibilityState !== 'visible' || Date.now() - lastRefreshAt < REFRESH_GAP_MS)
|
|
73
|
-
return;
|
|
74
|
-
void refresh({ fresh: true });
|
|
75
|
-
};
|
|
76
|
-
win.document.addEventListener('visibilitychange', onFront);
|
|
77
|
-
win.addEventListener('focus', onFront);
|
|
78
|
-
},
|
|
79
|
-
set: apply,
|
|
80
|
-
};
|
|
81
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import type { ShortcutAction } from './match.js';
|
|
2
|
-
/** The apps a person tells apart, in the order a settings page shows them. */
|
|
3
|
-
export declare const SHORTCUT_APPS: readonly [Readonly<{
|
|
4
|
-
id: "plantasia-space";
|
|
5
|
-
label: "Plantasia Space";
|
|
6
|
-
}>, Readonly<{
|
|
7
|
-
id: "orbiters";
|
|
8
|
-
label: "Orbiters";
|
|
9
|
-
}>, Readonly<{
|
|
10
|
-
id: "entangled-worlds";
|
|
11
|
-
label: "Entangled Worlds";
|
|
12
|
-
}>];
|
|
13
|
-
export type ShortcutAppId = (typeof SHORTCUT_APPS)[number]['id'];
|
|
14
|
-
export interface ShortcutSection {
|
|
15
|
-
readonly id: string;
|
|
16
|
-
readonly label: string;
|
|
17
|
-
/** The app it belongs to. */
|
|
18
|
-
readonly app: ShortcutAppId;
|
|
19
|
-
/** Its name inside that app (`Play`, `Studio`); none when the app has only this section. */
|
|
20
|
-
readonly part?: string;
|
|
21
|
-
readonly actions: readonly ShortcutAction[];
|
|
22
|
-
}
|
|
23
|
-
export declare const SHORTCUT_SECTIONS: readonly ShortcutSection[];
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
// Every app's catalogue in one place, in the order a settings page shows them. A section is one
|
|
2
|
-
// surface's keys; two actions may share a key only across sections (the Orbiter Studio lies over
|
|
3
|
-
// play, and takes ⌘Z from it while it is open).
|
|
4
|
-
import { EW_PLAYER_SECTION, EW_PLAYER_SHORTCUTS, EW_STUDIO_SECTION, EW_STUDIO_SHORTCUTS } from './entangledWorlds.js';
|
|
5
|
-
import { ORBITERS_PLAY_SECTION, ORBITERS_PLAY_SHORTCUTS, ORBITERS_STUDIO_SECTION, ORBITERS_STUDIO_SHORTCUTS } from './orbiters.js';
|
|
6
|
-
import { SITE_SECTION, SITE_SHORTCUTS } from './site.js';
|
|
7
|
-
/** The apps a person tells apart, in the order a settings page shows them. */
|
|
8
|
-
export const SHORTCUT_APPS = Object.freeze([
|
|
9
|
-
Object.freeze({ id: 'plantasia-space', label: 'Plantasia Space' }),
|
|
10
|
-
Object.freeze({ id: 'orbiters', label: 'Orbiters' }),
|
|
11
|
-
Object.freeze({ id: 'entangled-worlds', label: 'Entangled Worlds' }),
|
|
12
|
-
]);
|
|
13
|
-
export const SHORTCUT_SECTIONS = Object.freeze([
|
|
14
|
-
Object.freeze({ id: SITE_SECTION, label: 'Plantasia Space', app: 'plantasia-space', actions: SITE_SHORTCUTS }),
|
|
15
|
-
Object.freeze({ id: ORBITERS_PLAY_SECTION, label: 'Orbiters play', app: 'orbiters', part: 'Play', actions: ORBITERS_PLAY_SHORTCUTS }),
|
|
16
|
-
Object.freeze({ id: ORBITERS_STUDIO_SECTION, label: 'Orbiter Studio', app: 'orbiters', part: 'Studio', actions: ORBITERS_STUDIO_SHORTCUTS }),
|
|
17
|
-
Object.freeze({ id: EW_STUDIO_SECTION, label: 'Entangled Worlds studio', app: 'entangled-worlds', part: 'Studio', actions: EW_STUDIO_SHORTCUTS }),
|
|
18
|
-
Object.freeze({ id: EW_PLAYER_SECTION, label: 'Entangled Worlds player', app: 'entangled-worlds', part: 'Player', actions: EW_PLAYER_SHORTCUTS }),
|
|
19
|
-
]);
|
package/dist/shortcuts/site.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { ShortcutAction } from './match.js';
|
|
2
|
-
export type SiteShortcut = ShortcutAction<'client'>;
|
|
3
|
-
export declare const SITE_SECTION = "site";
|
|
4
|
-
/**
|
|
5
|
-
* Two-key sequences move around the site (G, then H for Home; N, then O for a new Orbiter), as on
|
|
6
|
-
* many sites: a single letter is an Orbiter's on a page that plays one, and the browser holds most
|
|
7
|
-
* ⌘ and ⇧⌘ letters.
|
|
8
|
-
*/
|
|
9
|
-
export declare const SITE_SHORTCUTS: readonly SiteShortcut[];
|
package/dist/shortcuts/site.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
// The Plantasia Space site's own keys: the pages around the apps (home, explore, settings). They
|
|
2
|
-
// work on any page of the site, outside an Orbiter or a world.
|
|
3
|
-
export const SITE_SECTION = 'site';
|
|
4
|
-
const site = (id, label, keys) => Object.freeze({ id: `site.${id}`, section: SITE_SECTION, label, defaultKeys: Object.freeze([keys]), scope: 'client' });
|
|
5
|
-
/**
|
|
6
|
-
* Two-key sequences move around the site (G, then H for Home; N, then O for a new Orbiter), as on
|
|
7
|
-
* many sites: a single letter is an Orbiter's on a page that plays one, and the browser holds most
|
|
8
|
-
* ⌘ and ⇧⌘ letters.
|
|
9
|
-
*/
|
|
10
|
-
export const SITE_SHORTCUTS = Object.freeze([
|
|
11
|
-
site('settings', 'Open settings', 'Mod+Shift+Comma'),
|
|
12
|
-
site('commands', 'Commands', 'Mod+KeyK'),
|
|
13
|
-
site('search', 'Search', 'Slash'),
|
|
14
|
-
site('go.home', 'Home', 'KeyG KeyH'),
|
|
15
|
-
site('go.playground', 'Playground', 'KeyG KeyP'),
|
|
16
|
-
site('go.notifications', 'Notifications', 'KeyG KeyN'),
|
|
17
|
-
site('go.audios', 'My audios', 'KeyG KeyA'),
|
|
18
|
-
site('go.orbiters', 'My Orbiters', 'KeyG KeyO'),
|
|
19
|
-
site('go.worlds', 'My Entangled Worlds', 'KeyG KeyW'),
|
|
20
|
-
site('go.collections', 'My collections', 'KeyG KeyC'),
|
|
21
|
-
site('go.stars', 'My stars', 'KeyG KeyS'),
|
|
22
|
-
site('new.orbiter', 'New Orbiter', 'KeyN KeyO'),
|
|
23
|
-
site('new.audio', 'New audio', 'KeyN KeyA'),
|
|
24
|
-
site('new.world', 'New Entangled World', 'KeyN KeyW'),
|
|
25
|
-
]);
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
// The Entangled Worlds catalogues: the studio (where a world's clip is made) and the full-window
|
|
2
|
-
// player. Escape and Enter inside dialogs stay with the dialogs and are not listed here.
|
|
3
|
-
|
|
4
|
-
import type { ShortcutAction } from './match.js'
|
|
5
|
-
|
|
6
|
-
export const EW_STUDIO_SECTION = 'ew-studio'
|
|
7
|
-
export const EW_PLAYER_SECTION = 'ew-player'
|
|
8
|
-
|
|
9
|
-
/** The studio's actions all act on what is open in it; the player has no other scope. */
|
|
10
|
-
export type EntangledWorldsShortcut = ShortcutAction<'studio' | 'player'>
|
|
11
|
-
|
|
12
|
-
const studio = (id: string, label: string, defaultKeys: readonly string[], group: string, command?: false): EntangledWorldsShortcut =>
|
|
13
|
-
Object.freeze({
|
|
14
|
-
id: `ew.studio.${id}`, section: EW_STUDIO_SECTION, label, defaultKeys: Object.freeze([...defaultKeys]), scope: 'studio' as const,
|
|
15
|
-
group, ...(command === false ? { command } : {}),
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
/** How the studio's command menu groups its actions, in its order. */
|
|
19
|
-
export const EW_STUDIO_COMMAND_GROUPS = Object.freeze([
|
|
20
|
-
{ id: 'edit', label: 'Edit' },
|
|
21
|
-
{ id: 'playback', label: 'Playback' },
|
|
22
|
-
{ id: 'steps', label: 'Steps' },
|
|
23
|
-
{ id: 'help', label: 'Help' },
|
|
24
|
-
] as const)
|
|
25
|
-
|
|
26
|
-
export const EW_STUDIO_SHORTCUTS: readonly EntangledWorldsShortcut[] = Object.freeze([
|
|
27
|
-
studio('undo', 'Undo', ['Mod+KeyZ'], 'edit'),
|
|
28
|
-
studio('redo', 'Redo', ['Mod+Shift+KeyZ'], 'edit'),
|
|
29
|
-
studio('duplicate', 'Duplicate the selection', ['Mod+KeyD'], 'edit'),
|
|
30
|
-
studio('copy', 'Copy the selection', ['Mod+KeyC'], 'edit'),
|
|
31
|
-
studio('paste', 'Paste', ['Mod+KeyV'], 'edit'),
|
|
32
|
-
studio('playPause', 'Play or pause', ['Shift?+Space'], 'playback'),
|
|
33
|
-
studio('remove', 'Remove the selection', ['Shift?+Delete', 'Shift?+Backspace'], 'edit'),
|
|
34
|
-
studio('step.audio', 'Audio step', ['Digit1', 'Numpad1'], 'steps'),
|
|
35
|
-
studio('step.animations', 'Animations step', ['Digit2', 'Numpad2'], 'steps'),
|
|
36
|
-
studio('step.third', 'Export step (Release where there is no export)', ['Digit3', 'Numpad3'], 'steps'),
|
|
37
|
-
studio('step.release', 'Release step', ['Digit4', 'Numpad4'], 'steps'),
|
|
38
|
-
studio('help', 'Keyboard shortcuts', ['Shift?+Slash'], 'help'),
|
|
39
|
-
// Opens the menu itself, so the menu does not list it.
|
|
40
|
-
studio('commands', 'Commands', ['Mod+KeyK'], 'help', false),
|
|
41
|
-
])
|
|
42
|
-
|
|
43
|
-
export const EW_PLAYER_SHORTCUTS: readonly EntangledWorldsShortcut[] = Object.freeze([
|
|
44
|
-
Object.freeze({
|
|
45
|
-
id: 'ew.player.playPause',
|
|
46
|
-
section: EW_PLAYER_SECTION,
|
|
47
|
-
label: 'Play or pause',
|
|
48
|
-
defaultKeys: Object.freeze(['Shift?+Alt?+Ctrl?+Meta?+Space']),
|
|
49
|
-
scope: 'player' as const,
|
|
50
|
-
}),
|
|
51
|
-
])
|