feat(app): persist expanded state in file explorer and diff panes
Remember which directories and diff entries are expanded across sidebar close/reopen cycles. State is stored per-workspace in the panel store (zustand + AsyncStorage) with no local React state copy, following the proven explorerTabByCheckout pattern. On desktop remount, expanded subdirectory listings are re-fetched so the tree renders fully.
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
import { useCallback, useEffect, useMemo, useRef } from "react";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import {
|
import {
|
||||||
ActivityIndicator,
|
ActivityIndicator,
|
||||||
@@ -118,7 +118,6 @@ export function FileExplorerPane({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
workspaceStateKey: actionsWorkspaceStateKey,
|
|
||||||
requestDirectoryListing,
|
requestDirectoryListing,
|
||||||
requestFileDownloadToken,
|
requestFileDownloadToken,
|
||||||
selectExplorerEntry,
|
selectExplorerEntry,
|
||||||
@@ -129,6 +128,16 @@ export function FileExplorerPane({
|
|||||||
});
|
});
|
||||||
const sortOption = usePanelStore((state) => state.explorerSortOption);
|
const sortOption = usePanelStore((state) => state.explorerSortOption);
|
||||||
const setSortOption = usePanelStore((state) => state.setExplorerSortOption);
|
const setSortOption = usePanelStore((state) => state.setExplorerSortOption);
|
||||||
|
const expandedPathsArray = usePanelStore((state) =>
|
||||||
|
workspaceStateKey ? state.expandedPathsByWorkspace[workspaceStateKey] : undefined,
|
||||||
|
);
|
||||||
|
const setExpandedPathsForWorkspace = usePanelStore(
|
||||||
|
(state) => state.setExpandedPathsForWorkspace,
|
||||||
|
);
|
||||||
|
const expandedPaths = useMemo(
|
||||||
|
() => new Set(expandedPathsArray && expandedPathsArray.length > 0 ? expandedPathsArray : ["."]),
|
||||||
|
[expandedPathsArray],
|
||||||
|
);
|
||||||
|
|
||||||
const directories = explorerState?.directories ?? new Map();
|
const directories = explorerState?.directories ?? new Map();
|
||||||
const pendingRequest = explorerState?.pendingRequest ?? null;
|
const pendingRequest = explorerState?.pendingRequest ?? null;
|
||||||
@@ -144,7 +153,6 @@ export function FileExplorerPane({
|
|||||||
[isExplorerLoading, pendingRequest?.mode, pendingRequest?.path],
|
[isExplorerLoading, pendingRequest?.mode, pendingRequest?.path],
|
||||||
);
|
);
|
||||||
|
|
||||||
const [expandedPaths, setExpandedPaths] = useState<Set<string>>(() => new Set(["."]));
|
|
||||||
const treeListRef = useRef<FlatList<TreeRow>>(null);
|
const treeListRef = useRef<FlatList<TreeRow>>(null);
|
||||||
const scrollbar = useWebScrollViewScrollbar(treeListRef, {
|
const scrollbar = useWebScrollViewScrollbar(treeListRef, {
|
||||||
enabled: showDesktopWebScrollbar,
|
enabled: showDesktopWebScrollbar,
|
||||||
@@ -154,8 +162,7 @@ export function FileExplorerPane({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
hasInitializedRef.current = false;
|
hasInitializedRef.current = false;
|
||||||
setExpandedPaths(new Set(["."]));
|
}, [workspaceStateKey]);
|
||||||
}, [actionsWorkspaceStateKey]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!hasWorkspaceScope) {
|
if (!hasWorkspaceScope) {
|
||||||
@@ -169,23 +176,35 @@ export function FileExplorerPane({
|
|||||||
recordHistory: false,
|
recordHistory: false,
|
||||||
setCurrentPath: false,
|
setCurrentPath: false,
|
||||||
});
|
});
|
||||||
}, [hasWorkspaceScope, requestDirectoryListing]);
|
const persistedPaths = usePanelStore.getState().expandedPathsByWorkspace[workspaceStateKey ?? ""];
|
||||||
|
if (persistedPaths) {
|
||||||
|
for (const path of persistedPaths) {
|
||||||
|
if (path !== ".") {
|
||||||
|
void requestDirectoryListing(path, {
|
||||||
|
recordHistory: false,
|
||||||
|
setCurrentPath: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [hasWorkspaceScope, requestDirectoryListing, workspaceStateKey]);
|
||||||
|
|
||||||
// Expand ancestor directories when a file is selected (e.g., from an inline path click)
|
// Expand ancestor directories when a file is selected (e.g., from an inline path click)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!selectedEntryPath || !hasWorkspaceScope) {
|
if (!selectedEntryPath || !workspaceStateKey) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const parentDir = getParentDirectory(selectedEntryPath);
|
const parentDir = getParentDirectory(selectedEntryPath);
|
||||||
const ancestors = getAncestorDirectories(parentDir);
|
const ancestors = getAncestorDirectories(parentDir);
|
||||||
|
const newPaths = ancestors.filter((path) => !expandedPaths.has(path));
|
||||||
setExpandedPaths((prev) => {
|
if (newPaths.length === 0) {
|
||||||
const next = new Set(prev);
|
return;
|
||||||
ancestors.forEach((path) => next.add(path));
|
}
|
||||||
return next;
|
setExpandedPathsForWorkspace(
|
||||||
});
|
workspaceStateKey,
|
||||||
|
[...Array.from(expandedPaths), ...newPaths],
|
||||||
ancestors.forEach((path) => {
|
);
|
||||||
|
newPaths.forEach((path) => {
|
||||||
if (!directories.has(path)) {
|
if (!directories.has(path)) {
|
||||||
void requestDirectoryListing(path, {
|
void requestDirectoryListing(path, {
|
||||||
recordHistory: false,
|
recordHistory: false,
|
||||||
@@ -193,34 +212,46 @@ export function FileExplorerPane({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, [directories, hasWorkspaceScope, requestDirectoryListing, selectedEntryPath]);
|
}, [
|
||||||
|
directories,
|
||||||
|
workspaceStateKey,
|
||||||
|
expandedPaths,
|
||||||
|
requestDirectoryListing,
|
||||||
|
selectedEntryPath,
|
||||||
|
setExpandedPathsForWorkspace,
|
||||||
|
]);
|
||||||
|
|
||||||
const handleToggleDirectory = useCallback(
|
const handleToggleDirectory = useCallback(
|
||||||
(entry: ExplorerEntry) => {
|
(entry: ExplorerEntry) => {
|
||||||
if (!hasWorkspaceScope) {
|
if (!workspaceStateKey) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isExpanded = expandedPaths.has(entry.path);
|
const isExpanded = expandedPaths.has(entry.path);
|
||||||
const nextExpanded = !isExpanded;
|
if (isExpanded) {
|
||||||
setExpandedPaths((prev) => {
|
setExpandedPathsForWorkspace(
|
||||||
const next = new Set(prev);
|
workspaceStateKey,
|
||||||
if (isExpanded) {
|
Array.from(expandedPaths).filter((path) => path !== entry.path),
|
||||||
next.delete(entry.path);
|
);
|
||||||
} else {
|
} else {
|
||||||
next.add(entry.path);
|
setExpandedPathsForWorkspace(
|
||||||
|
workspaceStateKey,
|
||||||
|
[...Array.from(expandedPaths), entry.path],
|
||||||
|
);
|
||||||
|
if (!directories.has(entry.path)) {
|
||||||
|
void requestDirectoryListing(entry.path, {
|
||||||
|
recordHistory: false,
|
||||||
|
setCurrentPath: false,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return next;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (nextExpanded && !directories.has(entry.path)) {
|
|
||||||
void requestDirectoryListing(entry.path, {
|
|
||||||
recordHistory: false,
|
|
||||||
setCurrentPath: false,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[directories, expandedPaths, hasWorkspaceScope, requestDirectoryListing],
|
[
|
||||||
|
workspaceStateKey,
|
||||||
|
expandedPaths,
|
||||||
|
directories,
|
||||||
|
requestDirectoryListing,
|
||||||
|
setExpandedPathsForWorkspace,
|
||||||
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleOpenFile = useCallback(
|
const handleOpenFile = useCallback(
|
||||||
|
|||||||
@@ -72,6 +72,8 @@ import { useWebScrollViewScrollbar } from "@/components/use-web-scrollbar";
|
|||||||
import { buildNewAgentRoute, resolveNewAgentWorkingDir } from "@/utils/new-agent-routing";
|
import { buildNewAgentRoute, resolveNewAgentWorkingDir } from "@/utils/new-agent-routing";
|
||||||
import { openExternalUrl } from "@/utils/open-external-url";
|
import { openExternalUrl } from "@/utils/open-external-url";
|
||||||
import { GitActionsSplitButton } from "@/components/git-actions-split-button";
|
import { GitActionsSplitButton } from "@/components/git-actions-split-button";
|
||||||
|
import { usePanelStore } from "@/stores/panel-store";
|
||||||
|
import { buildWorkspaceExplorerStateKey } from "@/hooks/use-file-explorer-actions";
|
||||||
|
|
||||||
export type { GitActionId, GitAction, GitActions } from "@/components/git-actions-policy";
|
export type { GitActionId, GitAction, GitActions } from "@/components/git-actions-policy";
|
||||||
|
|
||||||
@@ -541,7 +543,25 @@ export function GitDiffPane({ serverId, workspaceId, cwd, hideHeaderRow }: GitDi
|
|||||||
});
|
});
|
||||||
// Track user-initiated refresh to avoid iOS RefreshControl animation on background fetches
|
// Track user-initiated refresh to avoid iOS RefreshControl animation on background fetches
|
||||||
const [isManualRefresh, setIsManualRefresh] = useState(false);
|
const [isManualRefresh, setIsManualRefresh] = useState(false);
|
||||||
const [expandedByPath, setExpandedByPath] = useState<Record<string, boolean>>({});
|
const normalizedWorkspaceRoot = useMemo(() => cwd.trim(), [cwd]);
|
||||||
|
const workspaceStateKey = useMemo(
|
||||||
|
() =>
|
||||||
|
buildWorkspaceExplorerStateKey({
|
||||||
|
workspaceId,
|
||||||
|
workspaceRoot: normalizedWorkspaceRoot,
|
||||||
|
}),
|
||||||
|
[normalizedWorkspaceRoot, workspaceId],
|
||||||
|
);
|
||||||
|
const expandedPathsArray = usePanelStore((state) =>
|
||||||
|
workspaceStateKey ? state.diffExpandedPathsByWorkspace[workspaceStateKey] : undefined,
|
||||||
|
);
|
||||||
|
const setDiffExpandedPathsForWorkspace = usePanelStore(
|
||||||
|
(state) => state.setDiffExpandedPathsForWorkspace,
|
||||||
|
);
|
||||||
|
const expandedPaths = useMemo(
|
||||||
|
() => new Set(expandedPathsArray ?? []),
|
||||||
|
[expandedPathsArray],
|
||||||
|
);
|
||||||
const diffListRef = useRef<FlatList<DiffFlatItem>>(null);
|
const diffListRef = useRef<FlatList<DiffFlatItem>>(null);
|
||||||
const scrollbar = useWebScrollViewScrollbar(diffListRef, {
|
const scrollbar = useWebScrollViewScrollbar(diffListRef, {
|
||||||
enabled: showDesktopWebScrollbar,
|
enabled: showDesktopWebScrollbar,
|
||||||
@@ -601,7 +621,7 @@ export function GitDiffPane({ serverId, workspaceId, cwd, hideHeaderRow }: GitDi
|
|||||||
const stickyIndices: number[] = [];
|
const stickyIndices: number[] = [];
|
||||||
for (let i = 0; i < files.length; i++) {
|
for (let i = 0; i < files.length; i++) {
|
||||||
const file = files[i];
|
const file = files[i];
|
||||||
const isExpanded = expandedByPath[file.path] ?? false;
|
const isExpanded = expandedPaths.has(file.path);
|
||||||
items.push({ type: "header", file, fileIndex: i, isExpanded });
|
items.push({ type: "header", file, fileIndex: i, isExpanded });
|
||||||
if (isExpanded) {
|
if (isExpanded) {
|
||||||
stickyIndices.push(items.length - 1);
|
stickyIndices.push(items.length - 1);
|
||||||
@@ -611,7 +631,7 @@ export function GitDiffPane({ serverId, workspaceId, cwd, hideHeaderRow }: GitDi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { flatItems: items, stickyHeaderIndices: stickyIndices };
|
return { flatItems: items, stickyHeaderIndices: stickyIndices };
|
||||||
}, [files, expandedByPath]);
|
}, [expandedPaths, files]);
|
||||||
|
|
||||||
const handleHeaderHeightChange = useCallback((path: string, height: number) => {
|
const handleHeaderHeightChange = useCallback((path: string, height: number) => {
|
||||||
if (!Number.isFinite(height) || height <= 0) {
|
if (!Number.isFinite(height) || height <= 0) {
|
||||||
@@ -657,18 +677,21 @@ export function GitDiffPane({ serverId, workspaceId, cwd, hideHeaderRow }: GitDi
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
offset += headerHeightByPathRef.current[file.path] ?? defaultHeaderHeight;
|
offset += headerHeightByPathRef.current[file.path] ?? defaultHeaderHeight;
|
||||||
if (expandedByPath[file.path]) {
|
if (expandedPaths.has(file.path)) {
|
||||||
offset += bodyHeightByPathRef.current[file.path] ?? 0;
|
offset += bodyHeightByPathRef.current[file.path] ?? 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Math.max(0, offset);
|
return Math.max(0, offset);
|
||||||
},
|
},
|
||||||
[expandedByPath, files],
|
[expandedPaths, files],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleToggleExpanded = useCallback(
|
const handleToggleExpanded = useCallback(
|
||||||
(path: string) => {
|
(path: string) => {
|
||||||
const isCurrentlyExpanded = expandedByPath[path] ?? false;
|
if (!workspaceStateKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const isCurrentlyExpanded = expandedPaths.has(path);
|
||||||
const nextExpanded = !isCurrentlyExpanded;
|
const nextExpanded = !isCurrentlyExpanded;
|
||||||
const targetOffset = isCurrentlyExpanded ? computeHeaderOffset(path) : null;
|
const targetOffset = isCurrentlyExpanded ? computeHeaderOffset(path) : null;
|
||||||
const headerHeight = headerHeightByPathRef.current[path] ?? defaultHeaderHeightRef.current;
|
const headerHeight = headerHeightByPathRef.current[path] ?? defaultHeaderHeightRef.current;
|
||||||
@@ -690,32 +713,32 @@ export function GitDiffPane({ serverId, workspaceId, cwd, hideHeaderRow }: GitDi
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setExpandedByPath((prev) => ({
|
const nextPaths = nextExpanded
|
||||||
...prev,
|
? [...expandedPaths, path]
|
||||||
// Use a deterministic target value (instead of toggling from prev) so duplicate
|
: Array.from(expandedPaths).filter((expandedPath) => expandedPath !== path);
|
||||||
// onPress events from sticky headers on Android can't flip back immediately.
|
setDiffExpandedPathsForWorkspace(workspaceStateKey, nextPaths);
|
||||||
[path]: nextExpanded,
|
|
||||||
}));
|
|
||||||
},
|
},
|
||||||
[computeHeaderOffset, expandedByPath],
|
[computeHeaderOffset, expandedPaths, setDiffExpandedPathsForWorkspace, workspaceStateKey],
|
||||||
);
|
);
|
||||||
|
|
||||||
const allExpanded = useMemo(() => {
|
const allExpanded = useMemo(() => {
|
||||||
if (files.length === 0) return false;
|
if (files.length === 0) return false;
|
||||||
return files.every((file) => expandedByPath[file.path]);
|
return files.every((file) => expandedPaths.has(file.path));
|
||||||
}, [files, expandedByPath]);
|
}, [expandedPaths, files]);
|
||||||
|
|
||||||
const handleToggleExpandAll = useCallback(() => {
|
const handleToggleExpandAll = useCallback(() => {
|
||||||
if (allExpanded) {
|
if (!workspaceStateKey) {
|
||||||
setExpandedByPath({});
|
return;
|
||||||
} else {
|
|
||||||
const newExpanded: Record<string, boolean> = {};
|
|
||||||
for (const file of files) {
|
|
||||||
newExpanded[file.path] = true;
|
|
||||||
}
|
|
||||||
setExpandedByPath(newExpanded);
|
|
||||||
}
|
}
|
||||||
}, [allExpanded, files]);
|
if (allExpanded) {
|
||||||
|
setDiffExpandedPathsForWorkspace(workspaceStateKey, []);
|
||||||
|
} else {
|
||||||
|
setDiffExpandedPathsForWorkspace(
|
||||||
|
workspaceStateKey,
|
||||||
|
files.map((file) => file.path),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [allExpanded, files, setDiffExpandedPathsForWorkspace, workspaceStateKey]);
|
||||||
|
|
||||||
// Reset manual refresh flag when fetch completes
|
// Reset manual refresh flag when fetch completes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -961,7 +984,7 @@ export function GitDiffPane({ serverId, workspaceId, cwd, hideHeaderRow }: GitDi
|
|||||||
renderItem={renderFlatItem}
|
renderItem={renderFlatItem}
|
||||||
keyExtractor={flatKeyExtractor}
|
keyExtractor={flatKeyExtractor}
|
||||||
stickyHeaderIndices={stickyHeaderIndices}
|
stickyHeaderIndices={stickyHeaderIndices}
|
||||||
extraData={{ expandedByPath, effectiveLayout, wrapLines }}
|
extraData={{ expandedPathsArray, effectiveLayout, wrapLines }}
|
||||||
style={styles.scrollView}
|
style={styles.scrollView}
|
||||||
contentContainerStyle={styles.contentContainer}
|
contentContainerStyle={styles.contentContainer}
|
||||||
testID="git-diff-scroll"
|
testID="git-diff-scroll"
|
||||||
|
|||||||
@@ -66,6 +66,8 @@ interface PanelState {
|
|||||||
// File explorer settings (shared between mobile/desktop)
|
// File explorer settings (shared between mobile/desktop)
|
||||||
explorerTab: ExplorerTab;
|
explorerTab: ExplorerTab;
|
||||||
explorerTabByCheckout: Record<string, ExplorerTab>;
|
explorerTabByCheckout: Record<string, ExplorerTab>;
|
||||||
|
expandedPathsByWorkspace: Record<string, string[]>;
|
||||||
|
diffExpandedPathsByWorkspace: Record<string, string[]>;
|
||||||
activeExplorerCheckout: ExplorerCheckoutContext | null;
|
activeExplorerCheckout: ExplorerCheckoutContext | null;
|
||||||
sidebarWidth: number;
|
sidebarWidth: number;
|
||||||
explorerWidth: number;
|
explorerWidth: number;
|
||||||
@@ -85,6 +87,8 @@ interface PanelState {
|
|||||||
// File explorer settings actions
|
// File explorer settings actions
|
||||||
setExplorerTab: (tab: ExplorerTab) => void;
|
setExplorerTab: (tab: ExplorerTab) => void;
|
||||||
setExplorerTabForCheckout: (params: ExplorerCheckoutContext & { tab: ExplorerTab }) => void;
|
setExplorerTabForCheckout: (params: ExplorerCheckoutContext & { tab: ExplorerTab }) => void;
|
||||||
|
setExpandedPathsForWorkspace: (workspaceKey: string, paths: string[]) => void;
|
||||||
|
setDiffExpandedPathsForWorkspace: (workspaceKey: string, paths: string[]) => void;
|
||||||
activateExplorerTabForCheckout: (checkout: ExplorerCheckoutContext) => void;
|
activateExplorerTabForCheckout: (checkout: ExplorerCheckoutContext) => void;
|
||||||
setActiveExplorerCheckout: (checkout: ExplorerCheckoutContext | null) => void;
|
setActiveExplorerCheckout: (checkout: ExplorerCheckoutContext | null) => void;
|
||||||
setSidebarWidth: (width: number) => void;
|
setSidebarWidth: (width: number) => void;
|
||||||
@@ -142,6 +146,8 @@ export const usePanelStore = create<PanelState>()(
|
|||||||
// File explorer defaults
|
// File explorer defaults
|
||||||
explorerTab: "changes",
|
explorerTab: "changes",
|
||||||
explorerTabByCheckout: {},
|
explorerTabByCheckout: {},
|
||||||
|
expandedPathsByWorkspace: {},
|
||||||
|
diffExpandedPathsByWorkspace: {},
|
||||||
activeExplorerCheckout: null,
|
activeExplorerCheckout: null,
|
||||||
sidebarWidth: DEFAULT_SIDEBAR_WIDTH,
|
sidebarWidth: DEFAULT_SIDEBAR_WIDTH,
|
||||||
explorerWidth: DEFAULT_EXPLORER_SIDEBAR_WIDTH,
|
explorerWidth: DEFAULT_EXPLORER_SIDEBAR_WIDTH,
|
||||||
@@ -261,6 +267,17 @@ export const usePanelStore = create<PanelState>()(
|
|||||||
}
|
}
|
||||||
return nextState;
|
return nextState;
|
||||||
}),
|
}),
|
||||||
|
setExpandedPathsForWorkspace: (workspaceKey, paths) =>
|
||||||
|
set((state) => ({
|
||||||
|
expandedPathsByWorkspace: { ...state.expandedPathsByWorkspace, [workspaceKey]: paths },
|
||||||
|
})),
|
||||||
|
setDiffExpandedPathsForWorkspace: (workspaceKey, paths) =>
|
||||||
|
set((state) => ({
|
||||||
|
diffExpandedPathsByWorkspace: {
|
||||||
|
...state.diffExpandedPathsByWorkspace,
|
||||||
|
[workspaceKey]: paths,
|
||||||
|
},
|
||||||
|
})),
|
||||||
activateExplorerTabForCheckout: (checkout) =>
|
activateExplorerTabForCheckout: (checkout) =>
|
||||||
set((state) => ({
|
set((state) => ({
|
||||||
activeExplorerCheckout: checkout,
|
activeExplorerCheckout: checkout,
|
||||||
@@ -295,7 +312,7 @@ export const usePanelStore = create<PanelState>()(
|
|||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
name: "panel-state",
|
name: "panel-state",
|
||||||
version: 8,
|
version: 10,
|
||||||
storage: createJSONStorage(() => AsyncStorage),
|
storage: createJSONStorage(() => AsyncStorage),
|
||||||
migrate: (persistedState, version) => {
|
migrate: (persistedState, version) => {
|
||||||
const state = persistedState as Partial<PanelState> & Record<string, unknown>;
|
const state = persistedState as Partial<PanelState> & Record<string, unknown>;
|
||||||
@@ -371,6 +388,22 @@ export const usePanelStore = create<PanelState>()(
|
|||||||
state.sidebarWidth = DEFAULT_SIDEBAR_WIDTH;
|
state.sidebarWidth = DEFAULT_SIDEBAR_WIDTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
version < 9 ||
|
||||||
|
typeof state.expandedPathsByWorkspace !== "object" ||
|
||||||
|
!state.expandedPathsByWorkspace
|
||||||
|
) {
|
||||||
|
state.expandedPathsByWorkspace = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
version < 10 ||
|
||||||
|
typeof state.diffExpandedPathsByWorkspace !== "object" ||
|
||||||
|
!state.diffExpandedPathsByWorkspace
|
||||||
|
) {
|
||||||
|
state.diffExpandedPathsByWorkspace = {};
|
||||||
|
}
|
||||||
|
|
||||||
state.activeExplorerCheckout = null;
|
state.activeExplorerCheckout = null;
|
||||||
|
|
||||||
return state as PanelState;
|
return state as PanelState;
|
||||||
@@ -380,6 +413,8 @@ export const usePanelStore = create<PanelState>()(
|
|||||||
desktop: state.desktop,
|
desktop: state.desktop,
|
||||||
explorerTab: state.explorerTab,
|
explorerTab: state.explorerTab,
|
||||||
explorerTabByCheckout: state.explorerTabByCheckout,
|
explorerTabByCheckout: state.explorerTabByCheckout,
|
||||||
|
expandedPathsByWorkspace: state.expandedPathsByWorkspace,
|
||||||
|
diffExpandedPathsByWorkspace: state.diffExpandedPathsByWorkspace,
|
||||||
sidebarWidth: state.sidebarWidth,
|
sidebarWidth: state.sidebarWidth,
|
||||||
explorerWidth: state.explorerWidth,
|
explorerWidth: state.explorerWidth,
|
||||||
explorerSortOption: state.explorerSortOption,
|
explorerSortOption: state.explorerSortOption,
|
||||||
|
|||||||
Reference in New Issue
Block a user