mirror of
https://github.com/actualbudget/actual.git
synced 2026-04-29 11:04:12 -05:00
159 lines
3.7 KiB
TypeScript
159 lines
3.7 KiB
TypeScript
import fs from 'fs';
|
|
import path from 'path';
|
|
|
|
import electron from 'electron';
|
|
import type { BrowserWindow } from 'electron';
|
|
|
|
type WindowState = Electron.Rectangle & {
|
|
isMaximized?: boolean;
|
|
isFullScreen?: boolean;
|
|
displayBounds?: Electron.Rectangle;
|
|
};
|
|
|
|
const getDataDir = () => {
|
|
if (!process.env.ACTUAL_DATA_DIR) {
|
|
throw new Error('ACTUAL_DATA_DIR is not set');
|
|
}
|
|
|
|
return process.env.ACTUAL_DATA_DIR;
|
|
};
|
|
|
|
async function loadState() {
|
|
let state: WindowState | undefined = undefined;
|
|
try {
|
|
state = JSON.parse(
|
|
fs.readFileSync(path.join(getDataDir(), 'window.json'), 'utf8'),
|
|
);
|
|
} catch {
|
|
console.log('Could not load window state');
|
|
}
|
|
|
|
return validateState(state);
|
|
}
|
|
|
|
function updateState(win: BrowserWindow, state: WindowState) {
|
|
const screen = electron.screen;
|
|
const bounds = win.getBounds();
|
|
if (!win.isMaximized() && !win.isMinimized() && !win.isFullScreen()) {
|
|
state.width = bounds.width;
|
|
state.height = bounds.height;
|
|
}
|
|
|
|
state.x = bounds.x;
|
|
state.y = bounds.y;
|
|
state.isMaximized = win.isMaximized();
|
|
state.isFullScreen = win.isFullScreen();
|
|
state.displayBounds = screen.getDisplayMatching(bounds).bounds;
|
|
}
|
|
|
|
async function saveState(win: BrowserWindow, state: WindowState) {
|
|
updateState(win, state);
|
|
fs.writeFileSync(
|
|
path.join(getDataDir(), 'window.json'),
|
|
JSON.stringify(state),
|
|
'utf8',
|
|
);
|
|
}
|
|
|
|
export function listen(win: BrowserWindow, state: WindowState) {
|
|
if (state.isMaximized) {
|
|
win.maximize();
|
|
}
|
|
if (state.isFullScreen) {
|
|
win.setFullScreen(true);
|
|
}
|
|
|
|
const saver = saveState.bind(null, win, state);
|
|
|
|
win.on('close', saver);
|
|
|
|
return () => {
|
|
win.removeListener('close', saver);
|
|
};
|
|
}
|
|
|
|
function hasBounds(state: WindowState) {
|
|
return (
|
|
Number.isInteger(state.x) &&
|
|
Number.isInteger(state.y) &&
|
|
Number.isInteger(state.width) &&
|
|
state.width > 0 &&
|
|
Number.isInteger(state.height) &&
|
|
state.height > 0
|
|
);
|
|
}
|
|
|
|
function validateState(state?: WindowState): Partial<WindowState> {
|
|
if (
|
|
!state ||
|
|
!(hasBounds(state) || state.isMaximized || state.isFullScreen)
|
|
) {
|
|
return {};
|
|
}
|
|
|
|
const newState = Object.assign({}, state);
|
|
|
|
if (hasBounds(state) && state.displayBounds) {
|
|
const screen = electron.screen;
|
|
|
|
// Check if the display where the window was last open is still available
|
|
const displayBounds = screen.getDisplayMatching(state).bounds;
|
|
|
|
if (
|
|
state.displayBounds.x !== displayBounds.x ||
|
|
state.displayBounds.y !== displayBounds.y ||
|
|
state.displayBounds.width !== displayBounds.width ||
|
|
state.displayBounds.height !== displayBounds.height
|
|
) {
|
|
if (displayBounds.width < state.displayBounds.width) {
|
|
if (state.x > displayBounds.width) {
|
|
newState.x = 0;
|
|
}
|
|
|
|
if (state.width > displayBounds.width) {
|
|
newState.width = displayBounds.width;
|
|
}
|
|
}
|
|
|
|
if (displayBounds.height < state.displayBounds.height) {
|
|
if (state.y > displayBounds.height) {
|
|
newState.y = 0;
|
|
}
|
|
|
|
if (state.height > displayBounds.height) {
|
|
newState.height = displayBounds.height;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return newState;
|
|
}
|
|
|
|
export async function get() {
|
|
if (process.env.EXECUTION_CONTEXT === 'playwright') {
|
|
// For Playwright screenshots to be consistent across machine we need a fixed window size
|
|
return {
|
|
x: 100,
|
|
y: 50,
|
|
width: 1300,
|
|
height: 800,
|
|
};
|
|
}
|
|
|
|
const screen = electron.screen;
|
|
const displayBounds = screen.getPrimaryDisplay().bounds;
|
|
|
|
const state: WindowState = Object.assign(
|
|
{
|
|
x: 100,
|
|
y: 50,
|
|
width: Math.min(1000, displayBounds.width - 100),
|
|
height: Math.min(700, displayBounds.width - 50),
|
|
},
|
|
await loadState(),
|
|
);
|
|
|
|
return state;
|
|
}
|