actually manage manual ordering; support arbitrary tags; bug fixes

This commit is contained in:
Matthew Hodgson 2015-11-06 20:54:07 +01:00
parent 8842147ec3
commit c884c5fc33
4 changed files with 135 additions and 38 deletions

View file

@ -351,7 +351,7 @@ module.exports = {
upload: undefined upload: undefined
}); });
}).done(undefined, function() { }).done(undefined, function() {
// display error message // TODO: display error message
}); });
}, },

View file

@ -56,16 +56,50 @@ var roomTileSource = {
console.log("roomTile endDrag for " + item.room.roomId + " with didDrop=" + monitor.didDrop()); console.log("roomTile endDrag for " + item.room.roomId + " with didDrop=" + monitor.didDrop());
if (!monitor.didDrop() || !item.targetList.props.editable) { if (monitor.didDrop() && item.targetList.props.editable) {
// if we moved lists, remove the old tag
if (item.targetList !== item.originalList) {
// commented out attempts to set a spinner on our target component as component is actually
// the original source component being dragged, not our target. To fix we just need to
// move all of this to endDrop in the target instead. FIXME later.
//component.state.set({ spinner: component.state.spinner ? component.state.spinner++ : 1 });
MatrixClientPeg.get().deleteRoomTag(item.room.roomId, item.originalList.props.tagName).finally(function() {
//component.state.set({ spinner: component.state.spinner-- });
}).fail(function(err) {
var ErrorDialog = sdk.getComponent("organisms.ErrorDialog");
Modal.createDialog(ErrorDialog, {
title: "Failed to remove tag " + item.originalList.props.tagName + " from room",
description: err.toString()
});
});
}
var newOrder= {};
if (item.targetList.props.order === 'manual') {
newOrder['order' = item.targetList.calcManualOrderTagData(item.room);
}
// if we moved lists or the ordering changed, add the new tag
if (item.targetList.props.tagName && item.targetList !== item.originalList || newOrder) {
//component.state.set({ spinner: component.state.spinner ? component.state.spinner++ : 1 });
MatrixClientPeg.get().setRoomTag(item.room.roomId, item.targetList.props.tagName, newOrder).finally(function() {
//component.state.set({ spinner: component.state.spinner-- });
}).fail(function(err) {
var ErrorDialog = sdk.getComponent("organisms.ErrorDialog");
Modal.createDialog(ErrorDialog, {
title: "Failed to add tag " + item.targetList.props.tagName + " to room",
description: err.toString()
});
});
}
}
else {
// cancel the drop and reset our original position
props.roomSubList.moveRoomTile(item.room, item.originalIndex); props.roomSubList.moveRoomTile(item.room, item.originalIndex);
if (item.targetList && item.targetList !== item.originalList) { if (item.targetList && item.targetList !== item.originalList) {
item.targetList.removeRoomTile(item.room); item.targetList.removeRoomTile(item.room);
} }
return;
}
else {
// When dropped on a compatible target, actually set the right tags for the new ordering
// persistNewOrder(item.room, dropResult.listId);
} }
} }
}; };
@ -88,6 +122,8 @@ var roomTileTarget = {
item.targetList = props.roomSubList; item.targetList = props.roomSubList;
} }
if (!item.targetList.props.editable) return;
if (item.targetList.props.order === 'manual') { if (item.targetList.props.order === 'manual') {
if (item.room.roomId !== props.room.roomId) { if (item.room.roomId !== props.room.roomId) {
var roomTile = props.roomSubList.findRoomTile(props.room); var roomTile = props.roomSubList.findRoomTile(props.room);
@ -146,7 +182,7 @@ var RoomTile = React.createClass({
var name; var name;
if (this.props.isInvite) { if (this.props.isInvite) {
name = this.props.room.getMember(MatrixClientPeg.get().credentials.userId).events.member.getSender(); name = this.props.room.getMember(myUserId).events.member.getSender();
} }
else { else {
name = this.props.room.name; name = this.props.room.name;

View file

@ -38,54 +38,71 @@ module.exports = React.createClass({
null; null;
var RoomSubList = sdk.getComponent('organisms.RoomSubList'); var RoomSubList = sdk.getComponent('organisms.RoomSubList');
var self = this;
return ( return (
<div className="mx_RoomList" onScroll={this._repositionTooltip}> <div className="mx_RoomList" onScroll={self._repositionTooltip}>
{ expandButton } { expandButton }
<RoomSubList list={ this.state.lists['invites'] } <RoomSubList list={ self.state.lists['invites'] }
label="Invites" label="Invites"
editable={ false } editable={ false }
order="recent" order="recent"
activityMap={ this.state.activityMap } activityMap={ self.state.activityMap }
selectedRoom={ this.props.selectedRoom } selectedRoom={ self.props.selectedRoom }
collapsed={ this.props.collapsed } /> collapsed={ self.props.collapsed } />
<RoomSubList list={ this.state.lists['favourites'] } <RoomSubList list={ self.state.lists['favourite'] }
label="Favourites" label="Favourites"
tagname="favourites" tagName="favourite"
verb="favourite" verb="favourite"
editable={ true } editable={ true }
order="manual" order="manual"
activityMap={ this.state.activityMap } activityMap={ self.state.activityMap }
selectedRoom={ this.props.selectedRoom } selectedRoom={ self.props.selectedRoom }
collapsed={ this.props.collapsed } /> collapsed={ self.props.collapsed } />
<RoomSubList list={ this.state.lists['recents'] } <RoomSubList list={ self.state.lists['recents'] }
label="Recents" label="Conversations"
editable={ true } editable={ true }
order="recent" order="recent"
activityMap={ this.state.activityMap } activityMap={ self.state.activityMap }
selectedRoom={ this.props.selectedRoom } selectedRoom={ self.props.selectedRoom }
collapsed={ this.props.collapsed } /> collapsed={ self.props.collapsed } />
<RoomSubList list={ this.state.lists['hidden'] } <RoomSubList list={ self.state.lists['lowpriority'] }
label="Hidden" label="Low priority"
tagname="hidden" tagName="lowpriority"
verb="hide" verb="deprioritize"
editable={ true } editable={ true }
order="recent" order="recent"
activityMap={ this.state.activityMap } activityMap={ self.state.activityMap }
selectedRoom={ this.props.selectedRoom } selectedRoom={ self.props.selectedRoom }
collapsed={ this.props.collapsed } /> collapsed={ self.props.collapsed } />
<RoomSubList list={ this.state.lists['archived'] } { Object.keys(self.state.lists).map(function(tagName) {
if (!tagName.match(/^(invites|favourite|recents|lowpriority|archived)$/)) {
return <RoomSubList list={ self.state.lists[tagName] }
key={ tagName }
label={ tagName }
tagName={ tagName }
verb={ "tag as " + tagName }
editable={ true }
order="manual"
activityMap={ self.state.activityMap }
selectedRoom={ self.props.selectedRoom }
collapsed={ self.props.collapsed } />
}
}) }
<RoomSubList list={ self.state.lists['archived'] }
label="Historical" label="Historical"
editable={ false } editable={ false }
order="recent" order="recent"
activityMap={ this.state.activityMap } activityMap={ self.state.activityMap }
selectedRoom={ this.props.selectedRoom } selectedRoom={ self.props.selectedRoom }
collapsed={ this.props.collapsed } /> collapsed={ self.props.collapsed } />
</div> </div>
); );
} }

View file

@ -48,7 +48,7 @@ var RoomSubList = React.createClass({
propTypes: { propTypes: {
list: React.PropTypes.arrayOf(React.PropTypes.object).isRequired, list: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
label: React.PropTypes.string.isRequired, label: React.PropTypes.string.isRequired,
tagname: React.PropTypes.string, tagName: React.PropTypes.string,
editable: React.PropTypes.bool, editable: React.PropTypes.bool,
order: React.PropTypes.string.isRequired, order: React.PropTypes.string.isRequired,
selectedRoom: React.PropTypes.string.isRequired, selectedRoom: React.PropTypes.string.isRequired,
@ -88,8 +88,9 @@ var RoomSubList = React.createClass({
}, },
manualComparator: function(roomA, roomB) { manualComparator: function(roomA, roomB) {
var a = roomA.tags[this.props.tagname].order; if (!roomA.tags[this.props.tagName] || !roomB.tags[this.props.tagName]) return 0;
var b = roomB.tags[this.props.tagname].order; var a = roomA.tags[this.props.tagName].order;
var b = roomB.tags[this.props.tagName].order;
return a == b ? this.recentsComparator(roomA, roomB) : ( a > b ? 1 : -1); return a == b ? this.recentsComparator(roomA, roomB) : ( a > b ? 1 : -1);
}, },
@ -152,6 +153,49 @@ var RoomSubList = React.createClass({
}); });
}, },
calcManualOrderTagData: function(room) {
var index = this.state.sortedList.indexOf(room);
// 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.
var orderA = 0.0; // by default we're next to the beginning of the list
if (index > 0) {
var 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;
}
}
var orderB = 1.0; // by default we're next to the end of the list too
if (index < this.state.sortedList.length - 1) {
var 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;
}
}
var order = (orderA + orderB) / 2.0;
if (order === orderA || order === orderB) {
console.error("Cannot describe new list position. This should be incredibly unlikely.");
// TODO: renumber the list
}
return order;
},
makeRoomTiles: function() { makeRoomTiles: function() {
var self = this; var self = this;
var RoomTile = sdk.getComponent("molecules.RoomTile"); var RoomTile = sdk.getComponent("molecules.RoomTile");