fix: preserve selections in same-side inactive tabs

clearSelectionsExcept was clearing all tabs including same-side inactive
ones, causing users to lose file selections when switching between tabs
on the same side. Now only the opposite side's selections are cleared.

Also scoped tree selection clearing to only affect opposite-side pane
IDs, preventing mounted but hidden SFTP surfaces from losing state.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
bincxz
2026-03-29 19:39:39 +08:00
parent 3bb98c9c27
commit 05c48b3d28
4 changed files with 23 additions and 14 deletions

View File

@@ -100,25 +100,25 @@ export const useSftpTabsState = ({
const clearSelectionsExcept = useCallback(
(target: { side: "left" | "right"; tabId: string } | null) => {
const clearSideSelections = (
prev: SftpSideTabs,
side: "left" | "right",
): SftpSideTabs => {
const clearAllTabs = (prev: SftpSideTabs): SftpSideTabs => {
let changed = false;
const tabs = prev.tabs.map((tab) => {
const shouldKeepSelection =
target?.side === side && target.tabId === tab.id;
if (shouldKeepSelection || tab.selectedFiles.size === 0) {
return tab;
}
if (tab.selectedFiles.size === 0) return tab;
changed = true;
return { ...tab, selectedFiles: EMPTY_SELECTION };
});
return changed ? { ...prev, tabs } : prev;
};
setLeftTabs((prev) => clearSideSelections(prev, "left"));
setRightTabs((prev) => clearSideSelections(prev, "right"));
// Only clear the opposite side's selections, preserving same-side inactive tabs
if (target) {
const clearOther = target.side === "left" ? setRightTabs : setLeftTabs;
clearOther(clearAllTabs);
} else {
// No target: clear everything
setLeftTabs(clearAllTabs);
setRightTabs(clearAllTabs);
}
},
[],
);

View File

@@ -153,7 +153,9 @@ const SftpSidePanelInner: React.FC<SftpSidePanelProps> = ({
const syncFocusedSelection = useCallback((tabId: string | null) => {
if (tabId) {
sftpRef.current.clearSelectionsExcept({ side: "left", tabId });
sftpTreeSelectionStore.clearAllExcept([tabId]);
// Keep tree selections for all left-side tabs
const keepIds = sftpRef.current.leftTabs.tabs.map(t => t.id);
sftpTreeSelectionStore.clearAllExcept(keepIds);
return;
}
sftpRef.current.clearSelectionsExcept(null);

View File

@@ -146,7 +146,10 @@ const SftpViewInner: React.FC<SftpViewProps> = ({
const activeTabId = sftpRef.current.getActiveTabId(side);
if (activeTabId) {
sftpRef.current.clearSelectionsExcept({ side, tabId: activeTabId });
sftpTreeSelectionStore.clearAllExcept([activeTabId]);
// Keep tree selections for all same-side tabs, only clear opposite side
const sameSideTabs = side === "left" ? sftpRef.current.leftTabs : sftpRef.current.rightTabs;
const keepIds = sameSideTabs.tabs.map(t => t.id);
sftpTreeSelectionStore.clearAllExcept(keepIds);
} else {
sftpRef.current.clearSelectionsExcept(null);
sftpTreeSelectionStore.clearAllExcept();

View File

@@ -45,7 +45,11 @@ export const useSftpViewTabs = ({ sftp, sftpRef }: UseSftpViewTabsParams): UseSf
const clearOtherPaneSelections = useCallback((target: { side: "left" | "right"; tabId: string } | null) => {
sftpRef.current.clearSelectionsExcept(target);
if (target) {
sftpTreeSelectionStore.clearAllExcept([target.tabId]);
// Keep tree selections for all same-side tabs, only clear opposite side
const sameSideTabs = target.side === "left"
? sftpRef.current.leftTabs : sftpRef.current.rightTabs;
const keepIds = sameSideTabs.tabs.map(t => t.id);
sftpTreeSelectionStore.clearAllExcept(keepIds);
return;
}
sftpTreeSelectionStore.clearAllExcept();