Fix right panel soft crashes due to missing room prop (#7923)
This commit is contained in:
parent
36adba101c
commit
7a32a68a0b
6 changed files with 29 additions and 39 deletions
|
@ -18,6 +18,7 @@ limitations under the License.
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_GroupView_error {
|
.mx_GroupView_error {
|
||||||
|
|
|
@ -983,7 +983,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||||
this.viewWelcome();
|
this.viewWelcome();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!this.state.currentGroupId && !this.state.currentRoomId) {
|
if (!this.state.currentGroupId && !this.state.currentRoomId && !this.state.currentUserId) {
|
||||||
this.viewHome();
|
this.viewHome();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,10 +92,23 @@ export default class RightPanel extends React.Component<IProps, IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getDerivedStateFromProps(props: IProps): Partial<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 {
|
return {
|
||||||
cardState: currentCard.state,
|
cardState: currentCard?.state,
|
||||||
phase: currentCard.phase,
|
phase: currentCard?.phase,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,11 +129,7 @@ export default class RightPanel extends React.Component<IProps, IState> {
|
||||||
};
|
};
|
||||||
|
|
||||||
private onRightPanelStoreUpdate = () => {
|
private onRightPanelStoreUpdate = () => {
|
||||||
const currentCard = RightPanelStore.instance.currentCardForRoom(this.props.room.roomId);
|
this.setState({ ...RightPanel.getDerivedStateFromProps(this.props) as IState });
|
||||||
this.setState({
|
|
||||||
cardState: currentCard.state,
|
|
||||||
phase: currentCard.phase,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private onClose = () => {
|
private onClose = () => {
|
||||||
|
@ -137,7 +146,7 @@ export default class RightPanel extends React.Component<IProps, IState> {
|
||||||
});
|
});
|
||||||
} else if (
|
} else if (
|
||||||
this.state.phase === RightPanelPhases.EncryptionPanel &&
|
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
|
// When the user clicks close on the encryption panel cancel the pending request first if any
|
||||||
this.state.cardState.verificationRequest.cancel();
|
this.state.cardState.verificationRequest.cancel();
|
||||||
|
@ -152,7 +161,7 @@ export default class RightPanel extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
public render(): JSX.Element {
|
public render(): JSX.Element {
|
||||||
let card = <div />;
|
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 phase = this.props.overwriteCard?.phase ?? this.state.phase;
|
||||||
const cardState = this.props.overwriteCard?.state ?? this.state.cardState;
|
const cardState = this.props.overwriteCard?.state ?? this.state.cardState;
|
||||||
switch (phase) {
|
switch (phase) {
|
||||||
|
|
|
@ -106,7 +106,7 @@ export default class ThreadView extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
public componentWillUnmount(): void {
|
public componentWillUnmount(): void {
|
||||||
this.teardownThread();
|
this.teardownThread();
|
||||||
dis.unregister(this.dispatcherRef);
|
if (this.dispatcherRef) dis.unregister(this.dispatcherRef);
|
||||||
const room = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId());
|
const room = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId());
|
||||||
room.removeListener(ThreadEvent.New, this.onNewThread);
|
room.removeListener(ThreadEvent.New, this.onNewThread);
|
||||||
SettingsStore.unwatchSetting(this.layoutWatcherRef);
|
SettingsStore.unwatchSetting(this.layoutWatcherRef);
|
||||||
|
|
|
@ -156,7 +156,7 @@ export default class RightPanelStore extends ReadyWatchingStore {
|
||||||
const cardState = redirect?.state ?? (Object.keys(card.state ?? {}).length === 0 ? null : card.state);
|
const cardState = redirect?.state ?? (Object.keys(card.state ?? {}).length === 0 ? null : card.state);
|
||||||
|
|
||||||
// Checks for wrong SetRightPanelPhase requests
|
// Checks for wrong SetRightPanelPhase requests
|
||||||
if (!this.isPhaseActionValid(targetPhase)) return;
|
if (!this.isPhaseValid(targetPhase)) return;
|
||||||
|
|
||||||
if ((targetPhase === this.currentCardForRoom(rId)?.phase && !!cardState)) {
|
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...)
|
// Update state: set right panel with a new state but keep the phase (dont know it this is ever needed...)
|
||||||
|
@ -195,16 +195,16 @@ export default class RightPanelStore extends ReadyWatchingStore {
|
||||||
const pState = redirect?.state ?? (Object.keys(card.state ?? {}).length === 0 ? null : card.state);
|
const pState = redirect?.state ?? (Object.keys(card.state ?? {}).length === 0 ? null : card.state);
|
||||||
|
|
||||||
// Checks for wrong SetRightPanelPhase requests
|
// 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) {
|
if (!!roomCache) {
|
||||||
// append new phase
|
// append new phase
|
||||||
roomCache.history.push({ state: pState, phase: targetPhase });
|
roomCache.history.push({ state: pState, phase: targetPhase });
|
||||||
roomCache.isOpen = allowClose ? roomCache.isOpen : true;
|
roomCache.isOpen = allowClose ? roomCache.isOpen : true;
|
||||||
} else {
|
} else {
|
||||||
// setup room panel cache with the new card
|
// setup room panel cache with the new card
|
||||||
roomCache = {
|
this.byRoom[rId] = {
|
||||||
history: [{ phase: targetPhase, state: pState ?? {} }],
|
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
|
// if there was no right panel store object the the panel was closed -> keep it closed, except if allowClose==false
|
||||||
isOpen: !allowClose,
|
isOpen: !allowClose,
|
||||||
|
@ -345,18 +345,18 @@ export default class RightPanelStore extends ReadyWatchingStore {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private isPhaseActionValid(targetPhase) {
|
public isPhaseValid(targetPhase: RightPanelPhases, isViewingRoom = this.isViewingRoom): boolean {
|
||||||
if (!RightPanelPhases[targetPhase]) {
|
if (!RightPanelPhases[targetPhase]) {
|
||||||
logger.warn(`Tried to switch right panel to unknown phase: ${targetPhase}`);
|
logger.warn(`Tried to switch right panel to unknown phase: ${targetPhase}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (GROUP_PHASES.includes(targetPhase) && this.isViewingRoom) {
|
if (GROUP_PHASES.includes(targetPhase) && isViewingRoom) {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
`Tried to switch right panel to a group phase: ${targetPhase}, ` +
|
`Tried to switch right panel to a group phase: ${targetPhase}, ` +
|
||||||
`but we are currently not viewing a group`,
|
`but we are currently not viewing a group`,
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
} else if (!GROUP_PHASES.includes(targetPhase) && !this.isViewingRoom) {
|
} else if (!GROUP_PHASES.includes(targetPhase) && !isViewingRoom) {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
`Tried to switch right panel to a room phase: ${targetPhase}, ` +
|
`Tried to switch right panel to a room phase: ${targetPhase}, ` +
|
||||||
`but we are currently not viewing a room`,
|
`but we are currently not viewing a room`,
|
||||||
|
|
|
@ -56,23 +56,3 @@ export function backLabelForPhase(phase: RightPanelPhases) {
|
||||||
}
|
}
|
||||||
return null;
|
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,
|
|
||||||
];
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue