Merge branch 'travis/room-list/css-layout' into travis/room-list/breadcrumbs
This commit is contained in:
commit
17d98e8956
15 changed files with 443 additions and 159 deletions
|
@ -12,6 +12,7 @@
|
||||||
@import "./structures/_HeaderButtons.scss";
|
@import "./structures/_HeaderButtons.scss";
|
||||||
@import "./structures/_HomePage.scss";
|
@import "./structures/_HomePage.scss";
|
||||||
@import "./structures/_LeftPanel.scss";
|
@import "./structures/_LeftPanel.scss";
|
||||||
|
@import "./structures/_LeftPanel2.scss";
|
||||||
@import "./structures/_MainSplit.scss";
|
@import "./structures/_MainSplit.scss";
|
||||||
@import "./structures/_MatrixChat.scss";
|
@import "./structures/_MatrixChat.scss";
|
||||||
@import "./structures/_MyGroups.scss";
|
@import "./structures/_MyGroups.scss";
|
||||||
|
@ -177,10 +178,12 @@
|
||||||
@import "./views/rooms/_RoomDropTarget.scss";
|
@import "./views/rooms/_RoomDropTarget.scss";
|
||||||
@import "./views/rooms/_RoomHeader.scss";
|
@import "./views/rooms/_RoomHeader.scss";
|
||||||
@import "./views/rooms/_RoomList.scss";
|
@import "./views/rooms/_RoomList.scss";
|
||||||
|
@import "./views/rooms/_RoomList2.scss";
|
||||||
@import "./views/rooms/_RoomPreviewBar.scss";
|
@import "./views/rooms/_RoomPreviewBar.scss";
|
||||||
@import "./views/rooms/_RoomRecoveryReminder.scss";
|
@import "./views/rooms/_RoomRecoveryReminder.scss";
|
||||||
@import "./views/rooms/_RoomSublist2.scss";
|
@import "./views/rooms/_RoomSublist2.scss";
|
||||||
@import "./views/rooms/_RoomTile.scss";
|
@import "./views/rooms/_RoomTile.scss";
|
||||||
|
@import "./views/rooms/_RoomTile2.scss";
|
||||||
@import "./views/rooms/_RoomUpgradeWarningBar.scss";
|
@import "./views/rooms/_RoomUpgradeWarningBar.scss";
|
||||||
@import "./views/rooms/_SearchBar.scss";
|
@import "./views/rooms/_SearchBar.scss";
|
||||||
@import "./views/rooms/_SendMessageComposer.scss";
|
@import "./views/rooms/_SendMessageComposer.scss";
|
||||||
|
|
|
@ -23,14 +23,6 @@ limitations under the License.
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Remove temporary indicator of new room list implementation.
|
|
||||||
// This border is meant to visually distinguish between the two components when the
|
|
||||||
// user has turned on the new room list implementation, at least until the designs
|
|
||||||
// themselves give it away.
|
|
||||||
.mx_LeftPanel2 .mx_LeftPanel {
|
|
||||||
border-left: 5px #e26dff solid;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_LeftPanel_container.collapsed {
|
.mx_LeftPanel_container.collapsed {
|
||||||
min-width: unset;
|
min-width: unset;
|
||||||
/* Collapsed LeftPanel 50px */
|
/* Collapsed LeftPanel 50px */
|
||||||
|
|
94
res/css/structures/_LeftPanel2.scss
Normal file
94
res/css/structures/_LeftPanel2.scss
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO: Rename to mx_LeftPanel during replacement of old component
|
||||||
|
|
||||||
|
// TODO: Put these variables in the right place, or namespace them.
|
||||||
|
$tagPanelWidth: 70px;
|
||||||
|
$roomListMinimizedWidth: 50px;
|
||||||
|
|
||||||
|
.mx_LeftPanel2 {
|
||||||
|
background-color: $header-panel-bg-color;
|
||||||
|
min-width: 260px;
|
||||||
|
max-width: 50%;
|
||||||
|
|
||||||
|
// Create a row-based flexbox for the TagPanel and the room list
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.mx_LeftPanel2_tagPanelContainer {
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
flex-basis: $tagPanelWidth;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
// Create another flexbox so the TagPanel fills the container
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
// TagPanel handles its own CSS
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: The 'room list' in this context is actually everything that isn't the tag
|
||||||
|
// panel, such as the menu options, breadcrumbs, filtering, etc
|
||||||
|
.mx_LeftPanel2_roomListContainer {
|
||||||
|
width: calc(100% - $tagPanelWidth);
|
||||||
|
|
||||||
|
// Create another flexbox (this time a column) for the room list components
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.mx_LeftPanel2_userHeader {
|
||||||
|
padding: 14px 12px 20px; // 14px top, 12px sides, 20px bottom
|
||||||
|
|
||||||
|
// Create another flexbox column for the rows to stack within
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
// There's 2 rows when breadcrumbs are present: the top bit and the breadcrumbs
|
||||||
|
.mx_LeftPanel2_headerRow {
|
||||||
|
// Create yet another flexbox, this time within the row, to ensure items stay
|
||||||
|
// aligned correctly. This is also a row-based flexbox.
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_LeftPanel2_userAvatarContainer {
|
||||||
|
position: relative; // to make default avatars work
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_LeftPanel2_userName {
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: $font-15px;
|
||||||
|
line-height: $font-20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_LeftPanel2_breadcrumbsContainer {
|
||||||
|
// TODO: Improve CSS for breadcrumbs (currently shoved into the view rather than placed)
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_LeftPanel2_filterContainer {
|
||||||
|
// TODO: Improve CSS for filtering and its input
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_LeftPanel2_actualRoomListContainer {
|
||||||
|
flex-grow: 1; // fill the available space
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -66,7 +66,7 @@ limitations under the License.
|
||||||
}
|
}
|
||||||
|
|
||||||
/* not the left panel, and not the resize handle, so the roomview/groupview/... */
|
/* not the left panel, and not the resize handle, so the roomview/groupview/... */
|
||||||
.mx_MatrixChat > :not(.mx_LeftPanel_container):not(.mx_ResizeHandle) {
|
.mx_MatrixChat > :not(.mx_LeftPanel_container):not(.mx_LeftPanel2):not(.mx_ResizeHandle) {
|
||||||
background-color: $primary-bg-color;
|
background-color: $primary-bg-color;
|
||||||
|
|
||||||
flex: 1 1 0;
|
flex: 1 1 0;
|
||||||
|
|
25
res/css/views/rooms/_RoomList2.scss
Normal file
25
res/css/views/rooms/_RoomList2.scss
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO: Rename to mx_RoomList during replacement of old component
|
||||||
|
|
||||||
|
.mx_RoomList2 {
|
||||||
|
// Create a column-based flexbox for the sublists. That's pretty much all we have to
|
||||||
|
// worry about in this stylesheet.
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
|
@ -14,8 +14,42 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// TODO: Rename to mx_RoomSublist during replacement of old component
|
||||||
|
|
||||||
|
// TODO: Just use the 3 selectors we need from this instead of importing it.
|
||||||
|
// We're going to end up with heavy modifications anyways.
|
||||||
@import "../../../../node_modules/react-resizable/css/styles.css";
|
@import "../../../../node_modules/react-resizable/css/styles.css";
|
||||||
|
|
||||||
.mx_RoomList2 .mx_RoomSubList_labelContainer {
|
.mx_RoomSublist2 {
|
||||||
z-index: 12;
|
// The sublist is a column of rows, essentially
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
margin-left: 8px;
|
||||||
|
margin-top: 12px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
|
||||||
|
.mx_RoomSublist2_headerContainer {
|
||||||
|
text-transform: uppercase;
|
||||||
|
opacity: 0.5;
|
||||||
|
line-height: $font-16px;
|
||||||
|
font-size: $font-12px;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_RoomSublist2_resizeBox {
|
||||||
|
// Create another flexbox column for the tiles
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.mx_RoomSublist2_showMoreButton {
|
||||||
|
height: 44px; // 1 room tile high
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
// We create a flexbox to cheat at alignment
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
103
res/css/views/rooms/_RoomTile2.scss
Normal file
103
res/css/views/rooms/_RoomTile2.scss
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO: Rename to mx_RoomTile during replacement of old component
|
||||||
|
|
||||||
|
// Note: the room tile expects to be in a flexbox column container
|
||||||
|
.mx_RoomTile2 {
|
||||||
|
width: calc(100% - 11px); // 8px for padding (4px on either side), 3px for margin
|
||||||
|
margin-bottom: 4px;
|
||||||
|
margin-right: 3px;
|
||||||
|
padding: 4px;
|
||||||
|
|
||||||
|
// The tile is also a flexbox row itself
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
&.mx_RoomTile2_selected {
|
||||||
|
background-color: $roomtile2-selected-bg-color;
|
||||||
|
border-radius: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_RoomTile2_avatarContainer {
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_RoomTile2_nameContainer {
|
||||||
|
// Create a new column layout flexbox for the name parts
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.mx_RoomTile2_name,
|
||||||
|
.mx_RoomTile2_messagePreview {
|
||||||
|
margin: 0 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Ellipsis on the name and preview
|
||||||
|
|
||||||
|
.mx_RoomTile2_name {
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: $font-14px;
|
||||||
|
line-height: $font-19px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_RoomTile2_messagePreview {
|
||||||
|
font-size: $font-13px;
|
||||||
|
line-height: $font-18px;
|
||||||
|
color: $roomtile2-preview-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_RoomTile2_badgeContainer {
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
// Create another flexbox row because it's super easy to position the badge at
|
||||||
|
// the end this way.
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
.mx_RoomTile2_badge {
|
||||||
|
background-color: $roomtile2-badge-color;
|
||||||
|
|
||||||
|
&:not(.mx_RoomTile2_badgeEmpty) {
|
||||||
|
border-radius: 16px;
|
||||||
|
font-size: $font-10px;
|
||||||
|
line-height: $font-14px;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-right: 14px;
|
||||||
|
color: #fff; // TODO: Variable
|
||||||
|
|
||||||
|
// TODO: Confirm padding on counted badges
|
||||||
|
padding: 2px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.mx_RoomTile2_badgeEmpty {
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
border-radius: 6px;
|
||||||
|
margin-right: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.mx_RoomTile2_badgeHighlight {
|
||||||
|
// TODO: Use a more specific variable
|
||||||
|
background-color: $warning-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -172,6 +172,12 @@ $header-divider-color: #91A1C0;
|
||||||
|
|
||||||
// ********************
|
// ********************
|
||||||
|
|
||||||
|
// TODO: Update variables for new room list
|
||||||
|
// TODO: Dark theme
|
||||||
|
$roomtile2-preview-color: #9e9e9e;
|
||||||
|
$roomtile2-badge-color: #61708b;
|
||||||
|
$roomtile2-selected-bg-color: #FFF;
|
||||||
|
|
||||||
$roomtile-name-color: #61708b;
|
$roomtile-name-color: #61708b;
|
||||||
$roomtile-badge-fg-color: $accent-fg-color;
|
$roomtile-badge-fg-color: $accent-fg-color;
|
||||||
$roomtile-selected-color: #212121;
|
$roomtile-selected-color: #212121;
|
||||||
|
|
|
@ -27,7 +27,7 @@ import RoomViewStore from './stores/RoomViewStore';
|
||||||
*/
|
*/
|
||||||
class ActiveRoomObserver {
|
class ActiveRoomObserver {
|
||||||
constructor() {
|
constructor() {
|
||||||
this._listeners = {};
|
this._listeners = {}; // key=roomId, value=function(isActive:boolean)
|
||||||
|
|
||||||
this._activeRoomId = RoomViewStore.getRoomId();
|
this._activeRoomId = RoomViewStore.getRoomId();
|
||||||
// TODO: We could self-destruct when the last listener goes away, or at least
|
// TODO: We could self-destruct when the last listener goes away, or at least
|
||||||
|
@ -35,6 +35,10 @@ class ActiveRoomObserver {
|
||||||
this._roomStoreToken = RoomViewStore.addListener(this._onRoomViewStoreUpdate.bind(this));
|
this._roomStoreToken = RoomViewStore.addListener(this._onRoomViewStoreUpdate.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get activeRoomId(): string {
|
||||||
|
return this._activeRoomId;
|
||||||
|
}
|
||||||
|
|
||||||
addListener(roomId, listener) {
|
addListener(roomId, listener) {
|
||||||
if (!this._listeners[roomId]) this._listeners[roomId] = [];
|
if (!this._listeners[roomId]) this._listeners[roomId] = [];
|
||||||
this._listeners[roomId].push(listener);
|
this._listeners[roomId].push(listener);
|
||||||
|
@ -51,23 +55,23 @@ class ActiveRoomObserver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_emit(roomId) {
|
_emit(roomId, isActive: boolean) {
|
||||||
if (!this._listeners[roomId]) return;
|
if (!this._listeners[roomId]) return;
|
||||||
|
|
||||||
for (const l of this._listeners[roomId]) {
|
for (const l of this._listeners[roomId]) {
|
||||||
l.call();
|
l.call(null, isActive);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_onRoomViewStoreUpdate() {
|
_onRoomViewStoreUpdate() {
|
||||||
// emit for the old room ID
|
// emit for the old room ID
|
||||||
if (this._activeRoomId) this._emit(this._activeRoomId);
|
if (this._activeRoomId) this._emit(this._activeRoomId, false);
|
||||||
|
|
||||||
// update our cache
|
// update our cache
|
||||||
this._activeRoomId = RoomViewStore.getRoomId();
|
this._activeRoomId = RoomViewStore.getRoomId();
|
||||||
|
|
||||||
// and emit for the new one
|
// and emit for the new one
|
||||||
if (this._activeRoomId) this._emit(this._activeRoomId);
|
if (this._activeRoomId) this._emit(this._activeRoomId, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,9 @@ import SearchBox from "./SearchBox";
|
||||||
import RoomList2 from "../views/rooms/RoomList2";
|
import RoomList2 from "../views/rooms/RoomList2";
|
||||||
import TopLeftMenuButton from "./TopLeftMenuButton";
|
import TopLeftMenuButton from "./TopLeftMenuButton";
|
||||||
import { Action } from "../../dispatcher/actions";
|
import { Action } from "../../dispatcher/actions";
|
||||||
|
import { MatrixClientPeg } from "../../MatrixClientPeg";
|
||||||
|
import BaseAvatar from '../views/avatars/BaseAvatar';
|
||||||
|
import RoomBreadcrumbs from "../views/rooms/RoomBreadcrumbs";
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
* CAUTION *
|
* CAUTION *
|
||||||
|
@ -82,24 +85,53 @@ export default class LeftPanel2 extends React.Component<IProps, IState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private renderHeader(): React.ReactNode {
|
||||||
|
// TODO: Update when profile info changes
|
||||||
|
// TODO: Presence
|
||||||
|
// TODO: Breadcrumbs toggle
|
||||||
|
// TODO: Menu button
|
||||||
|
const avatarSize = 32;
|
||||||
|
// TODO: Don't do this profile lookup in render()
|
||||||
|
const client = MatrixClientPeg.get();
|
||||||
|
let displayName = client.getUserId();
|
||||||
|
let avatarUrl: string = null;
|
||||||
|
const myUser = client.getUser(client.getUserId());
|
||||||
|
if (myUser) {
|
||||||
|
displayName = myUser.rawDisplayName;
|
||||||
|
avatarUrl = myUser.avatarUrl;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className="mx_LeftPanel2_userHeader">
|
||||||
|
<div className="mx_LeftPanel2_headerRow">
|
||||||
|
<span className="mx_LeftPanel2_userAvatarContainer">
|
||||||
|
<BaseAvatar
|
||||||
|
idName={MatrixClientPeg.get().getUserId()}
|
||||||
|
name={displayName}
|
||||||
|
url={avatarUrl}
|
||||||
|
width={avatarSize}
|
||||||
|
height={avatarSize}
|
||||||
|
resizeMethod="crop"
|
||||||
|
className="mx_LeftPanel2_userAvatar"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span className="mx_LeftPanel2_userName">{displayName}</span>
|
||||||
|
</div>
|
||||||
|
<div className="mx_LeftPanel2_headerRow mx_LeftPanel2_breadcrumbsContainer">
|
||||||
|
<RoomBreadcrumbs />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public render(): React.ReactNode {
|
public render(): React.ReactNode {
|
||||||
const tagPanel = (
|
const tagPanel = (
|
||||||
<div className="mx_LeftPanel_tagPanelContainer">
|
<div className="mx_LeftPanel2_tagPanelContainer">
|
||||||
<TagPanel/>
|
<TagPanel/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const exploreButton = (
|
|
||||||
<div
|
|
||||||
className={classNames("mx_LeftPanel_explore", {"mx_LeftPanel_explore_hidden": this.state.searchExpanded})}>
|
|
||||||
<AccessibleButton onClick={() => dis.dispatch({action: 'view_room_directory'})}>
|
|
||||||
{_t("Explore")}
|
|
||||||
</AccessibleButton>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
const searchBox = (<SearchBox
|
const searchBox = (<SearchBox
|
||||||
className="mx_LeftPanel_filterRooms"
|
className="mx_LeftPanel2_filterRoomsSearch"
|
||||||
enableRoomSearchFocus={true}
|
enableRoomSearchFocus={true}
|
||||||
blurredPlaceholder={_t('Filter')}
|
blurredPlaceholder={_t('Filter')}
|
||||||
placeholder={_t('Filter rooms…')}
|
placeholder={_t('Filter rooms…')}
|
||||||
|
@ -124,29 +156,25 @@ export default class LeftPanel2 extends React.Component<IProps, IState> {
|
||||||
// TODO: Conference handling / calls
|
// TODO: Conference handling / calls
|
||||||
|
|
||||||
const containerClasses = classNames({
|
const containerClasses = classNames({
|
||||||
"mx_LeftPanel_container": true,
|
"mx_LeftPanel2": true,
|
||||||
"mx_fadable": true,
|
|
||||||
"collapsed": false, // TODO: Collapsed support
|
|
||||||
"mx_LeftPanel_container_hasTagPanel": true, // TODO: TagPanel support
|
|
||||||
"mx_fadable_faded": false,
|
|
||||||
"mx_LeftPanel2": true, // TODO: Remove flag when RoomList2 ships (used as an indicator)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={containerClasses}>
|
<div className={containerClasses}>
|
||||||
{tagPanel}
|
{tagPanel}
|
||||||
<aside className="mx_LeftPanel dark-panel">
|
<aside className="mx_LeftPanel2_roomListContainer">
|
||||||
<TopLeftMenuButton collapsed={false}/>
|
{this.renderHeader()}
|
||||||
<div
|
<div
|
||||||
className="mx_LeftPanel_exploreAndFilterRow"
|
className="mx_LeftPanel2_filterContainer"
|
||||||
onKeyDown={() => {/*TODO*/}}
|
onKeyDown={() => {/*TODO*/}}
|
||||||
onFocus={() => {/*TODO*/}}
|
onFocus={() => {/*TODO*/}}
|
||||||
onBlur={() => {/*TODO*/}}
|
onBlur={() => {/*TODO*/}}
|
||||||
>
|
>
|
||||||
{exploreButton}
|
|
||||||
{searchBox}
|
{searchBox}
|
||||||
</div>
|
</div>
|
||||||
{roomList}
|
<div className="mx_LeftPanel2_actualRoomListContainer">
|
||||||
|
{roomList}
|
||||||
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -96,7 +96,7 @@ const TAG_AESTHETICS: {
|
||||||
defaultHidden: false,
|
defaultHidden: false,
|
||||||
},
|
},
|
||||||
[DefaultTagID.DM]: {
|
[DefaultTagID.DM]: {
|
||||||
sectionLabel: _td("Direct Messages"),
|
sectionLabel: _td("People"),
|
||||||
isInvite: false,
|
isInvite: false,
|
||||||
defaultHidden: false,
|
defaultHidden: false,
|
||||||
addRoomLabel: _td("Start chat"),
|
addRoomLabel: _td("Start chat"),
|
||||||
|
@ -200,6 +200,7 @@ export default class RoomList2 extends React.Component<IProps, IState> {
|
||||||
addRoomLabel={aesthetics.addRoomLabel}
|
addRoomLabel={aesthetics.addRoomLabel}
|
||||||
isInvite={aesthetics.isInvite}
|
isInvite={aesthetics.isInvite}
|
||||||
layout={this.state.layouts.get(orderedTagId)}
|
layout={this.state.layouts.get(orderedTagId)}
|
||||||
|
showMessagePreviews={orderedTagId === DefaultTagID.DM}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -216,7 +217,7 @@ export default class RoomList2 extends React.Component<IProps, IState> {
|
||||||
onFocus={this.props.onFocus}
|
onFocus={this.props.onFocus}
|
||||||
onBlur={this.props.onBlur}
|
onBlur={this.props.onBlur}
|
||||||
onKeyDown={onKeyDownHandler}
|
onKeyDown={onKeyDownHandler}
|
||||||
className="mx_RoomList mx_RoomList2"
|
className="mx_RoomList2"
|
||||||
role="tree"
|
role="tree"
|
||||||
aria-label={_t("Rooms")}
|
aria-label={_t("Rooms")}
|
||||||
// Firefox sometimes makes this element focusable due to
|
// Firefox sometimes makes this element focusable due to
|
||||||
|
|
|
@ -20,15 +20,13 @@ import * as React from "react";
|
||||||
import { createRef } from "react";
|
import { createRef } from "react";
|
||||||
import { Room } from "matrix-js-sdk/src/models/room";
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import * as RoomNotifs from '../../../RoomNotifs';
|
|
||||||
import { RovingTabIndexWrapper } from "../../../accessibility/RovingTabIndex";
|
import { RovingTabIndexWrapper } from "../../../accessibility/RovingTabIndex";
|
||||||
import { _t } from "../../../languageHandler";
|
import { _t } from "../../../languageHandler";
|
||||||
import AccessibleButton from "../../views/elements/AccessibleButton";
|
import AccessibleButton from "../../views/elements/AccessibleButton";
|
||||||
import AccessibleTooltipButton from "../../views/elements/AccessibleTooltipButton";
|
|
||||||
import * as FormattingUtils from '../../../utils/FormattingUtils';
|
|
||||||
import RoomTile2 from "./RoomTile2";
|
import RoomTile2 from "./RoomTile2";
|
||||||
import { ResizableBox, ResizeCallbackData } from "react-resizable";
|
import { ResizableBox, ResizeCallbackData } from "react-resizable";
|
||||||
import { ListLayout } from "../../../stores/room-list/ListLayout";
|
import { ListLayout } from "../../../stores/room-list/ListLayout";
|
||||||
|
import { DefaultTagID, TagID } from "../../../stores/room-list/models";
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
* CAUTION *
|
* CAUTION *
|
||||||
|
@ -43,6 +41,7 @@ interface IProps {
|
||||||
rooms?: Room[];
|
rooms?: Room[];
|
||||||
startAsHidden: boolean;
|
startAsHidden: boolean;
|
||||||
label: string;
|
label: string;
|
||||||
|
showMessagePreviews: boolean;
|
||||||
onAddRoom?: () => void;
|
onAddRoom?: () => void;
|
||||||
addRoomLabel: string;
|
addRoomLabel: string;
|
||||||
isInvite: boolean;
|
isInvite: boolean;
|
||||||
|
@ -93,7 +92,13 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
if (this.props.rooms) {
|
if (this.props.rooms) {
|
||||||
for (const room of this.props.rooms) {
|
for (const room of this.props.rooms) {
|
||||||
tiles.push(<RoomTile2 room={room} key={`room-${room.roomId}`}/>);
|
tiles.push(
|
||||||
|
<RoomTile2
|
||||||
|
room={room}
|
||||||
|
key={`room-${room.roomId}`}
|
||||||
|
showMessagePreview={this.props.showMessagePreviews}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,25 +106,16 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderHeader(): React.ReactElement {
|
private renderHeader(): React.ReactElement {
|
||||||
const notifications = !this.props.isInvite
|
// TODO: Handle badge count
|
||||||
? RoomNotifs.aggregateNotificationCount(this.props.rooms)
|
// const notifications = !this.props.isInvite
|
||||||
: {count: 0, highlight: true};
|
// ? RoomNotifs.aggregateNotificationCount(this.props.rooms)
|
||||||
const notifCount = notifications.count;
|
// : {count: 0, highlight: true};
|
||||||
const notifHighlight = notifications.highlight;
|
// const notifCount = notifications.count;
|
||||||
|
// const notifHighlight = notifications.highlight;
|
||||||
|
|
||||||
// TODO: Title on collapsed
|
// TODO: Title on collapsed
|
||||||
// TODO: Incoming call box
|
// TODO: Incoming call box
|
||||||
|
|
||||||
let chevron = null;
|
|
||||||
if (this.hasTiles()) {
|
|
||||||
const chevronClasses = classNames({
|
|
||||||
'mx_RoomSubList_chevron': true,
|
|
||||||
'mx_RoomSubList_chevronRight': false, // isCollapsed
|
|
||||||
'mx_RoomSubList_chevronDown': true, // !isCollapsed
|
|
||||||
});
|
|
||||||
chevron = (<div className={chevronClasses}/>);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RovingTabIndexWrapper inputRef={this.headerButton}>
|
<RovingTabIndexWrapper inputRef={this.headerButton}>
|
||||||
{({onFocus, isActive, ref}) => {
|
{({onFocus, isActive, ref}) => {
|
||||||
|
@ -127,68 +123,68 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
|
||||||
const tabIndex = isActive ? 0 : -1;
|
const tabIndex = isActive ? 0 : -1;
|
||||||
|
|
||||||
// TODO: Collapsed state
|
// TODO: Collapsed state
|
||||||
let badge;
|
// TODO: Handle badge count
|
||||||
if (true) { // !isCollapsed
|
// let badge;
|
||||||
const badgeClasses = classNames({
|
// if (true) { // !isCollapsed
|
||||||
'mx_RoomSubList_badge': true,
|
// const showCount = localStorage.getItem("mx_rls_count") || notifHighlight;
|
||||||
'mx_RoomSubList_badgeHighlight': notifHighlight,
|
// const badgeClasses = classNames({
|
||||||
});
|
// 'mx_RoomSublist2_badge': true,
|
||||||
// Wrap the contents in a div and apply styles to the child div so that the browser default outline works
|
// 'mx_RoomSublist2_badgeHighlight': notifHighlight,
|
||||||
if (notifCount > 0) {
|
// 'mx_RoomSublist2_badgeEmpty': !showCount,
|
||||||
badge = (
|
// });
|
||||||
<AccessibleButton
|
// // Wrap the contents in a div and apply styles to the child div so that the browser default outline works
|
||||||
tabIndex={tabIndex}
|
// if (notifCount > 0) {
|
||||||
className={badgeClasses}
|
// const count = <div>{FormattingUtils.formatCount(notifCount)}</div>;
|
||||||
aria-label={_t("Jump to first unread room.")}
|
// badge = (
|
||||||
>
|
// <AccessibleButton
|
||||||
<div>
|
// tabIndex={tabIndex}
|
||||||
{FormattingUtils.formatCount(notifCount)}
|
// className={badgeClasses}
|
||||||
</div>
|
// aria-label={_t("Jump to first unread room.")}
|
||||||
</AccessibleButton>
|
// >
|
||||||
);
|
// {showCount ? count : null}
|
||||||
} else if (this.props.isInvite && this.hasTiles()) {
|
// </AccessibleButton>
|
||||||
// Render the `!` badge for invites
|
// );
|
||||||
badge = (
|
// } else if (this.props.isInvite && this.hasTiles()) {
|
||||||
<AccessibleButton
|
// // Render the `!` badge for invites
|
||||||
tabIndex={tabIndex}
|
// badge = (
|
||||||
className={badgeClasses}
|
// <AccessibleButton
|
||||||
aria-label={_t("Jump to first invite.")}
|
// tabIndex={tabIndex}
|
||||||
>
|
// className={badgeClasses}
|
||||||
<div>
|
// aria-label={_t("Jump to first invite.")}
|
||||||
{FormattingUtils.formatCount(this.numTiles)}
|
// >
|
||||||
</div>
|
// <div>
|
||||||
</AccessibleButton>
|
// {FormattingUtils.formatCount(this.numTiles)}
|
||||||
);
|
// </div>
|
||||||
}
|
// </AccessibleButton>
|
||||||
}
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
let addRoomButton = null;
|
// TODO: Aux button
|
||||||
if (!!this.props.onAddRoom) {
|
// let addRoomButton = null;
|
||||||
addRoomButton = (
|
// if (!!this.props.onAddRoom) {
|
||||||
<AccessibleTooltipButton
|
// addRoomButton = (
|
||||||
tabIndex={tabIndex}
|
// <AccessibleTooltipButton
|
||||||
onClick={this.onAddRoom}
|
// tabIndex={tabIndex}
|
||||||
className="mx_RoomSubList_addRoom"
|
// onClick={this.onAddRoom}
|
||||||
title={this.props.addRoomLabel || _t("Add room")}
|
// className="mx_RoomSublist2_addButton"
|
||||||
/>
|
// title={this.props.addRoomLabel || _t("Add room")}
|
||||||
);
|
// />
|
||||||
}
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
// TODO: a11y (see old component)
|
// TODO: a11y (see old component)
|
||||||
return (
|
return (
|
||||||
<div className={"mx_RoomSubList_labelContainer"}>
|
<div className={"mx_RoomSublist2_headerContainer"}>
|
||||||
<AccessibleButton
|
<AccessibleButton
|
||||||
inputRef={ref}
|
inputRef={ref}
|
||||||
tabIndex={tabIndex}
|
tabIndex={tabIndex}
|
||||||
className={"mx_RoomSubList_label"}
|
className={"mx_RoomSublist2_headerText"}
|
||||||
role="treeitem"
|
role="treeitem"
|
||||||
aria-level="1"
|
aria-level="1"
|
||||||
>
|
>
|
||||||
{chevron}
|
|
||||||
<span>{this.props.label}</span>
|
<span>{this.props.label}</span>
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
{badge}
|
|
||||||
{addRoomButton}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
@ -204,9 +200,8 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
const classes = classNames({
|
const classes = classNames({
|
||||||
// TODO: Proper collapse support
|
// TODO: Proper collapse support
|
||||||
'mx_RoomSubList': true,
|
'mx_RoomSublist2': true,
|
||||||
'mx_RoomSubList_hidden': false, // len && isCollapsed
|
'mx_RoomSublist2_collapsed': false, // len && isCollapsed
|
||||||
'mx_RoomSubList_nonEmpty': this.hasTiles(), // len && !isCollapsed
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let content = null;
|
let content = null;
|
||||||
|
@ -244,7 +239,7 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
|
||||||
visibleTiles.splice(visibleTiles.length - 1, 1, (
|
visibleTiles.splice(visibleTiles.length - 1, 1, (
|
||||||
<div
|
<div
|
||||||
onClick={this.onShowAllClick}
|
onClick={this.onShowAllClick}
|
||||||
style={{height: '34px', lineHeight: '34px', cursor: 'pointer'}}
|
className='mx_RoomSublist2_showMoreButton'
|
||||||
key='showall'
|
key='showall'
|
||||||
>
|
>
|
||||||
{_t("Show %(n)s more", {n: numMissing})}
|
{_t("Show %(n)s more", {n: numMissing})}
|
||||||
|
|
|
@ -23,7 +23,6 @@ import classNames from "classnames";
|
||||||
import { RovingTabIndexWrapper } from "../../../accessibility/RovingTabIndex";
|
import { RovingTabIndexWrapper } from "../../../accessibility/RovingTabIndex";
|
||||||
import AccessibleButton from "../../views/elements/AccessibleButton";
|
import AccessibleButton from "../../views/elements/AccessibleButton";
|
||||||
import RoomAvatar from "../../views/avatars/RoomAvatar";
|
import RoomAvatar from "../../views/avatars/RoomAvatar";
|
||||||
import Tooltip from "../../views/elements/Tooltip";
|
|
||||||
import dis from '../../../dispatcher/dispatcher';
|
import dis from '../../../dispatcher/dispatcher';
|
||||||
import { Key } from "../../../Keyboard";
|
import { Key } from "../../../Keyboard";
|
||||||
import * as RoomNotifs from '../../../RoomNotifs';
|
import * as RoomNotifs from '../../../RoomNotifs';
|
||||||
|
@ -32,6 +31,7 @@ import * as Unread from '../../../Unread';
|
||||||
import * as FormattingUtils from "../../../utils/FormattingUtils";
|
import * as FormattingUtils from "../../../utils/FormattingUtils";
|
||||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||||
|
import ActiveRoomObserver from "../../../ActiveRoomObserver";
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
* CAUTION *
|
* CAUTION *
|
||||||
|
@ -51,6 +51,7 @@ enum NotificationColor {
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
room: Room;
|
room: Room;
|
||||||
|
showMessagePreview: boolean;
|
||||||
|
|
||||||
// TODO: Allow falsifying counts (for invites and stuff)
|
// TODO: Allow falsifying counts (for invites and stuff)
|
||||||
// TODO: Transparency? Was this ever used?
|
// TODO: Transparency? Was this ever used?
|
||||||
|
@ -65,6 +66,7 @@ interface INotificationState {
|
||||||
interface IState {
|
interface IState {
|
||||||
hover: boolean;
|
hover: boolean;
|
||||||
notificationState: INotificationState;
|
notificationState: INotificationState;
|
||||||
|
selected: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class RoomTile2 extends React.Component<IProps, IState> {
|
export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
|
@ -87,12 +89,14 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
this.state = {
|
this.state = {
|
||||||
hover: false,
|
hover: false,
|
||||||
notificationState: this.getNotificationState(),
|
notificationState: this.getNotificationState(),
|
||||||
|
selected: ActiveRoomObserver.activeRoomId === this.props.room.roomId,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.props.room.on("Room.receipt", this.handleRoomEventUpdate);
|
this.props.room.on("Room.receipt", this.handleRoomEventUpdate);
|
||||||
this.props.room.on("Room.timeline", this.handleRoomEventUpdate);
|
this.props.room.on("Room.timeline", this.handleRoomEventUpdate);
|
||||||
this.props.room.on("Room.redaction", this.handleRoomEventUpdate);
|
this.props.room.on("Room.redaction", this.handleRoomEventUpdate);
|
||||||
MatrixClientPeg.get().on("Event.decrypted", this.handleRoomEventUpdate);
|
MatrixClientPeg.get().on("Event.decrypted", this.handleRoomEventUpdate);
|
||||||
|
ActiveRoomObserver.addListener(this.props.room.roomId, this.onActiveRoomUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentWillUnmount() {
|
public componentWillUnmount() {
|
||||||
|
@ -100,6 +104,7 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
this.props.room.removeListener("Room.receipt", this.handleRoomEventUpdate);
|
this.props.room.removeListener("Room.receipt", this.handleRoomEventUpdate);
|
||||||
this.props.room.removeListener("Room.timeline", this.handleRoomEventUpdate);
|
this.props.room.removeListener("Room.timeline", this.handleRoomEventUpdate);
|
||||||
this.props.room.removeListener("Room.redaction", this.handleRoomEventUpdate);
|
this.props.room.removeListener("Room.redaction", this.handleRoomEventUpdate);
|
||||||
|
ActiveRoomObserver.removeListener(this.props.room.roomId, this.onActiveRoomUpdate);
|
||||||
}
|
}
|
||||||
if (MatrixClientPeg.get()) {
|
if (MatrixClientPeg.get()) {
|
||||||
MatrixClientPeg.get().removeListener("Event.decrypted", this.handleRoomEventUpdate);
|
MatrixClientPeg.get().removeListener("Event.decrypted", this.handleRoomEventUpdate);
|
||||||
|
@ -186,39 +191,33 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private onActiveRoomUpdate = (isActive: boolean) => {
|
||||||
|
this.setState({selected: isActive});
|
||||||
|
};
|
||||||
|
|
||||||
public render(): React.ReactElement {
|
public render(): React.ReactElement {
|
||||||
// TODO: Collapsed state
|
// TODO: Collapsed state
|
||||||
// TODO: Invites
|
// TODO: Invites
|
||||||
// TODO: a11y proper
|
// TODO: a11y proper
|
||||||
// TODO: Render more than bare minimum
|
// TODO: Render more than bare minimum
|
||||||
|
|
||||||
const hasBadge = this.state.notificationState.color > NotificationColor.Bold;
|
|
||||||
const isUnread = this.state.notificationState.color > NotificationColor.None;
|
|
||||||
const classes = classNames({
|
const classes = classNames({
|
||||||
'mx_RoomTile': true,
|
'mx_RoomTile2': true,
|
||||||
// 'mx_RoomTile_selected': this.state.selected,
|
'mx_RoomTile2_selected': this.state.selected,
|
||||||
'mx_RoomTile_unread': isUnread,
|
|
||||||
'mx_RoomTile_unreadNotify': this.state.notificationState.color >= NotificationColor.Grey,
|
|
||||||
'mx_RoomTile_highlight': this.state.notificationState.color >= NotificationColor.Red,
|
|
||||||
'mx_RoomTile_invited': this.roomIsInvite,
|
|
||||||
// 'mx_RoomTile_menuDisplayed': isMenuDisplayed,
|
|
||||||
'mx_RoomTile_noBadges': !hasBadge,
|
|
||||||
// 'mx_RoomTile_transparent': this.props.transparent,
|
|
||||||
// 'mx_RoomTile_hasSubtext': subtext && !this.props.collapsed,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const avatarClasses = classNames({
|
|
||||||
'mx_RoomTile_avatar': true,
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
let badge;
|
let badge;
|
||||||
|
const hasBadge = this.state.notificationState.color > NotificationColor.Bold;
|
||||||
if (hasBadge) {
|
if (hasBadge) {
|
||||||
|
const hasNotif = this.state.notificationState.color >= NotificationColor.Red;
|
||||||
|
const isEmptyBadge = !localStorage.getItem("mx_rl_rt_badgeCount");
|
||||||
const badgeClasses = classNames({
|
const badgeClasses = classNames({
|
||||||
'mx_RoomTile_badge': true,
|
'mx_RoomTile2_badge': true,
|
||||||
'mx_RoomTile_badgeButton': false, // this.state.badgeHover || isMenuDisplayed
|
'mx_RoomTile2_badgeHighlight': hasNotif,
|
||||||
|
'mx_RoomTile2_badgeEmpty': isEmptyBadge,
|
||||||
});
|
});
|
||||||
badge = <div className={badgeClasses}>{this.state.notificationState.symbol}</div>;
|
const symbol = this.state.notificationState.symbol;
|
||||||
|
badge = <div className={badgeClasses}>{isEmptyBadge ? null : symbol}</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: the original RoomTile uses state for the room name. Do we need to?
|
// TODO: the original RoomTile uses state for the room name. Do we need to?
|
||||||
|
@ -226,20 +225,21 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
if (typeof name !== 'string') name = '';
|
if (typeof name !== 'string') name = '';
|
||||||
name = name.replace(":", ":\u200b"); // add a zero-width space to allow linewrapping after the colon
|
name = name.replace(":", ":\u200b"); // add a zero-width space to allow linewrapping after the colon
|
||||||
|
|
||||||
const nameClasses = classNames({
|
|
||||||
'mx_RoomTile_name': true,
|
|
||||||
'mx_RoomTile_invite': this.roomIsInvite,
|
|
||||||
'mx_RoomTile_badgeShown': hasBadge,
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO: Support collapsed state properly
|
// TODO: Support collapsed state properly
|
||||||
let tooltip = null;
|
// TODO: Tooltip?
|
||||||
if (false) { // isCollapsed
|
|
||||||
if (this.state.hover) {
|
let messagePreview = null;
|
||||||
tooltip = <Tooltip className="mx_RoomTile_tooltip" label={this.props.room.name} />
|
if (this.props.showMessagePreview) {
|
||||||
}
|
// TODO: Actually get the real message preview from state
|
||||||
|
messagePreview = <div className="mx_RoomTile2_messagePreview">I just ate a pie.</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const nameClasses = classNames({
|
||||||
|
"mx_RoomTile2_name": true,
|
||||||
|
"mx_RoomTile2_nameWithPreview": !!messagePreview,
|
||||||
|
});
|
||||||
|
|
||||||
|
const avatarSize = 32;
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<RovingTabIndexWrapper inputRef={this.roomTile}>
|
<RovingTabIndexWrapper inputRef={this.roomTile}>
|
||||||
|
@ -254,20 +254,18 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
onClick={this.onTileClick}
|
onClick={this.onTileClick}
|
||||||
role="treeitem"
|
role="treeitem"
|
||||||
>
|
>
|
||||||
<div className={avatarClasses}>
|
<div className="mx_RoomTile2_avatarContainer">
|
||||||
<div className="mx_RoomTile_avatar_container">
|
<RoomAvatar room={this.props.room} width={avatarSize} height={avatarSize}/>
|
||||||
<RoomAvatar room={this.props.room} width={24} height={24}/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_RoomTile_nameContainer">
|
<div className="mx_RoomTile2_nameContainer">
|
||||||
<div className="mx_RoomTile_labelContainer">
|
<div title={name} className={nameClasses} tabIndex={-1} dir="auto">
|
||||||
<div title={name} className={nameClasses} tabIndex={-1} dir="auto">
|
{name}
|
||||||
{name}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
{messagePreview}
|
||||||
|
</div>
|
||||||
|
<div className="mx_RoomTile2_badgeContainer">
|
||||||
{badge}
|
{badge}
|
||||||
</div>
|
</div>
|
||||||
{tooltip}
|
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
}
|
}
|
||||||
</RovingTabIndexWrapper>
|
</RovingTabIndexWrapper>
|
||||||
|
|
|
@ -1090,6 +1090,7 @@
|
||||||
"Low priority": "Low priority",
|
"Low priority": "Low priority",
|
||||||
"Historical": "Historical",
|
"Historical": "Historical",
|
||||||
"System Alerts": "System Alerts",
|
"System Alerts": "System Alerts",
|
||||||
|
"People": "People",
|
||||||
"This room": "This room",
|
"This room": "This room",
|
||||||
"Joining room …": "Joining room …",
|
"Joining room …": "Joining room …",
|
||||||
"Loading …": "Loading …",
|
"Loading …": "Loading …",
|
||||||
|
@ -1133,9 +1134,6 @@
|
||||||
"Securely back up your keys to avoid losing them. <a>Learn more.</a>": "Securely back up your keys to avoid losing them. <a>Learn more.</a>",
|
"Securely back up your keys to avoid losing them. <a>Learn more.</a>": "Securely back up your keys to avoid losing them. <a>Learn more.</a>",
|
||||||
"Not now": "Not now",
|
"Not now": "Not now",
|
||||||
"Don't ask me again": "Don't ask me again",
|
"Don't ask me again": "Don't ask me again",
|
||||||
"Jump to first unread room.": "Jump to first unread room.",
|
|
||||||
"Jump to first invite.": "Jump to first invite.",
|
|
||||||
"Add room": "Add room",
|
|
||||||
"Show %(n)s more": "Show %(n)s more",
|
"Show %(n)s more": "Show %(n)s more",
|
||||||
"Options": "Options",
|
"Options": "Options",
|
||||||
"%(count)s unread messages including mentions.|other": "%(count)s unread messages including mentions.",
|
"%(count)s unread messages including mentions.|other": "%(count)s unread messages including mentions.",
|
||||||
|
@ -2017,6 +2015,9 @@
|
||||||
"Sent messages will be stored until your connection has returned.": "Sent messages will be stored until your connection has returned.",
|
"Sent messages will be stored until your connection has returned.": "Sent messages will be stored until your connection has returned.",
|
||||||
"Active call": "Active call",
|
"Active call": "Active call",
|
||||||
"There's no one else here! Would you like to <inviteText>invite others</inviteText> or <nowarnText>stop warning about the empty room</nowarnText>?": "There's no one else here! Would you like to <inviteText>invite others</inviteText> or <nowarnText>stop warning about the empty room</nowarnText>?",
|
"There's no one else here! Would you like to <inviteText>invite others</inviteText> or <nowarnText>stop warning about the empty room</nowarnText>?": "There's no one else here! Would you like to <inviteText>invite others</inviteText> or <nowarnText>stop warning about the empty room</nowarnText>?",
|
||||||
|
"Jump to first unread room.": "Jump to first unread room.",
|
||||||
|
"Jump to first invite.": "Jump to first invite.",
|
||||||
|
"Add room": "Add room",
|
||||||
"You seem to be uploading files, are you sure you want to quit?": "You seem to be uploading files, are you sure you want to quit?",
|
"You seem to be uploading files, are you sure you want to quit?": "You seem to be uploading files, are you sure you want to quit?",
|
||||||
"You seem to be in a call, are you sure you want to quit?": "You seem to be in a call, are you sure you want to quit?",
|
"You seem to be in a call, are you sure you want to quit?": "You seem to be in a call, are you sure you want to quit?",
|
||||||
"Search failed": "Search failed",
|
"Search failed": "Search failed",
|
||||||
|
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
||||||
|
|
||||||
import { TagID } from "./models";
|
import { TagID } from "./models";
|
||||||
|
|
||||||
const TILE_HEIGHT_PX = 34;
|
const TILE_HEIGHT_PX = 44;
|
||||||
|
|
||||||
interface ISerializedListLayout {
|
interface ISerializedListLayout {
|
||||||
numTiles: number;
|
numTiles: number;
|
||||||
|
|
Loading…
Reference in a new issue