feat: Allow to disable showing paths to folders (#1274)

https://github.com/Termix-SSH/Support/issues/1274
This commit is contained in:
LukeGus committed 2026-09-20 18:17:29 -05:00
1 parent 6ce5e78165
commit d0c25cf183
7 files changed
+46 -1

No files matched your search

+7
View File
@@ -49,6 +49,8 @@ export interface HostSidebarDisplayPreferences {
statusColorScheme: StatusColorScheme; statusColorScheme: StatusColorScheme;
/** When true, a host row needs a double click to launch its session. */ /** When true, a host row needs a double click to launch its session. */
openOnDoubleClick: boolean; openOnDoubleClick: boolean;
/** When false, nested folders hide the parent-path breadcrumb before their name. */
showFolderPaths: boolean;
} }
export interface HostSidebarPreferences { export interface HostSidebarPreferences {
@@ -130,6 +132,7 @@ export function defaultHostSidebarPreferences(): HostSidebarPreferences {
trayTrigger: "always", trayTrigger: "always",
statusColorScheme: "accent", statusColorScheme: "accent",
openOnDoubleClick: false, openOnDoubleClick: false,
showFolderPaths: true,
}, },
}; };
} }
@@ -203,6 +206,10 @@ export function sanitizeHostSidebarPreferences(
typeof displayObj.openOnDoubleClick === "boolean" typeof displayObj.openOnDoubleClick === "boolean"
? displayObj.openOnDoubleClick ? displayObj.openOnDoubleClick
: defaults.display.openOnDoubleClick, : defaults.display.openOnDoubleClick,
showFolderPaths:
typeof displayObj.showFolderPaths === "boolean"
? displayObj.showFolderPaths
: defaults.display.showFolderPaths,
}; };
return { return {
+2
View File
@@ -1404,6 +1404,8 @@
"actionsClick": "Click to expand/collapse", "actionsClick": "Click to expand/collapse",
"openOnDoubleClick": "Open on double click", "openOnDoubleClick": "Open on double click",
"openOnDoubleClickDesc": "Require a double click to open a host session instead of a single click", "openOnDoubleClickDesc": "Require a double click to open a host session instead of a single click",
"showFolderPaths": "Show folder paths",
"showFolderPathsDesc": "Show the parent folder path above nested subfolder names. Subfolders stay indented either way.",
"deletedHost": "Deleted {{name}}", "deletedHost": "Deleted {{name}}",
"copiedToClipboard": "Copied to clipboard", "copiedToClipboard": "Copied to clipboard",
"terminalUrlCopied": "Terminal URL copied", "terminalUrlCopied": "Terminal URL copied",
+14
View File
@@ -97,6 +97,20 @@ export function CustomizeSidebarPanel({
} }
/> />
</SettingRow> </SettingRow>
<SettingRow
label={t("hosts.showFolderPaths")}
description={t("hosts.showFolderPathsDesc")}
>
<FakeSwitch
checked={preferences.display.showFolderPaths}
onChange={(v) =>
update((prev) => ({
...prev,
display: { ...prev.display, showFolderPaths: v },
}))
}
/>
</SettingRow>
<div className="flex flex-col gap-1.5 py-3 border-b border-border last:border-0"> <div className="flex flex-col gap-1.5 py-3 border-b border-border last:border-0">
<div className="flex flex-col gap-0.5"> <div className="flex flex-col gap-0.5">
<span className="text-sm font-medium leading-snug"> <span className="text-sm font-medium leading-snug">
+1
View File
@@ -1076,6 +1076,7 @@ export function HostsPanel({
trayTrigger={sidebarPrefs.display.trayTrigger} trayTrigger={sidebarPrefs.display.trayTrigger}
showTags={sidebarPrefs.display.showTags} showTags={sidebarPrefs.display.showTags}
openOnDoubleClick={sidebarPrefs.display.openOnDoubleClick} openOnDoubleClick={sidebarPrefs.display.openOnDoubleClick}
showFolderPaths={sidebarPrefs.display.showFolderPaths}
/> />
</div> </div>
)} )}
@@ -68,6 +68,7 @@ export function FolderItem({
trayTrigger = "hover", trayTrigger = "hover",
showTags = true, showTags = true,
openOnDoubleClick = false, openOnDoubleClick = false,
showFolderPaths = true,
arrangeMode = false, arrangeMode = false,
isDragging = false, isDragging = false,
onReorderDrop, onReorderDrop,
@@ -115,6 +116,8 @@ export function FolderItem({
trayTrigger?: HostTrayTrigger; trayTrigger?: HostTrayTrigger;
showTags?: boolean; showTags?: boolean;
openOnDoubleClick?: boolean; openOnDoubleClick?: boolean;
/** When false, nested folders hide the parent-path breadcrumb before their name. */
showFolderPaths?: boolean;
/** When true (rearranging unlocked), the header can be dragged and its /** When true (rearranging unlocked), the header can be dragged and its
* top/bottom edges become reorder drop zones. The middle still accepts * top/bottom edges become reorder drop zones. The middle still accepts
* hosts dropped into the folder. */ * hosts dropped into the folder. */
@@ -152,7 +155,8 @@ export function FolderItem({
// Nested folders show their parent path as a muted breadcrumb so depth stays // Nested folders show their parent path as a muted breadcrumb so depth stays
// legible even when a folder is reached via search auto-expand rather than // legible even when a folder is reached via search auto-expand rather than
// by manually opening every ancestor. // by manually opening every ancestor.
const pathSegments = isGroup ? [] : folderPath.split(" / "); const pathSegments =
isGroup || !showFolderPaths ? [] : folderPath.split(" / ");
const breadcrumb = const breadcrumb =
pathSegments.length > 1 ? pathSegments.slice(0, -1).join(" / ") : null; pathSegments.length > 1 ? pathSegments.slice(0, -1).join(" / ") : null;
const folderHosts = collectAllHosts(folder.children); const folderHosts = collectAllHosts(folder.children);
@@ -337,6 +341,7 @@ export function FolderItem({
trayTrigger={trayTrigger} trayTrigger={trayTrigger}
showTags={showTags} showTags={showTags}
openOnDoubleClick={openOnDoubleClick} openOnDoubleClick={openOnDoubleClick}
showFolderPaths={showFolderPaths}
arrangeMode={arrangeMode} arrangeMode={arrangeMode}
onReorderDrop={onReorderDrop} onReorderDrop={onReorderDrop}
onFolderDragStart={onFolderDragStart} onFolderDragStart={onFolderDragStart}
+4
View File
@@ -87,6 +87,7 @@ export function SidebarTree({
trayTrigger = "hover", trayTrigger = "hover",
showTags = true, showTags = true,
openOnDoubleClick = false, openOnDoubleClick = false,
showFolderPaths = true,
}: { }: {
children: (Host | HostFolder)[]; children: (Host | HostFolder)[];
onOpenTab: ( onOpenTab: (
@@ -108,6 +109,8 @@ export function SidebarTree({
trayTrigger?: HostTrayTrigger; trayTrigger?: HostTrayTrigger;
showTags?: boolean; showTags?: boolean;
openOnDoubleClick?: boolean; openOnDoubleClick?: boolean;
/** When false, nested folders hide the parent-path breadcrumb before their name. */
showFolderPaths?: boolean;
}) { }) {
const { t } = useTranslation(); const { t } = useTranslation();
// Knobs with no other owner come straight from the interface preset; the // Knobs with no other owner come straight from the interface preset; the
@@ -996,6 +999,7 @@ export function SidebarTree({
trayTrigger={trayTrigger} trayTrigger={trayTrigger}
showTags={showTags} showTags={showTags}
openOnDoubleClick={openOnDoubleClick} openOnDoubleClick={openOnDoubleClick}
showFolderPaths={showFolderPaths}
arrangeMode={arrangeMode} arrangeMode={arrangeMode}
isDragging={ isDragging={
draggedReorderKey === `folder:${item.path ?? item.name}` draggedReorderKey === `folder:${item.path ?? item.name}`
@@ -26,6 +26,7 @@ describe("defaultHostSidebarPreferences", () => {
trayTrigger: "always", trayTrigger: "always",
statusColorScheme: "accent", statusColorScheme: "accent",
openOnDoubleClick: false, openOnDoubleClick: false,
showFolderPaths: true,
}, },
}); });
}); });
@@ -63,6 +64,7 @@ describe("sanitizeHostSidebarPreferences", () => {
trayTrigger: "click", trayTrigger: "click",
statusColorScheme: "status", statusColorScheme: "status",
openOnDoubleClick: true, openOnDoubleClick: true,
showFolderPaths: false,
}, },
}; };
expect(sanitizeHostSidebarPreferences(valid)).toEqual(valid); expect(sanitizeHostSidebarPreferences(valid)).toEqual(valid);
@@ -78,6 +80,16 @@ describe("sanitizeHostSidebarPreferences", () => {
).toBe(false); ).toBe(false);
}); });
it("defaults showFolderPaths to true when missing or not a boolean", () => {
expect(
sanitizeHostSidebarPreferences({ display: {} }).display.showFolderPaths,
).toBe(true);
expect(
sanitizeHostSidebarPreferences({ display: { showFolderPaths: "no" } })
.display.showFolderPaths,
).toBe(true);
});
it("falls back to defaults for invalid enum values", () => { it("falls back to defaults for invalid enum values", () => {
const result = sanitizeHostSidebarPreferences({ const result = sanitizeHostSidebarPreferences({
sort: { key: "not-a-real-key", pinnedFirst: "yes" }, sort: { key: "not-a-real-key", pinnedFirst: "yes" },