mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-15 05:37:32 +00:00
fix(core): add free plan prompt (#5441)
fix TOV-91 
This commit is contained in:
@@ -3,17 +3,21 @@ import {
|
|||||||
BlockSuiteEditor,
|
BlockSuiteEditor,
|
||||||
EditorLoading,
|
EditorLoading,
|
||||||
} from '@affine/component/block-suite-editor';
|
} 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 { 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 { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||||
|
import { useUserSubscription } from '@affine/core/hooks/use-subscription';
|
||||||
import { waitForCurrentWorkspaceAtom } from '@affine/core/modules/workspace';
|
import { waitForCurrentWorkspaceAtom } from '@affine/core/modules/workspace';
|
||||||
|
import { SubscriptionPlan } from '@affine/graphql';
|
||||||
|
import { Trans } from '@affine/i18n';
|
||||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
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 type { Page, Workspace } from '@blocksuite/store';
|
||||||
import * as Collapsible from '@radix-ui/react-collapsible';
|
import * as Collapsible from '@radix-ui/react-collapsible';
|
||||||
import type { DialogContentProps } from '@radix-ui/react-dialog';
|
import type { DialogContentProps } from '@radix-ui/react-dialog';
|
||||||
import { useAtom, useAtomValue } from 'jotai';
|
import { atom, useAtom, useAtomValue, useSetAtom } from 'jotai';
|
||||||
import {
|
import {
|
||||||
Fragment,
|
Fragment,
|
||||||
type PropsWithChildren,
|
type PropsWithChildren,
|
||||||
@@ -154,6 +158,71 @@ const HistoryEditorPreview = ({
|
|||||||
</div>
|
</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 = ({
|
const PageHistoryList = ({
|
||||||
pageDocId,
|
pageDocId,
|
||||||
@@ -191,6 +260,7 @@ const PageHistoryList = ({
|
|||||||
</div>
|
</div>
|
||||||
<Scrollable.Root className={styles.historyListScrollable}>
|
<Scrollable.Root className={styles.historyListScrollable}>
|
||||||
<Scrollable.Viewport className={styles.historyListScrollableInner}>
|
<Scrollable.Viewport className={styles.historyListScrollableInner}>
|
||||||
|
<PlanPrompt />
|
||||||
{historyListByDay.map(([day, list], i) => {
|
{historyListByDay.map(([day, list], i) => {
|
||||||
const collapsed = collapsedMap[i];
|
const collapsed = collapsedMap[i];
|
||||||
return (
|
return (
|
||||||
@@ -252,7 +322,7 @@ const PageHistoryList = ({
|
|||||||
className={styles.historyItemLoadMore}
|
className={styles.historyItemLoadMore}
|
||||||
onClick={loadMore}
|
onClick={loadMore}
|
||||||
>
|
>
|
||||||
Load More
|
{t['com.affine.history.confirm-restore-modal.load-more']()}
|
||||||
</Button>
|
</Button>
|
||||||
) : null}
|
) : null}
|
||||||
</Scrollable.Viewport>
|
</Scrollable.Viewport>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export const root = style({
|
|||||||
vars: {
|
vars: {
|
||||||
[headerHeight]: '52px',
|
[headerHeight]: '52px',
|
||||||
[footerHeight]: '68px',
|
[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,
|
||||||
|
});
|
||||||
|
|||||||
@@ -1011,6 +1011,12 @@
|
|||||||
"com.affine.history.empty-prompt.description": "This document is such a spring chicken, it hasn't sprouted a single historical sprig yet!",
|
"com.affine.history.empty-prompt.description": "This document is such a spring chicken, it hasn't sprouted a single historical sprig yet!",
|
||||||
"com.affine.history.confirm-restore-modal.restore": "Restore",
|
"com.affine.history.confirm-restore-modal.restore": "Restore",
|
||||||
"com.affine.history.confirm-restore-modal.hint": "You are about to restore the current version of the page to the latest version available. This action will overwrite any changes made prior to the latest version.",
|
"com.affine.history.confirm-restore-modal.hint": "You are about to restore the current version of the page to the latest version available. This action will overwrite any changes made prior to the latest version.",
|
||||||
|
"com.affine.history.confirm-restore-modal.load-more": "Load More",
|
||||||
|
"com.affine.history.confirm-restore-modal.plan-prompt.title": "HELP INFO",
|
||||||
|
"com.affine.history.confirm-restore-modal.plan-prompt.limited-title": "LIMITED PAGE HISTORY",
|
||||||
|
"com.affine.history.confirm-restore-modal.free-plan-prompt.description": "Free users can view up to the <1>last 7 days<1> of page history.",
|
||||||
|
"com.affine.history.confirm-restore-modal.pro-plan-prompt.description": "Pro users can view up to the <1>last 30 days<1> of page history.",
|
||||||
|
"com.affine.history.confirm-restore-modal.pro-plan-prompt.upgrade": "Upgrade",
|
||||||
"com.affine.share-page.header.present": "Present",
|
"com.affine.share-page.header.present": "Present",
|
||||||
"com.affine.page-operation.add-linked-page": "Add linked page",
|
"com.affine.page-operation.add-linked-page": "Add linked page",
|
||||||
"com.affine.onboarding.workspace-guide.title": "Start AFFiNE by creating your own Workspace here!",
|
"com.affine.onboarding.workspace-guide.title": "Start AFFiNE by creating your own Workspace here!",
|
||||||
|
|||||||
Reference in New Issue
Block a user