ci(core): eslint errors for core (#4662)
This commit is contained in:
@@ -58,7 +58,7 @@ const createPattern = packageName => [
|
|||||||
const allPackages = [
|
const allPackages = [
|
||||||
'packages/backend/server',
|
'packages/backend/server',
|
||||||
'packages/frontend/component',
|
'packages/frontend/component',
|
||||||
'packages/frontend/web',
|
'packages/frontend/core',
|
||||||
'packages/frontend/electron',
|
'packages/frontend/electron',
|
||||||
'packages/frontend/graphql',
|
'packages/frontend/graphql',
|
||||||
'packages/frontend/hooks',
|
'packages/frontend/hooks',
|
||||||
@@ -255,6 +255,12 @@ const config = {
|
|||||||
],
|
],
|
||||||
'@typescript-eslint/no-misused-promises': ['error'],
|
'@typescript-eslint/no-misused-promises': ['error'],
|
||||||
'i/no-extraneous-dependencies': ['error'],
|
'i/no-extraneous-dependencies': ['error'],
|
||||||
|
'react-hooks/exhaustive-deps': [
|
||||||
|
'warn',
|
||||||
|
{
|
||||||
|
additionalHooks: 'useAsyncCallback',
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
})),
|
})),
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -51,7 +51,6 @@
|
|||||||
"jotai-effect": "^0.2.2",
|
"jotai-effect": "^0.2.2",
|
||||||
"jotai-scope": "^0.4.0",
|
"jotai-scope": "^0.4.0",
|
||||||
"lit": "^3.0.2",
|
"lit": "^3.0.2",
|
||||||
"lodash": "^4.17.21",
|
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"lottie-react": "^2.4.0",
|
"lottie-react": "^2.4.0",
|
||||||
"lottie-web": "^5.12.2",
|
"lottie-web": "^5.12.2",
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Skeleton } from '@mui/material';
|
|||||||
import { assignInlineVars } from '@vanilla-extract/dynamic';
|
import { assignInlineVars } from '@vanilla-extract/dynamic';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { useAtom, useAtomValue } from 'jotai';
|
import { useAtom, useAtomValue } from 'jotai';
|
||||||
import debounce from 'lodash/debounce';
|
import { debounce } from 'lodash-es';
|
||||||
import type { PropsWithChildren, ReactElement } from 'react';
|
import type { PropsWithChildren, ReactElement } from 'react';
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@affine-test/fixtures": "workspace:*",
|
"@affine-test/fixtures": "workspace:*",
|
||||||
|
"@affine/cmdk": "workspace:*",
|
||||||
"@affine/component": "workspace:*",
|
"@affine/component": "workspace:*",
|
||||||
"@affine/debug": "workspace:*",
|
"@affine/debug": "workspace:*",
|
||||||
"@affine/env": "workspace:*",
|
"@affine/env": "workspace:*",
|
||||||
@@ -31,6 +32,7 @@
|
|||||||
"@blocksuite/icons": "2.1.35",
|
"@blocksuite/icons": "2.1.35",
|
||||||
"@blocksuite/lit": "0.0.0-20231110042432-4fdac4dc-nightly",
|
"@blocksuite/lit": "0.0.0-20231110042432-4fdac4dc-nightly",
|
||||||
"@blocksuite/store": "0.0.0-20231110042432-4fdac4dc-nightly",
|
"@blocksuite/store": "0.0.0-20231110042432-4fdac4dc-nightly",
|
||||||
|
"@blocksuite/virgo": "0.0.0-20231110042432-4fdac4dc-nightly",
|
||||||
"@dnd-kit/core": "^6.0.8",
|
"@dnd-kit/core": "^6.0.8",
|
||||||
"@dnd-kit/sortable": "^7.0.2",
|
"@dnd-kit/sortable": "^7.0.2",
|
||||||
"@emotion/cache": "^11.11.0",
|
"@emotion/cache": "^11.11.0",
|
||||||
@@ -39,31 +41,44 @@
|
|||||||
"@emotion/styled": "^11.11.0",
|
"@emotion/styled": "^11.11.0",
|
||||||
"@marsidev/react-turnstile": "^0.3.1",
|
"@marsidev/react-turnstile": "^0.3.1",
|
||||||
"@mui/material": "^5.14.14",
|
"@mui/material": "^5.14.14",
|
||||||
|
"@radix-ui/react-collapsible": "^1.0.3",
|
||||||
|
"@radix-ui/react-dialog": "^1.0.4",
|
||||||
|
"@radix-ui/react-scroll-area": "^1.0.5",
|
||||||
"@radix-ui/react-select": "^2.0.0",
|
"@radix-ui/react-select": "^2.0.0",
|
||||||
"@react-hookz/web": "^23.1.0",
|
"@react-hookz/web": "^23.1.0",
|
||||||
"@toeverything/components": "^0.0.46",
|
"@toeverything/components": "^0.0.46",
|
||||||
|
"@toeverything/theme": "^0.7.20",
|
||||||
|
"@vanilla-extract/css": "^1.13.0",
|
||||||
|
"@vanilla-extract/dynamic": "^2.0.3",
|
||||||
"async-call-rpc": "^6.3.1",
|
"async-call-rpc": "^6.3.1",
|
||||||
"bytes": "^3.1.2",
|
"bytes": "^3.1.2",
|
||||||
|
"clsx": "^2.0.0",
|
||||||
"css-spring": "^4.1.0",
|
"css-spring": "^4.1.0",
|
||||||
"cssnano": "^6.0.1",
|
"cssnano": "^6.0.1",
|
||||||
|
"dayjs": "^1.11.10",
|
||||||
|
"foxact": "^0.2.20",
|
||||||
"graphql": "^16.8.1",
|
"graphql": "^16.8.1",
|
||||||
|
"idb": "^7.1.1",
|
||||||
"intl-segmenter-polyfill-rs": "^0.1.6",
|
"intl-segmenter-polyfill-rs": "^0.1.6",
|
||||||
"jotai": "^2.4.3",
|
"jotai": "^2.4.3",
|
||||||
"jotai-devtools": "^0.7.0",
|
"jotai-devtools": "^0.7.0",
|
||||||
"lit": "^3.0.2",
|
"lit": "^3.0.2",
|
||||||
"lottie-web": "^5.12.2",
|
"lottie-web": "^5.12.2",
|
||||||
"mini-css-extract-plugin": "^2.7.6",
|
"mini-css-extract-plugin": "^2.7.6",
|
||||||
|
"nanoid": "^5.0.1",
|
||||||
"next-auth": "^4.23.2",
|
"next-auth": "^4.23.2",
|
||||||
"next-themes": "^0.2.1",
|
"next-themes": "^0.2.1",
|
||||||
"postcss-loader": "^7.3.3",
|
"postcss-loader": "^7.3.3",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
|
"react-error-boundary": "^4.0.11",
|
||||||
"react-is": "18.2.0",
|
"react-is": "18.2.0",
|
||||||
"react-resizable-panels": "^0.0.55",
|
"react-resizable-panels": "^0.0.55",
|
||||||
"react-router-dom": "^6.16.0",
|
"react-router-dom": "^6.16.0",
|
||||||
"rxjs": "^7.8.1",
|
"rxjs": "^7.8.1",
|
||||||
"ses": "^0.18.8",
|
"ses": "^0.18.8",
|
||||||
"swr": "2.2.4",
|
"swr": "2.2.4",
|
||||||
|
"uuid": "^9.0.1",
|
||||||
"valtio": "^1.11.2",
|
"valtio": "^1.11.2",
|
||||||
"y-protocols": "^1.0.6",
|
"y-protocols": "^1.0.6",
|
||||||
"yjs": "^13.6.8",
|
"yjs": "^13.6.8",
|
||||||
@@ -76,12 +91,15 @@
|
|||||||
"@sentry/webpack-plugin": "^2.8.0",
|
"@sentry/webpack-plugin": "^2.8.0",
|
||||||
"@svgr/webpack": "^8.1.0",
|
"@svgr/webpack": "^8.1.0",
|
||||||
"@swc/core": "^1.3.93",
|
"@swc/core": "^1.3.93",
|
||||||
|
"@testing-library/react": "^14.0.0",
|
||||||
"@types/bytes": "^3.1.3",
|
"@types/bytes": "^3.1.3",
|
||||||
"@types/lodash-es": "^4.17.9",
|
"@types/lodash-es": "^4.17.9",
|
||||||
|
"@types/uuid": "^9.0.5",
|
||||||
"@types/webpack-env": "^1.18.2",
|
"@types/webpack-env": "^1.18.2",
|
||||||
"copy-webpack-plugin": "^11.0.0",
|
"copy-webpack-plugin": "^11.0.0",
|
||||||
"css-loader": "^6.8.1",
|
"css-loader": "^6.8.1",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
|
"fake-indexeddb": "^5.0.0",
|
||||||
"html-webpack-plugin": "^5.5.3",
|
"html-webpack-plugin": "^5.5.3",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"mime-types": "^2.1.35",
|
"mime-types": "^2.1.35",
|
||||||
@@ -91,6 +109,7 @@
|
|||||||
"swc-loader": "^0.2.3",
|
"swc-loader": "^0.2.3",
|
||||||
"swc-plugin-coverage-instrument": "^0.0.20",
|
"swc-plugin-coverage-instrument": "^0.0.20",
|
||||||
"thread-loader": "^4.0.2",
|
"thread-loader": "^4.0.2",
|
||||||
|
"vitest": "0.34.6",
|
||||||
"webpack": "^5.89.0",
|
"webpack": "^5.89.0",
|
||||||
"webpack-cli": "^5.1.4",
|
"webpack-cli": "^5.1.4",
|
||||||
"webpack-dev-server": "^4.15.1",
|
"webpack-dev-server": "^4.15.1",
|
||||||
|
|||||||
@@ -147,36 +147,49 @@ export const pageCollectionBaseAtom =
|
|||||||
|
|
||||||
return new Observable<BaseCollectionsDataType>(subscriber => {
|
return new Observable<BaseCollectionsDataType>(subscriber => {
|
||||||
const group = new DisposableGroup();
|
const group = new DisposableGroup();
|
||||||
currentWorkspacePromise.then(async currentWorkspace => {
|
currentWorkspacePromise
|
||||||
const workspaceSetting = getWorkspaceSetting(currentWorkspace);
|
.then(async currentWorkspace => {
|
||||||
migrateCollectionsFromIdbData(currentWorkspace).then(collections => {
|
const workspaceSetting = getWorkspaceSetting(currentWorkspace);
|
||||||
if (collections.length) {
|
migrateCollectionsFromIdbData(currentWorkspace)
|
||||||
workspaceSetting.addCollection(...collections);
|
.then(collections => {
|
||||||
}
|
if (collections.length) {
|
||||||
});
|
workspaceSetting.addCollection(...collections);
|
||||||
migrateCollectionsFromUserData(currentWorkspace).then(collections => {
|
}
|
||||||
if (collections.length) {
|
})
|
||||||
workspaceSetting.addCollection(...collections);
|
.catch(error => {
|
||||||
}
|
console.error(error);
|
||||||
});
|
});
|
||||||
subscriber.next({
|
migrateCollectionsFromUserData(currentWorkspace)
|
||||||
loading: false,
|
.then(collections => {
|
||||||
collections: workspaceSetting.collections,
|
if (collections.length) {
|
||||||
});
|
workspaceSetting.addCollection(...collections);
|
||||||
if (group.disposed) {
|
}
|
||||||
return;
|
})
|
||||||
}
|
.catch(error => {
|
||||||
const fn = () => {
|
console.error(error);
|
||||||
|
});
|
||||||
subscriber.next({
|
subscriber.next({
|
||||||
loading: false,
|
loading: false,
|
||||||
collections: workspaceSetting.collections,
|
collections: workspaceSetting.collections,
|
||||||
});
|
});
|
||||||
};
|
if (group.disposed) {
|
||||||
workspaceSetting.collectionsYArray.observe(fn);
|
return;
|
||||||
group.add(() => {
|
}
|
||||||
workspaceSetting.collectionsYArray.unobserve(fn);
|
const fn = () => {
|
||||||
|
subscriber.next({
|
||||||
|
loading: false,
|
||||||
|
collections: workspaceSetting.collections,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
workspaceSetting.collectionsYArray.observe(fn);
|
||||||
|
group.add(() => {
|
||||||
|
workspaceSetting.collectionsYArray.unobserve(fn);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
subscriber.error(error);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
return () => {
|
return () => {
|
||||||
group.dispose();
|
group.dispose();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
import { Trans } from '@affine/i18n';
|
import { Trans } from '@affine/i18n';
|
||||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||||
import { Button } from '@toeverything/components/button';
|
import { Button } from '@toeverything/components/button';
|
||||||
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
import React, { useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
|
|
||||||
import { useCurrentLoginStatus } from '../../../hooks/affine/use-current-login-status';
|
import { useCurrentLoginStatus } from '../../../hooks/affine/use-current-login-status';
|
||||||
@@ -31,7 +32,7 @@ export const AfterSignInSendEmail = ({
|
|||||||
onSignedIn?.();
|
onSignedIn?.();
|
||||||
}
|
}
|
||||||
|
|
||||||
const onResendClick = useCallback(async () => {
|
const onResendClick = useAsyncCallback(async () => {
|
||||||
if (verifyToken) {
|
if (verifyToken) {
|
||||||
await signIn(email, verifyToken, challenge);
|
await signIn(email, verifyToken, challenge);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
} from '@affine/component/auth-components';
|
} from '@affine/component/auth-components';
|
||||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||||
import { Button } from '@toeverything/components/button';
|
import { Button } from '@toeverything/components/button';
|
||||||
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
import { type FC, useCallback } from 'react';
|
import { type FC, useCallback } from 'react';
|
||||||
|
|
||||||
import { useCurrentLoginStatus } from '../../../hooks/affine/use-current-login-status';
|
import { useCurrentLoginStatus } from '../../../hooks/affine/use-current-login-status';
|
||||||
@@ -29,7 +30,7 @@ export const AfterSignUpSendEmail: FC<AuthPanelProps> = ({
|
|||||||
onSignedIn?.();
|
onSignedIn?.();
|
||||||
}
|
}
|
||||||
|
|
||||||
const onResendClick = useCallback(async () => {
|
const onResendClick = useAsyncCallback(async () => {
|
||||||
if (verifyToken) {
|
if (verifyToken) {
|
||||||
await signUp(email, verifyToken, challenge);
|
await signUp(email, verifyToken, challenge);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||||
import { useMutation } from '@affine/workspace/affine/gql';
|
import { useMutation } from '@affine/workspace/affine/gql';
|
||||||
import { Button } from '@toeverything/components/button';
|
import { Button } from '@toeverything/components/button';
|
||||||
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
import { useSetAtom } from 'jotai/react';
|
import { useSetAtom } from 'jotai/react';
|
||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
|
|
||||||
@@ -146,7 +147,7 @@ export const SendEmail = ({
|
|||||||
const buttonContent = useButtonContent(emailType);
|
const buttonContent = useButtonContent(emailType);
|
||||||
const { loading, sendEmail } = useSendEmail(emailType);
|
const { loading, sendEmail } = useSendEmail(emailType);
|
||||||
|
|
||||||
const onSendEmail = useCallback(async () => {
|
const onSendEmail = useAsyncCallback(async () => {
|
||||||
// TODO: add error handler
|
// TODO: add error handler
|
||||||
await sendEmail(email);
|
await sendEmail(email);
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
} from '@affine/component/auth-components';
|
} from '@affine/component/auth-components';
|
||||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||||
import { Button } from '@toeverything/components/button';
|
import { Button } from '@toeverything/components/button';
|
||||||
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
||||||
import { useSession } from 'next-auth/react';
|
import { useSession } from 'next-auth/react';
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
@@ -26,7 +27,7 @@ export const SignInWithPassword: FC<AuthPanelProps> = ({
|
|||||||
const [password, setPassword] = useState('');
|
const [password, setPassword] = useState('');
|
||||||
const [passwordError, setPasswordError] = useState(false);
|
const [passwordError, setPasswordError] = useState(false);
|
||||||
|
|
||||||
const onSignIn = useCallback(async () => {
|
const onSignIn = useAsyncCallback(async () => {
|
||||||
const res = await signInCloud('credentials', {
|
const res = await signInCloud('credentials', {
|
||||||
redirect: false,
|
redirect: false,
|
||||||
email,
|
email,
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
|||||||
import { useMutation } from '@affine/workspace/affine/gql';
|
import { useMutation } from '@affine/workspace/affine/gql';
|
||||||
import { ArrowDownBigIcon, GoogleDuotoneIcon } from '@blocksuite/icons';
|
import { ArrowDownBigIcon, GoogleDuotoneIcon } from '@blocksuite/icons';
|
||||||
import { Button } from '@toeverything/components/button';
|
import { Button } from '@toeverything/components/button';
|
||||||
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
import { GraphQLError } from 'graphql';
|
import { GraphQLError } from 'graphql';
|
||||||
import { type FC, useState } from 'react';
|
import { type FC, useState } from 'react';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
@@ -52,7 +53,7 @@ export const SignIn: FC<AuthPanelProps> = ({
|
|||||||
onSignedIn?.();
|
onSignedIn?.();
|
||||||
}
|
}
|
||||||
|
|
||||||
const onContinue = useCallback(async () => {
|
const onContinue = useAsyncCallback(async () => {
|
||||||
if (!validateEmail(email)) {
|
if (!validateEmail(email)) {
|
||||||
setIsValidEmail(false);
|
setIsValidEmail(false);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
|||||||
import { useMutation, useQuery } from '@affine/workspace/affine/gql';
|
import { useMutation, useQuery } from '@affine/workspace/affine/gql';
|
||||||
import { Button } from '@toeverything/components/button';
|
import { Button } from '@toeverything/components/button';
|
||||||
import { Loading } from '@toeverything/components/loading';
|
import { Loading } from '@toeverything/components/loading';
|
||||||
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
import { nanoid } from 'nanoid';
|
import { nanoid } from 'nanoid';
|
||||||
import { Suspense, useCallback, useEffect, useMemo } from 'react';
|
import { Suspense, useCallback, useEffect, useMemo } from 'react';
|
||||||
|
|
||||||
@@ -33,12 +34,12 @@ const usePaymentRedirect = () => {
|
|||||||
mutation: checkoutMutation,
|
mutation: checkoutMutation,
|
||||||
});
|
});
|
||||||
|
|
||||||
return useCallback(() => {
|
return useAsyncCallback(async () => {
|
||||||
checkoutSubscription({ recurring, idempotencyKey })
|
const { checkout } = await checkoutSubscription({
|
||||||
.then(({ checkout }) => {
|
recurring,
|
||||||
window.open(checkout, '_self', 'norefferer');
|
idempotencyKey,
|
||||||
})
|
});
|
||||||
.catch(e => console.error(e));
|
window.open(checkout, '_self', 'norefferer');
|
||||||
}, [recurring, idempotencyKey, checkoutSubscription]);
|
}, [recurring, idempotencyKey, checkoutSubscription]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
Modal,
|
Modal,
|
||||||
} from '@toeverything/components/modal';
|
} from '@toeverything/components/modal';
|
||||||
import { Tooltip } from '@toeverything/components/tooltip';
|
import { Tooltip } from '@toeverything/components/tooltip';
|
||||||
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
import type {
|
import type {
|
||||||
LoadDBFileResult,
|
LoadDBFileResult,
|
||||||
SelectDBFileLocationResult,
|
SelectDBFileLocationResult,
|
||||||
@@ -330,14 +331,13 @@ export const CreateWorkspaceModal = ({
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
const onConfirmName = useCallback(
|
const onConfirmName = useAsyncCallback(
|
||||||
(name: string) => {
|
async (name: string) => {
|
||||||
setWorkspaceName(name);
|
setWorkspaceName(name);
|
||||||
// this will be the last step for web for now
|
// this will be the last step for web for now
|
||||||
// fix me later
|
// fix me later
|
||||||
createLocalWorkspace(name).then(id => {
|
const id = await createLocalWorkspace(name);
|
||||||
onCreate(id);
|
onCreate(id);
|
||||||
});
|
|
||||||
},
|
},
|
||||||
[createLocalWorkspace, onCreate]
|
[createLocalWorkspace, onCreate]
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export const EnableAffineCloudModal = ({
|
|||||||
const setAuthAtom = useSetAtom(authAtom);
|
const setAuthAtom = useSetAtom(authAtom);
|
||||||
const setOnceSignedInEvent = useSetAtom(setOnceSignedInEventAtom);
|
const setOnceSignedInEvent = useSetAtom(setOnceSignedInEventAtom);
|
||||||
|
|
||||||
const confirm = useCallback(async () => {
|
const confirm = useCallback(() => {
|
||||||
return propsOnConfirm?.();
|
return propsOnConfirm?.();
|
||||||
}, [propsOnConfirm]);
|
}, [propsOnConfirm]);
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
import { pushNotificationAtom } from '@affine/component/notification-center';
|
import { pushNotificationAtom } from '@affine/component/notification-center';
|
||||||
import { SettingRow } from '@affine/component/setting-components';
|
import { SettingRow } from '@affine/component/setting-components';
|
||||||
import { isDesktop } from '@affine/env/constant';
|
|
||||||
import type { AffineOfficialWorkspace } from '@affine/env/workspace';
|
import type { AffineOfficialWorkspace } from '@affine/env/workspace';
|
||||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||||
import { Button } from '@toeverything/components/button';
|
import { Button } from '@toeverything/components/button';
|
||||||
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
import type { SaveDBFileResult } from '@toeverything/infra/type';
|
import type { SaveDBFileResult } from '@toeverything/infra/type';
|
||||||
import { useSetAtom } from 'jotai';
|
import { useSetAtom } from 'jotai';
|
||||||
import { useCallback, useState } from 'react';
|
import { useState } from 'react';
|
||||||
import type { Doc } from 'yjs';
|
import type { Doc } from 'yjs';
|
||||||
import { encodeStateAsUpdate } from 'yjs';
|
import { encodeStateAsUpdate } from 'yjs';
|
||||||
|
|
||||||
async function syncBlobsToSqliteDb(workspace: AffineOfficialWorkspace) {
|
async function syncBlobsToSqliteDb(workspace: AffineOfficialWorkspace) {
|
||||||
if (window.apis && isDesktop) {
|
if (window.apis && environment.isDesktop) {
|
||||||
const bs = workspace.blockSuiteWorkspace.blob;
|
const bs = workspace.blockSuiteWorkspace.blob;
|
||||||
const blobsInDb = await window.apis.db.getBlobKeys(workspace.id);
|
const blobsInDb = await window.apis.db.getBlobKeys(workspace.id);
|
||||||
const blobsInStorage = await bs.list();
|
const blobsInStorage = await bs.list();
|
||||||
@@ -32,7 +32,7 @@ async function syncBlobsToSqliteDb(workspace: AffineOfficialWorkspace) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function syncDocsToSqliteDb(workspace: AffineOfficialWorkspace) {
|
async function syncDocsToSqliteDb(workspace: AffineOfficialWorkspace) {
|
||||||
if (window.apis && isDesktop) {
|
if (window.apis && environment.isDesktop) {
|
||||||
const workspaceId = workspace.blockSuiteWorkspace.doc.guid;
|
const workspaceId = workspace.blockSuiteWorkspace.doc.guid;
|
||||||
const syncDoc = async (doc: Doc) => {
|
const syncDoc = async (doc: Doc) => {
|
||||||
await window.apis.db.applyDocUpdate(
|
await window.apis.db.applyDocUpdate(
|
||||||
@@ -56,7 +56,7 @@ export const ExportPanel = ({ workspace }: ExportPanelProps) => {
|
|||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
const [syncing, setSyncing] = useState(false);
|
const [syncing, setSyncing] = useState(false);
|
||||||
const pushNotification = useSetAtom(pushNotificationAtom);
|
const pushNotification = useSetAtom(pushNotificationAtom);
|
||||||
const onExport = useCallback(async () => {
|
const onExport = useAsyncCallback(async () => {
|
||||||
if (syncing) {
|
if (syncing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,8 +77,8 @@ export const ProfilePanel = ({ workspace, isOwner }: ProfilePanelProps) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const handleUploadAvatar = useCallback(
|
const handleUploadAvatar = useCallback(
|
||||||
async (file: File) => {
|
(file: File) => {
|
||||||
await update(file)
|
update(file)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
pushNotification({
|
pushNotification({
|
||||||
title: 'Update workspace avatar success',
|
title: 'Update workspace avatar success',
|
||||||
|
|||||||
@@ -11,9 +11,10 @@ import { WorkspaceFlavour } from '@affine/env/workspace';
|
|||||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||||
import { Button } from '@toeverything/components/button';
|
import { Button } from '@toeverything/components/button';
|
||||||
import { Tooltip } from '@toeverything/components/tooltip';
|
import { Tooltip } from '@toeverything/components/tooltip';
|
||||||
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
import { useBlockSuiteWorkspaceName } from '@toeverything/hooks/use-block-suite-workspace-name';
|
import { useBlockSuiteWorkspaceName } from '@toeverything/hooks/use-block-suite-workspace-name';
|
||||||
import { noop } from 'foxact/noop';
|
import { noop } from 'foxact/noop';
|
||||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import { toast } from '../../../utils';
|
import { toast } from '../../../utils';
|
||||||
import { EnableAffineCloudModal } from '../enable-affine-cloud-modal';
|
import { EnableAffineCloudModal } from '../enable-affine-cloud-modal';
|
||||||
@@ -52,7 +53,7 @@ const PublishPanelAffine = (props: PublishPanelAffineProps) => {
|
|||||||
);
|
);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const copyUrl = useCallback(async () => {
|
const copyUrl = useAsyncCallback(async () => {
|
||||||
await navigator.clipboard.writeText(shareUrl);
|
await navigator.clipboard.writeText(shareUrl);
|
||||||
toast(t['Copied link to clipboard']());
|
toast(t['Copied link to clipboard']());
|
||||||
}, [shareUrl, t]);
|
}, [shareUrl, t]);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import { useMutation, useQuery } from '@affine/workspace/affine/gql';
|
|||||||
import { ArrowRightSmallIcon, CameraIcon } from '@blocksuite/icons';
|
import { ArrowRightSmallIcon, CameraIcon } from '@blocksuite/icons';
|
||||||
import { Avatar } from '@toeverything/components/avatar';
|
import { Avatar } from '@toeverything/components/avatar';
|
||||||
import { Button } from '@toeverything/components/button';
|
import { Button } from '@toeverything/components/button';
|
||||||
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
import { validateAndReduceImage } from '@toeverything/hooks/use-block-suite-workspace-avatar-url';
|
import { validateAndReduceImage } from '@toeverything/hooks/use-block-suite-workspace-avatar-url';
|
||||||
import bytes from 'bytes';
|
import bytes from 'bytes';
|
||||||
import { useSetAtom } from 'jotai';
|
import { useSetAtom } from 'jotai';
|
||||||
@@ -50,7 +51,7 @@ export const UserAvatar = () => {
|
|||||||
mutation: removeAvatarMutation,
|
mutation: removeAvatarMutation,
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleUpdateUserAvatar = useCallback(
|
const handleUpdateUserAvatar = useAsyncCallback(
|
||||||
async (file: File) => {
|
async (file: File) => {
|
||||||
try {
|
try {
|
||||||
const reducedFile = await validateAndReduceImage(file);
|
const reducedFile = await validateAndReduceImage(file);
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import { ArrowRightSmallIcon } from '@blocksuite/icons';
|
|||||||
import { Skeleton } from '@mui/material';
|
import { Skeleton } from '@mui/material';
|
||||||
import { Button, IconButton } from '@toeverything/components/button';
|
import { Button, IconButton } from '@toeverything/components/button';
|
||||||
import { Loading } from '@toeverything/components/loading';
|
import { Loading } from '@toeverything/components/loading';
|
||||||
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
import { useSetAtom } from 'jotai';
|
import { useSetAtom } from 'jotai';
|
||||||
import { Suspense, useCallback, useMemo, useState } from 'react';
|
import { Suspense, useCallback, useMemo, useState } from 'react';
|
||||||
|
|
||||||
@@ -255,8 +256,8 @@ const PaymentMethodUpdater = () => {
|
|||||||
});
|
});
|
||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
|
|
||||||
const update = useCallback(() => {
|
const update = useAsyncCallback(async () => {
|
||||||
trigger(null, {
|
await trigger(null, {
|
||||||
onSuccess: data => {
|
onSuccess: data => {
|
||||||
window.open(data.createCustomerPortal, '_blank', 'noopener noreferrer');
|
window.open(data.createCustomerPortal, '_blank', 'noopener noreferrer');
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,9 +4,10 @@ import {
|
|||||||
resumeSubscriptionMutation,
|
resumeSubscriptionMutation,
|
||||||
} from '@affine/graphql';
|
} from '@affine/graphql';
|
||||||
import { useMutation } from '@affine/workspace/affine/gql';
|
import { useMutation } from '@affine/workspace/affine/gql';
|
||||||
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
import { nanoid } from 'nanoid';
|
import { nanoid } from 'nanoid';
|
||||||
import type { PropsWithChildren } from 'react';
|
import type { PropsWithChildren } from 'react';
|
||||||
import { useCallback, useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
|
||||||
import { ConfirmLoadingModal, DowngradeModal } from './modals';
|
import { ConfirmLoadingModal, DowngradeModal } from './modals';
|
||||||
|
|
||||||
@@ -30,8 +31,8 @@ export const CancelAction = ({
|
|||||||
mutation: cancelSubscriptionMutation,
|
mutation: cancelSubscriptionMutation,
|
||||||
});
|
});
|
||||||
|
|
||||||
const downgrade = useCallback(() => {
|
const downgrade = useAsyncCallback(async () => {
|
||||||
trigger(
|
await trigger(
|
||||||
{ idempotencyKey },
|
{ idempotencyKey },
|
||||||
{
|
{
|
||||||
onSuccess: data => {
|
onSuccess: data => {
|
||||||
@@ -78,8 +79,8 @@ export const ResumeAction = ({
|
|||||||
mutation: resumeSubscriptionMutation,
|
mutation: resumeSubscriptionMutation,
|
||||||
});
|
});
|
||||||
|
|
||||||
const resume = useCallback(() => {
|
const resume = useAsyncCallback(async () => {
|
||||||
trigger(
|
await trigger(
|
||||||
{ idempotencyKey },
|
{ idempotencyKey },
|
||||||
{
|
{
|
||||||
onSuccess: data => {
|
onSuccess: data => {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import { useMutation } from '@affine/workspace/affine/gql';
|
|||||||
import { DoneIcon } from '@blocksuite/icons';
|
import { DoneIcon } from '@blocksuite/icons';
|
||||||
import { Button } from '@toeverything/components/button';
|
import { Button } from '@toeverything/components/button';
|
||||||
import { Tooltip } from '@toeverything/components/tooltip';
|
import { Tooltip } from '@toeverything/components/tooltip';
|
||||||
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
import { useSetAtom } from 'jotai';
|
import { useSetAtom } from 'jotai';
|
||||||
import { useAtom } from 'jotai';
|
import { useAtom } from 'jotai';
|
||||||
import { nanoid } from 'nanoid';
|
import { nanoid } from 'nanoid';
|
||||||
@@ -364,7 +365,7 @@ const Upgrade = ({
|
|||||||
}, [onSubscriptionUpdate]);
|
}, [onSubscriptionUpdate]);
|
||||||
|
|
||||||
const [, openPaymentDisableModal] = useAtom(openPaymentDisableAtom);
|
const [, openPaymentDisableModal] = useAtom(openPaymentDisableAtom);
|
||||||
const upgrade = useCallback(() => {
|
const upgrade = useAsyncCallback(async () => {
|
||||||
if (!runtimeConfig.enablePayment) {
|
if (!runtimeConfig.enablePayment) {
|
||||||
openPaymentDisableModal(true);
|
openPaymentDisableModal(true);
|
||||||
return;
|
return;
|
||||||
@@ -373,7 +374,7 @@ const Upgrade = ({
|
|||||||
if (newTabRef.current) {
|
if (newTabRef.current) {
|
||||||
newTabRef.current.focus();
|
newTabRef.current.focus();
|
||||||
} else {
|
} else {
|
||||||
trigger(
|
await trigger(
|
||||||
{ recurring, idempotencyKey },
|
{ recurring, idempotencyKey },
|
||||||
{
|
{
|
||||||
onSuccess: data => {
|
onSuccess: data => {
|
||||||
@@ -439,8 +440,8 @@ const ChangeRecurring = ({
|
|||||||
mutation: updateSubscriptionMutation,
|
mutation: updateSubscriptionMutation,
|
||||||
});
|
});
|
||||||
|
|
||||||
const change = useCallback(() => {
|
const change = useAsyncCallback(async () => {
|
||||||
trigger(
|
await trigger(
|
||||||
{ recurring: to, idempotencyKey },
|
{ recurring: to, idempotencyKey },
|
||||||
{
|
{
|
||||||
onSuccess: data => {
|
onSuccess: data => {
|
||||||
@@ -492,7 +493,7 @@ const ChangeRecurring = ({
|
|||||||
const SignUpAction = ({ children }: PropsWithChildren) => {
|
const SignUpAction = ({ children }: PropsWithChildren) => {
|
||||||
const setOpen = useSetAtom(authAtom);
|
const setOpen = useSetAtom(authAtom);
|
||||||
|
|
||||||
const onClickSignIn = useCallback(async () => {
|
const onClickSignIn = useCallback(() => {
|
||||||
setOpen(state => ({
|
setOpen(state => ({
|
||||||
...state,
|
...state,
|
||||||
openModal: true,
|
openModal: true,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { pushNotificationAtom } from '@affine/component/notification-center';
|
|||||||
import { WorkspaceSubPath } from '@affine/env/workspace';
|
import { WorkspaceSubPath } from '@affine/env/workspace';
|
||||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||||
import { rootWorkspacesMetadataAtom } from '@affine/workspace/atom';
|
import { rootWorkspacesMetadataAtom } from '@affine/workspace/atom';
|
||||||
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
import { useBlockSuiteWorkspaceName } from '@toeverything/hooks/use-block-suite-workspace-name';
|
import { useBlockSuiteWorkspaceName } from '@toeverything/hooks/use-block-suite-workspace-name';
|
||||||
import { useSetAtom } from 'jotai';
|
import { useSetAtom } from 'jotai';
|
||||||
import { useAtomValue } from 'jotai';
|
import { useAtomValue } from 'jotai';
|
||||||
@@ -65,7 +66,7 @@ export const WorkspaceSetting = ({ workspaceId }: { workspaceId: string }) => {
|
|||||||
workspaces,
|
workspaces,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const handleDeleteWorkspace = useCallback(async () => {
|
const handleDeleteWorkspace = useAsyncCallback(async () => {
|
||||||
closeAndJumpOut();
|
closeAndJumpOut();
|
||||||
await deleteWorkspace(workspaceId);
|
await deleteWorkspace(workspaceId);
|
||||||
|
|
||||||
@@ -75,7 +76,7 @@ export const WorkspaceSetting = ({ workspaceId }: { workspaceId: string }) => {
|
|||||||
});
|
});
|
||||||
}, [closeAndJumpOut, deleteWorkspace, pushNotification, t, workspaceId]);
|
}, [closeAndJumpOut, deleteWorkspace, pushNotification, t, workspaceId]);
|
||||||
|
|
||||||
const handleLeaveWorkspace = useCallback(async () => {
|
const handleLeaveWorkspace = useAsyncCallback(async () => {
|
||||||
closeAndJumpOut();
|
closeAndJumpOut();
|
||||||
await leaveWorkspace(workspaceId, workspaceName);
|
await leaveWorkspace(workspaceId, workspaceName);
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
MenuItem,
|
MenuItem,
|
||||||
MenuSeparator,
|
MenuSeparator,
|
||||||
} from '@toeverything/components/menu';
|
} from '@toeverything/components/menu';
|
||||||
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
import {
|
import {
|
||||||
useBlockSuitePageMeta,
|
useBlockSuitePageMeta,
|
||||||
usePageMetaHelper,
|
usePageMetaHelper,
|
||||||
@@ -99,7 +100,7 @@ export const PageMenu = ({ rename, pageId }: PageMenuProps) => {
|
|||||||
const exportHandler = useExportPage(currentPage);
|
const exportHandler = useExportPage(currentPage);
|
||||||
const setPageMode = useSetAtom(setPageModeAtom);
|
const setPageMode = useSetAtom(setPageModeAtom);
|
||||||
|
|
||||||
const duplicate = useCallback(async () => {
|
const duplicate = useAsyncCallback(async () => {
|
||||||
const currentPageMeta = currentPage.meta;
|
const currentPageMeta = currentPage.meta;
|
||||||
const newPage = createPage();
|
const newPage = createPage();
|
||||||
await newPage.waitForLoaded();
|
await newPage.waitForLoaded();
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { toast } from '@affine/component';
|
import { toast } from '@affine/component';
|
||||||
import { WorkspaceSubPath } from '@affine/env/workspace';
|
import { WorkspaceSubPath } from '@affine/env/workspace';
|
||||||
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
import { useBlockSuiteWorkspaceHelper } from '@toeverything/hooks/use-block-suite-workspace-helper';
|
import { useBlockSuiteWorkspaceHelper } from '@toeverything/hooks/use-block-suite-workspace-helper';
|
||||||
import { initEmptyPage } from '@toeverything/infra/blocksuite';
|
import { initEmptyPage } from '@toeverything/infra/blocksuite';
|
||||||
import { useAtomValue, useSetAtom } from 'jotai';
|
import { useAtomValue, useSetAtom } from 'jotai';
|
||||||
@@ -33,7 +34,7 @@ export const usePageHelper = (blockSuiteWorkspace: BlockSuiteWorkspace) => {
|
|||||||
const createEdgelessAndOpen = useCallback(() => {
|
const createEdgelessAndOpen = useCallback(() => {
|
||||||
return createPageAndOpen('edgeless');
|
return createPageAndOpen('edgeless');
|
||||||
}, [createPageAndOpen]);
|
}, [createPageAndOpen]);
|
||||||
const importFileAndOpen = useCallback(async () => {
|
const importFileAndOpen = useAsyncCallback(async () => {
|
||||||
const { showImportModal } = await import('@blocksuite/blocks');
|
const { showImportModal } = await import('@blocksuite/blocks');
|
||||||
const onSuccess = (pageIds: string[], isWorkspaceFile: boolean) => {
|
const onSuccess = (pageIds: string[], isWorkspaceFile: boolean) => {
|
||||||
toast(
|
toast(
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||||
import { CloudWorkspaceIcon } from '@blocksuite/icons';
|
import { CloudWorkspaceIcon } from '@blocksuite/icons';
|
||||||
import { Avatar } from '@toeverything/components/avatar';
|
import { Avatar } from '@toeverything/components/avatar';
|
||||||
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
|
|
||||||
import { useCurrentLoginStatus } from '../../hooks/affine/use-current-login-status';
|
import { useCurrentLoginStatus } from '../../hooks/affine/use-current-login-status';
|
||||||
import { useCurrentUser } from '../../hooks/affine/use-current-user';
|
import { useCurrentUser } from '../../hooks/affine/use-current-user';
|
||||||
@@ -10,16 +11,16 @@ import { StyledSignInButton } from '../pure/footer/styles';
|
|||||||
export const LoginCard = () => {
|
export const LoginCard = () => {
|
||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
const loginStatus = useCurrentLoginStatus();
|
const loginStatus = useCurrentLoginStatus();
|
||||||
|
|
||||||
|
const onSignInClick = useAsyncCallback(async () => {
|
||||||
|
await signInCloud();
|
||||||
|
}, []);
|
||||||
|
|
||||||
if (loginStatus === 'authenticated') {
|
if (loginStatus === 'authenticated') {
|
||||||
return <UserCard />;
|
return <UserCard />;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<StyledSignInButton
|
<StyledSignInButton data-testid="sign-in-button" onClick={onSignInClick}>
|
||||||
data-testid="sign-in-button"
|
|
||||||
onClick={async () => {
|
|
||||||
signInCloud().catch(console.error);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className="circle">
|
<div className="circle">
|
||||||
<CloudWorkspaceIcon />
|
<CloudWorkspaceIcon />
|
||||||
</div>{' '}
|
</div>{' '}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import {
|
|||||||
PreconditionStrategy,
|
PreconditionStrategy,
|
||||||
} from '@toeverything/infra/command';
|
} from '@toeverything/infra/command';
|
||||||
import { atom, useAtomValue } from 'jotai';
|
import { atom, useAtomValue } from 'jotai';
|
||||||
import groupBy from 'lodash/groupBy';
|
import { groupBy } from 'lodash-es';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { Command } from '@affine/cmdk';
|
|||||||
import { formatDate } from '@affine/component/page-list';
|
import { formatDate } from '@affine/component/page-list';
|
||||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||||
import type { PageMeta } from '@blocksuite/store';
|
import type { PageMeta } from '@blocksuite/store';
|
||||||
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
import type { CommandCategory } from '@toeverything/infra/command';
|
import type { CommandCategory } from '@toeverything/infra/command';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { useAtom } from 'jotai';
|
import { useAtom } from 'jotai';
|
||||||
@@ -55,6 +56,19 @@ const QuickSearchGroup = ({
|
|||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
const i18nkey = categoryToI18nKey[category];
|
const i18nkey = categoryToI18nKey[category];
|
||||||
const [query, setQuery] = useAtom(cmdkQueryAtom);
|
const [query, setQuery] = useAtom(cmdkQueryAtom);
|
||||||
|
|
||||||
|
const onCommendSelect = useAsyncCallback(
|
||||||
|
async (command: CMDKCommand) => {
|
||||||
|
try {
|
||||||
|
await command.run();
|
||||||
|
} finally {
|
||||||
|
setQuery('');
|
||||||
|
onOpenChange?.(false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[setQuery, onOpenChange]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Command.Group key={category} heading={t[i18nkey]()}>
|
<Command.Group key={category} heading={t[i18nkey]()}>
|
||||||
{commands.map(command => {
|
{commands.map(command => {
|
||||||
@@ -67,11 +81,7 @@ const QuickSearchGroup = ({
|
|||||||
return (
|
return (
|
||||||
<Command.Item
|
<Command.Item
|
||||||
key={command.id}
|
key={command.id}
|
||||||
onSelect={() => {
|
onSelect={() => onCommendSelect(command)}
|
||||||
command.run();
|
|
||||||
setQuery('');
|
|
||||||
onOpenChange?.(false);
|
|
||||||
}}
|
|
||||||
value={command.value}
|
value={command.value}
|
||||||
data-is-danger={
|
data-is-danger={
|
||||||
command.id === 'editor:page-move-to-trash' ||
|
command.id === 'editor:page-move-to-trash' ||
|
||||||
|
|||||||
@@ -18,8 +18,9 @@ import type { DragEndEvent } from '@dnd-kit/core';
|
|||||||
import { useDroppable } from '@dnd-kit/core';
|
import { useDroppable } from '@dnd-kit/core';
|
||||||
import * as Collapsible from '@radix-ui/react-collapsible';
|
import * as Collapsible from '@radix-ui/react-collapsible';
|
||||||
import { IconButton } from '@toeverything/components/button';
|
import { IconButton } from '@toeverything/components/button';
|
||||||
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
import { useBlockSuitePageMeta } from '@toeverything/hooks/use-block-suite-page-meta';
|
import { useBlockSuitePageMeta } from '@toeverything/hooks/use-block-suite-page-meta';
|
||||||
import { useCallback, useMemo, useState } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
import { collectionsCRUDAtom } from '../../../../atoms/collections';
|
import { collectionsCRUDAtom } from '../../../../atoms/collections';
|
||||||
@@ -80,9 +81,9 @@ const CollectionRenderer = ({
|
|||||||
() => new Set(collection.allowList),
|
() => new Set(collection.allowList),
|
||||||
[collection.allowList]
|
[collection.allowList]
|
||||||
);
|
);
|
||||||
const removeFromAllowList = useCallback(
|
const removeFromAllowList = useAsyncCallback(
|
||||||
(id: string) => {
|
async (id: string) => {
|
||||||
return setting.updateCollection({
|
await setting.updateCollection({
|
||||||
...collection,
|
...collection,
|
||||||
allowList: collection.allowList?.filter(v => v != id),
|
allowList: collection.allowList?.filter(v => v != id),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { PlusIcon } from '@blocksuite/icons';
|
import { PlusIcon } from '@blocksuite/icons';
|
||||||
import type { Workspace } from '@blocksuite/store';
|
import type { Workspace } from '@blocksuite/store';
|
||||||
import { IconButton } from '@toeverything/components/button';
|
import { IconButton } from '@toeverything/components/button';
|
||||||
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
import { usePageMetaHelper } from '@toeverything/hooks/use-block-suite-page-meta';
|
import { usePageMetaHelper } from '@toeverything/hooks/use-block-suite-page-meta';
|
||||||
import { useCallback } from 'react';
|
|
||||||
|
|
||||||
import { usePageHelper } from '../../../blocksuite/block-suite-page-list/utils';
|
import { usePageHelper } from '../../../blocksuite/block-suite-page-list/utils';
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ type AddFavouriteButtonProps = {
|
|||||||
export const AddFavouriteButton = ({ workspace }: AddFavouriteButtonProps) => {
|
export const AddFavouriteButton = ({ workspace }: AddFavouriteButtonProps) => {
|
||||||
const { createPage } = usePageHelper(workspace);
|
const { createPage } = usePageHelper(workspace);
|
||||||
const { setPageMeta } = usePageMetaHelper(workspace);
|
const { setPageMeta } = usePageMetaHelper(workspace);
|
||||||
const handleAddFavorite = useCallback(async () => {
|
const handleAddFavorite = useAsyncCallback(async () => {
|
||||||
const page = createPage();
|
const page = createPage();
|
||||||
await page.waitForLoaded();
|
await page.waitForLoaded();
|
||||||
setPageMeta(page.id, { favorite: true });
|
setPageMeta(page.id, { favorite: true });
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ const SignInItem = () => {
|
|||||||
|
|
||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
|
|
||||||
const onClickSignIn = useCallback(async () => {
|
const onClickSignIn = useCallback(() => {
|
||||||
if (!runtimeConfig.enableCloud) {
|
if (!runtimeConfig.enableCloud) {
|
||||||
setDisableCloudOpen(true);
|
setDisableCloudOpen(true);
|
||||||
} else {
|
} else {
|
||||||
@@ -76,7 +76,7 @@ export const UserWithWorkspaceList = ({
|
|||||||
onEventEnd?.();
|
onEventEnd?.();
|
||||||
}, [onEventEnd, setOpenCreateWorkspaceModal]);
|
}, [onEventEnd, setOpenCreateWorkspaceModal]);
|
||||||
|
|
||||||
const onAddWorkspace = useCallback(async () => {
|
const onAddWorkspace = useCallback(() => {
|
||||||
setOpenCreateWorkspaceModal('add');
|
setOpenCreateWorkspaceModal('add');
|
||||||
onEventEnd?.();
|
onEventEnd?.();
|
||||||
}, [onEventEnd, setOpenCreateWorkspaceModal]);
|
}, [onEventEnd, setOpenCreateWorkspaceModal]);
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ export const AFFiNEWorkspaceList = ({
|
|||||||
onEventEnd?.();
|
onEventEnd?.();
|
||||||
}, [onEventEnd, setOpenCreateWorkspaceModal]);
|
}, [onEventEnd, setOpenCreateWorkspaceModal]);
|
||||||
|
|
||||||
const onAddWorkspace = useCallback(async () => {
|
const onAddWorkspace = useCallback(() => {
|
||||||
setOpenCreateWorkspaceModal('add');
|
setOpenCreateWorkspaceModal('add');
|
||||||
onEventEnd?.();
|
onEventEnd?.();
|
||||||
}, [onEventEnd, setOpenCreateWorkspaceModal]);
|
}, [onEventEnd, setOpenCreateWorkspaceModal]);
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import { FolderIcon, SettingsIcon } from '@blocksuite/icons';
|
|||||||
import type { Page } from '@blocksuite/store';
|
import type { Page } from '@blocksuite/store';
|
||||||
import { useDroppable } from '@dnd-kit/core';
|
import { useDroppable } from '@dnd-kit/core';
|
||||||
import { Menu } from '@toeverything/components/menu';
|
import { Menu } from '@toeverything/components/menu';
|
||||||
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
import { useAtom, useAtomValue } from 'jotai';
|
import { useAtom, useAtomValue } from 'jotai';
|
||||||
import type { HTMLAttributes, ReactElement } from 'react';
|
import type { HTMLAttributes, ReactElement } from 'react';
|
||||||
import { forwardRef, useCallback, useEffect, useMemo } from 'react';
|
import { forwardRef, useCallback, useEffect, useMemo } from 'react';
|
||||||
@@ -107,7 +108,7 @@ export const RootAppSidebar = ({
|
|||||||
);
|
);
|
||||||
const generalShortcutsInfo = useGeneralShortcuts();
|
const generalShortcutsInfo = useGeneralShortcuts();
|
||||||
|
|
||||||
const onClickNewPage = useCallback(async () => {
|
const onClickNewPage = useAsyncCallback(async () => {
|
||||||
const page = createPage();
|
const page = createPage();
|
||||||
await page.waitForLoaded();
|
await page.waitForLoaded();
|
||||||
openPage(page.id);
|
openPage(page.id);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
useCollectionManager,
|
useCollectionManager,
|
||||||
} from '@affine/component/page-list';
|
} from '@affine/component/page-list';
|
||||||
import { Unreachable } from '@affine/env/constant';
|
import { Unreachable } from '@affine/env/constant';
|
||||||
import type { Collection } from '@affine/env/filter';
|
import type { Collection, Filter } from '@affine/env/filter';
|
||||||
import type {
|
import type {
|
||||||
WorkspaceFlavour,
|
WorkspaceFlavour,
|
||||||
WorkspaceHeaderProps,
|
WorkspaceHeaderProps,
|
||||||
@@ -13,6 +13,7 @@ import type {
|
|||||||
import { WorkspaceSubPath } from '@affine/env/workspace';
|
import { WorkspaceSubPath } from '@affine/env/workspace';
|
||||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||||
import { DeleteIcon } from '@blocksuite/icons';
|
import { DeleteIcon } from '@blocksuite/icons';
|
||||||
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
import { useSetAtom } from 'jotai/react';
|
import { useSetAtom } from 'jotai/react';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
@@ -44,6 +45,17 @@ const FilterContainer = ({ workspaceId }: { workspaceId: string }) => {
|
|||||||
},
|
},
|
||||||
[setting, navigateHelper, workspaceId]
|
[setting, navigateHelper, workspaceId]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const onFilterChange = useAsyncCallback(
|
||||||
|
async (filterList: Filter[]) => {
|
||||||
|
await setting.updateCollection({
|
||||||
|
...setting.currentCollection,
|
||||||
|
filterList,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[setting]
|
||||||
|
);
|
||||||
|
|
||||||
if (!setting.isDefault || !setting.currentCollection.filterList.length) {
|
if (!setting.isDefault || !setting.currentCollection.filterList.length) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -54,12 +66,7 @@ const FilterContainer = ({ workspaceId }: { workspaceId: string }) => {
|
|||||||
<FilterList
|
<FilterList
|
||||||
propertiesMeta={currentWorkspace.blockSuiteWorkspace.meta.properties}
|
propertiesMeta={currentWorkspace.blockSuiteWorkspace.meta.properties}
|
||||||
value={setting.currentCollection.filterList}
|
value={setting.currentCollection.filterList}
|
||||||
onChange={filterList => {
|
onChange={onFilterChange}
|
||||||
return setting.updateCollection({
|
|
||||||
...setting.currentCollection,
|
|
||||||
filterList,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { LOCALES, useI18N } from '@affine/i18n';
|
import { LOCALES, useI18N } from '@affine/i18n';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
export function useLanguageHelper() {
|
export function useLanguageHelper() {
|
||||||
const i18n = useI18N();
|
const i18n = useI18N();
|
||||||
@@ -16,9 +17,9 @@ export function useLanguageHelper() {
|
|||||||
})),
|
})),
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
const onLanguageChange = useCallback(
|
const onLanguageChange = useAsyncCallback(
|
||||||
(event: string) => {
|
async (event: string) => {
|
||||||
i18n.changeLanguage(event);
|
await i18n.changeLanguage(event);
|
||||||
},
|
},
|
||||||
[i18n]
|
[i18n]
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -117,8 +117,8 @@ export function useRegisterBlocksuiteEditorCommands(
|
|||||||
category: `editor:${mode}`,
|
category: `editor:${mode}`,
|
||||||
icon: mode === 'page' ? <PageIcon /> : <EdgelessIcon />,
|
icon: mode === 'page' ? <PageIcon /> : <EdgelessIcon />,
|
||||||
label: t['Export to PDF'](),
|
label: t['Export to PDF'](),
|
||||||
run() {
|
async run() {
|
||||||
exportHandler('pdf');
|
await exportHandler('pdf');
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -130,8 +130,8 @@ export function useRegisterBlocksuiteEditorCommands(
|
|||||||
category: `editor:${mode}`,
|
category: `editor:${mode}`,
|
||||||
icon: mode === 'page' ? <PageIcon /> : <EdgelessIcon />,
|
icon: mode === 'page' ? <PageIcon /> : <EdgelessIcon />,
|
||||||
label: t['Export to HTML'](),
|
label: t['Export to HTML'](),
|
||||||
run() {
|
async run() {
|
||||||
exportHandler('html');
|
await exportHandler('html');
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -143,8 +143,8 @@ export function useRegisterBlocksuiteEditorCommands(
|
|||||||
category: `editor:${mode}`,
|
category: `editor:${mode}`,
|
||||||
icon: mode === 'page' ? <PageIcon /> : <EdgelessIcon />,
|
icon: mode === 'page' ? <PageIcon /> : <EdgelessIcon />,
|
||||||
label: t['Export to PNG'](),
|
label: t['Export to PNG'](),
|
||||||
run() {
|
async run() {
|
||||||
exportHandler('png');
|
await exportHandler('png');
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -156,8 +156,8 @@ export function useRegisterBlocksuiteEditorCommands(
|
|||||||
category: `editor:${mode}`,
|
category: `editor:${mode}`,
|
||||||
icon: mode === 'page' ? <PageIcon /> : <EdgelessIcon />,
|
icon: mode === 'page' ? <PageIcon /> : <EdgelessIcon />,
|
||||||
label: t['Export to Markdown'](),
|
label: t['Export to Markdown'](),
|
||||||
run() {
|
async run() {
|
||||||
exportHandler('markdown');
|
await exportHandler('markdown');
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import {
|
|||||||
rootWorkspacesMetadataAtom,
|
rootWorkspacesMetadataAtom,
|
||||||
workspaceAdaptersAtom,
|
workspaceAdaptersAtom,
|
||||||
} from '@affine/workspace/atom';
|
} from '@affine/workspace/atom';
|
||||||
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
import { currentPageIdAtom } from '@toeverything/infra/atom';
|
import { currentPageIdAtom } from '@toeverything/infra/atom';
|
||||||
import { WorkspaceVersion } from '@toeverything/infra/blocksuite';
|
import { WorkspaceVersion } from '@toeverything/infra/blocksuite';
|
||||||
import { useAtomValue, useSetAtom } from 'jotai';
|
import { useAtomValue, useSetAtom } from 'jotai';
|
||||||
import { useCallback } from 'react';
|
|
||||||
|
|
||||||
import { openSettingModalAtom } from '../../atoms';
|
import { openSettingModalAtom } from '../../atoms';
|
||||||
import { useNavigateHelper } from '../use-navigate-helper';
|
import { useNavigateHelper } from '../use-navigate-helper';
|
||||||
@@ -24,7 +24,7 @@ export function useOnTransformWorkspace() {
|
|||||||
const currentPageId = useAtomValue(currentPageIdAtom);
|
const currentPageId = useAtomValue(currentPageIdAtom);
|
||||||
const pushNotification = useSetAtom(pushNotificationAtom);
|
const pushNotification = useSetAtom(pushNotificationAtom);
|
||||||
|
|
||||||
return useCallback(
|
return useAsyncCallback(
|
||||||
async <From extends WorkspaceFlavour, To extends WorkspaceFlavour>(
|
async <From extends WorkspaceFlavour, To extends WorkspaceFlavour>(
|
||||||
from: From,
|
from: From,
|
||||||
to: To,
|
to: To,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { type SubscriptionQuery, subscriptionQuery } from '@affine/graphql';
|
import { type SubscriptionQuery, subscriptionQuery } from '@affine/graphql';
|
||||||
import { useQuery } from '@affine/workspace/affine/gql';
|
import { useQuery } from '@affine/workspace/affine/gql';
|
||||||
import { useCallback } from 'react';
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
|
|
||||||
export type Subscription = NonNullable<
|
export type Subscription = NonNullable<
|
||||||
NonNullable<SubscriptionQuery['currentUser']>['subscription']
|
NonNullable<SubscriptionQuery['currentUser']>['subscription']
|
||||||
@@ -16,9 +16,9 @@ export const useUserSubscription = () => {
|
|||||||
query: subscriptionQuery,
|
query: subscriptionQuery,
|
||||||
});
|
});
|
||||||
|
|
||||||
const set: SubscriptionMutator = useCallback(
|
const set: SubscriptionMutator = useAsyncCallback(
|
||||||
(update?: Partial<Subscription>) => {
|
async (update?: Partial<Subscription>) => {
|
||||||
mutate(prev => {
|
await mutate(prev => {
|
||||||
if (!update || !prev?.currentUser?.subscription) {
|
if (!update || !prev?.currentUser?.subscription) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ type WorkspaceLayoutProps = {
|
|||||||
function useLoadWorkspacePages() {
|
function useLoadWorkspacePages() {
|
||||||
const [currentWorkspace] = useCurrentWorkspace();
|
const [currentWorkspace] = useCurrentWorkspace();
|
||||||
const pageMetas = useBlockSuitePageMeta(currentWorkspace.blockSuiteWorkspace);
|
const pageMetas = useBlockSuitePageMeta(currentWorkspace.blockSuiteWorkspace);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (currentWorkspace) {
|
if (currentWorkspace) {
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
@@ -129,7 +130,7 @@ function useLoadWorkspacePages() {
|
|||||||
.map(id => currentWorkspace.blockSuiteWorkspace.getPage(id))
|
.map(id => currentWorkspace.blockSuiteWorkspace.getPage(id))
|
||||||
.filter((p): p is Page => !!p);
|
.filter((p): p is Page => !!p);
|
||||||
pages.forEach(page => {
|
pages.forEach(page => {
|
||||||
loadPage(page, -10);
|
loadPage(page, -10).catch(e => console.error(e));
|
||||||
});
|
});
|
||||||
}, 10 * 1000); // load pages after 10s
|
}, 10 * 1000); // load pages after 10s
|
||||||
return () => {
|
return () => {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { NotFoundPage } from '@affine/component/not-found-page';
|
import { NotFoundPage } from '@affine/component/not-found-page';
|
||||||
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
||||||
import { useSession } from 'next-auth/react';
|
import { useSession } from 'next-auth/react';
|
||||||
import type { ReactElement } from 'react';
|
import type { ReactElement } from 'react';
|
||||||
@@ -22,7 +23,7 @@ export const Component = (): ReactElement => {
|
|||||||
setOpen(true);
|
setOpen(true);
|
||||||
}, [setOpen]);
|
}, [setOpen]);
|
||||||
|
|
||||||
const onConfirmSignOut = useCallback(async () => {
|
const onConfirmSignOut = useAsyncCallback(async () => {
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
await signOutCloud({
|
await signOutCloud({
|
||||||
callbackUrl: '/signIn',
|
callbackUrl: '/signIn',
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
PageIcon,
|
PageIcon,
|
||||||
ViewLayersIcon,
|
ViewLayersIcon,
|
||||||
} from '@blocksuite/icons';
|
} from '@blocksuite/icons';
|
||||||
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
import { getCurrentStore } from '@toeverything/infra/atom';
|
import { getCurrentStore } from '@toeverything/infra/atom';
|
||||||
import { useAtomValue } from 'jotai';
|
import { useAtomValue } from 'jotai';
|
||||||
import { useSetAtom } from 'jotai';
|
import { useSetAtom } from 'jotai';
|
||||||
@@ -92,11 +93,13 @@ export const Component = function CollectionPage() {
|
|||||||
const Placeholder = ({ collection }: { collection: Collection }) => {
|
const Placeholder = ({ collection }: { collection: Collection }) => {
|
||||||
const { updateCollection } = useCollectionManager(collectionsCRUDAtom);
|
const { updateCollection } = useCollectionManager(collectionsCRUDAtom);
|
||||||
const { node, open } = useEditCollection(useAllPageListConfig());
|
const { node, open } = useEditCollection(useAllPageListConfig());
|
||||||
const openPageEdit = useCallback(() => {
|
const openPageEdit = useAsyncCallback(async () => {
|
||||||
open({ ...collection }, 'page').then(updateCollection);
|
const ret = await open({ ...collection }, 'page');
|
||||||
|
await updateCollection(ret);
|
||||||
}, [open, collection, updateCollection]);
|
}, [open, collection, updateCollection]);
|
||||||
const openRuleEdit = useCallback(() => {
|
const openRuleEdit = useAsyncCallback(async () => {
|
||||||
open({ ...collection }, 'rule').then(updateCollection);
|
const ret = await open({ ...collection }, 'rule');
|
||||||
|
await updateCollection(ret);
|
||||||
}, [collection, open, updateCollection]);
|
}, [collection, open, updateCollection]);
|
||||||
const [showTips, setShowTips] = useState(false);
|
const [showTips, setShowTips] = useState(false);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { WorkspaceSubPath } from '@affine/env/workspace';
|
import { WorkspaceSubPath } from '@affine/env/workspace';
|
||||||
import { assertExists } from '@blocksuite/global/utils';
|
import { assertExists } from '@blocksuite/global/utils';
|
||||||
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
import { useAtom } from 'jotai';
|
import { useAtom } from 'jotai';
|
||||||
import type { ReactElement } from 'react';
|
import type { ReactElement } from 'react';
|
||||||
import { lazy, Suspense, useCallback } from 'react';
|
import { lazy, Suspense, useCallback } from 'react';
|
||||||
@@ -154,13 +155,10 @@ export const SignOutConfirmModal = () => {
|
|||||||
const { jumpToIndex } = useNavigateHelper();
|
const { jumpToIndex } = useNavigateHelper();
|
||||||
const [open, setOpen] = useAtom(openSignOutModalAtom);
|
const [open, setOpen] = useAtom(openSignOutModalAtom);
|
||||||
|
|
||||||
const onConfirm = useCallback(async () => {
|
const onConfirm = useAsyncCallback(async () => {
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
signOutCloud()
|
await signOutCloud();
|
||||||
.then(() => {
|
jumpToIndex();
|
||||||
jumpToIndex();
|
|
||||||
})
|
|
||||||
.catch(console.error);
|
|
||||||
}, [jumpToIndex, setOpen]);
|
}, [jumpToIndex, setOpen]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import '@toeverything/hooks/use-affine-ipc-renderer';
|
|||||||
import { pushNotificationAtom } from '@affine/component/notification-center';
|
import { pushNotificationAtom } from '@affine/component/notification-center';
|
||||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||||
import { refreshRootMetadataAtom } from '@affine/workspace/atom';
|
import { refreshRootMetadataAtom } from '@affine/workspace/atom';
|
||||||
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
import { useAtom, useSetAtom } from 'jotai';
|
import { useAtom, useSetAtom } from 'jotai';
|
||||||
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
||||||
import { SessionProvider, useSession } from 'next-auth/react';
|
import { SessionProvider, useSession } from 'next-auth/react';
|
||||||
@@ -24,6 +25,12 @@ const SessionDefence = (props: PropsWithChildren) => {
|
|||||||
const refreshMetadata = useSetAtom(refreshRootMetadataAtom);
|
const refreshMetadata = useSetAtom(refreshRootMetadataAtom);
|
||||||
const onceSignedInEvents = useOnceSignedInEvents();
|
const onceSignedInEvents = useOnceSignedInEvents();
|
||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
|
|
||||||
|
const refreshAfterSignedInEvents = useAsyncCallback(async () => {
|
||||||
|
await onceSignedInEvents();
|
||||||
|
refreshMetadata();
|
||||||
|
}, [onceSignedInEvents, refreshMetadata]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (sessionInAtom !== session && session.status === 'authenticated') {
|
if (sessionInAtom !== session && session.status === 'authenticated') {
|
||||||
setSession(session);
|
setSession(session);
|
||||||
@@ -35,11 +42,7 @@ const SessionDefence = (props: PropsWithChildren) => {
|
|||||||
prevSession.current?.status === 'unauthenticated' &&
|
prevSession.current?.status === 'unauthenticated' &&
|
||||||
session.status === 'authenticated'
|
session.status === 'authenticated'
|
||||||
) {
|
) {
|
||||||
startTransition(() => {
|
startTransition(() => refreshAfterSignedInEvents());
|
||||||
onceSignedInEvents().then(() => {
|
|
||||||
refreshMetadata();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
pushNotification({
|
pushNotification({
|
||||||
title: t['com.affine.auth.has.signed'](),
|
title: t['com.affine.auth.has.signed'](),
|
||||||
message: t['com.affine.auth.has.signed.message'](),
|
message: t['com.affine.auth.has.signed.message'](),
|
||||||
@@ -57,9 +60,8 @@ const SessionDefence = (props: PropsWithChildren) => {
|
|||||||
sessionInAtom,
|
sessionInAtom,
|
||||||
prevSession,
|
prevSession,
|
||||||
setSession,
|
setSession,
|
||||||
onceSignedInEvents,
|
|
||||||
pushNotification,
|
pushNotification,
|
||||||
refreshMetadata,
|
refreshAfterSignedInEvents,
|
||||||
t,
|
t,
|
||||||
]);
|
]);
|
||||||
return props.children;
|
return props.children;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
"@graphql-codegen/typescript": "^4.0.1",
|
"@graphql-codegen/typescript": "^4.0.1",
|
||||||
"@graphql-codegen/typescript-operations": "^4.0.1",
|
"@graphql-codegen/typescript-operations": "^4.0.1",
|
||||||
"@types/lodash-es": "^4.17.9",
|
"@types/lodash-es": "^4.17.9",
|
||||||
|
"lodash": "^4.17.21",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"prettier": "^3.0.3",
|
"prettier": "^3.0.3",
|
||||||
"vitest": "0.34.6"
|
"vitest": "0.34.6"
|
||||||
|
|||||||
27
packages/frontend/hooks/src/affine-async-hooks.ts
Normal file
27
packages/frontend/hooks/src/affine-async-hooks.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export type AsyncErrorHandler = (error: Error) => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* App should provide a global error handler for async callback in the root.
|
||||||
|
*/
|
||||||
|
export const AsyncCallbackContext = React.createContext<AsyncErrorHandler>(e =>
|
||||||
|
console.error(e)
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translate async function to sync function and handle error automatically.
|
||||||
|
* Only accept void function, return data here is meaningless.
|
||||||
|
*/
|
||||||
|
export function useAsyncCallback<T extends any[]>(
|
||||||
|
callback: (...args: T) => Promise<void>,
|
||||||
|
deps: any[]
|
||||||
|
): (...args: T) => void {
|
||||||
|
const handleAsyncError = React.useContext(AsyncCallbackContext);
|
||||||
|
return React.useCallback(
|
||||||
|
(...args: any) => {
|
||||||
|
callback(...args).catch(e => handleAsyncError(e));
|
||||||
|
},
|
||||||
|
[...deps] // eslint-disable-line react-hooks/exhaustive-deps
|
||||||
|
);
|
||||||
|
}
|
||||||
25
yarn.lock
25
yarn.lock
@@ -178,7 +178,7 @@ __metadata:
|
|||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
"@affine/cmdk@workspace:packages/common/cmdk":
|
"@affine/cmdk@workspace:*, @affine/cmdk@workspace:packages/common/cmdk":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@affine/cmdk@workspace:packages/common/cmdk"
|
resolution: "@affine/cmdk@workspace:packages/common/cmdk"
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -242,7 +242,6 @@ __metadata:
|
|||||||
jotai-effect: "npm:^0.2.2"
|
jotai-effect: "npm:^0.2.2"
|
||||||
jotai-scope: "npm:^0.4.0"
|
jotai-scope: "npm:^0.4.0"
|
||||||
lit: "npm:^3.0.2"
|
lit: "npm:^3.0.2"
|
||||||
lodash: "npm:^4.17.21"
|
|
||||||
lodash-es: "npm:^4.17.21"
|
lodash-es: "npm:^4.17.21"
|
||||||
lottie-react: "npm:^2.4.0"
|
lottie-react: "npm:^2.4.0"
|
||||||
lottie-web: "npm:^5.12.2"
|
lottie-web: "npm:^5.12.2"
|
||||||
@@ -304,6 +303,7 @@ __metadata:
|
|||||||
resolution: "@affine/core@workspace:packages/frontend/core"
|
resolution: "@affine/core@workspace:packages/frontend/core"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@affine-test/fixtures": "workspace:*"
|
"@affine-test/fixtures": "workspace:*"
|
||||||
|
"@affine/cmdk": "workspace:*"
|
||||||
"@affine/component": "workspace:*"
|
"@affine/component": "workspace:*"
|
||||||
"@affine/debug": "workspace:*"
|
"@affine/debug": "workspace:*"
|
||||||
"@affine/env": "workspace:*"
|
"@affine/env": "workspace:*"
|
||||||
@@ -319,6 +319,7 @@ __metadata:
|
|||||||
"@blocksuite/icons": "npm:2.1.35"
|
"@blocksuite/icons": "npm:2.1.35"
|
||||||
"@blocksuite/lit": "npm:0.0.0-20231110042432-4fdac4dc-nightly"
|
"@blocksuite/lit": "npm:0.0.0-20231110042432-4fdac4dc-nightly"
|
||||||
"@blocksuite/store": "npm:0.0.0-20231110042432-4fdac4dc-nightly"
|
"@blocksuite/store": "npm:0.0.0-20231110042432-4fdac4dc-nightly"
|
||||||
|
"@blocksuite/virgo": "npm:0.0.0-20231110042432-4fdac4dc-nightly"
|
||||||
"@dnd-kit/core": "npm:^6.0.8"
|
"@dnd-kit/core": "npm:^6.0.8"
|
||||||
"@dnd-kit/sortable": "npm:^7.0.2"
|
"@dnd-kit/sortable": "npm:^7.0.2"
|
||||||
"@emotion/cache": "npm:^11.11.0"
|
"@emotion/cache": "npm:^11.11.0"
|
||||||
@@ -329,24 +330,37 @@ __metadata:
|
|||||||
"@mui/material": "npm:^5.14.14"
|
"@mui/material": "npm:^5.14.14"
|
||||||
"@perfsee/webpack": "npm:^1.8.4"
|
"@perfsee/webpack": "npm:^1.8.4"
|
||||||
"@pmmmwh/react-refresh-webpack-plugin": "npm:^0.5.11"
|
"@pmmmwh/react-refresh-webpack-plugin": "npm:^0.5.11"
|
||||||
|
"@radix-ui/react-collapsible": "npm:^1.0.3"
|
||||||
|
"@radix-ui/react-dialog": "npm:^1.0.4"
|
||||||
|
"@radix-ui/react-scroll-area": "npm:^1.0.5"
|
||||||
"@radix-ui/react-select": "npm:^2.0.0"
|
"@radix-ui/react-select": "npm:^2.0.0"
|
||||||
"@react-hookz/web": "npm:^23.1.0"
|
"@react-hookz/web": "npm:^23.1.0"
|
||||||
"@sentry/webpack-plugin": "npm:^2.8.0"
|
"@sentry/webpack-plugin": "npm:^2.8.0"
|
||||||
"@svgr/webpack": "npm:^8.1.0"
|
"@svgr/webpack": "npm:^8.1.0"
|
||||||
"@swc/core": "npm:^1.3.93"
|
"@swc/core": "npm:^1.3.93"
|
||||||
|
"@testing-library/react": "npm:^14.0.0"
|
||||||
"@toeverything/components": "npm:^0.0.46"
|
"@toeverything/components": "npm:^0.0.46"
|
||||||
|
"@toeverything/theme": "npm:^0.7.20"
|
||||||
"@types/bytes": "npm:^3.1.3"
|
"@types/bytes": "npm:^3.1.3"
|
||||||
"@types/lodash-es": "npm:^4.17.9"
|
"@types/lodash-es": "npm:^4.17.9"
|
||||||
|
"@types/uuid": "npm:^9.0.5"
|
||||||
"@types/webpack-env": "npm:^1.18.2"
|
"@types/webpack-env": "npm:^1.18.2"
|
||||||
|
"@vanilla-extract/css": "npm:^1.13.0"
|
||||||
|
"@vanilla-extract/dynamic": "npm:^2.0.3"
|
||||||
async-call-rpc: "npm:^6.3.1"
|
async-call-rpc: "npm:^6.3.1"
|
||||||
bytes: "npm:^3.1.2"
|
bytes: "npm:^3.1.2"
|
||||||
|
clsx: "npm:^2.0.0"
|
||||||
copy-webpack-plugin: "npm:^11.0.0"
|
copy-webpack-plugin: "npm:^11.0.0"
|
||||||
css-loader: "npm:^6.8.1"
|
css-loader: "npm:^6.8.1"
|
||||||
css-spring: "npm:^4.1.0"
|
css-spring: "npm:^4.1.0"
|
||||||
cssnano: "npm:^6.0.1"
|
cssnano: "npm:^6.0.1"
|
||||||
|
dayjs: "npm:^1.11.10"
|
||||||
express: "npm:^4.18.2"
|
express: "npm:^4.18.2"
|
||||||
|
fake-indexeddb: "npm:^5.0.0"
|
||||||
|
foxact: "npm:^0.2.20"
|
||||||
graphql: "npm:^16.8.1"
|
graphql: "npm:^16.8.1"
|
||||||
html-webpack-plugin: "npm:^5.5.3"
|
html-webpack-plugin: "npm:^5.5.3"
|
||||||
|
idb: "npm:^7.1.1"
|
||||||
intl-segmenter-polyfill-rs: "npm:^0.1.6"
|
intl-segmenter-polyfill-rs: "npm:^0.1.6"
|
||||||
jotai: "npm:^2.4.3"
|
jotai: "npm:^2.4.3"
|
||||||
jotai-devtools: "npm:^0.7.0"
|
jotai-devtools: "npm:^0.7.0"
|
||||||
@@ -355,12 +369,14 @@ __metadata:
|
|||||||
lottie-web: "npm:^5.12.2"
|
lottie-web: "npm:^5.12.2"
|
||||||
mime-types: "npm:^2.1.35"
|
mime-types: "npm:^2.1.35"
|
||||||
mini-css-extract-plugin: "npm:^2.7.6"
|
mini-css-extract-plugin: "npm:^2.7.6"
|
||||||
|
nanoid: "npm:^5.0.1"
|
||||||
next-auth: "npm:^4.23.2"
|
next-auth: "npm:^4.23.2"
|
||||||
next-themes: "npm:^0.2.1"
|
next-themes: "npm:^0.2.1"
|
||||||
postcss-loader: "npm:^7.3.3"
|
postcss-loader: "npm:^7.3.3"
|
||||||
raw-loader: "npm:^4.0.2"
|
raw-loader: "npm:^4.0.2"
|
||||||
react: "npm:18.2.0"
|
react: "npm:18.2.0"
|
||||||
react-dom: "npm:18.2.0"
|
react-dom: "npm:18.2.0"
|
||||||
|
react-error-boundary: "npm:^4.0.11"
|
||||||
react-is: "npm:18.2.0"
|
react-is: "npm:18.2.0"
|
||||||
react-resizable-panels: "npm:^0.0.55"
|
react-resizable-panels: "npm:^0.0.55"
|
||||||
react-router-dom: "npm:^6.16.0"
|
react-router-dom: "npm:^6.16.0"
|
||||||
@@ -372,7 +388,9 @@ __metadata:
|
|||||||
swc-plugin-coverage-instrument: "npm:^0.0.20"
|
swc-plugin-coverage-instrument: "npm:^0.0.20"
|
||||||
swr: "npm:2.2.4"
|
swr: "npm:2.2.4"
|
||||||
thread-loader: "npm:^4.0.2"
|
thread-loader: "npm:^4.0.2"
|
||||||
|
uuid: "npm:^9.0.1"
|
||||||
valtio: "npm:^1.11.2"
|
valtio: "npm:^1.11.2"
|
||||||
|
vitest: "npm:0.34.6"
|
||||||
webpack: "npm:^5.89.0"
|
webpack: "npm:^5.89.0"
|
||||||
webpack-cli: "npm:^5.1.4"
|
webpack-cli: "npm:^5.1.4"
|
||||||
webpack-dev-server: "npm:^4.15.1"
|
webpack-dev-server: "npm:^4.15.1"
|
||||||
@@ -482,6 +500,7 @@ __metadata:
|
|||||||
"@graphql-codegen/typescript-operations": "npm:^4.0.1"
|
"@graphql-codegen/typescript-operations": "npm:^4.0.1"
|
||||||
"@types/lodash-es": "npm:^4.17.9"
|
"@types/lodash-es": "npm:^4.17.9"
|
||||||
graphql: "npm:^16.8.1"
|
graphql: "npm:^16.8.1"
|
||||||
|
lodash: "npm:^4.17.21"
|
||||||
lodash-es: "npm:^4.17.21"
|
lodash-es: "npm:^4.17.21"
|
||||||
nanoid: "npm:^5.0.1"
|
nanoid: "npm:^5.0.1"
|
||||||
prettier: "npm:^3.0.3"
|
prettier: "npm:^3.0.3"
|
||||||
@@ -12679,7 +12698,7 @@ __metadata:
|
|||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
"@toeverything/theme@npm:^0.7.21, @toeverything/theme@npm:^0.7.24":
|
"@toeverything/theme@npm:^0.7.20, @toeverything/theme@npm:^0.7.21, @toeverything/theme@npm:^0.7.24":
|
||||||
version: 0.7.24
|
version: 0.7.24
|
||||||
resolution: "@toeverything/theme@npm:0.7.24"
|
resolution: "@toeverything/theme@npm:0.7.24"
|
||||||
checksum: faa97dad2a411e895090497ff6cbb83836e9be963e608cbc7f3421c4a933d86393551250fa015d4b9060778f0abb0e122a41d12a70e6f7fb7c9eadc2324a6035
|
checksum: faa97dad2a411e895090497ff6cbb83836e9be963e608cbc7f3421c4a933d86393551250fa015d4b9060778f0abb0e122a41d12a70e6f7fb7c9eadc2324a6035
|
||||||
|
|||||||
Reference in New Issue
Block a user