109 lines
3.7 KiB
TypeScript
109 lines
3.7 KiB
TypeScript
|
import * as electron from "electron";
|
||
|
import * as fs from "fs-extra";
|
||
|
import * as path from "path";
|
||
|
|
||
|
/* We read/write to this file every time again because this file could be used by multible processes */
|
||
|
const data_file: string = path.join(electron.app.getPath('userData'), "window-bounds.json");
|
||
|
|
||
|
import BrowserWindow = Electron.BrowserWindow;
|
||
|
import Rectangle = Electron.Rectangle;
|
||
|
|
||
|
let _changed_data: {[key: string]:Rectangle} = {};
|
||
|
let _changed_saver: NodeJS.Timer;
|
||
|
|
||
|
export async function save_changes() {
|
||
|
clearTimeout(_changed_saver);
|
||
|
|
||
|
try {
|
||
|
const data = (await fs.pathExists(data_file) ? await fs.readJson(data_file) : {}) || {};
|
||
|
Object.assign(data, _changed_data);
|
||
|
|
||
|
await fs.ensureFile(data_file);
|
||
|
await fs.writeJson(data_file, data);
|
||
|
path_exists = true;
|
||
|
|
||
|
_changed_data = {};
|
||
|
} catch(error) {
|
||
|
console.warn("Failed to save window bounds: %o", error);
|
||
|
}
|
||
|
console.log("Window bounds have been successfully saved!");
|
||
|
}
|
||
|
|
||
|
let path_exists = undefined;
|
||
|
export async function get_last_bounds(key: string) : Promise<Rectangle> {
|
||
|
try {
|
||
|
if(typeof(path_exists) === "undefined" ? !(path_exists = await fs.pathExists(data_file)) : !path_exists)
|
||
|
throw "skip!";
|
||
|
|
||
|
const data = await fs.readJson(data_file) || {};
|
||
|
if(data[key])
|
||
|
return data[key];
|
||
|
} catch(error) {
|
||
|
if(error !== "skip!")
|
||
|
console.warn("Failed to load window bounds for %s: %o", key, error);
|
||
|
}
|
||
|
|
||
|
return {
|
||
|
height: undefined,
|
||
|
width: undefined,
|
||
|
x: undefined,
|
||
|
y: undefined
|
||
|
}
|
||
|
}
|
||
|
|
||
|
export function track_bounds(key: string, window: BrowserWindow) {
|
||
|
const events = ['move', 'moved', 'resize'];
|
||
|
|
||
|
const update_bounds = () => {
|
||
|
_changed_data[key] = window.getBounds();
|
||
|
|
||
|
clearTimeout(_changed_saver);
|
||
|
_changed_saver = setTimeout(save_changes, 1000);
|
||
|
};
|
||
|
|
||
|
for(const event of events)
|
||
|
window.on(event as any, update_bounds);
|
||
|
|
||
|
window.on('closed', () => {
|
||
|
for(const event of events)
|
||
|
window.removeListener(event as any, update_bounds);
|
||
|
})
|
||
|
}
|
||
|
|
||
|
export async function apply_bounds(key: string, window: BrowserWindow, bounds?: Rectangle, options?: { apply_size?: boolean; apply_position?: boolean }) {
|
||
|
const screen = electron.screen;
|
||
|
|
||
|
if(!bounds)
|
||
|
bounds = await get_last_bounds(key);
|
||
|
|
||
|
if(!options)
|
||
|
options = {};
|
||
|
|
||
|
const original_bounds = window.getBounds();
|
||
|
|
||
|
if(typeof(options.apply_size) !== "boolean" || options.apply_size) {
|
||
|
let height = bounds.height > 0 ? bounds.height : original_bounds.height;
|
||
|
let width = bounds.width > 0 ? bounds.width : original_bounds.width;
|
||
|
|
||
|
if(height != original_bounds.height || width != original_bounds.width)
|
||
|
window.setSize(width, height, true);
|
||
|
}
|
||
|
if(typeof(options.apply_position) !== "boolean" || options.apply_position) {
|
||
|
let x = typeof(bounds.x) === "number" ? bounds.x : original_bounds.x;
|
||
|
let y = typeof(bounds.y) === "number" ? bounds.y : original_bounds.y;
|
||
|
|
||
|
if(x != original_bounds.x || y != original_bounds.y) {
|
||
|
const display = screen.getDisplayNearestPoint({ x: x, y: y });
|
||
|
if(display) {
|
||
|
const bounds = display.workArea || display.bounds;
|
||
|
let flag_invalid = false;
|
||
|
flag_invalid = flag_invalid || bounds.x > x || (bounds.x + bounds.width) < x;
|
||
|
flag_invalid = flag_invalid || bounds.y > x || (bounds.y + bounds.height) < y;
|
||
|
if(!flag_invalid) {
|
||
|
window.setPosition(x, y, true);
|
||
|
console.log("Updating position for %s", key);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|