From 08a41bf0938e8cf5ad70534482130ae74c29d406 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Fri, 1 Apr 2016 02:16:29 +0100 Subject: [PATCH 01/11] improve layout for LinkPreviewWidget --- .../views/rooms/UrlPreviewWidget.css | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/skins/vector/css/matrix-react-sdk/views/rooms/UrlPreviewWidget.css diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/UrlPreviewWidget.css b/src/skins/vector/css/matrix-react-sdk/views/rooms/UrlPreviewWidget.css new file mode 100644 index 00000000..e8ef26b7 --- /dev/null +++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/UrlPreviewWidget.css @@ -0,0 +1,49 @@ +/* +Copyright 2015, 2016 OpenMarket Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +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_LinkPreviewWidget { + padding-left: 15px; + margin-top: 15px; + margin-right: 15px; + margin-bottom: 15px; + display: -webkit-flex; + display: flex; + border-left: 5px solid #ddd; + color: #888; +} + +.mx_LinkPreviewWidget_image { + -webkit-flex: 0 0 100px; + flex: 0 0 100px; + text-align: center; +} + +.mx_LinkPreviewWidget_caption { + margin-left: 15px; +} + +.mx_LinkPreviewWidget_title { + display: inline; + font-weight: bold; +} + +.mx_LinkPreviewWidget_siteName { + display: inline; +} + +.mx_LinkPreviewWidget_description { + margin-top: 8px; +} From 8247bb4a76c23f442ec39c83a5fff68d71af3018 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sat, 2 Apr 2016 00:36:53 +0100 Subject: [PATCH 02/11] match style for markdown quotes --- .../css/matrix-react-sdk/views/rooms/UrlPreviewWidget.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/UrlPreviewWidget.css b/src/skins/vector/css/matrix-react-sdk/views/rooms/UrlPreviewWidget.css index e8ef26b7..ae54b900 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/rooms/UrlPreviewWidget.css +++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/UrlPreviewWidget.css @@ -21,7 +21,7 @@ limitations under the License. margin-bottom: 15px; display: -webkit-flex; display: flex; - border-left: 5px solid #ddd; + border-left: 4px solid #ddd; color: #888; } From 8c0a23dd8b50cd506f01245fae78d9f6982e8d48 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sun, 3 Apr 2016 02:06:24 +0100 Subject: [PATCH 03/11] fix widget layout --- .../css/matrix-react-sdk/views/rooms/UrlPreviewWidget.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/UrlPreviewWidget.css b/src/skins/vector/css/matrix-react-sdk/views/rooms/UrlPreviewWidget.css index ae54b900..800883a1 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/rooms/UrlPreviewWidget.css +++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/UrlPreviewWidget.css @@ -15,7 +15,6 @@ limitations under the License. */ .mx_LinkPreviewWidget { - padding-left: 15px; margin-top: 15px; margin-right: 15px; margin-bottom: 15px; @@ -28,6 +27,7 @@ limitations under the License. .mx_LinkPreviewWidget_image { -webkit-flex: 0 0 100px; flex: 0 0 100px; + margin-left: 15px; text-align: center; } @@ -46,4 +46,5 @@ limitations under the License. .mx_LinkPreviewWidget_description { margin-top: 8px; + white-space: normal; } From ff2885087da8a87ce40db2942675a09a8dc6422a Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sun, 3 Apr 2016 02:50:51 +0100 Subject: [PATCH 04/11] support cancelling and uncancelling previews --- .../views/rooms/MessageContextMenu.js | 23 +++++++++++++++++++ .../views/rooms/UrlPreviewWidget.css | 11 +++++++++ 2 files changed, 34 insertions(+) diff --git a/src/components/views/rooms/MessageContextMenu.js b/src/components/views/rooms/MessageContextMenu.js index a0a3f1cf..24948f74 100644 --- a/src/components/views/rooms/MessageContextMenu.js +++ b/src/components/views/rooms/MessageContextMenu.js @@ -66,6 +66,15 @@ module.exports = React.createClass({ if (this.props.onFinished) this.props.onFinished(); }, + onUnhidePreviewClick: function() { + if (global.localStorage) { + // FIXME: factor this out with LinkPreviewWidget + // FIXME: somehow propagate this to the EventTile such that it updates itself and realises the link has rematerialised + global.localStorage.removeItem("hide_preview_" + this.props.mxEvent.getId()); + if (this.props.onFinished) this.props.onFinished(); + } + }, + render: function() { var eventStatus = this.props.mxEvent.status; var resendButton; @@ -73,6 +82,7 @@ module.exports = React.createClass({ var redactButton; var cancelButton; var permalinkButton; + var unhidePreviewButton; if (eventStatus === 'not_sent') { resendButton = ( @@ -104,6 +114,18 @@ module.exports = React.createClass({ ); + + if (global.localStorage) { + // FIXME: factor this out with LinkPreviewWidget + if (global.localStorage.getItem("hide_preview_" + this.props.mxEvent.getId()) === "1") { + unhidePreviewButton = ( +
+ Unhide Preview +
+ ) + } + } + // XXX: this should be https://matrix.to. // XXX: if we use room ID, we should also include a server where the event can be found (other than in the domain of the event ID) permalinkButton = ( @@ -119,6 +141,7 @@ module.exports = React.createClass({ {redactButton} {cancelButton} {viewSourceButton} + {unhidePreviewButton} {permalinkButton} ); diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/UrlPreviewWidget.css b/src/skins/vector/css/matrix-react-sdk/views/rooms/UrlPreviewWidget.css index 800883a1..8a92ae4c 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/rooms/UrlPreviewWidget.css +++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/UrlPreviewWidget.css @@ -33,6 +33,8 @@ limitations under the License. .mx_LinkPreviewWidget_caption { margin-left: 15px; + -webkit-flex: 1; + flex: 1; } .mx_LinkPreviewWidget_title { @@ -48,3 +50,12 @@ limitations under the License. margin-top: 8px; white-space: normal; } + +.mx_LinkPreviewWidget_cancel { + visibility: hidden; + cursor: pointer; +} + +.mx_LinkPreviewWidget:hover .mx_LinkPreviewWidget_cancel { + visibility: visible; +} From d414127f8062ba998789cbea3b86fa3456de4fd2 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sun, 3 Apr 2016 23:31:42 +0100 Subject: [PATCH 05/11] track whether widget should be hidden on the event, as well as persisting it in localStorage --- src/components/views/rooms/MessageContextMenu.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/MessageContextMenu.js b/src/components/views/rooms/MessageContextMenu.js index 24948f74..0d162a82 100644 --- a/src/components/views/rooms/MessageContextMenu.js +++ b/src/components/views/rooms/MessageContextMenu.js @@ -71,8 +71,9 @@ module.exports = React.createClass({ // FIXME: factor this out with LinkPreviewWidget // FIXME: somehow propagate this to the EventTile such that it updates itself and realises the link has rematerialised global.localStorage.removeItem("hide_preview_" + this.props.mxEvent.getId()); - if (this.props.onFinished) this.props.onFinished(); } + this.props.mxEvent.widgetHidden = false; + if (this.props.onFinished) this.props.onFinished(); }, render: function() { @@ -116,7 +117,7 @@ module.exports = React.createClass({ if (global.localStorage) { - // FIXME: factor this out with LinkPreviewWidget + // FIXME: factor this out with LinkPreviewWidget if (global.localStorage.getItem("hide_preview_" + this.props.mxEvent.getId()) === "1") { unhidePreviewButton = (
From 333f1e46ca20af186a6a2243dbd7848f7f856498 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sun, 3 Apr 2016 23:57:44 +0100 Subject: [PATCH 06/11] document properties and remove spurious 'view full screen' button --- src/components/views/elements/ImageView.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/components/views/elements/ImageView.js b/src/components/views/elements/ImageView.js index db23e91b..a55e59e0 100644 --- a/src/components/views/elements/ImageView.js +++ b/src/components/views/elements/ImageView.js @@ -27,6 +27,10 @@ module.exports = React.createClass({ displayName: 'ImageView', propTypes: { + mxEvent: React.PropTypes.object, + src: React.PropTypes.string.isRequired, + width: React.PropTypes.number, + height: React.PropTypes.number, onFinished: React.PropTypes.func.isRequired, name: React.PropTypes.string }, @@ -164,11 +168,6 @@ module.exports = React.createClass({ { size } { res }
- { eventRedact }
From d7eb23db53499244a350dd3247974f8ee05c9747 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Mon, 4 Apr 2016 00:16:52 +0100 Subject: [PATCH 07/11] specify sizes and hyperlinks for non-event images --- src/components/views/elements/ImageView.js | 26 ++++++++++++++++------ 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/components/views/elements/ImageView.js b/src/components/views/elements/ImageView.js index a55e59e0..361e18fd 100644 --- a/src/components/views/elements/ImageView.js +++ b/src/components/views/elements/ImageView.js @@ -29,8 +29,10 @@ module.exports = React.createClass({ propTypes: { mxEvent: React.PropTypes.object, src: React.PropTypes.string.isRequired, + link: React.PropTypes.string, width: React.PropTypes.number, height: React.PropTypes.number, + size: React.PropTypes.number, onFinished: React.PropTypes.func.isRequired, name: React.PropTypes.string }, @@ -76,11 +78,15 @@ module.exports = React.createClass({ if(this.props.name) { name = this.props.name; } else if(this.props.mxEvent) { - name = props.mxEvent.getContent().body; + name = this.props.mxEvent.getContent().body; } else { name = null; } + if (name && this.props.link) { + name = { name }; + } + return name; }, @@ -121,14 +127,20 @@ module.exports = React.createClass({ width: this.props.width, height: this.props.height, }; - res = ", " + style.width + "x" + style.height + "px"; + res = style.width + "x" + style.height + "px"; } var size; - if (this.props.mxEvent && - this.props.mxEvent.getContent().info && - this.props.mxEvent.getContent().info.size) { - size = filesize(this.props.mxEvent.getContent().info.size); + if (this.props.size) { + size = filesize(this.props.size); + } + + var size_res; + if (size && res) { + size_res = size + ", " + res; + } + else { + size_res = size || res; } var showEventMeta = !!this.props.mxEvent; @@ -165,7 +177,7 @@ module.exports = React.createClass({
Download this file
- { size } { res } + { size_res }
{ eventRedact } From 41373f30f7883ed101fad994d1152273d9740db1 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Mon, 4 Apr 2016 00:33:15 +0100 Subject: [PATCH 08/11] oops, name LinkPreviewWidget correctly --- .../views/rooms/{UrlPreviewWidget.css => LinkPreviewWidget.css} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/skins/vector/css/matrix-react-sdk/views/rooms/{UrlPreviewWidget.css => LinkPreviewWidget.css} (100%) diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/UrlPreviewWidget.css b/src/skins/vector/css/matrix-react-sdk/views/rooms/LinkPreviewWidget.css similarity index 100% rename from src/skins/vector/css/matrix-react-sdk/views/rooms/UrlPreviewWidget.css rename to src/skins/vector/css/matrix-react-sdk/views/rooms/LinkPreviewWidget.css From d107151f8afa1be5629d1413e70603cb38025190 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Thu, 7 Apr 2016 18:09:50 +0100 Subject: [PATCH 09/11] rename `size` prop as `fileSize`, add comments, and honour explicit properties rather than mxEvent fields --- src/components/views/elements/ImageView.js | 35 ++++++++++------------ 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/src/components/views/elements/ImageView.js b/src/components/views/elements/ImageView.js index 361e18fd..38ca2e58 100644 --- a/src/components/views/elements/ImageView.js +++ b/src/components/views/elements/ImageView.js @@ -27,14 +27,19 @@ module.exports = React.createClass({ displayName: 'ImageView', propTypes: { + src: React.PropTypes.string.isRequired, // the source of the image being displayed + name: React.PropTypes.string, // the main title ('name') for the image + link: React.PropTypes.string, // the link (if any) applied to the name of the image + width: React.PropTypes.number, // width of the image src in pixels + height: React.PropTypes.number, // height of the image src in pixels + fileSize: React.PropTypes.number, // size of the image src in bytes + onFinished: React.PropTypes.func.isRequired, // callback when the lightbox is dismissed + + // the event (if any) that the Image is displaying. Used for event-specific stuff like + // redactions, senders, timestamps etc. Other descriptors are taken from the explicit + // properties above, which let us use lightboxes to display images which aren't associated + // with events. mxEvent: React.PropTypes.object, - src: React.PropTypes.string.isRequired, - link: React.PropTypes.string, - width: React.PropTypes.number, - height: React.PropTypes.number, - size: React.PropTypes.number, - onFinished: React.PropTypes.func.isRequired, - name: React.PropTypes.string }, // XXX: keyboard shortcuts for managing dialogs should be done by the modal @@ -73,20 +78,10 @@ module.exports = React.createClass({ }, getName: function () { - var name; - - if(this.props.name) { - name = this.props.name; - } else if(this.props.mxEvent) { - name = this.props.mxEvent.getContent().body; - } else { - name = null; - } - + var name = this.props.name; if (name && this.props.link) { name = { name }; } - return name; }, @@ -131,8 +126,8 @@ module.exports = React.createClass({ } var size; - if (this.props.size) { - size = filesize(this.props.size); + if (this.props.fileSize) { + size = filesize(this.props.fileSize); } var size_res; From cdc89c062346c80e184aa7ae0dbe5b4d9273a235 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Fri, 8 Apr 2016 21:42:42 +0100 Subject: [PATCH 10/11] add the concept of eventTileOps for managing widget visibility based on vdh's PR feedback --- src/components/views/rooms/MessageContextMenu.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/MessageContextMenu.js b/src/components/views/rooms/MessageContextMenu.js index 0d162a82..1e220fcc 100644 --- a/src/components/views/rooms/MessageContextMenu.js +++ b/src/components/views/rooms/MessageContextMenu.js @@ -27,6 +27,17 @@ var Resend = require("matrix-react-sdk/lib/Resend"); module.exports = React.createClass({ displayName: 'MessageContextMenu', + propTypes: { + /* the MatrixEvent associated with the context menu */ + mxEvent: React.PropTypes.object.isRequired, + + /* an optional EventTileOps implementation that can be used to unhide preview widgets */ + eventTileOps: React.PropTypes.object, + + /* callback called when the menu is dismissed */ + onFinished: React.PropTypes.func, + }, + onResendClick: function() { Resend.resend(this.props.mxEvent); if (this.props.onFinished) this.props.onFinished(); @@ -69,10 +80,11 @@ module.exports = React.createClass({ onUnhidePreviewClick: function() { if (global.localStorage) { // FIXME: factor this out with LinkPreviewWidget - // FIXME: somehow propagate this to the EventTile such that it updates itself and realises the link has rematerialised global.localStorage.removeItem("hide_preview_" + this.props.mxEvent.getId()); } - this.props.mxEvent.widgetHidden = false; + if (this.props.eventTileOps) { + this.props.eventTileOps.unhideWidget(); + } if (this.props.onFinished) this.props.onFinished(); }, From efd01d69290fbf398401b579703549b25ad3208f Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Mon, 11 Apr 2016 23:54:00 +0100 Subject: [PATCH 11/11] move localstorage crap entirely to TextualBody --- src/components/views/rooms/MessageContextMenu.js | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/components/views/rooms/MessageContextMenu.js b/src/components/views/rooms/MessageContextMenu.js index 1e220fcc..4eea4603 100644 --- a/src/components/views/rooms/MessageContextMenu.js +++ b/src/components/views/rooms/MessageContextMenu.js @@ -78,10 +78,6 @@ module.exports = React.createClass({ }, onUnhidePreviewClick: function() { - if (global.localStorage) { - // FIXME: factor this out with LinkPreviewWidget - global.localStorage.removeItem("hide_preview_" + this.props.mxEvent.getId()); - } if (this.props.eventTileOps) { this.props.eventTileOps.unhideWidget(); } @@ -127,10 +123,8 @@ module.exports = React.createClass({ ); - - if (global.localStorage) { - // FIXME: factor this out with LinkPreviewWidget - if (global.localStorage.getItem("hide_preview_" + this.props.mxEvent.getId()) === "1") { + if (this.props.eventTileOps) { + if (this.props.eventTileOps.isWidgetHidden()) { unhidePreviewButton = (
Unhide Preview