From fc96af50140fafadc6465977e3dfd975d734c40e Mon Sep 17 00:00:00 2001 From: Andy Balaam Date: Fri, 10 Dec 2021 12:17:26 +0000 Subject: [PATCH] Show poll question in message preview (#7320) --- src/stores/room-list/MessagePreviewStore.ts | 6 ++ .../previews/PollStartEventPreview.ts | 60 ++++++++++++++++ .../previews/PollStartEventPreview-test.ts | 71 +++++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100644 src/stores/room-list/previews/PollStartEventPreview.ts create mode 100644 test/stores/room-list/previews/PollStartEventPreview-test.ts diff --git a/src/stores/room-list/MessagePreviewStore.ts b/src/stores/room-list/MessagePreviewStore.ts index aa8bf97953..ffd8c1ced5 100644 --- a/src/stores/room-list/MessagePreviewStore.ts +++ b/src/stores/room-list/MessagePreviewStore.ts @@ -22,6 +22,7 @@ import { ActionPayload } from "../../dispatcher/payloads"; import { AsyncStoreWithClient } from "../AsyncStoreWithClient"; import defaultDispatcher from "../../dispatcher/dispatcher"; import { MessageEventPreview } from "./previews/MessageEventPreview"; +import { PollStartEventPreview } from "./previews/PollStartEventPreview"; import { TagID } from "./models"; import { CallInviteEventPreview } from "./previews/CallInviteEventPreview"; import { CallAnswerEventPreview } from "./previews/CallAnswerEventPreview"; @@ -29,6 +30,7 @@ import { CallHangupEvent } from "./previews/CallHangupEvent"; import { StickerEventPreview } from "./previews/StickerEventPreview"; import { ReactionEventPreview } from "./previews/ReactionEventPreview"; import { UPDATE_EVENT } from "../AsyncStore"; +import { POLL_START_EVENT_TYPE } from "../../polls/consts"; // Emitted event for when a room's preview has changed. First argument will the room for which // the change happened. @@ -39,6 +41,10 @@ const PREVIEWS = { isState: false, previewer: new MessageEventPreview(), }, + [POLL_START_EVENT_TYPE.name]: { + isState: false, + previewer: new PollStartEventPreview(), + }, 'm.call.invite': { isState: false, previewer: new CallInviteEventPreview(), diff --git a/src/stores/room-list/previews/PollStartEventPreview.ts b/src/stores/room-list/previews/PollStartEventPreview.ts new file mode 100644 index 0000000000..ff78258d3b --- /dev/null +++ b/src/stores/room-list/previews/PollStartEventPreview.ts @@ -0,0 +1,60 @@ +/* +Copyright 2021 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 { MatrixEvent } from "matrix-js-sdk/src/models/event"; + +import { IPreview } from "./IPreview"; +import { TagID } from "../models"; +import { _t, sanitizeForTranslation } from "../../../languageHandler"; +import { getSenderName, isSelf, shouldPrefixMessagesIn } from "./utils"; +import { POLL_START_EVENT_TYPE, TEXT_NODE_TYPE } from "../../../polls/consts"; +import MatrixClientContext from "../../../contexts/MatrixClientContext"; + +export class PollStartEventPreview implements IPreview { + public static contextType = MatrixClientContext; + public context!: React.ContextType; + + public getTextFor(event: MatrixEvent, tagId?: TagID, isThread?: boolean): string { + let eventContent = event.getContent(); + + if (event.isRelation("m.replace")) { + // It's an edit, generate the preview on the new text + eventContent = event.getContent()['m.new_content']; + } + + // Check we have the information we need, and bail out if not + if (!eventContent || !eventContent[POLL_START_EVENT_TYPE.name]) { + return null; + } + + let question = + eventContent[POLL_START_EVENT_TYPE.name].question[TEXT_NODE_TYPE.name]; + question = (question || '').trim(); + question = sanitizeForTranslation(question); + + if ( + isThread || + isSelf(event) || + !shouldPrefixMessagesIn(event.getRoomId(), tagId) + ) { + return question; + } else { + return _t("%(senderName)s: %(message)s", + { senderName: getSenderName(event), message: question }, + ); + } + } +} diff --git a/test/stores/room-list/previews/PollStartEventPreview-test.ts b/test/stores/room-list/previews/PollStartEventPreview-test.ts new file mode 100644 index 0000000000..d1df55685a --- /dev/null +++ b/test/stores/room-list/previews/PollStartEventPreview-test.ts @@ -0,0 +1,71 @@ +/* +Copyright 2021 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 { MatrixEvent } from "matrix-js-sdk"; + +import { IPollAnswer } from "../../../../src/polls/consts"; +import { PollStartEventPreview } from "../../../../src/stores/room-list/previews/PollStartEventPreview"; +import { MatrixClientPeg } from "../../../../src/MatrixClientPeg"; + +MatrixClientPeg.matrixClient = { + getUserId: () => "@me:example.com", +}; + +describe("PollStartEventPreview", () => { + it("shows the question for a poll I created", async () => { + const pollStartEvent = newPollStartEvent("My Question", "@me:example.com"); + const preview = new PollStartEventPreview(); + expect(preview.getTextFor(pollStartEvent)).toBe("My Question"); + }); + + it("shows the sender and question for a poll created by someone else", async () => { + const pollStartEvent = newPollStartEvent("Your Question", "@yo:example.com"); + const preview = new PollStartEventPreview(); + expect(preview.getTextFor(pollStartEvent)).toBe("@yo:example.com: Your Question"); + }); +}); + +function newPollStartEvent( + question: string, + sender: string, + answers?: IPollAnswer[], +): MatrixEvent { + if (!answers) { + answers = [ + { "id": "socks", "org.matrix.msc1767.text": "Socks" }, + { "id": "shoes", "org.matrix.msc1767.text": "Shoes" }, + ]; + } + + return new MatrixEvent( + { + "event_id": "$mypoll", + "room_id": "#myroom:example.com", + "sender": sender, + "content": { + "org.matrix.msc3381.poll.start": { + "question": { + "org.matrix.msc1767.text": question, + }, + "kind": "org.matrix.msc3381.poll.disclosed", + "answers": answers, + }, + "org.matrix.msc1767.text": `${question}: answers`, + }, + }, + ); +} +