'use strict'; const React = require('react'); const create = require('create-react-class'); const Promise = require('bluebird'); const colorConvert = require('color-convert'); const sanitize = require('sanitize-html'); const riot = require('../lib/riot-utils.js'); const FileUpload = require('./fileUpload.js'); let input = create({ displayName: "Input", getInitialState: function() { return { uploads: [] }; }, setRef: function(ref) { if (ref !=null) { ref.addEventListener("keydown", (e) => { // only send on plain 'enter' if (e.key == "Enter") { if (!e.shiftKey && !e.altKey && !e.ctrlKey) { this.send(e); return; } } }); ref.addEventListener('change', this.resize_textarea); ref.addEventListener('cut', this.resize_textarea_delayed); ref.addEventListener('paste', this.resize_textarea_delayed); ref.addEventListener('drop', this.resize_textarea_delayed); ref.addEventListener('keydown', this.resize_textarea_delayed); this.setState({ref: ref}); } }, addUpload: function(upload) { let uploads = this.state.uploads; uploads.push(upload); this.setState({uploads: uploads}); }, removeUpload: function(index) { let uploads = this.state.uploads; uploads.splice(index, 1); this.setState({uploads: uploads}); }, resize_textarea: function(element) { if (element == undefined) { return; } let ref = element.target; if (ref != undefined) { ref.style.height = 'auto'; ref.style.height = ref.scrollHeight+'px'; } }, resize_textarea_delayed: function(e) { setTimeout(() => this.resize_textarea(e), 5); }, send: function(e) { let msg = e.target.value; if (msg.trim().length != 0) { //TODO: parse markdown (commonmark?) if (msg.startsWith('/')) { // Handle other commands let parts = msg.split(' '); let command = parts[0]; let result = handleCommands(command, parts); if (result != null) { if (result.type == "html") { this.sendHTML(result.content); } else { this.sendPlain(result.content); } } } else { this.sendPlain(msg); } } if (this.state.uploads.length > 0) { this.uploadFiles(this.state.uploads); this.setState({uploads: []}); } e.target.value = ""; e.preventDefault(); this.resize_textarea_delayed(e); }, uploadFiles: function(uploads) { let client = this.props.client; return Promise.map(uploads, (upload) => { let fileUploadPromise = client.uploadContent(upload.file, {onlyContentUri: false}).then((response) => { return response.content_uri; }); let mimeType = upload.file.type; let eventType = "m.file"; let additionalPromise; if (mimeType.startsWith("image/") || mimeType.startsWith("video/")) { function elementToThumbnail(element) { return Promise.try(() => { return riot.createThumbnail(element, element.width, element.height, thumbnailType ); }).catch((error) => { console.error("neo: error getting thumbnail", error); throw error; }).then((thumbResult) => { return client.uploadContent(thumbResult.thumbnail, {onlyContentUri: false}); }).then((response) => { return { thumbnail_url: response.content_uri, thumbnail_info: { mimetype: thumbnailType } }; }); } if (mimeType.startsWith("image/")) { eventType = "m.image"; additionalPromise = riot.loadImageElement(upload.file) .then((element) => {return elementToThumbnail(element);}); } else if (mimeType.startsWith("video/")) { eventType = "m.video"; additionalPromise = riot.loadVideoElement(upload.file) .then((element) => {return elementToThumbnail(element);}); } // create and upload thumbnail let thumbnailType = "image/png"; if (mimeType == "image/jpeg") { thumbnailType = mimeType; } } else if (mimeType.startsWith("audio/")) { eventType = "m.audio"; } else { // m.file } return Promise.all([fileUploadPromise, additionalPromise]).then((result) => { console.log(result); let info = { mimetype: mimeType }; if (result[1] != undefined) { info = Object.assign(info, result[1]); } return client.sendEvent(this.props.roomId, "m.room.message", { body: upload.file.name, msgtype: eventType, info: info, url: result[0] }); }); }); }, sendPlain: function(string) { let content = { body: string, msgtype: "m.text" }; content = this.sendReply(content); /* FIXME: Promisify */ this.props.client.sendEvent(this.props.roomId, "m.room.message", content, (err, _res) => { if (err != null) { console.log(err); } }); }, sendHTML: function(html) { let content = { body: sanitize(html, {allowedTags: []}), formatted_body: html, format: "org.matrix.custom.html", msgtype: "m.text" }; content = this.sendReply(content); /* FIXME: Promisify */ this.props.client.sendEvent(this.props.roomId, "m.room.message", content, (err, _res) => { console.log(err); }); }, sendReply: function(content) { if (this.props.replyEvent != undefined) { content['m.relates_to'] = { 'm.in_reply_to': { event_id: this.props.replyEvent.event_id } }; this.props.onReplyClick(); } return content; }, render: function() { return
{this.props.replyEvent &&
this.props.onReplyClick()}> {this.props.replyEvent.plaintext()}
} {this.state.uploads.length > 0 &&
{this.state.uploads.map((upload, key) => { return (
this.removeUpload(key)}>X
); })}
}
; } }); function handleCommands(command, parts) { if (command == "/rainbow") { if (parts.length < 2) { return; } let string = parts[1]; for(let i=2; i < parts.length; i++) { string += " " + parts[i]; } let html = rainbowTransform(string); return { type: 'html', content: html }; } return null; } function rainbowTransform(text) { let array = text.split(""); let delta = 360/text.length; if (delta < 10) { delta = 10; } else if (delta > 20) { delta = 20; } let h = -1 * delta; // start at beginning let rainbowArray = array.map((char) => { h = h + delta; if (h > 360) { h = 0; } return `${char}`; }); let rainbow = rainbowArray.join(""); return rainbow; } module.exports = input;