From 41980188cff9533d9b8a3b0016bbafbba9248beb Mon Sep 17 00:00:00 2001
From: lawvs <18554747+lawvs@users.noreply.github.com>
Date: Fri, 12 Aug 2022 13:53:51 +0800
Subject: [PATCH 1/9] chore: update warn message
---
libs/components/layout/src/header/LayoutHeader.tsx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libs/components/layout/src/header/LayoutHeader.tsx b/libs/components/layout/src/header/LayoutHeader.tsx
index 604b6caa6d..beade0de0d 100644
--- a/libs/components/layout/src/header/LayoutHeader.tsx
+++ b/libs/components/layout/src/header/LayoutHeader.tsx
@@ -52,8 +52,8 @@ export const LayoutHeader = () => {
- AFFiNE now under active development, the version is
- UNSTABLE, please DO NOT store important data in this version
+ AFFiNE is currently under active development. This build is
+ UNSTABLE. Please DO NOT store important data.
From 7024b7f11a1edd8c410c7528f28973aae6274652 Mon Sep 17 00:00:00 2001
From: lawvs <18554747+lawvs@users.noreply.github.com>
Date: Fri, 12 Aug 2022 13:54:11 +0800
Subject: [PATCH 2/9] chore: clean page tree styles
---
.../workspace-sidebar/page-tree/DndTree.tsx | 12 +-
.../page-tree/tree-item/DndTreeItem.tsx | 6 +-
.../page-tree/tree-item/TreeItem.tsx | 73 ++++++-------
.../page-tree/tree-item/styles.ts | 103 +++---------------
4 files changed, 53 insertions(+), 141 deletions(-)
diff --git a/libs/components/layout/src/workspace-sidebar/page-tree/DndTree.tsx b/libs/components/layout/src/workspace-sidebar/page-tree/DndTree.tsx
index 40991b930c..6db19e3e86 100755
--- a/libs/components/layout/src/workspace-sidebar/page-tree/DndTree.tsx
+++ b/libs/components/layout/src/workspace-sidebar/page-tree/DndTree.tsx
@@ -36,19 +36,13 @@ export type DndTreeProps = {
indentationWidth?: number;
collapsible?: boolean;
removable?: boolean;
- showDragIndicator?: boolean;
};
/**
* Currently does not support drag and drop using the keyboard.
*/
export function DndTree(props: DndTreeProps) {
- const {
- indentationWidth = 20,
- collapsible,
- removable,
- showDragIndicator,
- } = props;
+ const { indentationWidth = 20, collapsible, removable } = props;
const sensors = useSensors(
useSensor(PointerSensor, { activationConstraint: { distance: 8 } })
@@ -111,7 +105,6 @@ export function DndTree(props: DndTreeProps) {
: depth
}
indentationWidth={indentationWidth}
- indicator={showDragIndicator}
childCount={children.length}
onCollapse={
collapsible && children.length
@@ -129,7 +122,8 @@ export function DndTree(props: DndTreeProps) {
)}
{activeId && activeItem ? (
ble-node; the ref of the inner dom is often used as draggable-node */
- wrapperRef?(node: HTMLLIElement): void;
-} & HTMLAttributes;
+} & HTMLAttributes;
export const TreeItem = forwardRef(
(
@@ -52,13 +48,10 @@ export const TreeItem = forwardRef(
ghost,
handleProps,
indentationWidth,
- indicator,
collapsed,
onCollapse,
onRemove,
- style,
value,
- wrapperRef,
pageId,
...props
},
@@ -71,8 +64,8 @@ export const TreeItem = forwardRef(
);
return (
- (
active={pageId === page_id}
{...props}
>
-
-
- {childCount !== 0 ? (
- collapsed ? (
-
- ) : (
-
- )
- ) : (
-
- )}
-
+ {childCount !== 0 ? (
+ collapsed ? (
+
+
+
+ ) : (
+
+
+
+ )
+ ) : (
+
+ )}
-
-
- {value}
-
- {BooleanPageTreeItemMoreActions && (
-
- )}
+
+
+ {value}
+
+ {BooleanPageTreeItemMoreActions && (
+
+ )}
- {/*{!clone && onRemove && }*/}
- {clone && childCount && childCount > 1 ? (
- {childCount}
- ) : null}
-
-
-
+ {/*{!clone && onRemove && }*/}
+ {clone && childCount && childCount > 1 ? (
+ {childCount}
+ ) : null}
+
+
);
}
);
diff --git a/libs/components/layout/src/workspace-sidebar/page-tree/tree-item/styles.ts b/libs/components/layout/src/workspace-sidebar/page-tree/tree-item/styles.ts
index 0040e5bef7..442715229c 100644
--- a/libs/components/layout/src/workspace-sidebar/page-tree/tree-item/styles.ts
+++ b/libs/components/layout/src/workspace-sidebar/page-tree/tree-item/styles.ts
@@ -1,22 +1,18 @@
import { styled } from '@toeverything/components/ui';
import { Link } from 'react-router-dom';
-export const TreeItemContainer = styled('div')`
- box-sizing: border-box;
- display: flex;
- align-items: center;
- color: #4c6275;
-`;
-
-export const Wrapper = styled('li')<{
+export const TreeItemContainer = styled('div')<{
spacing: string;
clone?: boolean;
ghost?: boolean;
- indicator?: boolean;
disableSelection?: boolean;
disableInteraction?: boolean;
active?: boolean;
}>`
+ display: flex;
+ align-items: center;
+ color: #4c6275;
+
box-sizing: border-box;
padding-left: ${({ spacing }) => spacing};
list-style: none;
@@ -26,21 +22,13 @@ export const Wrapper = styled('li')<{
${({ clone, disableSelection }) =>
(clone || disableSelection) &&
- `width: 100%;
- .Text,
- .Count {
- user-select: none;
- -webkit-user-select: none;
- }`}
-
- ${({ indicator }) =>
- indicator &&
- `width: 100%;
- .Text,
- .Count {
- user-select: none;
- -webkit-user-select: none;
- }`}
+ `
+ width: 100%;
+ user-select: none;
+ opacity: 0.7;
+ background: transparent;
+ cursor: grab;
+ `}
${({ disableInteraction }) => disableInteraction && `pointer-events: none;`}
@@ -48,64 +36,6 @@ export const Wrapper = styled('li')<{
background: #f5f7f8;
border-radius: 5px;
}
-
- &.clone {
- display: inline-block;
- padding: 0;
- margin-left: 10px;
- margin-top: 5px;
- pointer-events: none;
-
- ${TreeItemContainer} {
- padding-right: 20px;
- border-radius: 4px;
- box-shadow: 0px 15px 15px 0 rgba(34, 33, 81, 0.1);
- }
- }
-
- &.ghost {
- &.indicator {
- opacity: 1;
- position: relative;
- z-index: 1;
- margin-bottom: -1px;
-
- ${TreeItemContainer} {
- position: relative;
- padding: 0;
- height: 8px;
- border-color: #2389ff;
- background-color: #56a1f8;
-
- &:before {
- position: absolute;
- left: -8px;
- top: -4px;
- display: block;
- content: '';
- width: 12px;
- height: 12px;
- border-radius: 50%;
- border: 1px solid #2389ff;
- }
-
- > * {
- /* Items are hidden using height and opacity to retain focus */
- opacity: 0;
- height: 0;
- }
- }
- }
-
- &:not(.indicator) {
- opacity: 0.5;
- }
-
- ${TreeItemContainer} > * {
- box-shadow: none;
- background-color: transparent;
- }
- }
`;
export const Counter = styled('span')`
@@ -138,7 +68,7 @@ export const ActionButton = styled('button')<{
border: none;
outline: none;
appearance: none;
- background-color: transparent;
+ background: transparent;
-webkit-tap-highlight-color: transparent;
svg {
@@ -151,8 +81,7 @@ export const ActionButton = styled('button')<{
}
&:active {
- background-color: ${({ background }) =>
- background ?? 'rgba(0, 0, 0, 0.05)'};
+ background: ${({ background }) => background ?? 'rgba(0, 0, 0, 0.05)'};
svg {
fill: ${({ fill }) => fill ?? '#788491'};
@@ -170,9 +99,7 @@ export const TreeItemMoreActions = styled('div')`
visibility: hidden;
`;
-export const TextLink = styled(Link, {
- shouldForwardProp: (prop: string) => !['active'].includes(prop),
-})<{ active?: boolean }>`
+export const TextLink = styled(Link)`
display: flex;
align-items: center;
flex-grow: 1;
From e47268bb8b0a6559527436e7b9d8e810c58b46f4 Mon Sep 17 00:00:00 2001
From: xiaodong zuo
Date: Fri, 12 Aug 2022 16:41:37 +0800
Subject: [PATCH 3/9] fix: link style issues
---
libs/components/common/src/lib/text/plugins/link.tsx | 11 ++++++-----
.../editor-blocks/src/blocks/page/PageView.tsx | 3 +++
2 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/libs/components/common/src/lib/text/plugins/link.tsx b/libs/components/common/src/lib/text/plugins/link.tsx
index 60193e38a0..5c1425460d 100644
--- a/libs/components/common/src/lib/text/plugins/link.tsx
+++ b/libs/components/common/src/lib/text/plugins/link.tsx
@@ -25,7 +25,6 @@ import { ReactEditor } from 'slate-react';
import OpenInNewIcon from '@mui/icons-material/OpenInNew';
import EditIcon from '@mui/icons-material/Edit';
import LinkOffIcon from '@mui/icons-material/LinkOff';
-import AttachmentIcon from '@mui/icons-material/Attachment';
import {
MuiTooltip as Tooltip,
styled,
@@ -39,7 +38,7 @@ import {
import { getRandomString } from '../utils';
import { colors } from '../../colors';
-
+import { LinkIcon } from '@toeverything/components/icons';
export type LinkElement = {
type: 'link';
url: string;
@@ -124,7 +123,7 @@ const LinkStyledTooltip = styled(({ className, ...props }: MuiTooltipProps) => (
))(({ theme }) => ({
[`& .${muiTooltipClasses.tooltip}`]: {
backgroundColor: '#fff',
- color: '#4C6275',
+ color: '#3E6FDB',
boxShadow: theme.affine.shadows.shadow1,
fontSize: '14px',
},
@@ -419,8 +418,8 @@ export const LinkModal = memo((props: LinkModalProps) => {
}}
>
({
const styles = style9.create({
linkModalContainerIcon: {
+ display: 'flex',
width: '16px',
margin: '0 16px 0 4px',
},
@@ -517,6 +517,7 @@ const styles = style9.create({
'::-webkit-input-placeholder': {
color: '#98acbd',
},
+ color: '#4C6275',
},
linkMask: {
position: 'fixed',
diff --git a/libs/components/editor-blocks/src/blocks/page/PageView.tsx b/libs/components/editor-blocks/src/blocks/page/PageView.tsx
index 64ea3c9536..4d5de824cf 100644
--- a/libs/components/editor-blocks/src/blocks/page/PageView.tsx
+++ b/libs/components/editor-blocks/src/blocks/page/PageView.tsx
@@ -119,5 +119,8 @@ const PageTitleBlock = styled('div')(({ theme }) => {
'.content': {
outline: 'none',
},
+ a: {
+ color: '#3e6fdb',
+ },
};
});
From 174779bb28176b6b7ddca33c56a9329fdfd31334 Mon Sep 17 00:00:00 2001
From: xiaodong zuo
Date: Fri, 12 Aug 2022 16:49:17 +0800
Subject: [PATCH 4/9] fix: link style issues
---
libs/components/common/src/lib/text/plugins/link.tsx | 1 +
1 file changed, 1 insertion(+)
diff --git a/libs/components/common/src/lib/text/plugins/link.tsx b/libs/components/common/src/lib/text/plugins/link.tsx
index 5c1425460d..619239c64d 100644
--- a/libs/components/common/src/lib/text/plugins/link.tsx
+++ b/libs/components/common/src/lib/text/plugins/link.tsx
@@ -507,6 +507,7 @@ const styles = style9.create({
display: 'flex',
width: '16px',
margin: '0 16px 0 4px',
+ color: '#4C6275',
},
linkModalContainerInput: {
flex: '1',
From edfa95057b47af1fca828268df6bc55a8ec578a3 Mon Sep 17 00:00:00 2001
From: DarkSky
Date: Fri, 12 Aug 2022 16:54:47 +0800
Subject: [PATCH 5/9] feat: optional provider
---
apps/ligo-virgo/src/pages/RoutePrivate.tsx | 2 +-
libs/components/account/src/login/fs.tsx | 8 +-
libs/components/account/src/login/index.tsx | 3 +-
.../layout/src/header/FileSystem.tsx | 112 ++++++++++++++++++
.../layout/src/header/LayoutHeader.tsx | 6 +-
.../db-service/src/services/database/index.ts | 13 +-
libs/datasource/jwt/src/adapter/yjs/index.ts | 42 ++++---
.../jwt/src/adapter/yjs/provider.ts | 97 ++++++++-------
libs/datasource/jwt/src/index.ts | 1 +
libs/datasource/state/src/user.ts | 21 +++-
pnpm-lock.yaml | 47 +++++++-
11 files changed, 267 insertions(+), 85 deletions(-)
create mode 100644 libs/components/layout/src/header/FileSystem.tsx
diff --git a/apps/ligo-virgo/src/pages/RoutePrivate.tsx b/apps/ligo-virgo/src/pages/RoutePrivate.tsx
index 58dcbe3db5..a7cedac934 100644
--- a/apps/ligo-virgo/src/pages/RoutePrivate.tsx
+++ b/apps/ligo-virgo/src/pages/RoutePrivate.tsx
@@ -23,7 +23,7 @@ export function RoutePrivate({
return ;
}
- if (!user) {
+ if (!user || !pathname.startsWith(`/${user.id}`)) {
return (
{
};
export const FileSystem = (props: { onError: () => void }) => {
- const onSelected = useLocalTrigger();
+ const [, onSelected] = useLocalTrigger();
const apiSupported = useMemo(() => {
try {
@@ -56,12 +56,6 @@ export const FileSystem = (props: { onError: () => void }) => {
}
}, []);
- useEffect(() => {
- if (process.env['NX_E2E']) {
- onSelected();
- }
- }, []);
-
return (
- {' '}
+ new Promise((resolve, reject) => {
+ const req = indexedDB.deleteDatabase(workspace);
+ req.addEventListener('error', e => reject(e));
+ req.addEventListener('blocked', e => reject(e));
+ req.addEventListener('upgradeneeded', e => reject(e));
+ req.addEventListener('success', e => resolve(e));
+ });
+
+const requestPermission = async (workspace: string) => {
+ await cleanupWorkspace(workspace);
+ const dirHandler = await window.showDirectoryPicker({
+ id: 'AFFiNE_' + workspace,
+ mode: 'readwrite',
+ startIn: 'documents',
+ });
+
+ const fileHandle = await dirHandler.getFileHandle('affine.db', {
+ create: true,
+ });
+ const file = await fileHandle.getFile();
+ const initialData = new Uint8Array(await file.arrayBuffer());
+
+ const exporter = async (contents: Uint8Array) => {
+ try {
+ const writable = await fileHandle.createWritable();
+ await writable.write(contents);
+ await writable.close();
+ } catch (e) {
+ console.log(e);
+ }
+ };
+
+ await services.api.editorBlock.setupDataExporter(
+ workspace,
+ new Uint8Array(initialData),
+ exporter
+ );
+};
+
+const StyledFileSystem = styled('div')<{ disabled?: boolean }>({
+ padding: '10px 12px',
+ fontWeight: 600,
+ fontSize: '14px',
+ color: '#3E6FDB',
+ textTransform: 'uppercase',
+ cursor: 'pointer',
+ '&:hover': {
+ background: '#F5F7F8',
+ borderRadius: '5px',
+ },
+});
+
+export const FileSystem = () => {
+ const [selected, onSelected] = useLocalTrigger();
+ const [error, setError] = useState(false);
+
+ const onError = useCallback(() => {
+ setError(true);
+ setTimeout(() => setError(false), 3000);
+ }, []);
+
+ const apiSupported = useMemo(() => {
+ try {
+ return 'showOpenFilePicker' in window;
+ } catch (e) {
+ return false;
+ }
+ }, []);
+
+ if (apiSupported && !selected) {
+ return (
+ <>
+ setError(false)}
+ >
+
+
+ }
+ />
+ {
+ try {
+ await requestPermission('AFFiNE');
+ onSelected();
+ } catch (e) {
+ onError();
+ }
+ }}
+ >
+ Sync to Disk
+
+ >
+ );
+ }
+ return null;
+};
diff --git a/libs/components/layout/src/header/LayoutHeader.tsx b/libs/components/layout/src/header/LayoutHeader.tsx
index beade0de0d..bc33736157 100644
--- a/libs/components/layout/src/header/LayoutHeader.tsx
+++ b/libs/components/layout/src/header/LayoutHeader.tsx
@@ -1,4 +1,4 @@
-import { IconButton, styled, MuiButton } from '@toeverything/components/ui';
+import { IconButton, styled } from '@toeverything/components/ui';
import {
LogoIcon,
SideBarViewIcon,
@@ -7,8 +7,9 @@ import {
} from '@toeverything/components/icons';
import { useShowSettingsSidebar } from '@toeverything/datasource/state';
-import { CurrentPageTitle } from './Title';
import { EditorBoardSwitcher } from './EditorBoardSwitcher';
+import { FileSystem } from './FileSystem';
+import { CurrentPageTitle } from './Title';
export const LayoutHeader = () => {
const { toggleSettingsSidebar: toggleInfoSidebar, showSettingsSidebar } =
@@ -25,6 +26,7 @@ export const LayoutHeader = () => {
+
Share
void;
+
type YjsProviders = {
awareness: Awareness;
- idb: IndexedDBProvider;
- binariesIdb: IndexedDBProvider;
+ binaries: Doc;
+ doc: Doc;
gatekeeper: GateKeeper;
connListener: { listeners?: ConnectivityListener };
userId: string;
remoteToken?: string; // remote storage token
};
+
const _yjsDatabaseInstance = new Map();
const _asyncInitLoading = new Set();
@@ -90,13 +90,9 @@ async function _initYjsDatabase(
const { userId, token } = options;
const doc = new Doc({ autoLoad: true, shouldLoad: true });
- const idb = await new IndexedDBProvider(workspace, doc).whenSynced;
+ // const idb = await new IndexedDBProvider(workspace, doc).whenSynced;
const binaries = new Doc({ autoLoad: true, shouldLoad: true });
- const binariesIdb = await new IndexedDBProvider(
- `${workspace}_binaries`,
- binaries
- ).whenSynced;
const awareness = new Awareness(doc);
@@ -114,16 +110,24 @@ async function _initYjsDatabase(
const emitState = (c: Connectivity) =>
connListener.listeners?.(workspace, c);
await Promise.all(
- Object.entries(options.provider).map(async ([, p]) =>
- p({ awareness, doc, token, workspace, emitState })
- )
+ Object.entries(options.provider).flatMap(async ([, p]) => [
+ p({ awareness, doc, token, workspace, emitState }),
+ p({
+ awareness,
+ doc: binaries,
+ token,
+ workspace: `${workspace}_binaries`,
+ emitState,
+ }),
+ ])
);
}
const newInstance = {
awareness,
- idb,
- binariesIdb,
+ binaries,
+ doc,
gatekeeper,
+
connListener,
userId,
remoteToken: token,
@@ -183,7 +187,7 @@ export class YjsAdapter implements AsyncDatabaseAdapter {
private constructor(providers: YjsProviders) {
this._provider = providers;
- this._doc = providers.idb.doc;
+ this._doc = providers.doc;
this._awareness = providers.awareness;
this._gatekeeper = providers.gatekeeper;
this._reload = () => {
@@ -201,7 +205,7 @@ export class YjsAdapter implements AsyncDatabaseAdapter {
});
// @ts-ignore
this._binaries = new YjsRemoteBinaries(
- providers.binariesIdb.doc.getMap(),
+ providers.binaries.getMap(),
providers.remoteToken
);
// @ts-ignore
@@ -336,7 +340,7 @@ export class YjsAdapter implements AsyncDatabaseAdapter {
});
const [file] = (await fromEvent(handles)) as File[];
const binary = await file.arrayBuffer();
- await this._provider.idb.clearData();
+ // await this._provider.idb.clearData();
const doc = new Doc({ autoLoad: true, shouldLoad: true });
let updated = 0;
let isUpdated = false;
@@ -357,8 +361,8 @@ export class YjsAdapter implements AsyncDatabaseAdapter {
};
check();
});
- await new IndexedDBProvider(this._provider.idb.name, doc)
- .whenSynced;
+ // await new IndexedDBProvider(this._provider.idb.name, doc)
+ // .whenSynced;
applyUpdate(doc, new Uint8Array(binary));
await update_check;
console.log('load success');
diff --git a/libs/datasource/jwt/src/adapter/yjs/provider.ts b/libs/datasource/jwt/src/adapter/yjs/provider.ts
index f7068288fd..e4cebd1f01 100644
--- a/libs/datasource/jwt/src/adapter/yjs/provider.ts
+++ b/libs/datasource/jwt/src/adapter/yjs/provider.ts
@@ -2,6 +2,7 @@ import { Doc } from 'yjs';
import { Awareness } from 'y-protocols/awareness.js';
import {
+ IndexedDBProvider,
SQLiteProvider,
WebsocketProvider,
} from '@toeverything/datasource/jwt-rpc';
@@ -19,7 +20,10 @@ type YjsDefaultInstances = {
export type YjsProvider = (instances: YjsDefaultInstances) => Promise;
+type ProviderType = 'idb' | 'sqlite' | 'ws';
+
export type YjsProviderOptions = {
+ enabled: ProviderType[];
backend: typeof BucketBackend[keyof typeof BucketBackend];
params?: Record;
importData?: () => Promise | Uint8Array | undefined;
@@ -30,53 +34,64 @@ export type YjsProviderOptions = {
export const getYjsProviders = (
options: YjsProviderOptions
): Record => {
+ console.log('getYjsProviders', options);
return {
+ indexeddb: async (instances: YjsDefaultInstances) => {
+ if (options.enabled.includes('idb')) {
+ await new IndexedDBProvider(instances.workspace, instances.doc)
+ .whenSynced;
+ }
+ },
sqlite: async (instances: YjsDefaultInstances) => {
- const fsHandle = setInterval(async () => {
- if (options.hasExporter?.()) {
- clearInterval(fsHandle);
- const fs = new SQLiteProvider(
- instances.workspace,
- instances.doc,
- await options.importData?.()
- );
- if (options.exportData) {
- fs.registerExporter(options.exportData);
+ if (options.enabled.includes('sqlite')) {
+ const fsHandle = setInterval(async () => {
+ if (options.hasExporter?.()) {
+ clearInterval(fsHandle);
+ const fs = new SQLiteProvider(
+ instances.workspace,
+ instances.doc,
+ await options.importData?.()
+ );
+ if (options.exportData) {
+ fs.registerExporter(options.exportData);
+ }
+ await fs.whenSynced;
}
- await fs.whenSynced;
- }
- }, 500);
+ }, 500);
+ }
},
ws: async (instances: YjsDefaultInstances) => {
- if (instances.token) {
- const ws = new WebsocketProvider(
- instances.token,
- options.backend,
- instances.workspace,
- instances.doc,
- {
- awareness: instances.awareness,
- params: options.params,
- }
- ) as any; // TODO: type is erased after cascading references
+ if (options.enabled.includes('ws')) {
+ if (instances.token) {
+ const ws = new WebsocketProvider(
+ instances.token,
+ options.backend,
+ instances.workspace,
+ instances.doc,
+ {
+ awareness: instances.awareness,
+ params: options.params,
+ }
+ ) as any; // TODO: type is erased after cascading references
- // Wait for ws synchronization to complete, otherwise the data will be modified in reverse, which can be optimized later
- return new Promise((resolve, reject) => {
- // TODO: synced will also be triggered on reconnection after losing sync
- // There needs to be an event mechanism to emit the synchronization state to the upper layer
- ws.once('synced', () => resolve());
- ws.once('lost-connection', () => resolve());
- ws.once('connection-error', () => reject());
- ws.on('synced', () => instances.emitState('connected'));
- ws.on('lost-connection', () =>
- instances.emitState('retry')
- );
- ws.on('connection-error', () =>
- instances.emitState('retry')
- );
- });
- } else {
- return;
+ // Wait for ws synchronization to complete, otherwise the data will be modified in reverse, which can be optimized later
+ return new Promise((resolve, reject) => {
+ // TODO: synced will also be triggered on reconnection after losing sync
+ // There needs to be an event mechanism to emit the synchronization state to the upper layer
+ ws.once('synced', () => resolve());
+ ws.once('lost-connection', () => resolve());
+ ws.once('connection-error', () => reject());
+ ws.on('synced', () => instances.emitState('connected'));
+ ws.on('lost-connection', () =>
+ instances.emitState('retry')
+ );
+ ws.on('connection-error', () =>
+ instances.emitState('retry')
+ );
+ });
+ } else {
+ return;
+ }
}
},
};
diff --git a/libs/datasource/jwt/src/index.ts b/libs/datasource/jwt/src/index.ts
index ecad7aebf9..38bc11396e 100644
--- a/libs/datasource/jwt/src/index.ts
+++ b/libs/datasource/jwt/src/index.ts
@@ -618,6 +618,7 @@ export class BlockClient<
const instance = await YjsAdapter.init(workspace, {
provider: getYjsProviders({
+ enabled: [],
backend: BucketBackend.YjsWebSocketAffine,
importData,
exportData,
diff --git a/libs/datasource/state/src/user.ts b/libs/datasource/state/src/user.ts
index fefb689f0a..d32fef2c56 100644
--- a/libs/datasource/state/src/user.ts
+++ b/libs/datasource/state/src/user.ts
@@ -1,3 +1,4 @@
+import { useNavigate } from 'react-router';
import {
getAuth,
onAuthStateChanged,
@@ -62,11 +63,17 @@ const BRAND_ID = 'AFFiNE';
const _localTrigger = atom(false);
const _useUserAndSpacesForFreeLogin = () => {
+ const navigate = useNavigate();
const [user, setUser] = useAtom(_userAtom);
const [loading, setLoading] = useAtom(_loadingAtom);
const [localTrigger] = useAtom(_localTrigger);
- useEffect(() => setLoading(false), []);
+ useEffect(() => {
+ if (loading) {
+ navigate('/demo');
+ setLoading(false);
+ }
+ }, []);
useEffect(() => {
if (localTrigger) {
@@ -77,6 +84,14 @@ const _useUserAndSpacesForFreeLogin = () => {
nickname: BRAND_ID,
email: '',
});
+ } else {
+ setUser({
+ photo: '',
+ id: 'demo',
+ username: 'demo',
+ nickname: 'demo',
+ email: '',
+ });
}
}, [localTrigger, setLoading, setUser]);
@@ -86,8 +101,8 @@ const _useUserAndSpacesForFreeLogin = () => {
};
export const useLocalTrigger = () => {
- const [, setTrigger] = useAtom(_localTrigger);
- return () => setTrigger(true);
+ const [trigger, setTrigger] = useAtom(_localTrigger);
+ return [trigger, () => setTrigger(true)] as [boolean, () => void];
};
export const useUserAndSpaces = process.env['NX_LOCAL']
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index dacfe065aa..a632fb99bd 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -194,7 +194,7 @@ importers:
yjs: ^13.5.41
dependencies:
authing-js-sdk: 4.23.35
- firebase-admin: 11.0.1_@firebase+app-types@0.7.0
+ firebase-admin: 11.0.1
lib0: 0.2.52
lru-cache: 7.13.2
nanoid: 4.0.0
@@ -571,6 +571,9 @@ importers:
dependencies:
ffc-js-client-side-sdk: 1.1.5
+ libs/datasource/jwst/pkg:
+ specifiers: {}
+
libs/datasource/jwt:
specifiers:
'@types/debug': ^4.1.7
@@ -3291,6 +3294,15 @@ packages:
- utf-8-validate
dev: true
+ /@firebase/auth-interop-types/0.1.6_@firebase+util@1.6.3:
+ resolution: {integrity: sha512-etIi92fW3CctsmR9e3sYM3Uqnoq861M0Id9mdOPF6PWIg38BXL5k4upCNBggGUpLIS0H1grMOvy/wn1xymwe2g==}
+ peerDependencies:
+ '@firebase/app-types': 0.x
+ '@firebase/util': 1.x
+ dependencies:
+ '@firebase/util': 1.6.3
+ dev: false
+
/@firebase/auth-interop-types/0.1.6_pbfwexsq7uf6mrzcwnikj3g37m:
resolution: {integrity: sha512-etIi92fW3CctsmR9e3sYM3Uqnoq861M0Id9mdOPF6PWIg38BXL5k4upCNBggGUpLIS0H1grMOvy/wn1xymwe2g==}
peerDependencies:
@@ -3299,6 +3311,7 @@ packages:
dependencies:
'@firebase/app-types': 0.7.0
'@firebase/util': 1.6.3
+ dev: true
/@firebase/auth-types/0.11.0_pbfwexsq7uf6mrzcwnikj3g37m:
resolution: {integrity: sha512-q7Bt6cx+ySj9elQHTsKulwk3+qDezhzRBFC9zlQ1BjgMueUOnGMcvqmU0zuKlQ4RhLSH7MNAdBV2znVaoN3Vxw==}
@@ -3334,6 +3347,19 @@ packages:
'@firebase/util': 1.6.3
tslib: 2.4.0
+ /@firebase/database-compat/0.2.4:
+ resolution: {integrity: sha512-VtsGixO5mTjNMJn6PwxAJEAR70fj+3blCXIdQKel3q+eYGZAfdqxox1+tzZDnf9NWBJpaOgAHPk3JVDxEo9NFQ==}
+ dependencies:
+ '@firebase/component': 0.5.17
+ '@firebase/database': 0.13.4
+ '@firebase/database-types': 0.9.12
+ '@firebase/logger': 0.3.3
+ '@firebase/util': 1.6.3
+ tslib: 2.4.0
+ transitivePeerDependencies:
+ - '@firebase/app-types'
+ dev: false
+
/@firebase/database-compat/0.2.4_@firebase+app-types@0.7.0:
resolution: {integrity: sha512-VtsGixO5mTjNMJn6PwxAJEAR70fj+3blCXIdQKel3q+eYGZAfdqxox1+tzZDnf9NWBJpaOgAHPk3JVDxEo9NFQ==}
dependencies:
@@ -3345,6 +3371,7 @@ packages:
tslib: 2.4.0
transitivePeerDependencies:
- '@firebase/app-types'
+ dev: true
/@firebase/database-types/0.9.10:
resolution: {integrity: sha512-2ji6nXRRsY+7hgU6zRhUtK0RmSjVWM71taI7Flgaw+BnopCo/lDF5HSwxp8z7LtiHlvQqeRA3Ozqx5VhlAbiKg==}
@@ -3359,6 +3386,19 @@ packages:
'@firebase/app-types': 0.7.0
'@firebase/util': 1.6.3
+ /@firebase/database/0.13.4:
+ resolution: {integrity: sha512-NW7bOoiaC4sJCj6DY/m9xHoFNa0CK32YPMCh6FiMweLCDQbOZM8Ql/Kn6yyuxCb7K7ypz9eSbRlCWQJsJRQjhg==}
+ dependencies:
+ '@firebase/auth-interop-types': 0.1.6_@firebase+util@1.6.3
+ '@firebase/component': 0.5.17
+ '@firebase/logger': 0.3.3
+ '@firebase/util': 1.6.3
+ faye-websocket: 0.11.4
+ tslib: 2.4.0
+ transitivePeerDependencies:
+ - '@firebase/app-types'
+ dev: false
+
/@firebase/database/0.13.4_@firebase+app-types@0.7.0:
resolution: {integrity: sha512-NW7bOoiaC4sJCj6DY/m9xHoFNa0CK32YPMCh6FiMweLCDQbOZM8Ql/Kn6yyuxCb7K7ypz9eSbRlCWQJsJRQjhg==}
dependencies:
@@ -3370,6 +3410,7 @@ packages:
tslib: 2.4.0
transitivePeerDependencies:
- '@firebase/app-types'
+ dev: true
/@firebase/firestore-compat/0.1.23_53yvy43rwpg2c45kgeszsxtrca:
resolution: {integrity: sha512-QfcuyMAavp//fQnjSfCEpnbWi7spIdKaXys1kOLu7395fLr+U6ykmto1HUMCSz8Yus9cEr/03Ujdi2SUl2GUAA==}
@@ -10863,12 +10904,12 @@ packages:
semver-regex: 2.0.0
dev: true
- /firebase-admin/11.0.1_@firebase+app-types@0.7.0:
+ /firebase-admin/11.0.1:
resolution: {integrity: sha512-rL3wlZbi2Kb/KJgcmj1YHlD4ZhfmhfgRO2YJialxAllm0tj1IQea878hHuBLGmv4DpbW9t9nLvX9kddNR2Y65Q==}
engines: {node: '>=14'}
dependencies:
'@fastify/busboy': 1.1.0
- '@firebase/database-compat': 0.2.4_@firebase+app-types@0.7.0
+ '@firebase/database-compat': 0.2.4
'@firebase/database-types': 0.9.10
'@types/node': 18.0.1
jsonwebtoken: 8.5.1
From ce0590449a89bcb4486ba5471e61ba7216841b9d Mon Sep 17 00:00:00 2001
From: DiamondThree
Date: Fri, 12 Aug 2022 17:04:12 +0800
Subject: [PATCH 6/9] fix:setTimeout error (#215)
---
.../editor-core/src/editor/selection/selection.ts | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/libs/components/editor-core/src/editor/selection/selection.ts b/libs/components/editor-core/src/editor/selection/selection.ts
index 38d7f86b0f..406f9adecb 100644
--- a/libs/components/editor-core/src/editor/selection/selection.ts
+++ b/libs/components/editor-core/src/editor/selection/selection.ts
@@ -48,7 +48,7 @@ export class SelectionManager implements VirgoSelection {
private _scrollDelay = 150;
private _selectEndDelayTime = 500;
private _hasEmitEndPending = false;
-
+ private _scrollTimer: number | null = null;
/**
*
* the selection info before current
@@ -681,6 +681,9 @@ export class SelectionManager implements VirgoSelection {
*/
public async activeNodeByNodeId(nodeId: string, position?: CursorTypes) {
try {
+ if (this._scrollTimer) {
+ clearTimeout(this._scrollTimer);
+ }
const node = await this._editor.getBlockById(nodeId);
if (node) {
this._activatedNodeId = nodeId;
@@ -689,7 +692,7 @@ export class SelectionManager implements VirgoSelection {
}
this.emit(nodeId, SelectEventTypes.active, this.lastPoint);
// TODO: Optimize the related logic after implementing the scroll bar
- setTimeout(() => {
+ this._scrollTimer = window.setTimeout(() => {
this._editor.scrollManager.keepBlockInView(node);
}, this._scrollDelay);
} else {
From 06d4dbc99b5ed75523c136028482e25e367968c6 Mon Sep 17 00:00:00 2001
From: xiaodong zuo
Date: Fri, 12 Aug 2022 17:06:21 +0800
Subject: [PATCH 7/9] fix: link style issues
---
libs/components/editor-blocks/src/blocks/page/PageView.tsx | 3 ---
.../editor-blocks/src/components/text-manage/TextManage.tsx | 3 +++
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/libs/components/editor-blocks/src/blocks/page/PageView.tsx b/libs/components/editor-blocks/src/blocks/page/PageView.tsx
index 4d5de824cf..64ea3c9536 100644
--- a/libs/components/editor-blocks/src/blocks/page/PageView.tsx
+++ b/libs/components/editor-blocks/src/blocks/page/PageView.tsx
@@ -119,8 +119,5 @@ const PageTitleBlock = styled('div')(({ theme }) => {
'.content': {
outline: 'none',
},
- a: {
- color: '#3e6fdb',
- },
};
});
diff --git a/libs/components/editor-blocks/src/components/text-manage/TextManage.tsx b/libs/components/editor-blocks/src/components/text-manage/TextManage.tsx
index 99179220a9..f433c1fba9 100644
--- a/libs/components/editor-blocks/src/components/text-manage/TextManage.tsx
+++ b/libs/components/editor-blocks/src/components/text-manage/TextManage.tsx
@@ -42,6 +42,9 @@ const TextBlockContainer = styled(Text)(({ theme }) => ({
fontFamily: theme.affine.typography.body1.fontFamily,
color: theme.affine.typography.body1.color,
letterSpacing: '0.1px',
+ a: {
+ color: '#3e6fdb',
+ },
}));
const findSlice = (arr: string[], p: string, q: string) => {
From c0c042dac0bcdcef23cc1341d82b2b3035e2d69e Mon Sep 17 00:00:00 2001
From: DarkSky
Date: Fri, 12 Aug 2022 17:49:39 +0800
Subject: [PATCH 8/9] feat: warning tips
---
apps/venus/src/app/index.tsx | 2 +-
.../layout/src/header/FileSystem.tsx | 16 ++++++------
.../layout/src/header/LayoutHeader.tsx | 25 ++++++++++++++-----
3 files changed, 29 insertions(+), 14 deletions(-)
diff --git a/apps/venus/src/app/index.tsx b/apps/venus/src/app/index.tsx
index e3b4a76c90..6939299dfd 100644
--- a/apps/venus/src/app/index.tsx
+++ b/apps/venus/src/app/index.tsx
@@ -27,7 +27,7 @@ const DiscordIcon = (props: any) => {
viewBox="0 0 71 55"
fill="currentcolor"
>
-
+
({
},
});
+export const fsApiSupported = () => {
+ try {
+ return 'showOpenFilePicker' in window;
+ } catch (e) {
+ return false;
+ }
+};
+
export const FileSystem = () => {
const [selected, onSelected] = useLocalTrigger();
const [error, setError] = useState(false);
@@ -68,13 +76,7 @@ export const FileSystem = () => {
setTimeout(() => setError(false), 3000);
}, []);
- const apiSupported = useMemo(() => {
- try {
- return 'showOpenFilePicker' in window;
- } catch (e) {
- return false;
- }
- }, []);
+ const apiSupported = useMemo(() => fsApiSupported(), []);
if (apiSupported && !selected) {
return (
diff --git a/libs/components/layout/src/header/LayoutHeader.tsx b/libs/components/layout/src/header/LayoutHeader.tsx
index bc33736157..f933348407 100644
--- a/libs/components/layout/src/header/LayoutHeader.tsx
+++ b/libs/components/layout/src/header/LayoutHeader.tsx
@@ -1,3 +1,5 @@
+import { useMemo } from 'react';
+
import { IconButton, styled } from '@toeverything/components/ui';
import {
LogoIcon,
@@ -5,16 +7,30 @@ import {
SearchIcon,
SideBarViewCloseIcon,
} from '@toeverything/components/icons';
-import { useShowSettingsSidebar } from '@toeverything/datasource/state';
+import {
+ useShowSettingsSidebar,
+ useLocalTrigger,
+} from '@toeverything/datasource/state';
import { EditorBoardSwitcher } from './EditorBoardSwitcher';
-import { FileSystem } from './FileSystem';
+import { fsApiSupported, FileSystem } from './FileSystem';
import { CurrentPageTitle } from './Title';
export const LayoutHeader = () => {
+ const [isLocalWorkspace] = useLocalTrigger();
const { toggleSettingsSidebar: toggleInfoSidebar, showSettingsSidebar } =
useShowSettingsSidebar();
+ const warningTips = useMemo(() => {
+ if (!fsApiSupported()) {
+ return 'Your browser does not support the local storage feature, please upgrade to the latest version of Chrome or Edge browser';
+ } else if (isLocalWorkspace) {
+ return 'You are in DEMO mode. Changes will NOT be saved unless you SYNC TO DISK';
+ } else {
+ return 'AFFiNE is under active development and the current version is UNSTABLE. Please DO NOT store information or data';
+ }
+ }, [isLocalWorkspace]);
+
return (
@@ -53,10 +69,7 @@ export const LayoutHeader = () => {
-
- AFFiNE is currently under active development. This build is
- UNSTABLE. Please DO NOT store important data.
-
+ {warningTips}
);
From dc98d4042befa122dbde0147c73b849a80103e5a Mon Sep 17 00:00:00 2001
From: DarkSky
Date: Fri, 12 Aug 2022 17:57:40 +0800
Subject: [PATCH 9/9] fix: types
---
libs/components/account/src/login/fs.tsx | 1 +
libs/components/layout/src/header/FileSystem.tsx | 1 +
2 files changed, 2 insertions(+)
diff --git a/libs/components/account/src/login/fs.tsx b/libs/components/account/src/login/fs.tsx
index bdccdd47ee..2482e5187c 100644
--- a/libs/components/account/src/login/fs.tsx
+++ b/libs/components/account/src/login/fs.tsx
@@ -17,6 +17,7 @@ const cleanupWorkspace = (workspace: string) =>
const requestPermission = async (workspace: string) => {
await cleanupWorkspace(workspace);
+ // @ts-ignore
const dirHandler = await window.showDirectoryPicker({
id: 'AFFiNE_' + workspace,
mode: 'readwrite',
diff --git a/libs/components/layout/src/header/FileSystem.tsx b/libs/components/layout/src/header/FileSystem.tsx
index a29ad9ea94..83c638c5b3 100644
--- a/libs/components/layout/src/header/FileSystem.tsx
+++ b/libs/components/layout/src/header/FileSystem.tsx
@@ -17,6 +17,7 @@ const cleanupWorkspace = (workspace: string) =>
const requestPermission = async (workspace: string) => {
await cleanupWorkspace(workspace);
+ // @ts-ignore
const dirHandler = await window.showDirectoryPicker({
id: 'AFFiNE_' + workspace,
mode: 'readwrite',