Private
Public Access
Add resizable room panel, searchable user picker, and direct room membership
Room info panel is now user-resizable (fixing a layout clip at narrow widths), and every user-selection spot (room membership, admin ownership transfer) uses a new searchable UserPicker instead of raw text input or prompt(). Member rows fold role + actions into a single inline dropdown instead of a row of buttons, so the member list stays usable as rooms grow. Room invites (the accept/decline flow) are replaced by adding a user to a room directly -- an admin/owner picks someone and they're a member immediately, with a "you've been added" notification email instead of an invite email. Drops the now-unused room_invites table.
This commit is contained in:
@@ -1,11 +1,9 @@
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { useNavigate, useParams } from 'react-router-dom'
|
||||
import { NetworkError } from '../api/client'
|
||||
import { listMyInvites } from '../api/invites'
|
||||
import { listMyRooms, listRoomMembers } from '../api/rooms'
|
||||
import { BrowseRoomsModal } from '../components/BrowseRoomsModal'
|
||||
import { ChatPane } from '../components/ChatPane'
|
||||
import { InvitesModal } from '../components/InvitesModal'
|
||||
import { NewRoomModal } from '../components/NewRoomModal'
|
||||
import { OfflineBanner } from '../components/OfflineBanner'
|
||||
import { RoomInfoPanel } from '../components/RoomInfoPanel'
|
||||
@@ -16,7 +14,7 @@ import { MOBILE_BREAKPOINT, useWindowWidth } from '../hooks/useWindowWidth'
|
||||
import type { MyRoomItem, RoomMember } from '../types'
|
||||
import './ChatShellPage.css'
|
||||
|
||||
type ModalKind = 'new' | 'browse' | 'invites' | null
|
||||
type ModalKind = 'new' | 'browse' | null
|
||||
|
||||
export function ChatShellPage() {
|
||||
const { roomId } = useParams<{ roomId?: string }>()
|
||||
@@ -28,7 +26,6 @@ export function ChatShellPage() {
|
||||
const [rooms, setRooms] = useState<MyRoomItem[]>([])
|
||||
const [search, setSearch] = useState('')
|
||||
const [members, setMembers] = useState<RoomMember[]>([])
|
||||
const [inviteCount, setInviteCount] = useState(0)
|
||||
const [infoOpen, setInfoOpen] = useState(false)
|
||||
const [modal, setModal] = useState<ModalKind>(null)
|
||||
const [roomsUnavailableOffline, setRoomsUnavailableOffline] = useState(false)
|
||||
@@ -59,12 +56,6 @@ export function ChatShellPage() {
|
||||
refreshRooms().catch(() => {})
|
||||
}, [refreshRooms])
|
||||
|
||||
useEffect(() => {
|
||||
listMyInvites()
|
||||
.then((list) => setInviteCount(list.length))
|
||||
.catch(() => {})
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
refreshMembers()
|
||||
// Also re-run when the logged-in user's own profile changes (display
|
||||
@@ -92,8 +83,6 @@ export function ChatShellPage() {
|
||||
onSearchChange={setSearch}
|
||||
onOpenNewRoom={() => setModal('new')}
|
||||
onOpenBrowse={() => setModal('browse')}
|
||||
onOpenInvites={() => setModal('invites')}
|
||||
inviteCount={inviteCount}
|
||||
unavailableOffline={roomsUnavailableOffline && rooms.length === 0}
|
||||
/>
|
||||
)}
|
||||
@@ -156,16 +145,6 @@ export function ChatShellPage() {
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{modal === 'invites' && (
|
||||
<InvitesModal
|
||||
onClose={() => setModal(null)}
|
||||
onInvitesChanged={setInviteCount}
|
||||
onAccepted={(id) => {
|
||||
setModal(null)
|
||||
refreshRooms().then(() => goToRoom(id))
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user