Merge branch 'streamline-file-explorer'

This commit is contained in:
Mohamed Boudra
2026-02-04 11:14:31 +07:00
2 changed files with 25 additions and 7 deletions
@@ -36,7 +36,11 @@ import { useDaemonConnections } from "@/contexts/daemon-connections-context";
import { useSessionStore } from "@/stores/session-store"; import { useSessionStore } from "@/stores/session-store";
import { useDownloadStore } from "@/stores/download-store"; import { useDownloadStore } from "@/stores/download-store";
import { useFileExplorerActions } from "@/hooks/use-file-explorer-actions"; import { useFileExplorerActions } from "@/hooks/use-file-explorer-actions";
import { usePanelStore, type SortOption } from "@/stores/panel-store"; import {
usePanelStore,
DEFAULT_EXPLORER_FILES_SPLIT_RATIO,
type SortOption,
} from "@/stores/panel-store";
import { formatTimeAgo } from "@/utils/time"; import { formatTimeAgo } from "@/utils/time";
const SORT_OPTIONS: { value: SortOption; label: string }[] = [ const SORT_OPTIONS: { value: SortOption; label: string }[] = [
@@ -309,6 +313,10 @@ export function FileExplorerPane({ serverId, agentId }: FileExplorerPaneProps) {
const minTreeWidth = 220; const minTreeWidth = 220;
const minPreviewWidth = 320; const minPreviewWidth = 320;
const safeSplitRatio = Number.isFinite(splitRatio)
? splitRatio
: DEFAULT_EXPLORER_FILES_SPLIT_RATIO;
const treePaneWidth = useMemo(() => { const treePaneWidth = useMemo(() => {
if (!shouldShowInlinePreview || containerWidth <= 0) { if (!shouldShowInlinePreview || containerWidth <= 0) {
return null; return null;
@@ -316,9 +324,9 @@ export function FileExplorerPane({ serverId, agentId }: FileExplorerPaneProps) {
const available = Math.max(0, containerWidth - dividerWidth); const available = Math.max(0, containerWidth - dividerWidth);
const maxTree = Math.max(minTreeWidth, available - minPreviewWidth); const maxTree = Math.max(minTreeWidth, available - minPreviewWidth);
const raw = Math.round(available * splitRatio); const raw = Math.round(available * safeSplitRatio);
return Math.max(minTreeWidth, Math.min(maxTree, raw)); return Math.max(minTreeWidth, Math.min(maxTree, raw));
}, [containerWidth, shouldShowInlinePreview, splitRatio]); }, [containerWidth, safeSplitRatio, shouldShowInlinePreview]);
const resizeStartRef = useRef<{ startWidth: number; available: number } | null>(null); const resizeStartRef = useRef<{ startWidth: number; available: number } | null>(null);
@@ -332,6 +340,8 @@ export function FileExplorerPane({ serverId, agentId }: FileExplorerPaneProps) {
return Gesture.Pan() return Gesture.Pan()
.enabled(!isMobile) .enabled(!isMobile)
.runOnJS(true) .runOnJS(true)
.activeOffsetX([-2, 2])
.failOffsetY([-5, 5])
.hitSlop({ left: 12, right: 12, top: 0, bottom: 0 }) .hitSlop({ left: 12, right: 12, top: 0, bottom: 0 })
.onBegin(() => { .onBegin(() => {
resizeStartRef.current = { resizeStartRef.current = {
@@ -344,10 +354,10 @@ export function FileExplorerPane({ serverId, agentId }: FileExplorerPaneProps) {
if (!start) { if (!start) {
return; return;
} }
const nextWidth = start.startWidth + event.translationX; const nextWidth = start.startWidth + (event.translationX ?? 0);
const maxTree = Math.max(minTreeWidth, start.available - minPreviewWidth); const maxTree = Math.max(minTreeWidth, start.available - minPreviewWidth);
const clamped = Math.max(minTreeWidth, Math.min(maxTree, nextWidth)); const clamped = Math.max(minTreeWidth, Math.min(maxTree, nextWidth));
const nextRatio = start.available > 0 ? clamped / start.available : splitRatio; const nextRatio = start.available > 0 ? clamped / start.available : safeSplitRatio;
setSplitRatio(nextRatio); setSplitRatio(nextRatio);
}) })
.onFinalize(() => { .onFinalize(() => {
@@ -359,7 +369,7 @@ export function FileExplorerPane({ serverId, agentId }: FileExplorerPaneProps) {
isMobile, isMobile,
setSplitRatio, setSplitRatio,
shouldShowInlinePreview, shouldShowInlinePreview,
splitRatio, safeSplitRatio,
treePaneWidth, treePaneWidth,
]); ]);
@@ -519,6 +529,7 @@ export function FileExplorerPane({ serverId, agentId }: FileExplorerPaneProps) {
<> <>
<GestureDetector gesture={splitResizeGesture}> <GestureDetector gesture={splitResizeGesture}>
<View <View
pointerEvents="box-only"
style={[ style={[
styles.splitResizeHandle, styles.splitResizeHandle,
Platform.OS === "web" && ({ cursor: "col-resize" } as any), Platform.OS === "web" && ({ cursor: "col-resize" } as any),
+8 -1
View File
@@ -67,6 +67,9 @@ interface PanelState {
} }
function clampNumber(value: number, min: number, max: number): number { function clampNumber(value: number, min: number, max: number): number {
if (!Number.isFinite(value)) {
return min;
}
return Math.max(min, Math.min(max, value)); return Math.max(min, Math.min(max, value));
} }
@@ -153,7 +156,11 @@ export const usePanelStore = create<PanelState>()(
setExplorerWidth: (width) => set({ explorerWidth: clampWidth(width) }), setExplorerWidth: (width) => set({ explorerWidth: clampWidth(width) }),
setExplorerSortOption: (option) => set({ explorerSortOption: option }), setExplorerSortOption: (option) => set({ explorerSortOption: option }),
setExplorerFilesSplitRatio: (ratio) => setExplorerFilesSplitRatio: (ratio) =>
set({ explorerFilesSplitRatio: clampExplorerFilesSplitRatio(ratio) }), set({
explorerFilesSplitRatio: Number.isFinite(ratio)
? clampExplorerFilesSplitRatio(ratio)
: DEFAULT_EXPLORER_FILES_SPLIT_RATIO,
}),
}), }),
{ {
name: "panel-state", name: "panel-state",