refactor: remove legacy Tauri desktop support

Electron updater now uses Electron release metadata only
Removed legacy Tauri package and migration workflow
Replaced Tauri shim usage with the desktop bridge
This commit is contained in:
Bohdan Triapitsyn
2026-06-03 02:42:00 +03:00
parent e80bd15dd9
commit c7bc026b4b
81 changed files with 269 additions and 16914 deletions
+66 -92
View File
@@ -185,19 +185,14 @@ export type DesktopSettings = {
draftStarters?: DraftStarterRef[];
};
type TauriGlobal = {
core?: {
invoke?: (cmd: string, args?: Record<string, unknown>) => Promise<unknown>;
};
dialog?: {
open?: (options: Record<string, unknown>) => Promise<unknown>;
};
event?: {
listen?: (
event: string,
handler: (evt: { payload?: unknown }) => void,
) => Promise<() => void>;
};
type DesktopBridgeGlobal = {
invoke?: (cmd: string, args?: Record<string, unknown>) => Promise<unknown>;
openDialog?: (options: Record<string, unknown>) => Promise<unknown>;
openExternal?: (url: string) => Promise<unknown>;
listen?: (
event: string,
handler: (evt: { payload?: unknown }) => void,
) => Promise<() => void>;
};
type ElectronRuntimeGlobal = {
@@ -209,27 +204,23 @@ const getElectronRuntime = (): ElectronRuntimeGlobal | null => {
return (window as unknown as { __OPENCHAMBER_ELECTRON__?: ElectronRuntimeGlobal }).__OPENCHAMBER_ELECTRON__ ?? null;
};
export const isTauriShell = (): boolean => {
if (typeof window === 'undefined') return false;
const tauri = (window as unknown as { __TAURI__?: TauriGlobal }).__TAURI__;
return typeof tauri?.core?.invoke === 'function';
const getDesktopBridge = (): DesktopBridgeGlobal | null => {
if (typeof window === 'undefined') return null;
return (window as unknown as { __OPENCHAMBER_DESKTOP__?: DesktopBridgeGlobal }).__OPENCHAMBER_DESKTOP__ ?? null;
};
export const isElectronShell = (): boolean => getElectronRuntime()?.runtime === 'electron';
export const hasDesktopInvoke = (): boolean => {
if (typeof window === 'undefined') return false;
const tauri = (window as unknown as { __TAURI__?: TauriGlobal }).__TAURI__;
return typeof tauri?.core?.invoke === 'function';
return typeof getDesktopBridge()?.invoke === 'function';
};
export const canUseElectronDesktopIPC = (): boolean => isElectronShell() && hasDesktopInvoke();
export const invokeDesktop = async <T = unknown>(command: string, args?: Record<string, unknown>): Promise<T | null> => {
if (typeof window === 'undefined') return null;
const tauri = (window as unknown as { __TAURI__?: TauriGlobal }).__TAURI__;
if (typeof tauri?.core?.invoke !== 'function') return null;
return tauri.core.invoke(command, args ?? {}) as Promise<T>;
const bridge = getDesktopBridge();
if (typeof bridge?.invoke !== 'function') return null;
return bridge.invoke(command, args ?? {}) as Promise<T>;
};
type LaunchAtLoginStatus = {
@@ -367,18 +358,16 @@ export const isDesktopLocalOriginActive = (): boolean => {
export const isDesktopShell = (): boolean => {
if (typeof window === 'undefined') return false;
return isTauriShell() || isElectronShell();
return isElectronShell();
};
export const startDesktopWindowDrag = async (): Promise<boolean> => {
if (!isDesktopShell() || !isTauriShell()) {
if (!isDesktopShell()) {
return false;
}
try {
const { getCurrentWindow } = await import('@tauri-apps/api/window');
const appWindow = getCurrentWindow();
await appWindow.startDragging();
await invokeDesktop('desktop_start_window_drag');
return true;
} catch {
return false;
@@ -418,10 +407,9 @@ export const requestDirectoryAccess = async (
directoryPath: string
): Promise<{ success: boolean; path?: string; projectId?: string; error?: string }> => {
// Desktop shell on local instance: use native folder picker.
if (isTauriShell() && isDesktopLocalOriginActive()) {
if (hasDesktopInvoke() && isDesktopLocalOriginActive()) {
try {
const tauri = (window as unknown as { __TAURI__?: TauriGlobal }).__TAURI__;
const selected = await tauri?.dialog?.open?.({
const selected = await getDesktopBridge()?.openDialog?.({
directory: true,
multiple: false,
title: 'Select Working Directory',
@@ -431,7 +419,7 @@ export const requestDirectoryAccess = async (
}
return { success: true, path: selected };
} catch (error) {
console.warn('Failed to request directory access (tauri)', error);
console.warn('Failed to request directory access', error);
return { success: false, error: error instanceof Error ? error.message : String(error) };
}
}
@@ -442,10 +430,9 @@ export const requestDirectoryAccess = async (
export const requestFileAccess = async (
options?: { filters?: Array<{ name: string; extensions: string[] }>; defaultPath?: string }
): Promise<{ success: boolean; path?: string; error?: string }> => {
if (isTauriShell() && isDesktopLocalOriginActive()) {
if (hasDesktopInvoke() && isDesktopLocalOriginActive()) {
try {
const tauri = (window as unknown as { __TAURI__?: TauriGlobal }).__TAURI__;
const selected = await tauri?.dialog?.open?.({
const selected = await getDesktopBridge()?.openDialog?.({
directory: false,
multiple: false,
title: 'Select File',
@@ -457,7 +444,7 @@ export const requestFileAccess = async (
}
return { success: true, path: selected };
} catch (error) {
console.warn('Failed to request file access (tauri)', error);
console.warn('Failed to request file access', error);
return { success: false, error: error instanceof Error ? error.message : String(error) };
}
}
@@ -482,10 +469,9 @@ export const stopAccessingDirectory = async (
export const sendAssistantCompletionNotification = async (
payload?: AssistantNotificationPayload
): Promise<boolean> => {
if (isTauriShell()) {
if (hasDesktopInvoke()) {
try {
const tauri = (window as unknown as { __TAURI__?: TauriGlobal }).__TAURI__;
await tauri?.core?.invoke?.('desktop_notify', {
await invokeDesktop('desktop_notify', {
payload: {
title: payload?.title,
body: payload?.body,
@@ -494,7 +480,7 @@ export const sendAssistantCompletionNotification = async (
});
return true;
} catch (error) {
console.warn('Failed to send assistant completion notification (tauri)', error);
console.warn('Failed to send assistant completion notification', error);
return false;
}
}
@@ -503,16 +489,15 @@ export const sendAssistantCompletionNotification = async (
};
export const checkForDesktopUpdates = async (): Promise<UpdateInfo | null> => {
if (!isTauriShell()) {
if (!hasDesktopInvoke()) {
return null;
}
try {
const tauri = (window as unknown as { __TAURI__?: TauriGlobal }).__TAURI__;
const info = await tauri?.core?.invoke?.('desktop_check_for_updates');
const info = await invokeDesktop<UpdateInfo>('desktop_check_for_updates');
return info as UpdateInfo;
} catch (error) {
console.warn('Failed to check for updates (tauri)', error);
console.warn('Failed to check for updates', error);
return null;
}
};
@@ -520,18 +505,18 @@ export const checkForDesktopUpdates = async (): Promise<UpdateInfo | null> => {
export const downloadDesktopUpdate = async (
onProgress?: (progress: UpdateProgress) => void
): Promise<boolean> => {
if (!isTauriShell()) {
if (!hasDesktopInvoke()) {
return false;
}
const tauri = (window as unknown as { __TAURI__?: TauriGlobal }).__TAURI__;
const bridge = getDesktopBridge();
let unlisten: null | (() => void | Promise<void>) = null;
let downloaded = 0;
let total: number | undefined;
try {
if (typeof onProgress === 'function' && tauri?.event?.listen) {
unlisten = await tauri.event.listen('openchamber:update-progress', (evt) => {
if (typeof onProgress === 'function' && bridge?.listen) {
unlisten = await bridge.listen('openchamber:update-progress', (evt) => {
const payload = evt?.payload;
if (!payload || typeof payload !== 'object') return;
const data = payload as { event?: unknown; data?: unknown };
@@ -560,10 +545,10 @@ export const downloadDesktopUpdate = async (
});
}
await tauri?.core?.invoke?.('desktop_download_and_install_update');
await invokeDesktop('desktop_download_and_install_update');
return true;
} catch (error) {
console.warn('Failed to download update (tauri)', error);
console.warn('Failed to download update', error);
return false;
} finally {
if (unlisten) {
@@ -580,7 +565,7 @@ export const downloadDesktopUpdate = async (
};
export const restartToApplyUpdate = async (): Promise<boolean> => {
if (!isTauriShell()) {
if (!hasDesktopInvoke()) {
return false;
}
@@ -588,37 +573,35 @@ export const restartToApplyUpdate = async (): Promise<boolean> => {
};
export const restartDesktopApp = async (): Promise<boolean> => {
if (!isTauriShell()) {
if (!hasDesktopInvoke()) {
return false;
}
try {
const tauri = (window as unknown as { __TAURI__?: TauriGlobal }).__TAURI__;
await tauri?.core?.invoke?.('desktop_restart');
await invokeDesktop('desktop_restart');
return true;
} catch (error) {
console.warn('Failed to restart desktop app (tauri)', error);
console.warn('Failed to restart desktop app', error);
return false;
}
};
export const getDesktopLanAddress = async (): Promise<string | null> => {
if (!isTauriShell() || !isDesktopLocalOriginActive()) {
if (!hasDesktopInvoke() || !isDesktopLocalOriginActive()) {
return null;
}
try {
const tauri = (window as unknown as { __TAURI__?: TauriGlobal }).__TAURI__;
const result = await tauri?.core?.invoke?.('desktop_get_lan_address');
const result = await invokeDesktop<string>('desktop_get_lan_address');
return typeof result === 'string' && result.trim().length > 0 ? result.trim() : null;
} catch (error) {
console.warn('Failed to get desktop LAN address (tauri)', error);
console.warn('Failed to get desktop LAN address', error);
return null;
}
};
export const openDesktopPath = async (path: string, app?: string | null): Promise<boolean> => {
if (!isTauriShell() || !isDesktopLocalOriginActive()) {
if (!hasDesktopInvoke() || !isDesktopLocalOriginActive()) {
return false;
}
@@ -628,20 +611,19 @@ export const openDesktopPath = async (path: string, app?: string | null): Promis
}
try {
const tauri = (window as unknown as { __TAURI__?: TauriGlobal }).__TAURI__;
await tauri?.core?.invoke?.('desktop_open_path', {
await invokeDesktop('desktop_open_path', {
path: trimmed,
app: typeof app === 'string' && app.trim().length > 0 ? app.trim() : undefined,
});
return true;
} catch (error) {
console.warn('Failed to open path (tauri)', error);
console.warn('Failed to open path', error);
return false;
}
};
export const revealDesktopPath = async (path: string): Promise<boolean> => {
if (!isTauriShell() || !isDesktopLocalOriginActive()) {
if (!hasDesktopInvoke() || !isDesktopLocalOriginActive()) {
return false;
}
@@ -651,8 +633,7 @@ export const revealDesktopPath = async (path: string): Promise<boolean> => {
}
try {
const tauri = (window as unknown as { __TAURI__?: TauriGlobal }).__TAURI__;
await tauri?.core?.invoke?.('desktop_reveal_path', {
await invokeDesktop('desktop_reveal_path', {
path: trimmed,
});
return true;
@@ -665,7 +646,7 @@ export const saveDesktopMarkdownFile = async (
defaultFileName: string,
content: string,
): Promise<string | null> => {
if (!isTauriShell() || !isDesktopLocalOriginActive()) {
if (!hasDesktopInvoke() || !isDesktopLocalOriginActive()) {
return null;
}
@@ -675,14 +656,13 @@ export const saveDesktopMarkdownFile = async (
}
try {
const tauri = (window as unknown as { __TAURI__?: TauriGlobal }).__TAURI__;
const result = await tauri?.core?.invoke?.('desktop_save_markdown_file', {
const result = await invokeDesktop<string>('desktop_save_markdown_file', {
defaultFileName: trimmedFileName,
content,
});
return typeof result === 'string' && result.trim().length > 0 ? result : null;
} catch (error) {
console.warn('Failed to save markdown file (tauri)', error);
console.warn('Failed to save markdown file', error);
return null;
}
};
@@ -692,7 +672,7 @@ export const openDesktopProjectInApp = async (
appId: string,
appName: string,
): Promise<boolean> => {
if (!isTauriShell() || !isDesktopLocalOriginActive()) {
if (!hasDesktopInvoke() || !isDesktopLocalOriginActive()) {
return false;
}
@@ -705,8 +685,7 @@ export const openDesktopProjectInApp = async (
}
try {
const tauri = (window as unknown as { __TAURI__?: TauriGlobal }).__TAURI__;
await tauri?.core?.invoke?.('desktop_open_in_app', {
await invokeDesktop('desktop_open_in_app', {
projectPath: trimmedProjectPath,
appId: trimmedAppId,
appName: trimmedAppName,
@@ -723,7 +702,7 @@ export const openDesktopFileInApp = async (
appId: string,
appName: string,
): Promise<boolean> => {
if (!isTauriShell() || !isDesktopLocalOriginActive()) {
if (!hasDesktopInvoke() || !isDesktopLocalOriginActive()) {
return false;
}
@@ -736,8 +715,7 @@ export const openDesktopFileInApp = async (
}
try {
const tauri = (window as unknown as { __TAURI__?: TauriGlobal }).__TAURI__;
await tauri?.core?.invoke?.('desktop_open_file_in_app', {
await invokeDesktop('desktop_open_file_in_app', {
filePath: trimmedFilePath,
appId: trimmedAppId,
appName: trimmedAppName,
@@ -750,7 +728,7 @@ export const openDesktopFileInApp = async (
};
export const filterInstalledDesktopApps = async (apps: string[]): Promise<string[]> => {
if (!isTauriShell() || !isDesktopLocalOriginActive()) {
if (!hasDesktopInvoke() || !isDesktopLocalOriginActive()) {
return [];
}
@@ -760,19 +738,18 @@ export const filterInstalledDesktopApps = async (apps: string[]): Promise<string
}
try {
const tauri = (window as unknown as { __TAURI__?: TauriGlobal }).__TAURI__;
const result = await tauri?.core?.invoke?.('desktop_filter_installed_apps', {
const result = await invokeDesktop<string[]>('desktop_filter_installed_apps', {
apps: candidate,
});
return Array.isArray(result) ? result.filter((value) => typeof value === 'string') : [];
} catch (error) {
console.warn('Failed to check installed apps (tauri)', error);
console.warn('Failed to check installed apps', error);
return [];
}
};
export const fetchDesktopAppIcons = async (apps: string[]): Promise<Record<string, string>> => {
if (!isTauriShell() || !isDesktopLocalOriginActive()) {
if (!hasDesktopInvoke() || !isDesktopLocalOriginActive()) {
return {};
}
@@ -782,8 +759,7 @@ export const fetchDesktopAppIcons = async (apps: string[]): Promise<Record<strin
}
try {
const tauri = (window as unknown as { __TAURI__?: TauriGlobal }).__TAURI__;
const result = await tauri?.core?.invoke?.('desktop_fetch_app_icons', {
const result = await invokeDesktop<unknown[]>('desktop_fetch_app_icons', {
apps: candidate,
});
if (!Array.isArray(result)) {
@@ -798,7 +774,7 @@ export const fetchDesktopAppIcons = async (apps: string[]): Promise<Record<strin
}
return map;
} catch (error) {
console.warn('Failed to fetch installed app icons (tauri)', error);
console.warn('Failed to fetch installed app icons', error);
return {};
}
};
@@ -819,7 +795,7 @@ export const fetchDesktopInstalledApps = async (
apps: string[],
force?: boolean
): Promise<FetchDesktopInstalledAppsResult> => {
if (!isTauriShell() || !isDesktopLocalOriginActive()) {
if (!hasDesktopInvoke() || !isDesktopLocalOriginActive()) {
return { apps: [], success: false, hasCache: false, isCacheStale: false };
}
@@ -829,8 +805,7 @@ export const fetchDesktopInstalledApps = async (
}
try {
const tauri = (window as unknown as { __TAURI__?: TauriGlobal }).__TAURI__;
const result = await tauri?.core?.invoke?.('desktop_get_installed_apps', {
const result = await invokeDesktop<unknown>('desktop_get_installed_apps', {
apps: candidate,
force: force === true ? true : undefined,
});
@@ -858,19 +833,18 @@ export const fetchDesktopInstalledApps = async (
isCacheStale: payload.isCacheStale === true,
};
} catch (error) {
console.warn('Failed to fetch installed apps (tauri)', error);
console.warn('Failed to fetch installed apps', error);
return { apps: [], success: false, hasCache: false, isCacheStale: false };
}
};
export const clearDesktopCache = async (): Promise<boolean> => {
if (!isTauriShell() || !isDesktopLocalOriginActive()) {
if (!hasDesktopInvoke() || !isDesktopLocalOriginActive()) {
return false;
}
try {
const tauri = (window as unknown as { __TAURI__?: TauriGlobal }).__TAURI__;
await tauri?.core?.invoke?.('desktop_clear_cache');
await invokeDesktop('desktop_clear_cache');
return true;
} catch (error) {
console.warn('Failed to clear cache', error);