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