Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

hide empty roomsublists when filtering via search/tagpanel #1954

Merged
merged 2 commits into from
Jun 25, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions .eslintignore.errorfiles
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

src/autocomplete/AutocompleteProvider.js
src/autocomplete/Autocompleter.js
src/autocomplete/EmojiProvider.js
src/autocomplete/UserProvider.js
src/component-index.js
src/components/structures/BottomLeftMenu.js
Expand All @@ -17,7 +16,6 @@ src/components/structures/MessagePanel.js
src/components/structures/NotificationPanel.js
src/components/structures/RoomDirectory.js
src/components/structures/RoomStatusBar.js
src/components/structures/RoomSubList.js
src/components/structures/RoomView.js
src/components/structures/ScrollPanel.js
src/components/structures/SearchBox.js
Expand All @@ -29,15 +27,13 @@ src/components/views/avatars/BaseAvatar.js
src/components/views/avatars/MemberAvatar.js
src/components/views/create_room/RoomAlias.js
src/components/views/dialogs/ChangelogDialog.js
src/components/views/dialogs/ChatCreateOrReuseDialog.js
src/components/views/dialogs/DeactivateAccountDialog.js
src/components/views/dialogs/SetPasswordDialog.js
src/components/views/dialogs/UnknownDeviceDialog.js
src/components/views/directory/NetworkDropdown.js
src/components/views/elements/AddressSelector.js
src/components/views/elements/DeviceVerifyButtons.js
src/components/views/elements/DirectorySearchBox.js
src/components/views/elements/EditableText.js
src/components/views/elements/ImageView.js
src/components/views/elements/InlineSpinner.js
src/components/views/elements/MemberEventListSummary.js
Expand Down Expand Up @@ -81,7 +77,6 @@ src/components/views/rooms/TopUnreadMessagesBar.js
src/components/views/rooms/UserTile.js
src/components/views/settings/AddPhoneNumber.js
src/components/views/settings/ChangeAvatar.js
src/components/views/settings/ChangeDisplayName.js
src/components/views/settings/ChangePassword.js
src/components/views/settings/DevicesPanel.js
src/components/views/settings/IntegrationsManager.js
Expand Down
179 changes: 89 additions & 90 deletions src/components/structures/RoomSubList.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*
Copyright 2017 Vector Creations Ltd
Copyright 2015, 2016 OpenMarket Ltd
Copyright 2017 Vector Creations Ltd
Copyright 2018 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.
Expand All @@ -15,30 +16,24 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';

var React = require('react');
var ReactDOM = require('react-dom');
var classNames = require('classnames');
var sdk = require('../../index');
import React from 'react';
import classNames from 'classnames';
import sdk from '../../index';
import { Droppable } from 'react-beautiful-dnd';
import { _t } from '../../languageHandler';
var dis = require('../../dispatcher');
var Unread = require('../../Unread');
var MatrixClientPeg = require('../../MatrixClientPeg');
var RoomNotifs = require('../../RoomNotifs');
var FormattingUtils = require('../../utils/FormattingUtils');
var AccessibleButton = require('../../components/views/elements/AccessibleButton');
import Modal from '../../Modal';
import dis from '../../dispatcher';
import Unread from '../../Unread';
import * as RoomNotifs from '../../RoomNotifs';
import * as FormattingUtils from '../../utils/FormattingUtils';
import { KeyCode } from '../../Keyboard';


// turn this on for drop & drag console debugging galore
var debug = false;
const debug = false;

const TRUNCATE_AT = 10;

var RoomSubList = React.createClass({
const RoomSubList = React.createClass({
displayName: 'RoomSubList',

debug: debug,
Expand Down Expand Up @@ -77,8 +72,10 @@ var RoomSubList = React.createClass({

getDefaultProps: function() {
return {
onHeaderClick: function() {}, // NOP
onShowMoreRooms: function() {}, // NOP
onHeaderClick: function() {
}, // NOP
onShowMoreRooms: function() {
}, // NOP
extraTiles: [],
isInvite: false,
};
Expand Down Expand Up @@ -115,7 +112,7 @@ var RoomSubList = React.createClass({
// The header is collapsable if it is hidden or not stuck
// The dataset elements are added in the RoomList _initAndPositionStickyHeaders method
isCollapsableOnClick: function() {
var stuck = this.refs.header.dataset.stuck;
const stuck = this.refs.header.dataset.stuck;
if (this.state.hidden || stuck === undefined || stuck === "none") {
return true;
} else {
Expand All @@ -141,12 +138,12 @@ var RoomSubList = React.createClass({
onClick: function(ev) {
if (this.isCollapsableOnClick()) {
// The header isCollapsable, so the click is to be interpreted as collapse and truncation logic
var isHidden = !this.state.hidden;
this.setState({ hidden : isHidden });
const isHidden = !this.state.hidden;
this.setState({hidden: isHidden});

if (isHidden) {
// as good a way as any to reset the truncate state
this.setState({ truncateAt : TRUNCATE_AT });
this.setState({truncateAt: TRUNCATE_AT});
}

this.props.onShowMoreRooms();
Expand All @@ -161,7 +158,7 @@ var RoomSubList = React.createClass({
dis.dispatch({
action: 'view_room',
room_id: roomId,
clear_search: (ev && (ev.keyCode == KeyCode.ENTER || ev.keyCode == KeyCode.SPACE)),
clear_search: (ev && (ev.keyCode === KeyCode.ENTER || ev.keyCode === KeyCode.SPACE)),
});
},

Expand All @@ -171,27 +168,27 @@ var RoomSubList = React.createClass({
},

_shouldShowMentionBadge: function(roomNotifState) {
return roomNotifState != RoomNotifs.MUTE;
return roomNotifState !== RoomNotifs.MUTE;
},

/**
* Total up all the notification counts from the rooms
*
* @param {Number} If supplied will only total notifications for rooms outside the truncation number
* @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
*/
roomNotificationCount: function(truncateAt) {
var self = this;
const self = this;

if (this.props.isInvite) {
return [0, true];
}

return this.props.list.reduce(function(result, room, index) {
if (truncateAt === undefined || index >= truncateAt) {
var roomNotifState = RoomNotifs.getRoomNotifsState(room.roomId);
var highlight = room.getUnreadNotificationCount('highlight') > 0;
var notificationCount = room.getUnreadNotificationCount();
const roomNotifState = RoomNotifs.getRoomNotifsState(room.roomId);
const highlight = room.getUnreadNotificationCount('highlight') > 0;
const notificationCount = room.getUnreadNotificationCount();

const notifBadges = notificationCount > 0 && self._shouldShowNotifBadge(roomNotifState);
const mentionBadges = highlight && self._shouldShowMentionBadge(roomNotifState);
Expand Down Expand Up @@ -241,163 +238,165 @@ var RoomSubList = React.createClass({
},

_getHeaderJsx: function() {
var TintableSvg = sdk.getComponent("elements.TintableSvg");
const subListNotifications = this.roomNotificationCount();
const subListNotifCount = subListNotifications[0];
const subListNotifHighlight = subListNotifications[1];

var subListNotifications = this.roomNotificationCount();
var subListNotifCount = subListNotifications[0];
var subListNotifHighlight = subListNotifications[1];
const totalTiles = this.props.list.length + (this.props.extraTiles || []).length;
const roomCount = totalTiles > 0 ? totalTiles : '';

var totalTiles = this.props.list.length + (this.props.extraTiles || []).length;
var roomCount = totalTiles > 0 ? totalTiles : '';

var chevronClasses = classNames({
const chevronClasses = classNames({
'mx_RoomSubList_chevron': true,
'mx_RoomSubList_chevronRight': this.state.hidden,
'mx_RoomSubList_chevronDown': !this.state.hidden,
});

var badgeClasses = classNames({
const badgeClasses = classNames({
'mx_RoomSubList_badge': true,
'mx_RoomSubList_badgeHighlight': subListNotifHighlight,
});

var badge;
let badge;
if (subListNotifCount > 0) {
badge = <div className={badgeClasses}>{ FormattingUtils.formatCount(subListNotifCount) }</div>;
badge = <div className={badgeClasses}>{FormattingUtils.formatCount(subListNotifCount)}</div>;
} else if (this.props.isInvite) {
// no notifications but highlight anyway because this is an invite badge
badge = <div className={badgeClasses}>!</div>;
}

// When collapsed, allow a long hover on the header to show user
// the full tag name and room count
var title;
let title;
if (this.props.collapsed) {
title = this.props.label;
if (roomCount !== '') {
title += " [" + roomCount + "]";
}
}

var incomingCall;
let incomingCall;
if (this.props.incomingCall) {
var self = this;
const self = this;
// Check if the incoming call is for this section
var incomingCallRoom = this.props.list.filter(function(room) {
const incomingCallRoom = this.props.list.filter(function(room) {
return self.props.incomingCall.roomId === room.roomId;
});

if (incomingCallRoom.length === 1) {
var IncomingCallBox = sdk.getComponent("voip.IncomingCallBox");
incomingCall = <IncomingCallBox className="mx_RoomSubList_incomingCall" incomingCall={ this.props.incomingCall }/>;
const IncomingCallBox = sdk.getComponent("voip.IncomingCallBox");
incomingCall =
<IncomingCallBox className="mx_RoomSubList_incomingCall" incomingCall={this.props.incomingCall} />;
}
}

var tabindex = this.props.searchFilter === "" ? "0" : "-1";
const tabindex = this.props.searchFilter === "" ? "0" : "-1";

const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
return (
<div className="mx_RoomSubList_labelContainer" title={ title } ref="header">
<AccessibleButton onClick={ this.onClick } className="mx_RoomSubList_label" tabIndex={tabindex}>
{ this.props.collapsed ? '' : this.props.label }
<div className="mx_RoomSubList_roomCount">{ roomCount }</div>
<div className={chevronClasses}></div>
{ badge }
{ incomingCall }
<div className="mx_RoomSubList_labelContainer" title={title} ref="header">
<AccessibleButton onClick={this.onClick} className="mx_RoomSubList_label" tabIndex={tabindex}>
{this.props.collapsed ? '' : this.props.label}
<div className="mx_RoomSubList_roomCount">{roomCount}</div>
<div className={chevronClasses} />
{badge}
{incomingCall}
</AccessibleButton>
</div>
);
},

_createOverflowTile: function(overflowCount, totalCount) {
var content = <div className="mx_RoomSubList_chevronDown"></div>;
let content = <div className="mx_RoomSubList_chevronDown" />;

var overflowNotifications = this.roomNotificationCount(TRUNCATE_AT);
var overflowNotifCount = overflowNotifications[0];
var overflowNotifHighlight = overflowNotifications[1];
const overflowNotifications = this.roomNotificationCount(TRUNCATE_AT);
const overflowNotifCount = overflowNotifications[0];
const overflowNotifHighlight = overflowNotifications[1];
if (overflowNotifCount && !this.props.collapsed) {
content = FormattingUtils.formatCount(overflowNotifCount);
}

var badgeClasses = classNames({
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>
<div className="mx_RoomSubList_more">{ _t("more") }</div>
<div className={ badgeClasses }>{ content }</div>
<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
truncateAt: -1,
});

this.props.onShowMoreRooms();
this.props.onHeaderClick(false);
},

render: function() {
var connectDropTarget = this.props.connectDropTarget;
var TruncatedList = sdk.getComponent('elements.TruncatedList');

var label = this.props.collapsed ? null : this.props.label;
const TruncatedList = sdk.getComponent('elements.TruncatedList');

let content;
if (this.state.sortedList.length === 0 && !this.props.searchFilter && this.props.extraTiles.length === 0) {
content = this.props.emptyContent;
if (this.state.sortedList.length === 0 && this.props.extraTiles.length === 0) {
// if no search filter is applied and there is a placeholder defined then show it, otherwise show nothing
if (!this.props.searchFilter && this.props.emptyContent) {
content = this.props.emptyContent;
} else {
// don't show an empty sublist
return null;
}
} else {
content = this.makeRoomTiles();
content.push(...this.props.extraTiles);
}

if (this.state.sortedList.length > 0 || this.props.extraTiles.length > 0 || this.props.editable) {
var subList;
var classes = "mx_RoomSubList";
let subList;
const classes = "mx_RoomSubList";

if (!this.state.hidden) {
subList = <TruncatedList className={ classes } truncateAt={this.state.truncateAt}
createOverflowElement={this._createOverflowTile} >
{ content }
</TruncatedList>;
}
else {
subList = <TruncatedList className={ classes }>
</TruncatedList>;
subList = <TruncatedList className={classes} truncateAt={this.state.truncateAt}
createOverflowElement={this._createOverflowTile}>
{content}
</TruncatedList>;
} else {
subList = <TruncatedList className={classes}>
</TruncatedList>;
}

const subListContent = <div>
{ this._getHeaderJsx() }
{ subList }
{this._getHeaderJsx()}
{subList}
</div>;

return this.props.editable ?
<Droppable
droppableId={"room-sub-list-droppable_" + this.props.tagName}
type="draggable-RoomTile"
>
{ (provided, snapshot) => (
{(provided, snapshot) => (
<div ref={provided.innerRef}>
{ subListContent }
{subListContent}
</div>
) }
)}
</Droppable> : subListContent;
}
else {
var Loader = sdk.getComponent("elements.Spinner");
} else {
const Loader = sdk.getComponent("elements.Spinner");
return (
<div className="mx_RoomSubList">
{ this.props.alwaysShowHeader ? this._getHeaderJsx() : undefined }
{ (this.props.showSpinner && !this.state.hidden) ? <Loader /> : undefined }
{this.props.alwaysShowHeader ? this._getHeaderJsx() : undefined}
{(this.props.showSpinner && !this.state.hidden) ? <Loader /> : undefined}
</div>
);
}
}
},
});

module.exports = RoomSubList;