'..' parent row in the file list

Synthetic cursor-navigable first row (hidden at /) — Enter/double-click goes to
the parent like the toolbar button. Excluded from selection, rename, delete,
chmod, and transfers; shown with an up-arrow icon.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Jokin
2026-07-11 19:14:24 +02:00
co-authored by Claude Fable 5
parent 83202ff414
commit 20e5703d29
4 changed files with 14 additions and 7 deletions
+9 -3
View File
@@ -23,7 +23,7 @@ export class PanelState {
readonly cursor = signal(0);
readonly selected = signal<ReadonlySet<string>>(new Set());
/** Directories first, then the active sort column. */
/** Directories first, then the active sort column. ".." (parent) is pinned on top. */
readonly sorted = computed(() => {
const list = [...this.entries()];
const key = this.sortKey();
@@ -41,6 +41,10 @@ export class PanelState {
}
return cmp * dir;
});
const cwd = this.cwd();
if (cwd && cwd !== '/') {
list.unshift({ name: '..', path: `${cwd}/..`, type: 'dir', size: 0, mtime: 0, mode: 0 });
}
return list;
});
@@ -120,6 +124,7 @@ export class PanelState {
}
toggleSelect(name: string): void {
if (name === '..') return;
this.selected.update((prev) => {
const next = new Set(prev);
if (next.has(name)) next.delete(name);
@@ -132,12 +137,13 @@ export class PanelState {
const [lo, hi] = fromIndex <= toIndex ? [fromIndex, toIndex] : [toIndex, fromIndex];
const names = this.sorted()
.slice(lo, hi + 1)
.map((e) => e.name);
.map((e) => e.name)
.filter((n) => n !== '..');
this.selected.update((prev) => new Set([...prev, ...names]));
}
selectAll(): void {
this.selected.set(new Set(this.sorted().map((e) => e.name)));
this.selected.set(new Set(this.sorted().map((e) => e.name).filter((n) => n !== '..')));
}
clearSelection(): void {