fix(core): multiple settings dialog should not appear when click user plan button repeatedly (#8924)

This commit is contained in:
JimmFly 2024-11-26 05:49:12 +00:00
parent 31c806ef7e
commit e12d5f8750
No known key found for this signature in database
GPG Key ID: 126E0320FEB0D05C
5 changed files with 48 additions and 18 deletions

View File

@ -1,10 +1,8 @@
import { Tooltip } from '@affine/component/ui/tooltip';
import { useCatchEventCallback } from '@affine/core/components/hooks/use-catch-event-hook';
import { GlobalDialogService } from '@affine/core/modules/dialogs';
import { SubscriptionPlan } from '@affine/graphql';
import { useI18n } from '@affine/i18n';
import { useLiveData, useService, useServices } from '@toeverything/infra';
import { useEffect } from 'react';
import { useLiveData, useServices } from '@toeverything/infra';
import { type SyntheticEvent, useEffect } from 'react';
import {
ServerConfigService,
@ -12,7 +10,11 @@ import {
} from '../../../modules/cloud';
import * as styles from './style.css';
export const UserPlanButton = () => {
export const UserPlanButton = ({
onClick,
}: {
onClick: (e: SyntheticEvent<Element, Event>) => void;
}) => {
const { serverConfigService, subscriptionService } = useServices({
ServerConfigService,
SubscriptionService,
@ -34,14 +36,6 @@ export const UserPlanButton = () => {
subscriptionService.subscription.revalidate();
}, [subscriptionService]);
const globalDialogService = useService(GlobalDialogService);
const handleClick = useCatchEventCallback(() => {
globalDialogService.open('setting', {
activeTab: 'plans',
scrollAnchor: 'cloudPricingPlan',
});
}, [globalDialogService]);
const t = useI18n();
if (!hasPayment) {
@ -61,7 +55,7 @@ export const UserPlanButton = () => {
<div
data-is-believer={isBeliever ? 'true' : undefined}
className={styles.userPlanButton}
onClick={handleClick}
onClick={onClick}
data-event-props="$.settingsPanel.profileAndBadge.viewPlans"
>
{planLabel}

View File

@ -30,6 +30,7 @@ import {
} from '../../modules/cloud';
import { UserPlanButton } from '../affine/auth/user-plan-button';
import { useSignOut } from '../hooks/affine/use-sign-out';
import { useCatchEventCallback } from '../hooks/use-catch-event-hook';
import * as styles from './index.css';
import { UnknownUserIcon } from './unknow-user';
@ -113,6 +114,14 @@ const CloudUsage = () => {
const quota = useService(UserQuotaService).quota;
const quotaError = useLiveData(quota.error$);
const globalDialogService = useService(GlobalDialogService);
const handleClick = useCatchEventCallback(() => {
globalDialogService.open('setting', {
activeTab: 'plans',
scrollAnchor: 'cloudPricingPlan',
});
}, [globalDialogService]);
useEffect(() => {
// revalidate quota to get the latest status
quota.revalidate();
@ -150,7 +159,7 @@ const CloudUsage = () => {
<span>&nbsp;/&nbsp;</span>
<span>{maxFormatted}</span>
</div>
<UserPlanButton />
<UserPlanButton onClick={handleClick} />
</div>
<div className={styles.cloudUsageBar}>

View File

@ -16,6 +16,7 @@ import {
import { useSetAtom } from 'jotai';
import { useCallback } from 'react';
import { useCatchEventCallback } from '../../hooks/use-catch-event-hook';
import { AddWorkspace } from './add-workspace';
import * as styles from './index.css';
import { UserAccountItem } from './user-account';
@ -129,12 +130,20 @@ const UserWithWorkspaceListInner = ({
const workspaceManager = useService(WorkspacesService);
const workspaces = useLiveData(workspaceManager.list.workspaces$);
const onOpenPricingPlan = useCatchEventCallback(() => {
globalDialogService.open('setting', {
activeTab: 'plans',
scrollAnchor: 'cloudPricingPlan',
});
}, [globalDialogService]);
return (
<div className={styles.workspaceListWrapper}>
{isAuthenticated ? (
<UserAccountItem
email={session.session.account.email ?? 'Unknown User'}
onEventEnd={onEventEnd}
onClick={onOpenPricingPlan}
/>
) : (
<SignInItem />

View File

@ -1,11 +1,14 @@
import { UserPlanButton } from '@affine/core/components/affine/auth/user-plan-button';
import type { SyntheticEvent } from 'react';
import * as styles from './index.css';
export const UserAccountItem = ({
email,
onClick,
}: {
email: string;
onClick: (e: SyntheticEvent<Element, Event>) => void;
onEventEnd?: () => void;
}) => {
return (
@ -13,7 +16,7 @@ export const UserAccountItem = ({
<div className={styles.leftContainer}>
<div className={styles.userEmail}>{email}</div>
</div>
<UserPlanButton />
<UserPlanButton onClick={onClick} />
</div>
);
};

View File

@ -7,6 +7,7 @@ import { Tooltip } from '@affine/component/ui/tooltip';
import { WorkspaceAvatar } from '@affine/component/workspace-avatar';
import { UserPlanButton } from '@affine/core/components/affine/auth/user-plan-button';
import { authAtom } from '@affine/core/components/atoms';
import { useCatchEventCallback } from '@affine/core/components/hooks/use-catch-event-hook';
import { useWorkspaceInfo } from '@affine/core/components/hooks/use-workspace-info';
import { AuthService } from '@affine/core/modules/cloud';
import { UserFeatureService } from '@affine/core/modules/cloud/services/user-feature';
@ -38,11 +39,24 @@ import * as style from './style.css';
export type UserInfoProps = {
onAccountSettingClick: () => void;
onTabChange: (
key: SettingTab,
workspaceMetadata: WorkspaceMetadata | null
) => void;
active?: boolean;
};
export const UserInfo = ({ onAccountSettingClick, active }: UserInfoProps) => {
export const UserInfo = ({
onAccountSettingClick,
onTabChange,
active,
}: UserInfoProps) => {
const account = useLiveData(useService(AuthService).session.account$);
const onClick = useCatchEventCallback(() => {
onTabChange('plans', null);
}, [onTabChange]);
if (!account) {
// TODO(@eyhn): loading ui
return;
@ -68,7 +82,7 @@ export const UserInfo = ({ onAccountSettingClick, active }: UserInfoProps) => {
<div className="name" title={account.label}>
{account.label}
</div>
<UserPlanButton />
<UserPlanButton onClick={onClick} />
</div>
<div className="email" title={account.email}>
@ -193,6 +207,7 @@ export const SettingSidebar = ({
<UserInfo
onAccountSettingClick={onAccountSettingClick}
active={activeTab === 'account'}
onTabChange={onTabChange}
/>
</Suspense>
) : null}