825160ee46
Chronological port of every Tauri release commit (v0.11.4 -> v0.15.2)
into the Electron rebuild, plus Discord-style audio handling that goes
beyond the Tauri original.
Highlights:
- All 17 Tauri release commits ported (audio fixes, custom notification
sound, Discord-style chat UX, profile banner, changelog page,
Discord-parity call UX, screen-share echo + re-watch UX, audio-loop
fix).
- Native napi-rs audio-loopback addon with WASAPI process-loopback:
* EXCLUDE_TARGET_PROCESS_TREE for full-screen shares -> peers
never hear themselves echoed back through the capture.
* INCLUDE_TARGET_PROCESS_TREE for window shares -> only the
picked window's audio is captured, not the whole OS mixer
(Discord parity).
* HWND -> PID resolution via Win32 GetWindowThreadProcessId.
- Discord-style screen-source picker (thumbnail grid, screens vs
apps tabs, live-refreshing thumbnails).
- Hash routing fix for packaged builds (file:// can't resolve
BrowserRouter paths).
- Tauri sources removed (apps/desktop/src-tauri).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
83 lines
2.3 KiB
TypeScript
83 lines
2.3 KiB
TypeScript
import { isTauriRuntime } from './globalShortcut';
|
|
|
|
export interface UpdateState {
|
|
available: boolean;
|
|
version: string | null;
|
|
notes: string | null;
|
|
downloading: boolean;
|
|
downloaded: boolean;
|
|
error: string | null;
|
|
}
|
|
|
|
export const IDLE_UPDATE_STATE: UpdateState = {
|
|
available: false,
|
|
version: null,
|
|
notes: null,
|
|
downloading: false,
|
|
downloaded: false,
|
|
error: null,
|
|
};
|
|
|
|
// Module-local flag: main owns the real "pending update" state via
|
|
// electron-updater, but the renderer also needs to refuse installUpdate()
|
|
// calls that weren't preceded by a successful checkForUpdate().
|
|
let hasPendingUpdate = false;
|
|
|
|
export async function checkForUpdate(): Promise<UpdateState> {
|
|
if (!isTauriRuntime()) {
|
|
return { ...IDLE_UPDATE_STATE };
|
|
}
|
|
try {
|
|
const result = await window.electronAPI.checkForUpdate();
|
|
if (!result.available || !result.info) {
|
|
hasPendingUpdate = false;
|
|
return { ...IDLE_UPDATE_STATE };
|
|
}
|
|
hasPendingUpdate = true;
|
|
return {
|
|
available: true,
|
|
version: result.info.version ?? null,
|
|
notes: result.info.releaseNotes ?? null,
|
|
downloading: false,
|
|
downloaded: false,
|
|
error: null,
|
|
};
|
|
} catch (err: unknown) {
|
|
const msg = err instanceof Error ? err.message : String(err);
|
|
const benign =
|
|
/could not fetch a valid release json|network|timed? out|failed to fetch|connection|enotfound|econnreset|etimedout|404/i.test(
|
|
msg,
|
|
);
|
|
if (!benign) {
|
|
console.warn('checkForUpdate failed', err);
|
|
}
|
|
return {
|
|
...IDLE_UPDATE_STATE,
|
|
error: benign ? null : msg,
|
|
};
|
|
}
|
|
}
|
|
|
|
// Downloads + installs the previously checked update. On Windows the
|
|
// app quits during install (passive installer); electron-updater
|
|
// triggers a relaunch on macOS/Linux.
|
|
export async function installUpdate(
|
|
onProgress?: (downloaded: number, total: number | null) => void,
|
|
): Promise<void> {
|
|
if (!hasPendingUpdate) {
|
|
throw new Error('no pending update — call checkForUpdate() first');
|
|
}
|
|
let unsub: (() => void) | null = null;
|
|
if (onProgress) {
|
|
unsub = window.electronAPI.onUpdaterProgress((p) => {
|
|
onProgress(p.transferred, p.total || null);
|
|
});
|
|
}
|
|
try {
|
|
await window.electronAPI.downloadInstallUpdate();
|
|
} finally {
|
|
unsub?.();
|
|
hasPendingUpdate = false;
|
|
}
|
|
}
|