mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-17 14:27:02 +08:00
chore(core): add event tracking for attachments (#9198)
Part of: [AF-1678](https://linear.app/affine-design/issue/AF-1678/添加埋点)
This commit is contained in:
@@ -17,6 +17,7 @@ import {
|
|||||||
Scroller,
|
Scroller,
|
||||||
ScrollSeekPlaceholder,
|
ScrollSeekPlaceholder,
|
||||||
} from '@affine/core/modules/pdf/views';
|
} from '@affine/core/modules/pdf/views';
|
||||||
|
import track from '@affine/track';
|
||||||
import type { AttachmentBlockModel } from '@blocksuite/affine/blocks';
|
import type { AttachmentBlockModel } from '@blocksuite/affine/blocks';
|
||||||
import { CollapseIcon, ExpandIcon } from '@blocksuite/icons/rc';
|
import { CollapseIcon, ExpandIcon } from '@blocksuite/icons/rc';
|
||||||
import { useLiveData, useService } from '@toeverything/infra';
|
import { useLiveData, useService } from '@toeverything/infra';
|
||||||
@@ -202,6 +203,12 @@ const PDFViewerInner = ({ pdf, state }: PDFViewerInnerProps) => {
|
|||||||
function PDFViewerStatus({ pdf }: { pdf: PDF }) {
|
function PDFViewerStatus({ pdf }: { pdf: PDF }) {
|
||||||
const state = useLiveData(pdf.state$);
|
const state = useLiveData(pdf.state$);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (state.status !== PDFStatus.Error) return;
|
||||||
|
|
||||||
|
track.$.attachment.$.openPDFRendererFail();
|
||||||
|
}, [state]);
|
||||||
|
|
||||||
if (state?.status !== PDFStatus.Opened) {
|
if (state?.status !== PDFStatus.Opened) {
|
||||||
return <LoadingSvg />;
|
return <LoadingSvg />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export type ImagePeekViewInfo = {
|
|||||||
|
|
||||||
export type AttachmentPeekViewInfo = {
|
export type AttachmentPeekViewInfo = {
|
||||||
type: 'attachment';
|
type: 'attachment';
|
||||||
docRef: DocReferenceInfo;
|
docRef: DocReferenceInfo & { filetype?: string };
|
||||||
};
|
};
|
||||||
|
|
||||||
export type AIChatBlockPeekViewInfo = {
|
export type AIChatBlockPeekViewInfo = {
|
||||||
@@ -173,6 +173,7 @@ function resolvePeekInfoFromPeekTarget(
|
|||||||
docRef: {
|
docRef: {
|
||||||
docId: blockModel.doc.id,
|
docId: blockModel.doc.id,
|
||||||
blockIds: [blockModel.id],
|
blockIds: [blockModel.id],
|
||||||
|
filetype: blockModel.type,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
} else if (isImageBlockModel(blockModel)) {
|
} else if (isImageBlockModel(blockModel)) {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { IconButton } from '@affine/component';
|
import { IconButton } from '@affine/component';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
|
import track from '@affine/track';
|
||||||
import type { DocMode } from '@blocksuite/affine/blocks';
|
import type { DocMode } from '@blocksuite/affine/blocks';
|
||||||
import {
|
import {
|
||||||
CloseIcon,
|
CloseIcon,
|
||||||
@@ -16,12 +17,16 @@ import {
|
|||||||
type ReactElement,
|
type ReactElement,
|
||||||
type SVGAttributes,
|
type SVGAttributes,
|
||||||
useCallback,
|
useCallback,
|
||||||
|
useEffect,
|
||||||
useMemo,
|
useMemo,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
|
|
||||||
import { WorkspaceDialogService } from '../../dialogs';
|
import { WorkspaceDialogService } from '../../dialogs';
|
||||||
import { WorkbenchService } from '../../workbench';
|
import { WorkbenchService } from '../../workbench';
|
||||||
import type { DocReferenceInfo } from '../entities/peek-view';
|
import type {
|
||||||
|
AttachmentPeekViewInfo,
|
||||||
|
DocReferenceInfo,
|
||||||
|
} from '../entities/peek-view';
|
||||||
import { PeekViewService } from '../services/peek-view';
|
import { PeekViewService } from '../services/peek-view';
|
||||||
import * as styles from './peek-view-controls.css';
|
import * as styles from './peek-view-controls.css';
|
||||||
|
|
||||||
@@ -154,33 +159,44 @@ export const DocPeekViewControls = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type AttachmentPeekViewControls = HTMLAttributes<HTMLDivElement> & {
|
||||||
|
mode?: DocMode;
|
||||||
|
docRef: AttachmentPeekViewInfo['docRef'];
|
||||||
|
};
|
||||||
|
|
||||||
export const AttachmentPeekViewControls = ({
|
export const AttachmentPeekViewControls = ({
|
||||||
docRef,
|
docRef,
|
||||||
className,
|
className,
|
||||||
...rest
|
...rest
|
||||||
}: DocPeekViewControlsProps) => {
|
}: AttachmentPeekViewControls) => {
|
||||||
|
const { docId, blockIds: [blockId] = [], filetype: type } = docRef;
|
||||||
const peekView = useService(PeekViewService).peekView;
|
const peekView = useService(PeekViewService).peekView;
|
||||||
const workbench = useService(WorkbenchService).workbench;
|
const workbench = useService(WorkbenchService).workbench;
|
||||||
const t = useI18n();
|
const t = useI18n();
|
||||||
|
|
||||||
const controls = useMemo(() => {
|
const controls = useMemo(() => {
|
||||||
return [
|
const controls = [
|
||||||
{
|
{
|
||||||
icon: <CloseIcon />,
|
icon: <CloseIcon />,
|
||||||
nameKey: 'close',
|
nameKey: 'close',
|
||||||
name: t['com.affine.peek-view-controls.close'](),
|
name: t['com.affine.peek-view-controls.close'](),
|
||||||
onClick: () => peekView.close(),
|
onClick: () => peekView.close(),
|
||||||
},
|
},
|
||||||
|
];
|
||||||
|
if (!type) return controls;
|
||||||
|
|
||||||
|
return [
|
||||||
|
...controls,
|
||||||
// TODO(@fundon): needs to be implemented on mobile
|
// TODO(@fundon): needs to be implemented on mobile
|
||||||
BUILD_CONFIG.isDesktopEdition && {
|
BUILD_CONFIG.isDesktopEdition && {
|
||||||
icon: <ExpandFullIcon />,
|
icon: <ExpandFullIcon />,
|
||||||
name: t['com.affine.peek-view-controls.open-attachment'](),
|
name: t['com.affine.peek-view-controls.open-attachment'](),
|
||||||
nameKey: 'open',
|
nameKey: 'open',
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
const { docId, blockIds: [blockId] = [] } = docRef;
|
workbench.openAttachment(docId, blockId);
|
||||||
if (docId && blockId) {
|
|
||||||
workbench.openAttachment(docId, blockId);
|
|
||||||
}
|
|
||||||
peekView.close(false);
|
peekView.close(false);
|
||||||
|
|
||||||
|
track.$.attachment.$.openAttachmentInFullscreen({ type });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -188,11 +204,10 @@ export const AttachmentPeekViewControls = ({
|
|||||||
nameKey: 'new-tab',
|
nameKey: 'new-tab',
|
||||||
name: t['com.affine.peek-view-controls.open-attachment-in-new-tab'](),
|
name: t['com.affine.peek-view-controls.open-attachment-in-new-tab'](),
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
const { docId, blockIds: [blockId] = [] } = docRef;
|
workbench.openAttachment(docId, blockId, { at: 'new-tab' });
|
||||||
if (docId && blockId) {
|
|
||||||
workbench.openAttachment(docId, blockId, { at: 'new-tab' });
|
|
||||||
}
|
|
||||||
peekView.close(false);
|
peekView.close(false);
|
||||||
|
|
||||||
|
track.$.attachment.$.openAttachmentInNewTab({ type });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
BUILD_CONFIG.isElectron && {
|
BUILD_CONFIG.isElectron && {
|
||||||
@@ -202,15 +217,21 @@ export const AttachmentPeekViewControls = ({
|
|||||||
'com.affine.peek-view-controls.open-attachment-in-split-view'
|
'com.affine.peek-view-controls.open-attachment-in-split-view'
|
||||||
](),
|
](),
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
const { docId, blockIds: [blockId] = [] } = docRef;
|
workbench.openAttachment(docId, blockId, { at: 'beside' });
|
||||||
if (docId && blockId) {
|
|
||||||
workbench.openAttachment(docId, blockId, { at: 'beside' });
|
|
||||||
}
|
|
||||||
peekView.close(false);
|
peekView.close(false);
|
||||||
|
|
||||||
|
track.$.attachment.$.openAttachmentInSplitView({ type });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
].filter((opt): opt is ControlButtonProps => Boolean(opt));
|
].filter((opt): opt is ControlButtonProps => Boolean(opt));
|
||||||
}, [t, peekView, workbench, docRef]);
|
}, [t, peekView, workbench, docId, blockId, type]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (type === undefined) return;
|
||||||
|
|
||||||
|
track.$.attachment.$.openAttachmentInPeekView({ type });
|
||||||
|
}, [type]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div {...rest} className={clsx(styles.root, className)}>
|
<div {...rest} className={clsx(styles.root, className)}>
|
||||||
{controls.map(option => (
|
{controls.map(option => (
|
||||||
|
|||||||
@@ -116,6 +116,15 @@ type PaymentEvents =
|
|||||||
| 'confirmResumingSubscription';
|
| 'confirmResumingSubscription';
|
||||||
// END SECTION
|
// END SECTION
|
||||||
|
|
||||||
|
// SECTION: attachment
|
||||||
|
type AttachmentEvents =
|
||||||
|
| 'openAttachmentInFullscreen'
|
||||||
|
| 'openAttachmentInNewTab'
|
||||||
|
| 'openAttachmentInPeekView'
|
||||||
|
| 'openAttachmentInSplitView'
|
||||||
|
| 'openPDFRendererFail';
|
||||||
|
// END SECTION
|
||||||
|
|
||||||
type UserEvents =
|
type UserEvents =
|
||||||
| GeneralEvents
|
| GeneralEvents
|
||||||
| AppEvents
|
| AppEvents
|
||||||
@@ -130,7 +139,8 @@ type UserEvents =
|
|||||||
| AuthEvents
|
| AuthEvents
|
||||||
| AccountEvents
|
| AccountEvents
|
||||||
| PaymentEvents
|
| PaymentEvents
|
||||||
| DNDEvents;
|
| DNDEvents
|
||||||
|
| AttachmentEvents;
|
||||||
interface PageDivision {
|
interface PageDivision {
|
||||||
[page: string]: {
|
[page: string]: {
|
||||||
[segment: string]: {
|
[segment: string]: {
|
||||||
@@ -284,6 +294,15 @@ const PageEvents = {
|
|||||||
importModal: ['open'],
|
importModal: ['open'],
|
||||||
snapshot: ['import', 'export'],
|
snapshot: ['import', 'export'],
|
||||||
},
|
},
|
||||||
|
attachment: {
|
||||||
|
$: [
|
||||||
|
'openAttachmentInFullscreen',
|
||||||
|
'openAttachmentInNewTab',
|
||||||
|
'openAttachmentInPeekView',
|
||||||
|
'openAttachmentInSplitView',
|
||||||
|
'openPDFRendererFail',
|
||||||
|
],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
doc: {
|
doc: {
|
||||||
editor: {
|
editor: {
|
||||||
@@ -353,6 +372,10 @@ type PaymentEventArgs = {
|
|||||||
recurring: string;
|
recurring: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type AttachmentEventArgs = {
|
||||||
|
type: string; // file type
|
||||||
|
};
|
||||||
|
|
||||||
type TabActionControlType =
|
type TabActionControlType =
|
||||||
| 'click'
|
| 'click'
|
||||||
| 'dnd'
|
| 'dnd'
|
||||||
@@ -435,6 +458,10 @@ export type EventArgs = {
|
|||||||
linkDoc: { type: string; journal: boolean };
|
linkDoc: { type: string; journal: boolean };
|
||||||
drop: { type: string };
|
drop: { type: string };
|
||||||
dragStart: { type: string };
|
dragStart: { type: string };
|
||||||
|
openAttachmentInFullscreen: AttachmentEventArgs;
|
||||||
|
openAttachmentInNewTab: AttachmentEventArgs;
|
||||||
|
openAttachmentInPeekView: AttachmentEventArgs;
|
||||||
|
openAttachmentInSplitView: AttachmentEventArgs;
|
||||||
};
|
};
|
||||||
|
|
||||||
// for type checking
|
// for type checking
|
||||||
|
|||||||
Reference in New Issue
Block a user