diff --git a/apps/desktop/src/main.ts b/apps/desktop/src/main.ts
index 2c9aa9feef0009de69fd06b91d2c0aeccb634539..107371cc16ebe5782a99fad33f13488604fc2504 100644
--- a/apps/desktop/src/main.ts
+++ b/apps/desktop/src/main.ts
@@ -10,13 +10,11 @@ import type { MenuItemConstructorOptions } from "electron";
import { showDesktopConfirmDialog } from "./confirmDialog";
import { fixPath } from "./fixPath";
-import { showDesktopPromptDialog } from "./promptDialog";
fixPath();
const PICK_FOLDER_CHANNEL = "desktop:pick-folder";
const CONFIRM_CHANNEL = "desktop:confirm";
-const PROMPT_CHANNEL = "desktop:prompt";
const CONTEXT_MENU_CHANNEL = "desktop:context-menu";
const OPEN_EXTERNAL_CHANNEL = "desktop:open-external";
const MENU_ACTION_CHANNEL = "desktop:menu-action";
@@ -436,20 +434,6 @@ function registerIpcHandlers(): void {
return showDesktopConfirmDialog(message, owner);
});
- ipcMain.removeHandler(PROMPT_CHANNEL);
- ipcMain.handle(PROMPT_CHANNEL, async (_event, message: unknown, defaultValue: unknown) => {
- if (typeof message !== "string") {
- return null;
- }
-
- const owner = BrowserWindow.getFocusedWindow() ?? mainWindow;
- return showDesktopPromptDialog(
- message,
- typeof defaultValue === "string" ? defaultValue : "",
- owner,
- );
- });
-
ipcMain.removeHandler(CONTEXT_MENU_CHANNEL);
ipcMain.handle(
CONTEXT_MENU_CHANNEL,
diff --git a/apps/desktop/src/preload.ts b/apps/desktop/src/preload.ts
index c251075e86844c8f58f4e1e03d25ccb574df4ec6..be8fbbddd82cb5654dd51172215965fbf4c47f40 100644
--- a/apps/desktop/src/preload.ts
+++ b/apps/desktop/src/preload.ts
@@ -3,7 +3,6 @@ import type { DesktopBridge } from "@t3tools/contracts";
const PICK_FOLDER_CHANNEL = "desktop:pick-folder";
const CONFIRM_CHANNEL = "desktop:confirm";
-const PROMPT_CHANNEL = "desktop:prompt";
const CONTEXT_MENU_CHANNEL = "desktop:context-menu";
const OPEN_EXTERNAL_CHANNEL = "desktop:open-external";
const MENU_ACTION_CHANNEL = "desktop:menu-action";
@@ -13,7 +12,6 @@ contextBridge.exposeInMainWorld("desktopBridge", {
getWsUrl: () => wsUrl,
pickFolder: () => ipcRenderer.invoke(PICK_FOLDER_CHANNEL),
confirm: (message) => ipcRenderer.invoke(CONFIRM_CHANNEL, message),
- prompt: (message, defaultValue) => ipcRenderer.invoke(PROMPT_CHANNEL, message, defaultValue),
showContextMenu: (items, position) => ipcRenderer.invoke(CONTEXT_MENU_CHANNEL, items, position),
openExternal: (url: string) => ipcRenderer.invoke(OPEN_EXTERNAL_CHANNEL, url),
onMenuAction: (listener) => {
diff --git a/apps/desktop/src/promptDialog.ts b/apps/desktop/src/promptDialog.ts
deleted file mode 100644
index 81f14dfcaf39c4a4fb966749a2cf440628aef557..0000000000000000000000000000000000000000
--- a/apps/desktop/src/promptDialog.ts
+++ /dev/null
@@ -1,231 +0,0 @@
-import { randomBytes } from "node:crypto";
-import { BrowserWindow, ipcMain } from "electron";
-
-const PROMPT_WIDTH = 420;
-const PROMPT_HEIGHT = 188;
-
-function createPromptHtml(input: {
- message: string;
- defaultValue: string;
- submitChannel: string;
- cancelChannel: string;
-}): string {
- const scriptConfig = JSON.stringify(input);
- return `
-
-
-
-
- ${input.message}
-
-
-
-
-
-
-
-`;
-}
-
-export async function showDesktopPromptDialog(
- message: string,
- defaultValue: string,
- ownerWindow: BrowserWindow | null,
-): Promise {
- const normalizedMessage = message.trim();
- if (normalizedMessage.length === 0) {
- return null;
- }
-
- const token = randomBytes(12).toString("hex");
- const submitChannel = `desktop:prompt-dialog:submit:${token}`;
- const cancelChannel = `desktop:prompt-dialog:cancel:${token}`;
-
- const promptWindow = new BrowserWindow({
- width: PROMPT_WIDTH,
- height: PROMPT_HEIGHT,
- useContentSize: true,
- show: false,
- resizable: false,
- minimizable: false,
- maximizable: false,
- fullscreenable: false,
- autoHideMenuBar: true,
- title: normalizedMessage,
- ...(ownerWindow ? { parent: ownerWindow } : {}),
- modal: ownerWindow !== null,
- webPreferences: {
- nodeIntegration: true,
- contextIsolation: false,
- },
- });
- promptWindow.removeMenu();
-
- return new Promise((resolve) => {
- let settled = false;
-
- const settle = (value: string | null) => {
- if (settled) return;
- settled = true;
- cleanup();
- resolve(value);
- };
-
- const cleanup = () => {
- ipcMain.removeAllListeners(submitChannel);
- ipcMain.removeAllListeners(cancelChannel);
- if (!promptWindow.isDestroyed()) {
- promptWindow.destroy();
- }
- };
-
- ipcMain.once(submitChannel, (_event, value: unknown) => {
- if (typeof value !== "string") {
- settle(null);
- return;
- }
- settle(value);
- });
- ipcMain.once(cancelChannel, () => settle(null));
- promptWindow.once("closed", () => settle(null));
-
- const html = createPromptHtml({
- message: normalizedMessage,
- defaultValue,
- submitChannel,
- cancelChannel,
- });
- void promptWindow
- .loadURL(`data:text/html;charset=utf-8,${encodeURIComponent(html)}`)
- .then(() => {
- if (!promptWindow.isDestroyed()) {
- promptWindow.show();
- }
- })
- .catch(() => settle(null));
- });
-}
diff --git a/apps/web/src/wsNativeApi.test.ts b/apps/web/src/wsNativeApi.test.ts
index 4e4f61e6d2217e931180120fa8265c61460c337d..80e283ee40fbe6630285ea7238876eb0963426fa 100644
--- a/apps/web/src/wsNativeApi.test.ts
+++ b/apps/web/src/wsNativeApi.test.ts
@@ -68,7 +68,6 @@ beforeEach(() => {
subscribeMock.mockClear();
channelListeners.clear();
Reflect.deleteProperty(getWindowForTest(), "desktopBridge");
- Reflect.deleteProperty(getWindowForTest(), "prompt");
});
afterEach(() => {
@@ -377,37 +376,4 @@ describe("wsNativeApi", () => {
);
});
- it("forwards prompt calls to desktop bridge", async () => {
- const prompt = vi.fn().mockResolvedValue("renamed");
- Object.defineProperty(getWindowForTest(), "desktopBridge", {
- configurable: true,
- writable: true,
- value: {
- prompt,
- },
- });
-
- const { createWsNativeApi } = await import("./wsNativeApi");
- const api = createWsNativeApi();
- const value = await api.dialogs.prompt("Rename thread", "Old title");
-
- expect(value).toBe("renamed");
- expect(prompt).toHaveBeenCalledWith("Rename thread", "Old title");
- });
-
- it("uses browser prompt fallback when desktop bridge is unavailable", async () => {
- const prompt = vi.fn().mockReturnValue("renamed");
- Object.defineProperty(getWindowForTest(), "prompt", {
- configurable: true,
- writable: true,
- value: prompt,
- });
-
- const { createWsNativeApi } = await import("./wsNativeApi");
- const api = createWsNativeApi();
- const value = await api.dialogs.prompt("Rename thread", "Old title");
-
- expect(value).toBe("renamed");
- expect(prompt).toHaveBeenCalledWith("Rename thread", "Old title");
- });
});
diff --git a/apps/web/src/wsNativeApi.ts b/apps/web/src/wsNativeApi.ts
index aa6830022b91daa126c6c72091d40708ef7d2cd6..871e01c911126daee8a492a33ec57fff44c42d82 100644
--- a/apps/web/src/wsNativeApi.ts
+++ b/apps/web/src/wsNativeApi.ts
@@ -124,16 +124,6 @@ export function createWsNativeApi(): NativeApi {
}
return window.confirm(message);
},
- prompt: async (message, defaultValue) => {
- if (window.desktopBridge) {
- return window.desktopBridge.prompt(message, defaultValue);
- }
- try {
- return window.prompt(message, defaultValue ?? "");
- } catch {
- return null;
- }
- },
},
terminal: {
open: (input) => transport.request(WS_METHODS.terminalOpen, input),
diff --git a/packages/contracts/src/ipc.ts b/packages/contracts/src/ipc.ts
index bf12d8cb5d8be47bb388edeebd7de6af74e538e2..aeec16ca0c32c9bee0d9b1f3c481e0917ac7587f 100644
--- a/packages/contracts/src/ipc.ts
+++ b/packages/contracts/src/ipc.ts
@@ -47,7 +47,6 @@ export interface DesktopBridge {
getWsUrl: () => string | null;
pickFolder: () => Promise;
confirm: (message: string) => Promise;
- prompt: (message: string, defaultValue?: string) => Promise;
showContextMenu: (
items: readonly ContextMenuItem[],
position?: { x: number; y: number },
@@ -60,7 +59,6 @@ export interface NativeApi {
dialogs: {
pickFolder: () => Promise;
confirm: (message: string) => Promise;
- prompt: (message: string, defaultValue?: string) => Promise;
};
terminal: {
open: (input: TerminalOpenInput) => Promise;