Skip to content

Commit 33f32cc

Browse files
authored
Leave browser zoom to the browser (#578)
The web build bound Cmd/Ctrl +, - and 0 and then did nothing with them, so zoom appeared broken. Those keys are the browser's own page zoom, which scales the whole page and remembers it per site. Adds an interfaceZoom capability: true on desktop, where the host zooms the webview, false in a browser. When false the app binds nothing and the hotkeys screen drops the three rows it can't configure.
1 parent 7ca7723 commit 33f32cc

6 files changed

Lines changed: 37 additions & 13 deletions

File tree

apps/yaak-client/components/Settings/SettingsHotkeys.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ export function SettingsHotkeys() {
124124
<HotkeyRow
125125
key={action}
126126
action={action}
127-
currentKeys={hotkeys[action]}
127+
currentKeys={hotkeys[action] ?? []}
128128
defaultKeys={defaultHotkeys[action]}
129129
onSave={async (keys) => {
130130
const newHotkeys = { ...settings.hotkeys };

apps/yaak-client/hooks/useHotKey.ts

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -112,17 +112,20 @@ export const hotkeysAtom = atom((get) => {
112112
// Merge default hotkeys with custom hotkeys from settings
113113
// Custom hotkeys override defaults for the same action
114114
// An empty array means the hotkey is intentionally disabled
115-
const merged: Record<HotkeyAction, string[]> = { ...defaultHotkeys };
115+
const merged: Partial<Record<HotkeyAction, string[]>> = {};
116+
for (const action of hotkeyActions) {
117+
merged[action] = defaultHotkeys[action];
118+
}
116119
for (const [action, keys] of Object.entries(customHotkeys)) {
117-
if (action in defaultHotkeys && Array.isArray(keys)) {
120+
if (action in merged && Array.isArray(keys)) {
118121
merged[action as HotkeyAction] = keys;
119122
}
120123
}
121124
return merged;
122125
});
123126

124127
/** Helper function to get current hotkeys from the store */
125-
function getHotkeys(): Record<HotkeyAction, string[]> {
128+
function getHotkeys(): Partial<Record<HotkeyAction, string[]>> {
126129
return jotaiStore.get(hotkeysAtom);
127130
}
128131

@@ -165,16 +168,25 @@ const layoutInsensitiveKeys = [
165168
"Space",
166169
];
167170

171+
/** Zoom is the browser's own on these keys, so the app has no such action there. */
172+
const ZOOM_ACTIONS: HotkeyAction[] = ["app.zoom_in", "app.zoom_out", "app.zoom_reset"];
173+
174+
/**
175+
* The actions this host actually has. An action left out of here has no keys in
176+
* `hotkeysAtom`, so it never matches and never claims the keystroke.
177+
*/
168178
export const hotkeyActions: HotkeyAction[] = (
169179
Object.keys(defaultHotkeys) as (keyof typeof defaultHotkeys)[]
170-
).sort((a, b) => {
171-
const scopeA = a.split(".")[0] || "";
172-
const scopeB = b.split(".")[0] || "";
173-
if (scopeA !== scopeB) {
174-
return scopeA.localeCompare(scopeB);
175-
}
176-
return hotkeyLabels[a].localeCompare(hotkeyLabels[b]);
177-
});
180+
)
181+
.filter((a) => platform.capabilities.interfaceZoom || !ZOOM_ACTIONS.includes(a))
182+
.sort((a, b) => {
183+
const scopeA = a.split(".")[0] || "";
184+
const scopeB = b.split(".")[0] || "";
185+
if (scopeA !== scopeB) {
186+
return scopeA.localeCompare(scopeB);
187+
}
188+
return hotkeyLabels[a].localeCompare(hotkeyLabels[b]);
189+
});
178190

179191
export type HotKeyOptions = {
180192
enable?: boolean | (() => boolean);

packages/platform/src/tauri/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ const ALL_CAPABILITIES: PlatformCapabilities = {
5959
timeline: true,
6060
multiWindow: true,
6161
windowChrome: true,
62+
interfaceZoom: true,
6263
plugins: true,
6364
encryption: true,
6465
updater: true,

packages/platform/src/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,11 @@ export interface PlatformCapabilities {
262262
* chrome should be reserved or drawn.
263263
*/
264264
windowChrome: boolean;
265+
/**
266+
* The app zooms its own interface, and so owns Cmd/Ctrl `+`, `-` and `0`.
267+
* False in a browser, where those keys are already the browser's.
268+
*/
269+
interfaceZoom: boolean;
265270
/** The plugin runtime. */
266271
plugins: boolean;
267272
/** Workspace encryption backed by a key the host keeps. */

packages/platform/src/web/README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,10 @@ Reported honestly, so callers gate on the question rather than on the host:
129129

130130
| True | False |
131131
| --- | --- |
132-
| `cookieJar` (the jar stores and edits here; only filling it needs the sender) | `grpc`, `websocket`, `git`, `sync`, `tlsOptions`, `localFiles`, `timeline`, `multiWindow`, `windowChrome`, `plugins`, `encryption`, `updater`, `clipboardRead`, `systemFonts`, `license` |
132+
| `cookieJar` (the jar stores and edits here; only filling it needs the sender) | `grpc`, `websocket`, `git`, `sync`, `tlsOptions`, `localFiles`, `timeline`, `multiWindow`, `windowChrome`, `interfaceZoom`, `plugins`, `encryption`, `updater`, `clipboardRead`, `systemFonts`, `license` |
133+
134+
`interfaceZoom: false` leaves Cmd/Ctrl `+`, `-` and `0` to the browser instead
135+
of swallowing them, and drops those three rows from the hotkeys screen.
133136

134137
`multiWindow: false` means the host cannot open a *second window* on demand —
135138
what `cmd_new_child_window` does for Settings and workspace switching. It is not

packages/platform/src/web/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ function capabilitiesFor(): PlatformCapabilities {
5252
// The browser draws the frame around the page. There are no traffic lights
5353
// to leave room for and no window controls to draw.
5454
windowChrome: false,
55+
// The browser already zooms the page, on the same keys, and remembers it
56+
// per site. The app stays out of the way.
57+
interfaceZoom: false,
5558
plugins: false,
5659
encryption: false,
5760
updater: false,

0 commit comments

Comments
 (0)