дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-09 11:15:40 +02:00
feat(zoom): route Increase/Decrease Font Size across editors, terminals and WebViews (#2172)
Increase, Decrease and Reset Font Size only reached the active CodeMirror editor, so they did nothing with focus in a terminal or plugin WebView. They now apply to the focused surface through a shared workbench service: an editor tab, a terminal tab (which refits), or a plugin WebView. Wheel zoom stays pointer-based. Co-authored-by: dengliu <[email protected]>
Цей коміт міститься в:
1 джерело
ea8e04e448
коміт
62a39dadb7
9 files changed
+259
-9
No files matched your search
@@ -102,6 +102,31 @@ describe("web view helpers", () => {
|
||||
});
|
||||
|
||||
describe("frame bridge", () => {
|
||||
it("accepts bounded zoom only from its parent with the bridge tag", () => {
|
||||
const script = /<script>([\s\S]*)<\/script>/.exec(frameDocument("", { dark: true, vars: {} }))![1]!;
|
||||
const parent = {};
|
||||
const handlers = new Map<string, (e: { source: object; data: object }) => void>();
|
||||
const root = document.createElement("html");
|
||||
const frameWindow = {
|
||||
parent,
|
||||
addEventListener: (type: string, fn: (e: { source: object; data: object }) => void) => handlers.set(type, fn),
|
||||
};
|
||||
new Function("window", "document", script)(frameWindow, { documentElement: root });
|
||||
const send = (source: object, data: object) => handlers.get("message")!({ source, data });
|
||||
send({}, { tag: FRAME_TAG, fontZoomDelta: 1 });
|
||||
send(parent, { tag: "other", fontZoomDelta: 1 });
|
||||
send(parent, { tag: FRAME_TAG, fontZoomDelta: NaN });
|
||||
send(parent, { tag: FRAME_TAG, fontZoomDelta: 100 });
|
||||
expect(root.style.zoom).toBe("");
|
||||
send(parent, { tag: FRAME_TAG, fontZoomDelta: 1 });
|
||||
expect(root.style.zoom).toBe("1.08");
|
||||
send(parent, { tag: FRAME_TAG, fontZoomDelta: -1 });
|
||||
expect(root.style.zoom).toBe("");
|
||||
send(parent, { tag: FRAME_TAG, fontZoomDelta: 1 });
|
||||
send(parent, { tag: FRAME_TAG, fontZoomDelta: 0 });
|
||||
expect(root.style.zoom).toBe("");
|
||||
});
|
||||
|
||||
it("asks the workbench for the document and edits it, and hears of changes made elsewhere", async () => {
|
||||
const script = /<script>([\s\S]*)<\/script>/.exec(frameDocument("", { dark: true, vars: {} }))![1]!;
|
||||
const sent: Array<{ call: number; op: string; args: unknown }> = [];
|
||||
|
||||
@@ -20,7 +20,7 @@ import { tx } from "@/platform/i18n";
|
||||
import { useProject } from "@/platform/project";
|
||||
import { subscribeTheme, themeKey } from "@/platform/themeWatch";
|
||||
import { EmptyState, Spinner } from "@/ui";
|
||||
import { editorService } from "@/workbench/contributions";
|
||||
import { editorService, registerFontZoomSurface } from "@/workbench/contributions";
|
||||
import { ToolWindowCornerActions, useOwnToolWindowHeader } from "@/workbench/toolwindows/ToolWindows";
|
||||
import { pluginsBackend, type FileFilter } from "../backend";
|
||||
import { errorText, usePlugins } from "../store";
|
||||
@@ -164,6 +164,10 @@ export function WebView({ pluginId, view, label, header = "default", document =
|
||||
const post = useCallback((message: object, transfer: Transferable[] = []) => {
|
||||
frame.current?.contentWindow?.postMessage({ tag: FRAME_TAG, ...message }, "*", transfer);
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
const host = frame.current;
|
||||
if (host) return registerFontZoomSurface(host, (delta) => post({ fontZoomDelta: delta }));
|
||||
}, [page, post]);
|
||||
const postTheme = useCallback(() => {
|
||||
const t = frameTheme();
|
||||
if (ownHeader) {
|
||||
@@ -360,6 +364,7 @@ export function WebView({ pluginId, view, label, header = "default", document =
|
||||
<iframe
|
||||
ref={frame}
|
||||
className={styles.frame}
|
||||
data-plugin-webview={pluginId}
|
||||
title={label}
|
||||
sandbox="allow-scripts"
|
||||
allow={clipboard ? "clipboard-read; clipboard-write" : undefined}
|
||||
|
||||
@@ -60,12 +60,18 @@
|
||||
|
||||
if (initialTheme) applyTheme(initialTheme);
|
||||
|
||||
const stepFrameFontZoom = (delta) => {
|
||||
const cur = Math.round((parseFloat(root.style.zoom || "1") || 1) * 100);
|
||||
const next = delta === 0 ? 100 : Math.max(60, Math.min(200, cur + delta * 8));
|
||||
root.style.zoom = next === 100 ? "" : (next / 100).toFixed(2);
|
||||
};
|
||||
|
||||
// IDE shortcuts (Save, Close, Find Action…) pressed while the page has focus:
|
||||
// the ones the page left alone go to the workbench. Editing keys stay here.
|
||||
const EDITING_KEYS = new Set(["a", "c", "v", "x", "z", "y"]);
|
||||
window.addEventListener("keydown", (e) => {
|
||||
const fn = /^F\d{1,2}$/.test(e.key);
|
||||
const mod = (e.metaKey || e.ctrlKey) && !EDITING_KEYS.has(e.key.toLowerCase());
|
||||
const mod = (e.metaKey || e.ctrlKey || e.altKey) && !EDITING_KEYS.has(e.key.toLowerCase());
|
||||
if (e.isComposing || (!fn && !mod)) return;
|
||||
// After every handler of the page has seen it.
|
||||
setTimeout(() => {
|
||||
@@ -78,6 +84,8 @@
|
||||
const m = e.data;
|
||||
if (e.source !== window.parent || !m || m.tag !== TAG) return;
|
||||
if (m.theme) applyTheme(m.theme);
|
||||
else if (m.fontZoomDelta === -1 || m.fontZoomDelta === 0 || m.fontZoomDelta === 1)
|
||||
stepFrameFontZoom(m.fontZoomDelta);
|
||||
else if (typeof m.reply === "number") {
|
||||
const p = pending.get(m.reply);
|
||||
pending.delete(m.reply);
|
||||
|
||||
Reference in new issue
Заблокувати користувача