Commit Graph

92 Commits

Author SHA1 Message Date
Fredrik Johansson
d09aa2b219 feat: reactions, link previews, mobile layout, TUI multi-network + /react usage hints
- TUI /react shows usage hint on bad/missing args instead of silently no-oping
- README: document /join /net /react slash commands and Ctrl+N keybinding
- README: add send_reaction IPC command and reaction IPC event to protocol reference
- FUTURE.md: mark reactions, link previews, responsive mobile layout, TUI
  multi-network and TUI reactions as shipped; add prose sections for each
- EXTENSIONS.md: add EXT-008 documenting reaction wire protocol, SQLite
  schema, IPC commands/events, history replay, and browser-mode implementation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 20:08:52 +02:00
Fredrik Johansson
437deca6a0 feat: TUI multi-network + reactions + history
Multi-network:
- Left panel now shows Networks section above Rooms
- /join <name> joins a new network at runtime; -network flag now optional
- ctrl+n cycles between joined networks; /net <n|name> switches by number or name
- All state (rooms, peers, messages) scoped per network via netData struct
- Messages keyed by "netId:room" (same as web store)

Reactions:
- /react <emoji>  — react to the last message in the current room
- /react <n> <emoji> — react to message number n
- Reactions displayed as a dimmed line below each message: 👍 2  ❤️ 1
- EvtReaction handler updates in-place and refreshes viewport

History:
- EvtHistoryLoaded now handled: historical messages prepended, deduped by mid, sorted by time

UX:
- Each message prefixed with [n] line number so /react targets are unambiguous
- -network flag is now optional (start idle, /join to connect)
- Status bar hint updated with new commands

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 20:02:50 +02:00
Fredrik Johansson
851cfdc7e9 fix: reactions in browser mode (BrowserAdapter)
- Include mid on the wire in sendChat() so recipients can reference it
- Handle incoming 'reaction' wire message in PeerConn._onControl
- Add PeerConn.sendReaction() to send the reaction wire message
- Handle 'send_reaction' IPC command in BrowserAdapter.send()
- Emit 'reaction' IPC event on receive and on local send
- Use wire mid (not synthetic peer-ts mid) when receiving chat messages

Reactions now work across all combinations: daemon↔daemon,
browser↔browser, and daemon↔browser.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 19:27:44 +02:00
Fredrik Johansson
4a7a95fe9d feat: message reactions + link/image previews
Reactions (full stack):
- Wire: MsgReaction peer message (reaction_mid, reaction_emoji)
- Store: reactions table (mid, emoji, from_peer), SaveReaction, ReactionsForRoom
- Daemon: CmdSendReaction IPC command; EvtReaction IPC event; stored reactions
  replayed to newly-connected IPC clients alongside history
- Web UI: reactions state (mid → emoji → [fromId]); hover a message to reveal
  a + button; click opens a 6-emoji picker (👍❤️😂😮😢🙏); reaction chips
  appear below the message with count and tooltip; own reactions highlighted

Link/image previews:
- URLs in message text rendered as clickable <a> links
- Image URLs (.jpg/.jpeg/.png/.gif/.webp/blob:/data:image) rendered as inline
  thumbnails (max 320×200px) below the link

Also scoped push notifications architecture in FUTURE.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 19:17:16 +02:00
Fredrik Johansson
32a6f46481 feat: responsive mobile layout with slide-over sidebar
On screens ≤600px the sidebar collapses off-screen. A hamburger button
in the message header opens it as a slide-over drawer with a dim
overlay; tapping a room/network or the ✕ button closes it. Desktop
layout is unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 18:53:18 +02:00
Fredrik Johansson
1d9c9d1524 fix: add explicit Join button to sidebar add-network form
All checks were successful
Build / Build & release (push) Successful in 13m37s
The form had no submit button so there was no visible way to confirm.
Enter should have worked but was unreliable with two inputs. Added a
disabled-until-valid Join button.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v.0.1.2
2026-06-29 18:40:41 +02:00
Fredrik Johansson
f5fb0862ff fix: key messages by networkId:room to prevent collision across networks
Two networks sharing a room name (e.g. "general") were clobbering each
other's message lists. Now keyed by `${networkId}:${room}` throughout
the web store, MessagePane, and Sidebar DM detection.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 16:55:16 +02:00
Fredrik Johansson
dab5387cbd feat: multi-network join, persistence, and switching in web UI
- Sidebar: "+" button next to Networks opens an inline join form;
  in browser mode shows anchor URL field; saves to waste_saved_networks
- Onboarding: saved networks shown as quick-join chips above the join
  form; auto-rejoin all saved networks on reconnect (not just one)
- Browser mode: networks persisted as [{name, anchor}] array in
  localStorage (waste_saved_networks); legacy waste_last_network kept
  for backward compat
- Daemon mode: daemon already tracks joined networks; web UI just needs
  the "+" to send join_network for additional ones

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 16:38:46 +02:00
Fredrik Johansson
1d9827beb0 docs: mark resume UX and history gossip shipped; remove proposal doc
- FUTURE.md: remove "not yet done" note on resume UX, update Native UI
  section to reflect tray/notifications shipped, add new roadmap entries
- Delete PROPOSAL-history-gossip.md (implemented, documented in EXTENSIONS.md)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 15:47:14 +02:00
Fredrik Johansson
fcbd84f873 fix: compact timestamps, historical alias resolution, wider ts column
- Timestamps now show "Jun 28 10:58" for older messages (dropped
  "Yesterday" which overflowed the fixed-width column)
- Timestamp column widened from 52px to 72px to fit date+time
- state_snapshot now includes known_peers (historically seen, not
  currently connected) so the UI can resolve aliases in history
- MessagePane aliasFor falls back to knownPeers map

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 13:43:29 +02:00
Fredrik Johansson
cef9374416 fix: show date in timestamps; fix history divider appearing immediately
- MessagePane: show date in timestamps (Yesterday/MMM D) for messages
  not from today; divider now appears at the top of history on load
  rather than waiting for a live message to create the boundary
- TUI: same date-aware timestamp formatting (Yesterday / Jan 2)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 11:45:51 +02:00
Fredrik Johansson
9ad3c96d43 fix: send stored history to IPC client on connect
history_loaded events were fired when peers exchanged history gossip,
but the browser UI often connects to the daemon after that handshake
has already happened. Now the daemon pushes recent messages for all
known rooms immediately after the state_snapshot on each new IPC
connection, so the browser always gets history regardless of timing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 11:30:33 +02:00
Fredrik Johansson
48400440dd fix: history gossip not triggering for pre-feature messages
Two bugs:
1. RecentMessagesSince had msg_id IS NOT NULL filter — messages sent
   before EXT-007 deployment all have msg_id=NULL so nothing was returned.
   Removed the filter; mid-based INSERT OR IGNORE dedup is sufficient.
2. queryMessages didn't SELECT room, so gossipped messages had empty room
   field. Added room to SELECT and Scan in queryMessages.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 11:14:43 +02:00
Fredrik Johansson
0e812a2479 fix: clear file progress on completion in daemon mode
file_complete in daemon mode carries transfer_id but no offer field.
The old condition required msg.offer, so the progress/cancel row was
never removed. Now clears using transfer_id first, offer.xid as fallback.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 10:55:00 +02:00
Fredrik Johansson
f319721e01 feat: resumable transfer UX — surface partial downloads to UI on reconnect
Daemon scans the download directory for .tmp.meta sidecars on network join
and emits resumable_transfers IPC event. Web UI shows them in the Transfers
panel with a dimmed progress bar and "will resume on reconnect" note.

- proto: ResumableFile type, EvtResumableTransfers, resumable_files IpcMessage field
- mesh: ScanResumable() scans download dir and emits the event
- netmgr: call ScanResumable() after join (both Join and JoinByHash paths)
- web: resumableFiles store state, resumable_transfers handler, Transfers UI section

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 10:02:49 +02:00
Fredrik Johansson
9de625d617 feat: render history_loaded in web UI with earlier messages divider
- store: handle history_loaded event — prepend gossipped messages,
  dedup by mid, sort by ts, record cutoff timestamp per room
- MessagePane: show "earlier messages" divider between history and
  live messages based on the cutoff timestamp
- types: add history_loaded, room_created, create_room to IpcMsgType;
  add messages field to IpcMessage

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 23:50:48 +02:00
Fredrik Johansson
15306dc0c2 ci: use npm install instead of npm ci to avoid lockfile sync issues
All checks were successful
Build / Build & release (push) Successful in 13m34s
The CI runner resolves @emnapi deps differently than local npm, causing
npm ci to fail regardless of Node version. npm install is more forgiving.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v0.1.1
2026-06-28 23:08:49 +02:00
Fredrik Johansson
7c3cedc549 feat: EXT-007 P2P message history gossip
After hello verification, the connecting peer sends history_request to
the first peer it meets (one per room, no fan-out). The responder queries
SQLite and replies with a history_chunk. Received history is stored via
INSERT OR IGNORE (mid dedup) and emitted as history_loaded IPC events.

- proto: MsgHistoryRequest/Chunk types, HistoryEntry, EvtHistoryLoaded,
  ComputeMsgID (sha256 content-addressed ID), MsgID field on ChatMessage
- store: ALTER TABLE ADD COLUMN msg_id + unique index migration (idempotent);
  RecentMessagesSince query (msg_id IS NOT NULL filter); msg_id persisted on save
- mesh: RequestHistoryFrom, HandleHistoryRequest, HandleHistoryChunk methods;
  historyRequested/historyFirstPeer state to ensure single-peer requests
- peer: dispatch history_request/history_chunk; RequestHistoryFrom after hello;
  stamp MsgID on incoming chat messages
- ipc: stamp MsgID on outgoing group chat messages
- EXTENSIONS.md: EXT-007 documented

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 23:08:17 +02:00
Fredrik Johansson
1c73f1b1ef ci: bump Node to 24 to match local lockfile; add history gossip proposal
Some checks failed
Build / Build & release (push) Failing after 7m6s
package-lock.json was generated with npm 11 (Node 24). CI was running
Node 20 which resolves @emnapi deps differently, causing npm ci to fail.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 22:53:35 +02:00
Fredrik Johansson
b2b5c8c7cb ci: fix webkit dep for Ubuntu 24.04 (Noble)
Some checks failed
Build / Build & release (push) Failing after 7m5s
libwebkit2gtk-4.0-dev was dropped in Noble; use 4.1 and pass
-tags webkit2_41 to wails build.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v0.1.2
2026-06-28 22:28:04 +02:00
Fredrik Johansson
b6ff30de78 ci: rewrite workflow as single job to avoid upload-artifact
Some checks failed
Build / Build & release (push) Failing after 5m15s
Gitea act_runner intercepts actions/upload-artifact regardless of version
tag and uses an incompatible built-in. Restructured as one job that builds
all server binaries (cross-compiled) and the Linux desktop app, then
publishes directly to the release — no artifact handoff needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 22:02:43 +02:00
Fredrik Johansson
1bd719fa58 ci: downgrade artifact actions to v3 for Gitea GHES compatibility
upload-artifact@v4 and download-artifact@v4 are not supported on GHES.
Also drop merge-multiple (v4-only) and adjust release glob to artifacts/*/*.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 21:53:07 +02:00
Fredrik Johansson
be297d3a49 docs: add QUICKSTART.md for non-technical users
Three paths: browser-only, desktop app download, headless daemon.
Covers invites, anchor server basics, and mobile install.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 21:46:37 +02:00
Fredrik Johansson
c426fa8c08 chore: gitignore root-level app and waste binaries
Some checks failed
Build / Server binaries (amd64, linux) (push) Has been cancelled
Build / Server binaries (amd64, windows) (push) Has been cancelled
Build / Server binaries (arm64, darwin) (push) Has been cancelled
Build / Server binaries (arm64, linux) (push) Has been cancelled
Build / Desktop app (Linux amd64) (push) Has been cancelled
Build / Publish release (push) Has been cancelled
Build / Server binaries (amd64, darwin) (push) Has been cancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v0.1.0
2026-06-28 21:38:50 +02:00
Fredrik Johansson
0789cf8840 feat: download dirs, file transfer resume, Wails desktop app, PWA, CI
Daemon:
- Per-network download directories (-download-dir flag, set_download_dir IPC)
- File transfer resume after disconnection: .tmp.meta sidecars survive
  interruption; resume_offset in file-accept lets sender seek and continue
- set_download_dir IPC command; download_dir reported in state_snapshot

Protocol:
- PeerMessage.ResumeOffset (EXT-006) for file transfer resume
- IpcMessage.ShareNetworks json tag changed from "networks" to "network_ids"
  to fix duplicate json tag collision with Networks []NetworkInfo

Desktop app (cmd/app):
- Wails v2 shell embedding daemon logic directly (no subprocess)
- System tray on Linux/Windows via getlantern/systray; macOS hides to Dock
- OS notifications for message_received and file_complete via Wails events
- notray build tag for headless/CI builds without GTK tray headers
- build-app.sh: builds web frontend, copies dist, runs wails build

Web / PWA:
- manifest.json + Apple touch icon meta tags for mobile "Add to Home Screen"
- PNG icons (192px, 512px, 180px) generated from SVG
- Wails EventsOn("notify") hook in App.tsx for native OS notifications

CI:
- .gitea/workflows/build.yml: server binaries cross-compiled for 5 platforms,
  desktop app for Linux amd64, release artifacts published on v* tags

Docs:
- README: download dir, file transfer resume, desktop app, PWA, CI sections
- EXTENSIONS.md: EXT-004 daemon mode marked shipped; EXT-006 resume added
- FUTURE.md: roadmap updated

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 21:38:28 +02:00
Fredrik Johansson
d233f4d79e docs: update README and FUTURE for TURN daemon, room creation, unread indicators
Mark TURN daemon mode, TUI room creation + SQLite persistence, and unread
room indicators as shipped. Update IPC reference with create_room/room_created.
Add TUI slash commands section. Remove now-stale "not yet done" notes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 22:36:13 +02:00
Fredrik Johansson
95fd29ae8d feat: unread indicator (*) for rooms with new messages
Rooms that receive a message while not active show a * prefix in the
sidebar. The marker clears when you tab to that room.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 22:30:10 +02:00
Fredrik Johansson
340735f992 feat: TUI room creation + daemon-side room persistence
/room <name> in the TUI sends create_room to the daemon, which persists
it in the rooms SQLite table and echoes room_created back. state_snapshot
now includes persisted rooms so they survive reconnects. Tab navigation
and room rendering pick them up automatically.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 22:26:12 +02:00
Fredrik Johansson
1308082c7b Add TURN relay support for daemon mode
-turn-url and -turn-secret flags on the daemon; credentials generated
using coturn use-auth-secret HMAC-SHA1 scheme (same as browser mode).
ICEServers field on mesh.Mesh threads extra ICE servers through to
every PeerConnection created by the anchor client.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 22:16:18 +02:00
Fredrik Johansson
31e13fd509 Add signed invites, hang links, multi-share, and EXTENSIONS.md
- Signed invites: waste: URI gains inviter+sig fields (Ed25519); hello
  carries the invite so receiving peers can verify against known keys
- RequireInvite per-network flag: rejects peers without valid signed invite
- Hash-based hang links: #waste:base64 fragment pre-fills join form without
  server-side leakage of network name
- Multi-share: shares.json (daemon) + waste_shares localStorage (browser);
  IPC add_share/remove_share/list_shares commands
- EXTENSIONS.md: addendum documenting all waste-go protocol deviations from
  YAW/2; all extensions are additive and backward compatible

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 22:05:56 +02:00
Fredrik Johansson
0e8ddbf4f4 docs: update README and FUTURE for multi-share, file browser, session persistence
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 21:18:56 +02:00
Fredrik Johansson
f326ff2605 fix: remove unused useEffect import in ShareManager
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 20:49:17 +02:00
Fredrik Johansson
e0704f210c feat: persistent multi-share configuration (shares.json + localStorage)
Daemon side:
- internal/shares: new package reads/writes shares.json next to identity
- proto: add ShareEntry type, add_share/remove_share/list_shares IPC commands,
  shares_list event, path field on FileEntry
- netmgr: load shares.json on startup; ScanAllShares combines legacy ShareDir
  with shares.json entries (recursive walk with relative paths)
- mesh: ScanFiles callback lets manager inject multi-share scanning without
  mesh knowing about shares.json
- ipc: handle add_share, remove_share, list_shares commands

Browser side:
- ShareManager component replaces FolderPicker: shows list of named shares
  with remove/re-pick buttons; persists share records to waste_shares in
  localStorage (name, global flag, networkId)
- FolderPicker retained for internal use; Sidebar now uses ShareManager

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 20:47:11 +02:00
Fredrik Johansson
0f54f3bbad feat: subfolder support in file sharing + directory browser UI
- FolderPicker: uses webkitRelativePath so paths like docs/report.pdf
  are preserved; adds "include subfolders" checkbox (default on)
- FileBrowser: virtual directory tree with breadcrumb navigation,
  sort by name/size, search filter, folders shown before files
- Protocol: browse sends path alongside name; get uses path as key
- FileEntry type gains optional path field

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 20:29:00 +02:00
Fredrik Johansson
80e05b81ac docs: clarify browser folder-picker upload prompt is a browser warning
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 20:18:34 +02:00
Fredrik Johansson
2c71d9c5c6 feat: session persistence, logout button, TURN HMAC fix; update docs
- Browser mode auto-rejoins saved network on reload (waste_last_network)
- Logout button (⏻) in sidebar clears session; optionally clears identity keypair
- TURN credentials now use HMAC-SHA1 of username (coturn use-auth-secret compatible)
- README: deploy scripts documented, session persistence section, serve-web.sh noted
- FUTURE.md: mark shipped items, add remaining work for daemon TURN + TUI rooms

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 20:16:18 +02:00
Fredrik Johansson
dfbdd34aaa fix(turn): generate HMAC-SHA1 credentials for coturn use-auth-secret
coturn's use-auth-secret mode requires the TURN password to be
HMAC-SHA1(secret, username), not the raw secret. Pass ice servers
as a constructor argument so the async credential generation happens
before RTCPeerConnection is created.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 20:07:53 +02:00
Fredrik Johansson
295851f966 docs: replace example TURN secret with placeholder
Committed a generated hex string that looked like a real secret.
Replaced with YOUR_SECRET_HERE to make it obviously an example.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 21:52:50 +02:00
Fredrik Johansson
02eb83b63a docs: use a real generated secret in coturn example
Replace placeholder YOUR_RANDOM_SECRET with an actual openssl rand -hex 32
output, with a note to generate a fresh one. Keeps the example copy-pasteable.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 21:16:48 +02:00
Fredrik Johansson
ea1eb767f1 Add TURN relay support and document coturn setup
Browser adapter reads turnURL + turnSecret from WASTE_CONFIG and adds a
TURN ICEServer entry automatically. Uses time-limited credentials
compatible with coturn's use-auth-secret mode.

README: new section under Hosting with coturn install, turnserver.conf,
firewall note (UDP 3478, no NPM needed), and config.js snippet.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 21:12:03 +02:00
Fredrik Johansson
c4032417ae Show peers immediately on discovery, before DataChannel opens
Emit peer_connected + peer_status(connecting) as soon as a PeerConn is
created, so peers appear in the sidebar even if ICE is still negotiating
or ultimately fails. The alias updates in-place once the DataChannel hello
arrives with the real nick.

Fixes: mobile/CGNAT peers being completely invisible when STUN hole
punching fails — they now show with a connecting/failed dot instead of
not appearing at all.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 20:54:47 +02:00
Fredrik Johansson
fb14ca82af Add rooms, per-network file sharing, and file transfer UX
Additional rooms:
- Store tracks customRooms per networkId; createRoom action slugifies and
  deduplicates, switches active room on creation
- Sidebar: + button next to Rooms label opens an inline input; Escape
  dismisses; Enter creates the room

Per-network share directories:
- Store tracks sharedFilesByNetwork keyed by networkId instead of a single
  global map; setSharedFiles(files, networkId?) defaults to activeNetworkId
- FolderPicker reads per-network map to display accurate file count label

File transfer UX:
- Incoming file-offer now emits pending_offer instead of auto-accepting;
  user sees Accept / Reject buttons in the sidebar Transfers section
- Progress events emitted per chunk during receive; Transfers panel shows
  a live progress bar with received/total sizes
- file-cancel protocol message: sender or receiver can cancel an in-flight
  transfer; DataChannel is closed and buffers discarded
- PeerConn: acceptOffer(), rejectOffer(), cancelRecv(), cancelSend()
- BrowserAdapter: acceptOffer(), rejectOffer(), cancelTransfer()
- Store: pendingOffers, fileProgress, acceptOffer, rejectOffer, cancelTransfer
- Transfers component renders in sidebar; auto-hides when no activity

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 20:49:15 +02:00
Fredrik Johansson
5421352e62 docs: update FUTURE.md to reflect current shipped state
Mark web UI, peer gossip, and identity backup as shipped. Expand TURN
section with concrete implementation notes (one-liner ICEServers change +
3 daemon flags). Add per-network share directories and additional
channels/rooms as next items. Remove stale "not implemented" notes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 20:40:33 +02:00
Fredrik Johansson
068e7e6566 docs: update README with file sharing and browser mode clarifications
Document the folder sharing, peer file browsing, and direct push (📎)
workflows added in the previous commit. Clarify that browser mode also
activates locally when config.js sets signalURL.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 20:31:54 +02:00
Fredrik Johansson
91b7406d01 Add peer-to-peer file transfer in browser mode
Implements both pull (browse & download from a shared folder) and push
(send a file directly to a peer) using the yaw2 file protocol over WebRTC
DataChannels.

- PeerConn: handle browse/files/get/file-offer/file-accept/file-done
  control messages; stream files in 64KB chunks over f:xid binary
  DataChannels; auto-accept incoming offers (push and pull)
- PeerConn.sendFilePush(): initiate an outbound file transfer without
  requiring the peer to browse first
- BrowserAdapter: sharedFiles map, setSharedFiles(), requestBrowse(),
  requestGet(), sendFileTo() — propagates share map to all active peers
- Store: activeFilePeer, setActiveFilePeer, setSharedFiles, browseFiles,
  sendFileTo; file_complete handler triggers browser download automatically
- FileBrowser component: third-column panel listing a peer's shared files
  with name, size, and a download button
- FolderPicker component: webkitdirectory input in the sidebar (browser
  mode only) for selecting a local folder to share
- Sidebar: 📎 send-file button on peer rows (hover) with inline file picker
- App.tsx: use browser mode when WASTE_CONFIG.signalURL is set, even on
  localhost — allows testing browser mode via npm run dev with config.js
- deploy-daemon.sh: kill existing daemon before scp to avoid upload failure
  when the binary is locked; remove duplicate kill block in restart step

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 20:29:54 +02:00
Fredrik Johansson
ea66e2eb58 ui: fix peer row spacing — alias no longer flex:1
ID takes flex:1 now, sitting right after the alias. Actions push right via margin-left:auto.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 19:51:27 +02:00
Fredrik Johansson
076f9641c2 ui: clean up self entry in peer list
Replace bold duplicate-looking self row with dimmed name + small accent
"you" badge. Removes the ID (already shown in identity section at top).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 19:48:28 +02:00
Fredrik Johansson
1d38766006 ui: fix message layout — no-wrap timestamp, tighter alias column
Switch back to flex, set explicit widths: 52px timestamp (nowrap, 24h),
90px alias (right-aligned). Eliminates wrapping and the large gap.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 19:47:19 +02:00
Fredrik Johansson
f5a11cb22b ui: fix message alignment, show self in peer list
Messages now use a fixed grid (44px ts · 120px alias right-aligned · 1fr text)
instead of flex, so text always starts at the same column regardless of alias length.

Self shown at top of peer list with accent dot and bold name.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 19:45:08 +02:00
Fredrik Johansson
478a0a32af chore: gitignore serve-web.sh
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 19:37:48 +02:00