114 lines
3.7 KiB
TypeScript
114 lines
3.7 KiB
TypeScript
|
|
/**
|
||
|
|
* Browse vs transfer session lifecycle helpers.
|
||
|
|
*
|
||
|
|
* FileZilla model: a *closed* terminal SFTP side panel can soft-close its browse
|
||
|
|
* SFTP channels while bulk transfers keep dedicated pool connections (and any
|
||
|
|
* leased browse sessions held by in-flight streams). Switching to another side
|
||
|
|
* panel tool (History / System / …) must keep browse warm — the owner stays
|
||
|
|
* mounted for instant switch-back, and parking would force reconnect + reload.
|
||
|
|
*/
|
||
|
|
|
||
|
|
export function isBrowseSessionInteractive(params: {
|
||
|
|
surfaceVisible: boolean;
|
||
|
|
/**
|
||
|
|
* Terminal side panel still open for this owner (another tool may be focused).
|
||
|
|
* Keeps browse sessions alive across tool switches without treating that as a
|
||
|
|
* full panel dismiss.
|
||
|
|
*/
|
||
|
|
ownerPanelOpen?: boolean;
|
||
|
|
hasOwnedEditorTab: boolean;
|
||
|
|
/** External editor temp files (Notepad++ etc.) still need the browse session. */
|
||
|
|
hasActiveExternalEdit?: boolean;
|
||
|
|
}): boolean {
|
||
|
|
return params.surfaceVisible
|
||
|
|
|| !!params.ownerPanelOpen
|
||
|
|
|| params.hasOwnedEditorTab
|
||
|
|
|| !!params.hasActiveExternalEdit;
|
||
|
|
}
|
||
|
|
|
||
|
|
export function listRemoteBrowseConnectionIds(
|
||
|
|
tabs: ReadonlyArray<{
|
||
|
|
connection: { id: string; isLocal: boolean } | null;
|
||
|
|
}>,
|
||
|
|
): string[] {
|
||
|
|
const ids = new Set<string>();
|
||
|
|
for (const tab of tabs) {
|
||
|
|
const connection = tab.connection;
|
||
|
|
if (!connection || connection.isLocal) continue;
|
||
|
|
ids.add(connection.id);
|
||
|
|
}
|
||
|
|
return [...ids];
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Stable SFTP pane tab ids for editor ownership across browse reconnects. */
|
||
|
|
export function listRemoteBrowseSftpTabIds(
|
||
|
|
tabs: ReadonlyArray<{
|
||
|
|
id: string;
|
||
|
|
connection: { id: string; isLocal: boolean } | null;
|
||
|
|
}>,
|
||
|
|
): string[] {
|
||
|
|
const ids = new Set<string>();
|
||
|
|
for (const tab of tabs) {
|
||
|
|
const connection = tab.connection;
|
||
|
|
if (!connection || connection.isLocal) continue;
|
||
|
|
ids.add(tab.id);
|
||
|
|
}
|
||
|
|
return [...ids];
|
||
|
|
}
|
||
|
|
|
||
|
|
export function shouldParkBrowseSessions(params: {
|
||
|
|
interactive: boolean;
|
||
|
|
/** True after we already soft-closed browse while the owner stayed mounted. */
|
||
|
|
browseParked: boolean;
|
||
|
|
/** Defer park while unfinished transfers may still use browse sessions pre-lease. */
|
||
|
|
activeTransfersCount?: number;
|
||
|
|
/**
|
||
|
|
* Defer park while an external editor still holds a downloaded temp file.
|
||
|
|
* Parking calls closeSftp, which deletes those temps and breaks save/sync.
|
||
|
|
*/
|
||
|
|
activeExternalEditCount?: number;
|
||
|
|
}): boolean {
|
||
|
|
if (params.activeTransfersCount && params.activeTransfersCount > 0) return false;
|
||
|
|
if (params.activeExternalEditCount && params.activeExternalEditCount > 0) return false;
|
||
|
|
return !params.interactive && !params.browseParked;
|
||
|
|
}
|
||
|
|
|
||
|
|
export function shouldRestoreBrowseSessions(params: {
|
||
|
|
interactive: boolean;
|
||
|
|
browseParked: boolean;
|
||
|
|
}): boolean {
|
||
|
|
return params.interactive && params.browseParked;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface BrowseSessionEntry {
|
||
|
|
connectionId: string;
|
||
|
|
sftpId: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Snapshot + clear the connectionId→sftpId map used by the file browser. */
|
||
|
|
export function takeBrowseSessionsForClose(
|
||
|
|
sessions: Map<string, string>,
|
||
|
|
): BrowseSessionEntry[] {
|
||
|
|
const entries = [...sessions.entries()].map(([connectionId, sftpId]) => ({
|
||
|
|
connectionId,
|
||
|
|
sftpId,
|
||
|
|
}));
|
||
|
|
sessions.clear();
|
||
|
|
return entries;
|
||
|
|
}
|
||
|
|
|
||
|
|
export function listRemoteConnectionIdsForRestore(params: {
|
||
|
|
leftTabs: ReadonlyArray<{ connection: { id: string; isLocal: boolean } | null }>;
|
||
|
|
rightTabs: ReadonlyArray<{ connection: { id: string; isLocal: boolean } | null }>;
|
||
|
|
liveSessionConnectionIds: ReadonlySet<string>;
|
||
|
|
}): string[] {
|
||
|
|
const ids = new Set<string>();
|
||
|
|
for (const tab of [...params.leftTabs, ...params.rightTabs]) {
|
||
|
|
const connection = tab.connection;
|
||
|
|
if (!connection || connection.isLocal) continue;
|
||
|
|
if (params.liveSessionConnectionIds.has(connection.id)) continue;
|
||
|
|
ids.add(connection.id);
|
||
|
|
}
|
||
|
|
return [...ids];
|
||
|
|
}
|