Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Works with any CLI agent. Built for local worktree-based development.
| **大規模ファイル diff 高速化** | 2000行超のファイルで CodeMirror 6 ベースの仮想化 diff ビューアに自動切替。ビューポート分のDOMのみ描画し、15000行でもスムーズ表示。既存テーマ・シンタックスハイライト再利用、未変更領域の自動折りたたみ | [#5](https://github.com/MocA-Love/superset/pull/5) | 2026-03-28 |
| **ports.json ポートの常時表示** | ports.json に定義されたポートをプロセス検出の有無にかかわらず常にサイドバーに表示。Docker 等で検知できないポートもラベル付きで一覧に出る。検出済みポートは従来通りアクティブ表示、未検出は グレー表示で区別 | [#7](https://github.com/MocA-Love/superset/pull/7) | 2026-03-28 |
| **Ports ワークスペース名の改善** | Ports セクションのワークスペース名をワークツリーのディレクトリ名ベースに変更。同名ワークスペースが複数ある場合でもどのワークツリーか一目で区別可能 | [#8](https://github.com/MocA-Love/superset/pull/8) | 2026-03-28 |
| **ブラウザタブのズーム機能** | ブラウザタブのツールバーに拡大(+)・縮小(-)・リセットボタンを追加。webview の zoom API を直接操作し、50%〜200% の範囲でズーム可能。パーセント表示クリックで 100% にリセット | [#9](https://github.com/MocA-Love/superset/pull/9) | 2026-03-29 |

## Fork のビルド方法 (macOS)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Tooltip, TooltipContent, TooltipTrigger } from "@superset/ui/tooltip";
import { GlobeIcon } from "lucide-react";
import { useCallback } from "react";
import { useCallback, useState } from "react";
import { LuMinus, LuPlus } from "react-icons/lu";
import { TbDeviceDesktop } from "react-icons/tb";
import type { MosaicBranch } from "react-mosaic-component";
import { electronTrpc } from "renderer/lib/electron-trpc";
Expand Down Expand Up @@ -53,11 +54,38 @@ export function BrowserPane({
navigateTo,
canGoBack,
canGoForward,
setGuestZoom,
} = usePersistentWebview({
paneId,
initialUrl: currentUrl,
});

// -- Zoom state (CSS zoom injected into guest page) ---------------------

const ZOOM_STEP = 10;
const ZOOM_MIN = 50;
const ZOOM_MAX = 200;

const [zoomPercent, setZoomPercent] = useState(100);

const applyZoom = useCallback(
(percent: number) => {
setZoomPercent(percent);
setGuestZoom(percent / 100);
},
[setGuestZoom],
);

const zoomIn = useCallback(
() => applyZoom(Math.min(ZOOM_MAX, zoomPercent + ZOOM_STEP)),
[applyZoom, zoomPercent],
);
const zoomOut = useCallback(
() => applyZoom(Math.max(ZOOM_MIN, zoomPercent - ZOOM_STEP)),
[applyZoom, zoomPercent],
);
const resetZoom = useCallback(() => applyZoom(100), [applyZoom]);

const handleOpenDevTools = useCallback(() => {
openDevTools({ paneId });
}, [openDevTools, paneId]);
Expand Down Expand Up @@ -92,6 +120,50 @@ export function BrowserPane({
closeHotkeyId="CLOSE_TERMINAL"
leadingActions={
<>
<div className="flex items-center gap-0.5">
<Tooltip>
<TooltipTrigger asChild>
<button
type="button"
onClick={zoomOut}
className="rounded p-0.5 text-muted-foreground/60 transition-colors hover:text-muted-foreground"
>
<LuMinus className="size-3.5" />
</button>
</TooltipTrigger>
<TooltipContent side="bottom" showArrow={false}>
Zoom Out
</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger asChild>
<button
type="button"
onClick={resetZoom}
className="rounded px-1 py-0.5 text-[10px] tabular-nums text-muted-foreground/60 transition-colors hover:text-muted-foreground"
>
{zoomPercent}%
</button>
</TooltipTrigger>
<TooltipContent side="bottom" showArrow={false}>
Reset Zoom
</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger asChild>
<button
type="button"
onClick={zoomIn}
className="rounded p-0.5 text-muted-foreground/60 transition-colors hover:text-muted-foreground"
>
<LuPlus className="size-3.5" />
</button>
</TooltipTrigger>
<TooltipContent side="bottom" showArrow={false}>
Zoom In
</TooltipContent>
</Tooltip>
</div>
<Tooltip>
<TooltipTrigger asChild>
<button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ const webviewRegistry = new Map<string, Electron.WebviewTag>();
const wrapperRegistry = new Map<string, HTMLDivElement>();
/** Tracks paneId → last-registered webContentsId so we can re-register if it changes. */
const registeredWebContentsIds = new Map<string, number>();
/** Tracks paneId → current CSS zoom factor so it can be re-applied after page loads. */
const zoomFactorRegistry = new Map<string, number>();
let hiddenContainer: HTMLDivElement | null = null;

function getHiddenContainer(): HTMLDivElement {
Expand Down Expand Up @@ -84,6 +86,7 @@ export function destroyPersistentWebview(paneId: string): void {
webviewRegistry.delete(paneId);
}
registeredWebContentsIds.delete(paneId);
zoomFactorRegistry.delete(paneId);
}

// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -275,24 +278,31 @@ export function usePersistentWebview({

if (isHistoryNavigation.current) {
isHistoryNavigation.current = false;
return;
} else {
const url = wv.getURL();
const title = wv.getTitle();
store.updateBrowserUrl(
paneId,
url ?? "",
title ?? "",
faviconUrlRef.current,
);

if (url && url !== "about:blank") {
upsertHistory({
url,
title: title ?? "",
faviconUrl: faviconUrlRef.current ?? null,
});
}
}

const url = wv.getURL();
const title = wv.getTitle();
store.updateBrowserUrl(
paneId,
url ?? "",
title ?? "",
faviconUrlRef.current,
);

if (url && url !== "about:blank") {
upsertHistory({
url,
title: title ?? "",
faviconUrl: faviconUrlRef.current ?? null,
});
// Re-apply CSS zoom after page load (zoom is lost on navigation/reload)
const factor = zoomFactorRegistry.get(paneId);
if (factor != null && factor !== 1) {
wv.executeJavaScript(
`document.documentElement.style.zoom = '${factor}'`,
).catch(() => {});
}
};

Expand Down Expand Up @@ -459,6 +469,23 @@ export function usePersistentWebview({
[paneId],
);

// -- Zoom (CSS zoom injected into guest page — guaranteed host-safe) ----

const setGuestZoom = useCallback(
(factor: number) => {
zoomFactorRegistry.set(paneId, factor);
const webview = webviewRegistry.get(paneId);
if (webview) {
webview
.executeJavaScript(
`document.documentElement.style.zoom = '${factor}'`,
)
.catch(() => {});
}
},
[paneId],
);

return {
containerRef,
goBack,
Expand All @@ -467,5 +494,6 @@ export function usePersistentWebview({
navigateTo,
canGoBack,
canGoForward,
setGuestZoom,
};
}