feat(desktop): port v0.11.4-v0.15.2 from Tauri to Electron + Discord-parity audio (v0.16.0)
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>
This commit is contained in:
@@ -1,29 +1,17 @@
|
||||
import {
|
||||
isPermissionGranted,
|
||||
requestPermission,
|
||||
sendNotification,
|
||||
} from '@tauri-apps/plugin-notification';
|
||||
// OS notifications via the Electron preload bridge. The exported API
|
||||
// stays identical to the Tauri-era version so callers don't change.
|
||||
//
|
||||
// Permission under Electron is implicit ('granted' always). The legacy
|
||||
// ASKED marker in localStorage is kept so we don't re-prompt after a
|
||||
// previously-denied run; we just fast-succeed now.
|
||||
|
||||
import { isTauriRuntime } from './globalShortcut';
|
||||
|
||||
// Tracks whether permission has already been requested this session so we
|
||||
// don't spam the OS prompt. Actual permission state lives in the OS, but we
|
||||
// also persist a "we've asked" marker in localStorage so reloads don't
|
||||
// re-request (OS would block anyway after denial, but calling it every reload
|
||||
// triggers noisy plugin warnings on some platforms).
|
||||
let permissionChecked = false;
|
||||
let permissionGranted = false;
|
||||
|
||||
const ASKED_KEY = 'chatapp.notif.asked';
|
||||
|
||||
function readAskedMarker(): boolean {
|
||||
try {
|
||||
return window.localStorage.getItem(ASKED_KEY) === '1';
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function writeAskedMarker(): void {
|
||||
try {
|
||||
window.localStorage.setItem(ASKED_KEY, '1');
|
||||
@@ -36,21 +24,13 @@ export async function ensureNotificationPermission(): Promise<boolean> {
|
||||
if (permissionChecked) return permissionGranted;
|
||||
permissionChecked = true;
|
||||
if (!isTauriRuntime()) {
|
||||
// Web preview / Chrome — Tauri notification plugin not available.
|
||||
permissionGranted = false;
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
let granted = await isPermissionGranted();
|
||||
if (!granted && !readAskedMarker()) {
|
||||
// First-install: prompt the user once. After this we remember via the
|
||||
// marker and never re-prompt — the user can re-enable later via OS
|
||||
// system settings if they change their mind.
|
||||
const result = await requestPermission();
|
||||
granted = result === 'granted';
|
||||
writeAskedMarker();
|
||||
}
|
||||
permissionGranted = granted;
|
||||
const state = await window.electronAPI.getNotificationPermission();
|
||||
permissionGranted = state === 'granted';
|
||||
writeAskedMarker();
|
||||
} catch (err: unknown) {
|
||||
permissionGranted = false;
|
||||
console.warn('notification permission check failed', err);
|
||||
@@ -65,7 +45,7 @@ export function isAppFocused(): boolean {
|
||||
interface NotifyOpts {
|
||||
title: string;
|
||||
body?: string;
|
||||
// Force notification even when app is focused. Default: suppress if focused.
|
||||
/** Force notification even when app is focused. Default: suppress if focused. */
|
||||
force?: boolean;
|
||||
}
|
||||
|
||||
@@ -75,8 +55,12 @@ export async function notify({ title, body, force = false }: NotifyOpts): Promis
|
||||
const granted = await ensureNotificationPermission();
|
||||
if (!granted) return;
|
||||
try {
|
||||
sendNotification({ title, ...(body ? { body } : {}) });
|
||||
await window.electronAPI.notify({
|
||||
title,
|
||||
body: body ?? '',
|
||||
silent: true,
|
||||
});
|
||||
} catch (err: unknown) {
|
||||
console.error('sendNotification failed', err);
|
||||
console.error('notify failed', err);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user