Make UI respond to thread events

This commit is contained in:
Germain Souquet 2021-08-17 17:42:47 +01:00
parent 458f860a26
commit 95f4513bd2
7 changed files with 44 additions and 17 deletions

View file

@ -89,11 +89,11 @@ limitations under the License.
} }
.mx_MessageActionBar_replyButton::after { .mx_MessageActionBar_replyButton::after {
mask-image: url('$(res)/img/element-icons/room/message-bar/reply.svg'); mask-image: url('$(res)/img/element-icons/room/files.svg');
} }
.mx_MessageActionBar_threadButton::after { .mx_MessageActionBar_threadButton::after {
mask-image: url('$(res)/img/element-icons/room/files.svg'); mask-image: url('$(res)/img/element-icons/message/thread.svg');
} }
.mx_MessageActionBar_editButton::after { .mx_MessageActionBar_editButton::after {

View file

@ -232,6 +232,10 @@ limitations under the License.
mask-image: url('$(res)/img/element-icons/room/files.svg'); mask-image: url('$(res)/img/element-icons/room/files.svg');
} }
.mx_RoomSummaryCard_icon_threads::before {
mask-image: url('$(res)/img/element-icons/message/thread.svg');
}
.mx_RoomSummaryCard_icon_share::before { .mx_RoomSummaryCard_icon_share::before {
mask-image: url('$(res)/img/element-icons/room/share.svg'); mask-image: url('$(res)/img/element-icons/room/share.svg');
} }

View file

@ -267,6 +267,7 @@ export default class MessagePanel extends React.Component<IProps, IState> {
componentDidMount() { componentDidMount() {
this.calculateRoomMembersCount(); this.calculateRoomMembersCount();
this.props.room?.on("RoomState.members", this.calculateRoomMembersCount); this.props.room?.on("RoomState.members", this.calculateRoomMembersCount);
this.props.room?.getThreads().forEach(thread => thread.fetchReplyChain());
this.isMounted = true; this.isMounted = true;
} }

View file

@ -52,13 +52,6 @@ class ThreadView extends React.Component<IProps, IState> {
public componentDidMount(): void { public componentDidMount(): void {
this.room.on("Thread.update", this.onThreadEventReceived); this.room.on("Thread.update", this.onThreadEventReceived);
this.room.on("Thread.ready", this.onThreadEventReceived); this.room.on("Thread.ready", this.onThreadEventReceived);
this.updateThreads(() => {
this.state.threads.forEach(thread => {
if (!thread.ready) {
thread.fetchReplyChain();
}
});
});
} }
public componentWillUnmount(): void { public componentWillUnmount(): void {

View file

@ -29,6 +29,7 @@ import MessageComposer from '../views/rooms/MessageComposer';
import { RoomPermalinkCreator } from '../../utils/permalinks/Permalinks'; import { RoomPermalinkCreator } from '../../utils/permalinks/Permalinks';
import { Layout } from '../../settings/Layout'; import { Layout } from '../../settings/Layout';
import TimelinePanel from './TimelinePanel'; import TimelinePanel from './TimelinePanel';
import { Thread } from '../../../../matrix-js-sdk/src/models/thread';
interface IProps { interface IProps {
roomId: string; roomId: string;
@ -40,6 +41,7 @@ interface IProps {
interface IState { interface IState {
replyToEvent?: MatrixEvent; replyToEvent?: MatrixEvent;
thread?: Thread;
} }
/* /*
@ -50,16 +52,29 @@ class ThreadView extends React.Component<IProps, IState> {
state = {}; state = {};
public componentDidMount(): void { public componentDidMount(): void {
// this.props.mxEvent.getThread().on("Thread.update", this.updateThread); this.setupThread();
this.props.mxEvent.getThread().once("Thread.ready", this.updateThread);
} }
public componentWillUnmount(): void { public componentWillUnmount(): void {
this.props.mxEvent.getThread().removeListener("Thread.update", this.updateThread); if (this.state.thread) {
this.state.thread.removeListener("Thread.update", this.updateThread);
this.state.thread.removeListener("Thread.ready", this.updateThread);
}
} }
setupThread = () => {
const thread = this.props.mxEvent.getThread();
if (thread) {
thread.on("Thread.update", this.updateThread);
thread.once("Thread.ready", this.updateThread);
this.updateThread();
}
};
updateThread = () => { updateThread = () => {
this.forceUpdate(); this.setState({
thread: this.props.mxEvent.getThread(),
});
}; };
public renderEventTile(event: MatrixEvent): JSX.Element { public renderEventTile(event: MatrixEvent): JSX.Element {

View file

@ -280,7 +280,7 @@ const RoomSummaryCard: React.FC<IProps> = ({ room, onClose }) => {
<Button className="mx_RoomSummaryCard_icon_files" onClick={onRoomFilesClick}> <Button className="mx_RoomSummaryCard_icon_files" onClick={onRoomFilesClick}>
{ _t("Show files") } { _t("Show files") }
</Button> </Button>
<Button className="mx_RoomSummaryCard_icon_files" onClick={onRoomThreadsClick}> <Button className="mx_RoomSummaryCard_icon_threads" onClick={onRoomThreadsClick}>
{ _t("Show threads") } { _t("Show threads") }
</Button> </Button>
<Button className="mx_RoomSummaryCard_icon_share" onClick={onShareRoomClick}> <Button className="mx_RoomSummaryCard_icon_share" onClick={onShareRoomClick}>

View file

@ -56,6 +56,7 @@ import MessageActionBar from "../messages/MessageActionBar";
import ReactionsRow from '../messages/ReactionsRow'; import ReactionsRow from '../messages/ReactionsRow';
import { getEventDisplayInfo } from '../../../utils/EventUtils'; import { getEventDisplayInfo } from '../../../utils/EventUtils';
import { RightPanelPhases } from "../../../stores/RightPanelStorePhases"; import { RightPanelPhases } from "../../../stores/RightPanelStorePhases";
import { Thread } from '../../../../../matrix-js-sdk/src/models/thread';
const eventTileTypes = { const eventTileTypes = {
[EventType.RoomMessage]: 'messages.MessageEvent', [EventType.RoomMessage]: 'messages.MessageEvent',
@ -319,6 +320,8 @@ interface IState {
reactions: Relations; reactions: Relations;
hover: boolean; hover: boolean;
thread?: Thread;
} }
@replaceableComponent("views.rooms.EventTile") @replaceableComponent("views.rooms.EventTile")
@ -355,6 +358,8 @@ export default class EventTile extends React.Component<IProps, IState> {
reactions: this.getReactions(), reactions: this.getReactions(),
hover: false, hover: false,
thread: this.props.mxEvent?.getThread(),
}; };
// don't do RR animations until we are mounted // don't do RR animations until we are mounted
@ -455,9 +460,18 @@ export default class EventTile extends React.Component<IProps, IState> {
client.on("Room.receipt", this.onRoomReceipt); client.on("Room.receipt", this.onRoomReceipt);
this.isListeningForReceipts = true; this.isListeningForReceipts = true;
} }
this.props.mxEvent.on("Thread.update", this.forceUpdate);
this.props.mxEvent.once("Thread.ready", this.updateThread);
this.props.mxEvent.on("Thread.update", this.updateThread);
} }
private updateThread = (thread) => {
this.setState({
thread,
});
this.forceUpdate();
};
// TODO: [REACT-WARNING] Replace with appropriate lifecycle event // TODO: [REACT-WARNING] Replace with appropriate lifecycle event
// eslint-disable-next-line // eslint-disable-next-line
UNSAFE_componentWillReceiveProps(nextProps) { UNSAFE_componentWillReceiveProps(nextProps) {
@ -468,7 +482,7 @@ export default class EventTile extends React.Component<IProps, IState> {
} }
} }
shouldComponentUpdate(nextProps, nextState) { shouldComponentUpdate(nextProps, nextState, nextContext) {
if (objectHasDiff(this.state, nextState)) { if (objectHasDiff(this.state, nextState)) {
return true; return true;
} }
@ -497,8 +511,8 @@ export default class EventTile extends React.Component<IProps, IState> {
} }
private renderThreadInfo(): React.ReactNode { private renderThreadInfo(): React.ReactNode {
const thread = this.state.thread;
const room = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId()); const room = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId());
const thread = room.getThread(this.props.mxEvent.getId());
if (!thread || this.props.showThreadInfo === false) { if (!thread || this.props.showThreadInfo === false) {
return null; return null;
} }