v1.1: fix transfer freeze, session tabs, per-panel toolbars, status bar
Freeze root cause: TransfersService consumed transferUpdate through an effect that both read and wrote the jobMap signal — the first progress message spun the effect into an infinite re-run loop, pegging the webview thread while the copy completed fine bun-side. Push messages now flow through plain callback registries on RpcService (also stops signal coalescing from dropping progress snapshots). Verified live: a 60MB boot-time self-test copy streamed progress into the running UI and the post-completion panel refreshes arrived. - Tabs: workspaces (left+right PanelState pair each) in PanelsService; tab bar replaces the header; sessions persist in background tabs; Cmd+T/Cmd+W/Ctrl+Tab; closing a tab disconnects its sessions; last tab can't close - Per-panel toolbar (top, icon-only): direction-explicit copy (-> / <-), rename, new folder/file, chmod, delete; panel footers removed - VSCode-style status bar: transfer summary (spinner/percent/queued/failures, click to expand the job list) + active panel info; function bar removed - transfer details list is collapsible, auto-expands on failure Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<!-- session strip -->
|
||||
<div class="relative flex items-center gap-1.5 border-b border-border px-2 py-1.5">
|
||||
<div class="relative flex items-center gap-1.5 border-b border-border px-2 py-1">
|
||||
<button
|
||||
(click)="menuOpen.set(!menuOpen())"
|
||||
class="flex min-w-0 items-center gap-1.5 rounded-md px-2 py-1 text-xs font-medium hover:bg-accent"
|
||||
@@ -27,6 +27,52 @@
|
||||
</button>
|
||||
}
|
||||
|
||||
<div class="flex-1"></div>
|
||||
|
||||
<!-- panel actions: act on THIS panel -->
|
||||
<button
|
||||
(click)="copyToOther()"
|
||||
[title]="side() === 'left' ? 'Copy to right panel (F5)' : 'Copy to left panel (F5)'"
|
||||
class="grid size-6 shrink-0 place-items-center rounded-md text-muted-foreground hover:bg-accent hover:text-primary"
|
||||
>
|
||||
<ng-icon [name]="copyIcon()" size="0.95rem" />
|
||||
</button>
|
||||
<button
|
||||
(click)="run('rename')"
|
||||
title="Rename (F2)"
|
||||
class="grid size-6 shrink-0 place-items-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground"
|
||||
>
|
||||
<ng-icon name="mynaEdit" size="0.9rem" />
|
||||
</button>
|
||||
<button
|
||||
(click)="run('mkdir')"
|
||||
title="New folder (F7)"
|
||||
class="grid size-6 shrink-0 place-items-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground"
|
||||
>
|
||||
<ng-icon name="mynaFolderPlus" size="0.9rem" />
|
||||
</button>
|
||||
<button
|
||||
(click)="run('createFile')"
|
||||
title="New file"
|
||||
class="grid size-6 shrink-0 place-items-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground"
|
||||
>
|
||||
<ng-icon name="mynaFilePlus" size="0.9rem" />
|
||||
</button>
|
||||
<button
|
||||
(click)="run('chmod')"
|
||||
title="Permissions"
|
||||
class="grid size-6 shrink-0 place-items-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground"
|
||||
>
|
||||
<ng-icon name="mynaLock" size="0.9rem" />
|
||||
</button>
|
||||
<button
|
||||
(click)="run('delete')"
|
||||
title="Delete (F8 / Del)"
|
||||
class="grid size-6 shrink-0 place-items-center rounded-md text-muted-foreground hover:bg-accent hover:text-destructive"
|
||||
>
|
||||
<ng-icon name="mynaTrash" size="0.9rem" />
|
||||
</button>
|
||||
|
||||
@if (menuOpen()) {
|
||||
<div class="fixed inset-0 z-20" (click)="menuOpen.set(false)"></div>
|
||||
<div
|
||||
@@ -135,7 +181,6 @@
|
||||
(keydown)="onKeydown($event)"
|
||||
(mousedown)="activate()"
|
||||
class="flex-1 overflow-y-auto outline-none"
|
||||
[class.bg-accent]="false"
|
||||
>
|
||||
@for (entry of panel().sorted(); track entry.name; let i = $index) {
|
||||
<div
|
||||
@@ -168,11 +213,3 @@
|
||||
<div class="p-6 text-center text-xs text-muted-foreground">Empty directory</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- footer -->
|
||||
<div class="flex items-center gap-2 border-t border-border px-2 py-1 text-[11px] text-muted-foreground">
|
||||
<span>{{ panel().sorted().length }} items</span>
|
||||
@if (panel().selected().size; as count) {
|
||||
<span>· {{ count }} selected</span>
|
||||
}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user