Basic threads analytics into Posthog MVP (#7871)

This commit is contained in:
Michael Telatynski 2022-02-28 14:11:14 +00:00 committed by GitHub
parent 182aedc3d4
commit 75e41b4c1c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 51 additions and 18 deletions

View file

@ -38,6 +38,8 @@ import TimelinePanel from './TimelinePanel';
import { Layout } from '../../settings/enums/Layout';
import { RoomPermalinkCreator } from '../../utils/permalinks/Permalinks';
import Measured from '../views/elements/Measured';
import PosthogTrackers from "../../PosthogTrackers";
import { ButtonEvent } from "../views/elements/AccessibleButton";
export async function getThreadTimelineSet(
client: MatrixClient,
@ -178,7 +180,15 @@ export const ThreadPanelHeader = ({ filterOption, setFilterOption, empty }: {
return <div className="mx_ThreadPanel__header">
<span>{ _t("Threads") }</span>
{ !empty && <>
<ContextMenuButton className="mx_ThreadPanel_dropdown" inputRef={button} isExpanded={menuDisplayed} onClick={() => menuDisplayed ? closeMenu() : openMenu()}>
<ContextMenuButton
className="mx_ThreadPanel_dropdown"
inputRef={button}
isExpanded={menuDisplayed}
onClick={(ev: ButtonEvent) => {
openMenu();
PosthogTrackers.trackInteraction("WebRightPanelThreadPanelFilterDropdown", ev);
}}
>
{ `${_t('Show:')} ${value.label}` }
</ContextMenuButton>
{ contextMenu }

View file

@ -50,6 +50,8 @@ import FileDropTarget from "./FileDropTarget";
import { getKeyBindingsManager } from "../../KeyBindingsManager";
import { KeyBindingAction } from "../../accessibility/KeyboardShortcuts";
import Measured from '../views/elements/Measured';
import PosthogTrackers from "../../PosthogTrackers";
import { ButtonEvent } from "../views/elements/AccessibleButton";
interface IProps {
room: Room;
@ -321,6 +323,9 @@ export default class ThreadView extends React.Component<IProps, IState> {
header={this.renderThreadViewHeader()}
ref={this.card}
onKeyDown={this.onKeyDown}
onBack={(ev: ButtonEvent) => {
PosthogTrackers.trackInteraction("WebThreadViewBackButton", ev);
}}
>
<Measured
sensor={this.card.current}

View file

@ -24,12 +24,13 @@ import classNames from 'classnames';
import Analytics from '../../../Analytics';
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
import { replaceableComponent } from "../../../utils/replaceableComponent";
import { ButtonEvent } from "../elements/AccessibleButton";
interface IProps {
// Whether this button is highlighted
isHighlighted: boolean;
// click handler
onClick: () => void;
onClick: (ev: ButtonEvent) => void;
// The parameters to track the click event
analytics: Parameters<typeof Analytics.trackEvent>;
@ -42,9 +43,9 @@ interface IProps {
// TODO: replace this, the composer buttons and the right panel buttons with a unified representation
@replaceableComponent("views.right_panel.HeaderButton")
export default class HeaderButton extends React.Component<IProps> {
private onClick = () => {
private onClick = (ev: ButtonEvent) => {
Analytics.trackEvent(...this.props.analytics);
this.props.onClick();
this.props.onClick(ev);
};
public render() {

View file

@ -38,6 +38,8 @@ import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNo
import { NotificationColor } from "../../../stores/notifications/NotificationColor";
import { ThreadsRoomNotificationState } from "../../../stores/notifications/ThreadsRoomNotificationState";
import { NotificationStateEvents } from "../../../stores/notifications/NotificationState";
import PosthogTrackers from "../../../PosthogTrackers";
import { ButtonEvent } from "../elements/AccessibleButton";
const ROOM_INFO_PHASES = [
RightPanelPhases.RoomSummary,
@ -207,11 +209,12 @@ export default class RoomHeaderButtons extends HeaderButtons<IProps> {
this.setPhase(RightPanelPhases.Timeline);
};
private onThreadsPanelClicked = () => {
private onThreadsPanelClicked = (ev: ButtonEvent) => {
if (RoomHeaderButtons.THREAD_PHASES.includes(this.state.phase)) {
RightPanelStore.instance.togglePanel();
} else {
showThreadPanel();
PosthogTrackers.trackInteraction("WebRoomHeaderButtonsThreadsButton", ev);
}
};

View file

@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { createRef } from 'react';
import React, { createRef, MouseEvent } from 'react';
import classNames from "classnames";
import { EventType, MsgType, RelationType } from "matrix-js-sdk/src/@types/event";
import { EventStatus, MatrixEvent, MatrixEventEvent } from "matrix-js-sdk/src/models/event";
@ -81,6 +81,7 @@ import { DecryptionFailureTracker } from '../../../DecryptionFailureTracker';
import RedactedBody from '../messages/RedactedBody';
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
import { shouldDisplayReply } from '../../../utils/Reply';
import PosthogTrackers from "../../../PosthogTrackers";
export type GetRelationsForEvent = (eventId: string, relationType: string, eventType: string) => Relations;
@ -684,17 +685,19 @@ export default class EventTile extends React.Component<IProps, IState> {
return (
<CardContext.Consumer>
{ context =>
<div
<AccessibleButton
className="mx_ThreadInfo"
onClick={() => {
onClick={(ev: ButtonEvent) => {
showThread({ rootEvent: this.props.mxEvent, push: context.isCard });
PosthogTrackers.trackInteraction("WebRoomTimelineThreadSummaryButton", ev);
}}
aria-label={_t("Open thread")}
>
<span className="mx_ThreadInfo_threads-amount">
{ count }
</span>
{ this.renderThreadLastMessagePreview() }
</div>
</AccessibleButton>
}
</CardContext.Consumer>
);
@ -1507,7 +1510,12 @@ export default class EventTile extends React.Component<IProps, IState> {
"data-notification": this.state.threadNotification,
"onMouseEnter": () => this.setState({ hover: true }),
"onMouseLeave": () => this.setState({ hover: false }),
"onClick": () => showThread({ rootEvent: this.props.mxEvent, push: true }),
"onClick": (ev: MouseEvent) => {
showThread({ rootEvent: this.props.mxEvent, push: true });
const target = ev.currentTarget as HTMLElement;
const index = Array.from(target.parentElement.children).indexOf(target);
PosthogTrackers.trackInteraction("WebThreadsPanelThreadItem", ev, index);
},
}, <>
{ sender }
{ avatar }

View file

@ -345,12 +345,17 @@ export class SendMessageComposer extends React.Component<ISendMessageComposerPro
return;
}
PosthogAnalytics.instance.trackEvent<ComposerEvent>({
const posthogEvent: ComposerEvent = {
eventName: "Composer",
isEditing: false,
inThread: this.props.relation?.rel_type === RelationType.Thread,
isReply: !!this.props.replyToEvent,
});
inThread: this.props.relation?.rel_type === RelationType.Thread,
};
if (posthogEvent.inThread) {
const threadRoot = this.props.room.findEventById(this.props.relation.event_id);
posthogEvent.startsThread = threadRoot?.getThread()?.events.length === 1;
}
PosthogAnalytics.instance.trackEvent<ComposerEvent>(posthogEvent);
// Replace emoticon at the end of the message
if (SettingsStore.getValue('MessageComposerInput.autoReplaceEmoji')) {