Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/desktop/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@
"react-dnd-html5-backend": "^16.0.1",
"react-dom": "19.2.0",
"react-hook-form": "^7.71.1",
"react-hotkeys-hook": "5.2.4",
"react-icons": "^5.5.0",
"react-markdown": "^10.1.0",
"react-mosaic-component": "^6.1.1",
Expand Down
133 changes: 0 additions & 133 deletions apps/desktop/src/lib/trpc/routers/hotkeys/index.ts

This file was deleted.

2 changes: 0 additions & 2 deletions apps/desktop/src/lib/trpc/routers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import { createExtensionsRouter } from "./extensions";
import { createExternalRouter } from "./external";
import { createFilesystemRouter } from "./filesystem";
import { createHostServiceManagerRouter } from "./host-service-manager";
import { createHotkeysRouter } from "./hotkeys";
import { createLanguageServicesRouter } from "./language-services";
import { createMenuRouter } from "./menu";
import { createModelProvidersRouter } from "./model-providers";
Expand Down Expand Up @@ -60,7 +59,6 @@ export const createAppRouter = (
ports: createPortsRouter(),
resourceMetrics: createResourceMetricsRouter(),
menu: createMenuRouter(),
hotkeys: createHotkeysRouter(getWindow),
languageServices: createLanguageServicesRouter(),
external: createExternalRouter(),
settings: createSettingsRouter(),
Expand Down
67 changes: 2 additions & 65 deletions apps/desktop/src/lib/trpc/routers/ui-state/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
import { observable } from "@trpc/server/observable";
import { appState } from "main/lib/app-state";
import type { TabsState, ThemeState } from "main/lib/app-state/schemas";
import { hotkeysEmitter } from "main/lib/hotkeys-events";
import {
buildOverridesFromBindings,
HOTKEYS_STATE_VERSION,
type HotkeysState,
} from "shared/hotkeys";
import { z } from "zod";
import { publicProcedure, router } from "../..";

Expand Down Expand Up @@ -268,15 +261,6 @@ const themeStateSchema = z.object({
systemDarkThemeId: z.string().optional(),
});

const hotkeysStateSchema = z.object({
version: z.number(),
byPlatform: z.object({
darwin: z.record(z.string(), z.string().nullable()).default({}),
win32: z.record(z.string(), z.string().nullable()).default({}),
linux: z.record(z.string(), z.string().nullable()).default({}),
}),
});

/**
* UI State router - manages tabs and theme persistence via lowdb
*/
Expand Down Expand Up @@ -312,58 +296,11 @@ export const createUiStateRouter = () => {
}),
}),

// Hotkeys state procedures
// Legacy hotkeys state (read-only, for one-time migration to localStorage)
hotkeys: router({
get: publicProcedure.query((): HotkeysState => {
get: publicProcedure.query(() => {
return appState.data.hotkeysState;
}),

set: publicProcedure
.input(hotkeysStateSchema)
.mutation(async ({ input }) => {
const version =
input.version === HOTKEYS_STATE_VERSION
? input.version
: HOTKEYS_STATE_VERSION;

const normalized: HotkeysState = {
version,
byPlatform: {
darwin: buildOverridesFromBindings(
input.byPlatform.darwin ?? {},
"darwin",
),
win32: buildOverridesFromBindings(
input.byPlatform.win32 ?? {},
"win32",
),
linux: buildOverridesFromBindings(
input.byPlatform.linux ?? {},
"linux",
),
},
};

appState.data.hotkeysState = normalized;
await appState.write();
hotkeysEmitter.emit("change", {
version: normalized.version,
updatedAt: new Date().toISOString(),
});
return { success: true };
}),

subscribe: publicProcedure.subscription(() => {
return observable<{ version: number; updatedAt: string }>((emit) => {
const onChange = (data: { version: number; updatedAt: string }) => {
emit.next(data);
};
hotkeysEmitter.on("change", onChange);
return () => {
hotkeysEmitter.off("change", onChange);
};
});
}),
}),
});
};
14 changes: 11 additions & 3 deletions apps/desktop/src/main/lib/app-state/schemas.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/**
* UI state schemas (persisted from renderer zustand stores)
*/
import { createDefaultHotkeysState, type HotkeysState } from "shared/hotkeys";
import type { BaseTabsState } from "shared/tabs-types";
import type { Theme } from "shared/themes";

Expand All @@ -15,10 +14,16 @@ export interface ThemeState {
systemDarkThemeId?: string;
}

/** Legacy hotkeys state shape (kept for reading old app-state.json during migration) */
interface LegacyHotkeysState {
version: number;
byPlatform: Record<string, Record<string, string | null>>;
}

export interface AppState {
tabsState: BaseTabsState;
themeState: ThemeState;
hotkeysState: HotkeysState;
hotkeysState: LegacyHotkeysState;
}

export const defaultAppState: AppState = {
Expand All @@ -35,5 +40,8 @@ export const defaultAppState: AppState = {
systemLightThemeId: "light",
systemDarkThemeId: "dark",
},
hotkeysState: createDefaultHotkeysState(),
hotkeysState: {
version: 1,
byPlatform: { darwin: {}, win32: {}, linux: {} },
},
};
8 changes: 0 additions & 8 deletions apps/desktop/src/main/lib/hotkeys-events.ts

This file was deleted.

40 changes: 6 additions & 34 deletions apps/desktop/src/main/lib/menu.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
import { COMPANY } from "@superset/shared/constants";
import { app, BrowserWindow, Menu, shell, webContents } from "electron";
import { env } from "main/env.main";
import { appState } from "main/lib/app-state";
import { hotkeysEmitter } from "main/lib/hotkeys-events";
import { resetTerminalStateDev } from "main/lib/terminal/dev-reset";
import type { BrowserShortcutAction } from "shared/browser-shortcuts";
import {
getCurrentPlatform,
getEffectiveHotkey,
type HotkeyId,
toElectronAccelerator,
} from "shared/hotkeys";
import {
checkForUpdatesInteractive,
simulateDownloading,
Expand All @@ -19,8 +11,6 @@ import {
} from "./auto-updater";
import { menuEmitter } from "./menu-events";

let isHotkeyListenerRegistered = false;

function getFocusedWebview() {
return webContents
.getAllWebContents()
Expand All @@ -41,31 +31,13 @@ function triggerBrowserShortcut(action: BrowserShortcutAction) {
menuEmitter.emit("browser-action", action);
}

function getMenuAccelerator(id: HotkeyId): string | undefined {
const platform = getCurrentPlatform();
const overrides = appState.data.hotkeysState.byPlatform[platform];
const keys = getEffectiveHotkey(id, overrides, platform);
const accelerator = toElectronAccelerator(keys, platform);
return accelerator ?? undefined;
}

export function registerMenuHotkeyUpdates() {
if (isHotkeyListenerRegistered) return;
isHotkeyListenerRegistered = true;
hotkeysEmitter.on("change", () => {
createApplicationMenu();
});
}

export function createApplicationMenu() {
const reloadAccelerator = getMenuAccelerator("RELOAD_WINDOW");
const browserReloadAccelerator = getMenuAccelerator("BROWSER_RELOAD");
const browserHardReloadAccelerator = getMenuAccelerator(
"BROWSER_HARD_RELOAD",
);
const closeAccelerator = getMenuAccelerator("CLOSE_WINDOW");
const showHotkeysAccelerator = getMenuAccelerator("SHOW_HOTKEYS");
const openSettingsAccelerator = getMenuAccelerator("OPEN_SETTINGS");
const reloadAccelerator = "CmdOrCtrl+R";
const browserReloadAccelerator = "CmdOrCtrl+Alt+R";
const browserHardReloadAccelerator = "CmdOrCtrl+Shift+Alt+R";
const closeAccelerator = "CmdOrCtrl+Shift+Q";
const showHotkeysAccelerator = "CmdOrCtrl+/";
const openSettingsAccelerator = "CmdOrCtrl+,";

const template: Electron.MenuItemConstructorOptions[] = [
{
Expand Down
3 changes: 1 addition & 2 deletions apps/desktop/src/main/windows/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { createIPCHandler } from "trpc-electron/main";
import { productName } from "~/package.json";
import { appState } from "../lib/app-state";
import { browserManager } from "../lib/browser/browser-manager";
import { createApplicationMenu, registerMenuHotkeyUpdates } from "../lib/menu";
import { createApplicationMenu } from "../lib/menu";
import { playNotificationSound } from "../lib/notification-sound";
import { NotificationManager } from "../lib/notifications/notification-manager";
import {
Expand Down Expand Up @@ -165,7 +165,6 @@ export async function MainWindow() {
});

createApplicationMenu();
registerMenuHotkeyUpdates();

currentWindow = window;
windowManager.register("main", window);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import type React from "react";
import type { ReactNode } from "react";
import { useCallback, useRef, useState } from "react";
import { useFocusPromptOnPane } from "renderer/components/Chat/ChatInterface/hooks/useFocusPromptOnPane";
import { useHotkeyText } from "renderer/stores/hotkeys";
import { useHotkeyDisplay } from "renderer/hotkeys";
import type { SlashCommand } from "../../hooks/useSlashCommands";
import type { ModelOption, PermissionMode } from "../../types";
import { IssueLinkCommand } from "../IssueLinkCommand";
Expand Down Expand Up @@ -80,7 +80,7 @@ export function ChatInputFooter({
const [linkedIssues, setLinkedIssues] = useState<LinkedIssue[]>([]);
const inputRootRef = useRef<HTMLDivElement>(null);
const errorMessage = getErrorMessage(error);
const focusShortcutText = useHotkeyText("FOCUS_CHAT_INPUT");
const focusShortcutText = useHotkeyDisplay("FOCUS_CHAT_INPUT").text;
const showFocusHint = focusShortcutText !== "Unassigned";

const addLinkedIssue = useCallback(
Expand Down
Loading