feat: optional provider
This commit is contained in:
@@ -23,7 +23,7 @@ export function RoutePrivate({
|
|||||||
return <PageLoading />;
|
return <PageLoading />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!user) {
|
if (!user || !pathname.startsWith(`/${user.id}`)) {
|
||||||
return (
|
return (
|
||||||
<Navigate
|
<Navigate
|
||||||
to={unauthorizedRedirectTo}
|
to={unauthorizedRedirectTo}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ const requestPermission = async (workspace: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const FileSystem = (props: { onError: () => void }) => {
|
export const FileSystem = (props: { onError: () => void }) => {
|
||||||
const onSelected = useLocalTrigger();
|
const [, onSelected] = useLocalTrigger();
|
||||||
|
|
||||||
const apiSupported = useMemo(() => {
|
const apiSupported = useMemo(() => {
|
||||||
try {
|
try {
|
||||||
@@ -56,12 +56,6 @@ export const FileSystem = (props: { onError: () => void }) => {
|
|||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (process.env['NX_E2E']) {
|
|
||||||
onSelected();
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MuiButton
|
<MuiButton
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export function Login() {
|
|||||||
<MuiSnackbar
|
<MuiSnackbar
|
||||||
anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
|
anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
|
||||||
open={error}
|
open={error}
|
||||||
message="Login failed, please check if you have permission"
|
message="Request File Permission failed, please check if you have permission"
|
||||||
/>
|
/>
|
||||||
<MuiGrid item xs={8}>
|
<MuiGrid item xs={8}>
|
||||||
<Error
|
<Error
|
||||||
@@ -32,7 +32,6 @@ export function Login() {
|
|||||||
</MuiGrid>
|
</MuiGrid>
|
||||||
|
|
||||||
<MuiGrid item xs={4}>
|
<MuiGrid item xs={4}>
|
||||||
{' '}
|
|
||||||
<MuiBox
|
<MuiBox
|
||||||
style={{
|
style={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
|
|||||||
112
libs/components/layout/src/header/FileSystem.tsx
Normal file
112
libs/components/layout/src/header/FileSystem.tsx
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/* eslint-disable filename-rules/match */
|
||||||
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
|
|
||||||
|
import { IconButton, MuiSnackbar, styled } from '@toeverything/components/ui';
|
||||||
|
import { services } from '@toeverything/datasource/db-service';
|
||||||
|
import { useLocalTrigger } from '@toeverything/datasource/state';
|
||||||
|
import { CloseIcon } from '@toeverything/components/common';
|
||||||
|
|
||||||
|
const cleanupWorkspace = (workspace: string) =>
|
||||||
|
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 (
|
||||||
|
<>
|
||||||
|
<MuiSnackbar
|
||||||
|
anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
|
||||||
|
open={error}
|
||||||
|
message="Request File Permission failed, please check if you have permission"
|
||||||
|
sx={{ marginTop: '3em' }}
|
||||||
|
action={
|
||||||
|
<IconButton
|
||||||
|
aria-label="close"
|
||||||
|
onClick={() => setError(false)}
|
||||||
|
>
|
||||||
|
<CloseIcon />
|
||||||
|
</IconButton>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<StyledFileSystem
|
||||||
|
onClick={async () => {
|
||||||
|
try {
|
||||||
|
await requestPermission('AFFiNE');
|
||||||
|
onSelected();
|
||||||
|
} catch (e) {
|
||||||
|
onError();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Sync to Disk
|
||||||
|
</StyledFileSystem>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { IconButton, styled, MuiButton } from '@toeverything/components/ui';
|
import { IconButton, styled } from '@toeverything/components/ui';
|
||||||
import {
|
import {
|
||||||
LogoIcon,
|
LogoIcon,
|
||||||
SideBarViewIcon,
|
SideBarViewIcon,
|
||||||
@@ -7,8 +7,9 @@ import {
|
|||||||
} from '@toeverything/components/icons';
|
} from '@toeverything/components/icons';
|
||||||
import { useShowSettingsSidebar } from '@toeverything/datasource/state';
|
import { useShowSettingsSidebar } from '@toeverything/datasource/state';
|
||||||
|
|
||||||
import { CurrentPageTitle } from './Title';
|
|
||||||
import { EditorBoardSwitcher } from './EditorBoardSwitcher';
|
import { EditorBoardSwitcher } from './EditorBoardSwitcher';
|
||||||
|
import { FileSystem } from './FileSystem';
|
||||||
|
import { CurrentPageTitle } from './Title';
|
||||||
|
|
||||||
export const LayoutHeader = () => {
|
export const LayoutHeader = () => {
|
||||||
const { toggleSettingsSidebar: toggleInfoSidebar, showSettingsSidebar } =
|
const { toggleSettingsSidebar: toggleInfoSidebar, showSettingsSidebar } =
|
||||||
@@ -25,6 +26,7 @@ export const LayoutHeader = () => {
|
|||||||
</FlexContainer>
|
</FlexContainer>
|
||||||
<FlexContainer>
|
<FlexContainer>
|
||||||
<StyledHelper>
|
<StyledHelper>
|
||||||
|
<FileSystem />
|
||||||
<StyledShare disabled={true}>Share</StyledShare>
|
<StyledShare disabled={true}>Share</StyledShare>
|
||||||
<div style={{ margin: '0px 12px' }}>
|
<div style={{ margin: '0px 12px' }}>
|
||||||
<IconButton
|
<IconButton
|
||||||
|
|||||||
@@ -37,6 +37,11 @@ async function _getCurrentToken() {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const _enabled = {
|
||||||
|
demo: [],
|
||||||
|
AFFiNE: ['sqlite'],
|
||||||
|
} as any;
|
||||||
|
|
||||||
async function _getBlockDatabase(
|
async function _getBlockDatabase(
|
||||||
workspace: string,
|
workspace: string,
|
||||||
options?: BlockInitOptions
|
options?: BlockInitOptions
|
||||||
@@ -45,16 +50,10 @@ async function _getBlockDatabase(
|
|||||||
await waitLoading(workspace);
|
await waitLoading(workspace);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (
|
|
||||||
// options?.userId &&
|
|
||||||
// workspaces[workspace]?.getUserId() !== options?.userId
|
|
||||||
// ) {
|
|
||||||
// delete workspaces[workspace];
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (!workspaces[workspace]) {
|
if (!workspaces[workspace]) {
|
||||||
loading.add(workspace);
|
loading.add(workspace);
|
||||||
workspaces[workspace] = await BlockClient.init(workspace, {
|
workspaces[workspace] = await BlockClient.init(workspace, {
|
||||||
|
enabled: _enabled[workspace] || ['idb'],
|
||||||
...options,
|
...options,
|
||||||
token: await _getCurrentToken(),
|
token: await _getCurrentToken(),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ import {
|
|||||||
snapshot,
|
snapshot,
|
||||||
} from 'yjs';
|
} from 'yjs';
|
||||||
|
|
||||||
import { IndexedDBProvider } from '@toeverything/datasource/jwt-rpc';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
AsyncDatabaseAdapter,
|
AsyncDatabaseAdapter,
|
||||||
BlockListener,
|
BlockListener,
|
||||||
@@ -48,15 +46,17 @@ type ConnectivityListener = (
|
|||||||
workspace: string,
|
workspace: string,
|
||||||
connectivity: Connectivity
|
connectivity: Connectivity
|
||||||
) => void;
|
) => void;
|
||||||
|
|
||||||
type YjsProviders = {
|
type YjsProviders = {
|
||||||
awareness: Awareness;
|
awareness: Awareness;
|
||||||
idb: IndexedDBProvider;
|
binaries: Doc;
|
||||||
binariesIdb: IndexedDBProvider;
|
doc: Doc;
|
||||||
gatekeeper: GateKeeper;
|
gatekeeper: GateKeeper;
|
||||||
connListener: { listeners?: ConnectivityListener };
|
connListener: { listeners?: ConnectivityListener };
|
||||||
userId: string;
|
userId: string;
|
||||||
remoteToken?: string; // remote storage token
|
remoteToken?: string; // remote storage token
|
||||||
};
|
};
|
||||||
|
|
||||||
const _yjsDatabaseInstance = new Map<string, YjsProviders>();
|
const _yjsDatabaseInstance = new Map<string, YjsProviders>();
|
||||||
|
|
||||||
const _asyncInitLoading = new Set<string>();
|
const _asyncInitLoading = new Set<string>();
|
||||||
@@ -90,13 +90,9 @@ async function _initYjsDatabase(
|
|||||||
const { userId, token } = options;
|
const { userId, token } = options;
|
||||||
|
|
||||||
const doc = new Doc({ autoLoad: true, shouldLoad: true });
|
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 binaries = new Doc({ autoLoad: true, shouldLoad: true });
|
||||||
const binariesIdb = await new IndexedDBProvider(
|
|
||||||
`${workspace}_binaries`,
|
|
||||||
binaries
|
|
||||||
).whenSynced;
|
|
||||||
|
|
||||||
const awareness = new Awareness(doc);
|
const awareness = new Awareness(doc);
|
||||||
|
|
||||||
@@ -114,16 +110,24 @@ async function _initYjsDatabase(
|
|||||||
const emitState = (c: Connectivity) =>
|
const emitState = (c: Connectivity) =>
|
||||||
connListener.listeners?.(workspace, c);
|
connListener.listeners?.(workspace, c);
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
Object.entries(options.provider).map(async ([, p]) =>
|
Object.entries(options.provider).flatMap(async ([, p]) => [
|
||||||
p({ awareness, doc, token, workspace, emitState })
|
p({ awareness, doc, token, workspace, emitState }),
|
||||||
)
|
p({
|
||||||
|
awareness,
|
||||||
|
doc: binaries,
|
||||||
|
token,
|
||||||
|
workspace: `${workspace}_binaries`,
|
||||||
|
emitState,
|
||||||
|
}),
|
||||||
|
])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const newInstance = {
|
const newInstance = {
|
||||||
awareness,
|
awareness,
|
||||||
idb,
|
binaries,
|
||||||
binariesIdb,
|
doc,
|
||||||
gatekeeper,
|
gatekeeper,
|
||||||
|
|
||||||
connListener,
|
connListener,
|
||||||
userId,
|
userId,
|
||||||
remoteToken: token,
|
remoteToken: token,
|
||||||
@@ -183,7 +187,7 @@ export class YjsAdapter implements AsyncDatabaseAdapter<YjsContentOperation> {
|
|||||||
|
|
||||||
private constructor(providers: YjsProviders) {
|
private constructor(providers: YjsProviders) {
|
||||||
this._provider = providers;
|
this._provider = providers;
|
||||||
this._doc = providers.idb.doc;
|
this._doc = providers.doc;
|
||||||
this._awareness = providers.awareness;
|
this._awareness = providers.awareness;
|
||||||
this._gatekeeper = providers.gatekeeper;
|
this._gatekeeper = providers.gatekeeper;
|
||||||
this._reload = () => {
|
this._reload = () => {
|
||||||
@@ -201,7 +205,7 @@ export class YjsAdapter implements AsyncDatabaseAdapter<YjsContentOperation> {
|
|||||||
});
|
});
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
this._binaries = new YjsRemoteBinaries(
|
this._binaries = new YjsRemoteBinaries(
|
||||||
providers.binariesIdb.doc.getMap(),
|
providers.binaries.getMap(),
|
||||||
providers.remoteToken
|
providers.remoteToken
|
||||||
);
|
);
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
@@ -336,7 +340,7 @@ export class YjsAdapter implements AsyncDatabaseAdapter<YjsContentOperation> {
|
|||||||
});
|
});
|
||||||
const [file] = (await fromEvent(handles)) as File[];
|
const [file] = (await fromEvent(handles)) as File[];
|
||||||
const binary = await file.arrayBuffer();
|
const binary = await file.arrayBuffer();
|
||||||
await this._provider.idb.clearData();
|
// await this._provider.idb.clearData();
|
||||||
const doc = new Doc({ autoLoad: true, shouldLoad: true });
|
const doc = new Doc({ autoLoad: true, shouldLoad: true });
|
||||||
let updated = 0;
|
let updated = 0;
|
||||||
let isUpdated = false;
|
let isUpdated = false;
|
||||||
@@ -357,8 +361,8 @@ export class YjsAdapter implements AsyncDatabaseAdapter<YjsContentOperation> {
|
|||||||
};
|
};
|
||||||
check();
|
check();
|
||||||
});
|
});
|
||||||
await new IndexedDBProvider(this._provider.idb.name, doc)
|
// await new IndexedDBProvider(this._provider.idb.name, doc)
|
||||||
.whenSynced;
|
// .whenSynced;
|
||||||
applyUpdate(doc, new Uint8Array(binary));
|
applyUpdate(doc, new Uint8Array(binary));
|
||||||
await update_check;
|
await update_check;
|
||||||
console.log('load success');
|
console.log('load success');
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { Doc } from 'yjs';
|
|||||||
import { Awareness } from 'y-protocols/awareness.js';
|
import { Awareness } from 'y-protocols/awareness.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
IndexedDBProvider,
|
||||||
SQLiteProvider,
|
SQLiteProvider,
|
||||||
WebsocketProvider,
|
WebsocketProvider,
|
||||||
} from '@toeverything/datasource/jwt-rpc';
|
} from '@toeverything/datasource/jwt-rpc';
|
||||||
@@ -19,7 +20,10 @@ type YjsDefaultInstances = {
|
|||||||
|
|
||||||
export type YjsProvider = (instances: YjsDefaultInstances) => Promise<void>;
|
export type YjsProvider = (instances: YjsDefaultInstances) => Promise<void>;
|
||||||
|
|
||||||
|
type ProviderType = 'idb' | 'sqlite' | 'ws';
|
||||||
|
|
||||||
export type YjsProviderOptions = {
|
export type YjsProviderOptions = {
|
||||||
|
enabled: ProviderType[];
|
||||||
backend: typeof BucketBackend[keyof typeof BucketBackend];
|
backend: typeof BucketBackend[keyof typeof BucketBackend];
|
||||||
params?: Record<string, string>;
|
params?: Record<string, string>;
|
||||||
importData?: () => Promise<Uint8Array> | Uint8Array | undefined;
|
importData?: () => Promise<Uint8Array> | Uint8Array | undefined;
|
||||||
@@ -30,53 +34,64 @@ export type YjsProviderOptions = {
|
|||||||
export const getYjsProviders = (
|
export const getYjsProviders = (
|
||||||
options: YjsProviderOptions
|
options: YjsProviderOptions
|
||||||
): Record<string, YjsProvider> => {
|
): Record<string, YjsProvider> => {
|
||||||
|
console.log('getYjsProviders', options);
|
||||||
return {
|
return {
|
||||||
|
indexeddb: async (instances: YjsDefaultInstances) => {
|
||||||
|
if (options.enabled.includes('idb')) {
|
||||||
|
await new IndexedDBProvider(instances.workspace, instances.doc)
|
||||||
|
.whenSynced;
|
||||||
|
}
|
||||||
|
},
|
||||||
sqlite: async (instances: YjsDefaultInstances) => {
|
sqlite: async (instances: YjsDefaultInstances) => {
|
||||||
const fsHandle = setInterval(async () => {
|
if (options.enabled.includes('sqlite')) {
|
||||||
if (options.hasExporter?.()) {
|
const fsHandle = setInterval(async () => {
|
||||||
clearInterval(fsHandle);
|
if (options.hasExporter?.()) {
|
||||||
const fs = new SQLiteProvider(
|
clearInterval(fsHandle);
|
||||||
instances.workspace,
|
const fs = new SQLiteProvider(
|
||||||
instances.doc,
|
instances.workspace,
|
||||||
await options.importData?.()
|
instances.doc,
|
||||||
);
|
await options.importData?.()
|
||||||
if (options.exportData) {
|
);
|
||||||
fs.registerExporter(options.exportData);
|
if (options.exportData) {
|
||||||
|
fs.registerExporter(options.exportData);
|
||||||
|
}
|
||||||
|
await fs.whenSynced;
|
||||||
}
|
}
|
||||||
await fs.whenSynced;
|
}, 500);
|
||||||
}
|
}
|
||||||
}, 500);
|
|
||||||
},
|
},
|
||||||
ws: async (instances: YjsDefaultInstances) => {
|
ws: async (instances: YjsDefaultInstances) => {
|
||||||
if (instances.token) {
|
if (options.enabled.includes('ws')) {
|
||||||
const ws = new WebsocketProvider(
|
if (instances.token) {
|
||||||
instances.token,
|
const ws = new WebsocketProvider(
|
||||||
options.backend,
|
instances.token,
|
||||||
instances.workspace,
|
options.backend,
|
||||||
instances.doc,
|
instances.workspace,
|
||||||
{
|
instances.doc,
|
||||||
awareness: instances.awareness,
|
{
|
||||||
params: options.params,
|
awareness: instances.awareness,
|
||||||
}
|
params: options.params,
|
||||||
) as any; // TODO: type is erased after cascading references
|
}
|
||||||
|
) 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
|
// Wait for ws synchronization to complete, otherwise the data will be modified in reverse, which can be optimized later
|
||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
// TODO: synced will also be triggered on reconnection after losing sync
|
// 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
|
// There needs to be an event mechanism to emit the synchronization state to the upper layer
|
||||||
ws.once('synced', () => resolve());
|
ws.once('synced', () => resolve());
|
||||||
ws.once('lost-connection', () => resolve());
|
ws.once('lost-connection', () => resolve());
|
||||||
ws.once('connection-error', () => reject());
|
ws.once('connection-error', () => reject());
|
||||||
ws.on('synced', () => instances.emitState('connected'));
|
ws.on('synced', () => instances.emitState('connected'));
|
||||||
ws.on('lost-connection', () =>
|
ws.on('lost-connection', () =>
|
||||||
instances.emitState('retry')
|
instances.emitState('retry')
|
||||||
);
|
);
|
||||||
ws.on('connection-error', () =>
|
ws.on('connection-error', () =>
|
||||||
instances.emitState('retry')
|
instances.emitState('retry')
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -618,6 +618,7 @@ export class BlockClient<
|
|||||||
|
|
||||||
const instance = await YjsAdapter.init(workspace, {
|
const instance = await YjsAdapter.init(workspace, {
|
||||||
provider: getYjsProviders({
|
provider: getYjsProviders({
|
||||||
|
enabled: [],
|
||||||
backend: BucketBackend.YjsWebSocketAffine,
|
backend: BucketBackend.YjsWebSocketAffine,
|
||||||
importData,
|
importData,
|
||||||
exportData,
|
exportData,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { useNavigate } from 'react-router';
|
||||||
import {
|
import {
|
||||||
getAuth,
|
getAuth,
|
||||||
onAuthStateChanged,
|
onAuthStateChanged,
|
||||||
@@ -62,11 +63,17 @@ const BRAND_ID = 'AFFiNE';
|
|||||||
|
|
||||||
const _localTrigger = atom<boolean>(false);
|
const _localTrigger = atom<boolean>(false);
|
||||||
const _useUserAndSpacesForFreeLogin = () => {
|
const _useUserAndSpacesForFreeLogin = () => {
|
||||||
|
const navigate = useNavigate();
|
||||||
const [user, setUser] = useAtom(_userAtom);
|
const [user, setUser] = useAtom(_userAtom);
|
||||||
const [loading, setLoading] = useAtom(_loadingAtom);
|
const [loading, setLoading] = useAtom(_loadingAtom);
|
||||||
const [localTrigger] = useAtom(_localTrigger);
|
const [localTrigger] = useAtom(_localTrigger);
|
||||||
|
|
||||||
useEffect(() => setLoading(false), []);
|
useEffect(() => {
|
||||||
|
if (loading) {
|
||||||
|
navigate('/demo');
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (localTrigger) {
|
if (localTrigger) {
|
||||||
@@ -77,6 +84,14 @@ const _useUserAndSpacesForFreeLogin = () => {
|
|||||||
nickname: BRAND_ID,
|
nickname: BRAND_ID,
|
||||||
email: '',
|
email: '',
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
setUser({
|
||||||
|
photo: '',
|
||||||
|
id: 'demo',
|
||||||
|
username: 'demo',
|
||||||
|
nickname: 'demo',
|
||||||
|
email: '',
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}, [localTrigger, setLoading, setUser]);
|
}, [localTrigger, setLoading, setUser]);
|
||||||
|
|
||||||
@@ -86,8 +101,8 @@ const _useUserAndSpacesForFreeLogin = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const useLocalTrigger = () => {
|
export const useLocalTrigger = () => {
|
||||||
const [, setTrigger] = useAtom(_localTrigger);
|
const [trigger, setTrigger] = useAtom(_localTrigger);
|
||||||
return () => setTrigger(true);
|
return [trigger, () => setTrigger(true)] as [boolean, () => void];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useUserAndSpaces = process.env['NX_LOCAL']
|
export const useUserAndSpaces = process.env['NX_LOCAL']
|
||||||
|
|||||||
47
pnpm-lock.yaml
generated
47
pnpm-lock.yaml
generated
@@ -194,7 +194,7 @@ importers:
|
|||||||
yjs: ^13.5.41
|
yjs: ^13.5.41
|
||||||
dependencies:
|
dependencies:
|
||||||
authing-js-sdk: 4.23.35
|
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
|
lib0: 0.2.52
|
||||||
lru-cache: 7.13.2
|
lru-cache: 7.13.2
|
||||||
nanoid: 4.0.0
|
nanoid: 4.0.0
|
||||||
@@ -571,6 +571,9 @@ importers:
|
|||||||
dependencies:
|
dependencies:
|
||||||
ffc-js-client-side-sdk: 1.1.5
|
ffc-js-client-side-sdk: 1.1.5
|
||||||
|
|
||||||
|
libs/datasource/jwst/pkg:
|
||||||
|
specifiers: {}
|
||||||
|
|
||||||
libs/datasource/jwt:
|
libs/datasource/jwt:
|
||||||
specifiers:
|
specifiers:
|
||||||
'@types/debug': ^4.1.7
|
'@types/debug': ^4.1.7
|
||||||
@@ -3291,6 +3294,15 @@ packages:
|
|||||||
- utf-8-validate
|
- utf-8-validate
|
||||||
dev: true
|
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:
|
/@firebase/auth-interop-types/0.1.6_pbfwexsq7uf6mrzcwnikj3g37m:
|
||||||
resolution: {integrity: sha512-etIi92fW3CctsmR9e3sYM3Uqnoq861M0Id9mdOPF6PWIg38BXL5k4upCNBggGUpLIS0H1grMOvy/wn1xymwe2g==}
|
resolution: {integrity: sha512-etIi92fW3CctsmR9e3sYM3Uqnoq861M0Id9mdOPF6PWIg38BXL5k4upCNBggGUpLIS0H1grMOvy/wn1xymwe2g==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -3299,6 +3311,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@firebase/app-types': 0.7.0
|
'@firebase/app-types': 0.7.0
|
||||||
'@firebase/util': 1.6.3
|
'@firebase/util': 1.6.3
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@firebase/auth-types/0.11.0_pbfwexsq7uf6mrzcwnikj3g37m:
|
/@firebase/auth-types/0.11.0_pbfwexsq7uf6mrzcwnikj3g37m:
|
||||||
resolution: {integrity: sha512-q7Bt6cx+ySj9elQHTsKulwk3+qDezhzRBFC9zlQ1BjgMueUOnGMcvqmU0zuKlQ4RhLSH7MNAdBV2znVaoN3Vxw==}
|
resolution: {integrity: sha512-q7Bt6cx+ySj9elQHTsKulwk3+qDezhzRBFC9zlQ1BjgMueUOnGMcvqmU0zuKlQ4RhLSH7MNAdBV2znVaoN3Vxw==}
|
||||||
@@ -3334,6 +3347,19 @@ packages:
|
|||||||
'@firebase/util': 1.6.3
|
'@firebase/util': 1.6.3
|
||||||
tslib: 2.4.0
|
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:
|
/@firebase/database-compat/0.2.4_@firebase+app-types@0.7.0:
|
||||||
resolution: {integrity: sha512-VtsGixO5mTjNMJn6PwxAJEAR70fj+3blCXIdQKel3q+eYGZAfdqxox1+tzZDnf9NWBJpaOgAHPk3JVDxEo9NFQ==}
|
resolution: {integrity: sha512-VtsGixO5mTjNMJn6PwxAJEAR70fj+3blCXIdQKel3q+eYGZAfdqxox1+tzZDnf9NWBJpaOgAHPk3JVDxEo9NFQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -3345,6 +3371,7 @@ packages:
|
|||||||
tslib: 2.4.0
|
tslib: 2.4.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@firebase/app-types'
|
- '@firebase/app-types'
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@firebase/database-types/0.9.10:
|
/@firebase/database-types/0.9.10:
|
||||||
resolution: {integrity: sha512-2ji6nXRRsY+7hgU6zRhUtK0RmSjVWM71taI7Flgaw+BnopCo/lDF5HSwxp8z7LtiHlvQqeRA3Ozqx5VhlAbiKg==}
|
resolution: {integrity: sha512-2ji6nXRRsY+7hgU6zRhUtK0RmSjVWM71taI7Flgaw+BnopCo/lDF5HSwxp8z7LtiHlvQqeRA3Ozqx5VhlAbiKg==}
|
||||||
@@ -3359,6 +3386,19 @@ packages:
|
|||||||
'@firebase/app-types': 0.7.0
|
'@firebase/app-types': 0.7.0
|
||||||
'@firebase/util': 1.6.3
|
'@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:
|
/@firebase/database/0.13.4_@firebase+app-types@0.7.0:
|
||||||
resolution: {integrity: sha512-NW7bOoiaC4sJCj6DY/m9xHoFNa0CK32YPMCh6FiMweLCDQbOZM8Ql/Kn6yyuxCb7K7ypz9eSbRlCWQJsJRQjhg==}
|
resolution: {integrity: sha512-NW7bOoiaC4sJCj6DY/m9xHoFNa0CK32YPMCh6FiMweLCDQbOZM8Ql/Kn6yyuxCb7K7ypz9eSbRlCWQJsJRQjhg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -3370,6 +3410,7 @@ packages:
|
|||||||
tslib: 2.4.0
|
tslib: 2.4.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@firebase/app-types'
|
- '@firebase/app-types'
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@firebase/firestore-compat/0.1.23_53yvy43rwpg2c45kgeszsxtrca:
|
/@firebase/firestore-compat/0.1.23_53yvy43rwpg2c45kgeszsxtrca:
|
||||||
resolution: {integrity: sha512-QfcuyMAavp//fQnjSfCEpnbWi7spIdKaXys1kOLu7395fLr+U6ykmto1HUMCSz8Yus9cEr/03Ujdi2SUl2GUAA==}
|
resolution: {integrity: sha512-QfcuyMAavp//fQnjSfCEpnbWi7spIdKaXys1kOLu7395fLr+U6ykmto1HUMCSz8Yus9cEr/03Ujdi2SUl2GUAA==}
|
||||||
@@ -10863,12 +10904,12 @@ packages:
|
|||||||
semver-regex: 2.0.0
|
semver-regex: 2.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/firebase-admin/11.0.1_@firebase+app-types@0.7.0:
|
/firebase-admin/11.0.1:
|
||||||
resolution: {integrity: sha512-rL3wlZbi2Kb/KJgcmj1YHlD4ZhfmhfgRO2YJialxAllm0tj1IQea878hHuBLGmv4DpbW9t9nLvX9kddNR2Y65Q==}
|
resolution: {integrity: sha512-rL3wlZbi2Kb/KJgcmj1YHlD4ZhfmhfgRO2YJialxAllm0tj1IQea878hHuBLGmv4DpbW9t9nLvX9kddNR2Y65Q==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@fastify/busboy': 1.1.0
|
'@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
|
'@firebase/database-types': 0.9.10
|
||||||
'@types/node': 18.0.1
|
'@types/node': 18.0.1
|
||||||
jsonwebtoken: 8.5.1
|
jsonwebtoken: 8.5.1
|
||||||
|
|||||||
Reference in New Issue
Block a user