mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
feat(desktop): add Cmd++ zoom shortcut (#174)
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
"windows": ["main"],
|
||||
"permissions": [
|
||||
"core:default",
|
||||
"core:webview:allow-set-webview-zoom",
|
||||
"core:window:allow-start-dragging",
|
||||
"core:window:allow-show",
|
||||
"core:window:allow-close",
|
||||
|
||||
@@ -58,10 +58,12 @@ import {
|
||||
SidebarProvider,
|
||||
SidebarTrigger,
|
||||
} from "@/shared/ui/sidebar";
|
||||
import { useWebviewZoomShortcuts } from "@/app/useWebviewZoomShortcuts";
|
||||
|
||||
type AppView = "home" | "channel" | "settings" | "agents";
|
||||
type MainView = Exclude<AppView, "settings">;
|
||||
export function AppShell() {
|
||||
useWebviewZoomShortcuts();
|
||||
const [selectedView, setSelectedView] = React.useState<AppView>("home");
|
||||
const [settingsSection, setSettingsSection] = React.useState<SettingsSection>(
|
||||
DEFAULT_SETTINGS_SECTION,
|
||||
@@ -182,7 +184,6 @@ export function AppShell() {
|
||||
),
|
||||
[messageProfilesQuery.data?.profiles, profileQuery.data],
|
||||
);
|
||||
|
||||
const timelineMessages = React.useMemo(
|
||||
() =>
|
||||
formatTimelineMessages(
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
import * as React from "react";
|
||||
import { getCurrentWebview } from "@tauri-apps/api/webview";
|
||||
|
||||
const DEFAULT_ZOOM_FACTOR = 1;
|
||||
const MIN_ZOOM_FACTOR = 0.2;
|
||||
const MAX_ZOOM_FACTOR = 10;
|
||||
const ZOOM_STEP = 0.2;
|
||||
|
||||
type ZoomAction = "increase" | "decrease" | "reset";
|
||||
|
||||
function getZoomAction(event: KeyboardEvent): ZoomAction | null {
|
||||
if (!(event.metaKey || event.ctrlKey) || event.altKey) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (
|
||||
event.key === "+" ||
|
||||
event.key === "=" ||
|
||||
event.code === "Equal" ||
|
||||
event.code === "NumpadAdd"
|
||||
) {
|
||||
return "increase";
|
||||
}
|
||||
|
||||
if (
|
||||
!event.shiftKey &&
|
||||
(event.key === "-" ||
|
||||
event.code === "Minus" ||
|
||||
event.code === "NumpadSubtract")
|
||||
) {
|
||||
return "decrease";
|
||||
}
|
||||
|
||||
if (
|
||||
!event.shiftKey &&
|
||||
(event.key === "0" || event.code === "Digit0" || event.code === "Numpad0")
|
||||
) {
|
||||
return "reset";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function getNextZoomFactor(action: ZoomAction, zoomFactor: number) {
|
||||
if (action === "reset") {
|
||||
return DEFAULT_ZOOM_FACTOR;
|
||||
}
|
||||
|
||||
if (action === "increase") {
|
||||
return Math.min(zoomFactor + ZOOM_STEP, MAX_ZOOM_FACTOR);
|
||||
}
|
||||
|
||||
return Math.max(zoomFactor - ZOOM_STEP, MIN_ZOOM_FACTOR);
|
||||
}
|
||||
|
||||
export function useWebviewZoomShortcuts() {
|
||||
const zoomFactorRef = React.useRef(DEFAULT_ZOOM_FACTOR);
|
||||
|
||||
React.useEffect(() => {
|
||||
const webview = getCurrentWebview();
|
||||
|
||||
function handleKeyDown(event: KeyboardEvent) {
|
||||
const action = getZoomAction(event);
|
||||
if (!action) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
const previousZoomFactor = zoomFactorRef.current;
|
||||
const nextZoomFactor = getNextZoomFactor(action, previousZoomFactor);
|
||||
|
||||
if (nextZoomFactor === previousZoomFactor) {
|
||||
return;
|
||||
}
|
||||
|
||||
zoomFactorRef.current = nextZoomFactor;
|
||||
|
||||
void webview.setZoom(nextZoomFactor).catch((error) => {
|
||||
zoomFactorRef.current = previousZoomFactor;
|
||||
console.error("Failed to update webview zoom", error);
|
||||
});
|
||||
}
|
||||
|
||||
window.addEventListener("keydown", handleKeyDown);
|
||||
return () => {
|
||||
window.removeEventListener("keydown", handleKeyDown);
|
||||
};
|
||||
}, []);
|
||||
}
|
||||
@@ -316,6 +316,7 @@ declare global {
|
||||
interface Window {
|
||||
__SPROUT_E2E__?: E2eConfig;
|
||||
__SPROUT_E2E_COMMANDS__?: string[];
|
||||
__SPROUT_E2E_WEBVIEW_ZOOM__?: number;
|
||||
__SPROUT_E2E_EMIT_MOCK_MESSAGE__?: (input: {
|
||||
channelName: string;
|
||||
content: string;
|
||||
@@ -3207,6 +3208,7 @@ export function maybeInstallE2eTauriMocks() {
|
||||
resetMockPersonas();
|
||||
mockWindows("main");
|
||||
window.__SPROUT_E2E_COMMANDS__ = [];
|
||||
window.__SPROUT_E2E_WEBVIEW_ZOOM__ = 1;
|
||||
window.__SPROUT_E2E_EMIT_MOCK_MESSAGE__ = ({
|
||||
channelName,
|
||||
content,
|
||||
@@ -3542,6 +3544,11 @@ export function maybeInstallE2eTauriMocks() {
|
||||
}
|
||||
|
||||
return disconnectMockSocket((payload as { id: number }).id);
|
||||
case "plugin:webview|set_webview_zoom":
|
||||
window.__SPROUT_E2E_WEBVIEW_ZOOM__ = (
|
||||
payload as { value: number }
|
||||
).value;
|
||||
return;
|
||||
default:
|
||||
throw new Error(`Unsupported mocked Tauri command: ${command}`);
|
||||
}
|
||||
|
||||
@@ -215,6 +215,45 @@ test("opens settings with the keyboard shortcut and updates theme", async ({
|
||||
await expect(page.getByTestId("chat-title")).toHaveText("Home");
|
||||
});
|
||||
|
||||
test("supports webview zoom keyboard shortcuts", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
|
||||
await page.keyboard.press(
|
||||
process.platform === "darwin" ? "Meta+Shift+Equal" : "Control+Shift+Equal",
|
||||
);
|
||||
|
||||
await expect
|
||||
.poll(() => page.evaluate(() => window.__SPROUT_E2E_WEBVIEW_ZOOM__))
|
||||
.toBe(1.2);
|
||||
|
||||
await page.keyboard.press(
|
||||
process.platform === "darwin" ? "Meta+Minus" : "Control+Minus",
|
||||
);
|
||||
|
||||
await expect
|
||||
.poll(() => page.evaluate(() => window.__SPROUT_E2E_WEBVIEW_ZOOM__))
|
||||
.toBe(1);
|
||||
|
||||
await page.keyboard.press(
|
||||
process.platform === "darwin" ? "Meta+Shift+Equal" : "Control+Shift+Equal",
|
||||
);
|
||||
await page.keyboard.press(
|
||||
process.platform === "darwin" ? "Meta+Shift+Equal" : "Control+Shift+Equal",
|
||||
);
|
||||
|
||||
await expect
|
||||
.poll(() => page.evaluate(() => window.__SPROUT_E2E_WEBVIEW_ZOOM__))
|
||||
.toBe(1.4);
|
||||
|
||||
await page.keyboard.press(
|
||||
process.platform === "darwin" ? "Meta+Digit0" : "Control+Digit0",
|
||||
);
|
||||
|
||||
await expect
|
||||
.poll(() => page.evaluate(() => window.__SPROUT_E2E_WEBVIEW_ZOOM__))
|
||||
.toBe(1);
|
||||
});
|
||||
|
||||
test("shows doctor checks for local sprout tooling", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user