mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-08-20 02:13:58 +02:00
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.
This commit is contained in:
@@ -124,7 +124,7 @@ export function SettingsHotkeys() {
|
||||
<HotkeyRow
|
||||
key={action}
|
||||
action={action}
|
||||
currentKeys={hotkeys[action]}
|
||||
currentKeys={hotkeys[action] ?? []}
|
||||
defaultKeys={defaultHotkeys[action]}
|
||||
onSave={async (keys) => {
|
||||
const newHotkeys = { ...settings.hotkeys };
|
||||
|
||||
@@ -112,9 +112,12 @@ export const hotkeysAtom = atom((get) => {
|
||||
// Merge default hotkeys with custom hotkeys from settings
|
||||
// Custom hotkeys override defaults for the same action
|
||||
// An empty array means the hotkey is intentionally disabled
|
||||
const merged: Record<HotkeyAction, string[]> = { ...defaultHotkeys };
|
||||
const merged: Partial<Record<HotkeyAction, string[]>> = {};
|
||||
for (const action of hotkeyActions) {
|
||||
merged[action] = defaultHotkeys[action];
|
||||
}
|
||||
for (const [action, keys] of Object.entries(customHotkeys)) {
|
||||
if (action in defaultHotkeys && Array.isArray(keys)) {
|
||||
if (action in merged && Array.isArray(keys)) {
|
||||
merged[action as HotkeyAction] = keys;
|
||||
}
|
||||
}
|
||||
@@ -122,7 +125,7 @@ export const hotkeysAtom = atom((get) => {
|
||||
});
|
||||
|
||||
/** Helper function to get current hotkeys from the store */
|
||||
function getHotkeys(): Record<HotkeyAction, string[]> {
|
||||
function getHotkeys(): Partial<Record<HotkeyAction, string[]>> {
|
||||
return jotaiStore.get(hotkeysAtom);
|
||||
}
|
||||
|
||||
@@ -165,16 +168,25 @@ const layoutInsensitiveKeys = [
|
||||
"Space",
|
||||
];
|
||||
|
||||
/** Zoom is the browser's own on these keys, so the app has no such action there. */
|
||||
const ZOOM_ACTIONS: HotkeyAction[] = ["app.zoom_in", "app.zoom_out", "app.zoom_reset"];
|
||||
|
||||
/**
|
||||
* The actions this host actually has. An action left out of here has no keys in
|
||||
* `hotkeysAtom`, so it never matches and never claims the keystroke.
|
||||
*/
|
||||
export const hotkeyActions: HotkeyAction[] = (
|
||||
Object.keys(defaultHotkeys) as (keyof typeof defaultHotkeys)[]
|
||||
).sort((a, b) => {
|
||||
const scopeA = a.split(".")[0] || "";
|
||||
const scopeB = b.split(".")[0] || "";
|
||||
if (scopeA !== scopeB) {
|
||||
return scopeA.localeCompare(scopeB);
|
||||
}
|
||||
return hotkeyLabels[a].localeCompare(hotkeyLabels[b]);
|
||||
});
|
||||
)
|
||||
.filter((a) => platform.capabilities.interfaceZoom || !ZOOM_ACTIONS.includes(a))
|
||||
.sort((a, b) => {
|
||||
const scopeA = a.split(".")[0] || "";
|
||||
const scopeB = b.split(".")[0] || "";
|
||||
if (scopeA !== scopeB) {
|
||||
return scopeA.localeCompare(scopeB);
|
||||
}
|
||||
return hotkeyLabels[a].localeCompare(hotkeyLabels[b]);
|
||||
});
|
||||
|
||||
export type HotKeyOptions = {
|
||||
enable?: boolean | (() => boolean);
|
||||
|
||||
@@ -59,6 +59,7 @@ const ALL_CAPABILITIES: PlatformCapabilities = {
|
||||
timeline: true,
|
||||
multiWindow: true,
|
||||
windowChrome: true,
|
||||
interfaceZoom: true,
|
||||
plugins: true,
|
||||
encryption: true,
|
||||
updater: true,
|
||||
|
||||
@@ -262,6 +262,11 @@ export interface PlatformCapabilities {
|
||||
* chrome should be reserved or drawn.
|
||||
*/
|
||||
windowChrome: boolean;
|
||||
/**
|
||||
* The app zooms its own interface, and so owns Cmd/Ctrl `+`, `-` and `0`.
|
||||
* False in a browser, where those keys are already the browser's.
|
||||
*/
|
||||
interfaceZoom: boolean;
|
||||
/** The plugin runtime. */
|
||||
plugins: boolean;
|
||||
/** Workspace encryption backed by a key the host keeps. */
|
||||
|
||||
@@ -129,7 +129,10 @@ Reported honestly, so callers gate on the question rather than on the host:
|
||||
|
||||
| True | False |
|
||||
| --- | --- |
|
||||
| `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` |
|
||||
| `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` |
|
||||
|
||||
`interfaceZoom: false` leaves Cmd/Ctrl `+`, `-` and `0` to the browser instead
|
||||
of swallowing them, and drops those three rows from the hotkeys screen.
|
||||
|
||||
`multiWindow: false` means the host cannot open a *second window* on demand —
|
||||
what `cmd_new_child_window` does for Settings and workspace switching. It is not
|
||||
|
||||
@@ -52,6 +52,9 @@ function capabilitiesFor(): PlatformCapabilities {
|
||||
// The browser draws the frame around the page. There are no traffic lights
|
||||
// to leave room for and no window controls to draw.
|
||||
windowChrome: false,
|
||||
// The browser already zooms the page, on the same keys, and remembers it
|
||||
// per site. The app stays out of the way.
|
||||
interfaceZoom: false,
|
||||
plugins: false,
|
||||
encryption: false,
|
||||
updater: false,
|
||||
|
||||
Reference in New Issue
Block a user