diff --git a/src/components/views/elements/ImageView.js b/src/components/views/elements/ImageView.js index 91dbdc4a..38ca2e58 100644 --- a/src/components/views/elements/ImageView.js +++ b/src/components/views/elements/ImageView.js @@ -27,8 +27,19 @@ module.exports = React.createClass({ displayName: 'ImageView', propTypes: { - onFinished: React.PropTypes.func.isRequired, - name: React.PropTypes.string + 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, }, // XXX: keyboard shortcuts for managing dialogs should be done by the modal @@ -67,16 +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; }, @@ -117,14 +122,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.fileSize) { + size = filesize(this.props.fileSize); + } + + var size_res; + if (size && res) { + size_res = size + ", " + res; + } + else { + size_res = size || res; } var showEventMeta = !!this.props.mxEvent; @@ -161,14 +172,9 @@ module.exports = React.createClass({
Download this file
- { size } { res } + { size_res }
-
- - View full screen - -
{ eventRedact }
diff --git a/src/components/views/rooms/MessageContextMenu.js b/src/components/views/rooms/MessageContextMenu.js index a0a3f1cf..4eea4603 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(); @@ -66,6 +77,13 @@ module.exports = React.createClass({ if (this.props.onFinished) this.props.onFinished(); }, + onUnhidePreviewClick: function() { + if (this.props.eventTileOps) { + this.props.eventTileOps.unhideWidget(); + } + if (this.props.onFinished) this.props.onFinished(); + }, + render: function() { var eventStatus = this.props.mxEvent.status; var resendButton; @@ -73,6 +91,7 @@ module.exports = React.createClass({ var redactButton; var cancelButton; var permalinkButton; + var unhidePreviewButton; if (eventStatus === 'not_sent') { resendButton = ( @@ -104,6 +123,16 @@ module.exports = React.createClass({ ); + if (this.props.eventTileOps) { + if (this.props.eventTileOps.isWidgetHidden()) { + 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 +148,7 @@ module.exports = React.createClass({ {redactButton} {cancelButton} {viewSourceButton} + {unhidePreviewButton} {permalinkButton} ); diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/LinkPreviewWidget.css b/src/skins/vector/css/matrix-react-sdk/views/rooms/LinkPreviewWidget.css new file mode 100644 index 00000000..8a92ae4c --- /dev/null +++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/LinkPreviewWidget.css @@ -0,0 +1,61 @@ +/* +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 { + margin-top: 15px; + margin-right: 15px; + margin-bottom: 15px; + display: -webkit-flex; + display: flex; + border-left: 4px solid #ddd; + color: #888; +} + +.mx_LinkPreviewWidget_image { + -webkit-flex: 0 0 100px; + flex: 0 0 100px; + margin-left: 15px; + text-align: center; +} + +.mx_LinkPreviewWidget_caption { + margin-left: 15px; + -webkit-flex: 1; + flex: 1; +} + +.mx_LinkPreviewWidget_title { + display: inline; + font-weight: bold; +} + +.mx_LinkPreviewWidget_siteName { + display: inline; +} + +.mx_LinkPreviewWidget_description { + margin-top: 8px; + white-space: normal; +} + +.mx_LinkPreviewWidget_cancel { + visibility: hidden; + cursor: pointer; +} + +.mx_LinkPreviewWidget:hover .mx_LinkPreviewWidget_cancel { + visibility: visible; +}