Commit Graph
14 Commits
Author SHA1 Message Date
jgamboaandClaude f7ebed5478 Make Linux a supported platform: HTML context menus + runtime deps + release target
`bun run start` died on Linux with ERR_DLOPEN_FAILED (missing
libayatana-appindicator3.so.1). Fixing the environment exposed the real gap:
electrobun's ContextMenu.showContextMenu is a documented no-op on Linux, and
since the UI suppresses the webview's own right-click menu, EVERY panel context
menu was silently dead there — Send to Other Panel, Open, Rename, Permissions,
Delete, Copy Path, Reveal and the column picker all unreachable. Electrobun
itself logs "Application menus are not supported on Linux. Implement menu UI in
your webview HTML instead." at boot.

- Context menus are now HTML on EVERY platform (ui/src/app/context-menu.ts +
  context-menu.service.ts), not just as a Linux fallback: one implementation
  cannot drift from a second one. The item builders are ported verbatim from
  the old bun menu, so ordering, per-platform labels and the Windows-local
  chmod hide are unchanged, and picks are emitted as the same `ctx-*` / `col:*`
  strings through RpcService.emitMenuAction — App.handleMenuAction is untouched
  and still the single dispatcher for both the macOS menubar and right-clicks.
  Adds what the native menu gave for free: arrow/Enter/Escape keys, viewport
  edge-flip, close on blur/resize/scroll. The Edit item now shows the real F4
  hint instead of the native menu's "e" mnemonic.
- New shellItemAction RPC replaces showRowMenu/showColumnsMenu — the only part
  the webview can't do itself (reveal, open-with-default, copy path). Deletes
  src/bun/context-menu.ts entirely.
- release.ts gains a linux-x64 target. Electrobun emits only the .tar.zst
  updater blob on Linux, so the artifact is a .tar.gz of the assembled app
  folder, mirroring the Windows portable zip.
- Docs: platform-notes gets a Linux runtime-dependency table (AppIndicator is
  linked HARD — a missing lib is a boot failure, not a degraded tray), the
  ldd diagnostic, GNOME tray caveat, known issues and a first-boot smoke test;
  gotchas gets the ERR_DLOPEN_FAILED trail and the benign GLX/GBM startup
  noise; architecture/build-and-release/README updated accordingly.

Verified: backend `tsc --noEmit` clean, `bun run build:ui` clean (399 kB
initial), app boots on Linux with no errors beyond the documented benign
warnings. NOT verified on macOS/Windows — the native menu is retired on those
platforms too, so the menus need eyeballing on a Mac before the next release.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-15 14:23:58 +02:00
jgamboaandClaude 697f7f22c8 Rename Copy to Send and put it first in the row context menu
The main feature (copy selection to the other panel, F5) is now labeled
"Send" in the toolbar button, tooltips, and context menu across all 7
locales. Internal identifiers (copyToOtherPanel, ctx-copy, i18n keys)
and secondary strings (toasts, status bar, errors) are unchanged.
The context-menu entry moves ahead of Open/Edit as the first row item.
README, marketing site, and the Windows QA checklist updated to match.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 13:12:05 +02:00
JokinandClaude Fable 5 dc5cb1f707 Developer documentation: architecture, build/release, platforms, gotchas
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 00:25:38 +02:00
JokinandClaude Fable 5 2585dd128b Multi-arch release script + Gitea workflow; retire legacy BunSCP name
bun run release -- --target mac-arm64|mac-x64|win-x64: gen version/icons,
build UI, electrobun build --env=stable, collect artifacts as
release/<target>/miniSCP-Build<n>-<target>.*. mac-x64 builds on the
arm64 Mac by running electrobun's x64 CLI under Rosetta 2 (verified:
x86_64 launcher in the produced app). Windows also zips a portable
build next to the Setup installer. Tag-triggered Gitea Actions matrix
included, inert until runners exist. legacyNames emptied — the BunSCP
migration has served its purpose.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 00:25:10 +02:00
JokinandClaude Fable 5 c7271fb7cf Windows compatibility pass (beta target)
External editor via cmd/start + exe picker; Permissions hidden for
Windows-local (chmod only flips read-only there); Explorer/Recycle Bin
wording; Ctrl vs Cmd shortcut labels; separator-aware path joins +
drive-root detection; drives list in the panel source picker; icon.ico
+ colored tray icon; icacls ACL on connections.json; README Windows
(beta) section with upstream known issues and a smoke-test checklist.
Runtime paths pending first boot on a real Windows machine.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 00:02:42 +02:00
JokinandClaude Fable 5 ba0b2434fb Rename to miniSCP; migrate legacy data dirs on boot
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 01:53:26 +02:00
JokinandClaude Fable 5 3fb08fdc24 Simplify tray: static template icon, click focuses the app
The setImage-swapped progress frames lost the template treatment on macOS and
rendered black-on-dark once transfers started. Dial back per user decision:
the tray is now just the glyph (template image set once at construction, never
swapped) and clicking it activates the window — no menu, no progress effects.
Removes everything that only served the fancy version: progress frames +
generation, engine.aggregateProgress, the workspacesSync webview->bun channel
(schema, send proxy, panels effect, handlers) and the activate-tab action.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 21:55:42 +02:00
JokinandClaude Fable 5 42e5e5bb9a Tray icon with live transfer progress and tabs menu
- AppTray: template menu-bar icon (22pt, adapts to light/dark). While
  transfers run it swaps to pre-rendered frames — faded arrows + a fill bar
  showing aggregate doneBytes/totalBytes of the queue (nearest 5%, throttled
  500ms); back to the glyph when idle. No runtime image encoding.
- Menu: one entry per tab (checkmark on the active one) with live per-tab
  transfer count and percentage (jobs mapped via session ids), an overall
  progress row while transferring, Show <app>, Quit. Selecting a tab
  activates the window and switches to it.
- First use of webview->bun messages: PanelsService pushes workspacesSync
  (tab names, sessions, active id) via a new ready-gated send proxy; verified
  end-to-end in the running app.
- engine.aggregateProgress(): totals + per-session breakdown over non-terminal
  jobs (unit-verified idle/mid-transfer/idle).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 21:41:51 +02:00
JokinandClaude Fable 5 c218cc2104 New logo: diagonal transfer arrows + lock (SVG-first icon pipeline)
Glyph composed from mynaui arrow-diagonal-one (both diagonals) with the
mini-lock of lock-square centered between them — the macOS squircle plays the
role of lock-square's outer square. Indigo gradient + white strokes + amber
lock face for the app icon; a pure black+alpha variant for the macOS template
tray icon, plus 21 pre-rendered tray progress frames (faded arrows + fill bar,
0-100% in 5% steps) for the upcoming tray feature.

Pipeline: scripts/gen-icons.ts renders every size directly from the SVGs with
@resvg/resvg-js (dev-only dep, prebuilt binaries, no postinstall); replaces
make-icon.py + gen-iconset.sh and the sips/iconutil path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 21:36:40 +02:00
JokinandClaude Fable 5 de75fb1480 Fix data loss: copying a file onto itself via two sessions truncated it to 0
Two panels on the same server hold two SSH sessions by design, and every
self-copy guard compared sessionId — so same-server same-path copies slipped
through all of them, and createWriteStream truncated the destination before
the read began: the file (or every file in a folder) became 0 bytes, with the
overwrite dialog making it look like a legitimate replace.

Fix, defense in depth, keyed on FILESYSTEM identity instead of session:
- fsKey on every provider: 'local', or resolvedIP:port for SFTP (host is
  DNS-resolved at connect so hostname-vs-IP aliases compare equal; username
  excluded — same host:port is the same filesystem regardless of login)
- engine guard blocks equal/nested paths when fsKeys match; per-file
  belt-and-suspenders check right before streams open
- probe layer for hidden aliases (different addresses, same machine): when
  fsKeys differ but paths collide, a token file written via dst and read via
  src decides; visible => same machine => blocked. SFTP exposes no dev/inode
  (what cp/rsync use), so probing is the only deterministic test; fails open
  and cleans up after itself
- UI: same-folder toast now fires across two sessions to one server, and the
  overwrite dialog auto-skips (never offers Replace) when the colliding item
  IS the source file

Known residual, documented in README 'Same-file protection': one filesystem
mounted at different paths on two connections is undetectable client-side.

Regression suite against the real box: file-onto-itself and folder-onto-itself
blocked with contents byte-intact, folder-into-descendant blocked, legit
same-server different-dir copies still work, local same-path still blocked,
simulated alias caught by the probe with cleanup verified.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 21:01:20 +02:00
JokinandClaude Fable 5 e4f7ca86f7 Edit file: built-in editor + external editor with watch & auto-upload
- Built-in editor (default): large modal with monospace textarea, Cmd+S save,
  dirty guard; reads/writes through the provider streams so it works on local
  and remote files identically (2MB cap with a friendly error)
- External editor: remote files download to appDataDir/edits/<id>, open via
  macOS `open -a`, the temp DIR is watched (survives atomic rename-saves) and
  every save enqueues a normal upload job (progress/errors in the transfer
  list); watchers + temp dirs are cleaned when the session disconnects
- Editor setting: Built-in | Custom with a NATIVE app picker (electrobun
  openFileDialog, /Applications, .app filter) and reset-to-default
- Leftover temp files from a crash prompt for cleanup at boot
- F4, toolbar button (mynaFileText), and File > Edit File (Cmd+E) menu entry
- README: feature notes + Portability notes (open/start/xdg-open seam
  documented in code and README per user request)

Verified headless against the box: sftp read/write roundtrip incl. UTF-8,
size cap, watch->save->auto-upload->remote-updated, session cleanup, orphan
listing and clearing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 20:28:54 +02:00
JokinandClaude Fable 5 6048d5c814 v1.2: overwrite confirm, transfer speed/ETA, settings + themes, fused macOS titlebar
- Overwrite confirmation: name-collision detection before enqueue; dialog shows
  source vs destination (size, mtime, 'newer' badge) with per-item Skip/Replace
  and batch Skip all / Replace all; type mismatches auto-skip with a toast;
  cancel aborts the whole operation
- Transfer speed + ETA: UI computes smoothed bytes/sec from progress deltas
  (callback bus makes deltas meaningful); shown in the expanded queue rows and
  the status-bar summary; unit follows the speed-unit setting
- Settings: bun-side SettingsStore (settings.json, 0600, atomic) + get/save RPC;
  SettingsService; gear popover on the tab row (theme segmented control, speed
  unit); persisted across restarts
- Light theme: data-theme on <html> drives token overrides; absent = follow OS
- macOS fused titlebar: hiddenInset + trafficLightOffset, tab row becomes the
  draggable titlebar (app-region drag/no-drag classes); other platforms keep a
  separate titlebar (gated by a platform value injected via window preload)
- README: known-issues note for the upstream Bun/Electrobun FFI crash

Verified: tsc + ui build clean; SettingsStore roundtrip + 0600 headless;
app boots and the UI fetches settings over RPC at startup.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 17:14:50 +02:00
JokinandClaude Fable 5 262f4de04d README: document tabs, status bar, new shortcuts
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 14:50:51 +02:00
JokinandClaude Fable 5 76b9b621a2 P6: placeholder icon, README, packaged build verified
- assets/icon.png (generated by scripts/make-icon.py) + icon.iconset
  (scripts/gen-iconset.sh); electrobun compiles it to AppIcon.icns
- branding.icon points at the iconset
- README: features, stack, dev/build, rebranding, plaintext-password warning,
  shortcuts, v1 scope
- verified: full production build (ng build + electrobun build) produces a
  launchable BunSCP.app that boots standalone from views://app

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 14:19:16 +02:00