mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-16 13:57:02 +08:00
fix(core): improve client-app navigation flow after team workspace upgrade (#11201)
This commit is contained in:
@@ -47,7 +47,8 @@ export const generateSubscriptionCallbackLink = (
|
|||||||
account: AuthAccountInfo | null,
|
account: AuthAccountInfo | null,
|
||||||
plan: SubscriptionPlan,
|
plan: SubscriptionPlan,
|
||||||
recurring: SubscriptionRecurring,
|
recurring: SubscriptionRecurring,
|
||||||
workspaceId?: string
|
workspaceId?: string,
|
||||||
|
clientScheme?: string
|
||||||
) => {
|
) => {
|
||||||
const baseUrl =
|
const baseUrl =
|
||||||
plan === SubscriptionPlan.AI
|
plan === SubscriptionPlan.AI
|
||||||
@@ -79,7 +80,7 @@ export const generateSubscriptionCallbackLink = (
|
|||||||
workspaceId ?? '',
|
workspaceId ?? '',
|
||||||
].join(separator);
|
].join(separator);
|
||||||
|
|
||||||
return `${baseUrl}?info=${encodeURIComponent(query)}`;
|
return `${baseUrl}?info=${encodeURIComponent(query)}${clientScheme ? `&client=${clientScheme}` : ''}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getSubscriptionInfo = (searchParams: URLSearchParams) => {
|
export const getSubscriptionInfo = (searchParams: URLSearchParams) => {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
SubscriptionService,
|
SubscriptionService,
|
||||||
} from '@affine/core/modules/cloud';
|
} from '@affine/core/modules/cloud';
|
||||||
import { GlobalDialogService } from '@affine/core/modules/dialogs';
|
import { GlobalDialogService } from '@affine/core/modules/dialogs';
|
||||||
|
import { UrlService } from '@affine/core/modules/url';
|
||||||
import {
|
import {
|
||||||
type CreateCheckoutSessionInput,
|
type CreateCheckoutSessionInput,
|
||||||
SubscriptionPlan,
|
SubscriptionPlan,
|
||||||
@@ -249,19 +250,25 @@ const Downgrade = ({ disabled }: { disabled?: boolean }) => {
|
|||||||
const UpgradeToTeam = ({ recurring }: { recurring: SubscriptionRecurring }) => {
|
const UpgradeToTeam = ({ recurring }: { recurring: SubscriptionRecurring }) => {
|
||||||
const t = useI18n();
|
const t = useI18n();
|
||||||
const serverService = useService(ServerService);
|
const serverService = useService(ServerService);
|
||||||
|
const urlService = useService(UrlService);
|
||||||
const url = `${serverService.server.baseUrl}/upgrade-to-team?recurring=${recurring}`;
|
const url = `${serverService.server.baseUrl}/upgrade-to-team?recurring=${recurring}`;
|
||||||
|
const scheme = urlService.getClientScheme();
|
||||||
|
const urlParams = new URLSearchParams();
|
||||||
|
if (scheme) {
|
||||||
|
urlParams.set('client', scheme);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
className={styles.planAction}
|
className={styles.planAction}
|
||||||
href={url}
|
href={`${url}${urlParams.toString() ? `&${urlParams.toString()}` : ''}`}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
className={styles.planAction}
|
className={styles.planAction}
|
||||||
variant="primary"
|
variant="primary"
|
||||||
data-event-args-url={url}
|
data-event-args-url={`${url}${urlParams.toString() ? `&${urlParams.toString()}` : ''}`}
|
||||||
>
|
>
|
||||||
{t['com.affine.payment.upgrade']()}
|
{t['com.affine.payment.upgrade']()}
|
||||||
</Button>
|
</Button>
|
||||||
@@ -289,6 +296,8 @@ export const Upgrade = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const t = useI18n();
|
const t = useI18n();
|
||||||
const authService = useService(AuthService);
|
const authService = useService(AuthService);
|
||||||
|
const urlService = useService(UrlService);
|
||||||
|
const schema = urlService.getClientScheme();
|
||||||
|
|
||||||
const handleBeforeCheckout = useCallback(() => {
|
const handleBeforeCheckout = useCallback(() => {
|
||||||
track.$.settingsPanel.plans.checkout({
|
track.$.settingsPanel.plans.checkout({
|
||||||
@@ -308,7 +317,8 @@ export const Upgrade = ({
|
|||||||
authService.session.account$.value,
|
authService.session.account$.value,
|
||||||
plan,
|
plan,
|
||||||
recurring,
|
recurring,
|
||||||
workspaceId
|
workspaceId || '',
|
||||||
|
schema
|
||||||
),
|
),
|
||||||
...checkoutInput,
|
...checkoutInput,
|
||||||
}),
|
}),
|
||||||
@@ -317,6 +327,7 @@ export const Upgrade = ({
|
|||||||
checkoutInput,
|
checkoutInput,
|
||||||
plan,
|
plan,
|
||||||
recurring,
|
recurring,
|
||||||
|
schema,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -16,14 +16,15 @@ export const Component = () => {
|
|||||||
const t = useI18n();
|
const t = useI18n();
|
||||||
const [params] = useSearchParams();
|
const [params] = useSearchParams();
|
||||||
|
|
||||||
const { jumpToIndex, jumpToOpenInApp } = useNavigateHelper();
|
const { jumpToOpenInApp } = useNavigateHelper();
|
||||||
const openAffine = useCallback(() => {
|
const openAFFiNE = useCallback(() => {
|
||||||
if (params.get('scheme')) {
|
if (params.get('client')) {
|
||||||
jumpToOpenInApp('bring-to-front');
|
return jumpToOpenInApp('bring-to-front');
|
||||||
} else {
|
} else {
|
||||||
jumpToIndex();
|
// close popup window
|
||||||
|
return window.close();
|
||||||
}
|
}
|
||||||
}, [jumpToIndex, jumpToOpenInApp, params]);
|
}, [jumpToOpenInApp, params]);
|
||||||
|
|
||||||
const subtitle = (
|
const subtitle = (
|
||||||
<div className={styles.leftContentText}>
|
<div className={styles.leftContentText}>
|
||||||
@@ -49,7 +50,7 @@ export const Component = () => {
|
|||||||
title={t['com.affine.payment.ai-upgrade-success-page.title']()}
|
title={t['com.affine.payment.ai-upgrade-success-page.title']()}
|
||||||
subtitle={subtitle}
|
subtitle={subtitle}
|
||||||
>
|
>
|
||||||
<Button variant="primary" size="extraLarge" onClick={openAffine}>
|
<Button variant="primary" size="extraLarge" onClick={openAFFiNE}>
|
||||||
{t['com.affine.other-page.nav.open-affine']()}
|
{t['com.affine.other-page.nav.open-affine']()}
|
||||||
</Button>
|
</Button>
|
||||||
</AuthPageContainer>
|
</AuthPageContainer>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Button, Loading } from '@affine/component';
|
import { Button, Loading } from '@affine/component';
|
||||||
|
import { UrlService } from '@affine/core/modules/url';
|
||||||
import { UserFriendlyError } from '@affine/error';
|
import { UserFriendlyError } from '@affine/error';
|
||||||
import {
|
import {
|
||||||
SubscriptionPlan,
|
SubscriptionPlan,
|
||||||
@@ -95,9 +96,10 @@ function getProductTriple(searchParams: URLSearchParams): ProductTriple {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const Component = () => {
|
export const Component = () => {
|
||||||
const { authService, subscriptionService } = useServices({
|
const { authService, subscriptionService, urlService } = useServices({
|
||||||
AuthService,
|
AuthService,
|
||||||
SubscriptionService,
|
SubscriptionService,
|
||||||
|
UrlService,
|
||||||
});
|
});
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
const [message, setMessage] = useState('');
|
const [message, setMessage] = useState('');
|
||||||
@@ -155,7 +157,8 @@ export const Component = () => {
|
|||||||
),
|
),
|
||||||
});
|
});
|
||||||
setMessage('Redirecting...');
|
setMessage('Redirecting...');
|
||||||
location.href = checkout;
|
urlService.openPopupWindow(checkout);
|
||||||
|
jumpToIndex();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const e = UserFriendlyError.fromAny(err);
|
const e = UserFriendlyError.fromAny(err);
|
||||||
setMessage(e.message);
|
setMessage(e.message);
|
||||||
@@ -180,6 +183,7 @@ export const Component = () => {
|
|||||||
retryKey,
|
retryKey,
|
||||||
variant,
|
variant,
|
||||||
coupon,
|
coupon,
|
||||||
|
urlService,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -16,16 +16,15 @@ export const Component = () => {
|
|||||||
const t = useI18n();
|
const t = useI18n();
|
||||||
const [params] = useSearchParams();
|
const [params] = useSearchParams();
|
||||||
|
|
||||||
const { jumpToIndex, jumpToOpenInApp } = useNavigateHelper();
|
const { jumpToOpenInApp } = useNavigateHelper();
|
||||||
const openAffine = useCallback(() => {
|
const openAFFiNE = useCallback(() => {
|
||||||
if (params.get('schema')) {
|
if (params.get('client')) {
|
||||||
jumpToOpenInApp('bring-to-front');
|
return jumpToOpenInApp('bring-to-front');
|
||||||
} else {
|
} else {
|
||||||
jumpToIndex();
|
// close popup window
|
||||||
|
return window.close();
|
||||||
}
|
}
|
||||||
// close popup window
|
}, [jumpToOpenInApp, params]);
|
||||||
window.close();
|
|
||||||
}, [jumpToIndex, jumpToOpenInApp, params]);
|
|
||||||
|
|
||||||
const subtitle = (
|
const subtitle = (
|
||||||
<div className={styles.leftContentText}>
|
<div className={styles.leftContentText}>
|
||||||
@@ -51,7 +50,7 @@ export const Component = () => {
|
|||||||
title={t['com.affine.payment.upgrade-success-page.title']()}
|
title={t['com.affine.payment.upgrade-success-page.title']()}
|
||||||
subtitle={subtitle}
|
subtitle={subtitle}
|
||||||
>
|
>
|
||||||
<Button variant="primary" size="extraLarge" onClick={openAffine}>
|
<Button variant="primary" size="extraLarge" onClick={openAFFiNE}>
|
||||||
{t['com.affine.other-page.nav.open-affine']()}
|
{t['com.affine.other-page.nav.open-affine']()}
|
||||||
</Button>
|
</Button>
|
||||||
</AuthPageContainer>
|
</AuthPageContainer>
|
||||||
|
|||||||
@@ -71,9 +71,12 @@ export const UpgradeToTeam = ({ recurring }: { recurring: string | null }) => {
|
|||||||
const [selectedWorkspace, setSelectedWorkspace] =
|
const [selectedWorkspace, setSelectedWorkspace] =
|
||||||
useState<WorkspaceMetadata | null>(null);
|
useState<WorkspaceMetadata | null>(null);
|
||||||
|
|
||||||
const information = useWorkspaceInfo(selectedWorkspace || undefined);
|
const workspacesService = useService(WorkspacesService);
|
||||||
|
const profile = selectedWorkspace
|
||||||
const name = information?.name ?? UNTITLED_WORKSPACE_NAME;
|
? workspacesService.getProfile(selectedWorkspace)
|
||||||
|
: undefined;
|
||||||
|
const workspaceInfo = useLiveData(profile?.profile$);
|
||||||
|
const name = workspaceInfo?.name ?? UNTITLED_WORKSPACE_NAME;
|
||||||
|
|
||||||
const menuTriggerText = useMemo(() => {
|
const menuTriggerText = useMemo(() => {
|
||||||
if (selectedWorkspace) {
|
if (selectedWorkspace) {
|
||||||
@@ -92,6 +95,39 @@ export const UpgradeToTeam = ({ recurring }: { recurring: string | null }) => {
|
|||||||
setOpenCreate(true);
|
setOpenCreate(true);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const revalidate = useCallback(() => {
|
||||||
|
profile?.revalidate();
|
||||||
|
}, [profile]);
|
||||||
|
|
||||||
|
const { jumpToPage, jumpToOpenInApp } = useNavigateHelper();
|
||||||
|
const [params] = useSearchParams();
|
||||||
|
const isTeam = workspaceInfo?.isTeam;
|
||||||
|
|
||||||
|
const openAFFiNE = useCallback(() => {
|
||||||
|
if (params.get('client')) {
|
||||||
|
jumpToOpenInApp(`/workspace/${selectedWorkspace?.id}/all`);
|
||||||
|
} else if (selectedWorkspace) {
|
||||||
|
jumpToPage(selectedWorkspace.id, 'all');
|
||||||
|
}
|
||||||
|
}, [jumpToOpenInApp, jumpToPage, params, selectedWorkspace]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
revalidate();
|
||||||
|
}, [selectedWorkspace, revalidate]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
window.addEventListener('focus', revalidate);
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('focus', revalidate);
|
||||||
|
};
|
||||||
|
}, [revalidate]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isTeam && selectedWorkspace) {
|
||||||
|
return openAFFiNE();
|
||||||
|
}
|
||||||
|
}, [isTeam, jumpToPage, openAFFiNE, selectedWorkspace]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AuthPageContainer title={t['com.affine.upgrade-to-team-page.title']()}>
|
<AuthPageContainer title={t['com.affine.upgrade-to-team-page.title']()}>
|
||||||
<div className={styles.root}>
|
<div className={styles.root}>
|
||||||
@@ -139,12 +175,15 @@ export const UpgradeToTeam = ({ recurring }: { recurring: string | null }) => {
|
|||||||
<div>
|
<div>
|
||||||
{t['com.affine.upgrade-to-team-page.benefit.description']()}
|
{t['com.affine.upgrade-to-team-page.benefit.description']()}
|
||||||
</div>
|
</div>
|
||||||
<UpgradeDialog
|
{selectedWorkspace && (
|
||||||
recurring={recurring}
|
<UpgradeDialog
|
||||||
open={openUpgrade}
|
recurring={recurring}
|
||||||
onOpenChange={setOpenUpgrade}
|
open={openUpgrade}
|
||||||
selectedWorkspace={selectedWorkspace}
|
onOpenChange={setOpenUpgrade}
|
||||||
/>
|
workspaceId={selectedWorkspace.id}
|
||||||
|
workspaceName={name}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<CreateWorkspaceDialog
|
<CreateWorkspaceDialog
|
||||||
open={openCreate}
|
open={openCreate}
|
||||||
onOpenChange={setOpenCreate}
|
onOpenChange={setOpenCreate}
|
||||||
@@ -172,52 +211,22 @@ export const UpgradeToTeam = ({ recurring }: { recurring: string | null }) => {
|
|||||||
const UpgradeDialog = ({
|
const UpgradeDialog = ({
|
||||||
open,
|
open,
|
||||||
onOpenChange,
|
onOpenChange,
|
||||||
selectedWorkspace,
|
workspaceId,
|
||||||
|
workspaceName,
|
||||||
recurring,
|
recurring,
|
||||||
}: {
|
}: {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
selectedWorkspace: WorkspaceMetadata | null;
|
workspaceId: string;
|
||||||
|
workspaceName: string;
|
||||||
recurring: string | null;
|
recurring: string | null;
|
||||||
onOpenChange: (open: boolean) => void;
|
onOpenChange: (open: boolean) => void;
|
||||||
}) => {
|
}) => {
|
||||||
const t = useI18n();
|
const t = useI18n();
|
||||||
const workspacesService = useService(WorkspacesService);
|
|
||||||
const { jumpToPage } = useNavigateHelper();
|
|
||||||
|
|
||||||
const profile = selectedWorkspace
|
|
||||||
? workspacesService.getProfile(selectedWorkspace)
|
|
||||||
: undefined;
|
|
||||||
const workspaceInfo = useLiveData(profile?.profile$);
|
|
||||||
const isTeam = workspaceInfo?.isTeam;
|
|
||||||
const workspaceName = workspaceInfo?.name;
|
|
||||||
const workspaceId = selectedWorkspace?.id;
|
|
||||||
|
|
||||||
const onClose = useCallback(() => {
|
const onClose = useCallback(() => {
|
||||||
onOpenChange(false);
|
onOpenChange(false);
|
||||||
}, [onOpenChange]);
|
}, [onOpenChange]);
|
||||||
|
|
||||||
const revalidate = useCallback(() => {
|
|
||||||
profile?.revalidate();
|
|
||||||
}, [profile]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
revalidate();
|
|
||||||
}, [selectedWorkspace, revalidate]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
window.addEventListener('focus', revalidate);
|
|
||||||
return () => {
|
|
||||||
window.removeEventListener('focus', revalidate);
|
|
||||||
};
|
|
||||||
}, [revalidate]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (isTeam && selectedWorkspace) {
|
|
||||||
onClose();
|
|
||||||
return jumpToPage(selectedWorkspace.id, 'all');
|
|
||||||
}
|
|
||||||
}, [isTeam, jumpToPage, onClose, selectedWorkspace]);
|
|
||||||
|
|
||||||
const currentRecurring =
|
const currentRecurring =
|
||||||
recurring &&
|
recurring &&
|
||||||
recurring.toLowerCase() === SubscriptionRecurring.Yearly.toLowerCase()
|
recurring.toLowerCase() === SubscriptionRecurring.Yearly.toLowerCase()
|
||||||
|
|||||||
Reference in New Issue
Block a user