Skip to content

Commit 519540e

Browse files
authored
Add individual zoom to editor, terminal and window (#342)
* Feat individual zoom feature * Fix type errors for zoom * Add individual zoom to window,pane and terminal
1 parent 312fd89 commit 519540e

File tree

11 files changed

+116
-36
lines changed

11 files changed

+116
-36
lines changed

src/App.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ function App() {
3636
const { recentFolders, openRecentFolder } = useRecentFoldersStore();
3737
const { loadAvailableFonts } = useFontStore.use.actions();
3838
const setRemoteWindow = useSidebarStore.use.setRemoteWindow();
39-
const zoomLevel = useZoomStore.use.zoomLevel();
39+
const zoomLevel = useZoomStore.use.windowZoomLevel();
4040

4141
// Platform-specific setup
4242
useEffect(() => {

src/components/bottom-pane.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ const BottomPane = ({ diagnostics, onDiagnosticClick }: BottomPaneProps) => {
6767
return (
6868
<div
6969
className={cn(
70-
"z-100 flex flex-col border-border border-t bg-secondary-bg",
71-
isFullScreen ? "fixed inset-x-0" : "relative",
70+
"z-50 flex flex-col border-border border-t bg-secondary-bg",
71+
isFullScreen ? "fixed inset-x-0" : "fixed inset-x-0 bottom-0",
7272
!isBottomPaneVisible && "hidden",
7373
"transition-all duration-200 ease-in-out",
7474
)}

src/components/editor-footer.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,9 @@ const LspStatusDropdown = ({ activeBuffer }: { activeBuffer: any }) => {
8787
} catch (error) {
8888
console.error("Failed to restart LSP:", error);
8989
updateToast(toastId, {
90-
message: `Failed to restart LSP: ${error instanceof Error ? error.message : "Unknown error"}`,
90+
message: `Failed to restart LSP: ${
91+
error instanceof Error ? error.message : "Unknown error"
92+
}`,
9193
type: "error",
9294
duration: 5000,
9395
});
@@ -117,7 +119,9 @@ const LspStatusDropdown = ({ activeBuffer }: { activeBuffer: any }) => {
117119
} catch (error) {
118120
console.error("Failed to toggle LSP:", error);
119121
updateToast(toastId, {
120-
message: `Failed to ${isCurrentlyConnected ? "disable" : "enable"} LSP: ${error instanceof Error ? error.message : "Unknown error"}`,
122+
message: `Failed to ${isCurrentlyConnected ? "disable" : "enable"} LSP: ${
123+
error instanceof Error ? error.message : "Unknown error"
124+
}`,
121125
type: "error",
122126
duration: 5000,
123127
});
@@ -237,7 +241,7 @@ const EditorFooter = () => {
237241
const cursorPosition = useEditorCursorStore.use.cursorPosition();
238242

239243
return (
240-
<div className="flex min-h-[32px] items-center justify-between border-border border-t bg-secondary-bg px-2 py-1">
244+
<div className="flex min-h-[32px] items-center justify-between border-border border-t bg-secondary-bg px-2 py-1 ">
241245
<div className="flex items-center gap-0.5 font-mono text-text-lighter text-xs">
242246
{/* Git branch manager */}
243247
{rootFolderPath && gitStatus?.branch && (

src/components/editor/code-editor.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { useEditorInstanceStore } from "@/stores/editor-instance-store";
1313
import { useEditorSearchStore } from "@/stores/editor-search-store";
1414
import { useEditorSettingsStore } from "@/stores/editor-settings-store";
1515
import { useLspStore } from "@/stores/lsp-store";
16+
import { useZoomStore } from "@/stores/zoom-store";
1617
import { useGitGutter } from "@/version-control/git/controllers/use-git-gutter";
1718
import FindBar from "../find-bar";
1819
import Breadcrumb from "./breadcrumb";
@@ -36,13 +37,13 @@ export interface CodeEditorRef {
3637

3738
const CodeEditor = ({ className }: CodeEditorProps) => {
3839
const editorRef = useRef<HTMLDivElement>(null as any);
39-
4040
const { setRefs, setContent, setFileInfo } = useEditorInstanceStore();
4141
// No longer need to sync content - editor-view-store computes from buffer
4242
const { setDisabled } = useEditorSettingsStore.use.actions();
4343

4444
const buffers = useBufferStore.use.buffers();
4545
const activeBufferId = useBufferStore.use.activeBufferId();
46+
const zoomLevel = useZoomStore.use.editorZoomLevel();
4647
const activeBuffer = buffers.find((b) => b.id === activeBufferId) || null;
4748
const { handleContentChange } = useAppStore.use.actions();
4849
const { searchQuery, searchMatches, currentMatchIndex, setSearchMatches, setCurrentMatchIndex } =
@@ -146,7 +147,6 @@ const CodeEditor = ({ className }: CodeEditorProps) => {
146147

147148
// Get cursor position
148149
const cursorPosition = useEditorCursorStore.use.cursorPosition();
149-
150150
// Track typing speed for dynamic debouncing
151151
const lastTypeTimeRef = useRef<number>(Date.now());
152152
const typingSpeedRef = useRef<number>(500);
@@ -264,7 +264,14 @@ const CodeEditor = ({ className }: CodeEditorProps) => {
264264
<div
265265
ref={editorRef}
266266
className={`editor-container relative flex-1 overflow-hidden ${className || ""}`}
267-
style={{ scrollbarWidth: "none", msOverflowStyle: "none" }}
267+
style={{
268+
scrollbarWidth: "none",
269+
msOverflowStyle: "none",
270+
transform: `scale(${zoomLevel})`,
271+
transformOrigin: "top left",
272+
width: `${100 / zoomLevel}%`,
273+
height: `${100 / zoomLevel}%`,
274+
}}
268275
>
269276
{/* Hover Tooltip */}
270277
<HoverTooltip />

src/components/layout/main-sidebar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ export const MainSidebar = memo(() => {
144144
}, [isGitViewActive, isSearchViewActive, isRemoteViewActive, isRemoteWindow]);
145145

146146
return (
147-
<div className="flex h-full flex-col">
147+
<div className="flex h-full flex-col ">
148148
{/* Pane Selection Row */}
149149
<SidebarPaneSelector
150150
isGitViewActive={isGitViewActive}

src/components/terminal/terminal-container.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type React from "react";
22
import { useCallback, useEffect, useRef, useState } from "react";
33
import { useTerminalTabs } from "@/hooks/use-terminal-tabs";
44
import { useUIState } from "@/stores/ui-state-store";
5+
import { useZoomStore } from "@/stores/zoom-store";
56
import { cn } from "@/utils/cn";
67
import TerminalSession from "./terminal-session";
78
import TerminalTabBar from "./terminal-tab-bar";
@@ -37,6 +38,8 @@ const TerminalContainer = ({
3738
setTerminalSplitMode,
3839
} = useTerminalTabs();
3940

41+
const zoomLevel = useZoomStore.use.terminalZoomLevel();
42+
4043
const [renamingTerminalId, setRenamingTerminalId] = useState<string | null>(null);
4144
const [newTerminalName, setNewTerminalName] = useState("");
4245
const hasInitializedRef = useRef(false);
@@ -394,7 +397,16 @@ const TerminalContainer = ({
394397
/>
395398

396399
{/* Terminal Sessions */}
397-
<div className="relative bg-primary-bg" style={{ height: "calc(100% - 28px)" }}>
400+
<div
401+
className="relative bg-primary-bg"
402+
style={{
403+
//height: "calc(100% - 28px)",
404+
transform: `scale(${zoomLevel})`,
405+
transformOrigin: "top left",
406+
width: `${100 / zoomLevel}%`,
407+
height: `${100 / zoomLevel}%`,
408+
}}
409+
>
398410
{(() => {
399411
return (
400412
<div className="h-full">

src/components/zoom-indicator.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
1-
import { useMemo } from "react";
21
import { useZoomStore } from "../stores/zoom-store";
32
import { cn } from "../utils/cn";
43

54
export function ZoomIndicator() {
65
const showZoomIndicator = useZoomStore.use.showZoomIndicator();
7-
const zoomLevel = useZoomStore.use.zoomLevel();
6+
//const { getZoomPercentage } = useZoomStore.use.actions();
7+
const windowZoomLevel = useZoomStore.use.windowZoomLevel();
8+
const terminalZoomLevel = useZoomStore.use.terminalZoomLevel();
89

9-
const zoomPercentage = useMemo(() => {
10+
function getZoomPercentage(zoomLevel: number) {
1011
return `${Math.round(zoomLevel * 100)}%`;
11-
}, [zoomLevel]);
12+
}
13+
14+
// const zoomPercentage = useMemo(() => {
15+
// return `${Math.round(zoomLevel * 100)}%`;
16+
// }, [zoomLevel]);
1217

1318
if (!showZoomIndicator) {
1419
return null;
@@ -29,7 +34,8 @@ export function ZoomIndicator() {
2934
animationFillMode: "forwards",
3035
}}
3136
>
32-
{zoomPercentage}
37+
Window: {getZoomPercentage(windowZoomLevel)}% Terminal: {getZoomPercentage(terminalZoomLevel)}
38+
%
3339
</div>
3440
);
3541
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { useEffect, useState } from "react";
2+
3+
export const useActiveElement = () => {
4+
const [active, setActive] = useState(document.activeElement);
5+
6+
const handleFocusIn = (_e: FocusEvent) => {
7+
setActive(document.activeElement);
8+
};
9+
10+
useEffect(() => {
11+
document.addEventListener("focusin", handleFocusIn);
12+
return () => {
13+
document.removeEventListener("focusin", handleFocusIn);
14+
};
15+
}, []);
16+
17+
return active;
18+
};

src/hooks/use-keyboard-shortcuts.ts

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import type { CoreFeaturesState } from "../settings/models/feature.types";
66
import { useZoomStore } from "../stores/zoom-store";
77
import type { Buffer } from "../types/buffer";
88

9+
//import { useActiveElement } from "./use-active-dom-element";
10+
911
interface UseKeyboardShortcutsProps {
1012
setIsBottomPaneVisible: (value: boolean | ((prev: boolean) => boolean)) => void;
1113
setBottomPaneActiveTab: (tab: "terminal" | "diagnostics") => void;
@@ -62,6 +64,8 @@ export const useKeyboardShortcuts = ({
6264
const { settings } = useSettingsStore();
6365
const { zoomIn, zoomOut, resetZoom } = useZoomStore.use.actions();
6466

67+
// const activeElement = useActiveElement();
68+
6569
useEffect(() => {
6670
const handleKeyDown = (e: KeyboardEvent) => {
6771
// Don't process regular shortcuts if vim mode is enabled and we're not using modifier keys
@@ -362,19 +366,37 @@ export const useKeyboardShortcuts = ({
362366
// Zoom controls
363367
if ((e.metaKey || e.ctrlKey) && (e.key === "=" || e.key === "+")) {
364368
e.preventDefault();
365-
zoomIn();
369+
const terminalContainer = document.querySelector('[data-terminal-container="active"]');
370+
const isTerminalFocused = terminalContainer?.contains(document.activeElement);
371+
if (isTerminalFocused) {
372+
zoomIn("terminal");
373+
} else {
374+
zoomIn("window");
375+
}
366376
return;
367377
}
368378

369379
if ((e.metaKey || e.ctrlKey) && e.key === "-") {
370380
e.preventDefault();
371-
zoomOut();
381+
const terminalContainer = document.querySelector('[data-terminal-container="active"]');
382+
const isTerminalFocused = terminalContainer?.contains(document.activeElement);
383+
if (isTerminalFocused) {
384+
zoomOut("terminal");
385+
} else {
386+
zoomOut("window");
387+
}
372388
return;
373389
}
374390

375391
if ((e.metaKey || e.ctrlKey) && e.key === "0") {
376392
e.preventDefault();
377-
resetZoom();
393+
const terminalContainer = document.querySelector('[data-terminal-container="active"]');
394+
const isTerminalFocused = terminalContainer?.contains(document.activeElement);
395+
if (isTerminalFocused) {
396+
resetZoom("terminal");
397+
} else {
398+
resetZoom("window");
399+
}
378400
return;
379401
}
380402

src/hooks/use-scroll.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ export function useScroll() {
1616

1717
if (e.deltaY < 0) {
1818
// Scroll up = zoom in
19-
zoomIn();
19+
zoomIn("editor");
2020
} else if (e.deltaY > 0) {
2121
// Scroll down = zoom out
22-
zoomOut();
22+
zoomOut("editor");
2323
}
2424
}
2525
};

0 commit comments

Comments
 (0)