From 2926154dce90671293a28348f00710c3593aee8e Mon Sep 17 00:00:00 2001 From: lukebarnard Date: Thu, 25 Jan 2018 22:30:58 +0100 Subject: [PATCH 1/9] Modify LeftPanel to include a DragDropContext that handles drag and drop for TagPanel and RoomList. This is to allow the future feature of dragging between the two components. --- src/components/structures/LeftPanel.js | 86 ++++++++++++++++--- .../css/vector-web/structures/_LeftPanel.scss | 4 + 2 files changed, 78 insertions(+), 12 deletions(-) diff --git a/src/components/structures/LeftPanel.js b/src/components/structures/LeftPanel.js index f78835b4..c1222396 100644 --- a/src/components/structures/LeftPanel.js +++ b/src/components/structures/LeftPanel.js @@ -17,22 +17,32 @@ limitations under the License. 'use strict'; import React from 'react'; +import PropTypes from 'prop-types'; import classNames from 'classnames'; +import { DragDropContext } from 'react-beautiful-dnd'; +import { MatrixClient } from 'matrix-js-sdk'; import { KeyCode } from 'matrix-react-sdk/lib/Keyboard'; import sdk from 'matrix-react-sdk'; import dis from 'matrix-react-sdk/lib/dispatcher'; import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg'; -import CallHandler from 'matrix-react-sdk/lib/CallHandler'; -import AccessibleButton from 'matrix-react-sdk/lib/components/views/elements/AccessibleButton'; import VectorConferenceHandler from '../../VectorConferenceHandler'; +import SettingsStore from "matrix-react-sdk/lib/settings/SettingsStore"; +import TagOrderActions from 'matrix-react-sdk/lib/actions/TagOrderActions'; +import RoomListActions from 'matrix-react-sdk/lib/actions/RoomListActions'; + + var LeftPanel = React.createClass({ displayName: 'LeftPanel', // NB. If you add props, don't forget to update // shouldComponentUpdate! propTypes: { - collapsed: React.PropTypes.bool.isRequired, + collapsed: PropTypes.bool.isRequired, + }, + + contextTypes: { + matrixClient: PropTypes.instanceOf(MatrixClient), }, getInitialState: function() { @@ -161,8 +171,54 @@ var LeftPanel = React.createClass({ this.setState({ searchFilter: term }); }, + onDragEnd: function(result) { + // Dragged to an invalid destination, not onto a droppable + if (!result.destination) { + return; + } + + const dest = result.destination.droppableId; + + if (dest === 'tag-panel-droppable') { + // Dispatch synchronously so that the TagPanel receives an + // optimistic update from TagOrderStore before the previous + // state is shown. + dis.dispatch(TagOrderActions.moveTag( + this.context.matrixClient, + result.draggableId, + result.destination.index, + ), true); + } else { + this.onRoomTileEndDrag(result); + } + }, + + onRoomTileEndDrag: function(result) { + let newTag = result.destination.droppableId.split('_')[1]; + let prevTag = result.source.droppableId.split('_')[1]; + if (newTag === 'undefined') newTag = undefined; + if (prevTag === 'undefined') prevTag = undefined; + + const roomId = result.draggableId.split('_')[1]; + + const oldIndex = result.source.index; + const newIndex = result.destination.index; + + dis.dispatch(RoomListActions.tagRoom( + this.context.matrixClient, + MatrixClientPeg.get().getRoom(roomId), + prevTag, newTag, + oldIndex, newIndex, + ), true); + }, + + collectRoomList: function(ref) { + this._roomList = ref; + }, + render: function() { const RoomList = sdk.getComponent('rooms.RoomList'); + const TagPanel = sdk.getComponent('structures.TagPanel'); const BottomLeftMenu = sdk.getComponent('structures.BottomLeftMenu'); const CallPreview = sdk.getComponent('voip.CallPreview'); @@ -184,15 +240,21 @@ var LeftPanel = React.createClass({ ); return ( - + +
+ { SettingsStore.isFeatureEnabled("feature_tag_panel") ? :
} + +
+ ); } }); diff --git a/src/skins/vector/css/vector-web/structures/_LeftPanel.scss b/src/skins/vector/css/vector-web/structures/_LeftPanel.scss index 8ae1fe15..a2147a02 100644 --- a/src/skins/vector/css/vector-web/structures/_LeftPanel.scss +++ b/src/skins/vector/css/vector-web/structures/_LeftPanel.scss @@ -21,6 +21,10 @@ limitations under the License. flex-direction: column; } +.mx_LeftPanel_container { + display: flex; +} + .mx_LeftPanel_hideButton { position: absolute; top: 10px; From 37fe3ac676ee06bd832cfa6762394bcc1bcbcc4c Mon Sep 17 00:00:00 2001 From: lukebarnard Date: Thu, 25 Jan 2018 22:51:40 +0100 Subject: [PATCH 2/9] Prevent RoomTiles from being dragged into other droppables for the time being at least. --- src/components/structures/RoomSubList.js | 18 +++++++++++------- src/components/views/rooms/DNDRoomTile.js | 1 + 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/components/structures/RoomSubList.js b/src/components/structures/RoomSubList.js index 15f56c00..398f2647 100644 --- a/src/components/structures/RoomSubList.js +++ b/src/components/structures/RoomSubList.js @@ -572,13 +572,17 @@ var RoomSubList = React.createClass({ { subList }
; - return this.props.editable ? - { (provided, snapshot) => ( -
- { subListContent } -
- ) } -
: subListContent; + return this.props.editable ? + + { (provided, snapshot) => ( +
+ { subListContent } +
+ ) } +
: subListContent; } else { var Loader = sdk.getComponent("elements.Spinner"); diff --git a/src/components/views/rooms/DNDRoomTile.js b/src/components/views/rooms/DNDRoomTile.js index 129e3f45..b8f8b402 100644 --- a/src/components/views/rooms/DNDRoomTile.js +++ b/src/components/views/rooms/DNDRoomTile.js @@ -41,6 +41,7 @@ export default class DNDRoomTile extends React.Component { key={props.room.roomId} draggableId={props.tagName + '_' + props.room.roomId} index={props.index} + type="draggable-RoomTile" > { (provided, snapshot) => { return ( From e46f436a472a017889f146bc4fcad1d1b2d379ac Mon Sep 17 00:00:00 2001 From: lukebarnard Date: Tue, 6 Feb 2018 11:50:34 +0000 Subject: [PATCH 3/9] Prefer context.matrixClient in LeftPanel --- src/components/structures/LeftPanel.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/structures/LeftPanel.js b/src/components/structures/LeftPanel.js index c1222396..398862f2 100644 --- a/src/components/structures/LeftPanel.js +++ b/src/components/structures/LeftPanel.js @@ -24,7 +24,6 @@ import { MatrixClient } from 'matrix-js-sdk'; import { KeyCode } from 'matrix-react-sdk/lib/Keyboard'; import sdk from 'matrix-react-sdk'; import dis from 'matrix-react-sdk/lib/dispatcher'; -import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg'; import VectorConferenceHandler from '../../VectorConferenceHandler'; import SettingsStore from "matrix-react-sdk/lib/settings/SettingsStore"; @@ -206,7 +205,7 @@ var LeftPanel = React.createClass({ dis.dispatch(RoomListActions.tagRoom( this.context.matrixClient, - MatrixClientPeg.get().getRoom(roomId), + this.context.matrixClient.getRoom(roomId), prevTag, newTag, oldIndex, newIndex, ), true); @@ -223,7 +222,7 @@ var LeftPanel = React.createClass({ const CallPreview = sdk.getComponent('voip.CallPreview'); let topBox; - if (MatrixClientPeg.get().isGuest()) { + if (this.context.matrixClient.isGuest()) { const LoginBox = sdk.getComponent('structures.LoginBox'); topBox = ; } else { From 83996c09d9a06f34fa11a07ab6c789c31770082f Mon Sep 17 00:00:00 2001 From: lukebarnard Date: Tue, 6 Feb 2018 11:51:46 +0000 Subject: [PATCH 4/9] General delint, cleanup --- .../context_menus/RoomTileContextMenu.js | 65 ++++++++++--------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/src/components/views/context_menus/RoomTileContextMenu.js b/src/components/views/context_menus/RoomTileContextMenu.js index 36602cfa..9ddafb83 100644 --- a/src/components/views/context_menus/RoomTileContextMenu.js +++ b/src/components/views/context_menus/RoomTileContextMenu.js @@ -20,6 +20,7 @@ limitations under the License. import Promise from 'bluebird'; import React from 'react'; import classNames from 'classnames'; +import PropTypes from 'prop-types'; import sdk from 'matrix-react-sdk'; import { _t, _td } from 'matrix-react-sdk/lib/languageHandler'; import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg'; @@ -28,14 +29,15 @@ import DMRoomMap from 'matrix-react-sdk/lib/utils/DMRoomMap'; import * as Rooms from 'matrix-react-sdk/lib/Rooms'; import * as RoomNotifs from 'matrix-react-sdk/lib/RoomNotifs'; import Modal from 'matrix-react-sdk/lib/Modal'; +import RoomListActions from 'matrix-react-sdk/lib/actions/RoomListActions'; module.exports = React.createClass({ displayName: 'RoomTileContextMenu', propTypes: { - room: React.PropTypes.object.isRequired, + room: PropTypes.object.isRequired, /* callback called when the menu is dismissed */ - onFinished: React.PropTypes.func, + onFinished: PropTypes.func, }, getInitialState() { @@ -45,7 +47,7 @@ module.exports = React.createClass({ isFavourite: this.props.room.tags.hasOwnProperty("m.favourite"), isLowPriority: this.props.room.tags.hasOwnProperty("m.lowpriority"), isDirectMessage: Boolean(dmRoomMap.getUserIdForRoomId(this.props.room.roomId)), - } + }; }, componentWillMount: function() { @@ -132,22 +134,22 @@ module.exports = React.createClass({ }, _onClickDM: function() { + if (MatrixClientPeg.get().isGuest()) return; + const newIsDirectMessage = !this.state.isDirectMessage; this.setState({ isDirectMessage: newIsDirectMessage, }); - if (MatrixClientPeg.get().isGuest()) return; - Rooms.guessAndSetDMRoom( - this.props.room, newIsDirectMessage + this.props.room, newIsDirectMessage, ).delay(500).finally(() => { // Close the context menu if (this.props.onFinished) { this.props.onFinished(); - }; + } }, (err) => { - var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); + const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); Modal.createTrackedDialog('Failed to set Direct Message status of room', '', ErrorDialog, { title: _t('Failed to set Direct Message status of room'), description: ((err && err.message) ? err.message : _t('Operation failed')), @@ -165,7 +167,7 @@ module.exports = React.createClass({ // Close the context menu if (this.props.onFinished) { this.props.onFinished(); - }; + } }, _onClickReject: function() { @@ -177,7 +179,7 @@ module.exports = React.createClass({ // Close the context menu if (this.props.onFinished) { this.props.onFinished(); - }; + } }, _onClickForget: function() { @@ -185,8 +187,8 @@ module.exports = React.createClass({ MatrixClientPeg.get().forget(this.props.room.roomId).done(function() { dis.dispatch({ action: 'view_next_room' }); }, function(err) { - var errCode = err.errcode || _td("unknown error code"); - var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); + const errCode = err.errcode || _td("unknown error code"); + const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); Modal.createTrackedDialog('Failed to forget room', '', ErrorDialog, { title: _t('Failed to forget room %(errCode)s', {errCode: errCode}), description: ((err && err.message) ? err.message : _t('Operation failed')), @@ -196,20 +198,19 @@ module.exports = React.createClass({ // Close the context menu if (this.props.onFinished) { this.props.onFinished(); - }; + } }, _saveNotifState: function(newState) { + if (MatrixClientPeg.get().isGuest()) return; + const oldState = this.state.roomNotifState; const roomId = this.props.room.roomId; - var cli = MatrixClientPeg.get(); - - if (cli.isGuest()) return; this.setState({ roomNotifState: newState, }); - RoomNotifs.setRoomNotifsState(this.props.room.roomId, newState).done(() => { + RoomNotifs.setRoomNotifsState(roomId, newState).done(() => { // delay slightly so that the user can see their state change // before closing the menu return Promise.delay(500).then(() => { @@ -217,7 +218,7 @@ module.exports = React.createClass({ // Close the context menu if (this.props.onFinished) { this.props.onFinished(); - }; + } }); }, (error) => { // TODO: some form of error notification to the user @@ -247,22 +248,22 @@ module.exports = React.createClass({ }, _renderNotifMenu: function() { - var alertMeClasses = classNames({ + const alertMeClasses = classNames({ 'mx_RoomTileContextMenu_notif_field': true, 'mx_RoomTileContextMenu_notif_fieldSet': this.state.roomNotifState == RoomNotifs.ALL_MESSAGES_LOUD, }); - var allNotifsClasses = classNames({ + const allNotifsClasses = classNames({ 'mx_RoomTileContextMenu_notif_field': true, 'mx_RoomTileContextMenu_notif_fieldSet': this.state.roomNotifState == RoomNotifs.ALL_MESSAGES, }); - var mentionsClasses = classNames({ + const mentionsClasses = classNames({ 'mx_RoomTileContextMenu_notif_field': true, 'mx_RoomTileContextMenu_notif_fieldSet': this.state.roomNotifState == RoomNotifs.MENTIONS_ONLY, }); - var muteNotifsClasses = classNames({ + const muteNotifsClasses = classNames({ 'mx_RoomTileContextMenu_notif_field': true, 'mx_RoomTileContextMenu_notif_fieldSet': this.state.roomNotifState == RoomNotifs.MUTE, }); @@ -272,22 +273,22 @@ module.exports = React.createClass({
-
+
{ _t('All messages (noisy)') }
-
+
{ _t('All messages') }
-
+
{ _t('Mentions only') }
-
+
{ _t('Mute') } @@ -322,7 +323,7 @@ module.exports = React.createClass({ return (
-
+
{ leaveText }
@@ -351,17 +352,17 @@ module.exports = React.createClass({ return (
-
+
{ _t('Favourite') }
-
+
{ _t('Low Priority') }
-
+
{ _t('Direct Chat') } @@ -372,7 +373,7 @@ module.exports = React.createClass({ render: function() { const myMember = this.props.room.getMember( - MatrixClientPeg.get().credentials.userId + MatrixClientPeg.get().credentials.userId, ); // Can't set notif level or tags on non-join rooms @@ -389,5 +390,5 @@ module.exports = React.createClass({ { this._renderRoomTagMenu() }
); - } + }, }); From 662942ec295183b185e50883b843c63bd4b3aa42 Mon Sep 17 00:00:00 2001 From: lukebarnard Date: Tue, 6 Feb 2018 11:52:39 +0000 Subject: [PATCH 5/9] Use dispatch to change room tags from RoomTileContextMenu --- .../context_menus/RoomTileContextMenu.js | 44 ++++--------------- 1 file changed, 9 insertions(+), 35 deletions(-) diff --git a/src/components/views/context_menus/RoomTileContextMenu.js b/src/components/views/context_menus/RoomTileContextMenu.js index 9ddafb83..06eb347d 100644 --- a/src/components/views/context_menus/RoomTileContextMenu.js +++ b/src/components/views/context_menus/RoomTileContextMenu.js @@ -59,42 +59,16 @@ module.exports = React.createClass({ }, _toggleTag: function(tagNameOn, tagNameOff) { - var self = this; - const roomId = this.props.room.roomId; - var cli = MatrixClientPeg.get(); - if (!cli.isGuest()) { - Promise.delay(500).then(function() { - if (tagNameOff !== null && tagNameOff !== undefined) { - cli.deleteRoomTag(roomId, tagNameOff).finally(function() { - // Close the context menu - if (self.props.onFinished) { - self.props.onFinished(); - }; - }).catch(function(err) { - var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); - Modal.createTrackedDialog('Failed to remove tag from room 1', '', ErrorDialog, { - title: _t('Failed to remove tag %(tagName)s from room', {tagName: tagNameOff}), - description: ((err && err.message) ? err.message : _t('Operation failed')), - }); - }); - } + if (!MatrixClientPeg.get().isGuest()) { + Promise.delay(500).then(() => { + dis.dispatch(RoomListActions.tagRoom( + MatrixClientPeg.get(), + this.props.room, + tagNameOff, tagNameOn, + undefined, 0, + ), true); - if (tagNameOn !== null && tagNameOn !== undefined) { - // If the tag ordering meta data is required, it is added by - // the RoomSubList when it sorts its rooms - cli.setRoomTag(roomId, tagNameOn, {}).finally(function() { - // Close the context menu - if (self.props.onFinished) { - self.props.onFinished(); - }; - }).catch(function(err) { - var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); - Modal.createTrackedDialog('Failed to remove tag from room 2', '', ErrorDialog, { - title: _t('Failed to remove tag %(tagName)s from room', {tagName: tagNameOn}), - description: ((err && err.message) ? err.message : _t('Operation failed')), - }); - }); - } + this.props.onFinished(); }); } }, From 495090c9ba41a05cc74acb27dc6bb31782a6ed1a Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 8 Feb 2018 14:08:20 +0000 Subject: [PATCH 6/9] Remove now unused RoomSubList code --- src/components/structures/RoomSubList.js | 117 ----------------------- 1 file changed, 117 deletions(-) diff --git a/src/components/structures/RoomSubList.js b/src/components/structures/RoomSubList.js index 398f2647..8bea76ab 100644 --- a/src/components/structures/RoomSubList.js +++ b/src/components/structures/RoomSubList.js @@ -38,31 +38,6 @@ var debug = false; const TRUNCATE_AT = 10; -var roomListTarget = { - canDrop: function() { - return true; - }, - - drop: function(props, monitor, component) { - if (debug) console.log("dropped on sublist") - }, - - hover: function(props, monitor, component) { - var item = monitor.getItem(); - - if (component.state.sortedList.length == 0 && props.editable) { - if (debug) console.log("hovering on sublist " + props.label + ", isOver=" + monitor.isOver()); - - if (item.targetList !== component) { - item.targetList.removeRoomTile(item.room); - item.targetList = component; - } - - component.moveRoomTile(item.room, 0); - } - }, -}; - var RoomSubList = React.createClass({ displayName: 'RoomSubList', @@ -279,98 +254,6 @@ var RoomSubList = React.createClass({ this.setState(this.state); }, - moveRoomTile: function(room, atIndex) { - if (debug) console.log("moveRoomTile: id " + room.roomId + ", atIndex " + atIndex); - //console.log("moveRoomTile before: " + JSON.stringify(this.state.rooms)); - var found = this.findRoomTile(room); - var rooms = this.state.sortedList; - if (found.room) { - if (debug) console.log("removing at index " + found.index + " and adding at index " + atIndex); - rooms.splice(found.index, 1); - rooms.splice(atIndex, 0, found.room); - } - else { - if (debug) console.log("Adding at index " + atIndex); - rooms.splice(atIndex, 0, room); - } - this.setState({ sortedList: rooms }); - // console.log("moveRoomTile after: " + JSON.stringify(this.state.rooms)); - }, - - // XXX: this isn't invoked via a property method but indirectly via - // the roomList property method. Unsure how evil this is. - removeRoomTile: function(room) { - if (debug) console.log("remove room " + room.roomId); - var found = this.findRoomTile(room); - var rooms = this.state.sortedList; - if (found.room) { - rooms.splice(found.index, 1); - } - else { - console.warn("Can't remove room " + room.roomId + " - can't find it"); - } - this.setState({ sortedList: rooms }); - }, - - findRoomTile: function(room) { - var index = this.state.sortedList.indexOf(room); - if (index >= 0) { - // console.log("found: room: " + room.roomId + " with index " + index); - } - else { - if (debug) console.log("didn't find room"); - room = null; - } - return ({ - room: room, - index: index, - }); - }, - - calcManualOrderTagData: function(index) { - // we sort rooms by the lexicographic ordering of the 'order' metadata on their tags. - // for convenience, we calculate this for now a floating point number between 0.0 and 1.0. - - let orderA = 0.0; // by default we're next to the beginning of the list - if (index > 0) { - const prevTag = this.state.sortedList[index - 1].tags[this.props.tagName]; - if (!prevTag) { - console.error("Previous room in sublist is not tagged to be in this list. This should never happen."); - } else if (prevTag.order === undefined) { - console.error("Previous room in sublist has no ordering metadata. This should never happen."); - } else { - orderA = prevTag.order; - } - } - - let orderB = 1.0; // by default we're next to the end of the list too - if (index < this.state.sortedList.length - 1) { - const nextTag = this.state.sortedList[index + 1].tags[this.props.tagName]; - if (!nextTag) { - console.error("Next room in sublist is not tagged to be in this list. This should never happen."); - } else if (nextTag.order === undefined) { - console.error("Next room in sublist has no ordering metadata. This should never happen."); - } else { - orderB = nextTag.order; - } - } - - const order = (orderA + orderB) / 2.0; - - if (order === orderA || order === orderB) { - console.error("Cannot describe new list position. This should be incredibly unlikely."); - this.state.sortedList.forEach((room, index) => { - MatrixClientPeg.get().setRoomTag( - room.roomId, this.props.tagName, - {order: index / this.state.sortedList.length}, - ); - }); - return index / this.state.sortedList.length; - } - - return order; - }, - makeRoomTiles: function() { var self = this; var DNDRoomTile = sdk.getComponent("rooms.DNDRoomTile"); From 0cdebcce89605e3297cc72fac09038a8d9aa3c38 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 8 Feb 2018 16:28:42 +0000 Subject: [PATCH 7/9] Move sublist sorting to RoomListStore NB: fixUndefinedOrdering was removed completely because it was code dealing with legacy favourites. see matrix-org/matrix-react-sdk@9b0df191 --- src/components/structures/RoomSubList.js | 114 ++--------------------- 1 file changed, 6 insertions(+), 108 deletions(-) diff --git a/src/components/structures/RoomSubList.js b/src/components/structures/RoomSubList.js index 8bea76ab..d119e271 100644 --- a/src/components/structures/RoomSubList.js +++ b/src/components/structures/RoomSubList.js @@ -85,13 +85,17 @@ var RoomSubList = React.createClass({ }, componentWillMount: function() { - this.sortList(this.applySearchFilter(this.props.list, this.props.searchFilter), this.props.order); + this.setState({ + sortedList: this.applySearchFilter(this.props.list, this.props.searchFilter), + }); }, componentWillReceiveProps: function(newProps) { // order the room list appropriately before we re-render //if (debug) console.log("received new props, list = " + newProps.list); - this.sortList(this.applySearchFilter(newProps.list, newProps.searchFilter), newProps.order); + this.setState({ + sortedList: this.applySearchFilter(newProps.list, newProps.searchFilter), + }); }, applySearchFilter: function(list, filter) { @@ -139,71 +143,6 @@ var RoomSubList = React.createClass({ }); }, - tsOfNewestEvent: function(room) { - for (var i = room.timeline.length - 1; i >= 0; --i) { - var ev = room.timeline[i]; - if (ev.getTs() && - (Unread.eventTriggersUnreadCount(ev) || - (ev.getSender() === MatrixClientPeg.get().credentials.userId)) - ) { - return ev.getTs(); - } - } - - // we might only have events that don't trigger the unread indicator, - // in which case use the oldest event even if normally it wouldn't count. - // This is better than just assuming the last event was forever ago. - if (room.timeline.length && room.timeline[0].getTs()) { - return room.timeline[0].getTs(); - } else { - return Number.MAX_SAFE_INTEGER; - } - }, - - // TODO: factor the comparators back out into a generic comparator - // so that view_prev_room and view_next_room can do the right thing - - recentsComparator: function(roomA, roomB) { - return this.tsOfNewestEvent(roomB) - this.tsOfNewestEvent(roomA); - }, - - lexicographicalComparator: function(roomA, roomB) { - return roomA.name > roomB.name ? 1 : -1; - }, - - // Generates the manual comparator using the given list - manualComparator: function(roomA, roomB) { - if (!roomA.tags[this.props.tagName] || !roomB.tags[this.props.tagName]) return 0; - - // Make sure the room tag has an order element, if not set it to be the bottom - var a = roomA.tags[this.props.tagName].order; - var b = roomB.tags[this.props.tagName].order; - - // Order undefined room tag orders to the bottom - if (a === undefined && b !== undefined) { - return 1; - } else if (a !== undefined && b === undefined) { - return -1; - } - - return a == b ? this.lexicographicalComparator(roomA, roomB) : ( a > b ? 1 : -1); - }, - - sortList: function(list, order) { - if (list === undefined) list = this.state.sortedList; - if (order === undefined) order = this.props.order; - var comparator; - list = list || []; - if (order === "manual") comparator = this.manualComparator; - if (order === "recent") comparator = this.recentsComparator; - - // Fix undefined orders here, and make sure the backend gets updated as well - this._fixUndefinedOrder(list); - - //if (debug) console.log("sorting list for sublist " + this.props.label + " with length " + list.length + ", this.props.list = " + this.props.list); - this.setState({ sortedList: list.sort(comparator) }); - }, - _shouldShowNotifBadge: function(roomNotifState) { const showBadgeInStates = [RoomNotifs.ALL_MESSAGES, RoomNotifs.ALL_MESSAGES_LOUD]; return showBadgeInStates.indexOf(roomNotifState) > -1; @@ -380,47 +319,6 @@ var RoomSubList = React.createClass({ this.props.onHeaderClick(false); }, - // Fix any undefined order elements of a room in a manual ordered list - // room.tag[tagname].order - _fixUndefinedOrder: function(list) { - if (this.props.order === "manual") { - var order = 0.0; - var self = this; - - // Find the highest (lowest position) order of a room in a manual ordered list - list.forEach(function(room) { - if (room.tags.hasOwnProperty(self.props.tagName)) { - if (order < room.tags[self.props.tagName].order) { - order = room.tags[self.props.tagName].order; - } - } - }); - - // Fix any undefined order elements of a room in a manual ordered list - // Do this one at a time, as each time a rooms tag data is updated the RoomList - // gets triggered and another list is passed in. Doing it one at a time means that - // we always correctly calculate the highest order for the list - stops multiple - // rooms getting the same order. This is only really relevant for the first time this - // is run with historical room tag data, after that there should only be undefined - // in the list at a time anyway. - for (let i = 0; i < list.length; i++) { - if (list[i].tags[self.props.tagName] && list[i].tags[self.props.tagName].order === undefined) { - MatrixClientPeg.get().setRoomTag(list[i].roomId, self.props.tagName, {order: (order + 1.0) / 2.0}).finally(function() { - // Do any final stuff here - }).catch(function(err) { - var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); - console.error("Failed to add tag " + self.props.tagName + " to room" + err); - Modal.createTrackedDialog('Failed to add tag to room', '', ErrorDialog, { - title: _t('Failed to add tag %(tagName)s to room', {tagName: self.props.tagName}), - description: ((err && err.message) ? err.message : _t('Operation failed')), - }); - }); - break; - }; - }; - } - }, - render: function() { var connectDropTarget = this.props.connectDropTarget; var TruncatedList = sdk.getComponent('elements.TruncatedList'); From e36baa8c3a66cd5d256b5d46ae11b43bd7edd2e5 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Mon, 12 Feb 2018 18:47:29 +0000 Subject: [PATCH 8/9] Fix quotes on import --- src/components/structures/LeftPanel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/LeftPanel.js b/src/components/structures/LeftPanel.js index 398862f2..3260c975 100644 --- a/src/components/structures/LeftPanel.js +++ b/src/components/structures/LeftPanel.js @@ -26,7 +26,7 @@ import sdk from 'matrix-react-sdk'; import dis from 'matrix-react-sdk/lib/dispatcher'; import VectorConferenceHandler from '../../VectorConferenceHandler'; -import SettingsStore from "matrix-react-sdk/lib/settings/SettingsStore"; +import SettingsStore from 'matrix-react-sdk/lib/settings/SettingsStore'; import TagOrderActions from 'matrix-react-sdk/lib/actions/TagOrderActions'; import RoomListActions from 'matrix-react-sdk/lib/actions/RoomListActions'; From 2269c945793e318ae2b03a4c6d8c8dcf68f3fbf6 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 13 Feb 2018 09:44:25 +0000 Subject: [PATCH 9/9] Move groups button to TagPanel --- src/components/structures/BottomLeftMenu.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/structures/BottomLeftMenu.js b/src/components/structures/BottomLeftMenu.js index 3aab61a1..5557e74b 100644 --- a/src/components/structures/BottomLeftMenu.js +++ b/src/components/structures/BottomLeftMenu.js @@ -167,7 +167,6 @@ module.exports = React.createClass({ const StartChatButton = sdk.getComponent('elements.StartChatButton'); const RoomDirectoryButton = sdk.getComponent('elements.RoomDirectoryButton'); const CreateRoomButton = sdk.getComponent('elements.CreateRoomButton'); - const GroupsButton = sdk.getComponent('elements.GroupsButton'); const SettingsButton = sdk.getComponent('elements.SettingsButton'); return ( @@ -183,7 +182,6 @@ module.exports = React.createClass({
-