mirror of
https://github.com/got-feedBack/feedBack-desktop.git
synced 2026-07-24 13:51:22 +00:00
* feat(window): persist main window size/position across launches The main window always opened at a fixed 1400x900, forcing a manual resize every session. Save the window geometry (normal bounds + maximized flag) to the existing desktop prefs store on close, and restore it in createWindow. Saved bounds are validated by a pure sanitizer against the current display layout before use, so stale state degrades safely instead of producing an off-screen or absurd window: - garbage/partial config -> 1400x900 centered defaults - size clamped between the 800x600 window minimums and the largest display's workArea - position kept only when the window overlaps a display by at least 100x50 px (unplugged monitor / resolution change -> re-center); negative multi-monitor coordinates remain valid - maximized sessions save getNormalBounds() and re-maximize on restore; fullscreen deliberately restores windowed No new dependency; reuses get/setDesktopConfig (atomic write, fail-soft) in soundfont-manager.ts. The store file is already in the reset-app-settings delete-set, so a config reset also resets bounds. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: gionnibgud <gionnibgud@gmail.com> * fix(window): don't crash shutdown if bounds persistence write fails The close listener called setDesktopConfig synchronously with no error handling; a disk-full or permissions failure during the write would throw unhandled inside the close handler, risking a shutdown crash. Wrap the write in try/catch and log a warning instead. Flagged by CodeRabbit on PR #97. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: gionnibgud <gionnibgud@gmail.com> --------- Signed-off-by: gionnibgud <gionnibgud@gmail.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
60 lines
2.9 KiB
JavaScript
60 lines
2.9 KiB
JavaScript
const test = require('node:test');
|
||
const assert = require('node:assert/strict');
|
||
const { loadTs } = require('./_load-ts');
|
||
|
||
const { sanitizeWindowBounds, DEFAULT_WIDTH, DEFAULT_HEIGHT, MIN_WIDTH, MIN_HEIGHT } =
|
||
loadTs('src/main/window-bounds.ts');
|
||
|
||
// A common single-display workArea (1920×1080 minus a 40px taskbar).
|
||
const PRIMARY = { x: 0, y: 0, width: 1920, height: 1040 };
|
||
const DEFAULTS = { width: DEFAULT_WIDTH, height: DEFAULT_HEIGHT, maximized: false };
|
||
|
||
test('valid bounds on a matching display round-trip', () => {
|
||
const saved = { x: 100, y: 50, width: 1200, height: 800, maximized: true };
|
||
assert.deepEqual(sanitizeWindowBounds(saved, [PRIMARY]), saved);
|
||
});
|
||
|
||
test('garbage input falls back to defaults', () => {
|
||
for (const bad of [undefined, null, 'wat', 42, {}, { x: 1, y: 2 }, { x: 'a', y: 0, width: 1200, height: 800 }, { x: NaN, y: 0, width: 1200, height: 800 }, { x: 0, y: 0, width: Infinity, height: 800 }]) {
|
||
assert.deepEqual(sanitizeWindowBounds(bad, [PRIMARY]), DEFAULTS);
|
||
}
|
||
});
|
||
|
||
test('empty display list falls back to defaults', () => {
|
||
assert.deepEqual(sanitizeWindowBounds({ x: 0, y: 0, width: 1200, height: 800 }, []), DEFAULTS);
|
||
});
|
||
|
||
test('oversize bounds clamp to the largest display workArea', () => {
|
||
const out = sanitizeWindowBounds({ x: 0, y: 0, width: 5000, height: 4000 }, [PRIMARY]);
|
||
assert.deepEqual(out, { x: 0, y: 0, width: 1920, height: 1040, maximized: false });
|
||
});
|
||
|
||
test('undersize bounds clamp up to the window minimums', () => {
|
||
const out = sanitizeWindowBounds({ x: 10, y: 10, width: 300, height: 200 }, [PRIMARY]);
|
||
assert.deepEqual(out, { x: 10, y: 10, width: MIN_WIDTH, height: MIN_HEIGHT, maximized: false });
|
||
});
|
||
|
||
test('position on a now-unplugged monitor is dropped, size kept', () => {
|
||
// Saved on a second display to the right that no longer exists.
|
||
const out = sanitizeWindowBounds({ x: 2000, y: 100, width: 1200, height: 800 }, [PRIMARY]);
|
||
assert.deepEqual(out, { width: 1200, height: 800, maximized: false });
|
||
});
|
||
|
||
test('negative coordinates on a left-of-primary monitor are kept', () => {
|
||
const leftMonitor = { x: -1920, y: 0, width: 1920, height: 1040 };
|
||
const saved = { x: -1800, y: 100, width: 1200, height: 800 };
|
||
const out = sanitizeWindowBounds(saved, [leftMonitor, PRIMARY]);
|
||
assert.deepEqual(out, { ...saved, maximized: false });
|
||
});
|
||
|
||
test('sliver overlap below the grab threshold drops the position', () => {
|
||
// Only 50px of the window's left edge on screen — not enough to grab.
|
||
const out = sanitizeWindowBounds({ x: 1870, y: 100, width: 1200, height: 800 }, [PRIMARY]);
|
||
assert.deepEqual(out, { width: 1200, height: 800, maximized: false });
|
||
});
|
||
|
||
test('fractional coordinates are rounded to integers', () => {
|
||
const out = sanitizeWindowBounds({ x: 10.6, y: 20.4, width: 1200.5, height: 800.2 }, [PRIMARY]);
|
||
assert.deepEqual(out, { x: 11, y: 20, width: 1201, height: 800, maximized: false });
|
||
});
|