Right panel store refactor (#7313)
Co-authored-by: J. Ryan Stinnett <jryans@gmail.com>
This commit is contained in:
parent
8e881336ab
commit
325e2ba99b
42 changed files with 765 additions and 811 deletions
|
@ -27,9 +27,9 @@ import { logger } from "matrix-js-sdk/src/logger";
|
|||
import { MatrixClientPeg } from '../../MatrixClientPeg';
|
||||
import EventIndexPeg from "../../indexing/EventIndexPeg";
|
||||
import { _t } from '../../languageHandler';
|
||||
import BaseCard from "../views/right_panel/BaseCard";
|
||||
import { RightPanelPhases } from "../../stores/RightPanelStorePhases";
|
||||
import { RightPanelPhases } from "../../stores/right-panel/RightPanelStorePhases";
|
||||
import DesktopBuildsNotice, { WarningKind } from "../views/elements/DesktopBuildsNotice";
|
||||
import BaseCard from "../views/right_panel/BaseCard";
|
||||
import { replaceableComponent } from "../../utils/replaceableComponent";
|
||||
import ResizeNotifier from '../../utils/ResizeNotifier';
|
||||
import TimelinePanel from "./TimelinePanel";
|
||||
|
|
|
@ -38,13 +38,14 @@ import GroupStore from '../../stores/GroupStore';
|
|||
import FlairStore from '../../stores/FlairStore';
|
||||
import { showGroupAddRoomDialog } from '../../GroupAddressPicker';
|
||||
import { makeGroupPermalink, makeUserPermalink } from "../../utils/permalinks/Permalinks";
|
||||
import RightPanelStore from "../../stores/RightPanelStore";
|
||||
import RightPanelStore from "../../stores/right-panel/RightPanelStore";
|
||||
import AutoHideScrollbar from "./AutoHideScrollbar";
|
||||
import { mediaFromMxc } from "../../customisations/Media";
|
||||
import { replaceableComponent } from "../../utils/replaceableComponent";
|
||||
import { createSpaceFromCommunity } from "../../utils/space";
|
||||
import { Action } from "../../dispatcher/actions";
|
||||
import { RightPanelPhases } from "../../stores/RightPanelStorePhases";
|
||||
import { RightPanelPhases } from "../../stores/right-panel/RightPanelStorePhases";
|
||||
import { UPDATE_EVENT } from "../../stores/AsyncStore";
|
||||
|
||||
const LONG_DESC_PLACEHOLDER = _td(
|
||||
`<h1>HTML for your community's page</h1>
|
||||
|
@ -427,7 +428,7 @@ export default class GroupView extends React.Component {
|
|||
membershipBusy: false,
|
||||
publicityBusy: false,
|
||||
inviterProfile: null,
|
||||
showRightPanel: RightPanelStore.getSharedInstance().isOpenForGroup,
|
||||
showRightPanel: RightPanelStore.instance.isOpenForGroup,
|
||||
showUpgradeNotice: !localStorage.getItem(UPGRADE_NOTICE_LS_KEY),
|
||||
};
|
||||
|
||||
|
@ -439,7 +440,7 @@ export default class GroupView extends React.Component {
|
|||
this._initGroupStore(this.props.groupId, true);
|
||||
|
||||
this._dispatcherRef = dis.register(this._onAction);
|
||||
this._rightPanelStoreToken = RightPanelStore.getSharedInstance().addListener(this._onRightPanelStoreUpdate);
|
||||
RightPanelStore.instance.on(UPDATE_EVENT, this._onRightPanelStoreUpdate);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
|
@ -447,10 +448,7 @@ export default class GroupView extends React.Component {
|
|||
this._matrixClient.removeListener("Group.myMembership", this._onGroupMyMembership);
|
||||
dis.unregister(this._dispatcherRef);
|
||||
|
||||
// Remove RightPanelStore listener
|
||||
if (this._rightPanelStoreToken) {
|
||||
this._rightPanelStoreToken.remove();
|
||||
}
|
||||
RightPanelStore.instance.off(UPDATE_EVENT, this._onRightPanelStoreUpdate);
|
||||
}
|
||||
|
||||
// TODO: [REACT-WARNING] Replace with appropriate lifecycle event
|
||||
|
@ -468,7 +466,7 @@ export default class GroupView extends React.Component {
|
|||
|
||||
_onRightPanelStoreUpdate = () => {
|
||||
this.setState({
|
||||
showRightPanel: RightPanelStore.getSharedInstance().isOpenForGroup,
|
||||
showRightPanel: RightPanelStore.instance.isOpenForGroup,
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -824,10 +822,7 @@ export default class GroupView extends React.Component {
|
|||
};
|
||||
|
||||
_onAdminsLinkClick = () => {
|
||||
dis.dispatch({
|
||||
action: Action.SetRightPanelPhase,
|
||||
phase: RightPanelPhases.GroupMemberList,
|
||||
});
|
||||
RightPanelStore.instance.setCard({ phase: RightPanelPhases.GroupMemberList });
|
||||
};
|
||||
|
||||
_getGroupSection() {
|
||||
|
|
|
@ -44,7 +44,6 @@ import CallContainer from '../views/voip/CallContainer';
|
|||
import { ViewRoomDeltaPayload } from "../../dispatcher/payloads/ViewRoomDeltaPayload";
|
||||
import RoomListStore from "../../stores/room-list/RoomListStore";
|
||||
import NonUrgentToastContainer from "./NonUrgentToastContainer";
|
||||
import { ToggleRightPanelPayload } from "../../dispatcher/payloads/ToggleRightPanelPayload";
|
||||
import { IOOBData, IThreepidInvite } from "../../stores/ThreepidInviteStore";
|
||||
import Modal from "../../Modal";
|
||||
import { ICollapseConfig } from "../../resizer/distributors/collapse";
|
||||
|
@ -68,6 +67,7 @@ import GroupFilterPanel from './GroupFilterPanel';
|
|||
import CustomRoomTagPanel from './CustomRoomTagPanel';
|
||||
import { mediaFromMxc } from "../../customisations/Media";
|
||||
import LegacyCommunityPreview from "./LegacyCommunityPreview";
|
||||
import RightPanelStore from '../../stores/right-panel/RightPanelStore';
|
||||
|
||||
// We need to fetch each pinned message individually (if we don't already have it)
|
||||
// so each pinned message may trigger a request. Limit the number per room for sanity.
|
||||
|
@ -489,10 +489,7 @@ class LoggedInView extends React.Component<IProps, IState> {
|
|||
break;
|
||||
case NavigationAction.ToggleRoomSidePanel:
|
||||
if (this.props.page_type === "room_view" || this.props.page_type === "group_view") {
|
||||
dis.dispatch<ToggleRightPanelPayload>({
|
||||
action: Action.ToggleRightPanel,
|
||||
type: this.props.page_type === "room_view" ? "room" : "group",
|
||||
});
|
||||
RightPanelStore.instance.togglePanel();
|
||||
handled = true;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -20,17 +20,12 @@ import { Room } from "matrix-js-sdk/src/models/room";
|
|||
import { RoomState } from "matrix-js-sdk/src/models/room-state";
|
||||
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
import { VerificationRequest } from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest";
|
||||
import { throttle } from 'lodash';
|
||||
|
||||
import dis from '../../dispatcher/dispatcher';
|
||||
import GroupStore from '../../stores/GroupStore';
|
||||
import {
|
||||
RIGHT_PANEL_PHASES_NO_ARGS,
|
||||
RIGHT_PANEL_SPACE_PHASES,
|
||||
RightPanelPhases,
|
||||
} from "../../stores/RightPanelStorePhases";
|
||||
import RightPanelStore from "../../stores/RightPanelStore";
|
||||
import { RightPanelPhases } from '../../stores/right-panel/RightPanelStorePhases';
|
||||
import RightPanelStore from "../../stores/right-panel/RightPanelStore";
|
||||
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
||||
import { Action } from "../../dispatcher/actions";
|
||||
import RoomSummaryCard from "../views/right_panel/RoomSummaryCard";
|
||||
|
@ -50,16 +45,17 @@ import ThreadPanel from "./ThreadPanel";
|
|||
import NotificationPanel from "./NotificationPanel";
|
||||
import ResizeNotifier from "../../utils/ResizeNotifier";
|
||||
import PinnedMessagesCard from "../views/right_panel/PinnedMessagesCard";
|
||||
import SpaceStore from "../../stores/spaces/SpaceStore";
|
||||
import { RoomPermalinkCreator } from '../../utils/permalinks/Permalinks';
|
||||
import { E2EStatus } from '../../utils/ShieldUtils';
|
||||
import { dispatchShowThreadsPanelEvent } from '../../dispatcher/dispatch-actions/threads';
|
||||
import TimelineCard from '../views/right_panel/TimelineCard';
|
||||
import { UPDATE_EVENT } from '../../stores/AsyncStore';
|
||||
import { IRightPanelCard, IRightPanelCardState } from '../../stores/right-panel/RightPanelStoreIPanelState';
|
||||
|
||||
interface IProps {
|
||||
room?: Room; // if showing panels for a given room, this is set
|
||||
groupId?: string; // if showing panels for a given group, this is set
|
||||
member?: RoomMember; // used if we know the room member ahead of opening the panel
|
||||
overwriteCard?: IRightPanelCard; // used to display a custom card and ignoring the RightPanelStore (used for UserView)
|
||||
resizeNotifier: ResizeNotifier;
|
||||
permalinkCreator?: RoomPermalinkCreator;
|
||||
e2eStatus?: E2EStatus;
|
||||
|
@ -68,17 +64,8 @@ interface IProps {
|
|||
interface IState {
|
||||
phase: RightPanelPhases;
|
||||
isUserPrivilegedInGroup?: boolean;
|
||||
member?: RoomMember;
|
||||
verificationRequest?: VerificationRequest;
|
||||
verificationRequestPromise?: Promise<VerificationRequest>;
|
||||
space?: Room;
|
||||
widgetId?: string;
|
||||
groupRoomId?: string;
|
||||
groupId?: string;
|
||||
event: MatrixEvent;
|
||||
initialEvent?: MatrixEvent;
|
||||
initialEventHighlighted?: boolean;
|
||||
searchQuery: string;
|
||||
cardState?: IRightPanelCardState;
|
||||
}
|
||||
|
||||
@replaceableComponent("structures.RightPanel")
|
||||
|
@ -89,11 +76,11 @@ export default class RightPanel extends React.Component<IProps, IState> {
|
|||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.state = {
|
||||
...RightPanelStore.getSharedInstance().roomPanelPhaseParams,
|
||||
phase: this.getPhaseFromProps(),
|
||||
cardState: RightPanelStore.instance.currentCard?.state,
|
||||
phase: RightPanelStore.instance.currentCard?.phase,
|
||||
isUserPrivilegedInGroup: null,
|
||||
member: this.getUserForPanel(),
|
||||
searchQuery: "",
|
||||
};
|
||||
}
|
||||
|
@ -102,56 +89,11 @@ export default class RightPanel extends React.Component<IProps, IState> {
|
|||
this.forceUpdate();
|
||||
}, 500, { leading: true, trailing: true });
|
||||
|
||||
// Helper function to split out the logic for getPhaseFromProps() and the constructor
|
||||
// as both are called at the same time in the constructor.
|
||||
private getUserForPanel(): RoomMember {
|
||||
if (this.state && this.state.member) return this.state.member;
|
||||
const lastParams = RightPanelStore.getSharedInstance().roomPanelPhaseParams;
|
||||
return this.props.member || lastParams['member'];
|
||||
}
|
||||
|
||||
// gets the current phase from the props and also maybe the store
|
||||
private getPhaseFromProps() {
|
||||
const rps = RightPanelStore.getSharedInstance();
|
||||
const userForPanel = this.getUserForPanel();
|
||||
if (this.props.groupId) {
|
||||
if (!RIGHT_PANEL_PHASES_NO_ARGS.includes(rps.groupPanelPhase)) {
|
||||
dis.dispatch({ action: Action.SetRightPanelPhase, phase: RightPanelPhases.GroupMemberList });
|
||||
return RightPanelPhases.GroupMemberList;
|
||||
}
|
||||
return rps.groupPanelPhase;
|
||||
} else if (SpaceStore.spacesEnabled && this.props.room?.isSpaceRoom()
|
||||
&& !RIGHT_PANEL_SPACE_PHASES.includes(rps.roomPanelPhase)
|
||||
) {
|
||||
return RightPanelPhases.SpaceMemberList;
|
||||
} else if (userForPanel) {
|
||||
// XXX FIXME AAAAAARGH: What is going on with this class!? It takes some of its state
|
||||
// from its props and some from a store, except if the contents of the store changes
|
||||
// while it's mounted in which case it replaces all of its state with that of the store,
|
||||
// except it uses a dispatch instead of a normal store listener?
|
||||
// Unfortunately rewriting this would almost certainly break showing the right panel
|
||||
// in some of the many cases, and I don't have time to re-architect it and test all
|
||||
// the flows now, so adding yet another special case so if the store thinks there is
|
||||
// a verification going on for the member we're displaying, we show that, otherwise
|
||||
// we race if a verification is started while the panel isn't displayed because we're
|
||||
// not mounted in time to get the dispatch.
|
||||
// Until then, let this code serve as a warning from history.
|
||||
if (
|
||||
rps.roomPanelPhaseParams.member &&
|
||||
userForPanel.userId === rps.roomPanelPhaseParams.member.userId &&
|
||||
rps.roomPanelPhaseParams.verificationRequest
|
||||
) {
|
||||
return rps.roomPanelPhase;
|
||||
}
|
||||
return RightPanelPhases.RoomMemberInfo;
|
||||
}
|
||||
return rps.roomPanelPhase;
|
||||
}
|
||||
|
||||
public componentDidMount(): void {
|
||||
this.dispatcherRef = dis.register(this.onAction);
|
||||
const cli = this.context;
|
||||
cli.on("RoomState.members", this.onRoomStateMember);
|
||||
RightPanelStore.instance.on(UPDATE_EVENT, this.onRightPanelStoreUpdate);
|
||||
this.initGroupStore(this.props.groupId);
|
||||
}
|
||||
|
||||
|
@ -160,6 +102,7 @@ export default class RightPanel extends React.Component<IProps, IState> {
|
|||
if (this.context) {
|
||||
this.context.removeListener("RoomState.members", this.onRoomStateMember);
|
||||
}
|
||||
RightPanelStore.instance.off(UPDATE_EVENT, this.onRightPanelStoreUpdate);
|
||||
this.unregisterGroupStore();
|
||||
}
|
||||
|
||||
|
@ -193,42 +136,36 @@ export default class RightPanel extends React.Component<IProps, IState> {
|
|||
// redraw the badge on the membership list
|
||||
if (this.state.phase === RightPanelPhases.RoomMemberList && member.roomId === this.props.room.roomId) {
|
||||
this.delayedUpdate();
|
||||
} else if (this.state.phase === RightPanelPhases.RoomMemberInfo && member.roomId === this.props.room.roomId &&
|
||||
member.userId === this.state.member.userId) {
|
||||
} else if (
|
||||
this.state.phase === RightPanelPhases.RoomMemberInfo && member.roomId === this.props.room.roomId &&
|
||||
member.userId === this.state.cardState.member.userId
|
||||
) {
|
||||
// refresh the member info (e.g. new power level)
|
||||
this.delayedUpdate();
|
||||
}
|
||||
};
|
||||
|
||||
private onRightPanelStoreUpdate = () => {
|
||||
const currentPanel = RightPanelStore.instance.currentCard;
|
||||
this.setState({
|
||||
cardState: currentPanel.state,
|
||||
phase: currentPanel.phase,
|
||||
});
|
||||
};
|
||||
|
||||
private onAction = (payload: ActionPayload) => {
|
||||
const isChangingRoom = payload.action === Action.ViewRoom && payload.room_id !== this.props.room.roomId;
|
||||
const isViewingThread = this.state.phase === RightPanelPhases.ThreadView;
|
||||
if (isChangingRoom && isViewingThread) {
|
||||
dispatchShowThreadsPanelEvent();
|
||||
}
|
||||
|
||||
if (payload.action === Action.AfterRightPanelPhaseChange) {
|
||||
this.setState({
|
||||
phase: payload.phase,
|
||||
groupRoomId: payload.groupRoomId,
|
||||
groupId: payload.groupId,
|
||||
member: payload.member,
|
||||
event: payload.event,
|
||||
initialEvent: payload.initialEvent,
|
||||
initialEventHighlighted: payload.highlighted,
|
||||
verificationRequest: payload.verificationRequest,
|
||||
verificationRequestPromise: payload.verificationRequestPromise,
|
||||
widgetId: payload.widgetId,
|
||||
space: payload.space,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
private onClose = () => {
|
||||
// XXX: There are three different ways of 'closing' this panel depending on what state
|
||||
// things are in... this knows far more than it should do about the state of the rest
|
||||
// of the app and is generally a bit silly.
|
||||
if (this.props.member) {
|
||||
if (this.props.overwriteCard?.state?.member) {
|
||||
// If we have a user prop then we're displaying a user from the 'user' page type
|
||||
// in LoggedInView, so need to change the page type to close the panel (we switch
|
||||
// to the home page which is not obviously the correct thing to do, but I'm not sure
|
||||
|
@ -238,16 +175,12 @@ export default class RightPanel extends React.Component<IProps, IState> {
|
|||
});
|
||||
} else if (
|
||||
this.state.phase === RightPanelPhases.EncryptionPanel &&
|
||||
this.state.verificationRequest && this.state.verificationRequest.pending
|
||||
this.state.cardState.verificationRequest && this.state.cardState.verificationRequest.pending
|
||||
) {
|
||||
// When the user clicks close on the encryption panel cancel the pending request first if any
|
||||
this.state.verificationRequest.cancel();
|
||||
this.state.cardState.verificationRequest.cancel();
|
||||
} else {
|
||||
// the RightPanelStore has no way of knowing which mode room/group it is in, so we handle closing here
|
||||
dis.dispatch({
|
||||
action: Action.ToggleRightPanel,
|
||||
type: this.props.groupId ? "group" : "room",
|
||||
});
|
||||
RightPanelStore.instance.togglePanel();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -256,13 +189,14 @@ export default class RightPanel extends React.Component<IProps, IState> {
|
|||
};
|
||||
|
||||
public render(): JSX.Element {
|
||||
let panel = <div />;
|
||||
let card = <div />;
|
||||
const roomId = this.props.room ? this.props.room.roomId : undefined;
|
||||
|
||||
switch (this.state.phase) {
|
||||
const phase = this.props.overwriteCard?.phase ?? this.state.phase;
|
||||
const cardState = this.props.overwriteCard?.state ?? this.state.cardState;
|
||||
switch (phase) {
|
||||
case RightPanelPhases.RoomMemberList:
|
||||
if (roomId) {
|
||||
panel = <MemberList
|
||||
card = <MemberList
|
||||
roomId={roomId}
|
||||
key={roomId}
|
||||
onClose={this.onClose}
|
||||
|
@ -272,9 +206,9 @@ export default class RightPanel extends React.Component<IProps, IState> {
|
|||
}
|
||||
break;
|
||||
case RightPanelPhases.SpaceMemberList:
|
||||
panel = <MemberList
|
||||
roomId={this.state.space ? this.state.space.roomId : roomId}
|
||||
key={this.state.space ? this.state.space.roomId : roomId}
|
||||
card = <MemberList
|
||||
roomId={cardState.spaceId ? cardState.spaceId : roomId}
|
||||
key={cardState.spaceId ? cardState.spaceId : roomId}
|
||||
onClose={this.onClose}
|
||||
searchQuery={this.state.searchQuery}
|
||||
onSearchQueryChanged={this.onSearchQueryChanged}
|
||||
|
@ -283,61 +217,66 @@ export default class RightPanel extends React.Component<IProps, IState> {
|
|||
|
||||
case RightPanelPhases.GroupMemberList:
|
||||
if (this.props.groupId) {
|
||||
panel = <GroupMemberList groupId={this.props.groupId} key={this.props.groupId} />;
|
||||
card = <GroupMemberList groupId={this.props.groupId} key={this.props.groupId} />;
|
||||
}
|
||||
break;
|
||||
|
||||
case RightPanelPhases.GroupRoomList:
|
||||
panel = <GroupRoomList groupId={this.props.groupId} key={this.props.groupId} />;
|
||||
card = <GroupRoomList groupId={this.props.groupId} key={this.props.groupId} />;
|
||||
break;
|
||||
|
||||
case RightPanelPhases.RoomMemberInfo:
|
||||
case RightPanelPhases.SpaceMemberInfo:
|
||||
case RightPanelPhases.EncryptionPanel:
|
||||
panel = <UserInfo
|
||||
user={this.state.member}
|
||||
room={this.context.getRoom(this.state.member.roomId) ?? this.props.room}
|
||||
key={roomId || this.state.member.userId}
|
||||
case RightPanelPhases.EncryptionPanel: {
|
||||
const roomMember = cardState.member instanceof RoomMember
|
||||
? cardState.member
|
||||
: undefined;
|
||||
card = <UserInfo
|
||||
user={cardState.member}
|
||||
room={this.context.getRoom(roomMember?.roomId) ?? this.props.room}
|
||||
key={roomId || cardState.member.userId}
|
||||
onClose={this.onClose}
|
||||
phase={this.state.phase}
|
||||
verificationRequest={this.state.verificationRequest}
|
||||
verificationRequestPromise={this.state.verificationRequestPromise}
|
||||
phase={phase}
|
||||
verificationRequest={cardState.verificationRequest}
|
||||
verificationRequestPromise={cardState.verificationRequestPromise}
|
||||
/>;
|
||||
break;
|
||||
|
||||
}
|
||||
case RightPanelPhases.Room3pidMemberInfo:
|
||||
case RightPanelPhases.Space3pidMemberInfo:
|
||||
panel = <ThirdPartyMemberInfo event={this.state.event} key={roomId} />;
|
||||
card = <ThirdPartyMemberInfo event={cardState.memberInfoEvent} key={roomId} />;
|
||||
break;
|
||||
|
||||
case RightPanelPhases.GroupMemberInfo:
|
||||
panel = <UserInfo
|
||||
user={this.state.member}
|
||||
card = <UserInfo
|
||||
user={cardState.member}
|
||||
groupId={this.props.groupId}
|
||||
key={this.state.member.userId}
|
||||
phase={this.state.phase}
|
||||
onClose={this.onClose} />;
|
||||
key={cardState.member.userId}
|
||||
phase={phase}
|
||||
onClose={this.onClose}
|
||||
/>;
|
||||
break;
|
||||
|
||||
case RightPanelPhases.GroupRoomInfo:
|
||||
panel = <GroupRoomInfo
|
||||
groupRoomId={this.state.groupRoomId}
|
||||
card = <GroupRoomInfo
|
||||
groupRoomId={cardState.groupRoomId}
|
||||
groupId={this.props.groupId}
|
||||
key={this.state.groupRoomId} />;
|
||||
key={cardState.groupRoomId}
|
||||
/>;
|
||||
break;
|
||||
|
||||
case RightPanelPhases.NotificationPanel:
|
||||
panel = <NotificationPanel onClose={this.onClose} />;
|
||||
card = <NotificationPanel onClose={this.onClose} />;
|
||||
break;
|
||||
|
||||
case RightPanelPhases.PinnedMessages:
|
||||
if (SettingsStore.getValue("feature_pinning")) {
|
||||
panel = <PinnedMessagesCard room={this.props.room} onClose={this.onClose} />;
|
||||
card = <PinnedMessagesCard room={this.props.room} onClose={this.onClose} />;
|
||||
}
|
||||
break;
|
||||
case RightPanelPhases.Timeline:
|
||||
if (!SettingsStore.getValue("feature_maximised_widgets")) break;
|
||||
panel = <TimelineCard
|
||||
card = <TimelineCard
|
||||
classNames="mx_ThreadPanel mx_TimelineCard"
|
||||
room={this.props.room}
|
||||
timelineSet={this.props.room.getUnfilteredTimelineSet()}
|
||||
|
@ -348,23 +287,24 @@ export default class RightPanel extends React.Component<IProps, IState> {
|
|||
/>;
|
||||
break;
|
||||
case RightPanelPhases.FilePanel:
|
||||
panel = <FilePanel roomId={roomId} resizeNotifier={this.props.resizeNotifier} onClose={this.onClose} />;
|
||||
card = <FilePanel roomId={roomId} resizeNotifier={this.props.resizeNotifier} onClose={this.onClose} />;
|
||||
break;
|
||||
|
||||
case RightPanelPhases.ThreadView:
|
||||
panel = <ThreadView
|
||||
card = <ThreadView
|
||||
room={this.props.room}
|
||||
resizeNotifier={this.props.resizeNotifier}
|
||||
onClose={this.onClose}
|
||||
mxEvent={this.state.event}
|
||||
initialEvent={this.state.initialEvent}
|
||||
initialEventHighlighted={this.state.initialEventHighlighted}
|
||||
mxEvent={cardState.threadHeadEvent}
|
||||
initialEvent={cardState.initialEvent}
|
||||
isInitialEventHighlighted={cardState.isInitialEventHighlighted}
|
||||
permalinkCreator={this.props.permalinkCreator}
|
||||
e2eStatus={this.props.e2eStatus} />;
|
||||
e2eStatus={this.props.e2eStatus}
|
||||
/>;
|
||||
break;
|
||||
|
||||
case RightPanelPhases.ThreadPanel:
|
||||
panel = <ThreadPanel
|
||||
card = <ThreadPanel
|
||||
roomId={roomId}
|
||||
resizeNotifier={this.props.resizeNotifier}
|
||||
onClose={this.onClose}
|
||||
|
@ -373,17 +313,21 @@ export default class RightPanel extends React.Component<IProps, IState> {
|
|||
break;
|
||||
|
||||
case RightPanelPhases.RoomSummary:
|
||||
panel = <RoomSummaryCard room={this.props.room} onClose={this.onClose} />;
|
||||
card = <RoomSummaryCard room={this.props.room} onClose={this.onClose} />;
|
||||
break;
|
||||
|
||||
case RightPanelPhases.Widget:
|
||||
panel = <WidgetCard room={this.props.room} widgetId={this.state.widgetId} onClose={this.onClose} />;
|
||||
card = <WidgetCard
|
||||
room={this.props.room}
|
||||
widgetId={cardState.widgetId}
|
||||
onClose={this.onClose}
|
||||
/>;
|
||||
break;
|
||||
}
|
||||
|
||||
return (
|
||||
<aside className="mx_RightPanel dark-panel" id="mx_RightPanel">
|
||||
{ panel }
|
||||
{ card }
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -84,6 +84,7 @@ interface IState {
|
|||
|
||||
@replaceableComponent("structures.RoomStatusBar")
|
||||
export default class RoomStatusBar extends React.PureComponent<IProps, IState> {
|
||||
private unmounted = false;
|
||||
public static contextType = MatrixClientContext;
|
||||
|
||||
constructor(props: IProps, context: typeof MatrixClientContext) {
|
||||
|
@ -110,6 +111,7 @@ export default class RoomStatusBar extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
|
||||
public componentWillUnmount(): void {
|
||||
this.unmounted = true;
|
||||
// we may have entirely lost our client as we're logging out before clicking login on the guest bar...
|
||||
const client = this.context;
|
||||
if (client) {
|
||||
|
@ -122,6 +124,7 @@ export default class RoomStatusBar extends React.PureComponent<IProps, IState> {
|
|||
if (state === "SYNCING" && prevState === "SYNCING") {
|
||||
return;
|
||||
}
|
||||
if (this.unmounted) return;
|
||||
this.setState({
|
||||
syncState: state,
|
||||
syncStateData: data,
|
||||
|
|
|
@ -53,7 +53,7 @@ import WidgetEchoStore from '../../stores/WidgetEchoStore';
|
|||
import SettingsStore from "../../settings/SettingsStore";
|
||||
import { Layout } from "../../settings/enums/Layout";
|
||||
import AccessibleButton from "../views/elements/AccessibleButton";
|
||||
import RightPanelStore from "../../stores/RightPanelStore";
|
||||
import RightPanelStore from "../../stores/right-panel/RightPanelStore";
|
||||
import { haveTileForEvent } from "../views/rooms/EventTile";
|
||||
import RoomContext, { TimelineRenderingType } from "../../contexts/RoomContext";
|
||||
import MatrixClientContext, { withMatrixClientHOC, MatrixClientProps } from "../../contexts/MatrixClientContext";
|
||||
|
@ -98,8 +98,7 @@ import { dispatchShowThreadEvent } from '../../dispatcher/dispatch-actions/threa
|
|||
import { fetchInitialEvent } from "../../utils/EventUtils";
|
||||
import { ComposerType } from "../../dispatcher/payloads/ComposerInsertPayload";
|
||||
import AppsDrawer from '../views/rooms/AppsDrawer';
|
||||
import { SetRightPanelPhasePayload } from '../../dispatcher/payloads/SetRightPanelPhasePayload';
|
||||
import { RightPanelPhases } from '../../stores/RightPanelStorePhases';
|
||||
import { RightPanelPhases } from '../../stores/right-panel/RightPanelStorePhases';
|
||||
|
||||
const DEBUG = false;
|
||||
let debuglog = function(msg: string) {};
|
||||
|
@ -214,7 +213,6 @@ export interface IRoomState {
|
|||
export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
||||
private readonly dispatcherRef: string;
|
||||
private readonly roomStoreToken: EventSubscription;
|
||||
private readonly rightPanelStoreToken: EventSubscription;
|
||||
private settingWatchers: string[];
|
||||
|
||||
private unmounted = false;
|
||||
|
@ -246,7 +244,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
canPeek: false,
|
||||
showApps: false,
|
||||
isPeeking: false,
|
||||
showRightPanel: RightPanelStore.getSharedInstance().isOpenForRoom,
|
||||
showRightPanel: RightPanelStore.instance.isOpenForRoom,
|
||||
joining: false,
|
||||
atEndOfLiveTimeline: true,
|
||||
atEndOfLiveTimelineInit: false,
|
||||
|
@ -289,7 +287,8 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
this.context.on("Event.decrypted", this.onEventDecrypted);
|
||||
// Start listening for RoomViewStore updates
|
||||
this.roomStoreToken = RoomViewStore.addListener(this.onRoomViewStoreUpdate);
|
||||
this.rightPanelStoreToken = RightPanelStore.getSharedInstance().addListener(this.onRightPanelStoreUpdate);
|
||||
|
||||
RightPanelStore.instance.on(UPDATE_EVENT, this.onRightPanelStoreUpdate);
|
||||
|
||||
WidgetEchoStore.on(UPDATE_EVENT, this.onWidgetEchoStoreUpdate);
|
||||
WidgetStore.instance.on(UPDATE_EVENT, this.onWidgetStoreUpdate);
|
||||
|
@ -337,13 +336,9 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
});
|
||||
if (WidgetLayoutStore.instance.hasMaximisedWidget(this.state.room)) {
|
||||
// Show chat in right panel when a widget is maximised
|
||||
dis.dispatch<SetRightPanelPhasePayload>({
|
||||
action: Action.SetRightPanelPhase,
|
||||
phase: RightPanelPhases.Timeline,
|
||||
});
|
||||
RightPanelStore.instance.setCard({ phase: RightPanelPhases.Timeline });
|
||||
}
|
||||
this.checkWidgets(this.state.room);
|
||||
this.checkRightPanel(this.state.room);
|
||||
};
|
||||
|
||||
private checkWidgets = (room) => {
|
||||
|
@ -361,22 +356,6 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
: MainSplitContentType.Timeline;
|
||||
};
|
||||
|
||||
private checkRightPanel = (room) => {
|
||||
// This is a hack to hide the chat. This should not be necessary once the right panel
|
||||
// phase is stored per room. (need to be done after check widget so that mainSplitContentType is updated)
|
||||
if (
|
||||
RightPanelStore.getSharedInstance().roomPanelPhase === RightPanelPhases.Timeline &&
|
||||
this.state.showRightPanel &&
|
||||
!WidgetLayoutStore.instance.hasMaximisedWidget(this.state.room)
|
||||
) {
|
||||
// Two timelines are shown prevent this by hiding the right panel
|
||||
dis.dispatch({
|
||||
action: Action.ToggleRightPanel,
|
||||
type: "room",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
private onReadReceiptsChange = () => {
|
||||
this.setState({
|
||||
showReadReceipts: SettingsStore.getValue("showReadReceipts", this.state.roomId),
|
||||
|
@ -754,11 +733,8 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
if (this.roomStoreToken) {
|
||||
this.roomStoreToken.remove();
|
||||
}
|
||||
// Remove RightPanelStore listener
|
||||
if (this.rightPanelStoreToken) {
|
||||
this.rightPanelStoreToken.remove();
|
||||
}
|
||||
|
||||
RightPanelStore.instance.off(UPDATE_EVENT, this.onRightPanelStoreUpdate);
|
||||
WidgetEchoStore.removeListener(UPDATE_EVENT, this.onWidgetEchoStoreUpdate);
|
||||
WidgetStore.instance.removeListener(UPDATE_EVENT, this.onWidgetStoreUpdate);
|
||||
|
||||
|
@ -793,7 +769,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
|
||||
private onRightPanelStoreUpdate = () => {
|
||||
this.setState({
|
||||
showRightPanel: RightPanelStore.getSharedInstance().isOpenForRoom,
|
||||
showRightPanel: RightPanelStore.instance.isOpenForRoom,
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -1039,7 +1015,6 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
this.updateE2EStatus(room);
|
||||
this.updatePermissions(room);
|
||||
this.checkWidgets(room);
|
||||
this.checkRightPanel(room);
|
||||
|
||||
this.setState({
|
||||
liveTimeline: room.getLiveTimeline(),
|
||||
|
|
|
@ -18,7 +18,6 @@ import React, { RefObject, useContext, useRef, useState } from "react";
|
|||
import { EventType } from "matrix-js-sdk/src/@types/event";
|
||||
import { JoinRule, Preset } from "matrix-js-sdk/src/@types/partials";
|
||||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
import { EventSubscription } from "fbemitter";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
||||
|
@ -43,9 +42,8 @@ import MainSplit from './MainSplit';
|
|||
import ErrorBoundary from "../views/elements/ErrorBoundary";
|
||||
import { ActionPayload } from "../../dispatcher/payloads";
|
||||
import RightPanel from "./RightPanel";
|
||||
import RightPanelStore from "../../stores/RightPanelStore";
|
||||
import { RightPanelPhases } from "../../stores/RightPanelStorePhases";
|
||||
import { SetRightPanelPhasePayload } from "../../dispatcher/payloads/SetRightPanelPhasePayload";
|
||||
import RightPanelStore from "../../stores/right-panel/RightPanelStore";
|
||||
import { RightPanelPhases } from "../../stores/right-panel/RightPanelStorePhases";
|
||||
import { useStateArray } from "../../hooks/useStateArray";
|
||||
import SpacePublicShare from "../views/spaces/SpacePublicShare";
|
||||
import {
|
||||
|
@ -85,6 +83,7 @@ import { useDispatcher } from "../../hooks/useDispatcher";
|
|||
import { useRoomState } from "../../hooks/useRoomState";
|
||||
import { shouldShowComponent } from "../../customisations/helpers/UIComponents";
|
||||
import { UIComponent } from "../../settings/UIFeature";
|
||||
import { UPDATE_EVENT } from "../../stores/AsyncStore";
|
||||
|
||||
interface IProps {
|
||||
space: Room;
|
||||
|
@ -164,10 +163,9 @@ const SpaceInfo = ({ space }: { space: Room }) => {
|
|||
kind="link"
|
||||
className="mx_SpaceRoomView_info_memberCount"
|
||||
onClick={() => {
|
||||
defaultDispatcher.dispatch<SetRightPanelPhasePayload>({
|
||||
action: Action.SetRightPanelPhase,
|
||||
RightPanelStore.instance.setCard({
|
||||
phase: RightPanelPhases.RoomMemberList,
|
||||
refireParams: { space },
|
||||
state: { spaceId: space.roomId },
|
||||
});
|
||||
}}
|
||||
>
|
||||
|
@ -473,11 +471,7 @@ const SpaceLanding = ({ space }: { space: Room }) => {
|
|||
}
|
||||
|
||||
const onMembersClick = () => {
|
||||
defaultDispatcher.dispatch<SetRightPanelPhasePayload>({
|
||||
action: Action.SetRightPanelPhase,
|
||||
phase: RightPanelPhases.RoomMemberList,
|
||||
refireParams: { space },
|
||||
});
|
||||
RightPanelStore.instance.setCard({ phase: RightPanelPhases.RoomMemberList, state: { spaceId: space.roomId } });
|
||||
};
|
||||
|
||||
return <div className="mx_SpaceRoomView_landing">
|
||||
|
@ -796,7 +790,6 @@ export default class SpaceRoomView extends React.PureComponent<IProps, IState> {
|
|||
|
||||
private readonly creator: string;
|
||||
private readonly dispatcherRef: string;
|
||||
private readonly rightPanelStoreToken: EventSubscription;
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
@ -813,18 +806,18 @@ export default class SpaceRoomView extends React.PureComponent<IProps, IState> {
|
|||
|
||||
this.state = {
|
||||
phase,
|
||||
showRightPanel: RightPanelStore.getSharedInstance().isOpenForRoom,
|
||||
showRightPanel: RightPanelStore.instance.isOpenForRoom,
|
||||
myMembership: this.props.space.getMyMembership(),
|
||||
};
|
||||
|
||||
this.dispatcherRef = defaultDispatcher.register(this.onAction);
|
||||
this.rightPanelStoreToken = RightPanelStore.getSharedInstance().addListener(this.onRightPanelStoreUpdate);
|
||||
RightPanelStore.instance.on(UPDATE_EVENT, this.onRightPanelStoreUpdate);
|
||||
this.context.on("Room.myMembership", this.onMyMembership);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
defaultDispatcher.unregister(this.dispatcherRef);
|
||||
this.rightPanelStoreToken.remove();
|
||||
RightPanelStore.instance.off(UPDATE_EVENT, this.onRightPanelStoreUpdate);
|
||||
this.context.off("Room.myMembership", this.onMyMembership);
|
||||
}
|
||||
|
||||
|
@ -836,7 +829,7 @@ export default class SpaceRoomView extends React.PureComponent<IProps, IState> {
|
|||
|
||||
private onRightPanelStoreUpdate = () => {
|
||||
this.setState({
|
||||
showRightPanel: RightPanelStore.getSharedInstance().isOpenForRoom,
|
||||
showRightPanel: RightPanelStore.instance.isOpenForRoom,
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -849,28 +842,19 @@ export default class SpaceRoomView extends React.PureComponent<IProps, IState> {
|
|||
if (payload.action !== Action.ViewUser && payload.action !== "view_3pid_invite") return;
|
||||
|
||||
if (payload.action === Action.ViewUser && payload.member) {
|
||||
defaultDispatcher.dispatch<SetRightPanelPhasePayload>({
|
||||
action: Action.SetRightPanelPhase,
|
||||
RightPanelStore.instance.setCard({
|
||||
phase: RightPanelPhases.SpaceMemberInfo,
|
||||
refireParams: {
|
||||
space: this.props.space,
|
||||
member: payload.member,
|
||||
},
|
||||
state: { spaceId: this.props.space.roomId, member: payload.member },
|
||||
});
|
||||
} else if (payload.action === "view_3pid_invite" && payload.event) {
|
||||
defaultDispatcher.dispatch<SetRightPanelPhasePayload>({
|
||||
action: Action.SetRightPanelPhase,
|
||||
RightPanelStore.instance.setCard({
|
||||
phase: RightPanelPhases.Space3pidMemberInfo,
|
||||
refireParams: {
|
||||
space: this.props.space,
|
||||
event: payload.event,
|
||||
},
|
||||
state: { spaceId: this.props.space.roomId, member: payload.member },
|
||||
});
|
||||
} else {
|
||||
defaultDispatcher.dispatch<SetRightPanelPhasePayload>({
|
||||
action: Action.SetRightPanelPhase,
|
||||
RightPanelStore.instance.setCard({
|
||||
phase: RightPanelPhases.SpaceMemberList,
|
||||
refireParams: { space: this.props.space },
|
||||
state: { spaceId: this.props.space.roomId },
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -20,7 +20,7 @@ import { Thread, ThreadEvent } from 'matrix-js-sdk/src/models/thread';
|
|||
import { RelationType } from 'matrix-js-sdk/src/@types/event';
|
||||
|
||||
import BaseCard from "../views/right_panel/BaseCard";
|
||||
import { RightPanelPhases } from "../../stores/RightPanelStorePhases";
|
||||
import { RightPanelPhases } from "../../stores/right-panel/RightPanelStorePhases";
|
||||
import { replaceableComponent } from "../../utils/replaceableComponent";
|
||||
import ResizeNotifier from '../../utils/ResizeNotifier';
|
||||
import { TileShape } from '../views/rooms/EventTile';
|
||||
|
@ -30,7 +30,6 @@ import { Layout } from '../../settings/enums/Layout';
|
|||
import TimelinePanel from './TimelinePanel';
|
||||
import dis from "../../dispatcher/dispatcher";
|
||||
import { ActionPayload } from '../../dispatcher/payloads';
|
||||
import { SetRightPanelPhasePayload } from '../../dispatcher/payloads/SetRightPanelPhasePayload';
|
||||
import { Action } from '../../dispatcher/actions';
|
||||
import { MatrixClientPeg } from '../../MatrixClientPeg';
|
||||
import { E2EStatus } from '../../utils/ShieldUtils';
|
||||
|
@ -40,7 +39,7 @@ import ContentMessages from '../../ContentMessages';
|
|||
import UploadBar from './UploadBar';
|
||||
import { _t } from '../../languageHandler';
|
||||
import ThreadListContextMenu from '../views/context_menus/ThreadListContextMenu';
|
||||
import RightPanelStore from '../../stores/RightPanelStore';
|
||||
import RightPanelStore from '../../stores/right-panel/RightPanelStore';
|
||||
import SettingsStore from '../../settings/SettingsStore';
|
||||
import { WidgetLayoutStore } from '../../stores/widgets/WidgetLayoutStore';
|
||||
|
||||
|
@ -52,7 +51,7 @@ interface IProps {
|
|||
permalinkCreator?: RoomPermalinkCreator;
|
||||
e2eStatus?: E2EStatus;
|
||||
initialEvent?: MatrixEvent;
|
||||
initialEventHighlighted?: boolean;
|
||||
isInitialEventHighlighted?: boolean;
|
||||
}
|
||||
interface IState {
|
||||
thread?: Thread;
|
||||
|
@ -94,10 +93,7 @@ export default class ThreadView extends React.Component<IProps, IState> {
|
|||
}
|
||||
|
||||
if (prevProps.room !== this.props.room) {
|
||||
dis.dispatch<SetRightPanelPhasePayload>({
|
||||
action: Action.SetRightPanelPhase,
|
||||
phase: RightPanelPhases.RoomSummary,
|
||||
});
|
||||
RightPanelStore.instance.setCard({ phase: RightPanelPhases.RoomSummary });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,7 +164,7 @@ export default class ThreadView extends React.Component<IProps, IState> {
|
|||
};
|
||||
|
||||
private onScroll = (): void => {
|
||||
if (this.props.initialEvent && this.props.initialEventHighlighted) {
|
||||
if (this.props.initialEvent && this.props.isInitialEventHighlighted) {
|
||||
dis.dispatch({
|
||||
action: Action.ViewRoom,
|
||||
room_id: this.props.room.roomId,
|
||||
|
@ -189,7 +185,7 @@ export default class ThreadView extends React.Component<IProps, IState> {
|
|||
};
|
||||
|
||||
public render(): JSX.Element {
|
||||
const highlightedEventId = this.props.initialEventHighlighted
|
||||
const highlightedEventId = this.props.isInitialEventHighlighted
|
||||
? this.props.initialEvent?.getId()
|
||||
: null;
|
||||
|
||||
|
@ -198,7 +194,7 @@ export default class ThreadView extends React.Component<IProps, IState> {
|
|||
event_id: this.state.thread?.id,
|
||||
};
|
||||
|
||||
let previousPhase = RightPanelStore.getSharedInstance().previousPhase;
|
||||
let previousPhase = RightPanelStore.instance.previousCard.phase;
|
||||
if (!SettingsStore.getValue("feature_maximised_widgets")) {
|
||||
previousPhase = RightPanelPhases.ThreadPanel;
|
||||
}
|
||||
|
|
|
@ -680,6 +680,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
|||
};
|
||||
|
||||
private onSync = (clientSyncState: SyncState, prevState: SyncState, data: object): void => {
|
||||
if (this.unmounted) return;
|
||||
this.setState({ clientSyncState });
|
||||
};
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ import MainSplit from "./MainSplit";
|
|||
import RightPanel from "./RightPanel";
|
||||
import Spinner from "../views/elements/Spinner";
|
||||
import ResizeNotifier from "../../utils/ResizeNotifier";
|
||||
import { RightPanelPhases } from "../../stores/right-panel/RightPanelStorePhases";
|
||||
|
||||
interface IProps {
|
||||
userId?: string;
|
||||
|
@ -88,7 +89,10 @@ export default class UserView extends React.Component<IProps, IState> {
|
|||
if (this.state.loading) {
|
||||
return <Spinner />;
|
||||
} else if (this.state.member) {
|
||||
const panel = <RightPanel member={this.state.member} resizeNotifier={this.props.resizeNotifier} />;
|
||||
const panel = <RightPanel
|
||||
overwriteCard={{ phase: RightPanelPhases.RoomMemberInfo, state: { member: this.state.member } }}
|
||||
resizeNotifier={this.props.resizeNotifier}
|
||||
/>;
|
||||
return (<MainSplit panel={panel} resizeNotifier={this.props.resizeNotifier}>
|
||||
<HomePage />
|
||||
</MainSplit>);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue