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>
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import { useState } from 'react'
|
||||
import { useWaste } from '../store'
|
||||
import type { PeerStatus } from '../store'
|
||||
import { FolderPicker } from './FolderPicker'
|
||||
import { Transfers } from './Transfers'
|
||||
|
||||
function makeYawCard(id: string, alias: string): string {
|
||||
const nick = encodeURIComponent(alias.trim().slice(0, 40))
|
||||
@@ -30,13 +32,24 @@ export function Sidebar() {
|
||||
networks, activeNetworkId, activeRoom,
|
||||
connectedPeers, peerStatus,
|
||||
setActiveRoom, setActiveNetwork, messages, browseFiles, sendFileTo, adapterMode,
|
||||
customRooms, createRoom,
|
||||
} = useWaste()
|
||||
const [addingRoom, setAddingRoom] = useState(false)
|
||||
const [newRoomName, setNewRoomName] = useState('')
|
||||
|
||||
const rooms = ['general']
|
||||
const netCustomRooms = activeNetworkId ? (customRooms[activeNetworkId] ?? []) : []
|
||||
const rooms = ['general', ...netCustomRooms]
|
||||
Object.keys(messages).forEach(r => {
|
||||
if (r.startsWith('dm:') && !rooms.includes(r)) rooms.push(r)
|
||||
})
|
||||
|
||||
function submitNewRoom(e: React.FormEvent) {
|
||||
e.preventDefault()
|
||||
if (newRoomName.trim()) createRoom(newRoomName)
|
||||
setNewRoomName('')
|
||||
setAddingRoom(false)
|
||||
}
|
||||
|
||||
const displayAlias = localPeer?.alias ?? masterAlias ?? ''
|
||||
const displayId = localPeer?.id ?? masterId ?? ''
|
||||
const card = displayId ? makeYawCard(displayId, displayAlias) : null
|
||||
@@ -75,7 +88,10 @@ export function Sidebar() {
|
||||
</div>
|
||||
|
||||
<div className="sidebar-section">
|
||||
<span className="sidebar-label">Rooms</span>
|
||||
<div className="sidebar-label-row">
|
||||
<span className="sidebar-label">Rooms</span>
|
||||
<button className="sidebar-add" onClick={() => setAddingRoom(v => !v)} title="New room">+</button>
|
||||
</div>
|
||||
{rooms.map(r => (
|
||||
<button
|
||||
key={r}
|
||||
@@ -85,6 +101,17 @@ export function Sidebar() {
|
||||
{r.startsWith('dm:') ? `@ ${r.slice(3, 11)}…` : `# ${r}`}
|
||||
</button>
|
||||
))}
|
||||
{addingRoom && (
|
||||
<form className="sidebar-new-room" onSubmit={submitNewRoom}>
|
||||
<input
|
||||
autoFocus
|
||||
value={newRoomName}
|
||||
onChange={e => setNewRoomName(e.target.value)}
|
||||
placeholder="room-name"
|
||||
onKeyDown={e => e.key === 'Escape' && (setAddingRoom(false), setNewRoomName(''))}
|
||||
/>
|
||||
</form>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{adapterMode === 'browser' && (
|
||||
@@ -94,6 +121,8 @@ export function Sidebar() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Transfers />
|
||||
|
||||
<div className="sidebar-section sidebar-peers">
|
||||
<span className="sidebar-label">Peers · {connectedPeers.length + 1}</span>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user