import { Component, createSignal, createMemo, For, Show } from "solid-js"; import { Portal } from "solid-js/web"; import { X, Search, UserPlus, UserMinus, Users, Copy, Check, } from "lucide-solid"; import Avatar from "../common/Avatar"; import Button from "../common/Button"; import Divider from "../common/Divider"; import { knownPeers, markAsFriend, unmarkAsFriend, } from "../../stores/directory"; import { identity } from "../../stores/identity"; import { setActiveDM } from "../../stores/dms"; import { addDMConversation } from "../../stores/dms"; import * as tauri from "../../lib/tauri"; interface UserDirectoryModalProps { isOpen: boolean; onClose: () => void; } type DirectoryTab = "all" | "friends"; const UserDirectoryModal: Component = (props) => { const [searchQuery, setSearchQuery] = createSignal(""); const [activeTab, setActiveTab] = createSignal("all"); const [copiedId, setCopiedId] = createSignal(null); // filter out our own peer id from the directory const filteredPeers = createMemo(() => { const myId = identity()?.peer_id; const query = searchQuery().toLowerCase().trim(); const tab = activeTab(); let peers = knownPeers(); if (tab === "friends") { peers = peers.filter((p) => p.is_friend); } if (query) { peers = peers.filter( (p) => p.display_name.toLowerCase().includes(query) || p.peer_id.toLowerCase().includes(query), ); } else { // if not searching, hide self from the list to avoid confusion peers = peers.filter((p) => p.peer_id !== myId); } return peers; }); async function handleToggleFriend(peerId: string, currentlyFriend: boolean) { try { if (currentlyFriend) { await tauri.removeFriend(peerId); unmarkAsFriend(peerId); } else { await tauri.addFriend(peerId); markAsFriend(peerId); } } catch (e) { console.error("failed to toggle friend status:", e); } } function handleMessagePeer(peerId: string, displayName: string) { // start a dm conversation with this peer addDMConversation({ peer_id: peerId, display_name: displayName, status: "Online", unread_count: 0, }); setActiveDM(peerId); props.onClose(); } function handleCopyPeerId(peerId: string) { navigator.clipboard.writeText(peerId); setCopiedId(peerId); setTimeout(() => setCopiedId(null), 2000); } function handleKeydown(e: KeyboardEvent) { if (e.key === "Escape") props.onClose(); } function handleBackdropClick(e: MouseEvent) { if (e.target === e.currentTarget) props.onClose(); } const tabs: { id: DirectoryTab; label: string }[] = [ { id: "all", label: "all peers" }, { id: "friends", label: "friends" }, ]; return (
{/* header */}

user directory

{/* tabs */}
{(tab) => ( )}
{/* search */}
setSearchQuery(e.currentTarget.value)} />
{/* peer list */}
0} fallback={

{searchQuery() ? "no peers matching your search" : activeTab() === "friends" ? "no friends added yet" : "no peers discovered yet"}

{activeTab() === "friends" ? "add friends from the all peers tab" : "peers will appear as you join communities"}

} > {(peer) => (

{peer.display_name}

friend

{peer.bio}

)}
{/* footer */}

{filteredPeers().length} peer {filteredPeers().length !== 1 ? "s" : ""} in directory

); }; export default UserDirectoryModal;