import { useChat } from '@/providers/ChatProvider' import { useNostr } from '@/providers/NostrProvider' import { useFetchProfile } from '@/hooks/useFetchProfile' import { Pubkey } from '@/domain' import { TAccessMode, EXPIRY_OPTIONS, DEFAULT_MESSAGE_EXPIRY } from '@/services/chat.service' import { Lock, LockOpen, Globe, UserPlus, UserMinus, ShieldPlus, ShieldMinus, UserCheck, UserX, Mail, MailX, Undo2, X, Bell, BellOff } from 'lucide-react' import { useState } from 'react' import { Button } from '../ui/button' type TSubmitKey = 'enter' | 'ctrl+enter' function loadSubmitKey(): TSubmitKey { const v = localStorage.getItem('nirc:submitKey') return v === 'enter' ? 'enter' : 'ctrl+enter' } export default function ChannelSettingsPanel({ onClose }: { onClose: () => void }) { const { currentChannel, channelMods, channelMembers, channelBlocked, channelInvited, channelRequested, channelRejected, channelAccessMode, isOwnerOrMod, addMod, removeMod, approveMember, removeMember, unblockUser, updateAccessMode, updateMessageExpiry, sendInvite, revokeInvite, acceptRequest, rejectRequest, revokeRejection, mutedChannels, toggleMuteChannel } = useChat() const { pubkey } = useNostr() const [addInput, setAddInput] = useState('') const [addMode, setAddMode] = useState<'member' | 'mod' | 'invite'>('member') const [submitKey, setSubmitKey] = useState(loadSubmitKey) if (!currentChannel) return null const isOwner = currentChannel.creator === pubkey const isMuted = mutedChannels.has(currentChannel.id) const handleAdd = async () => { const pk = addInput.trim() if (!pk) return let hexPk = pk const parsed = Pubkey.tryFromString(pk) if (parsed) hexPk = parsed.hex if (addMode === 'mod') { await addMod(hexPk) } else if (addMode === 'invite') { await sendInvite(hexPk) } else { await approveMember(hexPk) } setAddInput('') } const accessModes: { mode: TAccessMode; label: string; icon: React.ReactNode }[] = [ { mode: 'open', label: 'Open', icon: }, { mode: 'whitelist', label: 'Whitelist', icon: }, { mode: 'blacklist', label: 'Blacklist', icon: } ] return (
{/* Header */}
Settings — #{currentChannel.name}
{/* --- Chat Settings (all users) --- */}

Chat

Send message with
{(['enter', 'ctrl+enter'] as const).map((key) => ( ))}
{submitKey === 'enter' ? 'Shift+Enter for newline' : 'Enter for newline'}
Notifications
{/* --- Access Mode (owner only) --- */} {isOwner && (

Access Mode

{accessModes.map(({ mode, label, icon }) => ( ))}
{channelAccessMode === 'open' && 'Anyone authenticated can read and write.'} {channelAccessMode === 'whitelist' && 'Only listed members, mods, and invitees can access.'} {channelAccessMode === 'blacklist' && 'Everyone except excluded users can access.'}
)} {/* --- Message Expiry (owner only) --- */} {isOwner && (

Message Expiry

{EXPIRY_OPTIONS.map(({ label, value }) => ( ))}
Messages will include a NIP-40 expiration tag set to this duration from send time.
)} {/* --- Add member/mod/invite (owner + mods) --- */} {isOwnerOrMod && (

Add User

{isOwner && ( )}
setAddInput(e.target.value)} className="flex-1 px-2 py-1 text-xs border rounded bg-background" onKeyDown={(e) => e.key === 'Enter' && handleAdd()} />
)} {/* --- Moderators --- */} {channelMods.length > 0 && (

Moderators

{channelMods.map((pk) => (
{pk === currentChannel.creator && ( (owner) )} {isOwner && pk !== currentChannel.creator && ( )}
))}
)} {/* --- Members / Excluded (depends on mode) --- */} {channelAccessMode === 'whitelist' && channelMembers.length > 0 && (

Allowed Members

{channelMembers.map((entry) => (
{entry.addedBy && ( via )} {isOwnerOrMod && ( )}
))}
)} {channelAccessMode === 'blacklist' && channelBlocked.length > 0 && (

Excluded Users

{channelBlocked.map((entry) => (
{entry.addedBy && ( by )} {isOwnerOrMod && ( )}
))}
)} {/* --- Invites (owner + mods) --- */} {isOwnerOrMod && channelInvited.length > 0 && (

Pending Invites

{channelInvited.map((entry) => (
{entry.addedBy && ( by )}
))}
)} {/* --- Requests (owner + mods) --- */} {isOwnerOrMod && channelRequested.length > 0 && (

Join Requests

{channelRequested.map((pk) => (
))}
)} {/* --- Rejected (owner only can revoke) --- */} {channelRejected.length > 0 && (

Rejected

{channelRejected.map((pk) => (
{isOwner && ( )}
))}
)} {/* --- Blocked users (from kind 44 mod actions, always shown) --- */} {channelAccessMode !== 'blacklist' && channelBlocked.length > 0 && (

Blocked

{channelBlocked.map((entry) => (
{isOwnerOrMod && ( )}
))}
)}
) } function PubkeyName({ hex }: { hex: string }) { const { profile } = useFetchProfile(hex) const pk = Pubkey.tryFromString(hex) return <>{profile?.username || pk?.formatNpub(8) || hex.slice(0, 12)} }