Commit Graph
112 Commits
Author SHA1 Message Date
jgamboaandClaude a40433b99e Add built-in auto-updater with tab-bar update pill
Wires electrobun's Updater to the /dl download host. The packaged app checks
https://miniscp.com/dl on launch + every 6h; when a newer build exists, an
accent-colored "update tool" appears next to Connections in the tab bar. It
announces the update, becomes its own inline progress bar while downloading,
then flips to "Restart to apply" (two-step: download, then user-triggered
relaunch).

- electrobun.config.ts: release.baseUrl = https://miniscp.com/dl (baked into
  version.json at build; miniscp.com fronted by an external proxy for TLS).
- rpc.ts: checkForUpdate/downloadUpdate/applyUpdate requests + updateStatus push.
- rpc-handlers.ts + index.ts: call Updater; poll on launch+6h; stream
  onStatusChange progress. checkForUpdate self-guards the dev channel.
- rpc.service.ts + new updater.service.ts: signal-based state
  (available -> downloading -> ready, ready derived from downloadUpdate ok).
- tab-bar.ts: single bg-primary pill; progress fills the pill itself.
- icons.ts: register mynaDownload. i18n: tabBar + menu keys across all locales.
- menu.ts + app.ts: "Check for Updates…" app-menu item -> UpdaterService.check().
- docs: build-and-release + architecture updated.

Unsigned builds still update (applyUpdate strips the macOS quarantine xattr).
Verified: tsc --noEmit (exit 0) + build:ui AOT (exit 0). Live pill + full
download/apply flow require a two-build test on the host.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-14 16:43:40 +02:00
jgamboaandClaude Fable 5 a0f56822cd Internationalization: 7 languages with live switching
Custom signal-based runtime (no i18n dependency): shared src/shared/i18n
dictionaries, ui I18nService.t() reactive by construction so language
switches live, and a backend i18n.ts for native menus + thrown errors.
Every user-facing string keyed across templates, toasts, dialogs, file
kinds, columns, macOS menu/context menus, and errors. Language picker in
Options (auto-detects OS locale, falls back to English); switching
relabels the webview and native chrome instantly. English/Spanish/French/
German fully drafted; Chinese/Japanese/Basque drafted, flagged for native
review. Docs updated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 15:52:54 +02:00
jgamboaandClaude Fable 5 ee5a9e13e6 Auto-refresh the active tab's panels (silent, non-disturbing)
Local panels are fs.watched (LocalDirWatcher + setWatchedDirs -> pathRefresh);
remote panels poll every 3s. New refresh({silent}) skips the loading/busy
flags and touches no DOM, snapshotting sessionId+cwd to discard results if the
user navigated mid-flight. Only the active tab is live; switching tabs
refreshes the new pair. A future on/off setting is left as commented
breadcrumbs. Docs updated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 14:03:35 +02:00
jgamboa 39b1858957 connection manager paragraphs tweak 2026-07-14 12:39:26 +02:00
jgamboa 5863ae1079 Revert back to more informative text in Import button 2026-07-14 10:22:56 +02:00
jgamboa 2d95857de1 Button ui tweaks 2026-07-14 09:43:06 +02:00
JokinandClaude Fable 5 ef34104cf0 Fix white/inverted flash when windows open
Three layers: windows are created hidden and revealed on the webview's
first dom-ready (800ms fallback); the bun preload bakes the persisted
theme data-attributes so the first paint is already themed; and
index.html carries an inline background style covering the
pre-stylesheet paint (values mirrored from styles.css tokens).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 09:17:31 +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 d80d5c23dc Sublime-style Build-n versioning + About box
Build n = commit count, baked at build time into a gitignored
version.gen.ts (postinstall + all build scripts regenerate it). About
lives in the macOS app menu and as a footer row in the options popover
(the cross-platform path), showing build, commit, date and engines.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 23:55:39 +02:00
JokinandClaude Fable 5 14b92b33a4 Suppress the webview's default right-click menu
Reload/Inspect Element no longer appear on uncontrolled right-clicks
in any window; text fields keep the system text menu.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 23:30:23 +02:00
JokinandClaude Fable 5 ab59c785b5 Configurable list columns via header right-click
Native checkable menu on the column headers toggles Size, Modified,
Kind, Rights, Owner and Group (persisted, both panels). Owner/group
come from the ls-style SFTP longname remotely and cached uid/gid
lookups locally (POSIX; undefined on Windows). All columns sort.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 23:30:23 +02:00
JokinandClaude Fable 5 485603fd30 Saved connections and stacks open remote on the right panel
Local left, remote right — the commander convention. Panel-dropdown
connects still target the panel they were opened from.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 23:18:34 +02:00
JokinandClaude Fable 5 d22bc9b4e2 Connection manager design refresh; fix stack-row button crowding
Import moves to the window header; sidebar widens with a muted tint;
the stack row's count and action buttons swap on hover instead of
sharing the row, so long names can't collide with them.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 23:13:53 +02:00
JokinandClaude Fable 5 7dd59a9752 Connection manager in its own native window, modal to main
Single window centered over the main app. Electrobun has no native
modality, so it's approximated: bun bounces the main window's focus back
to the manager, the main webview shows a click-swallowing overlay, and
main-targeted menu/keyboard actions are dropped while open. Editor
windows stay fully usable. Connect/open-stack execute in the main
window via the existing connect: action channel; store edits push a
connectionsChanged refresh. Trigger moved from the panel dropdown to a
tab-bar button.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 23:11:58 +02:00
Jokin 27d0ac81d6 file icons setting text 2026-07-13 23:04:16 +02:00
JokinandClaude Fable 5 62ff845944 Decouple dialog refocus from PanelsService via FocusService
Dialogs only needed refocus(); injecting PanelsService boots a whole
workspace, which secondary windows must not do.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 23:02:25 +02:00
JokinandClaude Fable 5 93a9b07722 Editor: live settings sync + session-death banner
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 22:39:31 +02:00
JokinandClaude Fable 5 6a19097b25 Editor: line numbers, wrap toggle, find bar
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 22:38:38 +02:00
JokinandClaude Fable 5 1652b9e298 Editor opens in native windows (one per file)
Real BrowserWindow per edited file with its own RPC instance, deduped by
sessionId+path. The same Angular bundle boots an editor-only root via
preload globals. Native close isn't cancellable in electrobun, so the
editor mirrors its draft to bun; traffic-light closes get a native
Save/Discard prompt after the fact, and failed saves park the draft in
the edit-leftovers dir. In-window closes (Cmd+W, Close) use a styled
prompt; the quit guard now also counts unsaved editors.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 22:36:11 +02:00
JokinandClaude Fable 5 70f3f2a2e6 Smaller accent swatches
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 21:54:56 +02:00
jgamboaandClaude Fable 5 e2f3737656 Redo connection manager: Stacks, More options, drag & drop, WinSCP import
Folders become Stacks (connections.json v2, no v1 migration): collapsible
stack-first list, open-stack-in-tabs (first reuses a pristine tab), drag
connections between stacks. More... reveals a per-connection Local
directory applied to the other panel when local and untouched. Import
reads a WinSCP.ini export incl. deobfuscated passwords.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 18:28:30 +02:00
jgamboa 9a4420fdc2 Toast fixes 2026-07-13 18:06:48 +02:00
jgamboaandClaude Fable 5 dda596c50c Panel busy states: Connecting placeholder with Cancel, slow-load overlay
Connecting blanks the list to a fading spinner with the target name and
a Cancel button (token discards late results and orphan sessions).
Listings >300ms dim the list under a spinner. All panel input is
blocked while busy; the source picker stays usable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 16:36:44 +02:00
jgamboaandClaude Fable 5 4a793ca50e Remove disconnect button; picking Local or closing the tab covers it
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 15:55:06 +02:00
jgamboa 9f79bb0b17 Change dark coloring 2026-07-13 15:53:37 +02:00
jgamboaandClaude Fable 5 bdae49ba24 Dark tone setting: grey Dark (default) vs near-black Darker
Tone row appears under Theme when the effective theme is dark.
Grey palette uses macOS-like #26262a background.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 15:43:01 +02:00
jgamboa eb86ca514d New tab icon sizing change 2026-07-13 14:28:53 +02:00
jgamboaandClaude Fable 5 628ccebd9a Rename Text size to Interface; scale panel header with it
Action buttons, server picker, and its dropdown now follow the size
setting via new --action-h/--action-font/--action-icon variables.
Default tier matches the old fixed sizes; tab bar stays fixed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 14:26:25 +02:00
jgamboa 09792c93cf Fix light-dark scroll bars 2026-07-13 14:19:46 +02:00
jgamboaandClaude Fable 5 f4819a58fe List ~/.ssh/config hosts in the panel source dropdown
Read-only group below saved connections; hosts resolve HostName/User/
Port/IdentityFile (Include, wildcards, %-tokens) and connect on click.
New ssh-agent auth kind covers hosts without a usable identity file;
ProxyJump/ProxyCommand hosts are shown disabled.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 14:10:52 +02:00
jgamboa fdf65766b5 Change to mynaDots icon, size change 2026-07-13 13:49:32 +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 320080de6d Blue as default accent; slightly smaller swatches
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 01:40:49 +02:00
JokinandClaude Fable 5 44f077380f File-type icon colors with Plain/Multi setting (multi default)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 01:31:10 +02:00
JokinandClaude Fable 5 2f4bc63ac8 Accent tone setting with macOS-style swatches (indigo default)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 01:26:35 +02:00
JokinandClaude Fable 5 c7b0418904 Jump to tab with Cmd+1-9 (Ctrl elsewhere), Firefox style
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 00:06:55 +02:00
JokinandClaude Fable 5 aed565e424 Key-file picker in the connection manager
Choose... button beside the private-key field opens the native file dialog
starting in ~/.ssh (Utils.openFileDialog via a pickKeyFile RPC).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 23:50:44 +02:00
JokinandClaude Fable 5 fbbde16f35 Right-click context menus on file panels
Native menus (electrobun ContextMenu) on rows and empty panel space. Rows:
Open (dirs navigate; local files open with the default app via Utils.openPath),
Edit, Copy to Other Panel, Rename, Permissions, Copy Path (works for remote
paths too), Reveal in Finder (local, Utils.showItemInFolder), Move to Trash
(local, Utils.moveToTrash — tooltip notes Finder Restore doesn't apply) and
Delete. Empty space / '..': New Folder, New File, Refresh, Reveal in Finder.

Right-click parks the cursor on the row (keeping the selection when clicking
inside it). Local shell actions run bun-side directly; everything else routes
through the existing menuAction channel back to the stored click target.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 23:48:23 +02:00
JokinandClaude Fable 5 9737cad6de Type-to-filter in file panels
Typing while the list is focused builds a filter query: a bar appears under
the column headers (search icon, query, live match count, Esc hint, clear
button) and the listing narrows to substring matches — '..' always stays.
Backspace edits the query, Escape clears it, cursor parks on the first match,
arrows/Enter keep working (the list never loses focus), and Space keeps its
select meaning until a query exists. Filter resets on directory change and
survives refresh; operations act only on visible (filtered) selection.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 22:05:23 +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 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 06dbe14d76 Toolbar buttons show text labels when the panel is wide
Container query on the panel (Tailwind v4 @container): Copy, Edit, Rename and
Delete grow labels at >=30rem panel width; New folder, New file and
Permissions stay icon-only (self-explanatory icons). Tooltips unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 20:30:24 +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 eaa2d00115 Finished-transfers setting + transfer-list header with Clear finished
- Options popover: 'Finished transfers' Auto-clear | Keep (default auto-clear,
  the previous behavior); persisted like the rest
- Transfer list header: 'N active · M finished' + Clear finished button
  (dismisses completed/failed/cancelled only, never running/queued)
- Failed rows now name the file that failed alongside the error message

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 19:56:24 +02:00
JokinandClaude Fable 5 45df0e450f Options button icon: mynaCog -> mynaConfigVertical
Manage connections keeps the cog; the global options gear gets the vertical
sliders icon.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 19:38:31 +02:00
JokinandClaude Fable 5 7712655c3d Connection manager fixes: folder select, open-all-in-tabs, stable hover
- Folder select showed '(none)' regardless of the actual folder (Angular sets
  [value] on the select before its options render), so 'move out of folder'
  silently saved the old folderId. Per-option [selected] bindings fix both the
  display and the save.
- Folder rows gain 'Open all in tabs': each connection opens in its own new
  tab with the left panel connecting (right stays local); manager closes.
- Folder-row action buttons no longer shift the row on hover (opacity toggle
  instead of display toggle); also canonicalized accent-primary classes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 19:37:51 +02:00
JokinandClaude Fable 5 2d7e7b44cd macOS application menu
Standard menus (App: hide/quit; Edit: clipboard roles enabling Cmd+C/V/X/Z;
View: Refresh Cmd+R + fullscreen; Window: minimize/zoom/cycle) plus File with
New/Close Tab (Cmd+T/W), New Folder/File, and a Connect submenu built from
saved connections (folders as nested submenus, Connection Manager entry).
Custom actions forward to the webview as menuAction messages; the menu rebuilds
whenever connections change. macOS-only per electrobun support.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 19:17:25 +02:00
JokinandClaude Fable 5 20e5703d29 '..' parent row in the file list
Synthetic cursor-navigable first row (hidden at /) — Enter/double-click goes to
the parent like the toolbar button. Excluded from selection, rename, delete,
chmod, and transfers; shown with an up-arrow icon.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 19:14:24 +02:00
JokinandClaude Fable 5 83202ff414 More breathing room between macOS traffic lights and the tabs (pl-20 -> pl-24)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 19:13:39 +02:00