From b291130c9b47261fcfb4140f726de429acd84be0 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 8 Nov 2022 16:30:28 -0600 Subject: [PATCH 01/26] Fix getRelationsForEvent tsc strictness --- src/components/structures/MessagePanel.tsx | 2 +- src/components/views/rooms/EventTile.tsx | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/structures/MessagePanel.tsx b/src/components/structures/MessagePanel.tsx index 56c396750ff..4c4e737eab7 100644 --- a/src/components/structures/MessagePanel.tsx +++ b/src/components/structures/MessagePanel.tsx @@ -186,7 +186,7 @@ interface IProps { // helper function to access relations for an event onUnfillRequest?(backwards: boolean, scrollToken: string): void; - getRelationsForEvent?(eventId: string, relationType: string, eventType: string): Relations; + getRelationsForEvent?(eventId: string, relationType: string, eventType: EventType | string): Relations | undefined; hideThreadedMessages?: boolean; disableGrouping?: boolean; diff --git a/src/components/views/rooms/EventTile.tsx b/src/components/views/rooms/EventTile.tsx index 4a3b1ebf8d6..92a00368ae5 100644 --- a/src/components/views/rooms/EventTile.tsx +++ b/src/components/views/rooms/EventTile.tsx @@ -87,7 +87,11 @@ import { isLocalRoom } from '../../../utils/localRoom/isLocalRoom'; import { ElementCall } from "../../../models/Call"; import { UnreadNotificationBadge } from './NotificationBadge/UnreadNotificationBadge'; -export type GetRelationsForEvent = (eventId: string, relationType: string, eventType: string) => Relations; +export type GetRelationsForEvent = ( + eventId: string, + relationType: string, + eventType: EventType | string, +) => Relations | undefined; // Our component structure for EventTiles on the timeline is: // From 331be20c7124f649a13980f1b33cf68a4ab190bf Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 8 Nov 2022 16:42:10 -0600 Subject: [PATCH 02/26] Use shared type for GetRelationsForEvent --- src/components/structures/MessagePanel.tsx | 5 ++--- .../views/dialogs/EndPollDialog.tsx | 8 ++------ src/components/views/elements/ReplyChain.tsx | 6 ++---- src/components/views/messages/IBodyProps.ts | 4 ++-- src/components/views/messages/MPollBody.tsx | 20 ++++--------------- .../views/messages/MessageActionBar.tsx | 13 +++--------- .../views/messages/MessageEvent.tsx | 5 ++--- src/components/views/rooms/ReplyTile.tsx | 5 ++--- 8 files changed, 19 insertions(+), 47 deletions(-) diff --git a/src/components/structures/MessagePanel.tsx b/src/components/structures/MessagePanel.tsx index 4c4e737eab7..d6e37eed18b 100644 --- a/src/components/structures/MessagePanel.tsx +++ b/src/components/structures/MessagePanel.tsx @@ -20,7 +20,6 @@ import classNames from 'classnames'; import { Room } from 'matrix-js-sdk/src/models/room'; import { EventType } from 'matrix-js-sdk/src/@types/event'; import { MatrixEvent } from 'matrix-js-sdk/src/models/event'; -import { Relations } from "matrix-js-sdk/src/models/relations"; import { logger } from 'matrix-js-sdk/src/logger'; import { RoomStateEvent } from "matrix-js-sdk/src/models/room-state"; import { M_BEACON_INFO } from 'matrix-js-sdk/src/@types/beacon'; @@ -35,7 +34,7 @@ import SettingsStore from '../../settings/SettingsStore'; import RoomContext, { TimelineRenderingType } from "../../contexts/RoomContext"; import { Layout } from "../../settings/enums/Layout"; import { _t } from "../../languageHandler"; -import EventTile, { UnwrappedEventTile, IReadReceiptProps } from "../views/rooms/EventTile"; +import EventTile, { UnwrappedEventTile, GetRelationsForEvent, IReadReceiptProps } from "../views/rooms/EventTile"; import { hasText } from "../../TextForEvent"; import IRCTimelineProfileResizer from "../views/elements/IRCTimelineProfileResizer"; import DMRoomMap from "../../utils/DMRoomMap"; @@ -186,7 +185,7 @@ interface IProps { // helper function to access relations for an event onUnfillRequest?(backwards: boolean, scrollToken: string): void; - getRelationsForEvent?(eventId: string, relationType: string, eventType: EventType | string): Relations | undefined; + getRelationsForEvent?: GetRelationsForEvent; hideThreadedMessages?: boolean; disableGrouping?: boolean; diff --git a/src/components/views/dialogs/EndPollDialog.tsx b/src/components/views/dialogs/EndPollDialog.tsx index 9a4b32cf798..4313a47cc76 100644 --- a/src/components/views/dialogs/EndPollDialog.tsx +++ b/src/components/views/dialogs/EndPollDialog.tsx @@ -17,7 +17,6 @@ limitations under the License. import React from "react"; import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import { MatrixClient } from "matrix-js-sdk/src/client"; -import { Relations } from "matrix-js-sdk/src/models/relations"; import { PollEndEvent } from "matrix-events-sdk"; import { _t } from "../../../languageHandler"; @@ -26,16 +25,13 @@ import QuestionDialog from "./QuestionDialog"; import { findTopAnswer } from "../messages/MPollBody"; import Modal from "../../../Modal"; import ErrorDialog from "./ErrorDialog"; +import { GetRelationsForEvent } from "../rooms/EventTile"; interface IProps extends IDialogProps { matrixClient: MatrixClient; event: MatrixEvent; onFinished: (success: boolean) => void; - getRelationsForEvent?: ( - eventId: string, - relationType: string, - eventType: string - ) => Relations; + getRelationsForEvent?: GetRelationsForEvent; } export default class EndPollDialog extends React.Component { diff --git a/src/components/views/elements/ReplyChain.tsx b/src/components/views/elements/ReplyChain.tsx index 6ecfc91d842..0647fb7260b 100644 --- a/src/components/views/elements/ReplyChain.tsx +++ b/src/components/views/elements/ReplyChain.tsx @@ -19,7 +19,6 @@ import React from 'react'; import classNames from 'classnames'; import { MatrixEvent } from 'matrix-js-sdk/src/models/event'; import { Room } from 'matrix-js-sdk/src/models/room'; -import { Relations } from 'matrix-js-sdk/src/models/relations'; import { MatrixClient } from 'matrix-js-sdk/src/client'; import { _t } from '../../../languageHandler'; @@ -36,6 +35,7 @@ import AccessibleButton, { ButtonEvent } from './AccessibleButton'; import { getParentEventId, shouldDisplayReply } from '../../../utils/Reply'; import RoomContext from "../../../contexts/RoomContext"; import { MatrixClientPeg } from '../../../MatrixClientPeg'; +import { GetRelationsForEvent } from "../rooms/EventTile"; /** * This number is based on the previous behavior - if we have message of height @@ -56,9 +56,7 @@ interface IProps { forExport?: boolean; isQuoteExpanded?: boolean; setQuoteExpanded: (isExpanded: boolean) => void; - getRelationsForEvent?: ( - (eventId: string, relationType: string, eventType: string) => Relations - ); + getRelationsForEvent?: GetRelationsForEvent; } interface IState { diff --git a/src/components/views/messages/IBodyProps.ts b/src/components/views/messages/IBodyProps.ts index 1e66d1d1933..e16de3ccd88 100644 --- a/src/components/views/messages/IBodyProps.ts +++ b/src/components/views/messages/IBodyProps.ts @@ -16,11 +16,11 @@ limitations under the License. import React, { LegacyRef } from "react"; import { MatrixEvent } from "matrix-js-sdk/src/models/event"; -import { Relations } from "matrix-js-sdk/src/models/relations"; import { MediaEventHelper } from "../../../utils/MediaEventHelper"; import EditorStateTransfer from "../../../utils/EditorStateTransfer"; import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks"; +import { GetRelationsForEvent } from "../rooms/EventTile"; export interface IBodyProps { mxEvent: MatrixEvent; @@ -52,7 +52,7 @@ export interface IBodyProps { isSeeingThroughMessageHiddenForModeration?: boolean; // helper function to access relations for this event - getRelationsForEvent?: (eventId: string, relationType: string, eventType: string) => Relations; + getRelationsForEvent?: GetRelationsForEvent; ref?: React.RefObject | LegacyRef; } diff --git a/src/components/views/messages/MPollBody.tsx b/src/components/views/messages/MPollBody.tsx index 7a48c7212a6..d69ca26eb12 100644 --- a/src/components/views/messages/MPollBody.tsx +++ b/src/components/views/messages/MPollBody.tsx @@ -17,7 +17,7 @@ limitations under the License. import React from 'react'; import classNames from 'classnames'; import { MatrixEvent, MatrixEventEvent } from "matrix-js-sdk/src/models/event"; -import { Relations, RelationsEvent } from 'matrix-js-sdk/src/models/relations'; +import { RelationsEvent } from 'matrix-js-sdk/src/models/relations'; import { MatrixClient } from 'matrix-js-sdk/src/matrix'; import { M_POLL_END, @@ -49,11 +49,7 @@ interface IState { } export function createVoteRelations( - getRelationsForEvent: ( - eventId: string, - relationType: string, - eventType: string - ) => Relations, + getRelationsForEvent: GetRelationsForEvent, eventId: string, ) { return new RelatedRelations([ @@ -73,11 +69,7 @@ export function createVoteRelations( export function findTopAnswer( pollEvent: MatrixEvent, matrixClient: MatrixClient, - getRelationsForEvent?: ( - eventId: string, - relationType: string, - eventType: string - ) => Relations, + getRelationsForEvent?: GetRelationsForEvent, ): string { if (!getRelationsForEvent) { return ""; @@ -132,11 +124,7 @@ export function findTopAnswer( export function isPollEnded( pollEvent: MatrixEvent, matrixClient: MatrixClient, - getRelationsForEvent?: ( - eventId: string, - relationType: string, - eventType: string - ) => Relations, + getRelationsForEvent?: GetRelationsForEvent, ): boolean { if (!getRelationsForEvent) { return false; diff --git a/src/components/views/messages/MessageActionBar.tsx b/src/components/views/messages/MessageActionBar.tsx index c1637b9a0cd..a3edbfd2c28 100644 --- a/src/components/views/messages/MessageActionBar.tsx +++ b/src/components/views/messages/MessageActionBar.tsx @@ -59,6 +59,7 @@ import { Action } from '../../../dispatcher/actions'; import SdkConfig from "../../../SdkConfig"; import { ShowThreadPayload } from "../../../dispatcher/payloads/ShowThreadPayload"; import useFavouriteMessages from '../../../hooks/useFavouriteMessages'; +import { GetRelationsForEvent } from '../rooms/EventTile'; interface IOptionsButtonProps { mxEvent: MatrixEvent; @@ -67,11 +68,7 @@ interface IOptionsButtonProps { getReplyChain: () => ReplyChain; permalinkCreator: RoomPermalinkCreator; onFocusChange: (menuDisplayed: boolean) => void; - getRelationsForEvent?: ( - eventId: string, - relationType: string, - eventType: string - ) => Relations; + getRelationsForEvent?: GetRelationsForEvent; } const OptionsButton: React.FC = ({ @@ -307,11 +304,7 @@ interface IMessageActionBarProps { onFocusChange?: (menuDisplayed: boolean) => void; toggleThreadExpanded: () => void; isQuoteExpanded?: boolean; - getRelationsForEvent?: ( - eventId: string, - relationType: RelationType | string, - eventType: string - ) => Relations; + getRelationsForEvent?: GetRelationsForEvent; } export default class MessageActionBar extends React.PureComponent { diff --git a/src/components/views/messages/MessageEvent.tsx b/src/components/views/messages/MessageEvent.tsx index 858bf0eb6c5..df850993b09 100644 --- a/src/components/views/messages/MessageEvent.tsx +++ b/src/components/views/messages/MessageEvent.tsx @@ -16,7 +16,6 @@ limitations under the License. import React, { createRef } from 'react'; import { EventType, MsgType } from "matrix-js-sdk/src/@types/event"; -import { Relations } from 'matrix-js-sdk/src/models/relations'; import { M_BEACON_INFO } from 'matrix-js-sdk/src/@types/beacon'; import { M_LOCATION } from 'matrix-js-sdk/src/@types/location'; import { M_POLL_START } from "matrix-events-sdk"; @@ -41,7 +40,7 @@ import MPollBody from "./MPollBody"; import MLocationBody from "./MLocationBody"; import MjolnirBody from "./MjolnirBody"; import MBeaconBody from "./MBeaconBody"; -import { IEventTileOps } from "../rooms/EventTile"; +import { GetRelationsForEvent, IEventTileOps } from "../rooms/EventTile"; import { VoiceBroadcastBody, VoiceBroadcastInfoEventType, VoiceBroadcastInfoState } from '../../../voice-broadcast'; // onMessageAllowed is handled internally @@ -51,7 +50,7 @@ interface IProps extends Omit; // helper function to access relations for this event - getRelationsForEvent?: (eventId: string, relationType: string, eventType: string) => Relations; + getRelationsForEvent?: GetRelationsForEvent; isSeeingThroughMessageHiddenForModeration?: boolean; } diff --git a/src/components/views/rooms/ReplyTile.tsx b/src/components/views/rooms/ReplyTile.tsx index 2b973abfca5..0e52d4391f3 100644 --- a/src/components/views/rooms/ReplyTile.tsx +++ b/src/components/views/rooms/ReplyTile.tsx @@ -33,6 +33,7 @@ import MFileBody from "../messages/MFileBody"; import MVoiceMessageBody from "../messages/MVoiceMessageBody"; import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload"; import { renderReplyTile } from "../../../events/EventTileFactory"; +import { GetRelationsForEvent } from "../rooms/EventTile"; interface IProps { mxEvent: MatrixEvent; @@ -41,9 +42,7 @@ interface IProps { highlightLink?: string; onHeightChanged?(): void; toggleExpandedQuote?: () => void; - getRelationsForEvent?: ( - (eventId: string, relationType: string, eventType: string) => Relations - ); + getRelationsForEvent?: GetRelationsForEvent; } export default class ReplyTile extends React.PureComponent { From 639ae6fa0c4f01bfae677d4a0e3e4efdbb80d0e5 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 8 Nov 2022 16:46:49 -0600 Subject: [PATCH 03/26] Fix lint --- src/components/views/rooms/ReplyTile.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/views/rooms/ReplyTile.tsx b/src/components/views/rooms/ReplyTile.tsx index 0e52d4391f3..5f8a8c1caf8 100644 --- a/src/components/views/rooms/ReplyTile.tsx +++ b/src/components/views/rooms/ReplyTile.tsx @@ -19,7 +19,6 @@ import classNames from 'classnames'; import { MatrixEvent, MatrixEventEvent } from "matrix-js-sdk/src/models/event"; import { EventType, MsgType } from 'matrix-js-sdk/src/@types/event'; import { logger } from "matrix-js-sdk/src/logger"; -import { Relations } from 'matrix-js-sdk/src/models/relations'; import { _t } from '../../../languageHandler'; import dis from '../../../dispatcher/dispatcher'; From 095347e14a15c9ff85f22cee0070eba6a29072a1 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 8 Nov 2022 16:58:59 -0600 Subject: [PATCH 04/26] Add alternative type --- src/components/views/rooms/EventTile.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/EventTile.tsx b/src/components/views/rooms/EventTile.tsx index 92a00368ae5..47747c54cc9 100644 --- a/src/components/views/rooms/EventTile.tsx +++ b/src/components/views/rooms/EventTile.tsx @@ -17,7 +17,7 @@ limitations under the License. import React, { createRef, forwardRef, MouseEvent, RefObject } from 'react'; import classNames from "classnames"; -import { EventType, MsgType } from "matrix-js-sdk/src/@types/event"; +import { EventType, MsgType, RelationType } from "matrix-js-sdk/src/@types/event"; import { EventStatus, MatrixEvent, MatrixEventEvent } from "matrix-js-sdk/src/models/event"; import { Relations } from "matrix-js-sdk/src/models/relations"; import { RoomMember } from "matrix-js-sdk/src/models/room-member"; @@ -89,7 +89,7 @@ import { UnreadNotificationBadge } from './NotificationBadge/UnreadNotificationB export type GetRelationsForEvent = ( eventId: string, - relationType: string, + relationType: RelationType | string, eventType: EventType | string, ) => Relations | undefined; From 6db8927cdfbbc0640c2f2324d034344097f3dcfa Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 8 Nov 2022 17:11:34 -0600 Subject: [PATCH 05/26] getRelationsForEvent is not required --- src/components/views/messages/MBeaconBody.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/views/messages/MBeaconBody.tsx b/src/components/views/messages/MBeaconBody.tsx index 7f8c9b8c8af..84faa0d53f9 100644 --- a/src/components/views/messages/MBeaconBody.tsx +++ b/src/components/views/messages/MBeaconBody.tsx @@ -101,8 +101,8 @@ const useUniqueId = (eventId: string): string => { // remove related beacon locations on beacon redaction const useHandleBeaconRedaction = ( event: MatrixEvent, - getRelationsForEvent: GetRelationsForEvent, - cli: MatrixClient, + matrixClient: MatrixClient, + getRelationsForEvent?: GetRelationsForEvent, ): void => { const onBeforeBeaconInfoRedaction = useCallback((_event: MatrixEvent, redactionEvent: MatrixEvent) => { const relations = getRelationsForEvent ? @@ -110,14 +110,14 @@ const useHandleBeaconRedaction = ( undefined; relations?.getRelations()?.forEach(locationEvent => { - cli.redactEvent( + matrixClient.redactEvent( locationEvent.getRoomId(), locationEvent.getId(), undefined, redactionEvent.getContent(), ); }); - }, [event, getRelationsForEvent, cli]); + }, [event, matrixClient, getRelationsForEvent]); useEffect(() => { event.addListener(MatrixEventEvent.BeforeRedaction, onBeforeBeaconInfoRedaction); @@ -151,7 +151,7 @@ const MBeaconBody: React.FC = React.forwardRef(({ mxEvent, getRelati const markerRoomMember = isSelfLocation(mxEvent.getContent()) ? mxEvent.sender : undefined; const isOwnBeacon = beacon?.beaconInfoOwner === matrixClient.getUserId(); - useHandleBeaconRedaction(mxEvent, getRelationsForEvent, matrixClient); + useHandleBeaconRedaction(mxEvent, matrixClient, getRelationsForEvent); const onClick = () => { if (displayStatus !== BeaconDisplayStatus.Active) { From 1eabf6af9ab0b461733cbd893c44c59c787624ff Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 8 Nov 2022 17:21:09 -0600 Subject: [PATCH 06/26] Relations are optional --- src/components/views/messages/MPollBody.tsx | 99 +++++++++++++-------- 1 file changed, 63 insertions(+), 36 deletions(-) diff --git a/src/components/views/messages/MPollBody.tsx b/src/components/views/messages/MPollBody.tsx index d69ca26eb12..b132c7bf870 100644 --- a/src/components/views/messages/MPollBody.tsx +++ b/src/components/views/messages/MPollBody.tsx @@ -52,18 +52,27 @@ export function createVoteRelations( getRelationsForEvent: GetRelationsForEvent, eventId: string, ) { - return new RelatedRelations([ - getRelationsForEvent( - eventId, - "m.reference", - M_POLL_RESPONSE.name, - ), - getRelationsForEvent( - eventId, - "m.reference", - M_POLL_RESPONSE.altName, - ), - ]); + const relationsList = []; + + const pollResponseRelations = getRelationsForEvent( + eventId, + "m.reference", + M_POLL_RESPONSE.name, + ); + if (pollResponseRelations) { + relationsList.push(pollResponseRelations); + } + + const pollResposnseAltRelations = getRelationsForEvent( + eventId, + "m.reference", + M_POLL_RESPONSE.altName, + ); + if (pollResposnseAltRelations) { + relationsList.push(pollResposnseAltRelations); + } + + return new RelatedRelations(relationsList); } export function findTopAnswer( @@ -138,18 +147,27 @@ export function isPollEnded( ); } - const endRelations = new RelatedRelations([ - getRelationsForEvent( - pollEvent.getId(), - "m.reference", - M_POLL_END.name, - ), - getRelationsForEvent( - pollEvent.getId(), - "m.reference", - M_POLL_END.altName, - ), - ]); + const relationsList = []; + + const pollEndRelations = getRelationsForEvent( + pollEvent.getId(), + "m.reference", + M_POLL_END.name, + ); + if (pollEndRelations) { + relationsList.push(pollEndRelations); + } + + const pollEndAltRelations = getRelationsForEvent( + pollEvent.getId(), + "m.reference", + M_POLL_END.altName, + ); + if (pollEndAltRelations) { + relationsList.push(pollEndAltRelations); + } + + const endRelations = new RelatedRelations(relationsList); if (!endRelations) { return false; @@ -323,18 +341,27 @@ export default class MPollBody extends React.Component { private fetchRelations(eventType: NamespacedValue): RelatedRelations | null { if (this.props.getRelationsForEvent) { - return new RelatedRelations([ - this.props.getRelationsForEvent( - this.props.mxEvent.getId(), - "m.reference", - eventType.name, - ), - this.props.getRelationsForEvent( - this.props.mxEvent.getId(), - "m.reference", - eventType.altName, - ), - ]); + const relationsList = []; + + const relations = this.props.getRelationsForEvent( + this.props.mxEvent.getId(), + "m.reference", + eventType.name, + ); + if (relations) { + relationsList.push(relations); + } + + const altRelations = this.props.getRelationsForEvent( + this.props.mxEvent.getId(), + "m.reference", + eventType.altName, + ); + if (altRelations) { + relationsList.push(altRelations); + } + + return new RelatedRelations(relationsList); } else { return null; } From 3060bba57aca7b505cf4bbea1335b1d34f19f9c7 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 8 Nov 2022 17:24:26 -0600 Subject: [PATCH 07/26] Reactions are optional --- src/components/views/rooms/EventTile.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/EventTile.tsx b/src/components/views/rooms/EventTile.tsx index 47747c54cc9..3aab94eecc1 100644 --- a/src/components/views/rooms/EventTile.tsx +++ b/src/components/views/rooms/EventTile.tsx @@ -237,7 +237,7 @@ interface IState { // Whether onRequestKeysClick has been called since mounting. previouslyRequestedKeys: boolean; // The Relations model from the JS SDK for reactions to `mxEvent` - reactions: Relations; + reactions?: Relations; hover: boolean; From bc788c071274c1cf107f898a7412435bfc967a54 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 8 Nov 2022 17:26:33 -0600 Subject: [PATCH 08/26] We expect relations in these tests --- test/components/views/messages/MPollBody-test.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/components/views/messages/MPollBody-test.tsx b/test/components/views/messages/MPollBody-test.tsx index e462584098e..70bc55dc764 100644 --- a/test/components/views/messages/MPollBody-test.tsx +++ b/test/components/views/messages/MPollBody-test.tsx @@ -321,8 +321,9 @@ describe("MPollBody", () => { const votes = [responseEvent("@me:example.com", "pizza", 100)]; const body = newMPollBody(votes); const props: IBodyProps = body.instance().props as IBodyProps; - const voteRelations: Relations = props.getRelationsForEvent( + const voteRelations = props.getRelationsForEvent( "$mypoll", "m.reference", M_POLL_RESPONSE.name); + expect(voteRelations).toBeDefined(); clickRadio(body, "pizza"); // When a new vote from me comes in @@ -344,6 +345,7 @@ describe("MPollBody", () => { const props: IBodyProps = body.instance().props as IBodyProps; const voteRelations: Relations = props.getRelationsForEvent( "$mypoll", "m.reference", M_POLL_RESPONSE.name); + expect(voteRelations).toBeDefined(); clickRadio(body, "pizza"); // When a new vote from someone else comes in From f42971ba25062de8f8ab852b043dd700ad70f96d Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 8 Nov 2022 17:45:35 -0600 Subject: [PATCH 09/26] Add more protection if the eventID is not defined --- src/components/views/messages/MPollBody.tsx | 75 +++++++++++++++------ 1 file changed, 54 insertions(+), 21 deletions(-) diff --git a/src/components/views/messages/MPollBody.tsx b/src/components/views/messages/MPollBody.tsx index b132c7bf870..02bd110bfae 100644 --- a/src/components/views/messages/MPollBody.tsx +++ b/src/components/views/messages/MPollBody.tsx @@ -16,8 +16,9 @@ limitations under the License. import React from 'react'; import classNames from 'classnames'; +import { logger } from "matrix-js-sdk/src/logger"; import { MatrixEvent, MatrixEventEvent } from "matrix-js-sdk/src/models/event"; -import { RelationsEvent } from 'matrix-js-sdk/src/models/relations'; +import { Relations, RelationsEvent } from 'matrix-js-sdk/src/models/relations'; import { MatrixClient } from 'matrix-js-sdk/src/matrix'; import { M_POLL_END, @@ -52,7 +53,7 @@ export function createVoteRelations( getRelationsForEvent: GetRelationsForEvent, eventId: string, ) { - const relationsList = []; + const relationsList: Relations[] = []; const pollResponseRelations = getRelationsForEvent( eventId, @@ -84,9 +85,18 @@ export function findTopAnswer( return ""; } + const pollEventId = pollEvent.getId(); + if (!pollEventId) { + logger.warn( + "findTopAnswer: Poll event needs an event ID to fetch relations in order to determine " + + "the top answer - assuming no best answer", + ); + return ""; + } + const poll = pollEvent.unstableExtensibleEvent as PollStartEvent; if (!poll?.isEquivalentTo(M_POLL_START)) { - console.warn("Failed to parse poll to determine top answer - assuming no best answer"); + logger.warn("Failed to parse poll to determine top answer - assuming no best answer"); return ""; } @@ -96,18 +106,27 @@ export function findTopAnswer( const voteRelations = createVoteRelations(getRelationsForEvent, pollEvent.getId()); - const endRelations = new RelatedRelations([ - getRelationsForEvent( - pollEvent.getId(), - "m.reference", - M_POLL_END.name, - ), - getRelationsForEvent( - pollEvent.getId(), - "m.reference", - M_POLL_END.altName, - ), - ]); + const relationsList: Relations[] = []; + + const pollEndRelations = getRelationsForEvent( + pollEventId, + "m.reference", + M_POLL_END.name, + ); + if (pollEndRelations) { + relationsList.push(pollEndRelations); + } + + const pollEndAltRelations = getRelationsForEvent( + pollEventId, + "m.reference", + M_POLL_END.altName, + ); + if (pollEndAltRelations) { + relationsList.push(pollEndAltRelations); + } + + const endRelations = new RelatedRelations(relationsList); const userVotes: Map = collectUserVotes( allVotes(pollEvent, matrixClient, voteRelations, endRelations), @@ -139,6 +158,15 @@ export function isPollEnded( return false; } + const pollEventId = pollEvent.getId(); + if (!pollEventId) { + logger.warn( + "isPollEnded: Poll event must have event ID in order to determine whether it has ended " + + "- assuming poll has not ended", + ); + return false; + } + const roomCurrentState = matrixClient.getRoom(pollEvent.getRoomId()).currentState; function userCanRedact(endEvent: MatrixEvent) { return roomCurrentState.maySendRedactionForEvent( @@ -147,10 +175,10 @@ export function isPollEnded( ); } - const relationsList = []; + const relationsList: Relations[] = []; const pollEndRelations = getRelationsForEvent( - pollEvent.getId(), + pollEventId, "m.reference", M_POLL_END.name, ); @@ -159,7 +187,7 @@ export function isPollEnded( } const pollEndAltRelations = getRelationsForEvent( - pollEvent.getId(), + pollEventId, "m.reference", M_POLL_END.altName, ); @@ -341,10 +369,15 @@ export default class MPollBody extends React.Component { private fetchRelations(eventType: NamespacedValue): RelatedRelations | null { if (this.props.getRelationsForEvent) { - const relationsList = []; + const relationsList: Relations[] = []; + + const eventId = this.props.mxEvent.getId(); + if (!eventId) { + return null; + } const relations = this.props.getRelationsForEvent( - this.props.mxEvent.getId(), + eventId, "m.reference", eventType.name, ); @@ -353,7 +386,7 @@ export default class MPollBody extends React.Component { } const altRelations = this.props.getRelationsForEvent( - this.props.mxEvent.getId(), + eventId, "m.reference", eventType.altName, ); From 6aec3efbec2d05306c3dab70be1d8f32fdba8411 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 8 Nov 2022 17:46:44 -0600 Subject: [PATCH 10/26] Allow null too --- src/components/views/rooms/EventTile.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/EventTile.tsx b/src/components/views/rooms/EventTile.tsx index 3aab94eecc1..f307e57432b 100644 --- a/src/components/views/rooms/EventTile.tsx +++ b/src/components/views/rooms/EventTile.tsx @@ -91,7 +91,7 @@ export type GetRelationsForEvent = ( eventId: string, relationType: RelationType | string, eventType: EventType | string, -) => Relations | undefined; +) => Relations | null | undefined; // Our component structure for EventTiles on the timeline is: // From 0f80d5a4fea52ddcafebd879ba0b6fe04f5dbba1 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 8 Nov 2022 17:48:03 -0600 Subject: [PATCH 11/26] Better test typing --- test/components/views/messages/MPollBody-test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/components/views/messages/MPollBody-test.tsx b/test/components/views/messages/MPollBody-test.tsx index 70bc55dc764..7e5aefaa8fd 100644 --- a/test/components/views/messages/MPollBody-test.tsx +++ b/test/components/views/messages/MPollBody-test.tsx @@ -321,7 +321,7 @@ describe("MPollBody", () => { const votes = [responseEvent("@me:example.com", "pizza", 100)]; const body = newMPollBody(votes); const props: IBodyProps = body.instance().props as IBodyProps; - const voteRelations = props.getRelationsForEvent( + const voteRelations = props!.getRelationsForEvent( "$mypoll", "m.reference", M_POLL_RESPONSE.name); expect(voteRelations).toBeDefined(); clickRadio(body, "pizza"); @@ -343,7 +343,7 @@ describe("MPollBody", () => { const votes = [responseEvent("@me:example.com", "pizza")]; const body = newMPollBody(votes); const props: IBodyProps = body.instance().props as IBodyProps; - const voteRelations: Relations = props.getRelationsForEvent( + const voteRelations = props!.getRelationsForEvent( "$mypoll", "m.reference", M_POLL_RESPONSE.name); expect(voteRelations).toBeDefined(); clickRadio(body, "pizza"); From bab05e2c8d9c671f54d8aca211786f27881650f1 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 8 Nov 2022 18:10:29 -0600 Subject: [PATCH 12/26] User ID is not necessary unless something is selected --- src/components/views/messages/MPollBody.tsx | 45 +++++++++++++++------ 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/src/components/views/messages/MPollBody.tsx b/src/components/views/messages/MPollBody.tsx index 02bd110bfae..194581faba6 100644 --- a/src/components/views/messages/MPollBody.tsx +++ b/src/components/views/messages/MPollBody.tsx @@ -104,7 +104,7 @@ export function findTopAnswer( return poll.answers.find(a => a.id === answerId)?.text ?? ""; }; - const voteRelations = createVoteRelations(getRelationsForEvent, pollEvent.getId()); + const voteRelations = createVoteRelations(getRelationsForEvent, pollEventId); const relationsList: Relations[] = []; @@ -130,7 +130,7 @@ export function findTopAnswer( const userVotes: Map = collectUserVotes( allVotes(pollEvent, matrixClient, voteRelations, endRelations), - matrixClient.getUserId(), + null, null, ); @@ -167,7 +167,16 @@ export function isPollEnded( return false; } - const roomCurrentState = matrixClient.getRoom(pollEvent.getRoomId()).currentState; + const roomId = pollEvent.getRoomId(); + if (!pollEventId) { + logger.warn( + "isPollEnded: Poll event must have room ID in order to determine whether it has ended " + + "- assuming poll has not ended", + ); + return false; + } + + const roomCurrentState = matrixClient.getRoom(roomId).currentState; function userCanRedact(endEvent: MatrixEvent) { return roomCurrentState.maySendRedactionForEvent( pollEvent, @@ -209,7 +218,10 @@ export function isPollEnded( export function pollAlreadyHasVotes(mxEvent: MatrixEvent, getRelationsForEvent?: GetRelationsForEvent): boolean { if (!getRelationsForEvent) return false; - const voteRelations = createVoteRelations(getRelationsForEvent, mxEvent.getId()); + const eventId = mxEvent.getId(); + if (!eventId) return false; + + const voteRelations = createVoteRelations(getRelationsForEvent, eventId); return voteRelations.getRelations().length > 0; } @@ -385,13 +397,16 @@ export default class MPollBody extends React.Component { relationsList.push(relations); } - const altRelations = this.props.getRelationsForEvent( - eventId, - "m.reference", - eventType.altName, - ); - if (altRelations) { - relationsList.push(altRelations); + // If there is an alternatve experimental event type, also look for that + if (eventType.altName) { + const altRelations = this.props.getRelationsForEvent( + eventId, + "m.reference", + eventType.altName, + ); + if (altRelations) { + relationsList.push(altRelations); + } } return new RelatedRelations(relationsList); @@ -703,11 +718,15 @@ function isPollResponse(responseEvent: MatrixEvent): boolean { /** * Figure out the correct vote for each user. + * @param userResponses current vote responses in the poll + * @param {string?} userId The userId for which the `selected` option will apply to. + * Should be set to the current user ID. + * @param {string?} selected Local echo selected option for the userId * @returns a Map of user ID to their vote info */ function collectUserVotes( userResponses: Array, - userId: string, + userId?: string, selected?: string, ): Map { const userVotes: Map = new Map(); @@ -719,7 +738,7 @@ function collectUserVotes( } } - if (selected) { + if (selected && userId) { userVotes.set(userId, new UserVote(0, userId, [selected])); } From a5a61d20b4e6950954271bc52c71c0f7a65db02e Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 8 Nov 2022 18:11:40 -0600 Subject: [PATCH 13/26] It's okay to [].includes(null) --- src/components/views/messages/MPollBody.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/messages/MPollBody.tsx b/src/components/views/messages/MPollBody.tsx index 194581faba6..33adc127d2b 100644 --- a/src/components/views/messages/MPollBody.tsx +++ b/src/components/views/messages/MPollBody.tsx @@ -443,7 +443,7 @@ export default class MPollBody extends React.Component { const newEvents: MatrixEvent[] = this.state.voteRelations.getRelations() .filter(isPollResponse) .filter((mxEvent: MatrixEvent) => - !this.seenEventIds.includes(mxEvent.getId())); + !this.seenEventIds.includes(mxEvent.getId()!)); let newSelected = this.state.selected; if (newEvents.length > 0) { From ae6dddc7edd61a97d310106602696719af6dc064 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 8 Nov 2022 18:13:39 -0600 Subject: [PATCH 14/26] Null is as good as undefined here --- src/components/views/messages/MPollBody.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/views/messages/MPollBody.tsx b/src/components/views/messages/MPollBody.tsx index 33adc127d2b..6b761768999 100644 --- a/src/components/views/messages/MPollBody.tsx +++ b/src/components/views/messages/MPollBody.tsx @@ -44,7 +44,7 @@ import PollCreateDialog from "../elements/PollCreateDialog"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; interface IState { - selected?: string; // Which option was clicked by the local user + selected?: string | null | undefined; // Which option was clicked by the local user voteRelations: RelatedRelations; // Voting (response) events endRelations: RelatedRelations; // Poll end events } @@ -726,8 +726,8 @@ function isPollResponse(responseEvent: MatrixEvent): boolean { */ function collectUserVotes( userResponses: Array, - userId?: string, - selected?: string, + userId?: string | null | undefined, + selected?: string | null | undefined, ): Map { const userVotes: Map = new Map(); From a51fb2c1f61849d37da6698b39d03526b94663f8 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 8 Nov 2022 18:14:57 -0600 Subject: [PATCH 15/26] Null or undefined is good here --- src/components/views/rooms/EventTile.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/EventTile.tsx b/src/components/views/rooms/EventTile.tsx index f307e57432b..70ebb4e3909 100644 --- a/src/components/views/rooms/EventTile.tsx +++ b/src/components/views/rooms/EventTile.tsx @@ -237,7 +237,7 @@ interface IState { // Whether onRequestKeysClick has been called since mounting. previouslyRequestedKeys: boolean; // The Relations model from the JS SDK for reactions to `mxEvent` - reactions?: Relations; + reactions?: Relations | null | undefined; hover: boolean; From 0cef622e59bb5ea41522766d716862acd84efd99 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 8 Nov 2022 18:17:55 -0600 Subject: [PATCH 16/26] We have some expectations for the tests --- test/components/views/messages/MPollBody-test.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/components/views/messages/MPollBody-test.tsx b/test/components/views/messages/MPollBody-test.tsx index 7e5aefaa8fd..f2ffabfac66 100644 --- a/test/components/views/messages/MPollBody-test.tsx +++ b/test/components/views/messages/MPollBody-test.tsx @@ -321,13 +321,13 @@ describe("MPollBody", () => { const votes = [responseEvent("@me:example.com", "pizza", 100)]; const body = newMPollBody(votes); const props: IBodyProps = body.instance().props as IBodyProps; - const voteRelations = props!.getRelationsForEvent( + const voteRelations = props!.getRelationsForEvent!( "$mypoll", "m.reference", M_POLL_RESPONSE.name); expect(voteRelations).toBeDefined(); clickRadio(body, "pizza"); // When a new vote from me comes in - voteRelations.addEvent(responseEvent("@me:example.com", "wings", 101)); + voteRelations!.addEvent(responseEvent("@me:example.com", "wings", 101)); // Then the new vote is counted, not the old one expect(votesCount(body, "pizza")).toBe("0 votes"); @@ -343,13 +343,13 @@ describe("MPollBody", () => { const votes = [responseEvent("@me:example.com", "pizza")]; const body = newMPollBody(votes); const props: IBodyProps = body.instance().props as IBodyProps; - const voteRelations = props!.getRelationsForEvent( + const voteRelations = props!.getRelationsForEvent!( "$mypoll", "m.reference", M_POLL_RESPONSE.name); expect(voteRelations).toBeDefined(); clickRadio(body, "pizza"); // When a new vote from someone else comes in - voteRelations.addEvent(responseEvent("@xx:example.com", "wings", 101)); + voteRelations!.addEvent(responseEvent("@xx:example.com", "wings", 101)); // Then my vote is still for pizza // NOTE: the new event does not affect the counts for other people - From 6caefb018300a3739400a792b902b127d4c00b06 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 8 Nov 2022 18:29:25 -0600 Subject: [PATCH 17/26] The room and user can be undefined too --- src/components/views/messages/MPollBody.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/views/messages/MPollBody.tsx b/src/components/views/messages/MPollBody.tsx index 6b761768999..1e9c42490f8 100644 --- a/src/components/views/messages/MPollBody.tsx +++ b/src/components/views/messages/MPollBody.tsx @@ -176,11 +176,12 @@ export function isPollEnded( return false; } - const roomCurrentState = matrixClient.getRoom(roomId).currentState; + const roomCurrentState = matrixClient.getRoom(roomId)?.currentState; function userCanRedact(endEvent: MatrixEvent) { - return roomCurrentState.maySendRedactionForEvent( + const endEventSender = endEvent.getSender(); + return endEventSender && roomCurrentState && roomCurrentState.maySendRedactionForEvent( pollEvent, - endEvent.getSender(), + endEventSender, ); } From eb30722a02feb7a16d9494205f1eb5221599a0c1 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 8 Nov 2022 18:33:01 -0600 Subject: [PATCH 18/26] Protec --- src/components/views/messages/MPollBody.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/messages/MPollBody.tsx b/src/components/views/messages/MPollBody.tsx index 1e9c42490f8..ec8ebadc72e 100644 --- a/src/components/views/messages/MPollBody.tsx +++ b/src/components/views/messages/MPollBody.tsx @@ -486,7 +486,7 @@ export default class MPollBody extends React.Component { const totalVotes = this.totalVotes(votes); const winCount = Math.max(...votes.values()); const userId = this.context.getUserId(); - const myVote = userVotes.get(userId)?.answers[0]; + const myVote = userVotes?.get(userId)?.answers[0]; const disclosed = M_POLL_KIND_DISCLOSED.matches(poll.kind.name); // Disclosed: votes are hidden until I vote or the poll ends From 7aaf107699bff122e81f5543c89f848361ffefd0 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 8 Nov 2022 18:34:04 -0600 Subject: [PATCH 19/26] Reactions are optional --- src/components/views/context_menus/MessageContextMenu.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/context_menus/MessageContextMenu.tsx b/src/components/views/context_menus/MessageContextMenu.tsx index f6961b627ea..60c91d7b039 100644 --- a/src/components/views/context_menus/MessageContextMenu.tsx +++ b/src/components/views/context_menus/MessageContextMenu.tsx @@ -130,7 +130,7 @@ interface IProps extends IPosition { // True if the menu is being used as a right click menu rightClick?: boolean; // The Relations model from the JS SDK for reactions to `mxEvent` - reactions?: Relations; + reactions?: Relations | null | undefined; // A permalink to this event or an href of an anchor element the user has clicked link?: string; From 75582e71042e82f07915314eb1ed519b76367066 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 8 Nov 2022 18:34:53 -0600 Subject: [PATCH 20/26] Try match signatures --- src/components/structures/TimelinePanel.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/TimelinePanel.tsx b/src/components/structures/TimelinePanel.tsx index 25d40dfaabd..af42db06e86 100644 --- a/src/components/structures/TimelinePanel.tsx +++ b/src/components/structures/TimelinePanel.tsx @@ -1720,7 +1720,7 @@ class TimelinePanel extends React.Component { private getRelationsForEvent = ( eventId: string, - relationType: RelationType, + relationType: RelationType | string, eventType: EventType | string, ) => this.props.timelineSet.relations?.getChildEventsForEvent(eventId, relationType, eventType); From 382c38004c97146b5696353ac8f04275385434a1 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 8 Nov 2022 18:41:10 -0600 Subject: [PATCH 21/26] Null or undefined --- src/components/views/emojipicker/ReactionPicker.tsx | 2 +- src/components/views/messages/MessageActionBar.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/emojipicker/ReactionPicker.tsx b/src/components/views/emojipicker/ReactionPicker.tsx index 51479cd5177..36099f67e95 100644 --- a/src/components/views/emojipicker/ReactionPicker.tsx +++ b/src/components/views/emojipicker/ReactionPicker.tsx @@ -29,7 +29,7 @@ import { FocusComposerPayload } from '../../../dispatcher/payloads/FocusComposer interface IProps { mxEvent: MatrixEvent; - reactions?: Relations; + reactions?: Relations | null | undefined; onFinished(): void; } diff --git a/src/components/views/messages/MessageActionBar.tsx b/src/components/views/messages/MessageActionBar.tsx index a3edbfd2c28..6691cf54286 100644 --- a/src/components/views/messages/MessageActionBar.tsx +++ b/src/components/views/messages/MessageActionBar.tsx @@ -296,7 +296,7 @@ const FavouriteButton = ({ mxEvent }: IFavouriteButtonProp) => { interface IMessageActionBarProps { mxEvent: MatrixEvent; - reactions?: Relations; + reactions?: Relations | null | undefined; // TODO: Types getTile: () => any | null; getReplyChain: () => ReplyChain | undefined; From 07089e7540707bc083b33912ccefc75d03f27370 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 8 Nov 2022 18:48:45 -0600 Subject: [PATCH 22/26] More null or undefined --- src/components/views/messages/MessageActionBar.tsx | 2 +- src/components/views/messages/ReactionsRow.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/messages/MessageActionBar.tsx b/src/components/views/messages/MessageActionBar.tsx index 6691cf54286..a6d9e2f13a8 100644 --- a/src/components/views/messages/MessageActionBar.tsx +++ b/src/components/views/messages/MessageActionBar.tsx @@ -132,7 +132,7 @@ const OptionsButton: React.FC = ({ interface IReactButtonProps { mxEvent: MatrixEvent; - reactions: Relations; + reactions?: Relations | null | undefined; onFocusChange: (menuDisplayed: boolean) => void; } diff --git a/src/components/views/messages/ReactionsRow.tsx b/src/components/views/messages/ReactionsRow.tsx index d0190fd5842..c310f714090 100644 --- a/src/components/views/messages/ReactionsRow.tsx +++ b/src/components/views/messages/ReactionsRow.tsx @@ -65,7 +65,7 @@ interface IProps { // The event we're displaying reactions for mxEvent: MatrixEvent; // The Relations model from the JS SDK for reactions to `mxEvent` - reactions?: Relations; + reactions?: Relations | null | undefined; } interface IState { From 847132e926bf708cb9e3b98470584f7bfca50d7d Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 8 Nov 2022 18:56:42 -0600 Subject: [PATCH 23/26] Protec --- src/components/views/messages/ReactionsRow.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/messages/ReactionsRow.tsx b/src/components/views/messages/ReactionsRow.tsx index c310f714090..4f24a0280be 100644 --- a/src/components/views/messages/ReactionsRow.tsx +++ b/src/components/views/messages/ReactionsRow.tsx @@ -114,7 +114,7 @@ export default class ReactionsRow extends React.PureComponent { } componentDidUpdate(prevProps: IProps) { - if (prevProps.reactions !== this.props.reactions) { + if (this.props.reactions && prevProps.reactions !== this.props.reactions) { this.props.reactions.on(RelationsEvent.Add, this.onReactionsChange); this.props.reactions.on(RelationsEvent.Remove, this.onReactionsChange); this.props.reactions.on(RelationsEvent.Redaction, this.onReactionsChange); From cd98cef68e603a607088b26f14c22e8d37c419b0 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Wed, 9 Nov 2022 01:55:14 -0600 Subject: [PATCH 24/26] Fix typo (wrong variable) --- src/components/views/messages/MPollBody.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/messages/MPollBody.tsx b/src/components/views/messages/MPollBody.tsx index ec8ebadc72e..5e8afd518a8 100644 --- a/src/components/views/messages/MPollBody.tsx +++ b/src/components/views/messages/MPollBody.tsx @@ -168,7 +168,7 @@ export function isPollEnded( } const roomId = pollEvent.getRoomId(); - if (!pollEventId) { + if (!roomId) { logger.warn( "isPollEnded: Poll event must have room ID in order to determine whether it has ended " + "- assuming poll has not ended", From a90945612ffaa4e95c71d22de51ba20c3b1b5ec7 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Wed, 9 Nov 2022 02:02:35 -0600 Subject: [PATCH 25/26] Remove optional params See https://github.com/matrix-org/matrix-react-sdk/pull/9558#discussion_r1017515913 --- src/components/views/messages/MPollBody.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/views/messages/MPollBody.tsx b/src/components/views/messages/MPollBody.tsx index 5e8afd518a8..8bd503dbd4d 100644 --- a/src/components/views/messages/MPollBody.tsx +++ b/src/components/views/messages/MPollBody.tsx @@ -130,8 +130,6 @@ export function findTopAnswer( const userVotes: Map = collectUserVotes( allVotes(pollEvent, matrixClient, voteRelations, endRelations), - null, - null, ); const votes: Map = countVotes(userVotes, poll); From 25d0e3624b3171ca9eea7b76728c5405532e2bf2 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Thu, 10 Nov 2022 15:48:16 -0600 Subject: [PATCH 26/26] Fix up last maaaaybe relevant lint --- src/components/views/messages/MPollBody.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/messages/MPollBody.tsx b/src/components/views/messages/MPollBody.tsx index 8bd503dbd4d..b39d286a0ce 100644 --- a/src/components/views/messages/MPollBody.tsx +++ b/src/components/views/messages/MPollBody.tsx @@ -484,7 +484,7 @@ export default class MPollBody extends React.Component { const totalVotes = this.totalVotes(votes); const winCount = Math.max(...votes.values()); const userId = this.context.getUserId(); - const myVote = userVotes?.get(userId)?.answers[0]; + const myVote = userVotes?.get(userId!)?.answers[0]; const disclosed = M_POLL_KIND_DISCLOSED.matches(poll.kind.name); // Disclosed: votes are hidden until I vote or the poll ends