diff --git a/packages/frontend/core/src/commands/affine-creation.tsx b/packages/frontend/core/src/commands/affine-creation.tsx
index b2f5697faf..e926d5bb0d 100644
--- a/packages/frontend/core/src/commands/affine-creation.tsx
+++ b/packages/frontend/core/src/commands/affine-creation.tsx
@@ -4,6 +4,7 @@ import type { createStore } from 'jotai';
import { openCreateWorkspaceModalAtom } from '../atoms';
import type { usePageHelper } from '../components/blocksuite/block-suite-page-list/utils';
+import { track } from '../mixpanel';
import { registerAffineCommand } from './registry';
export function registerAffineCreationCommands({
@@ -29,6 +30,8 @@ export function registerAffineCreationCommands({
}
: undefined,
run() {
+ track.$.cmdk.creation.createDoc({ mode: 'page' });
+
pageHelper.createPage();
},
})
@@ -41,6 +44,10 @@ export function registerAffineCreationCommands({
icon: ,
label: t['com.affine.cmdk.affine.new-edgeless-page'](),
run() {
+ track.$.cmdk.creation.createDoc({
+ mode: 'edgeless',
+ });
+
pageHelper.createEdgeless();
},
})
@@ -53,6 +60,8 @@ export function registerAffineCreationCommands({
icon: ,
label: t['com.affine.cmdk.affine.new-workspace'](),
run() {
+ track.$.cmdk.workspace.createWorkspace();
+
store.set(openCreateWorkspaceModalAtom, 'new');
},
})
@@ -67,6 +76,10 @@ export function registerAffineCreationCommands({
return environment.isDesktop;
},
run() {
+ track.$.cmdk.workspace.createWorkspace({
+ control: 'import',
+ });
+
store.set(openCreateWorkspaceModalAtom, 'add');
},
})
diff --git a/packages/frontend/core/src/commands/affine-help.tsx b/packages/frontend/core/src/commands/affine-help.tsx
index dfb10a3c8e..369beee727 100644
--- a/packages/frontend/core/src/commands/affine-help.tsx
+++ b/packages/frontend/core/src/commands/affine-help.tsx
@@ -3,6 +3,7 @@ import { ContactWithUsIcon, NewIcon } from '@blocksuite/icons/rc';
import type { createStore } from 'jotai';
import { openSettingModalAtom } from '../atoms';
+import { track } from '../mixpanel';
import { popupWindow } from '../utils';
import { registerAffineCommand } from './registry';
@@ -21,6 +22,7 @@ export function registerAffineHelpCommands({
icon: ,
label: t['com.affine.cmdk.affine.whats-new'](),
run() {
+ track.$.cmdk.help.openChangelog();
popupWindow(runtimeConfig.changelogUrl);
},
})
@@ -32,6 +34,7 @@ export function registerAffineHelpCommands({
icon: ,
label: t['com.affine.cmdk.affine.contact-us'](),
run() {
+ track.$.cmdk.help.contactUs();
store.set(openSettingModalAtom, {
open: true,
activeTab: 'about',
diff --git a/packages/frontend/core/src/commands/affine-layout.tsx b/packages/frontend/core/src/commands/affine-layout.tsx
index 584927f263..730171c99f 100644
--- a/packages/frontend/core/src/commands/affine-layout.tsx
+++ b/packages/frontend/core/src/commands/affine-layout.tsx
@@ -3,6 +3,7 @@ import { SidebarIcon } from '@blocksuite/icons/rc';
import type { createStore } from 'jotai';
import { appSidebarOpenAtom } from '../components/app-sidebar';
+import { track } from '../mixpanel';
import { registerAffineCommand } from './registry';
export function registerAffineLayoutCommands({
@@ -27,6 +28,8 @@ export function registerAffineLayoutCommands({
binding: '$mod+/',
},
run() {
+ track.$.navigationPanel.$.toggle();
+
store.set(appSidebarOpenAtom, v => !v);
},
})
diff --git a/packages/frontend/core/src/commands/affine-navigation.tsx b/packages/frontend/core/src/commands/affine-navigation.tsx
index 0a3094c4b0..7ce36bbefd 100644
--- a/packages/frontend/core/src/commands/affine-navigation.tsx
+++ b/packages/frontend/core/src/commands/affine-navigation.tsx
@@ -28,6 +28,10 @@ export function registerAffineNavigationCommands({
icon: ,
label: t['com.affine.cmdk.affine.navigation.goto-all-pages'](),
run() {
+ track.$.cmdk.navigation.navigate({
+ to: 'allDocs',
+ });
+
navigationHelper.jumpToSubPath(docCollection.id, WorkspaceSubPath.ALL);
},
})
@@ -40,6 +44,10 @@ export function registerAffineNavigationCommands({
icon: ,
label: 'Go to Collection List',
run() {
+ track.$.cmdk.navigation.navigate({
+ to: 'collectionList',
+ });
+
navigationHelper.jumpToCollections(docCollection.id);
},
})
@@ -52,6 +60,10 @@ export function registerAffineNavigationCommands({
icon: ,
label: 'Go to Tag List',
run() {
+ track.$.cmdk.navigation.navigate({
+ to: 'tagList',
+ });
+
navigationHelper.jumpToTags(docCollection.id);
},
})
@@ -64,6 +76,10 @@ export function registerAffineNavigationCommands({
icon: ,
label: t['com.affine.cmdk.affine.navigation.goto-workspace'](),
run() {
+ track.$.cmdk.navigation.navigate({
+ to: 'workspace',
+ });
+
store.set(openWorkspaceListModalAtom, true);
},
})
@@ -109,6 +125,10 @@ export function registerAffineNavigationCommands({
icon: ,
label: t['com.affine.cmdk.affine.navigation.goto-trash'](),
run() {
+ track.$.cmdk.navigation.navigate({
+ to: 'trash',
+ });
+
navigationHelper.jumpToSubPath(
docCollection.id,
WorkspaceSubPath.TRASH
diff --git a/packages/frontend/core/src/commands/affine-settings.tsx b/packages/frontend/core/src/commands/affine-settings.tsx
index 78c0aee75f..6e0164374a 100644
--- a/packages/frontend/core/src/commands/affine-settings.tsx
+++ b/packages/frontend/core/src/commands/affine-settings.tsx
@@ -6,6 +6,7 @@ import type { createStore } from 'jotai';
import type { useTheme } from 'next-themes';
import type { useLanguageHelper } from '../hooks/affine/use-language-helper';
+import { track } from '../mixpanel';
import { registerAffineCommand } from './registry';
export function registerAffineSettingsCommands({
@@ -34,6 +35,10 @@ export function registerAffineSettingsCommands({
icon: ,
preconditionStrategy: () => theme.theme !== 'system',
run() {
+ track.$.cmdk.settings.changeAppSetting({
+ key: 'theme',
+ value: 'system',
+ });
theme.setTheme('system');
},
})
@@ -48,6 +53,10 @@ export function registerAffineSettingsCommands({
icon: ,
preconditionStrategy: () => theme.theme !== 'dark',
run() {
+ track.$.cmdk.settings.changeAppSetting({
+ key: 'theme',
+ value: 'dark',
+ });
theme.setTheme('dark');
},
})
@@ -63,6 +72,11 @@ export function registerAffineSettingsCommands({
icon: ,
preconditionStrategy: () => theme.theme !== 'light',
run() {
+ track.$.cmdk.settings.changeAppSetting({
+ key: 'theme',
+ value: 'light',
+ });
+
theme.setTheme('light');
},
})
@@ -80,6 +94,11 @@ export function registerAffineSettingsCommands({
preconditionStrategy: () =>
store.get(appSettingAtom).fontStyle !== 'Sans',
run() {
+ track.$.cmdk.settings.changeAppSetting({
+ key: 'fontStyle',
+ value: 'Sans',
+ });
+
store.set(appSettingAtom, prev => ({
...prev,
fontStyle: 'Sans',
@@ -99,6 +118,11 @@ export function registerAffineSettingsCommands({
preconditionStrategy: () =>
store.get(appSettingAtom).fontStyle !== 'Serif',
run() {
+ track.$.cmdk.settings.changeAppSetting({
+ key: 'fontStyle',
+ value: 'Serif',
+ });
+
store.set(appSettingAtom, prev => ({
...prev,
fontStyle: 'Serif',
@@ -118,6 +142,11 @@ export function registerAffineSettingsCommands({
preconditionStrategy: () =>
store.get(appSettingAtom).fontStyle !== 'Mono',
run() {
+ track.$.cmdk.settings.changeAppSetting({
+ key: 'fontStyle',
+ value: 'Mono',
+ });
+
store.set(appSettingAtom, prev => ({
...prev,
fontStyle: 'Mono',
@@ -138,6 +167,11 @@ export function registerAffineSettingsCommands({
icon: ,
preconditionStrategy: () => currentLanguage?.tag !== language.tag,
run() {
+ track.$.cmdk.settings.changeAppSetting({
+ key: 'language',
+ value: language.name,
+ });
+
onLanguageChange(language.tag);
},
})
@@ -158,6 +192,10 @@ export function registerAffineSettingsCommands({
icon: ,
preconditionStrategy: () => environment.isDesktop,
run() {
+ track.$.cmdk.settings.changeAppSetting({
+ key: 'clientBorder',
+ value: store.get(appSettingAtom).clientBorder ? 'off' : 'on',
+ });
store.set(appSettingAtom, prev => ({
...prev,
clientBorder: !prev.clientBorder,
@@ -178,6 +216,11 @@ export function registerAffineSettingsCommands({
category: 'affine:settings',
icon: ,
run() {
+ track.$.cmdk.settings.changeAppSetting({
+ key: 'fullWidthLayout',
+ value: store.get(appSettingAtom).fullWidthLayout ? 'off' : 'on',
+ });
+
store.set(appSettingAtom, prev => ({
...prev,
fullWidthLayout: !prev.fullWidthLayout,
@@ -201,6 +244,11 @@ export function registerAffineSettingsCommands({
icon: ,
preconditionStrategy: () => environment.isDesktop,
run() {
+ track.$.cmdk.settings.changeAppSetting({
+ key: 'enableNoisyBackground',
+ value: store.get(appSettingAtom).enableNoisyBackground ? 'off' : 'on',
+ });
+
store.set(appSettingAtom, prev => ({
...prev,
enableNoisyBackground: !prev.enableNoisyBackground,
@@ -222,6 +270,10 @@ export function registerAffineSettingsCommands({
icon: ,
preconditionStrategy: () => environment.isDesktop && environment.isMacOs,
run() {
+ track.$.cmdk.settings.changeAppSetting({
+ key: 'enableBlurBackground',
+ value: store.get(appSettingAtom).enableBlurBackground ? 'off' : 'on',
+ });
store.set(appSettingAtom, prev => ({
...prev,
enableBlurBackground: !prev.enableBlurBackground,
diff --git a/packages/frontend/core/src/commands/affine-updates.tsx b/packages/frontend/core/src/commands/affine-updates.tsx
index 2d43150943..39921883f0 100644
--- a/packages/frontend/core/src/commands/affine-updates.tsx
+++ b/packages/frontend/core/src/commands/affine-updates.tsx
@@ -5,6 +5,7 @@ import type { useI18n } from '@affine/i18n';
import { ResetIcon } from '@blocksuite/icons/rc';
import type { createStore } from 'jotai';
+import { track } from '../mixpanel';
import { registerAffineCommand } from './registry';
export function registerAffineUpdatesCommands({
@@ -24,6 +25,8 @@ export function registerAffineUpdatesCommands({
label: t['com.affine.cmdk.affine.restart-to-upgrade'](),
preconditionStrategy: () => !!store.get(updateReadyAtom),
run() {
+ track.$.cmdk.updates.quitAndInstall();
+
apis?.updater.quitAndInstall().catch(err => {
notify.error({
title: 'Failed to restart to upgrade',
diff --git a/packages/frontend/core/src/components/blocksuite/block-suite-header/menu/index.tsx b/packages/frontend/core/src/components/blocksuite/block-suite-header/menu/index.tsx
index 2f7134bb8b..cc345a313f 100644
--- a/packages/frontend/core/src/components/blocksuite/block-suite-header/menu/index.tsx
+++ b/packages/frontend/core/src/components/blocksuite/block-suite-header/menu/index.tsx
@@ -150,7 +150,9 @@ export const PageHeaderMenuButton = ({
const handleSwitchMode = useCallback(() => {
doc.toggleMode();
- track.$.header.docOptions.switchPageMode();
+ track.$.header.docOptions.switchPageMode({
+ mode: currentMode === 'page' ? 'edgeless' : 'page',
+ });
toast(
currentMode === 'page'
? t['com.affine.toastMessage.edgelessMode']()
diff --git a/packages/frontend/core/src/hooks/affine/use-register-blocksuite-editor-commands.tsx b/packages/frontend/core/src/hooks/affine/use-register-blocksuite-editor-commands.tsx
index 9d0b36a06c..058b457553 100644
--- a/packages/frontend/core/src/hooks/affine/use-register-blocksuite-editor-commands.tsx
+++ b/packages/frontend/core/src/hooks/affine/use-register-blocksuite-editor-commands.tsx
@@ -102,6 +102,8 @@ export function useRegisterBlocksuiteEditorCommands() {
icon: mode === 'page' ? : ,
label: t['com.affine.page-properties.page-info.view'](),
run() {
+ track.$.cmdk.docInfo.open();
+
openInfoModal();
},
})
@@ -118,6 +120,8 @@ export function useRegisterBlocksuiteEditorCommands() {
: t['com.affine.favoritePageOperation.add'](),
run() {
favAdapter.toggle(docId, 'doc');
+ track.$.cmdk.editor.toggleFavorite();
+
toast(
favorite
? t['com.affine.cmdk.affine.editor.remove-from-favourites']()
@@ -141,6 +145,10 @@ export function useRegisterBlocksuiteEditorCommands() {
: t['com.affine.pageMode.page']()
}`,
run() {
+ track.$.cmdk.editor.switchPageMode({
+ mode: mode === 'page' ? 'edgeless' : 'page',
+ });
+
doc.toggleMode();
toast(
mode === 'page'
@@ -161,7 +169,7 @@ export function useRegisterBlocksuiteEditorCommands() {
label: t['com.affine.header.option.duplicate'](),
run() {
duplicate(docId);
- track.$.cmdk.$.createDoc({
+ track.$.cmdk.editor.createDoc({
control: 'duplicate',
});
},
@@ -176,6 +184,10 @@ export function useRegisterBlocksuiteEditorCommands() {
icon: mode === 'page' ? : ,
label: t['Export to PDF'](),
async run() {
+ track.$.cmdk.editor.export({
+ type: 'pdf',
+ });
+
await exportHandler('pdf');
},
})
@@ -189,6 +201,10 @@ export function useRegisterBlocksuiteEditorCommands() {
icon: mode === 'page' ? : ,
label: t['Export to HTML'](),
async run() {
+ track.$.cmdk.editor.export({
+ type: 'html',
+ });
+
await exportHandler('html');
},
})
@@ -202,6 +218,10 @@ export function useRegisterBlocksuiteEditorCommands() {
icon: mode === 'page' ? : ,
label: t['Export to PNG'](),
async run() {
+ track.$.cmdk.editor.export({
+ type: 'png',
+ });
+
await exportHandler('png');
},
})
@@ -215,6 +235,10 @@ export function useRegisterBlocksuiteEditorCommands() {
icon: mode === 'page' ? : ,
label: t['Export to Markdown'](),
async run() {
+ track.$.cmdk.editor.export({
+ type: 'markdown',
+ });
+
await exportHandler('markdown');
},
})
@@ -228,6 +252,8 @@ export function useRegisterBlocksuiteEditorCommands() {
icon: mode === 'page' ? : ,
label: t['com.affine.moveToTrash.title'](),
run() {
+ track.$.cmdk.editor.deleteDoc();
+
onClickDelete(doc.title$.value);
},
})
@@ -242,6 +268,8 @@ export function useRegisterBlocksuiteEditorCommands() {
icon: mode === 'page' ? : ,
label: t['com.affine.cmdk.affine.editor.restore-from-trash'](),
run() {
+ track.$.cmdk.editor.restoreDoc();
+
doc.restoreFromTrash();
},
})
@@ -255,6 +283,8 @@ export function useRegisterBlocksuiteEditorCommands() {
icon: ,
label: t['com.affine.cmdk.affine.editor.reveal-page-history-modal'](),
run() {
+ track.$.cmdk.docHistory.open();
+
openHistoryModal();
},
})
diff --git a/packages/frontend/core/src/hooks/affine/use-register-copy-link-commands.tsx b/packages/frontend/core/src/hooks/affine/use-register-copy-link-commands.tsx
index ca1912344f..a40ccfec76 100644
--- a/packages/frontend/core/src/hooks/affine/use-register-copy-link-commands.tsx
+++ b/packages/frontend/core/src/hooks/affine/use-register-copy-link-commands.tsx
@@ -3,9 +3,10 @@ import {
registerAffineCommand,
} from '@affine/core/commands';
import { useSharingUrl } from '@affine/core/hooks/affine/use-share-url';
+import { track } from '@affine/core/mixpanel';
import { useIsActiveView } from '@affine/core/modules/workbench';
import { WorkspaceFlavour } from '@affine/env/workspace';
-import type { WorkspaceMetadata } from '@toeverything/infra';
+import { type WorkspaceMetadata } from '@toeverything/infra';
import { useEffect } from 'react';
export function useRegisterCopyLinkCommands({
@@ -38,6 +39,8 @@ export function useRegisterCopyLinkCommands({
label: '',
icon: null,
run() {
+ track.$.cmdk.general.copyShareLink({ type: 'private' });
+
isActiveView && isCloud && onClickCopyLink();
},
})
diff --git a/packages/frontend/core/src/hooks/affine/use-register-find-in-page-commands.ts b/packages/frontend/core/src/hooks/affine/use-register-find-in-page-commands.ts
index dbca1c48c7..5c0751d8e5 100644
--- a/packages/frontend/core/src/hooks/affine/use-register-find-in-page-commands.ts
+++ b/packages/frontend/core/src/hooks/affine/use-register-find-in-page-commands.ts
@@ -2,6 +2,7 @@ import {
PreconditionStrategy,
registerAffineCommand,
} from '@affine/core/commands';
+import { track } from '@affine/core/mixpanel';
import { FindInPageService } from '@affine/core/modules/find-in-page/services/find-in-page';
import { useService } from '@toeverything/infra';
import { useCallback, useEffect } from 'react';
@@ -24,13 +25,15 @@ export function useRegisterFindInPageCommands() {
unsubs.push(
registerAffineCommand({
preconditionStrategy: PreconditionStrategy.Never,
- id: `editor:find-in-page`,
+ id: `affine:find-in-page`,
keyBinding: {
binding: '$mod+f',
},
icon: null,
label: '',
run() {
+ track.$.cmdk.general.findInPage();
+
toggleVisible();
},
})
diff --git a/packages/frontend/core/src/mixpanel/events.ts b/packages/frontend/core/src/mixpanel/events.ts
index cc40f95389..df79c8abf8 100644
--- a/packages/frontend/core/src/mixpanel/events.ts
+++ b/packages/frontend/core/src/mixpanel/events.ts
@@ -2,21 +2,26 @@
/* eslint-disable rxjs/finnish */
// SECTION: app events
-type GeneralEvents = 'openMigrationDataHelp' | 'export';
-type CmdkEvents = 'quickSearch';
+type GeneralEvents = 'openMigrationDataHelp';
+type CmdkEvents = 'quickSearch' | 'recentDocs' | 'searchResultsDocs';
type AppEvents =
| 'checkUpdates'
| 'downloadUpdate'
| 'downloadApp'
| 'quitAndInstall'
| 'openChangelog'
- | 'dismissChangelog';
+ | 'dismissChangelog'
+ | 'contactUs'
+ | 'findInPage';
type NavigationEvents =
| 'openInNewTab'
| 'openInSplitView'
| 'switchTab'
| 'switchSplitView'
| 'navigate'
+ | 'goBack'
+ | 'goForward'
+ | 'toggle' // toggle navigation panel
| 'open'
| 'close'; // openclose modal/diaglog
@@ -35,6 +40,7 @@ type DocEvents =
| 'renameDoc'
| 'linkDoc'
| 'deleteDoc'
+ | 'restoreDoc'
| 'switchPageMode'
| 'openDocOptionsMenu'
| 'openDocInfo';
@@ -61,7 +67,6 @@ type FolderEvents =
| 'deleteFolder';
type TagEvents = 'createTag' | 'deleteTag' | 'renameTag' | 'tagDoc';
type FavoriteEvents = 'toggleFavorite';
-type DocInfoEvents = 'toggle' | 'open';
type OrganizeItemEvents = // doc, link, folder, collection, tag
| 'createOrganizeItem'
@@ -111,8 +116,7 @@ type UserEvents =
| ShareEvents
| AuthEvents
| AccountEvents
- | PaymentEvents
- | DocInfoEvents;
+ | PaymentEvents;
interface PageDivision {
[page: string]: {
@@ -161,11 +165,28 @@ const PageEvents = {
about: ['checkUpdates', 'downloadUpdate', 'changeAppSetting'],
},
cmdk: {
- $: ['createDoc'],
+ recent: ['recentDocs'],
+ results: ['searchResultsDocs'],
+ general: ['copyShareLink', 'goBack', 'goForward', 'findInPage'],
+ creation: ['createDoc'],
+ workspace: ['createWorkspace'],
settings: ['openSettings', 'changeAppSetting'],
+ navigation: ['navigate'],
+ editor: [
+ 'toggleFavorite',
+ 'switchPageMode',
+ 'createDoc',
+ 'export',
+ 'deleteDoc',
+ 'restoreDoc',
+ ],
+ docInfo: ['open'],
+ docHistory: ['open'],
+ updates: ['quitAndInstall'],
+ help: ['contactUs', 'openChangelog'],
},
navigationPanel: {
- $: ['quickSearch', 'createDoc', 'navigate', 'openSettings'],
+ $: ['quickSearch', 'createDoc', 'navigate', 'openSettings', 'toggle'],
organize: [
'createOrganizeItem',
'renameOrganizeItem',
diff --git a/packages/frontend/core/src/modules/navigation/view/use-register-navigation-commands.ts b/packages/frontend/core/src/modules/navigation/view/use-register-navigation-commands.ts
index c349fed65d..32307240b1 100644
--- a/packages/frontend/core/src/modules/navigation/view/use-register-navigation-commands.ts
+++ b/packages/frontend/core/src/modules/navigation/view/use-register-navigation-commands.ts
@@ -2,6 +2,7 @@ import {
PreconditionStrategy,
registerAffineCommand,
} from '@affine/core/commands';
+import { track } from '@affine/core/mixpanel';
import { useService } from '@toeverything/infra';
import { useEffect } from 'react';
@@ -23,6 +24,8 @@ export function useRegisterNavigationCommands() {
binding: '$mod+[',
},
run() {
+ track.$.cmdk.general.goBack();
+
navigator.back();
},
})
@@ -38,6 +41,8 @@ export function useRegisterNavigationCommands() {
binding: '$mod+]',
},
run() {
+ track.$.cmdk.general.goForward();
+
navigator.forward();
},
})
diff --git a/packages/frontend/core/src/modules/quicksearch/services/cmdk.ts b/packages/frontend/core/src/modules/quicksearch/services/cmdk.ts
index 548ed5875f..2c7097088c 100644
--- a/packages/frontend/core/src/modules/quicksearch/services/cmdk.ts
+++ b/packages/frontend/core/src/modules/quicksearch/services/cmdk.ts
@@ -1,3 +1,4 @@
+import { track } from '@affine/core/mixpanel';
import type { DocsService } from '@toeverything/infra';
import { Service } from '@toeverything/infra';
@@ -47,6 +48,10 @@ export class CMDKQuickSearchService extends Service {
blockId?: string;
} = result.payload;
+ result.source === 'recent-doc' && track.$.cmdk.recent.recentDocs();
+ result.source === 'docs' &&
+ track.$.cmdk.results.searchResultsDocs();
+
this.workbenchService.workbench.openDoc({
docId: doc.docId,
blockId: doc.blockId,