Merge branch 'develop' into kegan/controller-merging4

This commit is contained in:
Kegan Dougal 2015-11-30 10:56:14 +00:00
commit 83b3702769
15 changed files with 107 additions and 63 deletions

View File

@ -288,6 +288,7 @@ module.exports = {
fillSpace: function() {
if (!this.refs.messagePanel) return;
if (this.state.searchResults) return; // TODO: paginate search results
var messageWrapperScroll = this._getScrollNode();
if (messageWrapperScroll.scrollTop < messageWrapperScroll.clientHeight && this.state.room.oldState.paginationToken) {
this.setState({paginating: true});
@ -426,7 +427,7 @@ module.exports = {
onSearch: function(term, scope) {
var filter;
if (scope === "Room") { // FIXME: should be enum
if (scope === "Room") {
filter = {
// XXX: it's unintuitive that the filter for searching doesn't have the same shape as the v2 filter API :(
rooms: [
@ -443,6 +444,14 @@ module.exports = {
search_term: term,
filter: filter,
order_by: "recent",
include_state: true,
groupings: {
group_by: [
{
key: "room_id"
}
]
},
event_context: {
before_limit: 1,
after_limit: 1,
@ -451,9 +460,28 @@ module.exports = {
}
}
}).then(function(data) {
// for debugging:
// data.search_categories.room_events.highlights = ["hello", "everybody"];
var highlights;
if (data.search_categories.room_events.highlights &&
data.search_categories.room_events.highlights.length > 0)
{
// postgres on synapse returns us precise details of the
// strings which actually got matched for highlighting.
// for overlapping highlights, favour longer (more specific) terms first
highlights = data.search_categories.room_events.highlights
.sort(function(a, b) { b.length - a.length });
}
else {
// sqlite doesn't, so just try to highlight the literal search term
highlights = [ term ];
}
self.setState({
searchTerm: term,
highlights: highlights,
searchResults: data,
searchScope: scope,
});
}, function(error) {
var ErrorDialog = sdk.getComponent("organisms.ErrorDialog");
@ -466,20 +494,34 @@ module.exports = {
getEventTiles: function() {
var DateSeparator = sdk.getComponent('molecules.DateSeparator');
var cli = MatrixClientPeg.get();
var ret = [];
var count = 0;
var EventTile = sdk.getComponent('messages.Event');
var self = this;
if (this.state.searchResults) {
// XXX: this dance is foul, due to the results API not returning sorted results
if (this.state.searchResults &&
this.state.searchResults.search_categories.room_events.results &&
this.state.searchResults.search_categories.room_events.groups)
{
// XXX: this dance is foul, due to the results API not directly returning sorted results
var results = this.state.searchResults.search_categories.room_events.results;
var eventIds = Object.keys(results);
var roomIdGroups = this.state.searchResults.search_categories.room_events.groups.room_id;
Object.keys(roomIdGroups)
.sort(function(a, b) { roomIdGroups[a].order - roomIdGroups[b].order }) // WHY NOT RETURN AN ORDERED ARRAY?!?!?!
.forEach(function(roomId)
{
// XXX: todo: merge overlapping results somehow?
// XXX: why doesn't searching on name work?
var resultList = eventIds.map(function(key) { return results[key]; }); // .sort(function(a, b) { b.rank - a.rank });
for (var i = 0; i < resultList.length; i++) {
if (self.state.searchScope === 'All') {
ret.push(<li key={ roomId }><h1>Room: { cli.getRoom(roomId).name }</h1></li>);
}
var resultList = roomIdGroups[roomId].results.map(function(eventId) { return results[eventId]; });
for (var i = resultList.length - 1; i >= 0; i--) {
var ts1 = resultList[i].result.origin_server_ts;
ret.push(<li key={ts1 + "-search"}><DateSeparator ts={ts1}/></li>); // Rank: {resultList[i].rank}
var mxEv = new Matrix.MatrixEvent(resultList[i].result);
@ -490,7 +532,7 @@ module.exports = {
}
}
if (EventTile.haveTileForEvent(mxEv)) {
ret.push(<li key={mxEv.getId() + "+0"}><EventTile mxEvent={mxEv} searchTerm={this.state.searchTerm}/></li>);
ret.push(<li key={mxEv.getId() + "+0"}><EventTile mxEvent={mxEv} highlights={self.state.highlights}/></li>);
}
if (resultList[i].context.events_after[0]) {
var mxEv2 = new Matrix.MatrixEvent(resultList[i].context.events_after[0]);
@ -499,6 +541,7 @@ module.exports = {
}
}
}
});
return ret;
}
@ -530,7 +573,7 @@ module.exports = {
var ts0 = this.state.room.timeline[i - 1].getTs();
var ts1 = this.state.room.timeline[i].getTs();
if (new Date(ts0).toDateString() !== new Date(ts1).toDateString()) {
dateSeparator = <DateSeparator key={ts1} ts={ts1}/>;
dateSeparator = <li key={ts1}><DateSeparator key={ts1} ts={ts1}/></li>;
continuation = false;
}
}

View File

@ -15,8 +15,7 @@ limitations under the License.
*/
.mx_MemberAvatar {
/* commenting this out as it breaks on FF seemingly */
/* position: relative; */
position: relative;
}
.mx_MemberAvatar_initial {

View File

@ -22,7 +22,12 @@ html {
}
body {
font-family: 'Myriad Pro', Helvetica, Arial, Sans-Serif;
/* Myriad Pro lacks combining diacritics, so these will fall through
to the next font. Helevetica's diacritics however do not combine
nicely with Myriad Pro (on OSX, at least) and result in a huge
horizontal mess. Arial empirically gets it right, hence prioritising
Arial here. */
font-family: 'Myriad Pro', Arial, Helvetica, Sans-Serif;
font-size: 16px;
color: #454545;
border: 0px;

View File

@ -16,4 +16,5 @@ limitations under the License.
.mx_EventAsTextTile {
opacity: 0.5;
overflow-y: hidden;
}

View File

@ -27,6 +27,7 @@ limitations under the License.
margin-left: -73px;
margin-top: -4px;
float: left;
position: relative;
}
.mx_EventTile_avatar img {
@ -44,6 +45,7 @@ limitations under the License.
font-size: 14px;
margin-bottom: 4px;
display: block;
overflow-y: hidden;
}
.mx_EventTile .mx_MessageTimestamp {
@ -63,6 +65,7 @@ limitations under the License.
.mx_MessageTile_content {
display: block;
margin-right: 100px;
overflow-y: hidden;
}
/* Various markdown overrides */
@ -87,6 +90,12 @@ limitations under the License.
color: #76cfa6;
}
.mx_MessageTile_content .markdown-body .hljs {
display: inherit ! important;
}
/* end of overrides */
.mx_MessageTile_searchHighlight {
background-color: #76cfa6;
color: #fff;

View File

@ -37,8 +37,10 @@ limitations under the License.
}
.mx_MemberInfo_profileField {
opacity: 0.6;
font-color: #999999;
font-size: 14px;
position: relative;
background-color: #fff;
}
.mx_MemberInfo_buttons {

View File

@ -98,10 +98,6 @@ limitations under the License.
opacity: 0.25;
}
.mx_MemberTile_zalgo {
font-family: Helvetica, Arial, Sans-Serif;
}
.mx_MemberTile:hover .mx_MessageTimestamp {
display: block;
}

View File

@ -59,7 +59,7 @@ limitations under the License.
box-shadow: none;
/* needed for FF */
font-family: 'Myriad Pro', Helvetica, Arial, Sans-Serif;
font-family: 'Myriad Pro', Arial, Helvetica, Sans-Serif;
}
/* hack for FF as vertical alignment of custom placeholder text is broken */

View File

@ -111,6 +111,7 @@ limitations under the License.
.mx_RoomHeader_nametext {
display: inline-block;
overflow-y: hidden;
}
.mx_RoomHeader_settingsButton {

View File

@ -13,8 +13,3 @@ 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.
*/
.mx_SenderProfile_zalgo {
font-family: Helvetica, Arial, Sans-Serif;
display: table-row ! important;
}

View File

@ -45,7 +45,7 @@ limitations under the License.
}
.mx_MemberList_invite {
font-family: 'Myriad Pro', Helvetica, Arial, Sans-Serif;
font-family: 'Myriad Pro', Arial, Helvetica, Sans-Serif;
border-radius: 3px;
border: 1px solid #f0f0f0;
padding: 9px;

View File

@ -125,7 +125,7 @@ limitations under the License.
clear: both;
}
.mx_RoomView_MessageList > h2 {
.mx_RoomView_MessageList h2 {
clear: both;
margin-top: 32px;
margin-bottom: 8px;

View File

@ -50,12 +50,10 @@ skin['messages.TextualEvent'] = require('matrix-react-sdk/lib/components/views/m
skin['messages.MRoomMemberEvent'] = require('matrix-react-sdk/lib/components/views/messages/MRoomMemberEvent');
skin['messages.Event'] = require('matrix-react-sdk/lib/components/views/messages/Event');
skin['messages.Message'] = require('matrix-react-sdk/lib/components/views/messages/Message');
skin['messages.MEmoteMessage'] = require('matrix-react-sdk/lib/components/views/messages/MEmoteMessage');
skin['messages.MFileMessage'] = require('matrix-react-sdk/lib/components/views/messages/MFileMessage');
skin['messages.MImageMessage'] = require('matrix-react-sdk/lib/components/views/messages/MImageMessage');
skin['messages.MNoticeMessage'] = require('matrix-react-sdk/lib/components/views/messages/MNoticeMessage');
skin['messages.MTextMessage'] = require('matrix-react-sdk/lib/components/views/messages/MTextMessage');
skin['messages.MVideoMessage'] = require('matrix-react-sdk/lib/components/views/messages/MVideoMessage');
skin['messages.TextualMessage'] = require('matrix-react-sdk/lib/components/views/messages/TextualMessage');
skin['messages.UnknownMessage'] = require('matrix-react-sdk/lib/components/views/messages/UnknownMessage');
skin['rooms.MemberInfo'] = require('matrix-react-sdk/lib/components/views/rooms/MemberInfo');

View File

@ -17,11 +17,6 @@ limitations under the License.
'use strict';
var React = require('react');
var classNames = require("classnames");
// The Lato WOFF doesn't include sensible combining diacritics, so Chrome chokes on rendering them.
// Revert to Arial when this happens, which on OSX works at least.
var zalgo = /[\u0300-\u036f\u1ab0-\u1aff\u1dc0-\u1dff\u20d0-\u20ff\ufe20-\ufe2f]/;
module.exports = React.createClass({
displayName: 'SenderProfile',
@ -30,18 +25,12 @@ module.exports = React.createClass({
var mxEvent = this.props.mxEvent;
var name = mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender();
var classes = classNames({
mx_SenderProfile: true,
// taken from https://en.wikipedia.org/wiki/Combining_character
mx_SenderProfile_zalgo: zalgo.test(name),
});
var msgtype = mxEvent.getContent().msgtype;
if (msgtype && msgtype == 'm.emote') {
name = ''; // emote message must include the name so don't duplicate it
}
return (
<span className={classes}>
<span className="mx_SenderProfile">
{name} { this.props.aux }
</span>
);

View File

@ -291,6 +291,12 @@ module.exports = React.createClass({
</div>;
}
var messageComposer;
if (!this.state.searchResults) {
messageComposer =
<MessageComposer room={this.state.room} roomView={this} uploadFile={this.uploadFile} />
}
return (
<div className="mx_RoomView">
<RoomHeader ref="header" room={this.state.room} editing={this.state.editingRoomSettings} onSearchClick={this.onSearchClick}
@ -313,10 +319,10 @@ module.exports = React.createClass({
<div className="mx_RoomView_statusArea">
<div className="mx_RoomView_statusAreaBox">
<div className="mx_RoomView_statusAreaBox_line"></div>
{statusBar}
{ this.state.searchResults ? null : statusBar }
</div>
</div>
<MessageComposer room={this.state.room} roomView={this} uploadFile={this.uploadFile} />
{ messageComposer }
</div>
);
}