Allow pinning polls ()

* Allow pinning polls

Signed-off-by: Robin Townsend <robin@robin.town>

* Show responses to pinned polls

Signed-off-by: Robin Townsend <robin@robin.town>

* Use enums more

Signed-off-by: Robin Townsend <robin@robin.town>
pull/21833/head
Robin 2022-03-04 09:26:13 -05:00 committed by GitHub
parent 881307e97c
commit 3099a75a5d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 62 additions and 1 deletions
src
components/views/rooms

View File

@ -17,6 +17,10 @@ limitations under the License.
import React from "react";
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { Relations } from "matrix-js-sdk/src/models/relations";
import { EventType, RelationType } from "matrix-js-sdk/src/@types/event";
import { logger } from "matrix-js-sdk/src/logger";
import { M_POLL_START, M_POLL_RESPONSE, M_POLL_END } from "matrix-events-sdk";
import dis from "../../../dispatcher/dispatcher";
import { Action } from "../../../dispatcher/actions";
@ -52,6 +56,51 @@ export default class PinnedEventTile extends React.Component<IProps> {
});
};
// For event types like polls that use relations, we fetch those manually on
// mount and store them here, exposing them through getRelationsForEvent
private relations = new Map<string, Map<string, Relations>>();
private getRelationsForEvent = (
eventId: string,
relationType: RelationType | string,
eventType: EventType | string,
): Relations => {
if (eventId === this.props.event.getId()) {
return this.relations.get(relationType)?.get(eventType);
}
};
async componentDidMount() {
// Fetch poll responses
if (M_POLL_START.matches(this.props.event.getType())) {
const eventId = this.props.event.getId();
const roomId = this.props.event.getRoomId();
const room = this.context.getRoom(roomId);
try {
await Promise.all(
[M_POLL_RESPONSE.name, M_POLL_RESPONSE.altName, M_POLL_END.name, M_POLL_END.altName]
.map(async eventType => {
const { events } = await this.context.relations(
roomId, eventId, RelationType.Reference, eventType,
);
const relations = new Relations(RelationType.Reference, eventType, room);
if (!this.relations.has(RelationType.Reference)) {
this.relations.set(RelationType.Reference, new Map<string, Relations>());
}
this.relations.get(RelationType.Reference).set(eventType, relations);
relations.setTargetEvent(this.props.event);
events.forEach(event => relations.addEvent(event));
}),
);
} catch (err) {
logger.error(`Error fetching responses to pinned poll ${eventId} in room ${roomId}`);
logger.error(err);
}
}
}
render() {
const sender = this.props.event.getSender();
@ -84,6 +133,7 @@ export default class PinnedEventTile extends React.Component<IProps> {
<div className="mx_PinnedEventTile_message">
<MessageEvent
mxEvent={this.props.event}
getRelationsForEvent={this.getRelationsForEvent}
// @ts-ignore - complaining that className is invalid when it's not
className="mx_PinnedEventTile_body"
maxImageHeight={150}

View File

@ -15,8 +15,19 @@ limitations under the License.
*/
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { EventType } from "matrix-js-sdk/src/@types/event";
import { M_POLL_START } from "matrix-events-sdk";
export default class PinningUtils {
/**
* Event types that may be pinned.
*/
static pinnableEventTypes: (EventType | string)[] = [
EventType.RoomMessage,
M_POLL_START.name,
M_POLL_START.altName,
];
/**
* Determines if the given event may be pinned.
* @param {MatrixEvent} event The event to check.
@ -24,7 +35,7 @@ export default class PinningUtils {
*/
static isPinnable(event: MatrixEvent): boolean {
if (!event) return false;
if (event.getType() !== "m.room.message") return false;
if (!this.pinnableEventTypes.includes(event.getType())) return false;
if (event.isRedacted()) return false;
return true;