diff --git a/components/events/image.js b/components/events/image.js
index ee3c976..820359e 100644
--- a/components/events/image.js
+++ b/components/events/image.js
@@ -34,9 +34,9 @@ let Event = create({
return (
)
}
diff --git a/components/events/video.js b/components/events/video.js
new file mode 100644
index 0000000..e14e66b
--- /dev/null
+++ b/components/events/video.js
@@ -0,0 +1,41 @@
+'use strict'
+const React = require('react')
+const ReactDOM = require('react-dom')
+const create = require('create-react-class')
+const Promise = require('bluebird')
+const defaultValue = require('default-value')
+
+const mediaLib = require('../../lib/media.js')
+
+const Text = require('./text.js')
+
+let Event = create({
+ displayName: "m.video",
+
+ getInitialState: function() {
+ let event = this.props.event
+ if (event.content.url == undefined) {
+ return null
+ }
+ return mediaLib.parseEvent(this.props.client, event, 1000, 1000)
+ },
+
+ render: function() {
+ let event = this.props.event
+
+ if (this.state == null) {
+ return "malformed video event: " + event.content.body
+ }
+
+ return (
+
+
+ {/**/}
+
+ )
+ }
+})
+
+module.exports = Event;
diff --git a/lib/media.js b/lib/media.js
new file mode 100644
index 0000000..a85ecfe
--- /dev/null
+++ b/lib/media.js
@@ -0,0 +1,56 @@
+// should be able to handle images, stickers, and video
+
+module.exports = {
+ parseEvent: function(client, event, maxHeight, maxWidth) {
+ if (event.content.msgtype == "m.image") {
+ let h = maxHeight
+ let w = maxWidth
+
+ let media_url = client.mxcUrlToHttp(event.content.url)
+ let thumb_url = event.content.url
+
+ if (event.content.info != null) {
+ if (event.content.info.thumbnail_url != null) {
+ thumb_url = event.content.info.thumbnail_url
+ }
+
+ if (event.content.info.thumbnail_info != null) {
+ h = (event.content.info.thumbnail_info.h < maxHeight) ? event.content.info.thumbnail_info.h : h
+ w = (event.content.info.thumbnail_info.w < maxWidth) ? event.content.info.thumbnail_info.w : w
+ } else {
+ h = (event.content.info.h < maxHeight) ? event.content.info.h : h
+ w = (event.content.info.w < maxWidth) ? event.content.info.w : w
+ }
+ }
+
+ thumb_url = client.mxcUrlToHttp(thumb_url, w, h, 'scale', false)
+
+ return {
+ full: media_url,
+ thumb: thumb_url,
+ size: {h, w}
+ }
+ }
+ if (event.content.msgtype == "m.video") {
+ let thumb = null
+ let h = maxHeight
+ let w = maxWidth
+
+ if (event.content.info != null) {
+ if (event.content.info.thumbnail_url != null) {
+ if (event.content.info.thumbnail_info != null) {
+ h = (event.content.info.thumbnail_info.h < maxHeight) ? event.content.info.thumbnail_info.h : h
+ w = (event.content.info.thumbnail_info.w < maxWidth) ? event.content.info.thumbnail_info.w : w
+ }
+
+ thumb = client.mxcUrlToHttp(event.content.thumbnail, w, h, 'scale', false)
+ }
+ }
+ return {
+ full: client.mxcUrlToHttp(event.content.url),
+ thumb: thumb,
+ size: {h, w}
+ }
+ }
+ }
+}
diff --git a/public/icons/file.svg b/public/icons/file.svg
new file mode 100644
index 0000000..478695a
--- /dev/null
+++ b/public/icons/file.svg
@@ -0,0 +1 @@
+
diff --git a/tests/lib/media.js b/tests/lib/media.js
new file mode 100644
index 0000000..441cb0b
--- /dev/null
+++ b/tests/lib/media.js
@@ -0,0 +1,89 @@
+let assert = require('assert')
+let urllib = require('url')
+let querystring = require('querystring')
+
+let mediaLib = require('../../lib/media.js')
+
+let client = {
+ mxcUrlToHttp: function(url, w, h, method, allowDirectLinks) {
+ let hs = "https://chat.privacytools.io"
+ let mxc = url.slice(6)
+ if (w) {
+ return `${hs}/_matrix/media/v1/thumbnail/${mxc}?w=${w}&h=${h}&method=${method}`
+ } else {
+ return `${hs}/_matrix/media/v1/download/${mxc}`
+ }
+ }
+}
+
+let mockEventTemplate = {
+ type: "m.room.message",
+ sender: "@f0x:privacytools.io",
+ content: {
+ body: "image.png",
+ info: {
+ size: 16692,
+ mimetype: "image/png",
+ thumbnail_info: {
+ w: 268,
+ h: 141,
+ mimetype: "image/png",
+ size: 16896
+ },
+ w: 268,
+ h: 141,
+ thumbnail_url: "mxc://privacytools.io/zBSerdKMhaXSIxfjzCmOnhXH"
+ },
+ msgtype: "m.image",
+ url: "mxc://privacytools.io/khPaFfeRyNdzlSttZraeAUre"
+ },
+ event_id: "$aaa:matrix.org",
+ origin_server_ts: 1558470168199,
+ unsigned: {
+ age: 143237861
+ },
+ room_id: "!aaa:matrix.org"
+}
+
+describe('media', function() {
+ describe('#parseEvent()', function() {
+ it('event without info', function() {
+ let mockEvent = JSON.parse(JSON.stringify(mockEventTemplate))
+ mockEvent.content.info = null
+
+ checkParsedEvent(mockEvent, {
+ w: 1000,
+ h: 1000,
+ method: 'scale'
+ })
+ }),
+ it('event without thumbnail', function() {
+ let mockEvent = JSON.parse(JSON.stringify(mockEventTemplate))
+ mockEvent.content.info.thumbnail_url = null
+ mockEvent.content.info.thumbnail_info = null
+ checkParsedEvent(mockEvent, {
+ w: 268,
+ h: 141,
+ method: 'scale'
+ })
+ })
+ it('event without thumbnail_info', function() {
+ let mockEvent = JSON.parse(JSON.stringify(mockEventTemplate))
+ mockEvent.content.info.thumbnail_url = null
+ checkParsedEvent(mockEvent, {
+ w: 268,
+ h: 141,
+ method: 'scale'
+ })
+ })
+ })
+})
+
+function checkParsedEvent(mockEvent, expected) {
+ let media = mediaLib.parseEvent(client, mockEvent, 1000, 1000)
+ let params = querystring.decode(urllib.parse(media.thumb).query)
+
+ Object.keys(params).forEach((key) => {
+ assert.equal(expected[key], params[key])
+ })
+}