diff --git a/package.json b/package.json index a1cbcce0e8b..edfe13584f9 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ }, "dependencies": { "@babel/runtime": "^7.12.5", - "@matrix-org/analytics-events": "^0.24.0", + "@matrix-org/analytics-events": "^0.25.0", "@matrix-org/emojibase-bindings": "^1.1.2", "@matrix-org/matrix-wysiwyg": "2.37.9", "@matrix-org/react-sdk-module-api": "^2.4.0", diff --git a/src/PosthogTrackers.ts b/src/PosthogTrackers.ts index 18b6edc064a..48b5d59300c 100644 --- a/src/PosthogTrackers.ts +++ b/src/PosthogTrackers.ts @@ -17,6 +17,7 @@ limitations under the License. import { PureComponent, SyntheticEvent } from "react"; 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 { PinUnpinAction } from "@matrix-org/analytics-events/types/typescript/PinUnpinAction"; import PageType from "./PageTypes"; import Views from "./Views"; @@ -106,6 +107,19 @@ export default class PosthogTrackers { 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({ + eventName: "PinUnpinAction", + kind, + from, + }); + } } export class PosthogScreenTracker extends PureComponent<{ screenName: ScreenName }> { diff --git a/src/TextForEvent.tsx b/src/TextForEvent.tsx index 96eb38f01b1..d85b7519ae6 100644 --- a/src/TextForEvent.tsx +++ b/src/TextForEvent.tsx @@ -40,12 +40,13 @@ import { WIDGET_LAYOUT_EVENT_TYPE } from "./stores/widgets/WidgetLayoutStore"; import { RightPanelPhases } from "./stores/right-panel/RightPanelStorePhases"; import defaultDispatcher from "./dispatcher/dispatcher"; 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 { highlightEvent, isLocationEvent } from "./utils/EventUtils"; import { ElementCall } from "./models/Call"; import { textForVoiceBroadcastStoppedEvent, VoiceBroadcastInfoEventType } from "./voice-broadcast"; import { getSenderName } from "./utils/event/getSenderName"; +import PosthogTrackers from "./PosthogTrackers.ts"; function getRoomMemberDisplayname(client: MatrixClient, event: MatrixEvent, userId = event.getSender()): string { const roomId = event.getRoomId(); @@ -563,6 +564,7 @@ function textForPowerEvent(event: MatrixEvent, client: MatrixClient): (() => str } const onPinnedMessagesClick = (): void => { + PosthogTrackers.trackInteraction("PinnedMessageStateEventClick"); RightPanelStore.instance.setCard({ phase: RightPanelPhases.PinnedMessages }, false); }; @@ -590,7 +592,10 @@ function textForPinnedEvent(event: MatrixEvent, client: MatrixClient, allowJSX: a: (sub) => ( highlightEvent(roomId, messageId)} + onClick={() => { + PosthogTrackers.trackInteraction("PinnedMessageStateEventClick"); + highlightEvent(roomId, messageId); + }} > {sub} @@ -623,7 +628,10 @@ function textForPinnedEvent(event: MatrixEvent, client: MatrixClient, allowJSX: a: (sub) => ( highlightEvent(roomId, messageId)} + onClick={() => { + PosthogTrackers.trackInteraction("PinnedMessageStateEventClick"); + highlightEvent(roomId, messageId); + }} > {sub} diff --git a/src/components/views/context_menus/MessageContextMenu.tsx b/src/components/views/context_menus/MessageContextMenu.tsx index 9da62c7d232..31f6a06cc17 100644 --- a/src/components/views/context_menus/MessageContextMenu.tsx +++ b/src/components/views/context_menus/MessageContextMenu.tsx @@ -60,6 +60,7 @@ import { getShareableLocationEvent } from "../../../events/location/getShareable import { ShowThreadPayload } from "../../../dispatcher/payloads/ShowThreadPayload"; import { CardContext } from "../right_panel/context"; import PinningUtils from "../../../utils/PinningUtils"; +import PosthogTrackers from "../../../PosthogTrackers.ts"; interface IReplyInThreadButton { mxEvent: MatrixEvent; @@ -243,9 +244,11 @@ export default class MessageContextMenu extends React.Component this.closeMenu(); }; - private onPinClick = (): void => { + private onPinClick = (isPinned: boolean): void => { // Pin or unpin in background PinningUtils.pinOrUnpinEvent(MatrixClientPeg.safeGet(), this.props.mxEvent); + PosthogTrackers.trackPinUnpinMessage(isPinned ? "Pin" : "Unpin", "Timeline"); + this.closeMenu(); }; @@ -618,7 +621,7 @@ export default class MessageContextMenu extends React.Component this.onPinClick(isPinned)} /> ); } diff --git a/src/components/views/dialogs/UnpinAllDialog.tsx b/src/components/views/dialogs/UnpinAllDialog.tsx index 4b752e820f6..e6ce5f556b4 100644 --- a/src/components/views/dialogs/UnpinAllDialog.tsx +++ b/src/components/views/dialogs/UnpinAllDialog.tsx @@ -22,6 +22,7 @@ import { logger } from "matrix-js-sdk/src/logger"; import BaseDialog from "../dialogs/BaseDialog"; import { _t } from "../../../languageHandler"; import PinningUtils from "../../../utils/PinningUtils.ts"; +import PosthogTrackers from "../../../PosthogTrackers.ts"; /** * Properties for {@link UnpinAllDialog}. @@ -61,6 +62,7 @@ export function UnpinAllDialog({ matrixClient, roomId, onFinished }: UnpinAllDia onClick={async () => { try { await PinningUtils.unpinAllEvents(matrixClient, roomId); + PosthogTrackers.trackPinUnpinMessage("Unpin", "UnpinAll"); } catch (e) { logger.error("Failed to unpin all events:", e); } diff --git a/src/components/views/messages/MessageActionBar.tsx b/src/components/views/messages/MessageActionBar.tsx index bb870e3dbe4..3c9da8b2940 100644 --- a/src/components/views/messages/MessageActionBar.tsx +++ b/src/components/views/messages/MessageActionBar.tsx @@ -67,6 +67,7 @@ import { GetRelationsForEvent, IEventTileType } from "../rooms/EventTile"; import { VoiceBroadcastInfoEventType } from "../../../voice-broadcast/types"; import { ButtonEvent } from "../elements/AccessibleButton"; import PinningUtils from "../../../utils/PinningUtils"; +import PosthogTrackers from "../../../PosthogTrackers.ts"; interface IOptionsButtonProps { mxEvent: MatrixEvent; @@ -407,12 +408,13 @@ export default class MessageActionBar extends React.PureComponent => { + private onPinClick = async (event: ButtonEvent, isPinned: boolean): Promise => { // Don't open the regular browser or our context menu on right-click event.preventDefault(); event.stopPropagation(); await PinningUtils.pinOrUnpinEvent(MatrixClientPeg.safeGet(), this.props.mxEvent); + PosthogTrackers.trackPinUnpinMessage(isPinned ? "Pin" : "Unpin", "Timeline"); }; public render(): React.ReactNode { @@ -441,8 +443,8 @@ export default class MessageActionBar extends React.PureComponent this.onPinClick(e, isPinned)} + onContextMenu={(e: ButtonEvent) => this.onPinClick(e, isPinned)} key="pin" placement="left" > diff --git a/src/components/views/right_panel/RoomSummaryCard.tsx b/src/components/views/right_panel/RoomSummaryCard.tsx index ece150495e4..f4dcccdae99 100644 --- a/src/components/views/right_panel/RoomSummaryCard.tsx +++ b/src/components/views/right_panel/RoomSummaryCard.tsx @@ -95,6 +95,7 @@ const onRoomFilesClick = (): void => { }; const onRoomPinsClick = (): void => { + PosthogTrackers.trackInteraction("PinnedMessageRoomInfoButton"); RightPanelStore.instance.pushCard({ phase: RightPanelPhases.PinnedMessages }, true); }; diff --git a/src/components/views/rooms/PinnedEventTile.tsx b/src/components/views/rooms/PinnedEventTile.tsx index af4ff71916f..ed3fa105ec8 100644 --- a/src/components/views/rooms/PinnedEventTile.tsx +++ b/src/components/views/rooms/PinnedEventTile.tsx @@ -42,6 +42,7 @@ import { OpenForwardDialogPayload } from "../../../dispatcher/payloads/OpenForwa import { createRedactEventDialog } from "../dialogs/ConfirmRedactDialog"; import { ShowThreadPayload } from "../../../dispatcher/payloads/ShowThreadPayload"; import PinningUtils from "../../../utils/PinningUtils.ts"; +import PosthogTrackers from "../../../PosthogTrackers.ts"; const AVATAR_SIZE = "32px"; @@ -152,6 +153,8 @@ function PinMenu({ event, room, permalinkCreator }: PinMenuProps): JSX.Element { * View the event in the timeline. */ const onViewInTimeline = useCallback(() => { + PosthogTrackers.trackInteraction("PinnedMessageListViewTimeline"); + dis.dispatch({ action: Action.ViewRoom, event_id: event.getId(), @@ -173,6 +176,7 @@ function PinMenu({ event, room, permalinkCreator }: PinMenuProps): JSX.Element { */ const onUnpin = useCallback(async (): Promise => { await PinningUtils.pinOrUnpinEvent(matrixClient, event); + PosthogTrackers.trackPinUnpinMessage("Unpin", "MessagePinningList"); }, [event, matrixClient]); const contentActionable = isContentActionable(event); diff --git a/src/components/views/rooms/PinnedMessageBanner.tsx b/src/components/views/rooms/PinnedMessageBanner.tsx index 3f6a1b14a61..8c9d2cf252d 100644 --- a/src/components/views/rooms/PinnedMessageBanner.tsx +++ b/src/components/views/rooms/PinnedMessageBanner.tsx @@ -32,6 +32,7 @@ import dis from "../../../dispatcher/dispatcher"; import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload"; import { Action } from "../../../dispatcher/actions"; import MessageEvent from "../messages/MessageEvent"; +import PosthogTrackers from "../../../PosthogTrackers.ts"; /** * The props for the {@link PinnedMessageBanner} component. @@ -68,6 +69,8 @@ export function PinnedMessageBanner({ room, permalinkCreator }: PinnedMessageBan const shouldUseMessageEvent = pinnedEvent.isRedacted() || pinnedEvent.isDecryptionFailure(); const onBannerClick = (): void => { + PosthogTrackers.trackInteraction("PinnedMessageBannerClick"); + // Scroll to the pinned message dis.dispatch({ action: Action.ViewRoom, @@ -309,6 +312,9 @@ function BannerButton({ room }: BannerButtonProps): JSX.Element { className="mx_PinnedMessageBanner_actions" kind="tertiary" onClick={() => { + if (isPinnedMessagesPhase) PosthogTrackers.trackInteraction("PinnedMessageBannerCloseListButton"); + else PosthogTrackers.trackInteraction("PinnedMessageBannerViewAllButton"); + RightPanelStore.instance.showOrHidePhase(RightPanelPhases.PinnedMessages); }} > diff --git a/yarn.lock b/yarn.lock index f0f8a5c495e..f872acbe5fb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1893,10 +1893,10 @@ resolved "https://registry.yarnpkg.com/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz#497c67a1cef50d1a2459ba60f315e448d2ad87fe" integrity sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q== -"@matrix-org/analytics-events@^0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@matrix-org/analytics-events/-/analytics-events-0.24.0.tgz#21a64537ac975b18e1eb13d9fd0bdc7d448a6039" - integrity sha512-3FDdtqZ+5cMqVffWjFNOIQ7RDFN6XS11kqdtN2ps8uvq5ce8gT0yXQvK37WeKWKZZ5QAKeoMzGhud+lsVcb1xg== +"@matrix-org/analytics-events@^0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@matrix-org/analytics-events/-/analytics-events-0.25.0.tgz#b0b85297dc05a67feaf89cc5d70b80283c988141" + integrity sha512-UCTuMjlJGArMqG9qXGfeNz/XtZDFldwuO+dkqP6Wo1nVdWasoWAOlcimDWQ2JnNFCg+UDZU+HLBdS5juTd6xTg== "@matrix-org/emojibase-bindings@^1.1.2": version "1.1.3"