diff --git a/src/controllers/organisms/RoomView.js b/src/controllers/organisms/RoomView.js
index 1fe7bd08ad..40564e5588 100644
--- a/src/controllers/organisms/RoomView.js
+++ b/src/controllers/organisms/RoomView.js
@@ -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,39 +494,54 @@ 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);
- // 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++) {
- var ts1 = resultList[i].result.origin_server_ts;
- ret.push(
); // Rank: {resultList[i].rank}
- var mxEv = new Matrix.MatrixEvent(resultList[i].result);
- if (resultList[i].context.events_before[0]) {
- var mxEv2 = new Matrix.MatrixEvent(resultList[i].context.events_before[0]);
- if (EventTile.haveTileForEvent(mxEv2)) {
- ret.push();
+ 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?
+ if (self.state.searchScope === 'All') {
+ ret.push(Room: { cli.getRoom(roomId).name }
);
+ }
+
+ 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(); // Rank: {resultList[i].rank}
+ var mxEv = new Matrix.MatrixEvent(resultList[i].result);
+ if (resultList[i].context.events_before[0]) {
+ var mxEv2 = new Matrix.MatrixEvent(resultList[i].context.events_before[0]);
+ if (EventTile.haveTileForEvent(mxEv2)) {
+ ret.push();
+ }
+ }
+ if (EventTile.haveTileForEvent(mxEv)) {
+ ret.push();
+ }
+ if (resultList[i].context.events_after[0]) {
+ var mxEv2 = new Matrix.MatrixEvent(resultList[i].context.events_after[0]);
+ if (EventTile.haveTileForEvent(mxEv2)) {
+ ret.push();
+ }
}
}
- if (EventTile.haveTileForEvent(mxEv)) {
- ret.push();
- }
- if (resultList[i].context.events_after[0]) {
- var mxEv2 = new Matrix.MatrixEvent(resultList[i].context.events_after[0]);
- if (EventTile.haveTileForEvent(mxEv2)) {
- ret.push();
- }
- }
- }
+ });
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 = ;
continuation = false;
}
}
diff --git a/src/skins/vector/css/atoms/MemberAvatar.css b/src/skins/vector/css/atoms/MemberAvatar.css
index e76c2ad103..5f7d18cb5c 100644
--- a/src/skins/vector/css/atoms/MemberAvatar.css
+++ b/src/skins/vector/css/atoms/MemberAvatar.css
@@ -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 {
diff --git a/src/skins/vector/css/common.css b/src/skins/vector/css/common.css
index ba931b9cbf..af2d4be4ab 100644
--- a/src/skins/vector/css/common.css
+++ b/src/skins/vector/css/common.css
@@ -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;
diff --git a/src/skins/vector/css/molecules/EventAsTextTile.css b/src/skins/vector/css/molecules/EventAsTextTile.css
index d18fdc809c..da95352296 100644
--- a/src/skins/vector/css/molecules/EventAsTextTile.css
+++ b/src/skins/vector/css/molecules/EventAsTextTile.css
@@ -16,4 +16,5 @@ limitations under the License.
.mx_EventAsTextTile {
opacity: 0.5;
+ overflow-y: hidden;
}
diff --git a/src/skins/vector/css/molecules/EventTile.css b/src/skins/vector/css/molecules/EventTile.css
index 697655e88f..152fde1f7c 100644
--- a/src/skins/vector/css/molecules/EventTile.css
+++ b/src/skins/vector/css/molecules/EventTile.css
@@ -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;
diff --git a/src/skins/vector/css/molecules/MemberInfo.css b/src/skins/vector/css/molecules/MemberInfo.css
index 6471a86cb6..ac11dde7c0 100644
--- a/src/skins/vector/css/molecules/MemberInfo.css
+++ b/src/skins/vector/css/molecules/MemberInfo.css
@@ -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 {
diff --git a/src/skins/vector/css/molecules/MemberTile.css b/src/skins/vector/css/molecules/MemberTile.css
index cfeaeaee0c..de34de595e 100644
--- a/src/skins/vector/css/molecules/MemberTile.css
+++ b/src/skins/vector/css/molecules/MemberTile.css
@@ -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;
}
diff --git a/src/skins/vector/css/molecules/MessageComposer.css b/src/skins/vector/css/molecules/MessageComposer.css
index 3fb38c317f..428d39e659 100644
--- a/src/skins/vector/css/molecules/MessageComposer.css
+++ b/src/skins/vector/css/molecules/MessageComposer.css
@@ -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 */
diff --git a/src/skins/vector/css/molecules/RoomHeader.css b/src/skins/vector/css/molecules/RoomHeader.css
index 5519c14de5..1a4fdbf329 100644
--- a/src/skins/vector/css/molecules/RoomHeader.css
+++ b/src/skins/vector/css/molecules/RoomHeader.css
@@ -111,6 +111,7 @@ limitations under the License.
.mx_RoomHeader_nametext {
display: inline-block;
+ overflow-y: hidden;
}
.mx_RoomHeader_settingsButton {
diff --git a/src/skins/vector/css/molecules/SenderProfile.css b/src/skins/vector/css/molecules/SenderProfile.css
index 45db913e68..fd88ee27f7 100644
--- a/src/skins/vector/css/molecules/SenderProfile.css
+++ b/src/skins/vector/css/molecules/SenderProfile.css
@@ -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;
-}
diff --git a/src/skins/vector/css/organisms/MemberList.css b/src/skins/vector/css/organisms/MemberList.css
index df699e6490..774f177a4f 100644
--- a/src/skins/vector/css/organisms/MemberList.css
+++ b/src/skins/vector/css/organisms/MemberList.css
@@ -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;
diff --git a/src/skins/vector/css/organisms/RoomView.css b/src/skins/vector/css/organisms/RoomView.css
index 870640f124..94fff29068 100644
--- a/src/skins/vector/css/organisms/RoomView.css
+++ b/src/skins/vector/css/organisms/RoomView.css
@@ -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;
diff --git a/src/skins/vector/skindex.js b/src/skins/vector/skindex.js
index 6137200f01..859641fbeb 100644
--- a/src/skins/vector/skindex.js
+++ b/src/skins/vector/skindex.js
@@ -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');
@@ -101,4 +99,4 @@ skin['organisms.ViewSource'] = require('./views/organisms/ViewSource');
skin['pages.CompatibilityPage'] = require('./views/pages/CompatibilityPage');
skin['pages.MatrixChat'] = require('./views/pages/MatrixChat');
-module.exports = skin;
\ No newline at end of file
+module.exports = skin;
diff --git a/src/skins/vector/views/molecules/SenderProfile.js b/src/skins/vector/views/molecules/SenderProfile.js
index c09685aad8..ef0173d975 100644
--- a/src/skins/vector/views/molecules/SenderProfile.js
+++ b/src/skins/vector/views/molecules/SenderProfile.js
@@ -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 (
-
+
{name} { this.props.aux }
);
diff --git a/src/skins/vector/views/organisms/RoomView.js b/src/skins/vector/views/organisms/RoomView.js
index 537bbd55b6..a34d321eea 100644
--- a/src/skins/vector/views/organisms/RoomView.js
+++ b/src/skins/vector/views/organisms/RoomView.js
@@ -206,7 +206,7 @@ module.exports = React.createClass({
if (this.state.syncState === "ERROR") {
statusBar = (
-
+
Connectivity to the server has been lost.
@@ -221,7 +221,7 @@ module.exports = React.createClass({
else if (this.state.hasUnsentMessages) {
statusBar = (
-
+
Some of your messages have not been sent.
@@ -291,6 +291,12 @@ module.exports = React.createClass({
;
}
+ var messageComposer;
+ if (!this.state.searchResults) {
+ messageComposer =
+
+ }
+
return (
- {statusBar}
+ { this.state.searchResults ? null : statusBar }
-
+ { messageComposer }
);
}