mirror of
https://github.com/toeverything/AFFiNE.git
synced 2025-01-03 21:35:19 +03:00
chore(core): add more telemetry (#6402)
This commit is contained in:
parent
1c648c2425
commit
822bbb54a4
@ -8,6 +8,7 @@ import { GithubIcon, GoogleDuotoneIcon } from '@blocksuite/icons';
|
||||
import type { ReactElement } from 'react';
|
||||
import { useCallback, useState } from 'react';
|
||||
|
||||
import { mixpanel } from '../../../utils';
|
||||
import { useAuth } from './use-auth';
|
||||
|
||||
const OAuthProviderMap: Record<
|
||||
@ -51,6 +52,7 @@ function OAuthProvider({ provider }: { provider: OAuthProviderType }) {
|
||||
const onClick = useCallback(() => {
|
||||
setIsConnecting(true);
|
||||
oauthSignIn(provider);
|
||||
mixpanel.track('OAuth', { provider });
|
||||
}, [provider, oauthSignIn]);
|
||||
|
||||
return (
|
||||
|
@ -91,6 +91,9 @@ export const SignIn: FC<AuthPanelProps> = ({
|
||||
if (user.hasPassword && !subscriptionData) {
|
||||
setAuthState('signInWithPassword');
|
||||
} else {
|
||||
mixpanel.track_forms('SignIn', 'Email', {
|
||||
email,
|
||||
});
|
||||
const res = await signIn(email, verifyToken, challenge);
|
||||
if (res?.status === 403 && res?.url === INTERNAL_BETA_URL) {
|
||||
return setAuthState('noAccess');
|
||||
@ -103,6 +106,9 @@ export const SignIn: FC<AuthPanelProps> = ({
|
||||
}
|
||||
} else {
|
||||
const res = await signUp(email, verifyToken, challenge);
|
||||
mixpanel.track_forms('SignUp', 'Email', {
|
||||
email,
|
||||
});
|
||||
if (res?.status === 403 && res?.url === INTERNAL_BETA_URL) {
|
||||
return setAuthState('noAccess');
|
||||
} else if (!res || res.status >= 400) {
|
||||
|
@ -19,6 +19,7 @@ import { useSetAtom } from 'jotai';
|
||||
import type { KeyboardEvent } from 'react';
|
||||
import { useCallback, useLayoutEffect, useState } from 'react';
|
||||
|
||||
import { mixpanel } from '../../../utils';
|
||||
import { CloudSvg } from '../share-page-modal/cloud-svg';
|
||||
import * as styles from './index.css';
|
||||
|
||||
@ -226,6 +227,9 @@ export const CreateWorkspaceModal = ({
|
||||
|
||||
const onConfirmName = useAsyncCallback(
|
||||
async (name: string, workspaceFlavour: WorkspaceFlavour) => {
|
||||
mixpanel.track_forms('CreateWorkspaceModel', 'CreateWorkspace', {
|
||||
workspaceFlavour,
|
||||
});
|
||||
if (loading) return;
|
||||
setLoading(true);
|
||||
|
||||
|
@ -27,7 +27,7 @@ import {
|
||||
import { encodeStateAsUpdate } from 'yjs';
|
||||
|
||||
import { pageHistoryModalAtom } from '../../../atoms/page-history';
|
||||
import { timestampToLocalTime } from '../../../utils';
|
||||
import { mixpanel, timestampToLocalTime } from '../../../utils';
|
||||
import { BlockSuiteEditor } from '../../blocksuite/block-suite-editor';
|
||||
import { StyledEditorModeSwitch } from '../../blocksuite/block-suite-mode-switch/style';
|
||||
import {
|
||||
@ -104,9 +104,15 @@ const HistoryEditorPreview = ({
|
||||
title,
|
||||
}: HistoryEditorPreviewProps) => {
|
||||
const onSwitchToPageMode = useCallback(() => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'HistorySwitchToPageMode',
|
||||
});
|
||||
onModeChange('page');
|
||||
}, [onModeChange]);
|
||||
const onSwitchToEdgelessMode = useCallback(() => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'HistorySwitchToEdgelessMode',
|
||||
});
|
||||
onModeChange('edgeless');
|
||||
}, [onModeChange]);
|
||||
|
||||
@ -528,6 +534,9 @@ export const GlobalPageHistoryModal = () => {
|
||||
const workspace = useService(Workspace);
|
||||
const handleOpenChange = useCallback(
|
||||
(open: boolean) => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: open ? 'OpenPageHistoryModal' : 'ClosePageHistoryModal',
|
||||
});
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
open,
|
||||
|
@ -33,6 +33,7 @@ import { useServerFeatures } from '../../../../hooks/affine/use-server-config';
|
||||
import { useMutation } from '../../../../hooks/use-mutation';
|
||||
import { useQuery } from '../../../../hooks/use-query';
|
||||
import { useUserSubscription } from '../../../../hooks/use-subscription';
|
||||
import { mixpanel } from '../../../../utils';
|
||||
import { validateAndReduceImage } from '../../../../utils/reduce-image';
|
||||
import { Upload } from '../../../pure/file-upload';
|
||||
import * as styles from './style.css';
|
||||
@ -52,6 +53,9 @@ export const UserAvatar = () => {
|
||||
const handleUpdateUserAvatar = useAsyncCallback(
|
||||
async (file: File) => {
|
||||
try {
|
||||
mixpanel.track_forms('UpdateProfile', 'UploadAvatar', {
|
||||
userId: user.id,
|
||||
});
|
||||
const reducedFile = await validateAndReduceImage(file);
|
||||
const data = await avatarTrigger({
|
||||
avatar: reducedFile, // Pass the reducedFile directly to the avatarTrigger
|
||||
@ -74,6 +78,9 @@ export const UserAvatar = () => {
|
||||
|
||||
const handleRemoveUserAvatar = useCallback(
|
||||
async (e: MouseEvent<HTMLButtonElement>) => {
|
||||
mixpanel.track('RemoveAvatar', {
|
||||
userId: user.id,
|
||||
});
|
||||
e.stopPropagation();
|
||||
await removeAvatarTrigger();
|
||||
user.update({ avatarUrl: null });
|
||||
@ -120,6 +127,9 @@ export const AvatarAndName = () => {
|
||||
}
|
||||
|
||||
try {
|
||||
mixpanel.track_forms('UpdateProfile', 'UpdateUsername', {
|
||||
userId: user.id,
|
||||
});
|
||||
const data = await updateProfile({
|
||||
input: { name: input },
|
||||
});
|
||||
@ -197,6 +207,9 @@ const StoragePanel = () => {
|
||||
|
||||
const setSettingModalAtom = useSetAtom(openSettingModalAtom);
|
||||
const onUpgrade = useCallback(() => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'UpgradeStorage',
|
||||
});
|
||||
setSettingModalAtom({
|
||||
open: true,
|
||||
activeTab: 'plans',
|
||||
|
@ -31,6 +31,7 @@ import { useMutation } from '../../../../../hooks/use-mutation';
|
||||
import { useQuery } from '../../../../../hooks/use-query';
|
||||
import type { SubscriptionMutator } from '../../../../../hooks/use-subscription';
|
||||
import { useUserSubscription } from '../../../../../hooks/use-subscription';
|
||||
import { mixpanel } from '../../../../../utils';
|
||||
import { SWRErrorBoundary } from '../../../../pure/swr-error-bundary';
|
||||
import { CancelAction, ResumeAction } from '../plans/actions';
|
||||
import * as styles from './style.css';
|
||||
@ -115,11 +116,15 @@ const SubscriptionSettings = () => {
|
||||
const setOpenSettingModalAtom = useSetAtom(openSettingModalAtom);
|
||||
|
||||
const gotoPlansSetting = useCallback(() => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'ChangePlan',
|
||||
currentPlan: plan,
|
||||
});
|
||||
setOpenSettingModalAtom({
|
||||
open: true,
|
||||
activeTab: 'plans',
|
||||
});
|
||||
}, [setOpenSettingModalAtom]);
|
||||
}, [setOpenSettingModalAtom, plan]);
|
||||
|
||||
const currentPlanDesc = useMemo(() => {
|
||||
const messageKey = getMessageKey(plan, recurring);
|
||||
|
@ -24,6 +24,7 @@ import { openPaymentDisableAtom } from '../../../../../atoms';
|
||||
import { authAtom } from '../../../../../atoms/index';
|
||||
import { useCurrentLoginStatus } from '../../../../../hooks/affine/use-current-login-status';
|
||||
import { useMutation } from '../../../../../hooks/use-mutation';
|
||||
import { mixpanel } from '../../../../../utils';
|
||||
import { CancelAction, ResumeAction } from './actions';
|
||||
import { BulledListIcon } from './icons/bulled-list';
|
||||
import { ConfirmLoadingModal } from './modals';
|
||||
@ -206,6 +207,7 @@ const ActionButton = ({
|
||||
|
||||
const mutateAndNotify = useCallback(
|
||||
(sub: Parameters<SubscriptionMutator>[0]) => {
|
||||
mixpanel.track_forms('Subscription', detail.plan, sub);
|
||||
onSubscriptionUpdate?.(sub);
|
||||
onNotify?.({ detail, recurring });
|
||||
},
|
||||
@ -346,6 +348,12 @@ const BookDemo = ({ plan }: { plan: SubscriptionPlan }) => {
|
||||
href={url}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
onClick={() => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'BookDemo',
|
||||
url,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Button className={styles.planAction} type="primary">
|
||||
{t['com.affine.payment.book-a-demo']()}
|
||||
|
@ -26,6 +26,7 @@ import { Suspense, useCallback, useMemo } from 'react';
|
||||
import { authAtom } from '../../../../atoms';
|
||||
import { useCurrentLoginStatus } from '../../../../hooks/affine/use-current-login-status';
|
||||
import { useCurrentUser } from '../../../../hooks/affine/use-current-user';
|
||||
import { mixpanel } from '../../../../utils';
|
||||
import { UserPlanButton } from '../../auth/user-plan-button';
|
||||
import { useGeneralSettingList } from '../general-setting';
|
||||
import type { ActiveTab, WorkspaceSubTab } from '../types';
|
||||
@ -115,10 +116,17 @@ export const SettingSidebar = ({
|
||||
const loginStatus = useCurrentLoginStatus();
|
||||
const generalList = useGeneralSettingList();
|
||||
const onAccountSettingClick = useCallback(() => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'AccountSetting',
|
||||
});
|
||||
onTabChange('account', null);
|
||||
}, [onTabChange]);
|
||||
const onWorkspaceSettingClick = useCallback(
|
||||
(subTab: WorkspaceSubTab, workspaceMetadata: WorkspaceMetadata) => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'WorkspaceSetting',
|
||||
workspaceId: workspaceMetadata.id,
|
||||
});
|
||||
onTabChange(`workspace:${subTab}`, workspaceMetadata);
|
||||
},
|
||||
[onTabChange]
|
||||
@ -141,6 +149,9 @@ export const SettingSidebar = ({
|
||||
key={key}
|
||||
title={title}
|
||||
onClick={() => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: key,
|
||||
});
|
||||
onTabChange(key, null);
|
||||
}}
|
||||
data-testid={testId}
|
||||
|
@ -2,6 +2,7 @@ import { CloseIcon, DownloadIcon } from '@blocksuite/icons';
|
||||
import clsx from 'clsx';
|
||||
import { useCallback, useState } from 'react';
|
||||
|
||||
import { mixpanel } from '../../../utils';
|
||||
import * as styles from './index.css';
|
||||
|
||||
// Although it is called an input, it is actually a button.
|
||||
@ -20,6 +21,9 @@ export function AppDownloadButton({
|
||||
|
||||
// TODO: unify this type of literal value.
|
||||
const handleClick = useCallback(() => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'GoToDownloadAppPage',
|
||||
});
|
||||
const url = `https://affine.pro/download?channel=stable`;
|
||||
open(url, '_blank');
|
||||
}, []);
|
||||
|
@ -7,7 +7,7 @@ import type { CSSProperties } from 'react';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
|
||||
import type { DocCollection } from '../../../shared';
|
||||
import { toast } from '../../../utils';
|
||||
import { mixpanel, toast } from '../../../utils';
|
||||
import { StyledEditorModeSwitch, StyledKeyboardItem } from './style';
|
||||
import { EdgelessSwitchItem, PageSwitchItem } from './switch-items';
|
||||
|
||||
@ -67,6 +67,9 @@ export const EditorModeSwitch = ({
|
||||
}, [currentMode, isPublic, page, pageId, t, trash]);
|
||||
|
||||
const onSwitchToPageMode = useCallback(() => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'SwitchToPageMode',
|
||||
});
|
||||
if (currentMode === 'page' || isPublic) {
|
||||
return;
|
||||
}
|
||||
@ -75,6 +78,9 @@ export const EditorModeSwitch = ({
|
||||
}, [currentMode, isPublic, page, t]);
|
||||
|
||||
const onSwitchToEdgelessMode = useCallback(() => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'SwitchToEdgelessMode',
|
||||
});
|
||||
if (currentMode === 'edgeless' || isPublic) {
|
||||
return;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import {
|
||||
openCreateWorkspaceModalAtom,
|
||||
openDisableCloudAlertModalAtom,
|
||||
} from '../../../../atoms';
|
||||
import { mixpanel } from '../../../../utils';
|
||||
import { AddWorkspace } from './add-workspace';
|
||||
import * as styles from './index.css';
|
||||
import { UserAccountItem } from './user-account';
|
||||
@ -27,6 +28,9 @@ export const SignInItem = () => {
|
||||
const t = useAFFiNEI18N();
|
||||
|
||||
const onClickSignIn = useCallback(() => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'SignIn',
|
||||
});
|
||||
if (!runtimeConfig.enableCloud) {
|
||||
setDisableCloudOpen(true);
|
||||
} else {
|
||||
@ -104,6 +108,9 @@ const UserWithWorkspaceListInner = ({
|
||||
) {
|
||||
return openSignInModal();
|
||||
}
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'NewWorkspace',
|
||||
});
|
||||
setOpenCreateWorkspaceModal('new');
|
||||
onEventEnd?.();
|
||||
}, [
|
||||
@ -114,6 +121,9 @@ const UserWithWorkspaceListInner = ({
|
||||
]);
|
||||
|
||||
const onAddWorkspace = useCallback(() => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'AddWorkspace',
|
||||
});
|
||||
setOpenCreateWorkspaceModal('add');
|
||||
onEventEnd?.();
|
||||
}, [onEventEnd, setOpenCreateWorkspaceModal]);
|
||||
|
@ -3,6 +3,7 @@ import { useAtom } from 'jotai';
|
||||
import { Suspense, useCallback } from 'react';
|
||||
|
||||
import { openWorkspaceListModalAtom } from '../../atoms';
|
||||
import { mixpanel } from '../../utils';
|
||||
import { UserWithWorkspaceList } from '../pure/workspace-slider-bar/user-with-workspace-list';
|
||||
import { WorkspaceCard } from '../pure/workspace-slider-bar/workspace-card';
|
||||
|
||||
@ -14,6 +15,9 @@ export const WorkspaceSelector = () => {
|
||||
setOpenUserWorkspaceList(false);
|
||||
}, [setOpenUserWorkspaceList]);
|
||||
const openUserWorkspaceList = useCallback(() => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'OpenWorkspaceList',
|
||||
});
|
||||
setOpenUserWorkspaceList(true);
|
||||
}, [setOpenUserWorkspaceList]);
|
||||
|
||||
|
@ -8,6 +8,7 @@ import { useService, Workspace, WorkspaceManager } from '@toeverything/infra';
|
||||
import { useState } from 'react';
|
||||
|
||||
import { WorkspaceSubPath } from '../../shared';
|
||||
import { mixpanel } from '../../utils';
|
||||
import * as styles from './upgrade.css';
|
||||
import { ArrowCircleIcon, HeartBreakIcon } from './upgrade-icon';
|
||||
|
||||
@ -27,6 +28,10 @@ export const WorkspaceUpgrade = function WorkspaceUpgrade() {
|
||||
return;
|
||||
}
|
||||
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'UpgradeWorkspace',
|
||||
});
|
||||
|
||||
try {
|
||||
const newWorkspace =
|
||||
await currentWorkspace.upgrade.upgrade(workspaceManager);
|
||||
|
@ -7,6 +7,7 @@ import { atomWithObservable, atomWithStorage } from 'jotai/utils';
|
||||
import { useCallback, useState } from 'react';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { mixpanel } from '../utils';
|
||||
import { useAsyncCallback } from './affine-async-hooks';
|
||||
|
||||
function rpcToObservable<
|
||||
@ -120,6 +121,9 @@ export const useAppUpdater = () => {
|
||||
);
|
||||
|
||||
const quitAndInstall = useCallback(() => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'QuitAndInstall',
|
||||
});
|
||||
if (updateReady) {
|
||||
setAppQuitting(true);
|
||||
apis?.updater.quitAndInstall().catch(err => {
|
||||
@ -130,6 +134,9 @@ export const useAppUpdater = () => {
|
||||
}, [updateReady]);
|
||||
|
||||
const checkForUpdates = useCallback(async () => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'CheckForUpdates',
|
||||
});
|
||||
if (checkingForUpdates) {
|
||||
return;
|
||||
}
|
||||
@ -146,6 +153,9 @@ export const useAppUpdater = () => {
|
||||
}, [checkingForUpdates, setCheckingForUpdates]);
|
||||
|
||||
const downloadUpdate = useCallback(() => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'DownloadUpdate',
|
||||
});
|
||||
apis?.updater.downloadUpdate().catch(err => {
|
||||
console.error('Error downloading update:', err);
|
||||
});
|
||||
@ -153,6 +163,10 @@ export const useAppUpdater = () => {
|
||||
|
||||
const toggleAutoDownload = useCallback(
|
||||
(enable: boolean) => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'ToggleAutoDownload',
|
||||
value: enable,
|
||||
});
|
||||
setSetting({
|
||||
autoDownloadUpdate: enable,
|
||||
});
|
||||
@ -162,6 +176,10 @@ export const useAppUpdater = () => {
|
||||
|
||||
const toggleAutoCheck = useCallback(
|
||||
(enable: boolean) => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'ToggleAutoCheck',
|
||||
value: enable,
|
||||
});
|
||||
setSetting({
|
||||
autoCheckUpdate: enable,
|
||||
});
|
||||
@ -170,11 +188,17 @@ export const useAppUpdater = () => {
|
||||
);
|
||||
|
||||
const openChangelog = useAsyncCallback(async () => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'OpenChangelog',
|
||||
});
|
||||
window.open(runtimeConfig.changelogUrl, '_blank');
|
||||
await setChangelogUnread(true);
|
||||
}, [setChangelogUnread]);
|
||||
|
||||
const dismissChangelog = useAsyncCallback(async () => {
|
||||
mixpanel.track('Button', {
|
||||
resolve: 'DismissChangelog',
|
||||
});
|
||||
await setChangelogUnread(true);
|
||||
}, [setChangelogUnread]);
|
||||
|
||||
|
@ -47,6 +47,7 @@ import {
|
||||
} from '../providers/modal-provider';
|
||||
import { SWRConfigProvider } from '../providers/swr-config-provider';
|
||||
import { pathGenerator } from '../shared';
|
||||
import { mixpanel } from '../utils';
|
||||
import * as styles from './styles.css';
|
||||
|
||||
const CMDKQuickSearchModal = lazy(() =>
|
||||
@ -60,6 +61,14 @@ export const QuickSearch = () => {
|
||||
openQuickSearchModalAtom
|
||||
);
|
||||
|
||||
const onToggleQuickSearch = useCallback(
|
||||
(open: boolean) => {
|
||||
mixpanel.track('QuickSearch', { open });
|
||||
setOpenQuickSearchModalAtom(open);
|
||||
},
|
||||
[setOpenQuickSearchModalAtom]
|
||||
);
|
||||
|
||||
const workbench = useService(Workbench);
|
||||
const currentPath = useLiveData(workbench.location$.map(l => l.pathname));
|
||||
const pageRecordList = useService(PageRecordList);
|
||||
@ -73,7 +82,7 @@ export const QuickSearch = () => {
|
||||
return (
|
||||
<CMDKQuickSearchModal
|
||||
open={openQuickSearchModal}
|
||||
onOpenChange={setOpenQuickSearchModalAtom}
|
||||
onOpenChange={onToggleQuickSearch}
|
||||
pageMeta={pageMeta}
|
||||
/>
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user