import { create } from 'zustand' import type { PeerInfo, NetworkInfo, ChatMessage, FileEntry, IpcMessage } from '../types' import { DaemonAdapter } from '../adapter/daemon' interface WasteState { // connection adapter: DaemonAdapter | null daemonStatus: 'disconnected' | 'connecting' | 'connected' // identity localPeer: PeerInfo | null // networks networks: NetworkInfo[] activeNetworkId: string | null // peers connectedPeers: PeerInfo[] // chat — keyed by room messages: Record activeRoom: string // file listings — keyed by peer id fileLists: Record // actions connect: (url: string) => void disconnect: () => void send: (msg: IpcMessage) => void setActiveNetwork: (id: string) => void setActiveRoom: (room: string) => void handleEvent: (msg: IpcMessage) => void } export const useWaste = create((set, get) => ({ adapter: null, daemonStatus: 'disconnected', localPeer: null, networks: [], activeNetworkId: null, connectedPeers: [], messages: {}, activeRoom: 'general', fileLists: {}, connect(url: string) { const adapter = new DaemonAdapter(url) adapter.onStatusChange = (s) => set({ daemonStatus: s }) adapter.on((msg) => get().handleEvent(msg)) adapter.connect() set({ adapter }) }, disconnect() { get().adapter?.disconnect() set({ adapter: null, daemonStatus: 'disconnected' }) }, send(msg) { get().adapter?.send(msg) }, setActiveNetwork(id) { set({ activeNetworkId: id }) }, setActiveRoom(room) { set({ activeRoom: room }) }, handleEvent(msg) { switch (msg.type) { case 'state_snapshot': { const networks = msg.networks ?? [] set({ localPeer: msg.local_peer ?? null, networks, connectedPeers: msg.connected_peers ?? [], activeNetworkId: networks[0]?.network_id ?? null, }) break } case 'network_joined': { set(s => ({ networks: s.networks.some(n => n.network_id === msg.network_id) ? s.networks : [...s.networks, { network_id: msg.network_id!, network_name: msg.network_name!, share_dir: msg.share_dir, }], activeNetworkId: s.activeNetworkId ?? msg.network_id!, })) break } case 'network_left': { set(s => ({ networks: s.networks.filter(n => n.network_id !== msg.network_id), activeNetworkId: s.activeNetworkId === msg.network_id ? (s.networks.find(n => n.network_id !== msg.network_id)?.network_id ?? null) : s.activeNetworkId, })) break } case 'peer_connected': { if (msg.peer) { set(s => ({ connectedPeers: s.connectedPeers.some(p => p.id === msg.peer!.id) ? s.connectedPeers : [...s.connectedPeers, msg.peer!], })) } break } case 'peer_disconnected': { set(s => ({ connectedPeers: s.connectedPeers.filter(p => p.id !== msg.peer_id), })) break } case 'message_received': { if (msg.message) { const room = msg.message.room set(s => ({ messages: { ...s.messages, [room]: [...(s.messages[room] ?? []), msg.message!], }, })) } break } case 'file_list': { if (msg.peer_id && msg.files) { set(s => ({ fileLists: { ...s.fileLists, [msg.peer_id!]: msg.files! }, })) } break } } }, }))