diff --git a/apps/client/src/AppRouter.tsx b/apps/client/src/AppRouter.tsx
index 0669c288c..308a52361 100644
--- a/apps/client/src/AppRouter.tsx
+++ b/apps/client/src/AppRouter.tsx
@@ -100,7 +100,7 @@ export default function AppRouter() {
path='teleprompter'
element={
-
+
}
@@ -225,7 +225,11 @@ function PresetView() {
const Component = PresetViewMap[preset.target as OntimeViewPresettable];
return (
-
+
{Component ? : }
);
diff --git a/apps/client/src/common/components/navigation-menu/ViewNavigationMenu.tsx b/apps/client/src/common/components/navigation-menu/ViewNavigationMenu.tsx
index 7bf1f9181..cdc2c869f 100644
--- a/apps/client/src/common/components/navigation-menu/ViewNavigationMenu.tsx
+++ b/apps/client/src/common/components/navigation-menu/ViewNavigationMenu.tsx
@@ -3,7 +3,6 @@ import { memo } from 'react';
import { useSearchParams } from 'react-router';
import { hasCustomParams } from '../../stores/savedViewParams';
-import { useViewHotkeysStore } from '../../stores/viewHotkeys';
import { useViewParamsEditorStore } from '../view-params-editor/viewParamsEditor.store';
import FloatingNavigation from './floating-navigation/FloatingNavigation';
import NavigationMenu from './NavigationMenu';
@@ -14,10 +13,12 @@ interface ViewNavigationMenuProps {
isNavigationLocked?: boolean;
/** prevent showing settings */
suppressSettings?: boolean;
+ /** leave Space to the view, for views which need the key themselves */
+ suppressSpaceHotkey?: boolean;
}
export default memo(ViewNavigationMenu);
-function ViewNavigationMenu({ isNavigationLocked, suppressSettings }: ViewNavigationMenuProps) {
+function ViewNavigationMenu({ isNavigationLocked, suppressSettings, suppressSpaceHotkey }: ViewNavigationMenuProps) {
const [isMenuOpen, menuHandler] = useDisclosure();
const { open: showEditFormDrawer } = useViewParamsEditorStore();
const [searchParams] = useSearchParams();
@@ -27,9 +28,7 @@ function ViewNavigationMenu({ isNavigationLocked, suppressSettings }: ViewNaviga
[
'Space',
() => {
- if (isNavigationLocked) return;
- // a view can take over Space for itself, see viewHotkeys store
- if (useViewHotkeysStore.getState().spaceClaimed) return;
+ if (isNavigationLocked || suppressSpaceHotkey) return;
menuHandler.toggle();
},
{ preventDefault: true },
diff --git a/apps/client/src/common/stores/viewHotkeys.ts b/apps/client/src/common/stores/viewHotkeys.ts
deleted file mode 100644
index 0d74754ce..000000000
--- a/apps/client/src/common/stores/viewHotkeys.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { create } from 'zustand';
-
-interface ViewHotkeysStore {
- /** a view has taken over the Space key and the navigation menu must not react to it */
- spaceClaimed: boolean;
- claimSpace: () => void;
- releaseSpace: () => void;
-}
-
-/**
- * Lets a view take ownership of a hotkey which the view chrome also binds.
- *
- * The navigation menu binds Space at document level, but the teleprompter needs
- * it for playback, which is the convention every prompter and every foot pedal
- * follows. Prop threading does not work here because AppRouter renders
- * ViewNavigationMenu generically for presets, so the claim lives in a store
- * which the view sets on mount and clears on unmount.
- */
-export const useViewHotkeysStore = create((set) => ({
- spaceClaimed: false,
- claimSpace: () => set({ spaceClaimed: true }),
- releaseSpace: () => set({ spaceClaimed: false }),
-}));
diff --git a/apps/client/src/views/teleprompter/useTeleprompterControls.ts b/apps/client/src/views/teleprompter/useTeleprompterControls.ts
index 5d827d785..af98d265a 100644
--- a/apps/client/src/views/teleprompter/useTeleprompterControls.ts
+++ b/apps/client/src/views/teleprompter/useTeleprompterControls.ts
@@ -1,7 +1,6 @@
import { useEffect, useRef } from 'react';
import { useViewParamsEditorStore } from '../../common/components/view-params-editor/viewParamsEditor.store';
-import { useViewHotkeysStore } from '../../common/stores/viewHotkeys';
import { resolveTeleprompterAction } from './teleprompter.keymap';
import type { TeleprompterAction, TeleprompterController } from './teleprompter.types';
@@ -18,22 +17,15 @@ const ignoredTags = new Set(['INPUT', 'TEXTAREA', 'SELECT']);
/**
* Binds the prompter keymap.
*
- * Space is claimed from the navigation menu for the lifetime of the view: it is
- * the universal run/stop key on prompter software and on the centre pedal of
- * every three pedal controller, so the view cannot leave it to the menu.
+ * Space is the universal run/stop key on prompter software and the centre pedal
+ * of every three pedal controller, so this view cannot leave it to the
+ * navigation menu. The routes which render the teleprompter pass
+ * suppressSpaceHotkey to ViewNavigationMenu so the menu stands down.
*/
export function useTeleprompterControls(args: UseTeleprompterControlsArgs) {
const argsRef = useRef(args);
argsRef.current = args;
- const claimSpace = useViewHotkeysStore((state) => state.claimSpace);
- const releaseSpace = useViewHotkeysStore((state) => state.releaseSpace);
-
- useEffect(() => {
- claimSpace();
- return releaseSpace;
- }, [claimSpace, releaseSpace]);
-
useEffect(() => {
function applyAction(action: TeleprompterAction) {
const { controller, onFlip, onFontSize, onResetFontSize, onToggleHelp } = argsRef.current;