mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-29 08:09:52 +08:00
feat(core): add notifications settings (#11004)
This commit is contained in:
@@ -8,6 +8,7 @@ import {
|
||||
FolderIcon,
|
||||
InformationIcon,
|
||||
KeyboardIcon,
|
||||
NotificationIcon,
|
||||
PenIcon,
|
||||
} from '@blocksuite/icons/rc';
|
||||
import { useLiveData, useServices } from '@toeverything/infra';
|
||||
@@ -22,6 +23,7 @@ import { BillingSettings } from './billing';
|
||||
import { EditorSettings } from './editor';
|
||||
import { ExperimentalFeatures } from './experimental-features';
|
||||
import { PaymentIcon, UpgradeIcon } from './icons';
|
||||
import { NotificationSettings } from './notifications';
|
||||
import { AFFiNEPricingPlans } from './plans';
|
||||
import { Shortcuts } from './shortcuts';
|
||||
|
||||
@@ -37,6 +39,7 @@ export const useGeneralSettingList = (): GeneralSettingList => {
|
||||
FeatureFlagService,
|
||||
});
|
||||
const status = useLiveData(authService.session.status$);
|
||||
const loggedIn = status === 'authenticated';
|
||||
const hasPaymentFeature = useLiveData(
|
||||
serverService.server.features$.map(f => f?.payment)
|
||||
);
|
||||
@@ -62,6 +65,14 @@ export const useGeneralSettingList = (): GeneralSettingList => {
|
||||
testId: 'shortcuts-panel-trigger',
|
||||
},
|
||||
];
|
||||
if (loggedIn) {
|
||||
settings.push({
|
||||
key: 'notifications',
|
||||
title: t['com.affine.setting.notifications'](),
|
||||
icon: <NotificationIcon />,
|
||||
testId: 'notifications-panel-trigger',
|
||||
});
|
||||
}
|
||||
if (enableEditorSettings) {
|
||||
// add editor settings to second position
|
||||
settings.splice(1, 0, {
|
||||
@@ -73,14 +84,14 @@ export const useGeneralSettingList = (): GeneralSettingList => {
|
||||
}
|
||||
|
||||
if (hasPaymentFeature) {
|
||||
settings.splice(3, 0, {
|
||||
settings.splice(4, 0, {
|
||||
key: 'plans',
|
||||
title: t['com.affine.payment.title'](),
|
||||
icon: <UpgradeIcon />,
|
||||
testId: 'plans-panel-trigger',
|
||||
});
|
||||
if (status === 'authenticated') {
|
||||
settings.splice(3, 0, {
|
||||
if (loggedIn) {
|
||||
settings.splice(4, 0, {
|
||||
key: 'billing',
|
||||
title: t['com.affine.payment.billing-setting.title'](),
|
||||
icon: <PaymentIcon />,
|
||||
@@ -130,6 +141,8 @@ export const GeneralSetting = ({
|
||||
switch (activeTab) {
|
||||
case 'shortcuts':
|
||||
return <Shortcuts />;
|
||||
case 'notifications':
|
||||
return <NotificationSettings />;
|
||||
case 'editor':
|
||||
return <EditorSettings />;
|
||||
case 'appearance':
|
||||
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
import { notify, Switch } from '@affine/component';
|
||||
import {
|
||||
SettingHeader,
|
||||
SettingRow,
|
||||
SettingWrapper,
|
||||
} from '@affine/component/setting-components';
|
||||
import {
|
||||
type UserSettings,
|
||||
UserSettingsService,
|
||||
} from '@affine/core/modules/cloud';
|
||||
import { UserFriendlyError } from '@affine/error';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import * as styles from './style.css';
|
||||
|
||||
export const NotificationSettings = () => {
|
||||
const t = useI18n();
|
||||
const userSettingsService = useService(UserSettingsService);
|
||||
|
||||
useEffect(() => {
|
||||
userSettingsService.revalidate();
|
||||
}, [userSettingsService]);
|
||||
|
||||
const userSettings = useLiveData(userSettingsService.userSettings$);
|
||||
const [isMutating, setIsMutating] = useState(false);
|
||||
const error = useLiveData(userSettingsService.error$);
|
||||
const errorMessage = useMemo(() => {
|
||||
if (error) {
|
||||
console.log('error', error);
|
||||
const userFriendlyError = UserFriendlyError.fromAny(error);
|
||||
return t[`error.${userFriendlyError.name}`](userFriendlyError.data);
|
||||
}
|
||||
return null;
|
||||
}, [error, t]);
|
||||
|
||||
const disable = !userSettings || isMutating;
|
||||
|
||||
const handleUpdate = useCallback(
|
||||
(key: keyof UserSettings, value: boolean) => {
|
||||
setIsMutating(true);
|
||||
userSettingsService
|
||||
.updateUserSettings({
|
||||
[key]: value,
|
||||
})
|
||||
.catch(err => {
|
||||
const userFriendlyError = UserFriendlyError.fromAny(err);
|
||||
notify.error({
|
||||
title: t[`error.${userFriendlyError.name}`](userFriendlyError.data),
|
||||
});
|
||||
})
|
||||
.finally(() => {
|
||||
setIsMutating(false);
|
||||
});
|
||||
},
|
||||
[userSettingsService, t]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<SettingHeader
|
||||
title={t['com.affine.setting.notifications.header.title']()}
|
||||
/>
|
||||
<SettingWrapper
|
||||
title={t['com.affine.setting.notifications.email.title']()}
|
||||
>
|
||||
{errorMessage && (
|
||||
<>
|
||||
<div className={styles.errorMessage}>{errorMessage}</div>
|
||||
<br />
|
||||
</>
|
||||
)}
|
||||
<SettingRow
|
||||
name={t['com.affine.setting.notifications.email.mention.title']()}
|
||||
desc={t['com.affine.setting.notifications.email.mention.subtitle']()}
|
||||
>
|
||||
<Switch
|
||||
data-testid="notification-email-mention-trigger"
|
||||
checked={userSettings?.receiveMentionEmail ?? false}
|
||||
disabled={disable}
|
||||
onChange={checked => handleUpdate('receiveMentionEmail', checked)}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t['com.affine.setting.notifications.email.invites.title']()}
|
||||
desc={t['com.affine.setting.notifications.email.invites.subtitle']()}
|
||||
>
|
||||
<Switch
|
||||
data-testid="notification-email-invites-trigger"
|
||||
checked={userSettings?.receiveInvitationEmail ?? false}
|
||||
disabled={disable}
|
||||
onChange={checked =>
|
||||
handleUpdate('receiveInvitationEmail', checked)
|
||||
}
|
||||
/>
|
||||
</SettingRow>
|
||||
</SettingWrapper>
|
||||
</>
|
||||
);
|
||||
};
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
import { cssVar } from '@toeverything/theme';
|
||||
import { style } from '@vanilla-extract/css';
|
||||
|
||||
export const errorMessage = style({
|
||||
color: cssVar('errorColor'),
|
||||
});
|
||||
Reference in New Issue
Block a user