diff --git a/.stylelintrc.js b/.stylelintrc.js index 0e6de7000f..c044b19a63 100644 --- a/.stylelintrc.js +++ b/.stylelintrc.js @@ -17,6 +17,7 @@ module.exports = { "selector-list-comma-newline-after": null, "at-rule-no-unknown": null, "no-descending-specificity": null, + "no-empty-first-line": true, "scss/at-rule-no-unknown": [true, { // https://github.com/vector-im/element-web/issues/10544 "ignoreAtRules": ["define-mixin"], diff --git a/res/css/views/rooms/_EventTile.scss b/res/css/views/rooms/_EventTile.scss index 1bf62d3fb1..0e77f20c49 100644 --- a/res/css/views/rooms/_EventTile.scss +++ b/res/css/views/rooms/_EventTile.scss @@ -643,6 +643,7 @@ $hover-select-border: 4px; // Remove some of the default tile padding so that the error is centered margin-right: 0; + .mx_EventTile_line { padding-left: 0; margin-right: 0; @@ -675,18 +676,17 @@ $hover-select-border: 4px; } } - .mx_ThreadInfo:hover { cursor: pointer; } .mx_ThreadView { - display: flex; flex-direction: column; .mx_ScrollPanel { margin-top: 20px; + .mx_RoomView_MessageList { padding: 0; } @@ -703,6 +703,7 @@ $hover-select-border: 4px; max-width: 100%; display: flex; align-items: center; + .mx_SenderProfile { flex: 1; } @@ -722,6 +723,7 @@ $hover-select-border: 4px; padding-left: 0 !important; order: 10 !important; } + .mx_EventTile { width: 100%; display: flex; diff --git a/res/css/views/rooms/_MessageComposer.scss b/res/css/views/rooms/_MessageComposer.scss index b2747f7a9b..54c250fc2e 100644 --- a/res/css/views/rooms/_MessageComposer.scss +++ b/res/css/views/rooms/_MessageComposer.scss @@ -347,9 +347,11 @@ limitations under the License. .mx_MessageComposer.mx_MessageComposer--compact { margin-right: 0; + .mx_MessageComposer_wrapper { padding: 0; } + .mx_MessageComposer_button:last-child { margin-right: 0; } diff --git a/src/MatrixClientPeg.ts b/src/MatrixClientPeg.ts index d3382a2b5e..7d0ff560b7 100644 --- a/src/MatrixClientPeg.ts +++ b/src/MatrixClientPeg.ts @@ -213,7 +213,7 @@ class MatrixClientPegClass implements IMatrixClientPeg { opts.pendingEventOrdering = PendingEventOrdering.Detached; opts.lazyLoadMembers = true; opts.clientWellKnownPollPeriod = 2 * 60 * 60; // 2 hours - opts.experimentalThreadSupport = SettingsStore.getValue("experimentalThreadSupport"); + opts.experimentalThreadSupport = SettingsStore.getValue("feature_thread"); // Connect the matrix client to the dispatcher and setting handlers MatrixActionCreators.start(this.matrixClient); diff --git a/src/components/structures/MessagePanel.tsx b/src/components/structures/MessagePanel.tsx index 49fb50814c..8bf1f5bd5f 100644 --- a/src/components/structures/MessagePanel.tsx +++ b/src/components/structures/MessagePanel.tsx @@ -267,7 +267,7 @@ export default class MessagePanel extends React.Component { componentDidMount() { this.calculateRoomMembersCount(); this.props.room?.on("RoomState.members", this.calculateRoomMembersCount); - if (SettingsStore.getValue("experimentalThreadSupport")) { + if (SettingsStore.getValue("feature_thread")) { this.props.room?.getThreads().forEach(thread => thread.fetchReplyChain()); } this.isMounted = true; @@ -448,8 +448,9 @@ export default class MessagePanel extends React.Component { // Always show highlighted event if (this.props.highlightedEventId === mxEv.getId()) return true; - const threadingEnabled = SettingsStore.getValue("experimentalThreadSupport"); - if (threadingEnabled && mxEv.replyEventId && this.props.hideThreadedMessages === true) { + if (mxEv.replyEventId + && this.props.hideThreadedMessages + && SettingsStore.getValue("feature_thread")) { return false; } diff --git a/src/components/structures/ThreadPanel.tsx b/src/components/structures/ThreadPanel.tsx index 9259dbe13b..047e527f34 100644 --- a/src/components/structures/ThreadPanel.tsx +++ b/src/components/structures/ThreadPanel.tsx @@ -1,6 +1,5 @@ /* -Copyright 2016 OpenMarket Ltd -Copyright 2019 The Matrix.org Foundation C.I.C. +Copyright 2021 New Vector Ltd. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -37,11 +36,8 @@ interface IState { threads?: Thread[]; } -/* - * Component which shows the filtered file using a TimelinePanel - */ @replaceableComponent("structures.ThreadView") -class ThreadView extends React.Component { +export default class ThreadPanel extends React.Component { private room: Room; constructor(props: IProps) { @@ -59,15 +55,15 @@ class ThreadView extends React.Component { this.room.removeListener("Thread.ready", this.onThreadEventReceived); } - public onThreadEventReceived = () => this.updateThreads(); + private onThreadEventReceived = () => this.updateThreads(); - public updateThreads = (callback?: () => void): void => { + private updateThreads = (callback?: () => void): void => { this.setState({ threads: this.room.getThreads(), }, callback); }; - public renderEventTile(event: MatrixEvent): JSX.Element { + private renderEventTile(event: MatrixEvent): JSX.Element { return { />; } - public render() { + public render(): JSX.Element { return ( { ); } } - -export default ThreadView; diff --git a/src/components/structures/ThreadView.tsx b/src/components/structures/ThreadView.tsx index 38b1c8dc08..03609c66d0 100644 --- a/src/components/structures/ThreadView.tsx +++ b/src/components/structures/ThreadView.tsx @@ -1,6 +1,5 @@ /* -Copyright 2016 OpenMarket Ltd -Copyright 2019 The Matrix.org Foundation C.I.C. +Copyright 2021 New Vector Ltd. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -22,7 +21,6 @@ import { Thread } from 'matrix-js-sdk/src/models/thread'; import BaseCard from "../views/right_panel/BaseCard"; import { RightPanelPhases } from "../../stores/RightPanelStorePhases"; import { replaceableComponent } from "../../utils/replaceableComponent"; -import { MatrixClientPeg } from '../../MatrixClientPeg'; import ResizeNotifier from '../../utils/ResizeNotifier'; import EventTile, { TileShape } from '../views/rooms/EventTile'; @@ -48,11 +46,8 @@ interface IState { thread?: Thread; } -/* - * Component which shows the filtered file using a TimelinePanel - */ @replaceableComponent("structures.ThreadView") -class ThreadView extends React.Component { +export default class ThreadView extends React.Component { private dispatcherRef: string; constructor(props: IProps) { @@ -93,7 +88,7 @@ class ThreadView extends React.Component { } }; - setupThread = (mxEv: MatrixEvent) => { + private setupThread = (mxEv: MatrixEvent) => { const thread = mxEv.getThread(); if (thread) { thread.on("Thread.update", this.updateThread); @@ -102,14 +97,14 @@ class ThreadView extends React.Component { } }; - teardownThread = () => { + private teardownThread = () => { if (this.state.thread) { this.state.thread.removeListener("Thread.update", this.updateThread); this.state.thread.removeListener("Thread.ready", this.updateThread); } }; - updateThread = (thread?: Thread) => { + private updateThread = (thread?: Thread) => { if (thread) { this.setState({ thread }); } else { @@ -128,7 +123,7 @@ class ThreadView extends React.Component { />; } - public render() { + public render(): JSX.Element { return ( { ); } } - -export default ThreadView; diff --git a/src/components/views/messages/MessageActionBar.js b/src/components/views/messages/MessageActionBar.js index 83e063ab8c..cb8ea7a50d 100644 --- a/src/components/views/messages/MessageActionBar.js +++ b/src/components/views/messages/MessageActionBar.js @@ -275,7 +275,7 @@ export default class MessageActionBar extends React.PureComponent { onClick={this.onReplyClick} key="reply" /> - { SettingsStore.getValue("experimentalThreadSupport") && ( + { SettingsStore.getValue("feature_thread") && ( = ({ room, onClose }) => { - { SettingsStore.getValue("experimentalThreadSupport") && ( + { SettingsStore.getValue("feature_thread") && ( diff --git a/src/components/views/rooms/EventTile.tsx b/src/components/views/rooms/EventTile.tsx index 638bef5061..935a349b10 100644 --- a/src/components/views/rooms/EventTile.tsx +++ b/src/components/views/rooms/EventTile.tsx @@ -462,7 +462,7 @@ export default class EventTile extends React.Component { this.isListeningForReceipts = true; } - if (SettingsStore.getValue("experimentalThreadSupport")) { + if (SettingsStore.getValue("feature_thread")) { this.props.mxEvent.once("Thread.ready", this.updateThread); this.props.mxEvent.on("Thread.update", this.updateThread); } @@ -514,7 +514,7 @@ export default class EventTile extends React.Component { } private renderThreadInfo(): React.ReactNode { - if (!SettingsStore.getValue("experimentalThreadSupport")) { + if (!SettingsStore.getValue("feature_thread")) { return null; } diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx index 6496231679..2dba4cf55d 100644 --- a/src/settings/Settings.tsx +++ b/src/settings/Settings.tsx @@ -211,7 +211,7 @@ export const SETTINGS: {[setting: string]: ISetting} = { supportedLevels: LEVELS_FEATURE, default: false, }, - "experimentalThreadSupport": { + "feature_thread": { isFeature: true, // Requires a reload as we change an option flag on the `js-sdk` // And the entire sync history needs to be parsed again