Skip to content
This repository was 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 all 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?.phase && !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,
];