feat(desktop): bundled renderer, modules and instance accounts (#3254)

This commit is contained in:
Hampus authored and GitHub committed 2026-10-07 16:48:07 +02:00
1 parent c748c8af4e
commit 7c5fa2180a
1275 files changed
+215074 -81246

No files matched your search

@@ -1,24 +1,21 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import FocusManager from '@app/features/platform/utils/FocusManager';
import {createWindowFocusInteractionGuard} from '@app/features/ui/utils/WindowFocusInteractionGuard';
import {useActivityRecorder} from '@app/features/voice/hooks/useActivityRecorder';
import * as WindowCommands from '@app/features/window/commands/WindowCommands';
import {useCallback, useEffect} from 'react';
interface WindowEventListenersOptions {
preventDocumentScroll: boolean;
}
export function useWindowEventListeners({preventDocumentScroll}: WindowEventListenersOptions): void {
export function useWindowEventListeners(): void {
const recordActivity = useActivityRecorder();
const handleUserActivity = useCallback(() => recordActivity(), [recordActivity]);
const handleImmediateActivity = useCallback(() => recordActivity(true), [recordActivity]);
const handleResize = useCallback(() => WindowCommands.resized(), []);
useEffect(() => {
FocusManager.init();
const guard = createWindowFocusInteractionGuard({initiallyFocused: document.hasFocus()});
guard.setFocused(document.hasFocus());
WindowCommands.focused(document.hasFocus());
WindowCommands.visibilityChanged(!document.hidden);
WindowCommands.resized();
const handleFocus = () => {
guard.setFocused(true);
WindowCommands.focused(true);
@@ -37,7 +34,6 @@ export function useWindowEventListeners({preventDocumentScroll}: WindowEventList
event.preventDefault();
}
};
const preventScroll = (event: Event) => event.preventDefault();
window.addEventListener('focus', handleFocus);
window.addEventListener('blur', handleBlur);
document.addEventListener('visibilitychange', handleVisibilityChange);
@@ -48,11 +44,7 @@ export function useWindowEventListeners({preventDocumentScroll}: WindowEventList
window.addEventListener('touchstart', handleImmediateActivity);
document.addEventListener('touchstart', preventPinchZoom, {passive: false});
document.addEventListener('touchmove', preventPinchZoom, {passive: false});
if (preventDocumentScroll) {
document.addEventListener('scroll', preventScroll);
}
return () => {
FocusManager.destroy();
guard.destroy();
window.removeEventListener('focus', handleFocus);
window.removeEventListener('blur', handleBlur);
@@ -64,9 +56,6 @@ export function useWindowEventListeners({preventDocumentScroll}: WindowEventList
window.removeEventListener('touchstart', handleImmediateActivity);
document.removeEventListener('touchstart', preventPinchZoom);
document.removeEventListener('touchmove', preventPinchZoom);
if (preventDocumentScroll) {
document.removeEventListener('scroll', preventScroll);
}
};
}, [handleImmediateActivity, handleUserActivity, handleResize, preventDocumentScroll]);
}, [handleImmediateActivity, handleUserActivity, handleResize]);
}
@@ -0,0 +1,49 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import {getElectronAPI} from '@app/features/ui/utils/NativeUtils';
const LIVE_RESIZE_CLASS = 'window-live-resizing';
type Listener = () => void;
let resizing = false;
let started = false;
const listeners = new Set<Listener>();
function applyClass(active: boolean): void {
if (typeof document === 'undefined') return;
document.documentElement.classList.toggle(LIVE_RESIZE_CLASS, active);
}
function setResizing(active: boolean): void {
if (resizing === active) return;
resizing = active;
applyClass(active);
for (const listener of listeners) listener();
}
function start(): void {
if (started) return;
started = true;
const electronApi = getElectronAPI();
if (electronApi?.onWindowLiveResizeChange == null) return;
electronApi.onWindowLiveResizeChange((active) => {
setResizing(active);
});
}
export function startLiveResizeTracking(): void {
start();
}
export function subscribeToLiveResize(listener: Listener): () => void {
start();
listeners.add(listener);
return () => {
listeners.delete(listener);
};
}
export function getLiveResizeSnapshot(): boolean {
return resizing;
}
+6 -12
View File
@@ -31,16 +31,6 @@ class Window {
constructor() {
makeAutoObservable(this, {}, {autoBind: true});
this.initListeners();
}
private initListeners(): void {
window.addEventListener('focus', () => this.setFocused(true));
window.addEventListener('blur', () => this.setFocused(false));
document.addEventListener('visibilitychange', () => {
this.setVisible(!document.hidden);
});
window.addEventListener('resize', () => this.updateWindowSize());
}
setFocused(focused: boolean): void {
@@ -61,8 +51,12 @@ class Window {
}
updateWindowSize(): void {
this.windowSize = getWindowSize();
logger.debug(`Window resized: ${this.windowSize.width}x${this.windowSize.height}`);
const next = getWindowSize();
if (next.width === this.windowSize.width && next.height === this.windowSize.height) {
return;
}
this.windowSize = next;
logger.debug(`Window resized: ${next.width}x${next.height}`);
}
isFocused(): boolean {