diff --git a/packages/app/src/hooks/use-workspace-helper.ts b/packages/app/src/hooks/use-workspace-helper.ts index f1dee901d3..480ba409c1 100644 --- a/packages/app/src/hooks/use-workspace-helper.ts +++ b/packages/app/src/hooks/use-workspace-helper.ts @@ -64,6 +64,14 @@ export const useWorkspaceHelper = () => { currentWorkspace && (await dataCenter.leaveWorkspace(currentWorkspace?.id)); }; + const acceptInvite = async (inviteCode: string) => { + let inviteInfo; + if (inviteCode) { + inviteInfo = await dataCenter.acceptInvitation(inviteCode); + } + return inviteInfo; + }; + return { createWorkspace, publishWorkspace, @@ -71,5 +79,6 @@ export const useWorkspaceHelper = () => { enableWorkspace, deleteWorkSpace, leaveWorkSpace, + acceptInvite, }; }; diff --git a/packages/app/src/pages/invite/[invite_code].tsx b/packages/app/src/pages/invite/[invite_code].tsx index e007a6cd25..342fa7c481 100644 --- a/packages/app/src/pages/invite/[invite_code].tsx +++ b/packages/app/src/pages/invite/[invite_code].tsx @@ -1,44 +1,37 @@ +import { useWorkspaceHelper } from '@/hooks/use-workspace-helper'; +import { useAppState } from '@/providers/app-state-provider'; import { styled } from '@/styles'; import { Empty } from '@/ui/empty'; -import { Avatar } from '@mui/material'; -// import { getDataCenter } from '@affine/datacenter'; +// import { Avatar } from '@mui/material'; import { useRouter } from 'next/router'; import { useEffect, useState } from 'react'; -const User = ({ name, avatar }: { name: string; avatar?: string }) => { - return ( - - {avatar ? ( - - ) : ( - {name.slice(0, 1)} - )} - {name} - - ); -}; +// const User = ({ name, avatar }: { name: string; avatar?: string }) => { +// return ( +// +// {avatar ? ( +// +// ) : ( +// {name.slice(0, 1)} +// )} +// {name} +// +// ); +// }; export default function DevPage() { const router = useRouter(); const [successInvited, setSuccessInvited] = useState(false); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const [inviteData, setInviteData] = useState(null); + const { acceptInvite } = useWorkspaceHelper(); + const { user } = useAppState(); useEffect(() => { - // getDataCenter() - // .then(dc => - // dc.apis.acceptInviting({ - // invitingCode: router.query.invite_code as string, - // }) - // ) - // .then(data => { - // setSuccessInvited(true); - // setInviteData(data); - // }) - // .catch(err => { - // console.log('err: ', err); - // }); - setSuccessInvited(true); - setInviteData(null); + router.query.invite_code && + acceptInvite(router.query.invite_code as string).then(data => { + if (data && data.accepted) { + setSuccessInvited(true); + user && router.push(`/workspace/${data.workspace_id}`); + } + }); }, [router.query.invite_code]); return ( @@ -47,11 +40,12 @@ export default function DevPage() { - invited - you to join - invited */} + {/* you to join */} + {/* + > */} {successInvited ? ( } permission */ async acceptInvitation(inviteCode: string, providerStr = 'affine') { const provider = this.providerMap.get(providerStr); if (provider) { return await provider.acceptInvitation(inviteCode); } - return []; + return null; } onMessage(cb: (message: Message) => void) { diff --git a/packages/data-center/src/provider/affine/affine.ts b/packages/data-center/src/provider/affine/affine.ts index 944d19c7fe..c8078c4cdc 100644 --- a/packages/data-center/src/provider/affine/affine.ts +++ b/packages/data-center/src/provider/affine/affine.ts @@ -102,10 +102,19 @@ export class AffineProvider extends BaseProvider { }); } - private _handlerAffineListMessage({ ws_details, metadata }: ChannelMessage) { + private async _handlerAffineListMessage({ + ws_details, + metadata, + }: ChannelMessage) { this._logger('receive server message'); - Object.entries(ws_details).forEach(async ([id, detail]) => { + const addedWorkspaces: WorkspaceUnit[] = []; + const removeWorkspaceList = this._workspaces.list().map(w => w.id); + for (const [id, detail] of Object.entries(ws_details)) { const { name, avatar } = metadata[id]; + const index = removeWorkspaceList.indexOf(id); + if (index !== -1) { + removeWorkspaceList.splice(index, 1); + } assert(name); const workspace = { name: name, @@ -122,15 +131,20 @@ export class AffineProvider extends BaseProvider { syncMode: 'core' as SyncMode, }; if (this._workspaces.get(id)) { + // update workspaces this._workspaces.update(id, workspace); } else { const workspaceUnit = await loadWorkspaceUnit( { id, ...workspace }, this._apis ); - this._workspaces.add(workspaceUnit); + addedWorkspaces.push(workspaceUnit); } - }); + } + // add workspaces + this._workspaces.add(addedWorkspaces); + // remove workspaces + this._workspaces.remove(removeWorkspaceList); } private _getWebsocketProvider(workspace: BlocksuiteWorkspace) { @@ -386,7 +400,7 @@ export class AffineProvider extends BaseProvider { return this._apis.getWorkspaceMembers({ id }); } - public override async acceptInvitation(invitingCode: string): Promise { - await this._apis.acceptInviting({ invitingCode }); + public override async acceptInvitation(invitingCode: string) { + return await this._apis.acceptInviting({ invitingCode }); } } diff --git a/packages/data-center/src/provider/affine/apis/workspace.ts b/packages/data-center/src/provider/affine/apis/workspace.ts index 83d065bbca..106dc72b04 100644 --- a/packages/data-center/src/provider/affine/apis/workspace.ts +++ b/packages/data-center/src/provider/affine/apis/workspace.ts @@ -197,13 +197,13 @@ export interface AcceptInvitingParams { export async function acceptInviting( params: AcceptInvitingParams -): Promise { - await bareClient - .post(`api/invitation/${params.invitingCode}`) - .catch(error => { - sendMessage(messageCode.acceptInvitingFailed); - throw new RequestError('accept inviting failed', error); - }); +): Promise { + try { + return bareClient.post(`api/invitation/${params.invitingCode}`).json(); + } catch (error) { + sendMessage(messageCode.acceptInvitingFailed); + throw new RequestError('accept inviting failed', error); + } } export async function uploadBlob(params: { blob: Blob }): Promise { diff --git a/packages/data-center/src/provider/base.ts b/packages/data-center/src/provider/base.ts index 0f0a23ead3..eb9a68d748 100644 --- a/packages/data-center/src/provider/base.ts +++ b/packages/data-center/src/provider/base.ts @@ -4,6 +4,7 @@ import { Logger, User } from '../types'; import type { WorkspaceUnitCollectionScope } from '../workspace-unit-collection'; import type { WorkspaceUnitCtorParams, WorkspaceUnit } from '../workspace-unit'; import { Member } from './affine/apis'; +import { Permission } from './affine/apis/workspace.js'; const defaultLogger = () => { return; @@ -233,8 +234,10 @@ export class BaseProvider { * @param {string} inviteCode * @returns */ - public async acceptInvitation(inviteCode: string): Promise { + public async acceptInvitation( + inviteCode: string + ): Promise { inviteCode; - return; + return null; } } diff --git a/packages/data-center/src/workspace-unit-collection.ts b/packages/data-center/src/workspace-unit-collection.ts index 7d55762560..b51f5d160f 100644 --- a/packages/data-center/src/workspace-unit-collection.ts +++ b/packages/data-center/src/workspace-unit-collection.ts @@ -8,7 +8,7 @@ export interface WorkspaceUnitCollectionScope { get: (workspaceId: string) => WorkspaceUnit | undefined; list: () => WorkspaceUnit[]; add: (workspace: WorkspaceUnit | WorkspaceUnit[]) => void; - remove: (workspaceId: string) => boolean; + remove: (workspaceId: string | string[]) => boolean; clear: () => void; update: ( workspaceId: string, @@ -18,7 +18,7 @@ export interface WorkspaceUnitCollectionScope { export interface WorkspaceUnitCollectionChangeEvent { added?: WorkspaceUnit[]; - deleted?: WorkspaceUnit; + deleted?: WorkspaceUnit[]; updated?: WorkspaceUnit; } @@ -62,16 +62,22 @@ export class WorkspaceUnitCollection { const workspaceUnits = Array.isArray(workspaceUnit) ? workspaceUnit : [workspaceUnit]; + let added = false; workspaceUnits.forEach(workspaceUnit => { if (this._workspaceUnitMap.has(workspaceUnit.id)) { // FIXME: multiple add same workspace return; } + added = true; this._workspaceUnitMap.set(workspaceUnit.id, workspaceUnit); scopedWorkspaceIds.add(workspaceUnit.id); }); + if (!added) { + return; + } + this._events.emit('change', [ { added: workspaceUnits, @@ -79,27 +85,39 @@ export class WorkspaceUnitCollection { ]); }; - const remove = (workspaceId: string) => { - if (!scopedWorkspaceIds.has(workspaceId)) { - return true; - } + const remove = (workspaceId: string | string[]) => { + const workspaceIds = Array.isArray(workspaceId) + ? workspaceId + : [workspaceId]; + const workspaceUnits: WorkspaceUnit[] = []; - const workspaceUnit = this._workspaceUnitMap.get(workspaceId); - if (workspaceUnit) { - const ret = this._workspaceUnitMap.delete(workspaceId); - // If deletion failed, return. - if (!ret) { - return ret; + workspaceIds.forEach(workspaceId => { + if (!scopedWorkspaceIds.has(workspaceId)) { + return; } + const workspaceUnit = this._workspaceUnitMap.get(workspaceId); + if (workspaceUnit) { + const ret = this._workspaceUnitMap.delete(workspaceId); + // If deletion failed, return. + if (!ret) { + return; + } - scopedWorkspaceIds.delete(workspaceId); + workspaceUnits.push(workspaceUnit); + scopedWorkspaceIds.delete(workspaceId); + } + }); - this._events.emit('change', [ - { - deleted: workspaceUnit, - } as WorkspaceUnitCollectionChangeEvent, - ]); + if (!workspaceUnits.length) { + return false; } + + this._events.emit('change', [ + { + deleted: workspaceUnits, + } as WorkspaceUnitCollectionChangeEvent, + ]); + return true; };