feat(web): role groups, last seen and unread markers in members, channels and spaces; lock channels without keys
This commit is contained in:
1 parent
5043c798ff
commit
d1ff8bab7d
23 files changed
+381
-34
No files matched your search
@@ -19,6 +19,7 @@ import { useAccount } from '@/store/account';
|
||||
import { permissionsOf } from '@/lib/roles';
|
||||
import { ThreadSidebar } from './ThreadSidebar';
|
||||
import { ChatPane } from './ChatPane';
|
||||
import { useThreadReads } from './useThreadReads';
|
||||
import { FileExplorer } from './FileExplorer';
|
||||
import { FilePaneResize } from './FilePaneResize';
|
||||
import { InviteSheet } from './InviteSheet';
|
||||
@@ -78,7 +79,10 @@ export function Workspace({ onCreateChannel }: { onCreateChannel: () => void })
|
||||
const [memberRevision, setMemberRevision] = useState(0);
|
||||
const [fileWidth, setFileWidth] = useState<number>();
|
||||
const [upload, setUpload] = useState<{ files: File[]; threadId: string; folderId?: string }>();
|
||||
const activeThread = threads.find((thread) => thread.id === threadId) ?? threads.find((thread) => thread.name === '常规') ?? threads[threads.length - 1];
|
||||
const locked = useWorkspace((s) => s.lockedThreads);
|
||||
// 没有密钥的频道不能打开:优先用选中的,其次「常规」,再其次最新的可用频道
|
||||
const usable = threads.filter((thread) => !locked.includes(thread.id));
|
||||
const activeThread = usable.find((thread) => thread.id === threadId) ?? usable.find((thread) => thread.name === '常规') ?? usable[usable.length - 1];
|
||||
const activeThreadId = activeThread?.id;
|
||||
const activeFolders = folders.filter((folder) => folder.threadId === activeThreadId);
|
||||
const activeFolderId = activeFolders.some((folder) => folder.id === folderId) ? folderId : undefined;
|
||||
@@ -98,6 +102,8 @@ export function Workspace({ onCreateChannel }: { onCreateChannel: () => void })
|
||||
const item = s.byId[id]; return item?.kind === 'file' && item.metadataHidden;
|
||||
})));
|
||||
|
||||
const { unread, marker } = useThreadReads(channel?.id, threads.map((thread) => thread.id), activeThreadId);
|
||||
|
||||
const requestFiles = useCallback((incoming: File[], destination?: { folderId?: string }) => {
|
||||
const target = destination ? destination.folderId : activeFolderId;
|
||||
if (incoming.length && activeThreadId && enabled) setUpload({ files: incoming, threadId: activeThreadId, ...(target ? { folderId: target } : {}) });
|
||||
@@ -131,11 +137,11 @@ export function Workspace({ onCreateChannel }: { onCreateChannel: () => void })
|
||||
const channelId = channel?.id;
|
||||
useEffect(() => { setDrawerOpen(false); }, [channelId]);
|
||||
const rail = <SpaceRail id={channel?.id} onCreate={onCreateChannel} onJoin={() => setScanOpen(true)} />;
|
||||
const threadSidebar = <ThreadSidebar threads={threads} groups={groups} selectedThreadId={activeThreadId} enabled={Boolean(channel?.canManageStructure) || perms.has('structure.manage')} canCreate={owner} owner={owner} onHistory={setChannelHistory}
|
||||
const threadSidebar = <ThreadSidebar threads={threads} groups={groups} selectedThreadId={activeThreadId} unread={unread} locked={locked} enabled={Boolean(channel?.canManageStructure) || perms.has('structure.manage')} canCreate={owner} owner={owner} onHistory={setChannelHistory}
|
||||
onSelectThread={(id) => { selectThread(id); setDrawerOpen(false); setMobileView('chat'); }} onCreateThread={createThread} onRenameThread={renameThread}
|
||||
onCreateGroup={createGroup} onRenameGroup={renameGroup} onDeleteGroup={deleteGroup} onGroupThread={groupThread} />;
|
||||
const navigation = <><SpaceHeader />{threadSidebar}{desktop ? <Notepad /> : null}</>;
|
||||
const chat = <ChatPane threadName={activeThread?.name ?? '选择频道'} ids={messages} enabled={enabled} onSend={(text) => sendText(text, activeThreadId)} onDelete={deleteItem} onOpenFile={setPreviewId} onFiles={requestFiles} />;
|
||||
const chat = <ChatPane threadName={activeThread?.name ?? '选择频道'} lastSeen={marker} ids={messages} enabled={enabled} onSend={(text) => sendText(text, activeThreadId)} onDelete={deleteItem} onOpenFile={setPreviewId} onFiles={requestFiles} />;
|
||||
const explorer = <>
|
||||
<FilterBar filter={filter} searchOpen={searchOpen} onChange={setFilter} />
|
||||
<FileExplorer key={activeThreadId} scope={`${channel?.id}:${activeThreadId}`} threadId={activeThreadId} threadName={activeThread?.name ?? '选择频道'}
|
||||
|
||||
Reference in new issue
Block a user