Add analytics event for pinned messages
This commit is contained in:
parent
bce710e34e
commit
08d1b6ceae
8 changed files with 48 additions and 8 deletions
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
import { PureComponent, SyntheticEvent } from "react";
|
import { PureComponent, SyntheticEvent } from "react";
|
||||||
import { WebScreen as ScreenEvent } from "@matrix-org/analytics-events/types/typescript/WebScreen";
|
import { WebScreen as ScreenEvent } from "@matrix-org/analytics-events/types/typescript/WebScreen";
|
||||||
import { Interaction as InteractionEvent } from "@matrix-org/analytics-events/types/typescript/Interaction";
|
import { Interaction as InteractionEvent } from "@matrix-org/analytics-events/types/typescript/Interaction";
|
||||||
|
import { PinUnpinAction } from "@matrix-org/analytics-events/types/typescript/PinUnpinAction";
|
||||||
|
|
||||||
import PageType from "./PageTypes";
|
import PageType from "./PageTypes";
|
||||||
import Views from "./Views";
|
import Views from "./Views";
|
||||||
|
@ -106,6 +107,19 @@ export default class PosthogTrackers {
|
||||||
name,
|
name,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Track a pin or unpin action on a message.
|
||||||
|
* @param kind - Is pin or unpin.
|
||||||
|
* @param from - From where the action is triggered.
|
||||||
|
*/
|
||||||
|
public static trackPinUnpinMessage(kind: PinUnpinAction["kind"], from: PinUnpinAction["from"]): void {
|
||||||
|
PosthogAnalytics.instance.trackEvent<PinUnpinAction>({
|
||||||
|
eventName: "PinUnpinAction",
|
||||||
|
kind,
|
||||||
|
from,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PosthogScreenTracker extends PureComponent<{ screenName: ScreenName }> {
|
export class PosthogScreenTracker extends PureComponent<{ screenName: ScreenName }> {
|
||||||
|
|
|
@ -40,12 +40,13 @@ import { WIDGET_LAYOUT_EVENT_TYPE } from "./stores/widgets/WidgetLayoutStore";
|
||||||
import { RightPanelPhases } from "./stores/right-panel/RightPanelStorePhases";
|
import { RightPanelPhases } from "./stores/right-panel/RightPanelStorePhases";
|
||||||
import defaultDispatcher from "./dispatcher/dispatcher";
|
import defaultDispatcher from "./dispatcher/dispatcher";
|
||||||
import { RoomSettingsTab } from "./components/views/dialogs/RoomSettingsDialog";
|
import { RoomSettingsTab } from "./components/views/dialogs/RoomSettingsDialog";
|
||||||
import AccessibleButton, { ButtonEvent } from "./components/views/elements/AccessibleButton";
|
import AccessibleButton from "./components/views/elements/AccessibleButton";
|
||||||
import RightPanelStore from "./stores/right-panel/RightPanelStore";
|
import RightPanelStore from "./stores/right-panel/RightPanelStore";
|
||||||
import { highlightEvent, isLocationEvent } from "./utils/EventUtils";
|
import { highlightEvent, isLocationEvent } from "./utils/EventUtils";
|
||||||
import { ElementCall } from "./models/Call";
|
import { ElementCall } from "./models/Call";
|
||||||
import { textForVoiceBroadcastStoppedEvent, VoiceBroadcastInfoEventType } from "./voice-broadcast";
|
import { textForVoiceBroadcastStoppedEvent, VoiceBroadcastInfoEventType } from "./voice-broadcast";
|
||||||
import { getSenderName } from "./utils/event/getSenderName";
|
import { getSenderName } from "./utils/event/getSenderName";
|
||||||
|
import PosthogTrackers from "./PosthogTrackers.ts";
|
||||||
|
|
||||||
function getRoomMemberDisplayname(client: MatrixClient, event: MatrixEvent, userId = event.getSender()): string {
|
function getRoomMemberDisplayname(client: MatrixClient, event: MatrixEvent, userId = event.getSender()): string {
|
||||||
const roomId = event.getRoomId();
|
const roomId = event.getRoomId();
|
||||||
|
@ -563,6 +564,7 @@ function textForPowerEvent(event: MatrixEvent, client: MatrixClient): (() => str
|
||||||
}
|
}
|
||||||
|
|
||||||
const onPinnedMessagesClick = (): void => {
|
const onPinnedMessagesClick = (): void => {
|
||||||
|
PosthogTrackers.trackInteraction("PinnedMessageStateEventClick");
|
||||||
RightPanelStore.instance.setCard({ phase: RightPanelPhases.PinnedMessages }, false);
|
RightPanelStore.instance.setCard({ phase: RightPanelPhases.PinnedMessages }, false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -590,7 +592,10 @@ function textForPinnedEvent(event: MatrixEvent, client: MatrixClient, allowJSX:
|
||||||
a: (sub) => (
|
a: (sub) => (
|
||||||
<AccessibleButton
|
<AccessibleButton
|
||||||
kind="link_inline"
|
kind="link_inline"
|
||||||
onClick={(e: ButtonEvent) => highlightEvent(roomId, messageId)}
|
onClick={() => {
|
||||||
|
PosthogTrackers.trackInteraction("PinnedMessageStateEventClick");
|
||||||
|
highlightEvent(roomId, messageId);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{sub}
|
{sub}
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
|
@ -623,7 +628,10 @@ function textForPinnedEvent(event: MatrixEvent, client: MatrixClient, allowJSX:
|
||||||
a: (sub) => (
|
a: (sub) => (
|
||||||
<AccessibleButton
|
<AccessibleButton
|
||||||
kind="link_inline"
|
kind="link_inline"
|
||||||
onClick={(e: ButtonEvent) => highlightEvent(roomId, messageId)}
|
onClick={() => {
|
||||||
|
PosthogTrackers.trackInteraction("PinnedMessageStateEventClick");
|
||||||
|
highlightEvent(roomId, messageId);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{sub}
|
{sub}
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
|
|
|
@ -60,6 +60,7 @@ import { getShareableLocationEvent } from "../../../events/location/getShareable
|
||||||
import { ShowThreadPayload } from "../../../dispatcher/payloads/ShowThreadPayload";
|
import { ShowThreadPayload } from "../../../dispatcher/payloads/ShowThreadPayload";
|
||||||
import { CardContext } from "../right_panel/context";
|
import { CardContext } from "../right_panel/context";
|
||||||
import PinningUtils from "../../../utils/PinningUtils";
|
import PinningUtils from "../../../utils/PinningUtils";
|
||||||
|
import PosthogTrackers from "../../../PosthogTrackers.ts";
|
||||||
|
|
||||||
interface IReplyInThreadButton {
|
interface IReplyInThreadButton {
|
||||||
mxEvent: MatrixEvent;
|
mxEvent: MatrixEvent;
|
||||||
|
@ -243,9 +244,11 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
||||||
this.closeMenu();
|
this.closeMenu();
|
||||||
};
|
};
|
||||||
|
|
||||||
private onPinClick = (): void => {
|
private onPinClick = (isPinned: boolean): void => {
|
||||||
// Pin or unpin in background
|
// Pin or unpin in background
|
||||||
PinningUtils.pinOrUnpinEvent(MatrixClientPeg.safeGet(), this.props.mxEvent);
|
PinningUtils.pinOrUnpinEvent(MatrixClientPeg.safeGet(), this.props.mxEvent);
|
||||||
|
PosthogTrackers.trackPinUnpinMessage(isPinned ? "Pin" : "Unpin", "Timeline");
|
||||||
|
|
||||||
this.closeMenu();
|
this.closeMenu();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -618,7 +621,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
||||||
<IconizedContextMenuOption
|
<IconizedContextMenuOption
|
||||||
iconClassName={isPinned ? "mx_MessageContextMenu_iconUnpin" : "mx_MessageContextMenu_iconPin"}
|
iconClassName={isPinned ? "mx_MessageContextMenu_iconUnpin" : "mx_MessageContextMenu_iconPin"}
|
||||||
label={isPinned ? _t("action|unpin") : _t("action|pin")}
|
label={isPinned ? _t("action|unpin") : _t("action|pin")}
|
||||||
onClick={this.onPinClick}
|
onClick={() => this.onPinClick(isPinned)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import { logger } from "matrix-js-sdk/src/logger";
|
||||||
import BaseDialog from "../dialogs/BaseDialog";
|
import BaseDialog from "../dialogs/BaseDialog";
|
||||||
import { _t } from "../../../languageHandler";
|
import { _t } from "../../../languageHandler";
|
||||||
import PinningUtils from "../../../utils/PinningUtils.ts";
|
import PinningUtils from "../../../utils/PinningUtils.ts";
|
||||||
|
import PosthogTrackers from "../../../PosthogTrackers.ts";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Properties for {@link UnpinAllDialog}.
|
* Properties for {@link UnpinAllDialog}.
|
||||||
|
@ -61,6 +62,7 @@ export function UnpinAllDialog({ matrixClient, roomId, onFinished }: UnpinAllDia
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
try {
|
try {
|
||||||
await PinningUtils.unpinAllEvents(matrixClient, roomId);
|
await PinningUtils.unpinAllEvents(matrixClient, roomId);
|
||||||
|
PosthogTrackers.trackPinUnpinMessage("Unpin", "UnpinAll");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error("Failed to unpin all events:", e);
|
logger.error("Failed to unpin all events:", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,6 +67,7 @@ import { GetRelationsForEvent, IEventTileType } from "../rooms/EventTile";
|
||||||
import { VoiceBroadcastInfoEventType } from "../../../voice-broadcast/types";
|
import { VoiceBroadcastInfoEventType } from "../../../voice-broadcast/types";
|
||||||
import { ButtonEvent } from "../elements/AccessibleButton";
|
import { ButtonEvent } from "../elements/AccessibleButton";
|
||||||
import PinningUtils from "../../../utils/PinningUtils";
|
import PinningUtils from "../../../utils/PinningUtils";
|
||||||
|
import PosthogTrackers from "../../../PosthogTrackers.ts";
|
||||||
|
|
||||||
interface IOptionsButtonProps {
|
interface IOptionsButtonProps {
|
||||||
mxEvent: MatrixEvent;
|
mxEvent: MatrixEvent;
|
||||||
|
@ -407,12 +408,13 @@ export default class MessageActionBar extends React.PureComponent<IMessageAction
|
||||||
/**
|
/**
|
||||||
* Pin or unpin the event.
|
* Pin or unpin the event.
|
||||||
*/
|
*/
|
||||||
private onPinClick = async (event: ButtonEvent): Promise<void> => {
|
private onPinClick = async (event: ButtonEvent, isPinned: boolean): Promise<void> => {
|
||||||
// Don't open the regular browser or our context menu on right-click
|
// Don't open the regular browser or our context menu on right-click
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
||||||
await PinningUtils.pinOrUnpinEvent(MatrixClientPeg.safeGet(), this.props.mxEvent);
|
await PinningUtils.pinOrUnpinEvent(MatrixClientPeg.safeGet(), this.props.mxEvent);
|
||||||
|
PosthogTrackers.trackPinUnpinMessage(isPinned ? "Pin" : "Unpin", "Timeline");
|
||||||
};
|
};
|
||||||
|
|
||||||
public render(): React.ReactNode {
|
public render(): React.ReactNode {
|
||||||
|
@ -441,8 +443,8 @@ export default class MessageActionBar extends React.PureComponent<IMessageAction
|
||||||
<RovingAccessibleButton
|
<RovingAccessibleButton
|
||||||
className="mx_MessageActionBar_iconButton"
|
className="mx_MessageActionBar_iconButton"
|
||||||
title={isPinned ? _t("action|unpin") : _t("action|pin")}
|
title={isPinned ? _t("action|unpin") : _t("action|pin")}
|
||||||
onClick={this.onPinClick}
|
onClick={(e) => this.onPinClick(e, isPinned)}
|
||||||
onContextMenu={this.onPinClick}
|
onContextMenu={(e: ButtonEvent) => this.onPinClick(e, isPinned)}
|
||||||
key="pin"
|
key="pin"
|
||||||
placement="left"
|
placement="left"
|
||||||
>
|
>
|
||||||
|
|
|
@ -95,6 +95,7 @@ const onRoomFilesClick = (): void => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const onRoomPinsClick = (): void => {
|
const onRoomPinsClick = (): void => {
|
||||||
|
PosthogTrackers.trackInteraction("PinnedMessageRoomInfoButton");
|
||||||
RightPanelStore.instance.pushCard({ phase: RightPanelPhases.PinnedMessages }, true);
|
RightPanelStore.instance.pushCard({ phase: RightPanelPhases.PinnedMessages }, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ import { OpenForwardDialogPayload } from "../../../dispatcher/payloads/OpenForwa
|
||||||
import { createRedactEventDialog } from "../dialogs/ConfirmRedactDialog";
|
import { createRedactEventDialog } from "../dialogs/ConfirmRedactDialog";
|
||||||
import { ShowThreadPayload } from "../../../dispatcher/payloads/ShowThreadPayload";
|
import { ShowThreadPayload } from "../../../dispatcher/payloads/ShowThreadPayload";
|
||||||
import PinningUtils from "../../../utils/PinningUtils.ts";
|
import PinningUtils from "../../../utils/PinningUtils.ts";
|
||||||
|
import PosthogTrackers from "../../../PosthogTrackers.ts";
|
||||||
|
|
||||||
const AVATAR_SIZE = "32px";
|
const AVATAR_SIZE = "32px";
|
||||||
|
|
||||||
|
@ -152,6 +153,8 @@ function PinMenu({ event, room, permalinkCreator }: PinMenuProps): JSX.Element {
|
||||||
* View the event in the timeline.
|
* View the event in the timeline.
|
||||||
*/
|
*/
|
||||||
const onViewInTimeline = useCallback(() => {
|
const onViewInTimeline = useCallback(() => {
|
||||||
|
PosthogTrackers.trackInteraction("PinnedMessageListViewTimeline");
|
||||||
|
|
||||||
dis.dispatch<ViewRoomPayload>({
|
dis.dispatch<ViewRoomPayload>({
|
||||||
action: Action.ViewRoom,
|
action: Action.ViewRoom,
|
||||||
event_id: event.getId(),
|
event_id: event.getId(),
|
||||||
|
@ -173,6 +176,7 @@ function PinMenu({ event, room, permalinkCreator }: PinMenuProps): JSX.Element {
|
||||||
*/
|
*/
|
||||||
const onUnpin = useCallback(async (): Promise<void> => {
|
const onUnpin = useCallback(async (): Promise<void> => {
|
||||||
await PinningUtils.pinOrUnpinEvent(matrixClient, event);
|
await PinningUtils.pinOrUnpinEvent(matrixClient, event);
|
||||||
|
PosthogTrackers.trackPinUnpinMessage("Unpin", "MessagePinningList");
|
||||||
}, [event, matrixClient]);
|
}, [event, matrixClient]);
|
||||||
|
|
||||||
const contentActionable = isContentActionable(event);
|
const contentActionable = isContentActionable(event);
|
||||||
|
|
|
@ -32,6 +32,7 @@ import dis from "../../../dispatcher/dispatcher";
|
||||||
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
||||||
import { Action } from "../../../dispatcher/actions";
|
import { Action } from "../../../dispatcher/actions";
|
||||||
import MessageEvent from "../messages/MessageEvent";
|
import MessageEvent from "../messages/MessageEvent";
|
||||||
|
import PosthogTrackers from "../../../PosthogTrackers.ts";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The props for the {@link PinnedMessageBanner} component.
|
* The props for the {@link PinnedMessageBanner} component.
|
||||||
|
@ -68,6 +69,8 @@ export function PinnedMessageBanner({ room, permalinkCreator }: PinnedMessageBan
|
||||||
const shouldUseMessageEvent = pinnedEvent.isRedacted() || pinnedEvent.isDecryptionFailure();
|
const shouldUseMessageEvent = pinnedEvent.isRedacted() || pinnedEvent.isDecryptionFailure();
|
||||||
|
|
||||||
const onBannerClick = (): void => {
|
const onBannerClick = (): void => {
|
||||||
|
PosthogTrackers.trackInteraction("PinnedMessageBannerClick");
|
||||||
|
|
||||||
// Scroll to the pinned message
|
// Scroll to the pinned message
|
||||||
dis.dispatch<ViewRoomPayload>({
|
dis.dispatch<ViewRoomPayload>({
|
||||||
action: Action.ViewRoom,
|
action: Action.ViewRoom,
|
||||||
|
@ -309,6 +312,9 @@ function BannerButton({ room }: BannerButtonProps): JSX.Element {
|
||||||
className="mx_PinnedMessageBanner_actions"
|
className="mx_PinnedMessageBanner_actions"
|
||||||
kind="tertiary"
|
kind="tertiary"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
if (isPinnedMessagesPhase) PosthogTrackers.trackInteraction("PinnedMessageBannerCloseListButton");
|
||||||
|
else PosthogTrackers.trackInteraction("PinnedMessageBannerViewAllButton");
|
||||||
|
|
||||||
RightPanelStore.instance.showOrHidePhase(RightPanelPhases.PinnedMessages);
|
RightPanelStore.instance.showOrHidePhase(RightPanelPhases.PinnedMessages);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
Loading…
Reference in a new issue