feat: interface zoom control settings (#7255)

* feat: interface zoom control settings

* fix: allow zoom controls using shortcuts

* fix: maintain consitency in zoom shortcuts and ui interface

* fix: added min max to 50% and 150% for zoom

* fix: moved percentageToZoomLevel function in bruno-common

* chore: abstractions

---------

Co-authored-by: shubh-bruno <shubh-bruno@shubh-bruno.local>
This commit is contained in:
shubh-bruno
2026-02-23 16:32:34 +05:30
committed by GitHub
parent 04ef477f3b
commit 89bf2fbf44
8 changed files with 341 additions and 9 deletions

View File

@@ -62,9 +62,27 @@ const template = [
submenu: [
{ role: 'toggledevtools' },
{ type: 'separator' },
{ role: 'resetzoom' },
{ role: 'zoomin' },
{ role: 'zoomout' },
{
label: 'Actual Size',
accelerator: 'CommandOrControl+0',
click() {
ipcMain.emit('menu:reset-zoom');
}
},
{
label: 'Zoom In',
accelerator: 'CommandOrControl+Plus',
click() {
ipcMain.emit('menu:zoom-in');
}
},
{
label: 'Zoom Out',
accelerator: 'CommandOrControl+-',
click() {
ipcMain.emit('menu:zoom-out');
}
},
{ type: 'separator' },
{ role: 'togglefullscreen' }
]

View File

@@ -4,6 +4,7 @@ const { execSync } = require('node:child_process');
const isDev = require('electron-is-dev');
const os = require('os');
const { initializeShellEnv } = require('@usebruno/requests');
const { percentageToZoomLevel } = require('@usebruno/common');
if (isDev) {
if (!fs.existsSync(path.join(__dirname, '../../bruno-js/src/sandbox/bundle-browser-rollup.js'))) {
@@ -47,6 +48,7 @@ const collectionWatcher = require('./app/collection-watcher');
const WorkspaceWatcher = require('./app/workspace-watcher');
const ApiSpecWatcher = require('./app/apiSpecsWatcher');
const { loadWindowState, saveBounds, saveMaximized } = require('./utils/window');
const { preferencesUtil, getPreferences, savePreferences } = require('./store/preferences');
const { globalEnvironmentsManager } = require('./store/workspace-environments');
const registerNotificationsIpc = require('./ipc/notifications');
const registerGlobalEnvironmentsIpc = require('./ipc/global-environments');
@@ -92,6 +94,25 @@ const isLinux = process.platform === 'linux';
let mainWindow;
let appProtocolUrl;
// Helper function to save zoom percentage to preferences and notify renderer
const saveZoomPreferences = async (percentage) => {
if (!mainWindow) return;
const clampedPercentage = Math.max(50, Math.min(150, percentage));
const prefs = getPreferences();
prefs.display = prefs.display || {};
prefs.display.zoomPercentage = clampedPercentage;
try {
await savePreferences(prefs);
// Notify renderer to update Redux state only after successful save
mainWindow.webContents.send('main:load-preferences', prefs);
} catch (err) {
console.error('Failed to save zoom preference:', err);
}
};
// Helper function to focus and restore the main window
const focusMainWindow = () => {
if (mainWindow) {
@@ -246,17 +267,32 @@ app.on('ready', async () => {
});
ipcMain.handle('renderer:reset-zoom', () => {
mainWindow.webContents.setZoomLevel(0);
updateZoomLevel(100);
});
ipcMain.handle('renderer:zoom-in', () => {
const currentZoom = mainWindow.webContents.getZoomLevel();
mainWindow.webContents.setZoomLevel(currentZoom + 0.5);
incrementZoomAndPersist(10);
});
ipcMain.handle('renderer:zoom-out', () => {
const currentZoom = mainWindow.webContents.getZoomLevel();
mainWindow.webContents.setZoomLevel(currentZoom - 0.5);
incrementZoomAndPersist(-10);
});
// Menu event handlers for zoom (from menu-template.js)
ipcMain.on('menu:reset-zoom', () => {
updateZoomLevel(100);
});
ipcMain.on('menu:zoom-in', () => {
incrementZoomAndPersist(10);
});
ipcMain.on('menu:zoom-out', () => {
incrementZoomAndPersist(-10);
});
ipcMain.handle('renderer:set-zoom-level', (event, zoomLevel) => {
mainWindow.webContents.setZoomLevel(zoomLevel);
});
ipcMain.handle('renderer:toggle-fullscreen', () => {
@@ -282,6 +318,12 @@ app.on('ready', async () => {
});
mainWindow.once('ready-to-show', () => {
// Apply saved zoom level from preferences before showing window
const zoomPercentage = preferencesUtil.getZoomPercentage();
if (zoomPercentage) {
const zoomLevel = percentageToZoomLevel(zoomPercentage);
mainWindow.webContents.setZoomLevel(zoomLevel);
}
mainWindow.show();
});
const devPort = process.env.BRUNO_DEV_PORT || 3000;
@@ -445,7 +487,7 @@ app.on('open-file', (event, path) => {
app.on('browser-window-focus', () => {
// Quick fix for Electron issue #29996: https://github.com/electron/electron/issues/29996
globalShortcut.register('Ctrl+=', () => {
mainWindow.webContents.setZoomLevel(mainWindow.webContents.getZoomLevel() + 1);
incrementZoomAndPersist(10);
});
});
@@ -453,3 +495,24 @@ app.on('browser-window-focus', () => {
app.on('browser-window-blur', () => {
globalShortcut.unregisterAll();
});
/**
* @param {number} inc (+/- amount to zoom in / out);
*/
function incrementZoomAndPersist(inc) {
const currentPercentage = preferencesUtil.getZoomPercentage();
const nextPercentage = Math.min(
Math.max(currentPercentage + inc, 50),
150
);
updateZoomLevel(nextPercentage);
}
/**
* @param {number} percent percentage to increase or decrease zoom by, percentage is converted to chrome's log value internally
*/
function updateZoomLevel(percent) {
const zoomLevel = percentageToZoomLevel(percent);
mainWindow.webContents.setZoomLevel(zoomLevel);
saveZoomPreferences(percent);
}

View File

@@ -56,6 +56,9 @@ const defaultPreferences = {
autoSave: {
enabled: false,
interval: 1000
},
display: {
zoomPercentage: 100
}
};
@@ -110,6 +113,9 @@ const preferencesSchema = Yup.object().shape({
autoSave: Yup.object({
enabled: Yup.boolean(),
interval: Yup.number().min(100)
}),
display: Yup.object({
zoomPercentage: Yup.number().min(50).max(150)
})
});
@@ -286,6 +292,9 @@ const preferencesUtil = {
isBetaFeatureEnabled: (featureName) => {
return get(getPreferences(), `beta.${featureName}`, false);
},
getZoomPercentage: () => {
return get(getPreferences(), 'display.zoomPercentage', 100);
},
hasLaunchedBefore: () => {
return get(getPreferences(), 'onboarding.hasLaunchedBefore', false);
},