Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit 1d45921

Browse files
Improve/add notifications for location and poll events (#7552)
* Add getSenderName() Signed-off-by: Šimon Brandner <[email protected]> * Handle location and poll event notifications Signed-off-by: Šimon Brandner <[email protected]> * i18n Signed-off-by: Šimon Brandner <[email protected]> * pollQuestions -> pollQuestion Signed-off-by: Šimon Brandner <[email protected]> * Make lookup safe and remove poll end event lookup as it wouldn't work Signed-off-by: Šimon Brandner <[email protected]> * i18n Signed-off-by: Šimon Brandner <[email protected]>
1 parent aac5964 commit 1d45921

File tree

4 files changed

+81
-12
lines changed

4 files changed

+81
-12
lines changed

src/Notifier.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { MatrixEvent } from "matrix-js-sdk/src/models/event";
2121
import { Room } from "matrix-js-sdk/src/models/room";
2222
import { logger } from "matrix-js-sdk/src/logger";
2323
import { MsgType } from "matrix-js-sdk/src/@types/event";
24+
import { LOCATION_EVENT_TYPE } from "matrix-js-sdk/src/@types/location";
2425

2526
import { MatrixClientPeg } from './MatrixClientPeg';
2627
import SdkConfig from './SdkConfig';
@@ -56,10 +57,16 @@ This is useful when the content body contains fallback text that would explain t
5657
type of tile.
5758
*/
5859
const msgTypeHandlers = {
59-
[MsgType.KeyVerificationRequest]: (event) => {
60+
[MsgType.KeyVerificationRequest]: (event: MatrixEvent) => {
6061
const name = (event.sender || {}).name;
6162
return _t("%(name)s is requesting verification", { name });
6263
},
64+
[LOCATION_EVENT_TYPE.name]: (event: MatrixEvent) => {
65+
return TextForEvent.textForLocationEvent(event)();
66+
},
67+
[LOCATION_EVENT_TYPE.altName]: (event: MatrixEvent) => {
68+
return TextForEvent.textForLocationEvent(event)();
69+
},
6370
};
6471

6572
export const Notifier = {

src/TextForEvent.tsx

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,16 @@ import { logger } from "matrix-js-sdk/src/logger";
2020
import { removeDirectionOverrideChars } from 'matrix-js-sdk/src/utils';
2121
import { GuestAccess, HistoryVisibility, JoinRule } from "matrix-js-sdk/src/@types/partials";
2222
import { EventType, MsgType } from "matrix-js-sdk/src/@types/event";
23-
import { M_EMOTE, M_NOTICE, M_MESSAGE, MessageEvent } from "matrix-events-sdk";
23+
import {
24+
M_EMOTE,
25+
M_NOTICE,
26+
M_MESSAGE,
27+
MessageEvent,
28+
M_POLL_START,
29+
M_POLL_END,
30+
PollStartEvent,
31+
} from "matrix-events-sdk";
32+
import { LOCATION_EVENT_TYPE } from "matrix-js-sdk/src/@types/location";
2433

2534
import { _t } from './languageHandler';
2635
import * as Roles from './Roles';
@@ -36,12 +45,16 @@ import { ROOM_SECURITY_TAB } from "./components/views/dialogs/RoomSettingsDialog
3645
import AccessibleButton from './components/views/elements/AccessibleButton';
3746
import RightPanelStore from './stores/right-panel/RightPanelStore';
3847

48+
export function getSenderName(event: MatrixEvent): string {
49+
return event.sender?.name ?? event.getSender() ?? _t("Someone");
50+
}
51+
3952
// These functions are frequently used just to check whether an event has
4053
// any text to display at all. For this reason they return deferred values
4154
// to avoid the expense of looking up translations when they're not needed.
4255

4356
function textForCallInviteEvent(event: MatrixEvent): () => string | null {
44-
const getSenderName = () => event.sender ? event.sender.name : _t('Someone');
57+
const senderName = getSenderName(event);
4558
// FIXME: Find a better way to determine this from the event?
4659
let isVoice = true;
4760
if (event.getContent().offer && event.getContent().offer.sdp &&
@@ -55,19 +68,19 @@ function textForCallInviteEvent(event: MatrixEvent): () => string | null {
5568
// and more accurate, we break out the string-based variables to a couple booleans.
5669
if (isVoice && isSupported) {
5770
return () => _t("%(senderName)s placed a voice call.", {
58-
senderName: getSenderName(),
71+
senderName: senderName,
5972
});
6073
} else if (isVoice && !isSupported) {
6174
return () => _t("%(senderName)s placed a voice call. (not supported by this browser)", {
62-
senderName: getSenderName(),
75+
senderName: senderName,
6376
});
6477
} else if (!isVoice && isSupported) {
6578
return () => _t("%(senderName)s placed a video call.", {
66-
senderName: getSenderName(),
79+
senderName: senderName,
6780
});
6881
} else if (!isVoice && !isSupported) {
6982
return () => _t("%(senderName)s placed a video call. (not supported by this browser)", {
70-
senderName: getSenderName(),
83+
senderName: senderName,
7184
});
7285
}
7386
}
@@ -325,6 +338,17 @@ function textForServerACLEvent(ev: MatrixEvent): () => string | null {
325338
}
326339

327340
function textForMessageEvent(ev: MatrixEvent): () => string | null {
341+
const type = ev.getType();
342+
const content = ev.getContent();
343+
const msgtype = content.msgtype;
344+
345+
if (
346+
(LOCATION_EVENT_TYPE.matches(type) || LOCATION_EVENT_TYPE.matches(msgtype)) &&
347+
SettingsStore.getValue("feature_location_share")
348+
) {
349+
return textForLocationEvent(ev);
350+
}
351+
328352
return () => {
329353
const senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender();
330354
let message = ev.getContent().body;
@@ -418,7 +442,7 @@ function textForCanonicalAliasEvent(ev: MatrixEvent): () => string | null {
418442
}
419443

420444
function textForThreePidInviteEvent(event: MatrixEvent): () => string | null {
421-
const senderName = event.sender ? event.sender.name : event.getSender();
445+
const senderName = getSenderName(event);
422446

423447
if (!isValid3pidInvite(event)) {
424448
return () => _t('%(senderName)s revoked the invitation for %(targetDisplayName)s to join the room.', {
@@ -434,7 +458,7 @@ function textForThreePidInviteEvent(event: MatrixEvent): () => string | null {
434458
}
435459

436460
function textForHistoryVisibilityEvent(event: MatrixEvent): () => string | null {
437-
const senderName = event.sender ? event.sender.name : event.getSender();
461+
const senderName = getSenderName(event);
438462
switch (event.getContent().history_visibility) {
439463
case HistoryVisibility.Invited:
440464
return () => _t('%(senderName)s made future room history visible to all room members, '
@@ -456,7 +480,7 @@ function textForHistoryVisibilityEvent(event: MatrixEvent): () => string | null
456480

457481
// Currently will only display a change if a user's power level is changed
458482
function textForPowerEvent(event: MatrixEvent): () => string | null {
459-
const senderName = event.sender ? event.sender.name : event.getSender();
483+
const senderName = getSenderName(event);
460484
if (!event.getPrevContent() || !event.getPrevContent().users ||
461485
!event.getContent() || !event.getContent().users) {
462486
return null;
@@ -523,7 +547,7 @@ const onPinnedMessagesClick = (): void => {
523547

524548
function textForPinnedEvent(event: MatrixEvent, allowJSX: boolean): () => string | JSX.Element | null {
525549
if (!SettingsStore.getValue("feature_pinning")) return null;
526-
const senderName = event.sender ? event.sender.name : event.getSender();
550+
const senderName = getSenderName(event);
527551
const roomId = event.getRoomId();
528552

529553
const pinned = event.getContent().pinned ?? [];
@@ -729,6 +753,25 @@ function textForMjolnirEvent(event: MatrixEvent): () => string | null {
729753
"for %(reason)s", { senderName, oldGlob: prevEntity, newGlob: entity, reason });
730754
}
731755

756+
export function textForLocationEvent(event: MatrixEvent): () => string | null {
757+
return () => _t("%(senderName)s has shared their location", {
758+
senderName: getSenderName(event),
759+
});
760+
}
761+
762+
function textForPollStartEvent(event: MatrixEvent): () => string | null {
763+
return () => _t("%(senderName)s has started a poll - %(pollQuestion)s", {
764+
senderName: getSenderName(event),
765+
pollQuestion: (event.unstableExtensibleEvent as PollStartEvent)?.question?.text,
766+
});
767+
}
768+
769+
function textForPollEndEvent(event: MatrixEvent): () => string | null {
770+
return () => _t("%(senderName)s has ended a poll", {
771+
senderName: getSenderName(event),
772+
});
773+
}
774+
732775
interface IHandlers {
733776
[type: string]:
734777
(ev: MatrixEvent, allowJSX: boolean, showHiddenEvents?: boolean) =>
@@ -739,6 +782,10 @@ const handlers: IHandlers = {
739782
[EventType.RoomMessage]: textForMessageEvent,
740783
[EventType.Sticker]: textForMessageEvent,
741784
[EventType.CallInvite]: textForCallInviteEvent,
785+
[M_POLL_START.name]: textForPollStartEvent,
786+
[M_POLL_END.name]: textForPollEndEvent,
787+
[M_POLL_START.altName]: textForPollStartEvent,
788+
[M_POLL_END.altName]: textForPollEndEvent,
742789
};
743790

744791
const stateHandlers: IHandlers = {

src/i18n/strings/en_EN.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,9 @@
589589
"%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching %(newGlob)s for %(reason)s",
590590
"%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching %(newGlob)s for %(reason)s",
591591
"%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s",
592+
"%(senderName)s has shared their location": "%(senderName)s has shared their location",
593+
"%(senderName)s has started a poll - %(pollQuestion)s": "%(senderName)s has started a poll - %(pollQuestion)s",
594+
"%(senderName)s has ended a poll": "%(senderName)s has ended a poll",
592595
"Light": "Light",
593596
"Light high contrast": "Light high contrast",
594597
"Dark": "Dark",

test/TextForEvent-test.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import './skinned-sdk';
33
import { MatrixEvent } from "matrix-js-sdk";
44
import renderer from 'react-test-renderer';
55

6-
import { textForEvent } from "../src/TextForEvent";
6+
import { getSenderName, textForEvent } from "../src/TextForEvent";
77
import SettingsStore from "../src/settings/SettingsStore";
88
import { SettingLevel } from "../src/settings/SettingLevel";
99

@@ -54,6 +54,18 @@ function renderComponent(component): string {
5454
}
5555

5656
describe('TextForEvent', () => {
57+
describe("getSenderName()", () => {
58+
it("Prefers sender.name", () => {
59+
expect(getSenderName({ sender: { name: "Alice" } } as MatrixEvent)).toBe("Alice");
60+
});
61+
it("Handles missing sender", () => {
62+
expect(getSenderName({ getSender: () => "Alice" } as MatrixEvent)).toBe("Alice");
63+
});
64+
it("Handles missing sender and get sender", () => {
65+
expect(getSenderName({ getSender: () => undefined } as MatrixEvent)).toBe("Someone");
66+
});
67+
});
68+
5769
describe("TextForPinnedEvent", () => {
5870
SettingsStore.setValue("feature_pinning", null, SettingLevel.DEVICE, true);
5971

0 commit comments

Comments
 (0)