mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 04:18:54 +00:00
fix(core): add free plan prompt (#5441)
fix TOV-91 
This commit is contained in:
@@ -3,17 +3,21 @@ import {
|
||||
BlockSuiteEditor,
|
||||
EditorLoading,
|
||||
} from '@affine/component/block-suite-editor';
|
||||
import { Button } from '@affine/component/ui/button';
|
||||
import { Button, IconButton } from '@affine/component/ui/button';
|
||||
import { ConfirmModal, Modal } from '@affine/component/ui/modal';
|
||||
import type { PageMode } from '@affine/core/atoms';
|
||||
import { openSettingModalAtom, type PageMode } from '@affine/core/atoms';
|
||||
import { useIsWorkspaceOwner } from '@affine/core/hooks/affine/use-is-workspace-owner';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { useUserSubscription } from '@affine/core/hooks/use-subscription';
|
||||
import { waitForCurrentWorkspaceAtom } from '@affine/core/modules/workspace';
|
||||
import { SubscriptionPlan } from '@affine/graphql';
|
||||
import { Trans } from '@affine/i18n';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { ToggleCollapseIcon } from '@blocksuite/icons';
|
||||
import { CloseIcon, ToggleCollapseIcon } from '@blocksuite/icons';
|
||||
import type { Page, Workspace } from '@blocksuite/store';
|
||||
import * as Collapsible from '@radix-ui/react-collapsible';
|
||||
import type { DialogContentProps } from '@radix-ui/react-dialog';
|
||||
import { useAtom, useAtomValue } from 'jotai';
|
||||
import { atom, useAtom, useAtomValue, useSetAtom } from 'jotai';
|
||||
import {
|
||||
Fragment,
|
||||
type PropsWithChildren,
|
||||
@@ -154,6 +158,71 @@ const HistoryEditorPreview = ({
|
||||
</div>
|
||||
);
|
||||
};
|
||||
const planPromptClosedAtom = atom(false);
|
||||
|
||||
const PlanPrompt = () => {
|
||||
const [subscription] = useUserSubscription();
|
||||
const currentWorkspace = useAtomValue(waitForCurrentWorkspaceAtom);
|
||||
const isOwner = useIsWorkspaceOwner(currentWorkspace.meta);
|
||||
const freePlan = subscription?.plan === SubscriptionPlan.Free;
|
||||
|
||||
const setSettingModalAtom = useSetAtom(openSettingModalAtom);
|
||||
const [planPromptClosed, setPlanPromptClosed] = useAtom(planPromptClosedAtom);
|
||||
|
||||
const closeFreePlanPrompt = useCallback(() => {
|
||||
setPlanPromptClosed(true);
|
||||
}, [setPlanPromptClosed]);
|
||||
|
||||
const onClickUpgrade = useCallback(() => {
|
||||
setSettingModalAtom({
|
||||
open: true,
|
||||
activeTab: 'plans',
|
||||
});
|
||||
}, [setSettingModalAtom]);
|
||||
|
||||
const t = useAFFiNEI18N();
|
||||
|
||||
return !planPromptClosed ? (
|
||||
<div className={styles.planPromptWrapper}>
|
||||
<div className={styles.planPrompt}>
|
||||
<div className={styles.planPromptTitle}>
|
||||
{freePlan
|
||||
? t[
|
||||
'com.affine.history.confirm-restore-modal.plan-prompt.limited-title'
|
||||
]()
|
||||
: t['com.affine.history.confirm-restore-modal.plan-prompt.title']()}
|
||||
|
||||
<IconButton
|
||||
size="small"
|
||||
icon={<CloseIcon />}
|
||||
onClick={closeFreePlanPrompt}
|
||||
/>
|
||||
</div>
|
||||
{freePlan ? (
|
||||
<>
|
||||
<Trans i18nKey="com.affine.history.confirm-restore-modal.free-plan-prompt.description">
|
||||
Free users can view up to the <b>last 7 days</b> of page history.
|
||||
</Trans>
|
||||
{isOwner ? (
|
||||
<span
|
||||
className={styles.planPromptUpdateButton}
|
||||
onClick={onClickUpgrade}
|
||||
>
|
||||
{t[
|
||||
'com.affine.history.confirm-restore-modal.pro-plan-prompt.upgrade'
|
||||
]()}
|
||||
</span>
|
||||
) : null}
|
||||
</>
|
||||
) : (
|
||||
<Trans i18nKey="com.affine.history.confirm-restore-modal.pro-plan-prompt.description">
|
||||
Pro users can view up to the <b>last 30 days</b> of page history.
|
||||
</Trans>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
) : null;
|
||||
};
|
||||
|
||||
const PageHistoryList = ({
|
||||
pageDocId,
|
||||
@@ -191,6 +260,7 @@ const PageHistoryList = ({
|
||||
</div>
|
||||
<Scrollable.Root className={styles.historyListScrollable}>
|
||||
<Scrollable.Viewport className={styles.historyListScrollableInner}>
|
||||
<PlanPrompt />
|
||||
{historyListByDay.map(([day, list], i) => {
|
||||
const collapsed = collapsedMap[i];
|
||||
return (
|
||||
@@ -252,7 +322,7 @@ const PageHistoryList = ({
|
||||
className={styles.historyItemLoadMore}
|
||||
onClick={loadMore}
|
||||
>
|
||||
Load More
|
||||
{t['com.affine.history.confirm-restore-modal.load-more']()}
|
||||
</Button>
|
||||
) : null}
|
||||
</Scrollable.Viewport>
|
||||
|
||||
@@ -10,7 +10,7 @@ export const root = style({
|
||||
vars: {
|
||||
[headerHeight]: '52px',
|
||||
[footerHeight]: '68px',
|
||||
[historyListWidth]: '160px',
|
||||
[historyListWidth]: '240px',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -273,3 +273,31 @@ export const collapsedIconContainer = style({
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const planPromptWrapper = style({
|
||||
padding: '4px 12px',
|
||||
});
|
||||
|
||||
export const planPrompt = style({
|
||||
gap: 6,
|
||||
borderRadius: 8,
|
||||
flexDirection: 'column',
|
||||
padding: 10,
|
||||
fontSize: 'var(--affine-font-xs)',
|
||||
backgroundColor: 'var(--affine-background-secondary-color)',
|
||||
});
|
||||
|
||||
export const planPromptTitle = style({
|
||||
fontWeight: 600,
|
||||
marginBottom: 14,
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
color: 'var(--affine-text-secondary-color)',
|
||||
});
|
||||
|
||||
export const planPromptUpdateButton = style({
|
||||
textDecoration: 'underline',
|
||||
cursor: 'pointer',
|
||||
marginLeft: 4,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user