mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-15 00:56:26 +08:00
refactor(core): replace all notification relies on jotai (#6417)
- remove all notification that implemented with jotai and replaced with new `notify` - Add some notify presets: - `notify.error` - `notify.success` - `notify.warning`
This commit is contained in:
@@ -1,11 +1,10 @@
|
||||
import { Wrapper } from '@affine/component';
|
||||
import { notify, Wrapper } from '@affine/component';
|
||||
import {
|
||||
AuthContent,
|
||||
AuthInput,
|
||||
BackButton,
|
||||
ModalHeader,
|
||||
} from '@affine/component/auth-components';
|
||||
import { pushNotificationAtom } from '@affine/component/notification-center';
|
||||
import { Button } from '@affine/component/ui/button';
|
||||
import { useCredentialsRequirement } from '@affine/core/hooks/affine/use-server-config';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
@@ -17,7 +16,6 @@ import {
|
||||
sendVerifyEmailMutation,
|
||||
} from '@affine/graphql';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { useSetAtom } from 'jotai/react';
|
||||
import { useCallback, useState } from 'react';
|
||||
|
||||
import { useMutation } from '../../../hooks/use-mutation';
|
||||
@@ -165,7 +163,6 @@ export const SendEmail = ({
|
||||
const t = useAFFiNEI18N();
|
||||
const { password: passwordLimits } = useCredentialsRequirement();
|
||||
const [hasSentEmail, setHasSentEmail] = useState(false);
|
||||
const pushNotification = useSetAtom(pushNotificationAtom);
|
||||
|
||||
const title = useEmailTitle(emailType);
|
||||
const hint = useNotificationHint(emailType);
|
||||
@@ -177,14 +174,9 @@ export const SendEmail = ({
|
||||
// TODO: add error handler
|
||||
await sendEmail(email);
|
||||
|
||||
pushNotification({
|
||||
title: hint,
|
||||
message: '',
|
||||
key: Date.now().toString(),
|
||||
type: 'success',
|
||||
});
|
||||
notify.success({ title: hint });
|
||||
setHasSentEmail(true);
|
||||
}, [email, hint, pushNotification, sendEmail]);
|
||||
}, [email, hint, sendEmail]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pushNotificationAtom } from '@affine/component/notification-center';
|
||||
import type { Notification } from '@affine/component/notification-center/index.jotai';
|
||||
import { notify } from '@affine/component';
|
||||
import type { OAuthProviderType } from '@affine/graphql';
|
||||
import { atom, useAtom, useSetAtom } from 'jotai';
|
||||
import { useCallback } from 'react';
|
||||
@@ -10,19 +9,6 @@ import { useSubscriptionSearch } from './use-subscription';
|
||||
const COUNT_DOWN_TIME = 60;
|
||||
export const INTERNAL_BETA_URL = `https://community.affine.pro/c/insider-general/`;
|
||||
|
||||
function handleSendEmailError(
|
||||
res: Response | undefined | void,
|
||||
pushNotification: (notification: Notification) => void
|
||||
) {
|
||||
if (!res?.ok) {
|
||||
pushNotification({
|
||||
title: 'Send email error',
|
||||
message: 'Please back to home and try again',
|
||||
type: 'error',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
type AuthStoreAtom = {
|
||||
allowSendEmail: boolean;
|
||||
resendCountDown: number;
|
||||
@@ -60,7 +46,6 @@ const countDownAtom = atom(
|
||||
|
||||
export const useAuth = () => {
|
||||
const subscriptionData = useSubscriptionSearch();
|
||||
const pushNotification = useSetAtom(pushNotificationAtom);
|
||||
const [authStore, setAuthStore] = useAtom(authStoreAtom);
|
||||
const startResendCountDown = useSetAtom(countDownAtom);
|
||||
|
||||
@@ -96,7 +81,13 @@ export const useAuth = () => {
|
||||
}
|
||||
).catch(console.error);
|
||||
|
||||
handleSendEmailError(res, pushNotification);
|
||||
if (!res?.ok) {
|
||||
// TODO: i18n
|
||||
notify.error({
|
||||
title: 'Send email error',
|
||||
message: 'Please back to home and try again',
|
||||
});
|
||||
}
|
||||
|
||||
setAuthStore({
|
||||
isMutating: false,
|
||||
@@ -104,11 +95,12 @@ export const useAuth = () => {
|
||||
resendCountDown: COUNT_DOWN_TIME,
|
||||
});
|
||||
|
||||
// TODO: when errored, should reset the count down
|
||||
startResendCountDown();
|
||||
|
||||
return res;
|
||||
},
|
||||
[pushNotification, setAuthStore, startResendCountDown, subscriptionData]
|
||||
[setAuthStore, startResendCountDown, subscriptionData]
|
||||
);
|
||||
|
||||
const signUp = useCallback(
|
||||
|
||||
+8
-14
@@ -1,5 +1,4 @@
|
||||
import { FlexWrapper, Input } from '@affine/component';
|
||||
import { pushNotificationAtom } from '@affine/component/notification-center';
|
||||
import { FlexWrapper, Input, notify } from '@affine/component';
|
||||
import {
|
||||
SettingHeader,
|
||||
SettingRow,
|
||||
@@ -35,7 +34,6 @@ import * as styles from './style.css';
|
||||
export const UserAvatar = () => {
|
||||
const t = useAFFiNEI18N();
|
||||
const user = useCurrentUser();
|
||||
const pushNotification = useSetAtom(pushNotificationAtom);
|
||||
|
||||
const { trigger: avatarTrigger } = useMutation({
|
||||
mutation: uploadAvatarMutation,
|
||||
@@ -55,19 +53,17 @@ export const UserAvatar = () => {
|
||||
avatar: reducedFile, // Pass the reducedFile directly to the avatarTrigger
|
||||
});
|
||||
user.update({ avatarUrl: data.uploadAvatar.avatarUrl });
|
||||
pushNotification({
|
||||
title: 'Update user avatar success',
|
||||
type: 'success',
|
||||
});
|
||||
// TODO: i18n
|
||||
notify.success({ title: 'Update user avatar success' });
|
||||
} catch (e) {
|
||||
pushNotification({
|
||||
// TODO: i18n
|
||||
notify.error({
|
||||
title: 'Update user avatar failed',
|
||||
message: String(e),
|
||||
type: 'error',
|
||||
});
|
||||
}
|
||||
},
|
||||
[avatarTrigger, pushNotification, user]
|
||||
[avatarTrigger, user]
|
||||
);
|
||||
|
||||
const handleRemoveUserAvatar = useCallback(
|
||||
@@ -109,7 +105,6 @@ export const AvatarAndName = () => {
|
||||
const t = useAFFiNEI18N();
|
||||
const user = useCurrentUser();
|
||||
const [input, setInput] = useState<string>(user.name);
|
||||
const pushNotification = useSetAtom(pushNotificationAtom);
|
||||
|
||||
const { trigger: updateProfile } = useMutation({
|
||||
mutation: updateUserProfileMutation,
|
||||
@@ -129,13 +124,12 @@ export const AvatarAndName = () => {
|
||||
});
|
||||
user.update({ name: data.updateProfile.name });
|
||||
} catch (e) {
|
||||
pushNotification({
|
||||
notify.error({
|
||||
title: 'Failed to update user name.',
|
||||
message: String(e),
|
||||
type: 'error',
|
||||
});
|
||||
}
|
||||
}, [allowUpdate, input, user, updateProfile, pushNotification]);
|
||||
}, [allowUpdate, input, user, updateProfile]);
|
||||
|
||||
return (
|
||||
<SettingRow
|
||||
|
||||
+8
-7
@@ -1,5 +1,4 @@
|
||||
import { RadioButton, RadioButtonGroup } from '@affine/component';
|
||||
import { pushNotificationAtom } from '@affine/component/notification-center';
|
||||
import { notify, RadioButton, RadioButtonGroup } from '@affine/component';
|
||||
import {
|
||||
pricesQuery,
|
||||
SubscriptionPlan,
|
||||
@@ -7,7 +6,8 @@ import {
|
||||
} from '@affine/graphql';
|
||||
import { Trans } from '@affine/i18n';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { useSetAtom } from 'jotai';
|
||||
import { SingleSelectSelectSolidIcon } from '@blocksuite/icons';
|
||||
import { cssVar } from '@toeverything/theme';
|
||||
import { Suspense, useEffect, useRef, useState } from 'react';
|
||||
import type { FallbackProps } from 'react-error-boundary';
|
||||
|
||||
@@ -36,7 +36,6 @@ const getRecurringLabel = ({
|
||||
const Settings = () => {
|
||||
const t = useAFFiNEI18N();
|
||||
const [subscription, mutateSubscription] = useUserSubscription();
|
||||
const pushNotification = useSetAtom(pushNotificationAtom);
|
||||
|
||||
const loggedIn = useCurrentLoginStatus() === 'authenticated';
|
||||
const planDetail = getPlanDetail(t);
|
||||
@@ -165,9 +164,11 @@ const Settings = () => {
|
||||
key={detail.plan}
|
||||
onSubscriptionUpdate={mutateSubscription}
|
||||
onNotify={({ detail, recurring }) => {
|
||||
pushNotification({
|
||||
type: 'success',
|
||||
theme: 'default',
|
||||
notify({
|
||||
style: 'normal',
|
||||
icon: (
|
||||
<SingleSelectSelectSolidIcon color={cssVar('primaryColor')} />
|
||||
),
|
||||
title: t['com.affine.payment.updated-notify-title'](),
|
||||
message:
|
||||
detail.plan === SubscriptionPlan.Free
|
||||
|
||||
+2
-7
@@ -1,4 +1,4 @@
|
||||
import { pushNotificationAtom } from '@affine/component/notification-center';
|
||||
import { notify } from '@affine/component';
|
||||
import { SettingRow } from '@affine/component/setting-components';
|
||||
import { ConfirmModal } from '@affine/component/ui/modal';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
@@ -39,7 +39,6 @@ export const DeleteLeaveWorkspace = ({
|
||||
const workspaceManager = useService(WorkspaceManager);
|
||||
const workspaceList = useLiveData(workspaceManager.list.workspaceList$);
|
||||
const currentWorkspace = useService(Workspace);
|
||||
const pushNotification = useSetAtom(pushNotificationAtom);
|
||||
|
||||
const onLeaveOrDelete = useCallback(() => {
|
||||
if (isOwner) {
|
||||
@@ -69,15 +68,11 @@ export const DeleteLeaveWorkspace = ({
|
||||
}
|
||||
|
||||
await workspaceManager.deleteWorkspace(workspaceMetadata);
|
||||
pushNotification({
|
||||
title: t['Successfully deleted'](),
|
||||
type: 'success',
|
||||
});
|
||||
notify.success({ title: t['Successfully deleted']() });
|
||||
}, [
|
||||
currentWorkspace?.id,
|
||||
jumpToIndex,
|
||||
jumpToSubPath,
|
||||
pushNotification,
|
||||
setSettingModal,
|
||||
t,
|
||||
workspaceList,
|
||||
|
||||
+4
-13
@@ -1,4 +1,4 @@
|
||||
import { pushNotificationAtom } from '@affine/component/notification-center';
|
||||
import { notify } from '@affine/component';
|
||||
import { SettingRow } from '@affine/component/setting-components';
|
||||
import { Button } from '@affine/component/ui/button';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
@@ -6,7 +6,6 @@ import { useSystemOnline } from '@affine/core/hooks/use-system-online';
|
||||
import { apis } from '@affine/electron-api';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import type { Workspace, WorkspaceMetadata } from '@toeverything/infra';
|
||||
import { useSetAtom } from 'jotai';
|
||||
import { useState } from 'react';
|
||||
|
||||
interface ExportPanelProps {
|
||||
@@ -23,7 +22,6 @@ export const ExportPanel = ({
|
||||
const [saving, setSaving] = useState(false);
|
||||
const isOnline = useSystemOnline();
|
||||
|
||||
const pushNotification = useSetAtom(pushNotificationAtom);
|
||||
const onExport = useAsyncCallback(async () => {
|
||||
if (saving || !workspace) {
|
||||
return;
|
||||
@@ -39,21 +37,14 @@ export const ExportPanel = ({
|
||||
if (result?.error) {
|
||||
throw new Error(result.error);
|
||||
} else if (!result?.canceled) {
|
||||
pushNotification({
|
||||
type: 'success',
|
||||
title: t['Export success'](),
|
||||
});
|
||||
notify.success({ title: t['Export success']() });
|
||||
}
|
||||
} catch (e: any) {
|
||||
pushNotification({
|
||||
type: 'error',
|
||||
title: t['Export failed'](),
|
||||
message: e.message,
|
||||
});
|
||||
notify.error({ title: t['Export failed'](), message: e.message });
|
||||
} finally {
|
||||
setSaving(false);
|
||||
}
|
||||
}, [isOnline, pushNotification, saving, t, workspace, workspaceId]);
|
||||
}, [isOnline, saving, t, workspace, workspaceId]);
|
||||
|
||||
return (
|
||||
<SettingRow name={t['Export']()} desc={t['Export Description']()}>
|
||||
|
||||
+5
-11
@@ -1,3 +1,4 @@
|
||||
import { notify } from '@affine/component';
|
||||
import type {
|
||||
InviteModalProps,
|
||||
PaginationProps,
|
||||
@@ -7,7 +8,6 @@ import {
|
||||
MemberLimitModal,
|
||||
Pagination,
|
||||
} from '@affine/component/member-components';
|
||||
import { pushNotificationAtom } from '@affine/component/notification-center';
|
||||
import { SettingRow } from '@affine/component/setting-components';
|
||||
import { Avatar } from '@affine/component/ui/avatar';
|
||||
import { Button, IconButton } from '@affine/component/ui/button';
|
||||
@@ -90,8 +90,6 @@ export const CloudWorkspaceMembersPanel = ({
|
||||
const [open, setOpen] = useState(false);
|
||||
const [memberSkip, setMemberSkip] = useState(0);
|
||||
|
||||
const pushNotification = useSetAtom(pushNotificationAtom);
|
||||
|
||||
const openModal = useCallback(() => {
|
||||
setOpen(true);
|
||||
}, []);
|
||||
@@ -109,15 +107,14 @@ export const CloudWorkspaceMembersPanel = ({
|
||||
true
|
||||
);
|
||||
if (success) {
|
||||
pushNotification({
|
||||
notify.success({
|
||||
title: t['Invitation sent'](),
|
||||
message: t['Invitation sent hint'](),
|
||||
type: 'success',
|
||||
});
|
||||
setOpen(false);
|
||||
}
|
||||
},
|
||||
[invite, pushNotification, t]
|
||||
[invite, t]
|
||||
);
|
||||
|
||||
const setSettingModalAtom = useSetAtom(openSettingModalAtom);
|
||||
@@ -146,13 +143,10 @@ export const CloudWorkspaceMembersPanel = ({
|
||||
async memberId => {
|
||||
const res = await revokeMemberPermission(memberId);
|
||||
if (res?.revoke) {
|
||||
pushNotification({
|
||||
title: t['Removed successfully'](),
|
||||
type: 'success',
|
||||
});
|
||||
notify.success({ title: t['Removed successfully']() });
|
||||
}
|
||||
},
|
||||
[pushNotification, revokeMemberPermission, t]
|
||||
[revokeMemberPermission, t]
|
||||
);
|
||||
|
||||
const desc = useMemo(() => {
|
||||
|
||||
+6
-16
@@ -1,5 +1,4 @@
|
||||
import { FlexWrapper, Input, Wrapper } from '@affine/component';
|
||||
import { pushNotificationAtom } from '@affine/component/notification-center';
|
||||
import { FlexWrapper, Input, notify, Wrapper } from '@affine/component';
|
||||
import { Avatar } from '@affine/component/ui/avatar';
|
||||
import { Button } from '@affine/component/ui/button';
|
||||
import { Upload } from '@affine/core/components/pure/file-upload';
|
||||
@@ -11,7 +10,6 @@ import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { CameraIcon } from '@blocksuite/icons';
|
||||
import type { Workspace } from '@toeverything/infra';
|
||||
import { useLiveData } from '@toeverything/infra';
|
||||
import { useSetAtom } from 'jotai';
|
||||
import type { KeyboardEvent, MouseEvent } from 'react';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
@@ -24,7 +22,6 @@ export interface ProfilePanelProps extends WorkspaceSettingDetailProps {
|
||||
|
||||
export const ProfilePanel = ({ isOwner, workspace }: ProfilePanelProps) => {
|
||||
const t = useAFFiNEI18N();
|
||||
const pushNotification = useSetAtom(pushNotificationAtom);
|
||||
|
||||
const workspaceIsReady = useLiveData(workspace?.engine.rootDocState$)?.ready;
|
||||
|
||||
@@ -93,12 +90,9 @@ export const ProfilePanel = ({ isOwner, workspace }: ProfilePanelProps) => {
|
||||
const handleUpdateWorkspaceName = useCallback(
|
||||
(name: string) => {
|
||||
setWorkspaceName(name);
|
||||
pushNotification({
|
||||
title: t['Update workspace name success'](),
|
||||
type: 'success',
|
||||
});
|
||||
notify.success({ title: t['Update workspace name success']() });
|
||||
},
|
||||
[pushNotification, setWorkspaceName, t]
|
||||
[setWorkspaceName, t]
|
||||
);
|
||||
|
||||
const handleSetInput = useCallback((value: string) => {
|
||||
@@ -130,20 +124,16 @@ export const ProfilePanel = ({ isOwner, workspace }: ProfilePanelProps) => {
|
||||
(file: File) => {
|
||||
setWorkspaceAvatar(file)
|
||||
.then(() => {
|
||||
pushNotification({
|
||||
title: 'Update workspace avatar success',
|
||||
type: 'success',
|
||||
});
|
||||
notify.success({ title: 'Update workspace avatar success' });
|
||||
})
|
||||
.catch(error => {
|
||||
pushNotification({
|
||||
notify.error({
|
||||
title: 'Update workspace avatar failed',
|
||||
message: error,
|
||||
type: 'error',
|
||||
});
|
||||
});
|
||||
},
|
||||
[pushNotification, setWorkspaceAvatar]
|
||||
[setWorkspaceAvatar]
|
||||
);
|
||||
|
||||
const canAdjustAvatar = workspaceIsReady && avatarUrl && isOwner;
|
||||
|
||||
+9
-11
@@ -1,5 +1,4 @@
|
||||
import { Tooltip } from '@affine/component';
|
||||
import { pushNotificationAtom } from '@affine/component/notification-center';
|
||||
import { notify, Tooltip } from '@affine/component';
|
||||
import { Avatar, type AvatarProps } from '@affine/component/ui/avatar';
|
||||
import { Loading } from '@affine/component/ui/loading';
|
||||
import { openSettingModalAtom } from '@affine/core/atoms';
|
||||
@@ -81,7 +80,6 @@ const OfflineStatus = () => {
|
||||
const useSyncEngineSyncProgress = () => {
|
||||
const t = useAFFiNEI18N();
|
||||
const isOnline = useSystemOnline();
|
||||
const pushNotification = useSetAtom(pushNotificationAtom);
|
||||
const { syncing, progress, retrying, errorMessage } = useDocEngineStatus();
|
||||
const [isOverCapacity, setIsOverCapacity] = useState(false);
|
||||
|
||||
@@ -89,7 +87,7 @@ const useSyncEngineSyncProgress = () => {
|
||||
const isOwner = useIsWorkspaceOwner(currentWorkspace.meta);
|
||||
|
||||
const setSettingModalAtom = useSetAtom(openSettingModalAtom);
|
||||
const jumpToPricePlan = useCallback(async () => {
|
||||
const jumpToPricePlan = useCallback(() => {
|
||||
setSettingModalAtom({
|
||||
open: true,
|
||||
activeTab: 'plans',
|
||||
@@ -108,17 +106,17 @@ const useSyncEngineSyncProgress = () => {
|
||||
}
|
||||
setIsOverCapacity(true);
|
||||
if (isOwner) {
|
||||
pushNotification({
|
||||
type: 'warning',
|
||||
notify.warning({
|
||||
title: t['com.affine.payment.storage-limit.title'](),
|
||||
message:
|
||||
t['com.affine.payment.storage-limit.description.owner'](),
|
||||
actionLabel: t['com.affine.payment.storage-limit.view'](),
|
||||
action: jumpToPricePlan,
|
||||
action: {
|
||||
label: t['com.affine.payment.storage-limit.view'](),
|
||||
onClick: jumpToPricePlan,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
pushNotification({
|
||||
type: 'warning',
|
||||
notify.warning({
|
||||
title: t['com.affine.payment.storage-limit.title'](),
|
||||
message:
|
||||
t['com.affine.payment.storage-limit.description.member'](),
|
||||
@@ -129,7 +127,7 @@ const useSyncEngineSyncProgress = () => {
|
||||
return () => {
|
||||
disposableOverCapacity?.dispose();
|
||||
};
|
||||
}, [currentWorkspace, isOwner, jumpToPricePlan, pushNotification, t]);
|
||||
}, [currentWorkspace, isOwner, jumpToPricePlan, t]);
|
||||
|
||||
const content = useMemo(() => {
|
||||
// TODO: add i18n
|
||||
|
||||
Reference in New Issue
Block a user