From 9e97160c855f16e04d4c12bbd44e0e28a061e67a Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Fri, 27 Nov 2015 16:20:14 +0000 Subject: [PATCH 1/8] fix inline blocks --- src/skins/vector/css/molecules/EventTile.css | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/skins/vector/css/molecules/EventTile.css b/src/skins/vector/css/molecules/EventTile.css index 697655e8..255eef34 100644 --- a/src/skins/vector/css/molecules/EventTile.css +++ b/src/skins/vector/css/molecules/EventTile.css @@ -87,6 +87,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; From 8de94d45b147cc95b62bdfdab35919d70e348b82 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sat, 28 Nov 2015 21:11:37 +0000 Subject: [PATCH 2/8] swim like a salmon and manually update skindex for a generic TextualMessage type --- src/skins/vector/skindex.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/skins/vector/skindex.js b/src/skins/vector/skindex.js index b4a8e119..1e747c62 100644 --- a/src/skins/vector/skindex.js +++ b/src/skins/vector/skindex.js @@ -47,12 +47,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'); @@ -99,4 +97,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; From e43edee9bb8b2252e110a9388a3f0607b2e4ee86 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sun, 29 Nov 2015 03:19:51 +0000 Subject: [PATCH 3/8] call highlighted search terms highlights, and uphold them if provided by synapse --- src/controllers/organisms/RoomView.js | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/controllers/organisms/RoomView.js b/src/controllers/organisms/RoomView.js index 1fe7bd08..e5fe6ce2 100644 --- a/src/controllers/organisms/RoomView.js +++ b/src/controllers/organisms/RoomView.js @@ -451,8 +451,26 @@ 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 highlight the literal search term + highlights = [ term ]; + } + self.setState({ - searchTerm: term, + highlights: highlights, searchResults: data, }); }, function(error) { @@ -490,7 +508,7 @@ module.exports = { } } if (EventTile.haveTileForEvent(mxEv)) { - ret.push(
  • ); + ret.push(
  • ); } if (resultList[i].context.events_after[0]) { var mxEv2 = new Matrix.MatrixEvent(resultList[i].context.events_after[0]); @@ -530,7 +548,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; } } From fc02331cd3b7b702465992187ec4ffbe5480e560 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sun, 29 Nov 2015 03:20:19 +0000 Subject: [PATCH 4/8] fix CSS for search timestamps --- src/skins/vector/css/organisms/RoomView.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/skins/vector/css/organisms/RoomView.css b/src/skins/vector/css/organisms/RoomView.css index 870640f1..94fff290 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; From 01f0e61d6e873717cc2f0f99c4247b0b7573a5bc Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sun, 29 Nov 2015 04:41:17 +0000 Subject: [PATCH 5/8] fix search ordering; add room labels; hide input areas if searching --- src/controllers/organisms/RoomView.js | 72 +++++++++++++------- src/skins/vector/views/organisms/RoomView.js | 23 +++++-- 2 files changed, 63 insertions(+), 32 deletions(-) diff --git a/src/controllers/organisms/RoomView.js b/src/controllers/organisms/RoomView.js index e5fe6ce2..f33b5ee9 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, @@ -465,13 +474,14 @@ module.exports = { .sort(function(a, b) { b.length - a.length }); } else { - // sqlite doesn't, so just highlight the literal search term + // sqlite doesn't, so just try to highlight the literal search term highlights = [ term ]; } self.setState({ highlights: highlights, searchResults: data, + searchScope: scope, }); }, function(error) { var ErrorDialog = sdk.getComponent("organisms.ErrorDialog"); @@ -484,39 +494,51 @@ 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 + // 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; } diff --git a/src/skins/vector/views/organisms/RoomView.js b/src/skins/vector/views/organisms/RoomView.js index 537bbd55..9a703beb 100644 --- a/src/skins/vector/views/organisms/RoomView.js +++ b/src/skins/vector/views/organisms/RoomView.js @@ -291,6 +291,20 @@ module.exports = React.createClass({ ; } + var statusArea, messageComposer; + if (!this.state.searchResults) { + statusArea = +
    +
    +
    + {statusBar} +
    +
    + + messageComposer = + + } + return (
    -
    -
    -
    - {statusBar} -
    -
    - + { statusArea } + { messageComposer } ); } From af6bd53d38e252fa49daaeeadd74e7d862f697f9 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sun, 29 Nov 2015 13:18:37 +0000 Subject: [PATCH 6/8] revert 23d45d7f33bcfe7a06ef2eaaf982ad99ab20706f and apply a better fix which works for both chrome & FF --- src/skins/vector/css/atoms/MemberAvatar.css | 3 +-- src/skins/vector/css/molecules/EventTile.css | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/skins/vector/css/atoms/MemberAvatar.css b/src/skins/vector/css/atoms/MemberAvatar.css index e76c2ad1..5f7d18cb 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/molecules/EventTile.css b/src/skins/vector/css/molecules/EventTile.css index 255eef34..e4d310c0 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 { From 9a64dc27fc9fd7d7838fae7e9ec677c1fa2a0182 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sun, 29 Nov 2015 13:32:13 +0000 Subject: [PATCH 7/8] improve layout for search results, fix syntax highlighting quirks in sublime, and don't crash on zero results --- src/controllers/organisms/RoomView.js | 5 ++++- src/skins/vector/views/organisms/RoomView.js | 21 +++++++++----------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/controllers/organisms/RoomView.js b/src/controllers/organisms/RoomView.js index f33b5ee9..40564e55 100644 --- a/src/controllers/organisms/RoomView.js +++ b/src/controllers/organisms/RoomView.js @@ -502,7 +502,10 @@ module.exports = { var EventTile = sdk.getComponent('messages.Event'); var self = this; - if (this.state.searchResults) { + 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 roomIdGroups = this.state.searchResults.search_categories.room_events.groups.room_id; diff --git a/src/skins/vector/views/organisms/RoomView.js b/src/skins/vector/views/organisms/RoomView.js index 9a703beb..a34d321e 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,16 +291,8 @@ module.exports = React.createClass({
    ; } - var statusArea, messageComposer; + var messageComposer; if (!this.state.searchResults) { - statusArea = -
    -
    -
    - {statusBar} -
    -
    - messageComposer = } @@ -324,7 +316,12 @@ module.exports = React.createClass({
    - { statusArea } +
    +
    +
    + { this.state.searchResults ? null : statusBar } +
    +
    { messageComposer }
    ); From cd040ae0ddb55217cf7c64df09100f255bb7220d Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Mon, 30 Nov 2015 01:13:59 +0000 Subject: [PATCH 8/8] fix zalgo properly! remove ugly regexp hacks for detecting combining diacritics and instead set the right font ordering, as Arial combines nicely with Myriad Pro whilst Helvetica doesn't. (Myriad Pro itself has no combining diacritic characters) --- src/skins/vector/css/common.css | 7 ++++++- src/skins/vector/css/molecules/EventAsTextTile.css | 1 + src/skins/vector/css/molecules/EventTile.css | 2 ++ src/skins/vector/css/molecules/MemberInfo.css | 4 +++- src/skins/vector/css/molecules/MemberTile.css | 4 ---- src/skins/vector/css/molecules/MessageComposer.css | 2 +- src/skins/vector/css/molecules/RoomHeader.css | 1 + src/skins/vector/css/molecules/SenderProfile.css | 5 ----- src/skins/vector/css/organisms/MemberList.css | 2 +- src/skins/vector/views/molecules/SenderProfile.js | 13 +------------ 10 files changed, 16 insertions(+), 25 deletions(-) diff --git a/src/skins/vector/css/common.css b/src/skins/vector/css/common.css index ba931b9c..af2d4be4 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 d18fdc80..da953522 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 e4d310c0..152fde1f 100644 --- a/src/skins/vector/css/molecules/EventTile.css +++ b/src/skins/vector/css/molecules/EventTile.css @@ -45,6 +45,7 @@ limitations under the License. font-size: 14px; margin-bottom: 4px; display: block; + overflow-y: hidden; } .mx_EventTile .mx_MessageTimestamp { @@ -64,6 +65,7 @@ limitations under the License. .mx_MessageTile_content { display: block; margin-right: 100px; + overflow-y: hidden; } /* Various markdown overrides */ diff --git a/src/skins/vector/css/molecules/MemberInfo.css b/src/skins/vector/css/molecules/MemberInfo.css index 6471a86c..ac11dde7 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 cfeaeaee..de34de59 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 3fb38c31..428d39e6 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 5519c14d..1a4fdbf3 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 45db913e..fd88ee27 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 df699e64..774f177a 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/views/molecules/SenderProfile.js b/src/skins/vector/views/molecules/SenderProfile.js index c09685aa..ef0173d9 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 } );