Revert "Merge pull request #807 from matrix-org/matthew/quick-search"
This reverts commit0ad1d8caf3
, reversing changes made to1189368aab
.
This commit is contained in:
parent
67c6a8b81d
commit
ebfafb3639
7 changed files with 99 additions and 265 deletions
|
@ -69,7 +69,7 @@
|
||||||
"react": "^15.4.0",
|
"react": "^15.4.0",
|
||||||
"react-addons-css-transition-group": "15.3.2",
|
"react-addons-css-transition-group": "15.3.2",
|
||||||
"react-dom": "^15.4.0",
|
"react-dom": "^15.4.0",
|
||||||
"react-gemini-scrollbar": "matrix-org/react-gemini-scrollbar#39d858c",
|
"react-gemini-scrollbar": "matrix-org/react-gemini-scrollbar#5e97aef",
|
||||||
"sanitize-html": "^1.11.1",
|
"sanitize-html": "^1.11.1",
|
||||||
"text-encoding-utf-8": "^1.0.1",
|
"text-encoding-utf-8": "^1.0.1",
|
||||||
"velocity-vector": "vector-im/velocity#059e3b2",
|
"velocity-vector": "vector-im/velocity#059e3b2",
|
||||||
|
|
|
@ -1,62 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2017 Vector Creations 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// singleton which dispatches invocations of a given type & argument
|
|
||||||
// rather than just a type (as per EventEmitter and Flux's dispatcher etc)
|
|
||||||
//
|
|
||||||
// This means you can have a single point which listens for an EventEmitter event
|
|
||||||
// and then dispatches out to one of thousands of RoomTiles (for instance) rather than
|
|
||||||
// having each RoomTile register for the EventEmitter event and having to
|
|
||||||
// iterate over all of them.
|
|
||||||
class ConstantTimeDispatcher {
|
|
||||||
constructor() {
|
|
||||||
// type -> arg -> [ listener(arg, params) ]
|
|
||||||
this.listeners = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
register(type, arg, listener) {
|
|
||||||
if (!this.listeners[type]) this.listeners[type] = {};
|
|
||||||
if (!this.listeners[type][arg]) this.listeners[type][arg] = [];
|
|
||||||
this.listeners[type][arg].push(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
unregister(type, arg, listener) {
|
|
||||||
if (this.listeners[type] && this.listeners[type][arg]) {
|
|
||||||
var i = this.listeners[type][arg].indexOf(listener);
|
|
||||||
if (i > -1) {
|
|
||||||
this.listeners[type][arg].splice(i, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.warn("Unregistering unrecognised listener (type=" + type + ", arg=" + arg + ")");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatch(type, arg, params) {
|
|
||||||
if (!this.listeners[type] || !this.listeners[type][arg]) {
|
|
||||||
console.warn("No registered listeners for dispatch (type=" + type + ", arg=" + arg + ")");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.listeners[type][arg].forEach(listener=>{
|
|
||||||
listener.call(arg, params);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!global.constantTimeDispatcher) {
|
|
||||||
global.constantTimeDispatcher = new ConstantTimeDispatcher();
|
|
||||||
}
|
|
||||||
module.exports = global.constantTimeDispatcher;
|
|
|
@ -32,5 +32,4 @@ module.exports = {
|
||||||
DELETE: 46,
|
DELETE: 46,
|
||||||
KEY_D: 68,
|
KEY_D: 68,
|
||||||
KEY_E: 69,
|
KEY_E: 69,
|
||||||
KEY_K: 75,
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -590,7 +590,6 @@ var TimelinePanel = React.createClass({
|
||||||
this.props.timelineSet.room.setUnreadNotificationCount('highlight', 0);
|
this.props.timelineSet.room.setUnreadNotificationCount('highlight', 0);
|
||||||
dis.dispatch({
|
dis.dispatch({
|
||||||
action: 'on_room_read',
|
action: 'on_room_read',
|
||||||
room: this.props.timelineSet.room,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,12 +47,6 @@ export default React.createClass({
|
||||||
this.props.onFinished(false);
|
this.props.onFinished(false);
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidMount: function() {
|
|
||||||
if (this.props.focus) {
|
|
||||||
this.refs.button.focus();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||||
const cancelButton = this.props.hasCancelButton ? (
|
const cancelButton = this.props.hasCancelButton ? (
|
||||||
|
@ -69,7 +63,7 @@ export default React.createClass({
|
||||||
{this.props.description}
|
{this.props.description}
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_Dialog_buttons">
|
<div className="mx_Dialog_buttons">
|
||||||
<button ref="button" className="mx_Dialog_primary" onClick={this.onOk}>
|
<button className="mx_Dialog_primary" onClick={this.onOk} autoFocus={this.props.focus}>
|
||||||
{this.props.button}
|
{this.props.button}
|
||||||
</button>
|
</button>
|
||||||
{this.props.extraButtons}
|
{this.props.extraButtons}
|
||||||
|
|
|
@ -21,13 +21,13 @@ var GeminiScrollbar = require('react-gemini-scrollbar');
|
||||||
var MatrixClientPeg = require("../../../MatrixClientPeg");
|
var MatrixClientPeg = require("../../../MatrixClientPeg");
|
||||||
var CallHandler = require('../../../CallHandler');
|
var CallHandler = require('../../../CallHandler');
|
||||||
var RoomListSorter = require("../../../RoomListSorter");
|
var RoomListSorter = require("../../../RoomListSorter");
|
||||||
|
var Unread = require('../../../Unread');
|
||||||
var dis = require("../../../dispatcher");
|
var dis = require("../../../dispatcher");
|
||||||
var sdk = require('../../../index');
|
var sdk = require('../../../index');
|
||||||
var rate_limited_func = require('../../../ratelimitedfunc');
|
var rate_limited_func = require('../../../ratelimitedfunc');
|
||||||
var Rooms = require('../../../Rooms');
|
var Rooms = require('../../../Rooms');
|
||||||
import DMRoomMap from '../../../utils/DMRoomMap';
|
import DMRoomMap from '../../../utils/DMRoomMap';
|
||||||
var Receipt = require('../../../utils/Receipt');
|
var Receipt = require('../../../utils/Receipt');
|
||||||
var constantTimeDispatcher = require('../../../ConstantTimeDispatcher');
|
|
||||||
|
|
||||||
var HIDE_CONFERENCE_CHANS = true;
|
var HIDE_CONFERENCE_CHANS = true;
|
||||||
|
|
||||||
|
@ -37,16 +37,10 @@ module.exports = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
ConferenceHandler: React.PropTypes.any,
|
ConferenceHandler: React.PropTypes.any,
|
||||||
collapsed: React.PropTypes.bool.isRequired,
|
collapsed: React.PropTypes.bool.isRequired,
|
||||||
selectedRoom: React.PropTypes.string,
|
currentRoom: React.PropTypes.string,
|
||||||
searchFilter: React.PropTypes.string,
|
searchFilter: React.PropTypes.string,
|
||||||
},
|
},
|
||||||
|
|
||||||
shouldComponentUpdate: function(nextProps, nextState) {
|
|
||||||
if (nextProps.collapsed !== this.props.collapsed) return true;
|
|
||||||
if (nextProps.searchFilter !== this.props.searchFilter) return true;
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
return {
|
return {
|
||||||
isLoadingLeftRooms: false,
|
isLoadingLeftRooms: false,
|
||||||
|
@ -63,18 +57,12 @@ module.exports = React.createClass({
|
||||||
cli.on("Room.name", this.onRoomName);
|
cli.on("Room.name", this.onRoomName);
|
||||||
cli.on("Room.tags", this.onRoomTags);
|
cli.on("Room.tags", this.onRoomTags);
|
||||||
cli.on("Room.receipt", this.onRoomReceipt);
|
cli.on("Room.receipt", this.onRoomReceipt);
|
||||||
cli.on("RoomState.members", this.onRoomStateMember);
|
cli.on("RoomState.events", this.onRoomStateEvents);
|
||||||
cli.on("RoomMember.name", this.onRoomMemberName);
|
cli.on("RoomMember.name", this.onRoomMemberName);
|
||||||
cli.on("accountData", this.onAccountData);
|
cli.on("accountData", this.onAccountData);
|
||||||
|
|
||||||
// lookup for which lists a given roomId is currently in.
|
|
||||||
this.listsForRoomId = {};
|
|
||||||
|
|
||||||
var s = this.getRoomLists();
|
var s = this.getRoomLists();
|
||||||
this.setState(s);
|
this.setState(s);
|
||||||
|
|
||||||
// order of the sublists
|
|
||||||
this.listOrder = [];
|
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
|
@ -83,22 +71,7 @@ module.exports = React.createClass({
|
||||||
this._updateStickyHeaders(true);
|
this._updateStickyHeaders(true);
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillReceiveProps: function(nextProps) {
|
componentDidUpdate: function() {
|
||||||
// short-circuit react when the room changes
|
|
||||||
// to avoid rerendering all the sublists everywhere
|
|
||||||
if (nextProps.selectedRoom !== this.props.selectedRoom) {
|
|
||||||
if (this.props.selectedRoom) {
|
|
||||||
constantTimeDispatcher.dispatch(
|
|
||||||
"RoomTile.select", this.props.selectedRoom, {}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
constantTimeDispatcher.dispatch(
|
|
||||||
"RoomTile.select", nextProps.selectedRoom, { selected: true }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
componentDidUpdate: function(prevProps, prevState) {
|
|
||||||
// Reinitialise the stickyHeaders when the component is updated
|
// Reinitialise the stickyHeaders when the component is updated
|
||||||
this._updateStickyHeaders(true);
|
this._updateStickyHeaders(true);
|
||||||
this._repositionIncomingCallBox(undefined, false);
|
this._repositionIncomingCallBox(undefined, false);
|
||||||
|
@ -124,24 +97,10 @@ module.exports = React.createClass({
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'on_room_read':
|
case 'on_room_read':
|
||||||
// poke the right RoomTile to refresh, using the constantTimeDispatcher
|
// Force an update because the notif count state is too deep to cause
|
||||||
// to avoid each and every RoomTile registering to the 'on_room_read' event
|
// an update. This forces the local echo of reading notifs to be
|
||||||
// XXX: if we like the constantTimeDispatcher we might want to dispatch
|
// reflected by the RoomTiles.
|
||||||
// directly from TimelinePanel rather than needlessly bouncing via here.
|
this.forceUpdate();
|
||||||
constantTimeDispatcher.dispatch(
|
|
||||||
"RoomTile.refresh", payload.room.roomId, {}
|
|
||||||
);
|
|
||||||
|
|
||||||
// also have to poke the right list(s)
|
|
||||||
var lists = this.listsForRoomId[payload.room.roomId];
|
|
||||||
if (lists) {
|
|
||||||
lists.forEach(list=>{
|
|
||||||
constantTimeDispatcher.dispatch(
|
|
||||||
"RoomSubList.refreshHeader", list, { room: payload.room }
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -155,7 +114,7 @@ module.exports = React.createClass({
|
||||||
MatrixClientPeg.get().removeListener("Room.name", this.onRoomName);
|
MatrixClientPeg.get().removeListener("Room.name", this.onRoomName);
|
||||||
MatrixClientPeg.get().removeListener("Room.tags", this.onRoomTags);
|
MatrixClientPeg.get().removeListener("Room.tags", this.onRoomTags);
|
||||||
MatrixClientPeg.get().removeListener("Room.receipt", this.onRoomReceipt);
|
MatrixClientPeg.get().removeListener("Room.receipt", this.onRoomReceipt);
|
||||||
MatrixClientPeg.get().removeListener("RoomState.members", this.onRoomStateMember);
|
MatrixClientPeg.get().removeListener("RoomState.events", this.onRoomStateEvents);
|
||||||
MatrixClientPeg.get().removeListener("RoomMember.name", this.onRoomMemberName);
|
MatrixClientPeg.get().removeListener("RoomMember.name", this.onRoomMemberName);
|
||||||
MatrixClientPeg.get().removeListener("accountData", this.onAccountData);
|
MatrixClientPeg.get().removeListener("accountData", this.onAccountData);
|
||||||
}
|
}
|
||||||
|
@ -164,14 +123,10 @@ module.exports = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
onRoom: function(room) {
|
onRoom: function(room) {
|
||||||
// XXX: this happens rarely; ideally we should only update the correct
|
|
||||||
// sublists when it does (e.g. via a constantTimeDispatch to the right sublist)
|
|
||||||
this._delayedRefreshRoomList();
|
this._delayedRefreshRoomList();
|
||||||
},
|
},
|
||||||
|
|
||||||
onDeleteRoom: function(roomId) {
|
onDeleteRoom: function(roomId) {
|
||||||
// XXX: this happens rarely; ideally we should only update the correct
|
|
||||||
// sublists when it does (e.g. via a constantTimeDispatch to the right sublist)
|
|
||||||
this._delayedRefreshRoomList();
|
this._delayedRefreshRoomList();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -194,10 +149,6 @@ module.exports = React.createClass({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_onMouseOver: function(ev) {
|
|
||||||
this._lastMouseOverTs = Date.now();
|
|
||||||
},
|
|
||||||
|
|
||||||
onSubListHeaderClick: function(isHidden, scrollToPosition) {
|
onSubListHeaderClick: function(isHidden, scrollToPosition) {
|
||||||
// The scroll area has expanded or contracted, so re-calculate sticky headers positions
|
// The scroll area has expanded or contracted, so re-calculate sticky headers positions
|
||||||
this._updateStickyHeaders(true, scrollToPosition);
|
this._updateStickyHeaders(true, scrollToPosition);
|
||||||
|
@ -207,89 +158,41 @@ module.exports = React.createClass({
|
||||||
if (toStartOfTimeline) return;
|
if (toStartOfTimeline) return;
|
||||||
if (!room) return;
|
if (!room) return;
|
||||||
if (data.timeline.getTimelineSet() !== room.getUnfilteredTimelineSet()) return;
|
if (data.timeline.getTimelineSet() !== room.getUnfilteredTimelineSet()) return;
|
||||||
|
this._delayedRefreshRoomList();
|
||||||
// rather than regenerate our full roomlists, which is very heavy, we poke the
|
|
||||||
// correct sublists to just re-sort themselves. This isn't enormously reacty,
|
|
||||||
// but is much faster than the default react reconciler, or having to do voodoo
|
|
||||||
// with shouldComponentUpdate and a pleaseRefresh property or similar.
|
|
||||||
var lists = this.listsForRoomId[room.roomId];
|
|
||||||
if (lists) {
|
|
||||||
lists.forEach(list=>{
|
|
||||||
constantTimeDispatcher.dispatch("RoomSubList.sort", list, { room: room });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// we have to explicitly hit the roomtile which just changed
|
|
||||||
constantTimeDispatcher.dispatch(
|
|
||||||
"RoomTile.refresh", room.roomId, {}
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onRoomReceipt: function(receiptEvent, room) {
|
onRoomReceipt: function(receiptEvent, room) {
|
||||||
// because if we read a notification, it will affect notification count
|
// because if we read a notification, it will affect notification count
|
||||||
// only bother updating if there's a receipt from us
|
// only bother updating if there's a receipt from us
|
||||||
if (Receipt.findReadReceiptFromUserId(receiptEvent, MatrixClientPeg.get().credentials.userId)) {
|
if (Receipt.findReadReceiptFromUserId(receiptEvent, MatrixClientPeg.get().credentials.userId)) {
|
||||||
var lists = this.listsForRoomId[room.roomId];
|
this._delayedRefreshRoomList();
|
||||||
if (lists) {
|
|
||||||
lists.forEach(list=>{
|
|
||||||
constantTimeDispatcher.dispatch(
|
|
||||||
"RoomSubList.refreshHeader", list, { room: room }
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// we have to explicitly hit the roomtile which just changed
|
|
||||||
constantTimeDispatcher.dispatch(
|
|
||||||
"RoomTile.refresh", room.roomId, {}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onRoomName: function(room) {
|
onRoomName: function(room) {
|
||||||
constantTimeDispatcher.dispatch(
|
|
||||||
"RoomTile.refresh", room.roomId, {}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
onRoomTags: function(event, room) {
|
|
||||||
// XXX: this happens rarely; ideally we should only update the correct
|
|
||||||
// sublists when it does (e.g. via a constantTimeDispatch to the right sublist)
|
|
||||||
this._delayedRefreshRoomList();
|
this._delayedRefreshRoomList();
|
||||||
},
|
},
|
||||||
|
|
||||||
onRoomStateMember: function(ev, state, member) {
|
onRoomTags: function(event, room) {
|
||||||
constantTimeDispatcher.dispatch(
|
this._delayedRefreshRoomList();
|
||||||
"RoomTile.refresh", member.roomId, {}
|
},
|
||||||
);
|
|
||||||
|
onRoomStateEvents: function(ev, state) {
|
||||||
|
this._delayedRefreshRoomList();
|
||||||
},
|
},
|
||||||
|
|
||||||
onRoomMemberName: function(ev, member) {
|
onRoomMemberName: function(ev, member) {
|
||||||
constantTimeDispatcher.dispatch(
|
this._delayedRefreshRoomList();
|
||||||
"RoomTile.refresh", member.roomId, {}
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onAccountData: function(ev) {
|
onAccountData: function(ev) {
|
||||||
if (ev.getType() == 'm.direct') {
|
if (ev.getType() == 'm.direct') {
|
||||||
// XXX: this happens rarely; ideally we should only update the correct
|
|
||||||
// sublists when it does (e.g. via a constantTimeDispatch to the right sublist)
|
|
||||||
this._delayedRefreshRoomList();
|
|
||||||
}
|
|
||||||
else if (ev.getType() == 'm.push_rules') {
|
|
||||||
this._delayedRefreshRoomList();
|
this._delayedRefreshRoomList();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_delayedRefreshRoomList: new rate_limited_func(function() {
|
_delayedRefreshRoomList: new rate_limited_func(function() {
|
||||||
// if the mouse has been moving over the RoomList in the last 500ms
|
this.refreshRoomList();
|
||||||
// then delay the refresh further to avoid bouncing around under the
|
|
||||||
// cursor
|
|
||||||
if (Date.now() - this._lastMouseOverTs > 500) {
|
|
||||||
this.refreshRoomList();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this._delayedRefreshRoomList();
|
|
||||||
}
|
|
||||||
}, 500),
|
}, 500),
|
||||||
|
|
||||||
refreshRoomList: function() {
|
refreshRoomList: function() {
|
||||||
|
@ -297,10 +200,12 @@ module.exports = React.createClass({
|
||||||
// (!this._lastRefreshRoomListTs ? "-" : (Date.now() - this._lastRefreshRoomListTs))
|
// (!this._lastRefreshRoomListTs ? "-" : (Date.now() - this._lastRefreshRoomListTs))
|
||||||
// );
|
// );
|
||||||
|
|
||||||
// TODO: ideally we'd calculate this once at start, and then maintain
|
// TODO: rather than bluntly regenerating and re-sorting everything
|
||||||
// any changes to it incrementally, updating the appropriate sublists
|
// every time we see any kind of room change from the JS SDK
|
||||||
// as needed.
|
// we could do incremental updates on our copy of the state
|
||||||
// Alternatively we'd do something magical with Immutable.js or similar.
|
// based on the room which has actually changed. This would stop
|
||||||
|
// us re-rendering all the sublists every time anything changes anywhere
|
||||||
|
// in the state of the client.
|
||||||
this.setState(this.getRoomLists());
|
this.setState(this.getRoomLists());
|
||||||
|
|
||||||
// this._lastRefreshRoomListTs = Date.now();
|
// this._lastRefreshRoomListTs = Date.now();
|
||||||
|
@ -317,9 +222,6 @@ module.exports = React.createClass({
|
||||||
s.lists["m.lowpriority"] = [];
|
s.lists["m.lowpriority"] = [];
|
||||||
s.lists["im.vector.fake.archived"] = [];
|
s.lists["im.vector.fake.archived"] = [];
|
||||||
|
|
||||||
this.listsForRoomId = {};
|
|
||||||
var otherTagNames = {};
|
|
||||||
|
|
||||||
const dmRoomMap = new DMRoomMap(MatrixClientPeg.get());
|
const dmRoomMap = new DMRoomMap(MatrixClientPeg.get());
|
||||||
|
|
||||||
MatrixClientPeg.get().getRooms().forEach(function(room) {
|
MatrixClientPeg.get().getRooms().forEach(function(room) {
|
||||||
|
@ -331,12 +233,7 @@ module.exports = React.createClass({
|
||||||
// ", target = " + me.events.member.getStateKey() +
|
// ", target = " + me.events.member.getStateKey() +
|
||||||
// ", prevMembership = " + me.events.member.getPrevContent().membership);
|
// ", prevMembership = " + me.events.member.getPrevContent().membership);
|
||||||
|
|
||||||
if (!self.listsForRoomId[room.roomId]) {
|
|
||||||
self.listsForRoomId[room.roomId] = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (me.membership == "invite") {
|
if (me.membership == "invite") {
|
||||||
self.listsForRoomId[room.roomId].push("im.vector.fake.invite");
|
|
||||||
s.lists["im.vector.fake.invite"].push(room);
|
s.lists["im.vector.fake.invite"].push(room);
|
||||||
}
|
}
|
||||||
else if (HIDE_CONFERENCE_CHANS && Rooms.isConfCallRoom(room, me, self.props.ConferenceHandler)) {
|
else if (HIDE_CONFERENCE_CHANS && Rooms.isConfCallRoom(room, me, self.props.ConferenceHandler)) {
|
||||||
|
@ -347,27 +244,23 @@ module.exports = React.createClass({
|
||||||
{
|
{
|
||||||
// Used to split rooms via tags
|
// Used to split rooms via tags
|
||||||
var tagNames = Object.keys(room.tags);
|
var tagNames = Object.keys(room.tags);
|
||||||
|
|
||||||
if (tagNames.length) {
|
if (tagNames.length) {
|
||||||
for (var i = 0; i < tagNames.length; i++) {
|
for (var i = 0; i < tagNames.length; i++) {
|
||||||
var tagName = tagNames[i];
|
var tagName = tagNames[i];
|
||||||
s.lists[tagName] = s.lists[tagName] || [];
|
s.lists[tagName] = s.lists[tagName] || [];
|
||||||
s.lists[tagName].push(room);
|
s.lists[tagNames[i]].push(room);
|
||||||
self.listsForRoomId[room.roomId].push(tagName);
|
|
||||||
otherTagNames[tagName] = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (dmRoomMap.getUserIdForRoomId(room.roomId)) {
|
else if (dmRoomMap.getUserIdForRoomId(room.roomId)) {
|
||||||
// "Direct Message" rooms (that we're still in and that aren't otherwise tagged)
|
// "Direct Message" rooms (that we're still in and that aren't otherwise tagged)
|
||||||
self.listsForRoomId[room.roomId].push("im.vector.fake.direct");
|
|
||||||
s.lists["im.vector.fake.direct"].push(room);
|
s.lists["im.vector.fake.direct"].push(room);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
self.listsForRoomId[room.roomId].push("im.vector.fake.recent");
|
|
||||||
s.lists["im.vector.fake.recent"].push(room);
|
s.lists["im.vector.fake.recent"].push(room);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (me.membership === "leave") {
|
else if (me.membership === "leave") {
|
||||||
self.listsForRoomId[room.roomId].push("im.vector.fake.archived");
|
|
||||||
s.lists["im.vector.fake.archived"].push(room);
|
s.lists["im.vector.fake.archived"].push(room);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -375,22 +268,44 @@ module.exports = React.createClass({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// we actually apply the sorting to this when receiving the prop in RoomSubLists.
|
if (s.lists["im.vector.fake.direct"].length == 0 &&
|
||||||
|
MatrixClientPeg.get().getAccountData('m.direct') === undefined &&
|
||||||
|
!MatrixClientPeg.get().isGuest())
|
||||||
|
{
|
||||||
|
// scan through the 'recents' list for any rooms which look like DM rooms
|
||||||
|
// and make them DM rooms
|
||||||
|
const oldRecents = s.lists["im.vector.fake.recent"];
|
||||||
|
s.lists["im.vector.fake.recent"] = [];
|
||||||
|
|
||||||
// we'll need this when we get to iterating through lists programatically - e.g. ctrl-shift-up/down
|
for (const room of oldRecents) {
|
||||||
/*
|
const me = room.getMember(MatrixClientPeg.get().credentials.userId);
|
||||||
this.listOrder = [
|
|
||||||
"im.vector.fake.invite",
|
if (me && Rooms.looksLikeDirectMessageRoom(room, me)) {
|
||||||
"m.favourite",
|
s.lists["im.vector.fake.direct"].push(room);
|
||||||
"im.vector.fake.recent",
|
} else {
|
||||||
"im.vector.fake.direct",
|
s.lists["im.vector.fake.recent"].push(room);
|
||||||
Object.keys(otherTagNames).filter(tagName=>{
|
}
|
||||||
return (!tagName.match(/^m\.(favourite|lowpriority)$/));
|
}
|
||||||
}).sort(),
|
|
||||||
"m.lowpriority",
|
// save these new guessed DM rooms into the account data
|
||||||
"im.vector.fake.archived"
|
const newMDirectEvent = {};
|
||||||
];
|
for (const room of s.lists["im.vector.fake.direct"]) {
|
||||||
*/
|
const me = room.getMember(MatrixClientPeg.get().credentials.userId);
|
||||||
|
const otherPerson = Rooms.getOnlyOtherMember(room, me);
|
||||||
|
if (!otherPerson) continue;
|
||||||
|
|
||||||
|
const roomList = newMDirectEvent[otherPerson.userId] || [];
|
||||||
|
roomList.push(room.roomId);
|
||||||
|
newMDirectEvent[otherPerson.userId] = roomList;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this fails, fine, we'll just do the same thing next time we get the room lists
|
||||||
|
MatrixClientPeg.get().setAccountData('m.direct', newMDirectEvent).done();
|
||||||
|
}
|
||||||
|
|
||||||
|
//console.log("calculated new roomLists; im.vector.fake.recent = " + s.lists["im.vector.fake.recent"]);
|
||||||
|
|
||||||
|
// we actually apply the sorting to this when receiving the prop in RoomSubLists.
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
},
|
},
|
||||||
|
@ -548,15 +463,15 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GeminiScrollbar className="mx_RoomList_scrollbar"
|
<GeminiScrollbar className="mx_RoomList_scrollbar"
|
||||||
autoshow={true} onScroll={ self._whenScrolling } onResize={ self._whenScrolling } ref="gemscroll">
|
autoshow={true} onScroll={ self._whenScrolling } ref="gemscroll">
|
||||||
<div className="mx_RoomList" onMouseOver={ this._onMouseOver }>
|
<div className="mx_RoomList">
|
||||||
<RoomSubList list={ self.state.lists['im.vector.fake.invite'] }
|
<RoomSubList list={ self.state.lists['im.vector.fake.invite'] }
|
||||||
label="Invites"
|
label="Invites"
|
||||||
editable={ false }
|
editable={ false }
|
||||||
order="recent"
|
order="recent"
|
||||||
|
selectedRoom={ self.props.selectedRoom }
|
||||||
incomingCall={ self.state.incomingCall }
|
incomingCall={ self.state.incomingCall }
|
||||||
collapsed={ self.props.collapsed }
|
collapsed={ self.props.collapsed }
|
||||||
selectedRoom={ self.props.selectedRoom }
|
|
||||||
searchFilter={ self.props.searchFilter }
|
searchFilter={ self.props.searchFilter }
|
||||||
onHeaderClick={ self.onSubListHeaderClick }
|
onHeaderClick={ self.onSubListHeaderClick }
|
||||||
onShowMoreRooms={ self.onShowMoreRooms } />
|
onShowMoreRooms={ self.onShowMoreRooms } />
|
||||||
|
@ -567,9 +482,9 @@ module.exports = React.createClass({
|
||||||
verb="favourite"
|
verb="favourite"
|
||||||
editable={ true }
|
editable={ true }
|
||||||
order="manual"
|
order="manual"
|
||||||
|
selectedRoom={ self.props.selectedRoom }
|
||||||
incomingCall={ self.state.incomingCall }
|
incomingCall={ self.state.incomingCall }
|
||||||
collapsed={ self.props.collapsed }
|
collapsed={ self.props.collapsed }
|
||||||
selectedRoom={ self.props.selectedRoom }
|
|
||||||
searchFilter={ self.props.searchFilter }
|
searchFilter={ self.props.searchFilter }
|
||||||
onHeaderClick={ self.onSubListHeaderClick }
|
onHeaderClick={ self.onSubListHeaderClick }
|
||||||
onShowMoreRooms={ self.onShowMoreRooms } />
|
onShowMoreRooms={ self.onShowMoreRooms } />
|
||||||
|
@ -580,9 +495,9 @@ module.exports = React.createClass({
|
||||||
verb="tag direct chat"
|
verb="tag direct chat"
|
||||||
editable={ true }
|
editable={ true }
|
||||||
order="recent"
|
order="recent"
|
||||||
|
selectedRoom={ self.props.selectedRoom }
|
||||||
incomingCall={ self.state.incomingCall }
|
incomingCall={ self.state.incomingCall }
|
||||||
collapsed={ self.props.collapsed }
|
collapsed={ self.props.collapsed }
|
||||||
selectedRoom={ self.props.selectedRoom }
|
|
||||||
alwaysShowHeader={ true }
|
alwaysShowHeader={ true }
|
||||||
searchFilter={ self.props.searchFilter }
|
searchFilter={ self.props.searchFilter }
|
||||||
onHeaderClick={ self.onSubListHeaderClick }
|
onHeaderClick={ self.onSubListHeaderClick }
|
||||||
|
@ -593,14 +508,14 @@ module.exports = React.createClass({
|
||||||
editable={ true }
|
editable={ true }
|
||||||
verb="restore"
|
verb="restore"
|
||||||
order="recent"
|
order="recent"
|
||||||
|
selectedRoom={ self.props.selectedRoom }
|
||||||
incomingCall={ self.state.incomingCall }
|
incomingCall={ self.state.incomingCall }
|
||||||
collapsed={ self.props.collapsed }
|
collapsed={ self.props.collapsed }
|
||||||
selectedRoom={ self.props.selectedRoom }
|
|
||||||
searchFilter={ self.props.searchFilter }
|
searchFilter={ self.props.searchFilter }
|
||||||
onHeaderClick={ self.onSubListHeaderClick }
|
onHeaderClick={ self.onSubListHeaderClick }
|
||||||
onShowMoreRooms={ self.onShowMoreRooms } />
|
onShowMoreRooms={ self.onShowMoreRooms } />
|
||||||
|
|
||||||
{ Object.keys(self.state.lists).sort().map(function(tagName) {
|
{ Object.keys(self.state.lists).map(function(tagName) {
|
||||||
if (!tagName.match(/^(m\.(favourite|lowpriority)|im\.vector\.fake\.(invite|recent|direct|archived))$/)) {
|
if (!tagName.match(/^(m\.(favourite|lowpriority)|im\.vector\.fake\.(invite|recent|direct|archived))$/)) {
|
||||||
return <RoomSubList list={ self.state.lists[tagName] }
|
return <RoomSubList list={ self.state.lists[tagName] }
|
||||||
key={ tagName }
|
key={ tagName }
|
||||||
|
@ -609,9 +524,9 @@ module.exports = React.createClass({
|
||||||
verb={ "tag as " + tagName }
|
verb={ "tag as " + tagName }
|
||||||
editable={ true }
|
editable={ true }
|
||||||
order="manual"
|
order="manual"
|
||||||
|
selectedRoom={ self.props.selectedRoom }
|
||||||
incomingCall={ self.state.incomingCall }
|
incomingCall={ self.state.incomingCall }
|
||||||
collapsed={ self.props.collapsed }
|
collapsed={ self.props.collapsed }
|
||||||
selectedRoom={ self.props.selectedRoom }
|
|
||||||
searchFilter={ self.props.searchFilter }
|
searchFilter={ self.props.searchFilter }
|
||||||
onHeaderClick={ self.onSubListHeaderClick }
|
onHeaderClick={ self.onSubListHeaderClick }
|
||||||
onShowMoreRooms={ self.onShowMoreRooms } />;
|
onShowMoreRooms={ self.onShowMoreRooms } />;
|
||||||
|
@ -625,9 +540,9 @@ module.exports = React.createClass({
|
||||||
verb="demote"
|
verb="demote"
|
||||||
editable={ true }
|
editable={ true }
|
||||||
order="recent"
|
order="recent"
|
||||||
|
selectedRoom={ self.props.selectedRoom }
|
||||||
incomingCall={ self.state.incomingCall }
|
incomingCall={ self.state.incomingCall }
|
||||||
collapsed={ self.props.collapsed }
|
collapsed={ self.props.collapsed }
|
||||||
selectedRoom={ self.props.selectedRoom }
|
|
||||||
searchFilter={ self.props.searchFilter }
|
searchFilter={ self.props.searchFilter }
|
||||||
onHeaderClick={ self.onSubListHeaderClick }
|
onHeaderClick={ self.onSubListHeaderClick }
|
||||||
onShowMoreRooms={ self.onShowMoreRooms } />
|
onShowMoreRooms={ self.onShowMoreRooms } />
|
||||||
|
@ -636,8 +551,8 @@ module.exports = React.createClass({
|
||||||
label="Historical"
|
label="Historical"
|
||||||
editable={ false }
|
editable={ false }
|
||||||
order="recent"
|
order="recent"
|
||||||
collapsed={ self.props.collapsed }
|
|
||||||
selectedRoom={ self.props.selectedRoom }
|
selectedRoom={ self.props.selectedRoom }
|
||||||
|
collapsed={ self.props.collapsed }
|
||||||
alwaysShowHeader={ true }
|
alwaysShowHeader={ true }
|
||||||
startAsHidden={ true }
|
startAsHidden={ true }
|
||||||
showSpinner={ self.state.isLoadingLeftRooms }
|
showSpinner={ self.state.isLoadingLeftRooms }
|
||||||
|
|
|
@ -27,8 +27,6 @@ var RoomNotifs = require('../../../RoomNotifs');
|
||||||
var FormattingUtils = require('../../../utils/FormattingUtils');
|
var FormattingUtils = require('../../../utils/FormattingUtils');
|
||||||
import AccessibleButton from '../elements/AccessibleButton';
|
import AccessibleButton from '../elements/AccessibleButton';
|
||||||
var UserSettingsStore = require('../../../UserSettingsStore');
|
var UserSettingsStore = require('../../../UserSettingsStore');
|
||||||
var constantTimeDispatcher = require('../../../ConstantTimeDispatcher');
|
|
||||||
var Unread = require('../../../Unread');
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
displayName: 'RoomTile',
|
displayName: 'RoomTile',
|
||||||
|
@ -38,10 +36,12 @@ module.exports = React.createClass({
|
||||||
connectDropTarget: React.PropTypes.func,
|
connectDropTarget: React.PropTypes.func,
|
||||||
onClick: React.PropTypes.func,
|
onClick: React.PropTypes.func,
|
||||||
isDragging: React.PropTypes.bool,
|
isDragging: React.PropTypes.bool,
|
||||||
selectedRoom: React.PropTypes.string,
|
|
||||||
|
|
||||||
room: React.PropTypes.object.isRequired,
|
room: React.PropTypes.object.isRequired,
|
||||||
collapsed: React.PropTypes.bool.isRequired,
|
collapsed: React.PropTypes.bool.isRequired,
|
||||||
|
selected: React.PropTypes.bool.isRequired,
|
||||||
|
unread: React.PropTypes.bool.isRequired,
|
||||||
|
highlight: React.PropTypes.bool.isRequired,
|
||||||
isInvite: React.PropTypes.bool.isRequired,
|
isInvite: React.PropTypes.bool.isRequired,
|
||||||
incomingCall: React.PropTypes.object,
|
incomingCall: React.PropTypes.object,
|
||||||
},
|
},
|
||||||
|
@ -54,11 +54,10 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
return({
|
return({
|
||||||
hover: false,
|
hover : false,
|
||||||
badgeHover: false,
|
badgeHover : false,
|
||||||
menuDisplayed: false,
|
menuDisplayed: false,
|
||||||
notifState: RoomNotifs.getRoomNotifsState(this.props.room.roomId),
|
notifState: RoomNotifs.getRoomNotifsState(this.props.room.roomId),
|
||||||
selected: this.props.room ? (this.props.selectedRoom === this.props.room.roomId) : false,
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -80,32 +79,23 @@ module.exports = React.createClass({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onAccountData: function(accountDataEvent) {
|
||||||
|
if (accountDataEvent.getType() == 'm.push_rules') {
|
||||||
|
this.setState({
|
||||||
|
notifState: RoomNotifs.getRoomNotifsState(this.props.room.roomId),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
componentWillMount: function() {
|
componentWillMount: function() {
|
||||||
constantTimeDispatcher.register("RoomTile.refresh", this.props.room.roomId, this.onRefresh);
|
MatrixClientPeg.get().on("accountData", this.onAccountData);
|
||||||
constantTimeDispatcher.register("RoomTile.select", this.props.room.roomId, this.onSelect);
|
|
||||||
this.onRefresh();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillUnmount: function() {
|
componentWillUnmount: function() {
|
||||||
constantTimeDispatcher.unregister("RoomTile.refresh", this.props.room.roomId, this.onRefresh);
|
var cli = MatrixClientPeg.get();
|
||||||
constantTimeDispatcher.unregister("RoomTile.select", this.props.room.roomId, this.onSelect);
|
if (cli) {
|
||||||
},
|
MatrixClientPeg.get().removeListener("accountData", this.onAccountData);
|
||||||
|
}
|
||||||
componentWillReceiveProps: function(nextProps) {
|
|
||||||
this.onRefresh();
|
|
||||||
},
|
|
||||||
|
|
||||||
onRefresh: function(params) {
|
|
||||||
this.setState({
|
|
||||||
unread: Unread.doesRoomHaveUnreadMessages(this.props.room),
|
|
||||||
highlight: this.props.room.getUnreadNotificationCount('highlight') > 0 || this.props.isInvite,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
onSelect: function(params) {
|
|
||||||
this.setState({
|
|
||||||
selected: params.selected,
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onClick: function(ev) {
|
onClick: function(ev) {
|
||||||
|
@ -179,13 +169,13 @@ module.exports = React.createClass({
|
||||||
// var highlightCount = this.props.room.getUnreadNotificationCount("highlight");
|
// var highlightCount = this.props.room.getUnreadNotificationCount("highlight");
|
||||||
|
|
||||||
const notifBadges = notificationCount > 0 && this._shouldShowNotifBadge();
|
const notifBadges = notificationCount > 0 && this._shouldShowNotifBadge();
|
||||||
const mentionBadges = this.state.highlight && this._shouldShowMentionBadge();
|
const mentionBadges = this.props.highlight && this._shouldShowMentionBadge();
|
||||||
const badges = notifBadges || mentionBadges;
|
const badges = notifBadges || mentionBadges;
|
||||||
|
|
||||||
var classes = classNames({
|
var classes = classNames({
|
||||||
'mx_RoomTile': true,
|
'mx_RoomTile': true,
|
||||||
'mx_RoomTile_selected': this.state.selected,
|
'mx_RoomTile_selected': this.props.selected,
|
||||||
'mx_RoomTile_unread': this.state.unread,
|
'mx_RoomTile_unread': this.props.unread,
|
||||||
'mx_RoomTile_unreadNotify': notifBadges,
|
'mx_RoomTile_unreadNotify': notifBadges,
|
||||||
'mx_RoomTile_highlight': mentionBadges,
|
'mx_RoomTile_highlight': mentionBadges,
|
||||||
'mx_RoomTile_invited': (me && me.membership == 'invite'),
|
'mx_RoomTile_invited': (me && me.membership == 'invite'),
|
||||||
|
@ -231,7 +221,7 @@ module.exports = React.createClass({
|
||||||
'mx_RoomTile_badgeShown': badges || this.state.badgeHover || this.state.menuDisplayed,
|
'mx_RoomTile_badgeShown': badges || this.state.badgeHover || this.state.menuDisplayed,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.state.selected) {
|
if (this.props.selected) {
|
||||||
let nameSelected = <EmojiText>{name}</EmojiText>;
|
let nameSelected = <EmojiText>{name}</EmojiText>;
|
||||||
|
|
||||||
label = <div title={ name } className={ nameClasses }>{ nameSelected }</div>;
|
label = <div title={ name } className={ nameClasses }>{ nameSelected }</div>;
|
||||||
|
@ -265,8 +255,7 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
let ret = (
|
let ret = (
|
||||||
<div> { /* Only native elements can be wrapped in a DnD object. */}
|
<div> { /* Only native elements can be wrapped in a DnD object. */}
|
||||||
<AccessibleButton className={classes} tabIndex="0" onClick={this.onClick}
|
<AccessibleButton className={classes} tabIndex="0" onClick={this.onClick} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>
|
||||||
onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>
|
|
||||||
<div className={avatarClasses}>
|
<div className={avatarClasses}>
|
||||||
<div className="mx_RoomTile_avatar_container">
|
<div className="mx_RoomTile_avatar_container">
|
||||||
<RoomAvatar room={this.props.room} width={24} height={24} />
|
<RoomAvatar room={this.props.room} width={24} height={24} />
|
||||||
|
|
Loading…
Reference in a new issue