+36
-2
@@ -67,6 +67,9 @@ let capture;
|
|||||||
let textIntel;
|
let textIntel;
|
||||||
let mainWindow;
|
let mainWindow;
|
||||||
let lastZoomShortcut = null;
|
let lastZoomShortcut = null;
|
||||||
|
let canvasZoomActive = false;
|
||||||
|
const UI_ZOOM_LEVEL_MIN = -8;
|
||||||
|
const UI_ZOOM_LEVEL_MAX = 8;
|
||||||
|
|
||||||
function reindex(guideId) {
|
function reindex(guideId) {
|
||||||
try {
|
try {
|
||||||
@@ -99,6 +102,29 @@ function dispatchZoomShortcut(kind) {
|
|||||||
sendToRenderer('editor:zoom-shortcut', kind);
|
sendToRenderer('editor:zoom-shortcut', kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ctrl+=/Ctrl+-/Ctrl+0 zoom the step editor's canvas while a guide is open
|
||||||
|
// there (dispatchZoomShortcut above); everywhere else — library, welcome,
|
||||||
|
// dialogs — the same keys scale the whole window's UI like a browser.
|
||||||
|
function applyUiZoom(kind) {
|
||||||
|
if (!mainWindow || mainWindow.isDestroyed()) return;
|
||||||
|
const wc = mainWindow.webContents;
|
||||||
|
if (kind === 'fit') {
|
||||||
|
wc.zoomLevel = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const delta = kind === 'in' ? 1 : kind === 'out' ? -1 : 0;
|
||||||
|
if (!delta) return;
|
||||||
|
wc.zoomLevel = Math.max(UI_ZOOM_LEVEL_MIN, Math.min(UI_ZOOM_LEVEL_MAX, wc.zoomLevel + delta));
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleZoomShortcut(kind) {
|
||||||
|
if (canvasZoomActive) {
|
||||||
|
dispatchZoomShortcut(kind);
|
||||||
|
} else {
|
||||||
|
applyUiZoom(kind);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function createWindow() {
|
function createWindow() {
|
||||||
mainWindow = new BrowserWindow({
|
mainWindow = new BrowserWindow({
|
||||||
width: 1280,
|
width: 1280,
|
||||||
@@ -129,7 +155,7 @@ function createWindow() {
|
|||||||
const kind = zoomShortcutFromInputEvent(input);
|
const kind = zoomShortcutFromInputEvent(input);
|
||||||
if (!kind) return;
|
if (!kind) return;
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
dispatchZoomShortcut(kind);
|
handleZoomShortcut(kind);
|
||||||
});
|
});
|
||||||
mainWindow.loadFile(path.join(__dirname, 'renderer', 'index.html'));
|
mainWindow.loadFile(path.join(__dirname, 'renderer', 'index.html'));
|
||||||
mainWindow.once('ready-to-show', () => {
|
mainWindow.once('ready-to-show', () => {
|
||||||
@@ -421,7 +447,7 @@ function registerHotkeys() {
|
|||||||
];
|
];
|
||||||
for (const [accel, kind] of zoomBindings) {
|
for (const [accel, kind] of zoomBindings) {
|
||||||
try {
|
try {
|
||||||
if (globalShortcut.register(accel, () => dispatchZoomShortcut(kind))) {
|
if (globalShortcut.register(accel, () => handleZoomShortcut(kind))) {
|
||||||
// Keep registering the other spellings so keyboards with different
|
// Keep registering the other spellings so keyboards with different
|
||||||
// plus/minus translations still land on the same action.
|
// plus/minus translations still land on the same action.
|
||||||
}
|
}
|
||||||
@@ -463,6 +489,14 @@ function setupIpc() {
|
|||||||
getMainWebContents: () => (mainWindow && !mainWindow.isDestroyed() ? mainWindow.webContents : null),
|
getMainWebContents: () => (mainWindow && !mainWindow.isDestroyed() ? mainWindow.webContents : null),
|
||||||
});
|
});
|
||||||
const c = security.check;
|
const c = security.check;
|
||||||
|
|
||||||
|
// The renderer reports whether the step editor (with a guide open) is the
|
||||||
|
// visible screen, so Ctrl+=/Ctrl+-/Ctrl+0 can pick canvas zoom vs UI zoom.
|
||||||
|
ipcMain.on('editor:canvas-zoom-active', (event, active) => {
|
||||||
|
if (!trustedSender(event)) return;
|
||||||
|
canvasZoomActive = Boolean(active);
|
||||||
|
});
|
||||||
|
|
||||||
const IMAGE_BUDGET = 256 * 1024 * 1024; // channels that carry base64 PNGs
|
const IMAGE_BUDGET = 256 * 1024 * 1024; // channels that carry base64 PNGs
|
||||||
const h = (channel, fn, opts = {}) => {
|
const h = (channel, fn, opts = {}) => {
|
||||||
const { maxChars = 2 * 1024 * 1024, validate = null } = opts;
|
const { maxChars = 2 * 1024 * 1024, validate = null } = opts;
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ const api = {
|
|||||||
},
|
},
|
||||||
editor: {
|
editor: {
|
||||||
onZoomShortcut: (fn) => ipcRenderer.on('editor:zoom-shortcut', (e, payload) => fn(payload)),
|
onZoomShortcut: (fn) => ipcRenderer.on('editor:zoom-shortcut', (e, payload) => fn(payload)),
|
||||||
|
setCanvasZoomActive: (active) => ipcRenderer.send('editor:canvas-zoom-active', Boolean(active)),
|
||||||
},
|
},
|
||||||
archive: {
|
archive: {
|
||||||
export: invoke('archive:export'),
|
export: invoke('archive:export'),
|
||||||
|
|||||||
@@ -178,6 +178,9 @@ class GuideEditor {
|
|||||||
|
|
||||||
setActive(active) {
|
setActive(active) {
|
||||||
this.active = Boolean(active);
|
this.active = Boolean(active);
|
||||||
|
if (api.editor && typeof api.editor.setCanvasZoomActive === 'function') {
|
||||||
|
api.editor.setCanvasZoomActive(this.active);
|
||||||
|
}
|
||||||
if (!this.active && this.guideId) {
|
if (!this.active && this.guideId) {
|
||||||
// Leaving the editor: flush pending debounced saves so navigation can
|
// Leaving the editor: flush pending debounced saves so navigation can
|
||||||
// never drop the last edit (failures keep the dirty state and retry),
|
// never drop the last edit (failures keep the dirty state and retry),
|
||||||
|
|||||||
Reference in New Issue
Block a user