feat(core): add notifications settings (#11004)
This commit is contained in:
@@ -0,0 +1,8 @@
|
|||||||
|
query getUserSettings {
|
||||||
|
currentUser {
|
||||||
|
settings {
|
||||||
|
receiveInvitationEmail
|
||||||
|
receiveMentionEmail
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -850,6 +850,19 @@ export const getUserFeaturesQuery = {
|
|||||||
}`,
|
}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getUserSettingsQuery = {
|
||||||
|
id: 'getUserSettingsQuery' as const,
|
||||||
|
op: 'getUserSettings',
|
||||||
|
query: `query getUserSettings {
|
||||||
|
currentUser {
|
||||||
|
settings {
|
||||||
|
receiveInvitationEmail
|
||||||
|
receiveMentionEmail
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
};
|
||||||
|
|
||||||
export const getUserQuery = {
|
export const getUserQuery = {
|
||||||
id: 'getUserQuery' as const,
|
id: 'getUserQuery' as const,
|
||||||
op: 'getUser',
|
op: 'getUser',
|
||||||
@@ -1436,6 +1449,14 @@ export const updateUserProfileMutation = {
|
|||||||
}`,
|
}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const updateUserSettingsMutation = {
|
||||||
|
id: 'updateUserSettingsMutation' as const,
|
||||||
|
op: 'updateUserSettings',
|
||||||
|
query: `mutation updateUserSettings($input: UpdateSettingsInput!) {
|
||||||
|
updateSettings(input: $input)
|
||||||
|
}`,
|
||||||
|
};
|
||||||
|
|
||||||
export const uploadAvatarMutation = {
|
export const uploadAvatarMutation = {
|
||||||
id: 'uploadAvatarMutation' as const,
|
id: 'uploadAvatarMutation' as const,
|
||||||
op: 'uploadAvatar',
|
op: 'uploadAvatar',
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
mutation updateUserSettings($input: UpdateSettingsInput!) {
|
||||||
|
updateSettings(input: $input)
|
||||||
|
}
|
||||||
@@ -3213,6 +3213,20 @@ export type GetUserFeaturesQuery = {
|
|||||||
} | null;
|
} | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type GetUserSettingsQueryVariables = Exact<{ [key: string]: never }>;
|
||||||
|
|
||||||
|
export type GetUserSettingsQuery = {
|
||||||
|
__typename?: 'Query';
|
||||||
|
currentUser: {
|
||||||
|
__typename?: 'UserType';
|
||||||
|
settings: {
|
||||||
|
__typename?: 'SettingsType';
|
||||||
|
receiveInvitationEmail: boolean;
|
||||||
|
receiveMentionEmail: boolean;
|
||||||
|
};
|
||||||
|
} | null;
|
||||||
|
};
|
||||||
|
|
||||||
export type GetUserQueryVariables = Exact<{
|
export type GetUserQueryVariables = Exact<{
|
||||||
email: Scalars['String']['input'];
|
email: Scalars['String']['input'];
|
||||||
}>;
|
}>;
|
||||||
@@ -3839,6 +3853,15 @@ export type UpdateUserProfileMutation = {
|
|||||||
updateProfile: { __typename?: 'UserType'; id: string; name: string };
|
updateProfile: { __typename?: 'UserType'; id: string; name: string };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type UpdateUserSettingsMutationVariables = Exact<{
|
||||||
|
input: UpdateSettingsInput;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export type UpdateUserSettingsMutation = {
|
||||||
|
__typename?: 'Mutation';
|
||||||
|
updateSettings: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
export type UploadAvatarMutationVariables = Exact<{
|
export type UploadAvatarMutationVariables = Exact<{
|
||||||
avatar: Scalars['Upload']['input'];
|
avatar: Scalars['Upload']['input'];
|
||||||
}>;
|
}>;
|
||||||
@@ -4230,6 +4253,11 @@ export type Queries =
|
|||||||
variables: GetUserFeaturesQueryVariables;
|
variables: GetUserFeaturesQueryVariables;
|
||||||
response: GetUserFeaturesQuery;
|
response: GetUserFeaturesQuery;
|
||||||
}
|
}
|
||||||
|
| {
|
||||||
|
name: 'getUserSettingsQuery';
|
||||||
|
variables: GetUserSettingsQueryVariables;
|
||||||
|
response: GetUserSettingsQuery;
|
||||||
|
}
|
||||||
| {
|
| {
|
||||||
name: 'getUserQuery';
|
name: 'getUserQuery';
|
||||||
variables: GetUserQueryVariables;
|
variables: GetUserQueryVariables;
|
||||||
@@ -4647,6 +4675,11 @@ export type Mutations =
|
|||||||
variables: UpdateUserProfileMutationVariables;
|
variables: UpdateUserProfileMutationVariables;
|
||||||
response: UpdateUserProfileMutation;
|
response: UpdateUserProfileMutation;
|
||||||
}
|
}
|
||||||
|
| {
|
||||||
|
name: 'updateUserSettingsMutation';
|
||||||
|
variables: UpdateUserSettingsMutationVariables;
|
||||||
|
response: UpdateUserSettingsMutation;
|
||||||
|
}
|
||||||
| {
|
| {
|
||||||
name: 'uploadAvatarMutation';
|
name: 'uploadAvatarMutation';
|
||||||
variables: UploadAvatarMutationVariables;
|
variables: UploadAvatarMutationVariables;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
FolderIcon,
|
FolderIcon,
|
||||||
InformationIcon,
|
InformationIcon,
|
||||||
KeyboardIcon,
|
KeyboardIcon,
|
||||||
|
NotificationIcon,
|
||||||
PenIcon,
|
PenIcon,
|
||||||
} from '@blocksuite/icons/rc';
|
} from '@blocksuite/icons/rc';
|
||||||
import { useLiveData, useServices } from '@toeverything/infra';
|
import { useLiveData, useServices } from '@toeverything/infra';
|
||||||
@@ -22,6 +23,7 @@ import { BillingSettings } from './billing';
|
|||||||
import { EditorSettings } from './editor';
|
import { EditorSettings } from './editor';
|
||||||
import { ExperimentalFeatures } from './experimental-features';
|
import { ExperimentalFeatures } from './experimental-features';
|
||||||
import { PaymentIcon, UpgradeIcon } from './icons';
|
import { PaymentIcon, UpgradeIcon } from './icons';
|
||||||
|
import { NotificationSettings } from './notifications';
|
||||||
import { AFFiNEPricingPlans } from './plans';
|
import { AFFiNEPricingPlans } from './plans';
|
||||||
import { Shortcuts } from './shortcuts';
|
import { Shortcuts } from './shortcuts';
|
||||||
|
|
||||||
@@ -37,6 +39,7 @@ export const useGeneralSettingList = (): GeneralSettingList => {
|
|||||||
FeatureFlagService,
|
FeatureFlagService,
|
||||||
});
|
});
|
||||||
const status = useLiveData(authService.session.status$);
|
const status = useLiveData(authService.session.status$);
|
||||||
|
const loggedIn = status === 'authenticated';
|
||||||
const hasPaymentFeature = useLiveData(
|
const hasPaymentFeature = useLiveData(
|
||||||
serverService.server.features$.map(f => f?.payment)
|
serverService.server.features$.map(f => f?.payment)
|
||||||
);
|
);
|
||||||
@@ -62,6 +65,14 @@ export const useGeneralSettingList = (): GeneralSettingList => {
|
|||||||
testId: 'shortcuts-panel-trigger',
|
testId: 'shortcuts-panel-trigger',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
if (loggedIn) {
|
||||||
|
settings.push({
|
||||||
|
key: 'notifications',
|
||||||
|
title: t['com.affine.setting.notifications'](),
|
||||||
|
icon: <NotificationIcon />,
|
||||||
|
testId: 'notifications-panel-trigger',
|
||||||
|
});
|
||||||
|
}
|
||||||
if (enableEditorSettings) {
|
if (enableEditorSettings) {
|
||||||
// add editor settings to second position
|
// add editor settings to second position
|
||||||
settings.splice(1, 0, {
|
settings.splice(1, 0, {
|
||||||
@@ -73,14 +84,14 @@ export const useGeneralSettingList = (): GeneralSettingList => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (hasPaymentFeature) {
|
if (hasPaymentFeature) {
|
||||||
settings.splice(3, 0, {
|
settings.splice(4, 0, {
|
||||||
key: 'plans',
|
key: 'plans',
|
||||||
title: t['com.affine.payment.title'](),
|
title: t['com.affine.payment.title'](),
|
||||||
icon: <UpgradeIcon />,
|
icon: <UpgradeIcon />,
|
||||||
testId: 'plans-panel-trigger',
|
testId: 'plans-panel-trigger',
|
||||||
});
|
});
|
||||||
if (status === 'authenticated') {
|
if (loggedIn) {
|
||||||
settings.splice(3, 0, {
|
settings.splice(4, 0, {
|
||||||
key: 'billing',
|
key: 'billing',
|
||||||
title: t['com.affine.payment.billing-setting.title'](),
|
title: t['com.affine.payment.billing-setting.title'](),
|
||||||
icon: <PaymentIcon />,
|
icon: <PaymentIcon />,
|
||||||
@@ -130,6 +141,8 @@ export const GeneralSetting = ({
|
|||||||
switch (activeTab) {
|
switch (activeTab) {
|
||||||
case 'shortcuts':
|
case 'shortcuts':
|
||||||
return <Shortcuts />;
|
return <Shortcuts />;
|
||||||
|
case 'notifications':
|
||||||
|
return <NotificationSettings />;
|
||||||
case 'editor':
|
case 'editor':
|
||||||
return <EditorSettings />;
|
return <EditorSettings />;
|
||||||
case 'appearance':
|
case 'appearance':
|
||||||
|
|||||||
@@ -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>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { cssVar } from '@toeverything/theme';
|
||||||
|
import { style } from '@vanilla-extract/css';
|
||||||
|
|
||||||
|
export const errorMessage = style({
|
||||||
|
color: cssVar('errorColor'),
|
||||||
|
});
|
||||||
@@ -24,6 +24,10 @@ export { SubscriptionService } from './services/subscription';
|
|||||||
export { UserCopilotQuotaService } from './services/user-copilot-quota';
|
export { UserCopilotQuotaService } from './services/user-copilot-quota';
|
||||||
export { UserFeatureService } from './services/user-feature';
|
export { UserFeatureService } from './services/user-feature';
|
||||||
export { UserQuotaService } from './services/user-quota';
|
export { UserQuotaService } from './services/user-quota';
|
||||||
|
export {
|
||||||
|
type UserSettings,
|
||||||
|
UserSettingsService,
|
||||||
|
} from './services/user-settings';
|
||||||
export { WorkspaceInvoicesService } from './services/workspace-invoices';
|
export { WorkspaceInvoicesService } from './services/workspace-invoices';
|
||||||
export { WorkspaceServerService } from './services/workspace-server';
|
export { WorkspaceServerService } from './services/workspace-server';
|
||||||
export { WorkspaceSubscriptionService } from './services/workspace-subscription';
|
export { WorkspaceSubscriptionService } from './services/workspace-subscription';
|
||||||
@@ -71,6 +75,7 @@ import { SubscriptionService } from './services/subscription';
|
|||||||
import { UserCopilotQuotaService } from './services/user-copilot-quota';
|
import { UserCopilotQuotaService } from './services/user-copilot-quota';
|
||||||
import { UserFeatureService } from './services/user-feature';
|
import { UserFeatureService } from './services/user-feature';
|
||||||
import { UserQuotaService } from './services/user-quota';
|
import { UserQuotaService } from './services/user-quota';
|
||||||
|
import { UserSettingsService } from './services/user-settings';
|
||||||
import { WorkspaceInvoicesService } from './services/workspace-invoices';
|
import { WorkspaceInvoicesService } from './services/workspace-invoices';
|
||||||
import { WorkspaceServerService } from './services/workspace-server';
|
import { WorkspaceServerService } from './services/workspace-server';
|
||||||
import { WorkspaceSubscriptionService } from './services/workspace-subscription';
|
import { WorkspaceSubscriptionService } from './services/workspace-subscription';
|
||||||
@@ -88,6 +93,7 @@ import { SubscriptionStore } from './stores/subscription';
|
|||||||
import { UserCopilotQuotaStore } from './stores/user-copilot-quota';
|
import { UserCopilotQuotaStore } from './stores/user-copilot-quota';
|
||||||
import { UserFeatureStore } from './stores/user-feature';
|
import { UserFeatureStore } from './stores/user-feature';
|
||||||
import { UserQuotaStore } from './stores/user-quota';
|
import { UserQuotaStore } from './stores/user-quota';
|
||||||
|
import { UserSettingsStore } from './stores/user-settings';
|
||||||
|
|
||||||
export function configureCloudModule(framework: Framework) {
|
export function configureCloudModule(framework: Framework) {
|
||||||
configureDefaultAuthProvider(framework);
|
configureDefaultAuthProvider(framework);
|
||||||
@@ -150,7 +156,9 @@ export function configureCloudModule(framework: Framework) {
|
|||||||
.service(AcceptInviteService, [AcceptInviteStore, InviteInfoStore])
|
.service(AcceptInviteService, [AcceptInviteStore, InviteInfoStore])
|
||||||
.store(AcceptInviteStore, [GraphQLService])
|
.store(AcceptInviteStore, [GraphQLService])
|
||||||
.service(PublicUserService, [PublicUserStore])
|
.service(PublicUserService, [PublicUserStore])
|
||||||
.store(PublicUserStore, [GraphQLService]);
|
.store(PublicUserStore, [GraphQLService])
|
||||||
|
.service(UserSettingsService, [UserSettingsStore])
|
||||||
|
.store(UserSettingsStore, [GraphQLService]);
|
||||||
|
|
||||||
framework
|
framework
|
||||||
.scope(WorkspaceScope)
|
.scope(WorkspaceScope)
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
import {
|
||||||
|
effect,
|
||||||
|
exhaustMapWithTrailing,
|
||||||
|
fromPromise,
|
||||||
|
LiveData,
|
||||||
|
onComplete,
|
||||||
|
onStart,
|
||||||
|
Service,
|
||||||
|
smartRetry,
|
||||||
|
} from '@toeverything/infra';
|
||||||
|
import { catchError, EMPTY, mergeMap } from 'rxjs';
|
||||||
|
|
||||||
|
import type {
|
||||||
|
UpdateUserSettingsInput,
|
||||||
|
UserSettings,
|
||||||
|
UserSettingsStore,
|
||||||
|
} from '../stores/user-settings';
|
||||||
|
|
||||||
|
export type { UserSettings };
|
||||||
|
|
||||||
|
export class UserSettingsService extends Service {
|
||||||
|
constructor(private readonly store: UserSettingsStore) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
userSettings$ = new LiveData<UserSettings | undefined>(undefined);
|
||||||
|
isLoading$ = new LiveData<boolean>(false);
|
||||||
|
error$ = new LiveData<any | undefined>(undefined);
|
||||||
|
|
||||||
|
revalidate = effect(
|
||||||
|
exhaustMapWithTrailing(() => {
|
||||||
|
return fromPromise(() => {
|
||||||
|
return this.store.getUserSettings();
|
||||||
|
}).pipe(
|
||||||
|
smartRetry(),
|
||||||
|
mergeMap(settings => {
|
||||||
|
this.userSettings$.value = settings;
|
||||||
|
return EMPTY;
|
||||||
|
}),
|
||||||
|
catchError(error => {
|
||||||
|
this.error$.value = error;
|
||||||
|
return EMPTY;
|
||||||
|
}),
|
||||||
|
onStart(() => {
|
||||||
|
this.isLoading$.value = true;
|
||||||
|
}),
|
||||||
|
onComplete(() => {
|
||||||
|
this.isLoading$.value = false;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
async updateUserSettings(settings: UpdateUserSettingsInput) {
|
||||||
|
await this.store.updateUserSettings(settings);
|
||||||
|
this.userSettings$.value = {
|
||||||
|
...this.userSettings$.value,
|
||||||
|
...(settings as UserSettings),
|
||||||
|
};
|
||||||
|
this.revalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import {
|
||||||
|
type GetUserSettingsQuery,
|
||||||
|
getUserSettingsQuery,
|
||||||
|
type UpdateSettingsInput,
|
||||||
|
updateUserSettingsMutation,
|
||||||
|
} from '@affine/graphql';
|
||||||
|
import { Store } from '@toeverything/infra';
|
||||||
|
|
||||||
|
import type { GraphQLService } from '../services/graphql';
|
||||||
|
|
||||||
|
export type UserSettings = NonNullable<
|
||||||
|
GetUserSettingsQuery['currentUser']
|
||||||
|
>['settings'];
|
||||||
|
|
||||||
|
export type UpdateUserSettingsInput = UpdateSettingsInput;
|
||||||
|
|
||||||
|
export class UserSettingsStore extends Store {
|
||||||
|
constructor(private readonly gqlService: GraphQLService) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
async getUserSettings(): Promise<UserSettings | undefined> {
|
||||||
|
const result = await this.gqlService.gql({
|
||||||
|
query: getUserSettingsQuery,
|
||||||
|
});
|
||||||
|
return result.currentUser?.settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateUserSettings(settings: UpdateUserSettingsInput) {
|
||||||
|
await this.gqlService.gql({
|
||||||
|
query: updateUserSettingsMutation,
|
||||||
|
variables: {
|
||||||
|
input: settings,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import type { WorkspaceMetadata } from '../workspace';
|
|||||||
|
|
||||||
export type SettingTab =
|
export type SettingTab =
|
||||||
| 'shortcuts'
|
| 'shortcuts'
|
||||||
|
| 'notifications'
|
||||||
| 'appearance'
|
| 'appearance'
|
||||||
| 'about'
|
| 'about'
|
||||||
| 'plans'
|
| 'plans'
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"el-GR": 96,
|
"el-GR": 96,
|
||||||
"en": 100,
|
"en": 100,
|
||||||
"es-AR": 96,
|
"es-AR": 96,
|
||||||
"es-CL": 98,
|
"es-CL": 97,
|
||||||
"es": 96,
|
"es": 96,
|
||||||
"fa": 96,
|
"fa": 96,
|
||||||
"fr": 96,
|
"fr": 96,
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
"it-IT": 96,
|
"it-IT": 96,
|
||||||
"it": 1,
|
"it": 1,
|
||||||
"ja": 96,
|
"ja": 96,
|
||||||
"ko": 61,
|
"ko": 60,
|
||||||
"pl": 96,
|
"pl": 96,
|
||||||
"pt-BR": 96,
|
"pt-BR": 96,
|
||||||
"ru": 96,
|
"ru": 96,
|
||||||
|
|||||||
@@ -4651,6 +4651,34 @@ export function useAFFiNEI18N(): {
|
|||||||
* `Search tags...`
|
* `Search tags...`
|
||||||
*/
|
*/
|
||||||
["com.affine.selector-tag.search.placeholder"](): string;
|
["com.affine.selector-tag.search.placeholder"](): string;
|
||||||
|
/**
|
||||||
|
* `Notifications`
|
||||||
|
*/
|
||||||
|
["com.affine.setting.notifications"](): string;
|
||||||
|
/**
|
||||||
|
* `Notifications`
|
||||||
|
*/
|
||||||
|
["com.affine.setting.notifications.header.title"](): string;
|
||||||
|
/**
|
||||||
|
* `Email notifications`
|
||||||
|
*/
|
||||||
|
["com.affine.setting.notifications.email.title"](): string;
|
||||||
|
/**
|
||||||
|
* `Mention`
|
||||||
|
*/
|
||||||
|
["com.affine.setting.notifications.email.mention.title"](): string;
|
||||||
|
/**
|
||||||
|
* `You will be notified through email when other members of the workspace @ you.`
|
||||||
|
*/
|
||||||
|
["com.affine.setting.notifications.email.mention.subtitle"](): string;
|
||||||
|
/**
|
||||||
|
* `Invites`
|
||||||
|
*/
|
||||||
|
["com.affine.setting.notifications.email.invites.title"](): string;
|
||||||
|
/**
|
||||||
|
* `Invitation related messages will be sent through emails.`
|
||||||
|
*/
|
||||||
|
["com.affine.setting.notifications.email.invites.subtitle"](): string;
|
||||||
/**
|
/**
|
||||||
* `Account settings`
|
* `Account settings`
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1156,6 +1156,13 @@
|
|||||||
"com.affine.selectPage.title": "Add include doc",
|
"com.affine.selectPage.title": "Add include doc",
|
||||||
"com.affine.selector-collection.search.placeholder": "Search collections...",
|
"com.affine.selector-collection.search.placeholder": "Search collections...",
|
||||||
"com.affine.selector-tag.search.placeholder": "Search tags...",
|
"com.affine.selector-tag.search.placeholder": "Search tags...",
|
||||||
|
"com.affine.setting.notifications": "Notifications",
|
||||||
|
"com.affine.setting.notifications.header.title": "Notifications",
|
||||||
|
"com.affine.setting.notifications.email.title": "Email notifications",
|
||||||
|
"com.affine.setting.notifications.email.mention.title": "Mention",
|
||||||
|
"com.affine.setting.notifications.email.mention.subtitle": "You will be notified through email when other members of the workspace @ you.",
|
||||||
|
"com.affine.setting.notifications.email.invites.title": "Invites",
|
||||||
|
"com.affine.setting.notifications.email.invites.subtitle": "Invitation related messages will be sent through emails.",
|
||||||
"com.affine.setting.account": "Account settings",
|
"com.affine.setting.account": "Account settings",
|
||||||
"com.affine.setting.account.delete": "Delete account",
|
"com.affine.setting.account.delete": "Delete account",
|
||||||
"com.affine.setting.account.delete.message": "Permanently delete this account and the Workspace data backup in AFFiNE Cloud. This action can not be undone.",
|
"com.affine.setting.account.delete.message": "Permanently delete this account and the Workspace data backup in AFFiNE Cloud. This action can not be undone.",
|
||||||
|
|||||||
Reference in New Issue
Block a user