From 8e76d8277ed65b16f9607653599decdc08c4fafd Mon Sep 17 00:00:00 2001 From: f0x Date: Fri, 24 May 2019 11:40:05 +0200 Subject: [PATCH] add untracked files, whoops --- components/events/image.js | 4 +- components/events/video.js | 41 ++++++++++++++++++ lib/media.js | 56 ++++++++++++++++++++++++ public/icons/file.svg | 1 + tests/lib/media.js | 89 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 189 insertions(+), 2 deletions(-) create mode 100644 components/events/video.js create mode 100644 lib/media.js create mode 100644 public/icons/file.svg create mode 100644 tests/lib/media.js 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]) + }) +}