diff --git a/blocksuite/affine/shared/src/services/telemetry-service/slash-menu.ts b/blocksuite/affine/shared/src/services/telemetry-service/slash-menu.ts new file mode 100644 index 0000000000..ef01366773 --- /dev/null +++ b/blocksuite/affine/shared/src/services/telemetry-service/slash-menu.ts @@ -0,0 +1,5 @@ +import type { TelemetryEvent } from './types.js'; + +export type SlashMenuEventType = 'OpenSlashMenu' | 'SelectSlashMenuItem'; + +export type SlashMenuEvents = Record; diff --git a/blocksuite/affine/shared/src/services/telemetry-service/telemetry-service.ts b/blocksuite/affine/shared/src/services/telemetry-service/telemetry-service.ts index e30b4fd6dd..5092ac7764 100644 --- a/blocksuite/affine/shared/src/services/telemetry-service/telemetry-service.ts +++ b/blocksuite/affine/shared/src/services/telemetry-service/telemetry-service.ts @@ -3,6 +3,7 @@ import { createIdentifier } from '@blocksuite/global/di'; import type { OutDatabaseAllEvents } from './database.js'; import type { LinkToolbarEvents } from './link.js'; import type { NoteEvents } from './note.js'; +import type { SlashMenuEvents } from './slash-menu.js'; import type { AttachmentUploadedEvent, BlockCreationEvent, @@ -18,6 +19,7 @@ import type { export type TelemetryEventMap = OutDatabaseAllEvents & LinkToolbarEvents & + SlashMenuEvents & NoteEvents & { DocCreated: DocCreatedEvent; Link: TelemetryEvent; diff --git a/blocksuite/affine/widgets/widget-slash-menu/src/slash-menu-popover.ts b/blocksuite/affine/widgets/widget-slash-menu/src/slash-menu-popover.ts index 7c426e084f..48b8504753 100644 --- a/blocksuite/affine/widgets/widget-slash-menu/src/slash-menu-popover.ts +++ b/blocksuite/affine/widgets/widget-slash-menu/src/slash-menu-popover.ts @@ -4,6 +4,10 @@ import { getInlineEditorByModel, getTextContentFromInlineRange, } from '@blocksuite/affine-rich-text'; +import { + DocModeProvider, + TelemetryProvider, +} from '@blocksuite/affine-shared/services'; import type { AffineInlineEditor } from '@blocksuite/affine-shared/types'; import { createKeydownObserver, @@ -42,7 +46,6 @@ import { parseGroup, slashItemClassName, } from './utils.js'; - type InnerSlashMenuContext = SlashMenuContext & { onClickItem: (item: SlashMenuActionItem) => void; searching: boolean; @@ -51,6 +54,14 @@ type InnerSlashMenuContext = SlashMenuContext & { export class SlashMenu extends WithDisposable(LitElement) { static override styles = styles; + private get _telemetry() { + return this.context.std.getOptional(TelemetryProvider); + } + + private get _editorMode() { + return this.context.std.get(DocModeProvider).getEditorMode(); + } + private readonly _handleClickItem = (item: SlashMenuActionItem) => { // Need to remove the search string // We must to do clean the slash string before we do the action @@ -64,6 +75,15 @@ export class SlashMenu extends WithDisposable(LitElement) { .waitForUpdate() .then(() => { item.action(this.context); + this._telemetry?.track('SelectSlashMenuItem', { + page: this._editorMode ?? undefined, + segment: + this.context.model.flavour === 'affine:edgeless-text' + ? 'edgeless-text' + : 'doc', + module: 'slash menu', + control: item.name, + }); this.abortController.abort(); }) .catch(console.error); @@ -263,6 +283,12 @@ export class SlashMenu extends WithDisposable(LitElement) { }, onAbort: () => this.abortController.abort(), }); + + this._telemetry?.track('OpenSlashMenu', { + page: this._editorMode ?? undefined, + type: this.context.model.flavour.split(':').pop(), + module: 'slash menu', + }); } protected override willUpdate() {