2015-11-30 16:55:00 +00:00
|
|
|
/*
|
2016-01-07 04:06:39 +00:00
|
|
|
Copyright 2015, 2016 OpenMarket Ltd
|
2018-08-13 12:49:22 +00:00
|
|
|
Copyright 2017, 2018 Vector Creations Ltd
|
2015-11-30 16:55:00 +00:00
|
|
|
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
'use strict';
|
2018-06-30 16:07:28 +00:00
|
|
|
import SettingsStore from "../../../settings/SettingsStore";
|
2019-02-11 15:17:15 +00:00
|
|
|
import Timer from "../../../utils/Timer";
|
2018-06-30 16:07:28 +00:00
|
|
|
|
2017-10-11 16:56:17 +00:00
|
|
|
const React = require("react");
|
|
|
|
const ReactDOM = require("react-dom");
|
2017-12-26 01:03:18 +00:00
|
|
|
import PropTypes from 'prop-types';
|
2017-11-13 19:19:33 +00:00
|
|
|
import { _t } from '../../../languageHandler';
|
2017-10-11 16:56:17 +00:00
|
|
|
const MatrixClientPeg = require("../../../MatrixClientPeg");
|
|
|
|
const CallHandler = require('../../../CallHandler');
|
|
|
|
const dis = require("../../../dispatcher");
|
|
|
|
const sdk = require('../../../index');
|
|
|
|
const rate_limited_func = require('../../../ratelimitedfunc');
|
2018-01-25 21:16:03 +00:00
|
|
|
import * as Rooms from '../../../Rooms';
|
2016-10-02 11:57:45 +00:00
|
|
|
import DMRoomMap from '../../../utils/DMRoomMap';
|
2017-10-11 16:56:17 +00:00
|
|
|
const Receipt = require('../../../utils/Receipt');
|
2018-01-03 11:33:59 +00:00
|
|
|
import TagOrderStore from '../../../stores/TagOrderStore';
|
2018-01-25 21:16:03 +00:00
|
|
|
import RoomListStore from '../../../stores/RoomListStore';
|
2019-02-05 17:38:36 +00:00
|
|
|
import CustomRoomTagStore from '../../../stores/CustomRoomTagStore';
|
2018-05-01 10:18:45 +00:00
|
|
|
import GroupStore from '../../../stores/GroupStore';
|
2018-11-02 14:27:17 +00:00
|
|
|
import RoomSubList from '../../structures/RoomSubList';
|
2018-10-18 13:19:45 +00:00
|
|
|
import ResizeHandle from '../elements/ResizeHandle';
|
2015-11-30 16:55:00 +00:00
|
|
|
|
2019-02-05 17:38:36 +00:00
|
|
|
import {Resizer} from '../../../resizer';
|
2019-01-24 14:43:49 +00:00
|
|
|
import {Layout, Distributor} from '../../../resizer/distributors/roomsublist2';
|
2017-04-26 17:59:16 +00:00
|
|
|
const HIDE_CONFERENCE_CHANS = true;
|
2018-08-06 17:00:40 +00:00
|
|
|
const STANDARD_TAGS_REGEX = /^(m\.(favourite|lowpriority|server_notice)|im\.vector\.fake\.(invite|recent|direct|archived))$/;
|
2019-02-11 15:17:15 +00:00
|
|
|
const HOVER_MOVE_TIMEOUT = 1000;
|
2017-04-26 17:59:16 +00:00
|
|
|
|
2018-08-06 15:58:54 +00:00
|
|
|
function labelForTagName(tagName) {
|
|
|
|
if (tagName.startsWith('u.')) return tagName.slice(2);
|
|
|
|
return tagName;
|
|
|
|
}
|
|
|
|
|
2017-06-19 16:49:22 +00:00
|
|
|
function phraseForSection(section) {
|
|
|
|
switch (section) {
|
|
|
|
case 'm.favourite':
|
2017-10-15 14:57:13 +00:00
|
|
|
return _t('Drop here to favourite');
|
2017-06-19 16:49:22 +00:00
|
|
|
case 'im.vector.fake.direct':
|
2017-10-15 14:57:13 +00:00
|
|
|
return _t('Drop here to tag direct chat');
|
2017-06-19 16:49:22 +00:00
|
|
|
case 'im.vector.fake.recent':
|
2017-10-15 14:57:13 +00:00
|
|
|
return _t('Drop here to restore');
|
2017-06-19 16:49:22 +00:00
|
|
|
case 'm.lowpriority':
|
2017-10-15 14:57:13 +00:00
|
|
|
return _t('Drop here to demote');
|
2017-06-19 16:49:22 +00:00
|
|
|
default:
|
|
|
|
return _t('Drop here to tag %(section)s', {section: section});
|
|
|
|
}
|
2017-10-11 16:56:17 +00:00
|
|
|
}
|
2015-11-30 16:55:00 +00:00
|
|
|
|
|
|
|
module.exports = React.createClass({
|
|
|
|
displayName: 'RoomList',
|
|
|
|
|
|
|
|
propTypes: {
|
2017-12-26 01:03:18 +00:00
|
|
|
ConferenceHandler: PropTypes.any,
|
|
|
|
collapsed: PropTypes.bool.isRequired,
|
|
|
|
searchFilter: PropTypes.string,
|
2015-11-30 16:55:00 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
getInitialState: function() {
|
2018-11-26 15:46:57 +00:00
|
|
|
|
2019-02-11 15:17:15 +00:00
|
|
|
this._hoverClearTimer = null;
|
2018-12-14 16:06:51 +00:00
|
|
|
this._subListRefs = {
|
|
|
|
// key => RoomSubList ref
|
|
|
|
};
|
|
|
|
|
2018-11-26 15:46:57 +00:00
|
|
|
const sizesJson = window.localStorage.getItem("mx_roomlist_sizes");
|
2018-12-03 09:39:31 +00:00
|
|
|
const collapsedJson = window.localStorage.getItem("mx_roomlist_collapsed");
|
2018-11-26 15:46:57 +00:00
|
|
|
this.subListSizes = sizesJson ? JSON.parse(sizesJson) : {};
|
2018-12-03 09:39:31 +00:00
|
|
|
this.collapsedState = collapsedJson ? JSON.parse(collapsedJson) : {};
|
2019-01-24 14:43:49 +00:00
|
|
|
this._layoutSections = [];
|
|
|
|
|
2019-01-28 17:28:04 +00:00
|
|
|
const unfilteredOptions = {
|
2019-01-29 16:21:14 +00:00
|
|
|
allowWhitespace: false,
|
2019-01-28 17:02:36 +00:00
|
|
|
handleHeight: 1,
|
|
|
|
};
|
2019-01-28 17:28:04 +00:00
|
|
|
this._unfilteredlayout = new Layout((key, size) => {
|
2019-01-24 14:43:49 +00:00
|
|
|
const subList = this._subListRefs[key];
|
|
|
|
if (subList) {
|
|
|
|
subList.setHeight(size);
|
|
|
|
}
|
|
|
|
// update overflow indicators
|
|
|
|
this._checkSubListsOverflow();
|
2019-01-28 13:35:04 +00:00
|
|
|
// don't store height for collapsed sublists
|
2019-02-11 15:27:29 +00:00
|
|
|
if (!this.collapsedState[key]) {
|
2019-01-28 13:35:04 +00:00
|
|
|
this.subListSizes[key] = size;
|
|
|
|
window.localStorage.setItem("mx_roomlist_sizes",
|
|
|
|
JSON.stringify(this.subListSizes));
|
|
|
|
}
|
2019-01-28 17:28:04 +00:00
|
|
|
}, this.subListSizes, this.collapsedState, unfilteredOptions);
|
|
|
|
|
|
|
|
this._filteredLayout = new Layout((key, size) => {
|
|
|
|
const subList = this._subListRefs[key];
|
|
|
|
if (subList) {
|
|
|
|
subList.setHeight(size);
|
|
|
|
}
|
|
|
|
}, null, null, {
|
|
|
|
allowWhitespace: false,
|
|
|
|
handleHeight: 0,
|
|
|
|
});
|
|
|
|
|
|
|
|
this._layout = this._unfilteredlayout;
|
2019-01-24 14:43:49 +00:00
|
|
|
|
2015-11-30 16:55:00 +00:00
|
|
|
return {
|
2015-12-18 15:13:59 +00:00
|
|
|
isLoadingLeftRooms: false,
|
2017-04-26 17:59:16 +00:00
|
|
|
totalRoomCount: null,
|
2015-11-30 16:55:00 +00:00
|
|
|
lists: {},
|
2018-12-06 18:45:58 +00:00
|
|
|
incomingCallTag: null,
|
2015-12-17 02:49:09 +00:00
|
|
|
incomingCall: null,
|
2017-11-29 16:35:16 +00:00
|
|
|
selectedTags: [],
|
2019-01-03 20:57:20 +00:00
|
|
|
hover: false,
|
2019-02-05 17:38:36 +00:00
|
|
|
customTags: CustomRoomTagStore.getTags(),
|
2017-01-20 14:22:27 +00:00
|
|
|
};
|
2015-11-30 16:55:00 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
componentWillMount: function() {
|
2017-05-18 16:33:32 +00:00
|
|
|
this.mounted = false;
|
|
|
|
|
2017-10-11 16:56:17 +00:00
|
|
|
const cli = MatrixClientPeg.get();
|
2017-12-05 11:25:30 +00:00
|
|
|
|
2015-11-30 16:55:00 +00:00
|
|
|
cli.on("Room", this.onRoom);
|
2015-12-16 16:27:46 +00:00
|
|
|
cli.on("deleteRoom", this.onDeleteRoom);
|
2017-04-18 21:36:54 +00:00
|
|
|
cli.on("Room.receipt", this.onRoomReceipt);
|
2015-11-30 16:55:00 +00:00
|
|
|
cli.on("RoomMember.name", this.onRoomMemberName);
|
2017-09-12 13:47:26 +00:00
|
|
|
cli.on("Event.decrypted", this.onEventDecrypted);
|
2016-09-07 16:46:45 +00:00
|
|
|
cli.on("accountData", this.onAccountData);
|
2017-09-21 15:28:49 +00:00
|
|
|
cli.on("Group.myMembership", this._onGroupMyMembership);
|
2019-01-10 22:43:22 +00:00
|
|
|
cli.on("RoomState.events", this.onRoomStateEvents);
|
2015-11-30 16:55:00 +00:00
|
|
|
|
2017-12-14 16:34:49 +00:00
|
|
|
const dmRoomMap = DMRoomMap.shared();
|
2017-12-14 16:17:06 +00:00
|
|
|
// A map between tags which are group IDs and the room IDs of rooms that should be kept
|
|
|
|
// in the room list when filtering by that tag.
|
2017-12-15 17:29:06 +00:00
|
|
|
this._visibleRoomsForGroup = {
|
2017-12-14 16:17:06 +00:00
|
|
|
// $groupId: [$roomId1, $roomId2, ...],
|
|
|
|
};
|
2018-01-05 12:33:26 +00:00
|
|
|
// All rooms that should be kept in the room list when filtering.
|
|
|
|
// By default, show all rooms.
|
2018-08-22 11:01:29 +00:00
|
|
|
this._visibleRooms = MatrixClientPeg.get().getVisibleRooms();
|
2018-05-01 13:24:58 +00:00
|
|
|
|
|
|
|
// Listen to updates to group data. RoomList cares about members and rooms in order
|
|
|
|
// to filter the room list when group tags are selected.
|
|
|
|
this._groupStoreToken = GroupStore.registerListener(null, () => {
|
2018-01-03 14:12:28 +00:00
|
|
|
(TagOrderStore.getOrderedTags() || []).forEach((tag) => {
|
2018-05-01 10:18:45 +00:00
|
|
|
if (tag[0] !== '+') {
|
2017-11-29 16:35:16 +00:00
|
|
|
return;
|
|
|
|
}
|
2018-05-01 13:24:58 +00:00
|
|
|
// This group's rooms or members may have updated, update rooms for its tag
|
|
|
|
this.updateVisibleRoomsForTag(dmRoomMap, tag);
|
|
|
|
this.updateVisibleRooms();
|
2017-11-29 16:35:16 +00:00
|
|
|
});
|
2018-05-01 13:24:58 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
this._tagStoreToken = TagOrderStore.addListener(() => {
|
|
|
|
// Filters themselves have changed
|
2017-12-15 17:29:06 +00:00
|
|
|
this.updateVisibleRooms();
|
2017-11-29 16:35:16 +00:00
|
|
|
});
|
|
|
|
|
2018-01-25 21:16:03 +00:00
|
|
|
this._roomListStoreToken = RoomListStore.addListener(() => {
|
|
|
|
this._delayedRefreshRoomList();
|
|
|
|
});
|
|
|
|
|
2019-02-07 18:04:30 +00:00
|
|
|
|
|
|
|
if (SettingsStore.isFeatureEnabled("feature_custom_tags")) {
|
|
|
|
this._customTagStoreToken = CustomRoomTagStore.addListener(() => {
|
|
|
|
this.setState({
|
|
|
|
customTags: CustomRoomTagStore.getTags(),
|
|
|
|
});
|
2019-02-05 17:38:36 +00:00
|
|
|
});
|
2019-02-07 18:04:30 +00:00
|
|
|
}
|
2019-02-05 17:38:36 +00:00
|
|
|
|
2017-04-26 17:59:16 +00:00
|
|
|
this.refreshRoomList();
|
|
|
|
|
|
|
|
// order of the sublists
|
|
|
|
//this.listOrder = [];
|
|
|
|
|
|
|
|
// loop count to stop a stack overflow if the user keeps waggling the
|
|
|
|
// mouse for >30s in a row, or if running under mocha
|
2017-10-11 16:56:17 +00:00
|
|
|
this._delayedRefreshRoomListLoopCount = 0;
|
2015-11-30 16:55:00 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
componentDidMount: function() {
|
|
|
|
this.dispatcherRef = dis.register(this.onAction);
|
2018-11-26 15:46:57 +00:00
|
|
|
const cfg = {
|
2019-02-04 18:38:31 +00:00
|
|
|
getLayout: () => this._layout,
|
2018-11-26 15:46:57 +00:00
|
|
|
};
|
2019-01-24 14:43:49 +00:00
|
|
|
this.resizer = new Resizer(this.resizeContainer, Distributor, cfg);
|
2018-10-18 13:51:58 +00:00
|
|
|
this.resizer.setClassNames({
|
|
|
|
handle: "mx_ResizeHandle",
|
|
|
|
vertical: "mx_ResizeHandle_vertical",
|
|
|
|
reverse: "mx_ResizeHandle_reverse"
|
|
|
|
});
|
2019-01-24 14:43:49 +00:00
|
|
|
this._layout.update(
|
|
|
|
this._layoutSections,
|
2019-01-24 15:45:26 +00:00
|
|
|
this.resizeContainer && this.resizeContainer.offsetHeight,
|
2019-01-24 14:43:49 +00:00
|
|
|
);
|
2018-12-18 13:26:33 +00:00
|
|
|
this._checkSubListsOverflow();
|
2017-05-18 16:33:32 +00:00
|
|
|
|
2018-10-18 13:51:58 +00:00
|
|
|
this.resizer.attach();
|
2019-03-28 16:56:12 +00:00
|
|
|
if (this.props.resizeNotifier) {
|
|
|
|
this.props.resizeNotifier.on("leftPanelResized", this.onResize);
|
|
|
|
}
|
2017-05-18 16:33:32 +00:00
|
|
|
this.mounted = true;
|
2015-11-30 16:55:00 +00:00
|
|
|
},
|
|
|
|
|
2018-12-14 16:06:51 +00:00
|
|
|
componentDidUpdate: function(prevProps) {
|
2019-01-28 17:28:04 +00:00
|
|
|
let forceLayoutUpdate = false;
|
2016-09-15 14:33:08 +00:00
|
|
|
this._repositionIncomingCallBox(undefined, false);
|
2019-01-28 17:28:04 +00:00
|
|
|
if (!this.props.searchFilter && prevProps.searchFilter) {
|
|
|
|
this._layout = this._unfilteredlayout;
|
|
|
|
forceLayoutUpdate = true;
|
|
|
|
} else if (this.props.searchFilter && !prevProps.searchFilter) {
|
|
|
|
this._layout = this._filteredLayout;
|
|
|
|
forceLayoutUpdate = true;
|
|
|
|
}
|
2019-01-24 14:43:49 +00:00
|
|
|
this._layout.update(
|
|
|
|
this._layoutSections,
|
|
|
|
this.resizeContainer && this.resizeContainer.clientHeight,
|
2019-01-28 17:28:04 +00:00
|
|
|
forceLayoutUpdate,
|
2019-01-24 14:43:49 +00:00
|
|
|
);
|
2019-01-28 17:28:04 +00:00
|
|
|
this._checkSubListsOverflow();
|
2016-08-25 18:46:01 +00:00
|
|
|
},
|
|
|
|
|
2015-11-30 16:55:00 +00:00
|
|
|
onAction: function(payload) {
|
|
|
|
switch (payload.action) {
|
|
|
|
case 'view_tooltip':
|
|
|
|
this.tooltip = payload.tooltip;
|
2015-12-17 02:49:09 +00:00
|
|
|
break;
|
|
|
|
case 'call_state':
|
|
|
|
var call = CallHandler.getCall(payload.room_id);
|
|
|
|
if (call && call.call_state === 'ringing') {
|
|
|
|
this.setState({
|
2017-10-11 16:56:17 +00:00
|
|
|
incomingCall: call,
|
2018-12-06 18:45:58 +00:00
|
|
|
incomingCallTag: this.getTagNameForRoomId(payload.room_id),
|
2015-12-17 02:49:09 +00:00
|
|
|
});
|
|
|
|
this._repositionIncomingCallBox(undefined, true);
|
2017-10-11 16:56:17 +00:00
|
|
|
} else {
|
2015-12-17 02:49:09 +00:00
|
|
|
this.setState({
|
2017-10-11 16:56:17 +00:00
|
|
|
incomingCall: null,
|
2018-12-06 18:45:58 +00:00
|
|
|
incomingCallTag: null,
|
2016-04-15 16:55:00 +00:00
|
|
|
});
|
2015-12-17 02:49:09 +00:00
|
|
|
}
|
|
|
|
break;
|
2015-11-30 16:55:00 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
componentWillUnmount: function() {
|
2017-05-18 16:33:32 +00:00
|
|
|
this.mounted = false;
|
|
|
|
|
2015-11-30 16:55:00 +00:00
|
|
|
dis.unregister(this.dispatcherRef);
|
|
|
|
if (MatrixClientPeg.get()) {
|
|
|
|
MatrixClientPeg.get().removeListener("Room", this.onRoom);
|
2016-02-04 15:55:24 +00:00
|
|
|
MatrixClientPeg.get().removeListener("deleteRoom", this.onDeleteRoom);
|
2017-04-18 21:36:54 +00:00
|
|
|
MatrixClientPeg.get().removeListener("Room.receipt", this.onRoomReceipt);
|
2016-02-04 15:55:24 +00:00
|
|
|
MatrixClientPeg.get().removeListener("RoomMember.name", this.onRoomMemberName);
|
2017-09-12 13:47:26 +00:00
|
|
|
MatrixClientPeg.get().removeListener("Event.decrypted", this.onEventDecrypted);
|
2016-09-07 16:46:45 +00:00
|
|
|
MatrixClientPeg.get().removeListener("accountData", this.onAccountData);
|
2017-09-21 15:28:49 +00:00
|
|
|
MatrixClientPeg.get().removeListener("Group.myMembership", this._onGroupMyMembership);
|
2019-01-10 22:43:22 +00:00
|
|
|
MatrixClientPeg.get().removeListener("RoomState.events", this.onRoomStateEvents);
|
2015-11-30 16:55:00 +00:00
|
|
|
}
|
2019-03-28 16:56:12 +00:00
|
|
|
|
|
|
|
if (this.props.resizeNotifier) {
|
|
|
|
this.props.resizeNotifier.removeListener("leftPanelResized", this.onResize);
|
|
|
|
}
|
2019-03-12 17:00:05 +00:00
|
|
|
|
2017-11-29 16:35:16 +00:00
|
|
|
|
2018-01-03 11:33:59 +00:00
|
|
|
if (this._tagStoreToken) {
|
|
|
|
this._tagStoreToken.remove();
|
2017-11-29 16:35:16 +00:00
|
|
|
}
|
|
|
|
|
2018-02-15 11:23:00 +00:00
|
|
|
if (this._roomListStoreToken) {
|
|
|
|
this._roomListStoreToken.remove();
|
|
|
|
}
|
2019-02-06 14:24:17 +00:00
|
|
|
if (this._customTagStoreToken) {
|
|
|
|
this._customTagStoreToken.remove();
|
|
|
|
}
|
2018-02-15 11:23:00 +00:00
|
|
|
|
2018-05-01 10:18:45 +00:00
|
|
|
// NB: GroupStore is not a Flux.Store
|
2018-05-01 10:38:57 +00:00
|
|
|
if (this._groupStoreToken) {
|
|
|
|
this._groupStoreToken.unregister();
|
|
|
|
}
|
2017-12-15 14:12:21 +00:00
|
|
|
|
2016-08-10 12:39:47 +00:00
|
|
|
// cancel any pending calls to the rate_limited_funcs
|
|
|
|
this._delayedRefreshRoomList.cancelPendingCall();
|
2015-11-30 16:55:00 +00:00
|
|
|
},
|
|
|
|
|
2019-03-12 17:00:05 +00:00
|
|
|
|
|
|
|
onResize: function() {
|
2019-01-25 17:48:25 +00:00
|
|
|
if (this.mounted && this._layout && this.resizeContainer &&
|
|
|
|
Array.isArray(this._layoutSections)
|
|
|
|
) {
|
|
|
|
this._layout.update(
|
|
|
|
this._layoutSections,
|
2019-03-12 17:00:05 +00:00
|
|
|
this.resizeContainer.offsetHeight,
|
2019-01-25 17:48:25 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
},
|
2015-11-30 16:55:00 +00:00
|
|
|
|
|
|
|
onRoom: function(room) {
|
2018-01-05 12:33:26 +00:00
|
|
|
this.updateVisibleRooms();
|
2015-11-30 16:55:00 +00:00
|
|
|
},
|
|
|
|
|
2019-01-10 22:43:22 +00:00
|
|
|
onRoomStateEvents: function(ev, state) {
|
|
|
|
if (ev.getType() === "m.room.create" || ev.getType() === "m.room.tombstone") {
|
|
|
|
this.updateVisibleRooms();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2015-12-16 16:27:46 +00:00
|
|
|
onDeleteRoom: function(roomId) {
|
2018-01-05 12:33:26 +00:00
|
|
|
this.updateVisibleRooms();
|
2015-12-16 16:27:46 +00:00
|
|
|
},
|
|
|
|
|
2016-08-30 10:55:51 +00:00
|
|
|
onArchivedHeaderClick: function(isHidden, scrollToPosition) {
|
2015-12-18 11:55:43 +00:00
|
|
|
if (!isHidden) {
|
2017-10-11 16:56:17 +00:00
|
|
|
const self = this;
|
2015-12-18 15:13:59 +00:00
|
|
|
this.setState({ isLoadingLeftRooms: true });
|
2015-12-18 11:55:43 +00:00
|
|
|
// we don't care about the response since it comes down via "Room"
|
|
|
|
// events.
|
|
|
|
MatrixClientPeg.get().syncLeftRooms().catch(function(err) {
|
|
|
|
console.error("Failed to sync left rooms: %s", err);
|
|
|
|
console.error(err);
|
2015-12-18 15:13:59 +00:00
|
|
|
}).finally(function() {
|
|
|
|
self.setState({ isLoadingLeftRooms: false });
|
2015-12-18 11:55:43 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2015-12-18 17:51:17 +00:00
|
|
|
onRoomReceipt: function(receiptEvent, room) {
|
|
|
|
// because if we read a notification, it will affect notification count
|
2016-01-07 10:38:44 +00:00
|
|
|
// only bother updating if there's a receipt from us
|
2016-09-09 15:59:59 +00:00
|
|
|
if (Receipt.findReadReceiptFromUserId(receiptEvent, MatrixClientPeg.get().credentials.userId)) {
|
2017-05-16 15:11:01 +00:00
|
|
|
this._delayedRefreshRoomList();
|
2016-01-07 10:38:44 +00:00
|
|
|
}
|
2015-12-18 17:51:17 +00:00
|
|
|
},
|
|
|
|
|
2015-11-30 16:55:00 +00:00
|
|
|
onRoomMemberName: function(ev, member) {
|
2017-05-16 15:11:01 +00:00
|
|
|
this._delayedRefreshRoomList();
|
2015-12-18 15:13:59 +00:00
|
|
|
},
|
|
|
|
|
2017-09-12 13:47:26 +00:00
|
|
|
onEventDecrypted: function(ev) {
|
|
|
|
// An event being decrypted may mean we need to re-order the room list
|
|
|
|
this._delayedRefreshRoomList();
|
|
|
|
},
|
|
|
|
|
2016-09-07 16:46:45 +00:00
|
|
|
onAccountData: function(ev) {
|
|
|
|
if (ev.getType() == 'm.direct') {
|
2017-04-24 14:44:45 +00:00
|
|
|
this._delayedRefreshRoomList();
|
2017-04-20 00:12:57 +00:00
|
|
|
}
|
2016-09-07 16:46:45 +00:00
|
|
|
},
|
|
|
|
|
2017-09-21 15:28:49 +00:00
|
|
|
_onGroupMyMembership: function(group) {
|
|
|
|
this.forceUpdate();
|
|
|
|
},
|
|
|
|
|
2019-02-11 15:17:15 +00:00
|
|
|
onMouseMove: async function(ev) {
|
|
|
|
if (!this._hoverClearTimer) {
|
|
|
|
this.setState({hover: true});
|
|
|
|
this._hoverClearTimer = new Timer(HOVER_MOVE_TIMEOUT);
|
|
|
|
this._hoverClearTimer.start();
|
|
|
|
let finished = true;
|
|
|
|
try {
|
|
|
|
await this._hoverClearTimer.finished();
|
|
|
|
} catch (err) {
|
|
|
|
finished = false;
|
|
|
|
}
|
|
|
|
this._hoverClearTimer = null;
|
|
|
|
if (finished) {
|
|
|
|
this.setState({hover: false});
|
|
|
|
this._delayedRefreshRoomList();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
this._hoverClearTimer.restart();
|
|
|
|
}
|
2019-01-03 20:57:20 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
onMouseLeave: function(ev) {
|
2019-02-11 15:17:15 +00:00
|
|
|
if (this._hoverClearTimer) {
|
|
|
|
this._hoverClearTimer.abort();
|
|
|
|
this._hoverClearTimer = null;
|
|
|
|
}
|
2019-01-03 20:57:20 +00:00
|
|
|
this.setState({hover: false});
|
|
|
|
|
|
|
|
// Refresh the room list just in case the user missed something.
|
|
|
|
this._delayedRefreshRoomList();
|
|
|
|
},
|
|
|
|
|
2016-02-04 18:06:24 +00:00
|
|
|
_delayedRefreshRoomList: new rate_limited_func(function() {
|
2017-05-16 15:11:01 +00:00
|
|
|
this.refreshRoomList();
|
2016-02-04 18:06:24 +00:00
|
|
|
}, 500),
|
2015-11-30 16:55:00 +00:00
|
|
|
|
2017-12-15 17:21:20 +00:00
|
|
|
// Update which rooms and users should appear in RoomList for a given group tag
|
2017-12-15 17:29:06 +00:00
|
|
|
updateVisibleRoomsForTag: function(dmRoomMap, tag) {
|
2017-11-29 16:35:16 +00:00
|
|
|
if (!this.mounted) return;
|
2017-12-15 14:23:35 +00:00
|
|
|
// For now, only handle group tags
|
2018-05-01 10:18:45 +00:00
|
|
|
if (tag[0] !== '+') return;
|
2017-12-15 14:23:35 +00:00
|
|
|
|
2017-12-15 17:29:06 +00:00
|
|
|
this._visibleRoomsForGroup[tag] = [];
|
2018-05-01 10:18:45 +00:00
|
|
|
GroupStore.getGroupRooms(tag).forEach((room) => this._visibleRoomsForGroup[tag].push(room.roomId));
|
|
|
|
GroupStore.getGroupMembers(tag).forEach((member) => {
|
2017-12-15 14:23:35 +00:00
|
|
|
if (member.userId === MatrixClientPeg.get().credentials.userId) return;
|
|
|
|
dmRoomMap.getDMRoomsForUserId(member.userId).forEach(
|
2017-12-15 17:29:06 +00:00
|
|
|
(roomId) => this._visibleRoomsForGroup[tag].push(roomId),
|
2017-12-15 14:23:35 +00:00
|
|
|
);
|
2017-12-05 11:25:30 +00:00
|
|
|
});
|
2017-12-15 14:23:35 +00:00
|
|
|
// TODO: Check if room has been tagged to the group by the user
|
|
|
|
},
|
2017-11-29 16:35:16 +00:00
|
|
|
|
2017-12-15 17:30:21 +00:00
|
|
|
// Update which rooms and users should appear according to which tags are selected
|
2017-12-15 17:29:06 +00:00
|
|
|
updateVisibleRooms: function() {
|
2018-01-05 10:23:20 +00:00
|
|
|
const selectedTags = TagOrderStore.getSelectedTags();
|
|
|
|
const visibleGroupRooms = [];
|
2018-01-04 11:50:33 +00:00
|
|
|
selectedTags.forEach((tag) => {
|
2017-12-15 17:29:06 +00:00
|
|
|
(this._visibleRoomsForGroup[tag] || []).forEach(
|
2018-01-05 10:23:20 +00:00
|
|
|
(roomId) => visibleGroupRooms.push(roomId),
|
2017-11-29 16:35:16 +00:00
|
|
|
);
|
|
|
|
});
|
2017-12-05 11:25:30 +00:00
|
|
|
|
2018-01-04 11:50:33 +00:00
|
|
|
// If there are any tags selected, constrain the rooms listed to the
|
|
|
|
// visible rooms as determined by visibleGroupRooms. Here, we
|
|
|
|
// de-duplicate and filter out rooms that the client doesn't know
|
|
|
|
// about (hence the Set and the null-guard on `room`).
|
|
|
|
if (selectedTags.length > 0) {
|
|
|
|
const roomSet = new Set();
|
|
|
|
visibleGroupRooms.forEach((roomId) => {
|
|
|
|
const room = MatrixClientPeg.get().getRoom(roomId);
|
|
|
|
if (room) {
|
|
|
|
roomSet.add(room);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
this._visibleRooms = Array.from(roomSet);
|
|
|
|
} else {
|
|
|
|
// Show all rooms
|
2018-08-22 11:01:29 +00:00
|
|
|
this._visibleRooms = MatrixClientPeg.get().getVisibleRooms();
|
2018-01-04 11:50:33 +00:00
|
|
|
}
|
2018-01-15 14:42:41 +00:00
|
|
|
this._delayedRefreshRoomList();
|
2017-11-29 16:35:16 +00:00
|
|
|
},
|
|
|
|
|
2015-11-30 16:55:00 +00:00
|
|
|
refreshRoomList: function() {
|
2019-01-03 20:57:20 +00:00
|
|
|
if (this.state.hover) {
|
|
|
|
// Don't re-sort the list if we're hovering over the list
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-04-26 17:59:16 +00:00
|
|
|
// TODO: ideally we'd calculate this once at start, and then maintain
|
|
|
|
// any changes to it incrementally, updating the appropriate sublists
|
|
|
|
// as needed.
|
|
|
|
// Alternatively we'd do something magical with Immutable.js or similar.
|
|
|
|
const lists = this.getRoomLists();
|
|
|
|
let totalRooms = 0;
|
|
|
|
for (const l of Object.values(lists)) {
|
|
|
|
totalRooms += l.length;
|
|
|
|
}
|
|
|
|
this.setState({
|
2018-01-25 21:16:03 +00:00
|
|
|
lists,
|
2017-04-26 17:59:16 +00:00
|
|
|
totalRoomCount: totalRooms,
|
2018-01-15 14:42:41 +00:00
|
|
|
// Do this here so as to not render every time the selected tags
|
|
|
|
// themselves change.
|
|
|
|
selectedTags: TagOrderStore.getSelectedTags(),
|
2018-12-18 13:26:33 +00:00
|
|
|
}, () => {
|
|
|
|
// we don't need to restore any size here, do we?
|
|
|
|
// i guess we could have triggered a new group to appear
|
|
|
|
// that already an explicit size the last time it appeared ...
|
|
|
|
this._checkSubListsOverflow();
|
2017-04-26 17:59:16 +00:00
|
|
|
});
|
2017-05-16 13:49:55 +00:00
|
|
|
|
2017-04-15 12:23:52 +00:00
|
|
|
// this._lastRefreshRoomListTs = Date.now();
|
2015-11-30 16:55:00 +00:00
|
|
|
},
|
|
|
|
|
2018-12-06 18:45:58 +00:00
|
|
|
getTagNameForRoomId: function(roomId) {
|
|
|
|
const lists = RoomListStore.getRoomLists();
|
|
|
|
for (const tagName of Object.keys(lists)) {
|
|
|
|
for (const room of lists[tagName]) {
|
|
|
|
// Should be impossible, but guard anyways.
|
|
|
|
if (!room) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
const myUserId = MatrixClientPeg.get().getUserId();
|
|
|
|
if (HIDE_CONFERENCE_CHANS && Rooms.isConfCallRoom(room, myUserId, this.props.ConferenceHandler)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (room.roomId === roomId) return tagName;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
},
|
|
|
|
|
2015-11-30 16:55:00 +00:00
|
|
|
getRoomLists: function() {
|
2018-01-25 21:16:03 +00:00
|
|
|
const lists = RoomListStore.getRoomLists();
|
2015-11-30 16:55:00 +00:00
|
|
|
|
2018-01-25 21:16:03 +00:00
|
|
|
const filteredLists = {};
|
2018-01-03 17:12:31 +00:00
|
|
|
|
2018-02-06 09:55:58 +00:00
|
|
|
const isRoomVisible = {
|
|
|
|
// $roomId: true,
|
|
|
|
};
|
|
|
|
|
|
|
|
this._visibleRooms.forEach((r) => {
|
|
|
|
isRoomVisible[r.roomId] = true;
|
|
|
|
});
|
|
|
|
|
2018-01-25 21:16:03 +00:00
|
|
|
Object.keys(lists).forEach((tagName) => {
|
2018-02-16 17:11:04 +00:00
|
|
|
const filteredRooms = lists[tagName].filter((taggedRoom) => {
|
2018-01-25 21:16:03 +00:00
|
|
|
// Somewhat impossible, but guard against it anyway
|
|
|
|
if (!taggedRoom) {
|
|
|
|
return;
|
|
|
|
}
|
2018-07-25 12:54:10 +00:00
|
|
|
const myUserId = MatrixClientPeg.get().getUserId();
|
|
|
|
if (HIDE_CONFERENCE_CHANS && Rooms.isConfCallRoom(taggedRoom, myUserId, this.props.ConferenceHandler)) {
|
2018-01-25 21:16:03 +00:00
|
|
|
return;
|
2016-08-11 15:45:19 +00:00
|
|
|
}
|
2017-04-18 01:43:29 +00:00
|
|
|
|
2018-02-12 18:35:13 +00:00
|
|
|
return Boolean(isRoomVisible[taggedRoom.roomId]);
|
2018-01-25 21:16:03 +00:00
|
|
|
});
|
2018-03-21 12:00:56 +00:00
|
|
|
|
2018-02-16 17:11:04 +00:00
|
|
|
if (filteredRooms.length > 0 || tagName.match(STANDARD_TAGS_REGEX)) {
|
|
|
|
filteredLists[tagName] = filteredRooms;
|
|
|
|
}
|
2018-01-25 21:16:03 +00:00
|
|
|
});
|
2017-04-26 17:59:16 +00:00
|
|
|
|
2018-01-25 21:16:03 +00:00
|
|
|
return filteredLists;
|
2015-11-30 16:55:00 +00:00
|
|
|
},
|
|
|
|
|
2015-12-17 02:49:09 +00:00
|
|
|
_getScrollNode: function() {
|
2017-05-18 16:33:32 +00:00
|
|
|
if (!this.mounted) return null;
|
2017-10-11 16:56:17 +00:00
|
|
|
const panel = ReactDOM.findDOMNode(this);
|
2015-12-17 02:49:09 +00:00
|
|
|
if (!panel) return null;
|
|
|
|
|
2017-05-18 18:03:51 +00:00
|
|
|
if (panel.classList.contains('gm-prevented')) {
|
|
|
|
return panel;
|
|
|
|
} else {
|
|
|
|
return panel.children[2]; // XXX: Fragile!
|
|
|
|
}
|
2015-12-17 02:49:09 +00:00
|
|
|
},
|
|
|
|
|
2016-08-25 18:46:01 +00:00
|
|
|
_whenScrolling: function(e) {
|
2016-09-03 11:44:55 +00:00
|
|
|
this._hideTooltip(e);
|
2015-12-17 02:49:09 +00:00
|
|
|
this._repositionIncomingCallBox(e, false);
|
|
|
|
},
|
|
|
|
|
2016-09-03 11:44:55 +00:00
|
|
|
_hideTooltip: function(e) {
|
|
|
|
// Hide tooltip when scrolling, as we'll no longer be over the one we were on
|
|
|
|
if (this.tooltip && this.tooltip.style.display !== "none") {
|
|
|
|
this.tooltip.style.display = "none";
|
2015-12-17 02:49:09 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
_repositionIncomingCallBox: function(e, firstTime) {
|
2017-10-11 16:56:17 +00:00
|
|
|
const incomingCallBox = document.getElementById("incomingCallBox");
|
2015-12-17 02:49:09 +00:00
|
|
|
if (incomingCallBox && incomingCallBox.parentElement) {
|
2017-10-11 16:56:17 +00:00
|
|
|
const scrollArea = this._getScrollNode();
|
2017-05-18 16:33:32 +00:00
|
|
|
if (!scrollArea) return;
|
2016-09-15 13:39:34 +00:00
|
|
|
// Use the offset of the top of the scroll area from the window
|
|
|
|
// as this is used to calculate the CSS fixed top position for the stickies
|
2017-10-11 16:56:17 +00:00
|
|
|
const scrollAreaOffset = scrollArea.getBoundingClientRect().top + window.pageYOffset;
|
2017-04-22 16:28:28 +00:00
|
|
|
// Use the offset of the top of the component from the window
|
2016-09-15 14:33:08 +00:00
|
|
|
// as this is used to calculate the CSS fixed top position for the stickies
|
2017-10-11 16:56:17 +00:00
|
|
|
const scrollAreaHeight = ReactDOM.findDOMNode(this).getBoundingClientRect().height;
|
2016-09-15 13:39:34 +00:00
|
|
|
|
2017-10-11 16:56:17 +00:00
|
|
|
let top = (incomingCallBox.parentElement.getBoundingClientRect().top + window.pageYOffset);
|
2016-09-15 14:33:08 +00:00
|
|
|
// Make sure we don't go too far up, if the headers aren't sticky
|
|
|
|
top = (top < scrollAreaOffset) ? scrollAreaOffset : top;
|
|
|
|
// make sure we don't go too far down, if the headers aren't sticky
|
2017-10-11 16:56:17 +00:00
|
|
|
const bottomMargin = scrollAreaOffset + (scrollAreaHeight - 45);
|
2016-09-15 14:33:08 +00:00
|
|
|
top = (top > bottomMargin) ? bottomMargin : top;
|
2016-02-19 02:21:17 +00:00
|
|
|
|
2015-12-17 02:49:09 +00:00
|
|
|
incomingCallBox.style.top = top + "px";
|
2016-09-15 14:33:08 +00:00
|
|
|
incomingCallBox.style.left = scrollArea.offsetLeft + scrollArea.offsetWidth + 12 + "px";
|
2015-11-30 16:55:00 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2017-05-04 12:55:52 +00:00
|
|
|
_getHeaderItems: function(section) {
|
2017-05-05 13:25:18 +00:00
|
|
|
const StartChatButton = sdk.getComponent('elements.StartChatButton');
|
|
|
|
const RoomDirectoryButton = sdk.getComponent('elements.RoomDirectoryButton');
|
|
|
|
const CreateRoomButton = sdk.getComponent('elements.CreateRoomButton');
|
2017-05-04 12:55:52 +00:00
|
|
|
switch (section) {
|
|
|
|
case 'im.vector.fake.direct':
|
|
|
|
return <span className="mx_RoomList_headerButtons">
|
2017-05-05 16:51:14 +00:00
|
|
|
<StartChatButton size="16" />
|
2017-05-04 12:55:52 +00:00
|
|
|
</span>;
|
|
|
|
case 'im.vector.fake.recent':
|
|
|
|
return <span className="mx_RoomList_headerButtons">
|
2017-05-05 16:51:14 +00:00
|
|
|
<RoomDirectoryButton size="16" />
|
|
|
|
<CreateRoomButton size="16" />
|
2017-05-04 12:55:52 +00:00
|
|
|
</span>;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2018-06-14 13:18:39 +00:00
|
|
|
_makeGroupInviteTiles(filter) {
|
2017-08-18 10:22:50 +00:00
|
|
|
const ret = [];
|
2018-06-14 13:18:39 +00:00
|
|
|
const lcFilter = filter && filter.toLowerCase();
|
2017-08-18 10:22:50 +00:00
|
|
|
|
|
|
|
const GroupInviteTile = sdk.getComponent('groups.GroupInviteTile');
|
|
|
|
for (const group of MatrixClientPeg.get().getGroups()) {
|
2018-06-14 15:48:00 +00:00
|
|
|
const {groupId, name, myMembership} = group;
|
2018-06-14 13:18:39 +00:00
|
|
|
// filter to only groups in invite state and group_id starts with filter or group name includes it
|
2018-06-14 15:48:00 +00:00
|
|
|
if (myMembership !== 'invite') continue;
|
|
|
|
if (lcFilter && !groupId.toLowerCase().startsWith(lcFilter) &&
|
2018-06-14 13:18:39 +00:00
|
|
|
!(name && name.toLowerCase().includes(lcFilter))) continue;
|
2018-06-14 15:48:00 +00:00
|
|
|
ret.push(<GroupInviteTile key={groupId} group={group} collapsed={this.props.collapsed} />);
|
2017-08-18 10:22:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
},
|
|
|
|
|
2018-11-02 14:27:17 +00:00
|
|
|
_applySearchFilter: function(list, filter) {
|
|
|
|
if (filter === "") return list;
|
|
|
|
const lcFilter = filter.toLowerCase();
|
|
|
|
// case insensitive if room name includes filter,
|
|
|
|
// or if starts with `#` and one of room's aliases starts with filter
|
|
|
|
return list.filter((room) => (room.name && room.name.toLowerCase().includes(lcFilter)) ||
|
|
|
|
(filter[0] === '#' && room.getAliases().some((alias) => alias.toLowerCase().startsWith(lcFilter))));
|
2018-03-21 15:58:14 +00:00
|
|
|
},
|
|
|
|
|
2018-12-18 09:56:00 +00:00
|
|
|
_handleCollapsedState: function(key, collapsed) {
|
|
|
|
// persist collapsed state
|
2018-12-03 09:39:31 +00:00
|
|
|
this.collapsedState[key] = collapsed;
|
|
|
|
window.localStorage.setItem("mx_roomlist_collapsed", JSON.stringify(this.collapsedState));
|
2018-12-18 09:56:00 +00:00
|
|
|
// load the persisted size configuration of the expanded sub list
|
2019-01-28 13:35:04 +00:00
|
|
|
if (collapsed) {
|
|
|
|
this._layout.collapseSection(key);
|
|
|
|
} else {
|
|
|
|
this._layout.expandSection(key, this.subListSizes[key]);
|
2018-12-18 09:56:00 +00:00
|
|
|
}
|
|
|
|
// check overflow, as sub lists sizes have changed
|
|
|
|
// important this happens after calling resize above
|
2018-12-18 13:26:33 +00:00
|
|
|
this._checkSubListsOverflow();
|
|
|
|
},
|
2017-08-18 10:22:50 +00:00
|
|
|
|
2018-12-18 13:26:33 +00:00
|
|
|
// check overflow for scroll indicator gradient
|
|
|
|
_checkSubListsOverflow() {
|
2018-12-18 09:56:00 +00:00
|
|
|
Object.values(this._subListRefs).forEach(l => l.checkOverflow());
|
2018-12-03 09:39:31 +00:00
|
|
|
},
|
|
|
|
|
2018-12-14 16:06:51 +00:00
|
|
|
_subListRef: function(key, ref) {
|
|
|
|
if (!ref) {
|
|
|
|
delete this._subListRefs[key];
|
|
|
|
} else {
|
|
|
|
this._subListRefs[key] = ref;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2018-11-02 14:27:17 +00:00
|
|
|
_mapSubListProps: function(subListsProps) {
|
2019-01-24 14:43:49 +00:00
|
|
|
this._layoutSections = [];
|
2018-11-02 14:27:17 +00:00
|
|
|
const defaultProps = {
|
|
|
|
collapsed: this.props.collapsed,
|
|
|
|
isFiltered: !!this.props.searchFilter,
|
|
|
|
incomingCall: this.state.incomingCall,
|
|
|
|
};
|
|
|
|
|
|
|
|
subListsProps.forEach((p) => {
|
|
|
|
p.list = this._applySearchFilter(p.list, this.props.searchFilter);
|
|
|
|
});
|
2018-06-30 16:07:28 +00:00
|
|
|
|
2018-11-02 14:27:17 +00:00
|
|
|
subListsProps = subListsProps.filter((props => {
|
|
|
|
const len = props.list.length + (props.extraTiles ? props.extraTiles.length : 0);
|
2019-01-22 16:54:04 +00:00
|
|
|
return len !== 0 || props.onAddRoom;
|
2018-11-02 14:27:17 +00:00
|
|
|
}));
|
|
|
|
|
|
|
|
return subListsProps.reduce((components, props, i) => {
|
|
|
|
props = Object.assign({}, defaultProps, props);
|
|
|
|
const isLast = i === subListsProps.length - 1;
|
2019-01-24 14:43:49 +00:00
|
|
|
const len = props.list.length + (props.extraTiles ? props.extraTiles.length : 0);
|
2018-12-03 09:39:31 +00:00
|
|
|
const {key, label, onHeaderClick, ... otherProps} = props;
|
2018-11-02 14:27:17 +00:00
|
|
|
const chosenKey = key || label;
|
2018-12-03 09:39:31 +00:00
|
|
|
const onSubListHeaderClick = (collapsed) => {
|
2018-12-18 09:56:00 +00:00
|
|
|
this._handleCollapsedState(chosenKey, collapsed);
|
2018-12-03 09:39:31 +00:00
|
|
|
if (onHeaderClick) {
|
|
|
|
onHeaderClick(collapsed);
|
|
|
|
}
|
|
|
|
};
|
2019-01-28 17:28:04 +00:00
|
|
|
let startAsHidden = props.startAsHidden || this.collapsedState[chosenKey];
|
2019-01-24 14:43:49 +00:00
|
|
|
this._layoutSections.push({
|
|
|
|
id: chosenKey,
|
|
|
|
count: len,
|
|
|
|
});
|
2018-12-03 09:39:31 +00:00
|
|
|
let subList = (<RoomSubList
|
2018-12-14 16:06:51 +00:00
|
|
|
ref={this._subListRef.bind(this, chosenKey)}
|
2018-12-03 09:39:31 +00:00
|
|
|
startAsHidden={startAsHidden}
|
2019-01-28 17:28:04 +00:00
|
|
|
forceExpand={!!this.props.searchFilter}
|
2018-12-03 09:39:31 +00:00
|
|
|
onHeaderClick={onSubListHeaderClick}
|
|
|
|
key={chosenKey}
|
|
|
|
label={label}
|
|
|
|
{...otherProps} />);
|
2018-11-02 14:27:17 +00:00
|
|
|
|
|
|
|
if (!isLast) {
|
|
|
|
return components.concat(
|
|
|
|
subList,
|
2018-11-26 15:46:57 +00:00
|
|
|
<ResizeHandle key={chosenKey+"-resizer"} vertical={true} id={chosenKey} />
|
2018-11-02 14:27:17 +00:00
|
|
|
);
|
|
|
|
} else {
|
|
|
|
return components.concat(subList);
|
|
|
|
}
|
|
|
|
}, []);
|
|
|
|
},
|
|
|
|
|
2018-11-26 15:46:57 +00:00
|
|
|
_collectResizeContainer: function(el) {
|
|
|
|
this.resizeContainer = el;
|
|
|
|
},
|
|
|
|
|
2018-11-02 14:27:17 +00:00
|
|
|
render: function() {
|
2018-12-06 18:45:58 +00:00
|
|
|
const incomingCallIfTaggedAs = (tagName) => {
|
|
|
|
if (!this.state.incomingCall) return null;
|
|
|
|
if (this.state.incomingCallTag !== tagName) return null;
|
|
|
|
return this.state.incomingCall;
|
|
|
|
};
|
|
|
|
|
2018-10-18 13:09:58 +00:00
|
|
|
let subLists = [
|
|
|
|
{
|
|
|
|
list: [],
|
2018-10-19 12:43:54 +00:00
|
|
|
extraTiles: this._makeGroupInviteTiles(this.props.searchFilter),
|
2018-10-18 13:09:58 +00:00
|
|
|
label: _t('Community Invites'),
|
|
|
|
order: "recent",
|
|
|
|
isInvite: true,
|
|
|
|
},
|
|
|
|
{
|
2018-10-19 12:43:54 +00:00
|
|
|
list: this.state.lists['im.vector.fake.invite'],
|
2018-10-18 13:09:58 +00:00
|
|
|
label: _t('Invites'),
|
|
|
|
order: "recent",
|
2019-01-03 23:00:23 +00:00
|
|
|
incomingCall: incomingCallIfTaggedAs('im.vector.fake.invite'),
|
2018-10-18 13:09:58 +00:00
|
|
|
isInvite: true,
|
|
|
|
},
|
|
|
|
{
|
2018-10-19 12:43:54 +00:00
|
|
|
list: this.state.lists['m.favourite'],
|
2018-10-18 13:09:58 +00:00
|
|
|
label: _t('Favourites'),
|
|
|
|
tagName: "m.favourite",
|
|
|
|
order: "manual",
|
2019-01-03 23:00:23 +00:00
|
|
|
incomingCall: incomingCallIfTaggedAs('m.favourite'),
|
2018-10-18 13:09:58 +00:00
|
|
|
},
|
|
|
|
{
|
2018-10-19 12:43:54 +00:00
|
|
|
list: this.state.lists['im.vector.fake.direct'],
|
2018-10-18 13:09:58 +00:00
|
|
|
label: _t('People'),
|
|
|
|
tagName: "im.vector.fake.direct",
|
|
|
|
headerItems: this._getHeaderItems('im.vector.fake.direct'),
|
|
|
|
order: "recent",
|
2019-01-03 23:00:23 +00:00
|
|
|
incomingCall: incomingCallIfTaggedAs('im.vector.fake.direct'),
|
2018-10-19 10:07:36 +00:00
|
|
|
onAddRoom: () => {dis.dispatch({action: 'view_create_chat'})},
|
2019-05-21 18:16:34 +00:00
|
|
|
addRoomLabel: _t("Start chat"),
|
2018-10-18 13:09:58 +00:00
|
|
|
},
|
|
|
|
{
|
2018-10-19 12:43:54 +00:00
|
|
|
list: this.state.lists['im.vector.fake.recent'],
|
2018-10-18 13:09:58 +00:00
|
|
|
label: _t('Rooms'),
|
|
|
|
headerItems: this._getHeaderItems('im.vector.fake.recent'),
|
|
|
|
order: "recent",
|
2019-01-03 23:00:23 +00:00
|
|
|
incomingCall: incomingCallIfTaggedAs('im.vector.fake.recent'),
|
2019-01-29 14:34:58 +00:00
|
|
|
onAddRoom: () => {dis.dispatch({action: 'view_room_directory'})},
|
2018-10-18 13:09:58 +00:00
|
|
|
},
|
|
|
|
];
|
2018-10-19 12:43:54 +00:00
|
|
|
const tagSubLists = Object.keys(this.state.lists)
|
2018-10-18 13:09:58 +00:00
|
|
|
.filter((tagName) => {
|
2019-02-08 12:03:58 +00:00
|
|
|
return (!this.state.customTags || this.state.customTags[tagName]) &&
|
2019-02-07 18:04:30 +00:00
|
|
|
!tagName.match(STANDARD_TAGS_REGEX);
|
2018-10-18 13:09:58 +00:00
|
|
|
}).map((tagName) => {
|
|
|
|
return {
|
2018-10-19 12:43:54 +00:00
|
|
|
list: this.state.lists[tagName],
|
2018-10-18 13:09:58 +00:00
|
|
|
key: tagName,
|
|
|
|
label: labelForTagName(tagName),
|
|
|
|
tagName: tagName,
|
|
|
|
order: "manual",
|
2019-01-03 23:00:23 +00:00
|
|
|
incomingCall: incomingCallIfTaggedAs(tagName),
|
2018-10-18 13:09:58 +00:00
|
|
|
};
|
|
|
|
});
|
|
|
|
subLists = subLists.concat(tagSubLists);
|
|
|
|
subLists = subLists.concat([
|
|
|
|
{
|
2018-10-19 12:43:54 +00:00
|
|
|
list: this.state.lists['m.lowpriority'],
|
2018-10-18 13:09:58 +00:00
|
|
|
label: _t('Low priority'),
|
|
|
|
tagName: "m.lowpriority",
|
|
|
|
order: "recent",
|
2019-01-03 23:00:23 +00:00
|
|
|
incomingCall: incomingCallIfTaggedAs('m.lowpriority'),
|
2018-10-18 13:09:58 +00:00
|
|
|
},
|
|
|
|
{
|
2018-10-19 12:43:54 +00:00
|
|
|
list: this.state.lists['im.vector.fake.archived'],
|
2018-10-18 13:09:58 +00:00
|
|
|
label: _t('Historical'),
|
|
|
|
order: "recent",
|
2019-01-03 23:00:23 +00:00
|
|
|
incomingCall: incomingCallIfTaggedAs('im.vector.fake.archived'),
|
2018-10-18 13:09:58 +00:00
|
|
|
startAsHidden: true,
|
2018-10-19 12:43:54 +00:00
|
|
|
showSpinner: this.state.isLoadingLeftRooms,
|
|
|
|
onHeaderClick: this.onArchivedHeaderClick,
|
2018-10-18 13:09:58 +00:00
|
|
|
},
|
|
|
|
{
|
2018-10-19 12:43:54 +00:00
|
|
|
list: this.state.lists['m.server_notice'],
|
2018-10-18 13:09:58 +00:00
|
|
|
label: _t('System Alerts'),
|
|
|
|
tagName: "m.lowpriority",
|
|
|
|
order: "recent",
|
2019-01-03 23:00:23 +00:00
|
|
|
incomingCall: incomingCallIfTaggedAs('m.server_notice'),
|
2018-10-18 13:09:58 +00:00
|
|
|
},
|
|
|
|
]);
|
|
|
|
|
2018-11-02 14:27:17 +00:00
|
|
|
const subListComponents = this._mapSubListProps(subLists);
|
2018-10-18 13:09:58 +00:00
|
|
|
|
2015-11-30 16:55:00 +00:00
|
|
|
return (
|
2019-01-03 20:57:20 +00:00
|
|
|
<div ref={this._collectResizeContainer} className="mx_RoomList"
|
2019-02-11 15:17:15 +00:00
|
|
|
onMouseMove={this.onMouseMove} onMouseLeave={this.onMouseLeave}>
|
2018-10-18 13:09:58 +00:00
|
|
|
{ subListComponents }
|
2018-01-25 20:58:35 +00:00
|
|
|
</div>
|
2015-11-30 16:55:00 +00:00
|
|
|
);
|
2017-10-11 16:56:17 +00:00
|
|
|
},
|
2019-01-10 17:40:26 +00:00
|
|
|
});
|