diff --git a/src/components/views/elements/ImageView.js b/src/components/views/elements/ImageView.js
index 91dbdc4a11..38ca2e5827 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 }
-
{ eventRedact }
diff --git a/src/components/views/rooms/MessageContextMenu.js b/src/components/views/rooms/MessageContextMenu.js
index a0a3f1cfd1..4eea46037c 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 0000000000..8a92ae4ce2
--- /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;
+}