feat(web): add spaces, grouped channels and file chat
This commit is contained in:
1 parent
c7d8ef15bc
commit
f6cfb12716
111 files changed
+4371
-506
No files matched your search
+70
-3
@@ -1,9 +1,13 @@
|
||||
import type {
|
||||
ChannelInfo,
|
||||
ChannelGroupInfo,
|
||||
ConnectionState,
|
||||
Device,
|
||||
FolderInfo,
|
||||
Item,
|
||||
SenderInfo,
|
||||
Snapshot,
|
||||
ThreadInfo,
|
||||
WorkspaceEvent,
|
||||
} from '@/core-bridge/types';
|
||||
|
||||
@@ -12,7 +16,13 @@ export interface WorkspaceData {
|
||||
connection: ConnectionState;
|
||||
channel: ChannelInfo | null;
|
||||
devices: Device[];
|
||||
threads: ThreadInfo[];
|
||||
groups: ChannelGroupInfo[];
|
||||
threadGroups: Record<string, string | null>;
|
||||
folders: FolderInfo[];
|
||||
locations: Record<string, { threadId: string; folderId?: string }>;
|
||||
byId: Record<string, Item>;
|
||||
authors: Record<string, SenderInfo>;
|
||||
/** 新的在前 */
|
||||
order: string[];
|
||||
snapshot: Snapshot;
|
||||
@@ -24,7 +34,13 @@ export const initialData: WorkspaceData = {
|
||||
connection: 'offline',
|
||||
channel: null,
|
||||
devices: [],
|
||||
threads: [],
|
||||
groups: [],
|
||||
threadGroups: {},
|
||||
folders: [],
|
||||
locations: {},
|
||||
byId: {},
|
||||
authors: {},
|
||||
order: [],
|
||||
snapshot: { text: '', updatedBy: '', updatedAt: 0 },
|
||||
error: null,
|
||||
@@ -51,18 +67,69 @@ export function reduce(s: WorkspaceData, e: WorkspaceEvent): WorkspaceData {
|
||||
return { ...s, channel: e.info };
|
||||
case 'devices':
|
||||
return { ...s, devices: e.devices };
|
||||
case 'thread-created': {
|
||||
const thread = { ...e.thread };
|
||||
if (thread.id in s.threadGroups) {
|
||||
const groupId = s.threadGroups[thread.id];
|
||||
if (groupId) thread.groupId = groupId;
|
||||
else delete thread.groupId;
|
||||
}
|
||||
return { ...s, threads: [thread, ...s.threads.filter((entry) => entry.id !== thread.id)] };
|
||||
}
|
||||
case 'thread-renamed':
|
||||
return { ...s, threads: s.threads.map((thread) => thread.id === e.id ? { ...thread, name: e.name } : thread) };
|
||||
case 'group-created':
|
||||
return { ...s, groups: [...s.groups.filter((group) => group.id !== e.group.id), e.group] };
|
||||
case 'group-renamed':
|
||||
return { ...s, groups: s.groups.map((group) => group.id === e.id ? { ...group, name: e.name } : group) };
|
||||
case 'thread-grouped':
|
||||
return { ...s, threadGroups: { ...s.threadGroups, [e.id]: e.groupId ?? null },
|
||||
threads: s.threads.map((thread) => thread.id === e.id ? { ...thread, groupId: e.groupId } : thread) };
|
||||
case 'folder-created':
|
||||
return { ...s, folders: [e.folder, ...s.folders.filter((folder) => folder.id !== e.folder.id)] };
|
||||
case 'folder-renamed':
|
||||
return { ...s, folders: s.folders.map((folder) => folder.id === e.id ? { ...folder, name: e.name } : folder) };
|
||||
case 'items-moved': {
|
||||
const byId = { ...s.byId };
|
||||
const locations = { ...s.locations };
|
||||
for (const id of e.itemIds) {
|
||||
locations[id] = { threadId: e.threadId, ...(e.folderId ? { folderId: e.folderId } : {}) };
|
||||
const item = byId[id];
|
||||
if (!item) continue;
|
||||
if (item.kind === 'file' && item.metadataHidden) continue;
|
||||
const moved = { ...item, threadId: e.threadId };
|
||||
if (e.folderId === undefined) delete moved.folderId;
|
||||
else moved.folderId = e.folderId;
|
||||
byId[id] = moved;
|
||||
}
|
||||
return { ...s, byId, locations };
|
||||
}
|
||||
case 'snapshot':
|
||||
return { ...s, snapshot: e.snapshot };
|
||||
case 'item-author': {
|
||||
const item = s.byId[e.id];
|
||||
return { ...s, authors: { ...s.authors, [e.id]: e.author },
|
||||
byId: item ? { ...s.byId, [e.id]: { ...item, author: e.author } } : s.byId };
|
||||
}
|
||||
case 'file-catalog':
|
||||
case 'item': {
|
||||
const known = e.item.id in s.byId;
|
||||
const byId = { ...s.byId, [e.item.id]: e.item };
|
||||
return { ...s, byId, order: known ? s.order : insertByTime(s.order, byId, e.item) };
|
||||
let item = e.item;
|
||||
const current = s.byId[item.id];
|
||||
const author = item.author ?? s.authors[item.id] ?? current?.author;
|
||||
if (author) item = { ...item, author };
|
||||
if (e.t === 'item' && item.kind === 'file' && item.metadataHidden && current?.kind === 'file' && !current.metadataHidden) return s;
|
||||
const location = s.locations[item.id];
|
||||
if (location && !(item.kind === 'file' && item.metadataHidden)) item = { ...item, threadId: location.threadId, folderId: location.folderId };
|
||||
const byId = { ...s.byId, [item.id]: item };
|
||||
return { ...s, byId, ...(author ? { authors: { ...s.authors, [item.id]: author } } : {}), order: known ? s.order : insertByTime(s.order, byId, item) };
|
||||
}
|
||||
case 'removed': {
|
||||
if (!(e.id in s.byId)) return s;
|
||||
const byId = { ...s.byId };
|
||||
delete byId[e.id];
|
||||
return { ...s, byId, order: s.order.filter((id) => id !== e.id) };
|
||||
const authors = { ...s.authors }; delete authors[e.id];
|
||||
return { ...s, byId, authors, order: s.order.filter((id) => id !== e.id) };
|
||||
}
|
||||
default: {
|
||||
const exhaustive: never = e;
|
||||
|
||||
Reference in new issue
Block a user