Merge pull request #2224 from matrix-org/bwindels/removedndmore

Redesign: remove room list truncation and DND
This commit is contained in:
Bruno Windels 2018-10-19 13:30:18 +00:00 committed by GitHub
commit f2ee8307dc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 15 additions and 242 deletions

View file

@ -127,81 +127,6 @@ limitations under the License.
transform: rotateZ(-90deg); transform: rotateZ(-90deg);
} }
/* The overflow section */
.mx_RoomSubList_ellipsis {
display: block;
line-height: 11px;
height: 18px;
position: relative;
cursor: pointer;
font-size: 13px;
background-color: $secondary-accent-color;
}
.mx_RoomSubList_line {
display: inline-block;
width: 159px;
border-top: dotted 2px $accent-color;
vertical-align: middle;
}
.mx_RoomSubList_more {
display: inline-block;
text-transform: uppercase;
font-size: 10px;
font-weight: 600;
text-align: left;
color: $accent-color;
padding-left: 7px;
padding-right: 7px;
padding-left: 7px;
vertical-align: middle;
}
.mx_RoomSubList_moreBadge {
display: inline-block;
min-width: 15px;
height: 13px;
position: absolute;
right: 8px; /*gutter */
top: -2px;
border-radius: 8px;
border: solid 1px $accent-color;
color: $accent-fg-color;
font-weight: 600;
font-size: 10px;
text-align: center;
padding-top: 1px;
padding-left: 3px;
padding-right: 3px;
background-color: $primary-bg-color;
vertical-align: middle;
}
.mx_RoomSubList_moreBadge.mx_RoomSubList_moreBadgeNotify {
background-color: $accent-color;
border: 0;
padding-top: 3px;
padding-left: 4px;
padding-right: 4px;
}
.mx_RoomSubList_moreBadge.mx_RoomSubList_moreBadgeHighlight {
background-color: $warning-color;
border: 0;
padding-top: 3px;
padding-left: 4px;
padding-right: 4px;
}
.mx_RoomSubList_ellipsis .mx_RoomSubList_chevronDown {
position: relative;
top: 4px;
left: 2px;
}
.collapsed { .collapsed {
.mx_RoomSubList_label { .mx_RoomSubList_label {
height: 17px; height: 17px;

View file

@ -33,8 +33,6 @@ import PropTypes from 'prop-types';
// turn this on for drop & drag console debugging galore // turn this on for drop & drag console debugging galore
const debug = false; const debug = false;
const TRUNCATE_AT = 10;
const RoomSubList = React.createClass({ const RoomSubList = React.createClass({
displayName: 'RoomSubList', displayName: 'RoomSubList',
@ -44,7 +42,6 @@ const RoomSubList = React.createClass({
list: PropTypes.arrayOf(PropTypes.object).isRequired, list: PropTypes.arrayOf(PropTypes.object).isRequired,
label: PropTypes.string.isRequired, label: PropTypes.string.isRequired,
tagName: PropTypes.string, tagName: PropTypes.string,
editable: PropTypes.bool,
order: PropTypes.string.isRequired, order: PropTypes.string.isRequired,
@ -68,7 +65,6 @@ const RoomSubList = React.createClass({
getInitialState: function() { getInitialState: function() {
return { return {
hidden: this.props.startAsHidden || false, hidden: this.props.startAsHidden || false,
truncateAt: -1, // TRUNCATE_AT,
sortedList: [], sortedList: [],
}; };
}, },
@ -144,12 +140,6 @@ const RoomSubList = React.createClass({
// The header isCollapsable, so the click is to be interpreted as collapse and truncation logic // The header isCollapsable, so the click is to be interpreted as collapse and truncation logic
const isHidden = !this.state.hidden; const isHidden = !this.state.hidden;
this.setState({hidden: isHidden}); this.setState({hidden: isHidden});
if (isHidden) {
// as good a way as any to reset the truncate state
this.setState({truncateAt: TRUNCATE_AT});
}
this.props.onShowMoreRooms(); this.props.onShowMoreRooms();
this.props.onHeaderClick(isHidden); this.props.onHeaderClick(isHidden);
} else { } else {
@ -178,10 +168,9 @@ const RoomSubList = React.createClass({
/** /**
* Total up all the notification counts from the rooms * Total up all the notification counts from the rooms
* *
* @param {Number} truncateAt If supplied will only total notifications for rooms outside the truncation number
* @returns {Array} The array takes the form [total, highlight] where highlight is a bool * @returns {Array} The array takes the form [total, highlight] where highlight is a bool
*/ */
roomNotificationCount: function(truncateAt) { roomNotificationCount: function() {
const self = this; const self = this;
if (this.props.isInvite) { if (this.props.isInvite) {
@ -189,20 +178,18 @@ const RoomSubList = React.createClass({
} }
return this.props.list.reduce(function(result, room, index) { return this.props.list.reduce(function(result, room, index) {
if (truncateAt === undefined || index >= truncateAt) { const roomNotifState = RoomNotifs.getRoomNotifsState(room.roomId);
const roomNotifState = RoomNotifs.getRoomNotifsState(room.roomId); const highlight = room.getUnreadNotificationCount('highlight') > 0;
const highlight = room.getUnreadNotificationCount('highlight') > 0; const notificationCount = room.getUnreadNotificationCount();
const notificationCount = room.getUnreadNotificationCount();
const notifBadges = notificationCount > 0 && self._shouldShowNotifBadge(roomNotifState); const notifBadges = notificationCount > 0 && self._shouldShowNotifBadge(roomNotifState);
const mentionBadges = highlight && self._shouldShowMentionBadge(roomNotifState); const mentionBadges = highlight && self._shouldShowMentionBadge(roomNotifState);
const badges = notifBadges || mentionBadges; const badges = notifBadges || mentionBadges;
if (badges) { if (badges) {
result[0] += notificationCount; result[0] += notificationCount;
if (highlight) { if (highlight) {
result[1] = true; result[1] = true;
}
} }
} }
return result; return result;
@ -217,15 +204,9 @@ const RoomSubList = React.createClass({
}, },
makeRoomTiles: function() { makeRoomTiles: function() {
const DNDRoomTile = sdk.getComponent("rooms.DNDRoomTile");
const RoomTile = sdk.getComponent("rooms.RoomTile"); const RoomTile = sdk.getComponent("rooms.RoomTile");
return this.state.sortedList.map((room, index) => { return this.state.sortedList.map((room, index) => {
// XXX: is it evil to pass in this as a prop to RoomTile? Yes. return <RoomTile
// We should only use <DNDRoomTile /> when editable
const RoomTileComponent = this.props.editable ? DNDRoomTile : RoomTile;
return <RoomTileComponent
index={index} // For DND
room={room} room={room}
roomSubList={this} roomSubList={this}
tagName={this.props.tagName} tagName={this.props.tagName}
@ -356,44 +337,7 @@ const RoomSubList = React.createClass({
// <div className="mx_RoomSubList_roomCount">{ roomCount }</div> // <div className="mx_RoomSubList_roomCount">{ roomCount }</div>
}, },
_createOverflowTile: function(overflowCount, totalCount) {
let content = <div className="mx_RoomSubList_chevronDown" />;
const overflowNotifications = this.roomNotificationCount(TRUNCATE_AT);
const overflowNotifCount = overflowNotifications[0];
const overflowNotifHighlight = overflowNotifications[1];
if (overflowNotifCount && !this.props.collapsed) {
content = FormattingUtils.formatCount(overflowNotifCount);
}
const badgeClasses = classNames({
'mx_RoomSubList_moreBadge': true,
'mx_RoomSubList_moreBadgeNotify': overflowNotifCount && !this.props.collapsed,
'mx_RoomSubList_moreBadgeHighlight': overflowNotifHighlight && !this.props.collapsed,
});
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
return (
<AccessibleButton className="mx_RoomSubList_ellipsis" onClick={this._showFullMemberList}>
<div className="mx_RoomSubList_line" />
<div className="mx_RoomSubList_more">{_t("more")}</div>
<div className={badgeClasses}>{content}</div>
</AccessibleButton>
);
},
_showFullMemberList: function() {
this.setState({
truncateAt: -1,
});
this.props.onShowMoreRooms();
this.props.onHeaderClick(false);
},
render: function() { render: function() {
const TruncatedList = sdk.getComponent('elements.TruncatedList');
let content; let content;
if (this.props.showEmpty) { if (this.props.showEmpty) {
@ -420,36 +364,14 @@ const RoomSubList = React.createClass({
} }
} }
if (this.state.sortedList.length > 0 || this.props.extraTiles.length > 0 || this.props.editable) { if (this.state.sortedList.length > 0 || this.props.extraTiles.length > 0) {
let subList;
const classes = "mx_RoomSubList";
if (!this.state.hidden) { const subList = this.state.hidden ? undefined : content;
subList = <TruncatedList className={classes} truncateAt={this.state.truncateAt}
createOverflowElement={this._createOverflowTile}>
{content}
</TruncatedList>;
} else {
subList = <TruncatedList className={classes}>
</TruncatedList>;
}
const subListContent = <div> return <div className={"mx_RoomSubList"}>
{this._getHeaderJsx()} {this._getHeaderJsx()}
{subList} {subList}
</div>; </div>;
return this.props.editable ?
<Droppable
droppableId={"room-sub-list-droppable_" + this.props.tagName}
type="draggable-RoomTile"
>
{(provided, snapshot) => (
<div ref={provided.innerRef}>
{subListContent}
</div>
)}
</Droppable> : subListContent;
} else { } else {
const Loader = sdk.getComponent("elements.Spinner"); const Loader = sdk.getComponent("elements.Spinner");
if (this.props.showSpinner) { if (this.props.showSpinner) {

View file

@ -1,65 +0,0 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
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 { Draggable } from 'react-beautiful-dnd';
import RoomTile from '../../../components/views/rooms/RoomTile';
import classNames from 'classnames';
export default class DNDRoomTile extends React.PureComponent {
constructor() {
super();
this.getClassName = this.getClassName.bind(this);
}
getClassName(isDragging) {
return classNames({
"mx_DNDRoomTile": true,
"mx_DNDRoomTile_dragging": isDragging,
});
}
render() {
const props = this.props;
return <div>
<Draggable
key={props.room.roomId}
draggableId={props.tagName + '_' + props.room.roomId}
index={props.index}
type="draggable-RoomTile"
>
{ (provided, snapshot) => {
return (
<div>
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
>
<div className={this.getClassName(snapshot.isDragging)}>
<RoomTile {...props} />
</div>
</div>
{ provided.placeholder }
</div>
);
} }
</Draggable>
</div>;
}
}

View file

@ -631,7 +631,6 @@ module.exports = React.createClass({
<RoomSubList list={[]} <RoomSubList list={[]}
extraTiles={this._makeGroupInviteTiles(self.props.searchFilter)} extraTiles={this._makeGroupInviteTiles(self.props.searchFilter)}
label={_t('Community Invites')} label={_t('Community Invites')}
editable={false}
order="recent" order="recent"
isInvite={true} isInvite={true}
collapsed={self.props.collapsed} collapsed={self.props.collapsed}
@ -643,7 +642,6 @@ module.exports = React.createClass({
<RoomSubList list={self.state.lists['im.vector.fake.invite']} <RoomSubList list={self.state.lists['im.vector.fake.invite']}
label={_t('Invites')} label={_t('Invites')}
editable={false}
order="recent" order="recent"
isInvite={true} isInvite={true}
incomingCall={self.state.incomingCall} incomingCall={self.state.incomingCall}
@ -658,7 +656,6 @@ module.exports = React.createClass({
label={_t('Favourites')} label={_t('Favourites')}
tagName="m.favourite" tagName="m.favourite"
emptyContent={this._getEmptyContent('m.favourite')} emptyContent={this._getEmptyContent('m.favourite')}
editable={true}
order="manual" order="manual"
incomingCall={self.state.incomingCall} incomingCall={self.state.incomingCall}
collapsed={self.props.collapsed} collapsed={self.props.collapsed}
@ -672,7 +669,6 @@ module.exports = React.createClass({
tagName="im.vector.fake.direct" tagName="im.vector.fake.direct"
emptyContent={this._getEmptyContent('im.vector.fake.direct')} emptyContent={this._getEmptyContent('im.vector.fake.direct')}
headerItems={this._getHeaderItems('im.vector.fake.direct')} headerItems={this._getHeaderItems('im.vector.fake.direct')}
editable={true}
order="recent" order="recent"
incomingCall={self.state.incomingCall} incomingCall={self.state.incomingCall}
collapsed={self.props.collapsed} collapsed={self.props.collapsed}
@ -684,7 +680,6 @@ module.exports = React.createClass({
<RoomSubList list={self.state.lists['im.vector.fake.recent']} <RoomSubList list={self.state.lists['im.vector.fake.recent']}
label={_t('Rooms')} label={_t('Rooms')}
editable={true}
emptyContent={this._getEmptyContent('im.vector.fake.recent')} emptyContent={this._getEmptyContent('im.vector.fake.recent')}
headerItems={this._getHeaderItems('im.vector.fake.recent')} headerItems={this._getHeaderItems('im.vector.fake.recent')}
order="recent" order="recent"
@ -702,7 +697,6 @@ module.exports = React.createClass({
label={labelForTagName(tagName)} label={labelForTagName(tagName)}
tagName={tagName} tagName={tagName}
emptyContent={this._getEmptyContent(tagName)} emptyContent={this._getEmptyContent(tagName)}
editable={true}
order="manual" order="manual"
incomingCall={self.state.incomingCall} incomingCall={self.state.incomingCall}
collapsed={self.props.collapsed} collapsed={self.props.collapsed}
@ -717,7 +711,6 @@ module.exports = React.createClass({
label={_t('Low priority')} label={_t('Low priority')}
tagName="m.lowpriority" tagName="m.lowpriority"
emptyContent={this._getEmptyContent('m.lowpriority')} emptyContent={this._getEmptyContent('m.lowpriority')}
editable={true}
order="recent" order="recent"
incomingCall={self.state.incomingCall} incomingCall={self.state.incomingCall}
collapsed={self.props.collapsed} collapsed={self.props.collapsed}
@ -735,7 +728,6 @@ module.exports = React.createClass({
</div> </div>
} }
label={_t('Historical')} label={_t('Historical')}
editable={false}
order="recent" order="recent"
collapsed={self.props.collapsed} collapsed={self.props.collapsed}
alwaysShowHeader={true} alwaysShowHeader={true}
@ -750,7 +742,6 @@ module.exports = React.createClass({
<RoomSubList list={self.state.lists['m.server_notice']} <RoomSubList list={self.state.lists['m.server_notice']}
label={_t('System Alerts')} label={_t('System Alerts')}
tagName="m.lowpriority" tagName="m.lowpriority"
editable={false}
order="recent" order="recent"
incomingCall={self.state.incomingCall} incomingCall={self.state.incomingCall}
collapsed={self.props.collapsed} collapsed={self.props.collapsed}