Files
miniSCP/src/shared/rpc.ts
T
jgamboaandClaude 2bac7678ca Remove the Windows 7 (7.css) skin
The win7 skin is dropped. Everything else the branch built stays: Linux
support and the HTML context menus, the workspace-tab menu, the continuous
interface scale (rem everywhere, stepper, Ctrl/Cmd +/-/0) and the core/
service layer. The modern tree already carried all of them, and nothing
outside skins/7like/ imported the win7 tree except main.ts and styles.css.

Removed: the skins/7like/ tree (5.1k lines, fonts), the 7.css dependency,
the skin setting and its options row + strings in all 7 locales, the
frameless-window plumbing (window-control RPCs, windowState push,
trackMaximizeState, the synthesized resize grip and its postinstall
watchdog), the session-skin pinning in buildPreload/chromeOptions, the
skin/skinfix cascade layers, and the win7-only probes and screenshot
harness (the harness cannot render the modern tree: plain Firefox has no
RPC bridge). chromeOptions() stays as the one shared frame decision.

Fixed on the way out:
- index.html's per-theme pre-paint background is restored. The branch had
  replaced it with a win7-only transparent rule, so modern dark windows had
  silently lost one of the three flash guards.
- editor-windows.ts wrote its window-key separator as a literal NUL byte,
  which made git and grep treat the file as binary; it is `\0` now (same
  string at runtime).

No settings migration: a stale "skin" key is carried harmlessly by the
store's spread-merge and dropped on the next save.

UI bundle: 616.7 kB -> 405.4 kB, back under the 500 kB budget.

Docs: architecture, gotchas and platform-notes lose the win7 material but
keep what stays true (construction-time preloads/frames, drag regions
ignoring preventDefault, electrobun's missing resize/maximize primitives);
flash-prevention, dev-URL and Bun-panic notes move back under Electrobun;
stale context-menu/tab-bar links fixed; README documents the scale keys.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-09-23 16:17:38 +02:00

202 lines
7.5 KiB
TypeScript

import type {
AppSettings,
ConnectionConfig,
ConnectionsFile,
EntryType,
FileEntry,
Result,
SavedConnection,
SshConfigHost,
Stack,
TransferSnapshot,
} from "./types";
/** Everything an editor window needs to know about the file it hosts. */
export interface EditorOpenContext {
sessionId: string;
path: string;
name: string;
sessionTitle: string;
}
// Structurally equivalent to electrobun's ElectrobunRPCSchema, written in
// resolved form so this file stays importable from the Angular bundle without
// pulling in bun-only type modules.
//
// bun.requests = calls the webview makes, handled in src/bun/rpc-handlers.ts
// webview.messages = push events from bun, handled in ui rpc.service.ts
//
// ONE schema serves both window kinds (main + editor): electrobun allows
// partial handler sets, and messages nobody listens to are silently dropped,
// so each side only implements/hears what applies to it.
export type AppRPC = {
bun: {
requests: {
// sessions
connect: {
params: { config: ConnectionConfig };
response: Result<{ sessionId: string; homeDir: string; fsKey: string }>;
};
disconnect: { params: { sessionId: string }; response: Result };
// filesystem (uniform across "local" and sftp sessions)
listDir: {
params: { sessionId: string; path: string | null }; // null -> home dir
response: Result<{ path: string; entries: FileEntry[] }>;
};
// Local dirs to fs.watch for auto-refresh (the active tab's local panels);
// a change pushes pathRefresh. Remote panels are polled UI-side instead.
setWatchedDirs: { params: { dirs: string[] }; response: Result };
mkdir: { params: { sessionId: string; path: string }; response: Result };
createFile: { params: { sessionId: string; path: string }; response: Result };
rename: {
params: { sessionId: string; oldPath: string; newPath: string };
response: Result;
};
deleteEntries: {
params: { sessionId: string; entries: { path: string; type: EntryType }[] };
response: Result;
};
chmod: {
params: { sessionId: string; paths: string[]; mode: number };
response: Result;
};
// transfers
enqueueTransfers: {
params: {
srcSessionId: string;
items: { path: string; type: EntryType }[];
dstSessionId: string;
dstDir: string;
};
response: Result<{ jobIds: string[] }>;
};
cancelTransfer: { params: { jobId: string }; response: Result };
dismissTransfer: { params: { jobId: string }; response: Result };
// connection store
getConnections: {
params: Record<string, never>;
response: Result<{ store: ConnectionsFile }>;
};
upsertConnection: {
params: { connection: SavedConnection };
response: Result<{ id: string }>;
};
deleteConnection: { params: { id: string }; response: Result };
upsertStack: { params: { stack: Stack }; response: Result<{ id: string }> };
deleteStack: { params: { id: string }; response: Result };
/** Native file picker + parse of a WinSCP.ini export into the store. */
importWinScp: {
params: Record<string, never>;
response: Result<{ connections: number; stacks: number; skipped: number }>;
};
getSshConfigHosts: {
params: Record<string, never>;
response: Result<{ hosts: SshConfigHost[] }>;
};
// settings
getSettings: {
params: Record<string, never>;
response: Result<{ settings: AppSettings }>;
};
saveSettings: { params: { settings: AppSettings }; response: Result };
// file editing
readFile: {
params: { sessionId: string; path: string };
response: Result<{ content: string }>;
};
writeFile: {
params: { sessionId: string; path: string; content: string };
response: Result;
};
editExternal: {
params: { sessionId: string; path: string };
response: Result<{ watching: boolean }>;
};
pickEditorApp: {
params: Record<string, never>;
response: Result<{ path: string | null }>;
};
pickKeyFile: {
params: Record<string, never>;
response: Result<{ path: string | null }>;
};
getEditLeftovers: {
params: Record<string, never>;
response: Result<{ names: string[] }>;
};
clearEditLeftovers: { params: Record<string, never>; response: Result };
// local shell integration
/**
* Shell actions the context menu triggers on a LOCAL path. The menu
* itself is HTML (ui/src/app/core/context-menu.service.ts) — electrobun's native
* context menu is a no-op on Linux — but these three still need the
* bun side's Utils.
*/
shellItemAction: {
params: { action: "reveal" | "open" | "copyPath"; path: string };
response: Result;
};
moveToTrash: { params: { path: string }; response: Result };
/** Native About box (name, Build n, commit, engine versions). */
showAbout: { params: Record<string, never>; response: Result };
/** Windows drive roots for the local panel ("C:\", …); empty elsewhere. */
listDrives: { params: Record<string, never>; response: Result<{ drives: string[] }> };
// editor windows
/** Main window only: open (or focus) a native editor window. */
openEditor: { params: EditorOpenContext; response: Result };
/** Editor windows only — handled by that window's own rpc closure. */
editorSave: { params: { content: string }; response: Result };
editorClose: { params: Record<string, never>; response: Result };
// connection-manager window
/** Main window: open (or focus) the single connection-manager window. */
openConnectionManager: { params: Record<string, never>; response: Result };
/** Manager window only: connect/open-stack run in the MAIN window. */
managerConnect: { params: { id: string }; response: Result };
managerOpenStack: { params: { id: string }; response: Result };
managerClose: { params: Record<string, never>; response: Result };
// auto-updater (electrobun Updater)
/** Main window: re-run the update check on demand (menu item). */
checkForUpdate: {
params: Record<string, never>;
response: Result<{ updateAvailable: boolean; version: string }>;
};
/** Download the pending update (patch-chain, else full). Progress arrives via updateStatus. */
downloadUpdate: { params: Record<string, never>; response: Result };
/** Swap in the downloaded update and relaunch — quits the app, so may not resolve. */
applyUpdate: { params: Record<string, never>; response: Result };
};
messages: {
/** Editor → bun draft mirror; safety net for the non-cancellable native close. */
editorState: { dirty: boolean; content: string };
};
};
webview: {
requests: Record<never, never>;
messages: {
transferUpdate: TransferSnapshot;
sessionClosed: { sessionId: string; reason: string };
menuAction: { action: string };
/** bun → editor windows when the main window saves settings. */
settingsChanged: { settings: AppSettings };
/** bun → main after an editor save, so matching panels refresh. */
pathRefresh: { sessionId: string; dir: string };
/** bun → one editor: run the in-window close flow (dirty prompt). */
editorCloseRequest: Record<string, never>;
/** bun → main: the modal connection manager opened/closed. */
managerState: { open: boolean };
/** bun → main: the manager window changed the connection store. */
connectionsChanged: Record<string, never>;
/**
* bun → main: auto-updater lifecycle, drives the tab-bar update pill.
* "ready" is not a phase — the UI derives it from downloadUpdate resolving ok.
*/
updateStatus: {
phase: "available" | "downloading" | "error";
version?: string;
progress?: number;
error?: string;
};
};
};
};