From 0e8ddbf4f47618f0855251b419b9a1de89c1e4b7 Mon Sep 17 00:00:00 2001 From: Fredrik Johansson Date: Fri, 26 Jun 2026 21:18:56 +0200 Subject: [PATCH] docs: update README and FUTURE for multi-share, file browser, session persistence Co-Authored-By: Claude Sonnet 4.6 --- FUTURE.md | 12 ++++++++++-- README.md | 12 +++++++++--- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/FUTURE.md b/FUTURE.md index b42510d..afadd96 100644 --- a/FUTURE.md +++ b/FUTURE.md @@ -68,9 +68,15 @@ When a new peer connects, the mesh immediately gossips the full peer list to the Browser mode now auto-rejoins on reload. The last-used network name, alias, and anchor URL are saved to `localStorage` on join and restored on load. A ⏻ logout button in the sidebar clears session state (optionally including the identity keypair) and reloads the page. ### Per-Network Share Directories ✅ (shipped) -Share state is tracked per `network_id` in the store (`sharedFilesByNetwork`). The folder picker shows per-network file count. Switching networks switches the active share. +Share state is tracked per `network_id` in the store (`sharedFilesByNetwork`). Switching networks switches the active share. -### Additional Channels / Rooms ✅ (shipped) +### Persistent Multi-Share Configuration ✅ (shipped) +Multiple share roots per network, with global (all networks) or scoped visibility. + +- **Daemon:** `shares.json` next to `identity.json` in the data dir. `add_share`/`remove_share`/`list_shares` IPC commands. File listing recursively walks all share roots, returning relative paths. Backward compatible with the existing `set_share_dir` single-dir mechanism. +- **Browser:** `waste_shares` in `localStorage` stores named share records (folder name, global flag). The `ShareManager` sidebar component shows the list with re-pick (↺) and remove (✕) buttons. Actual `File` objects live in memory — the record persists across reloads so the user can restore with one click. + +### Additional Channels / Rooms ✅ (shipped, web UI) The `+` button in the Rooms sidebar section creates custom rooms, stored in `customRooms` keyed by `network_id`. Room names are slugified strings — any peer that sends to a room name causes it to appear on the recipient automatically. DM rooms (`dm:`) appear automatically when messages arrive. **Not yet done:** TUI room creation, daemon-side SQLite persistence of room lists across restarts. @@ -113,6 +119,8 @@ Web frontend (React, already built) + Tauri shell for native packaging. The IPC | ✅ shipped | TURN relay (browser mode, coturn `use-auth-secret`) | | ✅ shipped | File transfer UX (progress, cancel, manual accept) | | ✅ shipped | Session persistence + logout (browser mode) | +| ✅ shipped | Persistent multi-share config (shares.json + localStorage) | +| ✅ shipped | Subfolder support + directory browser UI in file browser | | next | TURN relay for daemon mode | | next | TUI room creation + daemon-side room persistence | | next | File transfer resume after disconnection | diff --git a/README.md b/README.md index 562f8ea..1573710 100644 --- a/README.md +++ b/README.md @@ -199,19 +199,21 @@ File transfer runs peer-to-peer over WebRTC DataChannels — files never touch t ### Sharing a folder -In the sidebar under **Sharing**, click **+ Share folder** to pick a local directory. The selected files become available for peers to browse and download. You can re-click to change the folder at any time; the new set is immediately reflected for any peer that browses again. +In the sidebar under **Sharing**, click **+ Share folder** to pick a local directory. The selected files become available for peers to browse and download. A checkbox lets you control whether subfolders are included (default: yes). + +Multiple folders can be shared — each appears in the list with a ↺ re-pick button (to restore after a page reload) and a ✕ remove button. The share list is saved in `localStorage` so it survives reloads; you'll be prompted to re-pick any folder whose files were lost on reload. > Your browser will show a warning along the lines of "really upload X files?" when you pick a folder. This is a built-in browser security prompt — **no files are uploaded anywhere.** Files are transferred directly to a peer only when they explicitly request one via the file browser. ### Browsing a peer's files -Hover over a peer in the sidebar to reveal action buttons. Click **⊞** to request their file list. A panel opens on the right showing their shared files with names and sizes. Click **↓** next to any file to download it directly from that peer. +Hover over a peer in the sidebar to reveal action buttons. Click **⊞** to request their file list. A panel opens on the right showing their shared files. Folders appear first and are clickable — navigate into them with a breadcrumb trail at the top. Sort by name or size; search to filter across all files in the current directory. Click **↓** next to any file to download it directly from that peer. ### Sending a file directly Hover over a peer and click **📎** to open a file picker. The selected file is pushed immediately to that peer — they don't need to be sharing anything. The recipient's browser auto-downloads the file on arrival. -> File transfer is currently browser mode only. In daemon mode, use `set_share_dir` via IPC and `get_file_list`/`send_file` commands (see IPC protocol below). +> In daemon mode, use `add_share` / `remove_share` via IPC to manage share roots. Share configuration is stored in `shares.json` next to `identity.json` in the data directory and survives restarts. `networks: ["*"]` makes a share visible on all networks; omit to scope it to specific network IDs. The legacy `set_share_dir` single-dir command still works alongside it. --- @@ -314,6 +316,10 @@ Newline-delimited JSON on TCP port 17337 (or WebSocket on 17338). {"type":"get_file_list"} {"type":"get_file_list","peer_id":"<64-hex>"} {"type":"send_file","peer_id":"<64-hex>","path":"notes.txt"} +{"type":"add_share","path":"/home/alice/Music"} // global share +{"type":"add_share","path":"/home/alice/Docs","networks":["abc123"]} // network-scoped +{"type":"remove_share","path":"/home/alice/Music"} +{"type":"list_shares"} {"type":"export_identity","passphrase":"..."} {"type":"import_identity","passphrase":"...","backup":"..."} ```