P1: typed RPC bridge + FileSystemProvider + dual-panel local browsing

- shared/types + shared/rpc: full wire contract (Result envelope, no exceptions cross the bridge)
- FileSystemProvider interface, LocalProvider, SessionRegistry with built-in 'local'
- walk.ts: provider-generic recursive walk + removeRecursive
- rpc-handlers wired into BrowserWindow; 10min request timeout for slow SFTP ops
- Angular: RpcService (Electroview bridge + plain-browser guard), PanelsService with
  signals-based PanelState (sort/cursor/selection), FilePanel component with
  keyboard nav (arrows/Space/Enter/Backspace/Tab), path bar, toasts
- verified: both panels listDir home over the bridge in the running app

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Jokin
2026-07-11 13:35:02 +02:00
co-authored by Claude Fable 5
parent 8092cb0c08
commit a150c5ee2e
17 changed files with 1062 additions and 15 deletions
+13 -2
View File
@@ -1,16 +1,27 @@
import { Component } from '@angular/core';
import { Component, inject } from '@angular/core';
import { NgIcon } from '@ng-icons/core';
import { BRANDING } from '@shared/branding';
import { FilePanel } from './file-panel/file-panel';
import { RpcService } from './rpc.service';
import { ToastService } from './toast.service';
@Component({
selector: 'app-root',
imports: [NgIcon],
imports: [NgIcon, FilePanel],
templateUrl: './app.html',
})
export class App {
readonly appName = BRANDING.appName;
readonly rpc = inject(RpcService);
readonly toast = inject(ToastService);
constructor() {
document.title = BRANDING.appName;
}
toastIcon(kind: 'error' | 'info' | 'success'): string {
if (kind === 'error') return 'mynaXCircle';
if (kind === 'success') return 'mynaCheckCircle';
return 'mynaCheck';
}
}