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>
This commit is contained in:
@@ -81,9 +81,30 @@ details summary { color: var(--muted); font-size: 12px; cursor: pointer; }
|
||||
.message { display: flex; align-items: baseline; gap: 0; padding: 2px 16px; line-height: 1.5; }
|
||||
.message:hover { background: rgba(255,255,255,0.02); }
|
||||
.message-ts { color: var(--muted); font-size: 11px; white-space: nowrap; flex-shrink: 0; width: 52px; }
|
||||
.message-alias { font-weight: 600; font-size: 13px; text-align: right; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex-shrink: 0; width: 90px; padding-right: 10px; }
|
||||
.message-alias { font-weight: 600; font-size: 13px; text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex-shrink: 0; width: 90px; padding-right: 10px; }
|
||||
.message.mine .message-alias { color: var(--accent); }
|
||||
.message-text { word-break: break-word; font-size: 14px; color: var(--text); }
|
||||
.compose { display: flex; gap: 8px; padding: 10px 16px; border-top: 1px solid var(--border); }
|
||||
.compose input { flex: 1; width: auto; }
|
||||
.compose button { flex-shrink: 0; }
|
||||
|
||||
/* ── file browser panel ── */
|
||||
.chat-layout.has-file-browser { grid-template-columns: var(--sidebar-w) 1fr 280px; }
|
||||
.file-browser { display: flex; flex-direction: column; background: var(--surface); border-left: 1px solid var(--border); }
|
||||
.file-browser-header { display: flex; align-items: center; justify-content: space-between; padding: 10px 12px; border-bottom: 1px solid var(--border); }
|
||||
.file-browser-title { font-size: 13px; font-weight: 600; }
|
||||
.file-browser-close { background: none; color: var(--muted); font-size: 14px; padding: 2px 6px; }
|
||||
.file-browser-close:hover { color: var(--text); background: none; }
|
||||
.file-browser-empty { padding: 16px 12px; color: var(--muted); font-size: 13px; }
|
||||
.file-list { list-style: none; padding: 4px 0; overflow-y: auto; flex: 1; }
|
||||
.file-entry { display: flex; align-items: center; gap: 6px; padding: 5px 12px; }
|
||||
.file-entry:hover { background: rgba(255,255,255,0.04); }
|
||||
.file-entry-name { flex: 1; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.file-entry-size { color: var(--muted); font-size: 11px; flex-shrink: 0; }
|
||||
.file-entry-dl { background: none; color: var(--accent); font-size: 14px; padding: 1px 4px; flex-shrink: 0; }
|
||||
.file-entry-dl:hover { background: rgba(124,106,247,0.15); }
|
||||
|
||||
/* ── folder picker ── */
|
||||
.folder-picker { width: 100%; }
|
||||
.folder-picker-btn { background: var(--surface); color: var(--muted); border: 1px solid var(--border); font-size: 12px; padding: 5px 10px; border-radius: 4px; width: 100%; text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.folder-picker-btn:hover { color: var(--text); border-color: var(--accent); background: var(--surface); }
|
||||
|
||||
Reference in New Issue
Block a user