import type { ChannelSession } from '@webdrop/core'; import type { SavedResource } from '../database'; import type { FileItem } from '../types'; import { persistPlan } from './transfer'; import { changeWorkspace, createWorkspaceChannel, createWorkspaceGroup } from './workspaceStructure'; import { getSession } from './sessions'; import { initializeChannelKeys, prepareObject } from './channelDataKeys'; import { toPublishedFile } from './fileCatalog'; import { apiFetch } from './http'; import { WORKSPACE_APP, type ResourceControl } from '../protocol/workspace'; import type { WorkspaceChannelRequest, WorkspaceGroupRequest, WorkspaceNameRequest, WorkspaceFolderRequest, WorkspaceMoveRequest } from '../generated/api'; const encoder = new TextEncoder(); export async function createThread(resourceId: string, name: string, groupId?: string): Promise { const id = await createWorkspaceChannel(resourceId, { name, groupId } satisfies WorkspaceChannelRequest); const { resource, session } = await getSession(resourceId); await initializeChannelKeys(resource, session, id); return id; } export async function createGroup(resourceId: string, name: string): Promise { return createWorkspaceGroup(resourceId, { name } satisfies WorkspaceNameRequest); } export async function renameGroup(resourceId: string, id: string, name: string): Promise { await changeWorkspace(resourceId, 'groups/' + id, 'PATCH', { name } satisfies WorkspaceNameRequest); } export async function groupThread(resourceId: string, id: string, groupId?: string): Promise { await changeWorkspace(resourceId, 'channels/' + id + '/group', 'PUT', { groupId: groupId ?? null } satisfies WorkspaceGroupRequest); } export async function renameThread(resourceId: string, id: string, name: string): Promise { await changeWorkspace(resourceId, 'channels/' + id, 'PATCH', { name } satisfies WorkspaceNameRequest); } export async function setChannelHistory(resourceId: string, id: string, chatHistory: boolean, filesHistory: boolean): Promise { const { session } = await getSession(resourceId); await apiFetch(`/spaces/${resourceId}/channels/${id}/history`, { method: 'PATCH', headers: { ...session.authHeaders('owner'), 'Content-Type': 'application/json' }, body: JSON.stringify({ chatHistory, filesHistory }) }); await import('./workspaceStructure').then(module => module.loadWorkspace(resourceId)); } export async function createFolder(resourceId: string, threadId: string, name: string, parentId?: string): Promise { await changeWorkspace(resourceId, 'folders', 'POST', { threadId, name, parentId } satisfies WorkspaceFolderRequest); } export async function renameFolder(resourceId: string, id: string, name: string, _threadId: string): Promise { await changeWorkspace(resourceId, 'folders/' + id, 'PATCH', { name } satisfies WorkspaceNameRequest); } export async function moveItems(resourceId: string, itemIds: string[], threadId: string, folderId?: string): Promise { await changeWorkspace(resourceId, 'locations', 'PUT', { itemIds, threadId, folderId } satisfies WorkspaceMoveRequest); } export async function queueFileCatalog(resource: SavedResource, session: ChannelSession, item: FileItem): Promise { if (!item.threadId) throw new Error('请先选择频道'); const prepared = await prepareObject(resource, session, item.threadId, 'files'); const control: ResourceControl = { op: 'file.published', item: toPublishedFile(item) }; const plan = session.encryptBytes(encoder.encode(JSON.stringify({ app: WORKSPACE_APP, v: 1, ...control })), { kind: 'other', threadId: item.threadId, dev: item.deviceId }, { ts: item.ts, control: true, itemId: prepared.itemIdBytes }); await persistPlan(resource, plan, undefined, { channelId: prepared.channelId, domain: prepared.domain, epoch: prepared.epoch, eventKind: 'file.catalog' }); }