mirror of https://github.com/vector-im/riot-web
commit
5a1bf03053
|
@ -162,6 +162,8 @@
|
|||
@import "./views/rooms/_EditMessageComposer.scss";
|
||||
@import "./views/rooms/_EntityTile.scss";
|
||||
@import "./views/rooms/_EventTile.scss";
|
||||
@import "./views/rooms/_GroupLayout.scss";
|
||||
@import "./views/rooms/_IRCLayout.scss";
|
||||
@import "./views/rooms/_InviteOnlyIcon.scss";
|
||||
@import "./views/rooms/_JumpToBottomButton.scss";
|
||||
@import "./views/rooms/_LinkPreviewWidget.scss";
|
||||
|
|
|
@ -37,7 +37,6 @@ limitations under the License.
|
|||
}
|
||||
|
||||
.mx_EventTile_avatar {
|
||||
position: absolute;
|
||||
top: 14px;
|
||||
left: 8px;
|
||||
cursor: pointer;
|
||||
|
@ -68,11 +67,9 @@ limitations under the License.
|
|||
display: inline-block; /* anti-zalgo, with overflow hidden */
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
padding-left: 65px; /* left gutter */
|
||||
padding-bottom: 0px;
|
||||
padding-top: 0px;
|
||||
margin: 0px;
|
||||
line-height: $font-17px;
|
||||
/* the next three lines, along with overflow hidden, truncate long display names */
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
|
@ -101,12 +98,9 @@ limitations under the License.
|
|||
|
||||
.mx_EventTile .mx_MessageTimestamp {
|
||||
display: block;
|
||||
visibility: hidden;
|
||||
white-space: nowrap;
|
||||
left: 0px;
|
||||
width: 46px; /* 8 + 30 (avatar) + 8 */
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
|
@ -117,10 +111,7 @@ limitations under the License.
|
|||
.mx_EventTile_line, .mx_EventTile_reply {
|
||||
position: relative;
|
||||
padding-left: 65px; /* left gutter */
|
||||
padding-top: 3px;
|
||||
padding-bottom: 3px;
|
||||
border-radius: 4px;
|
||||
line-height: $font-22px;
|
||||
}
|
||||
|
||||
.mx_RoomView_timeline_rr_enabled,
|
||||
|
@ -151,10 +142,6 @@ limitations under the License.
|
|||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.mx_EventTile_info .mx_EventTile_line {
|
||||
padding-left: 83px;
|
||||
}
|
||||
|
||||
/* HACK to override line-height which is already marked important elsewhere */
|
||||
.mx_EventTile_bigEmoji.mx_EventTile_bigEmoji {
|
||||
font-size: 48px !important;
|
||||
|
@ -560,84 +547,6 @@ limitations under the License.
|
|||
|
||||
/* end of overrides */
|
||||
|
||||
.mx_MatrixChat_useCompactLayout {
|
||||
.mx_EventTile {
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
.mx_EventTile.mx_EventTile_info {
|
||||
// same as the padding for non-compact .mx_EventTile.mx_EventTile_info
|
||||
padding-top: 0px;
|
||||
font-size: $font-13px;
|
||||
.mx_EventTile_line, .mx_EventTile_reply {
|
||||
line-height: $font-20px;
|
||||
}
|
||||
.mx_EventTile_avatar {
|
||||
top: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_EventTile .mx_SenderProfile {
|
||||
font-size: $font-13px;
|
||||
}
|
||||
|
||||
.mx_EventTile.mx_EventTile_emote {
|
||||
// add a bit more space for emotes so that avatars don't collide
|
||||
padding-top: 8px;
|
||||
.mx_EventTile_avatar {
|
||||
top: 2px;
|
||||
}
|
||||
.mx_EventTile_line, .mx_EventTile_reply {
|
||||
padding-top: 0px;
|
||||
padding-bottom: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_EventTile.mx_EventTile_emote.mx_EventTile_continuation {
|
||||
padding-top: 0;
|
||||
.mx_EventTile_line, .mx_EventTile_reply {
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_EventTile_line, .mx_EventTile_reply {
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
.mx_EventTile_avatar {
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
.mx_EventTile_e2eIcon {
|
||||
top: 3px;
|
||||
}
|
||||
|
||||
.mx_EventTile_readAvatars {
|
||||
top: 27px;
|
||||
}
|
||||
|
||||
.mx_EventTile_continuation .mx_EventTile_readAvatars,
|
||||
.mx_EventTile_emote .mx_EventTile_readAvatars {
|
||||
top: 5px;
|
||||
}
|
||||
|
||||
.mx_EventTile_info .mx_EventTile_readAvatars {
|
||||
top: 4px;
|
||||
}
|
||||
|
||||
.mx_RoomView_MessageList h2 {
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.mx_EventTile_content .markdown-body {
|
||||
p, ul, ol, dl, blockquote, pre, table {
|
||||
margin-bottom: 4px; // 1/4 of the non-compact margin-bottom
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mx_EventTile_tileError {
|
||||
color: red;
|
||||
text-align: center;
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
Copyright 2015, 2016 OpenMarket Ltd
|
||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
$left-gutter: 65px;
|
||||
|
||||
.mx_GroupLayout {
|
||||
|
||||
.mx_EventTile {
|
||||
> .mx_SenderProfile {
|
||||
line-height: $font-17px;
|
||||
padding-left: $left-gutter;
|
||||
}
|
||||
|
||||
> .mx_EventTile_line {
|
||||
padding-left: $left-gutter;
|
||||
}
|
||||
|
||||
> .mx_EventTile_avatar {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.mx_MessageTimestamp {
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
width: 46px; /* 8 + 30 (avatar) + 8 */
|
||||
}
|
||||
|
||||
.mx_EventTile_line, .mx_EventTile_reply {
|
||||
padding-top: 3px;
|
||||
padding-bottom: 3px;
|
||||
line-height: $font-22px;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_EventTile_info .mx_EventTile_line {
|
||||
padding-left: calc($left-gutter + 18px);
|
||||
}
|
||||
}
|
||||
|
||||
/* Compact layout overrides */
|
||||
|
||||
.mx_MatrixChat_useCompactLayout {
|
||||
.mx_EventTile {
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
.mx_EventTile.mx_EventTile_info {
|
||||
// same as the padding for non-compact .mx_EventTile.mx_EventTile_info
|
||||
padding-top: 0px;
|
||||
font-size: $font-13px;
|
||||
.mx_EventTile_line, .mx_EventTile_reply {
|
||||
line-height: $font-20px;
|
||||
}
|
||||
.mx_EventTile_avatar {
|
||||
top: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_EventTile .mx_SenderProfile {
|
||||
font-size: $font-13px;
|
||||
}
|
||||
|
||||
.mx_EventTile.mx_EventTile_emote {
|
||||
// add a bit more space for emotes so that avatars don't collide
|
||||
padding-top: 8px;
|
||||
.mx_EventTile_avatar {
|
||||
top: 2px;
|
||||
}
|
||||
.mx_EventTile_line, .mx_EventTile_reply {
|
||||
padding-top: 0px;
|
||||
padding-bottom: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_EventTile.mx_EventTile_emote.mx_EventTile_continuation {
|
||||
padding-top: 0;
|
||||
.mx_EventTile_line, .mx_EventTile_reply {
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_EventTile_line, .mx_EventTile_reply {
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
.mx_EventTile_avatar {
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
.mx_EventTile_e2eIcon {
|
||||
top: 3px;
|
||||
}
|
||||
|
||||
.mx_EventTile_readAvatars {
|
||||
top: 27px;
|
||||
}
|
||||
|
||||
.mx_EventTile_continuation .mx_EventTile_readAvatars,
|
||||
.mx_EventTile_emote .mx_EventTile_readAvatars {
|
||||
top: 5px;
|
||||
}
|
||||
|
||||
.mx_EventTile_info .mx_EventTile_readAvatars {
|
||||
top: 4px;
|
||||
}
|
||||
|
||||
.mx_RoomView_MessageList h2 {
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.mx_EventTile_content .markdown-body {
|
||||
p, ul, ol, dl, blockquote, pre, table {
|
||||
margin-bottom: 4px; // 1/4 of the non-compact margin-bottom
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
$icon-width: 14px;
|
||||
$timestamp-width: 45px;
|
||||
$right-padding: 5px;
|
||||
$irc-line-height: $font-18px;
|
||||
|
||||
.mx_IRCLayout {
|
||||
--name-width: 70px;
|
||||
|
||||
line-height: $irc-line-height !important;
|
||||
|
||||
.mx_EventTile {
|
||||
|
||||
// timestamps are links which shouldn't be underlined
|
||||
> a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
padding-top: 0;
|
||||
|
||||
> * {
|
||||
margin-right: $right-padding;
|
||||
}
|
||||
|
||||
> .mx_EventTile_msgOption {
|
||||
order: 4;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
> .mx_SenderProfile {
|
||||
order: 2;
|
||||
flex-shrink: 0;
|
||||
width: var(--name-width);
|
||||
text-overflow: ellipsis;
|
||||
text-align: right;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
overflow: visible;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.mx_EventTile_line, .mx_EventTile_reply {
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
order: 3;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
> .mx_EventTile_avatar {
|
||||
order: 1;
|
||||
position: relative;
|
||||
top: 0;
|
||||
left: 0;
|
||||
flex-shrink: 0;
|
||||
height: $irc-line-height;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
// Need to use important to override the js provided height and width values.
|
||||
> .mx_BaseAvatar, .mx_BaseAvatar > * {
|
||||
height: $font-14px !important;
|
||||
width: $font-14px !important;
|
||||
font-size: $font-10px !important;
|
||||
line-height: $font-15px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_MessageTimestamp {
|
||||
font-size: $font-10px;
|
||||
width: $timestamp-width;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.mx_EventTile_e2eIcon {
|
||||
position: relative;
|
||||
right: unset;
|
||||
left: unset;
|
||||
top: -2px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.mx_EventTile_line {
|
||||
.mx_EventTile_e2eIcon,
|
||||
.mx_TextualEvent,
|
||||
.mx_MTextBody,
|
||||
.mx_ReplyThread_wrapper_empty {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_EvenTile_line .mx_MessageActionBar,
|
||||
.mx_EvenTile_line .mx_ReplyThread_wrapper {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.mx_EventTile_reply {
|
||||
order: 3;
|
||||
}
|
||||
|
||||
.mx_EditMessageComposer_buttons {
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_EventTile_emote {
|
||||
> .mx_EventTile_avatar {
|
||||
margin-left: calc(var(--name-width) + $icon-width + $right-padding);
|
||||
}
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.mx_EventListSummary {
|
||||
> .mx_EventTile_line {
|
||||
padding-left: calc(var(--name-width) + $icon-width + $timestamp-width + 3 * $right-padding); // 15 px of padding
|
||||
}
|
||||
|
||||
.mx_EventListSummary_avatars {
|
||||
padding: 0;
|
||||
margin: 0 9px 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_EventTile.mx_EventTile_info {
|
||||
.mx_EventTile_avatar {
|
||||
left: calc(var(--name-width) + 10px + $icon-width);
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.mx_EventTile_line {
|
||||
left: calc(var(--name-width) + 10px + $icon-width);
|
||||
}
|
||||
|
||||
.mx_TextualEvent {
|
||||
line-height: $irc-line-height;
|
||||
}
|
||||
}
|
||||
|
||||
// Suppress highlight thing from the normal Layout.
|
||||
.mx_EventTile:hover.mx_EventTile_verified .mx_EventTile_line,
|
||||
.mx_EventTile:hover.mx_EventTile_unverified .mx_EventTile_line,
|
||||
.mx_EventTile:hover.mx_EventTile_unknown .mx_EventTile_line {
|
||||
padding-left: 0;
|
||||
border-left: 0;
|
||||
}
|
||||
|
||||
.mx_SenderProfile_hover {
|
||||
background-color: $primary-bg-color;
|
||||
overflow: hidden;
|
||||
|
||||
> span {
|
||||
display: flex;
|
||||
|
||||
> .mx_SenderProfile_name {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mx_SenderProfile:hover {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.mx_SenderProfile_hover:hover {
|
||||
overflow: visible;
|
||||
width: max(auto, 100%);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.mx_ReplyThread {
|
||||
margin: 0;
|
||||
.mx_SenderProfile {
|
||||
width: unset;
|
||||
max-width: var(--name-width);
|
||||
}
|
||||
}
|
||||
|
||||
.mx_ProfileResizer {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 15px;
|
||||
left: calc(80px + var(--name-width));
|
||||
cursor: col-resize;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
// Need to use important to override the js provided height and width values.
|
||||
.mx_Flair > img {
|
||||
height: $font-14px !important;
|
||||
width: $font-14px !important;
|
||||
}
|
||||
}
|
|
@ -29,6 +29,7 @@ import SettingsStore from '../../settings/SettingsStore';
|
|||
import {_t} from "../../languageHandler";
|
||||
import {haveTileForEvent} from "../views/rooms/EventTile";
|
||||
import {textForEvent} from "../../TextForEvent";
|
||||
import IRCTimelineProfileResizer from "../views/elements/IRCTimelineProfileResizer";
|
||||
|
||||
const CONTINUATION_MAX_INTERVAL = 5 * 60 * 1000; // 5 minutes
|
||||
const continuedTypes = ['m.sticker', 'm.room.message'];
|
||||
|
@ -109,14 +110,16 @@ export default class MessagePanel extends React.Component {
|
|||
showReactions: PropTypes.bool,
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
// Force props to be loaded for useIRCLayout
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
// previous positions the read marker has been in, so we can
|
||||
// display 'ghost' read markers that are animating away
|
||||
ghostReadMarkers: [],
|
||||
showTypingNotifications: SettingsStore.getValue("showTypingNotifications"),
|
||||
useIRCLayout: this.useIRCLayout(SettingsStore.getValue("feature_irc_ui")),
|
||||
};
|
||||
|
||||
// opaque readreceipt info for each userId; used by ReadReceiptMarker
|
||||
|
@ -169,6 +172,8 @@ export default class MessagePanel extends React.Component {
|
|||
|
||||
this._showTypingNotificationsWatcherRef =
|
||||
SettingsStore.watchSetting("showTypingNotifications", null, this.onShowTypingNotificationsChange);
|
||||
|
||||
this._layoutWatcherRef = SettingsStore.watchSetting("feature_irc_ui", null, this.onLayoutChange);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
@ -178,6 +183,7 @@ export default class MessagePanel extends React.Component {
|
|||
componentWillUnmount() {
|
||||
this._isMounted = false;
|
||||
SettingsStore.unwatchSetting(this._showTypingNotificationsWatcherRef);
|
||||
SettingsStore.unwatchSetting(this._layoutWatcherRef);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
|
@ -196,6 +202,17 @@ export default class MessagePanel extends React.Component {
|
|||
});
|
||||
};
|
||||
|
||||
onLayoutChange = () => {
|
||||
this.setState({
|
||||
useIRCLayout: this.useIRCLayout(SettingsStore.getValue("feature_irc_ui")),
|
||||
});
|
||||
}
|
||||
|
||||
useIRCLayout(ircLayoutSelected) {
|
||||
// if room is null we are not in a normal room list
|
||||
return ircLayoutSelected && this.props.room;
|
||||
}
|
||||
|
||||
/* get the DOM node representing the given event */
|
||||
getNodeForEventId(eventId) {
|
||||
if (!this.eventNodes) {
|
||||
|
@ -597,6 +614,7 @@ export default class MessagePanel extends React.Component {
|
|||
isSelectedEvent={highlight}
|
||||
getRelationsForEvent={this.props.getRelationsForEvent}
|
||||
showReactions={this.props.showReactions}
|
||||
useIRCLayout={this.state.useIRCLayout}
|
||||
/>
|
||||
</TileErrorBoundary>
|
||||
</li>,
|
||||
|
@ -779,6 +797,8 @@ export default class MessagePanel extends React.Component {
|
|||
this.props.className,
|
||||
{
|
||||
"mx_MessagePanel_alwaysShowTimestamps": this.props.alwaysShowTimestamps,
|
||||
"mx_IRCLayout": this.state.useIRCLayout,
|
||||
"mx_GroupLayout": !this.state.useIRCLayout,
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -792,6 +812,15 @@ export default class MessagePanel extends React.Component {
|
|||
);
|
||||
}
|
||||
|
||||
let ircResizer = null;
|
||||
if (this.state.useIRCLayout) {
|
||||
ircResizer = <IRCTimelineProfileResizer
|
||||
minWidth={20}
|
||||
maxWidth={600}
|
||||
roomId={this.props.room ? this.props.roomroomId : null}
|
||||
/>;
|
||||
}
|
||||
|
||||
return (
|
||||
<ErrorBoundary>
|
||||
<ScrollPanel
|
||||
|
@ -804,6 +833,7 @@ export default class MessagePanel extends React.Component {
|
|||
style={style}
|
||||
stickyBottom={this.props.stickyBottom}
|
||||
resizeNotifier={this.props.resizeNotifier}
|
||||
fixedChildren={ircResizer}
|
||||
>
|
||||
{ topSpinner }
|
||||
{ this._getEventTiles() }
|
||||
|
|
|
@ -144,6 +144,11 @@ export default createReactClass({
|
|||
/* resizeNotifier: ResizeNotifier to know when middle column has changed size
|
||||
*/
|
||||
resizeNotifier: PropTypes.object,
|
||||
|
||||
/* fixedChildren: allows for children to be passed which are rendered outside
|
||||
* of the wrapper
|
||||
*/
|
||||
fixedChildren: PropTypes.node,
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
|
@ -881,6 +886,7 @@ export default createReactClass({
|
|||
return (<AutoHideScrollbar wrappedRef={this._collectScroll}
|
||||
onScroll={this.onScroll}
|
||||
className={`mx_ScrollPanel ${this.props.className}`} style={this.props.style}>
|
||||
{ this.props.fixedChildren }
|
||||
<div className="mx_RoomView_messageListWrapper">
|
||||
<ol ref={this._itemlist} className="mx_RoomView_MessageList" aria-live="polite" role="list">
|
||||
{ this.props.children }
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
interface IProps {
|
||||
className: string,
|
||||
dragFunc: (currentLocation: ILocationState, event: MouseEvent) => ILocationState,
|
||||
onMouseUp: (event: MouseEvent) => void,
|
||||
}
|
||||
|
||||
interface IState {
|
||||
onMouseMove: (event: MouseEvent) => void,
|
||||
onMouseUp: (event: MouseEvent) => void,
|
||||
location: ILocationState,
|
||||
}
|
||||
|
||||
export interface ILocationState {
|
||||
currentX: number,
|
||||
currentY: number,
|
||||
}
|
||||
|
||||
export default class Draggable extends React.Component<IProps, IState> {
|
||||
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
onMouseMove: this.onMouseMove.bind(this),
|
||||
onMouseUp: this.onMouseUp.bind(this),
|
||||
location: {
|
||||
currentX: 0,
|
||||
currentY: 0,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private onMouseDown = (event: MouseEvent): void => {
|
||||
this.setState({
|
||||
location: {
|
||||
currentX: event.clientX,
|
||||
currentY: event.clientY,
|
||||
},
|
||||
});
|
||||
|
||||
document.addEventListener("mousemove", this.state.onMouseMove);
|
||||
document.addEventListener("mouseup", this.state.onMouseUp);
|
||||
console.log("Mouse down")
|
||||
}
|
||||
|
||||
private onMouseUp = (event: MouseEvent): void => {
|
||||
document.removeEventListener("mousemove", this.state.onMouseMove);
|
||||
document.removeEventListener("mouseup", this.state.onMouseUp);
|
||||
this.props.onMouseUp(event);
|
||||
console.log("Mouse up")
|
||||
}
|
||||
|
||||
private onMouseMove(event: MouseEvent): void {
|
||||
console.log("Mouse Move")
|
||||
const newLocation = this.props.dragFunc(this.state.location, event);
|
||||
|
||||
this.setState({
|
||||
location: newLocation,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div className={this.props.className} onMouseDown={this.onMouseDown.bind(this)} />
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
||||
import Draggable, {ILocationState} from './Draggable';
|
||||
|
||||
interface IProps {
|
||||
// Current room
|
||||
roomId: string,
|
||||
minWidth: number,
|
||||
maxWidth: number,
|
||||
};
|
||||
|
||||
interface IState {
|
||||
width: number,
|
||||
IRCLayoutRoot: HTMLElement,
|
||||
};
|
||||
|
||||
export default class IRCTimelineProfileResizer extends React.Component<IProps, IState> {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
width: SettingsStore.getValue("ircDisplayNameWidth", this.props.roomId),
|
||||
IRCLayoutRoot: null,
|
||||
}
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.setState({
|
||||
IRCLayoutRoot: document.querySelector(".mx_IRCLayout") as HTMLElement,
|
||||
}, () => this.updateCSSWidth(this.state.width))
|
||||
}
|
||||
|
||||
private dragFunc = (location: ILocationState, event: React.MouseEvent<Element, MouseEvent>): ILocationState => {
|
||||
const offset = event.clientX - location.currentX;
|
||||
const newWidth = this.state.width + offset;
|
||||
|
||||
console.log({offset})
|
||||
// If we're trying to go smaller than min width, don't.
|
||||
if (newWidth < this.props.minWidth) {
|
||||
return location;
|
||||
}
|
||||
|
||||
if (newWidth > this.props.maxWidth) {
|
||||
return location;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
width: newWidth,
|
||||
});
|
||||
|
||||
this.updateCSSWidth.bind(this)(newWidth);
|
||||
|
||||
return {
|
||||
currentX: event.clientX,
|
||||
currentY: location.currentY,
|
||||
}
|
||||
}
|
||||
|
||||
private updateCSSWidth(newWidth: number) {
|
||||
this.state.IRCLayoutRoot.style.setProperty("--name-width", newWidth + "px");
|
||||
}
|
||||
|
||||
private onMoueUp(event: MouseEvent) {
|
||||
if (this.props.roomId) {
|
||||
SettingsStore.setValue("ircDisplayNameWidth", this.props.roomId, SettingLevel.ROOM_DEVICE, this.state.width);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return <Draggable className="mx_ProfileResizer" dragFunc={this.dragFunc.bind(this)} onMouseUp={this.onMoueUp.bind(this)}/>
|
||||
}
|
||||
};
|
|
@ -37,6 +37,8 @@ export default class ReplyThread extends React.Component {
|
|||
// called when the ReplyThread contents has changed, including EventTiles thereof
|
||||
onHeightChanged: PropTypes.func.isRequired,
|
||||
permalinkCreator: PropTypes.instanceOf(RoomPermalinkCreator).isRequired,
|
||||
// Specifies which layout to use.
|
||||
useIRCLayout: PropTypes.bool,
|
||||
};
|
||||
|
||||
static contextType = MatrixClientContext;
|
||||
|
@ -176,12 +178,17 @@ export default class ReplyThread extends React.Component {
|
|||
};
|
||||
}
|
||||
|
||||
static makeThread(parentEv, onHeightChanged, permalinkCreator, ref) {
|
||||
static makeThread(parentEv, onHeightChanged, permalinkCreator, ref, useIRCLayout) {
|
||||
if (!ReplyThread.getParentEventId(parentEv)) {
|
||||
return <div />;
|
||||
return <div className="mx_ReplyThread_wrapper_empty" />;
|
||||
}
|
||||
return <ReplyThread parentEv={parentEv} onHeightChanged={onHeightChanged}
|
||||
ref={ref} permalinkCreator={permalinkCreator} />;
|
||||
return <ReplyThread
|
||||
parentEv={parentEv}
|
||||
onHeightChanged={onHeightChanged}
|
||||
ref={ref}
|
||||
permalinkCreator={permalinkCreator}
|
||||
useIRCLayout={useIRCLayout}
|
||||
/>;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
@ -331,11 +338,13 @@ export default class ReplyThread extends React.Component {
|
|||
onHeightChanged={this.props.onHeightChanged}
|
||||
permalinkCreator={this.props.permalinkCreator}
|
||||
isRedacted={ev.isRedacted()}
|
||||
isTwelveHour={SettingsStore.getValue("showTwelveHourTimestamps")} />
|
||||
isTwelveHour={SettingsStore.getValue("showTwelveHourTimestamps")}
|
||||
useIRCLayout={this.props.useIRCLayout}
|
||||
/>
|
||||
</blockquote>;
|
||||
});
|
||||
|
||||
return <div>
|
||||
return <div className="mx_ReplyThread_wrapper">
|
||||
<div>{ header }</div>
|
||||
<div>{ evTiles }</div>
|
||||
</div>;
|
||||
|
|
|
@ -131,7 +131,9 @@ export default createReactClass({
|
|||
|
||||
return (
|
||||
<div className="mx_SenderProfile" dir="auto" onClick={this.props.onClick}>
|
||||
{ content }
|
||||
<div className="mx_SenderProfile_hover">
|
||||
{ content }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -206,6 +206,9 @@ export default createReactClass({
|
|||
|
||||
// whether to show reactions for this event
|
||||
showReactions: PropTypes.bool,
|
||||
|
||||
// whether to use the irc layout
|
||||
useIRCLayout: PropTypes.bool,
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
|
@ -695,6 +698,9 @@ export default createReactClass({
|
|||
// joins/parts/etc
|
||||
avatarSize = 14;
|
||||
needsSenderProfile = false;
|
||||
} else if (this.props.useIRCLayout) {
|
||||
avatarSize = 14;
|
||||
needsSenderProfile = true;
|
||||
} else if (this.props.continuation && this.props.tileShape !== "file_grid") {
|
||||
// no avatar or sender profile for continuation messages
|
||||
avatarSize = 0;
|
||||
|
@ -786,6 +792,17 @@ export default createReactClass({
|
|||
/>;
|
||||
}
|
||||
|
||||
const linkedTimestamp = <a
|
||||
href={permalink}
|
||||
onClick={this.onPermalinkClicked}
|
||||
aria-label={formatTime(new Date(this.props.mxEvent.getTs()), this.props.isTwelveHour)}
|
||||
>
|
||||
{ timestamp }
|
||||
</a>;
|
||||
|
||||
const groupTimestamp = !this.props.useIRCLayout ? linkedTimestamp : null;
|
||||
const ircTimestamp = this.props.useIRCLayout ? linkedTimestamp : null;
|
||||
|
||||
switch (this.props.tileShape) {
|
||||
case 'notif': {
|
||||
const room = this.context.getRoom(this.props.mxEvent.getRoomId());
|
||||
|
@ -853,12 +870,11 @@ export default createReactClass({
|
|||
}
|
||||
return (
|
||||
<div className={classes}>
|
||||
{ ircTimestamp }
|
||||
{ avatar }
|
||||
{ sender }
|
||||
<div className="mx_EventTile_reply">
|
||||
<a href={permalink} onClick={this.onPermalinkClicked}>
|
||||
{ timestamp }
|
||||
</a>
|
||||
{ groupTimestamp }
|
||||
{ !isBubbleMessage && this._renderE2EPadlock() }
|
||||
{ thread }
|
||||
<EventTileType ref={this._tile}
|
||||
|
@ -877,22 +893,19 @@ export default createReactClass({
|
|||
this.props.onHeightChanged,
|
||||
this.props.permalinkCreator,
|
||||
this._replyThread,
|
||||
this.props.useIRCLayout,
|
||||
);
|
||||
|
||||
// tab-index=-1 to allow it to be focusable but do not add tab stop for it, primarily for screen readers
|
||||
return (
|
||||
<div className={classes} tabIndex={-1}>
|
||||
{ ircTimestamp }
|
||||
<div className="mx_EventTile_msgOption">
|
||||
{ readAvatars }
|
||||
</div>
|
||||
{ sender }
|
||||
<div className="mx_EventTile_line">
|
||||
<a
|
||||
href={permalink}
|
||||
onClick={this.onPermalinkClicked}
|
||||
aria-label={formatTime(new Date(this.props.mxEvent.getTs()), this.props.isTwelveHour)}
|
||||
>
|
||||
{ timestamp }
|
||||
</a>
|
||||
{ groupTimestamp }
|
||||
{ !isBubbleMessage && this._renderE2EPadlock() }
|
||||
{ thread }
|
||||
<EventTileType ref={this._tile}
|
||||
|
|
|
@ -381,7 +381,7 @@ export default class MessageComposer extends React.Component {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="mx_MessageComposer">
|
||||
<div className="mx_MessageComposer mx_GroupLayout">
|
||||
<div className="mx_MessageComposer_wrapper">
|
||||
<div className="mx_MessageComposer_row">
|
||||
{ controls }
|
||||
|
|
|
@ -407,6 +407,7 @@
|
|||
"Multiple integration managers": "Multiple integration managers",
|
||||
"Try out new ways to ignore people (experimental)": "Try out new ways to ignore people (experimental)",
|
||||
"Support adding custom themes": "Support adding custom themes",
|
||||
"Use IRC layout": "Use IRC layout",
|
||||
"Enable cross-signing to verify per-user instead of per-session": "Enable cross-signing to verify per-user instead of per-session",
|
||||
"Show info about bridges in room settings": "Show info about bridges in room settings",
|
||||
"Enable Emoji suggestions while typing": "Enable Emoji suggestions while typing",
|
||||
|
@ -453,6 +454,7 @@
|
|||
"Keep recovery passphrase in memory for this session": "Keep recovery passphrase in memory for this session",
|
||||
"How fast should messages be downloaded.": "How fast should messages be downloaded.",
|
||||
"Manually verify all remote sessions": "Manually verify all remote sessions",
|
||||
"IRC display name width": "IRC display name width",
|
||||
"Collecting app version information": "Collecting app version information",
|
||||
"Collecting logs": "Collecting logs",
|
||||
"Uploading report": "Uploading report",
|
||||
|
|
|
@ -137,6 +137,12 @@ export const SETTINGS = {
|
|||
supportedLevels: LEVELS_FEATURE,
|
||||
default: false,
|
||||
},
|
||||
"feature_irc_ui": {
|
||||
supportedLevels: LEVELS_ACCOUNT_SETTINGS,
|
||||
displayName: _td('Use IRC layout'),
|
||||
default: false,
|
||||
isFeature: true,
|
||||
},
|
||||
"mjolnirRooms": {
|
||||
supportedLevels: ['account'],
|
||||
default: [],
|
||||
|
@ -519,4 +525,11 @@ export const SETTINGS = {
|
|||
MatrixClient.prototype.setCryptoTrustCrossSignedDevices, true,
|
||||
),
|
||||
},
|
||||
"ircDisplayNameWidth": {
|
||||
// We specifically want to have room-device > device so that users may set a device default
|
||||
// with a per-room override.
|
||||
supportedLevels: ['room-device', 'device'],
|
||||
displayName: _td("IRC display name width"),
|
||||
default: 80,
|
||||
},
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue