diff --git a/package.json b/package.json index 7b46cd64fd..05196d016a 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "linkifyjs": "^4.0.0-beta.4", "lodash": "^4.17.20", "maplibre-gl": "^1.15.2", - "matrix-analytics-events": "github:matrix-org/matrix-analytics-events.git#df9c0312f51911a7364810466d041f2b79e7e080", + "matrix-analytics-events": "github:matrix-org/matrix-analytics-events.git#8e75aaf0b3e045587daeaf97a7691dbfda2f20c0", "matrix-events-sdk": "^0.0.1-beta.6", "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop", "matrix-widget-api": "^0.1.0-beta.18", diff --git a/src/BasePlatform.ts b/src/BasePlatform.ts index 048ed30c06..54fc6081c9 100644 --- a/src/BasePlatform.ts +++ b/src/BasePlatform.ts @@ -189,7 +189,7 @@ export default abstract class BasePlatform { const payload: ViewRoomPayload = { action: Action.ViewRoom, room_id: room.roomId, - _trigger: "Notification", + metricsTrigger: "Notification", }; if (ev.getThread()) { diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index a060846890..8fd9db1ef1 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -891,7 +891,7 @@ export default class CallHandler extends EventEmitter { dis.dispatch({ action: Action.ViewRoom, room_id: roomId, - _trigger: "WebAcceptCall", + metricsTrigger: "WebAcceptCall", }); } @@ -929,7 +929,7 @@ export default class CallHandler extends EventEmitter { dis.dispatch({ action: Action.ViewRoom, room_id: roomId, - _trigger: "WebDialPad", + metricsTrigger: "WebDialPad", }); await this.placeMatrixCall(roomId, CallType.Voice, null); @@ -962,7 +962,7 @@ export default class CallHandler extends EventEmitter { room_id: dmRoomId, should_peek: false, joining: false, - _trigger: undefined, // other + metricsTrigger: undefined, // other }); } else { try { diff --git a/src/SlashCommands.tsx b/src/SlashCommands.tsx index 81521c6a1d..637f324743 100644 --- a/src/SlashCommands.tsx +++ b/src/SlashCommands.tsx @@ -350,8 +350,8 @@ export const Commands = [ event_id: eventId, highlighted: true, room_id: roomId, - _trigger: "SlashCommand", - _viaKeyboard: true, + metricsTrigger: "SlashCommand", + metricsViaKeyboard: true, }); })()); } @@ -615,8 +615,8 @@ export const Commands = [ action: Action.ViewRoom, room_alias: roomAlias, auto_join: true, - _trigger: "SlashCommand", - _viaKeyboard: true, + metricsTrigger: "SlashCommand", + metricsViaKeyboard: true, }); return success(); } else if (params[0][0] === '!') { @@ -627,8 +627,8 @@ export const Commands = [ room_id: roomId, via_servers: viaServers, // for the rejoin button auto_join: true, - _trigger: "SlashCommand", - _viaKeyboard: true, + metricsTrigger: "SlashCommand", + metricsViaKeyboard: true, }); return success(); } else if (isPermalink) { @@ -653,8 +653,8 @@ export const Commands = [ const dispatch: ViewRoomPayload = { action: Action.ViewRoom, auto_join: true, - _trigger: "SlashCommand", - _viaKeyboard: true, + metricsTrigger: "SlashCommand", + metricsViaKeyboard: true, }; if (entity[0] === '!') dispatch["room_id"] = entity; @@ -1155,8 +1155,8 @@ export const Commands = [ dis.dispatch({ action: Action.ViewRoom, room_id: roomId, - _trigger: "SlashCommand", - _viaKeyboard: true, + metricsTrigger: "SlashCommand", + metricsViaKeyboard: true, }); })()); }, @@ -1179,8 +1179,8 @@ export const Commands = [ dis.dispatch({ action: Action.ViewRoom, room_id: roomId, - _trigger: "SlashCommand", - _viaKeyboard: true, + metricsTrigger: "SlashCommand", + metricsViaKeyboard: true, }); if (msg) { cli.sendTextMessage(roomId, msg); diff --git a/src/TextForEvent.tsx b/src/TextForEvent.tsx index 2ee8cce5d6..49da76b8b8 100644 --- a/src/TextForEvent.tsx +++ b/src/TextForEvent.tsx @@ -535,7 +535,7 @@ const onPinnedOrUnpinnedMessageClick = (messageId: string, roomId: string): void event_id: messageId, highlighted: true, room_id: roomId, - _trigger: undefined, // room doesn't change + metricsTrigger: undefined, // room doesn't change }); }; diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index d5658321ec..3a52f9cb38 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -1084,7 +1084,7 @@ export default class MatrixChat extends React.PureComponent { dis.dispatch({ action: Action.ViewRoom, room_id: dmRooms[0], - _trigger: "MessageUser", + metricsTrigger: "MessageUser", }); } else { dis.dispatch({ @@ -1356,7 +1356,7 @@ export default class MatrixChat extends React.PureComponent { dis.dispatch({ action: Action.ViewRoom, room_id: localStorage.getItem('mx_last_room_id'), - _trigger: undefined, // other + metricsTrigger: undefined, // other }); } @@ -1797,7 +1797,7 @@ export default class MatrixChat extends React.PureComponent { }, room_alias: undefined, room_id: undefined, - _trigger: undefined, // unknown or external trigger + metricsTrigger: undefined, // unknown or external trigger }; if (roomString[0] === '#') { payload.room_alias = roomString; diff --git a/src/components/structures/RoomDirectory.tsx b/src/components/structures/RoomDirectory.tsx index 0f8a98ca15..b29cc245fd 100644 --- a/src/components/structures/RoomDirectory.tsx +++ b/src/components/structures/RoomDirectory.tsx @@ -489,7 +489,7 @@ export default class RoomDirectory extends React.Component { action: Action.ViewRoom, auto_join: autoJoin, should_peek: shouldPeek, - _trigger: "RoomDirectory", + metricsTrigger: "RoomDirectory", }; if (room) { // Don't let the user view a room they won't be able to either diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index 2df218f2c7..53a7262fee 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -102,6 +102,7 @@ import { RightPanelPhases } from '../../stores/right-panel/RightPanelStorePhases import { ActionPayload } from "../../dispatcher/payloads"; import { KeyBindingAction } from "../../accessibility/KeyboardShortcuts"; import { ViewRoomPayload } from "../../dispatcher/payloads/ViewRoomPayload"; +import { JoinRoomPayload } from "../../dispatcher/payloads/JoinRoomPayload"; const DEBUG = false; let debuglog = function(msg: string) {}; @@ -776,7 +777,7 @@ export class RoomView extends React.Component { event_id: this.state.initialEventId, highlighted: false, replyingToEvent: this.state.replyToEvent, - _trigger: undefined, // room doesn't change + metricsTrigger: undefined, // room doesn't change }); } }; @@ -879,7 +880,7 @@ export class RoomView extends React.Component { action: Action.ViewRoom, room_id: roomId, deferred_action: payload, - _trigger: "MessageSearch", + metricsTrigger: "MessageSearch", }); }); } @@ -1179,7 +1180,7 @@ export class RoomView extends React.Component { dis.dispatch({ action: Action.ViewRoom, room_id: this.state.room.roomId, - _trigger: undefined, // room doesn't change + metricsTrigger: undefined, // room doesn't change }); return; // this event cannot affect permissions so bail } @@ -1283,10 +1284,11 @@ export class RoomView extends React.Component { } else { Promise.resolve().then(() => { const signUrl = this.props.threepidInvite?.signUrl; - dis.dispatch({ + dis.dispatch({ action: Action.JoinRoom, roomId: this.getRoomId(), opts: { inviteSignUrl: signUrl }, + metricsTrigger: this.state.room?.getMyMembership() === "invite" ? "Invite" : "RoomPreview", }); return Promise.resolve(); }); @@ -1651,7 +1653,7 @@ export class RoomView extends React.Component { dis.dispatch({ action: Action.ViewRoom, room_id: this.state.room.roomId, - _trigger: undefined, // room doesn't change + metricsTrigger: undefined, // room doesn't change }); } else { // Otherwise we have to jump manually @@ -1787,7 +1789,7 @@ export class RoomView extends React.Component { dis.dispatch({ action: Action.ViewRoom, room_id: oldRoom.roomId, - _trigger: "Predecessor", + metricsTrigger: "Predecessor", }); }; diff --git a/src/components/structures/SpaceHierarchy.tsx b/src/components/structures/SpaceHierarchy.tsx index 459f9fd0e3..d1331e0d96 100644 --- a/src/components/structures/SpaceHierarchy.tsx +++ b/src/components/structures/SpaceHierarchy.tsx @@ -63,6 +63,7 @@ import { IOOBData } from "../../stores/ThreepidInviteStore"; import { awaitRoomDownSync } from "../../utils/RoomUpgrade"; import RoomViewStore from "../../stores/RoomViewStore"; import { ViewRoomPayload } from "../../dispatcher/payloads/ViewRoomPayload"; +import { JoinRoomReadyPayload } from "../../dispatcher/payloads/JoinRoomReadyPayload"; interface IProps { space: Room; @@ -339,7 +340,7 @@ export const showRoom = (cli: MatrixClient, hierarchy: RoomHierarchy, roomId: st name: room.name || roomAlias || _t("Unnamed room"), roomType, } as IOOBData, - _trigger: "RoomDirectory", + metricsTrigger: "RoomDirectory", }); }; @@ -355,7 +356,13 @@ export const joinRoom = (cli: MatrixClient, hierarchy: RoomHierarchy, roomId: st viaServers: Array.from(hierarchy.viaMap.get(roomId) || []), }); - prom.catch(err => { + prom.then(() => { + dis.dispatch({ + action: Action.JoinRoomReady, + roomId, + metricsTrigger: "SpaceHierarchy", + }); + }, err => { RoomViewStore.showJoinRoomError(err, roomId); }); diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx index cfab45171a..e5faebb1b8 100644 --- a/src/components/structures/SpaceRoomView.tsx +++ b/src/components/structures/SpaceRoomView.tsx @@ -867,7 +867,7 @@ export default class SpaceRoomView extends React.PureComponent { defaultDispatcher.dispatch({ action: Action.ViewRoom, room_id: this.state.firstRoomId, - _trigger: undefined, // other + metricsTrigger: undefined, // other }); return; } diff --git a/src/components/structures/ThreadView.tsx b/src/components/structures/ThreadView.tsx index cf8db378be..da8d49aaeb 100644 --- a/src/components/structures/ThreadView.tsx +++ b/src/components/structures/ThreadView.tsx @@ -202,7 +202,7 @@ export default class ThreadView extends React.Component { event_id: this.props.initialEvent?.getId(), highlighted: false, replyingToEvent: this.state.replyToEvent, - _trigger: undefined, // room doesn't change + metricsTrigger: undefined, // room doesn't change }); } }; diff --git a/src/components/structures/TimelinePanel.tsx b/src/components/structures/TimelinePanel.tsx index aa81c7c63d..a5cb4add5a 100644 --- a/src/components/structures/TimelinePanel.tsx +++ b/src/components/structures/TimelinePanel.tsx @@ -1195,7 +1195,7 @@ class TimelinePanel extends React.Component { dis.dispatch({ action: Action.ViewRoom, room_id: this.props.timelineSet.room.roomId, - _trigger: undefined, // room doesn't change + metricsTrigger: undefined, // room doesn't change }); }; } diff --git a/src/components/views/context_menus/MessageContextMenu.tsx b/src/components/views/context_menus/MessageContextMenu.tsx index 3a9882564b..0602ea6013 100644 --- a/src/components/views/context_menus/MessageContextMenu.tsx +++ b/src/components/views/context_menus/MessageContextMenu.tsx @@ -269,7 +269,7 @@ export default class MessageContextMenu extends React.Component event_id: this.props.mxEvent.getId(), highlighted: true, room_id: this.props.mxEvent.getRoomId(), - _trigger: undefined, // room doesn't change + metricsTrigger: undefined, // room doesn't change }); this.closeMenu(); }; diff --git a/src/components/views/context_menus/RoomContextMenu.tsx b/src/components/views/context_menus/RoomContextMenu.tsx index 73dac3e791..290b53c1d8 100644 --- a/src/components/views/context_menus/RoomContextMenu.tsx +++ b/src/components/views/context_menus/RoomContextMenu.tsx @@ -253,8 +253,8 @@ const RoomContextMenu = ({ room, onFinished, ...props }: IProps) => { dis.dispatch({ action: Action.ViewRoom, room_id: room.roomId, - _trigger: "RoomList", - _viaKeyboard: ev.type !== "click", + metricsTrigger: "RoomList", + metricsViaKeyboard: ev.type !== "click", }, true); }; diff --git a/src/components/views/context_menus/SpaceContextMenu.tsx b/src/components/views/context_menus/SpaceContextMenu.tsx index 3d16884302..aab270e2e8 100644 --- a/src/components/views/context_menus/SpaceContextMenu.tsx +++ b/src/components/views/context_menus/SpaceContextMenu.tsx @@ -120,7 +120,7 @@ const SpaceContextMenu = ({ space, hideHeader, onFinished, ...props }: IProps) = action: Action.ViewRoom, room_id: space.roomId, forceTimeline: true, - _trigger: undefined, // room doesn't change + metricsTrigger: undefined, // room doesn't change }); onFinished(); }; @@ -197,7 +197,7 @@ const SpaceContextMenu = ({ space, hideHeader, onFinished, ...props }: IProps) = defaultDispatcher.dispatch({ action: Action.ViewRoom, room_id: space.roomId, - _trigger: undefined, // other + metricsTrigger: undefined, // other }); onFinished(); }; diff --git a/src/components/views/context_menus/ThreadListContextMenu.tsx b/src/components/views/context_menus/ThreadListContextMenu.tsx index 0340109811..67d0396532 100644 --- a/src/components/views/context_menus/ThreadListContextMenu.tsx +++ b/src/components/views/context_menus/ThreadListContextMenu.tsx @@ -81,7 +81,7 @@ const ThreadListContextMenu: React.FC = ({ event_id: mxEvent.getId(), highlighted: true, room_id: mxEvent.getRoomId(), - _trigger: undefined, // room doesn't change + metricsTrigger: undefined, // room doesn't change }); closeThreadOptions(); }, [mxEvent, closeThreadOptions]); diff --git a/src/components/views/dialogs/CreateCommunityPrototypeDialog.tsx b/src/components/views/dialogs/CreateCommunityPrototypeDialog.tsx index 5f68968613..215903c5af 100644 --- a/src/components/views/dialogs/CreateCommunityPrototypeDialog.tsx +++ b/src/components/views/dialogs/CreateCommunityPrototypeDialog.tsx @@ -104,7 +104,7 @@ export default class CreateCommunityPrototypeDialog extends React.PureComponent< dis.dispatch({ action: Action.ViewRoom, room_id: result.room_id, - _trigger: undefined, // Deprecated groups + metricsTrigger: undefined, // Deprecated groups }); showCommunityRoomInviteDialog(result.room_id, this.state.name); } else { diff --git a/src/components/views/dialogs/CreateSpaceFromCommunityDialog.tsx b/src/components/views/dialogs/CreateSpaceFromCommunityDialog.tsx index 8c3d9a25f7..cefffe888a 100644 --- a/src/components/views/dialogs/CreateSpaceFromCommunityDialog.tsx +++ b/src/components/views/dialogs/CreateSpaceFromCommunityDialog.tsx @@ -230,7 +230,7 @@ const CreateSpaceFromCommunityDialog: React.FC = ({ matrixClient: cli, g dis.dispatch({ action: Action.ViewRoom, room_id: roomId, - _trigger: undefined, // other + metricsTrigger: undefined, // other }); }; diff --git a/src/components/views/dialogs/ForwardDialog.tsx b/src/components/views/dialogs/ForwardDialog.tsx index b1983a7e72..13cea20be3 100644 --- a/src/components/views/dialogs/ForwardDialog.tsx +++ b/src/components/views/dialogs/ForwardDialog.tsx @@ -81,8 +81,8 @@ const Entry: React.FC = ({ room, event, matrixClient: cli, onFinish dis.dispatch({ action: Action.ViewRoom, room_id: room.roomId, - _trigger: "WebForwardShortcut", - _viaKeyboard: ev.type !== "click", + metricsTrigger: "WebForwardShortcut", + metricsViaKeyboard: ev.type !== "click", }); onFinished(true); }; diff --git a/src/components/views/dialogs/InviteDialog.tsx b/src/components/views/dialogs/InviteDialog.tsx index 3a79cb732c..c8271033ad 100644 --- a/src/components/views/dialogs/InviteDialog.tsx +++ b/src/components/views/dialogs/InviteDialog.tsx @@ -682,7 +682,7 @@ export default class InviteDialog extends React.PureComponent _td("General"), "mx_RoomSettingsDialog_settingsIcon", , + "RoomSettingsGeneral", )); tabs.push(new Tab( ROOM_SECURITY_TAB, @@ -103,18 +104,21 @@ export default class RoomSettingsDialog extends React.Component roomId={this.props.roomId} closeSettingsFn={() => this.props.onFinished(true)} />, + "RoomSettingsSecurityPrivacy", )); tabs.push(new Tab( ROOM_ROLES_TAB, _td("Roles & Permissions"), "mx_RoomSettingsDialog_rolesIcon", , + "RoomSettingsRolesPermissions", )); tabs.push(new Tab( ROOM_NOTIFICATIONS_TAB, _td("Notifications"), "mx_RoomSettingsDialog_notificationsIcon", this.props.onFinished(true)} />, + "RoomSettingsNotifications", )); if (SettingsStore.getValue("feature_bridge_state")) { @@ -123,6 +127,7 @@ export default class RoomSettingsDialog extends React.Component _td("Bridges"), "mx_RoomSettingsDialog_bridgesIcon", , + "RoomSettingsBridges", )); } @@ -135,6 +140,7 @@ export default class RoomSettingsDialog extends React.Component roomId={this.props.roomId} closeSettingsFn={() => this.props.onFinished(true)} />, + "RoomSettingsAdvanced", )); } diff --git a/src/components/views/dialogs/SpotlightDialog.tsx b/src/components/views/dialogs/SpotlightDialog.tsx index 4c0bf1da1d..a9071e5459 100644 --- a/src/components/views/dialogs/SpotlightDialog.tsx +++ b/src/components/views/dialogs/SpotlightDialog.tsx @@ -30,6 +30,7 @@ import { normalize } from "matrix-js-sdk/src/utils"; import { IHierarchyRoom } from "matrix-js-sdk/src/@types/spaces"; import { RoomHierarchy } from "matrix-js-sdk/src/room-hierarchy"; import { RoomType } from "matrix-js-sdk/src/@types/event"; +import { WebSearch as WebSearchEvent } from "matrix-analytics-events/types/typescript/WebSearch"; import { IDialogProps } from "./IDialogProps"; import { _t } from "../../../languageHandler"; @@ -72,6 +73,7 @@ import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload"; import { getMetaSpaceName } from "../../../stores/spaces"; import { getKeyBindingsManager } from "../../../KeyBindingsManager"; import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts"; +import { PosthogAnalytics } from "../../../PosthogAnalytics"; import { getCachedRoomIDForAlias } from "../../../RoomAliasCache"; const MAX_RECENT_SEARCHES = 10; @@ -205,6 +207,26 @@ type Result = IRoomResult | IResult; const isRoomResult = (result: any): result is IRoomResult => !!result?.room; +export const useWebSearchMetrics = (numResults: number, queryLength: number, viaSpotlight: boolean): void => { + useEffect(() => { + if (!queryLength) return; + + // send metrics after a 1s debounce + const timeoutId = setTimeout(() => { + PosthogAnalytics.instance.trackEvent({ + eventName: "WebSearch", + viaSpotlight, + numResults, + queryLength, + }); + }, 1000); + + return () => { + clearTimeout(timeoutId); + }; + }, [numResults, queryLength, viaSpotlight]); +}; + const SpotlightDialog: React.FC = ({ initialText = "", onFinished }) => { const cli = MatrixClientPeg.get(); const rovingContext = useContext(RovingTabIndexContext); @@ -270,6 +292,9 @@ const SpotlightDialog: React.FC = ({ initialText = "", onFinished }) => return results; }, [possibleResults, trimmedQuery]); + const numResults = trimmedQuery ? people.length + rooms.length + spaces.length : 0; + useWebSearchMetrics(numResults, query.length, true); + const activeSpace = SpaceStore.instance.activeSpaceRoom; const [spaceResults, spaceResultsLoading] = useSpaceResults(activeSpace, query); @@ -310,8 +335,8 @@ const SpotlightDialog: React.FC = ({ initialText = "", onFinished }) => defaultDispatcher.dispatch({ action: Action.ViewRoom, room_id: roomId, - _trigger: "WebUnifiedSearch", - _viaKeyboard: viaKeyboard, + metricsTrigger: "WebUnifiedSearch", + metricsViaKeyboard: viaKeyboard, }); onFinished(); }; @@ -429,8 +454,8 @@ const SpotlightDialog: React.FC = ({ initialText = "", onFinished }) => action: Action.ViewRoom, room_alias: trimmedQuery, auto_join: true, - _trigger: "WebUnifiedSearch", - _viaKeyboard: ev.type !== "click", + metricsTrigger: "WebUnifiedSearch", + metricsViaKeyboard: ev.type !== "click", }); onFinished(); }} @@ -670,6 +695,7 @@ const SpotlightDialog: React.FC = ({ initialText = "", onFinished }) => onFinished={onFinished} hasCancel={false} onKeyDown={onDialogKeyDown} + screenName="UnifiedSearch" >
title={_t("Settings")} >
- +
); diff --git a/src/components/views/elements/ImageView.tsx b/src/components/views/elements/ImageView.tsx index 0e05bab698..11d07c4542 100644 --- a/src/components/views/elements/ImageView.tsx +++ b/src/components/views/elements/ImageView.tsx @@ -339,7 +339,7 @@ export default class ImageView extends React.Component { event_id: this.props.mxEvent.getId(), highlighted: true, room_id: this.props.mxEvent.getRoomId(), - _trigger: undefined, // room doesn't change + metricsTrigger: undefined, // room doesn't change }); this.props.onFinished(); }; diff --git a/src/components/views/messages/DateSeparator.tsx b/src/components/views/messages/DateSeparator.tsx index 809250dd99..e7aeb3e155 100644 --- a/src/components/views/messages/DateSeparator.tsx +++ b/src/components/views/messages/DateSeparator.tsx @@ -147,7 +147,7 @@ export default class DateSeparator extends React.Component { event_id: eventId, highlighted: true, room_id: roomId, - _trigger: undefined, // room doesn't change + metricsTrigger: undefined, // room doesn't change }); } catch (e) { const code = e.errcode || e.statusCode; diff --git a/src/components/views/messages/RoomCreate.tsx b/src/components/views/messages/RoomCreate.tsx index 42007c16c3..c2d407c8b9 100644 --- a/src/components/views/messages/RoomCreate.tsx +++ b/src/components/views/messages/RoomCreate.tsx @@ -45,8 +45,8 @@ export default class RoomCreate extends React.Component { event_id: predecessor['event_id'], highlighted: true, room_id: predecessor['room_id'], - _trigger: "Predecessor", - _viaKeyboard: e.type !== "click", + metricsTrigger: "Predecessor", + metricsViaKeyboard: e.type !== "click", }); }; diff --git a/src/components/views/right_panel/TimelineCard.tsx b/src/components/views/right_panel/TimelineCard.tsx index c3d076a95d..b03dfa4deb 100644 --- a/src/components/views/right_panel/TimelineCard.tsx +++ b/src/components/views/right_panel/TimelineCard.tsx @@ -151,7 +151,7 @@ export default class TimelineCard extends React.Component { event_id: this.state.initialEventId, highlighted: false, replyingToEvent: this.state.replyToEvent, - _trigger: undefined, // room doesn't change + metricsTrigger: undefined, // room doesn't change }); } }; diff --git a/src/components/views/right_panel/UserInfo.tsx b/src/components/views/right_panel/UserInfo.tsx index 2ee0bc63a1..f6a478ce3e 100644 --- a/src/components/views/right_panel/UserInfo.tsx +++ b/src/components/views/right_panel/UserInfo.tsx @@ -131,8 +131,8 @@ async function openDMForUser(matrixClient: MatrixClient, userId: string, viaKeyb dis.dispatch({ action: Action.ViewRoom, room_id: lastActiveRoom.roomId, - _trigger: "MessageUser", - _viaKeyboard: viaKeyboard, + metricsTrigger: "MessageUser", + metricsViaKeyboard: viaKeyboard, }); return; } @@ -397,7 +397,7 @@ const UserOptionsSection: React.FC<{ highlighted: true, event_id: room.getEventReadUpTo(member.userId), room_id: member.roomId, - _trigger: undefined, // room doesn't change + metricsTrigger: undefined, // room doesn't change }); }; diff --git a/src/components/views/rooms/EventTile.tsx b/src/components/views/rooms/EventTile.tsx index 2df45e86b6..f1f5a4f36d 100644 --- a/src/components/views/rooms/EventTile.tsx +++ b/src/components/views/rooms/EventTile.tsx @@ -720,7 +720,7 @@ export default class EventTile extends React.Component { event_id: this.props.mxEvent.getId(), highlighted: true, room_id: this.props.mxEvent.getRoomId(), - _trigger: undefined, // room doesn't change + metricsTrigger: undefined, // room doesn't change }); }; @@ -1023,7 +1023,9 @@ export default class EventTile extends React.Component { event_id: this.props.mxEvent.getId(), highlighted: true, room_id: this.props.mxEvent.getRoomId(), - _trigger: this.props.timelineRenderingType === TimelineRenderingType.Search ? "MessageSearch" : undefined, + metricsTrigger: this.props.timelineRenderingType === TimelineRenderingType.Search + ? "MessageSearch" + : undefined, }); }; diff --git a/src/components/views/rooms/MessageComposer.tsx b/src/components/views/rooms/MessageComposer.tsx index a36c9a9f08..c368f2a2cc 100644 --- a/src/components/views/rooms/MessageComposer.tsx +++ b/src/components/views/rooms/MessageComposer.tsx @@ -237,8 +237,8 @@ export default class MessageComposer extends React.Component { // Try to join via the server that sent the event. This converts @something:example.org // into a server domain by splitting on colons and ignoring the first entry ("@something"). via_servers: viaServers, - _trigger: "Tombstone", - _viaKeyboard: ev.type !== "click", + metricsTrigger: "Tombstone", + metricsViaKeyboard: ev.type !== "click", }); }; diff --git a/src/components/views/rooms/PinnedEventTile.tsx b/src/components/views/rooms/PinnedEventTile.tsx index 65f988878d..8f45039cf2 100644 --- a/src/components/views/rooms/PinnedEventTile.tsx +++ b/src/components/views/rooms/PinnedEventTile.tsx @@ -51,7 +51,7 @@ export default class PinnedEventTile extends React.Component { event_id: this.props.event.getId(), highlighted: true, room_id: this.props.event.getRoomId(), - _trigger: undefined, // room doesn't change + metricsTrigger: undefined, // room doesn't change }); }; diff --git a/src/components/views/rooms/RecentlyViewedButton.tsx b/src/components/views/rooms/RecentlyViewedButton.tsx index dc6876214f..5a5ec1520e 100644 --- a/src/components/views/rooms/RecentlyViewedButton.tsx +++ b/src/components/views/rooms/RecentlyViewedButton.tsx @@ -44,8 +44,8 @@ const RecentlyViewedButton = () => { dis.dispatch({ action: Action.ViewRoom, room_id: crumb.roomId, - _trigger: "WebVerticalBreadcrumbs", - _viaKeyboard: ev.type !== "click", + metricsTrigger: "WebVerticalBreadcrumbs", + metricsViaKeyboard: ev.type !== "click", }); tooltipRef.current?.hideTooltip(); }} diff --git a/src/components/views/rooms/ReplyTile.tsx b/src/components/views/rooms/ReplyTile.tsx index af4d1230f0..8de63c6b19 100644 --- a/src/components/views/rooms/ReplyTile.tsx +++ b/src/components/views/rooms/ReplyTile.tsx @@ -100,7 +100,7 @@ export default class ReplyTile extends React.PureComponent { event_id: this.props.mxEvent.getId(), highlighted: true, room_id: this.props.mxEvent.getRoomId(), - _trigger: undefined, // room doesn't change + metricsTrigger: undefined, // room doesn't change }); } } diff --git a/src/components/views/rooms/RoomBreadcrumbs.tsx b/src/components/views/rooms/RoomBreadcrumbs.tsx index 48f483b731..f4fc41c459 100644 --- a/src/components/views/rooms/RoomBreadcrumbs.tsx +++ b/src/components/views/rooms/RoomBreadcrumbs.tsx @@ -110,8 +110,8 @@ export default class RoomBreadcrumbs extends React.PureComponent defaultDispatcher.dispatch({ action: Action.ViewRoom, room_id: room.roomId, - _trigger: "WebHorizontalBreadcrumbs", - _viaKeyboard: viaKeyboard, + metricsTrigger: "WebHorizontalBreadcrumbs", + metricsViaKeyboard: viaKeyboard, }); }; diff --git a/src/components/views/rooms/RoomDetailList.tsx b/src/components/views/rooms/RoomDetailList.tsx index d36c284980..8503ef30fd 100644 --- a/src/components/views/rooms/RoomDetailList.tsx +++ b/src/components/views/rooms/RoomDetailList.tsx @@ -44,7 +44,7 @@ export default class RoomDetailList extends React.Component { action: Action.ViewRoom, room_id: room.roomId, room_alias: room.getCanonicalAlias() || (room.getAltAliases() || [])[0], - _trigger: undefined, // Deprecated groups + metricsTrigger: undefined, // Deprecated groups }); }; diff --git a/src/components/views/rooms/RoomList.tsx b/src/components/views/rooms/RoomList.tsx index 99ad379f83..86829d9149 100644 --- a/src/components/views/rooms/RoomList.tsx +++ b/src/components/views/rooms/RoomList.tsx @@ -221,7 +221,7 @@ const UntaggedAuxButton = ({ tabIndex }: IAuxButtonProps) => { defaultDispatcher.dispatch({ action: Action.ViewRoom, room_id: activeSpace.roomId, - _trigger: undefined, // other + metricsTrigger: undefined, // other }); PosthogTrackers.trackInteraction("WebRoomListRoomsSublistPlusMenuExploreRoomsItem", e); }} @@ -424,8 +424,8 @@ export default class RoomList extends React.PureComponent { action: Action.ViewRoom, room_id: room.roomId, show_room_tile: true, // to make sure the room gets scrolled into view - _trigger: "WebKeyboardShortcut", - _viaKeyboard: true, + metricsTrigger: "WebKeyboardShortcut", + metricsViaKeyboard: true, }); } } else if (payload.action === Action.PstnSupportUpdated) { @@ -509,7 +509,7 @@ export default class RoomList extends React.PureComponent { defaultDispatcher.dispatch({ action: Action.ViewRoom, room_id: this.props.activeSpace, - _trigger: undefined, // other + metricsTrigger: undefined, // other }); PosthogTrackers.trackInteraction("WebRoomListRoomsSublistPlusMenuExploreRoomsItem", ev); } else { @@ -542,8 +542,8 @@ export default class RoomList extends React.PureComponent { avatarUrl: room.avatar_url, name, }, - _trigger: "RoomList", - _viaKeyboard: ev.type !== "click", + metricsTrigger: "RoomList", + metricsViaKeyboard: ev.type !== "click", }); }; return ( diff --git a/src/components/views/rooms/RoomListHeader.tsx b/src/components/views/rooms/RoomListHeader.tsx index a91cba17e5..70cafe10ac 100644 --- a/src/components/views/rooms/RoomListHeader.tsx +++ b/src/components/views/rooms/RoomListHeader.tsx @@ -61,6 +61,7 @@ import TooltipTarget from "../elements/TooltipTarget"; import { BetaPill } from "../beta/BetaCard"; import PosthogTrackers from "../../../PosthogTrackers"; import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload"; +import { useWebSearchMetrics } from "../dialogs/SpotlightDialog"; const contextMenuBelow = (elementRect: DOMRect) => { // align the context menu's icons with the icon which opened the context menu @@ -108,7 +109,7 @@ const PrototypeCommunityContextMenu = (props: ComponentProps({ action: Action.ViewRoom, room_id: chat.roomId, - _trigger: undefined, // Deprecated groups + metricsTrigger: undefined, // Deprecated groups }, true); RightPanelStore.instance.setCard({ phase: RightPanelPhases.RoomMemberList }, undefined, chat.roomId); } else { @@ -177,14 +178,18 @@ const RoomListHeader = ({ spacePanelDisabled, onVisibilityChange }: IProps) => { }); const joiningRooms = useJoiningRooms(); + const filterCondition = RoomListStore.instance.getFirstNameFilterCondition(); const count = useEventEmitterState(RoomListStore.instance, LISTS_UPDATE_EVENT, () => { - if (RoomListStore.instance.getFirstNameFilterCondition()) { + if (filterCondition) { return Object.values(RoomListStore.instance.orderedLists).flat(1).length; } else { return null; } }); + // we pass null for the queryLength to inhibit the metrics hook for when there is no filterCondition + useWebSearchMetrics(count, filterCondition ? filterCondition.search.length : null, false); + const spaceName = useEventEmitterState(activeSpace, "Room.name", () => activeSpace?.name); useEffect(() => { @@ -279,7 +284,7 @@ const RoomListHeader = ({ spacePanelDisabled, onVisibilityChange }: IProps) => { defaultDispatcher.dispatch({ action: Action.ViewRoom, room_id: activeSpace.roomId, - _trigger: undefined, // other + metricsTrigger: undefined, // other }); closePlusMenu(); PosthogTrackers.trackInteraction("WebRoomListHeaderPlusMenuExploreRoomsItem", e); diff --git a/src/components/views/rooms/RoomSublist.tsx b/src/components/views/rooms/RoomSublist.tsx index ae82cff968..32ff441661 100644 --- a/src/components/views/rooms/RoomSublist.tsx +++ b/src/components/views/rooms/RoomSublist.tsx @@ -433,8 +433,8 @@ export default class RoomSublist extends React.Component { action: Action.ViewRoom, room_id: room.roomId, show_room_tile: true, // to make sure the room gets scrolled into view - _trigger: "WebRoomListNotificationBadge", - _viaKeyboard: ev.type !== "click", + metricsTrigger: "WebRoomListNotificationBadge", + metricsViaKeyboard: ev.type !== "click", }); } }; diff --git a/src/components/views/rooms/RoomTile.tsx b/src/components/views/rooms/RoomTile.tsx index e464114c39..08ae3bf3f1 100644 --- a/src/components/views/rooms/RoomTile.tsx +++ b/src/components/views/rooms/RoomTile.tsx @@ -245,8 +245,8 @@ export default class RoomTile extends React.PureComponent { show_room_tile: true, // make sure the room is visible in the list room_id: this.props.room.roomId, clear_search: (ev && (ev.key === Key.ENTER || ev.key === Key.SPACE)), - _trigger: "RoomList", - _viaKeyboard: ev.type !== "click", + metricsTrigger: "RoomList", + metricsViaKeyboard: ev.type !== "click", }); }; diff --git a/src/components/views/settings/JoinRuleSettings.tsx b/src/components/views/settings/JoinRuleSettings.tsx index df64b82080..1244b344b9 100644 --- a/src/components/views/settings/JoinRuleSettings.tsx +++ b/src/components/views/settings/JoinRuleSettings.tsx @@ -271,7 +271,7 @@ const JoinRuleSettings = ({ room, promptUpgrade, aliasWarning, onError, beforeCh dis.dispatch({ action: Action.ViewRoom, room_id: roomId, - _trigger: undefined, // other + metricsTrigger: undefined, // other }); // open new settings on this tab diff --git a/src/components/views/settings/tabs/room/AdvancedRoomSettingsTab.tsx b/src/components/views/settings/tabs/room/AdvancedRoomSettingsTab.tsx index e01e53506a..fd5aadc90f 100644 --- a/src/components/views/settings/tabs/room/AdvancedRoomSettingsTab.tsx +++ b/src/components/views/settings/tabs/room/AdvancedRoomSettingsTab.tsx @@ -95,8 +95,8 @@ export default class AdvancedRoomSettingsTab extends React.Component { dis.dispatch({ action: Action.ViewRoom, room_id: community.spaceId, - _trigger: undefined, // other + metricsTrigger: undefined, // other }); onFinished(); } else { diff --git a/src/components/views/toasts/VerificationRequestToast.tsx b/src/components/views/toasts/VerificationRequestToast.tsx index c0d99a1f72..54d4348a82 100644 --- a/src/components/views/toasts/VerificationRequestToast.tsx +++ b/src/components/views/toasts/VerificationRequestToast.tsx @@ -115,7 +115,7 @@ export default class VerificationRequestToast extends React.PureComponent { dis.dispatch({ action: Action.ViewRoom, room_id: roomId, - _trigger: "WebFloatingCallWindow", + metricsTrigger: "WebFloatingCallWindow", }); }; diff --git a/src/components/views/voip/PipView.tsx b/src/components/views/voip/PipView.tsx index 4dbe5c2111..1c3c9edc68 100644 --- a/src/components/views/voip/PipView.tsx +++ b/src/components/views/voip/PipView.tsx @@ -218,7 +218,7 @@ export default class PipView extends React.Component { dis.dispatch({ action: Action.ViewRoom, room_id: callRoomId ?? widgetRoomId, - _trigger: "WebFloatingCallWindow", + metricsTrigger: "WebFloatingCallWindow", }); } }; diff --git a/src/createRoom.ts b/src/createRoom.ts index dab6dd75e0..2a1d56e72f 100644 --- a/src/createRoom.ts +++ b/src/createRoom.ts @@ -264,7 +264,7 @@ export default async function createRoom(opts: IOpts): Promise { // stream, if it hasn't already. joining: true, justCreatedOpts: opts, - _trigger: "Created", + metricsTrigger: "Created", }); } return roomId; diff --git a/src/dispatcher/actions.ts b/src/dispatcher/actions.ts index c92d887524..113cc6e8bf 100644 --- a/src/dispatcher/actions.ts +++ b/src/dispatcher/actions.ts @@ -153,12 +153,12 @@ export enum Action { UploadCanceled = "upload_canceled", /** - * Fired when requesting to join a room + * Fired when requesting to join a room. Should be used with JoinRoomPayload. */ JoinRoom = "join_room", /** - * Fired when successfully joining a room + * Fired when successfully joining a room. Should be used with a JoinRoomReadyPayload. */ JoinRoomReady = "join_room_ready", @@ -168,7 +168,7 @@ export enum Action { JoinRoomError = "join_room_error", /** - * Inserts content into the active composer. Should be used with ComposerInsertPayload + * Inserts content into the active composer. Should be used with ComposerInsertPayload. */ ComposerInsert = "composer_insert", diff --git a/src/dispatcher/payloads/JoinRoomPayload.ts b/src/dispatcher/payloads/JoinRoomPayload.ts new file mode 100644 index 0000000000..5937475e2d --- /dev/null +++ b/src/dispatcher/payloads/JoinRoomPayload.ts @@ -0,0 +1,33 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { JoinedRoom as JoinedRoomEvent } from "matrix-analytics-events/types/typescript/JoinedRoom"; +import { IJoinRoomOpts } from "matrix-js-sdk/src/@types/requests"; + +import { ActionPayload } from "../payloads"; +import { Action } from "../actions"; + +/* eslint-disable camelcase */ +export interface JoinRoomPayload extends Pick { + action: Action.JoinRoom; + + roomId: string; + opts?: IJoinRoomOpts; + + // additional parameters for the purpose of metrics & instrumentation + metricsTrigger: JoinedRoomEvent["trigger"]; +} +/* eslint-enable camelcase */ diff --git a/src/dispatcher/payloads/JoinRoomReadyPayload.ts b/src/dispatcher/payloads/JoinRoomReadyPayload.ts new file mode 100644 index 0000000000..2f16028bc7 --- /dev/null +++ b/src/dispatcher/payloads/JoinRoomReadyPayload.ts @@ -0,0 +1,30 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { JoinedRoom as JoinedRoomEvent } from "matrix-analytics-events/types/typescript/JoinedRoom"; + +import { ActionPayload } from "../payloads"; +import { Action } from "../actions"; + +/* eslint-disable camelcase */ +export interface JoinRoomReadyPayload extends Pick { + action: Action.JoinRoomReady; + roomId: string; + + // additional parameters for the purpose of metrics & instrumentation + metricsTrigger: JoinedRoomEvent["trigger"]; +} +/* eslint-enable camelcase */ diff --git a/src/dispatcher/payloads/ViewRoomPayload.ts b/src/dispatcher/payloads/ViewRoomPayload.ts index 5bfc9efeb3..d85c07e666 100644 --- a/src/dispatcher/payloads/ViewRoomPayload.ts +++ b/src/dispatcher/payloads/ViewRoomPayload.ts @@ -48,7 +48,7 @@ export interface ViewRoomPayload extends Pick { deferred_action?: ActionPayload; // Action to fire after MatrixChat handles this ViewRoom action // additional parameters for the purpose of metrics & instrumentation - _trigger: ViewRoomEvent["trigger"]; - _viaKeyboard?: ViewRoomEvent["viaKeyboard"]; + metricsTrigger: ViewRoomEvent["trigger"]; + metricsViaKeyboard?: ViewRoomEvent["viaKeyboard"]; } /* eslint-enable camelcase */ diff --git a/src/linkify-matrix.ts b/src/linkify-matrix.ts index 541754d1e1..1fdd8106ba 100644 --- a/src/linkify-matrix.ts +++ b/src/linkify-matrix.ts @@ -120,8 +120,8 @@ function onAliasClick(event: MouseEvent, roomAlias: string) { dis.dispatch({ action: Action.ViewRoom, room_alias: roomAlias, - _trigger: "Timeline", - _viaKeyboard: false, + metricsTrigger: "Timeline", + metricsViaKeyboard: false, }); } diff --git a/src/stores/CommunityPrototypeStore.ts b/src/stores/CommunityPrototypeStore.ts index 6a82b6e76d..4d4dc661fd 100644 --- a/src/stores/CommunityPrototypeStore.ts +++ b/src/stores/CommunityPrototypeStore.ts @@ -154,7 +154,7 @@ export class CommunityPrototypeStore extends AsyncStoreWithClient { dis.dispatch({ action: Action.ViewRoom, room_id: chat.roomId, - _trigger: undefined, // Deprecated groups + metricsTrigger: undefined, // Deprecated groups }); } } diff --git a/src/stores/RoomViewStore.tsx b/src/stores/RoomViewStore.tsx index c2dcb256d0..2b87b3ab73 100644 --- a/src/stores/RoomViewStore.tsx +++ b/src/stores/RoomViewStore.tsx @@ -21,7 +21,9 @@ import { Store } from 'flux/utils'; import { MatrixError } from "matrix-js-sdk/src/http-api"; import { logger } from "matrix-js-sdk/src/logger"; import { ViewRoom as ViewRoomEvent } from "matrix-analytics-events/types/typescript/ViewRoom"; +import { JoinedRoom as JoinedRoomEvent } from "matrix-analytics-events/types/typescript/JoinedRoom"; import { JoinRule } from "matrix-js-sdk/src/@types/partials"; +import { Room } from "matrix-js-sdk/src/models/room"; import dis from '../dispatcher/dispatcher'; import { MatrixClientPeg } from '../MatrixClientPeg'; @@ -38,6 +40,8 @@ import { ViewRoomPayload } from "../dispatcher/payloads/ViewRoomPayload"; import DMRoomMap from "../utils/DMRoomMap"; import SpaceStore from "./spaces/SpaceStore"; import { isMetaSpace, MetaSpace } from "./spaces"; +import { JoinRoomPayload } from "../dispatcher/payloads/JoinRoomPayload"; +import { JoinRoomReadyPayload } from "../dispatcher/payloads/JoinRoomReadyPayload"; const NUM_JOIN_RETRY = 5; @@ -149,11 +153,42 @@ class RoomViewStore extends Store { case Action.JoinRoomError: this.joinRoomError(payload); break; - case Action.JoinRoomReady: + case Action.JoinRoomReady: { if (this.state.roomId === payload.roomId) { this.setState({ shouldPeek: false }); } + + const cli = MatrixClientPeg.get(); + + const updateMetrics = () => { + const room = cli.getRoom(payload.roomId); + const numMembers = room.getJoinedMemberCount(); + const roomSize = numMembers > 1000 ? "MoreThanAThousand" + : numMembers > 100 ? "OneHundredAndOneToAThousand" + : numMembers > 10 ? "ElevenToOneHundred" + : numMembers > 2 ? "ThreeToTen" + : numMembers > 1 ? "Two" + : "One"; + + PosthogAnalytics.instance.trackEvent({ + eventName: "JoinedRoom", + trigger: payload.metricsTrigger, + roomSize, + isDM: !!DMRoomMap.shared().getUserIdForRoomId(room.roomId), + isSpace: room.isSpaceRoom(), + }); + + cli.off("Room", updateMetrics); + }; + + if (cli.getRoom(payload.roomId)) { + updateMetrics(); + } else { + cli.on("Room", updateMetrics); + } + break; + } case 'on_client_not_viable': case 'on_logged_out': this.reset(); @@ -168,7 +203,7 @@ class RoomViewStore extends Store { action: Action.ViewRoom, room_id: payload.event.getRoomId(), replyingToEvent: payload.event, - _trigger: undefined, // room doesn't change + metricsTrigger: undefined, // room doesn't change }); } else { this.setState({ @@ -191,7 +226,7 @@ class RoomViewStore extends Store { private async viewRoom(payload: ViewRoomPayload): Promise { if (payload.room_id) { - if (payload._trigger !== null && payload.room_id !== this.state.roomId) { + if (payload.metricsTrigger !== null && payload.room_id !== this.state.roomId) { let activeSpace: ViewRoomEvent["activeSpace"]; if (SpaceStore.instance.activeSpace === MetaSpace.Home) { activeSpace = "Home"; @@ -205,8 +240,8 @@ class RoomViewStore extends Store { PosthogAnalytics.instance.trackEvent({ eventName: "ViewRoom", - trigger: payload._trigger, - viaKeyboard: payload._viaKeyboard, + trigger: payload.metricsTrigger, + viaKeyboard: payload.metricsViaKeyboard, isDM: !!DMRoomMap.shared().getUserIdForRoomId(payload.room_id), isSpace: MatrixClientPeg.get().getRoom(payload.room_id)?.isSpaceRoom(), activeSpace, @@ -240,10 +275,11 @@ class RoomViewStore extends Store { this.setState(newState); if (payload.auto_join) { - dis.dispatch({ + dis.dispatch({ ...payload, action: Action.JoinRoom, roomId: payload.room_id, + metricsTrigger: payload.metricsTrigger as JoinRoomPayload["metricsTrigger"], }); } } else if (payload.room_alias) { @@ -297,7 +333,7 @@ class RoomViewStore extends Store { }); } - private async joinRoom(payload: ActionPayload) { + private async joinRoom(payload: JoinRoomPayload) { this.setState({ joining: true, }); @@ -308,9 +344,9 @@ class RoomViewStore extends Store { const address = roomAlias || roomId; const viaServers = this.state.viaServers || []; try { - await retry(() => cli.joinRoom(address, { + await retry(() => cli.joinRoom(address, { viaServers, - ...payload.opts, + ...(payload.opts || {}), }), NUM_JOIN_RETRY, (err) => { // if we received a Gateway timeout then retry return err.httpStatus === 504; @@ -319,9 +355,10 @@ class RoomViewStore extends Store { // We do *not* clear the 'joining' flag because the Room object and/or our 'joined' member event may not // have come down the sync stream yet, and that's the point at which we'd consider the user joined to the // room. - dis.dispatch({ + dis.dispatch({ action: Action.JoinRoomReady, roomId, + metricsTrigger: payload.metricsTrigger, }); } catch (err) { dis.dispatch({ diff --git a/src/stores/spaces/SpaceStore.ts b/src/stores/spaces/SpaceStore.ts index ebcf987d4b..3e685a2839 100644 --- a/src/stores/spaces/SpaceStore.ts +++ b/src/stores/spaces/SpaceStore.ts @@ -161,7 +161,8 @@ export class SpaceStoreClass extends AsyncStoreWithClient { defaultDispatcher.dispatch({ action: Action.ViewRoom, room_id: roomId, - _trigger: "WebSpacePanelNotificationBadge", + context_switch: true, + metricsTrigger: "WebSpacePanelNotificationBadge", }); } else { const lists = RoomListStore.instance.unfilteredLists; @@ -178,7 +179,8 @@ export class SpaceStoreClass extends AsyncStoreWithClient { defaultDispatcher.dispatch({ action: Action.ViewRoom, room_id: unreadRoom.roomId, - _trigger: "WebSpacePanelNotificationBadge", + context_switch: true, + metricsTrigger: "WebSpacePanelNotificationBadge", }); break; } @@ -227,14 +229,14 @@ export class SpaceStoreClass extends AsyncStoreWithClient { action: Action.ViewRoom, room_id: roomId, context_switch: true, - _trigger: "WebSpaceContextSwitch", + metricsTrigger: "WebSpaceContextSwitch", }); } else if (cliSpace) { defaultDispatcher.dispatch({ action: Action.ViewRoom, room_id: space, context_switch: true, - _trigger: "WebSpaceContextSwitch", + metricsTrigger: "WebSpaceContextSwitch", }); } else { defaultDispatcher.dispatch({ diff --git a/src/stores/widgets/StopGapWidget.ts b/src/stores/widgets/StopGapWidget.ts index a3e8c105d7..ab8a0cdff9 100644 --- a/src/stores/widgets/StopGapWidget.ts +++ b/src/stores/widgets/StopGapWidget.ts @@ -296,7 +296,7 @@ export class StopGapWidget extends EventEmitter { defaultDispatcher.dispatch({ action: Action.ViewRoom, room_id: targetRoomId, - _trigger: "Widget", + metricsTrigger: "Widget", }); // acknowledge so the widget doesn't freak out diff --git a/src/utils/membership.ts b/src/utils/membership.ts index 2783d16ba0..cc977fda9d 100644 --- a/src/utils/membership.ts +++ b/src/utils/membership.ts @@ -191,7 +191,7 @@ export async function leaveRoomBehaviour(roomId: string, retry = true, spinner = dis.dispatch({ action: Action.ViewRoom, room_id: SpaceStore.instance.activeSpace, - _trigger: undefined, // other + metricsTrigger: undefined, // other }); } else { dis.dispatch({ action: 'view_home_page' }); diff --git a/src/utils/promise.ts b/src/utils/promise.ts index abcfc49a08..04a9ac8818 100644 --- a/src/utils/promise.ts +++ b/src/utils/promise.ts @@ -28,7 +28,11 @@ export async function timeout(promise: Promise, timeoutValue: Y, ms: nu } // Helper method to retry a Promise a given number of times or until a predicate fails -export async function retry(fn: () => Promise, num: number, predicate?: (e: E) => boolean) { +export async function retry( + fn: () => Promise, + num: number, + predicate?: (e: E) => boolean, +): Promise { let lastErr: E; for (let i = 0; i < num; i++) { try { diff --git a/test/stores/RoomViewStore-test.js b/test/stores/RoomViewStore-test.js index bf8fa01e38..6c9e8d47f9 100644 --- a/test/stores/RoomViewStore-test.js +++ b/test/stores/RoomViewStore-test.js @@ -38,6 +38,8 @@ describe('RoomViewStore', function() { beforeEach(function() { testUtils.stubClient(); peg.get().credentials = { userId: "@test:example.com" }; + peg.get().on = jest.fn(); + peg.get().off = jest.fn(); // Reset the state of the store RoomViewStore.reset(); diff --git a/yarn.lock b/yarn.lock index ce8543a251..51ea173f58 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6249,9 +6249,9 @@ mathml-tag-names@^2.1.3: resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3" integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg== -"matrix-analytics-events@github:matrix-org/matrix-analytics-events.git#df9c0312f51911a7364810466d041f2b79e7e080": +"matrix-analytics-events@github:matrix-org/matrix-analytics-events.git#8e75aaf0b3e045587daeaf97a7691dbfda2f20c0": version "0.0.1" - resolved "https://codeload.github.com/matrix-org/matrix-analytics-events/tar.gz/df9c0312f51911a7364810466d041f2b79e7e080" + resolved "https://codeload.github.com/matrix-org/matrix-analytics-events/tar.gz/8e75aaf0b3e045587daeaf97a7691dbfda2f20c0" matrix-events-sdk@^0.0.1-beta.6: version "0.0.1-beta.6"