Set up the complete project foundation for ClawX, a graphical AI assistant: - Electron main process with IPC handlers, menu, tray, and gateway management - React renderer with routing, layout components, and page scaffolding - Zustand state management for gateway, settings, channels, skills, chat, and cron - shadcn/ui components with Tailwind CSS and CSS variable theming - Build tooling with Vite, electron-builder, and TypeScript configuration - Testing setup with Vitest and Playwright - Development configurations (ESLint, Prettier, gitignore, env example)
85 lines
1.8 KiB
TypeScript
85 lines
1.8 KiB
TypeScript
/**
|
|
* Window Management Utilities
|
|
* Handles window state persistence and multi-window management
|
|
*/
|
|
import { BrowserWindow, screen } from 'electron';
|
|
import Store from 'electron-store';
|
|
|
|
interface WindowState {
|
|
x?: number;
|
|
y?: number;
|
|
width: number;
|
|
height: number;
|
|
isMaximized: boolean;
|
|
}
|
|
|
|
const store = new Store<{ windowState: WindowState }>({
|
|
name: 'window-state',
|
|
defaults: {
|
|
windowState: {
|
|
width: 1280,
|
|
height: 800,
|
|
isMaximized: false,
|
|
},
|
|
},
|
|
});
|
|
|
|
/**
|
|
* Get saved window state with bounds validation
|
|
*/
|
|
export function getWindowState(): WindowState {
|
|
const state = store.get('windowState');
|
|
|
|
// Validate that the window is visible on a screen
|
|
if (state.x !== undefined && state.y !== undefined) {
|
|
const displays = screen.getAllDisplays();
|
|
const isVisible = displays.some((display) => {
|
|
const { x, y, width, height } = display.bounds;
|
|
return (
|
|
state.x! >= x &&
|
|
state.x! < x + width &&
|
|
state.y! >= y &&
|
|
state.y! < y + height
|
|
);
|
|
});
|
|
|
|
if (!isVisible) {
|
|
// Reset position if not visible
|
|
delete state.x;
|
|
delete state.y;
|
|
}
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
|
/**
|
|
* Save window state
|
|
*/
|
|
export function saveWindowState(win: BrowserWindow): void {
|
|
const isMaximized = win.isMaximized();
|
|
|
|
if (!isMaximized) {
|
|
const bounds = win.getBounds();
|
|
store.set('windowState', {
|
|
x: bounds.x,
|
|
y: bounds.y,
|
|
width: bounds.width,
|
|
height: bounds.height,
|
|
isMaximized,
|
|
});
|
|
} else {
|
|
store.set('windowState.isMaximized', true);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Track window state changes
|
|
*/
|
|
export function trackWindowState(win: BrowserWindow): void {
|
|
// Save state on window events
|
|
['resize', 'move', 'close'].forEach((event) => {
|
|
win.on(event as any, () => saveWindowState(win));
|
|
});
|
|
}
|