Skip to content
Merged
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
2 changes: 1 addition & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function App() {
const { recentFolders, openRecentFolder } = useRecentFoldersStore();
const { loadAvailableFonts } = useFontStore.use.actions();
const setRemoteWindow = useSidebarStore.use.setRemoteWindow();
const zoomLevel = useZoomStore.use.zoomLevel();
const zoomLevel = useZoomStore.use.windowZoomLevel();

// Platform-specific setup
useEffect(() => {
Expand Down
4 changes: 2 additions & 2 deletions src/components/bottom-pane.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ const BottomPane = ({ diagnostics, onDiagnosticClick }: BottomPaneProps) => {
return (
<div
className={cn(
"z-100 flex flex-col border-border border-t bg-secondary-bg",
isFullScreen ? "fixed inset-x-0" : "relative",
"z-50 flex flex-col border-border border-t bg-secondary-bg",
isFullScreen ? "fixed inset-x-0" : "fixed inset-x-0 bottom-0",
!isBottomPaneVisible && "hidden",
"transition-all duration-200 ease-in-out",
)}
Expand Down
10 changes: 7 additions & 3 deletions src/components/editor-footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,9 @@ const LspStatusDropdown = ({ activeBuffer }: { activeBuffer: any }) => {
} catch (error) {
console.error("Failed to restart LSP:", error);
updateToast(toastId, {
message: `Failed to restart LSP: ${error instanceof Error ? error.message : "Unknown error"}`,
message: `Failed to restart LSP: ${
error instanceof Error ? error.message : "Unknown error"
}`,
type: "error",
duration: 5000,
});
Expand Down Expand Up @@ -117,7 +119,9 @@ const LspStatusDropdown = ({ activeBuffer }: { activeBuffer: any }) => {
} catch (error) {
console.error("Failed to toggle LSP:", error);
updateToast(toastId, {
message: `Failed to ${isCurrentlyConnected ? "disable" : "enable"} LSP: ${error instanceof Error ? error.message : "Unknown error"}`,
message: `Failed to ${isCurrentlyConnected ? "disable" : "enable"} LSP: ${
error instanceof Error ? error.message : "Unknown error"
}`,
type: "error",
duration: 5000,
});
Expand Down Expand Up @@ -237,7 +241,7 @@ const EditorFooter = () => {
const cursorPosition = useEditorCursorStore.use.cursorPosition();

return (
<div className="flex min-h-[32px] items-center justify-between border-border border-t bg-secondary-bg px-2 py-1">
<div className="flex min-h-[32px] items-center justify-between border-border border-t bg-secondary-bg px-2 py-1 ">
<div className="flex items-center gap-0.5 font-mono text-text-lighter text-xs">
{/* Git branch manager */}
{rootFolderPath && gitStatus?.branch && (
Expand Down
13 changes: 10 additions & 3 deletions src/components/editor/code-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { useEditorInstanceStore } from "@/stores/editor-instance-store";
import { useEditorSearchStore } from "@/stores/editor-search-store";
import { useEditorSettingsStore } from "@/stores/editor-settings-store";
import { useLspStore } from "@/stores/lsp-store";
import { useZoomStore } from "@/stores/zoom-store";
import { useGitGutter } from "@/version-control/git/controllers/use-git-gutter";
import FindBar from "../find-bar";
import Breadcrumb from "./breadcrumb";
Expand All @@ -36,13 +37,13 @@ export interface CodeEditorRef {

const CodeEditor = ({ className }: CodeEditorProps) => {
const editorRef = useRef<HTMLDivElement>(null as any);

const { setRefs, setContent, setFileInfo } = useEditorInstanceStore();
// No longer need to sync content - editor-view-store computes from buffer
const { setDisabled } = useEditorSettingsStore.use.actions();

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

// Get cursor position
const cursorPosition = useEditorCursorStore.use.cursorPosition();

// Track typing speed for dynamic debouncing
const lastTypeTimeRef = useRef<number>(Date.now());
const typingSpeedRef = useRef<number>(500);
Expand Down Expand Up @@ -264,7 +264,14 @@ const CodeEditor = ({ className }: CodeEditorProps) => {
<div
ref={editorRef}
className={`editor-container relative flex-1 overflow-hidden ${className || ""}`}
style={{ scrollbarWidth: "none", msOverflowStyle: "none" }}
style={{
scrollbarWidth: "none",
msOverflowStyle: "none",
transform: `scale(${zoomLevel})`,
transformOrigin: "top left",
width: `${100 / zoomLevel}%`,
height: `${100 / zoomLevel}%`,
}}
>
{/* Hover Tooltip */}
<HoverTooltip />
Expand Down
2 changes: 1 addition & 1 deletion src/components/layout/main-sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ export const MainSidebar = memo(() => {
}, [isGitViewActive, isSearchViewActive, isRemoteViewActive, isRemoteWindow]);

return (
<div className="flex h-full flex-col">
<div className="flex h-full flex-col ">
{/* Pane Selection Row */}
<SidebarPaneSelector
isGitViewActive={isGitViewActive}
Expand Down
14 changes: 13 additions & 1 deletion src/components/terminal/terminal-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type React from "react";
import { useCallback, useEffect, useRef, useState } from "react";
import { useTerminalTabs } from "@/hooks/use-terminal-tabs";
import { useUIState } from "@/stores/ui-state-store";
import { useZoomStore } from "@/stores/zoom-store";
import { cn } from "@/utils/cn";
import TerminalSession from "./terminal-session";
import TerminalTabBar from "./terminal-tab-bar";
Expand Down Expand Up @@ -37,6 +38,8 @@ const TerminalContainer = ({
setTerminalSplitMode,
} = useTerminalTabs();

const zoomLevel = useZoomStore.use.terminalZoomLevel();

const [renamingTerminalId, setRenamingTerminalId] = useState<string | null>(null);
const [newTerminalName, setNewTerminalName] = useState("");
const hasInitializedRef = useRef(false);
Expand Down Expand Up @@ -394,7 +397,16 @@ const TerminalContainer = ({
/>

{/* Terminal Sessions */}
<div className="relative bg-primary-bg" style={{ height: "calc(100% - 28px)" }}>
<div
className="relative bg-primary-bg"
style={{
//height: "calc(100% - 28px)",
transform: `scale(${zoomLevel})`,
transformOrigin: "top left",
width: `${100 / zoomLevel}%`,
height: `${100 / zoomLevel}%`,
}}
>
{(() => {
return (
<div className="h-full">
Expand Down
16 changes: 11 additions & 5 deletions src/components/zoom-indicator.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import { useMemo } from "react";
import { useZoomStore } from "../stores/zoom-store";
import { cn } from "../utils/cn";

export function ZoomIndicator() {
const showZoomIndicator = useZoomStore.use.showZoomIndicator();
const zoomLevel = useZoomStore.use.zoomLevel();
//const { getZoomPercentage } = useZoomStore.use.actions();
const windowZoomLevel = useZoomStore.use.windowZoomLevel();
const terminalZoomLevel = useZoomStore.use.terminalZoomLevel();

const zoomPercentage = useMemo(() => {
function getZoomPercentage(zoomLevel: number) {
return `${Math.round(zoomLevel * 100)}%`;
}, [zoomLevel]);
}

// const zoomPercentage = useMemo(() => {
// return `${Math.round(zoomLevel * 100)}%`;
// }, [zoomLevel]);

if (!showZoomIndicator) {
return null;
Expand All @@ -29,7 +34,8 @@ export function ZoomIndicator() {
animationFillMode: "forwards",
}}
>
{zoomPercentage}
Window: {getZoomPercentage(windowZoomLevel)}% Terminal: {getZoomPercentage(terminalZoomLevel)}
%
</div>
);
}
18 changes: 18 additions & 0 deletions src/hooks/use-active-dom-element.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { useEffect, useState } from "react";

export const useActiveElement = () => {
const [active, setActive] = useState(document.activeElement);

const handleFocusIn = (_e: FocusEvent) => {
setActive(document.activeElement);
};

useEffect(() => {
document.addEventListener("focusin", handleFocusIn);
return () => {
document.removeEventListener("focusin", handleFocusIn);
};
}, []);

return active;
};
28 changes: 25 additions & 3 deletions src/hooks/use-keyboard-shortcuts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import type { CoreFeaturesState } from "../settings/models/feature.types";
import { useZoomStore } from "../stores/zoom-store";
import type { Buffer } from "../types/buffer";

//import { useActiveElement } from "./use-active-dom-element";

interface UseKeyboardShortcutsProps {
setIsBottomPaneVisible: (value: boolean | ((prev: boolean) => boolean)) => void;
setBottomPaneActiveTab: (tab: "terminal" | "diagnostics") => void;
Expand Down Expand Up @@ -62,6 +64,8 @@ export const useKeyboardShortcuts = ({
const { settings } = useSettingsStore();
const { zoomIn, zoomOut, resetZoom } = useZoomStore.use.actions();

// const activeElement = useActiveElement();

useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
// Don't process regular shortcuts if vim mode is enabled and we're not using modifier keys
Expand Down Expand Up @@ -362,19 +366,37 @@ export const useKeyboardShortcuts = ({
// Zoom controls
if ((e.metaKey || e.ctrlKey) && (e.key === "=" || e.key === "+")) {
e.preventDefault();
zoomIn();
const terminalContainer = document.querySelector('[data-terminal-container="active"]');
const isTerminalFocused = terminalContainer?.contains(document.activeElement);
if (isTerminalFocused) {
zoomIn("terminal");
} else {
zoomIn("window");
}
return;
}

if ((e.metaKey || e.ctrlKey) && e.key === "-") {
e.preventDefault();
zoomOut();
const terminalContainer = document.querySelector('[data-terminal-container="active"]');
const isTerminalFocused = terminalContainer?.contains(document.activeElement);
if (isTerminalFocused) {
zoomOut("terminal");
} else {
zoomOut("window");
}
return;
}

if ((e.metaKey || e.ctrlKey) && e.key === "0") {
e.preventDefault();
resetZoom();
const terminalContainer = document.querySelector('[data-terminal-container="active"]');
const isTerminalFocused = terminalContainer?.contains(document.activeElement);
if (isTerminalFocused) {
resetZoom("terminal");
} else {
resetZoom("window");
}
return;
}

Expand Down
4 changes: 2 additions & 2 deletions src/hooks/use-scroll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ export function useScroll() {

if (e.deltaY < 0) {
// Scroll up = zoom in
zoomIn();
zoomIn("editor");
} else if (e.deltaY > 0) {
// Scroll down = zoom out
zoomOut();
zoomOut("editor");
}
}
};
Expand Down
41 changes: 26 additions & 15 deletions src/stores/zoom-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,24 @@ import { createSelectors } from "@/utils/zustand-selectors";
const ZOOM_LEVELS = [0.5, 0.75, 0.9, 1.0, 1.1, 1.25, 1.5, 1.75, 2.0, 2.5, 3.0];
const DEFAULT_ZOOM = 1.0;

type ZoomType = "window" | "editor" | "terminal";

interface ZoomState {
zoomLevel: number;
// zoomLevel: number;
windowZoomLevel: number;
editorZoomLevel: number;
terminalZoomLevel: number;
showZoomIndicator: boolean;
zoomIndicatorTimeout: NodeJS.Timeout | null;
actions: ZoomActions;
}

interface ZoomActions {
zoomIn: () => void;
zoomOut: () => void;
resetZoom: () => void;
zoomIn: (type: ZoomType) => void;
zoomOut: (type: ZoomType) => void;
resetZoom: (type: ZoomType) => void;
showZoomIndicatorTemporarily: () => void;
getZoomPercentage: (type: ZoomType) => number;
}

export const useZoomStore = createSelectors(
Expand All @@ -36,42 +42,47 @@ export const useZoomStore = createSelectors(
};

return {
zoomLevel: DEFAULT_ZOOM,
windowZoomLevel: DEFAULT_ZOOM,
editorZoomLevel: DEFAULT_ZOOM,
terminalZoomLevel: DEFAULT_ZOOM,
showZoomIndicator: false,
zoomIndicatorTimeout: null,
actions: {
zoomIn: () => {
const current = get().zoomLevel;
zoomIn: (type: ZoomType) => {
const current = get()[`${type}ZoomLevel`];
const currentIndex = ZOOM_LEVELS.findIndex((level) => level >= current);
const nextIndex = Math.min(currentIndex + 1, ZOOM_LEVELS.length - 1);
const newZoom = ZOOM_LEVELS[nextIndex];

console.log("zoomIn", type, newZoom);
if (newZoom !== current) {
set({ zoomLevel: newZoom });
set({ [`${type}ZoomLevel`]: newZoom });
showZoomIndicatorTemporarily();
}
},

zoomOut: () => {
const current = get().zoomLevel;
zoomOut: (type: ZoomType) => {
const current = get()[`${type}ZoomLevel`];
const currentIndex = ZOOM_LEVELS.findIndex((level) => level >= current);
const prevIndex = Math.max(currentIndex - 1, 0);
const newZoom = ZOOM_LEVELS[prevIndex];

if (newZoom !== current) {
set({ zoomLevel: newZoom });
set({ [`${type}ZoomLevel`]: newZoom });
showZoomIndicatorTemporarily();
}
},

resetZoom: () => {
if (get().zoomLevel !== DEFAULT_ZOOM) {
set({ zoomLevel: DEFAULT_ZOOM });
resetZoom: (type: ZoomType) => {
if ((get()[`${type}ZoomLevel` as keyof ZoomState] as number) !== DEFAULT_ZOOM) {
set({ [`${type}ZoomLevel`]: DEFAULT_ZOOM });
showZoomIndicatorTemporarily();
}
},

showZoomIndicatorTemporarily,

getZoomPercentage: (type: ZoomType) =>
Math.round((get()[`${type}ZoomLevel` as keyof ZoomState] as number) * 100),
},
};
}),
Expand Down
Loading