mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-21 16:26:58 +08:00
feat(core): improve mixpanel (#7652)
move @affine/core/utils/mixpanel -> @affine/core/mixpanel now you can debug mixpanel on browser devtool 
This commit is contained in:
@@ -6,7 +6,7 @@ import type { createStore } from 'jotai';
|
|||||||
|
|
||||||
import { openSettingModalAtom, openWorkspaceListModalAtom } from '../atoms';
|
import { openSettingModalAtom, openWorkspaceListModalAtom } from '../atoms';
|
||||||
import type { useNavigateHelper } from '../hooks/use-navigate-helper';
|
import type { useNavigateHelper } from '../hooks/use-navigate-helper';
|
||||||
import { mixpanel } from '../utils/mixpanel';
|
import { mixpanel } from '../mixpanel';
|
||||||
import { registerAffineCommand } from './registry';
|
import { registerAffineCommand } from './registry';
|
||||||
|
|
||||||
export function registerAffineNavigationCommands({
|
export function registerAffineNavigationCommands({
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Button, FlexWrapper, notify } from '@affine/component';
|
import { Button, FlexWrapper, notify } from '@affine/component';
|
||||||
import { openSettingModalAtom } from '@affine/core/atoms';
|
import { openSettingModalAtom } from '@affine/core/atoms';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { SubscriptionService } from '@affine/core/modules/cloud';
|
import { SubscriptionService } from '@affine/core/modules/cloud';
|
||||||
import { mixpanel } from '@affine/core/utils';
|
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { AiIcon } from '@blocksuite/icons/rc';
|
import { AiIcon } from '@blocksuite/icons/rc';
|
||||||
import {
|
import {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { Button, IconButton, Modal } from '@affine/component';
|
import { Button, IconButton, Modal } from '@affine/component';
|
||||||
import { openSettingModalAtom } from '@affine/core/atoms';
|
import { openSettingModalAtom } from '@affine/core/atoms';
|
||||||
import { useBlurRoot } from '@affine/core/hooks/use-blur-root';
|
import { useBlurRoot } from '@affine/core/hooks/use-blur-root';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { AuthService, SubscriptionService } from '@affine/core/modules/cloud';
|
import { AuthService, SubscriptionService } from '@affine/core/modules/cloud';
|
||||||
import { mixpanel } from '@affine/core/utils';
|
|
||||||
import { Trans, useI18n } from '@affine/i18n';
|
import { Trans, useI18n } from '@affine/i18n';
|
||||||
import { ArrowLeftSmallIcon } from '@blocksuite/icons/rc';
|
import { ArrowLeftSmallIcon } from '@blocksuite/icons/rc';
|
||||||
import { useLiveData, useServices } from '@toeverything/infra';
|
import { useLiveData, useServices } from '@toeverything/infra';
|
||||||
@@ -117,7 +117,7 @@ export const AIOnboardingGeneral = () => {
|
|||||||
scrollAnchor: 'aiPricingPlan',
|
scrollAnchor: 'aiPricingPlan',
|
||||||
});
|
});
|
||||||
mixpanel.track('PlansViewed', {
|
mixpanel.track('PlansViewed', {
|
||||||
page: 'whiteboard-editor',
|
page: 'whiteboard editor',
|
||||||
segment: 'ai onboarding',
|
segment: 'ai onboarding',
|
||||||
module: 'general',
|
module: 'general',
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { notify, Skeleton } from '@affine/component';
|
import { notify, Skeleton } from '@affine/component';
|
||||||
import { Button } from '@affine/component/ui/button';
|
import { Button } from '@affine/component/ui/button';
|
||||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { OAuthProviderType } from '@affine/graphql';
|
import { OAuthProviderType } from '@affine/graphql';
|
||||||
import { GithubIcon, GoogleDuotoneIcon } from '@blocksuite/icons/rc';
|
import { GithubIcon, GoogleDuotoneIcon } from '@blocksuite/icons/rc';
|
||||||
import { useLiveData, useService } from '@toeverything/infra';
|
import { useLiveData, useService } from '@toeverything/infra';
|
||||||
@@ -8,7 +9,6 @@ import type { ReactElement } from 'react';
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
|
||||||
import { AuthService, ServerConfigService } from '../../../modules/cloud';
|
import { AuthService, ServerConfigService } from '../../../modules/cloud';
|
||||||
import { mixpanel } from '../../../utils';
|
|
||||||
|
|
||||||
const OAuthProviderMap: Record<
|
const OAuthProviderMap: Record<
|
||||||
OAuthProviderType,
|
OAuthProviderType,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { AuthInput, ModalHeader } from '@affine/component/auth-components';
|
|||||||
import { Button } from '@affine/component/ui/button';
|
import { Button } from '@affine/component/ui/button';
|
||||||
import { authAtom } from '@affine/core/atoms';
|
import { authAtom } from '@affine/core/atoms';
|
||||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { Trans, useI18n } from '@affine/i18n';
|
import { Trans, useI18n } from '@affine/i18n';
|
||||||
import { ArrowDownBigIcon } from '@blocksuite/icons/rc';
|
import { ArrowDownBigIcon } from '@blocksuite/icons/rc';
|
||||||
import { useLiveData, useService } from '@toeverything/infra';
|
import { useLiveData, useService } from '@toeverything/infra';
|
||||||
@@ -12,7 +13,6 @@ import { useCallback, useEffect, useState } from 'react';
|
|||||||
import { useSearchParams } from 'react-router-dom';
|
import { useSearchParams } from 'react-router-dom';
|
||||||
|
|
||||||
import { AuthService } from '../../../modules/cloud';
|
import { AuthService } from '../../../modules/cloud';
|
||||||
import { mixpanel } from '../../../utils';
|
|
||||||
import { emailRegex } from '../../../utils/email-regex';
|
import { emailRegex } from '../../../utils/email-regex';
|
||||||
import type { AuthPanelProps } from './index';
|
import type { AuthPanelProps } from './index';
|
||||||
import { OAuth } from './oauth';
|
import { OAuth } from './oauth';
|
||||||
@@ -74,7 +74,7 @@ export const SignIn: FC<AuthPanelProps> = ({
|
|||||||
if (hasPassword) {
|
if (hasPassword) {
|
||||||
setAuthState('signInWithPassword');
|
setAuthState('signInWithPassword');
|
||||||
} else {
|
} else {
|
||||||
mixpanel.track_forms('SignIn', 'Email', {
|
mixpanel.track('SignIn', {
|
||||||
email,
|
email,
|
||||||
});
|
});
|
||||||
await authService.sendEmailMagicLink(
|
await authService.sendEmailMagicLink(
|
||||||
@@ -92,7 +92,7 @@ export const SignIn: FC<AuthPanelProps> = ({
|
|||||||
challenge,
|
challenge,
|
||||||
searchParams.get('redirect_uri')
|
searchParams.get('redirect_uri')
|
||||||
);
|
);
|
||||||
mixpanel.track_forms('SignUp', 'Email', {
|
mixpanel.track('SignUp', {
|
||||||
email,
|
email,
|
||||||
});
|
});
|
||||||
setAuthState('afterSignUpSendEmail');
|
setAuthState('afterSignUpSendEmail');
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Tooltip } from '@affine/component/ui/tooltip';
|
import { Tooltip } from '@affine/component/ui/tooltip';
|
||||||
import { mixpanel } from '@affine/core/utils';
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { SubscriptionPlan } from '@affine/graphql';
|
import { SubscriptionPlan } from '@affine/graphql';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { useLiveData, useServices } from '@toeverything/infra';
|
import { useLiveData, useServices } from '@toeverything/infra';
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import type { ConfirmModalProps } from '@affine/component/ui/modal';
|
|||||||
import { ConfirmModal, Modal } from '@affine/component/ui/modal';
|
import { ConfirmModal, Modal } from '@affine/component/ui/modal';
|
||||||
import { authAtom } from '@affine/core/atoms';
|
import { authAtom } from '@affine/core/atoms';
|
||||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { DebugLogger } from '@affine/debug';
|
import { DebugLogger } from '@affine/debug';
|
||||||
import { apis } from '@affine/electron-api';
|
import { apis } from '@affine/electron-api';
|
||||||
import { WorkspaceFlavour } from '@affine/env/workspace';
|
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||||
@@ -20,7 +21,6 @@ import { useCallback, useLayoutEffect, useState } from 'react';
|
|||||||
import { buildShowcaseWorkspace } from '../../../bootstrap/first-app-data';
|
import { buildShowcaseWorkspace } from '../../../bootstrap/first-app-data';
|
||||||
import { AuthService } from '../../../modules/cloud';
|
import { AuthService } from '../../../modules/cloud';
|
||||||
import { _addLocalWorkspace } from '../../../modules/workspace-engine';
|
import { _addLocalWorkspace } from '../../../modules/workspace-engine';
|
||||||
import { mixpanel } from '../../../utils';
|
|
||||||
import { CloudSvg } from '../share-page-modal/cloud-svg';
|
import { CloudSvg } from '../share-page-modal/cloud-svg';
|
||||||
import * as styles from './index.css';
|
import * as styles from './index.css';
|
||||||
|
|
||||||
@@ -221,7 +221,7 @@ export const CreateWorkspaceModal = ({
|
|||||||
|
|
||||||
const onConfirmName = useAsyncCallback(
|
const onConfirmName = useAsyncCallback(
|
||||||
async (name: string, workspaceFlavour: WorkspaceFlavour) => {
|
async (name: string, workspaceFlavour: WorkspaceFlavour) => {
|
||||||
mixpanel.track_forms('CreateWorkspaceModel', 'CreateWorkspace', {
|
mixpanel.track('CreateWorkspace', {
|
||||||
workspaceFlavour,
|
workspaceFlavour,
|
||||||
});
|
});
|
||||||
if (loading) return;
|
if (loading) return;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Button, IconButton } from '@affine/component/ui/button';
|
|||||||
import { Modal, useConfirmModal } from '@affine/component/ui/modal';
|
import { Modal, useConfirmModal } from '@affine/component/ui/modal';
|
||||||
import { openSettingModalAtom } from '@affine/core/atoms';
|
import { openSettingModalAtom } from '@affine/core/atoms';
|
||||||
import { useDocCollectionPageTitle } from '@affine/core/hooks/use-block-suite-workspace-page-title';
|
import { useDocCollectionPageTitle } from '@affine/core/hooks/use-block-suite-workspace-page-title';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { WorkspacePermissionService } from '@affine/core/modules/permissions';
|
import { WorkspacePermissionService } from '@affine/core/modules/permissions';
|
||||||
import { WorkspaceQuotaService } from '@affine/core/modules/quota';
|
import { WorkspaceQuotaService } from '@affine/core/modules/quota';
|
||||||
import { i18nTime, Trans, useI18n } from '@affine/i18n';
|
import { i18nTime, Trans, useI18n } from '@affine/i18n';
|
||||||
@@ -32,7 +33,6 @@ import {
|
|||||||
import { encodeStateAsUpdate } from 'yjs';
|
import { encodeStateAsUpdate } from 'yjs';
|
||||||
|
|
||||||
import { pageHistoryModalAtom } from '../../../atoms/page-history';
|
import { pageHistoryModalAtom } from '../../../atoms/page-history';
|
||||||
import { mixpanel } from '../../../utils';
|
|
||||||
import { BlockSuiteEditor } from '../../blocksuite/block-suite-editor';
|
import { BlockSuiteEditor } from '../../blocksuite/block-suite-editor';
|
||||||
import { StyledEditorModeSwitch } from '../../blocksuite/block-suite-mode-switch/style';
|
import { StyledEditorModeSwitch } from '../../blocksuite/block-suite-mode-switch/style';
|
||||||
import {
|
import {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { ConfirmModal } from '@affine/component/ui/modal';
|
import { ConfirmModal } from '@affine/component/ui/modal';
|
||||||
import { openQuotaModalAtom, openSettingModalAtom } from '@affine/core/atoms';
|
import { openQuotaModalAtom, openSettingModalAtom } from '@affine/core/atoms';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { UserQuotaService } from '@affine/core/modules/cloud';
|
import { UserQuotaService } from '@affine/core/modules/cloud';
|
||||||
import { WorkspacePermissionService } from '@affine/core/modules/permissions';
|
import { WorkspacePermissionService } from '@affine/core/modules/permissions';
|
||||||
import { WorkspaceQuotaService } from '@affine/core/modules/quota';
|
import { WorkspaceQuotaService } from '@affine/core/modules/quota';
|
||||||
import { mixpanel } from '@affine/core/utils';
|
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { useLiveData, useService, WorkspaceService } from '@toeverything/infra';
|
import { useLiveData, useService, WorkspaceService } from '@toeverything/infra';
|
||||||
import bytes from 'bytes';
|
import bytes from 'bytes';
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { Button, ErrorMessage, Skeleton } from '@affine/component';
|
import { Button, ErrorMessage, Skeleton } from '@affine/component';
|
||||||
import { SettingRow } from '@affine/component/setting-components';
|
import { SettingRow } from '@affine/component/setting-components';
|
||||||
import { openSettingModalAtom } from '@affine/core/atoms';
|
import { openSettingModalAtom } from '@affine/core/atoms';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import {
|
import {
|
||||||
ServerConfigService,
|
ServerConfigService,
|
||||||
SubscriptionService,
|
SubscriptionService,
|
||||||
UserCopilotQuotaService,
|
UserCopilotQuotaService,
|
||||||
} from '@affine/core/modules/cloud';
|
} from '@affine/core/modules/cloud';
|
||||||
import { mixpanel } from '@affine/core/utils';
|
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { useLiveData, useService } from '@toeverything/infra';
|
import { useLiveData, useService } from '@toeverything/infra';
|
||||||
import { cssVar } from '@toeverything/theme';
|
import { cssVar } from '@toeverything/theme';
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
import { Avatar } from '@affine/component/ui/avatar';
|
import { Avatar } from '@affine/component/ui/avatar';
|
||||||
import { Button } from '@affine/component/ui/button';
|
import { Button } from '@affine/component/ui/button';
|
||||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { ArrowRightSmallIcon, CameraIcon } from '@blocksuite/icons/rc';
|
import { ArrowRightSmallIcon, CameraIcon } from '@blocksuite/icons/rc';
|
||||||
import {
|
import {
|
||||||
@@ -24,7 +25,6 @@ import {
|
|||||||
openSignOutModalAtom,
|
openSignOutModalAtom,
|
||||||
} from '../../../../atoms';
|
} from '../../../../atoms';
|
||||||
import { AuthService, ServerConfigService } from '../../../../modules/cloud';
|
import { AuthService, ServerConfigService } from '../../../../modules/cloud';
|
||||||
import { mixpanel } from '../../../../utils';
|
|
||||||
import { Upload } from '../../../pure/file-upload';
|
import { Upload } from '../../../pure/file-upload';
|
||||||
import { AIUsagePanel } from './ai-usage-panel';
|
import { AIUsagePanel } from './ai-usage-panel';
|
||||||
import { StorageProgress } from './storage-progress';
|
import { StorageProgress } from './storage-progress';
|
||||||
@@ -38,7 +38,7 @@ export const UserAvatar = () => {
|
|||||||
const handleUpdateUserAvatar = useAsyncCallback(
|
const handleUpdateUserAvatar = useAsyncCallback(
|
||||||
async (file: File) => {
|
async (file: File) => {
|
||||||
try {
|
try {
|
||||||
mixpanel.track_forms('UpdateProfile', 'UploadAvatar', {
|
mixpanel.track('UploadAvatar', {
|
||||||
userId: account.id,
|
userId: account.id,
|
||||||
});
|
});
|
||||||
await session.uploadAvatar(file);
|
await session.uploadAvatar(file);
|
||||||
@@ -104,7 +104,7 @@ export const AvatarAndName = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mixpanel.track_forms('UpdateProfile', 'UpdateUsername', {
|
mixpanel.track('UpdateUsername', {
|
||||||
userId: account.id,
|
userId: account.id,
|
||||||
});
|
});
|
||||||
await session.updateLabel(input);
|
await session.updateLabel(input);
|
||||||
|
|||||||
@@ -5,13 +5,14 @@ import {
|
|||||||
SettingWrapper,
|
SettingWrapper,
|
||||||
} from '@affine/component/setting-components';
|
} from '@affine/component/setting-components';
|
||||||
import { useAppUpdater } from '@affine/core/hooks/use-app-updater';
|
import { useAppUpdater } from '@affine/core/hooks/use-app-updater';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { ArrowRightSmallIcon, OpenInNewIcon } from '@blocksuite/icons/rc';
|
import { ArrowRightSmallIcon, OpenInNewIcon } from '@blocksuite/icons/rc';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
import { useAppSettingHelper } from '../../../../../hooks/affine/use-app-setting-helper';
|
import { useAppSettingHelper } from '../../../../../hooks/affine/use-app-setting-helper';
|
||||||
import { appIconMap, appNames } from '../../../../../pages/open-app';
|
import { appIconMap, appNames } from '../../../../../pages/open-app';
|
||||||
import { mixpanel, popupWindow } from '../../../../../utils';
|
import { popupWindow } from '../../../../../utils';
|
||||||
import { relatedLinks } from './config';
|
import { relatedLinks } from './config';
|
||||||
import * as styles from './style.css';
|
import * as styles from './style.css';
|
||||||
import { UpdateCheckSection } from './update-check-section';
|
import { UpdateCheckSection } from './update-check-section';
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { Button, IconButton } from '@affine/component/ui/button';
|
|||||||
import { Loading } from '@affine/component/ui/loading';
|
import { Loading } from '@affine/component/ui/loading';
|
||||||
import { getUpgradeQuestionnaireLink } from '@affine/core/hooks/affine/use-subscription-notify';
|
import { getUpgradeQuestionnaireLink } from '@affine/core/hooks/affine/use-subscription-notify';
|
||||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import type { InvoicesQuery } from '@affine/graphql';
|
import type { InvoicesQuery } from '@affine/graphql';
|
||||||
import {
|
import {
|
||||||
createCustomerPortalMutation,
|
createCustomerPortalMutation,
|
||||||
@@ -32,7 +33,7 @@ import {
|
|||||||
import { useMutation } from '../../../../../hooks/use-mutation';
|
import { useMutation } from '../../../../../hooks/use-mutation';
|
||||||
import { useQuery } from '../../../../../hooks/use-query';
|
import { useQuery } from '../../../../../hooks/use-query';
|
||||||
import { AuthService, SubscriptionService } from '../../../../../modules/cloud';
|
import { AuthService, SubscriptionService } from '../../../../../modules/cloud';
|
||||||
import { mixpanel, mixpanelTrack, popupWindow } from '../../../../../utils';
|
import { popupWindow } from '../../../../../utils';
|
||||||
import { SWRErrorBoundary } from '../../../../pure/swr-error-bundary';
|
import { SWRErrorBoundary } from '../../../../pure/swr-error-bundary';
|
||||||
import { CancelAction, ResumeAction } from '../plans/actions';
|
import { CancelAction, ResumeAction } from '../plans/actions';
|
||||||
import { AICancel, AIResume, AISubscribe } from '../plans/ai/actions';
|
import { AICancel, AIResume, AISubscribe } from '../plans/ai/actions';
|
||||||
@@ -479,7 +480,7 @@ const ResumeSubscription = () => {
|
|||||||
const type = subscription.pro$.value?.plan;
|
const type = subscription.pro$.value?.plan;
|
||||||
const category = subscription.pro$.value?.recurring;
|
const category = subscription.pro$.value?.recurring;
|
||||||
if (type && category) {
|
if (type && category) {
|
||||||
mixpanelTrack('PlanChangeStarted', {
|
mixpanel.track('PlanChangeStarted', {
|
||||||
segment: 'settings panel',
|
segment: 'settings panel',
|
||||||
module: 'pricing plan list',
|
module: 'pricing plan list',
|
||||||
control: 'paying',
|
control: 'paying',
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { getDowngradeQuestionnaireLink } from '@affine/core/hooks/affine/use-subscription-notify';
|
import { getDowngradeQuestionnaireLink } from '@affine/core/hooks/affine/use-subscription-notify';
|
||||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||||
import type { MixpanelEvents } from '@affine/core/mixpanel';
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { mixpanelTrack } from '@affine/core/utils';
|
import type { MixpanelEvents } from '@affine/core/mixpanel/events';
|
||||||
import { SubscriptionPlan } from '@affine/graphql';
|
import { SubscriptionPlan } from '@affine/graphql';
|
||||||
import { useLiveData, useService } from '@toeverything/infra';
|
import { useLiveData, useService } from '@toeverything/infra';
|
||||||
import { nanoid } from 'nanoid';
|
import { nanoid } from 'nanoid';
|
||||||
@@ -36,7 +36,7 @@ export const CancelAction = ({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!open || !proSubscription) return;
|
if (!open || !proSubscription) return;
|
||||||
mixpanelTrack('PlanChangeStarted', {
|
mixpanel.track('PlanChangeStarted', {
|
||||||
segment: 'settings panel',
|
segment: 'settings panel',
|
||||||
module,
|
module,
|
||||||
control: 'cancel',
|
control: 'cancel',
|
||||||
@@ -58,7 +58,7 @@ export const CancelAction = ({
|
|||||||
onOpenChange(false);
|
onOpenChange(false);
|
||||||
const proSubscription = subscription.pro$.value;
|
const proSubscription = subscription.pro$.value;
|
||||||
if (proSubscription) {
|
if (proSubscription) {
|
||||||
mixpanelTrack('PlanChangeSucceeded', {
|
mixpanel.track('PlanChangeSucceeded', {
|
||||||
control: 'cancel',
|
control: 'cancel',
|
||||||
type: proSubscription.plan,
|
type: proSubscription.plan,
|
||||||
category: proSubscription.recurring,
|
category: proSubscription.recurring,
|
||||||
@@ -128,7 +128,7 @@ export const ResumeAction = ({
|
|||||||
onOpenChange(false);
|
onOpenChange(false);
|
||||||
const proSubscription = subscription.pro$.value;
|
const proSubscription = subscription.pro$.value;
|
||||||
if (proSubscription) {
|
if (proSubscription) {
|
||||||
mixpanelTrack('PlanChangeSucceeded', {
|
mixpanel.track('PlanChangeSucceeded', {
|
||||||
control: 'paying',
|
control: 'paying',
|
||||||
type: proSubscription.plan,
|
type: proSubscription.plan,
|
||||||
category: proSubscription.recurring,
|
category: proSubscription.recurring,
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import { Button, type ButtonProps, useConfirmModal } from '@affine/component';
|
|||||||
import { useDowngradeNotify } from '@affine/core/components/affine/subscription-landing/notify';
|
import { useDowngradeNotify } from '@affine/core/components/affine/subscription-landing/notify';
|
||||||
import { getDowngradeQuestionnaireLink } from '@affine/core/hooks/affine/use-subscription-notify';
|
import { getDowngradeQuestionnaireLink } from '@affine/core/hooks/affine/use-subscription-notify';
|
||||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||||
import type { MixpanelEvents } from '@affine/core/mixpanel';
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
|
import type { MixpanelEvents } from '@affine/core/mixpanel/events';
|
||||||
import { AuthService, SubscriptionService } from '@affine/core/modules/cloud';
|
import { AuthService, SubscriptionService } from '@affine/core/modules/cloud';
|
||||||
import { mixpanel, mixpanelTrack } from '@affine/core/utils';
|
|
||||||
import { SubscriptionPlan } from '@affine/graphql';
|
import { SubscriptionPlan } from '@affine/graphql';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { useService } from '@toeverything/infra';
|
import { useService } from '@toeverything/infra';
|
||||||
@@ -27,7 +27,7 @@ export const AICancel = ({ module, ...btnProps }: AICancelProps) => {
|
|||||||
const cancel = useAsyncCallback(async () => {
|
const cancel = useAsyncCallback(async () => {
|
||||||
const aiSubscription = subscription.ai$.value;
|
const aiSubscription = subscription.ai$.value;
|
||||||
if (aiSubscription) {
|
if (aiSubscription) {
|
||||||
mixpanelTrack('PlanChangeStarted', {
|
mixpanel.track('PlanChangeStarted', {
|
||||||
module,
|
module,
|
||||||
segment: 'settings panel',
|
segment: 'settings panel',
|
||||||
control: 'cancel',
|
control: 'cancel',
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import {
|
|||||||
useConfirmModal,
|
useConfirmModal,
|
||||||
} from '@affine/component';
|
} from '@affine/component';
|
||||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||||
import type { MixpanelEvents } from '@affine/core/mixpanel';
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
|
import type { MixpanelEvents } from '@affine/core/mixpanel/events';
|
||||||
import { SubscriptionService } from '@affine/core/modules/cloud';
|
import { SubscriptionService } from '@affine/core/modules/cloud';
|
||||||
import { mixpanelTrack } from '@affine/core/utils';
|
|
||||||
import { SubscriptionPlan } from '@affine/graphql';
|
import { SubscriptionPlan } from '@affine/graphql';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { SingleSelectSelectSolidIcon } from '@blocksuite/icons/rc';
|
import { SingleSelectSelectSolidIcon } from '@blocksuite/icons/rc';
|
||||||
@@ -32,7 +32,7 @@ export const AIResume = ({ module, ...btnProps }: AIResumeProps) => {
|
|||||||
const resume = useAsyncCallback(async () => {
|
const resume = useAsyncCallback(async () => {
|
||||||
const aiSubscription = subscription.ai$.value;
|
const aiSubscription = subscription.ai$.value;
|
||||||
if (aiSubscription) {
|
if (aiSubscription) {
|
||||||
mixpanelTrack('PlanChangeStarted', {
|
mixpanel.track('PlanChangeStarted', {
|
||||||
module,
|
module,
|
||||||
segment: 'settings panel',
|
segment: 'settings panel',
|
||||||
control: 'paying',
|
control: 'paying',
|
||||||
@@ -59,7 +59,7 @@ export const AIResume = ({ module, ...btnProps }: AIResumeProps) => {
|
|||||||
SubscriptionPlan.AI
|
SubscriptionPlan.AI
|
||||||
);
|
);
|
||||||
if (aiSubscription) {
|
if (aiSubscription) {
|
||||||
mixpanelTrack('PlanChangeSucceeded', {
|
mixpanel.track('PlanChangeSucceeded', {
|
||||||
category: aiSubscription.recurring,
|
category: aiSubscription.recurring,
|
||||||
control: 'paying',
|
control: 'paying',
|
||||||
type: aiSubscription.plan,
|
type: aiSubscription.plan,
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { Button, type ButtonProps, Skeleton } from '@affine/component';
|
import { Button, type ButtonProps, Skeleton } from '@affine/component';
|
||||||
import { generateSubscriptionCallbackLink } from '@affine/core/hooks/affine/use-subscription-notify';
|
import { generateSubscriptionCallbackLink } from '@affine/core/hooks/affine/use-subscription-notify';
|
||||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { AuthService, SubscriptionService } from '@affine/core/modules/cloud';
|
import { AuthService, SubscriptionService } from '@affine/core/modules/cloud';
|
||||||
import { mixpanel, popupWindow } from '@affine/core/utils';
|
import { popupWindow } from '@affine/core/utils';
|
||||||
import { SubscriptionPlan, SubscriptionRecurring } from '@affine/graphql';
|
import { SubscriptionPlan, SubscriptionRecurring } from '@affine/graphql';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { useLiveData, useService } from '@toeverything/infra';
|
import { useLiveData, useService } from '@toeverything/infra';
|
||||||
|
|||||||
@@ -2,8 +2,9 @@ import { Button } from '@affine/component/ui/button';
|
|||||||
import { Tooltip } from '@affine/component/ui/tooltip';
|
import { Tooltip } from '@affine/component/ui/tooltip';
|
||||||
import { generateSubscriptionCallbackLink } from '@affine/core/hooks/affine/use-subscription-notify';
|
import { generateSubscriptionCallbackLink } from '@affine/core/hooks/affine/use-subscription-notify';
|
||||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { AuthService, SubscriptionService } from '@affine/core/modules/cloud';
|
import { AuthService, SubscriptionService } from '@affine/core/modules/cloud';
|
||||||
import { mixpanelTrack, popupWindow } from '@affine/core/utils';
|
import { popupWindow } from '@affine/core/utils';
|
||||||
import type { SubscriptionRecurring } from '@affine/graphql';
|
import type { SubscriptionRecurring } from '@affine/graphql';
|
||||||
import { SubscriptionPlan, SubscriptionStatus } from '@affine/graphql';
|
import { SubscriptionPlan, SubscriptionStatus } from '@affine/graphql';
|
||||||
import { Trans, useI18n } from '@affine/i18n';
|
import { Trans, useI18n } from '@affine/i18n';
|
||||||
@@ -16,7 +17,6 @@ import type { HTMLAttributes, PropsWithChildren } from 'react';
|
|||||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import { authAtom } from '../../../../../atoms/index';
|
import { authAtom } from '../../../../../atoms/index';
|
||||||
import { mixpanel } from '../../../../../utils';
|
|
||||||
import { CancelAction, ResumeAction } from './actions';
|
import { CancelAction, ResumeAction } from './actions';
|
||||||
import type { DynamicPrice, FixedPrice } from './cloud-plans';
|
import type { DynamicPrice, FixedPrice } from './cloud-plans';
|
||||||
import { ConfirmLoadingModal } from './modals';
|
import { ConfirmLoadingModal } from './modals';
|
||||||
@@ -337,7 +337,7 @@ const ChangeRecurring = ({
|
|||||||
const subscription = useService(SubscriptionService).subscription;
|
const subscription = useService(SubscriptionService).subscription;
|
||||||
|
|
||||||
const onStartChange = useCallback(() => {
|
const onStartChange = useCallback(() => {
|
||||||
mixpanelTrack('PlanChangeStarted', {
|
mixpanel.track('PlanChangeStarted', {
|
||||||
segment: 'settings panel',
|
segment: 'settings panel',
|
||||||
module: 'pricing plan list',
|
module: 'pricing plan list',
|
||||||
control: 'paying',
|
control: 'paying',
|
||||||
@@ -422,7 +422,7 @@ const ResumeButton = () => {
|
|||||||
setOpen(true);
|
setOpen(true);
|
||||||
const pro = subscription.pro$.value;
|
const pro = subscription.pro$.value;
|
||||||
if (pro) {
|
if (pro) {
|
||||||
mixpanelTrack('PlanChangeStarted', {
|
mixpanel.track('PlanChangeStarted', {
|
||||||
segment: 'settings panel',
|
segment: 'settings panel',
|
||||||
module: 'pricing plan list',
|
module: 'pricing plan list',
|
||||||
control: 'paying',
|
control: 'paying',
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { Avatar } from '@affine/component/ui/avatar';
|
|||||||
import { Tooltip } from '@affine/component/ui/tooltip';
|
import { Tooltip } from '@affine/component/ui/tooltip';
|
||||||
import { WorkspaceAvatar } from '@affine/component/workspace-avatar';
|
import { WorkspaceAvatar } from '@affine/component/workspace-avatar';
|
||||||
import { useWorkspaceInfo } from '@affine/core/hooks/use-workspace-info';
|
import { useWorkspaceInfo } from '@affine/core/hooks/use-workspace-info';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { AuthService } from '@affine/core/modules/cloud';
|
import { AuthService } from '@affine/core/modules/cloud';
|
||||||
import { UserFeatureService } from '@affine/core/modules/cloud/services/user-feature';
|
import { UserFeatureService } from '@affine/core/modules/cloud/services/user-feature';
|
||||||
import { UNTITLED_WORKSPACE_NAME } from '@affine/env/constant';
|
import { UNTITLED_WORKSPACE_NAME } from '@affine/env/constant';
|
||||||
@@ -24,7 +25,6 @@ import { useAtom } from 'jotai/react';
|
|||||||
import { Suspense, useCallback, useEffect, useMemo } from 'react';
|
import { Suspense, useCallback, useEffect, useMemo } from 'react';
|
||||||
|
|
||||||
import { authAtom } from '../../../../atoms';
|
import { authAtom } from '../../../../atoms';
|
||||||
import { mixpanel } from '../../../../utils';
|
|
||||||
import { UserPlanButton } from '../../auth/user-plan-button';
|
import { UserPlanButton } from '../../auth/user-plan-button';
|
||||||
import { useGeneralSettingList } from '../general-setting';
|
import { useGeneralSettingList } from '../general-setting';
|
||||||
import type { ActiveTab, WorkspaceSubTab } from '../types';
|
import type { ActiveTab, WorkspaceSubTab } from '../types';
|
||||||
|
|||||||
@@ -21,9 +21,9 @@ import { useMemberCount } from '@affine/core/hooks/affine/use-member-count';
|
|||||||
import type { Member } from '@affine/core/hooks/affine/use-members';
|
import type { Member } from '@affine/core/hooks/affine/use-members';
|
||||||
import { useMembers } 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 { useRevokeMemberPermission } from '@affine/core/hooks/affine/use-revoke-member-permission';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { WorkspacePermissionService } from '@affine/core/modules/permissions';
|
import { WorkspacePermissionService } from '@affine/core/modules/permissions';
|
||||||
import { WorkspaceQuotaService } from '@affine/core/modules/quota';
|
import { WorkspaceQuotaService } from '@affine/core/modules/quota';
|
||||||
import { mixpanel } from '@affine/core/utils';
|
|
||||||
import { WorkspaceFlavour } from '@affine/env/workspace';
|
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||||
import { Permission } from '@affine/graphql';
|
import { Permission } from '@affine/graphql';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import { Button } from '@affine/component/ui/button';
|
|||||||
import { Menu, MenuItem, MenuTrigger } from '@affine/component/ui/menu';
|
import { Menu, MenuItem, MenuTrigger } from '@affine/component/ui/menu';
|
||||||
import { useSharingUrl } from '@affine/core/hooks/affine/use-share-url';
|
import { useSharingUrl } from '@affine/core/hooks/affine/use-share-url';
|
||||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { ServerConfigService } from '@affine/core/modules/cloud';
|
import { ServerConfigService } from '@affine/core/modules/cloud';
|
||||||
import { ShareService } from '@affine/core/modules/share-doc';
|
import { ShareService } from '@affine/core/modules/share-doc';
|
||||||
import { mixpanel } from '@affine/core/utils';
|
|
||||||
import { WorkspaceFlavour } from '@affine/env/workspace';
|
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||||
import { PublicPageMode } from '@affine/graphql';
|
import { PublicPageMode } from '@affine/graphql';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { CloseIcon, DownloadIcon } from '@blocksuite/icons/rc';
|
import { CloseIcon, DownloadIcon } from '@blocksuite/icons/rc';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
|
|
||||||
import { mixpanel } from '../../../utils';
|
|
||||||
import * as styles from './index.css';
|
import * as styles from './index.css';
|
||||||
|
|
||||||
// Although it is called an input, it is actually a button.
|
// Although it is called an input, it is actually a button.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { notify } from '@affine/component';
|
|||||||
import { authAtom, openSettingModalAtom } from '@affine/core/atoms';
|
import { authAtom, openSettingModalAtom } from '@affine/core/atoms';
|
||||||
import { AIProvider } from '@affine/core/blocksuite/presets/ai';
|
import { AIProvider } from '@affine/core/blocksuite/presets/ai';
|
||||||
import { toggleGeneralAIOnboarding } from '@affine/core/components/affine/ai-onboarding/apis';
|
import { toggleGeneralAIOnboarding } from '@affine/core/components/affine/ai-onboarding/apis';
|
||||||
import { mixpanel } from '@affine/core/utils';
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import {
|
import {
|
||||||
getBaseUrl,
|
getBaseUrl,
|
||||||
type getCopilotHistoriesQuery,
|
type getCopilotHistoriesQuery,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { AIProvider } from '@affine/core/blocksuite/presets/ai';
|
import { AIProvider } from '@affine/core/blocksuite/presets/ai';
|
||||||
import { mixpanel } from '@affine/core/utils';
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import type { EditorHost } from '@blocksuite/block-std';
|
import type { EditorHost } from '@blocksuite/block-std';
|
||||||
import type { BlockModel } from '@blocksuite/store';
|
import type { BlockModel } from '@blocksuite/store';
|
||||||
import { lowerCase, omit } from 'lodash-es';
|
import { lowerCase, omit } from 'lodash-es';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { WorkspacePropertiesAdapter } from '@affine/core/modules/properties';
|
import { WorkspacePropertiesAdapter } from '@affine/core/modules/properties';
|
||||||
import { mixpanel } from '@affine/core/utils';
|
|
||||||
import { I18n, i18nTime } from '@affine/i18n';
|
import { I18n, i18nTime } from '@affine/i18n';
|
||||||
import type { EditorHost } from '@blocksuite/block-std';
|
import type { EditorHost } from '@blocksuite/block-std';
|
||||||
import type { AffineInlineEditor } from '@blocksuite/blocks';
|
import type { AffineInlineEditor } from '@blocksuite/blocks';
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import {
|
|||||||
AIEdgelessRootBlockSpec,
|
AIEdgelessRootBlockSpec,
|
||||||
AIPageRootBlockSpec,
|
AIPageRootBlockSpec,
|
||||||
} from '@affine/core/blocksuite/presets/ai';
|
} from '@affine/core/blocksuite/presets/ai';
|
||||||
import { mixpanel } from '@affine/core/utils';
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import type {
|
import type {
|
||||||
EdgelessRootBlockSpecType,
|
EdgelessRootBlockSpecType,
|
||||||
PageRootBlockSpecType,
|
PageRootBlockSpecType,
|
||||||
@@ -42,7 +42,7 @@ function withAffineRootService(Service: typeof RootService) {
|
|||||||
eventName: T,
|
eventName: T,
|
||||||
props: TelemetryEventMap[T]
|
props: TelemetryEventMap[T]
|
||||||
) => {
|
) => {
|
||||||
mixpanel.track(eventName, props);
|
mixpanel.track(eventName as string, props as Record<string, unknown>);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
toReactNode,
|
toReactNode,
|
||||||
type useConfirmModal,
|
type useConfirmModal,
|
||||||
} from '@affine/component';
|
} from '@affine/component';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { DocsSearchService } from '@affine/core/modules/docs-search';
|
import { DocsSearchService } from '@affine/core/modules/docs-search';
|
||||||
import { resolveLinkToDoc } from '@affine/core/modules/navigation';
|
import { resolveLinkToDoc } from '@affine/core/modules/navigation';
|
||||||
import type { PeekViewService } from '@affine/core/modules/peek-view';
|
import type { PeekViewService } from '@affine/core/modules/peek-view';
|
||||||
@@ -18,7 +19,6 @@ import {
|
|||||||
QuickSearchService,
|
QuickSearchService,
|
||||||
RecentDocsQuickSearchSession,
|
RecentDocsQuickSearchSession,
|
||||||
} from '@affine/core/modules/quicksearch';
|
} from '@affine/core/modules/quicksearch';
|
||||||
import { mixpanel } from '@affine/core/utils';
|
|
||||||
import { DebugLogger } from '@affine/debug';
|
import { DebugLogger } from '@affine/debug';
|
||||||
import type { BlockSpec, WidgetComponent } from '@blocksuite/block-std';
|
import type { BlockSpec, WidgetComponent } from '@blocksuite/block-std';
|
||||||
import {
|
import {
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ import { useEnableCloud } from '@affine/core/hooks/affine/use-enable-cloud';
|
|||||||
import { useExportPage } from '@affine/core/hooks/affine/use-export-page';
|
import { useExportPage } from '@affine/core/hooks/affine/use-export-page';
|
||||||
import { useTrashModalHelper } from '@affine/core/hooks/affine/use-trash-modal-helper';
|
import { useTrashModalHelper } from '@affine/core/hooks/affine/use-trash-modal-helper';
|
||||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { useDetailPageHeaderResponsive } from '@affine/core/pages/workspace/detail-page/use-header-responsive';
|
import { useDetailPageHeaderResponsive } from '@affine/core/pages/workspace/detail-page/use-header-responsive';
|
||||||
import { mixpanel } from '@affine/core/utils';
|
|
||||||
import { WorkspaceFlavour } from '@affine/env/workspace';
|
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import {
|
import {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Tooltip } from '@affine/component/ui/tooltip';
|
import { Tooltip } from '@affine/component/ui/tooltip';
|
||||||
import { useBlockSuiteDocMeta } from '@affine/core/hooks/use-block-suite-page-meta';
|
import { useBlockSuiteDocMeta } from '@affine/core/hooks/use-block-suite-page-meta';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import {
|
import {
|
||||||
type DocMode,
|
type DocMode,
|
||||||
@@ -11,7 +12,7 @@ import type { CSSProperties } from 'react';
|
|||||||
import { useCallback, useEffect } from 'react';
|
import { useCallback, useEffect } from 'react';
|
||||||
|
|
||||||
import type { DocCollection } from '../../../shared';
|
import type { DocCollection } from '../../../shared';
|
||||||
import { mixpanel, toast } from '../../../utils';
|
import { toast } from '../../../utils';
|
||||||
import { StyledEditorModeSwitch, StyledKeyboardItem } from './style';
|
import { StyledEditorModeSwitch, StyledKeyboardItem } from './style';
|
||||||
import { EdgelessSwitchItem, PageSwitchItem } from './switch-items';
|
import { EdgelessSwitchItem, PageSwitchItem } from './switch-items';
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { DropdownButton, Menu } from '@affine/component';
|
import { DropdownButton, Menu } from '@affine/component';
|
||||||
import { BlockCard } from '@affine/component/card/block-card';
|
import { BlockCard } from '@affine/component/card/block-card';
|
||||||
import { mixpanel } from '@affine/core/utils';
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { EdgelessIcon, ImportIcon, PageIcon } from '@blocksuite/icons/rc';
|
import { EdgelessIcon, ImportIcon, PageIcon } from '@blocksuite/icons/rc';
|
||||||
import type { PropsWithChildren } from 'react';
|
import type { PropsWithChildren } from 'react';
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ import {
|
|||||||
} from '@affine/component';
|
} from '@affine/component';
|
||||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||||
import { useNavigateHelper } from '@affine/core/hooks/use-navigate-helper';
|
import { useNavigateHelper } from '@affine/core/hooks/use-navigate-helper';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import type { Tag } from '@affine/core/modules/tag';
|
import type { Tag } from '@affine/core/modules/tag';
|
||||||
import { TagService } from '@affine/core/modules/tag';
|
import { TagService } from '@affine/core/modules/tag';
|
||||||
import { mixpanel } from '@affine/core/utils';
|
|
||||||
import type { Collection } from '@affine/env/filter';
|
import type { Collection } from '@affine/env/filter';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import {
|
import {
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ import {
|
|||||||
import { useAppSettingHelper } from '@affine/core/hooks/affine/use-app-setting-helper';
|
import { useAppSettingHelper } from '@affine/core/hooks/affine/use-app-setting-helper';
|
||||||
import { useBlockSuiteMetaHelper } from '@affine/core/hooks/affine/use-block-suite-meta-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 { useTrashModalHelper } from '@affine/core/hooks/affine/use-trash-modal-helper';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { FavoriteService } from '@affine/core/modules/favorite';
|
import { FavoriteService } from '@affine/core/modules/favorite';
|
||||||
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
||||||
import { WorkbenchService } from '@affine/core/modules/workbench';
|
import { WorkbenchService } from '@affine/core/modules/workbench';
|
||||||
import { mixpanel } from '@affine/core/utils';
|
|
||||||
import type { Collection, DeleteCollectionInfo } from '@affine/env/filter';
|
import type { Collection, DeleteCollectionInfo } from '@affine/env/filter';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import {
|
import {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Loading } from '@affine/component';
|
import { Loading } from '@affine/component';
|
||||||
import { Divider } from '@affine/component/ui/divider';
|
import { Divider } from '@affine/component/ui/divider';
|
||||||
import { MenuItem } from '@affine/component/ui/menu';
|
import { MenuItem } from '@affine/component/ui/menu';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { AuthService } from '@affine/core/modules/cloud';
|
import { AuthService } from '@affine/core/modules/cloud';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { Logo1Icon } from '@blocksuite/icons/rc';
|
import { Logo1Icon } from '@blocksuite/icons/rc';
|
||||||
@@ -13,7 +14,6 @@ import { useSetAtom } from 'jotai';
|
|||||||
import { Suspense, useCallback } from 'react';
|
import { Suspense, useCallback } from 'react';
|
||||||
|
|
||||||
import { authAtom, openCreateWorkspaceModalAtom } from '../../../../atoms';
|
import { authAtom, openCreateWorkspaceModalAtom } from '../../../../atoms';
|
||||||
import { mixpanel } from '../../../../utils';
|
|
||||||
import { AddWorkspace } from './add-workspace';
|
import { AddWorkspace } from './add-workspace';
|
||||||
import * as styles from './index.css';
|
import * as styles from './index.css';
|
||||||
import { UserAccountItem } from './user-account';
|
import { UserAccountItem } from './user-account';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { TelemetryWorkspaceContextService } from '@affine/core/modules/telemetry/services/telemetry';
|
import { TelemetryWorkspaceContextService } from '@affine/core/modules/telemetry/services/telemetry';
|
||||||
import { mixpanel } from '@affine/core/utils';
|
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { ImportIcon } from '@blocksuite/icons/rc';
|
import { ImportIcon } from '@blocksuite/icons/rc';
|
||||||
import { useService } from '@toeverything/infra';
|
import { useService } from '@toeverything/infra';
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { openSettingModalAtom } from '@affine/core/atoms';
|
import { openSettingModalAtom } from '@affine/core/atoms';
|
||||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||||
import { useNavigateHelper } from '@affine/core/hooks/use-navigate-helper';
|
import { useNavigateHelper } from '@affine/core/hooks/use-navigate-helper';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import {
|
import {
|
||||||
ExplorerCollections,
|
ExplorerCollections,
|
||||||
ExplorerFavorites,
|
ExplorerFavorites,
|
||||||
@@ -12,7 +13,6 @@ import { ExplorerTags } from '@affine/core/modules/explorer/views/sections/tags'
|
|||||||
import { CMDKQuickSearchService } from '@affine/core/modules/quicksearch/services/cmdk';
|
import { CMDKQuickSearchService } from '@affine/core/modules/quicksearch/services/cmdk';
|
||||||
import { TelemetryWorkspaceContextService } from '@affine/core/modules/telemetry/services/telemetry';
|
import { TelemetryWorkspaceContextService } from '@affine/core/modules/telemetry/services/telemetry';
|
||||||
import { pathGenerator } from '@affine/core/shared';
|
import { pathGenerator } from '@affine/core/shared';
|
||||||
import { mixpanel } from '@affine/core/utils';
|
|
||||||
import { apis, events } from '@affine/electron-api';
|
import { apis, events } from '@affine/electron-api';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { FolderIcon, SettingsIcon } from '@blocksuite/icons/rc';
|
import { FolderIcon, SettingsIcon } from '@blocksuite/icons/rc';
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import {
|
|||||||
openSettingModalAtom,
|
openSettingModalAtom,
|
||||||
openSignOutModalAtom,
|
openSignOutModalAtom,
|
||||||
} from '@affine/core/atoms';
|
} from '@affine/core/atoms';
|
||||||
import { mixpanel } from '@affine/core/utils';
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { AccountIcon, SignOutIcon } from '@blocksuite/icons/rc';
|
import { AccountIcon, SignOutIcon } from '@blocksuite/icons/rc';
|
||||||
import { useLiveData, useService } from '@toeverything/infra';
|
import { useLiveData, useService } from '@toeverything/infra';
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { Menu } from '@affine/component';
|
import { Menu } from '@affine/component';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { useService, WorkspacesService } from '@toeverything/infra';
|
import { useService, WorkspacesService } from '@toeverything/infra';
|
||||||
import { useAtom } from 'jotai';
|
import { useAtom } from 'jotai';
|
||||||
import { useCallback, useEffect } from 'react';
|
import { useCallback, useEffect } from 'react';
|
||||||
|
|
||||||
import { openWorkspaceListModalAtom } from '../../atoms';
|
import { openWorkspaceListModalAtom } from '../../atoms';
|
||||||
import { mixpanel } from '../../utils';
|
|
||||||
import { UserWithWorkspaceList } from '../pure/workspace-slider-bar/user-with-workspace-list';
|
import { UserWithWorkspaceList } from '../pure/workspace-slider-bar/user-with-workspace-list';
|
||||||
import { WorkspaceCard } from '../pure/workspace-slider-bar/workspace-card';
|
import { WorkspaceCard } from '../pure/workspace-slider-bar/workspace-card';
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ 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 { 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 { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||||
import { useNavigateHelper } from '@affine/core/hooks/use-navigate-helper';
|
import { useNavigateHelper } from '@affine/core/hooks/use-navigate-helper';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { WorkspaceSubPath } from '@affine/core/shared';
|
import { WorkspaceSubPath } from '@affine/core/shared';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { useLiveData, useService, WorkspaceService } from '@toeverything/infra';
|
import { useLiveData, useService, WorkspaceService } from '@toeverything/infra';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
|
||||||
import { mixpanel } from '../../utils';
|
|
||||||
import * as styles from './upgrade.css';
|
import * as styles from './upgrade.css';
|
||||||
import { ArrowCircleIcon, HeartBreakIcon } from './upgrade-icon';
|
import { ArrowCircleIcon, HeartBreakIcon } from './upgrade-icon';
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {
|
|||||||
pushGlobalLoadingEventAtom,
|
pushGlobalLoadingEventAtom,
|
||||||
resolveGlobalLoadingEventAtom,
|
resolveGlobalLoadingEventAtom,
|
||||||
} from '@affine/component/global-loading';
|
} from '@affine/component/global-loading';
|
||||||
import { mixpanel } from '@affine/core/utils';
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { apis } from '@affine/electron-api';
|
import { apis } from '@affine/electron-api';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import type { PageRootService, RootBlockModel } from '@blocksuite/blocks';
|
import type { PageRootService, RootBlockModel } from '@blocksuite/blocks';
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import {
|
|||||||
PreconditionStrategy,
|
PreconditionStrategy,
|
||||||
registerAffineCommand,
|
registerAffineCommand,
|
||||||
} from '@affine/core/commands';
|
} from '@affine/core/commands';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
||||||
import { TelemetryWorkspaceContextService } from '@affine/core/modules/telemetry/services/telemetry';
|
import { TelemetryWorkspaceContextService } from '@affine/core/modules/telemetry/services/telemetry';
|
||||||
import { mixpanel } from '@affine/core/utils';
|
|
||||||
import { WorkspaceFlavour } from '@affine/env/workspace';
|
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { EdgelessIcon, HistoryIcon, PageIcon } from '@blocksuite/icons/rc';
|
import { EdgelessIcon, HistoryIcon, PageIcon } from '@blocksuite/icons/rc';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { notify } from '@affine/component';
|
import { notify } from '@affine/component';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { getAffineCloudBaseUrl } from '@affine/core/modules/cloud/services/fetch';
|
import { getAffineCloudBaseUrl } from '@affine/core/modules/cloud/services/fetch';
|
||||||
import { mixpanel } from '@affine/core/utils';
|
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import type { Disposable } from '@blocksuite/global/utils';
|
import type { Disposable } from '@blocksuite/global/utils';
|
||||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useUpgradeNotify } from '@affine/core/components/affine/subscription-landing/notify';
|
import { useUpgradeNotify } from '@affine/core/components/affine/subscription-landing/notify';
|
||||||
import { mixpanelTrack } from '@affine/core/utils';
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { SubscriptionPlan, SubscriptionRecurring } from '@affine/graphql';
|
import { SubscriptionPlan, SubscriptionRecurring } from '@affine/graphql';
|
||||||
import { nanoid } from 'nanoid';
|
import { nanoid } from 'nanoid';
|
||||||
import { useCallback, useEffect } from 'react';
|
import { useCallback, useEffect } from 'react';
|
||||||
@@ -130,7 +130,7 @@ export const useSubscriptionNotifyReader = () => {
|
|||||||
localStorage.removeItem(localStorageKey);
|
localStorage.removeItem(localStorageKey);
|
||||||
|
|
||||||
// mixpanel
|
// mixpanel
|
||||||
mixpanelTrack('PlanChangeSucceeded', {
|
mixpanel.track('PlanChangeSucceeded', {
|
||||||
category: recurring,
|
category: recurring,
|
||||||
type: plan,
|
type: plan,
|
||||||
control: 'new subscription',
|
control: 'new subscription',
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ import { atomWithObservable, atomWithStorage } from 'jotai/utils';
|
|||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
import { mixpanel, popupWindow } from '../utils';
|
import { mixpanel } from '../mixpanel';
|
||||||
|
import { popupWindow } from '../utils';
|
||||||
import { useAsyncCallback } from './affine-async-hooks';
|
import { useAsyncCallback } from './affine-async-hooks';
|
||||||
|
|
||||||
function rpcToObservable<
|
function rpcToObservable<
|
||||||
|
|||||||
23
packages/frontend/core/src/mixpanel/events/index.ts
Normal file
23
packages/frontend/core/src/mixpanel/events/index.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import type { PlanChangeStartedEvent } from './plan-change-started';
|
||||||
|
import type { PlanChangeSucceededEvent } from './plan-change-succeed';
|
||||||
|
|
||||||
|
export interface MixpanelEvents {
|
||||||
|
PlanChangeStarted: PlanChangeStartedEvent;
|
||||||
|
PlanChangeSucceeded: PlanChangeSucceededEvent;
|
||||||
|
OAuth: {
|
||||||
|
provider: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GeneralMixpanelEvent {
|
||||||
|
// location
|
||||||
|
page?: string | null;
|
||||||
|
segment?: string | null;
|
||||||
|
module?: string | null;
|
||||||
|
control?: string | null;
|
||||||
|
|
||||||
|
// entity
|
||||||
|
type?: string | null;
|
||||||
|
category?: string | null;
|
||||||
|
id?: string | null;
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import type { SubscriptionPlan, SubscriptionRecurring } from '@affine/graphql';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Before subscription plan changed
|
||||||
|
*/
|
||||||
|
export interface PlanChangeStartedEvent {
|
||||||
|
segment?: 'settings panel';
|
||||||
|
module?: 'pricing plan list' | 'billing subscription list';
|
||||||
|
control?:
|
||||||
|
| 'new subscription' // no subscription before
|
||||||
|
| 'cancel'
|
||||||
|
| 'paying' // resume: subscribed before
|
||||||
|
| 'plan cancel action';
|
||||||
|
type?: SubscriptionPlan;
|
||||||
|
category?: SubscriptionRecurring;
|
||||||
|
}
|
||||||
@@ -5,5 +5,5 @@ import type { PlanChangeStartedEvent } from './plan-change-started';
|
|||||||
*/
|
*/
|
||||||
export type PlanChangeSucceededEvent = Pick<
|
export type PlanChangeSucceededEvent = Pick<
|
||||||
PlanChangeStartedEvent,
|
PlanChangeStartedEvent,
|
||||||
'control' | 'type' | 'category'
|
'control' | 'type' | 'category' | 'segment'
|
||||||
>;
|
>;
|
||||||
@@ -1,7 +1,88 @@
|
|||||||
import type { PlanChangeStartedEvent } from './plan-change-started';
|
import { DebugLogger } from '@affine/debug';
|
||||||
import type { PlanChangeSucceededEvent } from './plan-change-succeed';
|
import type { OverridedMixpanel } from 'mixpanel-browser';
|
||||||
|
import mixpanelBrowser from 'mixpanel-browser';
|
||||||
|
|
||||||
export interface MixpanelEvents {
|
import type { GeneralMixpanelEvent, MixpanelEvents } from './events';
|
||||||
PlanChangeStarted: PlanChangeStartedEvent;
|
|
||||||
PlanChangeSucceeded: PlanChangeSucceededEvent;
|
const logger = new DebugLogger('mixpanel');
|
||||||
|
|
||||||
|
function createMixpanel() {
|
||||||
|
let mixpanel;
|
||||||
|
if (process.env.MIXPANEL_TOKEN) {
|
||||||
|
mixpanelBrowser.init(process.env.MIXPANEL_TOKEN || '', {
|
||||||
|
track_pageview: true,
|
||||||
|
persistence: 'localStorage',
|
||||||
|
api_host: 'https://telemetry.affine.run',
|
||||||
|
});
|
||||||
|
mixpanel = mixpanelBrowser;
|
||||||
|
} else {
|
||||||
|
mixpanel = new Proxy(
|
||||||
|
function () {} as unknown as OverridedMixpanel,
|
||||||
|
createProxyHandler()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapped = {
|
||||||
|
reset() {
|
||||||
|
mixpanel.reset();
|
||||||
|
mixpanel.register({
|
||||||
|
appVersion: runtimeConfig.appVersion,
|
||||||
|
environment: runtimeConfig.appBuildType,
|
||||||
|
editorVersion: runtimeConfig.editorVersion,
|
||||||
|
isSelfHosted: Boolean(runtimeConfig.isSelfHosted),
|
||||||
|
isDesktop: environment.isDesktop,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
track<
|
||||||
|
T extends string,
|
||||||
|
P extends (T extends keyof MixpanelEvents
|
||||||
|
? MixpanelEvents[T]
|
||||||
|
: Record<string, unknown>) &
|
||||||
|
GeneralMixpanelEvent,
|
||||||
|
>(event_name: T, properties?: P) {
|
||||||
|
logger.debug('track', event_name, properties);
|
||||||
|
mixpanel.track(event_name, properties);
|
||||||
|
},
|
||||||
|
opt_out_tracking() {
|
||||||
|
mixpanel.opt_out_tracking();
|
||||||
|
},
|
||||||
|
opt_in_tracking() {
|
||||||
|
mixpanel.opt_in_tracking();
|
||||||
|
},
|
||||||
|
has_opted_in_tracking() {
|
||||||
|
mixpanel.has_opted_in_tracking();
|
||||||
|
},
|
||||||
|
has_opted_out_tracking() {
|
||||||
|
mixpanel.has_opted_out_tracking();
|
||||||
|
},
|
||||||
|
identify(unique_id?: string) {
|
||||||
|
mixpanel.identify(unique_id);
|
||||||
|
},
|
||||||
|
get people() {
|
||||||
|
return mixpanel.people;
|
||||||
|
},
|
||||||
|
track_pageview(properties?: { location?: string }) {
|
||||||
|
logger.debug('track_pageview', properties);
|
||||||
|
mixpanel.track_pageview(properties);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
wrapped.reset();
|
||||||
|
|
||||||
|
return wrapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const mixpanel = createMixpanel();
|
||||||
|
|
||||||
|
function createProxyHandler() {
|
||||||
|
const handler = {
|
||||||
|
get: () => {
|
||||||
|
return new Proxy(
|
||||||
|
function () {} as unknown as OverridedMixpanel,
|
||||||
|
createProxyHandler()
|
||||||
|
);
|
||||||
|
},
|
||||||
|
apply: () => {},
|
||||||
|
} as ProxyHandler<OverridedMixpanel>;
|
||||||
|
return handler;
|
||||||
}
|
}
|
||||||
|
|||||||
19
packages/frontend/core/src/mixpanel/mixpanel.d.ts
vendored
Normal file
19
packages/frontend/core/src/mixpanel/mixpanel.d.ts
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars, unused-imports/no-unused-imports
|
||||||
|
import * as mixpanel from 'mixpanel-browser';
|
||||||
|
|
||||||
|
import type { GeneralMixpanelEvent, MixpanelEvents } from './events';
|
||||||
|
|
||||||
|
declare module 'mixpanel-browser' {
|
||||||
|
export interface OverridedMixpanel {
|
||||||
|
track<
|
||||||
|
T extends string,
|
||||||
|
P extends (T extends keyof MixpanelEvents
|
||||||
|
? MixpanelEvents[T]
|
||||||
|
: Record<string, unknown>) &
|
||||||
|
GeneralMixpanelEvent,
|
||||||
|
>(
|
||||||
|
event_name: T,
|
||||||
|
properties?: P
|
||||||
|
): void;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
import type { SubscriptionPlan, SubscriptionRecurring } from '@affine/graphql';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Before subscription plan changed
|
|
||||||
*/
|
|
||||||
export interface PlanChangeStartedEvent {
|
|
||||||
segment: 'settings panel';
|
|
||||||
module: 'pricing plan list' | 'billing subscription list';
|
|
||||||
control:
|
|
||||||
| 'new subscription' // no subscription before
|
|
||||||
| 'cancel'
|
|
||||||
| 'paying'; // resume: subscribed before
|
|
||||||
type: SubscriptionPlan;
|
|
||||||
category: SubscriptionRecurring;
|
|
||||||
}
|
|
||||||
@@ -9,7 +9,7 @@ export const Empty = ({
|
|||||||
}: {
|
}: {
|
||||||
onDrop: (data: DropTargetDropEvent<AffineDNDData>) => void;
|
onDrop: (data: DropTargetDropEvent<AffineDNDData>) => void;
|
||||||
}) => {
|
}) => {
|
||||||
const { dropTargetRef } = useDropTarget(
|
const { dropTargetRef } = useDropTarget<AffineDNDData>(
|
||||||
() => ({
|
() => ({
|
||||||
onDrop,
|
onDrop,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { mixpanel } from '@affine/core/utils';
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import type { QuotaQuery } from '@affine/graphql';
|
import type { QuotaQuery } from '@affine/graphql';
|
||||||
import type { WorkspaceScope } from '@toeverything/infra';
|
import type { WorkspaceScope } from '@toeverything/infra';
|
||||||
import {
|
import {
|
||||||
@@ -31,20 +31,6 @@ export class TelemetryService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onApplicationStart() {
|
onApplicationStart() {
|
||||||
if (process.env.MIXPANEL_TOKEN) {
|
|
||||||
mixpanel.init(process.env.MIXPANEL_TOKEN || '', {
|
|
||||||
track_pageview: true,
|
|
||||||
persistence: 'localStorage',
|
|
||||||
api_host: 'https://telemetry.affine.run',
|
|
||||||
});
|
|
||||||
mixpanel.register({
|
|
||||||
appVersion: runtimeConfig.appVersion,
|
|
||||||
environment: runtimeConfig.appBuildType,
|
|
||||||
editorVersion: runtimeConfig.editorVersion,
|
|
||||||
isSelfHosted: Boolean(runtimeConfig.isSelfHosted),
|
|
||||||
isDesktop: environment.isDesktop,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const account = this.auth.session.account$.value;
|
const account = this.auth.session.account$.value;
|
||||||
this.updateIdentity(account);
|
this.updateIdentity(account);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { mixpanel } from '@affine/core/utils';
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { createEvent, Service } from '@toeverything/infra';
|
import { createEvent, Service } from '@toeverything/infra';
|
||||||
import { combineLatest, distinctUntilChanged, map, skip } from 'rxjs';
|
import { combineLatest, distinctUntilChanged, map, skip } from 'rxjs';
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import { EMPTY, mergeMap, switchMap } from 'rxjs';
|
|||||||
|
|
||||||
import { generateSubscriptionCallbackLink } from '../hooks/affine/use-subscription-notify';
|
import { generateSubscriptionCallbackLink } from '../hooks/affine/use-subscription-notify';
|
||||||
import { RouteLogic, useNavigateHelper } from '../hooks/use-navigate-helper';
|
import { RouteLogic, useNavigateHelper } from '../hooks/use-navigate-helper';
|
||||||
|
import { mixpanel } from '../mixpanel';
|
||||||
import { AuthService, SubscriptionService } from '../modules/cloud';
|
import { AuthService, SubscriptionService } from '../modules/cloud';
|
||||||
import { mixpanel } from '../utils';
|
|
||||||
import { container } from './subscribe.css';
|
import { container } from './subscribe.css';
|
||||||
|
|
||||||
export const Component = () => {
|
export const Component = () => {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
import { Header } from '@affine/core/components/pure/header';
|
import { Header } from '@affine/core/components/pure/header';
|
||||||
import { WorkspaceModeFilterTab } from '@affine/core/components/pure/workspace-mode-filter-tab';
|
import { WorkspaceModeFilterTab } from '@affine/core/components/pure/workspace-mode-filter-tab';
|
||||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||||
import { mixpanel } from '@affine/core/utils';
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import type { Filter } from '@affine/env/filter';
|
import type { Filter } from '@affine/env/filter';
|
||||||
import { PlusIcon } from '@blocksuite/icons/rc';
|
import { PlusIcon } from '@blocksuite/icons/rc';
|
||||||
import { useService, WorkspaceService } from '@toeverything/infra';
|
import { useService, WorkspaceService } from '@toeverything/infra';
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { appSettingAtom } from '@toeverything/infra';
|
|||||||
import { useAtomValue } from 'jotai/react';
|
import { useAtomValue } from 'jotai/react';
|
||||||
import { useLayoutEffect } from 'react';
|
import { useLayoutEffect } from 'react';
|
||||||
|
|
||||||
import { mixpanel } from './utils/mixpanel';
|
import { mixpanel } from './mixpanel';
|
||||||
|
|
||||||
export function Telemetry() {
|
export function Telemetry() {
|
||||||
const settings = useAtomValue(appSettingAtom);
|
const settings = useAtomValue(appSettingAtom);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
export * from './create-emotion-cache';
|
export * from './create-emotion-cache';
|
||||||
export * from './fractional-indexing';
|
export * from './fractional-indexing';
|
||||||
export * from './mixpanel';
|
|
||||||
export * from './popup';
|
export * from './popup';
|
||||||
export * from './string2color';
|
export * from './string2color';
|
||||||
export * from './toast';
|
export * from './toast';
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
import { DebugLogger } from '@affine/debug';
|
|
||||||
import type { OverridedMixpanel } from 'mixpanel-browser';
|
|
||||||
import mixpanelBrowser from 'mixpanel-browser';
|
|
||||||
|
|
||||||
import type { MixpanelEvents } from '../mixpanel';
|
|
||||||
|
|
||||||
const logger = new DebugLogger('affine:mixpanel');
|
|
||||||
|
|
||||||
export const mixpanel = process.env.MIXPANEL_TOKEN
|
|
||||||
? mixpanelBrowser
|
|
||||||
: new Proxy(
|
|
||||||
function () {} as unknown as OverridedMixpanel,
|
|
||||||
createProxyHandler()
|
|
||||||
);
|
|
||||||
|
|
||||||
function createProxyHandler(property?: string | symbol) {
|
|
||||||
const handler = {
|
|
||||||
get: (_target, childProperty) => {
|
|
||||||
const path = property
|
|
||||||
? String(property) + '.' + String(childProperty)
|
|
||||||
: String(childProperty);
|
|
||||||
return new Proxy(
|
|
||||||
function () {} as unknown as OverridedMixpanel,
|
|
||||||
createProxyHandler(path)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
apply: (_target, _thisArg, args) => {
|
|
||||||
logger.debug(
|
|
||||||
`mixpanel.${property ? String(property) : 'mixpanel'}`,
|
|
||||||
...args
|
|
||||||
);
|
|
||||||
},
|
|
||||||
} as ProxyHandler<OverridedMixpanel>;
|
|
||||||
return handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function mixpanelTrack<T extends keyof MixpanelEvents>(
|
|
||||||
event: T,
|
|
||||||
properties?: MixpanelEvents[T]
|
|
||||||
) {
|
|
||||||
return mixpanel.track(event, properties);
|
|
||||||
}
|
|
||||||
@@ -10,7 +10,7 @@ export async function waitForEditorLoad(page: Page) {
|
|||||||
export async function waitForAllPagesLoad(page: Page) {
|
export async function waitForAllPagesLoad(page: Page) {
|
||||||
// if filters tag is rendered, we believe all_pages is ready
|
// if filters tag is rendered, we believe all_pages is ready
|
||||||
await page.waitForSelector('[data-testid="create-first-filter"]', {
|
await page.waitForSelector('[data-testid="create-first-filter"]', {
|
||||||
timeout: 1000,
|
timeout: 20000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user