Move all polls processing to events-sdk & prep for stable polls (#7517)
* Move all polls processing to events-sdk This makes polls support the full range of extensible events (both parsing and generation). * Appease the linter * Fix & update tests * Update events-sdk for polls bugfix * Update events-sdk for typechecking * Add missing type cast * Update per review
This commit is contained in:
parent
12e967a97c
commit
65987e6b72
17 changed files with 727 additions and 299 deletions
|
@ -19,8 +19,8 @@ import React, { ReactElement } from 'react';
|
|||
import { EventStatus, MatrixEvent } from 'matrix-js-sdk/src/models/event';
|
||||
import { EventType, RelationType } from "matrix-js-sdk/src/@types/event";
|
||||
import { Relations } from 'matrix-js-sdk/src/models/relations';
|
||||
import { POLL_START_EVENT_TYPE } from "matrix-js-sdk/src/@types/polls";
|
||||
import { LOCATION_EVENT_TYPE } from 'matrix-js-sdk/src/@types/location';
|
||||
import { M_POLL_START } from "matrix-events-sdk";
|
||||
|
||||
import { MatrixClientPeg } from '../../../MatrixClientPeg';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
|
@ -140,7 +140,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
|||
|
||||
private canEndPoll(mxEvent: MatrixEvent): boolean {
|
||||
return (
|
||||
POLL_START_EVENT_TYPE.matches(mxEvent.getType()) &&
|
||||
M_POLL_START.matches(mxEvent.getType()) &&
|
||||
this.state.canRedact &&
|
||||
!isPollEnded(mxEvent, MatrixClientPeg.get(), this.props.getRelationsForEvent)
|
||||
);
|
||||
|
|
|
@ -18,8 +18,7 @@ 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 { IPollEndContent, POLL_END_EVENT_TYPE } from "matrix-js-sdk/src/@types/polls";
|
||||
import { TEXT_NODE_TYPE } from "matrix-js-sdk/src/@types/extensible_events";
|
||||
import { PollEndEvent } from "matrix-events-sdk";
|
||||
|
||||
import { _t } from "../../../languageHandler";
|
||||
import { IDialogProps } from "./IDialogProps";
|
||||
|
@ -57,17 +56,10 @@ export default class EndPollDialog extends React.Component<IProps> {
|
|||
);
|
||||
|
||||
if (endPoll) {
|
||||
const endContent: IPollEndContent = {
|
||||
[POLL_END_EVENT_TYPE.name]: {},
|
||||
"m.relates_to": {
|
||||
"event_id": this.props.event.getId(),
|
||||
"rel_type": "m.reference",
|
||||
},
|
||||
[TEXT_NODE_TYPE.name]: message,
|
||||
};
|
||||
const endEvent = PollEndEvent.from(this.props.event.getId(), message).serialize();
|
||||
|
||||
this.props.matrixClient.sendEvent(
|
||||
this.props.event.getRoomId(), POLL_END_EVENT_TYPE.name, endContent,
|
||||
this.props.event.getRoomId(), endEvent.type, endEvent.content,
|
||||
).catch((e: any) => {
|
||||
console.error("Failed to submit poll response event:", e);
|
||||
Modal.createTrackedDialog(
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||
Copyright 2021 - 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.
|
||||
|
@ -16,8 +16,7 @@ limitations under the License.
|
|||
|
||||
import React, { ChangeEvent, createRef } from "react";
|
||||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
import { makePollContent } from "matrix-js-sdk/src/content-helpers";
|
||||
import { POLL_KIND_DISCLOSED, POLL_START_EVENT_TYPE } from "matrix-js-sdk/src/@types/polls";
|
||||
import { M_POLL_KIND_DISCLOSED, PollStartEvent } from "matrix-events-sdk";
|
||||
|
||||
import ScrollableBaseModal, { IScrollableBaseState } from "../dialogs/ScrollableBaseModal";
|
||||
import { IDialogProps } from "../dialogs/IDialogProps";
|
||||
|
@ -99,13 +98,12 @@ export default class PollCreateDialog extends ScrollableBaseModal<IProps, IState
|
|||
|
||||
protected submit(): void {
|
||||
this.setState({ busy: true, canSubmit: false });
|
||||
this.matrixClient.sendEvent(
|
||||
this.props.room.roomId,
|
||||
POLL_START_EVENT_TYPE.name,
|
||||
makePollContent(
|
||||
this.state.question, this.state.options, POLL_KIND_DISCLOSED.name,
|
||||
),
|
||||
).then(
|
||||
const pollEvent = PollStartEvent.from(
|
||||
this.state.question.trim(),
|
||||
this.state.options.map(a => a.trim()).filter(a => !!a),
|
||||
M_POLL_KIND_DISCLOSED,
|
||||
).serialize();
|
||||
this.matrixClient.sendEvent(this.props.room.roomId, pollEvent.type, pollEvent.content).then(
|
||||
() => this.props.onFinished(true),
|
||||
).catch(e => {
|
||||
console.error("Failed to post poll:", e);
|
||||
|
|
|
@ -19,15 +19,16 @@ import classNames from 'classnames';
|
|||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
import { Relations } from 'matrix-js-sdk/src/models/relations';
|
||||
import { MatrixClient } from 'matrix-js-sdk/src/matrix';
|
||||
import { TEXT_NODE_TYPE } from "matrix-js-sdk/src/@types/extensible_events";
|
||||
import {
|
||||
IPollAnswer,
|
||||
IPollContent,
|
||||
IPollResponseContent,
|
||||
POLL_END_EVENT_TYPE,
|
||||
POLL_RESPONSE_EVENT_TYPE,
|
||||
POLL_START_EVENT_TYPE,
|
||||
} from "matrix-js-sdk/src/@types/polls";
|
||||
M_POLL_END,
|
||||
M_POLL_RESPONSE,
|
||||
M_POLL_START,
|
||||
NamespacedValue,
|
||||
PollAnswerSubevent,
|
||||
PollResponseEvent,
|
||||
PollStartEvent,
|
||||
} from "matrix-events-sdk";
|
||||
import { RelatedRelations } from "matrix-js-sdk/src/models/related-relations";
|
||||
|
||||
import { _t } from '../../../languageHandler';
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
|
@ -40,8 +41,8 @@ import ErrorDialog from '../dialogs/ErrorDialog';
|
|||
|
||||
interface IState {
|
||||
selected?: string; // Which option was clicked by the local user
|
||||
voteRelations: Relations; // Voting (response) events
|
||||
endRelations: Relations; // Poll end events
|
||||
voteRelations: RelatedRelations; // Voting (response) events
|
||||
endRelations: RelatedRelations; // Poll end events
|
||||
}
|
||||
|
||||
export function findTopAnswer(
|
||||
|
@ -57,28 +58,41 @@ export function findTopAnswer(
|
|||
return "";
|
||||
}
|
||||
|
||||
const pollContents: IPollContent = pollEvent.getContent();
|
||||
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");
|
||||
return "";
|
||||
}
|
||||
|
||||
const findAnswerText = (answerId: string) => {
|
||||
for (const answer of pollContents[POLL_START_EVENT_TYPE.name].answers) {
|
||||
if (answer.id == answerId) {
|
||||
return answer[TEXT_NODE_TYPE.name];
|
||||
}
|
||||
}
|
||||
return "";
|
||||
return poll.answers.find(a => a.id === answerId)?.text ?? "";
|
||||
};
|
||||
|
||||
const voteRelations: Relations = getRelationsForEvent(
|
||||
pollEvent.getId(),
|
||||
"m.reference",
|
||||
POLL_RESPONSE_EVENT_TYPE.name,
|
||||
);
|
||||
const voteRelations = new RelatedRelations([
|
||||
getRelationsForEvent(
|
||||
pollEvent.getId(),
|
||||
"m.reference",
|
||||
M_POLL_RESPONSE.name,
|
||||
),
|
||||
getRelationsForEvent(
|
||||
pollEvent.getId(),
|
||||
"m.reference",
|
||||
M_POLL_RESPONSE.altName,
|
||||
),
|
||||
]);
|
||||
|
||||
const endRelations: Relations = getRelationsForEvent(
|
||||
pollEvent.getId(),
|
||||
"m.reference",
|
||||
POLL_END_EVENT_TYPE.name,
|
||||
);
|
||||
const endRelations = new RelatedRelations([
|
||||
getRelationsForEvent(
|
||||
pollEvent.getId(),
|
||||
"m.reference",
|
||||
M_POLL_END.name,
|
||||
),
|
||||
getRelationsForEvent(
|
||||
pollEvent.getId(),
|
||||
"m.reference",
|
||||
M_POLL_END.altName,
|
||||
),
|
||||
]);
|
||||
|
||||
const userVotes: Map<string, UserVote> = collectUserVotes(
|
||||
allVotes(pollEvent, matrixClient, voteRelations, endRelations),
|
||||
|
@ -86,7 +100,7 @@ export function findTopAnswer(
|
|||
null,
|
||||
);
|
||||
|
||||
const votes: Map<string, number> = countVotes(userVotes, pollEvent.getContent());
|
||||
const votes: Map<string, number> = countVotes(userVotes, poll);
|
||||
const highestScore: number = Math.max(...votes.values());
|
||||
|
||||
const bestAnswerIds: string[] = [];
|
||||
|
@ -122,11 +136,18 @@ export function isPollEnded(
|
|||
);
|
||||
}
|
||||
|
||||
const endRelations = getRelationsForEvent(
|
||||
pollEvent.getId(),
|
||||
"m.reference",
|
||||
POLL_END_EVENT_TYPE.name,
|
||||
);
|
||||
const endRelations = new RelatedRelations([
|
||||
getRelationsForEvent(
|
||||
pollEvent.getId(),
|
||||
"m.reference",
|
||||
M_POLL_END.name,
|
||||
),
|
||||
getRelationsForEvent(
|
||||
pollEvent.getId(),
|
||||
"m.reference",
|
||||
M_POLL_END.altName,
|
||||
),
|
||||
]);
|
||||
|
||||
if (!endRelations) {
|
||||
return false;
|
||||
|
@ -163,7 +184,7 @@ export default class MPollBody extends React.Component<IBodyProps, IState> {
|
|||
this.removeListeners(this.state.voteRelations, this.state.endRelations);
|
||||
}
|
||||
|
||||
private addListeners(voteRelations?: Relations, endRelations?: Relations) {
|
||||
private addListeners(voteRelations?: RelatedRelations, endRelations?: RelatedRelations) {
|
||||
if (voteRelations) {
|
||||
voteRelations.on("Relations.add", this.onRelationsChange);
|
||||
voteRelations.on("Relations.remove", this.onRelationsChange);
|
||||
|
@ -176,7 +197,7 @@ export default class MPollBody extends React.Component<IBodyProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
private removeListeners(voteRelations?: Relations, endRelations?: Relations) {
|
||||
private removeListeners(voteRelations?: RelatedRelations, endRelations?: RelatedRelations) {
|
||||
if (voteRelations) {
|
||||
voteRelations.off("Relations.add", this.onRelationsChange);
|
||||
voteRelations.off("Relations.remove", this.onRelationsChange);
|
||||
|
@ -194,13 +215,13 @@ export default class MPollBody extends React.Component<IBodyProps, IState> {
|
|||
return;
|
||||
}
|
||||
|
||||
if (POLL_RESPONSE_EVENT_TYPE.matches(eventType)) {
|
||||
if (M_POLL_RESPONSE.matches(eventType)) {
|
||||
this.voteRelationsReceived = true;
|
||||
const newVoteRelations = this.fetchVoteRelations();
|
||||
this.addListeners(newVoteRelations);
|
||||
this.removeListeners(this.state.voteRelations);
|
||||
this.setState({ voteRelations: newVoteRelations });
|
||||
} else if (POLL_END_EVENT_TYPE.matches(eventType)) {
|
||||
} else if (M_POLL_END.matches(eventType)) {
|
||||
this.endRelationsReceived = true;
|
||||
const newEndRelations = this.fetchEndRelations();
|
||||
this.addListeners(newEndRelations);
|
||||
|
@ -233,20 +254,12 @@ export default class MPollBody extends React.Component<IBodyProps, IState> {
|
|||
return;
|
||||
}
|
||||
|
||||
const responseContent: IPollResponseContent = {
|
||||
[POLL_RESPONSE_EVENT_TYPE.name]: {
|
||||
"answers": [answerId],
|
||||
},
|
||||
"m.relates_to": {
|
||||
"event_id": this.props.mxEvent.getId(),
|
||||
"rel_type": "m.reference",
|
||||
},
|
||||
};
|
||||
const response = PollResponseEvent.from([answerId], this.props.mxEvent.getId()).serialize();
|
||||
|
||||
this.context.sendEvent(
|
||||
this.props.mxEvent.getRoomId(),
|
||||
POLL_RESPONSE_EVENT_TYPE.name,
|
||||
responseContent,
|
||||
response.type,
|
||||
response.content,
|
||||
).catch((e: any) => {
|
||||
console.error("Failed to submit poll response event:", e);
|
||||
|
||||
|
@ -269,21 +282,28 @@ export default class MPollBody extends React.Component<IBodyProps, IState> {
|
|||
this.selectOption(e.currentTarget.value);
|
||||
};
|
||||
|
||||
private fetchVoteRelations(): Relations | null {
|
||||
return this.fetchRelations(POLL_RESPONSE_EVENT_TYPE.name);
|
||||
private fetchVoteRelations(): RelatedRelations | null {
|
||||
return this.fetchRelations(M_POLL_RESPONSE);
|
||||
}
|
||||
|
||||
private fetchEndRelations(): Relations | null {
|
||||
return this.fetchRelations(POLL_END_EVENT_TYPE.name);
|
||||
private fetchEndRelations(): RelatedRelations | null {
|
||||
return this.fetchRelations(M_POLL_END);
|
||||
}
|
||||
|
||||
private fetchRelations(eventType: string): Relations | null {
|
||||
private fetchRelations(eventType: NamespacedValue<string, string>): RelatedRelations | null {
|
||||
if (this.props.getRelationsForEvent) {
|
||||
return this.props.getRelationsForEvent(
|
||||
this.props.mxEvent.getId(),
|
||||
"m.reference",
|
||||
eventType,
|
||||
);
|
||||
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,
|
||||
),
|
||||
]);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
@ -349,17 +369,13 @@ export default class MPollBody extends React.Component<IBodyProps, IState> {
|
|||
}
|
||||
|
||||
render() {
|
||||
const pollStart: IPollContent = this.props.mxEvent.getContent();
|
||||
const pollInfo = pollStart[POLL_START_EVENT_TYPE.name];
|
||||
|
||||
if (pollInfo.answers.length < 1 || pollInfo.answers.length > 20) {
|
||||
return null;
|
||||
}
|
||||
const poll = this.props.mxEvent.unstableExtensibleEvent as PollStartEvent;
|
||||
if (!poll?.isEquivalentTo(M_POLL_START)) return null; // invalid
|
||||
|
||||
const ended = this.isEnded();
|
||||
const pollId = this.props.mxEvent.getId();
|
||||
const userVotes = this.collectUserVotes();
|
||||
const votes = countVotes(userVotes, this.props.mxEvent.getContent());
|
||||
const votes = countVotes(userVotes, poll);
|
||||
const totalVotes = this.totalVotes(votes);
|
||||
const winCount = Math.max(...votes.values());
|
||||
const userId = this.context.getUserId();
|
||||
|
@ -385,10 +401,10 @@ export default class MPollBody extends React.Component<IBodyProps, IState> {
|
|||
}
|
||||
|
||||
return <div className="mx_MPollBody">
|
||||
<h2>{ pollInfo.question[TEXT_NODE_TYPE.name] }</h2>
|
||||
<h2>{ poll.question.text }</h2>
|
||||
<div className="mx_MPollBody_allOptions">
|
||||
{
|
||||
pollInfo.answers.map((answer: IPollAnswer) => {
|
||||
poll.answers.map((answer: PollAnswerSubevent) => {
|
||||
let answerVotes = 0;
|
||||
let votesText = "";
|
||||
|
||||
|
@ -448,7 +464,7 @@ export default class MPollBody extends React.Component<IBodyProps, IState> {
|
|||
}
|
||||
|
||||
interface IEndedPollOptionProps {
|
||||
answer: IPollAnswer;
|
||||
answer: PollAnswerSubevent;
|
||||
checked: boolean;
|
||||
votesText: string;
|
||||
}
|
||||
|
@ -461,7 +477,7 @@ function EndedPollOption(props: IEndedPollOptionProps) {
|
|||
return <div className={cls} data-value={props.answer.id}>
|
||||
<div className="mx_MPollBody_optionDescription">
|
||||
<div className="mx_MPollBody_optionText">
|
||||
{ props.answer[TEXT_NODE_TYPE.name] }
|
||||
{ props.answer.text }
|
||||
</div>
|
||||
<div className="mx_MPollBody_optionVoteCount">
|
||||
{ props.votesText }
|
||||
|
@ -472,7 +488,7 @@ function EndedPollOption(props: IEndedPollOptionProps) {
|
|||
|
||||
interface ILivePollOptionProps {
|
||||
pollId: string;
|
||||
answer: IPollAnswer;
|
||||
answer: PollAnswerSubevent;
|
||||
checked: boolean;
|
||||
votesText: string;
|
||||
onOptionSelected: (e: React.FormEvent<HTMLInputElement>) => void;
|
||||
|
@ -487,7 +503,7 @@ function LivePollOption(props: ILivePollOptionProps) {
|
|||
>
|
||||
<div className="mx_MPollBody_optionDescription">
|
||||
<div className="mx_MPollBody_optionText">
|
||||
{ props.answer[TEXT_NODE_TYPE.name] }
|
||||
{ props.answer.text }
|
||||
</div>
|
||||
<div className="mx_MPollBody_optionVoteCount">
|
||||
{ props.votesText }
|
||||
|
@ -502,21 +518,23 @@ export class UserVote {
|
|||
}
|
||||
|
||||
function userResponseFromPollResponseEvent(event: MatrixEvent): UserVote {
|
||||
const pr = event.getContent() as IPollResponseContent;
|
||||
const answers = pr[POLL_RESPONSE_EVENT_TYPE.name].answers;
|
||||
const response = event.unstableExtensibleEvent as PollResponseEvent;
|
||||
if (!response?.isEquivalentTo(M_POLL_RESPONSE)) {
|
||||
throw new Error("Failed to parse Poll Response Event to determine user response");
|
||||
}
|
||||
|
||||
return new UserVote(
|
||||
event.getTs(),
|
||||
event.getSender(),
|
||||
answers,
|
||||
response.answerIds,
|
||||
);
|
||||
}
|
||||
|
||||
export function allVotes(
|
||||
pollEvent: MatrixEvent,
|
||||
matrixClient: MatrixClient,
|
||||
voteRelations: Relations,
|
||||
endRelations: Relations,
|
||||
voteRelations: RelatedRelations,
|
||||
endRelations: RelatedRelations,
|
||||
): Array<UserVote> {
|
||||
const endTs = pollEndTs(pollEvent, matrixClient, endRelations);
|
||||
|
||||
|
@ -546,7 +564,7 @@ export function allVotes(
|
|||
export function pollEndTs(
|
||||
pollEvent: MatrixEvent,
|
||||
matrixClient: MatrixClient,
|
||||
endRelations: Relations,
|
||||
endRelations: RelatedRelations,
|
||||
): number | null {
|
||||
if (!endRelations) {
|
||||
return null;
|
||||
|
@ -575,10 +593,7 @@ export function pollEndTs(
|
|||
}
|
||||
|
||||
function isPollResponse(responseEvent: MatrixEvent): boolean {
|
||||
return (
|
||||
POLL_RESPONSE_EVENT_TYPE.matches(responseEvent.getType()) &&
|
||||
POLL_RESPONSE_EVENT_TYPE.findIn(responseEvent.getContent())
|
||||
);
|
||||
return responseEvent.unstableExtensibleEvent?.isEquivalentTo(M_POLL_RESPONSE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -608,24 +623,15 @@ function collectUserVotes(
|
|||
|
||||
function countVotes(
|
||||
userVotes: Map<string, UserVote>,
|
||||
pollStart: IPollContent,
|
||||
pollStart: PollStartEvent,
|
||||
): Map<string, number> {
|
||||
const collected = new Map<string, number>();
|
||||
|
||||
const pollInfo = pollStart[POLL_START_EVENT_TYPE.name];
|
||||
const maxSelections = 1; // See MSC3381 - later this will be in pollInfo
|
||||
|
||||
const allowedAnswerIds = pollInfo.answers.map((ans: IPollAnswer) => ans.id);
|
||||
function isValidAnswer(answerId: string) {
|
||||
return allowedAnswerIds.includes(answerId);
|
||||
}
|
||||
|
||||
for (const response of userVotes.values()) {
|
||||
if (response.answers.every(isValidAnswer)) {
|
||||
for (const [index, answerId] of response.answers.entries()) {
|
||||
if (index >= maxSelections) {
|
||||
break;
|
||||
}
|
||||
const tempResponse = PollResponseEvent.from(response.answers, "$irrelevant");
|
||||
tempResponse.validateAgainst(pollStart);
|
||||
if (!tempResponse.spoiled) {
|
||||
for (const answerId of tempResponse.answerIds) {
|
||||
if (collected.has(answerId)) {
|
||||
collected.set(answerId, collected.get(answerId) + 1);
|
||||
} else {
|
||||
|
|
|
@ -17,8 +17,8 @@ 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 { POLL_START_EVENT_TYPE } from "matrix-js-sdk/src/@types/polls";
|
||||
import { LOCATION_EVENT_TYPE } from 'matrix-js-sdk/src/@types/location';
|
||||
import { M_POLL_START } from "matrix-events-sdk";
|
||||
|
||||
import * as sdk from '../../../index';
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
|
@ -125,7 +125,7 @@ export default class MessageEvent extends React.Component<IProps> implements IMe
|
|||
BodyType = UnknownBody;
|
||||
}
|
||||
|
||||
if (type && type === POLL_START_EVENT_TYPE.name) {
|
||||
if (M_POLL_START.matches(type)) {
|
||||
// TODO: this can all disappear when Polls comes out of labs -
|
||||
// instead, add something like this into this.evTypes:
|
||||
// [EventType.Poll]: "messages.MPollBody"
|
||||
|
|
|
@ -18,7 +18,7 @@ import React, { createRef, SyntheticEvent } from 'react';
|
|||
import ReactDOM from 'react-dom';
|
||||
import highlight from 'highlight.js';
|
||||
import { MsgType } from "matrix-js-sdk/src/@types/event";
|
||||
import { isEventLike, LegacyMsgType, MessageEvent } from "matrix-events-sdk";
|
||||
import { isEventLike, LegacyMsgType, M_MESSAGE, MessageEvent } from "matrix-events-sdk";
|
||||
|
||||
import * as HtmlUtils from '../../../HtmlUtils';
|
||||
import { formatDate } from '../../../DateUtils';
|
||||
|
@ -542,8 +542,8 @@ export default class TextualBody extends React.Component<IBodyProps, IState> {
|
|||
const stripReply = !mxEvent.replacingEvent() && !!ReplyChain.getParentEventId(mxEvent);
|
||||
let body;
|
||||
if (SettingsStore.isEnabled("feature_extensible_events")) {
|
||||
const extev = this.props.mxEvent.unstableExtensibleEvent;
|
||||
if (extev && extev instanceof MessageEvent) {
|
||||
const extev = this.props.mxEvent.unstableExtensibleEvent as MessageEvent;
|
||||
if (extev?.isEquivalentTo(M_MESSAGE)) {
|
||||
isEmote = isEventLike(extev.wireFormat, LegacyMsgType.Emote);
|
||||
isNotice = isEventLike(extev.wireFormat, LegacyMsgType.Notice);
|
||||
body = HtmlUtils.bodyToHtml({
|
||||
|
|
|
@ -24,7 +24,7 @@ import { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
|||
import { Thread, ThreadEvent } from 'matrix-js-sdk/src/models/thread';
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { NotificationCountType, Room } from 'matrix-js-sdk/src/models/room';
|
||||
import { POLL_START_EVENT_TYPE } from "matrix-js-sdk/src/@types/polls";
|
||||
import { M_POLL_START } from "matrix-events-sdk";
|
||||
|
||||
import ReplyChain from "../elements/ReplyChain";
|
||||
import { _t } from '../../../languageHandler';
|
||||
|
@ -78,7 +78,8 @@ import { CardContext } from '../right_panel/BaseCard';
|
|||
const eventTileTypes = {
|
||||
[EventType.RoomMessage]: 'messages.MessageEvent',
|
||||
[EventType.Sticker]: 'messages.MessageEvent',
|
||||
[POLL_START_EVENT_TYPE.name]: 'messages.MessageEvent',
|
||||
[M_POLL_START.name]: 'messages.MessageEvent',
|
||||
[M_POLL_START.altName]: 'messages.MessageEvent',
|
||||
[EventType.KeyVerificationCancel]: 'messages.MKeyVerificationConclusion',
|
||||
[EventType.KeyVerificationDone]: 'messages.MKeyVerificationConclusion',
|
||||
[EventType.CallInvite]: 'messages.CallEvent',
|
||||
|
@ -178,7 +179,7 @@ export function getHandlerTile(ev: MatrixEvent): string {
|
|||
}
|
||||
|
||||
if (
|
||||
POLL_START_EVENT_TYPE.matches(type) &&
|
||||
M_POLL_START.matches(type) &&
|
||||
!SettingsStore.getValue("feature_polls")
|
||||
) {
|
||||
return undefined;
|
||||
|
|
|
@ -19,7 +19,7 @@ import { MatrixEvent, IEventRelation } from "matrix-js-sdk/src/models/event";
|
|||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
||||
import { RelationType } from 'matrix-js-sdk/src/@types/event';
|
||||
import { POLL_START_EVENT_TYPE } from "matrix-js-sdk/src/@types/polls";
|
||||
import { M_POLL_START } from "matrix-events-sdk";
|
||||
|
||||
import { _t } from '../../../languageHandler';
|
||||
import { MatrixClientPeg } from '../../../MatrixClientPeg';
|
||||
|
@ -197,7 +197,7 @@ interface IPollButtonProps extends Pick<ICollapsibleButtonProps, "narrowMode"> {
|
|||
class PollButton extends React.PureComponent<IPollButtonProps> {
|
||||
private onCreateClick = () => {
|
||||
const canSend = this.props.room.currentState.maySendEvent(
|
||||
POLL_START_EVENT_TYPE.name,
|
||||
M_POLL_START.name,
|
||||
MatrixClientPeg.get().getUserId(),
|
||||
);
|
||||
if (!canSend) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue