Fix threads broken layout (#6997)
This commit is contained in:
parent
115c6e8357
commit
35b5109c2a
5 changed files with 44 additions and 27 deletions
|
@ -24,6 +24,11 @@ $left-gutter: 64px;
|
||||||
font-size: $font-14px;
|
font-size: $font-14px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
.mx_ThreadInfo {
|
||||||
|
margin-right: 110px;
|
||||||
|
margin-left: 64px;
|
||||||
|
}
|
||||||
|
|
||||||
&.mx_EventTile_info {
|
&.mx_EventTile_info {
|
||||||
padding-top: 1px;
|
padding-top: 1px;
|
||||||
}
|
}
|
||||||
|
@ -693,7 +698,7 @@ $left-gutter: 64px;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
clear: both;
|
clear: both;
|
||||||
|
|
||||||
&:hover, &-active {
|
&:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border: 1px solid $quinary-content;
|
border: 1px solid $quinary-content;
|
||||||
padding-top: 7px;
|
padding-top: 7px;
|
||||||
|
@ -785,6 +790,12 @@ $left-gutter: 64px;
|
||||||
left: auto;
|
left: auto;
|
||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_ReactionsRow {
|
||||||
|
order: 999;
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_MessageComposer_sendMessage {
|
.mx_MessageComposer_sendMessage {
|
||||||
|
|
|
@ -560,6 +560,9 @@ export default class MessagePanel extends React.Component<IProps, IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private get pendingEditItem(): string | undefined {
|
private get pendingEditItem(): string | undefined {
|
||||||
|
if (!this.props.room) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
return localStorage.getItem(`mx_edit_room_${this.props.room.roomId}_${this.context.timelineRenderingType}`);
|
return localStorage.getItem(`mx_edit_room_${this.props.room.roomId}_${this.context.timelineRenderingType}`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
|
@ -64,10 +64,10 @@ const useFilteredThreadsTimelinePanel = ({
|
||||||
filterOption: ThreadFilterType;
|
filterOption: ThreadFilterType;
|
||||||
updateTimeline: () => void;
|
updateTimeline: () => void;
|
||||||
}) => {
|
}) => {
|
||||||
const timelineSet = useMemo(() => new EventTimelineSet(room, {
|
const timelineSet = useMemo(() => new EventTimelineSet(null, {
|
||||||
unstableClientRelationAggregation: true,
|
|
||||||
timelineSupport: true,
|
timelineSupport: true,
|
||||||
}), [room]);
|
unstableClientRelationAggregation: true,
|
||||||
|
}), []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let filteredThreads = Array.from(threads);
|
let filteredThreads = Array.from(threads);
|
||||||
|
@ -217,7 +217,7 @@ const ThreadPanel: React.FC<IProps> = ({ roomId, onClose }) => {
|
||||||
showReactions={true}
|
showReactions={true}
|
||||||
className="mx_RoomView_messagePanel mx_GroupLayout"
|
className="mx_RoomView_messagePanel mx_GroupLayout"
|
||||||
membersLoaded={true}
|
membersLoaded={true}
|
||||||
tileShape={TileShape.Thread}
|
tileShape={TileShape.ThreadPanel}
|
||||||
/>
|
/>
|
||||||
</BaseCard>
|
</BaseCard>
|
||||||
</RoomContext.Provider>
|
</RoomContext.Provider>
|
||||||
|
|
|
@ -561,13 +561,14 @@ export default class EventTile extends React.Component<IProps, IState> {
|
||||||
thread.addEvent(this.props.mxEvent, true);
|
thread.addEvent(this.props.mxEvent, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!thread || this.props.showThreadInfo === false || thread.length <= 1) {
|
if (!thread || this.props.showThreadInfo === false || thread.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const threadMessagePreview = MessagePreviewStore.instance.generateThreadPreview(this.state.thread);
|
const [lastEvent] = thread.events
|
||||||
|
.filter(event => event.isThreadRelation)
|
||||||
if (!threadMessagePreview) return null;
|
.slice(-1);
|
||||||
|
const threadMessagePreview = MessagePreviewStore.instance.generatePreviewForEvent(lastEvent);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
@ -579,15 +580,17 @@ export default class EventTile extends React.Component<IProps, IState> {
|
||||||
<span className="mx_ThreadInfo_thread-icon" />
|
<span className="mx_ThreadInfo_thread-icon" />
|
||||||
<span className="mx_ThreadInfo_threads-amount">
|
<span className="mx_ThreadInfo_threads-amount">
|
||||||
{ _t("%(count)s reply", {
|
{ _t("%(count)s reply", {
|
||||||
count: thread.length - 1,
|
count: thread.length,
|
||||||
}) }
|
}) }
|
||||||
</span>
|
</span>
|
||||||
<MemberAvatar member={thread.replyToEvent.sender} width={24} height={24} />
|
{ (threadMessagePreview && lastEvent.sender) && <>
|
||||||
<div className="mx_ThreadInfo_content">
|
<MemberAvatar member={lastEvent.sender} width={24} height={24} />
|
||||||
<span className="mx_ThreadInfo_message-preview">
|
<div className="mx_ThreadInfo_content">
|
||||||
{ threadMessagePreview }
|
<span className="mx_ThreadInfo_message-preview">
|
||||||
</span>
|
{ threadMessagePreview }
|
||||||
</div>
|
</span>
|
||||||
|
</div>
|
||||||
|
</> }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1214,7 +1217,7 @@ export default class EventTile extends React.Component<IProps, IState> {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
case TileShape.Thread: {
|
case TileShape.Thread: {
|
||||||
const thread = haveTileForEvent(this.props.mxEvent) &&
|
const replyChain = haveTileForEvent(this.props.mxEvent) &&
|
||||||
ReplyChain.hasReply(this.props.mxEvent) ? (
|
ReplyChain.hasReply(this.props.mxEvent) ? (
|
||||||
<ReplyChain
|
<ReplyChain
|
||||||
parentEv={this.props.mxEvent}
|
parentEv={this.props.mxEvent}
|
||||||
|
@ -1233,7 +1236,7 @@ export default class EventTile extends React.Component<IProps, IState> {
|
||||||
"aria-live": ariaLive,
|
"aria-live": ariaLive,
|
||||||
"aria-atomic": true,
|
"aria-atomic": true,
|
||||||
"data-scroll-tokens": scrollToken,
|
"data-scroll-tokens": scrollToken,
|
||||||
"data-has-reply": !!thread,
|
"data-has-reply": !!replyChain,
|
||||||
}, [
|
}, [
|
||||||
<div className="mx_EventTile_roomName" key="mx_EventTile_roomName">
|
<div className="mx_EventTile_roomName" key="mx_EventTile_roomName">
|
||||||
<RoomAvatar room={room} width={28} height={28} />
|
<RoomAvatar room={room} width={28} height={28} />
|
||||||
|
@ -1249,7 +1252,7 @@ export default class EventTile extends React.Component<IProps, IState> {
|
||||||
</a>
|
</a>
|
||||||
</div>,
|
</div>,
|
||||||
<div className="mx_EventTile_line" key="mx_EventTile_line">
|
<div className="mx_EventTile_line" key="mx_EventTile_line">
|
||||||
{ thread }
|
{ replyChain }
|
||||||
<EventTileType ref={this.tile}
|
<EventTileType ref={this.tile}
|
||||||
mxEvent={this.props.mxEvent}
|
mxEvent={this.props.mxEvent}
|
||||||
highlights={this.props.highlights}
|
highlights={this.props.highlights}
|
||||||
|
@ -1262,6 +1265,7 @@ export default class EventTile extends React.Component<IProps, IState> {
|
||||||
/>
|
/>
|
||||||
{ actionBar }
|
{ actionBar }
|
||||||
</div>,
|
</div>,
|
||||||
|
reactionsRow,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
case TileShape.FileGrid: {
|
case TileShape.FileGrid: {
|
||||||
|
@ -1297,7 +1301,7 @@ export default class EventTile extends React.Component<IProps, IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
const thread = haveTileForEvent(this.props.mxEvent) &&
|
const replyChain = haveTileForEvent(this.props.mxEvent) &&
|
||||||
ReplyChain.hasReply(this.props.mxEvent) ? (
|
ReplyChain.hasReply(this.props.mxEvent) ? (
|
||||||
<ReplyChain
|
<ReplyChain
|
||||||
parentEv={this.props.mxEvent}
|
parentEv={this.props.mxEvent}
|
||||||
|
@ -1323,7 +1327,7 @@ export default class EventTile extends React.Component<IProps, IState> {
|
||||||
"data-scroll-tokens": scrollToken,
|
"data-scroll-tokens": scrollToken,
|
||||||
"data-layout": this.props.layout,
|
"data-layout": this.props.layout,
|
||||||
"data-self": isOwnEvent,
|
"data-self": isOwnEvent,
|
||||||
"data-has-reply": !!thread,
|
"data-has-reply": !!replyChain,
|
||||||
"onMouseEnter": () => this.setState({ hover: true }),
|
"onMouseEnter": () => this.setState({ hover: true }),
|
||||||
"onMouseLeave": () => this.setState({ hover: false }),
|
"onMouseLeave": () => this.setState({ hover: false }),
|
||||||
}, <>
|
}, <>
|
||||||
|
@ -1334,7 +1338,7 @@ export default class EventTile extends React.Component<IProps, IState> {
|
||||||
<div className="mx_EventTile_line" key="mx_EventTile_line">
|
<div className="mx_EventTile_line" key="mx_EventTile_line">
|
||||||
{ groupTimestamp }
|
{ groupTimestamp }
|
||||||
{ groupPadlock }
|
{ groupPadlock }
|
||||||
{ thread }
|
{ replyChain }
|
||||||
<EventTileType ref={this.tile}
|
<EventTileType ref={this.tile}
|
||||||
mxEvent={this.props.mxEvent}
|
mxEvent={this.props.mxEvent}
|
||||||
forExport={this.props.forExport}
|
forExport={this.props.forExport}
|
||||||
|
|
|
@ -27,7 +27,7 @@ import { CallHangupEvent } from "./previews/CallHangupEvent";
|
||||||
import { StickerEventPreview } from "./previews/StickerEventPreview";
|
import { StickerEventPreview } from "./previews/StickerEventPreview";
|
||||||
import { ReactionEventPreview } from "./previews/ReactionEventPreview";
|
import { ReactionEventPreview } from "./previews/ReactionEventPreview";
|
||||||
import { UPDATE_EVENT } from "../AsyncStore";
|
import { UPDATE_EVENT } from "../AsyncStore";
|
||||||
import { Thread } from "matrix-js-sdk/src/models/thread";
|
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||||
|
|
||||||
// Emitted event for when a room's preview has changed. First argument will the room for which
|
// Emitted event for when a room's preview has changed. First argument will the room for which
|
||||||
// the change happened.
|
// the change happened.
|
||||||
|
@ -109,12 +109,11 @@ export class MessagePreviewStore extends AsyncStoreWithClient<IState> {
|
||||||
return previews.get(inTagId);
|
return previews.get(inTagId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public generateThreadPreview(thread: Thread): string {
|
public generatePreviewForEvent(event: MatrixEvent): string {
|
||||||
const lastEvent = thread.replyToEvent;
|
const previewDef = PREVIEWS[event.getType()];
|
||||||
const previewDef = PREVIEWS[lastEvent.getType()];
|
|
||||||
// TODO: Handle case where we don't have
|
// TODO: Handle case where we don't have
|
||||||
if (!previewDef) return '';
|
if (!previewDef) return '';
|
||||||
const previewText = previewDef.previewer.getTextFor(lastEvent, null, true);
|
const previewText = previewDef.previewer.getTextFor(event, null, true);
|
||||||
return previewText ?? '';
|
return previewText ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue