mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 12:28:42 +00:00
feat: add affine global channel (#1762)
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
import type { WorkspaceFlavour } from '@affine/workspace/type';
|
||||
import { jotaiStore, jotaiWorkspacesAtom } from '@affine/workspace/atom';
|
||||
import type { EditorContainer } from '@blocksuite/editor';
|
||||
import type { Page } from '@blocksuite/store';
|
||||
import { assertExists } from '@blocksuite/store';
|
||||
import { atom, createStore } from 'jotai';
|
||||
import { atom } from 'jotai';
|
||||
import { atomWithStorage } from 'jotai/utils';
|
||||
import { unstable_batchedUpdates } from 'react-dom';
|
||||
|
||||
import { WorkspacePlugins } from '../plugins';
|
||||
import type { RemWorkspace } from '../shared';
|
||||
import type { AllWorkspace } from '../shared';
|
||||
// workspace necessary atoms
|
||||
export const currentWorkspaceIdAtom = atom<string | null>(null);
|
||||
export const currentPageIdAtom = atom<string | null>(null);
|
||||
@@ -34,19 +34,7 @@ export const openWorkspacesModalAtom = atom(false);
|
||||
export const openCreateWorkspaceModalAtom = atom(false);
|
||||
export const openQuickSearchModalAtom = atom(false);
|
||||
|
||||
export const jotaiStore = createStore();
|
||||
|
||||
type JotaiWorkspace = {
|
||||
id: string;
|
||||
flavour: WorkspaceFlavour;
|
||||
};
|
||||
|
||||
export const jotaiWorkspacesAtom = atomWithStorage<JotaiWorkspace[]>(
|
||||
'jotai-workspaces',
|
||||
[]
|
||||
);
|
||||
|
||||
export const workspacesAtom = atom<Promise<RemWorkspace[]>>(async get => {
|
||||
export const workspacesAtom = atom<Promise<AllWorkspace[]>>(async get => {
|
||||
const flavours: string[] = Object.values(WorkspacePlugins).map(
|
||||
plugin => plugin.flavour
|
||||
);
|
||||
@@ -62,7 +50,7 @@ export const workspacesAtom = atom<Promise<RemWorkspace[]>>(async get => {
|
||||
return CRUD.get(workspace.id);
|
||||
})
|
||||
);
|
||||
return workspaces.filter(workspace => workspace !== null) as RemWorkspace[];
|
||||
return workspaces.filter(workspace => workspace !== null) as AllWorkspace[];
|
||||
});
|
||||
|
||||
type View = { id: string; mode: 'page' | 'edgeless' };
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { config } from '@affine/env';
|
||||
import type { Provider } from '@affine/workspace/type';
|
||||
|
||||
import type { BlockSuiteWorkspace, Provider } from '../shared';
|
||||
import type { BlockSuiteWorkspace } from '../shared';
|
||||
import {
|
||||
createAffineWebSocketProvider,
|
||||
createBroadCastChannelProvider,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { AffineDownloadProvider } from '@affine/workspace/type';
|
||||
import { assertExists } from '@blocksuite/store';
|
||||
|
||||
import type { AffineDownloadProvider } from '../../../shared';
|
||||
import { BlockSuiteWorkspace } from '../../../shared';
|
||||
import { affineApis } from '../../../shared/apis';
|
||||
import { providerLogger } from '../../logger';
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { BroadCastChannelProvider } from '@affine/workspace/type';
|
||||
import { assertExists } from '@blocksuite/store';
|
||||
import type { Awareness } from 'y-protocols/awareness';
|
||||
import {
|
||||
@@ -5,7 +6,6 @@ import {
|
||||
encodeAwarenessUpdate,
|
||||
} from 'y-protocols/awareness';
|
||||
|
||||
import type { BroadCastChannelProvider } from '../../../shared';
|
||||
import { BlockSuiteWorkspace } from '../../../shared';
|
||||
import { providerLogger } from '../../logger';
|
||||
import type {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { KeckProvider } from '@affine/workspace/affine/keck';
|
||||
import { getLoginStorage } from '@affine/workspace/affine/login';
|
||||
import type {
|
||||
AffineWebSocketProvider,
|
||||
LocalIndexedDBProvider,
|
||||
} from '@affine/workspace/type';
|
||||
import { assertExists } from '@blocksuite/store';
|
||||
import { IndexeddbPersistence } from 'y-indexeddb';
|
||||
|
||||
import type {
|
||||
AffineWebSocketProvider,
|
||||
BlockSuiteWorkspace,
|
||||
LocalIndexedDBProvider,
|
||||
} from '../../shared';
|
||||
import type { BlockSuiteWorkspace } from '../../shared';
|
||||
import { providerLogger } from '../logger';
|
||||
import { createBroadCastChannelProvider } from './broad-cast-channel';
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Button, IconButton, Menu, MenuItem, Wrapper } from '@affine/component';
|
||||
import { useTranslation } from '@affine/i18n';
|
||||
import { PermissionType } from '@affine/workspace/affine/api';
|
||||
import type { AffineWorkspace, LocalWorkspace } from '@affine/workspace/type';
|
||||
import { WorkspaceFlavour } from '@affine/workspace/type';
|
||||
import {
|
||||
DeleteTemporarilyIcon,
|
||||
@@ -11,7 +12,6 @@ import type React from 'react';
|
||||
import { useCallback, useState } from 'react';
|
||||
|
||||
import { useMembers } from '../../../../../hooks/affine/use-members';
|
||||
import type { AffineWorkspace, LocalWorkspace } from '../../../../../shared';
|
||||
import { toast } from '../../../../../utils';
|
||||
import { Unreachable } from '../../../affine-error-eoundary';
|
||||
import { TransformWorkspaceToAffineModal } from '../../../transform-workspace-to-affine-modal';
|
||||
|
||||
@@ -6,17 +6,14 @@ import {
|
||||
Wrapper,
|
||||
} from '@affine/component';
|
||||
import { useTranslation } from '@affine/i18n';
|
||||
import type { AffineWorkspace, LocalWorkspace } from '@affine/workspace/type';
|
||||
import { WorkspaceFlavour } from '@affine/workspace/type';
|
||||
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,
|
||||
AffineWorkspace,
|
||||
LocalWorkspace,
|
||||
} from '../../../../../shared';
|
||||
import type { AffineOfficialWorkspace } from '../../../../../shared';
|
||||
import { toast } from '../../../../../utils';
|
||||
import { Unreachable } from '../../../affine-error-eoundary';
|
||||
import { EnableAffineCloudModal } from '../../../enable-affine-cloud-modal';
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
setLoginStorage,
|
||||
SignMethod,
|
||||
} from '@affine/workspace/affine/login';
|
||||
import type { LocalWorkspace } from '@affine/workspace/type';
|
||||
import { WorkspaceFlavour } from '@affine/workspace/type';
|
||||
import {
|
||||
CloudWorkspaceIcon,
|
||||
@@ -18,10 +19,7 @@ import React, { useEffect, useState } from 'react';
|
||||
import { affineAuth } from '../../../../hooks/affine/use-affine-log-in';
|
||||
import { useCurrentWorkspace } from '../../../../hooks/current/use-current-workspace';
|
||||
import { useTransformWorkspace } from '../../../../hooks/use-transform-workspace';
|
||||
import type {
|
||||
AffineOfficialWorkspace,
|
||||
LocalWorkspace,
|
||||
} from '../../../../shared';
|
||||
import type { AffineOfficialWorkspace } from '../../../../shared';
|
||||
import { TransformWorkspaceToAffineModal } from '../../../affine/transform-workspace-to-affine-modal';
|
||||
|
||||
const IconWrapper = styled('div')(({ theme }) => {
|
||||
|
||||
@@ -3,7 +3,7 @@ import type React from 'react';
|
||||
import { memo } from 'react';
|
||||
|
||||
import { useBlockSuiteWorkspaceAvatarUrl } from '../../../hooks/use-blocksuite-workspace-avatar-url';
|
||||
import type { BlockSuiteWorkspace, RemWorkspace } from '../../../shared';
|
||||
import type { AllWorkspace, BlockSuiteWorkspace } from '../../../shared';
|
||||
import { stringToColour } from '../../../utils';
|
||||
|
||||
interface AvatarProps {
|
||||
@@ -75,7 +75,7 @@ export const Avatar: React.FC<AvatarProps> = memo<AvatarProps>(function Avatar({
|
||||
|
||||
export type WorkspaceUnitAvatarProps = {
|
||||
size?: number;
|
||||
workspace: RemWorkspace | null;
|
||||
workspace: AllWorkspace | null;
|
||||
style?: React.CSSProperties;
|
||||
};
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import type React from 'react';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { useBlockSuiteWorkspaceName } from '../../../hooks/use-blocksuite-workspace-name';
|
||||
import type { RemWorkspace } from '../../../shared';
|
||||
import type { AllWorkspace } from '../../../shared';
|
||||
import {
|
||||
CloudWorkspaceIcon,
|
||||
JoinedWorkspaceIcon,
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
StyleWorkspaceTitle,
|
||||
} from './styles';
|
||||
export type WorkspaceTypeProps = {
|
||||
workspace: RemWorkspace;
|
||||
workspace: AllWorkspace;
|
||||
};
|
||||
|
||||
const WorkspaceType: React.FC<WorkspaceTypeProps> = ({ workspace }) => {
|
||||
@@ -58,9 +58,9 @@ const WorkspaceType: React.FC<WorkspaceTypeProps> = ({ workspace }) => {
|
||||
|
||||
export type WorkspaceCardProps = {
|
||||
currentWorkspaceId: string | null;
|
||||
workspace: RemWorkspace;
|
||||
onClick: (workspace: RemWorkspace) => void;
|
||||
onSettingClick: (workspace: RemWorkspace) => void;
|
||||
workspace: AllWorkspace;
|
||||
onClick: (workspace: AllWorkspace) => void;
|
||||
onSettingClick: (workspace: AllWorkspace) => void;
|
||||
};
|
||||
|
||||
export const WorkspaceCard: React.FC<WorkspaceCardProps> = ({
|
||||
|
||||
@@ -8,7 +8,7 @@ import { useTranslation } from '@affine/i18n';
|
||||
import type { AccessTokenMessage } from '@affine/workspace/affine/login';
|
||||
import { HelpIcon, PlusIcon } from '@blocksuite/icons';
|
||||
|
||||
import type { RemWorkspace } from '../../../shared';
|
||||
import type { AllWorkspace } from '../../../shared';
|
||||
import { Footer } from '../footer';
|
||||
import { WorkspaceCard } from '../workspace-card';
|
||||
import { LanguageMenu } from './language-menu';
|
||||
@@ -28,12 +28,12 @@ import {
|
||||
|
||||
interface WorkspaceModalProps {
|
||||
user: AccessTokenMessage | null;
|
||||
workspaces: RemWorkspace[];
|
||||
currentWorkspaceId: RemWorkspace['id'] | null;
|
||||
workspaces: AllWorkspace[];
|
||||
currentWorkspaceId: AllWorkspace['id'] | null;
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
onClickWorkspace: (workspace: RemWorkspace) => void;
|
||||
onClickWorkspaceSetting: (workspace: RemWorkspace) => void;
|
||||
onClickWorkspace: (workspace: AllWorkspace) => void;
|
||||
onClickWorkspaceSetting: (workspace: AllWorkspace) => void;
|
||||
onClickLogin: () => void;
|
||||
onClickLogout: () => void;
|
||||
onCreateWorkspace: () => void;
|
||||
|
||||
@@ -5,7 +5,7 @@ import type { PageMeta } from '@blocksuite/store';
|
||||
import type { MouseEvent } from 'react';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
|
||||
import type { RemWorkspace } from '../../../shared';
|
||||
import type { AllWorkspace } from '../../../shared';
|
||||
import type { TreeNode } from '../../affine/pivots';
|
||||
import {
|
||||
PivotRender,
|
||||
@@ -20,7 +20,7 @@ export const PivotInternal = ({
|
||||
openPage,
|
||||
allMetas,
|
||||
}: {
|
||||
currentWorkspace: RemWorkspace;
|
||||
currentWorkspace: AllWorkspace;
|
||||
openPage: (pageId: string) => void;
|
||||
allMetas: PageMeta[];
|
||||
}) => {
|
||||
@@ -68,7 +68,7 @@ export const Pivots = ({
|
||||
openPage,
|
||||
allMetas,
|
||||
}: {
|
||||
currentWorkspace: RemWorkspace;
|
||||
currentWorkspace: AllWorkspace;
|
||||
openPage: (pageId: string) => void;
|
||||
allMetas: PageMeta[];
|
||||
}) => {
|
||||
|
||||
@@ -3,7 +3,7 @@ import type React from 'react';
|
||||
|
||||
import { useCurrentWorkspace } from '../../../../hooks/current/use-current-workspace';
|
||||
import { useBlockSuiteWorkspaceName } from '../../../../hooks/use-blocksuite-workspace-name';
|
||||
import type { RemWorkspace } from '../../../../shared';
|
||||
import type { AllWorkspace } from '../../../../shared';
|
||||
import { WorkspaceAvatar } from '../../workspace-avatar';
|
||||
import {
|
||||
StyledSelectorContainer,
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
} from './styles';
|
||||
|
||||
export type WorkspaceSelectorProps = {
|
||||
currentWorkspace: RemWorkspace | null;
|
||||
currentWorkspace: AllWorkspace | null;
|
||||
onClick: () => void;
|
||||
};
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import { useCallback } from 'react';
|
||||
|
||||
import { useSidebarStatus } from '../../../hooks/affine/use-sidebar-status';
|
||||
import { usePageMeta } from '../../../hooks/use-page-meta';
|
||||
import type { RemWorkspace } from '../../../shared';
|
||||
import type { AllWorkspace } from '../../../shared';
|
||||
import { SidebarSwitch } from '../../affine/sidebar-switch';
|
||||
import { ChangeLog } from './changeLog';
|
||||
import Favorite from './favorite';
|
||||
@@ -39,7 +39,7 @@ export type WorkSpaceSliderBarProps = {
|
||||
isPublicWorkspace: boolean;
|
||||
onOpenQuickSearchModal: () => void;
|
||||
onOpenWorkspaceListModal: () => void;
|
||||
currentWorkspace: RemWorkspace | null;
|
||||
currentWorkspace: AllWorkspace | null;
|
||||
currentPageId: string | null;
|
||||
openPage: (pageId: string) => void;
|
||||
createPage: () => Page;
|
||||
|
||||
@@ -5,6 +5,8 @@ import 'fake-indexeddb/auto';
|
||||
|
||||
import assert from 'node:assert';
|
||||
|
||||
import { jotaiWorkspacesAtom } from '@affine/workspace/atom';
|
||||
import type { LocalWorkspace } from '@affine/workspace/type';
|
||||
import { WorkspaceFlavour } from '@affine/workspace/type';
|
||||
import { __unstableSchemas, AffineSchemas } from '@blocksuite/blocks/models';
|
||||
import type { Page } from '@blocksuite/store';
|
||||
@@ -17,13 +19,8 @@ import { createDynamicRouteParser } from 'next-router-mock/dynamic-routes';
|
||||
import type React from 'react';
|
||||
import { beforeAll, beforeEach, describe, expect, test, vi } from 'vitest';
|
||||
|
||||
import {
|
||||
currentWorkspaceIdAtom,
|
||||
jotaiWorkspacesAtom,
|
||||
workspacesAtom,
|
||||
} from '../../atoms';
|
||||
import { currentWorkspaceIdAtom, workspacesAtom } from '../../atoms';
|
||||
import { LocalPlugin } from '../../plugins/local';
|
||||
import type { LocalWorkspace } from '../../shared';
|
||||
import { BlockSuiteWorkspace, WorkspaceSubPath } from '../../shared';
|
||||
import {
|
||||
useGuideHidden,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { currentAffineUserAtom } from '@affine/workspace/affine/atom';
|
||||
import { clearLoginStorage } from '@affine/workspace/affine/login';
|
||||
import { jotaiWorkspacesAtom } from '@affine/workspace/atom';
|
||||
import { WorkspaceFlavour } from '@affine/workspace/type';
|
||||
import { useSetAtom } from 'jotai';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { jotaiWorkspacesAtom } from '../../atoms';
|
||||
import { WorkspacePlugins } from '../../plugins';
|
||||
|
||||
export function useAffineLogOut() {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { jotaiStore, jotaiWorkspacesAtom } from '@affine/workspace/atom';
|
||||
import type { AffineWorkspace } from '@affine/workspace/type';
|
||||
import { useCallback } from 'react';
|
||||
import useSWR from 'swr';
|
||||
|
||||
import { jotaiStore, jotaiWorkspacesAtom } from '../../atoms';
|
||||
import { QueryKey } from '../../plugins/affine/fetcher';
|
||||
import type { AffineWorkspace } from '../../shared';
|
||||
import { affineApis } from '../../shared/apis';
|
||||
|
||||
export function useToggleWorkspacePublish(workspace: AffineWorkspace) {
|
||||
|
||||
@@ -7,9 +7,9 @@ import {
|
||||
currentWorkspaceIdAtom,
|
||||
workspacesAtom,
|
||||
} from '../../atoms';
|
||||
import type { RemWorkspace } from '../../shared';
|
||||
import type { AllWorkspace } from '../../shared';
|
||||
|
||||
export const currentWorkspaceAtom = atom<Promise<RemWorkspace | null>>(
|
||||
export const currentWorkspaceAtom = atom<Promise<AllWorkspace | null>>(
|
||||
async get => {
|
||||
const id = get(currentWorkspaceIdAtom);
|
||||
const workspaces = await get(workspacesAtom);
|
||||
@@ -23,7 +23,7 @@ export const lastWorkspaceIdAtom = atomWithStorage<string | null>(
|
||||
);
|
||||
|
||||
export function useCurrentWorkspace(): [
|
||||
RemWorkspace | null,
|
||||
AllWorkspace | null,
|
||||
(id: string | null) => void
|
||||
] {
|
||||
const currentWorkspace = useAtomValue(currentWorkspaceAtom);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { DEFAULT_WORKSPACE_NAME } from '@affine/env';
|
||||
import { jotaiWorkspacesAtom } from '@affine/workspace/atom';
|
||||
import { WorkspaceFlavour } from '@affine/workspace/type';
|
||||
import { createEmptyBlockSuiteWorkspace } from '@affine/workspace/utils';
|
||||
import { assertEquals, assertExists, nanoid } from '@blocksuite/store';
|
||||
import { useAtom } from 'jotai';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { jotaiWorkspacesAtom } from '../atoms';
|
||||
import { LocalPlugin } from '../plugins/local';
|
||||
|
||||
export function useCreateFirstWorkspace() {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { jotaiStore } from '@affine/workspace/atom';
|
||||
import { WorkspaceFlavour } from '@affine/workspace/type';
|
||||
import type { NextRouter } from 'next/router';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { currentPageIdAtom, jotaiStore } from '../atoms';
|
||||
import type { RemWorkspace } from '../shared';
|
||||
import { currentPageIdAtom } from '../atoms';
|
||||
import type { AllWorkspace } from '../shared';
|
||||
import { WorkspaceSubPath } from '../shared';
|
||||
import { useCurrentPageId } from './current/use-current-page-id';
|
||||
import { useCurrentWorkspace } from './current/use-current-workspace';
|
||||
@@ -11,7 +12,7 @@ import { RouteLogic, useRouterHelper } from './use-router-helper';
|
||||
import { useWorkspaces } from './use-workspaces';
|
||||
|
||||
export function findSuitablePageId(
|
||||
workspace: RemWorkspace,
|
||||
workspace: AllWorkspace,
|
||||
targetId: string
|
||||
): string | null {
|
||||
switch (workspace.flavour) {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { jotaiWorkspacesAtom } from '@affine/workspace/atom';
|
||||
import type { WorkspaceFlavour } from '@affine/workspace/type';
|
||||
import type { WorkspaceRegistry } from '@affine/workspace/type';
|
||||
import { useSetAtom } from 'jotai';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { jotaiWorkspacesAtom } from '../atoms';
|
||||
import { WorkspacePlugins } from '../plugins';
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
import { jotaiWorkspacesAtom } from '@affine/workspace/atom';
|
||||
import type { LocalWorkspace } from '@affine/workspace/type';
|
||||
import { WorkspaceFlavour } from '@affine/workspace/type';
|
||||
import { createEmptyBlockSuiteWorkspace } from '@affine/workspace/utils';
|
||||
import { nanoid } from '@blocksuite/store';
|
||||
import { useAtomValue, useSetAtom } from 'jotai';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
|
||||
import { jotaiWorkspacesAtom, workspacesAtom } from '../atoms';
|
||||
import { workspacesAtom } from '../atoms';
|
||||
import { WorkspacePlugins } from '../plugins';
|
||||
import { LocalPlugin } from '../plugins/local';
|
||||
import type { LocalWorkspace, RemWorkspace } from '../shared';
|
||||
import type { AllWorkspace } from '../shared';
|
||||
|
||||
export function useWorkspaces(): RemWorkspace[] {
|
||||
export function useWorkspaces(): AllWorkspace[] {
|
||||
return useAtomValue(workspacesAtom);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { DebugLogger } from '@affine/debug';
|
||||
import { setUpLanguage, useTranslation } from '@affine/i18n';
|
||||
import { createAffineGlobalChannel } from '@affine/workspace/affine/sync';
|
||||
import { jotaiWorkspacesAtom } from '@affine/workspace/atom';
|
||||
import { WorkspaceFlavour } from '@affine/workspace/type';
|
||||
import { assertExists, nanoid } from '@blocksuite/store';
|
||||
import { NoSsr } from '@mui/material';
|
||||
import { useAtom, useAtomValue, useSetAtom } from 'jotai';
|
||||
@@ -11,7 +14,6 @@ import { Suspense, useCallback, useEffect } from 'react';
|
||||
|
||||
import {
|
||||
currentWorkspaceIdAtom,
|
||||
jotaiWorkspacesAtom,
|
||||
openQuickSearchModalAtom,
|
||||
openWorkspacesModalAtom,
|
||||
workspaceLockAtom,
|
||||
@@ -33,13 +35,13 @@ import { useRouterTitle } from '../hooks/use-router-title';
|
||||
import { useWorkspaces } from '../hooks/use-workspaces';
|
||||
import { WorkspacePlugins } from '../plugins';
|
||||
import { ModalProvider } from '../providers/ModalProvider';
|
||||
import type { RemWorkspace } from '../shared';
|
||||
import type { AllWorkspace } from '../shared';
|
||||
import { pathGenerator, publicPathGenerator } from '../shared';
|
||||
import { StyledPage, StyledToolWrapper, StyledWrapper } from './styles';
|
||||
|
||||
declare global {
|
||||
// eslint-disable-next-line no-var
|
||||
var currentWorkspace: RemWorkspace;
|
||||
var currentWorkspace: AllWorkspace;
|
||||
}
|
||||
|
||||
const QuickSearchModal = dynamic(
|
||||
@@ -89,6 +91,10 @@ export const QuickSearch: React.FC = () => {
|
||||
};
|
||||
|
||||
const logger = new DebugLogger('workspace-layout');
|
||||
|
||||
const affineGlobalChannel = createAffineGlobalChannel(
|
||||
WorkspacePlugins[WorkspaceFlavour.AFFINE].CRUD
|
||||
);
|
||||
export const WorkspaceLayout: React.FC<React.PropsWithChildren> =
|
||||
function WorkspacesSuspense({ children }) {
|
||||
const { i18n } = useTranslation();
|
||||
@@ -105,6 +111,7 @@ export const WorkspaceLayout: React.FC<React.PropsWithChildren> =
|
||||
const lists = Object.values(WorkspacePlugins)
|
||||
.sort((a, b) => a.loadPriority - b.loadPriority)
|
||||
.map(({ CRUD }) => CRUD.list);
|
||||
|
||||
async function fetch() {
|
||||
const items = [];
|
||||
for (const list of lists) {
|
||||
@@ -121,6 +128,7 @@ export const WorkspaceLayout: React.FC<React.PropsWithChildren> =
|
||||
set([...items]);
|
||||
logger.info('mount first data:', items);
|
||||
}
|
||||
|
||||
fetch();
|
||||
return () => {
|
||||
controller.abort();
|
||||
@@ -128,6 +136,19 @@ export const WorkspaceLayout: React.FC<React.PropsWithChildren> =
|
||||
};
|
||||
}, [set]);
|
||||
const currentWorkspaceId = useAtomValue(currentWorkspaceIdAtom);
|
||||
const jotaiWorkspaces = useAtomValue(jotaiWorkspacesAtom);
|
||||
|
||||
useEffect(() => {
|
||||
const flavour = jotaiWorkspaces.find(
|
||||
x => x.id === currentWorkspaceId
|
||||
)?.flavour;
|
||||
if (flavour === WorkspaceFlavour.AFFINE) {
|
||||
affineGlobalChannel.connect();
|
||||
return () => {
|
||||
affineGlobalChannel.disconnect();
|
||||
};
|
||||
}
|
||||
}, [currentWorkspaceId, jotaiWorkspaces]);
|
||||
return (
|
||||
<NoSsr>
|
||||
{/* fixme(himself65): don't re-render whole modals */}
|
||||
|
||||
@@ -2,6 +2,7 @@ import '../styles/globals.css';
|
||||
|
||||
import { config, setupGlobal } from '@affine/env';
|
||||
import { createI18n, I18nextProvider } from '@affine/i18n';
|
||||
import { jotaiStore } from '@affine/workspace/atom';
|
||||
import type { EmotionCache } from '@emotion/cache';
|
||||
import { CacheProvider } from '@emotion/react';
|
||||
import { Provider } from 'jotai';
|
||||
@@ -11,7 +12,6 @@ import { useRouter } from 'next/router';
|
||||
import type { ReactElement } from 'react';
|
||||
import React, { Suspense, useEffect, useMemo } from 'react';
|
||||
|
||||
import { jotaiStore } from '../atoms';
|
||||
import { AffineErrorBoundary } from '../components/affine/affine-error-eoundary';
|
||||
import { ProviderComposer } from '../components/provider-composer';
|
||||
import { PageLoading } from '../components/pure/loading';
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Button } from '@affine/component';
|
||||
import { DebugLogger } from '@affine/debug';
|
||||
import type { BroadCastChannelProvider } from '@affine/workspace/type';
|
||||
import { createEmptyBlockSuiteWorkspace } from '@affine/workspace/utils';
|
||||
import { nanoid } from '@blocksuite/store';
|
||||
import { Typography } from '@mui/material';
|
||||
@@ -9,7 +10,6 @@ import { useEffect, useMemo, useState } from 'react';
|
||||
import { createBroadCastChannelProvider } from '../../blocksuite/providers';
|
||||
import PageList from '../../components/blocksuite/block-suite-page-list/page-list';
|
||||
import { StyledPage, StyledWrapper } from '../../layouts/styles';
|
||||
import type { BroadCastChannelProvider } from '../../shared';
|
||||
import { toast } from '../../utils';
|
||||
|
||||
const logger = new DebugLogger('broadcast');
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useTranslation } from '@affine/i18n';
|
||||
import type { LocalIndexedDBProvider } from '@affine/workspace/type';
|
||||
import { WorkspaceFlavour } from '@affine/workspace/type';
|
||||
import { FolderIcon } from '@blocksuite/icons';
|
||||
import { assertEquals, assertExists, nanoid } from '@blocksuite/store';
|
||||
@@ -17,10 +18,7 @@ import { useRouterHelper } from '../../../hooks/use-router-helper';
|
||||
import { useSyncRouterWithCurrentWorkspace } from '../../../hooks/use-sync-router-with-current-workspace';
|
||||
import { WorkspaceLayout } from '../../../layouts';
|
||||
import { WorkspacePlugins } from '../../../plugins';
|
||||
import type {
|
||||
LocalIndexedDBProvider,
|
||||
NextPageWithLayout,
|
||||
} from '../../../shared';
|
||||
import type { NextPageWithLayout } from '../../../shared';
|
||||
|
||||
const AllPage: NextPageWithLayout = () => {
|
||||
const router = useRouter();
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { getLoginStorage } from '@affine/workspace/affine/login';
|
||||
import { jotaiStore } from '@affine/workspace/atom';
|
||||
import type { AffineWorkspace } from '@affine/workspace/type';
|
||||
import { WorkspaceFlavour } from '@affine/workspace/type';
|
||||
import { createEmptyBlockSuiteWorkspace } from '@affine/workspace/utils';
|
||||
import { assertExists } from '@blocksuite/store';
|
||||
|
||||
import { jotaiStore, workspacesAtom } from '../../atoms';
|
||||
import { workspacesAtom } from '../../atoms';
|
||||
import { createAffineProviders } from '../../blocksuite';
|
||||
import { Unreachable } from '../../components/affine/affine-error-eoundary';
|
||||
import type { AffineWorkspace } from '../../shared';
|
||||
import { affineApis } from '../../shared/apis';
|
||||
|
||||
type Query = (typeof QueryKey)[keyof typeof QueryKey];
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { getLoginStorage } from '@affine/workspace/affine/login';
|
||||
import type { AffineWorkspace } from '@affine/workspace/type';
|
||||
import { LoadPriority, WorkspaceFlavour } from '@affine/workspace/type';
|
||||
import { createEmptyBlockSuiteWorkspace } from '@affine/workspace/utils';
|
||||
import { createJSONStorage } from 'jotai/utils';
|
||||
@@ -11,7 +12,6 @@ import { PageNotFoundError } from '../../components/affine/affine-error-eoundary
|
||||
import { WorkspaceSettingDetail } from '../../components/affine/workspace-setting-detail';
|
||||
import { BlockSuitePageList } from '../../components/blocksuite/block-suite-page-list';
|
||||
import { PageDetailEditor } from '../../components/page-detail-editor';
|
||||
import type { AffineWorkspace } from '../../shared';
|
||||
import { BlockSuiteWorkspace } from '../../shared';
|
||||
import { affineApis } from '../../shared/apis';
|
||||
import { initPage } from '../../utils';
|
||||
|
||||
@@ -5,17 +5,9 @@ import type {
|
||||
} from '@affine/workspace/type';
|
||||
import { WorkspaceFlavour } from '@affine/workspace/type';
|
||||
|
||||
import type { AffineWorkspace, LocalWorkspace } from '../shared';
|
||||
import { AffinePlugin } from './affine';
|
||||
import { LocalPlugin } from './local';
|
||||
|
||||
declare module '@affine/workspace/type' {
|
||||
interface WorkspaceRegistry {
|
||||
[WorkspaceFlavour.AFFINE]: AffineWorkspace;
|
||||
[WorkspaceFlavour.LOCAL]: LocalWorkspace;
|
||||
}
|
||||
}
|
||||
|
||||
export interface WorkspacePlugin<Flavour extends WorkspaceFlavour> {
|
||||
flavour: Flavour;
|
||||
// Plugin will be loaded according to the priority
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { DEFAULT_WORKSPACE_NAME } from '@affine/env';
|
||||
import type { LocalWorkspace } from '@affine/workspace/type';
|
||||
import { LoadPriority, WorkspaceFlavour } from '@affine/workspace/type';
|
||||
import { createEmptyBlockSuiteWorkspace } from '@affine/workspace/utils';
|
||||
import { nanoid } from '@blocksuite/store';
|
||||
@@ -12,9 +13,8 @@ import { PageNotFoundError } from '../../components/affine/affine-error-eoundary
|
||||
import { WorkspaceSettingDetail } from '../../components/affine/workspace-setting-detail';
|
||||
import { BlockSuitePageList } from '../../components/blocksuite/block-suite-page-list';
|
||||
import { PageDetailEditor } from '../../components/page-detail-editor';
|
||||
import type { LocalWorkspace } from '../../shared';
|
||||
import { BlockSuiteWorkspace } from '../../shared';
|
||||
import { initPage } from '../../utils/blocksuite';
|
||||
import { initPage } from '../../utils';
|
||||
import type { WorkspacePlugin } from '..';
|
||||
|
||||
const getStorage = () => createJSONStorage(() => localStorage);
|
||||
|
||||
@@ -6,8 +6,8 @@ import {
|
||||
import { currentAffineUserAtom } from '@affine/workspace/affine/atom';
|
||||
import type { LoginResponse } from '@affine/workspace/affine/login';
|
||||
import { parseIdToken, setLoginStorage } from '@affine/workspace/affine/login';
|
||||
import { jotaiStore } from '@affine/workspace/atom';
|
||||
|
||||
import { jotaiStore } from '../atoms';
|
||||
import { isValidIPAddress } from '../utils';
|
||||
|
||||
let prefixUrl = '/';
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import type { Workspace as RemoteWorkspace } from '@affine/workspace/affine/api';
|
||||
import type { WorkspaceFlavour } from '@affine/workspace/type';
|
||||
import type { AffineWorkspace, LocalWorkspace } from '@affine/workspace/type';
|
||||
import { Workspace as BlockSuiteWorkspace } from '@blocksuite/store';
|
||||
import type { NextPage } from 'next';
|
||||
import type { ReactElement, ReactNode } from 'react';
|
||||
@@ -12,59 +11,9 @@ declare global {
|
||||
}
|
||||
}
|
||||
|
||||
export interface AffineWorkspace extends RemoteWorkspace {
|
||||
flavour: WorkspaceFlavour.AFFINE;
|
||||
// empty
|
||||
blockSuiteWorkspace: BlockSuiteWorkspace;
|
||||
providers: Provider[];
|
||||
}
|
||||
|
||||
export interface LocalWorkspace {
|
||||
flavour: WorkspaceFlavour.LOCAL;
|
||||
id: string;
|
||||
blockSuiteWorkspace: BlockSuiteWorkspace;
|
||||
providers: Provider[];
|
||||
}
|
||||
|
||||
export type BaseProvider = {
|
||||
flavour: string;
|
||||
// if this is true, we will connect the provider on the background
|
||||
background: boolean;
|
||||
connect: () => void;
|
||||
disconnect: () => void;
|
||||
// cleanup data when workspace is removed
|
||||
cleanup: () => void;
|
||||
};
|
||||
|
||||
export interface BackgroundProvider extends BaseProvider {
|
||||
background: true;
|
||||
callbacks: Set<() => void>;
|
||||
}
|
||||
|
||||
export interface AffineDownloadProvider extends BaseProvider {
|
||||
flavour: 'affine-download';
|
||||
}
|
||||
|
||||
export interface BroadCastChannelProvider extends BaseProvider {
|
||||
flavour: 'broadcast-channel';
|
||||
}
|
||||
|
||||
export interface LocalIndexedDBProvider extends BackgroundProvider {
|
||||
flavour: 'local-indexeddb';
|
||||
}
|
||||
|
||||
export interface AffineWebSocketProvider extends BaseProvider {
|
||||
flavour: 'affine-websocket';
|
||||
}
|
||||
|
||||
export type Provider =
|
||||
| LocalIndexedDBProvider
|
||||
| AffineWebSocketProvider
|
||||
| BroadCastChannelProvider;
|
||||
|
||||
export type AffineOfficialWorkspace = AffineWorkspace | LocalWorkspace;
|
||||
|
||||
export type RemWorkspace = AffineOfficialWorkspace;
|
||||
export type AllWorkspace = AffineOfficialWorkspace;
|
||||
|
||||
export type NextPageWithLayout<P = Record<string, unknown>, IP = P> = NextPage<
|
||||
P,
|
||||
|
||||
Reference in New Issue
Block a user