From a5d2fafad63c9ede4e38f812476b78b983e7009c Mon Sep 17 00:00:00 2001 From: Alex Yang Date: Mon, 3 Jul 2023 22:29:37 +0800 Subject: [PATCH] refactor: remove legacy cloud (#2987) --- .../src/stories/share-menu.stories.tsx | 13 +- apps/web/src/adapters/affine/fetcher.ts | 92 --- apps/web/src/adapters/affine/index.tsx | 380 ---------- apps/web/src/adapters/local/index.tsx | 18 - apps/web/src/adapters/shared.ts | 11 +- apps/web/src/adapters/workspace.ts | 4 - apps/web/src/atoms/public-workspace/index.ts | 68 -- apps/web/src/atoms/root.ts | 17 +- .../affine/affine-error-eoundary.tsx | 9 - .../enable-affine-cloud-modal/index.tsx | 4 +- .../delete-leave-workspace/index.tsx | 4 +- .../new-workspace-setting-detail/index.tsx | 6 - .../members/index.tsx | 160 ---- .../members/invite-member-modal/index.tsx | 222 ------ .../members/style.css.ts | 54 -- .../new-workspace-setting-detail/profile.tsx | 50 +- .../new-workspace-setting-detail/publish.tsx | 18 +- .../components/affine/setting-modal/index.tsx | 4 +- .../setting-modal/setting-sidebar/index.tsx | 6 +- .../components/affine/setting-modal/type.ts | 4 +- .../index.tsx | 4 +- .../workspace-setting-detail/index.css.ts | 208 ------ .../affine/workspace-setting-detail/index.tsx | 169 ----- .../panel/collaboration/index.tsx | 229 ------ .../invite-member-modal/index.tsx | 218 ------ .../panel/collaboration/style.ts | 101 --- .../panel/export/index.tsx | 35 - .../panel/general/delete/index.tsx | 112 --- .../panel/general/delete/style.ts | 76 -- .../panel/general/icons.tsx | 18 - .../panel/general/index.tsx | 283 -------- .../panel/general/leave/index.tsx | 50 -- .../panel/general/leave/style.ts | 45 -- .../panel/general/style.ts | 51 -- .../panel/publish/index.tsx | 171 ----- .../panel/sync/index.tsx | 51 -- .../header-right-items/share-menu.tsx | 25 +- .../header-right-items/sync-user.tsx | 163 ----- .../header-right-items/user-avatar.tsx | 4 +- .../blocksuite/workspace-header/header.tsx | 8 - apps/web/src/components/pure/footer/index.tsx | 82 +-- .../components/pure/message-center/index.tsx | 59 -- .../pure/workspace-list-modal/index.tsx | 13 +- .../src/components/root-app-sidebar/index.tsx | 21 - .../web/src/hooks/affine/use-affine-log-in.ts | 16 - .../src/hooks/affine/use-affine-log-out.ts | 15 - .../affine/use-affine-refresh-auth-token.ts | 50 -- .../hooks/affine/use-is-workspace-owner.ts | 10 - apps/web/src/hooks/affine/use-members.ts | 42 -- .../affine/use-toggle-workspace-publish.ts | 26 - .../src/hooks/affine/use-users-by-email.ts | 24 - .../web/src/hooks/current/use-current-user.ts | 7 - .../hooks/root/use-on-transform-workspace.ts | 23 +- apps/web/src/layouts/workspace-layout.tsx | 33 +- apps/web/src/pages/_app.tsx | 2 - apps/web/src/pages/_debug/login.dev.tsx | 105 --- apps/web/src/pages/invite/[invite-code].tsx | 112 --- .../pages/public-workspace/[workspaceId].tsx | 134 ---- .../[workspaceId]/[pageId].tsx | 158 ---- .../pages/workspace/[workspaceId]/setting.tsx | 136 ---- .../providers/affine-swr-config-provider.tsx | 17 - apps/web/src/providers/modal-provider.tsx | 7 - apps/web/src/shared/index.ts | 4 +- .../components/card/workspace-card/index.tsx | 29 +- .../src/components/share-menu/share-menu.tsx | 6 +- .../src/components/share-menu/share-page.tsx | 2 +- .../components/share-menu/share-workspace.tsx | 11 +- .../src/components/workspace-avatar/index.tsx | 4 +- .../src/components/workspace-list/index.tsx | 12 +- packages/env/src/workspace.ts | 41 +- packages/workspace/package.json | 8 +- packages/workspace/src/affine/api/index.ts | 313 -------- packages/workspace/src/affine/api/status.ts | 10 - packages/workspace/src/affine/atom.ts | 11 - packages/workspace/src/affine/channel.ts | 99 --- packages/workspace/src/affine/keck/README.md | 5 - packages/workspace/src/affine/keck/handler.ts | 59 -- packages/workspace/src/affine/keck/index.ts | 290 -------- .../workspace/src/affine/keck/processor.ts | 25 - packages/workspace/src/affine/login.ts | 238 ------ packages/workspace/src/affine/shared.ts | 76 -- packages/workspace/src/affine/sync.ts | 85 --- packages/workspace/src/blob/index.ts | 118 --- .../src/providers/affine-download.ts | 57 -- packages/workspace/src/providers/index.ts | 63 +- packages/workspace/src/utils.ts | 26 +- yarn.lock | 682 +----------------- 87 files changed, 148 insertions(+), 6383 deletions(-) delete mode 100644 apps/web/src/adapters/affine/fetcher.ts delete mode 100644 apps/web/src/adapters/affine/index.tsx delete mode 100644 apps/web/src/atoms/public-workspace/index.ts delete mode 100644 apps/web/src/components/affine/new-workspace-setting-detail/members/index.tsx delete mode 100644 apps/web/src/components/affine/new-workspace-setting-detail/members/invite-member-modal/index.tsx delete mode 100644 apps/web/src/components/affine/new-workspace-setting-detail/members/style.css.ts delete mode 100644 apps/web/src/components/affine/workspace-setting-detail/index.css.ts delete mode 100644 apps/web/src/components/affine/workspace-setting-detail/index.tsx delete mode 100644 apps/web/src/components/affine/workspace-setting-detail/panel/collaboration/index.tsx delete mode 100644 apps/web/src/components/affine/workspace-setting-detail/panel/collaboration/invite-member-modal/index.tsx delete mode 100644 apps/web/src/components/affine/workspace-setting-detail/panel/collaboration/style.ts delete mode 100644 apps/web/src/components/affine/workspace-setting-detail/panel/export/index.tsx delete mode 100644 apps/web/src/components/affine/workspace-setting-detail/panel/general/delete/index.tsx delete mode 100644 apps/web/src/components/affine/workspace-setting-detail/panel/general/delete/style.ts delete mode 100644 apps/web/src/components/affine/workspace-setting-detail/panel/general/index.tsx delete mode 100644 apps/web/src/components/affine/workspace-setting-detail/panel/general/leave/index.tsx delete mode 100644 apps/web/src/components/affine/workspace-setting-detail/panel/general/leave/style.ts delete mode 100644 apps/web/src/components/affine/workspace-setting-detail/panel/general/style.ts delete mode 100644 apps/web/src/components/affine/workspace-setting-detail/panel/publish/index.tsx delete mode 100644 apps/web/src/components/affine/workspace-setting-detail/panel/sync/index.tsx delete mode 100644 apps/web/src/components/blocksuite/workspace-header/header-right-items/sync-user.tsx delete mode 100644 apps/web/src/components/pure/message-center/index.tsx delete mode 100644 apps/web/src/hooks/affine/use-affine-log-in.ts delete mode 100644 apps/web/src/hooks/affine/use-affine-log-out.ts delete mode 100644 apps/web/src/hooks/affine/use-affine-refresh-auth-token.ts delete mode 100644 apps/web/src/hooks/affine/use-is-workspace-owner.ts delete mode 100644 apps/web/src/hooks/affine/use-members.ts delete mode 100644 apps/web/src/hooks/affine/use-toggle-workspace-publish.ts delete mode 100644 apps/web/src/hooks/affine/use-users-by-email.ts delete mode 100644 apps/web/src/hooks/current/use-current-user.ts delete mode 100644 apps/web/src/pages/_debug/login.dev.tsx delete mode 100644 apps/web/src/pages/invite/[invite-code].tsx delete mode 100644 apps/web/src/pages/public-workspace/[workspaceId].tsx delete mode 100644 apps/web/src/pages/public-workspace/[workspaceId]/[pageId].tsx delete mode 100644 apps/web/src/pages/workspace/[workspaceId]/setting.tsx delete mode 100644 apps/web/src/providers/affine-swr-config-provider.tsx delete mode 100644 packages/workspace/src/affine/api/index.ts delete mode 100644 packages/workspace/src/affine/api/status.ts delete mode 100644 packages/workspace/src/affine/atom.ts delete mode 100644 packages/workspace/src/affine/channel.ts delete mode 100644 packages/workspace/src/affine/keck/README.md delete mode 100644 packages/workspace/src/affine/keck/handler.ts delete mode 100644 packages/workspace/src/affine/keck/index.ts delete mode 100644 packages/workspace/src/affine/keck/processor.ts delete mode 100644 packages/workspace/src/affine/login.ts delete mode 100644 packages/workspace/src/affine/shared.ts delete mode 100644 packages/workspace/src/affine/sync.ts delete mode 100644 packages/workspace/src/blob/index.ts delete mode 100644 packages/workspace/src/providers/affine-download.ts diff --git a/apps/storybook/src/stories/share-menu.stories.tsx b/apps/storybook/src/stories/share-menu.stories.tsx index 6e222a8884..340e015941 100644 --- a/apps/storybook/src/stories/share-menu.stories.tsx +++ b/apps/storybook/src/stories/share-menu.stories.tsx @@ -5,14 +5,10 @@ import { } from '@affine/component/share-menu'; import { ShareMenu } from '@affine/component/share-menu'; import type { - AffineLegacyCloudWorkspace, + AffineCloudWorkspace, LocalWorkspace, } from '@affine/env/workspace'; import { WorkspaceFlavour } from '@affine/env/workspace'; -import { - PermissionType, - WorkspaceType, -} from '@affine/env/workspace/legacy-cloud'; import { createEmptyBlockSuiteWorkspace } from '@affine/workspace/utils'; import type { Page } from '@blocksuite/store'; import { expect } from '@storybook/jest'; @@ -59,13 +55,10 @@ const localWorkspace: LocalWorkspace = { blockSuiteWorkspace, }; -const affineWorkspace: AffineLegacyCloudWorkspace = { +const affineWorkspace: AffineCloudWorkspace = { id: 'test-workspace', - flavour: WorkspaceFlavour.AFFINE, + flavour: WorkspaceFlavour.AFFINE_CLOUD, blockSuiteWorkspace, - public: false, - type: WorkspaceType.Normal, - permission: PermissionType.Owner, }; async function unimplemented() { diff --git a/apps/web/src/adapters/affine/fetcher.ts b/apps/web/src/adapters/affine/fetcher.ts deleted file mode 100644 index 0d6fd3baf5..0000000000 --- a/apps/web/src/adapters/affine/fetcher.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { Unreachable } from '@affine/env/constant'; -import type { AffineLegacyCloudWorkspace } from '@affine/env/workspace'; -import { WorkspaceFlavour } from '@affine/env/workspace'; -import { affineApis } from '@affine/workspace/affine/shared'; -import { createEmptyBlockSuiteWorkspace } from '@affine/workspace/utils'; -import { assertExists } from '@blocksuite/store'; -import { rootStore } from '@toeverything/plugin-infra/manager'; - -import { workspacesAtom } from '../../atoms'; - -type Query = (typeof QueryKey)[keyof typeof QueryKey]; - -export const fetcher = async ( - query: - | Query - | [Query, string, boolean] - | [Query, string] - | [Query, string, string] -) => { - if (Array.isArray(query)) { - if (query[0] === QueryKey.downloadWorkspace) { - if (typeof query[2] !== 'boolean') { - throw new Unreachable(); - } - return affineApis.downloadWorkspace(query[1], query[2]); - } else if (query[0] === QueryKey.getMembers) { - return affineApis.getWorkspaceMembers({ - id: query[1], - }); - } else if (query[0] === QueryKey.getUserByEmail) { - if (typeof query[2] !== 'string') { - throw new Unreachable(); - } - return affineApis.getUserByEmail({ - workspace_id: query[1], - email: query[2], - }); - } else if (query[0] === QueryKey.getImage) { - const workspaceId = query[1]; - const key = query[2]; - if (typeof key !== 'string') { - throw new TypeError('key must be a string'); - } - const workspaces = await rootStore.get(workspacesAtom); - const workspace = workspaces.find(({ id }) => id === workspaceId); - assertExists(workspace); - const storage = await workspace.blockSuiteWorkspace.blobs; - if (!storage) { - return null; - } - return storage.get(key); - } else if (query[0] === QueryKey.acceptInvite) { - const invitingCode = query[1]; - if (typeof invitingCode !== 'string') { - throw new TypeError('invitingCode must be a string'); - } - return affineApis.acceptInviting({ - invitingCode, - }); - } - } else { - if (query === QueryKey.getWorkspaces) { - return affineApis.getWorkspaces().then(workspaces => { - return workspaces.map(workspace => { - const blockSuiteWorkspace = createEmptyBlockSuiteWorkspace( - workspace.id, - WorkspaceFlavour.AFFINE, - { - workspaceApis: affineApis, - } - ); - const remWorkspace: AffineLegacyCloudWorkspace = { - ...workspace, - flavour: WorkspaceFlavour.AFFINE, - blockSuiteWorkspace, - }; - return remWorkspace; - }); - }); - } - return (affineApis as any)[query](); - } -}; - -export const QueryKey = { - acceptInvite: 'acceptInvite', - getImage: 'getImage', - getWorkspaces: 'getWorkspaces', - downloadWorkspace: 'downloadWorkspace', - getMembers: 'getMembers', - getUserByEmail: 'getUserByEmail', -} as const; diff --git a/apps/web/src/adapters/affine/index.tsx b/apps/web/src/adapters/affine/index.tsx deleted file mode 100644 index 48eb460295..0000000000 --- a/apps/web/src/adapters/affine/index.tsx +++ /dev/null @@ -1,380 +0,0 @@ -/** - * This file has deprecated because we do not maintain legacy affine cloud, - * please use new affine cloud instead. - */ -import { initEmptyPage } from '@affine/env/blocksuite'; -import { AFFINE_STORAGE_KEY, PageNotFoundError } from '@affine/env/constant'; -import type { - AffineDownloadProvider, - AffineLegacyCloudWorkspace, - LocalIndexedDBDownloadProvider, -} from '@affine/env/workspace'; -import type { WorkspaceAdapter } from '@affine/env/workspace'; -import { - LoadPriority, - ReleaseType, - WorkspaceFlavour, -} from '@affine/env/workspace'; -import { currentAffineUserAtom } from '@affine/workspace/affine/atom'; -import { - clearLoginStorage, - getLoginStorage, - isExpired, - parseIdToken, - setLoginStorage, - SignMethod, -} from '@affine/workspace/affine/login'; -import { affineApis, affineAuth } from '@affine/workspace/affine/shared'; -import { rootWorkspacesMetadataAtom } from '@affine/workspace/atom'; -import { createIndexedDBDownloadProvider } from '@affine/workspace/providers'; -import { createAffineDownloadProvider } from '@affine/workspace/providers'; -import { - cleanupWorkspace, - createEmptyBlockSuiteWorkspace, -} from '@affine/workspace/utils'; -import { rootStore } from '@toeverything/plugin-infra/manager'; -import { createJSONStorage } from 'jotai/utils'; -import type { PropsWithChildren, ReactElement } from 'react'; -import { Suspense, useEffect } from 'react'; -import { mutate } from 'swr'; -import { z } from 'zod'; - -import { PageLoading } from '../../components/pure/loading'; -import { useAffineRefreshAuthToken } from '../../hooks/affine/use-affine-refresh-auth-token'; -import { BlockSuiteWorkspace } from '../../shared'; -import { toast } from '../../utils'; -import { - BlockSuitePageList, - NewWorkspaceSettingDetail, - PageDetailEditor, - WorkspaceHeader, - WorkspaceSettingDetail, -} from '../shared'; -import { QueryKey } from './fetcher'; - -const storage = createJSONStorage(() => localStorage); -const schema = z.object({ - id: z.string(), - type: z.number(), - public: z.boolean(), - permission: z.number(), -}); - -const getPersistenceAllWorkspace = () => { - const items = storage.getItem(AFFINE_STORAGE_KEY, []); - const allWorkspaces: AffineLegacyCloudWorkspace[] = []; - if ( - Array.isArray(items) && - items.every(item => schema.safeParse(item).success) - ) { - allWorkspaces.push( - ...items.map((item: z.infer) => { - const blockSuiteWorkspace = createEmptyBlockSuiteWorkspace( - item.id, - WorkspaceFlavour.AFFINE, - { - workspaceApis: affineApis, - } - ); - const affineWorkspace: AffineLegacyCloudWorkspace = { - ...item, - flavour: WorkspaceFlavour.AFFINE, - blockSuiteWorkspace, - }; - return affineWorkspace; - }) - ); - } - return allWorkspaces; -}; - -function AuthContext({ children }: PropsWithChildren): ReactElement { - const login = useAffineRefreshAuthToken(); - - useEffect(() => { - if (!login) { - console.warn('No login, redirecting to local workspace page...'); - } - }, [login]); - if (!login) { - return ; - } - return <>{children}; -} - -export const AffineAdapter: WorkspaceAdapter = { - releaseType: ReleaseType.STABLE, - flavour: WorkspaceFlavour.AFFINE, - loadPriority: LoadPriority.HIGH, - Events: { - 'workspace:access': async () => { - if (!runtimeConfig.enableLegacyCloud) { - console.warn('Legacy cloud is disabled'); - return; - } - const response = await affineAuth.generateToken(SignMethod.Google); - if (response) { - setLoginStorage(response); - const user = parseIdToken(response.token); - rootStore.set(currentAffineUserAtom, user); - } else { - toast('Login failed'); - } - }, - 'workspace:revoke': async () => { - if (!runtimeConfig.enableLegacyCloud) { - console.warn('Legacy cloud is disabled'); - return; - } - await rootStore.set(rootWorkspacesMetadataAtom, workspaces => - workspaces.filter( - workspace => workspace.flavour !== WorkspaceFlavour.AFFINE - ) - ); - storage.removeItem(AFFINE_STORAGE_KEY); - clearLoginStorage(); - rootStore.set(currentAffineUserAtom, null); - }, - }, - CRUD: { - create: async blockSuiteWorkspace => { - const binary = BlockSuiteWorkspace.Y.encodeStateAsUpdate( - blockSuiteWorkspace.doc - ); - const { id } = await affineApis.createWorkspace(binary); - // fixme: syncing images - const newWorkspaceId = id; - - await new Promise(resolve => setTimeout(resolve, 1000)); - const blobManager = blockSuiteWorkspace.blobs; - for (const id of await blobManager.list()) { - const blob = await blobManager.get(id); - if (blob) { - await affineApis.uploadBlob( - newWorkspaceId, - await blob.arrayBuffer(), - blob.type - ); - } - } - { - const bs = createEmptyBlockSuiteWorkspace(id, WorkspaceFlavour.AFFINE, { - workspaceApis: affineApis, - }); - // fixme: - // force to download workspace binary - // to make sure the workspace is synced - const provider = createAffineDownloadProvider(bs.id, bs.doc, { - awareness: bs.awarenessStore.awareness, - }) as AffineDownloadProvider; - const indexedDBProvider = createIndexedDBDownloadProvider( - bs.id, - bs.doc, - { - awareness: bs.awarenessStore.awareness, - } - ) as LocalIndexedDBDownloadProvider; - indexedDBProvider.sync(); - await indexedDBProvider.whenReady; - provider.disconnect(); - } - - await mutate(matcher => matcher === QueryKey.getWorkspaces); - // refresh the local storage - await AffineAdapter.CRUD.list(); - return id; - }, - delete: async workspace => { - const items = storage.getItem(AFFINE_STORAGE_KEY, []); - if ( - Array.isArray(items) && - items.every(item => schema.safeParse(item).success) - ) { - storage.setItem( - AFFINE_STORAGE_KEY, - items.filter(item => item.id !== workspace.id) - ); - } - await affineApis.deleteWorkspace({ - id: workspace.id, - }); - await mutate(matcher => matcher === QueryKey.getWorkspaces); - }, - get: async workspaceId => { - // fixme(himself65): rewrite the auth logic - try { - const loginStorage = getLoginStorage(); - if ( - loginStorage == null || - isExpired(parseIdToken(loginStorage.token)) - ) { - rootStore.set(currentAffineUserAtom, null); - storage.removeItem(AFFINE_STORAGE_KEY); - cleanupWorkspace(WorkspaceFlavour.AFFINE); - return null; - } - const workspaces: AffineLegacyCloudWorkspace[] = - await AffineAdapter.CRUD.list(); - return ( - workspaces.find(workspace => workspace.id === workspaceId) ?? null - ); - } catch (e) { - const workspaces = getPersistenceAllWorkspace(); - return ( - workspaces.find(workspace => workspace.id === workspaceId) ?? null - ); - } - }, - list: async () => { - const allWorkspaces = getPersistenceAllWorkspace(); - const loginStorage = getLoginStorage(); - // fixme(himself65): rewrite the auth logic - try { - if ( - loginStorage == null || - isExpired(parseIdToken(loginStorage.token)) - ) { - rootStore.set(currentAffineUserAtom, null); - storage.removeItem(AFFINE_STORAGE_KEY); - return []; - } - } catch (e) { - storage.removeItem(AFFINE_STORAGE_KEY); - return []; - } - try { - const workspaces = await affineApis.getWorkspaces().then(workspaces => { - return workspaces.map(workspace => { - const blockSuiteWorkspace = createEmptyBlockSuiteWorkspace( - workspace.id, - WorkspaceFlavour.AFFINE, - { - workspaceApis: affineApis, - } - ); - const dump = workspaces.map(workspace => { - return { - id: workspace.id, - type: workspace.type, - public: workspace.public, - permission: workspace.permission, - } satisfies z.infer; - }); - const old = storage.getItem(AFFINE_STORAGE_KEY, []); - if ( - Array.isArray(old) && - old.every(item => schema.safeParse(item).success) - ) { - const data = [...dump]; - old.forEach((item: z.infer) => { - const has = dump.find(dump => dump.id === item.id); - if (!has) { - data.push(item); - } - }); - storage.setItem(AFFINE_STORAGE_KEY, [...data]); - } - - const affineWorkspace: AffineLegacyCloudWorkspace = { - ...workspace, - flavour: WorkspaceFlavour.AFFINE, - blockSuiteWorkspace, - }; - return affineWorkspace; - }); - }); - workspaces.forEach(workspace => { - const idx = allWorkspaces.findIndex(({ id }) => id === workspace.id); - if (idx !== -1) { - allWorkspaces.splice(idx, 1, workspace); - } else { - allWorkspaces.push(workspace); - } - }); - - // only save data when login in - const dump = allWorkspaces.map(workspace => { - return { - id: workspace.id, - type: workspace.type, - public: workspace.public, - permission: workspace.permission, - } satisfies z.infer; - }); - storage.setItem(AFFINE_STORAGE_KEY, [...dump]); - } catch (e) { - console.error('fetch affine workspaces failed', e); - } - return [...allWorkspaces]; - }, - }, - UI: { - Provider: ({ children }) => { - return ( - }> - {children} - - ); - }, - Header: WorkspaceHeader, - PageDetail: ({ currentWorkspace, currentPageId, onLoadEditor }) => { - const page = currentWorkspace.blockSuiteWorkspace.getPage(currentPageId); - if (!page) { - throw new PageNotFoundError( - currentWorkspace.blockSuiteWorkspace, - currentPageId - ); - } - return ( - <> - - - ); - }, - PageList: ({ blockSuiteWorkspace, onOpenPage, collection }) => { - return ( - - ); - }, - SettingsDetail: ({ - currentWorkspace, - onChangeTab, - currentTab, - onDeleteWorkspace, - onTransformWorkspace, - }) => { - return ( - - ); - }, - NewSettingsDetail: ({ - currentWorkspace, - onDeleteWorkspace, - onTransformWorkspace, - }) => { - return ( - - ); - }, - }, -}; diff --git a/apps/web/src/adapters/local/index.tsx b/apps/web/src/adapters/local/index.tsx index b9a175e4ff..ed91d19e92 100644 --- a/apps/web/src/adapters/local/index.tsx +++ b/apps/web/src/adapters/local/index.tsx @@ -25,7 +25,6 @@ import { NewWorkspaceSettingDetail, PageDetailEditor, WorkspaceHeader, - WorkspaceSettingDetail, } from '../shared'; const logger = new DebugLogger('use-create-first-workspace'); @@ -105,23 +104,6 @@ export const LocalAdapter: WorkspaceAdapter = { /> ); }, - SettingsDetail: ({ - currentWorkspace, - onChangeTab, - currentTab, - onDeleteWorkspace, - onTransformWorkspace, - }) => { - return ( - - ); - }, NewSettingsDetail: ({ currentWorkspace, onDeleteWorkspace, diff --git a/apps/web/src/adapters/shared.ts b/apps/web/src/adapters/shared.ts index 0d3eef79ef..90ad5e5716 100644 --- a/apps/web/src/adapters/shared.ts +++ b/apps/web/src/adapters/shared.ts @@ -1,12 +1,5 @@ import { lazy } from 'react'; -// export { WorkspaceSettingDetail as NewWorkspaceSettingDetail } from '../components/affine/new-workspace-setting-detail'; -export const WorkspaceSettingDetail = lazy(() => - import('../components/affine/workspace-setting-detail').then( - ({ WorkspaceSettingDetail }) => ({ - default: WorkspaceSettingDetail, - }) - ) -); + export const NewWorkspaceSettingDetail = lazy(() => import('../components/affine/new-workspace-setting-detail').then( ({ WorkspaceSettingDetail }) => ({ @@ -14,6 +7,7 @@ export const NewWorkspaceSettingDetail = lazy(() => }) ) ); + export const BlockSuitePageList = lazy(() => import('../components/blocksuite/block-suite-page-list').then( ({ BlockSuitePageList }) => ({ @@ -21,6 +15,7 @@ export const BlockSuitePageList = lazy(() => }) ) ); + export const PageDetailEditor = lazy(() => import('../components/page-detail-editor').then(({ PageDetailEditor }) => ({ default: PageDetailEditor, diff --git a/apps/web/src/adapters/workspace.ts b/apps/web/src/adapters/workspace.ts index fa7e4f8ad6..dbb74d709f 100644 --- a/apps/web/src/adapters/workspace.ts +++ b/apps/web/src/adapters/workspace.ts @@ -10,7 +10,6 @@ import { WorkspaceFlavour, } from '@affine/env/workspace'; -import { AffineAdapter } from './affine'; import { LocalAdapter } from './local'; const unimplemented = () => { @@ -22,7 +21,6 @@ const bypassList = async () => { }; export const WorkspaceAdapters = { - [WorkspaceFlavour.AFFINE]: AffineAdapter, [WorkspaceFlavour.LOCAL]: LocalAdapter, [WorkspaceFlavour.AFFINE_CLOUD]: { releaseType: ReleaseType.UNRELEASED, @@ -42,7 +40,6 @@ export const WorkspaceAdapters = { Header: unimplemented, PageDetail: unimplemented, PageList: unimplemented, - SettingsDetail: unimplemented, NewSettingsDetail: unimplemented, }, }, @@ -64,7 +61,6 @@ export const WorkspaceAdapters = { Header: unimplemented, PageDetail: unimplemented, PageList: unimplemented, - SettingsDetail: unimplemented, NewSettingsDetail: unimplemented, }, }, diff --git a/apps/web/src/atoms/public-workspace/index.ts b/apps/web/src/atoms/public-workspace/index.ts deleted file mode 100644 index d57dbe9e81..0000000000 --- a/apps/web/src/atoms/public-workspace/index.ts +++ /dev/null @@ -1,68 +0,0 @@ -import type { BlockSuiteFeatureFlags } from '@affine/env/global'; -import type { AffinePublicWorkspace } from '@affine/env/workspace'; -import { WorkspaceFlavour } from '@affine/env/workspace'; -import { affineApis } from '@affine/workspace/affine/shared'; -import { createEmptyBlockSuiteWorkspace } from '@affine/workspace/utils'; -import { atom } from 'jotai'; - -import { BlockSuiteWorkspace } from '../../shared'; - -function createPublicWorkspace( - workspaceId: string, - binary: ArrayBuffer, - singlePage = false -): AffinePublicWorkspace { - const blockSuiteWorkspace = createEmptyBlockSuiteWorkspace( - workspaceId, - WorkspaceFlavour.AFFINE, - { - workspaceApis: affineApis, - cachePrefix: WorkspaceFlavour.PUBLIC + (singlePage ? '-single-page' : ''), - } - ); - BlockSuiteWorkspace.Y.applyUpdate( - blockSuiteWorkspace.doc, - new Uint8Array(binary) - ); - Object.entries(runtimeConfig.editorFlags).forEach(([key, value]) => { - blockSuiteWorkspace.awarenessStore.setFlag( - key as keyof BlockSuiteFeatureFlags, - value - ); - }); - // force disable some features - blockSuiteWorkspace.awarenessStore.setFlag('enable_block_hub', false); - blockSuiteWorkspace.awarenessStore.setFlag('enable_drag_handle', false); - return { - flavour: WorkspaceFlavour.PUBLIC, - id: workspaceId, - blockSuiteWorkspace, - }; -} - -export const publicWorkspaceIdAtom = atom(null); -export const publicWorkspacePageIdAtom = atom(null); -export const publicPageBlockSuiteAtom = atom>( - async get => { - const workspaceId = get(publicWorkspaceIdAtom); - const pageId = get(publicWorkspacePageIdAtom); - if (!workspaceId || !pageId) { - throw new Error('No workspace id or page id'); - } - const binary = await affineApis.downloadPublicWorkspacePage( - workspaceId, - pageId - ); - return createPublicWorkspace(workspaceId, binary, true); - } -); -export const publicWorkspaceAtom = atom>( - async get => { - const workspaceId = get(publicWorkspaceIdAtom); - if (!workspaceId) { - throw new Error('No workspace id'); - } - const binary = await affineApis.downloadWorkspace(workspaceId, true); - return createPublicWorkspace(workspaceId, binary, false); - } -); diff --git a/apps/web/src/atoms/root.ts b/apps/web/src/atoms/root.ts index 4cba0e05f0..7f8b8ad870 100644 --- a/apps/web/src/atoms/root.ts +++ b/apps/web/src/atoms/root.ts @@ -4,7 +4,7 @@ import type { WorkspaceAdapter, WorkspaceRegistry, } from '@affine/env/workspace'; -import { WorkspaceFlavour } from '@affine/env/workspace'; +import type { WorkspaceFlavour } from '@affine/env/workspace'; import { rootCurrentWorkspaceIdAtom, rootWorkspacesMetadataAtom, @@ -26,16 +26,9 @@ export const workspacesAtom = atom>( const flavours: string[] = Object.values(WorkspaceAdapters).map( plugin => plugin.flavour ); - const jotaiWorkspaces = (await get(rootWorkspacesMetadataAtom)) - .filter( - workspace => flavours.includes(workspace.flavour) - // TODO: remove this when we remove the legacy cloud - ) - .filter(workspace => - !runtimeConfig.enableLegacyCloud - ? workspace.flavour !== WorkspaceFlavour.AFFINE - : true - ); + const jotaiWorkspaces = (await get(rootWorkspacesMetadataAtom)).filter( + workspace => flavours.includes(workspace.flavour) + ); if (jotaiWorkspaces.some(meta => !('version' in meta))) { // wait until all workspaces have migrated to v2 await new Promise((resolve, reject) => { @@ -63,7 +56,7 @@ export const workspacesAtom = atom>( }) ).then(workspaces => workspaces.filter( - (workspace): workspace is WorkspaceRegistry['affine' | 'local'] => + (workspace): workspace is WorkspaceRegistry['affine-cloud' | 'local'] => workspace !== null ) ); diff --git a/apps/web/src/components/affine/affine-error-eoundary.tsx b/apps/web/src/components/affine/affine-error-eoundary.tsx index a47039fada..7416c87e24 100644 --- a/apps/web/src/components/affine/affine-error-eoundary.tsx +++ b/apps/web/src/components/affine/affine-error-eoundary.tsx @@ -4,7 +4,6 @@ import type { WorkspaceNotFoundError, } from '@affine/env/constant'; import { PageNotFoundError } from '@affine/env/constant'; -import { RequestError } from '@affine/workspace/affine/api'; import type { NextRouter } from 'next/router'; import type { ErrorInfo, ReactNode } from 'react'; import type React from 'react'; @@ -19,7 +18,6 @@ type AffineError = | Unreachable | WorkspaceNotFoundError | PageNotFoundError - | RequestError | Error; interface AffineErrorBoundaryState { @@ -78,13 +76,6 @@ export class AffineErrorBoundary extends Component< ); - } else if (error instanceof RequestError) { - return ( - <> -

Sorry.. there was an error

- {error.message} - - ); } return ( <> diff --git a/apps/web/src/components/affine/enable-affine-cloud-modal/index.tsx b/apps/web/src/components/affine/enable-affine-cloud-modal/index.tsx index 5fae1c8c61..5a6c230dd6 100644 --- a/apps/web/src/components/affine/enable-affine-cloud-modal/index.tsx +++ b/apps/web/src/components/affine/enable-affine-cloud-modal/index.tsx @@ -3,7 +3,6 @@ import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { CloseIcon } from '@blocksuite/icons'; import type React from 'react'; -import { useCurrentUser } from '../../../hooks/current/use-current-user'; import { Content, ContentTitle, Header, StyleButton, StyleTips } from './style'; interface EnableAffineCloudModalProps { @@ -18,7 +17,6 @@ export const EnableAffineCloudModal: React.FC = ({ onClose, }) => { const t = useAFFiNEI18N(); - const user = useCurrentUser(); return ( @@ -39,7 +37,7 @@ export const EnableAffineCloudModal: React.FC = ({ type="primary" onClick={onConfirm} > - {user ? t.Enable() : t['Sign in and Enable']()} + {t['Sign in and Enable']()} {t['Not now']()} diff --git a/apps/web/src/components/affine/new-workspace-setting-detail/delete-leave-workspace/index.tsx b/apps/web/src/components/affine/new-workspace-setting-detail/delete-leave-workspace/index.tsx index 7cd9d7350a..b38de0b85f 100644 --- a/apps/web/src/components/affine/new-workspace-setting-detail/delete-leave-workspace/index.tsx +++ b/apps/web/src/components/affine/new-workspace-setting-detail/delete-leave-workspace/index.tsx @@ -3,7 +3,6 @@ import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { ArrowRightSmallIcon } from '@blocksuite/icons'; import { type FC, useState } from 'react'; -import { useIsWorkspaceOwner } from '../../../../hooks/affine/use-is-workspace-owner'; import type { AffineOfficialWorkspace } from '../../../../shared'; import type { WorkspaceSettingDetailProps } from '../index'; import { WorkspaceDeleteModal } from './delete'; @@ -14,7 +13,8 @@ export const DeleteLeaveWorkspace: FC<{ onDeleteWorkspace: WorkspaceSettingDetailProps['onDeleteWorkspace']; }> = ({ workspace, onDeleteWorkspace }) => { const t = useAFFiNEI18N(); - const isOwner = useIsWorkspaceOwner(workspace); + // fixme: cloud regression + const isOwner = true; const [showDelete, setShowDelete] = useState(false); const [showLeave, setShowLeave] = useState(false); diff --git a/apps/web/src/components/affine/new-workspace-setting-detail/index.tsx b/apps/web/src/components/affine/new-workspace-setting-detail/index.tsx index 6c8c3a55b6..74569b7507 100644 --- a/apps/web/src/components/affine/new-workspace-setting-detail/index.tsx +++ b/apps/web/src/components/affine/new-workspace-setting-detail/index.tsx @@ -14,7 +14,6 @@ import type { FC } from 'react'; import type { AffineOfficialWorkspace } from '../../../shared'; import { DeleteLeaveWorkspace } from './delete-leave-workspace'; import { ExportPanel } from './export'; -import { MembersPanel } from './members'; import { ProfilePanel } from './profile'; import { PublishPanel } from './publish'; import { StoragePanel } from './storage'; @@ -63,11 +62,6 @@ export const WorkspaceSettingDetail: FC = ({ onDeleteWorkspace={onDeleteWorkspace} {...props} /> - {environment.isDesktop ? ( diff --git a/apps/web/src/components/affine/new-workspace-setting-detail/members/index.tsx b/apps/web/src/components/affine/new-workspace-setting-detail/members/index.tsx deleted file mode 100644 index 734fb1349d..0000000000 --- a/apps/web/src/components/affine/new-workspace-setting-detail/members/index.tsx +++ /dev/null @@ -1,160 +0,0 @@ -import { Button, IconButton, Menu, MenuItem } from '@affine/component'; -import { SettingRow } from '@affine/component/setting-components'; -import { UserAvatar } from '@affine/component/user-avatar'; -import { Unreachable } from '@affine/env/constant'; -import type { AffineLegacyCloudWorkspace } from '@affine/env/workspace'; -import { WorkspaceFlavour } from '@affine/env/workspace'; -import { PermissionType } from '@affine/env/workspace/legacy-cloud'; -import { useAFFiNEI18N } from '@affine/i18n/hooks'; -import { DeleteTemporarilyIcon, MoreVerticalIcon } from '@blocksuite/icons'; -import type { FC } from 'react'; -import React, { useCallback, useState } from 'react'; - -import { useMembers } from '../../../../hooks/affine/use-members'; -import type { AffineOfficialWorkspace } from '../../../../shared'; -import { toast } from '../../../../utils'; -import type { WorkspaceSettingDetailProps } from '../index'; -import { fakeWrapper } from '../style.css'; -import { InviteMemberModal } from './invite-member-modal'; -import * as style from './style.css'; - -export type AffineRemoteMembersProps = WorkspaceSettingDetailProps & { - workspace: AffineLegacyCloudWorkspace; -}; -export type MemberPanelProps = WorkspaceSettingDetailProps & { - workspace: AffineOfficialWorkspace; -}; - -const MemberList: FC<{ - workspace: AffineLegacyCloudWorkspace; -}> = ({ workspace }) => { - const t = useAFFiNEI18N(); - const { members, removeMember } = useMembers(workspace.id); - - if (members.length) { - return null; - } - - return ( -
    - {members - .sort((b, a) => a.type - b.type) - .map(member => { - const { id, name, email, avatar_url } = { - name: '', - email: '', - avatar_url: '', - ...member, - }; - return ( -
  • -
    - -
    -

    {name}

    -

    {email}

    -
    -
    -
    -
    - {member.accepted - ? member.type !== PermissionType.Owner - ? t['Member']() - : t['Owner']() - : t['Pending']()} -
    - - { - await removeMember(Number(id)); - toast( - t['Member has been removed']({ - name, - }) - ); - }} - icon={} - > - {t['Remove from workspace']()} - - - } - placement="bottom" - disablePortal={true} - trigger="click" - > - - - - -
    -
  • - ); - })} -
- ); -}; - -export const AffineRemoteMembers: FC = ({ - workspace, -}) => { - const t = useAFFiNEI18N(); - const { members } = useMembers(workspace.id); - - const [isInviteModalShow, setIsInviteModalShow] = useState(false); - - return ( - <> - - - - - { - setIsInviteModalShow(false); - }, [])} - onInviteSuccess={useCallback(() => { - setIsInviteModalShow(false); - }, [])} - workspaceId={workspace.id} - open={isInviteModalShow} - /> - - ); -}; -export const FakeMembers: FC = () => { - const t = useAFFiNEI18N(); - return ( -
- - - -
- ); -}; - -export const MembersPanel: FC = props => { - switch (props.workspace.flavour) { - case WorkspaceFlavour.AFFINE: { - const workspace = props.workspace as AffineLegacyCloudWorkspace; - return ; - } - case WorkspaceFlavour.LOCAL: { - return ; - } - } - throw new Unreachable(); -}; diff --git a/apps/web/src/components/affine/new-workspace-setting-detail/members/invite-member-modal/index.tsx b/apps/web/src/components/affine/new-workspace-setting-detail/members/invite-member-modal/index.tsx deleted file mode 100644 index 909b1a4853..0000000000 --- a/apps/web/src/components/affine/new-workspace-setting-detail/members/invite-member-modal/index.tsx +++ /dev/null @@ -1,222 +0,0 @@ -import { - Button, - Input, - Modal, - ModalCloseButton, - ModalWrapper, - MuiAvatar, - styled, -} from '@affine/component'; -import { useAFFiNEI18N } from '@affine/i18n/hooks'; -import { EmailIcon } from '@blocksuite/icons'; -import type React from 'react'; -import { Suspense, useCallback, useState } from 'react'; - -import { useMembers } from '../../../../../hooks/affine/use-members'; -import { useUsersByEmail } from '../../../../../hooks/affine/use-users-by-email'; - -interface LoginModalProps { - open: boolean; - onClose: () => void; - workspaceId: string; - onInviteSuccess: () => void; -} - -const gmailReg = - /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@(gmail|example)\.(com|org)$/; - -const Result: React.FC<{ - workspaceId: string; - queryEmail: string; -}> = ({ workspaceId, queryEmail }) => { - const users = useUsersByEmail(workspaceId, queryEmail); - const firstUser = users?.at(0) ?? null; - if (!firstUser || !firstUser.email) { - return null; - } - return ( - - - {firstUser.avatar_url ? ( - - ) : ( - - - - )} - {firstUser.email} - {/*
invited
*/} -
-
- ); -}; - -export const InviteMemberModal = ({ - open, - onClose, - onInviteSuccess, - workspaceId, -}: LoginModalProps) => { - const { inviteMember } = useMembers(workspaceId); - const [email, setEmail] = useState(''); - const [showMemberPreview, setShowMemberPreview] = useState(false); - const t = useAFFiNEI18N(); - const inputChange = useCallback((value: string) => { - setEmail(value); - }, []); - return ( -
- - -
- { - onClose(); - setEmail(''); - }} - /> -
- - {t['Invite Members']()} - - { - setShowMemberPreview(true); - }, [])} - onBlur={useCallback(() => { - setShowMemberPreview(false); - }, [])} - placeholder={t['Invite placeholder']()} - /> - {showMemberPreview && gmailReg.test(email) && ( - - - - )} - - -
- -
-
-
-
- ); -}; - -const Header = styled('div')({ - position: 'relative', - height: '44px', -}); - -const Content = styled('div')({ - display: 'flex', - flexDirection: 'column', - alignItems: 'center', -}); - -const ContentTitle = styled('h1')({ - fontSize: '20px', - lineHeight: '28px', - fontWeight: 600, - textAlign: 'center', - paddingBottom: '16px', -}); - -const Footer = styled('div')({ - height: '102px', - margin: '32px 0', - textAlign: 'center', -}); - -const InviteBox = styled('div')({ - position: 'relative', -}); - -const Members = styled('div')(() => { - return { - position: 'absolute', - width: '100%', - background: 'var(--affine-background-primary-color)', - textAlign: 'left', - zIndex: 1, - borderRadius: '0px 10px 10px 10px', - height: '56px', - padding: '8px 12px', - input: { - '&::placeholder': { - color: 'var(--affine-placeholder-color)', - }, - }, - }; -}); - -// const NoFind = styled('div')(({ theme }) => { -// return { -// color: 'var(--affine-icon-color)', -// fontSize: 'var(--affine-font-sm)', -// lineHeight: '40px', -// userSelect: 'none', -// width: '100%', -// }; -// }); - -const Member = styled('div')(() => { - return { - color: 'var(--affine-icon-color)', - fontSize: 'var(--affine-font-sm)', - lineHeight: '40px', - userSelect: 'none', - display: 'flex', - }; -}); - -const MemberIcon = styled('div')(() => { - return { - width: '40px', - height: '40px', - borderRadius: '50%', - color: 'var(--affine-primary-color)', - background: '#F5F5F5', - textAlign: 'center', - lineHeight: '45px', - // icon size - fontSize: '20px', - overflow: 'hidden', - img: { - width: '100%', - height: '100%', - }, - }; -}); - -const Email = styled('div')(() => { - return { - flex: '1', - overflow: 'hidden', - textOverflow: 'ellipsis', - whiteSpace: 'nowrap', - marginLeft: '8px', - }; -}); diff --git a/apps/web/src/components/affine/new-workspace-setting-detail/members/style.css.ts b/apps/web/src/components/affine/new-workspace-setting-detail/members/style.css.ts deleted file mode 100644 index 9ac5ba1e58..0000000000 --- a/apps/web/src/components/affine/new-workspace-setting-detail/members/style.css.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { globalStyle, style } from '@vanilla-extract/css'; - -export const memberList = style({ - marginTop: '12px', -}); - -globalStyle(`${memberList} .member-list-item`, { - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', -}); -globalStyle(`${memberList} .member-list-item:not(:last-of-type)`, { - marginBottom: '8px', -}); - -globalStyle(`${memberList} .left-col`, { - display: 'flex', - alignItems: 'center', - width: '60%', -}); -globalStyle(`${memberList} .right-col`, { - display: 'flex', - justifyContent: 'flex-end', - alignItems: 'center', - width: '35%', -}); -globalStyle(`${memberList} .user-info-wrapper`, { - flexGrow: 1, - marginLeft: '12px', - overflow: 'hidden', -}); - -globalStyle(`${memberList} .user-info-wrapper p`, { - width: '100%', - overflow: 'hidden', - textOverflow: 'ellipsis', - whiteSpace: 'nowrap', -}); - -globalStyle(`${memberList} .user-name`, { - fontSize: 'var(--affine-font-sm)', -}); -globalStyle(`${memberList} .email`, { - fontSize: 'var(--affine-font-xs)', - color: 'var(--affine-text-secondary-color)', -}); -globalStyle(`${memberList} .user-identity`, { - fontSize: 'var(--affine-font-sm)', - marginRight: '15px', - flexGrow: '1', - overflow: 'hidden', - textOverflow: 'ellipsis', - whiteSpace: 'nowrap', -}); diff --git a/apps/web/src/components/affine/new-workspace-setting-detail/profile.tsx b/apps/web/src/components/affine/new-workspace-setting-detail/profile.tsx index e84c4e560c..321225a639 100644 --- a/apps/web/src/components/affine/new-workspace-setting-detail/profile.tsx +++ b/apps/web/src/components/affine/new-workspace-setting-detail/profile.tsx @@ -6,17 +6,33 @@ import { useBlockSuiteWorkspaceAvatarUrl } from '@toeverything/hooks/use-block-s import { useBlockSuiteWorkspaceName } from '@toeverything/hooks/use-block-suite-workspace-name'; import { type FC, useCallback, useState } from 'react'; -import { useIsWorkspaceOwner } from '../../../hooks/affine/use-is-workspace-owner'; import type { AffineOfficialWorkspace } from '../../../shared'; import { Upload } from '../../pure/file-upload'; -import { CameraIcon } from '../workspace-setting-detail/panel/general/icons'; import * as style from './style.css'; +const CameraIcon = () => { + return ( + + + + ); +}; + export const ProfilePanel: FC<{ workspace: AffineOfficialWorkspace; }> = ({ workspace }) => { const t = useAFFiNEI18N(); - const isOwner = useIsWorkspaceOwner(workspace); const [, update] = useBlockSuiteWorkspaceAvatarUrl( workspace.blockSuiteWorkspace @@ -38,22 +54,18 @@ export const ProfilePanel: FC<{ return (
- {isOwner ? ( - - <> -
- -
- - -
- ) : ( - - )} + + <> +
+ +
+ + +
= props => { const { workspace } = props; const t = useAFFiNEI18N(); - const toggleWorkspacePublish = useToggleWorkspacePublish(workspace); + // const toggleWorkspacePublish = useToggleWorkspacePublish(workspace); const [origin, setOrigin] = useState(''); const shareUrl = origin + '/public-workspace/' + workspace.id; @@ -54,13 +53,14 @@ const PublishPanelAffine: FC = props => { - toggleWorkspacePublish(checked)} - /> + /> */} - - - { - setIsInviteModalShow(false); - }, [])} - onInviteSuccess={useCallback(() => { - setIsInviteModalShow(false); - }, [])} - workspaceId={workspace.id} - open={isInviteModalShow} - /> - - ); -}; - -const LocalCollaborationPanel: React.FC< - Omit & { - workspace: LocalWorkspace; - } -> = ({ workspace, onTransferWorkspace }) => { - const t = useAFFiNEI18N(); - const [open, setOpen] = useState(false); - return ( - <> - {t['Collaboration Description']()} - - - {runtimeConfig.enableLegacyCloud ? ( - { - setOpen(false); - }} - onConform={() => { - onTransferWorkspace( - WorkspaceFlavour.LOCAL, - WorkspaceFlavour.AFFINE, - workspace - ); - setOpen(false); - }} - /> - ) : ( - { - setOpen(false); - }} - /> - )} - - ); -}; - -export const CollaborationPanel: React.FC = props => { - switch (props.workspace.flavour) { - case WorkspaceFlavour.AFFINE: { - const workspace = props.workspace as AffineLegacyCloudWorkspace; - return ( - - ); - } - case WorkspaceFlavour.LOCAL: { - const workspace = props.workspace as LocalWorkspace; - return ; - } - } - throw new Unreachable(); -}; diff --git a/apps/web/src/components/affine/workspace-setting-detail/panel/collaboration/invite-member-modal/index.tsx b/apps/web/src/components/affine/workspace-setting-detail/panel/collaboration/invite-member-modal/index.tsx deleted file mode 100644 index 34939679fa..0000000000 --- a/apps/web/src/components/affine/workspace-setting-detail/panel/collaboration/invite-member-modal/index.tsx +++ /dev/null @@ -1,218 +0,0 @@ -import { - Button, - Input, - Modal, - ModalCloseButton, - ModalWrapper, - MuiAvatar, - styled, -} from '@affine/component'; -import { useAFFiNEI18N } from '@affine/i18n/hooks'; -import { EmailIcon } from '@blocksuite/icons'; -import type React from 'react'; -import { Suspense, useCallback, useState } from 'react'; - -import { useMembers } from '../../../../../../hooks/affine/use-members'; -import { useUsersByEmail } from '../../../../../../hooks/affine/use-users-by-email'; - -interface LoginModalProps { - open: boolean; - onClose: () => void; - workspaceId: string; - onInviteSuccess: () => void; -} - -const gmailReg = - /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@(gmail|example)\.(com|org)$/; - -const Result: React.FC<{ - workspaceId: string; - queryEmail: string; -}> = ({ workspaceId, queryEmail }) => { - const users = useUsersByEmail(workspaceId, queryEmail); - const firstUser = users?.at(0) ?? null; - if (!firstUser || !firstUser.email) { - return null; - } - return ( - - - {firstUser.avatar_url ? ( - - ) : ( - - - - )} - {firstUser.email} - {/*
invited
*/} -
-
- ); -}; - -export const InviteMemberModal = ({ - open, - onClose, - onInviteSuccess, - workspaceId, -}: LoginModalProps) => { - const { inviteMember } = useMembers(workspaceId); - const [email, setEmail] = useState(''); - const [showMemberPreview, setShowMemberPreview] = useState(false); - const t = useAFFiNEI18N(); - const inputChange = useCallback((value: string) => { - setEmail(value); - }, []); - return ( -
- - -
- { - onClose(); - setEmail(''); - }} - /> -
- - {t['Invite Members']()} - - { - setShowMemberPreview(true); - }, [])} - onBlur={useCallback(() => { - setShowMemberPreview(false); - }, [])} - placeholder={t['Invite placeholder']()} - /> - {showMemberPreview && gmailReg.test(email) && ( - - - - )} - - -
- -
-
-
-
- ); -}; - -const Header = styled('div')({ - position: 'relative', - height: '44px', -}); - -const Content = styled('div')({ - display: 'flex', - flexDirection: 'column', - alignItems: 'center', -}); - -const ContentTitle = styled('h1')({ - fontSize: '20px', - lineHeight: '28px', - fontWeight: 600, - textAlign: 'center', - paddingBottom: '16px', -}); - -const Footer = styled('div')({ - height: '102px', - margin: '32px 0', - textAlign: 'center', -}); - -const InviteBox = styled('div')({ - position: 'relative', -}); - -const Members = styled('div')(() => { - return { - position: 'absolute', - width: '100%', - background: 'var(--affine-background-primary-color)', - textAlign: 'left', - zIndex: 1, - borderRadius: '0px 10px 10px 10px', - height: '56px', - padding: '8px 12px', - input: { - '&::placeholder': { - color: 'var(--affine-placeholder-color)', - }, - }, - }; -}); - -// const NoFind = styled('div')(({ theme }) => { -// return { -// color: 'var(--affine-icon-color)', -// fontSize: 'var(--affine-font-sm)', -// lineHeight: '40px', -// userSelect: 'none', -// width: '100%', -// }; -// }); - -const Member = styled('div')(() => { - return { - color: 'var(--affine-icon-color)', - fontSize: 'var(--affine-font-sm)', - lineHeight: '40px', - userSelect: 'none', - display: 'flex', - }; -}); - -const MemberIcon = styled('div')(() => { - return { - width: '40px', - height: '40px', - borderRadius: '50%', - color: 'var(--affine-primary-color)', - background: '#F5F5F5', - textAlign: 'center', - lineHeight: '45px', - // icon size - fontSize: '20px', - overflow: 'hidden', - img: { - width: '100%', - height: '100%', - }, - }; -}); - -const Email = styled('div')(() => { - return { - flex: '1', - overflow: 'hidden', - textOverflow: 'ellipsis', - whiteSpace: 'nowrap', - marginLeft: '8px', - }; -}); diff --git a/apps/web/src/components/affine/workspace-setting-detail/panel/collaboration/style.ts b/apps/web/src/components/affine/workspace-setting-detail/panel/collaboration/style.ts deleted file mode 100644 index 616d1ef076..0000000000 --- a/apps/web/src/components/affine/workspace-setting-detail/panel/collaboration/style.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { styled } from '@affine/component'; -import { MuiAvatar } from '@affine/component'; - -export const StyledMemberTitleContainer = styled('li')(() => { - return { - display: 'flex', - fontWeight: '500', - marginBottom: '42px', - flex: 1, - }; -}); -export const StyledMemberContainer = styled('div')(() => { - return { - display: 'flex', - height: '100%', - flexDirection: 'column', - overflow: 'hidden', - }; -}); - -export const StyledMemberAvatar = styled(MuiAvatar)(() => { - return { height: '40px', width: '40px' }; -}); - -export const StyledMemberNameContainer = styled('div')(() => { - return { - display: 'flex', - alignItems: 'center', - flex: '2 0 402px', - }; -}); - -export const StyledMemberRoleContainer = styled('div')(() => { - return { - display: 'flex', - alignItems: 'center', - flex: '1 0 222px', - }; -}); - -export const StyledMemberListContainer = styled('ul')(() => { - return { - overflowY: 'scroll', - flexGrow: 1, - paddingBottom: '58px', - }; -}); - -export const StyledMemberListItem = styled('li')(() => { - return { - display: 'flex', - alignItems: 'center', - height: '72px', - width: '100%', - }; -}); - -export const StyledMemberInfo = styled('div')(() => { - return { - paddingLeft: '12px', - }; -}); - -export const StyledMemberName = styled('div')(() => { - return { - fontWeight: '400', - fontSize: '18px', - lineHeight: '26px', - color: 'var(--affine-text-primary-color)', - }; -}); - -export const StyledMemberEmail = styled('div')(() => { - return { - fontWeight: '400', - fontSize: '16px', - lineHeight: '22px', - color: 'var(--affine-icon-color)', - }; -}); - -export const StyledMemberButtonContainer = styled('div')(() => { - return { - position: 'fixed', - bottom: '20px', - }; -}); - -export const StyledMoreVerticalDiv = styled('div')(() => { - return { - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - width: '24px', - height: '24px', - cursor: 'pointer', - paddingRight: '48px', - }; -}); - -export const StyledMoreVerticalButton = styled(StyledMoreVerticalDiv)``; diff --git a/apps/web/src/components/affine/workspace-setting-detail/panel/export/index.tsx b/apps/web/src/components/affine/workspace-setting-detail/panel/export/index.tsx deleted file mode 100644 index 254102d35d..0000000000 --- a/apps/web/src/components/affine/workspace-setting-detail/panel/export/index.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { Button, toast, Wrapper } from '@affine/component'; -import { useAFFiNEI18N } from '@affine/i18n/hooks'; -import { rootCurrentWorkspaceIdAtom } from '@affine/workspace/atom'; -import { useAtomValue } from 'jotai'; - -export const ExportPanel = () => { - const id = useAtomValue(rootCurrentWorkspaceIdAtom); - const t = useAFFiNEI18N(); - return ( - <> - {t['Export Description']()} - - - ); -}; diff --git a/apps/web/src/components/affine/workspace-setting-detail/panel/general/delete/index.tsx b/apps/web/src/components/affine/workspace-setting-detail/panel/general/delete/index.tsx deleted file mode 100644 index 1d03787255..0000000000 --- a/apps/web/src/components/affine/workspace-setting-detail/panel/general/delete/index.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import { Button, Input, Modal, ModalCloseButton } from '@affine/component'; -import { WorkspaceFlavour } from '@affine/env/workspace'; -import { Trans } from '@affine/i18n'; -import { useAFFiNEI18N } from '@affine/i18n/hooks'; -import { useBlockSuiteWorkspaceName } from '@toeverything/hooks/use-block-suite-workspace-name'; -import { useCallback, useState } from 'react'; - -import type { AffineOfficialWorkspace } from '../../../../../../shared'; -import { toast } from '../../../../../../utils'; -import { - StyledButtonContent, - StyledInputContent, - StyledModalHeader, - StyledModalWrapper, - StyledTextContent, - StyledWorkspaceName, -} from './style'; - -interface WorkspaceDeleteProps { - open: boolean; - onClose: () => void; - workspace: AffineOfficialWorkspace; - onDeleteWorkspace: () => Promise; -} - -export const WorkspaceDeleteModal = ({ - open, - onClose, - workspace, - onDeleteWorkspace, -}: WorkspaceDeleteProps) => { - const [workspaceName] = useBlockSuiteWorkspaceName( - workspace.blockSuiteWorkspace ?? null - ); - const [deleteStr, setDeleteStr] = useState(''); - const allowDelete = deleteStr === workspaceName; - const t = useAFFiNEI18N(); - - const handleDelete = useCallback(() => { - onDeleteWorkspace() - .then(() => { - toast(t['Successfully deleted'](), { - portal: document.body, - }); - }) - .catch(() => { - // ignore error - }); - }, [onDeleteWorkspace, t]); - - return ( - - - - {t['Delete Workspace']()}? - {workspace.flavour === WorkspaceFlavour.LOCAL ? ( - - - Deleting ( - - {{ workspace: workspaceName } as any} - - ) cannot be undone, please proceed with caution. All contents will - be lost. - - - ) : ( - - - Deleting ( - - {{ workspace: workspaceName } as any} - - ) will delete both local and cloud data, this operation cannot be - undone, please proceed with caution. - - - )} - - { - if (ref) { - setTimeout(() => ref.focus(), 0); - } - }} - onChange={setDeleteStr} - data-testid="delete-workspace-input" - placeholder={t['Placeholder of delete workspace']()} - value={deleteStr} - width={315} - height={42} - /> - - - - - - - - ); -}; diff --git a/apps/web/src/components/affine/workspace-setting-detail/panel/general/delete/style.ts b/apps/web/src/components/affine/workspace-setting-detail/panel/general/delete/style.ts deleted file mode 100644 index e214baf703..0000000000 --- a/apps/web/src/components/affine/workspace-setting-detail/panel/general/delete/style.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { styled } from '@affine/component'; - -export const StyledModalWrapper = styled('div')(() => { - return { - position: 'relative', - padding: '0px', - width: '560px', - background: 'var(--affine-white)', - borderRadius: '12px', - // height: '312px', - }; -}); - -export const StyledModalHeader = styled('div')(() => { - return { - margin: '44px 0px 12px 0px', - width: '560px', - fontWeight: '600', - fontSize: '20px;', - textAlign: 'center', - }; -}); - -// export const StyledModalContent = styled('div')(({ theme }) => {}); - -export const StyledTextContent = styled('div')(() => { - return { - margin: 'auto', - width: '425px', - fontFamily: 'Avenir Next', - fontStyle: 'normal', - fontWeight: '400', - fontSize: '18px', - lineHeight: '26px', - textAlign: 'left', - }; -}); - -export const StyledInputContent = styled('div')(() => { - return { - display: 'flex', - flexDirection: 'row', - justifyContent: 'center', - margin: '24px 0', - fontSize: 'var(--affine-font-base)', - }; -}); - -export const StyledButtonContent = styled('div')(() => { - return { - marginBottom: '42px', - display: 'flex', - flexDirection: 'row', - justifyContent: 'center', - }; -}); - -export const StyledWorkspaceName = styled('span')(() => { - return { - fontWeight: '600', - }; -}); - -// export const StyledCancelButton = styled(Button)(({ theme }) => { -// return { -// width: '100px', -// justifyContent: 'center', -// }; -// }); - -// export const StyledDeleteButton = styled(Button)(({ theme }) => { -// return { -// width: '100px', -// justifyContent: 'center', -// }; -// }); diff --git a/apps/web/src/components/affine/workspace-setting-detail/panel/general/icons.tsx b/apps/web/src/components/affine/workspace-setting-detail/panel/general/icons.tsx index 391ae942db..e69de29bb2 100644 --- a/apps/web/src/components/affine/workspace-setting-detail/panel/general/icons.tsx +++ b/apps/web/src/components/affine/workspace-setting-detail/panel/general/icons.tsx @@ -1,18 +0,0 @@ -export const CameraIcon = () => { - return ( - - - - ); -}; diff --git a/apps/web/src/components/affine/workspace-setting-detail/panel/general/index.tsx b/apps/web/src/components/affine/workspace-setting-detail/panel/general/index.tsx deleted file mode 100644 index e65b5afd43..0000000000 --- a/apps/web/src/components/affine/workspace-setting-detail/panel/general/index.tsx +++ /dev/null @@ -1,283 +0,0 @@ -import { Button, toast } from '@affine/component'; -import { WorkspaceAvatar } from '@affine/component/workspace-avatar'; -import { useAFFiNEI18N } from '@affine/i18n/hooks'; -import { - ArrowRightSmallIcon, - DeleteIcon, - FolderIcon, - MoveToIcon, - SaveIcon, -} from '@blocksuite/icons'; -import { useBlockSuiteWorkspaceAvatarUrl } from '@toeverything/hooks/use-block-suite-workspace-avatar-url'; -import { useBlockSuiteWorkspaceName } from '@toeverything/hooks/use-block-suite-workspace-name'; -import clsx from 'clsx'; -import type React from 'react'; -import { useCallback, useEffect, useState } from 'react'; - -import { useIsWorkspaceOwner } from '../../../../../hooks/affine/use-is-workspace-owner'; -import { Upload } from '../../../../pure/file-upload'; -import type { PanelProps } from '../../index'; -import * as style from '../../index.css'; -import { WorkspaceDeleteModal } from './delete'; -import { CameraIcon } from './icons'; -import { WorkspaceLeave } from './leave'; -import { StyledInput } from './style'; - -const useShowOpenDBFile = (workspaceId: string) => { - const [show, setShow] = useState(false); - useEffect(() => { - if ( - window.apis && - window.events && - environment.isDesktop && - runtimeConfig.enableSQLiteProvider - ) { - window.apis.workspace - .getMeta(workspaceId) - .then(meta => { - setShow(!!meta.secondaryDBPath); - }) - .catch(err => { - console.error(err); - }); - return window.events.workspace.onMetaChange((newMeta: any) => { - if (newMeta.workspaceId === workspaceId) { - const meta = newMeta.meta; - setShow(!!meta.secondaryDBPath); - } - }); - } - }, [workspaceId]); - return show; -}; - -export const GeneralPanel: React.FC = ({ - workspace, - onDeleteWorkspace, -}) => { - const [showDelete, setShowDelete] = useState(false); - const [showLeave, setShowLeave] = useState(false); - const [name, setName] = useBlockSuiteWorkspaceName( - workspace.blockSuiteWorkspace - ); - const [input, setInput] = useState(name); - const isOwner = useIsWorkspaceOwner(workspace); - const t = useAFFiNEI18N(); - - const handleUpdateWorkspaceName = (name: string) => { - setName(name); - toast(t['Update workspace name success']()); - }; - - const [, update] = useBlockSuiteWorkspaceAvatarUrl( - workspace.blockSuiteWorkspace - ); - - return ( - <> -
-
-
- {t['Workspace Avatar']()} -
-
- {t['Change avatar hint']()} -
-
-
-
- {isOwner ? ( - - <> -
- -
- - -
- ) : ( - - )} -
-
-
-
- -
-
-
{t['Workspace Name']()}
-
- {t['Change workspace name hint']()} -
-
- -
- -
- -
- -
-
- {environment.isDesktop && runtimeConfig.enableSQLiteProvider ? ( - - ) : null} -
-
-
- {t['Delete Workspace']()} -
-
- {t['Delete Workspace Label Hint']()} -
-
- -
-
- {isOwner ? ( - <> - - { - setShowDelete(false); - }} - workspace={workspace} - /> - - ) : ( - <> - - { - setShowLeave(false); - }} - /> - - )} -
-
- - ); -}; - -function DesktopClientOnly({ workspaceId }: { workspaceId: string }) { - const t = useAFFiNEI18N(); - const showOpenFolder = useShowOpenDBFile(workspaceId); - const onRevealDBFile = useCallback(() => { - if (environment.isDesktop && runtimeConfig.enableSQLiteProvider) { - window.apis?.dialog.revealDBFile(workspaceId).catch(err => { - console.error(err); - }); - } - }, [workspaceId]); - const [moveToInProgress, setMoveToInProgress] = useState(false); - const handleMoveTo = useCallback(() => { - if (moveToInProgress) { - return; - } - setMoveToInProgress(true); - window.apis?.dialog - .moveDBFile(workspaceId) - .then(result => { - if (!result?.error && !result?.canceled) { - toast(t['Move folder success']()); - } else if (result?.error) { - // @ts-expect-error: result.error is dynamic - toast(t[result.error]()); - } - }) - .catch(() => { - toast(t['UNKNOWN_ERROR']()); - }) - .finally(() => { - setMoveToInProgress(false); - }); - }, [moveToInProgress, t, workspaceId]); - const openFolderNode = showOpenFolder ? ( -
- -
-
{t['Open folder']()}
-
- {t['Open folder hint']()} -
-
- -
- ) : null; - return ( -
-
-
{t['Storage Folder']()}
-
- {t['Storage Folder Hint']()} -
-
- -
- {openFolderNode} - -
- -
-
{t['Move folder']()}
-
- {t['Move folder hint']()} -
-
- -
-
-
-
- ); -} diff --git a/apps/web/src/components/affine/workspace-setting-detail/panel/general/leave/index.tsx b/apps/web/src/components/affine/workspace-setting-detail/panel/general/leave/index.tsx deleted file mode 100644 index ed6dabdf3f..0000000000 --- a/apps/web/src/components/affine/workspace-setting-detail/panel/general/leave/index.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { Modal } from '@affine/component'; -import { ModalCloseButton } from '@affine/component'; -import { Button } from '@affine/component'; -import { useAFFiNEI18N } from '@affine/i18n/hooks'; - -import { - StyledButtonContent, - StyledModalHeader, - StyledModalWrapper, - StyledTextContent, -} from './style'; - -interface WorkspaceDeleteProps { - open: boolean; - onClose: () => void; -} - -export const WorkspaceLeave = ({ open, onClose }: WorkspaceDeleteProps) => { - // const { leaveWorkSpace } = useWorkspaceHelper(); - const t = useAFFiNEI18N(); - const handleLeave = async () => { - // await leaveWorkSpace(); - onClose(); - }; - - return ( - - - - {t['Leave Workspace']()} - - {t['Leave Workspace Description']()} - - - - - - - - ); -}; diff --git a/apps/web/src/components/affine/workspace-setting-detail/panel/general/leave/style.ts b/apps/web/src/components/affine/workspace-setting-detail/panel/general/leave/style.ts deleted file mode 100644 index 64254a5aa0..0000000000 --- a/apps/web/src/components/affine/workspace-setting-detail/panel/general/leave/style.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { styled } from '@affine/component'; - -export const StyledModalWrapper = styled('div')(() => { - return { - position: 'relative', - padding: '0px', - width: '460px', - background: 'var(--affine-white)', - borderRadius: '12px', - }; -}); - -export const StyledModalHeader = styled('div')(() => { - return { - margin: '44px 0px 12px 0px', - width: '460px', - fontWeight: '600', - fontSize: '20px;', - textAlign: 'center', - }; -}); - -// export const StyledModalContent = styled('div')(({ theme }) => {}); - -export const StyledTextContent = styled('div')(() => { - return { - margin: 'auto', - width: '425px', - fontFamily: 'Avenir Next', - fontStyle: 'normal', - fontWeight: '400', - fontSize: '18px', - lineHeight: '26px', - textAlign: 'center', - }; -}); - -export const StyledButtonContent = styled('div')(() => { - return { - display: 'flex', - flexDirection: 'row', - justifyContent: 'center', - margin: '0px 0 32px 0', - }; -}); diff --git a/apps/web/src/components/affine/workspace-setting-detail/panel/general/style.ts b/apps/web/src/components/affine/workspace-setting-detail/panel/general/style.ts deleted file mode 100644 index afa38a62b3..0000000000 --- a/apps/web/src/components/affine/workspace-setting-detail/panel/general/style.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { displayFlex, styled } from '@affine/component'; -import { Input } from '@affine/component'; - -export const StyledInput = Input; - -export const StyledWorkspaceInfo = styled('div')(() => { - return { - ...displayFlex('flex-start', 'center'), - fontSize: '20px', - span: { - fontSize: 'var(--affine-font-base)', - marginLeft: '15px', - }, - }; -}); - -export const StyledAvatar = styled('div')( - ({ disabled }: { disabled: boolean }) => { - return { - position: 'relative', - marginRight: '20px', - cursor: disabled ? 'default' : 'pointer', - ':hover': { - '.camera-icon': { - display: 'flex', - }, - }, - '.camera-icon': { - position: 'absolute', - top: 0, - left: 0, - display: 'none', - width: '100%', - height: '100%', - borderRadius: '50%', - backgroundColor: 'rgba(60, 61, 63, 0.5)', - justifyContent: 'center', - alignItems: 'center', - zIndex: 10, - }, - }; - } -); - -export const StyledEditButton = styled('div')(() => { - return { - color: 'var(--affine-primary-color)', - cursor: 'pointer', - marginLeft: '36px', - }; -}); diff --git a/apps/web/src/components/affine/workspace-setting-detail/panel/publish/index.tsx b/apps/web/src/components/affine/workspace-setting-detail/panel/publish/index.tsx deleted file mode 100644 index 5d166adbb8..0000000000 --- a/apps/web/src/components/affine/workspace-setting-detail/panel/publish/index.tsx +++ /dev/null @@ -1,171 +0,0 @@ -import { - Button, - Content, - FlexWrapper, - Input, - Wrapper, -} from '@affine/component'; -import { isBrowser, Unreachable } from '@affine/env/constant'; -import type { - AffineLegacyCloudWorkspace, - LocalWorkspace, -} from '@affine/env/workspace'; -import { WorkspaceFlavour } from '@affine/env/workspace'; -import { useAFFiNEI18N } from '@affine/i18n/hooks'; -import { Box } from '@mui/material'; -import type React from 'react'; -import { useCallback, useEffect, useState } from 'react'; - -import { useToggleWorkspacePublish } from '../../../../../hooks/affine/use-toggle-workspace-publish'; -import type { AffineOfficialWorkspace } from '../../../../../shared'; -import { toast } from '../../../../../utils'; -import { EnableAffineCloudModal } from '../../../enable-affine-cloud-modal'; -import { TmpDisableAffineCloudModal } from '../../../tmp-disable-affine-cloud-modal'; -import type { WorkspaceSettingDetailProps } from '../../index'; - -export type PublishPanelProps = WorkspaceSettingDetailProps & { - workspace: AffineOfficialWorkspace; -}; - -export type PublishPanelAffineProps = WorkspaceSettingDetailProps & { - workspace: AffineLegacyCloudWorkspace; -}; - -const PublishPanelAffine: React.FC = ({ - workspace, -}) => { - const [origin, setOrigin] = useState(''); - useEffect(() => { - setOrigin( - isBrowser && window.location.origin ? window.location.origin : '' - ); - }, []); - const shareUrl = origin + '/public-workspace/' + workspace.id; - const t = useAFFiNEI18N(); - const publishWorkspace = useToggleWorkspacePublish(workspace); - const copyUrl = useCallback(async () => { - await navigator.clipboard.writeText(shareUrl); - toast(t['Copied link to clipboard']()); - }, [shareUrl, t]); - - if (workspace.public) { - return ( - <> - {t['Published Description']()} - - - {t['Share with link']()} - - - - - - - - ); - } - return ( - <> - {t['Publishing Description']()} - - - ); -}; - -export type PublishPanelLocalProps = WorkspaceSettingDetailProps & { - workspace: LocalWorkspace; -}; - -const PublishPanelLocal: React.FC = ({ - workspace, - onTransferWorkspace, -}) => { - const t = useAFFiNEI18N(); - const [open, setOpen] = useState(false); - return ( - <> - - {t['Publishing']()} - - {/* TmpDisableAffineCloudModal */} - - - {runtimeConfig.enableLegacyCloud ? ( - { - setOpen(false); - }} - onConfirm={() => { - onTransferWorkspace( - WorkspaceFlavour.LOCAL, - WorkspaceFlavour.AFFINE, - workspace - ); - setOpen(false); - }} - /> - ) : ( - { - setOpen(false); - }} - /> - )} - - ); -}; - -export const PublishPanel: React.FC = props => { - if (props.workspace.flavour === WorkspaceFlavour.AFFINE) { - return ; - } else if (props.workspace.flavour === WorkspaceFlavour.LOCAL) { - return ; - } - throw new Unreachable(); -}; diff --git a/apps/web/src/components/affine/workspace-setting-detail/panel/sync/index.tsx b/apps/web/src/components/affine/workspace-setting-detail/panel/sync/index.tsx deleted file mode 100644 index 6a6d1047de..0000000000 --- a/apps/web/src/components/affine/workspace-setting-detail/panel/sync/index.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { Content, FlexWrapper, styled } from '@affine/component'; -import { WorkspaceFlavour } from '@affine/env/workspace'; -import { Trans } from '@affine/i18n'; -import { useAFFiNEI18N } from '@affine/i18n/hooks'; -import { useBlockSuiteWorkspaceAvatarUrl } from '@toeverything/hooks/use-block-suite-workspace-avatar-url'; -import { useBlockSuiteWorkspaceName } from '@toeverything/hooks/use-block-suite-workspace-name'; -import type React from 'react'; - -import { useCurrentUser } from '../../../../../hooks/current/use-current-user'; -import { WorkspaceAvatar } from '../../../../pure/footer'; -import type { PanelProps } from '../../index'; - -export const StyledWorkspaceName = styled('span')(() => { - return { - fontWeight: '400', - fontSize: 'var(--affine-font-h6)', - }; -}); - -export const SyncPanel: React.FC = ({ workspace }) => { - if (workspace.flavour !== WorkspaceFlavour.AFFINE) { - throw new TypeError('SyncPanel can only be used with Affine workspace'); - } - const [name] = useBlockSuiteWorkspaceName(workspace.blockSuiteWorkspace); - const [avatar] = useBlockSuiteWorkspaceAvatarUrl( - workspace.blockSuiteWorkspace - ); - const user = useCurrentUser(); - const t = useAFFiNEI18N(); - return ( - <> - - - {name} -   - {t['is a Cloud Workspace']()} - - - All data will be synchronised and saved to the AFFiNE account - {{ - email: user?.email, - }} - - - ); -}; diff --git a/apps/web/src/components/blocksuite/workspace-header/header-right-items/share-menu.tsx b/apps/web/src/components/blocksuite/workspace-header/header-right-items/share-menu.tsx index fea30809b5..62ee97a365 100644 --- a/apps/web/src/components/blocksuite/workspace-header/header-right-items/share-menu.tsx +++ b/apps/web/src/components/blocksuite/workspace-header/header-right-items/share-menu.tsx @@ -1,7 +1,7 @@ import { ShareMenu } from '@affine/component/share-menu'; import { Unreachable } from '@affine/env/constant'; import type { - AffineLegacyCloudWorkspace, + AffineCloudWorkspace, LocalWorkspace, } from '@affine/env/workspace'; import { WorkspaceFlavour, WorkspaceSubPath } from '@affine/env/workspace'; @@ -11,21 +11,20 @@ import { useRouter } from 'next/router'; import type React from 'react'; import { useCallback, useState } from 'react'; -import { useToggleWorkspacePublish } from '../../../../hooks/affine/use-toggle-workspace-publish'; import { useOnTransformWorkspace } from '../../../../hooks/root/use-on-transform-workspace'; import { useRouterHelper } from '../../../../hooks/use-router-helper'; import { TransformWorkspaceToAffineModal } from '../../../affine/transform-workspace-to-affine-modal'; import type { BaseHeaderProps } from '../header'; const AffineHeaderShareMenu: React.FC = props => { - // todo: these hooks should be moved to the top level - const togglePublish = useToggleWorkspacePublish( - props.workspace as AffineLegacyCloudWorkspace - ); + // fixme: cloud regression + // const togglePublish = useToggleWorkspacePublish( + // props.workspace as AffineCloudWorkspace + // ); const helper = useRouterHelper(useRouter()); return ( { throw new Unreachable( @@ -42,12 +41,12 @@ const AffineHeaderShareMenu: React.FC = props => { page.workspace.setPageMeta(page.id, { isPublic }); }, [])} toggleWorkspacePublish={useCallback( - async (workspace, publish) => { - assertEquals(workspace.flavour, WorkspaceFlavour.AFFINE); + async workspace => { + assertEquals(workspace.flavour, WorkspaceFlavour.AFFINE_CLOUD); assertEquals(workspace.id, props.workspace.id); - await togglePublish(publish); + throw new Error('unreachable'); }, - [props.workspace.id, togglePublish] + [props.workspace.id] )} /> ); @@ -98,7 +97,7 @@ const LocalHeaderShareMenu: React.FC = props => { onConform={async () => { await onTransformWorkspace( WorkspaceFlavour.LOCAL, - WorkspaceFlavour.AFFINE, + WorkspaceFlavour.AFFINE_CLOUD, props.workspace as LocalWorkspace ); setOpen(false); @@ -112,7 +111,7 @@ export const HeaderShareMenu: React.FC = props => { if (!runtimeConfig.enableLegacyCloud) { return null; } - if (props.workspace.flavour === WorkspaceFlavour.AFFINE) { + if (props.workspace.flavour === WorkspaceFlavour.AFFINE_CLOUD) { return ; } else if (props.workspace.flavour === WorkspaceFlavour.LOCAL) { return ; diff --git a/apps/web/src/components/blocksuite/workspace-header/header-right-items/sync-user.tsx b/apps/web/src/components/blocksuite/workspace-header/header-right-items/sync-user.tsx deleted file mode 100644 index ab32a87141..0000000000 --- a/apps/web/src/components/blocksuite/workspace-header/header-right-items/sync-user.tsx +++ /dev/null @@ -1,163 +0,0 @@ -import { displayFlex, IconButton, styled, Tooltip } from '@affine/component'; -import type { LocalWorkspace } from '@affine/env/workspace'; -import { WorkspaceFlavour } from '@affine/env/workspace'; -import { useAFFiNEI18N } from '@affine/i18n/hooks'; -import { - getLoginStorage, - setLoginStorage, - SignMethod, -} from '@affine/workspace/affine/login'; -import { affineAuth } from '@affine/workspace/affine/shared'; -import { - CloudWorkspaceIcon, - LocalWorkspaceIcon, - NoNetworkIcon, -} from '@blocksuite/icons'; -import { assertEquals, assertExists } from '@blocksuite/store'; -import { useRouter } from 'next/router'; -import React, { useEffect, useState } from 'react'; - -import { useCurrentWorkspace } from '../../../../hooks/current/use-current-workspace'; -import { useTransformWorkspace } from '../../../../hooks/use-transform-workspace'; -import type { AffineOfficialWorkspace } from '../../../../shared'; -import { TransformWorkspaceToAffineModal } from '../../../affine/transform-workspace-to-affine-modal'; - -const IconWrapper = styled('div')(() => { - return { - width: '32px', - height: '32px', - marginRight: '12px', - fontSize: '24px', - color: 'var(--affine-icon-color)', - WebkitAppRegion: 'no-drag', - ...displayFlex('center', 'center'), - }; -}); - -const getStatus = (workspace: AffineOfficialWorkspace) => { - if (!navigator.onLine) { - return 'offline'; - } - if (workspace.flavour === 'local') { - return 'local'; - } - return 'cloud'; -}; - -export const SyncUser = () => { - //#region fixme(himself65): remove these hooks ASAP - const [workspace] = useCurrentWorkspace(); - assertExists(workspace); - const router = useRouter(); - - const [status, setStatus] = useState<'offline' | 'local' | 'cloud'>( - getStatus(workspace) - ); - const [prevWorkspace, setPrevWorkspace] = useState(workspace); - if (prevWorkspace !== workspace) { - setPrevWorkspace(workspace); - setStatus(getStatus(workspace)); - } - - useEffect(() => { - const online = () => { - setStatus(getStatus(workspace)); - }; - - const offline = () => { - setStatus('offline'); - }; - window.addEventListener('online', online); - window.addEventListener('offline', offline); - return () => { - window.removeEventListener('online', online); - window.removeEventListener('offline', offline); - }; - }, [workspace]); - //#endregion - - const [open, setOpen] = useState(false); - - const t = useAFFiNEI18N(); - const transformWorkspace = useTransformWorkspace(); - - if (!runtimeConfig.enableLegacyCloud) { - return null; - } - - if (status === 'offline') { - return ( - - - - - - ); - } - - if (status === 'local') { - return ( - <> - - { - setOpen(true); - }} - style={{ marginRight: '12px' }} - > - - - - { - setOpen(false); - }} - onConform={async () => { - if (!getLoginStorage()) { - const response = await affineAuth.generateToken( - SignMethod.Google - ); - if (response) { - setLoginStorage(response); - } - router.reload(); - return; - } - assertEquals(workspace.flavour, WorkspaceFlavour.LOCAL); - const id = await transformWorkspace( - WorkspaceFlavour.LOCAL, - WorkspaceFlavour.AFFINE, - workspace as LocalWorkspace - ); - // fixme(himself65): refactor this - await router.replace({ - pathname: `/workspace/[workspaceId]/all`, - query: { - workspaceId: id, - }, - }); - setOpen(false); - router.reload(); - }} - /> - - ); - } - - return ( - - - - - - ); -}; - -export default SyncUser; diff --git a/apps/web/src/components/blocksuite/workspace-header/header-right-items/user-avatar.tsx b/apps/web/src/components/blocksuite/workspace-header/header-right-items/user-avatar.tsx index c0b90b993c..71d05778cd 100644 --- a/apps/web/src/components/blocksuite/workspace-header/header-right-items/user-avatar.tsx +++ b/apps/web/src/components/blocksuite/workspace-header/header-right-items/user-avatar.tsx @@ -3,7 +3,6 @@ import { AffineLogoSBlue2_1Icon, SignOutIcon } from '@blocksuite/icons'; import type { CSSProperties } from 'react'; import { forwardRef } from 'react'; -import { useCurrentUser } from '../../../../hooks/current/use-current-user'; const EditMenu = ( }> Sign Out @@ -11,7 +10,8 @@ const EditMenu = ( ); export const UserAvatar = () => { - const user = useCurrentUser(); + // fixme: cloud regression + const user: any = null; return ( = { return currentPage?.meta.trash === true; }, }, - [HeaderRightItemName.SyncUser]: { - Component: SyncUser, - availableWhen: (_, currentPage, { isPublic }) => { - return !isPublic; - }, - }, [HeaderRightItemName.ShareMenu]: { Component: HeaderShareMenu, availableWhen: (workspace, currentPage) => { diff --git a/apps/web/src/components/pure/footer/index.tsx b/apps/web/src/components/pure/footer/index.tsx index 571abeb961..c24f59bb12 100644 --- a/apps/web/src/components/pure/footer/index.tsx +++ b/apps/web/src/components/pure/footer/index.tsx @@ -1,76 +1,34 @@ -import { FlexWrapper } from '@affine/component'; -import { IconButton } from '@affine/component'; -import { Tooltip } from '@affine/component'; import { useAFFiNEI18N } from '@affine/i18n/hooks'; -import type { AccessTokenMessage } from '@affine/workspace/affine/login'; -import { CloudWorkspaceIcon, SignOutIcon } from '@blocksuite/icons'; +import { CloudWorkspaceIcon } from '@blocksuite/icons'; import { useSetAtom } from 'jotai'; -import type { CSSProperties } from 'react'; -import type React from 'react'; -import { forwardRef } from 'react'; +import { type CSSProperties, type FC, forwardRef } from 'react'; import { openDisableCloudAlertModalAtom } from '../../../atoms'; import { stringToColour } from '../../../utils'; -import { StyledFooter, StyledSignInButton, StyleUserInfo } from './styles'; +import { StyledFooter, StyledSignInButton } from './styles'; -export type FooterProps = { - user: AccessTokenMessage | null; - onLogin: () => void; - onLogout: () => void; -}; - -export const Footer: React.FC = ({ user, onLogin, onLogout }) => { +export const Footer: FC = () => { const t = useAFFiNEI18N(); const setOpen = useSetAtom(openDisableCloudAlertModalAtom); return ( - {user && ( - <> - - - -

{user.name}

-

{user.email}

-
-
- - { - onLogout(); - }} - > - - - - - )} - - {!user && ( - - -
+ + +
+ } + onClick={async () => { + if (!runtimeConfig.enableLegacyCloud) { + setOpen(true); } - onClick={async () => { - if (!runtimeConfig.enableLegacyCloud) { - setOpen(true); - } else { - onLogin(); - } - }} - > - {t['Sign in']()} - - )} + }} + > + {t['Sign in']()} + ); }; diff --git a/apps/web/src/components/pure/message-center/index.tsx b/apps/web/src/components/pure/message-center/index.tsx deleted file mode 100644 index 5e74a990ef..0000000000 --- a/apps/web/src/components/pure/message-center/index.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { MessageCode, Messages } from '@affine/env/constant'; -import { setLoginStorage, SignMethod } from '@affine/workspace/affine/login'; -import { affineAuth } from '@affine/workspace/affine/shared'; -import type { FC } from 'react'; -import { memo, useEffect, useState } from 'react'; - -import { useAffineLogOut } from '../../../hooks/affine/use-affine-log-out'; -import { toast } from '../../../utils'; - -declare global { - interface DocumentEventMap { - 'affine-error': CustomEvent<{ - code: keyof typeof Messages; - }>; - } -} - -export const MessageCenter: FC = memo(function MessageCenter() { - const [popup, setPopup] = useState(false); - const onLogout = useAffineLogOut(); - useEffect(() => { - const listener = ( - event: CustomEvent<{ - code: keyof typeof Messages; - }> - ) => { - // fixme: need refactor - // - login and refresh refresh logic should be refactored - // - error message should be refactored - if ( - !popup && - (event.detail.code === MessageCode.refreshTokenError || - event.detail.code === MessageCode.loginError) - ) { - setPopup(true); - affineAuth - .generateToken(SignMethod.Google) - .then(response => { - if (response) { - setLoginStorage(response); - } - setPopup(false); - }) - .catch(() => { - setPopup(false); - return onLogout(); - }); - } else { - toast(Messages[event.detail.code].message); - } - }; - - document.addEventListener('affine-error', listener); - return () => { - document.removeEventListener('affine-error', listener); - }; - }, [onLogout, popup]); - return null; -}); diff --git a/apps/web/src/components/pure/workspace-list-modal/index.tsx b/apps/web/src/components/pure/workspace-list-modal/index.tsx index 7433ffa369..e172a84a8e 100644 --- a/apps/web/src/components/pure/workspace-list-modal/index.tsx +++ b/apps/web/src/components/pure/workspace-list-modal/index.tsx @@ -9,12 +9,11 @@ import { import { ScrollableContainer } from '@affine/component'; import { WorkspaceList } from '@affine/component/workspace-list'; import type { - AffineLegacyCloudWorkspace, + AffineCloudWorkspace, LocalWorkspace, } from '@affine/env/workspace'; import { WorkspaceFlavour } from '@affine/env/workspace'; import { useAFFiNEI18N } from '@affine/i18n/hooks'; -import type { AccessTokenMessage } from '@affine/workspace/affine/login'; import { HelpIcon, ImportIcon, PlusIcon } from '@blocksuite/icons'; import type { DragEndEvent } from '@dnd-kit/core'; import { useCallback, useRef } from 'react'; @@ -41,15 +40,12 @@ import { interface WorkspaceModalProps { disabled?: boolean; - user: AccessTokenMessage | null; workspaces: AllWorkspace[]; currentWorkspaceId: AllWorkspace['id'] | null; open: boolean; onClose: () => void; onClickWorkspace: (workspace: AllWorkspace) => void; onClickWorkspaceSetting: (workspace: AllWorkspace) => void; - onClickLogin: () => void; - onClickLogout: () => void; onNewWorkspace: () => void; onAddWorkspace: () => void; onMoveWorkspace: (activeId: string, overId: string) => void; @@ -161,9 +157,6 @@ export const WorkspaceListModal = ({ open, onClose, workspaces, - user, - onClickLogin, - onClickLogout, onClickWorkspace, onClickWorkspaceSetting, onNewWorkspace, @@ -213,7 +206,7 @@ export const WorkspaceListModal = ({ items={ workspaces.filter( ({ flavour }) => flavour !== WorkspaceFlavour.PUBLIC - ) as (AffineLegacyCloudWorkspace | LocalWorkspace)[] + ) as (AffineCloudWorkspace | LocalWorkspace)[] } currentWorkspaceId={currentWorkspaceId} onClick={onClickWorkspace} @@ -234,7 +227,7 @@ export const WorkspaceListModal = ({ /> -