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:
@@ -34,6 +34,8 @@ export class FilePanel {
|
||||
readonly panel = computed(() => this.panels.get(this.side()));
|
||||
readonly isActive = computed(() => this.panels.activeSide() === this.side());
|
||||
readonly isRemote = computed(() => this.panel().sessionId() !== 'local');
|
||||
/** The copy button points toward the other panel. */
|
||||
readonly copyIcon = computed(() => (this.side() === 'left' ? 'mynaArrowRight' : 'mynaArrowLeft'));
|
||||
|
||||
readonly pathDraft = signal('');
|
||||
readonly menuOpen = signal(false);
|
||||
@@ -55,7 +57,17 @@ export class FilePanel {
|
||||
}
|
||||
|
||||
activate(): void {
|
||||
this.panels.activeSide.set(this.side());
|
||||
this.panels.setActiveSide(this.side());
|
||||
}
|
||||
|
||||
copyToOther(): void {
|
||||
this.activate();
|
||||
void this.transfers.copyToOtherPanel(this.side());
|
||||
}
|
||||
|
||||
run(action: 'rename' | 'mkdir' | 'createFile' | 'chmod' | 'delete'): void {
|
||||
this.activate();
|
||||
this.actions[action](this.panel());
|
||||
}
|
||||
|
||||
pickLocal(): void {
|
||||
@@ -129,7 +141,7 @@ export class FilePanel {
|
||||
|
||||
if (key === 'Tab') {
|
||||
event.preventDefault();
|
||||
this.panels.activeSide.set(this.panels.otherSide(this.side()));
|
||||
this.panels.setActiveSide(this.panels.otherSide(this.side()));
|
||||
return;
|
||||
}
|
||||
if ((event.metaKey || event.ctrlKey) && key.toLowerCase() === 'a') {
|
||||
@@ -171,17 +183,17 @@ export class FilePanel {
|
||||
panel.up();
|
||||
break;
|
||||
case 'F2':
|
||||
this.actions.rename();
|
||||
this.actions.rename(panel);
|
||||
break;
|
||||
case 'F5':
|
||||
void this.transfers.copyToOtherPanel();
|
||||
void this.transfers.copyToOtherPanel(this.side());
|
||||
break;
|
||||
case 'F7':
|
||||
this.actions.mkdir();
|
||||
this.actions.mkdir(panel);
|
||||
break;
|
||||
case 'F8':
|
||||
case 'Delete':
|
||||
this.actions.delete();
|
||||
this.actions.delete(panel);
|
||||
break;
|
||||
default:
|
||||
return; // let unhandled keys through
|
||||
|
||||
Reference in New Issue
Block a user