mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-21 12:06:35 +08:00
chore(core): replace with new track impl (#7735)
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { Button, FlexWrapper, notify } from '@affine/component';
|
||||
import { openSettingModalAtom } from '@affine/core/atoms';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { SubscriptionService } from '@affine/core/modules/cloud';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { AiIcon } from '@blocksuite/icons/rc';
|
||||
@@ -65,11 +65,7 @@ export const AIOnboardingEdgeless = () => {
|
||||
const mode = useLiveData(doc.mode$);
|
||||
|
||||
const goToPricingPlans = useCallback(() => {
|
||||
mixpanel.track('PlansViewed', {
|
||||
page: 'whiteboard editor',
|
||||
segment: 'ai onboarding',
|
||||
module: 'whiteboard dialog',
|
||||
});
|
||||
track.$.aiOnboarding.dialog.viewPlans();
|
||||
setSettingModal({
|
||||
open: true,
|
||||
activeTab: 'plans',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Button, IconButton, Modal } from '@affine/component';
|
||||
import { openSettingModalAtom } from '@affine/core/atoms';
|
||||
import { useBlurRoot } from '@affine/core/hooks/use-blur-root';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { AuthService, SubscriptionService } from '@affine/core/modules/cloud';
|
||||
import { Trans, useI18n } from '@affine/i18n';
|
||||
import { ArrowLeftSmallIcon } from '@blocksuite/icons/rc';
|
||||
@@ -116,11 +116,7 @@ export const AIOnboardingGeneral = () => {
|
||||
activeTab: 'plans',
|
||||
scrollAnchor: 'aiPricingPlan',
|
||||
});
|
||||
mixpanel.track('PlansViewed', {
|
||||
page: 'whiteboard editor',
|
||||
segment: 'ai onboarding',
|
||||
module: 'general',
|
||||
});
|
||||
track.$.aiOnboarding.dialog.viewPlans();
|
||||
closeAndDismiss();
|
||||
}, [closeAndDismiss, setSettingModal]);
|
||||
const onPrev = useCallback(() => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { notify, Skeleton } from '@affine/component';
|
||||
import { Button } from '@affine/component/ui/button';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { OAuthProviderType } from '@affine/graphql';
|
||||
import { GithubIcon, GoogleDuotoneIcon } from '@blocksuite/icons/rc';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
@@ -75,7 +75,7 @@ function OAuthProvider({
|
||||
notify.error({ title: 'Failed to sign in, please try again.' });
|
||||
} finally {
|
||||
setIsConnecting(false);
|
||||
mixpanel.track('OAuth', { provider });
|
||||
track.$.$.auth.oauth({ provider });
|
||||
}
|
||||
}, [authService, provider, redirectUri]);
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { AuthInput, ModalHeader } from '@affine/component/auth-components';
|
||||
import { Button } from '@affine/component/ui/button';
|
||||
import { authAtom } from '@affine/core/atoms';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { Trans, useI18n } from '@affine/i18n';
|
||||
import { ArrowRightBigIcon } from '@blocksuite/icons/rc';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
@@ -75,9 +75,7 @@ export const SignIn: FC<AuthPanelProps> = ({
|
||||
if (hasPassword) {
|
||||
setAuthState('signInWithPassword');
|
||||
} else {
|
||||
mixpanel.track('SignIn', {
|
||||
email,
|
||||
});
|
||||
track.$.$.auth.signIn();
|
||||
await authService.sendEmailMagicLink(
|
||||
email,
|
||||
verifyToken,
|
||||
@@ -93,9 +91,7 @@ export const SignIn: FC<AuthPanelProps> = ({
|
||||
challenge,
|
||||
searchParams.get('redirect_uri')
|
||||
);
|
||||
mixpanel.track('SignUp', {
|
||||
email,
|
||||
});
|
||||
track.$.$.auth.signUp();
|
||||
setAuthState('afterSignUpSendEmail');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Tooltip } from '@affine/component/ui/tooltip';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { SubscriptionPlan } from '@affine/graphql';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { useLiveData, useServices } from '@toeverything/infra';
|
||||
@@ -44,10 +43,6 @@ export const UserPlanButton = () => {
|
||||
activeTab: 'plans',
|
||||
scrollAnchor: 'cloudPricingPlan',
|
||||
});
|
||||
mixpanel.track('PlansViewed', {
|
||||
segment: 'settings panel',
|
||||
module: 'profile and badge',
|
||||
});
|
||||
},
|
||||
[setSettingModalAtom]
|
||||
);
|
||||
@@ -72,6 +67,7 @@ export const UserPlanButton = () => {
|
||||
data-is-believer={isBeliever ? 'true' : undefined}
|
||||
className={styles.userPlanButton}
|
||||
onClick={handleClick}
|
||||
data-event-props="$.settingsPanel.profileAndBadge.viewPlans"
|
||||
>
|
||||
{planLabel}
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { ConfirmModalProps } from '@affine/component/ui/modal';
|
||||
import { ConfirmModal, Modal } from '@affine/component/ui/modal';
|
||||
import { authAtom } from '@affine/core/atoms';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { DebugLogger } from '@affine/debug';
|
||||
import { apis } from '@affine/electron-api';
|
||||
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||
@@ -222,9 +222,7 @@ export const CreateWorkspaceModal = ({
|
||||
|
||||
const onConfirmName = useAsyncCallback(
|
||||
async (name: string, workspaceFlavour: WorkspaceFlavour) => {
|
||||
mixpanel.track('CreateWorkspace', {
|
||||
workspaceFlavour,
|
||||
});
|
||||
track.$.$.$.createWorkspace({ flavour: workspaceFlavour });
|
||||
if (loading) return;
|
||||
setLoading(true);
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Button, IconButton } from '@affine/component/ui/button';
|
||||
import { Modal, useConfirmModal } from '@affine/component/ui/modal';
|
||||
import { openSettingModalAtom } from '@affine/core/atoms';
|
||||
import { useDocCollectionPageTitle } from '@affine/core/hooks/use-block-suite-workspace-page-title';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { WorkspacePermissionService } from '@affine/core/modules/permissions';
|
||||
import { WorkspaceQuotaService } from '@affine/core/modules/quota';
|
||||
import { i18nTime, Trans, useI18n } from '@affine/i18n';
|
||||
@@ -108,18 +108,17 @@ const HistoryEditorPreview = ({
|
||||
mode,
|
||||
title,
|
||||
}: HistoryEditorPreviewProps) => {
|
||||
const onSwitchToPageMode = useCallback(() => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'HistorySwitchToPageMode',
|
||||
});
|
||||
onModeChange('page');
|
||||
}, [onModeChange]);
|
||||
const onSwitchToEdgelessMode = useCallback(() => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'HistorySwitchToEdgelessMode',
|
||||
});
|
||||
onModeChange('edgeless');
|
||||
}, [onModeChange]);
|
||||
const { onSwitchToPageMode, onSwitchToEdgelessMode } = useMemo(
|
||||
() => ({
|
||||
onSwitchToPageMode: () => {
|
||||
onModeChange('page');
|
||||
},
|
||||
onSwitchToEdgelessMode: () => {
|
||||
onModeChange('edgeless');
|
||||
},
|
||||
}),
|
||||
[onModeChange]
|
||||
);
|
||||
|
||||
const content = useMemo(() => {
|
||||
return (
|
||||
@@ -129,11 +128,15 @@ const HistoryEditorPreview = ({
|
||||
<PageSwitchItem
|
||||
data-testid="switch-page-mode-button"
|
||||
active={mode === 'page'}
|
||||
data-event-props="$.docHistory.$.switchPageMode"
|
||||
data-event-args-type="page"
|
||||
onClick={onSwitchToPageMode}
|
||||
/>
|
||||
<EdgelessSwitchItem
|
||||
data-testid="switch-edgeless-mode-button"
|
||||
active={mode === 'edgeless'}
|
||||
data-event-props="$.docHistory.$.switchPageMode"
|
||||
data-event-args-type="edgeless"
|
||||
onClick={onSwitchToEdgelessMode}
|
||||
/>
|
||||
</StyledEditorModeSwitch>
|
||||
@@ -229,9 +232,7 @@ const PlanPrompt = () => {
|
||||
activeTab: 'plans',
|
||||
scrollAnchor: 'cloudPricingPlan',
|
||||
});
|
||||
mixpanel.track('PlansViewed', {
|
||||
segment: 'doc history',
|
||||
});
|
||||
track.$.docHistory.$.viewPlans();
|
||||
}, [setSettingModalAtom]);
|
||||
|
||||
const t = useI18n();
|
||||
@@ -562,9 +563,7 @@ export const GlobalPageHistoryModal = () => {
|
||||
const workspace = useService(WorkspaceService).workspace;
|
||||
const handleOpenChange = useCallback(
|
||||
(open: boolean) => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: open ? 'OpenPageHistoryModal' : 'ClosePageHistoryModal',
|
||||
});
|
||||
track.$.docHistory.$[open ? 'open' : 'close']();
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
open,
|
||||
|
||||
+2
-6
@@ -1,6 +1,6 @@
|
||||
import { ConfirmModal } from '@affine/component/ui/modal';
|
||||
import { openQuotaModalAtom, openSettingModalAtom } from '@affine/core/atoms';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { UserQuotaService } from '@affine/core/modules/cloud';
|
||||
import { WorkspacePermissionService } from '@affine/core/modules/permissions';
|
||||
import { WorkspaceQuotaService } from '@affine/core/modules/quota';
|
||||
@@ -50,11 +50,7 @@ export const CloudQuotaModal = () => {
|
||||
scrollAnchor: 'cloudPricingPlan',
|
||||
});
|
||||
|
||||
mixpanel.track('PlansViewed', {
|
||||
segment: 'payment wall',
|
||||
category: 'payment wall storage',
|
||||
});
|
||||
|
||||
track.$.paywall.storage.viewPlans();
|
||||
setOpen(false);
|
||||
}, [setOpen, setSettingModalAtom]);
|
||||
|
||||
|
||||
+4
-8
@@ -1,12 +1,13 @@
|
||||
import { Button, ErrorMessage, Skeleton } from '@affine/component';
|
||||
import { SettingRow } from '@affine/component/setting-components';
|
||||
import { openSettingModalAtom } from '@affine/core/atoms';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import {
|
||||
ServerConfigService,
|
||||
SubscriptionService,
|
||||
UserCopilotQuotaService,
|
||||
} from '@affine/core/modules/cloud';
|
||||
import { SubscriptionPlan } from '@affine/graphql';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import { cssVar } from '@toeverything/theme';
|
||||
@@ -47,12 +48,7 @@ export const AIUsagePanel = () => {
|
||||
open: true,
|
||||
activeTab: 'billing',
|
||||
});
|
||||
mixpanel.track('BillingViewed', {
|
||||
segment: 'settings panel',
|
||||
module: 'account usage list',
|
||||
control: 'change plan button',
|
||||
type: 'ai subscription',
|
||||
});
|
||||
track.$.settingsPanel.accountUsage.viewPlans({ plan: SubscriptionPlan.AI });
|
||||
}, [setOpenSettingModal]);
|
||||
|
||||
if (loading) {
|
||||
@@ -104,7 +100,7 @@ export const AIUsagePanel = () => {
|
||||
>
|
||||
{copilotActionLimit === 'unlimited' ? (
|
||||
hasPaymentFeature && aiSubscription?.canceledAt ? (
|
||||
<AIResume module="billing subscription list" />
|
||||
<AIResume />
|
||||
) : (
|
||||
<Button onClick={openBilling}>
|
||||
{t['com.affine.payment.ai.usage.change-button-label']()}
|
||||
|
||||
+9
-17
@@ -6,7 +6,8 @@ import {
|
||||
import { Avatar } from '@affine/component/ui/avatar';
|
||||
import { Button } from '@affine/component/ui/button';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { SubscriptionPlan } from '@affine/graphql';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { ArrowRightSmallIcon, CameraIcon } from '@blocksuite/icons/rc';
|
||||
import {
|
||||
@@ -38,9 +39,7 @@ export const UserAvatar = () => {
|
||||
const handleUpdateUserAvatar = useAsyncCallback(
|
||||
async (file: File) => {
|
||||
try {
|
||||
mixpanel.track('UploadAvatar', {
|
||||
userId: account.id,
|
||||
});
|
||||
track.$.settingsPanel.accountSettings.uploadAvatar();
|
||||
await session.uploadAvatar(file);
|
||||
notify.success({ title: 'Update user avatar success' });
|
||||
} catch (e) {
|
||||
@@ -51,18 +50,16 @@ export const UserAvatar = () => {
|
||||
});
|
||||
}
|
||||
},
|
||||
[account, session]
|
||||
[session]
|
||||
);
|
||||
|
||||
const handleRemoveUserAvatar = useAsyncCallback(
|
||||
async (e: MouseEvent<HTMLButtonElement>) => {
|
||||
mixpanel.track('RemoveAvatar', {
|
||||
userId: account.id,
|
||||
});
|
||||
track.$.settingsPanel.accountSettings.removeAvatar();
|
||||
e.stopPropagation();
|
||||
await session.removeAvatar();
|
||||
},
|
||||
[account, session]
|
||||
[session]
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -104,9 +101,7 @@ export const AvatarAndName = () => {
|
||||
}
|
||||
|
||||
try {
|
||||
mixpanel.track('UpdateUsername', {
|
||||
userId: account.id,
|
||||
});
|
||||
track.$.settingsPanel.accountSettings.updateUserName();
|
||||
await session.updateLabel(input);
|
||||
} catch (e) {
|
||||
notify.error({
|
||||
@@ -161,11 +156,8 @@ const StoragePanel = () => {
|
||||
|
||||
const setSettingModalAtom = useSetAtom(openSettingModalAtom);
|
||||
const onUpgrade = useCallback(() => {
|
||||
mixpanel.track('PlansViewed', {
|
||||
segment: 'settings panel',
|
||||
module: 'account usage list',
|
||||
control: 'cloud storage upgrade button',
|
||||
type: 'cloud subscription',
|
||||
track.$.settingsPanel.accountUsage.viewPlans({
|
||||
plan: SubscriptionPlan.Pro,
|
||||
});
|
||||
setSettingModalAtom({
|
||||
open: true,
|
||||
|
||||
+12
-33
@@ -9,7 +9,7 @@ import { Button, IconButton } from '@affine/component/ui/button';
|
||||
import { Loading } from '@affine/component/ui/loading';
|
||||
import { getUpgradeQuestionnaireLink } from '@affine/core/hooks/affine/use-subscription-notify';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import type { InvoicesQuery } from '@affine/graphql';
|
||||
import {
|
||||
createCustomerPortalMutation,
|
||||
@@ -112,22 +112,14 @@ const SubscriptionSettings = () => {
|
||||
|
||||
const openPlans = useCallback(
|
||||
(scrollAnchor?: PlansScrollAnchor) => {
|
||||
mixpanel.track('PlansViewed', {
|
||||
type: proSubscription?.plan,
|
||||
category: proSubscription?.recurring,
|
||||
// page:
|
||||
segment: 'settings panel',
|
||||
module: 'billing subscription list',
|
||||
control: 'change plan button',
|
||||
});
|
||||
|
||||
track.$.settingsPanel.billing.viewPlans();
|
||||
setOpenSettingModalAtom({
|
||||
open: true,
|
||||
activeTab: 'plans',
|
||||
scrollAnchor: scrollAnchor,
|
||||
});
|
||||
},
|
||||
[proSubscription?.plan, proSubscription?.recurring, setOpenSettingModalAtom]
|
||||
[setOpenSettingModalAtom]
|
||||
);
|
||||
const gotoCloudPlansSetting = useCallback(
|
||||
() => openPlans('cloudPricingPlan'),
|
||||
@@ -238,7 +230,6 @@ const SubscriptionSettings = () => {
|
||||
</SettingRow>
|
||||
) : (
|
||||
<CancelAction
|
||||
module="billing subscription list"
|
||||
open={openCancelModal}
|
||||
onOpenChange={setOpenCancelModal}
|
||||
>
|
||||
@@ -396,15 +387,9 @@ const AIPlanCard = ({ onClick }: { onClick: () => void }) => {
|
||||
{price?.yearlyAmount ? (
|
||||
subscription ? (
|
||||
subscription.canceledAt ? (
|
||||
<AIResume
|
||||
module="billing subscription list"
|
||||
className={styles.planAction}
|
||||
/>
|
||||
<AIResume className={styles.planAction} />
|
||||
) : (
|
||||
<AICancel
|
||||
module="billing subscription list"
|
||||
className={styles.planAction}
|
||||
/>
|
||||
<AICancel className={styles.planAction} />
|
||||
)
|
||||
) : (
|
||||
<AISubscribe className={styles.planAction}>
|
||||
@@ -470,22 +455,16 @@ const ResumeSubscription = () => {
|
||||
const subscription = useService(SubscriptionService).subscription;
|
||||
const handleClick = useCallback(() => {
|
||||
setOpen(true);
|
||||
const type = subscription.pro$.value?.plan;
|
||||
const category = subscription.pro$.value?.recurring;
|
||||
if (type && category) {
|
||||
mixpanel.track('PlanChangeStarted', {
|
||||
segment: 'settings panel',
|
||||
module: 'pricing plan list',
|
||||
control: 'paying',
|
||||
type,
|
||||
category,
|
||||
});
|
||||
}
|
||||
}, [subscription.pro$.value?.plan, subscription.pro$.value?.recurring]);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<ResumeAction open={open} onOpenChange={setOpen}>
|
||||
<Button onClick={handleClick}>
|
||||
<Button
|
||||
onClick={handleClick}
|
||||
data-event-props="$.settingsPanel.plans.resumeSubscription"
|
||||
data-event-args-type={subscription.pro$.value?.plan}
|
||||
data-event-args-category={subscription.pro$.value?.recurring}
|
||||
>
|
||||
{t['com.affine.payment.billing-setting.resume-subscription']()}
|
||||
</Button>
|
||||
</ResumeAction>
|
||||
|
||||
+11
-18
@@ -1,6 +1,6 @@
|
||||
import { getDowngradeQuestionnaireLink } from '@affine/core/hooks/affine/use-subscription-notify';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { SubscriptionPlan } from '@affine/graphql';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import { nanoid } from 'nanoid';
|
||||
@@ -20,11 +20,9 @@ export const CancelAction = ({
|
||||
children,
|
||||
open,
|
||||
onOpenChange,
|
||||
module,
|
||||
}: {
|
||||
open: boolean;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
module: string;
|
||||
} & PropsWithChildren) => {
|
||||
const [idempotencyKey, setIdempotencyKey] = useState(nanoid());
|
||||
const [isMutating, setIsMutating] = useState(false);
|
||||
@@ -35,14 +33,11 @@ export const CancelAction = ({
|
||||
|
||||
useEffect(() => {
|
||||
if (!open || !proSubscription) return;
|
||||
mixpanel.track('PlanChangeStarted', {
|
||||
segment: 'settings panel',
|
||||
module,
|
||||
control: 'cancel',
|
||||
type: proSubscription.plan,
|
||||
category: proSubscription.recurring,
|
||||
track.$.settingsPanel.plans.cancelSubscription({
|
||||
plan: proSubscription.plan,
|
||||
recurring: proSubscription.recurring,
|
||||
});
|
||||
}, [module, open, proSubscription]);
|
||||
}, [open, proSubscription]);
|
||||
|
||||
const downgrade = useAsyncCallback(async () => {
|
||||
try {
|
||||
@@ -57,10 +52,9 @@ export const CancelAction = ({
|
||||
onOpenChange(false);
|
||||
const proSubscription = subscription.pro$.value;
|
||||
if (proSubscription) {
|
||||
mixpanel.track('PlanChangeSucceeded', {
|
||||
control: 'cancel',
|
||||
type: proSubscription.plan,
|
||||
category: proSubscription.recurring,
|
||||
track.$.settingsPanel.plans.confirmCancelingSubscription({
|
||||
plan: proSubscription.plan,
|
||||
recurring: proSubscription.recurring,
|
||||
});
|
||||
}
|
||||
if (account && prevRecurring) {
|
||||
@@ -127,10 +121,9 @@ export const ResumeAction = ({
|
||||
onOpenChange(false);
|
||||
const proSubscription = subscription.pro$.value;
|
||||
if (proSubscription) {
|
||||
mixpanel.track('PlanChangeSucceeded', {
|
||||
control: 'paying',
|
||||
type: proSubscription.plan,
|
||||
category: proSubscription.recurring,
|
||||
track.$.settingsPanel.plans.confirmResumingSubscription({
|
||||
plan: proSubscription.plan,
|
||||
recurring: proSubscription.recurring,
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
|
||||
+8
-16
@@ -2,7 +2,7 @@ import { Button, type ButtonProps, useConfirmModal } from '@affine/component';
|
||||
import { useDowngradeNotify } from '@affine/core/components/affine/subscription-landing/notify';
|
||||
import { getDowngradeQuestionnaireLink } from '@affine/core/hooks/affine/use-subscription-notify';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { AuthService, SubscriptionService } from '@affine/core/modules/cloud';
|
||||
import { SubscriptionPlan } from '@affine/graphql';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
@@ -10,10 +10,7 @@ import { useService } from '@toeverything/infra';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { useState } from 'react';
|
||||
|
||||
export interface AICancelProps extends ButtonProps {
|
||||
module: string;
|
||||
}
|
||||
export const AICancel = ({ module, ...btnProps }: AICancelProps) => {
|
||||
export const AICancel = (btnProps: ButtonProps) => {
|
||||
const t = useI18n();
|
||||
const [isMutating, setMutating] = useState(false);
|
||||
const [idempotencyKey, setIdempotencyKey] = useState(nanoid());
|
||||
@@ -26,12 +23,9 @@ export const AICancel = ({ module, ...btnProps }: AICancelProps) => {
|
||||
const cancel = useAsyncCallback(async () => {
|
||||
const aiSubscription = subscription.ai$.value;
|
||||
if (aiSubscription) {
|
||||
mixpanel.track('PlanChangeStarted', {
|
||||
module,
|
||||
segment: 'settings panel',
|
||||
control: 'cancel',
|
||||
type: SubscriptionPlan.AI,
|
||||
category: aiSubscription.recurring,
|
||||
track.$.settingsPanel.plans.cancelSubscription({
|
||||
plan: SubscriptionPlan.AI,
|
||||
recurring: aiSubscription.recurring,
|
||||
});
|
||||
}
|
||||
openConfirmModal({
|
||||
@@ -57,10 +51,9 @@ export const AICancel = ({ module, ...btnProps }: AICancelProps) => {
|
||||
SubscriptionPlan.AI
|
||||
);
|
||||
setIdempotencyKey(nanoid());
|
||||
mixpanel.track('PlanChangeSucceeded', {
|
||||
segment: 'settings panel',
|
||||
control: 'plan cancel action',
|
||||
type: subscription.ai$.value?.plan,
|
||||
track.$.settingsPanel.plans.confirmCancelingSubscription({
|
||||
plan: SubscriptionPlan.AI,
|
||||
recurring: aiSubscription?.recurring,
|
||||
});
|
||||
const account = authService.session.account$.value;
|
||||
const prevRecurring = subscription.ai$.value?.recurring;
|
||||
@@ -81,7 +74,6 @@ export const AICancel = ({ module, ...btnProps }: AICancelProps) => {
|
||||
},
|
||||
});
|
||||
}, [
|
||||
module,
|
||||
subscription,
|
||||
openConfirmModal,
|
||||
t,
|
||||
|
||||
+9
-17
@@ -5,7 +5,7 @@ import {
|
||||
useConfirmModal,
|
||||
} from '@affine/component';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { SubscriptionService } from '@affine/core/modules/cloud';
|
||||
import { SubscriptionPlan } from '@affine/graphql';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
@@ -15,11 +15,7 @@ import { cssVar } from '@toeverything/theme';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { useState } from 'react';
|
||||
|
||||
export interface AIResumeProps extends ButtonProps {
|
||||
module: string;
|
||||
}
|
||||
|
||||
export const AIResume = ({ module, ...btnProps }: AIResumeProps) => {
|
||||
export const AIResume = (btnProps: ButtonProps) => {
|
||||
const t = useI18n();
|
||||
const [idempotencyKey, setIdempotencyKey] = useState(nanoid());
|
||||
const subscription = useService(SubscriptionService).subscription;
|
||||
@@ -31,12 +27,9 @@ export const AIResume = ({ module, ...btnProps }: AIResumeProps) => {
|
||||
const resume = useAsyncCallback(async () => {
|
||||
const aiSubscription = subscription.ai$.value;
|
||||
if (aiSubscription) {
|
||||
mixpanel.track('PlanChangeStarted', {
|
||||
module,
|
||||
segment: 'settings panel',
|
||||
control: 'paying',
|
||||
type: aiSubscription.plan,
|
||||
category: aiSubscription.recurring,
|
||||
track.$.settingsPanel.plans.resumeSubscription({
|
||||
plan: SubscriptionPlan.AI,
|
||||
recurring: aiSubscription.recurring,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -58,10 +51,9 @@ export const AIResume = ({ module, ...btnProps }: AIResumeProps) => {
|
||||
SubscriptionPlan.AI
|
||||
);
|
||||
if (aiSubscription) {
|
||||
mixpanel.track('PlanChangeSucceeded', {
|
||||
category: aiSubscription.recurring,
|
||||
control: 'paying',
|
||||
type: aiSubscription.plan,
|
||||
track.$.settingsPanel.plans.confirmResumingSubscription({
|
||||
plan: aiSubscription.plan,
|
||||
recurring: aiSubscription.recurring,
|
||||
});
|
||||
}
|
||||
notify({
|
||||
@@ -75,7 +67,7 @@ export const AIResume = ({ module, ...btnProps }: AIResumeProps) => {
|
||||
setIdempotencyKey(nanoid());
|
||||
},
|
||||
});
|
||||
}, [subscription, openConfirmModal, t, module, idempotencyKey]);
|
||||
}, [subscription, openConfirmModal, t, idempotencyKey]);
|
||||
|
||||
return (
|
||||
<Button
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
import { Button, type ButtonProps, Skeleton } from '@affine/component';
|
||||
import { generateSubscriptionCallbackLink } from '@affine/core/hooks/affine/use-subscription-notify';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { AuthService, SubscriptionService } from '@affine/core/modules/cloud';
|
||||
import { popupWindow } from '@affine/core/utils';
|
||||
import { SubscriptionPlan, SubscriptionRecurring } from '@affine/graphql';
|
||||
@@ -50,9 +50,9 @@ export const AISubscribe = ({
|
||||
|
||||
const subscribe = useAsyncCallback(async () => {
|
||||
setMutating(true);
|
||||
mixpanel.track('PlanUpgradeStarted', {
|
||||
category: SubscriptionRecurring.Yearly,
|
||||
type: SubscriptionPlan.AI,
|
||||
track.$.settingsPanel.plans.checkout({
|
||||
plan: SubscriptionPlan.AI,
|
||||
recurring: SubscriptionRecurring.Yearly,
|
||||
});
|
||||
try {
|
||||
const session = await subscriptionService.createCheckoutSession({
|
||||
|
||||
+2
-8
@@ -53,15 +53,9 @@ export const AIPlan = () => {
|
||||
isLoggedIn ? (
|
||||
subscription ? (
|
||||
subscription.canceledAt ? (
|
||||
<AIResume
|
||||
module="pricing plan list"
|
||||
className={styles.purchaseButton}
|
||||
/>
|
||||
<AIResume className={styles.purchaseButton} />
|
||||
) : (
|
||||
<AICancel
|
||||
module="pricing plan list"
|
||||
className={styles.purchaseButton}
|
||||
/>
|
||||
<AICancel className={styles.purchaseButton} />
|
||||
)
|
||||
) : (
|
||||
<>
|
||||
|
||||
+17
-27
@@ -2,7 +2,7 @@ import { Button, type ButtonProps } from '@affine/component/ui/button';
|
||||
import { Tooltip } from '@affine/component/ui/tooltip';
|
||||
import { generateSubscriptionCallbackLink } from '@affine/core/hooks/affine/use-subscription-notify';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { AuthService, SubscriptionService } from '@affine/core/modules/cloud';
|
||||
import { popupWindow } from '@affine/core/utils';
|
||||
import type { SubscriptionRecurring } from '@affine/graphql';
|
||||
@@ -190,7 +190,7 @@ const Downgrade = ({ disabled }: { disabled?: boolean }) => {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<CancelAction module="pricing plan list" open={open} onOpenChange={setOpen}>
|
||||
<CancelAction open={open} onOpenChange={setOpen}>
|
||||
<Tooltip content={tooltipContent} rootOptions={{ delayDuration: 0 }}>
|
||||
<div className={styles.planAction}>
|
||||
<Button
|
||||
@@ -226,14 +226,13 @@ const BookDemo = ({ plan }: { plan: SubscriptionPlan }) => {
|
||||
href={url}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
onClick={() => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'BookDemo',
|
||||
url,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Button className={styles.planAction} variant="primary">
|
||||
<Button
|
||||
className={styles.planAction}
|
||||
variant="primary"
|
||||
data-event-props="$.settingsPanel.billing.bookDemo"
|
||||
data-event-args-url={url}
|
||||
>
|
||||
{t['com.affine.payment.tell-us-use-case']()}
|
||||
</Button>
|
||||
</a>
|
||||
@@ -276,12 +275,9 @@ export const Upgrade = ({
|
||||
|
||||
const upgrade = useAsyncCallback(async () => {
|
||||
setMutating(true);
|
||||
mixpanel.track('PlanUpgradeStarted', {
|
||||
segment: 'settings panel',
|
||||
module: 'pricing plan list',
|
||||
control: 'pricing plan action',
|
||||
type: 'cloud pro subscription',
|
||||
category: recurring,
|
||||
track.$.settingsPanel.plans.checkout({
|
||||
plan: SubscriptionPlan.Pro,
|
||||
recurring: recurring,
|
||||
});
|
||||
const link = await subscriptionService.createCheckoutSession({
|
||||
recurring,
|
||||
@@ -338,12 +334,9 @@ const ChangeRecurring = ({
|
||||
const subscription = useService(SubscriptionService).subscription;
|
||||
|
||||
const onStartChange = useCallback(() => {
|
||||
mixpanel.track('PlanChangeStarted', {
|
||||
segment: 'settings panel',
|
||||
module: 'pricing plan list',
|
||||
control: 'paying',
|
||||
type: SubscriptionPlan.Pro,
|
||||
category: to,
|
||||
track.$.settingsPanel.plans.changeSubscriptionRecurring({
|
||||
plan: SubscriptionPlan.Pro,
|
||||
recurring: to,
|
||||
});
|
||||
setOpen(true);
|
||||
}, [to]);
|
||||
@@ -422,12 +415,9 @@ const ResumeButton = () => {
|
||||
setOpen(true);
|
||||
const pro = subscription.pro$.value;
|
||||
if (pro) {
|
||||
mixpanel.track('PlanChangeStarted', {
|
||||
segment: 'settings panel',
|
||||
module: 'pricing plan list',
|
||||
control: 'paying',
|
||||
type: SubscriptionPlan.Pro,
|
||||
category: pro.recurring,
|
||||
track.$.settingsPanel.plans.resumeSubscription({
|
||||
plan: SubscriptionPlan.Pro,
|
||||
recurring: pro.recurring,
|
||||
});
|
||||
}
|
||||
}, [subscription.pro$.value]);
|
||||
|
||||
+24
-33
@@ -6,7 +6,7 @@ import { Avatar } from '@affine/component/ui/avatar';
|
||||
import { Tooltip } from '@affine/component/ui/tooltip';
|
||||
import { WorkspaceAvatar } from '@affine/component/workspace-avatar';
|
||||
import { useWorkspaceInfo } from '@affine/core/hooks/use-workspace-info';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { AuthService } from '@affine/core/modules/cloud';
|
||||
import { UserFeatureService } from '@affine/core/modules/cloud/services/user-feature';
|
||||
import { UNTITLED_WORKSPACE_NAME } from '@affine/env/constant';
|
||||
@@ -22,7 +22,13 @@ import {
|
||||
} from '@toeverything/infra';
|
||||
import clsx from 'clsx';
|
||||
import { useAtom } from 'jotai/react';
|
||||
import { Suspense, useCallback, useEffect, useMemo } from 'react';
|
||||
import {
|
||||
type MouseEvent,
|
||||
Suspense,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
} from 'react';
|
||||
|
||||
import { authAtom } from '../../../../atoms';
|
||||
import { UserPlanButton } from '../../auth/user-plan-button';
|
||||
@@ -115,29 +121,30 @@ export const SettingSidebar = ({
|
||||
const t = useI18n();
|
||||
const loginStatus = useLiveData(useService(AuthService).session.status$);
|
||||
const generalList = useGeneralSettingList();
|
||||
const gotoTab = useCallback(
|
||||
(e: MouseEvent<HTMLDivElement>) => {
|
||||
const tab = e.currentTarget.dataset.eventArg;
|
||||
if (!tab) return;
|
||||
track.$.settingsPanel.menu.openSettings({ to: tab });
|
||||
onTabChange(tab as ActiveTab, null);
|
||||
},
|
||||
[onTabChange]
|
||||
);
|
||||
const onAccountSettingClick = useCallback(() => {
|
||||
mixpanel.track('AccountSettingsViewed', {
|
||||
// page:
|
||||
segment: 'settings panel',
|
||||
module: 'settings menu',
|
||||
control: 'menu item',
|
||||
});
|
||||
track.$.settingsPanel.menu.openSettings({ to: 'account' });
|
||||
onTabChange('account', null);
|
||||
}, [onTabChange]);
|
||||
const onWorkspaceSettingClick = useCallback(
|
||||
(subTab: WorkspaceSubTab, workspaceMetadata: WorkspaceMetadata) => {
|
||||
mixpanel.track(`view workspace setting`, {
|
||||
// page:
|
||||
segment: 'settings panel',
|
||||
module: 'settings menu',
|
||||
control: 'menu item',
|
||||
type: subTab,
|
||||
workspaceId: workspaceMetadata.id,
|
||||
track.$.settingsPanel.menu.openSettings({
|
||||
to: 'workspace',
|
||||
control: subTab,
|
||||
});
|
||||
onTabChange(`workspace:${subTab}`, workspaceMetadata);
|
||||
},
|
||||
[onTabChange]
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={style.settingSlideBar} data-testid="settings-sidebar">
|
||||
<div className={style.sidebarTitle}>
|
||||
@@ -155,24 +162,8 @@ export const SettingSidebar = ({
|
||||
})}
|
||||
key={key}
|
||||
title={title}
|
||||
onClick={() => {
|
||||
if (key === 'billing') {
|
||||
mixpanel.track('BillingViewed', {
|
||||
// page:
|
||||
segment: 'settings panel',
|
||||
module: 'settings menu',
|
||||
control: 'menu item',
|
||||
});
|
||||
} else if (key === 'plans') {
|
||||
mixpanel.track('PlansViewed', {
|
||||
// page:
|
||||
segment: 'settings panel',
|
||||
module: 'settings menu',
|
||||
control: 'menu item',
|
||||
});
|
||||
}
|
||||
onTabChange(key, null);
|
||||
}}
|
||||
data-event-arg={key}
|
||||
onClick={gotoTab}
|
||||
data-testid={testId}
|
||||
>
|
||||
{icon({ className: 'icon' })}
|
||||
|
||||
+3
-6
@@ -21,7 +21,7 @@ import { useMemberCount } from '@affine/core/hooks/affine/use-member-count';
|
||||
import type { Member } from '@affine/core/hooks/affine/use-members';
|
||||
import { useMembers } from '@affine/core/hooks/affine/use-members';
|
||||
import { useRevokeMemberPermission } from '@affine/core/hooks/affine/use-revoke-member-permission';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { WorkspacePermissionService } from '@affine/core/modules/permissions';
|
||||
import { WorkspaceQuotaService } from '@affine/core/modules/quota';
|
||||
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||
@@ -146,11 +146,8 @@ export const CloudWorkspaceMembersPanel = () => {
|
||||
activeTab: 'plans',
|
||||
scrollAnchor: 'cloudPricingPlan',
|
||||
});
|
||||
mixpanel.track('PlansViewed', {
|
||||
// page:
|
||||
segment: 'settings panel',
|
||||
module: 'workspace setting',
|
||||
control: 'invite member',
|
||||
track.$.settingsPanel.workspace.viewPlans({
|
||||
control: 'inviteMember',
|
||||
});
|
||||
}, [setSettingModalAtom]);
|
||||
|
||||
|
||||
+3
-6
@@ -4,7 +4,7 @@ import { Button } from '@affine/component/ui/button';
|
||||
import { Menu, MenuItem, MenuTrigger } from '@affine/component/ui/menu';
|
||||
import { useSharingUrl } from '@affine/core/hooks/affine/use-share-url';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { ServerConfigService } from '@affine/core/modules/cloud';
|
||||
import { ShareService } from '@affine/core/modules/share-doc';
|
||||
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||
@@ -106,11 +106,8 @@ export const AffineSharePage = (props: ShareMenuProps) => {
|
||||
await shareService.share.enableShare(
|
||||
mode === 'edgeless' ? PublicPageMode.Edgeless : PublicPageMode.Page
|
||||
);
|
||||
mixpanel.track('ShareCreated', {
|
||||
segment: 'sharing panel',
|
||||
module: 'public share',
|
||||
control: 'share panel',
|
||||
type: mode,
|
||||
track.$.header.share.createShareLink({
|
||||
mode,
|
||||
});
|
||||
notify.success({
|
||||
title:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { CloseIcon, DownloadIcon } from '@blocksuite/icons/rc';
|
||||
import clsx from 'clsx';
|
||||
import { useCallback, useState } from 'react';
|
||||
@@ -21,9 +21,7 @@ export function AppDownloadButton({
|
||||
|
||||
// TODO(@JimmFly): unify this type of literal value.
|
||||
const handleClick = useCallback(() => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'GoToDownloadAppPage',
|
||||
});
|
||||
track.$.navigationPanel.bottomButtons.downloadApp();
|
||||
const url = `https://affine.pro/download?channel=stable`;
|
||||
open(url, '_blank');
|
||||
}, []);
|
||||
|
||||
+2
-5
@@ -2,7 +2,7 @@ import { notify } from '@affine/component';
|
||||
import { authAtom, openSettingModalAtom } from '@affine/core/atoms';
|
||||
import { AIProvider } from '@affine/core/blocksuite/presets/ai';
|
||||
import { toggleGeneralAIOnboarding } from '@affine/core/components/affine/ai-onboarding/apis';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import {
|
||||
getBaseUrl,
|
||||
type getCopilotHistoriesQuery,
|
||||
@@ -470,10 +470,7 @@ Could you make a new website based on these notes and send back just the html fi
|
||||
activeTab: 'billing',
|
||||
open: true,
|
||||
});
|
||||
mixpanel.track('PlansViewed', {
|
||||
segment: 'payment wall',
|
||||
category: 'payment wall ai action count',
|
||||
});
|
||||
track.$.paywall.aiAction.viewPlans();
|
||||
});
|
||||
|
||||
AIProvider.slots.requestLogin.on(() => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { AIProvider } from '@affine/core/blocksuite/presets/ai';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { mixpanel, track } from '@affine/core/mixpanel';
|
||||
import type { EditorHost } from '@blocksuite/block-std';
|
||||
import type { BlockModel } from '@blocksuite/store';
|
||||
import { lowerCase, omit } from 'lodash-es';
|
||||
@@ -13,7 +13,7 @@ type AIActionEventName =
|
||||
| 'AI result accepted';
|
||||
|
||||
type AIActionEventProperties = {
|
||||
page: 'doc-editor' | 'whiteboard-editor';
|
||||
page: 'doc' | 'edgeless';
|
||||
segment:
|
||||
| 'AI action panel'
|
||||
| 'right side bar'
|
||||
@@ -73,9 +73,7 @@ const trackAction = ({
|
||||
};
|
||||
|
||||
const inferPageMode = (host: EditorHost) => {
|
||||
return host.querySelector('affine-page-root')
|
||||
? 'doc-editor'
|
||||
: 'whiteboard-editor';
|
||||
return host.querySelector('affine-page-root') ? 'doc' : 'edgeless';
|
||||
};
|
||||
|
||||
const defaultActionOptions = [
|
||||
@@ -253,14 +251,12 @@ const toTrackedOptions = (
|
||||
|
||||
export function setupTracker() {
|
||||
AIProvider.slots.requestUpgradePlan.on(() => {
|
||||
mixpanel.track('AI', {
|
||||
action: 'requestUpgradePlan',
|
||||
});
|
||||
track.$.paywall.aiAction.viewPlans();
|
||||
});
|
||||
|
||||
AIProvider.slots.requestLogin.on(() => {
|
||||
mixpanel.track('AI', {
|
||||
action: 'requestLogin',
|
||||
track.$.$.auth.signIn({
|
||||
control: 'aiAction',
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+2
-7
@@ -1,4 +1,4 @@
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { WorkspacePropertiesAdapter } from '@affine/core/modules/properties';
|
||||
import { I18n, i18nTime } from '@affine/i18n';
|
||||
import type { EditorHost } from '@blocksuite/block-std';
|
||||
@@ -75,12 +75,7 @@ export function createLinkedWidgetConfig(framework: FrameworkProvider) {
|
||||
inlineEditor,
|
||||
docId: doc.id,
|
||||
});
|
||||
mixpanel.track('LinkedDocCreated', {
|
||||
control: 'linked doc',
|
||||
module: 'inline @',
|
||||
type: 'doc',
|
||||
other: 'existing doc',
|
||||
});
|
||||
track.doc.editor.atMenu.linkDoc();
|
||||
},
|
||||
})),
|
||||
maxDisplay: MAX_DOCS,
|
||||
|
||||
+4
-23
@@ -7,7 +7,7 @@ import {
|
||||
toReactNode,
|
||||
type useConfirmModal,
|
||||
} from '@affine/component';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { DocsSearchService } from '@affine/core/modules/docs-search';
|
||||
import { resolveLinkToDoc } from '@affine/core/modules/navigation';
|
||||
import type { PeekViewService } from '@affine/core/modules/peek-view';
|
||||
@@ -465,30 +465,11 @@ export function patchQuickSearchService(
|
||||
pageId: linkedDoc.id,
|
||||
},
|
||||
]);
|
||||
const isEdgeless =
|
||||
rootComponent instanceof EdgelessRootBlockComponent;
|
||||
if (result.isNewDoc) {
|
||||
mixpanel.track('DocCreated', {
|
||||
control: 'linked doc',
|
||||
module: 'slash commands',
|
||||
type: 'linked doc',
|
||||
category: 'doc',
|
||||
page: isEdgeless ? 'whiteboard editor' : 'doc editor',
|
||||
});
|
||||
mixpanel.track('LinkedDocCreated', {
|
||||
control: 'new doc',
|
||||
module: 'slash commands',
|
||||
type: 'doc',
|
||||
page: isEdgeless ? 'whiteboard editor' : 'doc editor',
|
||||
});
|
||||
} else {
|
||||
mixpanel.track('LinkedDocCreated', {
|
||||
control: 'linked doc',
|
||||
module: 'slash commands',
|
||||
type: 'doc',
|
||||
page: isEdgeless ? 'whiteboard editor' : 'doc editor',
|
||||
});
|
||||
track.doc.editor.slashMenu.createDoc({ control: 'linkDoc' });
|
||||
track.doc.editor.slashMenu.linkDoc({ control: 'createDoc' });
|
||||
}
|
||||
track.doc.editor.slashMenu.linkDoc({ control: 'linkDoc' });
|
||||
} else if ('userInput' in result) {
|
||||
const embedOptions = service.getEmbedBlockOptions(
|
||||
result.userInput
|
||||
|
||||
@@ -18,7 +18,7 @@ import { useEnableCloud } from '@affine/core/hooks/affine/use-enable-cloud';
|
||||
import { useExportPage } from '@affine/core/hooks/affine/use-export-page';
|
||||
import { useTrashModalHelper } from '@affine/core/hooks/affine/use-trash-modal-helper';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { WorkbenchService } from '@affine/core/modules/workbench';
|
||||
import { ViewService } from '@affine/core/modules/workbench/services/view';
|
||||
import { useDetailPageHeaderResponsive } from '@affine/core/pages/workspace/detail-page/use-header-responsive';
|
||||
@@ -157,36 +157,23 @@ export const PageHeaderMenuButton = ({
|
||||
|
||||
const handleDuplicate = useCallback(() => {
|
||||
duplicate(pageId);
|
||||
mixpanel.track('DocCreated', {
|
||||
segment: 'editor header',
|
||||
page: doc.mode$.value === 'page' ? 'doc editor' : 'edgeless editor',
|
||||
module: 'header menu',
|
||||
control: 'copy doc',
|
||||
type: 'doc duplicate',
|
||||
category: 'doc',
|
||||
track.$.header.actions.createDoc({
|
||||
control: 'duplicate',
|
||||
});
|
||||
}, [doc.mode$.value, duplicate, pageId]);
|
||||
}, [duplicate, pageId]);
|
||||
|
||||
const onImportFile = useAsyncCallback(async () => {
|
||||
const options = await importFile();
|
||||
if (options.isWorkspaceFile) {
|
||||
mixpanel.track('WorkspaceCreated', {
|
||||
segment: 'editor header',
|
||||
page: doc.mode$.value === 'page' ? 'doc editor' : 'edgeless editor',
|
||||
module: 'header menu',
|
||||
control: 'import button',
|
||||
type: 'imported workspace',
|
||||
track.$.header.actions.createWorkspace({
|
||||
control: 'import',
|
||||
});
|
||||
} else {
|
||||
mixpanel.track('DocCreated', {
|
||||
segment: 'editor header',
|
||||
page: doc.mode$.value === 'page' ? 'doc editor' : 'edgeless editor',
|
||||
module: 'header menu',
|
||||
control: 'import button',
|
||||
type: 'imported doc',
|
||||
track.$.header.actions.createDoc({
|
||||
control: 'import',
|
||||
});
|
||||
}
|
||||
}, [doc.mode$.value, importFile]);
|
||||
}, [importFile]);
|
||||
|
||||
const showResponsiveMenu = hideShare;
|
||||
const ResponsiveMenuItems = (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Tooltip } from '@affine/component/ui/tooltip';
|
||||
import { useBlockSuiteDocMeta } from '@affine/core/hooks/use-block-suite-page-meta';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import {
|
||||
type DocMode,
|
||||
@@ -62,8 +62,8 @@ export const EditorModeSwitch = ({
|
||||
}, [currentMode, isPublic, doc, pageId, t, trash]);
|
||||
|
||||
const onSwitchToPageMode = useCallback(() => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'SwitchToPageMode',
|
||||
track.$.header.actions.switchPageMode({
|
||||
mode: 'page',
|
||||
});
|
||||
if (currentMode === 'page' || isPublic) {
|
||||
return;
|
||||
@@ -73,8 +73,8 @@ export const EditorModeSwitch = ({
|
||||
}, [currentMode, isPublic, doc, t]);
|
||||
|
||||
const onSwitchToEdgelessMode = useCallback(() => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'SwitchToEdgelessMode',
|
||||
track.$.header.actions.switchPageMode({
|
||||
mode: 'edgeless',
|
||||
});
|
||||
if (currentMode === 'edgeless' || isPublic) {
|
||||
return;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { DropdownButton, Menu } from '@affine/component';
|
||||
import { BlockCard } from '@affine/component/card/block-card';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { EdgelessIcon, ImportIcon, PageIcon } from '@blocksuite/icons/rc';
|
||||
import type { PropsWithChildren } from 'react';
|
||||
@@ -70,26 +70,14 @@ export const NewPageButton = ({
|
||||
const handleCreateNewPage = useCallback(() => {
|
||||
createNewPage();
|
||||
setOpen(false);
|
||||
mixpanel.track('DocCreated', {
|
||||
page: 'doc library',
|
||||
segment: 'all doc',
|
||||
module: 'doc list header',
|
||||
control: 'new doc button',
|
||||
type: 'doc',
|
||||
category: 'page',
|
||||
});
|
||||
track.allDocs.header.actions.createDoc();
|
||||
}, [createNewPage]);
|
||||
|
||||
const handleCreateNewEdgeless = useCallback(() => {
|
||||
createNewEdgeless();
|
||||
setOpen(false);
|
||||
mixpanel.track('DocCreated', {
|
||||
page: 'doc library',
|
||||
segment: 'all doc',
|
||||
module: 'doc list header',
|
||||
control: 'new whiteboard button',
|
||||
type: 'doc',
|
||||
category: 'whiteboard',
|
||||
track.allDocs.header.actions.createDoc({
|
||||
mode: 'edgeless',
|
||||
});
|
||||
}, [createNewEdgeless]);
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
} from '@affine/component';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { useNavigateHelper } from '@affine/core/hooks/use-navigate-helper';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import type { Tag } from '@affine/core/modules/tag';
|
||||
import { TagService } from '@affine/core/modules/tag';
|
||||
import type { Collection } from '@affine/env/filter';
|
||||
@@ -49,21 +49,12 @@ export const PageListHeader = () => {
|
||||
const onImportFile = useAsyncCallback(async () => {
|
||||
const options = await importFile();
|
||||
if (options.isWorkspaceFile) {
|
||||
mixpanel.track('WorkspaceCreated', {
|
||||
page: 'doc library',
|
||||
segment: 'all doc',
|
||||
module: 'doc list header',
|
||||
control: 'import button',
|
||||
type: 'imported workspace',
|
||||
track.allDocs.header.actions.createWorkspace({
|
||||
control: 'import',
|
||||
});
|
||||
} else {
|
||||
mixpanel.track('DocCreated', {
|
||||
page: 'doc library',
|
||||
segment: 'all doc',
|
||||
module: 'doc list header',
|
||||
control: 'import button',
|
||||
type: 'imported doc',
|
||||
// category
|
||||
track.allDocs.header.actions.createDoc({
|
||||
control: 'import',
|
||||
});
|
||||
}
|
||||
}, [importFile]);
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
import { useAppSettingHelper } from '@affine/core/hooks/affine/use-app-setting-helper';
|
||||
import { useBlockSuiteMetaHelper } from '@affine/core/hooks/affine/use-block-suite-meta-helper';
|
||||
import { useTrashModalHelper } from '@affine/core/hooks/affine/use-trash-modal-helper';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { FavoriteService } from '@affine/core/modules/favorite';
|
||||
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
||||
import { WorkbenchService } from '@affine/core/modules/workbench';
|
||||
@@ -115,13 +115,8 @@ export const PageOperationCell = ({
|
||||
|
||||
const onDuplicate = useCallback(() => {
|
||||
duplicate(page.id, false);
|
||||
mixpanel.track('DocCreated', {
|
||||
segment: 'all doc',
|
||||
module: 'doc item menu',
|
||||
control: 'copy doc',
|
||||
type: 'doc duplicate',
|
||||
category: 'doc',
|
||||
page: 'doc library',
|
||||
track.allDocs.list.docMenu.createDoc({
|
||||
control: 'duplicate',
|
||||
});
|
||||
}, [duplicate, page.id]);
|
||||
|
||||
|
||||
+6
-9
@@ -1,7 +1,7 @@
|
||||
import { Loading } from '@affine/component';
|
||||
import { Divider } from '@affine/component/ui/divider';
|
||||
import { MenuItem } from '@affine/component/ui/menu';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { AuthService } from '@affine/core/modules/cloud';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { Logo1Icon } from '@blocksuite/icons/rc';
|
||||
@@ -25,9 +25,7 @@ export const SignInItem = () => {
|
||||
const t = useI18n();
|
||||
|
||||
const onClickSignIn = useCallback(() => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'SignIn',
|
||||
});
|
||||
track.$.navigationPanel.workspaceList.signIn();
|
||||
setOpen(state => ({
|
||||
...state,
|
||||
openModal: true,
|
||||
@@ -92,9 +90,7 @@ const UserWithWorkspaceListInner = ({
|
||||
if (!isAuthenticated && !runtimeConfig.allowLocalWorkspace) {
|
||||
return openSignInModal();
|
||||
}
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'NewWorkspace',
|
||||
});
|
||||
track.$.navigationPanel.workspaceList.createWorkspace();
|
||||
setOpenCreateWorkspaceModal('new');
|
||||
onEventEnd?.();
|
||||
}, [
|
||||
@@ -104,9 +100,10 @@ const UserWithWorkspaceListInner = ({
|
||||
setOpenCreateWorkspaceModal,
|
||||
]);
|
||||
|
||||
track.$.navigationPanel.workspaceList.createWorkspace();
|
||||
const onAddWorkspace = useCallback(() => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'AddWorkspace',
|
||||
track.$.navigationPanel.workspaceList.createWorkspace({
|
||||
control: 'import',
|
||||
});
|
||||
setOpenCreateWorkspaceModal('add');
|
||||
onEventEnd?.();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { ImportIcon } from '@blocksuite/icons/rc';
|
||||
|
||||
@@ -13,22 +13,11 @@ const ImportPage = ({ docCollection }: { docCollection: DocCollection }) => {
|
||||
|
||||
const onImportFile = useAsyncCallback(async () => {
|
||||
const options = await importFile();
|
||||
if (options.isWorkspaceFile) {
|
||||
mixpanel.track('WorkspaceCreated', {
|
||||
segment: 'navigation panel',
|
||||
module: 'doc list header',
|
||||
control: 'import button',
|
||||
type: 'imported workspace',
|
||||
});
|
||||
} else {
|
||||
mixpanel.track('DocCreated', {
|
||||
segment: 'navigation panel',
|
||||
module: 'doc list header',
|
||||
control: 'import button',
|
||||
type: 'imported doc',
|
||||
// category
|
||||
});
|
||||
}
|
||||
track.$.navigationPanel.workspaceList[
|
||||
options.isWorkspaceFile ? 'createWorkspace' : 'createDoc'
|
||||
]({
|
||||
control: 'import',
|
||||
});
|
||||
}, [importFile]);
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { openSettingModalAtom } from '@affine/core/atoms';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import {
|
||||
ExplorerCollections,
|
||||
ExplorerFavorites,
|
||||
@@ -91,21 +91,14 @@ export const RootAppSidebar = (): ReactElement => {
|
||||
async (e?: MouseEvent) => {
|
||||
const page = pageHelper.createPage('page', false);
|
||||
page.load();
|
||||
mixpanel.track('DocCreated', {
|
||||
segment: 'navigation panel',
|
||||
module: 'bottom button',
|
||||
control: 'new doc button',
|
||||
category: 'page',
|
||||
type: 'doc',
|
||||
});
|
||||
track.$.navigationPanel.$.createDoc();
|
||||
|
||||
workbench.openDoc(page.id, {
|
||||
at: e?.ctrlKey || e?.metaKey ? 'new-tab' : 'active',
|
||||
});
|
||||
},
|
||||
[pageHelper, workbench]
|
||||
);
|
||||
|
||||
// Listen to the "New Page" action from the menu
|
||||
useEffect(() => {
|
||||
if (environment.isDesktop) {
|
||||
return events?.applicationMenu.onNewPageAction(() => onClickNewPage());
|
||||
@@ -120,12 +113,7 @@ export const RootAppSidebar = (): ReactElement => {
|
||||
activeTab: 'appearance',
|
||||
open: true,
|
||||
});
|
||||
mixpanel.track('SettingsViewed', {
|
||||
// page:
|
||||
segment: 'navigation panel',
|
||||
module: 'general list',
|
||||
control: 'settings button',
|
||||
});
|
||||
track.$.navigationPanel.$.openSettings();
|
||||
}, [setOpenSettingModalAtom]);
|
||||
|
||||
const sidebarOpen = useAtomValue(appSidebarOpenAtom);
|
||||
@@ -153,7 +141,7 @@ export const RootAppSidebar = (): ReactElement => {
|
||||
<QuickSearchInput
|
||||
className={quickSearch}
|
||||
data-testid="slider-bar-quick-search-button"
|
||||
data-event-props="$.navigationPanel.generalFunction.quickSearch"
|
||||
data-event-props="$.navigationPanel.$.quickSearch"
|
||||
onClick={onOpenQuickSearchModal}
|
||||
/>
|
||||
<AddPageButton onClick={onClickNewPage} />
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
openSettingModalAtom,
|
||||
openSignOutModalAtom,
|
||||
} from '@affine/core/atoms';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { AccountIcon, SignOutIcon } from '@blocksuite/icons/rc';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
@@ -83,12 +83,7 @@ const AccountMenu = () => {
|
||||
const setOpenSignOutModalAtom = useSetAtom(openSignOutModalAtom);
|
||||
|
||||
const onOpenAccountSetting = useCallback(() => {
|
||||
mixpanel.track('AccountSettingsViewed', {
|
||||
// page:
|
||||
segment: 'navigation panel',
|
||||
module: 'profile and badge',
|
||||
control: 'profile and email',
|
||||
});
|
||||
track.$.navigationPanel.profileAndBadge.openSettings({ to: 'account' });
|
||||
setSettingModalAtom(prev => ({
|
||||
...prev,
|
||||
open: true,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Menu } from '@affine/component';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { useService, WorkspacesService } from '@toeverything/infra';
|
||||
import { useAtom } from 'jotai';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
@@ -16,9 +16,7 @@ export const WorkspaceSelector = () => {
|
||||
setOpenUserWorkspaceList(false);
|
||||
}, [setOpenUserWorkspaceList]);
|
||||
const openUserWorkspaceList = useCallback(() => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'OpenWorkspaceList',
|
||||
});
|
||||
track.$.navigationPanel.workspaceList.open();
|
||||
setOpenUserWorkspaceList(true);
|
||||
}, [setOpenUserWorkspaceList]);
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Button } from '@affine/component/ui/button';
|
||||
import { AffineShapeIcon } from '@affine/core/components/page-list'; // TODO(@eyhn): import from page-list temporarily, need to defined common svg icon/images management.
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { useNavigateHelper } from '@affine/core/hooks/use-navigate-helper';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { WorkspaceSubPath } from '@affine/core/shared';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { useLiveData, useService, WorkspaceService } from '@toeverything/infra';
|
||||
@@ -26,9 +26,7 @@ export const WorkspaceUpgrade = function WorkspaceUpgrade() {
|
||||
return;
|
||||
}
|
||||
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'UpgradeWorkspace',
|
||||
});
|
||||
track.workspace.$.$.upgradeWorkspace();
|
||||
|
||||
try {
|
||||
const newWorkspace = await currentWorkspace.upgrade.upgrade();
|
||||
|
||||
Reference in New Issue
Block a user