import type { ParsedChannelLink } from '@/lib/channelLink'; import type { AccountInvitation } from './account'; import type { ParsedShareLink } from '@/lib/shareLink'; import type { WorkspaceApi } from './api'; import type { ShareApi } from './shareApi'; import { callWorker, subscribeWorker } from './workerClient'; import type { ArchiveEntry, ChannelInfo, ChannelSettingsPatch, CreateOptions, Share, ShareEvent, ShareSettings, WorkspaceEvent } from './types'; const API_BASE = import.meta.env.VITE_WEBDROP_API_URL ?? '/api/v1'; function reportChannelUnavailable(id: string, onEvent: (event: WorkspaceEvent) => void): void { onEvent({ t: 'connection', state: 'offline' }); onEvent({ t: 'ready' }); void id; } export const realApi: WorkspaceApi = { createChannel: (options: CreateOptions, captchaToken?: string) => callWorker('createChannel', { options, captchaToken, apiBase: API_BASE }), updateChannelSettings: (patch: ChannelSettingsPatch) => callWorker('updateChannelSettings', { id: currentChannelId(), patch, apiBase: API_BASE }), renameDevice: (endpointHash, name) => callWorker('renameDevice', { id: currentChannelId(), endpointHash, name, apiBase: API_BASE }), releaseDevice: (endpointHash) => callWorker('releaseDevice', { id: currentChannelId(), endpointHash, apiBase: API_BASE }), joinChannel: (link: ParsedChannelLink, password?: string) => callWorker('joinChannel', { link, password, apiBase: API_BASE }), inviteUser: (username) => callWorker('inviteChannelUser', { id: currentChannelId(), username, apiBase: API_BASE }), listInvitations: () => callWorker('listChannelInvitations', { id: currentChannelId(), apiBase: API_BASE }), revokeInvitation: (username) => callWorker('revokeChannelInvitation', { id: currentChannelId(), username, apiBase: API_BASE }), listSaved: () => callWorker('listChannels', { apiBase: API_BASE }), forget: (id) => callWorker('forgetChannel', { id, apiBase: API_BASE }), connect(channelId, onEvent) { activeChannelId = channelId; activeShareId = ''; const unsubscribe = subscribeWorker(channelId, onEvent); void callWorker('connectChannel', { id: channelId, apiBase: API_BASE }).catch(() => reportChannelUnavailable(channelId, onEvent)); return () => { unsubscribe(); void callWorker('stopChannel', { id: channelId, apiBase: API_BASE }); }; }, sendText: (text, threadId) => callWorker('sendText', { id: currentChannelId(), text, threadId, apiBase: API_BASE }), sendFiles: (files, options, threadId, folderId) => callWorker('sendFiles', { id: currentChannelId(), files, options, threadId, folderId, apiBase: API_BASE }), createThread: (name, groupId) => callWorker('createThread', { id: currentChannelId(), name, groupId, apiBase: API_BASE }), createGroup: (name) => callWorker('createGroup', { id: currentChannelId(), name, apiBase: API_BASE }), renameGroup: (groupId, name) => callWorker('renameGroup', { id: currentChannelId(), groupId, name, apiBase: API_BASE }), groupThread: (threadId, groupId) => callWorker('groupThread', { id: currentChannelId(), threadId, groupId, apiBase: API_BASE }), renameThread: (threadId, name) => callWorker('renameThread', { id: currentChannelId(), threadId, name, apiBase: API_BASE }), setChannelHistory: (threadId, chatHistory, filesHistory) => callWorker('setChannelHistory', { id: currentChannelId(), threadId, chatHistory, filesHistory, apiBase: API_BASE }), createFolder: (threadId, name, parentId) => callWorker('createFolder', { id: currentChannelId(), threadId, name, parentId, apiBase: API_BASE }), renameFolder: (folderId, threadId, name) => callWorker('renameFolder', { id: currentChannelId(), folderId, threadId, name, apiBase: API_BASE }), moveItems: (itemIds, threadId, folderId) => callWorker('moveItems', { id: currentChannelId(), itemIds, threadId, folderId, apiBase: API_BASE }), editText: (id, text, threadId) => callWorker('editChannelText', { id: currentChannelId(), itemId: id, text, threadId, apiBase: API_BASE }), resolveConflict: (id, choice) => callWorker('resolveTextConflict', { id: currentChannelId(), itemId: id, choice, apiBase: API_BASE }), remove: (id) => callWorker('removeChannelItem', { id: currentChannelId(), itemId: id, apiBase: API_BASE }), setSnapshot: (text) => callWorker('updateSnapshot', { id: currentChannelId(), text, apiBase: API_BASE }), getBlob: (id, versionId) => callWorker('getChannelBlob', { id: currentChannelId(), itemId: id, versionId, apiBase: API_BASE }), listArchive: (_id: string): Promise => callWorker('listArchive', { id: currentChannelId(), apiBase: API_BASE }), markSeen: (id) => callWorker('markChannelSeen', { id: currentChannelId(), itemId: id, apiBase: API_BASE }), }; export const realShareApi: ShareApi = { createDraft: (settings: ShareSettings, captchaToken?: string) => callWorker('createShare', { settings, captchaToken, apiBase: API_BASE }), listSaved: () => callWorker('listShares', { apiBase: API_BASE }), updateSettings: (id, patch) => callWorker('updateShareSettings', { id, patch, apiBase: API_BASE }), seal: (id) => callWorker('sealShare', { id, apiBase: API_BASE }), join: (link: ParsedShareLink) => callWorker('joinShare', { link, apiBase: API_BASE }), forget: (id) => callWorker('forgetShare', { id, apiBase: API_BASE }), connect(shareId, onEvent) { activeShareId = shareId; activeChannelId = ''; const unsubscribe = subscribeWorker(shareId, onEvent); void callWorker('connectShare', { id: shareId, apiBase: API_BASE }).catch((error: unknown) => { onEvent({ t: 'error', message: error instanceof Error ? error.message : '无法打开分享' }); onEvent({ t: 'ready' }); }); return () => { unsubscribe(); void callWorker('stopShare', { id: shareId, apiBase: API_BASE }); }; }, addText: (text) => callWorker('addShareText', { id: currentShareId(), text, apiBase: API_BASE }), editText: (id, text) => callWorker('editShareText', { id: currentShareId(), itemId: id, text, apiBase: API_BASE }), addFiles: (files) => callWorker('addShareFiles', { id: currentShareId(), files, apiBase: API_BASE }), removeItem: (id) => callWorker('removeShareItem', { id: currentShareId(), itemId: id, apiBase: API_BASE }), getBlob: (id) => callWorker('getShareBlob', { id: currentShareId(), itemId: id, apiBase: API_BASE }), listArchive: (_id: string): Promise => callWorker('listArchive', { id: currentShareId(), apiBase: API_BASE }), }; let activeChannelId = ''; let activeShareId = ''; function currentChannelId(): string { return activeChannelId; } function currentShareId(): string { return activeShareId; }