mirror of
https://github.com/element-hq/element-web
synced 2024-11-23 09:46:09 +03:00
Apply tweaks to Thread list as per design spec (#8149)
Co-authored-by: Germain Souquet <germains@element.io>
This commit is contained in:
parent
4f6b939426
commit
27e48062b6
7 changed files with 173 additions and 72 deletions
|
@ -20,14 +20,17 @@ limitations under the License.
|
|||
|
||||
.mx_BaseCard_header {
|
||||
margin-bottom: 12px;
|
||||
|
||||
.mx_BaseCard_close,
|
||||
.mx_BaseCard_back {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.mx_BaseCard_back {
|
||||
left: -4px;
|
||||
}
|
||||
|
||||
.mx_BaseCard_close {
|
||||
right: -4px;
|
||||
}
|
||||
|
@ -66,6 +69,7 @@ limitations under the License.
|
|||
--size: 24px;
|
||||
width: var(--size);
|
||||
height: var(--size);
|
||||
|
||||
&::after {
|
||||
mask-size: var(--size);
|
||||
mask-image: url("$(res)/img/element-icons/message/overflow-large.svg");
|
||||
|
@ -99,11 +103,10 @@ limitations under the License.
|
|||
}
|
||||
|
||||
.mx_AutoHideScrollbar {
|
||||
background: #fff;
|
||||
background-color: $background;
|
||||
border-radius: 8px;
|
||||
width: calc(100% - 16px);
|
||||
padding-right: 16px;
|
||||
width: calc(100% - 24px);
|
||||
padding-right: 18px;
|
||||
}
|
||||
|
||||
&.mx_ThreadView .mx_ThreadView_timelinePanelWrapper {
|
||||
|
@ -125,13 +128,15 @@ limitations under the License.
|
|||
padding-right: 0;
|
||||
}
|
||||
|
||||
.mx_EventTile, .mx_GenericEventListSummary {
|
||||
.mx_EventTile,
|
||||
.mx_GenericEventListSummary {
|
||||
// Account for scrollbar when hovering
|
||||
padding-top: 0;
|
||||
|
||||
.mx_ThreadInfo {
|
||||
position: relative;
|
||||
padding-right: 11px;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
display: block;
|
||||
|
@ -157,6 +162,10 @@ limitations under the License.
|
|||
.mx_EventTile_e2eIcon {
|
||||
left: 8px;
|
||||
}
|
||||
|
||||
&:hover .mx_EventTile_line {
|
||||
box-shadow: unset !important; // don't show the verification left stroke in the thread list
|
||||
}
|
||||
}
|
||||
|
||||
.mx_MessageComposer {
|
||||
|
@ -190,10 +199,6 @@ limitations under the License.
|
|||
float: right;
|
||||
}
|
||||
|
||||
.mx_ThreadPanel_dropdown[aria-expanded=true]::before {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.mx_MessageTimestamp {
|
||||
font-size: $font-12px;
|
||||
color: $secondary-content;
|
||||
|
@ -272,19 +277,23 @@ limitations under the License.
|
|||
|
||||
h2 {
|
||||
color: $primary-content;
|
||||
font-weight: 600;
|
||||
font-weight: $font-semi-bold;
|
||||
font-size: $font-18px;
|
||||
margin-top: 24px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: $font-15px;
|
||||
color: $secondary-content;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
button {
|
||||
border: none;
|
||||
background: none;
|
||||
color: $accent;
|
||||
font-size: $font-15px;
|
||||
|
||||
&:hover,
|
||||
&:active {
|
||||
|
@ -292,6 +301,15 @@ limitations under the License.
|
|||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_ThreadPanel_empty_tip {
|
||||
font-size: $font-12px;
|
||||
line-height: $font-15px;
|
||||
|
||||
>b {
|
||||
font-weight: $font-semi-bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mx_ThreadPanel_largeIcon {
|
||||
|
@ -317,6 +335,7 @@ limitations under the License.
|
|||
.mx_ContextualMenu_wrapper.mx_ThreadPanel__header {
|
||||
.mx_ContextualMenu {
|
||||
position: initial;
|
||||
|
||||
span:first-of-type {
|
||||
font-weight: $font-semi-bold;
|
||||
font-size: inherit;
|
||||
|
@ -336,6 +355,7 @@ limitations under the License.
|
|||
left: auto;
|
||||
right: 22px;
|
||||
border-bottom-color: $quinary-content;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
border: inherit;
|
||||
|
@ -357,10 +377,12 @@ limitations under the License.
|
|||
&:hover {
|
||||
background-color: $event-selected-color;
|
||||
}
|
||||
|
||||
&[aria-checked="true"] {
|
||||
:first-child {
|
||||
margin-left: -20px;
|
||||
}
|
||||
|
||||
:first-child::before {
|
||||
content: "";
|
||||
width: 12px;
|
||||
|
|
|
@ -43,9 +43,11 @@ $left-gutter: 64px;
|
|||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_EventTile_receiptSent::before {
|
||||
mask-image: url('$(res)/img/element-icons/circle-sent.svg');
|
||||
}
|
||||
|
||||
.mx_EventTile_receiptSending::before {
|
||||
mask-image: url('$(res)/img/element-icons/circle-sending.svg');
|
||||
}
|
||||
|
@ -61,11 +63,11 @@ $left-gutter: 64px;
|
|||
&[data-shape=ThreadsList][data-notification]::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
right: -16px;
|
||||
top: 6px;
|
||||
right: -25px; // center it in the gutter (16px margin + 4px padding + half 10px width)
|
||||
top: 4px;
|
||||
left: auto;
|
||||
}
|
||||
|
||||
|
@ -79,7 +81,6 @@ $left-gutter: 64px;
|
|||
|
||||
.mx_ThreadInfo,
|
||||
.mx_ThreadSummaryIcon {
|
||||
margin-right: 110px;
|
||||
margin-left: 64px;
|
||||
}
|
||||
|
||||
|
@ -115,7 +116,8 @@ $left-gutter: 64px;
|
|||
.mx_DisambiguatedProfile {
|
||||
color: $primary-content;
|
||||
font-size: $font-14px;
|
||||
display: inline-block; /* anti-zalgo, with overflow hidden */
|
||||
display: inline-block;
|
||||
/* anti-zalgo, with overflow hidden */
|
||||
overflow: hidden;
|
||||
padding-bottom: 0px;
|
||||
padding-top: 0px;
|
||||
|
@ -142,7 +144,8 @@ $left-gutter: 64px;
|
|||
clear: both;
|
||||
}
|
||||
|
||||
.mx_EventTile_line, .mx_EventTile_reply {
|
||||
.mx_EventTile_line,
|
||||
.mx_EventTile_reply {
|
||||
position: relative;
|
||||
padding-left: $left-gutter;
|
||||
border-radius: 8px;
|
||||
|
@ -308,11 +311,19 @@ $left-gutter: 64px;
|
|||
|
||||
.mx_RoomView_timeline_rr_enabled {
|
||||
.mx_EventTile[data-layout=group] {
|
||||
|
||||
.mx_ThreadInfo,
|
||||
.mx_ThreadSummaryIcon,
|
||||
.mx_EventTile_line {
|
||||
/* ideally should be 100px, but 95px gives us a max thumbnail size of 800x600, which is nice */
|
||||
margin-right: 110px;
|
||||
}
|
||||
|
||||
.mx_ThreadInfo {
|
||||
max-width: min(calc(100% - $left-gutter - 110px), 600px); // leave space on both left & right gutters
|
||||
}
|
||||
}
|
||||
|
||||
// on ELS we need the margin to allow interaction with the expand/collapse button which is normally in the RR gutter
|
||||
}
|
||||
|
||||
|
@ -408,7 +419,8 @@ $left-gutter: 64px;
|
|||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
|
||||
&::before, &::after {
|
||||
&::before,
|
||||
&::after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
|
@ -433,6 +445,7 @@ $left-gutter: 64px;
|
|||
mask-image: url('$(res)/img/e2e/warning.svg');
|
||||
background-color: $alert;
|
||||
}
|
||||
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
|
@ -441,6 +454,7 @@ $left-gutter: 64px;
|
|||
mask-image: url('$(res)/img/e2e/normal.svg');
|
||||
background-color: $header-panel-text-primary-color;
|
||||
}
|
||||
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
|
@ -479,7 +493,8 @@ $left-gutter: 64px;
|
|||
color: inherit; // inherit the colour from the dark or light theme by default (but not for code blocks)
|
||||
font-size: $font-14px;
|
||||
|
||||
pre, code {
|
||||
pre,
|
||||
code {
|
||||
font-family: $monospace-font-family !important;
|
||||
background-color: $codeblock-background-color;
|
||||
}
|
||||
|
@ -492,7 +507,7 @@ $left-gutter: 64px;
|
|||
pre code {
|
||||
white-space: pre; // we want code blocks to be scrollable and not wrap
|
||||
|
||||
> * {
|
||||
>* {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
|
@ -514,6 +529,7 @@ $left-gutter: 64px;
|
|||
float: left;
|
||||
margin: 0 0.5em 0 -1.5em;
|
||||
color: gray;
|
||||
|
||||
& span {
|
||||
text-align: right;
|
||||
display: block;
|
||||
|
@ -547,18 +563,22 @@ $left-gutter: 64px;
|
|||
height: 19px;
|
||||
background-color: $message-action-bar-fg-color;
|
||||
}
|
||||
|
||||
.mx_EventTile_buttonBottom {
|
||||
top: 33px;
|
||||
}
|
||||
|
||||
.mx_EventTile_copyButton {
|
||||
mask-image: url($copy-button-url);
|
||||
}
|
||||
|
||||
.mx_EventTile_collapseButton {
|
||||
mask-size: 75%;
|
||||
mask-position: center;
|
||||
mask-repeat: no-repeat;
|
||||
mask-image: url("$(res)/img/element-icons/minimise-collapse.svg");
|
||||
}
|
||||
|
||||
.mx_EventTile_expandButton {
|
||||
mask-size: 75%;
|
||||
mask-position: center;
|
||||
|
@ -674,10 +694,13 @@ $left-gutter: 64px;
|
|||
}
|
||||
|
||||
@media only screen and (max-width: 480px) {
|
||||
.mx_EventTile_line, .mx_EventTile_reply {
|
||||
|
||||
.mx_EventTile_line,
|
||||
.mx_EventTile_reply {
|
||||
padding-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.mx_EventTile_content {
|
||||
margin-top: 10px;
|
||||
margin-right: 0;
|
||||
|
@ -692,23 +715,28 @@ $left-gutter: 64px;
|
|||
mask-position: center;
|
||||
height: 18px;
|
||||
min-width: 18px;
|
||||
background-color: $secondary-content;
|
||||
background-color: $secondary-content !important;
|
||||
mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
}
|
||||
|
||||
.mx_ThreadSummaryIcon {
|
||||
display: inline-block;
|
||||
font-size: $font-12px;
|
||||
color: $secondary-content;
|
||||
color: $secondary-content !important;
|
||||
margin-top: 8px;
|
||||
margin-bottom: 8px;
|
||||
|
||||
&::before {
|
||||
vertical-align: middle;
|
||||
margin-left: 8px;
|
||||
margin-right: 8px;
|
||||
margin-top: -2px;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_ThreadInfo {
|
||||
min-width: 267px;
|
||||
max-width: min(calc(100% - $left-gutter - 64px), 600px); // leave space on both left & right gutters
|
||||
max-width: min(calc(100% - $left-gutter), 600px); // leave space on both left & right gutters
|
||||
width: fit-content;
|
||||
height: 40px;
|
||||
position: relative;
|
||||
|
@ -756,7 +784,8 @@ $left-gutter: 64px;
|
|||
}
|
||||
}
|
||||
|
||||
&:hover, &:focus {
|
||||
&:hover,
|
||||
&:focus {
|
||||
cursor: pointer;
|
||||
border-color: $quinary-content;
|
||||
|
||||
|
@ -782,6 +811,9 @@ $threadInfoLineHeight: calc(2 * $font-12px);
|
|||
.mx_ThreadInfo_sender {
|
||||
font-weight: $font-semi-bold;
|
||||
line-height: $threadInfoLineHeight;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.mx_ThreadInfo_content {
|
||||
|
@ -792,6 +824,7 @@ $threadInfoLineHeight: calc(2 * $font-12px);
|
|||
font-size: $font-12px;
|
||||
line-height: $threadInfoLineHeight;
|
||||
color: $secondary-content;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.mx_ThreadInfo_avatar {
|
||||
|
@ -810,9 +843,10 @@ $threadInfoLineHeight: calc(2 * $font-12px);
|
|||
.mx_EventTile[data-shape=ThreadsList] {
|
||||
--topOffset: 20px;
|
||||
--leftOffset: 46px;
|
||||
$borderRadius: 8px;
|
||||
|
||||
margin: var(--topOffset) 16px var(--topOffset) 0;
|
||||
border-radius: 8px;
|
||||
border-radius: $borderRadius;
|
||||
|
||||
display: flex;
|
||||
flex-flow: wrap;
|
||||
|
@ -847,6 +881,7 @@ $threadInfoLineHeight: calc(2 * $font-12px);
|
|||
&::after {
|
||||
content: unset;
|
||||
}
|
||||
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
|
@ -857,7 +892,7 @@ $threadInfoLineHeight: calc(2 * $font-12px);
|
|||
padding-top: 0;
|
||||
|
||||
.mx_EventTile_avatar {
|
||||
top: -4px;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
|
@ -892,7 +927,7 @@ $threadInfoLineHeight: calc(2 * $font-12px);
|
|||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding-left: var(--leftOffset) !important;
|
||||
padding-bottom: 0;
|
||||
border-radius: $borderRadius !important; // override 4px
|
||||
}
|
||||
|
||||
.mx_MessageTimestamp {
|
||||
|
@ -918,7 +953,7 @@ $threadInfoLineHeight: calc(2 * $font-12px);
|
|||
.mx_EventTile {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-top: 0;
|
||||
padding-top: 14px; // due to layout differences, this odd number matches the 18px padding-top of main tl events
|
||||
|
||||
.mx_EventTile_line {
|
||||
padding-left: 0;
|
||||
|
@ -973,7 +1008,7 @@ $threadInfoLineHeight: calc(2 * $font-12px);
|
|||
.mx_UnknownBody,
|
||||
.mx_MPollBody,
|
||||
.mx_ReplyChain_wrapper {
|
||||
margin-left: 36px;
|
||||
margin-left: 48px;
|
||||
margin-right: 8px;
|
||||
|
||||
.mx_EventTile_content,
|
||||
|
@ -997,16 +1032,17 @@ $threadInfoLineHeight: calc(2 * $font-12px);
|
|||
.mx_EventTile_senderDetails {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: calc(6px + $selected-message-border-width);
|
||||
gap: calc(14px + $selected-message-border-width);
|
||||
|
||||
a {
|
||||
flex: 1;
|
||||
min-width: none;
|
||||
min-width: unset;
|
||||
max-width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.mx_DisambiguatedProfile {
|
||||
margin-left: 8px;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
@ -1026,4 +1062,13 @@ $threadInfoLineHeight: calc(2 * $font-12px);
|
|||
.mx_MessageComposer_sendMessage {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.mx_EditMessageComposer {
|
||||
margin-left: 30px !important; // align start of first letter with that of the event body
|
||||
}
|
||||
|
||||
.mx_EditMessageComposer_buttons {
|
||||
padding-right: 11px; // align with right edge of input
|
||||
margin-right: 0; // align with right edge of background
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,7 +101,7 @@ export const ThreadPanelHeader = ({ filterOption, setFilterOption, empty }: {
|
|||
isSelected={opt === value}
|
||||
/>);
|
||||
const contextMenu = menuDisplayed ? <ContextMenu
|
||||
top={100}
|
||||
top={108}
|
||||
right={33}
|
||||
onFinished={closeMenu}
|
||||
chevronFace={ChevronFace.Top}
|
||||
|
@ -129,25 +129,44 @@ export const ThreadPanelHeader = ({ filterOption, setFilterOption, empty }: {
|
|||
};
|
||||
|
||||
interface EmptyThreadIProps {
|
||||
hasThreads: boolean;
|
||||
filterOption: ThreadFilterType;
|
||||
showAllThreadsCallback: () => void;
|
||||
}
|
||||
|
||||
const EmptyThread: React.FC<EmptyThreadIProps> = ({ filterOption, showAllThreadsCallback }) => {
|
||||
const EmptyThread: React.FC<EmptyThreadIProps> = ({ hasThreads, filterOption, showAllThreadsCallback }) => {
|
||||
let body: JSX.Element;
|
||||
if (hasThreads) {
|
||||
body = <>
|
||||
<p>
|
||||
{ _t("Reply to an ongoing thread or use “%(replyInThread)s” "
|
||||
+ "when hovering over a message to start a new one.", {
|
||||
replyInThread: _t("Reply in thread"),
|
||||
}) }
|
||||
</p>
|
||||
<p>
|
||||
{ /* Always display that paragraph to prevent layout shift when hiding the button */ }
|
||||
{ (filterOption === ThreadFilterType.My)
|
||||
? <button onClick={showAllThreadsCallback}>{ _t("Show all threads") }</button>
|
||||
: <> </>
|
||||
}
|
||||
</p>
|
||||
</>;
|
||||
} else {
|
||||
body = <>
|
||||
<p>{ _t("Threads help keep your conversations on-topic and easy to track.") }</p>
|
||||
<p className="mx_ThreadPanel_empty_tip">
|
||||
{ _t('<b>Tip:</b> Use "Reply in thread" when hovering over a message.', {}, {
|
||||
b: sub => <b>{ sub }</b>,
|
||||
}) }
|
||||
</p>
|
||||
</>;
|
||||
}
|
||||
|
||||
return <aside className="mx_ThreadPanel_empty">
|
||||
<div className="mx_ThreadPanel_largeIcon" />
|
||||
<h2>{ _t("Keep discussions organised with threads") }</h2>
|
||||
<p>{ _t("Reply to an ongoing thread or use “%(replyInThread)s” "
|
||||
+ "when hovering over a message to start a new one.", { replyInThread: _t("Reply in thread") }) }
|
||||
</p>
|
||||
<p>
|
||||
{ /* Always display that paragraph to prevent layout shift
|
||||
When hiding the button */ }
|
||||
{ filterOption === ThreadFilterType.My
|
||||
? <button onClick={showAllThreadsCallback}>{ _t("Show all threads") }</button>
|
||||
: <> </>
|
||||
}
|
||||
</p>
|
||||
{ body }
|
||||
</aside>;
|
||||
};
|
||||
|
||||
|
@ -247,6 +266,7 @@ const ThreadPanel: React.FC<IProps> = ({
|
|||
timelineSet={timelineSet}
|
||||
showUrlPreview={false} // No URL previews at the threads list level
|
||||
empty={<EmptyThread
|
||||
hasThreads={room.threadsTimelineSets?.[0]?.getLiveTimeline().getEvents().length > 0}
|
||||
filterOption={filterOption}
|
||||
showAllThreadsCallback={() => setFilterOption(ThreadFilterType.All)}
|
||||
/>}
|
||||
|
|
|
@ -44,7 +44,6 @@ import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks";
|
|||
import { ChevronFace, IPosition } from '../../structures/ContextMenu';
|
||||
import RoomContext, { TimelineRenderingType } from '../../../contexts/RoomContext';
|
||||
import { ComposerInsertPayload } from "../../../dispatcher/payloads/ComposerInsertPayload";
|
||||
import { WidgetLayoutStore } from '../../../stores/widgets/WidgetLayoutStore';
|
||||
import EndPollDialog from '../dialogs/EndPollDialog';
|
||||
import { isPollEnded } from '../messages/MPollBody';
|
||||
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
||||
|
@ -472,14 +471,11 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
|||
timelineRenderingType === TimelineRenderingType.Thread ||
|
||||
timelineRenderingType === TimelineRenderingType.ThreadsList
|
||||
);
|
||||
const isThreadRootEvent = isThread && this.props.mxEvent?.getThread()?.rootEvent === this.props.mxEvent;
|
||||
const isThreadRootEvent = isThread && this.props.mxEvent.isThreadRoot;
|
||||
|
||||
const isMainSplitTimelineShown = !WidgetLayoutStore.instance.hasMaximisedWidget(
|
||||
MatrixClientPeg.get().getRoom(mxEvent.getRoomId()),
|
||||
);
|
||||
const commonItemsList = (
|
||||
<IconizedContextMenuOptionList>
|
||||
{ (isThreadRootEvent && isMainSplitTimelineShown) && <IconizedContextMenuOption
|
||||
{ isThreadRootEvent && <IconizedContextMenuOption
|
||||
iconClassName="mx_MessageContextMenu_iconViewInRoom"
|
||||
label={_t("View in room")}
|
||||
onClick={this.viewInRoom}
|
||||
|
|
|
@ -607,9 +607,14 @@ export default class TextualBody extends React.Component<IBodyProps, IState> {
|
|||
if (this.props.highlightLink) {
|
||||
body = <a href={this.props.highlightLink}>{ body }</a>;
|
||||
} else if (content.data && typeof content.data["org.matrix.neb.starter_link"] === "string") {
|
||||
body = <AccessibleButton kind="link_inline"
|
||||
onClick={this.onStarterLinkClick.bind(this, content.data["org.matrix.neb.starter_link"])}
|
||||
>{ body }</AccessibleButton>;
|
||||
body = (
|
||||
<AccessibleButton
|
||||
kind="link_inline"
|
||||
onClick={this.onStarterLinkClick.bind(this, content.data["org.matrix.neb.starter_link"])}
|
||||
>
|
||||
{ body }
|
||||
</AccessibleButton>
|
||||
);
|
||||
}
|
||||
|
||||
let widgets;
|
||||
|
@ -651,9 +656,7 @@ export default class TextualBody extends React.Component<IBodyProps, IState> {
|
|||
);
|
||||
}
|
||||
return (
|
||||
<div className="mx_MTextBody mx_EventTile_content"
|
||||
onClick={this.onBodyLinkClick}
|
||||
>
|
||||
<div className="mx_MTextBody mx_EventTile_content" onClick={this.onBodyLinkClick}>
|
||||
{ body }
|
||||
{ widgets }
|
||||
</div>
|
||||
|
|
|
@ -631,12 +631,22 @@ export class UnwrappedEventTile extends React.Component<IProps, IState> {
|
|||
}
|
||||
|
||||
private renderThreadInfo(): React.ReactNode {
|
||||
if (this.state.thread?.id === this.props.mxEvent.getId()) {
|
||||
return <ThreadSummary mxEvent={this.props.mxEvent} thread={this.state.thread} />;
|
||||
}
|
||||
|
||||
if (this.context.timelineRenderingType === TimelineRenderingType.Search && this.props.mxEvent.threadRootId) {
|
||||
if (this.props.highlightLink) {
|
||||
return (
|
||||
<a className="mx_ThreadSummaryIcon" href={this.props.highlightLink}>
|
||||
{ _t("From a thread") }
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<p className="mx_ThreadSummaryIcon">{ _t("From a thread") }</p>
|
||||
);
|
||||
} else if (this.state.thread?.id === this.props.mxEvent.getId()) {
|
||||
return <ThreadSummary mxEvent={this.props.mxEvent} thread={this.state.thread} />;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1100,6 +1110,7 @@ export class UnwrappedEventTile extends React.Component<IProps, IState> {
|
|||
let isContinuation = this.props.continuation;
|
||||
if (this.context.timelineRenderingType !== TimelineRenderingType.Room &&
|
||||
this.context.timelineRenderingType !== TimelineRenderingType.Search &&
|
||||
this.context.timelineRenderingType !== TimelineRenderingType.Thread &&
|
||||
this.props.layout !== Layout.Bubble
|
||||
) {
|
||||
isContinuation = false;
|
||||
|
@ -1146,16 +1157,17 @@ export class UnwrappedEventTile extends React.Component<IProps, IState> {
|
|||
? undefined
|
||||
: this.props.mxEvent.getId();
|
||||
|
||||
let avatar;
|
||||
let sender;
|
||||
let avatarSize;
|
||||
let needsSenderProfile;
|
||||
let avatar: JSX.Element;
|
||||
let sender: JSX.Element;
|
||||
let avatarSize: number;
|
||||
let needsSenderProfile: boolean;
|
||||
|
||||
if (this.context.timelineRenderingType === TimelineRenderingType.Notification ||
|
||||
this.context.timelineRenderingType === TimelineRenderingType.ThreadsList
|
||||
) {
|
||||
if (this.context.timelineRenderingType === TimelineRenderingType.Notification) {
|
||||
avatarSize = 24;
|
||||
needsSenderProfile = true;
|
||||
} else if (this.context.timelineRenderingType === TimelineRenderingType.ThreadsList) {
|
||||
avatarSize = 36;
|
||||
needsSenderProfile = true;
|
||||
} else if (tileHandler === 'messages.RoomCreate' || isBubbleMessage) {
|
||||
avatarSize = 0;
|
||||
needsSenderProfile = false;
|
||||
|
@ -1364,7 +1376,8 @@ export class UnwrappedEventTile extends React.Component<IProps, IState> {
|
|||
</a>
|
||||
</div>,
|
||||
<div className={lineClasses} key="mx_EventTile_line">
|
||||
<EventTileType ref={this.tile}
|
||||
<EventTileType
|
||||
ref={this.tile}
|
||||
mxEvent={this.props.mxEvent}
|
||||
highlights={this.props.highlights}
|
||||
highlightLink={this.props.highlightLink}
|
||||
|
@ -1399,9 +1412,7 @@ export class UnwrappedEventTile extends React.Component<IProps, IState> {
|
|||
</div>,
|
||||
<div className="mx_EventTile_senderDetails" key="mx_EventTile_senderDetails">
|
||||
{ avatar }
|
||||
<a href={permalink} onClick={this.onPermalinkClicked}>
|
||||
{ sender }
|
||||
</a>
|
||||
{ sender }
|
||||
</div>,
|
||||
<div className={lineClasses} key="mx_EventTile_line">
|
||||
{ replyChain }
|
||||
|
@ -1417,7 +1428,9 @@ export class UnwrappedEventTile extends React.Component<IProps, IState> {
|
|||
isSeeingThroughMessageHiddenForModeration={isSeeingThroughMessageHiddenForModeration}
|
||||
/>
|
||||
{ actionBar }
|
||||
{ timestamp }
|
||||
<a href={permalink} onClick={this.onPermalinkClicked}>
|
||||
{ timestamp }
|
||||
</a>
|
||||
</div>,
|
||||
reactionsRow,
|
||||
]);
|
||||
|
|
|
@ -3099,9 +3099,11 @@
|
|||
"My threads": "My threads",
|
||||
"Shows all threads you've participated in": "Shows all threads you've participated in",
|
||||
"Show:": "Show:",
|
||||
"Keep discussions organised with threads": "Keep discussions organised with threads",
|
||||
"Reply to an ongoing thread or use “%(replyInThread)s” when hovering over a message to start a new one.": "Reply to an ongoing thread or use “%(replyInThread)s” when hovering over a message to start a new one.",
|
||||
"Show all threads": "Show all threads",
|
||||
"Threads help keep your conversations on-topic and easy to track.": "Threads help keep your conversations on-topic and easy to track.",
|
||||
"<b>Tip:</b> Use \"Reply in thread\" when hovering over a message.": "<b>Tip:</b> Use \"Reply in thread\" when hovering over a message.",
|
||||
"Keep discussions organised with threads": "Keep discussions organised with threads",
|
||||
"Thread": "Thread",
|
||||
"Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.",
|
||||
"Tried to load a specific point in this room's timeline, but was unable to find it.": "Tried to load a specific point in this room's timeline, but was unable to find it.",
|
||||
|
|
Loading…
Reference in a new issue