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

Commit ee13e23

Browse files
author
Germain
authored
Resilience fix for homeserver without thread notification support (#9565)
* Notification state resilience * TypeScript strict fixes * Add tests
1 parent 8ebdcab commit ee13e23

File tree

2 files changed

+30
-20
lines changed

2 files changed

+30
-20
lines changed

src/components/views/right_panel/RoomHeaderButtons.tsx

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ import { RightPanelPhases } from '../../../stores/right-panel/RightPanelStorePha
3030
import { Action } from "../../../dispatcher/actions";
3131
import { ActionPayload } from "../../../dispatcher/payloads";
3232
import RightPanelStore from "../../../stores/right-panel/RightPanelStore";
33-
import { useSettingValue } from "../../../hooks/useSettings";
3433
import { useReadPinnedEvents, usePinnedEvents } from './PinnedMessagesCard';
3534
import { showThreadPanel } from "../../../dispatcher/dispatch-actions/threads";
3635
import SettingsStore from "../../../settings/SettingsStore";
@@ -85,9 +84,8 @@ interface IHeaderButtonProps {
8584
}
8685

8786
const PinnedMessagesHeaderButton = ({ room, isHighlighted, onClick }: IHeaderButtonProps) => {
88-
const pinningEnabled = useSettingValue("feature_pinning");
89-
const pinnedEvents = usePinnedEvents(pinningEnabled && room);
90-
const readPinnedEvents = useReadPinnedEvents(pinningEnabled && room);
87+
const pinnedEvents = usePinnedEvents(room);
88+
const readPinnedEvents = useReadPinnedEvents(room);
9189
if (!pinnedEvents?.length) return null;
9290

9391
let unreadIndicator;
@@ -135,7 +133,7 @@ export default class RoomHeaderButtons extends HeaderButtons<IProps> {
135133
RightPanelPhases.ThreadPanel,
136134
RightPanelPhases.ThreadView,
137135
];
138-
private threadNotificationState: ThreadsRoomNotificationState;
136+
private threadNotificationState: ThreadsRoomNotificationState | null;
139137
private globalNotificationState: SummarizedNotificationState;
140138

141139
private get supportsThreadNotifications(): boolean {
@@ -146,9 +144,9 @@ export default class RoomHeaderButtons extends HeaderButtons<IProps> {
146144
constructor(props: IProps) {
147145
super(props, HeaderKind.Room);
148146

149-
if (!this.supportsThreadNotifications) {
150-
this.threadNotificationState = RoomNotificationStateStore.instance.getThreadsRoomState(this.props.room);
151-
}
147+
this.threadNotificationState = !this.supportsThreadNotifications && this.props.room
148+
? RoomNotificationStateStore.instance.getThreadsRoomState(this.props.room)
149+
: null;
152150
this.globalNotificationState = RoomNotificationStateStore.instance.globalState;
153151
}
154152

@@ -176,7 +174,7 @@ export default class RoomHeaderButtons extends HeaderButtons<IProps> {
176174
private onNotificationUpdate = (): void => {
177175
let threadNotificationColor: NotificationColor;
178176
if (!this.supportsThreadNotifications) {
179-
threadNotificationColor = this.threadNotificationState.color;
177+
threadNotificationColor = this.threadNotificationState?.color ?? NotificationColor.None;
180178
} else {
181179
threadNotificationColor = this.notificationColor;
182180
}
@@ -189,7 +187,7 @@ export default class RoomHeaderButtons extends HeaderButtons<IProps> {
189187
};
190188

191189
private get notificationColor(): NotificationColor {
192-
switch (this.props.room.threadsAggregateNotificationType) {
190+
switch (this.props.room?.threadsAggregateNotificationType) {
193191
case NotificationCountType.Highlight:
194192
return NotificationColor.Red;
195193
case NotificationCountType.Total:
@@ -263,23 +261,29 @@ export default class RoomHeaderButtons extends HeaderButtons<IProps> {
263261

264262
private onThreadsPanelClicked = (ev: ButtonEvent) => {
265263
if (RoomHeaderButtons.THREAD_PHASES.includes(this.state.phase)) {
266-
RightPanelStore.instance.togglePanel(this.props.room?.roomId);
264+
RightPanelStore.instance.togglePanel(this.props.room?.roomId ?? null);
267265
} else {
268266
showThreadPanel();
269267
PosthogTrackers.trackInteraction("WebRoomHeaderButtonsThreadsButton", ev);
270268
}
271269
};
272270

273271
public renderButtons() {
272+
if (!this.props.room) {
273+
return <></>;
274+
}
275+
274276
const rightPanelPhaseButtons: Map<RightPanelPhases, any> = new Map();
275277

276-
rightPanelPhaseButtons.set(RightPanelPhases.PinnedMessages,
277-
<PinnedMessagesHeaderButton
278-
key="pinnedMessagesButton"
279-
room={this.props.room}
280-
isHighlighted={this.isPhase(RightPanelPhases.PinnedMessages)}
281-
onClick={this.onPinnedMessagesClicked} />,
282-
);
278+
if (SettingsStore.getValue("feature_pinning")) {
279+
rightPanelPhaseButtons.set(RightPanelPhases.PinnedMessages,
280+
<PinnedMessagesHeaderButton
281+
key="pinnedMessagesButton"
282+
room={this.props.room}
283+
isHighlighted={this.isPhase(RightPanelPhases.PinnedMessages)}
284+
onClick={this.onPinnedMessagesClicked} />,
285+
);
286+
}
283287
rightPanelPhaseButtons.set(RightPanelPhases.Timeline,
284288
<TimelineCardHeaderButton
285289
key="timelineButton"

test/components/views/right_panel/RoomHeaderButtons-test.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ limitations under the License.
1616

1717
import { render } from "@testing-library/react";
1818
import { MatrixClient, PendingEventOrdering } from "matrix-js-sdk/src/client";
19+
import { Feature, ServerSupport } from "matrix-js-sdk/src/feature";
1920
import { NotificationCountType, Room } from "matrix-js-sdk/src/models/room";
2021
import React from "react";
2122

@@ -34,7 +35,7 @@ describe("RoomHeaderButtons-test.tsx", function() {
3435

3536
stubClient();
3637
client = MatrixClientPeg.get();
37-
room = new Room(ROOM_ID, client, client.getUserId(), {
38+
room = new Room(ROOM_ID, client, client.getUserId() ?? "", {
3839
pendingEventOrdering: PendingEventOrdering.Detached,
3940
});
4041

@@ -43,7 +44,7 @@ describe("RoomHeaderButtons-test.tsx", function() {
4344
});
4445
});
4546

46-
function getComponent(room: Room) {
47+
function getComponent(room?: Room) {
4748
return render(<RoomHeaderButtons
4849
room={room}
4950
excludedRightPanelPhaseButtons={[]}
@@ -94,4 +95,9 @@ describe("RoomHeaderButtons-test.tsx", function() {
9495

9596
expect(container.querySelector(".mx_RightPanel_threadsButton .mx_Indicator")).toBeNull();
9697
});
98+
99+
it("does not explode without a room", () => {
100+
client.canSupport.set(Feature.ThreadUnreadNotifications, ServerSupport.Unsupported);
101+
expect(() => getComponent()).not.toThrow();
102+
});
97103
});

0 commit comments

Comments
 (0)