More posthog tracking around joining rooms and room search (#7807)

This commit is contained in:
Michael Telatynski 2022-02-17 18:03:27 +00:00 committed by GitHub
parent e997676ae2
commit 658590e5bc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
59 changed files with 276 additions and 116 deletions

View file

@ -91,7 +91,7 @@
"linkifyjs": "^4.0.0-beta.4", "linkifyjs": "^4.0.0-beta.4",
"lodash": "^4.17.20", "lodash": "^4.17.20",
"maplibre-gl": "^1.15.2", "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-events-sdk": "^0.0.1-beta.6",
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop", "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop",
"matrix-widget-api": "^0.1.0-beta.18", "matrix-widget-api": "^0.1.0-beta.18",

View file

@ -189,7 +189,7 @@ export default abstract class BasePlatform {
const payload: ViewRoomPayload = { const payload: ViewRoomPayload = {
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: room.roomId, room_id: room.roomId,
_trigger: "Notification", metricsTrigger: "Notification",
}; };
if (ev.getThread()) { if (ev.getThread()) {

View file

@ -891,7 +891,7 @@ export default class CallHandler extends EventEmitter {
dis.dispatch<ViewRoomPayload>({ dis.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: roomId, room_id: roomId,
_trigger: "WebAcceptCall", metricsTrigger: "WebAcceptCall",
}); });
} }
@ -929,7 +929,7 @@ export default class CallHandler extends EventEmitter {
dis.dispatch<ViewRoomPayload>({ dis.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: roomId, room_id: roomId,
_trigger: "WebDialPad", metricsTrigger: "WebDialPad",
}); });
await this.placeMatrixCall(roomId, CallType.Voice, null); await this.placeMatrixCall(roomId, CallType.Voice, null);
@ -962,7 +962,7 @@ export default class CallHandler extends EventEmitter {
room_id: dmRoomId, room_id: dmRoomId,
should_peek: false, should_peek: false,
joining: false, joining: false,
_trigger: undefined, // other metricsTrigger: undefined, // other
}); });
} else { } else {
try { try {

View file

@ -350,8 +350,8 @@ export const Commands = [
event_id: eventId, event_id: eventId,
highlighted: true, highlighted: true,
room_id: roomId, room_id: roomId,
_trigger: "SlashCommand", metricsTrigger: "SlashCommand",
_viaKeyboard: true, metricsViaKeyboard: true,
}); });
})()); })());
} }
@ -615,8 +615,8 @@ export const Commands = [
action: Action.ViewRoom, action: Action.ViewRoom,
room_alias: roomAlias, room_alias: roomAlias,
auto_join: true, auto_join: true,
_trigger: "SlashCommand", metricsTrigger: "SlashCommand",
_viaKeyboard: true, metricsViaKeyboard: true,
}); });
return success(); return success();
} else if (params[0][0] === '!') { } else if (params[0][0] === '!') {
@ -627,8 +627,8 @@ export const Commands = [
room_id: roomId, room_id: roomId,
via_servers: viaServers, // for the rejoin button via_servers: viaServers, // for the rejoin button
auto_join: true, auto_join: true,
_trigger: "SlashCommand", metricsTrigger: "SlashCommand",
_viaKeyboard: true, metricsViaKeyboard: true,
}); });
return success(); return success();
} else if (isPermalink) { } else if (isPermalink) {
@ -653,8 +653,8 @@ export const Commands = [
const dispatch: ViewRoomPayload = { const dispatch: ViewRoomPayload = {
action: Action.ViewRoom, action: Action.ViewRoom,
auto_join: true, auto_join: true,
_trigger: "SlashCommand", metricsTrigger: "SlashCommand",
_viaKeyboard: true, metricsViaKeyboard: true,
}; };
if (entity[0] === '!') dispatch["room_id"] = entity; if (entity[0] === '!') dispatch["room_id"] = entity;
@ -1155,8 +1155,8 @@ export const Commands = [
dis.dispatch<ViewRoomPayload>({ dis.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: roomId, room_id: roomId,
_trigger: "SlashCommand", metricsTrigger: "SlashCommand",
_viaKeyboard: true, metricsViaKeyboard: true,
}); });
})()); })());
}, },
@ -1179,8 +1179,8 @@ export const Commands = [
dis.dispatch<ViewRoomPayload>({ dis.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: roomId, room_id: roomId,
_trigger: "SlashCommand", metricsTrigger: "SlashCommand",
_viaKeyboard: true, metricsViaKeyboard: true,
}); });
if (msg) { if (msg) {
cli.sendTextMessage(roomId, msg); cli.sendTextMessage(roomId, msg);

View file

@ -535,7 +535,7 @@ const onPinnedOrUnpinnedMessageClick = (messageId: string, roomId: string): void
event_id: messageId, event_id: messageId,
highlighted: true, highlighted: true,
room_id: roomId, room_id: roomId,
_trigger: undefined, // room doesn't change metricsTrigger: undefined, // room doesn't change
}); });
}; };

View file

@ -1084,7 +1084,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
dis.dispatch<ViewRoomPayload>({ dis.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: dmRooms[0], room_id: dmRooms[0],
_trigger: "MessageUser", metricsTrigger: "MessageUser",
}); });
} else { } else {
dis.dispatch({ dis.dispatch({
@ -1356,7 +1356,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
dis.dispatch<ViewRoomPayload>({ dis.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: localStorage.getItem('mx_last_room_id'), 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<IProps, IState> {
}, },
room_alias: undefined, room_alias: undefined,
room_id: undefined, room_id: undefined,
_trigger: undefined, // unknown or external trigger metricsTrigger: undefined, // unknown or external trigger
}; };
if (roomString[0] === '#') { if (roomString[0] === '#') {
payload.room_alias = roomString; payload.room_alias = roomString;

View file

@ -489,7 +489,7 @@ export default class RoomDirectory extends React.Component<IProps, IState> {
action: Action.ViewRoom, action: Action.ViewRoom,
auto_join: autoJoin, auto_join: autoJoin,
should_peek: shouldPeek, should_peek: shouldPeek,
_trigger: "RoomDirectory", metricsTrigger: "RoomDirectory",
}; };
if (room) { if (room) {
// Don't let the user view a room they won't be able to either // Don't let the user view a room they won't be able to either

View file

@ -102,6 +102,7 @@ import { RightPanelPhases } from '../../stores/right-panel/RightPanelStorePhases
import { ActionPayload } from "../../dispatcher/payloads"; import { ActionPayload } from "../../dispatcher/payloads";
import { KeyBindingAction } from "../../accessibility/KeyboardShortcuts"; import { KeyBindingAction } from "../../accessibility/KeyboardShortcuts";
import { ViewRoomPayload } from "../../dispatcher/payloads/ViewRoomPayload"; import { ViewRoomPayload } from "../../dispatcher/payloads/ViewRoomPayload";
import { JoinRoomPayload } from "../../dispatcher/payloads/JoinRoomPayload";
const DEBUG = false; const DEBUG = false;
let debuglog = function(msg: string) {}; let debuglog = function(msg: string) {};
@ -776,7 +777,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
event_id: this.state.initialEventId, event_id: this.state.initialEventId,
highlighted: false, highlighted: false,
replyingToEvent: this.state.replyToEvent, 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<IRoomProps, IRoomState> {
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: roomId, room_id: roomId,
deferred_action: payload, deferred_action: payload,
_trigger: "MessageSearch", metricsTrigger: "MessageSearch",
}); });
}); });
} }
@ -1179,7 +1180,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
dis.dispatch<ViewRoomPayload>({ dis.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: this.state.room.roomId, 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 return; // this event cannot affect permissions so bail
} }
@ -1283,10 +1284,11 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
} else { } else {
Promise.resolve().then(() => { Promise.resolve().then(() => {
const signUrl = this.props.threepidInvite?.signUrl; const signUrl = this.props.threepidInvite?.signUrl;
dis.dispatch({ dis.dispatch<JoinRoomPayload>({
action: Action.JoinRoom, action: Action.JoinRoom,
roomId: this.getRoomId(), roomId: this.getRoomId(),
opts: { inviteSignUrl: signUrl }, opts: { inviteSignUrl: signUrl },
metricsTrigger: this.state.room?.getMyMembership() === "invite" ? "Invite" : "RoomPreview",
}); });
return Promise.resolve(); return Promise.resolve();
}); });
@ -1651,7 +1653,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
dis.dispatch<ViewRoomPayload>({ dis.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: this.state.room.roomId, room_id: this.state.room.roomId,
_trigger: undefined, // room doesn't change metricsTrigger: undefined, // room doesn't change
}); });
} else { } else {
// Otherwise we have to jump manually // Otherwise we have to jump manually
@ -1787,7 +1789,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
dis.dispatch<ViewRoomPayload>({ dis.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: oldRoom.roomId, room_id: oldRoom.roomId,
_trigger: "Predecessor", metricsTrigger: "Predecessor",
}); });
}; };

View file

@ -63,6 +63,7 @@ import { IOOBData } from "../../stores/ThreepidInviteStore";
import { awaitRoomDownSync } from "../../utils/RoomUpgrade"; import { awaitRoomDownSync } from "../../utils/RoomUpgrade";
import RoomViewStore from "../../stores/RoomViewStore"; import RoomViewStore from "../../stores/RoomViewStore";
import { ViewRoomPayload } from "../../dispatcher/payloads/ViewRoomPayload"; import { ViewRoomPayload } from "../../dispatcher/payloads/ViewRoomPayload";
import { JoinRoomReadyPayload } from "../../dispatcher/payloads/JoinRoomReadyPayload";
interface IProps { interface IProps {
space: Room; space: Room;
@ -339,7 +340,7 @@ export const showRoom = (cli: MatrixClient, hierarchy: RoomHierarchy, roomId: st
name: room.name || roomAlias || _t("Unnamed room"), name: room.name || roomAlias || _t("Unnamed room"),
roomType, roomType,
} as IOOBData, } 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) || []), viaServers: Array.from(hierarchy.viaMap.get(roomId) || []),
}); });
prom.catch(err => { prom.then(() => {
dis.dispatch<JoinRoomReadyPayload>({
action: Action.JoinRoomReady,
roomId,
metricsTrigger: "SpaceHierarchy",
});
}, err => {
RoomViewStore.showJoinRoomError(err, roomId); RoomViewStore.showJoinRoomError(err, roomId);
}); });

View file

@ -867,7 +867,7 @@ export default class SpaceRoomView extends React.PureComponent<IProps, IState> {
defaultDispatcher.dispatch<ViewRoomPayload>({ defaultDispatcher.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: this.state.firstRoomId, room_id: this.state.firstRoomId,
_trigger: undefined, // other metricsTrigger: undefined, // other
}); });
return; return;
} }

View file

@ -202,7 +202,7 @@ export default class ThreadView extends React.Component<IProps, IState> {
event_id: this.props.initialEvent?.getId(), event_id: this.props.initialEvent?.getId(),
highlighted: false, highlighted: false,
replyingToEvent: this.state.replyToEvent, replyingToEvent: this.state.replyToEvent,
_trigger: undefined, // room doesn't change metricsTrigger: undefined, // room doesn't change
}); });
} }
}; };

View file

@ -1195,7 +1195,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
dis.dispatch<ViewRoomPayload>({ dis.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: this.props.timelineSet.room.roomId, room_id: this.props.timelineSet.room.roomId,
_trigger: undefined, // room doesn't change metricsTrigger: undefined, // room doesn't change
}); });
}; };
} }

View file

@ -269,7 +269,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
event_id: this.props.mxEvent.getId(), event_id: this.props.mxEvent.getId(),
highlighted: true, highlighted: true,
room_id: this.props.mxEvent.getRoomId(), room_id: this.props.mxEvent.getRoomId(),
_trigger: undefined, // room doesn't change metricsTrigger: undefined, // room doesn't change
}); });
this.closeMenu(); this.closeMenu();
}; };

View file

@ -253,8 +253,8 @@ const RoomContextMenu = ({ room, onFinished, ...props }: IProps) => {
dis.dispatch<ViewRoomPayload>({ dis.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: room.roomId, room_id: room.roomId,
_trigger: "RoomList", metricsTrigger: "RoomList",
_viaKeyboard: ev.type !== "click", metricsViaKeyboard: ev.type !== "click",
}, true); }, true);
}; };

View file

@ -120,7 +120,7 @@ const SpaceContextMenu = ({ space, hideHeader, onFinished, ...props }: IProps) =
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: space.roomId, room_id: space.roomId,
forceTimeline: true, forceTimeline: true,
_trigger: undefined, // room doesn't change metricsTrigger: undefined, // room doesn't change
}); });
onFinished(); onFinished();
}; };
@ -197,7 +197,7 @@ const SpaceContextMenu = ({ space, hideHeader, onFinished, ...props }: IProps) =
defaultDispatcher.dispatch<ViewRoomPayload>({ defaultDispatcher.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: space.roomId, room_id: space.roomId,
_trigger: undefined, // other metricsTrigger: undefined, // other
}); });
onFinished(); onFinished();
}; };

View file

@ -81,7 +81,7 @@ const ThreadListContextMenu: React.FC<IExtendedProps> = ({
event_id: mxEvent.getId(), event_id: mxEvent.getId(),
highlighted: true, highlighted: true,
room_id: mxEvent.getRoomId(), room_id: mxEvent.getRoomId(),
_trigger: undefined, // room doesn't change metricsTrigger: undefined, // room doesn't change
}); });
closeThreadOptions(); closeThreadOptions();
}, [mxEvent, closeThreadOptions]); }, [mxEvent, closeThreadOptions]);

View file

@ -104,7 +104,7 @@ export default class CreateCommunityPrototypeDialog extends React.PureComponent<
dis.dispatch<ViewRoomPayload>({ dis.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: result.room_id, room_id: result.room_id,
_trigger: undefined, // Deprecated groups metricsTrigger: undefined, // Deprecated groups
}); });
showCommunityRoomInviteDialog(result.room_id, this.state.name); showCommunityRoomInviteDialog(result.room_id, this.state.name);
} else { } else {

View file

@ -230,7 +230,7 @@ const CreateSpaceFromCommunityDialog: React.FC<IProps> = ({ matrixClient: cli, g
dis.dispatch<ViewRoomPayload>({ dis.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: roomId, room_id: roomId,
_trigger: undefined, // other metricsTrigger: undefined, // other
}); });
}; };

View file

@ -81,8 +81,8 @@ const Entry: React.FC<IEntryProps> = ({ room, event, matrixClient: cli, onFinish
dis.dispatch<ViewRoomPayload>({ dis.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: room.roomId, room_id: room.roomId,
_trigger: "WebForwardShortcut", metricsTrigger: "WebForwardShortcut",
_viaKeyboard: ev.type !== "click", metricsViaKeyboard: ev.type !== "click",
}); });
onFinished(true); onFinished(true);
}; };

View file

@ -682,7 +682,7 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
room_id: existingRoom.roomId, room_id: existingRoom.roomId,
should_peek: false, should_peek: false,
joining: false, joining: false,
_trigger: "MessageUser", metricsTrigger: "MessageUser",
}); });
this.props.onFinished(true); this.props.onFinished(true);
return; return;

View file

@ -94,6 +94,7 @@ export default class RoomSettingsDialog extends React.Component<IProps, IState>
_td("General"), _td("General"),
"mx_RoomSettingsDialog_settingsIcon", "mx_RoomSettingsDialog_settingsIcon",
<GeneralRoomSettingsTab roomId={this.props.roomId} />, <GeneralRoomSettingsTab roomId={this.props.roomId} />,
"RoomSettingsGeneral",
)); ));
tabs.push(new Tab( tabs.push(new Tab(
ROOM_SECURITY_TAB, ROOM_SECURITY_TAB,
@ -103,18 +104,21 @@ export default class RoomSettingsDialog extends React.Component<IProps, IState>
roomId={this.props.roomId} roomId={this.props.roomId}
closeSettingsFn={() => this.props.onFinished(true)} closeSettingsFn={() => this.props.onFinished(true)}
/>, />,
"RoomSettingsSecurityPrivacy",
)); ));
tabs.push(new Tab( tabs.push(new Tab(
ROOM_ROLES_TAB, ROOM_ROLES_TAB,
_td("Roles & Permissions"), _td("Roles & Permissions"),
"mx_RoomSettingsDialog_rolesIcon", "mx_RoomSettingsDialog_rolesIcon",
<RolesRoomSettingsTab roomId={this.props.roomId} />, <RolesRoomSettingsTab roomId={this.props.roomId} />,
"RoomSettingsRolesPermissions",
)); ));
tabs.push(new Tab( tabs.push(new Tab(
ROOM_NOTIFICATIONS_TAB, ROOM_NOTIFICATIONS_TAB,
_td("Notifications"), _td("Notifications"),
"mx_RoomSettingsDialog_notificationsIcon", "mx_RoomSettingsDialog_notificationsIcon",
<NotificationSettingsTab roomId={this.props.roomId} closeSettingsFn={() => this.props.onFinished(true)} />, <NotificationSettingsTab roomId={this.props.roomId} closeSettingsFn={() => this.props.onFinished(true)} />,
"RoomSettingsNotifications",
)); ));
if (SettingsStore.getValue("feature_bridge_state")) { if (SettingsStore.getValue("feature_bridge_state")) {
@ -123,6 +127,7 @@ export default class RoomSettingsDialog extends React.Component<IProps, IState>
_td("Bridges"), _td("Bridges"),
"mx_RoomSettingsDialog_bridgesIcon", "mx_RoomSettingsDialog_bridgesIcon",
<BridgeSettingsTab roomId={this.props.roomId} />, <BridgeSettingsTab roomId={this.props.roomId} />,
"RoomSettingsBridges",
)); ));
} }
@ -135,6 +140,7 @@ export default class RoomSettingsDialog extends React.Component<IProps, IState>
roomId={this.props.roomId} roomId={this.props.roomId}
closeSettingsFn={() => this.props.onFinished(true)} closeSettingsFn={() => this.props.onFinished(true)}
/>, />,
"RoomSettingsAdvanced",
)); ));
} }

View file

@ -30,6 +30,7 @@ import { normalize } from "matrix-js-sdk/src/utils";
import { IHierarchyRoom } from "matrix-js-sdk/src/@types/spaces"; import { IHierarchyRoom } from "matrix-js-sdk/src/@types/spaces";
import { RoomHierarchy } from "matrix-js-sdk/src/room-hierarchy"; import { RoomHierarchy } from "matrix-js-sdk/src/room-hierarchy";
import { RoomType } from "matrix-js-sdk/src/@types/event"; 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 { IDialogProps } from "./IDialogProps";
import { _t } from "../../../languageHandler"; import { _t } from "../../../languageHandler";
@ -72,6 +73,7 @@ import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
import { getMetaSpaceName } from "../../../stores/spaces"; import { getMetaSpaceName } from "../../../stores/spaces";
import { getKeyBindingsManager } from "../../../KeyBindingsManager"; import { getKeyBindingsManager } from "../../../KeyBindingsManager";
import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts"; import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts";
import { PosthogAnalytics } from "../../../PosthogAnalytics";
import { getCachedRoomIDForAlias } from "../../../RoomAliasCache"; import { getCachedRoomIDForAlias } from "../../../RoomAliasCache";
const MAX_RECENT_SEARCHES = 10; const MAX_RECENT_SEARCHES = 10;
@ -205,6 +207,26 @@ type Result = IRoomResult | IResult;
const isRoomResult = (result: any): result is IRoomResult => !!result?.room; 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<WebSearchEvent>({
eventName: "WebSearch",
viaSpotlight,
numResults,
queryLength,
});
}, 1000);
return () => {
clearTimeout(timeoutId);
};
}, [numResults, queryLength, viaSpotlight]);
};
const SpotlightDialog: React.FC<IProps> = ({ initialText = "", onFinished }) => { const SpotlightDialog: React.FC<IProps> = ({ initialText = "", onFinished }) => {
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
const rovingContext = useContext(RovingTabIndexContext); const rovingContext = useContext(RovingTabIndexContext);
@ -270,6 +292,9 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", onFinished }) =>
return results; return results;
}, [possibleResults, trimmedQuery]); }, [possibleResults, trimmedQuery]);
const numResults = trimmedQuery ? people.length + rooms.length + spaces.length : 0;
useWebSearchMetrics(numResults, query.length, true);
const activeSpace = SpaceStore.instance.activeSpaceRoom; const activeSpace = SpaceStore.instance.activeSpaceRoom;
const [spaceResults, spaceResultsLoading] = useSpaceResults(activeSpace, query); const [spaceResults, spaceResultsLoading] = useSpaceResults(activeSpace, query);
@ -310,8 +335,8 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", onFinished }) =>
defaultDispatcher.dispatch<ViewRoomPayload>({ defaultDispatcher.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: roomId, room_id: roomId,
_trigger: "WebUnifiedSearch", metricsTrigger: "WebUnifiedSearch",
_viaKeyboard: viaKeyboard, metricsViaKeyboard: viaKeyboard,
}); });
onFinished(); onFinished();
}; };
@ -429,8 +454,8 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", onFinished }) =>
action: Action.ViewRoom, action: Action.ViewRoom,
room_alias: trimmedQuery, room_alias: trimmedQuery,
auto_join: true, auto_join: true,
_trigger: "WebUnifiedSearch", metricsTrigger: "WebUnifiedSearch",
_viaKeyboard: ev.type !== "click", metricsViaKeyboard: ev.type !== "click",
}); });
onFinished(); onFinished();
}} }}
@ -670,6 +695,7 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", onFinished }) =>
onFinished={onFinished} onFinished={onFinished}
hasCancel={false} hasCancel={false}
onKeyDown={onDialogKeyDown} onKeyDown={onDialogKeyDown}
screenName="UnifiedSearch"
> >
<div className="mx_SpotlightDialog_searchBox mx_textinput"> <div className="mx_SpotlightDialog_searchBox mx_textinput">
<input <input

View file

@ -199,7 +199,11 @@ export default class UserSettingsDialog extends React.Component<IProps, IState>
title={_t("Settings")} title={_t("Settings")}
> >
<div className='mx_SettingsDialog_content'> <div className='mx_SettingsDialog_content'>
<TabbedView tabs={this.getTabs()} initialTabId={this.props.initialTabId} /> <TabbedView
tabs={this.getTabs()}
initialTabId={this.props.initialTabId}
screenName="UserSettings"
/>
</div> </div>
</BaseDialog> </BaseDialog>
); );

View file

@ -339,7 +339,7 @@ export default class ImageView extends React.Component<IProps, IState> {
event_id: this.props.mxEvent.getId(), event_id: this.props.mxEvent.getId(),
highlighted: true, highlighted: true,
room_id: this.props.mxEvent.getRoomId(), room_id: this.props.mxEvent.getRoomId(),
_trigger: undefined, // room doesn't change metricsTrigger: undefined, // room doesn't change
}); });
this.props.onFinished(); this.props.onFinished();
}; };

View file

@ -147,7 +147,7 @@ export default class DateSeparator extends React.Component<IProps, IState> {
event_id: eventId, event_id: eventId,
highlighted: true, highlighted: true,
room_id: roomId, room_id: roomId,
_trigger: undefined, // room doesn't change metricsTrigger: undefined, // room doesn't change
}); });
} catch (e) { } catch (e) {
const code = e.errcode || e.statusCode; const code = e.errcode || e.statusCode;

View file

@ -45,8 +45,8 @@ export default class RoomCreate extends React.Component<IProps> {
event_id: predecessor['event_id'], event_id: predecessor['event_id'],
highlighted: true, highlighted: true,
room_id: predecessor['room_id'], room_id: predecessor['room_id'],
_trigger: "Predecessor", metricsTrigger: "Predecessor",
_viaKeyboard: e.type !== "click", metricsViaKeyboard: e.type !== "click",
}); });
}; };

View file

@ -151,7 +151,7 @@ export default class TimelineCard extends React.Component<IProps, IState> {
event_id: this.state.initialEventId, event_id: this.state.initialEventId,
highlighted: false, highlighted: false,
replyingToEvent: this.state.replyToEvent, replyingToEvent: this.state.replyToEvent,
_trigger: undefined, // room doesn't change metricsTrigger: undefined, // room doesn't change
}); });
} }
}; };

View file

@ -131,8 +131,8 @@ async function openDMForUser(matrixClient: MatrixClient, userId: string, viaKeyb
dis.dispatch<ViewRoomPayload>({ dis.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: lastActiveRoom.roomId, room_id: lastActiveRoom.roomId,
_trigger: "MessageUser", metricsTrigger: "MessageUser",
_viaKeyboard: viaKeyboard, metricsViaKeyboard: viaKeyboard,
}); });
return; return;
} }
@ -397,7 +397,7 @@ const UserOptionsSection: React.FC<{
highlighted: true, highlighted: true,
event_id: room.getEventReadUpTo(member.userId), event_id: room.getEventReadUpTo(member.userId),
room_id: member.roomId, room_id: member.roomId,
_trigger: undefined, // room doesn't change metricsTrigger: undefined, // room doesn't change
}); });
}; };

View file

@ -720,7 +720,7 @@ export default class EventTile extends React.Component<IProps, IState> {
event_id: this.props.mxEvent.getId(), event_id: this.props.mxEvent.getId(),
highlighted: true, highlighted: true,
room_id: this.props.mxEvent.getRoomId(), 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<IProps, IState> {
event_id: this.props.mxEvent.getId(), event_id: this.props.mxEvent.getId(),
highlighted: true, highlighted: true,
room_id: this.props.mxEvent.getRoomId(), room_id: this.props.mxEvent.getRoomId(),
_trigger: this.props.timelineRenderingType === TimelineRenderingType.Search ? "MessageSearch" : undefined, metricsTrigger: this.props.timelineRenderingType === TimelineRenderingType.Search
? "MessageSearch"
: undefined,
}); });
}; };

View file

@ -237,8 +237,8 @@ export default class MessageComposer extends React.Component<IProps, IState> {
// Try to join via the server that sent the event. This converts @something:example.org // 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"). // into a server domain by splitting on colons and ignoring the first entry ("@something").
via_servers: viaServers, via_servers: viaServers,
_trigger: "Tombstone", metricsTrigger: "Tombstone",
_viaKeyboard: ev.type !== "click", metricsViaKeyboard: ev.type !== "click",
}); });
}; };

View file

@ -51,7 +51,7 @@ export default class PinnedEventTile extends React.Component<IProps> {
event_id: this.props.event.getId(), event_id: this.props.event.getId(),
highlighted: true, highlighted: true,
room_id: this.props.event.getRoomId(), room_id: this.props.event.getRoomId(),
_trigger: undefined, // room doesn't change metricsTrigger: undefined, // room doesn't change
}); });
}; };

View file

@ -44,8 +44,8 @@ const RecentlyViewedButton = () => {
dis.dispatch<ViewRoomPayload>({ dis.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: crumb.roomId, room_id: crumb.roomId,
_trigger: "WebVerticalBreadcrumbs", metricsTrigger: "WebVerticalBreadcrumbs",
_viaKeyboard: ev.type !== "click", metricsViaKeyboard: ev.type !== "click",
}); });
tooltipRef.current?.hideTooltip(); tooltipRef.current?.hideTooltip();
}} }}

View file

@ -100,7 +100,7 @@ export default class ReplyTile extends React.PureComponent<IProps> {
event_id: this.props.mxEvent.getId(), event_id: this.props.mxEvent.getId(),
highlighted: true, highlighted: true,
room_id: this.props.mxEvent.getRoomId(), room_id: this.props.mxEvent.getRoomId(),
_trigger: undefined, // room doesn't change metricsTrigger: undefined, // room doesn't change
}); });
} }
} }

View file

@ -110,8 +110,8 @@ export default class RoomBreadcrumbs extends React.PureComponent<IProps, IState>
defaultDispatcher.dispatch<ViewRoomPayload>({ defaultDispatcher.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: room.roomId, room_id: room.roomId,
_trigger: "WebHorizontalBreadcrumbs", metricsTrigger: "WebHorizontalBreadcrumbs",
_viaKeyboard: viaKeyboard, metricsViaKeyboard: viaKeyboard,
}); });
}; };

View file

@ -44,7 +44,7 @@ export default class RoomDetailList extends React.Component<IProps> {
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: room.roomId, room_id: room.roomId,
room_alias: room.getCanonicalAlias() || (room.getAltAliases() || [])[0], room_alias: room.getCanonicalAlias() || (room.getAltAliases() || [])[0],
_trigger: undefined, // Deprecated groups metricsTrigger: undefined, // Deprecated groups
}); });
}; };

View file

@ -221,7 +221,7 @@ const UntaggedAuxButton = ({ tabIndex }: IAuxButtonProps) => {
defaultDispatcher.dispatch<ViewRoomPayload>({ defaultDispatcher.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: activeSpace.roomId, room_id: activeSpace.roomId,
_trigger: undefined, // other metricsTrigger: undefined, // other
}); });
PosthogTrackers.trackInteraction("WebRoomListRoomsSublistPlusMenuExploreRoomsItem", e); PosthogTrackers.trackInteraction("WebRoomListRoomsSublistPlusMenuExploreRoomsItem", e);
}} }}
@ -424,8 +424,8 @@ export default class RoomList extends React.PureComponent<IProps, IState> {
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: room.roomId, room_id: room.roomId,
show_room_tile: true, // to make sure the room gets scrolled into view show_room_tile: true, // to make sure the room gets scrolled into view
_trigger: "WebKeyboardShortcut", metricsTrigger: "WebKeyboardShortcut",
_viaKeyboard: true, metricsViaKeyboard: true,
}); });
} }
} else if (payload.action === Action.PstnSupportUpdated) { } else if (payload.action === Action.PstnSupportUpdated) {
@ -509,7 +509,7 @@ export default class RoomList extends React.PureComponent<IProps, IState> {
defaultDispatcher.dispatch<ViewRoomPayload>({ defaultDispatcher.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: this.props.activeSpace, room_id: this.props.activeSpace,
_trigger: undefined, // other metricsTrigger: undefined, // other
}); });
PosthogTrackers.trackInteraction("WebRoomListRoomsSublistPlusMenuExploreRoomsItem", ev); PosthogTrackers.trackInteraction("WebRoomListRoomsSublistPlusMenuExploreRoomsItem", ev);
} else { } else {
@ -542,8 +542,8 @@ export default class RoomList extends React.PureComponent<IProps, IState> {
avatarUrl: room.avatar_url, avatarUrl: room.avatar_url,
name, name,
}, },
_trigger: "RoomList", metricsTrigger: "RoomList",
_viaKeyboard: ev.type !== "click", metricsViaKeyboard: ev.type !== "click",
}); });
}; };
return ( return (

View file

@ -61,6 +61,7 @@ import TooltipTarget from "../elements/TooltipTarget";
import { BetaPill } from "../beta/BetaCard"; import { BetaPill } from "../beta/BetaCard";
import PosthogTrackers from "../../../PosthogTrackers"; import PosthogTrackers from "../../../PosthogTrackers";
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload"; import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
import { useWebSearchMetrics } from "../dialogs/SpotlightDialog";
const contextMenuBelow = (elementRect: DOMRect) => { const contextMenuBelow = (elementRect: DOMRect) => {
// align the context menu's icons with the icon which opened the context menu // align the context menu's icons with the icon which opened the context menu
@ -108,7 +109,7 @@ const PrototypeCommunityContextMenu = (props: ComponentProps<typeof SpaceContext
dis.dispatch<ViewRoomPayload>({ dis.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: chat.roomId, room_id: chat.roomId,
_trigger: undefined, // Deprecated groups metricsTrigger: undefined, // Deprecated groups
}, true); }, true);
RightPanelStore.instance.setCard({ phase: RightPanelPhases.RoomMemberList }, undefined, chat.roomId); RightPanelStore.instance.setCard({ phase: RightPanelPhases.RoomMemberList }, undefined, chat.roomId);
} else { } else {
@ -177,14 +178,18 @@ const RoomListHeader = ({ spacePanelDisabled, onVisibilityChange }: IProps) => {
}); });
const joiningRooms = useJoiningRooms(); const joiningRooms = useJoiningRooms();
const filterCondition = RoomListStore.instance.getFirstNameFilterCondition();
const count = useEventEmitterState(RoomListStore.instance, LISTS_UPDATE_EVENT, () => { const count = useEventEmitterState(RoomListStore.instance, LISTS_UPDATE_EVENT, () => {
if (RoomListStore.instance.getFirstNameFilterCondition()) { if (filterCondition) {
return Object.values(RoomListStore.instance.orderedLists).flat(1).length; return Object.values(RoomListStore.instance.orderedLists).flat(1).length;
} else { } else {
return null; 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); const spaceName = useEventEmitterState(activeSpace, "Room.name", () => activeSpace?.name);
useEffect(() => { useEffect(() => {
@ -279,7 +284,7 @@ const RoomListHeader = ({ spacePanelDisabled, onVisibilityChange }: IProps) => {
defaultDispatcher.dispatch<ViewRoomPayload>({ defaultDispatcher.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: activeSpace.roomId, room_id: activeSpace.roomId,
_trigger: undefined, // other metricsTrigger: undefined, // other
}); });
closePlusMenu(); closePlusMenu();
PosthogTrackers.trackInteraction("WebRoomListHeaderPlusMenuExploreRoomsItem", e); PosthogTrackers.trackInteraction("WebRoomListHeaderPlusMenuExploreRoomsItem", e);

View file

@ -433,8 +433,8 @@ export default class RoomSublist extends React.Component<IProps, IState> {
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: room.roomId, room_id: room.roomId,
show_room_tile: true, // to make sure the room gets scrolled into view show_room_tile: true, // to make sure the room gets scrolled into view
_trigger: "WebRoomListNotificationBadge", metricsTrigger: "WebRoomListNotificationBadge",
_viaKeyboard: ev.type !== "click", metricsViaKeyboard: ev.type !== "click",
}); });
} }
}; };

View file

@ -245,8 +245,8 @@ export default class RoomTile extends React.PureComponent<IProps, IState> {
show_room_tile: true, // make sure the room is visible in the list show_room_tile: true, // make sure the room is visible in the list
room_id: this.props.room.roomId, room_id: this.props.room.roomId,
clear_search: (ev && (ev.key === Key.ENTER || ev.key === Key.SPACE)), clear_search: (ev && (ev.key === Key.ENTER || ev.key === Key.SPACE)),
_trigger: "RoomList", metricsTrigger: "RoomList",
_viaKeyboard: ev.type !== "click", metricsViaKeyboard: ev.type !== "click",
}); });
}; };

View file

@ -271,7 +271,7 @@ const JoinRuleSettings = ({ room, promptUpgrade, aliasWarning, onError, beforeCh
dis.dispatch<ViewRoomPayload>({ dis.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: roomId, room_id: roomId,
_trigger: undefined, // other metricsTrigger: undefined, // other
}); });
// open new settings on this tab // open new settings on this tab

View file

@ -95,8 +95,8 @@ export default class AdvancedRoomSettingsTab extends React.Component<IProps, ISt
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: this.state.oldRoomId, room_id: this.state.oldRoomId,
event_id: this.state.oldEventId, event_id: this.state.oldEventId,
_trigger: "WebPredecessorSettings", metricsTrigger: "WebPredecessorSettings",
_viaKeyboard: e.type !== "click", metricsViaKeyboard: e.type !== "click",
}); });
this.props.closeSettingsFn(); this.props.closeSettingsFn();
}; };

View file

@ -117,7 +117,7 @@ const CommunityMigrator = ({ onFinished }) => {
dis.dispatch<ViewRoomPayload>({ dis.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: community.spaceId, room_id: community.spaceId,
_trigger: undefined, // other metricsTrigger: undefined, // other
}); });
onFinished(); onFinished();
} else { } else {

View file

@ -115,7 +115,7 @@ export default class VerificationRequestToast extends React.PureComponent<IProps
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: request.channel.roomId, room_id: request.channel.roomId,
should_peek: false, should_peek: false,
_trigger: "VerificationRequest", metricsTrigger: "VerificationRequest",
}); });
const member = cli.getUser(request.otherUserId); const member = cli.getUser(request.otherUserId);
RightPanelStore.instance.setCards( RightPanelStore.instance.setCards(

View file

@ -41,7 +41,7 @@ const onExpandClick = (roomId: string) => {
dis.dispatch<ViewRoomPayload>({ dis.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: roomId, room_id: roomId,
_trigger: "WebFloatingCallWindow", metricsTrigger: "WebFloatingCallWindow",
}); });
}; };

View file

@ -218,7 +218,7 @@ export default class PipView extends React.Component<IProps, IState> {
dis.dispatch<ViewRoomPayload>({ dis.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: callRoomId ?? widgetRoomId, room_id: callRoomId ?? widgetRoomId,
_trigger: "WebFloatingCallWindow", metricsTrigger: "WebFloatingCallWindow",
}); });
} }
}; };

View file

@ -264,7 +264,7 @@ export default async function createRoom(opts: IOpts): Promise<string | null> {
// stream, if it hasn't already. // stream, if it hasn't already.
joining: true, joining: true,
justCreatedOpts: opts, justCreatedOpts: opts,
_trigger: "Created", metricsTrigger: "Created",
}); });
} }
return roomId; return roomId;

View file

@ -153,12 +153,12 @@ export enum Action {
UploadCanceled = "upload_canceled", 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", 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", JoinRoomReady = "join_room_ready",
@ -168,7 +168,7 @@ export enum Action {
JoinRoomError = "join_room_error", 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", ComposerInsert = "composer_insert",

View file

@ -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<ActionPayload, "action"> {
action: Action.JoinRoom;
roomId: string;
opts?: IJoinRoomOpts;
// additional parameters for the purpose of metrics & instrumentation
metricsTrigger: JoinedRoomEvent["trigger"];
}
/* eslint-enable camelcase */

View file

@ -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<ActionPayload, "action"> {
action: Action.JoinRoomReady;
roomId: string;
// additional parameters for the purpose of metrics & instrumentation
metricsTrigger: JoinedRoomEvent["trigger"];
}
/* eslint-enable camelcase */

View file

@ -48,7 +48,7 @@ export interface ViewRoomPayload extends Pick<ActionPayload, "action"> {
deferred_action?: ActionPayload; // Action to fire after MatrixChat handles this ViewRoom action deferred_action?: ActionPayload; // Action to fire after MatrixChat handles this ViewRoom action
// additional parameters for the purpose of metrics & instrumentation // additional parameters for the purpose of metrics & instrumentation
_trigger: ViewRoomEvent["trigger"]; metricsTrigger: ViewRoomEvent["trigger"];
_viaKeyboard?: ViewRoomEvent["viaKeyboard"]; metricsViaKeyboard?: ViewRoomEvent["viaKeyboard"];
} }
/* eslint-enable camelcase */ /* eslint-enable camelcase */

View file

@ -120,8 +120,8 @@ function onAliasClick(event: MouseEvent, roomAlias: string) {
dis.dispatch<ViewRoomPayload>({ dis.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_alias: roomAlias, room_alias: roomAlias,
_trigger: "Timeline", metricsTrigger: "Timeline",
_viaKeyboard: false, metricsViaKeyboard: false,
}); });
} }

View file

@ -154,7 +154,7 @@ export class CommunityPrototypeStore extends AsyncStoreWithClient<IState> {
dis.dispatch<ViewRoomPayload>({ dis.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: chat.roomId, room_id: chat.roomId,
_trigger: undefined, // Deprecated groups metricsTrigger: undefined, // Deprecated groups
}); });
} }
} }

View file

@ -21,7 +21,9 @@ import { Store } from 'flux/utils';
import { MatrixError } from "matrix-js-sdk/src/http-api"; import { MatrixError } from "matrix-js-sdk/src/http-api";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { ViewRoom as ViewRoomEvent } from "matrix-analytics-events/types/typescript/ViewRoom"; 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 { JoinRule } from "matrix-js-sdk/src/@types/partials";
import { Room } from "matrix-js-sdk/src/models/room";
import dis from '../dispatcher/dispatcher'; import dis from '../dispatcher/dispatcher';
import { MatrixClientPeg } from '../MatrixClientPeg'; import { MatrixClientPeg } from '../MatrixClientPeg';
@ -38,6 +40,8 @@ import { ViewRoomPayload } from "../dispatcher/payloads/ViewRoomPayload";
import DMRoomMap from "../utils/DMRoomMap"; import DMRoomMap from "../utils/DMRoomMap";
import SpaceStore from "./spaces/SpaceStore"; import SpaceStore from "./spaces/SpaceStore";
import { isMetaSpace, MetaSpace } from "./spaces"; import { isMetaSpace, MetaSpace } from "./spaces";
import { JoinRoomPayload } from "../dispatcher/payloads/JoinRoomPayload";
import { JoinRoomReadyPayload } from "../dispatcher/payloads/JoinRoomReadyPayload";
const NUM_JOIN_RETRY = 5; const NUM_JOIN_RETRY = 5;
@ -149,11 +153,42 @@ class RoomViewStore extends Store<ActionPayload> {
case Action.JoinRoomError: case Action.JoinRoomError:
this.joinRoomError(payload); this.joinRoomError(payload);
break; break;
case Action.JoinRoomReady: case Action.JoinRoomReady: {
if (this.state.roomId === payload.roomId) { if (this.state.roomId === payload.roomId) {
this.setState({ shouldPeek: false }); 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<JoinedRoomEvent>({
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; break;
}
case 'on_client_not_viable': case 'on_client_not_viable':
case 'on_logged_out': case 'on_logged_out':
this.reset(); this.reset();
@ -168,7 +203,7 @@ class RoomViewStore extends Store<ActionPayload> {
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: payload.event.getRoomId(), room_id: payload.event.getRoomId(),
replyingToEvent: payload.event, replyingToEvent: payload.event,
_trigger: undefined, // room doesn't change metricsTrigger: undefined, // room doesn't change
}); });
} else { } else {
this.setState({ this.setState({
@ -191,7 +226,7 @@ class RoomViewStore extends Store<ActionPayload> {
private async viewRoom(payload: ViewRoomPayload): Promise<void> { private async viewRoom(payload: ViewRoomPayload): Promise<void> {
if (payload.room_id) { 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"]; let activeSpace: ViewRoomEvent["activeSpace"];
if (SpaceStore.instance.activeSpace === MetaSpace.Home) { if (SpaceStore.instance.activeSpace === MetaSpace.Home) {
activeSpace = "Home"; activeSpace = "Home";
@ -205,8 +240,8 @@ class RoomViewStore extends Store<ActionPayload> {
PosthogAnalytics.instance.trackEvent<ViewRoomEvent>({ PosthogAnalytics.instance.trackEvent<ViewRoomEvent>({
eventName: "ViewRoom", eventName: "ViewRoom",
trigger: payload._trigger, trigger: payload.metricsTrigger,
viaKeyboard: payload._viaKeyboard, viaKeyboard: payload.metricsViaKeyboard,
isDM: !!DMRoomMap.shared().getUserIdForRoomId(payload.room_id), isDM: !!DMRoomMap.shared().getUserIdForRoomId(payload.room_id),
isSpace: MatrixClientPeg.get().getRoom(payload.room_id)?.isSpaceRoom(), isSpace: MatrixClientPeg.get().getRoom(payload.room_id)?.isSpaceRoom(),
activeSpace, activeSpace,
@ -240,10 +275,11 @@ class RoomViewStore extends Store<ActionPayload> {
this.setState(newState); this.setState(newState);
if (payload.auto_join) { if (payload.auto_join) {
dis.dispatch({ dis.dispatch<JoinRoomPayload>({
...payload, ...payload,
action: Action.JoinRoom, action: Action.JoinRoom,
roomId: payload.room_id, roomId: payload.room_id,
metricsTrigger: payload.metricsTrigger as JoinRoomPayload["metricsTrigger"],
}); });
} }
} else if (payload.room_alias) { } else if (payload.room_alias) {
@ -297,7 +333,7 @@ class RoomViewStore extends Store<ActionPayload> {
}); });
} }
private async joinRoom(payload: ActionPayload) { private async joinRoom(payload: JoinRoomPayload) {
this.setState({ this.setState({
joining: true, joining: true,
}); });
@ -308,9 +344,9 @@ class RoomViewStore extends Store<ActionPayload> {
const address = roomAlias || roomId; const address = roomAlias || roomId;
const viaServers = this.state.viaServers || []; const viaServers = this.state.viaServers || [];
try { try {
await retry<any, MatrixError>(() => cli.joinRoom(address, { await retry<Room, MatrixError>(() => cli.joinRoom(address, {
viaServers, viaServers,
...payload.opts, ...(payload.opts || {}),
}), NUM_JOIN_RETRY, (err) => { }), NUM_JOIN_RETRY, (err) => {
// if we received a Gateway timeout then retry // if we received a Gateway timeout then retry
return err.httpStatus === 504; return err.httpStatus === 504;
@ -319,9 +355,10 @@ class RoomViewStore extends Store<ActionPayload> {
// We do *not* clear the 'joining' flag because the Room object and/or our 'joined' member event may not // 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 // have come down the sync stream yet, and that's the point at which we'd consider the user joined to the
// room. // room.
dis.dispatch({ dis.dispatch<JoinRoomReadyPayload>({
action: Action.JoinRoomReady, action: Action.JoinRoomReady,
roomId, roomId,
metricsTrigger: payload.metricsTrigger,
}); });
} catch (err) { } catch (err) {
dis.dispatch({ dis.dispatch({

View file

@ -161,7 +161,8 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
defaultDispatcher.dispatch<ViewRoomPayload>({ defaultDispatcher.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: roomId, room_id: roomId,
_trigger: "WebSpacePanelNotificationBadge", context_switch: true,
metricsTrigger: "WebSpacePanelNotificationBadge",
}); });
} else { } else {
const lists = RoomListStore.instance.unfilteredLists; const lists = RoomListStore.instance.unfilteredLists;
@ -178,7 +179,8 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
defaultDispatcher.dispatch<ViewRoomPayload>({ defaultDispatcher.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: unreadRoom.roomId, room_id: unreadRoom.roomId,
_trigger: "WebSpacePanelNotificationBadge", context_switch: true,
metricsTrigger: "WebSpacePanelNotificationBadge",
}); });
break; break;
} }
@ -227,14 +229,14 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: roomId, room_id: roomId,
context_switch: true, context_switch: true,
_trigger: "WebSpaceContextSwitch", metricsTrigger: "WebSpaceContextSwitch",
}); });
} else if (cliSpace) { } else if (cliSpace) {
defaultDispatcher.dispatch<ViewRoomPayload>({ defaultDispatcher.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: space, room_id: space,
context_switch: true, context_switch: true,
_trigger: "WebSpaceContextSwitch", metricsTrigger: "WebSpaceContextSwitch",
}); });
} else { } else {
defaultDispatcher.dispatch({ defaultDispatcher.dispatch({

View file

@ -296,7 +296,7 @@ export class StopGapWidget extends EventEmitter {
defaultDispatcher.dispatch<ViewRoomPayload>({ defaultDispatcher.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: targetRoomId, room_id: targetRoomId,
_trigger: "Widget", metricsTrigger: "Widget",
}); });
// acknowledge so the widget doesn't freak out // acknowledge so the widget doesn't freak out

View file

@ -191,7 +191,7 @@ export async function leaveRoomBehaviour(roomId: string, retry = true, spinner =
dis.dispatch<ViewRoomPayload>({ dis.dispatch<ViewRoomPayload>({
action: Action.ViewRoom, action: Action.ViewRoom,
room_id: SpaceStore.instance.activeSpace, room_id: SpaceStore.instance.activeSpace,
_trigger: undefined, // other metricsTrigger: undefined, // other
}); });
} else { } else {
dis.dispatch({ action: 'view_home_page' }); dis.dispatch({ action: 'view_home_page' });

View file

@ -28,7 +28,11 @@ export async function timeout<T, Y>(promise: Promise<T>, timeoutValue: Y, ms: nu
} }
// Helper method to retry a Promise a given number of times or until a predicate fails // Helper method to retry a Promise a given number of times or until a predicate fails
export async function retry<T, E extends Error>(fn: () => Promise<T>, num: number, predicate?: (e: E) => boolean) { export async function retry<T, E extends Error>(
fn: () => Promise<T>,
num: number,
predicate?: (e: E) => boolean,
): Promise<T> {
let lastErr: E; let lastErr: E;
for (let i = 0; i < num; i++) { for (let i = 0; i < num; i++) {
try { try {

View file

@ -38,6 +38,8 @@ describe('RoomViewStore', function() {
beforeEach(function() { beforeEach(function() {
testUtils.stubClient(); testUtils.stubClient();
peg.get().credentials = { userId: "@test:example.com" }; peg.get().credentials = { userId: "@test:example.com" };
peg.get().on = jest.fn();
peg.get().off = jest.fn();
// Reset the state of the store // Reset the state of the store
RoomViewStore.reset(); RoomViewStore.reset();

View file

@ -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" resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3"
integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg== 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" 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: matrix-events-sdk@^0.0.1-beta.6:
version "0.0.1-beta.6" version "0.0.1-beta.6"