Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Add new thread message preview (#18958)
Browse files Browse the repository at this point in the history
  • Loading branch information
Dariusz Niemczyk committed Oct 15, 2021
1 parent af55ac7 commit 61d3109
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 16 deletions.
51 changes: 49 additions & 2 deletions res/css/views/rooms/_EventTile.scss
Original file line number Diff line number Diff line change
Expand Up @@ -676,10 +676,57 @@ $hover-select-border: 4px;
}
}

.mx_ThreadInfo:hover {
cursor: pointer;
.mx_ThreadInfo {
height: 35px;
position: relative;
background-color: $system;
padding-left: 12px;
display: flex;
align-items: center;
border-radius: 8px;
padding-right: 16px;
padding-top: 8px;
padding-bottom: 8px;
font-size: 12px;
color: $secondary-content;
box-sizing: border-box;
justify-content: flex-start;

&:hover, &-active {
cursor: pointer;
border: 1px solid $quinary-content;
padding-top: 7px;
padding-bottom: 7px;
padding-left: 11px;
padding-right: 15px;
}

.mx_ThreadInfo_content {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
padding-left: 8px;
}

.mx_ThreadInfo_thread-icon {
mask-image: url('$(res)/img/element-icons/thread-summary.svg');
mask-position: center;
height: 16px;
min-width: 16px;
background-color: $secondary-content;
mask-repeat: no-repeat;
mask-size: contain;
}
.mx_ThreadInfo_threads-amount {
font-weight: 600;
position: relative;
padding: 0 8px;
white-space: nowrap;
}
}



.mx_ThreadView {
display: flex;
flex-direction: column;
Expand Down
1 change: 1 addition & 0 deletions res/img/element-icons/thread-summary.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 15 additions & 8 deletions src/components/views/rooms/EventTile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import { getEventDisplayInfo } from '../../../utils/EventUtils';
import SettingsStore from "../../../settings/SettingsStore";
import MKeyVerificationConclusion from "../messages/MKeyVerificationConclusion";
import { dispatchShowThreadEvent } from '../../../dispatcher/dispatch-actions/threads';
import { MessagePreviewStore } from '../../../stores/room-list/MessagePreviewStore';

const eventTileTypes = {
[EventType.RoomMessage]: 'messages.MessageEvent',
Expand Down Expand Up @@ -532,15 +533,13 @@ export default class EventTile extends React.Component<IProps, IState> {
}

const thread = this.state.thread;
const room = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId());
if (!thread || this.props.showThreadInfo === false || thread.length <= 1) {
return null;
}

const avatars = Array.from(thread.participants).map((mxId: string) => {
const member = room.getMember(mxId);
return <MemberAvatar key={member.userId} member={member} width={14} height={14} />;
});
const threadMessagePreview = MessagePreviewStore.instance.generateThreadPreview(this.state.thread);

if (!threadMessagePreview) return null;

return (
<div
Expand All @@ -549,10 +548,18 @@ export default class EventTile extends React.Component<IProps, IState> {
dispatchShowThreadEvent(this.props.mxEvent);
}}
>
<span className="mx_EventListSummary_avatars">
{ avatars }
<span className="mx_ThreadInfo_thread-icon" />
<span className="mx_ThreadInfo_threads-amount">
{ _t("%(count)s reply", {
count: thread.length - 1,
}) }
</span>
{ thread.length - 1 } { thread.length === 2 ? 'reply' : 'replies' }
<MemberAvatar member={thread.replyToEvent.sender} width={24} height={24} />
<div className="mx_ThreadInfo_content">
<span className="mx_ThreadInfo_message-preview">
{ threadMessagePreview }
</span>
</div>
</div>
);
}
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -1551,6 +1551,8 @@
"Send as message": "Send as message",
"Edit message": "Edit message",
"Mod": "Mod",
"%(count)s reply|other": "%(count)s replies",
"%(count)s reply|one": "%(count)s reply",
"This event could not be displayed": "This event could not be displayed",
"Your key share request has been sent - please check your other sessions for key share requests.": "Your key share request has been sent - please check your other sessions for key share requests.",
"Key share requests are sent to your other sessions automatically. If you rejected or dismissed the key share request on your other sessions, click here to request the keys for this session again.": "Key share requests are sent to your other sessions automatically. If you rejected or dismissed the key share request on your other sessions, click here to request the keys for this session again.",
Expand Down
10 changes: 10 additions & 0 deletions src/stores/room-list/MessagePreviewStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { CallHangupEvent } from "./previews/CallHangupEvent";
import { StickerEventPreview } from "./previews/StickerEventPreview";
import { ReactionEventPreview } from "./previews/ReactionEventPreview";
import { UPDATE_EVENT } from "../AsyncStore";
import { Thread } from "matrix-js-sdk/src/models/thread";

// Emitted event for when a room's preview has changed. First argument will the room for which
// the change happened.
Expand Down Expand Up @@ -108,6 +109,15 @@ export class MessagePreviewStore extends AsyncStoreWithClient<IState> {
return previews.get(inTagId);
}

public generateThreadPreview(thread: Thread): string {
const lastEvent = thread.replyToEvent;
const previewDef = PREVIEWS[lastEvent.getType()];
// TODO: Handle case where we don't have
if (!previewDef) return '';
const previewText = previewDef.previewer.getTextFor(lastEvent, null, true);
return previewText ?? '';
}

private async generatePreview(room: Room, tagId?: TagID) {
const events = room.timeline;
if (!events) return; // should only happen in tests
Expand Down
4 changes: 2 additions & 2 deletions src/stores/room-list/previews/MessageEventPreview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import ReplyThread from "../../../components/views/elements/ReplyThread";
import { getHtmlText } from "../../../HtmlUtils";

export class MessageEventPreview implements IPreview {
public getTextFor(event: MatrixEvent, tagId?: TagID): string {
public getTextFor(event: MatrixEvent, tagId?: TagID, isThread?: boolean): string {
let eventContent = event.getContent();

if (event.isRelation("m.replace")) {
Expand Down Expand Up @@ -64,7 +64,7 @@ export class MessageEventPreview implements IPreview {
return _t("* %(senderName)s %(emote)s", { senderName: getSenderName(event), emote: body });
}

if (isSelf(event) || !shouldPrefixMessagesIn(event.getRoomId(), tagId)) {
if (isThread || isSelf(event) || !shouldPrefixMessagesIn(event.getRoomId(), tagId)) {
return body;
} else {
return _t("%(senderName)s: %(message)s", { senderName: getSenderName(event), message: body });
Expand Down
4 changes: 2 additions & 2 deletions src/stores/room-list/previews/ReactionEventPreview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import SettingsStore from "../../../settings/SettingsStore";
import DMRoomMap from "../../../utils/DMRoomMap";

export class ReactionEventPreview implements IPreview {
public getTextFor(event: MatrixEvent, tagId?: TagID): string {
public getTextFor(event: MatrixEvent, tagId?: TagID, isThread?: boolean): string {
const showDms = SettingsStore.getValue("feature_roomlist_preview_reactions_dms");
const showAll = SettingsStore.getValue("feature_roomlist_preview_reactions_all");

Expand All @@ -41,7 +41,7 @@ export class ReactionEventPreview implements IPreview {
const reaction = relation.key;
if (!reaction) return null; // invalid reaction (unknown format)

if (isSelf(event) || !shouldPrefixMessagesIn(event.getRoomId(), tagId)) {
if (isThread || isSelf(event) || !shouldPrefixMessagesIn(event.getRoomId(), tagId)) {
return reaction;
} else {
return _t("%(senderName)s: %(reaction)s", { senderName: getSenderName(event), reaction });
Expand Down
4 changes: 2 additions & 2 deletions src/stores/room-list/previews/StickerEventPreview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ import { getSenderName, isSelf, shouldPrefixMessagesIn } from "./utils";
import { _t } from "../../../languageHandler";

export class StickerEventPreview implements IPreview {
public getTextFor(event: MatrixEvent, tagId?: TagID): string {
public getTextFor(event: MatrixEvent, tagId?: TagID, isThread?: boolean): string {
const stickerName = event.getContent()['body'];
if (!stickerName) return null;

if (isSelf(event) || !shouldPrefixMessagesIn(event.getRoomId(), tagId)) {
if (isThread || isSelf(event) || !shouldPrefixMessagesIn(event.getRoomId(), tagId)) {
return stickerName;
} else {
return _t("%(senderName)s: %(stickerName)s", { senderName: getSenderName(event), stickerName });
Expand Down

0 comments on commit 61d3109

Please sign in to comment.