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

Fix right panel soft crashes due to missing room prop #7923

Merged
merged 7 commits into from
Mar 1, 2022
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions res/css/structures/_GroupView.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ limitations under the License.
display: flex;
flex-direction: column;
overflow: hidden;
flex-grow: 1;
}

.mx_GroupView_error {
Expand Down
2 changes: 1 addition & 1 deletion src/components/structures/MatrixChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -983,7 +983,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
this.viewWelcome();
return;
}
if (!this.state.currentGroupId && !this.state.currentRoomId) {
if (!this.state.currentGroupId && !this.state.currentRoomId && !this.state.currentUserId) {
this.viewHome();
}
}
Expand Down
29 changes: 19 additions & 10 deletions src/components/structures/RightPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,23 @@ export default class RightPanel extends React.Component<IProps, IState> {
}

public static getDerivedStateFromProps(props: IProps): Partial<IState> {
const currentCard = RightPanelStore.instance.currentCardForRoom(props.room.roomId);
let currentCard: IRightPanelCard;
if (props.room) {
currentCard = RightPanelStore.instance.currentCardForRoom(props.room.roomId);
}
if (props.groupId) {
currentCard = RightPanelStore.instance.currentGroup;
}

if (currentCard && !RightPanelStore.instance.isPhaseValid(currentCard.phase, !!props.room)) {
// XXX: We can probably get rid of this workaround once GroupView is dead, it's unmounting happens weirdly
// late causing the app to soft-crash due to lack of a room object being passed to a RightPanel
return null; // skip this update, we're about to be unmounted and don't have the appropriate props
}

return {
cardState: currentCard.state,
phase: currentCard.phase,
cardState: currentCard?.state,
phase: currentCard?.phase,
};
}

Expand All @@ -116,11 +129,7 @@ export default class RightPanel extends React.Component<IProps, IState> {
};

private onRightPanelStoreUpdate = () => {
const currentCard = RightPanelStore.instance.currentCardForRoom(this.props.room.roomId);
this.setState({
cardState: currentCard.state,
phase: currentCard.phase,
});
this.setState({ ...RightPanel.getDerivedStateFromProps(this.props) as IState });
};

private onClose = () => {
Expand All @@ -137,7 +146,7 @@ export default class RightPanel extends React.Component<IProps, IState> {
});
} else if (
this.state.phase === RightPanelPhases.EncryptionPanel &&
this.state.cardState.verificationRequest && this.state.cardState.verificationRequest.pending
this.state.cardState.verificationRequest?.pending
) {
// When the user clicks close on the encryption panel cancel the pending request first if any
this.state.cardState.verificationRequest.cancel();
Expand All @@ -152,7 +161,7 @@ export default class RightPanel extends React.Component<IProps, IState> {

public render(): JSX.Element {
let card = <div />;
const roomId = this.props.room ? this.props.room.roomId : undefined;
const roomId = this.props.room?.roomId;
const phase = this.props.overwriteCard?.phase ?? this.state.phase;
const cardState = this.props.overwriteCard?.state ?? this.state.cardState;
switch (phase) {
Expand Down
2 changes: 1 addition & 1 deletion src/components/structures/ThreadView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ export default class ThreadView extends React.Component<IProps, IState> {

public componentWillUnmount(): void {
this.teardownThread();
dis.unregister(this.dispatcherRef);
if (this.dispatcherRef) dis.unregister(this.dispatcherRef);
const room = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId());
room.removeListener(ThreadEvent.New, this.onNewThread);
SettingsStore.unwatchSetting(this.layoutWatcherRef);
Expand Down
14 changes: 7 additions & 7 deletions src/stores/right-panel/RightPanelStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ export default class RightPanelStore extends ReadyWatchingStore {
const cardState = redirect?.state ?? (Object.keys(card.state ?? {}).length === 0 ? null : card.state);

// Checks for wrong SetRightPanelPhase requests
if (!this.isPhaseActionValid(targetPhase)) return;
if (!this.isPhaseValid(targetPhase)) return;

if ((targetPhase === this.currentCardForRoom(rId)?.phase && !!cardState)) {
// Update state: set right panel with a new state but keep the phase (dont know it this is ever needed...)
Expand Down Expand Up @@ -195,16 +195,16 @@ export default class RightPanelStore extends ReadyWatchingStore {
const pState = redirect?.state ?? (Object.keys(card.state ?? {}).length === 0 ? null : card.state);

// Checks for wrong SetRightPanelPhase requests
if (!this.isPhaseActionValid(targetPhase)) return;
if (!this.isPhaseValid(targetPhase)) return;

let roomCache = this.byRoom[rId];
const roomCache = this.byRoom[rId];
if (!!roomCache) {
// append new phase
roomCache.history.push({ state: pState, phase: targetPhase });
roomCache.isOpen = allowClose ? roomCache.isOpen : true;
} else {
// setup room panel cache with the new card
roomCache = {
this.byRoom[rId] = {
history: [{ phase: targetPhase, state: pState ?? {} }],
// if there was no right panel store object the the panel was closed -> keep it closed, except if allowClose==false
isOpen: !allowClose,
Expand Down Expand Up @@ -345,18 +345,18 @@ export default class RightPanelStore extends ReadyWatchingStore {
return null;
}

private isPhaseActionValid(targetPhase) {
public isPhaseValid(targetPhase: RightPanelPhases, isViewingRoom = this.isViewingRoom): boolean {
if (!RightPanelPhases[targetPhase]) {
logger.warn(`Tried to switch right panel to unknown phase: ${targetPhase}`);
return false;
}
if (GROUP_PHASES.includes(targetPhase) && this.isViewingRoom) {
if (GROUP_PHASES.includes(targetPhase) && isViewingRoom) {
logger.warn(
`Tried to switch right panel to a group phase: ${targetPhase}, ` +
`but we are currently not viewing a group`,
);
return false;
} else if (!GROUP_PHASES.includes(targetPhase) && !this.isViewingRoom) {
} else if (!GROUP_PHASES.includes(targetPhase) && !isViewingRoom) {
logger.warn(
`Tried to switch right panel to a room phase: ${targetPhase}, ` +
`but we are currently not viewing a room`,
Expand Down
20 changes: 0 additions & 20 deletions src/stores/right-panel/RightPanelStorePhases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,23 +56,3 @@ export function backLabelForPhase(phase: RightPanelPhases) {
}
return null;
}

// These are the phases that are safe to persist (the ones that don't require additional
// arguments).
export const RIGHT_PANEL_PHASES_NO_ARGS = [
RightPanelPhases.RoomSummary,
RightPanelPhases.NotificationPanel,
RightPanelPhases.PinnedMessages,
RightPanelPhases.FilePanel,
RightPanelPhases.RoomMemberList,
RightPanelPhases.GroupMemberList,
RightPanelPhases.GroupRoomList,
RightPanelPhases.Timeline,
];

// Subset of phases visible in the Space View
export const RIGHT_PANEL_SPACE_PHASES = [
RightPanelPhases.SpaceMemberList,
RightPanelPhases.Space3pidMemberInfo,
RightPanelPhases.SpaceMemberInfo,
];