From 26c6c25a4cce7a87799ffd52ec86b41a418f6192 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Sun, 3 Dec 2017 11:23:44 +0000 Subject: [PATCH 001/170] Add dom-to-image dep. --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index b443b4c72a..dc526b7105 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "classnames": "^2.1.2", "commonmark": "^0.27.0", "counterpart": "^0.18.0", + "dom-to-image": "^2.6.0", "draft-js": "^0.11.0-alpha", "draft-js-export-html": "^0.6.0", "draft-js-export-markdown": "^0.3.0", From 3a89b90e57c7e2b13a2fe623e71495da2e0603ca Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Sun, 3 Dec 2017 11:25:15 +0000 Subject: [PATCH 002/170] Add stub handler for image snapshot --- src/components/views/elements/AppTile.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index a005406133..db722bd66d 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -221,6 +221,10 @@ export default React.createClass({ }, "mx_IntegrationsManager"); }, + _onSnapshotClick(e) { + console.log("Snapshot widget ID ", this.props.id); + }, + /* If user has permission to modify widgets, delete the widget, * otherwise revoke access for the widget to load in the user's browser */ @@ -379,11 +383,25 @@ export default React.createClass({ deleteClasses += ' mx_AppTileMenuBarWidgetDelete'; } + // Picture snapshot + const showPictureSnapshotButton = true; // FIXME - Make this dynamic + const showPictureSnapshotIcon = 'img/camera_green.svg'; + return (
{ this.formatAppTileName() } + { /* Snapshot widget */ } + { showPictureSnapshotButton && } + { /* Edit widget */ } { showEditButton && Date: Sun, 3 Dec 2017 19:44:59 +0000 Subject: [PATCH 003/170] Workings for future posterity - Can't access iframe content from parent. iframe needs to initiate. Postmessage data up the stack. --- src/components/structures/RoomView.js | 3 +++ src/components/views/elements/AppTile.js | 22 +++++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 1fda05fb76..cf3320b607 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -468,6 +468,9 @@ module.exports = React.createClass({ unsentMessageError: this._getUnsentMessageError(this.state.room), }); break; + case 'picture_snapshot': + this.uploadFile(payload.file); + break; case 'notifier_enabled': case 'upload_failed': case 'upload_started': diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index db722bd66d..a0eb7efe52 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -32,6 +32,7 @@ import AppWarning from './AppWarning'; import MessageSpinner from './MessageSpinner'; import WidgetUtils from '../../../WidgetUtils'; import dis from '../../../dispatcher'; +import domtoimage from 'dom-to-image'; const ALLOWED_APP_URL_SCHEMES = ['https:', 'http:']; @@ -222,7 +223,14 @@ export default React.createClass({ }, _onSnapshotClick(e) { - console.log("Snapshot widget ID ", this.props.id); + const iframe = this.refs.appFrame; + domtoimage.toPng(iframe).then(function(dataUrl) { + console.log("Image data URL:", dataUrl); + dis.dispatch({ + action: 'picture_snapshot', + file: dataURLtoBlob(dataUrl), + }, true); + }); }, /* If user has permission to modify widgets, delete the widget, @@ -428,3 +436,15 @@ export default React.createClass({ ); }, }); + +function dataURLtoBlob(dataurl) { + const arr = dataurl.split(','); + const mime = arr[0].match(/:(.*?);/)[1]; + const bstr = atob(arr[1]); + let n = bstr.length; + const u8arr = new Uint8Array(n); + while (n--) { + u8arr[n] = bstr.charCodeAt(n); + } + return new Blob([u8arr], {type: mime}); +} From c234e209fbb375b8ef227fa1d27648d961bb496b Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Fri, 15 Dec 2017 15:24:22 +0000 Subject: [PATCH 004/170] Add postmessage api and move functions in to class --- src/MatrixPostMessageApi.js | 101 +++++++++++ src/WidgetMessaging.js | 348 +++++++++++++++++++----------------- 2 files changed, 286 insertions(+), 163 deletions(-) create mode 100644 src/MatrixPostMessageApi.js diff --git a/src/MatrixPostMessageApi.js b/src/MatrixPostMessageApi.js new file mode 100644 index 0000000000..dd65cbd8fa --- /dev/null +++ b/src/MatrixPostMessageApi.js @@ -0,0 +1,101 @@ +import Promise from "bluebird"; + + +function defer() { + let resolve, reject; + let isPending = true; + let promise = new Promise(function(...args) { + resolve = args[0]; + reject = args[1]; + }); + return { + resolve: function(...args) { + if (!isPending) { + return; + } + isPending = false; + resolve(args[0]); + }, + reject: function(...args) { + if (!isPending) { + return; + } + isPending = false; + reject(args[0]); + }, + isPending: function() { + return isPending; + }, + promise: promise, + }; +} + +// NOTE: PostMessageApi only handles message events with a data payload with a +// response field +export default class PostMessageApi { + constructor(targetWindow, timeoutMs) { + this._window = targetWindow || window.parent; // default to parent window + this._timeoutMs = timeoutMs || 5000; // default to 5s timer + this._counter = 0; + this._pending = { + // $ID: Deferred + }; + } + + start() { + addEventListener('message', this.getOnMessageCallback()); + } + + stop() { + removeEventListener('message', this.getOnMessageCallback()); + } + + // Somewhat convoluted so we can successfully capture the PostMessageApi 'this' instance. + getOnMessageCallback() { + if (this._onMsgCallback) { + return this._onMsgCallback; + } + let self = this; + this._onMsgCallback = function(ev) { + // THIS IS ALL UNSAFE EXECUTION. + // We do not verify who the sender of `ev` is! + let payload = ev.data; + // NOTE: Workaround for running in a mobile WebView where a + // postMessage immediately triggers this callback even though it is + // not the response. + if (payload.response === undefined) { + return; + } + let deferred = self._pending[payload._id]; + if (!deferred) { + return; + } + if (!deferred.isPending()) { + return; + } + delete self._pending[payload._id]; + deferred.resolve(payload); + }; + return this._onMsgCallback; + } + + exec(action, target) { + this._counter += 1; + target = target || "*"; + action._id = Date.now() + "-" + Math.random().toString(36) + "-" + this._counter; + let d = defer(); + this._pending[action._id] = d; + this._window.postMessage(action, target); + + if (this._timeoutMs > 0) { + setTimeout(function() { + if (!d.isPending()) { + return; + } + console.error("postMessage request timed out. Sent object: " + JSON.stringify(action)); + d.reject(new Error("Timed out")); + }, this._timeoutMs); + } + return d.promise; + } +} diff --git a/src/WidgetMessaging.js b/src/WidgetMessaging.js index 0f23413b5f..7cd18132af 100644 --- a/src/WidgetMessaging.js +++ b/src/WidgetMessaging.js @@ -112,14 +112,14 @@ Example: */ import URL from 'url'; +import dis from './dispatcher'; +import MatrixPostMessageApi from './MatrixPostMessageApi'; const WIDGET_API_VERSION = '0.0.1'; // Current API version const SUPPORTED_WIDGET_API_VERSIONS = [ '0.0.1', ]; -import dis from './dispatcher'; - if (!global.mxWidgetMessagingListenerCount) { global.mxWidgetMessagingListenerCount = 0; } @@ -127,176 +127,205 @@ if (!global.mxWidgetMessagingMessageEndpoints) { global.mxWidgetMessagingMessageEndpoints = []; } - -/** - * Register widget message event listeners - */ -function startListening() { - if (global.mxWidgetMessagingListenerCount === 0) { - window.addEventListener("message", onMessage, false); - } - global.mxWidgetMessagingListenerCount += 1; -} - -/** - * De-register widget message event listeners - */ -function stopListening() { - global.mxWidgetMessagingListenerCount -= 1; - if (global.mxWidgetMessagingListenerCount === 0) { - window.removeEventListener("message", onMessage); - } - if (global.mxWidgetMessagingListenerCount < 0) { - // Make an error so we get a stack trace - const e = new Error( - "WidgetMessaging: mismatched startListening / stopListening detected." + - " Negative count", - ); - console.error(e); - } -} - -/** - * Register a widget endpoint for trusted postMessage communication - * @param {string} widgetId Unique widget identifier - * @param {string} endpointUrl Widget wurl origin (protocol + (optional port) + host) - */ -function addEndpoint(widgetId, endpointUrl) { - const u = URL.parse(endpointUrl); - if (!u || !u.protocol || !u.host) { - console.warn("Invalid origin:", endpointUrl); - return; +export default class WidgetMessaging extends MatrixPostMessageApi { + constructor(targetWindow) { + super(targetWindow); } - const origin = u.protocol + '//' + u.host; - const endpoint = new WidgetMessageEndpoint(widgetId, origin); - if (global.mxWidgetMessagingMessageEndpoints) { - if (global.mxWidgetMessagingMessageEndpoints.some(function(ep) { - return (ep.widgetId === widgetId && ep.endpointUrl === endpointUrl); - })) { - // Message endpoint already registered - console.warn("Endpoint already registered"); + exec(action) { + return super.exec(action).then((data) => { + // check for errors and reject if found + if (data.response === undefined) { // null is valid + throw new Error("Missing 'response' field"); + } + if (data.response && data.response.error) { + const err = data.response.error; + const msg = String(err.message ? err.message : "An error was returned"); + if (err._error) { + console.error(err._error); + } + // Potential XSS attack if 'msg' is not appropriately sanitized, + // as it is untrusted input by our parent window (which we assume is Riot). + // We can't aggressively sanitize [A-z0-9] since it might be a translation. + throw new Error(msg); + } + // return the response field for the request + return data.response; + }); + } + + /** + * Register widget message event listeners + */ + startListening() { + if (global.mxWidgetMessagingListenerCount === 0) { + window.addEventListener("message", this.onMessage, false); + } + global.mxWidgetMessagingListenerCount += 1; + } + + /** + * De-register widget message event listeners + */ + stopListening() { + global.mxWidgetMessagingListenerCount -= 1; + if (global.mxWidgetMessagingListenerCount === 0) { + window.removeEventListener("message", this.onMessage); + } + if (global.mxWidgetMessagingListenerCount < 0) { + // Make an error so we get a stack trace + const e = new Error( + "WidgetMessaging: mismatched startListening / stopListening detected." + + " Negative count", + ); + console.error(e); + } + } + + /** + * Register a widget endpoint for trusted postMessage communication + * @param {string} widgetId Unique widget identifier + * @param {string} endpointUrl Widget wurl origin (protocol + (optional port) + host) + */ + addEndpoint(widgetId, endpointUrl) { + const u = URL.parse(endpointUrl); + if (!u || !u.protocol || !u.host) { + console.warn("Invalid origin:", endpointUrl); return; } - global.mxWidgetMessagingMessageEndpoints.push(endpoint); - } -} -/** - * De-register a widget endpoint from trusted communication sources - * @param {string} widgetId Unique widget identifier - * @param {string} endpointUrl Widget wurl origin (protocol + (optional port) + host) - * @return {boolean} True if endpoint was successfully removed - */ -function removeEndpoint(widgetId, endpointUrl) { - const u = URL.parse(endpointUrl); - if (!u || !u.protocol || !u.host) { - console.warn("Invalid origin"); - return; + const origin = u.protocol + '//' + u.host; + const endpoint = new WidgetMessageEndpoint(widgetId, origin); + if (global.mxWidgetMessagingMessageEndpoints) { + if (global.mxWidgetMessagingMessageEndpoints.some(function(ep) { + return (ep.widgetId === widgetId && ep.endpointUrl === endpointUrl); + })) { + // Message endpoint already registered + console.warn("Endpoint already registered"); + return; + } + global.mxWidgetMessagingMessageEndpoints.push(endpoint); + } } - const origin = u.protocol + '//' + u.host; - if (global.mxWidgetMessagingMessageEndpoints && global.mxWidgetMessagingMessageEndpoints.length > 0) { - const length = global.mxWidgetMessagingMessageEndpoints.length; - global.mxWidgetMessagingMessageEndpoints = global.mxWidgetMessagingMessageEndpoints.filter(function(endpoint) { - return (endpoint.widgetId != widgetId || endpoint.endpointUrl != origin); - }); - return (length > global.mxWidgetMessagingMessageEndpoints.length); - } - return false; -} + /** + * De-register a widget endpoint from trusted communication sources + * @param {string} widgetId Unique widget identifier + * @param {string} endpointUrl Widget wurl origin (protocol + (optional port) + host) + * @return {boolean} True if endpoint was successfully removed + */ + removeEndpoint(widgetId, endpointUrl) { + const u = URL.parse(endpointUrl); + if (!u || !u.protocol || !u.host) { + console.warn("Invalid origin"); + return; + } - -/** - * Handle widget postMessage events - * @param {Event} event Event to handle - * @return {undefined} - */ -function onMessage(event) { - if (!event.origin) { // Handle chrome - event.origin = event.originalEvent.origin; - } - - // Event origin is empty string if undefined - if ( - event.origin.length === 0 || - !trustedEndpoint(event.origin) || - event.data.api !== "widget" || - !event.data.widgetId - ) { - return; // don't log this - debugging APIs like to spam postMessage which floods the log otherwise - } - - const action = event.data.action; - const widgetId = event.data.widgetId; - if (action === 'content_loaded') { - dis.dispatch({ - action: 'widget_content_loaded', - widgetId: widgetId, - }); - sendResponse(event, {success: true}); - } else if (action === 'supported_api_versions') { - sendResponse(event, { - api: "widget", - supported_versions: SUPPORTED_WIDGET_API_VERSIONS, - }); - } else if (action === 'api_version') { - sendResponse(event, { - api: "widget", - version: WIDGET_API_VERSION, - }); - } else { - console.warn("Widget postMessage event unhandled"); - sendError(event, {message: "The postMessage was unhandled"}); - } -} - -/** - * Check if message origin is registered as trusted - * @param {string} origin PostMessage origin to check - * @return {boolean} True if trusted - */ -function trustedEndpoint(origin) { - if (!origin) { + const origin = u.protocol + '//' + u.host; + if (global.mxWidgetMessagingMessageEndpoints && global.mxWidgetMessagingMessageEndpoints.length > 0) { + const length = global.mxWidgetMessagingMessageEndpoints.length; + global.mxWidgetMessagingMessageEndpoints = global.mxWidgetMessagingMessageEndpoints. + filter(function(endpoint) { + return (endpoint.widgetId != widgetId || endpoint.endpointUrl != origin); + }); + return (length > global.mxWidgetMessagingMessageEndpoints.length); + } return false; } - return global.mxWidgetMessagingMessageEndpoints.some((endpoint) => { - return endpoint.endpointUrl === origin; - }); -} -/** - * Send a postmessage response to a postMessage request - * @param {Event} event The original postMessage request event - * @param {Object} res Response data - */ -function sendResponse(event, res) { - const data = JSON.parse(JSON.stringify(event.data)); - data.response = res; - event.source.postMessage(data, event.origin); -} + /** + * Handle widget postMessage events + * @param {Event} event Event to handle + * @return {undefined} + */ + onMessage(event) { + if (!event.origin) { // Handle chrome + event.origin = event.originalEvent.origin; + } -/** - * Send an error response to a postMessage request - * @param {Event} event The original postMessage request event - * @param {string} msg Error message - * @param {Error} nestedError Nested error event (optional) - */ -function sendError(event, msg, nestedError) { - console.error("Action:" + event.data.action + " failed with message: " + msg); - const data = JSON.parse(JSON.stringify(event.data)); - data.response = { - error: { - message: msg, - }, - }; - if (nestedError) { - data.response.error._error = nestedError; + // Event origin is empty string if undefined + if ( + event.origin.length === 0 || + !this.trustedEndpoint(event.origin) || + event.data.api !== "widget" || + !event.data.widgetId + ) { + return; // don't log this - debugging APIs like to spam postMessage which floods the log otherwise + } + + const action = event.data.action; + const widgetId = event.data.widgetId; + if (action === 'content_loaded') { + dis.dispatch({ + action: 'widget_content_loaded', + widgetId: widgetId, + }); + this.sendResponse(event, {success: true}); + } else if (action === 'supported_api_versions') { + this.sendResponse(event, { + api: "widget", + supported_versions: SUPPORTED_WIDGET_API_VERSIONS, + }); + } else if (action === 'api_version') { + this.sendResponse(event, { + api: "widget", + version: WIDGET_API_VERSION, + }); + } else { + console.warn("Widget postMessage event unhandled"); + this.sendError(event, {message: "The postMessage was unhandled"}); + } + } + + /** + * Check if message origin is registered as trusted + * @param {string} origin PostMessage origin to check + * @return {boolean} True if trusted + */ + trustedEndpoint(origin) { + if (!origin) { + return false; + } + + return global.mxWidgetMessagingMessageEndpoints.some((endpoint) => { + return endpoint.endpointUrl === origin; + }); + } + + /** + * Send a postmessage response to a postMessage request + * @param {Event} event The original postMessage request event + * @param {Object} res Response data + */ + sendResponse(event, res) { + const data = JSON.parse(JSON.stringify(event.data)); + data.response = res; + event.source.postMessage(data, event.origin); + } + + /** + * Send an error response to a postMessage request + * @param {Event} event The original postMessage request event + * @param {string} msg Error message + * @param {Error} nestedError Nested error event (optional) + */ + sendError(event, msg, nestedError) { + console.error("Action:" + event.data.action + " failed with message: " + msg); + const data = JSON.parse(JSON.stringify(event.data)); + data.response = { + error: { + message: msg, + }, + }; + if (nestedError) { + data.response.error._error = nestedError; + } + event.source.postMessage(data, event.origin); } - event.source.postMessage(data, event.origin); } + /** * Represents mapping of widget instance to URLs for trusted postMessage communication. */ @@ -317,10 +346,3 @@ class WidgetMessageEndpoint { this.endpointUrl = endpointUrl; } } - -export default { - startListening: startListening, - stopListening: stopListening, - addEndpoint: addEndpoint, - removeEndpoint: removeEndpoint, -}; From 56f497d39eddefa036bb9c81fe1c27e9f799f69a Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Fri, 15 Dec 2017 16:39:04 +0000 Subject: [PATCH 005/170] Add comments and outbound postmessage action to request a widget screenshot. --- src/WidgetMessaging.js | 53 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/src/WidgetMessaging.js b/src/WidgetMessaging.js index 7cd18132af..a35dc3d714 100644 --- a/src/WidgetMessaging.js +++ b/src/WidgetMessaging.js @@ -52,8 +52,8 @@ They look like: } The "message" key should be a human-friendly string. -ACTIONS -======= +INBOUND ACTIONS +=============== ** All actions must include an "api" field with valie "widget".** All actions can return an error response instead of the response outlined below. @@ -109,6 +109,45 @@ Example: action: "supported_api_versions", } + +OUTBOUND ACTIONS +================ + +In addition to listening for inbound requests, the API can be used to initiate +actionss in the widget iframe, and request data from the widget instance. + +Outbound actions use the "widget_client" API key / name, which must be included +on all requests. + +{ + api: "widget_client", + action: "screenshot", + widgetId: $WIDGET_ID, + data: {} + // additional request fields +} + + +screenshot +---------- + +Request a screenshot from the widget (if supported). +This can only be supported by widgets that have access to all of their DOM tree. +For example, widgets that nest further levels of iframes can not support this. + +Request: + - No additional fields. +Response: +{ + screenshot: {data...} +} +Example: +{ + api: "widget_client", + action: "screenshot", + widgetId: $WIDGET_ID +} + */ import URL from 'url'; @@ -323,6 +362,16 @@ export default class WidgetMessaging extends MatrixPostMessageApi { } event.source.postMessage(data, event.origin); } + + /** + * Request a screenshot from a widget + */ + getScreenshot() { + const screenshot = this.exec({ + action: "screenshot", + }); + console.warn("got screenshot", screenshot); + } } From 9f733ebc940760059ecf6321163b1c2f67a9098c Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Fri, 15 Dec 2017 16:55:33 +0000 Subject: [PATCH 006/170] Fix binding and promise handling --- src/WidgetMessaging.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/WidgetMessaging.js b/src/WidgetMessaging.js index a35dc3d714..1180dd2df2 100644 --- a/src/WidgetMessaging.js +++ b/src/WidgetMessaging.js @@ -198,7 +198,7 @@ export default class WidgetMessaging extends MatrixPostMessageApi { */ startListening() { if (global.mxWidgetMessagingListenerCount === 0) { - window.addEventListener("message", this.onMessage, false); + window.addEventListener("message", () => this.onMessage, false); } global.mxWidgetMessagingListenerCount += 1; } @@ -209,7 +209,7 @@ export default class WidgetMessaging extends MatrixPostMessageApi { stopListening() { global.mxWidgetMessagingListenerCount -= 1; if (global.mxWidgetMessagingListenerCount === 0) { - window.removeEventListener("message", this.onMessage); + window.removeEventListener("message", () => this.onMessage); } if (global.mxWidgetMessagingListenerCount < 0) { // Make an error so we get a stack trace @@ -367,10 +367,11 @@ export default class WidgetMessaging extends MatrixPostMessageApi { * Request a screenshot from a widget */ getScreenshot() { - const screenshot = this.exec({ + this.exec({ action: "screenshot", + }).then(function(screenshot) { + console.warn("got screenshot", screenshot); }); - console.warn("got screenshot", screenshot); } } From f2ad7be3f3e77a38bb15aa5a2faffa50b54f38c8 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Fri, 15 Dec 2017 16:56:02 +0000 Subject: [PATCH 007/170] Add event handlers and comments. --- src/components/views/elements/AppTile.js | 33 ++++++++++++++++-------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 812d8e8bdd..d97f844038 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -155,12 +155,15 @@ export default React.createClass({ }, componentWillMount() { - WidgetMessaging.startListening(); - WidgetMessaging.addEndpoint(this.props.id, this.props.url); - window.addEventListener('message', this._onMessage, false); this.setScalarToken(); }, + componentDidMount() { + // Legacy Jitsi widget messaging -- TODO replace this with standard widget + // postMessaging API + window.addEventListener('message', this._onMessage, false); + }, + /** * Adds a scalar token to the widget URL, if required * Component initialisation is only complete when this function has resolved @@ -234,6 +237,8 @@ export default React.createClass({ } }, + // Legacy Jitsi widget messaging + // TODO -- This should be replaced with the new widget postMessaging API _onMessage(event) { if (this.props.type !== 'jitsi') { return; @@ -268,14 +273,16 @@ export default React.createClass({ }, _onSnapshotClick(e) { - const iframe = this.refs.appFrame; - domtoimage.toPng(iframe).then(function(dataUrl) { - console.log("Image data URL:", dataUrl); - dis.dispatch({ - action: 'picture_snapshot', - file: dataURLtoBlob(dataUrl), - }, true); - }); + console.warn("Requesting widget snapshot"); + this.widgetMessaging.getScreenshot(); + // const iframe = this.refs.appFrame; + // domtoimage.toPng(iframe).then(function(dataUrl) { + // console.log("Image data URL:", dataUrl); + // dis.dispatch({ + // action: 'picture_snapshot', + // file: dataURLtoBlob(dataUrl), + // }, true); + // }); }, /* If user has permission to modify widgets, delete the widget, @@ -317,6 +324,10 @@ export default React.createClass({ * Called when widget iframe has finished loading */ _onLoaded() { + // console.warn("App frame", this.refs.appFrame.contentWindow); + this.widgetMessaging = new WidgetMessaging(this.refs.appFrame.contentWindow); + this.widgetMessaging.startListening(); + this.widgetMessaging.addEndpoint(this.props.id, this.props.url); this.setState({loading: false}); }, From 954c6eecd6665d204a4fb9ec7767971b4db84dc2 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Fri, 15 Dec 2017 19:42:06 +0000 Subject: [PATCH 008/170] Set correct API name. --- src/WidgetMessaging.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/WidgetMessaging.js b/src/WidgetMessaging.js index 1180dd2df2..134f93f0f7 100644 --- a/src/WidgetMessaging.js +++ b/src/WidgetMessaging.js @@ -368,6 +368,7 @@ export default class WidgetMessaging extends MatrixPostMessageApi { */ getScreenshot() { this.exec({ + api: "widget_client", action: "screenshot", }).then(function(screenshot) { console.warn("got screenshot", screenshot); From e63f5696a6897341d24909bb53bb97e049654be0 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Fri, 15 Dec 2017 21:36:02 +0000 Subject: [PATCH 009/170] Screenshot handlers --- src/WidgetMessaging.js | 19 ++++++++++++++----- src/components/views/elements/AppTile.js | 17 ++++++++--------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/WidgetMessaging.js b/src/WidgetMessaging.js index 134f93f0f7..2efdc366b6 100644 --- a/src/WidgetMessaging.js +++ b/src/WidgetMessaging.js @@ -153,6 +153,7 @@ Example: import URL from 'url'; import dis from './dispatcher'; import MatrixPostMessageApi from './MatrixPostMessageApi'; +import Promise from 'bluebird'; const WIDGET_API_VERSION = '0.0.1'; // Current API version const SUPPORTED_WIDGET_API_VERSIONS = [ @@ -197,6 +198,7 @@ export default class WidgetMessaging extends MatrixPostMessageApi { * Register widget message event listeners */ startListening() { + this.start(); if (global.mxWidgetMessagingListenerCount === 0) { window.addEventListener("message", () => this.onMessage, false); } @@ -207,6 +209,7 @@ export default class WidgetMessaging extends MatrixPostMessageApi { * De-register widget message event listeners */ stopListening() { + this.stop(); global.mxWidgetMessagingListenerCount -= 1; if (global.mxWidgetMessagingListenerCount === 0) { window.removeEventListener("message", () => this.onMessage); @@ -365,13 +368,19 @@ export default class WidgetMessaging extends MatrixPostMessageApi { /** * Request a screenshot from a widget + * @return {Promise} To be resolved when screenshot has been generated */ getScreenshot() { - this.exec({ - api: "widget_client", - action: "screenshot", - }).then(function(screenshot) { - console.warn("got screenshot", screenshot); + return new Promise((resolve, reject) => { + this.exec({ + api: "widget_client", + action: "screenshot", + }).then(function(response) { + // console.warn("got screenshot", response.screenshot); + resolve(response.screenshot); + }).catch((error) => { + reject(Error("Failed to get screenshot: " + error.message)); + }); }); } } diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index d97f844038..b10d7f91ad 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -274,15 +274,14 @@ export default React.createClass({ _onSnapshotClick(e) { console.warn("Requesting widget snapshot"); - this.widgetMessaging.getScreenshot(); - // const iframe = this.refs.appFrame; - // domtoimage.toPng(iframe).then(function(dataUrl) { - // console.log("Image data URL:", dataUrl); - // dis.dispatch({ - // action: 'picture_snapshot', - // file: dataURLtoBlob(dataUrl), - // }, true); - // }); + this.widgetMessaging.getScreenshot().then((screenshot) => { + dis.dispatch({ + action: 'picture_snapshot', + file: screenshot, + }, true); + }).catch((err) => { + console.error("Failed to get screenshot", err); + }); }, /* If user has permission to modify widgets, delete the widget, From 83f9a4162b1fd3d5dcd279dc227583fb142a25d6 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Sat, 16 Dec 2017 09:16:24 +0000 Subject: [PATCH 010/170] Request capabilities (e.g. ability to take snapshots) from widgets. --- src/WidgetMessaging.js | 14 +++++++++++ src/components/views/elements/AppTile.js | 32 +++++++++++++----------- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/WidgetMessaging.js b/src/WidgetMessaging.js index 2efdc366b6..d71d86f8f5 100644 --- a/src/WidgetMessaging.js +++ b/src/WidgetMessaging.js @@ -383,6 +383,20 @@ export default class WidgetMessaging extends MatrixPostMessageApi { }); }); } + + getCapabilities() { + return new Promise((resolve, reject) => { + this.exec({ + api: "widget_client", + action: "capabilities", + }).then(function(response) { + // console.warn("got capabilities", response.capabilities); + resolve(response.capabilities); + }).catch((error) => { + reject(Error("Failed to get capabilities: " + error.message)); + }); + }); + } } diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index b10d7f91ad..770406e645 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -33,7 +33,6 @@ import AppWarning from './AppWarning'; import MessageSpinner from './MessageSpinner'; import WidgetUtils from '../../../WidgetUtils'; import dis from '../../../dispatcher'; -import domtoimage from 'dom-to-image'; const ALLOWED_APP_URL_SCHEMES = ['https:', 'http:']; @@ -83,9 +82,20 @@ export default React.createClass({ error: null, deleting: false, widgetPageTitle: newProps.widgetPageTitle, + capabilities: [], }; }, + + /** + * Does the widget support a given capability + * @param {[type]} capability Capability to check for + * @return {Boolean} True if capability supported + */ + _hasCapability(capability) { + return this.state.capabilities.some((c) => {return c === capability;}); + }, + /** * Add widget instance specific parameters to pass in wUrl * Properties passed to widget instance: @@ -327,6 +337,12 @@ export default React.createClass({ this.widgetMessaging = new WidgetMessaging(this.refs.appFrame.contentWindow); this.widgetMessaging.startListening(); this.widgetMessaging.addEndpoint(this.props.id, this.props.url); + this.widgetMessaging.getCapabilities().then((capabilities) => { + console.log("Got widget capabilities", this.widgetId, capabilities); + this.setState({capabilities}); + }).catch((err) => { + console.log("Failed to get widget capabilities", this.widgetId, err); + }); this.setState({loading: false}); }, @@ -468,7 +484,7 @@ export default React.createClass({ } // Picture snapshot - const showPictureSnapshotButton = true; // FIXME - Make this dynamic + const showPictureSnapshotButton = this._hasCapability('screenshot'); const showPictureSnapshotIcon = 'img/camera_green.svg'; const windowStateIcon = (this.props.show ? 'img/minimize.svg' : 'img/maximize.svg'); @@ -525,15 +541,3 @@ export default React.createClass({ ); }, }); - -function dataURLtoBlob(dataurl) { - const arr = dataurl.split(','); - const mime = arr[0].match(/:(.*?);/)[1]; - const bstr = atob(arr[1]); - let n = bstr.length; - const u8arr = new Uint8Array(n); - while (n--) { - u8arr[n] = bstr.charCodeAt(n); - } - return new Blob([u8arr], {type: mime}); -} From 774774c365a69ec4a563f972c608bf9f05dd45b5 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Tue, 19 Dec 2017 17:06:08 +0000 Subject: [PATCH 011/170] Remove unused dep. --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 0e2074f381..943c443c59 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,6 @@ "classnames": "^2.1.2", "commonmark": "^0.27.0", "counterpart": "^0.18.0", - "dom-to-image": "^2.6.0", "draft-js": "^0.11.0-alpha", "draft-js-export-html": "^0.6.0", "draft-js-export-markdown": "^0.3.0", From 8e5c3f01b47da99b6188805d671e792d4eb6b0d6 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Tue, 19 Dec 2017 17:08:17 +0000 Subject: [PATCH 012/170] License and linting fixes. --- src/MatrixPostMessageApi.js | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/MatrixPostMessageApi.js b/src/MatrixPostMessageApi.js index dd65cbd8fa..d6417f8764 100644 --- a/src/MatrixPostMessageApi.js +++ b/src/MatrixPostMessageApi.js @@ -1,10 +1,26 @@ +/* +Copyright 2017 New Vector 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. +*/ + import Promise from "bluebird"; - function defer() { - let resolve, reject; + let resolve; + let reject; let isPending = true; - let promise = new Promise(function(...args) { + const promise = new Promise(function(...args) { resolve = args[0]; reject = args[1]; }); @@ -55,18 +71,18 @@ export default class PostMessageApi { if (this._onMsgCallback) { return this._onMsgCallback; } - let self = this; + const self = this; this._onMsgCallback = function(ev) { // THIS IS ALL UNSAFE EXECUTION. // We do not verify who the sender of `ev` is! - let payload = ev.data; + const payload = ev.data; // NOTE: Workaround for running in a mobile WebView where a // postMessage immediately triggers this callback even though it is // not the response. if (payload.response === undefined) { return; } - let deferred = self._pending[payload._id]; + const deferred = self._pending[payload._id]; if (!deferred) { return; } @@ -83,7 +99,7 @@ export default class PostMessageApi { this._counter += 1; target = target || "*"; action._id = Date.now() + "-" + Math.random().toString(36) + "-" + this._counter; - let d = defer(); + const d = defer(); this._pending[action._id] = d; this._window.postMessage(action, target); From 536d4efc4059127c6e407524436e1ea034057a99 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Tue, 19 Dec 2017 17:11:36 +0000 Subject: [PATCH 013/170] Fix comments. --- src/WidgetMessaging.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/WidgetMessaging.js b/src/WidgetMessaging.js index d71d86f8f5..2ca8589b54 100644 --- a/src/WidgetMessaging.js +++ b/src/WidgetMessaging.js @@ -54,7 +54,7 @@ The "message" key should be a human-friendly string. INBOUND ACTIONS =============== -** All actions must include an "api" field with valie "widget".** +** All actions must include an "api" field with value of "widget".** All actions can return an error response instead of the response outlined below. content_loaded @@ -66,7 +66,7 @@ Request: - No additional fields. Response: { - success: true + success: "true" } Example: { @@ -114,7 +114,7 @@ OUTBOUND ACTIONS ================ In addition to listening for inbound requests, the API can be used to initiate -actionss in the widget iframe, and request data from the widget instance. +actions in the widget iframe, and request data from the widget instance. Outbound actions use the "widget_client" API key / name, which must be included on all requests. @@ -135,11 +135,13 @@ Request a screenshot from the widget (if supported). This can only be supported by widgets that have access to all of their DOM tree. For example, widgets that nest further levels of iframes can not support this. +The screenshot is returned as a Blob object. + Request: - No additional fields. Response: { - screenshot: {data...} + screenshot: {data...} } Example: { From 08bcfc5c4e123f7382c06d182350b6df70438c47 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Tue, 19 Dec 2017 17:15:06 +0000 Subject: [PATCH 014/170] Make sure that capabilities array is initialised. --- src/components/views/elements/AppTile.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 770406e645..ea4f07e657 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -339,6 +339,7 @@ export default React.createClass({ this.widgetMessaging.addEndpoint(this.props.id, this.props.url); this.widgetMessaging.getCapabilities().then((capabilities) => { console.log("Got widget capabilities", this.widgetId, capabilities); + capabilities = capabilities || []; this.setState({capabilities}); }).catch((err) => { console.log("Failed to get widget capabilities", this.widgetId, err); From baf472b4a32d91992e3b774c6f2bfeff1df3f306 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Tue, 19 Dec 2017 17:16:38 +0000 Subject: [PATCH 015/170] Only show snapshot button when apps are maximised. --- src/components/views/elements/AppTile.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index ea4f07e657..07a24cba5b 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -484,8 +484,8 @@ export default React.createClass({ deleteClasses += ' mx_AppTileMenuBarWidgetDelete'; } - // Picture snapshot - const showPictureSnapshotButton = this._hasCapability('screenshot'); + // Picture snapshot - only show button when apps are maximised. + const showPictureSnapshotButton = this._hasCapability('screenshot') && this.props.show; const showPictureSnapshotIcon = 'img/camera_green.svg'; const windowStateIcon = (this.props.show ? 'img/minimize.svg' : 'img/maximize.svg'); From 7b59774b34b18b8a3f029f9c7d811cb3aa9536cc Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 28 Dec 2017 17:08:50 +0000 Subject: [PATCH 017/170] Update comment. --- src/WidgetMessaging.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WidgetMessaging.js b/src/WidgetMessaging.js index 2ca8589b54..37dd6b8be4 100644 --- a/src/WidgetMessaging.js +++ b/src/WidgetMessaging.js @@ -132,7 +132,7 @@ screenshot ---------- Request a screenshot from the widget (if supported). -This can only be supported by widgets that have access to all of their DOM tree. +This can currently only be supported by widgets that have access to all of their DOM tree. For example, widgets that nest further levels of iframes can not support this. The screenshot is returned as a Blob object. From 76601760793b577706016354ecd7b11a5e831143 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 28 Dec 2017 22:27:12 +0000 Subject: [PATCH 018/170] Fix comment linting errors. Stop listening and cleanup endpoints correctly. --- src/components/views/elements/AppTile.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 07a24cba5b..8032b9d76b 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -72,8 +72,8 @@ export default React.createClass({ const widgetPermissionId = [newProps.room.roomId, encodeURIComponent(newProps.url)].join('_'); const hasPermissionToLoad = localStorage.getItem(widgetPermissionId); return { - initialising: true, // True while we are mangling the widget URL - loading: this.props.waitForIframeLoad, // True while the iframe content is loading + initialising: true, // True while we are mangling the widget URL + loading: this.props.waitForIframeLoad, // True while the iframe content is loading widgetUrl: this._addWurlParams(newProps.url), widgetPermissionId: widgetPermissionId, // Assume that widget has permission to load if we are the user who @@ -227,8 +227,8 @@ export default React.createClass({ }, componentWillUnmount() { - WidgetMessaging.stopListening(); - WidgetMessaging.removeEndpoint(this.props.id, this.props.url); + this.widgetMessaging.stopListening(); + this.widgetMessaging.removeEndpoint(this.props.id, this.props.url); window.removeEventListener('message', this._onMessage); }, From a408b985049a7f7ce816dd423dfa60d3fa240c19 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Fri, 29 Dec 2017 14:34:52 +0000 Subject: [PATCH 019/170] Set widget ID on WidgetMessaging instance. --- src/WidgetMessaging.js | 3 ++- src/components/views/elements/AppTile.js | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/WidgetMessaging.js b/src/WidgetMessaging.js index 37dd6b8be4..7918e435cb 100644 --- a/src/WidgetMessaging.js +++ b/src/WidgetMessaging.js @@ -170,8 +170,9 @@ if (!global.mxWidgetMessagingMessageEndpoints) { } export default class WidgetMessaging extends MatrixPostMessageApi { - constructor(targetWindow) { + constructor(widgetId, targetWindow) { super(targetWindow); + this.widgetId = widgetId; } exec(action) { diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 8032b9d76b..2fbb30ff90 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -334,11 +334,11 @@ export default React.createClass({ */ _onLoaded() { // console.warn("App frame", this.refs.appFrame.contentWindow); - this.widgetMessaging = new WidgetMessaging(this.refs.appFrame.contentWindow); + this.widgetMessaging = new WidgetMessaging(this.props.id, this.refs.appFrame.contentWindow); this.widgetMessaging.startListening(); this.widgetMessaging.addEndpoint(this.props.id, this.props.url); this.widgetMessaging.getCapabilities().then((capabilities) => { - console.log("Got widget capabilities", this.widgetId, capabilities); + console.log("Got widget capabilities", this.props.id, capabilities); capabilities = capabilities || []; this.setState({capabilities}); }).catch((err) => { From e96d199b282fdd875d26761a327dcaba23eade72 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 4 Jan 2018 09:53:26 +0000 Subject: [PATCH 020/170] Inject stickers --- src/ContentMessages.js | 6 ++++++ src/WidgetMessaging.js | 21 +++++++++++++-------- src/components/structures/RoomView.js | 18 ++++++++++++++++++ 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/src/ContentMessages.js b/src/ContentMessages.js index 8d40b65124..a173a9f727 100644 --- a/src/ContentMessages.js +++ b/src/ContentMessages.js @@ -275,6 +275,12 @@ class ContentMessages { this.nextId = 0; } + sendURLContentToRoom(url, roomId, info, text, matrixClient) { + return MatrixClientPeg.get().sendImageMessage(roomId, url, info, text).catch((e) => { + console.warn(`Failed to send content with URL ${url} to room ${roomId}`, e); + }); + } + sendContentToRoom(file, roomId, matrixClient) { const content = { body: file.name || 'Attachment', diff --git a/src/WidgetMessaging.js b/src/WidgetMessaging.js index 37dd6b8be4..9db88ae441 100644 --- a/src/WidgetMessaging.js +++ b/src/WidgetMessaging.js @@ -15,6 +15,9 @@ limitations under the License. */ /* +POSTMESSAGE API +=============== + Listens for incoming postMessage requests from embedded widgets. The following API is exposed: { api: "widget", @@ -38,7 +41,7 @@ The "api" field is required to use this API, and must be set to "widget" in all The "action" determines the format of the request and response. All actions can return an error response. -Additional data can be sent as additional, abritrary fields. However, typically the data object should be used. +Additional data can be sent as abritrary fields. However, typically the data object should be used. A success response is an object with zero or more keys. @@ -52,8 +55,8 @@ They look like: } The "message" key should be a human-friendly string. -INBOUND ACTIONS -=============== +ACTIONS +======= ** All actions must include an "api" field with value of "widget".** All actions can return an error response instead of the response outlined below. @@ -110,11 +113,13 @@ Example: } -OUTBOUND ACTIONS -================ +OUTBOUND POSTMESSAGE API +======================== -In addition to listening for inbound requests, the API can be used to initiate -actions in the widget iframe, and request data from the widget instance. +This API can be used to initiate actions in remote widget instances. + +ACTIONS +======= Outbound actions use the "widget_client" API key / name, which must be included on all requests. @@ -133,7 +138,7 @@ screenshot Request a screenshot from the widget (if supported). This can currently only be supported by widgets that have access to all of their DOM tree. -For example, widgets that nest further levels of iframes can not support this. +For example, widgets that nest further levels of iframes can not support this capability. The screenshot is returned as a Blob object. diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index f68348c13d..a5e5273b82 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -459,6 +459,9 @@ module.exports = React.createClass({ case 'message_sent': this._checkIfAlone(this.state.room); break; + case 'inject_sticker': + this.injectSticker(payload.url, payload.info, payload.text); + break; case 'picture_snapshot': this.uploadFile(payload.file); break; @@ -904,6 +907,21 @@ module.exports = React.createClass({ }); }, + injectSticker: function(url, info, text) { + if (MatrixClientPeg.get().isGuest()) { + dis.dispatch({action: 'view_set_mxid'}); + return; + } + + ContentMessages.sendURLContentToRoom(url, this.state.room.roomId, info, text, MatrixClientPeg.get()) + .done(undefined, (error) => { + if (error.name === "UnknownDeviceError") { + // Let the staus bar handle this + return; + } + }); + }, + onSearch: function(term, scope) { this.setState({ searchTerm: term, From eb4053bc9945690a489b86ce2fa8df5456267320 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 4 Jan 2018 18:41:47 +0000 Subject: [PATCH 021/170] Handle sticker message payloads --- src/WidgetMessaging.js | 7 ++++++- src/components/structures/RoomView.js | 7 +++++-- src/components/views/elements/AppTile.js | 16 +++++++++++++++- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/WidgetMessaging.js b/src/WidgetMessaging.js index 4b50b21626..43d72e9ba0 100644 --- a/src/WidgetMessaging.js +++ b/src/WidgetMessaging.js @@ -253,8 +253,10 @@ export default class WidgetMessaging extends MatrixPostMessageApi { // Message endpoint already registered console.warn("Endpoint already registered"); return; + } else { + console.warn(`Adding widget messaging endpoint for ${widgetId}`); + global.mxWidgetMessagingMessageEndpoints.push(endpoint); } - global.mxWidgetMessagingMessageEndpoints.push(endpoint); } } @@ -322,6 +324,9 @@ export default class WidgetMessaging extends MatrixPostMessageApi { api: "widget", version: WIDGET_API_VERSION, }); + } else if (action === 'sticker_message') { + console.warn('got widget sticker message', widgetId); + dis.dispatch({action: 'sticker_message', data: event.data.data}); } else { console.warn("Widget postMessage event unhandled"); this.sendError(event, {message: "The postMessage was unhandled"}); diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index a5e5273b82..7980e100ba 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -459,8 +459,11 @@ module.exports = React.createClass({ case 'message_sent': this._checkIfAlone(this.state.room); break; - case 'inject_sticker': - this.injectSticker(payload.url, payload.info, payload.text); + case 'post_sticker_message': + this.injectSticker( + payload.data.content.url, + payload.data.content.info, + payload.data.description || payload.data.name); break; case 'picture_snapshot': this.uploadFile(payload.file); diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 2fbb30ff90..9e24c12cd5 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -333,7 +333,7 @@ export default React.createClass({ * Called when widget iframe has finished loading */ _onLoaded() { - // console.warn("App frame", this.refs.appFrame.contentWindow); + console.warn("App frame loaded", this.props.id); this.widgetMessaging = new WidgetMessaging(this.props.id, this.refs.appFrame.contentWindow); this.widgetMessaging.startListening(); this.widgetMessaging.addEndpoint(this.props.id, this.props.url); @@ -345,8 +345,22 @@ export default React.createClass({ console.log("Failed to get widget capabilities", this.widgetId, err); }); this.setState({loading: false}); + + dis.register(this._onAction); }, + _onAction(payload) { + switch (payload) { + case payload.action === 'sticker_message': + if (this._hasCapability('sticker_message')) { + dis.dispatch({action: 'post_sticker_message', data: payload.data}); + } else { + console.warn('Ignoring sticker message. Invalid capability'); + } + break; + } + }, + /** * Set remote content title on AppTile * @param {string} url Url to check for title From 32aecd06304ccac283eba35b6c9a77233508888e Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 4 Jan 2018 18:43:08 +0000 Subject: [PATCH 022/170] Fix event call --- src/WidgetMessaging.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WidgetMessaging.js b/src/WidgetMessaging.js index 4b50b21626..934f9bc3f2 100644 --- a/src/WidgetMessaging.js +++ b/src/WidgetMessaging.js @@ -208,7 +208,7 @@ export default class WidgetMessaging extends MatrixPostMessageApi { startListening() { this.start(); if (global.mxWidgetMessagingListenerCount === 0) { - window.addEventListener("message", () => this.onMessage, false); + window.addEventListener("message", (evt) => this.onMessage(evt), false); } global.mxWidgetMessagingListenerCount += 1; } From d20aebfbd76ef038d3c96322ffe3b9d52b56bdeb Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 4 Jan 2018 18:58:55 +0000 Subject: [PATCH 023/170] Correctly handle sticker message events. --- src/WidgetMessaging.js | 3 +-- src/components/views/elements/AppTile.js | 22 ++++++++++++---------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/WidgetMessaging.js b/src/WidgetMessaging.js index 1b66dd89dd..4e64cedbc1 100644 --- a/src/WidgetMessaging.js +++ b/src/WidgetMessaging.js @@ -325,8 +325,7 @@ export default class WidgetMessaging extends MatrixPostMessageApi { version: WIDGET_API_VERSION, }); } else if (action === 'sticker_message') { - console.warn('got widget sticker message', widgetId); - dis.dispatch({action: 'sticker_message', data: event.data.data}); + dis.dispatch({action: 'sticker_message', data: event.data.widgetData, widgetId: event.data.widgetId}); } else { console.warn("Widget postMessage event unhandled"); this.sendError(event, {message: "The postMessage was unhandled"}); diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 9e24c12cd5..49e747b05e 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -350,16 +350,18 @@ export default React.createClass({ }, _onAction(payload) { - switch (payload) { - case payload.action === 'sticker_message': - if (this._hasCapability('sticker_message')) { - dis.dispatch({action: 'post_sticker_message', data: payload.data}); - } else { - console.warn('Ignoring sticker message. Invalid capability'); - } - break; - } - }, + if (payload.widgetId === this.props.id) { + switch (payload.action) { + case 'sticker_message': + if (this._hasCapability('sticker_message')) { + dis.dispatch({action: 'post_sticker_message', data: payload.data}); + } else { + console.warn('Ignoring sticker message. Invalid capability'); + } + break; + } + } + }, /** * Set remote content title on AppTile From 54671ab67ed65f31ba5bc9e74a4f57ff9c6f6f79 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 4 Jan 2018 21:57:24 +0000 Subject: [PATCH 024/170] Send m.sticker messages --- src/ContentMessages.js | 4 ++-- src/components/structures/RoomView.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ContentMessages.js b/src/ContentMessages.js index a173a9f727..47ad87a8d7 100644 --- a/src/ContentMessages.js +++ b/src/ContentMessages.js @@ -275,8 +275,8 @@ class ContentMessages { this.nextId = 0; } - sendURLContentToRoom(url, roomId, info, text, matrixClient) { - return MatrixClientPeg.get().sendImageMessage(roomId, url, info, text).catch((e) => { + sendStickerContentToRoom(url, roomId, info, text, matrixClient) { + return MatrixClientPeg.get().sendStickerMessage(roomId, url, info, text).catch((e) => { console.warn(`Failed to send content with URL ${url} to room ${roomId}`, e); }); } diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 7980e100ba..60987fe26e 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -916,7 +916,7 @@ module.exports = React.createClass({ return; } - ContentMessages.sendURLContentToRoom(url, this.state.room.roomId, info, text, MatrixClientPeg.get()) + ContentMessages.sendStickerContentToRoom(url, this.state.room.roomId, info, text, MatrixClientPeg.get()) .done(undefined, (error) => { if (error.name === "UnknownDeviceError") { // Let the staus bar handle this From 1c8586e80294ba1e281b13dee5074356873235f2 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 4 Jan 2018 22:21:38 +0000 Subject: [PATCH 025/170] Add sticker message rendering. --- src/components/views/messages/MStickerBody.js | 253 ++++++++++++++++++ src/components/views/messages/MessageEvent.js | 13 +- 2 files changed, 261 insertions(+), 5 deletions(-) create mode 100644 src/components/views/messages/MStickerBody.js diff --git a/src/components/views/messages/MStickerBody.js b/src/components/views/messages/MStickerBody.js new file mode 100644 index 0000000000..8424bbca22 --- /dev/null +++ b/src/components/views/messages/MStickerBody.js @@ -0,0 +1,253 @@ +/* +Copyright 2017 New Vector 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. +*/ + +'use strict'; + +import React from 'react'; +import MFileBody from './MFileBody'; +import MatrixClientPeg from '../../../MatrixClientPeg'; +import ImageUtils from '../../../ImageUtils'; +import Modal from '../../../Modal'; +import sdk from '../../../index'; +import dis from '../../../dispatcher'; +import { decryptFile, readBlobAsDataUri } from '../../../utils/DecryptFile'; +import Promise from 'bluebird'; +import { _t } from '../../../languageHandler'; +import SettingsStore from "../../../settings/SettingsStore"; + +module.exports = React.createClass({ + displayName: 'MStickerBody', + + propTypes: { + /* the MatrixEvent to show */ + mxEvent: React.PropTypes.object.isRequired, + + /* called when the image has loaded */ + onWidgetLoad: React.PropTypes.func.isRequired, + }, + + getInitialState: function() { + return { + decryptedUrl: null, + decryptedThumbnailUrl: null, + decryptedBlob: null, + error: null, + }; + }, + + + onClick: function onClick(ev) { + if (ev.button == 0 && !ev.metaKey) { + ev.preventDefault(); + const content = this.props.mxEvent.getContent(); + const httpUrl = this._getContentUrl(); + const ImageView = sdk.getComponent("elements.ImageView"); + const params = { + src: httpUrl, + name: content.body && content.body.length > 0 ? content.body : _t('Attachment'), + mxEvent: this.props.mxEvent, + }; + + if (content.info) { + params.width = content.info.w; + params.height = content.info.h; + params.fileSize = content.info.size; + } + + Modal.createDialog(ImageView, params, "mx_Dialog_lightbox"); + } + }, + + _isGif: function() { + const content = this.props.mxEvent.getContent(); + return ( + content && + content.info && + content.info.mimetype === "image/gif" + ); + }, + + onImageEnter: function(e) { + if (!this._isGif() || SettingsStore.getValue("autoplayGifsAndVideos")) { + return; + } + const imgElement = e.target; + imgElement.src = this._getContentUrl(); + }, + + onImageLeave: function(e) { + if (!this._isGif() || SettingsStore.getValue("autoplayGifsAndVideos")) { + return; + } + const imgElement = e.target; + imgElement.src = this._getThumbUrl(); + }, + + _getContentUrl: function() { + const content = this.props.mxEvent.getContent(); + if (content.file !== undefined) { + return this.state.decryptedUrl; + } else { + return MatrixClientPeg.get().mxcUrlToHttp(content.url); + } + }, + + _getThumbUrl: function() { + const content = this.props.mxEvent.getContent(); + if (content.file !== undefined) { + // Don't use the thumbnail for clients wishing to autoplay gifs. + if (this.state.decryptedThumbnailUrl) { + return this.state.decryptedThumbnailUrl; + } + return this.state.decryptedUrl; + } else { + return MatrixClientPeg.get().mxcUrlToHttp(content.url, 800, 600); + } + }, + + componentDidMount: function() { + this.dispatcherRef = dis.register(this.onAction); + this.fixupHeight(); + const content = this.props.mxEvent.getContent(); + if (content.file !== undefined && this.state.decryptedUrl === null) { + let thumbnailPromise = Promise.resolve(null); + if (content.info.thumbnail_file) { + thumbnailPromise = decryptFile( + content.info.thumbnail_file, + ).then(function(blob) { + return readBlobAsDataUri(blob); + }); + } + let decryptedBlob; + thumbnailPromise.then((thumbnailUrl) => { + return decryptFile(content.file).then(function(blob) { + decryptedBlob = blob; + return readBlobAsDataUri(blob); + }).then((contentUrl) => { + this.setState({ + decryptedUrl: contentUrl, + decryptedThumbnailUrl: thumbnailUrl, + decryptedBlob: decryptedBlob, + }); + this.props.onWidgetLoad(); + }); + }).catch((err) => { + console.warn("Unable to decrypt attachment: ", err); + // Set a placeholder image when we can't decrypt the image. + this.setState({ + error: err, + }); + }).done(); + } + }, + + componentWillUnmount: function() { + dis.unregister(this.dispatcherRef); + }, + + onAction: function(payload) { + if (payload.action === "timeline_resize") { + this.fixupHeight(); + } + }, + + fixupHeight: function() { + if (!this.refs.image) { + console.warn("Refusing to fix up height on MStickerBody with no image element"); + return; + } + + const content = this.props.mxEvent.getContent(); + const timelineWidth = this.refs.body.offsetWidth; + const maxHeight = 600; // let images take up as much width as they can so long as the height doesn't exceed 600px. + // the alternative here would be 600*timelineWidth/800; to scale them down to fit inside a 4:3 bounding box + + //console.log("trying to fit image into timelineWidth of " + this.refs.body.offsetWidth + " or " + this.refs.body.clientWidth); + let thumbHeight = null; + if (content.info) { + thumbHeight = ImageUtils.thumbHeight(content.info.w, content.info.h, timelineWidth, maxHeight); + } + this.refs.image.style.height = thumbHeight + "px"; + // console.log("Image height now", thumbHeight); + }, + + render: function() { + const TintableSvg = sdk.getComponent("elements.TintableSvg"); + const content = this.props.mxEvent.getContent(); + + if (this.state.error !== null) { + return ( + + + { _t("Error decrypting image") } + + ); + } + + if (content.file !== undefined && this.state.decryptedUrl === null) { + // Need to decrypt the attachment + // The attachment is decrypted in componentDidMount. + // For now add an img tag with a spinner. + return ( + +
+ {content.body} +
+
+ ); + } + + const contentUrl = this._getContentUrl(); + let thumbUrl; + if (this._isGif() && SettingsStore.getValue("autoplayGifsAndVideos")) { + thumbUrl = contentUrl; + } else { + thumbUrl = this._getThumbUrl(); + } + + if (thumbUrl) { + return ( + + + {content.body} + + + ); + } else if (content.body) { + return ( + + { _t("Image '%(Body)s' cannot be displayed.", {Body: content.body}) } + + ); + } else { + return ( + + { _t("This image cannot be displayed.") } + + ); + } + }, +}); diff --git a/src/components/views/messages/MessageEvent.js b/src/components/views/messages/MessageEvent.js index deda1d8d20..7dd5661bb8 100644 --- a/src/components/views/messages/MessageEvent.js +++ b/src/components/views/messages/MessageEvent.js @@ -54,6 +54,7 @@ module.exports = React.createClass({ 'm.notice': sdk.getComponent('messages.TextualBody'), 'm.emote': sdk.getComponent('messages.TextualBody'), 'm.image': sdk.getComponent('messages.MImageBody'), + 'm.sticker': sdk.getComponent('messages.MStickerBody'), 'm.file': sdk.getComponent('messages.MFileBody'), 'm.audio': sdk.getComponent('messages.MAudioBody'), 'm.video': sdk.getComponent('messages.MVideoBody'), @@ -69,10 +70,12 @@ module.exports = React.createClass({ BodyType = bodyTypes['m.file']; } - return ; + return ; }, }); From d652f117fb350c6de7fe5ccd309b356f32ed7521 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 4 Jan 2018 22:36:29 +0000 Subject: [PATCH 026/170] Remove click handlers etc. --- src/components/views/messages/MStickerBody.js | 37 +++---------------- 1 file changed, 5 insertions(+), 32 deletions(-) diff --git a/src/components/views/messages/MStickerBody.js b/src/components/views/messages/MStickerBody.js index 8424bbca22..38b45e4789 100644 --- a/src/components/views/messages/MStickerBody.js +++ b/src/components/views/messages/MStickerBody.js @@ -17,7 +17,6 @@ limitations under the License. 'use strict'; import React from 'react'; -import MFileBody from './MFileBody'; import MatrixClientPeg from '../../../MatrixClientPeg'; import ImageUtils from '../../../ImageUtils'; import Modal from '../../../Modal'; @@ -48,29 +47,6 @@ module.exports = React.createClass({ }; }, - - onClick: function onClick(ev) { - if (ev.button == 0 && !ev.metaKey) { - ev.preventDefault(); - const content = this.props.mxEvent.getContent(); - const httpUrl = this._getContentUrl(); - const ImageView = sdk.getComponent("elements.ImageView"); - const params = { - src: httpUrl, - name: content.body && content.body.length > 0 ? content.body : _t('Attachment'), - mxEvent: this.props.mxEvent, - }; - - if (content.info) { - params.width = content.info.w; - params.height = content.info.h; - params.fileSize = content.info.size; - } - - Modal.createDialog(ImageView, params, "mx_Dialog_lightbox"); - } - }, - _isGif: function() { const content = this.props.mxEvent.getContent(); return ( @@ -185,7 +161,6 @@ module.exports = React.createClass({ }, render: function() { - const TintableSvg = sdk.getComponent("elements.TintableSvg"); const content = this.props.mxEvent.getContent(); if (this.state.error !== null) { @@ -227,13 +202,11 @@ module.exports = React.createClass({ if (thumbUrl) { return ( - - {content.body} - + {content.body} ); } else if (content.body) { From 7b313b7acf31588d6018dc0b4669dab0269860c0 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 4 Jan 2018 22:38:52 +0000 Subject: [PATCH 027/170] Comment logging. --- src/WidgetMessaging.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WidgetMessaging.js b/src/WidgetMessaging.js index 4e64cedbc1..cd1e4a0996 100644 --- a/src/WidgetMessaging.js +++ b/src/WidgetMessaging.js @@ -254,7 +254,7 @@ export default class WidgetMessaging extends MatrixPostMessageApi { console.warn("Endpoint already registered"); return; } else { - console.warn(`Adding widget messaging endpoint for ${widgetId}`); + // console.warn(`Adding widget messaging endpoint for ${widgetId}`); global.mxWidgetMessagingMessageEndpoints.push(endpoint); } } From d256e473eb71b63dc2f9b18dbc2ceaeb7d1ac140 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 4 Jan 2018 22:51:49 +0000 Subject: [PATCH 028/170] Fix header and remove unused deps. --- src/components/views/messages/MStickerBody.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/messages/MStickerBody.js b/src/components/views/messages/MStickerBody.js index 38b45e4789..3fbd1b23e5 100644 --- a/src/components/views/messages/MStickerBody.js +++ b/src/components/views/messages/MStickerBody.js @@ -1,5 +1,5 @@ /* -Copyright 2017 New Vector Ltd +Copyright 2018 New Vector Ltd Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From 57247493d9e9daedafdea78cb120df5448f8b71d Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 4 Jan 2018 22:59:50 +0000 Subject: [PATCH 029/170] Remove unused deps. --- src/components/views/messages/MStickerBody.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/views/messages/MStickerBody.js b/src/components/views/messages/MStickerBody.js index 3fbd1b23e5..bd86eed568 100644 --- a/src/components/views/messages/MStickerBody.js +++ b/src/components/views/messages/MStickerBody.js @@ -19,8 +19,6 @@ limitations under the License. import React from 'react'; import MatrixClientPeg from '../../../MatrixClientPeg'; import ImageUtils from '../../../ImageUtils'; -import Modal from '../../../Modal'; -import sdk from '../../../index'; import dis from '../../../dispatcher'; import { decryptFile, readBlobAsDataUri } from '../../../utils/DecryptFile'; import Promise from 'bluebird'; From 54d128658e5926eb095b3c5edc03d1b8b151aa0d Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 4 Jan 2018 23:00:10 +0000 Subject: [PATCH 030/170] Comment logging. --- src/components/views/elements/AppTile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 49e747b05e..a9ea8c6cf9 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -333,7 +333,7 @@ export default React.createClass({ * Called when widget iframe has finished loading */ _onLoaded() { - console.warn("App frame loaded", this.props.id); + // console.warn("App frame loaded", this.props.id); this.widgetMessaging = new WidgetMessaging(this.props.id, this.refs.appFrame.contentWindow); this.widgetMessaging.startListening(); this.widgetMessaging.addEndpoint(this.props.id, this.props.url); From dc1423052fc4fcceda6f7997e48e898ed93928ff Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Mon, 8 Jan 2018 11:32:23 +0000 Subject: [PATCH 031/170] De-register listener. --- src/components/views/elements/AppTile.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index a9ea8c6cf9..fa8696ea74 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -229,6 +229,7 @@ export default React.createClass({ componentWillUnmount() { this.widgetMessaging.stopListening(); this.widgetMessaging.removeEndpoint(this.props.id, this.props.url); + dis.unregister(this._onAction); window.removeEventListener('message', this._onMessage); }, From 486b2cf10259170c7478726c089ecd1bf9b749e4 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Mon, 8 Jan 2018 11:32:38 +0000 Subject: [PATCH 032/170] Handle sticker message event. --- src/components/views/messages/MessageEvent.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/views/messages/MessageEvent.js b/src/components/views/messages/MessageEvent.js index 7dd5661bb8..53cbc3e5d3 100644 --- a/src/components/views/messages/MessageEvent.js +++ b/src/components/views/messages/MessageEvent.js @@ -54,7 +54,6 @@ module.exports = React.createClass({ 'm.notice': sdk.getComponent('messages.TextualBody'), 'm.emote': sdk.getComponent('messages.TextualBody'), 'm.image': sdk.getComponent('messages.MImageBody'), - 'm.sticker': sdk.getComponent('messages.MStickerBody'), 'm.file': sdk.getComponent('messages.MFileBody'), 'm.audio': sdk.getComponent('messages.MAudioBody'), 'm.video': sdk.getComponent('messages.MVideoBody'), @@ -65,6 +64,8 @@ module.exports = React.createClass({ let BodyType = UnknownBody; if (msgtype && bodyTypes[msgtype]) { BodyType = bodyTypes[msgtype]; + } else if (this.props.mxEvent.getType() === 'm.room.sticker') { + BodyType = sdk.getComponent('messages.MStickerBody'); } else if (content.url) { // Fallback to MFileBody if there's a content URL BodyType = bodyTypes['m.file']; From 5df9a01e6488a7d58904988c0a81e59d81193281 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Mon, 8 Jan 2018 12:06:32 +0000 Subject: [PATCH 033/170] Use m.room.sticker event. --- src/components/structures/FilePanel.js | 3 +++ src/components/views/rooms/EventTile.js | 1 + 2 files changed, 4 insertions(+) diff --git a/src/components/structures/FilePanel.js b/src/components/structures/FilePanel.js index ffa5e45249..6a8d0c5bdd 100644 --- a/src/components/structures/FilePanel.js +++ b/src/components/structures/FilePanel.js @@ -67,6 +67,9 @@ const FilePanel = React.createClass({ "room": { "timeline": { "contains_url": true, + "not_types": [ + "m.room.sticker", + ], }, }, }, diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index 3407ea159d..46dc0d19db 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -33,6 +33,7 @@ const ObjectUtils = require('../../../ObjectUtils'); const eventTileTypes = { 'm.room.message': 'messages.MessageEvent', + 'm.room.sticker': 'messages.MessageEvent', 'm.call.invite': 'messages.TextualEvent', 'm.call.answer': 'messages.TextualEvent', 'm.call.hangup': 'messages.TextualEvent', From 0577316c8680c2d24b47b9d4699395a35fcdc2d9 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Mon, 8 Jan 2018 13:40:33 +0000 Subject: [PATCH 034/170] Fix duplicate event registration. --- src/components/views/elements/AppTile.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index fa8696ea74..46cccde19f 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -171,6 +171,7 @@ export default React.createClass({ componentDidMount() { // Legacy Jitsi widget messaging -- TODO replace this with standard widget // postMessaging API + dis.register(this._onAction); window.addEventListener('message', this._onMessage, false); }, @@ -346,8 +347,6 @@ export default React.createClass({ console.log("Failed to get widget capabilities", this.widgetId, err); }); this.setState({loading: false}); - - dis.register(this._onAction); }, _onAction(payload) { From adebf71a1d8b3d8bee237f6639fe7343314285d6 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Mon, 8 Jan 2018 15:38:01 +0000 Subject: [PATCH 035/170] Set user widgets on application data. --- src/ScalarMessaging.js | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index 7bde607451..7befee217a 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -291,6 +291,7 @@ function setWidget(event, roomId) { const widgetUrl = event.data.url; const widgetName = event.data.name; // optional const widgetData = event.data.data; // optional + const userWidget = event.data.userWidget; const client = MatrixClientPeg.get(); if (!client) { @@ -330,17 +331,32 @@ function setWidget(event, roomId) { name: widgetName, data: widgetData, }; - if (widgetUrl === null) { // widget is being deleted - content = {}; - } - client.sendStateEvent(roomId, "im.vector.modular.widgets", content, widgetId).done(() => { - sendResponse(event, { - success: true, + if (userWidget) { + const client = MatrixClientPeg.get(); + let userWidgets = client.getAccountData('m.widgets'); + + // Delete existing widget with ID + userWidgets = userWidgets.filter((widget) => widget.data.id === widgetId ? false : true); + + // Add new widget / update + if (widgetUrl !== null) { + userWidgets.push(content); + } + + client.setAccountData('m.widgets', userWidgets); + } else { // Room widget + if (widgetUrl === null) { // widget is being deleted + content = {}; + } + client.sendStateEvent(roomId, "im.vector.modular.widgets", content, widgetId).done(() => { + sendResponse(event, { + success: true, + }); + }, (err) => { + sendError(event, _t('Failed to send request.'), err); }); - }, (err) => { - sendError(event, _t('Failed to send request.'), err); - }); + } } function getWidgets(event, roomId) { From 60e7646f928e10845816b38810702f369ae15937 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Mon, 8 Jan 2018 16:47:49 +0000 Subject: [PATCH 036/170] Save user widgets in accountData --- src/ScalarMessaging.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index 7befee217a..41c667be25 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -333,18 +333,27 @@ function setWidget(event, roomId) { }; if (userWidget) { + console.warn('Adding user widget'); const client = MatrixClientPeg.get(); - let userWidgets = client.getAccountData('m.widgets'); + let userWidgets = client.getAccountData('m.widgets') || {}; // Delete existing widget with ID - userWidgets = userWidgets.filter((widget) => widget.data.id === widgetId ? false : true); + delete userWidgets[widgetId]; // Add new widget / update if (widgetUrl !== null) { - userWidgets.push(content); + userWidgets[widgetId] = { + content: content, + sender: client.getUserId(), + stateKey: widgetId, + type: 'm.widget', + }; } - client.setAccountData('m.widgets', userWidgets); + client.setAccountData('m.widgets', {widgets: userWidgets}); + sendResponse(event, { + success: true, + }); } else { // Room widget if (widgetUrl === null) { // widget is being deleted content = {}; From 9e9de765dc3ffad4362bf5bc061a7f744149719a Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Tue, 9 Jan 2018 14:37:45 +0000 Subject: [PATCH 037/170] Handle user widgets. --- src/ScalarMessaging.js | 70 +++++++++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 22 deletions(-) diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index 41c667be25..40e985a5aa 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -335,10 +335,15 @@ function setWidget(event, roomId) { if (userWidget) { console.warn('Adding user widget'); const client = MatrixClientPeg.get(); - let userWidgets = client.getAccountData('m.widgets') || {}; + // client.setAccountData('m.widgets', {}); + const userWidgets = client.getAccountData('m.widgets').getContent() || {}; // Delete existing widget with ID - delete userWidgets[widgetId]; + try { + delete userWidgets[widgetId]; + } catch (e) { + console.error(`$widgetId is non-configurable`); + } // Add new widget / update if (widgetUrl !== null) { @@ -346,15 +351,21 @@ function setWidget(event, roomId) { content: content, sender: client.getUserId(), stateKey: widgetId, - type: 'm.widget', + type: 'im.vector.modular.widgets', + id: widgetId, }; } - client.setAccountData('m.widgets', {widgets: userWidgets}); + client.setAccountData('m.widgets', userWidgets); + console.warn(`Set user widgets to:`, client.getAccountData('m.widgets')); sendResponse(event, { success: true, }); } else { // Room widget + if (!roomId) { + sendError(event, _t('Missing roomId.'), null); + } + if (widgetUrl === null) { // widget is being deleted content = {}; } @@ -374,19 +385,30 @@ function getWidgets(event, roomId) { sendError(event, _t('You need to be logged in.')); return; } - const room = client.getRoom(roomId); - if (!room) { - sendError(event, _t('This room is not recognised.')); - return; - } - const stateEvents = room.currentState.getStateEvents("im.vector.modular.widgets"); - // Only return widgets which have required fields - const widgetStateEvents = []; - stateEvents.forEach((ev) => { - if (ev.getContent().type && ev.getContent().url) { - widgetStateEvents.push(ev.event); // return the raw event + let widgetStateEvents = []; + + if (roomId) { + const room = client.getRoom(roomId); + if (!room) { + sendError(event, _t('This room is not recognised.')); + return; } - }); + const stateEvents = room.currentState.getStateEvents("im.vector.modular.widgets"); + // Only return widgets which have required fields + if (room) { + stateEvents.forEach((ev) => { + if (ev.getContent().type && ev.getContent().url) { + widgetStateEvents.push(ev.event); // return the raw event + } + }); + } + } + + // Add user widgets (not linked to a specific room) + const userWidgets = client.getAccountData('m.widgets').getContent() || {}; + const userWidgetArray = Object.keys(userWidgets).map((key) => userWidgets[key]); + widgetStateEvents = widgetStateEvents.concat(userWidgetArray); + console.warn('Sending user widgets', userWidgetArray); sendResponse(event, widgetStateEvents); } @@ -595,6 +617,16 @@ const onMessage = function(event) { const roomId = event.data.room_id; const userId = event.data.user_id; + + // These APIs don't require roomId + if (event.data.action === "get_widgets") { + getWidgets(event, roomId); + return; + } else if (event.data.action === "set_widget") { + setWidget(event, roomId); + return; + } + if (!roomId) { sendError(event, _t('Missing room_id in request')); return; @@ -628,12 +660,6 @@ const onMessage = function(event) { } else if (event.data.action === "get_membership_count") { getMembershipCount(event, roomId); return; - } else if (event.data.action === "set_widget") { - setWidget(event, roomId); - return; - } else if (event.data.action === "get_widgets") { - getWidgets(event, roomId); - return; } else if (event.data.action === "get_room_enc_state") { getRoomEncState(event, roomId); return; From 6b0b25c2d26a34d7c4ba109ed25c268a7125134b Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Tue, 9 Jan 2018 16:01:53 +0000 Subject: [PATCH 038/170] Translations --- src/i18n/strings/en_EN.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index f28322398c..41f1b75e43 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -304,6 +304,8 @@ "Video call": "Video call", "Hide Apps": "Hide Apps", "Show Apps": "Show Apps", + "Hide Stickers": "Hide Stickers", + "Show Stickers": "Show Stickers", "Upload file": "Upload file", "Show Text Formatting Toolbar": "Show Text Formatting Toolbar", "Send an encrypted message": "Send an encrypted message", From 9abb1601207c4b41c37b83e9e5e289f47d3bd72a Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Tue, 9 Jan 2018 16:02:17 +0000 Subject: [PATCH 039/170] Replace apps button with stickers button in message composer. --- src/components/views/rooms/MessageComposer.js | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 2841f30423..84091e8a68 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -31,8 +31,8 @@ export default class MessageComposer extends React.Component { this.onCallClick = this.onCallClick.bind(this); this.onHangupClick = this.onHangupClick.bind(this); this.onUploadClick = this.onUploadClick.bind(this); - this.onShowAppsClick = this.onShowAppsClick.bind(this); - this.onHideAppsClick = this.onHideAppsClick.bind(this); + this.onShowStickersClick = this.onShowStickersClick.bind(this); + this.onHideStickersClick = this.onHideStickersClick.bind(this); this.onUploadFileSelected = this.onUploadFileSelected.bind(this); this.uploadFiles = this.uploadFiles.bind(this); this.onVoiceCallClick = this.onVoiceCallClick.bind(this); @@ -53,6 +53,7 @@ export default class MessageComposer extends React.Component { wordCount: 0, }, showFormatting: SettingsStore.getValue('MessageComposer.showFormatting'), + showStickers: false, }; } @@ -189,18 +190,12 @@ export default class MessageComposer extends React.Component { // this._startCallApp(true); } - onShowAppsClick(ev) { - dis.dispatch({ - action: 'appsDrawer', - show: true, - }); + onShowStickersClick(ev) { + this.setState({showStickers: true}); } - onHideAppsClick(ev) { - dis.dispatch({ - action: 'appsDrawer', - show: false, - }); + onHideStickersClick(ev) { + this.setState({showStickers: false}); } onInputContentChanged(content: string, selection: {start: number, end: number}) { @@ -268,7 +263,7 @@ export default class MessageComposer extends React.Component { alt={e2eTitle} title={e2eTitle} />, ); - let callButton, videoCallButton, hangupButton, showAppsButton, hideAppsButton; + let callButton, videoCallButton, hangupButton, showStickersButton, hideStickersButton; if (this.props.callState && this.props.callState !== 'ended') { hangupButton =
@@ -286,15 +281,23 @@ export default class MessageComposer extends React.Component { } // Apps - if (this.props.showApps) { - hideAppsButton = -
- + if (this.state.showStickers) { + hideStickersButton = +
+
; } else { - showAppsButton = -
- + showStickersButton = +
+
; } @@ -343,8 +346,8 @@ export default class MessageComposer extends React.Component { hangupButton, callButton, videoCallButton, - showAppsButton, - hideAppsButton, + showStickersButton, + hideStickersButton, ); } else { controls.push( @@ -409,7 +412,4 @@ MessageComposer.propTypes = { // callback when a file to upload is chosen uploadFile: React.PropTypes.func.isRequired, - - // string representing the current room app drawer state - showApps: React.PropTypes.bool, }; From 53b590f55e57031abf7c006058146a0ab0ed382b Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Wed, 10 Jan 2018 20:27:43 +0000 Subject: [PATCH 040/170] Add stickers popover. --- package.json | 1 + src/components/views/rooms/MessageComposer.js | 24 +++++++++++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 943c443c59..24f5e3ef58 100644 --- a/package.json +++ b/package.json @@ -81,6 +81,7 @@ "react-dnd-html5-backend": "^2.1.2", "react-dom": "^15.4.0", "react-gemini-scrollbar": "matrix-org/react-gemini-scrollbar#5e97aef", + "react-simple-popover": "^0.2.2", "sanitize-html": "^1.14.1", "text-encoding-utf-8": "^1.0.1", "url": "^0.11.0", diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 84091e8a68..64dd6cf4ba 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -23,7 +23,7 @@ import sdk from '../../../index'; import dis from '../../../dispatcher'; import Autocomplete from './Autocomplete'; import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore"; - +import Popover from 'react-simple-popover'; export default class MessageComposer extends React.Component { constructor(props, context) { @@ -42,6 +42,7 @@ export default class MessageComposer extends React.Component { this.onToggleMarkdownClicked = this.onToggleMarkdownClicked.bind(this); this.onInputStateChanged = this.onInputStateChanged.bind(this); this.onEvent = this.onEvent.bind(this); + this.render = this.render.bind(this); this.state = { autocompleteQuery: '', @@ -280,15 +281,27 @@ export default class MessageComposer extends React.Component {
; } - // Apps + // Stickers if (this.state.showStickers) { + const children =

Stickers popover

; hideStickersButton =
+
; } else { showStickersButton = @@ -300,6 +313,10 @@ export default class MessageComposer extends React.Component {
; } + const stickersContainer =
+ { showStickersButton } + { hideStickersButton } +
; const canSendMessages = this.props.room.currentState.maySendMessage( MatrixClientPeg.get().credentials.userId); @@ -346,8 +363,7 @@ export default class MessageComposer extends React.Component { hangupButton, callButton, videoCallButton, - showStickersButton, - hideStickersButton, + stickersContainer, ); } else { controls.push( From 2bb51bafe1f865286749203aded16d460a7e11a1 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Wed, 10 Jan 2018 20:29:36 +0000 Subject: [PATCH 041/170] Content placeholder. --- src/components/views/rooms/MessageComposer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 64dd6cf4ba..5c131c8a20 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -283,7 +283,7 @@ export default class MessageComposer extends React.Component { // Stickers if (this.state.showStickers) { - const children =

Stickers popover

; + const stickersContent =

Click here to add your first sitckerpack

; hideStickersButton =
; } else { From 52f28d09e0bdbac532b74f0763a56e65a4036d10 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Wed, 10 Jan 2018 20:44:14 +0000 Subject: [PATCH 042/170] Stickerpack styling --- src/components/views/rooms/MessageComposer.js | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 5c131c8a20..37e5e1f911 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -283,7 +283,15 @@ export default class MessageComposer extends React.Component { // Stickers if (this.state.showStickers) { - const stickersContent =

Click here to add your first sitckerpack

; + let stickerpackWidget = ''; + let stickersContent =

Click here to add your first sitckerpack

; + if (true) { + stickersContent = ; + } + hideStickersButton =
; From 1a994b88f52885350b75e0a825cbce90fca1f872 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 11 Jan 2018 10:32:37 +0000 Subject: [PATCH 043/170] Move widget utility functions in to their own file. --- src/ScalarMessaging.js | 7 +++--- src/utils/widgets.js | 56 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 src/utils/widgets.js diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index 40e985a5aa..9a57ab5bce 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -235,6 +235,7 @@ const SdkConfig = require('./SdkConfig'); const MatrixClientPeg = require("./MatrixClientPeg"); const MatrixEvent = require("matrix-js-sdk").MatrixEvent; const dis = require("./dispatcher"); +const Widgets = require('./utils/widgets'); import { _t } from './languageHandler'; function sendResponse(event, res) { @@ -405,10 +406,8 @@ function getWidgets(event, roomId) { } // Add user widgets (not linked to a specific room) - const userWidgets = client.getAccountData('m.widgets').getContent() || {}; - const userWidgetArray = Object.keys(userWidgets).map((key) => userWidgets[key]); - widgetStateEvents = widgetStateEvents.concat(userWidgetArray); - console.warn('Sending user widgets', userWidgetArray); + const userWidgets = Widgets.getUserWidgets(); + widgetStateEvents = widgetStateEvents.concat(userWidgets); sendResponse(event, widgetStateEvents); } diff --git a/src/utils/widgets.js b/src/utils/widgets.js new file mode 100644 index 0000000000..4e26fa6ceb --- /dev/null +++ b/src/utils/widgets.js @@ -0,0 +1,56 @@ +import MatrixClientPeg from '../MatrixClientPeg'; + +/** + * Get all widgets (user and room) for the current user + * @param {object} room The room to get widgets for + * @return {[object]} Array containing current / active room and user widget state events + */ +function getWidgets(room) { + const widgets = getRoomWidgets(room); + widgets.concat(getUserWidgets()); + return widgets; +} + +/** + * Get room specific widgets + * @param {object} room The room to get widgets force + * @return {[object]} Array containing current / active room widgets + */ +function getRoomWidgets(room) { + const appsStateEvents = room.currentState.getStateEvents('im.vector.modular.widgets'); + if (!appsStateEvents) { + return []; + } + + return appsStateEvents.filter((ev) => { + return ev.getContent().type && ev.getContent().url; + }); +} + +/** + * Get user specific widgets (not linked to a specific room) + * @return {[object]} Array containing current / active user widgets + */ +function getUserWidgets() { + const client = MatrixClientPeg.get(); + if (!client) { + throw new Error('User not logged in'); + } + const userWidgets = client.getAccountData('m.widgets').getContent() || {}; + return Object.keys(userWidgets).map((key) => userWidgets[key]); +} + +/** + * Get active stickerpack widgets (stickerpacks are user widgets by nature) + * @return {[object]} Array containing current / active stickerpack widgets + */ +function getStickerpackWidgets() { + return getUserWidgets().filter((widget) => widget.type='stickerpack'); +} + +export default { + getWidgets, + getRoomWidgets, + getUserWidgets, + getStickerpackWidgets, +}; From 2cf9da8c954f85e20faea386a92936867332e748 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 11 Jan 2018 11:12:46 +0000 Subject: [PATCH 044/170] Load user stickerpacks --- src/components/views/rooms/MessageComposer.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 37e5e1f911..b26a3b2c17 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -24,6 +24,7 @@ import dis from '../../../dispatcher'; import Autocomplete from './Autocomplete'; import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore"; import Popover from 'react-simple-popover'; +import Widgets from '../../../utils/widgets'; export default class MessageComposer extends React.Component { constructor(props, context) { @@ -283,10 +284,11 @@ export default class MessageComposer extends React.Component { // Stickers if (this.state.showStickers) { - let stickerpackWidget = ''; + const stickerpackWidget = Widgets.getStickerpackWidgets()[0]; + console.warn('Stickerpack widgets', stickerpackWidget); let stickersContent =

Click here to add your first sitckerpack

; - if (true) { - stickersContent = ; From 78bd25eff0a75a2c6bacc41460085ec3651624f7 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 11 Jan 2018 11:36:19 +0000 Subject: [PATCH 045/170] Sticker popover styling --- src/components/views/rooms/MessageComposer.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index b26a3b2c17..ba7b238bd3 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -289,8 +289,8 @@ export default class MessageComposer extends React.Component { let stickersContent =

Click here to add your first sitckerpack

; if (stickerpackWidget && stickerpackWidget.content && stickerpackWidget.content.url) { stickersContent = ; } @@ -309,12 +309,14 @@ export default class MessageComposer extends React.Component { show={this.state.showStickers} onHide={this.onHideStickersClick} containerStyle={{ - zIndex: 100, + zIndex: 1000, }} style={{ borderRadius: '5px', width: 'initial', padding: 0, + overflow: 'hidden', + height: '160px' }} children={stickersContent} /> From d0c16fa7a1fa604425102d9e45768c494f7b2028 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 11 Jan 2018 11:49:46 +0000 Subject: [PATCH 046/170] Convert to ES6 class. --- src/components/views/elements/AppTile.js | 104 +++++++++++------------ 1 file changed, 51 insertions(+), 53 deletions(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 46cccde19f..4759537960 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -1,4 +1,4 @@ -/* +/** Copyright 2017 Vector Creations Ltd Licensed under the Apache License, Version 2.0 (the "License"); @@ -36,31 +36,8 @@ import dis from '../../../dispatcher'; const ALLOWED_APP_URL_SCHEMES = ['https:', 'http:']; -export default React.createClass({ - displayName: 'AppTile', - - propTypes: { - id: React.PropTypes.string.isRequired, - url: React.PropTypes.string.isRequired, - name: React.PropTypes.string.isRequired, - room: React.PropTypes.object.isRequired, - type: React.PropTypes.string.isRequired, - // Specifying 'fullWidth' as true will render the app tile to fill the width of the app drawer continer. - // This should be set to true when there is only one widget in the app drawer, otherwise it should be false. - fullWidth: React.PropTypes.bool, - // UserId of the current user - userId: React.PropTypes.string.isRequired, - // UserId of the entity that added / modified the widget - creatorUserId: React.PropTypes.string, - waitForIframeLoad: React.PropTypes.bool, - }, - - getDefaultProps() { - return { - url: "", - waitForIframeLoad: true, - }; - }, +export default class AppTile extends React.Component { + static displayName ='AppTile'; /** * Set initial component state when the App wUrl (widget URL) is being updated. @@ -84,7 +61,7 @@ export default React.createClass({ widgetPageTitle: newProps.widgetPageTitle, capabilities: [], }; - }, + } /** @@ -94,7 +71,7 @@ export default React.createClass({ */ _hasCapability(capability) { return this.state.capabilities.some((c) => {return c === capability;}); - }, + } /** * Add widget instance specific parameters to pass in wUrl @@ -122,11 +99,11 @@ export default React.createClass({ u.query = params; return u.format(); - }, + } getInitialState() { return this._getNewState(this.props); - }, + } /** * Returns true if specified url is a scalar URL, typically https://scalar.vector.im/api @@ -150,7 +127,7 @@ export default React.createClass({ } } return false; - }, + } isMixedContent() { const parentContentProtocol = window.location.protocol; @@ -162,18 +139,18 @@ export default React.createClass({ return true; } return false; - }, + } componentWillMount() { this.setScalarToken(); - }, + } componentDidMount() { // Legacy Jitsi widget messaging -- TODO replace this with standard widget // postMessaging API dis.register(this._onAction); window.addEventListener('message', this._onMessage, false); - }, + } /** * Adds a scalar token to the widget URL, if required @@ -225,14 +202,14 @@ export default React.createClass({ initialising: false, }); }); - }, + } componentWillUnmount() { this.widgetMessaging.stopListening(); this.widgetMessaging.removeEndpoint(this.props.id, this.props.url); dis.unregister(this._onAction); window.removeEventListener('message', this._onMessage); - }, + } componentWillReceiveProps(nextProps) { if (nextProps.url !== this.props.url) { @@ -247,7 +224,7 @@ export default React.createClass({ widgetPageTitle: nextProps.widgetPageTitle, }); } - }, + } // Legacy Jitsi widget messaging // TODO -- This should be replaced with the new widget postMessaging API @@ -268,11 +245,11 @@ export default React.createClass({ .document.querySelector('iframe[id^="jitsiConferenceFrame"]'); PlatformPeg.get().setupScreenSharingForIframe(iframe); } - }, + } _canUserModify() { return WidgetUtils.canUserModifyWidgets(this.props.room.roomId); - }, + } _onEditClick(e) { console.log("Edit widget ID ", this.props.id); @@ -282,7 +259,7 @@ export default React.createClass({ Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, { src: src, }, "mx_IntegrationsManager"); - }, + } _onSnapshotClick(e) { console.warn("Requesting widget snapshot"); @@ -294,7 +271,7 @@ export default React.createClass({ }).catch((err) => { console.error("Failed to get screenshot", err); }); - }, + } /* If user has permission to modify widgets, delete the widget, * otherwise revoke access for the widget to load in the user's browser @@ -329,7 +306,7 @@ export default React.createClass({ console.log("Revoke widget permissions - %s", this.props.id); this._revokeWidgetPermission(); } - }, + } /** * Called when widget iframe has finished loading @@ -347,7 +324,7 @@ export default React.createClass({ console.log("Failed to get widget capabilities", this.widgetId, err); }); this.setState({loading: false}); - }, + } _onAction(payload) { if (payload.widgetId === this.props.id) { @@ -361,7 +338,7 @@ export default React.createClass({ break; } } - }, + } /** * Set remote content title on AppTile @@ -375,7 +352,7 @@ export default React.createClass({ }, (err) =>{ console.error("Failed to get page title", err); }); - }, + } // Widget labels to render, depending upon user permissions // These strings are translated at the point that they are inserted in to the DOM, in the render method @@ -384,20 +361,20 @@ export default React.createClass({ return _td('Delete widget'); } return _td('Revoke widget access'); - }, + } /* TODO -- Store permission in account data so that it is persisted across multiple devices */ _grantWidgetPermission() { console.warn('Granting permission to load widget - ', this.state.widgetUrl); localStorage.setItem(this.state.widgetPermissionId, true); this.setState({hasPermissionToLoad: true}); - }, + } _revokeWidgetPermission() { console.warn('Revoking permission to load widget - ', this.state.widgetUrl); localStorage.removeItem(this.state.widgetPermissionId); this.setState({hasPermissionToLoad: false}); - }, + } formatAppTileName() { let appTileName = "No name"; @@ -405,7 +382,7 @@ export default React.createClass({ appTileName = this.props.name.trim(); } return appTileName; - }, + } onClickMenuBar(ev) { ev.preventDefault(); @@ -420,7 +397,7 @@ export default React.createClass({ action: 'appsDrawer', show: !this.props.show, }); - }, + } _getSafeUrl() { const parsedWidgetUrl = url.parse(this.state.widgetUrl); @@ -429,7 +406,7 @@ export default React.createClass({ safeWidgetUrl = url.format(parsedWidgetUrl); } return safeWidgetUrl; - }, + } render() { let appTileBody; @@ -556,5 +533,26 @@ export default React.createClass({ { appTileBody }
); - }, -}); + } +} + +AppTile.propTypes = { + id: React.PropTypes.string.isRequired, + url: React.PropTypes.string.isRequired, + name: React.PropTypes.string.isRequired, + room: React.PropTypes.object.isRequired, + type: React.PropTypes.string.isRequired, + // Specifying 'fullWidth' as true will render the app tile to fill the width of the app drawer continer. + // This should be set to true when there is only one widget in the app drawer, otherwise it should be false. + fullWidth: React.PropTypes.bool, + // UserId of the current user + userId: React.PropTypes.string.isRequired, + // UserId of the entity that added / modified the widget + creatorUserId: React.PropTypes.string, + waitForIframeLoad: React.PropTypes.bool, +}; + +AppTile.defaultProps = { + url: "", + waitForIframeLoad: true, +}; From 4f3670941d187ecba0e2223543abfe824c718eca Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 11 Jan 2018 12:33:02 +0000 Subject: [PATCH 047/170] Bind functions --- src/components/views/elements/AppTile.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 4759537960..4bbc06413d 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -39,6 +39,19 @@ const ALLOWED_APP_URL_SCHEMES = ['https:', 'http:']; export default class AppTile extends React.Component { static displayName ='AppTile'; + constructor(props) { + super(props); + this.state = this._getNewState(this.props); + + this._onAction = this._onAction.bind(this); + this._onMessage = this._onMessage.bind(this); + this._onLoaded = this._onLoaded.bind(this); + this._onEditClick = this._onEditClick.bind(this); + this._onDeleteClick = this._onDeleteClick.bind(this); + this._onSnapshotClick = this._onSnapshotClick.bind(this); + this.onClickMenuBar = this.onClickMenuBar.bind(this); + } + /** * Set initial component state when the App wUrl (widget URL) is being updated. * Component props *must* be passed (rather than relying on this.props). @@ -101,9 +114,6 @@ export default class AppTile extends React.Component { return u.format(); } - getInitialState() { - return this._getNewState(this.props); - } /** * Returns true if specified url is a scalar URL, typically https://scalar.vector.im/api From 1ab71f6f50092aeafc4de44bc9f248c9e8a021d9 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 11 Jan 2018 13:20:58 +0000 Subject: [PATCH 048/170] Load stickers in AppTile --- src/components/views/elements/AppTile.js | 16 ++++++++++---- src/components/views/rooms/MessageComposer.js | 22 +++++++++++++++---- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 4bbc06413d..60df6ade9b 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -41,7 +41,8 @@ export default class AppTile extends React.Component { constructor(props) { super(props); - this.state = this._getNewState(this.props); + console.warn('AppTile constructor', props); + this.state = this._getNewState(props); this._onAction = this._onAction.bind(this); this._onMessage = this._onMessage.bind(this); @@ -158,8 +159,10 @@ export default class AppTile extends React.Component { componentDidMount() { // Legacy Jitsi widget messaging -- TODO replace this with standard widget // postMessaging API - dis.register(this._onAction); window.addEventListener('message', this._onMessage, false); + + // General event handler + dis.register(this._onAction); } /** @@ -322,7 +325,7 @@ export default class AppTile extends React.Component { * Called when widget iframe has finished loading */ _onLoaded() { - // console.warn("App frame loaded", this.props.id); + console.warn("App frame loaded", this.props.id); this.widgetMessaging = new WidgetMessaging(this.props.id, this.refs.appFrame.contentWindow); this.widgetMessaging.startListening(); this.widgetMessaging.addEndpoint(this.props.id, this.props.url); @@ -494,6 +497,7 @@ export default class AppTile extends React.Component { return (
+ { this.props.showMenubar &&
-
+
} { appTileBody }
); @@ -560,9 +564,13 @@ AppTile.propTypes = { // UserId of the entity that added / modified the widget creatorUserId: React.PropTypes.string, waitForIframeLoad: React.PropTypes.bool, + showMenubar: React.PropTypes.bool, + // Should the AppTile render itself + show: React.PropTypes.bool, }; AppTile.defaultProps = { url: "", waitForIframeLoad: true, + showMenubar: true, }; diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index ba7b238bd3..7e318c57d5 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -25,6 +25,7 @@ import Autocomplete from './Autocomplete'; import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore"; import Popover from 'react-simple-popover'; import Widgets from '../../../utils/widgets'; +import AppTile from '../elements/AppTile'; export default class MessageComposer extends React.Component { constructor(props, context) { @@ -285,13 +286,26 @@ export default class MessageComposer extends React.Component { // Stickers if (this.state.showStickers) { const stickerpackWidget = Widgets.getStickerpackWidgets()[0]; - console.warn('Stickerpack widgets', stickerpackWidget); let stickersContent =

Click here to add your first sitckerpack

; if (stickerpackWidget && stickerpackWidget.content && stickerpackWidget.content.url) { - stickersContent = ; + }}> + +
; } hideStickersButton = @@ -316,7 +330,7 @@ export default class MessageComposer extends React.Component { width: 'initial', padding: 0, overflow: 'hidden', - height: '160px' + height: '160px', }} children={stickersContent} /> From 9df4dae9755c14619c4a55c283b58b5d14ef42fc Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 11 Jan 2018 13:41:20 +0000 Subject: [PATCH 049/170] Used forked version of react-popover --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 24f5e3ef58..43a5ebfcfd 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "react-dnd-html5-backend": "^2.1.2", "react-dom": "^15.4.0", "react-gemini-scrollbar": "matrix-org/react-gemini-scrollbar#5e97aef", - "react-simple-popover": "^0.2.2", + "react-simple-popover": "matrix-org/react-popover", "sanitize-html": "^1.14.1", "text-encoding-utf-8": "^1.0.1", "url": "^0.11.0", From 90b7cb37607477a3a59253db5d0722db2caf1c70 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 11 Jan 2018 13:41:55 +0000 Subject: [PATCH 050/170] Consistent popover size --- src/components/views/rooms/MessageComposer.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 7e318c57d5..9f4a017689 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -285,12 +285,15 @@ export default class MessageComposer extends React.Component { // Stickers if (this.state.showStickers) { + const popoverWidth = '300px'; + const popoverHeight = '300px'; const stickerpackWidget = Widgets.getStickerpackWidgets()[0]; let stickersContent =

Click here to add your first sitckerpack

; if (stickerpackWidget && stickerpackWidget.content && stickerpackWidget.content.url) { stickersContent =
From 23543614e1752be9c29ba5ad399ecb9b650cef9b Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Fri, 12 Jan 2018 09:52:53 +0000 Subject: [PATCH 051/170] Add react-popover-tiny --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 43a5ebfcfd..36f35556fc 100644 --- a/package.json +++ b/package.json @@ -82,6 +82,7 @@ "react-dom": "^15.4.0", "react-gemini-scrollbar": "matrix-org/react-gemini-scrollbar#5e97aef", "react-simple-popover": "matrix-org/react-popover", + "react-tiny-popover": "^3.2.5", "sanitize-html": "^1.14.1", "text-encoding-utf-8": "^1.0.1", "url": "^0.11.0", From a3c6dd36eff90f386b553af96b45166a30dc3dc6 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Fri, 12 Jan 2018 17:38:21 +0000 Subject: [PATCH 052/170] Stickers popover. --- src/components/views/rooms/MessageComposer.js | 129 +++++++++++------- 1 file changed, 79 insertions(+), 50 deletions(-) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 9f4a017689..b17694011c 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -23,7 +23,7 @@ import sdk from '../../../index'; import dis from '../../../dispatcher'; import Autocomplete from './Autocomplete'; import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore"; -import Popover from 'react-simple-popover'; +import Popover, {ArrowContainer} from 'react-tiny-popover'; import Widgets from '../../../utils/widgets'; import AppTile from '../elements/AppTile'; @@ -266,7 +266,13 @@ export default class MessageComposer extends React.Component { alt={e2eTitle} title={e2eTitle} />, ); - let callButton, videoCallButton, hangupButton, showStickersButton, hideStickersButton; + + let callButton; + let videoCallButton; + let hangupButton; + let stickersButton; + + // Call buttons if (this.props.callState && this.props.callState !== 'ended') { hangupButton =
@@ -284,63 +290,58 @@ export default class MessageComposer extends React.Component { } // Stickers - if (this.state.showStickers) { - const popoverWidth = '300px'; - const popoverHeight = '300px'; - const stickerpackWidget = Widgets.getStickerpackWidgets()[0]; - let stickersContent =

Click here to add your first sitckerpack

; - if (stickerpackWidget && stickerpackWidget.content && stickerpackWidget.content.url) { - stickersContent =
- -
; - } + }} + > + +
; + } else { + // Default content to show if stickerpack widget not added + this.state.stickersContent =

Click here to add your first sitckerpack

; + } - hideStickersButton = + + if (this.state.showStickers) { + // Show hide-stickers button + stickersButton =
-
; } else { - showStickersButton = + // Show show-stickers button + stickersButton =
; } - const stickersContainer =
- { showStickersButton } - { hideStickersButton } -
; + + const stickers = ( + +
+ { this.state.stickersContent } +
+
+ )} + > +
+ { stickersButton } +
+
; const canSendMessages = this.props.room.currentState.maySendMessage( MatrixClientPeg.get().credentials.userId); @@ -398,7 +427,7 @@ export default class MessageComposer extends React.Component { hangupButton, callButton, videoCallButton, - stickersContainer, + stickers, ); } else { controls.push( From 351bbdfd4eba77a485e4315e48cd2dadff4f9b5c Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Mon, 15 Jan 2018 10:25:19 +0000 Subject: [PATCH 053/170] Styling --- src/components/views/rooms/MessageComposer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index b17694011c..531dc7aff1 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -366,10 +366,10 @@ export default class MessageComposer extends React.Component {
{ this.state.stickersContent } From 0fab905a2e5e90077719ed22f9830c0bf2771a35 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Mon, 15 Jan 2018 11:16:07 +0000 Subject: [PATCH 054/170] Cleanup styles. --- src/components/views/rooms/MessageComposer.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 531dc7aff1..39c51ebe3a 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -366,9 +366,6 @@ export default class MessageComposer extends React.Component {
From 5e6da4d7583273c8f52dcea4fc2213ecd6e997ec Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Mon, 15 Jan 2018 14:22:41 +0000 Subject: [PATCH 055/170] * Fix key error * Remove redundant logging * Catch error --- src/components/views/elements/AppTile.js | 9 ++++++--- src/components/views/rooms/MessageComposer.js | 1 + 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 60df6ade9b..1da344227e 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -41,7 +41,6 @@ export default class AppTile extends React.Component { constructor(props) { super(props); - console.warn('AppTile constructor', props); this.state = this._getNewState(props); this._onAction = this._onAction.bind(this); @@ -218,8 +217,12 @@ export default class AppTile extends React.Component { } componentWillUnmount() { - this.widgetMessaging.stopListening(); - this.widgetMessaging.removeEndpoint(this.props.id, this.props.url); + try { + this.widgetMessaging.stopListening(); + this.widgetMessaging.removeEndpoint(this.props.id, this.props.url); + } catch (e) { + console.error('Failed to stop listening for widgetMessaging events', e.message); + } dis.unregister(this._onAction); window.removeEventListener('message', this._onMessage); } diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 39c51ebe3a..f87ac02d05 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -354,6 +354,7 @@ export default class MessageComposer extends React.Component { isOpen={this.state.showStickers} position={'top'} padding={1} + key='stickersPopover' content={({ position, targetRect, popoverRect }) => ( Date: Mon, 15 Jan 2018 14:25:56 +0000 Subject: [PATCH 056/170] Remove arrow opacity. --- src/components/views/rooms/MessageComposer.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index f87ac02d05..3becd6e2fb 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -362,7 +362,6 @@ export default class MessageComposer extends React.Component { popoverRect={popoverRect} arrowColor={'#76CFA6'} arrowSize={20} - arrowStyle={{ opacity: 0.7 }} >
Date: Mon, 15 Jan 2018 18:27:14 +0000 Subject: [PATCH 057/170] Select apropriate theme colour for popover. --- src/components/views/rooms/MessageComposer.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 3becd6e2fb..8b70b67a1e 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -350,6 +350,11 @@ export default class MessageComposer extends React.Component {
; } + // Fall back to default highlight color if we can't compute one from the DOM + const highlightColor = document.getElementById('mx_theme_accentColor') ? + window.getComputedStyle(document.getElementById('mx_theme_accentColor')).color : + '#76CFA6'; + const stickers =
{ this.state.stickersContent } From 87d8ed5af84507f4cd54960f6cfd602123b3f6cd Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Tue, 16 Jan 2018 17:01:25 +0000 Subject: [PATCH 058/170] Add comment --- src/components/views/rooms/MessageComposer.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 8b70b67a1e..aa27dc4ae4 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -292,6 +292,8 @@ export default class MessageComposer extends React.Component { // Stickers const popoverWidth = '300px'; const popoverHeight = '300px'; + // TODO - Add support for stickerpacks from multiple app stores. + // Render content from multiple stickerpack sources, each within their own iframe, within the stickerpack UI element. const stickerpackWidget = Widgets.getStickerpackWidgets()[0]; // Load stickerpack content From cb7f25f4defa33e63d21808a8c9c184f89611a4b Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Tue, 16 Jan 2018 18:13:52 +0000 Subject: [PATCH 059/170] Remove rubbish lib. --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 36f35556fc..43a5ebfcfd 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,6 @@ "react-dom": "^15.4.0", "react-gemini-scrollbar": "matrix-org/react-gemini-scrollbar#5e97aef", "react-simple-popover": "matrix-org/react-popover", - "react-tiny-popover": "^3.2.5", "sanitize-html": "^1.14.1", "text-encoding-utf-8": "^1.0.1", "url": "^0.11.0", From 86542d86e97be93cff49bea52378a7db13334395 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Tue, 16 Jan 2018 18:14:32 +0000 Subject: [PATCH 060/170] Move stickers into stand-alone component. --- src/components/views/rooms/MessageComposer.js | 117 +-------------- src/components/views/rooms/Stickerpack.js | 139 ++++++++++++++++++ 2 files changed, 143 insertions(+), 113 deletions(-) create mode 100644 src/components/views/rooms/Stickerpack.js diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index aa27dc4ae4..7e001165c0 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -23,9 +23,7 @@ import sdk from '../../../index'; import dis from '../../../dispatcher'; import Autocomplete from './Autocomplete'; import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore"; -import Popover, {ArrowContainer} from 'react-tiny-popover'; -import Widgets from '../../../utils/widgets'; -import AppTile from '../elements/AppTile'; +import Stickerpack from './Stickerpack'; export default class MessageComposer extends React.Component { constructor(props, context) { @@ -33,8 +31,6 @@ export default class MessageComposer extends React.Component { this.onCallClick = this.onCallClick.bind(this); this.onHangupClick = this.onHangupClick.bind(this); this.onUploadClick = this.onUploadClick.bind(this); - this.onShowStickersClick = this.onShowStickersClick.bind(this); - this.onHideStickersClick = this.onHideStickersClick.bind(this); this.onUploadFileSelected = this.onUploadFileSelected.bind(this); this.uploadFiles = this.uploadFiles.bind(this); this.onVoiceCallClick = this.onVoiceCallClick.bind(this); @@ -46,6 +42,8 @@ export default class MessageComposer extends React.Component { this.onEvent = this.onEvent.bind(this); this.render = this.render.bind(this); + // + this.state = { autocompleteQuery: '', selection: null, @@ -56,7 +54,6 @@ export default class MessageComposer extends React.Component { wordCount: 0, }, showFormatting: SettingsStore.getValue('MessageComposer.showFormatting'), - showStickers: false, }; } @@ -193,14 +190,6 @@ export default class MessageComposer extends React.Component { // this._startCallApp(true); } - onShowStickersClick(ev) { - this.setState({showStickers: true}); - } - - onHideStickersClick(ev) { - this.setState({showStickers: false}); - } - onInputContentChanged(content: string, selection: {start: number, end: number}) { this.setState({ autocompleteQuery: content, @@ -270,7 +259,6 @@ export default class MessageComposer extends React.Component { let callButton; let videoCallButton; let hangupButton; - let stickersButton; // Call buttons if (this.props.callState && this.props.callState !== 'ended') { @@ -289,103 +277,6 @@ export default class MessageComposer extends React.Component {
; } - // Stickers - const popoverWidth = '300px'; - const popoverHeight = '300px'; - // TODO - Add support for stickerpacks from multiple app stores. - // Render content from multiple stickerpack sources, each within their own iframe, within the stickerpack UI element. - const stickerpackWidget = Widgets.getStickerpackWidgets()[0]; - - // Load stickerpack content - if (stickerpackWidget && stickerpackWidget.content && stickerpackWidget.content.url) { - this.state.stickersContent =
- -
; - } else { - // Default content to show if stickerpack widget not added - this.state.stickersContent =

Click here to add your first sitckerpack

; - } - - - if (this.state.showStickers) { - // Show hide-stickers button - stickersButton = -
- -
; - } else { - // Show show-stickers button - stickersButton = -
- -
; - } - - // Fall back to default highlight color if we can't compute one from the DOM - const highlightColor = document.getElementById('mx_theme_accentColor') ? - window.getComputedStyle(document.getElementById('mx_theme_accentColor')).color : - '#76CFA6'; - - const stickers = ( - -
- { this.state.stickersContent } -
-
- )} - > -
- { stickersButton } -
-
; - const canSendMessages = this.props.room.currentState.maySendMessage( MatrixClientPeg.get().credentials.userId); @@ -431,7 +322,7 @@ export default class MessageComposer extends React.Component { hangupButton, callButton, videoCallButton, - stickers, + , ); } else { controls.push( diff --git a/src/components/views/rooms/Stickerpack.js b/src/components/views/rooms/Stickerpack.js new file mode 100644 index 0000000000..97b1aedb3c --- /dev/null +++ b/src/components/views/rooms/Stickerpack.js @@ -0,0 +1,139 @@ +/* +Copyright 2015, 2016 OpenMarket Ltd +Copyright 2017 New Vector 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. +*/ +import React from 'react'; +import { _t } from '../../../languageHandler'; +import Widgets from '../../../utils/widgets'; +import AppTile from '../elements/AppTile'; +import ContextualMenu from '../../structures/ContextualMenu'; +import MatrixClientPeg from '../../../MatrixClientPeg'; +import sdk from '../../../index'; + + +export default class Stickerpack extends React.Component { + constructor(props) { + super(props); + this.onShowStickersClick = this.onShowStickersClick.bind(this); + this.onHideStickersClick = this.onHideStickersClick.bind(this); + + this.defaultStickersContent = (
+

You don't currently have any stickerpacks enabled

+

Click here to add some!

+
); + this.popoverWidth = 300; + this.popoverHeight = 300; + + this.state = { + stickersContent: this.defaultStickersContent, + showStickers: false, + }; + } + + onComponentDidMount() { + // Stickers + // TODO - Add support for stickerpacks from multiple app stores. + // Render content from multiple stickerpack sources, each within their own iframe, within the stickerpack UI element. + const stickerpackWidget = Widgets.getStickerpackWidgets()[0]; + let stickersContent; + + // Load stickerpack content + if (stickerpackWidget && stickerpackWidget.content && stickerpackWidget.content.url) { + stickersContent =
+ +
; + } else { + // Default content to show if stickerpack widget not added + stickersContent =

Click here to add your first sitckerpack

; + } + this.setState({stickersContent}); + } + + onShowStickersClick(e) { + const GenericElementContextMenu = sdk.getComponent('context_menus.GenericElementContextMenu'); + const buttonRect = e.target.getBoundingClientRect(); + + // The window X and Y offsets are to adjust position when zoomed in to page + const x = buttonRect.right + window.pageXOffset - 40; + const y = (buttonRect.top + (buttonRect.height / 2) + window.pageYOffset) - 19; + // const self = this; + ContextualMenu.createMenu(GenericElementContextMenu, { + chevronOffset: 10, + chevronFace: 'bottom', + left: x, + top: y, + menuWidth: this.popoverWidth, + menuHeight: this.popoverHeight, + element: this.state.stickersContent, + }); + + + this.setState({showStickers: true}); + } + + onHideStickersClick(ev) { + this.setState({showStickers: false}); + } + + render() { + const TintableSvg = sdk.getComponent("elements.TintableSvg"); + let stickersButton; + if (this.state.showStickers) { + // Show hide-stickers button + stickersButton = +
+ +
; + } else { + // Show show-stickers button + stickersButton = +
+ +
; + } + return stickersButton; + } +} From 933928409083c48f54621bcfbcc275cf6fe8b871 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Tue, 16 Jan 2018 21:06:57 +0000 Subject: [PATCH 061/170] Stickerpack content placeholder. --- src/components/views/rooms/Stickerpack.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/components/views/rooms/Stickerpack.js b/src/components/views/rooms/Stickerpack.js index 97b1aedb3c..52cd32ba4f 100644 --- a/src/components/views/rooms/Stickerpack.js +++ b/src/components/views/rooms/Stickerpack.js @@ -29,10 +29,13 @@ export default class Stickerpack extends React.Component { this.onShowStickersClick = this.onShowStickersClick.bind(this); this.onHideStickersClick = this.onHideStickersClick.bind(this); - this.defaultStickersContent = (
-

You don't currently have any stickerpacks enabled

-

Click here to add some!

-
); + this.defaultStickersContent = ( +
+

You don't currently have any stickerpacks enabled

+

Click here to add some!

+ Add a stickerpack +
+ ); this.popoverWidth = 300; this.popoverHeight = 300; @@ -86,7 +89,7 @@ export default class Stickerpack extends React.Component { const buttonRect = e.target.getBoundingClientRect(); // The window X and Y offsets are to adjust position when zoomed in to page - const x = buttonRect.right + window.pageXOffset - 40; + const x = buttonRect.right + window.pageXOffset - 37; const y = (buttonRect.top + (buttonRect.height / 2) + window.pageYOffset) - 19; // const self = this; ContextualMenu.createMenu(GenericElementContextMenu, { From 7676fc0c10110336279d1d27c361b4c34581fef6 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Tue, 16 Jan 2018 21:28:15 +0000 Subject: [PATCH 062/170] Handle stickerpack close. --- src/components/views/rooms/Stickerpack.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/components/views/rooms/Stickerpack.js b/src/components/views/rooms/Stickerpack.js index 52cd32ba4f..18ace9300c 100644 --- a/src/components/views/rooms/Stickerpack.js +++ b/src/components/views/rooms/Stickerpack.js @@ -28,6 +28,7 @@ export default class Stickerpack extends React.Component { super(props); this.onShowStickersClick = this.onShowStickersClick.bind(this); this.onHideStickersClick = this.onHideStickersClick.bind(this); + this.onFinished = this.onFinished.bind(this); this.defaultStickersContent = (
@@ -100,6 +101,7 @@ export default class Stickerpack extends React.Component { menuWidth: this.popoverWidth, menuHeight: this.popoverHeight, element: this.state.stickersContent, + onFinished: this.onFinished, }); @@ -110,6 +112,10 @@ export default class Stickerpack extends React.Component { this.setState({showStickers: false}); } + onFinished() { + this.setState({showStickers: false}); + } + render() { const TintableSvg = sdk.getComponent("elements.TintableSvg"); let stickersButton; From 38ed01bebdc9334e43e55bc8f9641620efa7c92b Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Tue, 16 Jan 2018 21:35:25 +0000 Subject: [PATCH 063/170] Pass room to stickerpack --- src/components/views/rooms/MessageComposer.js | 2 +- src/components/views/rooms/Stickerpack.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 7e001165c0..9dbfb994c7 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -322,7 +322,7 @@ export default class MessageComposer extends React.Component { hangupButton, callButton, videoCallButton, - , + , ); } else { controls.push( diff --git a/src/components/views/rooms/Stickerpack.js b/src/components/views/rooms/Stickerpack.js index 18ace9300c..0553fbbdc6 100644 --- a/src/components/views/rooms/Stickerpack.js +++ b/src/components/views/rooms/Stickerpack.js @@ -46,11 +46,12 @@ export default class Stickerpack extends React.Component { }; } - onComponentDidMount() { + componentDidMount() { // Stickers // TODO - Add support for stickerpacks from multiple app stores. // Render content from multiple stickerpack sources, each within their own iframe, within the stickerpack UI element. const stickerpackWidget = Widgets.getStickerpackWidgets()[0]; + console.warn('Stickerpack widget', stickerpackWidget); let stickersContent; // Load stickerpack content From 86da20416972b38cb839a617bb25ca1e39705708 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Tue, 16 Jan 2018 23:25:07 +0000 Subject: [PATCH 064/170] Add manage stickerpacks link --- src/components/views/rooms/Stickerpack.js | 67 +++++++++++++++-------- 1 file changed, 44 insertions(+), 23 deletions(-) diff --git a/src/components/views/rooms/Stickerpack.js b/src/components/views/rooms/Stickerpack.js index 0553fbbdc6..a12f1f359d 100644 --- a/src/components/views/rooms/Stickerpack.js +++ b/src/components/views/rooms/Stickerpack.js @@ -56,29 +56,50 @@ export default class Stickerpack extends React.Component { // Load stickerpack content if (stickerpackWidget && stickerpackWidget.content && stickerpackWidget.content.url) { - stickersContent =
- -
; + stickersContent = ( +
+
+ +
+
+ Add sticker packs +
+
+ ); } else { // Default content to show if stickerpack widget not added stickersContent =

Click here to add your first sitckerpack

; From 614a10c6d397c794c2f93fc27b96355c89174ea4 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Wed, 17 Jan 2018 00:04:06 +0000 Subject: [PATCH 065/170] Add manage integration link. --- src/components/views/rooms/Stickerpack.js | 36 ++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/components/views/rooms/Stickerpack.js b/src/components/views/rooms/Stickerpack.js index a12f1f359d..7afad74a4c 100644 --- a/src/components/views/rooms/Stickerpack.js +++ b/src/components/views/rooms/Stickerpack.js @@ -20,7 +20,10 @@ import Widgets from '../../../utils/widgets'; import AppTile from '../elements/AppTile'; import ContextualMenu from '../../structures/ContextualMenu'; import MatrixClientPeg from '../../../MatrixClientPeg'; +import Modal from '../../../Modal'; import sdk from '../../../index'; +import SdkConfig from '../../../SdkConfig'; +import ScalarAuthClient from '../../../ScalarAuthClient'; export default class Stickerpack extends React.Component { @@ -29,6 +32,7 @@ export default class Stickerpack extends React.Component { this.onShowStickersClick = this.onShowStickersClick.bind(this); this.onHideStickersClick = this.onHideStickersClick.bind(this); this.onFinished = this.onFinished.bind(this); + this._launchManageIntegrations = this._launchManageIntegrations.bind(this); this.defaultStickersContent = (
@@ -47,6 +51,20 @@ export default class Stickerpack extends React.Component { } componentDidMount() { + this.scalarClient = null; + if (SdkConfig.get().integrations_ui_url && SdkConfig.get().integrations_rest_url) { + this.scalarClient = new ScalarAuthClient(); + this.scalarClient.connect().then(() => { + this.forceUpdate(); + }).catch((e) => { + console.log("Failed to connect to integrations server"); + // TODO -- Handle Scalar errors + // this.setState({ + // scalar_error: err, + // }); + }); + } + // Stickers // TODO - Add support for stickerpacks from multiple app stores. // Render content from multiple stickerpack sources, each within their own iframe, within the stickerpack UI element. @@ -56,6 +74,7 @@ export default class Stickerpack extends React.Component { // Load stickerpack content if (stickerpackWidget && stickerpackWidget.content && stickerpackWidget.content.url) { + this.widgetId = stickerpackWidget.id; stickersContent = (
- Add sticker packs + Add sticker packs
); @@ -138,6 +157,21 @@ export default class Stickerpack extends React.Component { this.setState({showStickers: false}); } + _launchManageIntegrations() { + this.onFinished(); + const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager"); + const src = (this.scalarClient !== null && this.scalarClient.hasCredentials()) ? + this.scalarClient.getScalarInterfaceUrlForRoom( + this.props.room.roomId, + 'add_integ', + // this.widgetId, + ) : + null; + Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, { + src: src, + }, "mx_IntegrationsManager"); + } + render() { const TintableSvg = sdk.getComponent("elements.TintableSvg"); let stickersButton; From 3331c8af273622c0c57e98ab56a51de1f504101f Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Wed, 17 Jan 2018 15:40:04 +0000 Subject: [PATCH 066/170] Use dispatcher ref for unregister call. --- src/components/views/elements/AppTile.js | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 1da344227e..fd88295122 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -43,7 +43,7 @@ export default class AppTile extends React.Component { super(props); this.state = this._getNewState(props); - this._onAction = this._onAction.bind(this); + this._onWidgetAction = this._onWidgetAction.bind(this); this._onMessage = this._onMessage.bind(this); this._onLoaded = this._onLoaded.bind(this); this._onEditClick = this._onEditClick.bind(this); @@ -161,7 +161,7 @@ export default class AppTile extends React.Component { window.addEventListener('message', this._onMessage, false); // General event handler - dis.register(this._onAction); + this.dispatcherRef = dis.register(this._onWidgetAction); } /** @@ -217,13 +217,19 @@ export default class AppTile extends React.Component { } componentWillUnmount() { + // Widget action listeners + dis.unregister(this.dispatcherRef); + + // Widget postMessage listeners try { - this.widgetMessaging.stopListening(); - this.widgetMessaging.removeEndpoint(this.props.id, this.props.url); + if (this.widgetMessaging) { + this.widgetMessaging.stopListening(); + this.widgetMessaging.removeEndpoint(this.props.id, this.props.url); + } } catch (e) { console.error('Failed to stop listening for widgetMessaging events', e.message); } - dis.unregister(this._onAction); + // Jitsi listener window.removeEventListener('message', this._onMessage); } @@ -342,7 +348,7 @@ export default class AppTile extends React.Component { this.setState({loading: false}); } - _onAction(payload) { + _onWidgetAction(payload) { if (payload.widgetId === this.props.id) { switch (payload.action) { case 'sticker_message': From 5a4271268b72c1e878c224b7290474ed70d787cd Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Wed, 17 Jan 2018 15:40:47 +0000 Subject: [PATCH 067/170] Keep reference to stickers menu --- src/components/views/rooms/Stickerpack.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/Stickerpack.js b/src/components/views/rooms/Stickerpack.js index 7afad74a4c..4bcb426a35 100644 --- a/src/components/views/rooms/Stickerpack.js +++ b/src/components/views/rooms/Stickerpack.js @@ -134,7 +134,7 @@ export default class Stickerpack extends React.Component { const x = buttonRect.right + window.pageXOffset - 37; const y = (buttonRect.top + (buttonRect.height / 2) + window.pageYOffset) - 19; // const self = this; - ContextualMenu.createMenu(GenericElementContextMenu, { + this.stickersMenu = ContextualMenu.createMenu(GenericElementContextMenu, { chevronOffset: 10, chevronFace: 'bottom', left: x, @@ -150,11 +150,12 @@ export default class Stickerpack extends React.Component { } onHideStickersClick(ev) { - this.setState({showStickers: false}); + this.stickersMenu.close(); } onFinished() { this.setState({showStickers: false}); + this.stickersMenu = null; } _launchManageIntegrations() { From fa336b7a99d1ae7564985dd05d47e21e92f32f9a Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Wed, 17 Jan 2018 15:41:15 +0000 Subject: [PATCH 068/170] Bring hide stickers icon to front when menu open. --- src/components/views/rooms/Stickerpack.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/Stickerpack.js b/src/components/views/rooms/Stickerpack.js index 4bcb426a35..84a7f4cbef 100644 --- a/src/components/views/rooms/Stickerpack.js +++ b/src/components/views/rooms/Stickerpack.js @@ -182,7 +182,7 @@ export default class Stickerpack extends React.Component {
From aa524c339d290560d32f7c2804f5a6ed4ef10e30 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Wed, 17 Jan 2018 15:49:36 +0000 Subject: [PATCH 069/170] Update class names. --- src/components/views/rooms/Stickerpack.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/views/rooms/Stickerpack.js b/src/components/views/rooms/Stickerpack.js index 84a7f4cbef..3c4a8f6425 100644 --- a/src/components/views/rooms/Stickerpack.js +++ b/src/components/views/rooms/Stickerpack.js @@ -35,7 +35,7 @@ export default class Stickerpack extends React.Component { this._launchManageIntegrations = this._launchManageIntegrations.bind(this); this.defaultStickersContent = ( -
+

You don't currently have any stickerpacks enabled

Click here to add some!

Add a stickerpack @@ -84,7 +84,7 @@ export default class Stickerpack extends React.Component { >
- Add sticker packs + Add sticker packs
); @@ -182,7 +182,7 @@ export default class Stickerpack extends React.Component {
From b6f85fbf9251bb36e61335a23091b4534d353870 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Wed, 17 Jan 2018 16:52:10 +0000 Subject: [PATCH 070/170] Don't treat sticker messages as info messages. --- src/components/views/rooms/EventTile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index 46dc0d19db..a6750ac792 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -440,7 +440,7 @@ module.exports = withMatrixClient(React.createClass({ const eventType = this.props.mxEvent.getType(); // Info messages are basically information about commands processed on a room - const isInfoMessage = (eventType !== 'm.room.message'); + const isInfoMessage = (eventType !== 'm.room.message' && eventType !== 'm.room.sticker'); const EventTileType = sdk.getComponent(getHandlerTile(this.props.mxEvent)); // This shouldn't happen: the caller should check we support this type From f8d7ab10fab9c742f2351477e698d5f6b0e6a5d1 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Wed, 17 Jan 2018 17:19:20 +0000 Subject: [PATCH 071/170] Handle non-m.room.message event types. --- src/components/structures/MessagePanel.js | 2 +- src/components/views/rooms/EventTile.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index 53cc660a9b..30ded948a4 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -450,7 +450,7 @@ module.exports = React.createClass({ if (prevEvent !== null && prevEvent.sender && mxEv.sender && mxEv.sender.userId === prevEvent.sender.userId - && mxEv.getType() == prevEvent.getType()) { + && Boolean(mxEv.getContent().body) == Boolean(prevEvent.getContent().body)) { continuation = true; } diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index a6750ac792..3245cf1ac3 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -440,7 +440,8 @@ module.exports = withMatrixClient(React.createClass({ const eventType = this.props.mxEvent.getType(); // Info messages are basically information about commands processed on a room - const isInfoMessage = (eventType !== 'm.room.message' && eventType !== 'm.room.sticker'); + // For now assume that anything that doesn't have a content body is an isInfoMessage + const isInfoMessage = !content.body; // Boolean comparison of non-boolean content body const EventTileType = sdk.getComponent(getHandlerTile(this.props.mxEvent)); // This shouldn't happen: the caller should check we support this type From 1293c53c4bbb4d5a95503ab65c0d952bd5387fbf Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 18 Jan 2018 12:02:45 +0000 Subject: [PATCH 072/170] Cleanup --- src/components/views/elements/AppTile.js | 39 +++++++++++++----------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index fd88295122..05ea8cfa0b 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -160,10 +160,30 @@ export default class AppTile extends React.Component { // postMessaging API window.addEventListener('message', this._onMessage, false); - // General event handler + // Widget action listeners this.dispatcherRef = dis.register(this._onWidgetAction); } + componentWillUnmount() { + // Widget action listeners + console.warn('Removing widget event listener', this.dispatcherRef); + dis.unregister(this.dispatcherRef); + + // Widget postMessage listeners + try { + if (this.widgetMessaging) { + this.widgetMessaging.stopListening(); + this.widgetMessaging.removeEndpoint(this.props.id, this.props.url); + } else { + console.warn('WidgetMessaging not initialised. Not stopping.'); + } + } catch (e) { + console.error('Failed to stop listening for widgetMessaging events', e.message); + } + // Jitsi listener + window.removeEventListener('message', this._onMessage); + } + /** * Adds a scalar token to the widget URL, if required * Component initialisation is only complete when this function has resolved @@ -216,23 +236,6 @@ export default class AppTile extends React.Component { }); } - componentWillUnmount() { - // Widget action listeners - dis.unregister(this.dispatcherRef); - - // Widget postMessage listeners - try { - if (this.widgetMessaging) { - this.widgetMessaging.stopListening(); - this.widgetMessaging.removeEndpoint(this.props.id, this.props.url); - } - } catch (e) { - console.error('Failed to stop listening for widgetMessaging events', e.message); - } - // Jitsi listener - window.removeEventListener('message', this._onMessage); - } - componentWillReceiveProps(nextProps) { if (nextProps.url !== this.props.url) { this._getNewState(nextProps); From 917d85d603d071764e2ce7151e8fdbb3f72fc287 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 18 Jan 2018 12:03:24 +0000 Subject: [PATCH 073/170] Refer rest parameters --- src/components/structures/ContextualMenu.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/structures/ContextualMenu.js b/src/components/structures/ContextualMenu.js index 3c2308e6a7..f3189c2e4b 100644 --- a/src/components/structures/ContextualMenu.js +++ b/src/components/structures/ContextualMenu.js @@ -51,11 +51,11 @@ module.exports = { createMenu: function(Element, props) { const self = this; - const closeMenu = function() { + const closeMenu = function(...args) { ReactDOM.unmountComponentAtNode(self.getOrCreateContainer()); if (props && props.onFinished) { - props.onFinished.apply(null, arguments); + props.onFinished.apply(null, args); } }; From 910623d287c131ec51ff3ec09091a91b5f85d6f2 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 18 Jan 2018 12:04:00 +0000 Subject: [PATCH 074/170] Close context menu on resize. --- src/components/structures/ContextualMenu.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/structures/ContextualMenu.js b/src/components/structures/ContextualMenu.js index f3189c2e4b..7ec078f739 100644 --- a/src/components/structures/ContextualMenu.js +++ b/src/components/structures/ContextualMenu.js @@ -59,6 +59,11 @@ module.exports = { } }; + // Close the menu on window resize + const windowResize = function() { + closeMenu(); + }; + const position = {}; let chevronFace = null; @@ -135,7 +140,7 @@ module.exports = {
{ chevron } - +
From 23bef68a8f0a3f08ff3a5d22646c26c41a8dbffa Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 18 Jan 2018 13:16:06 +0000 Subject: [PATCH 075/170] Fix duplicate message listeners --- src/WidgetMessaging.js | 16 ++++++++++++---- src/components/views/elements/AppTile.js | 8 ++------ 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/WidgetMessaging.js b/src/WidgetMessaging.js index cd1e4a0996..c1af402e4d 100644 --- a/src/WidgetMessaging.js +++ b/src/WidgetMessaging.js @@ -178,6 +178,10 @@ export default class WidgetMessaging extends MatrixPostMessageApi { constructor(widgetId, targetWindow) { super(targetWindow); this.widgetId = widgetId; + + this.startListening = this.startListening.bind(this); + this.stopListening = this.stopListening.bind(this); + this.onMessage = this.onMessage.bind(this); } exec(action) { @@ -206,9 +210,11 @@ export default class WidgetMessaging extends MatrixPostMessageApi { * Register widget message event listeners */ startListening() { - this.start(); if (global.mxWidgetMessagingListenerCount === 0) { - window.addEventListener("message", (evt) => this.onMessage(evt), false); + // Start postMessage API listener + this.start(); + // Start widget specific listener + window.addEventListener("message", this.onMessage, false); } global.mxWidgetMessagingListenerCount += 1; } @@ -217,10 +223,12 @@ export default class WidgetMessaging extends MatrixPostMessageApi { * De-register widget message event listeners */ stopListening() { - this.stop(); global.mxWidgetMessagingListenerCount -= 1; if (global.mxWidgetMessagingListenerCount === 0) { - window.removeEventListener("message", () => this.onMessage); + // Stop widget specific listener + window.removeEventListener("message", this.onMessage, false); + // Stop postMessage API listener + this.stop(); } if (global.mxWidgetMessagingListenerCount < 0) { // Make an error so we get a stack trace diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 05ea8cfa0b..582cc01a57 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -171,12 +171,8 @@ export default class AppTile extends React.Component { // Widget postMessage listeners try { - if (this.widgetMessaging) { - this.widgetMessaging.stopListening(); - this.widgetMessaging.removeEndpoint(this.props.id, this.props.url); - } else { - console.warn('WidgetMessaging not initialised. Not stopping.'); - } + this.widgetMessaging.stopListening(); + this.widgetMessaging.removeEndpoint(this.props.id, this.props.url); } catch (e) { console.error('Failed to stop listening for widgetMessaging events', e.message); } From 0441487e97573dde03578efd8b621ab5394ff0a0 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Mon, 22 Jan 2018 17:00:50 +0100 Subject: [PATCH 076/170] Manage sticker packs link and add comments --- src/components/views/rooms/Stickerpack.js | 21 ++++++++++++++++++--- src/i18n/strings/en_EN.json | 1 + 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/components/views/rooms/Stickerpack.js b/src/components/views/rooms/Stickerpack.js index 3c4a8f6425..cb2a19eae7 100644 --- a/src/components/views/rooms/Stickerpack.js +++ b/src/components/views/rooms/Stickerpack.js @@ -115,7 +115,7 @@ export default class Stickerpack extends React.Component { padding: '5px', borderTop: '1px solid #999', }}> - Add sticker packs + { _t("Manage sticker packs") }
); @@ -126,6 +126,11 @@ export default class Stickerpack extends React.Component { this.setState({stickersContent}); } + /** + * Show the sticker picker overlay + * If no stickerpacks have been added, show a link to the integration manager add sticker packs page. + * @param {Event} e Event that triggered the function + */ onShowStickersClick(e) { const GenericElementContextMenu = sdk.getComponent('context_menus.GenericElementContextMenu'); const buttonRect = e.target.getBoundingClientRect(); @@ -149,23 +154,33 @@ export default class Stickerpack extends React.Component { this.setState({showStickers: true}); } + /** + * Trigger hiding of the sticker picker overlay + * @param {Event} ev Event that triggered the function call + */ onHideStickersClick(ev) { this.stickersMenu.close(); } + /** + * The stickers picker was hidden + */ onFinished() { this.setState({showStickers: false}); this.stickersMenu = null; } + /** + * Launch the integrations manager on the stickers integration page + */ _launchManageIntegrations() { this.onFinished(); const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager"); const src = (this.scalarClient !== null && this.scalarClient.hasCredentials()) ? this.scalarClient.getScalarInterfaceUrlForRoom( this.props.room.roomId, - 'add_integ', - // this.widgetId, + 'type_stickerpack', + this.widgetId, ) : null; Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, { diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 41f1b75e43..a4152ef94a 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -555,6 +555,7 @@ "NOTE: Apps are not end-to-end encrypted": "NOTE: Apps are not end-to-end encrypted", "Do you want to load widget from URL:": "Do you want to load widget from URL:", "Allow": "Allow", + "Manage sticker packs": "Manage sticker packs", "Delete Widget": "Delete Widget", "Deleting a widget removes it for all users in this room. Are you sure you want to delete this widget?": "Deleting a widget removes it for all users in this room. Are you sure you want to delete this widget?", "Delete widget": "Delete widget", From 29962ed89d1f4716a46e41877a17b4f5425d4672 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Mon, 5 Feb 2018 11:48:48 +0000 Subject: [PATCH 077/170] Add stickerpack strings. --- src/i18n/strings/en_EN.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index a4152ef94a..4458fefbf1 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -241,6 +241,11 @@ "Cannot add any more widgets": "Cannot add any more widgets", "The maximum permitted number of widgets have already been added to this room.": "The maximum permitted number of widgets have already been added to this room.", "Add a widget": "Add a widget", + "You don't currently have any stickerpacks enabled": "You don't currently have any stickerpacks enabled", + "Click": "Click", + "here": "here", + "to add some!": "to add some!", + "Add a stickerpack": "Add a stickerpack", "Drop File Here": "Drop File Here", "Drop file here to upload": "Drop file here to upload", " (unsupported)": " (unsupported)", From 34de3729fe12c61f263f102131e2a3bf61761259 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Mon, 5 Feb 2018 11:49:26 +0000 Subject: [PATCH 078/170] Add method to remove all stickerpacks. --- src/utils/widgets.js | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/utils/widgets.js b/src/utils/widgets.js index 4e26fa6ceb..806906f072 100644 --- a/src/utils/widgets.js +++ b/src/utils/widgets.js @@ -45,12 +45,33 @@ function getUserWidgets() { * @return {[object]} Array containing current / active stickerpack widgets */ function getStickerpackWidgets() { - return getUserWidgets().filter((widget) => widget.type='stickerpack'); + const stickerpackWidgets = getUserWidgets().filter((widget) => widget.type='stickerpack'); + console.warn('Stickerpack widgets', stickerpackWidgets); + return stickerpackWidgets; } +/** + * Remove all stickerpack widgets (stickerpacks are user widgets by nature) + */ +function removeStickerpackWidgets() { + const client = MatrixClientPeg.get(); + if (!client) { + throw new Error('User not logged in'); + } + const userWidgets = client.getAccountData('m.widgets').getContent() || {}; + Object.entries(userWidgets).forEach(([key, widget]) => { + if (widget.type === 'stickerpack') { + delete userWidgets[key]; + } + }); + client.setAccountData('m.widgets', userWidgets); +} + + export default { getWidgets, getRoomWidgets, getUserWidgets, getStickerpackWidgets, + removeStickerpackWidgets, }; From 992c4771f4d78ee349e05a2e1d05ca9d88b19b1c Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Mon, 5 Feb 2018 11:49:44 +0000 Subject: [PATCH 079/170] Add button to remove all stickerpacks --- src/components/views/rooms/Stickerpack.js | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/components/views/rooms/Stickerpack.js b/src/components/views/rooms/Stickerpack.js index cb2a19eae7..77e188198a 100644 --- a/src/components/views/rooms/Stickerpack.js +++ b/src/components/views/rooms/Stickerpack.js @@ -33,12 +33,13 @@ export default class Stickerpack extends React.Component { this.onHideStickersClick = this.onHideStickersClick.bind(this); this.onFinished = this.onFinished.bind(this); this._launchManageIntegrations = this._launchManageIntegrations.bind(this); + this._removeStickerpackWidgets = this._removeStickerpackWidgets.bind(this); this.defaultStickersContent = (
-

You don't currently have any stickerpacks enabled

-

Click here to add some!

- Add a stickerpack +

{_t("You don't currently have any stickerpacks enabled")}

+

{_t("Click")} { _t("here") } {_t("to add some!")}

+ {_t('Add
); this.popoverWidth = 300; @@ -50,6 +51,11 @@ export default class Stickerpack extends React.Component { }; } + _removeStickerpackWidgets() { + console.warn('Removing stickerpack widgets'); + Widgets.removeStickerpackWidgets() + } + componentDidMount() { this.scalarClient = null; if (SdkConfig.get().integrations_ui_url && SdkConfig.get().integrations_rest_url) { @@ -91,6 +97,14 @@ export default class Stickerpack extends React.Component { width: this.popoverWidth, }} > +
X
Click here to add your first sitckerpack

; + stickersContent = this.defaultStickersContent; } this.setState({stickersContent}); } From e508f0676547732b9905839fe37418392cdc82e3 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Mon, 5 Feb 2018 11:50:25 +0000 Subject: [PATCH 080/170] Add asset add / remove messaging clauses. --- src/ScalarMessaging.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index 9a57ab5bce..0fa342e69f 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -624,6 +624,12 @@ const onMessage = function(event) { } else if (event.data.action === "set_widget") { setWidget(event, roomId); return; + } else if (event.data.action === "add_widget_asset") { + addWidgetAsset(event, roomId); + return; + } else if (event.data.action === "remove_widget_asset") { + removeWidgetAsset(event, roomId); + return; } if (!roomId) { From 393236ba3438707da047debbca7464912b61a01f Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Wed, 7 Feb 2018 09:23:00 +0000 Subject: [PATCH 081/170] Update / remove stickerpacks --- src/ScalarMessaging.js | 2 + src/components/views/rooms/Stickerpack.js | 45 +++++++++++++++++++---- src/utils/widgets.js | 4 +- 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index 0fa342e69f..3d585108dd 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -362,6 +362,8 @@ function setWidget(event, roomId) { sendResponse(event, { success: true, }); + + dis.dispatch({ action: "user_widget_updated" }); } else { // Room widget if (!roomId) { sendError(event, _t('Missing roomId.'), null); diff --git a/src/components/views/rooms/Stickerpack.js b/src/components/views/rooms/Stickerpack.js index 77e188198a..a61ca84fbd 100644 --- a/src/components/views/rooms/Stickerpack.js +++ b/src/components/views/rooms/Stickerpack.js @@ -24,7 +24,7 @@ import Modal from '../../../Modal'; import sdk from '../../../index'; import SdkConfig from '../../../SdkConfig'; import ScalarAuthClient from '../../../ScalarAuthClient'; - +import dis from '../../../dispatcher'; export default class Stickerpack extends React.Component { constructor(props) { @@ -34,11 +34,12 @@ export default class Stickerpack extends React.Component { this.onFinished = this.onFinished.bind(this); this._launchManageIntegrations = this._launchManageIntegrations.bind(this); this._removeStickerpackWidgets = this._removeStickerpackWidgets.bind(this); + this._onWidgetAction = this._onWidgetAction.bind(this); this.defaultStickersContent = (
-

{_t("You don't currently have any stickerpacks enabled")}

-

{_t("Click")} { _t("here") } {_t("to add some!")}

+

{ _t("You don't currently have any stickerpacks enabled") }

+

{ _t("Click") } { _t("here") } { _t("to add some!") }

{_t('Add
); @@ -53,7 +54,9 @@ export default class Stickerpack extends React.Component { _removeStickerpackWidgets() { console.warn('Removing stickerpack widgets'); - Widgets.removeStickerpackWidgets() + Widgets.removeStickerpackWidgets(); + this._getStickerPickerWidget(); + this.onFinished(); } componentDidMount() { @@ -70,16 +73,36 @@ export default class Stickerpack extends React.Component { // }); }); } + this._getStickerPickerWidget(); + this.dispatcherRef = dis.register(this._onWidgetAction); + } + componentWillUnmount() { + dis.unregister(this.dispatcherRef); + } + + _onWidgetAction(payload) { + if (payload.action === "user_widget_updated") { + console.warn("user widget updated"); + this._getStickerPickerWidget(); + return; + } + console.error("Unhandled widget action"); + } + + _getStickerPickerWidget() { // Stickers // TODO - Add support for stickerpacks from multiple app stores. // Render content from multiple stickerpack sources, each within their own iframe, within the stickerpack UI element. + console.warn("Checking for sticker picker widgets"); const stickerpackWidget = Widgets.getStickerpackWidgets()[0]; - console.warn('Stickerpack widget', stickerpackWidget); let stickersContent; // Load stickerpack content if (stickerpackWidget && stickerpackWidget.content && stickerpackWidget.content.url) { + // Set default name + stickerpackWidget.content.name = stickerpackWidget.name || "Stickerpack"; + console.warn('Stickerpack widget', stickerpackWidget); this.widgetId = stickerpackWidget.id; stickersContent = (
X
widget.type='stickerpack'); + const widgets = getUserWidgets(); + console.warn("widgets", widgets); + const stickerpackWidgets = widgets.filter((widget) => widget.type='stickerpack'); console.warn('Stickerpack widgets', stickerpackWidgets); return stickerpackWidgets; } From f3943bef51e9551634b42ffad6daef72fc9879c8 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Wed, 7 Feb 2018 10:05:50 +0000 Subject: [PATCH 082/170] Check for empty user widgets. --- src/components/views/rooms/Stickerpack.js | 1 - src/utils/widgets.js | 8 ++++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/components/views/rooms/Stickerpack.js b/src/components/views/rooms/Stickerpack.js index a61ca84fbd..3722818bf6 100644 --- a/src/components/views/rooms/Stickerpack.js +++ b/src/components/views/rooms/Stickerpack.js @@ -87,7 +87,6 @@ export default class Stickerpack extends React.Component { this._getStickerPickerWidget(); return; } - console.error("Unhandled widget action"); } _getStickerPickerWidget() { diff --git a/src/utils/widgets.js b/src/utils/widgets.js index 081815fed9..2c7901a18f 100644 --- a/src/utils/widgets.js +++ b/src/utils/widgets.js @@ -36,8 +36,12 @@ function getUserWidgets() { if (!client) { throw new Error('User not logged in'); } - const userWidgets = client.getAccountData('m.widgets').getContent() || {}; - return Object.keys(userWidgets).map((key) => userWidgets[key]); + const userWidgets = client.getAccountData('m.widgets'); + let userWidgetContent = {}; + if (userWidgets && userWidgets.getContent()) { + userWidgetContent = userWidgets.getContent(); + } + return Object.keys(userWidgetContent).map((key) => userWidgetContent[key]); } /** From 7b75dbbd15d621df14fb292716d0c499b8ac198e Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Wed, 7 Feb 2018 14:44:01 +0000 Subject: [PATCH 083/170] Use default AppTile menu bar. --- src/components/views/elements/AppTile.js | 109 ++++++++++++++-------- src/components/views/rooms/Stickerpack.js | 31 ++---- 2 files changed, 79 insertions(+), 61 deletions(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 582cc01a57..c96ce9f775 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -274,12 +274,16 @@ export default class AppTile extends React.Component { _onEditClick(e) { console.log("Edit widget ID ", this.props.id); - const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager"); - const src = this._scalarClient.getScalarInterfaceUrlForRoom( - this.props.room.roomId, 'type_' + this.props.type, this.props.id); - Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, { - src: src, - }, "mx_IntegrationsManager"); + if (this.props.onEditClick) { + this.props.onEditClick(); + } else { + const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager"); + const src = this._scalarClient.getScalarInterfaceUrlForRoom( + this.props.room.roomId, 'type_' + this.props.type, this.props.id); + Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, { + src: src, + }, "mx_IntegrationsManager"); + } } _onSnapshotClick(e) { @@ -298,34 +302,38 @@ export default class AppTile extends React.Component { * otherwise revoke access for the widget to load in the user's browser */ _onDeleteClick() { - if (this._canUserModify()) { - // Show delete confirmation dialog - const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); - Modal.createTrackedDialog('Delete Widget', '', QuestionDialog, { - title: _t("Delete Widget"), - description: _t( - "Deleting a widget removes it for all users in this room." + - " Are you sure you want to delete this widget?"), - button: _t("Delete widget"), - onFinished: (confirmed) => { - if (!confirmed) { - return; - } - this.setState({deleting: true}); - MatrixClientPeg.get().sendStateEvent( - this.props.room.roomId, - 'im.vector.modular.widgets', - {}, // empty content - this.props.id, - ).catch((e) => { - console.error('Failed to delete widget', e); - this.setState({deleting: false}); - }); - }, - }); + if (this.props.onDeleteClick) { + this.props.onDeleteClick(); } else { - console.log("Revoke widget permissions - %s", this.props.id); - this._revokeWidgetPermission(); + if (this._canUserModify()) { + // Show delete confirmation dialog + const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); + Modal.createTrackedDialog('Delete Widget', '', QuestionDialog, { + title: _t("Delete Widget"), + description: _t( + "Deleting a widget removes it for all users in this room." + + " Are you sure you want to delete this widget?"), + button: _t("Delete widget"), + onFinished: (confirmed) => { + if (!confirmed) { + return; + } + this.setState({deleting: true}); + MatrixClientPeg.get().sendStateEvent( + this.props.room.roomId, + 'im.vector.modular.widgets', + {}, // empty content + this.props.id, + ).catch((e) => { + console.error('Failed to delete widget', e); + this.setState({deleting: false}); + }); + }, + }); + } else { + console.log("Revoke widget permissions - %s", this.props.id); + this._revokeWidgetPermission(); + } } } @@ -429,6 +437,22 @@ export default class AppTile extends React.Component { return safeWidgetUrl; } + _getTileTitle() { + const name = this.formatAppTileName(); + const titleSpacer =  - ; + let title = ''; + if (this.state.widgetPageTitle && this.state.widgetPageTitle != this.formatAppTileName()) { + title = this.state.widgetPageTitle; + } + + return ( + + { name } + { title ? titleSpacer : '' }{ title } + + ); + } + render() { let appTileBody; @@ -508,17 +532,14 @@ export default class AppTile extends React.Component { { this.props.showMenubar &&
- - { this.formatAppTileName() } - { this.state.widgetPageTitle && this.state.widgetPageTitle != this.formatAppTileName() && ( -  - { this.state.widgetPageTitle } - ) } + /> } + { this.props.showTitle && this._getTileTitle() } { /* Snapshot widget */ } @@ -575,10 +596,20 @@ AppTile.propTypes = { showMenubar: React.PropTypes.bool, // Should the AppTile render itself show: React.PropTypes.bool, + // Optional onEditClickHandler (overrides default behaviour) + onEditClick: React.PropTypes.func, + // Optional onDeleteClickHandler (overrides default behaviour) + onDeleteClick: React.PropTypes.func, + // Optionally hide the tile title + showTitle: React.PropTypes.bool, + // Optionally hide the tile minimise icon + showMinimise: React.PropTypes.bool, }; AppTile.defaultProps = { url: "", waitForIframeLoad: true, showMenubar: true, + showTitle: true, + showMinimise: true, }; diff --git a/src/components/views/rooms/Stickerpack.js b/src/components/views/rooms/Stickerpack.js index 3722818bf6..6a61618b2c 100644 --- a/src/components/views/rooms/Stickerpack.js +++ b/src/components/views/rooms/Stickerpack.js @@ -25,6 +25,8 @@ import sdk from '../../../index'; import SdkConfig from '../../../SdkConfig'; import ScalarAuthClient from '../../../ScalarAuthClient'; import dis from '../../../dispatcher'; +import TintableSvgButton from '../elements/TintableSvgButton'; + export default class Stickerpack extends React.Component { constructor(props) { @@ -103,6 +105,7 @@ export default class Stickerpack extends React.Component { stickerpackWidget.content.name = stickerpackWidget.name || "Stickerpack"; console.warn('Stickerpack widget', stickerpackWidget); this.widgetId = stickerpackWidget.id; + stickersContent = (
-
X
-
- { _t("Manage sticker packs") } -
); } else { From 5e30468a0080b02f175222e96f29ba53dda6a347 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Wed, 7 Feb 2018 14:48:43 +0000 Subject: [PATCH 084/170] Linting --- src/components/views/elements/AppTile.js | 4 ++-- src/components/views/rooms/Stickerpack.js | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index c96ce9f775..9d76e3410e 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -37,8 +37,6 @@ import dis from '../../../dispatcher'; const ALLOWED_APP_URL_SCHEMES = ['https:', 'http:']; export default class AppTile extends React.Component { - static displayName ='AppTile'; - constructor(props) { super(props); this.state = this._getNewState(props); @@ -579,6 +577,8 @@ export default class AppTile extends React.Component { } } +AppTile.displayName ='AppTile'; + AppTile.propTypes = { id: React.PropTypes.string.isRequired, url: React.PropTypes.string.isRequired, diff --git a/src/components/views/rooms/Stickerpack.js b/src/components/views/rooms/Stickerpack.js index 6a61618b2c..e04098a06b 100644 --- a/src/components/views/rooms/Stickerpack.js +++ b/src/components/views/rooms/Stickerpack.js @@ -25,8 +25,6 @@ import sdk from '../../../index'; import SdkConfig from '../../../SdkConfig'; import ScalarAuthClient from '../../../ScalarAuthClient'; import dis from '../../../dispatcher'; -import TintableSvgButton from '../elements/TintableSvgButton'; - export default class Stickerpack extends React.Component { constructor(props) { From 234ca8b062f088f23a2f50d508d2a20056a73c79 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 8 Feb 2018 17:50:30 +0000 Subject: [PATCH 085/170] Remove top padding from app tile. --- src/ScalarMessaging.js | 1 - src/components/structures/ContextualMenu.js | 4 ++++ src/components/views/rooms/Stickerpack.js | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index 3d585108dd..ac68d1a2d2 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -336,7 +336,6 @@ function setWidget(event, roomId) { if (userWidget) { console.warn('Adding user widget'); const client = MatrixClientPeg.get(); - // client.setAccountData('m.widgets', {}); const userWidgets = client.getAccountData('m.widgets').getContent() || {}; // Delete existing widget with ID diff --git a/src/components/structures/ContextualMenu.js b/src/components/structures/ContextualMenu.js index 7ec078f739..3c23e0ceae 100644 --- a/src/components/structures/ContextualMenu.js +++ b/src/components/structures/ContextualMenu.js @@ -134,6 +134,10 @@ module.exports = { menuStyle["backgroundColor"] = props.menuColour; } + if (!isNaN(Number(props.menuPaddingTop))) { + menuStyle["paddingTop"] = props.menuPaddingTop; + } + // FIXME: If a menu uses getDefaultProps it clobbers the onFinished // property set here so you can't close the menu from a button click! const menu = ( diff --git a/src/components/views/rooms/Stickerpack.js b/src/components/views/rooms/Stickerpack.js index e04098a06b..24bd44c3d3 100644 --- a/src/components/views/rooms/Stickerpack.js +++ b/src/components/views/rooms/Stickerpack.js @@ -175,6 +175,7 @@ export default class Stickerpack extends React.Component { menuHeight: this.popoverHeight, element: this.state.stickersContent, onFinished: this.onFinished, + menuPaddingTop: 0, }); From 9e3c1fbc7ac6a7e1da09e9a82406497ec388d2af Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Fri, 9 Feb 2018 11:44:27 +0000 Subject: [PATCH 086/170] Pass room name. --- src/ScalarAuthClient.js | 5 ++++- src/components/views/elements/AppTile.js | 2 +- src/components/views/elements/ManageIntegsButton.js | 4 ++-- src/components/views/rooms/AppsDrawer.js | 2 +- src/components/views/rooms/RoomHeader.js | 2 +- src/components/views/rooms/Stickerpack.js | 2 +- 6 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/ScalarAuthClient.js b/src/ScalarAuthClient.js index 3e775a94ab..756965d41e 100644 --- a/src/ScalarAuthClient.js +++ b/src/ScalarAuthClient.js @@ -105,10 +105,13 @@ class ScalarAuthClient { return defer.promise; } - getScalarInterfaceUrlForRoom(roomId, screen, id) { + getScalarInterfaceUrlForRoom(room, screen, id) { + const roomId = room.roomId; + const roomName = room.name; let url = SdkConfig.get().integrations_ui_url; url += "?scalar_token=" + encodeURIComponent(this.scalarToken); url += "&room_id=" + encodeURIComponent(roomId); + url += "&room_name=" + encodeURIComponent(roomName); if (id) { url += '&integ_id=' + encodeURIComponent(id); } diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 9d76e3410e..cc11a8542a 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -277,7 +277,7 @@ export default class AppTile extends React.Component { } else { const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager"); const src = this._scalarClient.getScalarInterfaceUrlForRoom( - this.props.room.roomId, 'type_' + this.props.type, this.props.id); + this.props.room, 'type_' + this.props.type, this.props.id); Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, { src: src, }, "mx_IntegrationsManager"); diff --git a/src/components/views/elements/ManageIntegsButton.js b/src/components/views/elements/ManageIntegsButton.js index 17dbbeee62..024c5feda5 100644 --- a/src/components/views/elements/ManageIntegsButton.js +++ b/src/components/views/elements/ManageIntegsButton.js @@ -64,7 +64,7 @@ export default class ManageIntegsButton extends React.Component { const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager"); Modal.createDialog(IntegrationsManager, { src: (this.scalarClient !== null && this.scalarClient.hasCredentials()) ? - this.scalarClient.getScalarInterfaceUrlForRoom(this.props.roomId) : + this.scalarClient.getScalarInterfaceUrlForRoom(this.props.room) : null, }, "mx_IntegrationsManager"); } @@ -103,5 +103,5 @@ export default class ManageIntegsButton extends React.Component { } ManageIntegsButton.propTypes = { - roomId: PropTypes.string.isRequired, + room: PropTypes.object.isRequired, }; diff --git a/src/components/views/rooms/AppsDrawer.js b/src/components/views/rooms/AppsDrawer.js index 78677e138b..7541b304a2 100644 --- a/src/components/views/rooms/AppsDrawer.js +++ b/src/components/views/rooms/AppsDrawer.js @@ -189,7 +189,7 @@ module.exports = React.createClass({ _launchManageIntegrations: function() { const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager"); const src = (this.scalarClient !== null && this.scalarClient.hasCredentials()) ? - this.scalarClient.getScalarInterfaceUrlForRoom(this.props.room.roomId, 'add_integ') : + this.scalarClient.getScalarInterfaceUrlForRoom(this.props.room, 'add_integ') : null; Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, { src: src, diff --git a/src/components/views/rooms/RoomHeader.js b/src/components/views/rooms/RoomHeader.js index aee229c5da..67ede1a011 100644 --- a/src/components/views/rooms/RoomHeader.js +++ b/src/components/views/rooms/RoomHeader.js @@ -391,7 +391,7 @@ module.exports = React.createClass({ let manageIntegsButton; if (this.props.room && this.props.room.roomId && this.props.inRoom) { manageIntegsButton = ; } diff --git a/src/components/views/rooms/Stickerpack.js b/src/components/views/rooms/Stickerpack.js index 24bd44c3d3..983a357d86 100644 --- a/src/components/views/rooms/Stickerpack.js +++ b/src/components/views/rooms/Stickerpack.js @@ -208,7 +208,7 @@ export default class Stickerpack extends React.Component { const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager"); const src = (this.scalarClient !== null && this.scalarClient.hasCredentials()) ? this.scalarClient.getScalarInterfaceUrlForRoom( - this.props.room.roomId, + this.props.room, 'type_stickerpack', this.widgetId, ) : From 55593416fa71c9c2a77382da8053457c6a5d4d39 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Fri, 9 Feb 2018 13:23:34 +0000 Subject: [PATCH 087/170] Hide apps drawer when viewining room settings. --- src/components/structures/RoomView.js | 3 +- src/components/views/rooms/AppsDrawer.js | 40 ++++++++++++++---------- src/components/views/rooms/AuxPanel.js | 9 +++++- 3 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 60987fe26e..4873bbc961 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -1605,7 +1605,8 @@ module.exports = React.createClass({ displayConfCallNotification={this.state.displayConfCallNotification} maxHeight={this.state.auxPanelMaxHeight} onResize={this.onChildResize} - showApps={this.state.showApps && !this.state.editingRoomSettings} > + showApps={this.state.showApps} + hideAppsDrawer={this.state.editingRoomSettings} > { aux } ); diff --git a/src/components/views/rooms/AppsDrawer.js b/src/components/views/rooms/AppsDrawer.js index 7541b304a2..a8336edfc3 100644 --- a/src/components/views/rooms/AppsDrawer.js +++ b/src/components/views/rooms/AppsDrawer.js @@ -35,7 +35,15 @@ module.exports = React.createClass({ displayName: 'AppsDrawer', propTypes: { + userId: React.PropTypes.string.isRequired, room: React.PropTypes.object.isRequired, + showApps: React.PropTypes.bool, // Should apps be rendered + hide: React.PropTypes.bool, // If rendered, should apps drawer be visible + }, + + defaultProps: { + showApps: true, + hide: false, }, getInitialState: function() { @@ -46,7 +54,7 @@ module.exports = React.createClass({ componentWillMount: function() { ScalarMessaging.startListening(); - MatrixClientPeg.get().on("RoomState.events", this.onRoomStateEvents); + MatrixClientPeg.get().on('RoomState.events', this.onRoomStateEvents); }, componentDidMount: function() { @@ -56,7 +64,7 @@ module.exports = React.createClass({ this.scalarClient.connect().then(() => { this.forceUpdate(); }).catch((e) => { - console.log("Failed to connect to integrations server"); + console.log('Failed to connect to integrations server'); // TODO -- Handle Scalar errors // this.setState({ // scalar_error: err, @@ -70,7 +78,7 @@ module.exports = React.createClass({ componentWillUnmount: function() { ScalarMessaging.stopListening(); if (MatrixClientPeg.get()) { - MatrixClientPeg.get().removeListener("RoomState.events", this.onRoomStateEvents); + MatrixClientPeg.get().removeListener('RoomState.events', this.onRoomStateEvents); } dis.unregister(this.dispatcherRef); }, @@ -81,7 +89,7 @@ module.exports = React.createClass({ }, onAction: function(action) { - const hideWidgetKey = this.props.room.roomId + "_hide_widget_drawer"; + const hideWidgetKey = this.props.room.roomId + '_hide_widget_drawer'; switch (action.action) { case 'appsDrawer': // When opening the app drawer when there aren't any apps, @@ -109,7 +117,7 @@ module.exports = React.createClass({ * passed through encodeURIComponent. * @param {string} pathTemplate The path with template variables e.g. '/foo/$bar'. * @param {Object} variables The key/value pairs to replace the template - * variables with. E.g. { "$bar": "baz" }. + * variables with. E.g. { '$bar': 'baz' }. * @return {string} The result of replacing all template variables e.g. '/foo/baz'. */ encodeUri: function(pathTemplate, variables) { @@ -187,13 +195,13 @@ module.exports = React.createClass({ }, _launchManageIntegrations: function() { - const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager"); + const IntegrationsManager = sdk.getComponent('views.settings.IntegrationsManager'); const src = (this.scalarClient !== null && this.scalarClient.hasCredentials()) ? this.scalarClient.getScalarInterfaceUrlForRoom(this.props.room, 'add_integ') : null; Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, { src: src, - }, "mx_IntegrationsManager"); + }, 'mx_IntegrationsManager'); }, onClickAddWidget: function(e) { @@ -201,12 +209,12 @@ module.exports = React.createClass({ // Display a warning dialog if the max number of widgets have already been added to the room const apps = this._getApps(); if (apps && apps.length >= MAX_WIDGETS) { - const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); + const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog'); const errorMsg = `The maximum number of ${MAX_WIDGETS} widgets have already been added to this room.`; console.error(errorMsg); Modal.createDialog(ErrorDialog, { - title: _t("Cannot add any more widgets"), - description: _t("The maximum permitted number of widgets have already been added to this room."), + title: _t('Cannot add any more widgets'), + description: _t('The maximum permitted number of widgets have already been added to this room.'), }); return; } @@ -238,11 +246,11 @@ module.exports = React.createClass({ ) { addWidget =
[+] { _t('Add a widget') } @@ -250,8 +258,8 @@ module.exports = React.createClass({ } return ( -
-
+
+
{ apps }
{ this._canUserModify() && addWidget } diff --git a/src/components/views/rooms/AuxPanel.js b/src/components/views/rooms/AuxPanel.js index c0857d9691..749026d5c6 100644 --- a/src/components/views/rooms/AuxPanel.js +++ b/src/components/views/rooms/AuxPanel.js @@ -31,7 +31,8 @@ module.exports = React.createClass({ // js-sdk room object room: React.PropTypes.object.isRequired, userId: React.PropTypes.string.isRequired, - showApps: React.PropTypes.bool, + showApps: React.PropTypes.bool, // Render apps + hideAppsDrawer: React.PropTypes.bool, // Do not display apps drawer and content (may still be rendered) // Conference Handler implementation conferenceHandler: React.PropTypes.object, @@ -51,6 +52,11 @@ module.exports = React.createClass({ onResize: React.PropTypes.func, }, + defaultProps: { + showApps: true, + hideAppsDrawer: false, + }, + shouldComponentUpdate: function(nextProps, nextState) { return (!ObjectUtils.shallowEqual(this.props, nextProps) || !ObjectUtils.shallowEqual(this.state, nextState)); @@ -133,6 +139,7 @@ module.exports = React.createClass({ userId={this.props.userId} maxHeight={this.props.maxHeight} showApps={this.props.showApps} + hide={this.props.hideAppsDrawer} />; return ( From ce560c577f04e88c27e9b8a86086f0a37e3a2f46 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 22 Feb 2018 15:20:51 +0000 Subject: [PATCH 088/170] Fix link spacing --- src/components/views/rooms/Stickerpack.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/Stickerpack.js b/src/components/views/rooms/Stickerpack.js index 983a357d86..e7403c3787 100644 --- a/src/components/views/rooms/Stickerpack.js +++ b/src/components/views/rooms/Stickerpack.js @@ -39,7 +39,7 @@ export default class Stickerpack extends React.Component { this.defaultStickersContent = (

{ _t("You don't currently have any stickerpacks enabled") }

-

{ _t("Click") } { _t("here") } { _t("to add some!") }

+

{ _t("Click") } { _t("here") } { _t("to add some!") }

{_t('Add
); From 9a5c916570ebe2e81077f270329f3f4cb1a90888 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 22 Feb 2018 15:36:01 +0000 Subject: [PATCH 089/170] Close modal on integration manager launch. --- src/components/views/rooms/Stickerpack.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/views/rooms/Stickerpack.js b/src/components/views/rooms/Stickerpack.js index e7403c3787..5aa845b4db 100644 --- a/src/components/views/rooms/Stickerpack.js +++ b/src/components/views/rooms/Stickerpack.js @@ -195,8 +195,6 @@ export default class Stickerpack extends React.Component { */ onFinished() { this.setState({showStickers: false}); - this.stickersMenu = null; - this.forceUpdate(); console.warn("finshed"); } @@ -204,7 +202,6 @@ export default class Stickerpack extends React.Component { * Launch the integrations manager on the stickers integration page */ _launchManageIntegrations() { - this.onFinished(); const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager"); const src = (this.scalarClient !== null && this.scalarClient.hasCredentials()) ? this.scalarClient.getScalarInterfaceUrlForRoom( @@ -216,6 +213,7 @@ export default class Stickerpack extends React.Component { Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, { src: src, }, "mx_IntegrationsManager"); + this.stickersMenu.close(); } render() { From 88288ff3f57f1a0628b036107bc15c5428016f73 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Fri, 23 Feb 2018 10:20:16 +0000 Subject: [PATCH 090/170] Add error handling for failure to connect to integration manager. --- src/components/views/rooms/Stickerpack.js | 26 ++++++++++++++++------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/components/views/rooms/Stickerpack.js b/src/components/views/rooms/Stickerpack.js index 5aa845b4db..7b3508b9a0 100644 --- a/src/components/views/rooms/Stickerpack.js +++ b/src/components/views/rooms/Stickerpack.js @@ -49,6 +49,7 @@ export default class Stickerpack extends React.Component { this.state = { stickersContent: this.defaultStickersContent, showStickers: false, + imError: null, }; } @@ -56,7 +57,7 @@ export default class Stickerpack extends React.Component { console.warn('Removing stickerpack widgets'); Widgets.removeStickerpackWidgets(); this._getStickerPickerWidget(); - this.onFinished(); + this.stickersMenu.close(); } componentDidMount() { @@ -66,21 +67,30 @@ export default class Stickerpack extends React.Component { this.scalarClient.connect().then(() => { this.forceUpdate(); }).catch((e) => { - console.log("Failed to connect to integrations server"); - // TODO -- Handle Scalar errors - // this.setState({ - // scalar_error: err, - // }); + this._imError("Failed to connect to integrations server", e); }); } - this._getStickerPickerWidget(); - this.dispatcherRef = dis.register(this._onWidgetAction); + + if (!this.state.imError) { + this._getStickerPickerWidget(); + this.dispatcherRef = dis.register(this._onWidgetAction); + } } componentWillUnmount() { dis.unregister(this.dispatcherRef); } + _imError(errorMsg, e) { + console.error(errorMsg, e); + const imErrorContent =

{ errorMsg }

; + this.setState({ + showStickers: false, + imError: errorMsg, + stickersContent: imErrorContent, + }); + } + _onWidgetAction(payload) { if (payload.action === "user_widget_updated") { console.warn("user widget updated"); From fefc325b12564e3b1018e8ad31c53f42e986085a Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Fri, 23 Feb 2018 10:29:52 +0000 Subject: [PATCH 091/170] Remove unused dep. --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 43a5ebfcfd..943c443c59 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,6 @@ "react-dnd-html5-backend": "^2.1.2", "react-dom": "^15.4.0", "react-gemini-scrollbar": "matrix-org/react-gemini-scrollbar#5e97aef", - "react-simple-popover": "matrix-org/react-popover", "sanitize-html": "^1.14.1", "text-encoding-utf-8": "^1.0.1", "url": "^0.11.0", From 46f94b3c5aab156b6b6d1406fa7d5aa00fc85089 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Fri, 23 Feb 2018 14:53:52 +0000 Subject: [PATCH 092/170] Ensure that roomId is validated before accessing room-based widgets. --- src/ScalarMessaging.js | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index ac68d1a2d2..abd1caaec1 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -334,7 +334,6 @@ function setWidget(event, roomId) { }; if (userWidget) { - console.warn('Adding user widget'); const client = MatrixClientPeg.get(); const userWidgets = client.getAccountData('m.widgets').getContent() || {}; @@ -357,7 +356,6 @@ function setWidget(event, roomId) { } client.setAccountData('m.widgets', userWidgets); - console.warn(`Set user widgets to:`, client.getAccountData('m.widgets')); sendResponse(event, { success: true, }); @@ -619,17 +617,14 @@ const onMessage = function(event) { const userId = event.data.user_id; // These APIs don't require roomId + // Get and set user widgets (not associated with a specific room) + // If roomId is specified, it must be validated, so room-based widgets agreed + // handled further down. if (event.data.action === "get_widgets") { - getWidgets(event, roomId); + getWidgets(event, null); return; } else if (event.data.action === "set_widget") { - setWidget(event, roomId); - return; - } else if (event.data.action === "add_widget_asset") { - addWidgetAsset(event, roomId); - return; - } else if (event.data.action === "remove_widget_asset") { - removeWidgetAsset(event, roomId); + setWidget(event, null); return; } @@ -656,6 +651,15 @@ const onMessage = function(event) { return; } + // Get and set room-based widgets + if (event.data.action === "get_widgets") { + getWidgets(event, null); + return; + } else if (event.data.action === "set_widget") { + setWidget(event, null); + return; + } + // These APIs don't require userId if (event.data.action === "join_rules_state") { getJoinRules(event, roomId); From 57b027b77619dd9e130cac74e072b5f1f3fccf0a Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Fri, 23 Feb 2018 15:11:28 +0000 Subject: [PATCH 093/170] Fix API names. --- src/WidgetMessaging.js | 158 +++-------------------------------------- 1 file changed, 9 insertions(+), 149 deletions(-) diff --git a/src/WidgetMessaging.js b/src/WidgetMessaging.js index c1af402e4d..75a9960987 100644 --- a/src/WidgetMessaging.js +++ b/src/WidgetMessaging.js @@ -15,146 +15,8 @@ limitations under the License. */ /* -POSTMESSAGE API -=============== - -Listens for incoming postMessage requests from embedded widgets. The following API is exposed: -{ - api: "widget", - action: "content_loaded", - widgetId: $WIDGET_ID, - data: {} - // additional request fields -} - -The complete request object is returned to the caller with an additional "response" key like so: -{ - api: "widget", - action: "content_loaded", - widgetId: $WIDGET_ID, - data: {}, - // additional request fields - response: { ... } -} - -The "api" field is required to use this API, and must be set to "widget" in all requests. - -The "action" determines the format of the request and response. All actions can return an error response. - -Additional data can be sent as abritrary fields. However, typically the data object should be used. - -A success response is an object with zero or more keys. - -An error response is a "response" object which consists of a sole "error" key to indicate an error. -They look like: -{ - error: { - message: "Unable to invite user into room.", - _error: - } -} -The "message" key should be a human-friendly string. - -ACTIONS -======= -** All actions must include an "api" field with value of "widget".** -All actions can return an error response instead of the response outlined below. - -content_loaded --------------- -Indicates that widget contet has fully loaded - -Request: - - widgetId is the unique ID of the widget instance in riot / matrix state. - - No additional fields. -Response: -{ - success: "true" -} -Example: -{ - api: "widget", - action: "content_loaded", - widgetId: $WIDGET_ID -} - - -api_version ------------ -Get the current version of the widget postMessage API - -Request: - - No additional fields. -Response: -{ - api_version: "0.0.1" -} -Example: -{ - api: "widget", - action: "api_version", -} - -supported_api_versions ----------------------- -Get versions of the widget postMessage API that are currently supported - -Request: - - No additional fields. -Response: -{ - api: "widget" - supported_versions: ["0.0.1"] -} -Example: -{ - api: "widget", - action: "supported_api_versions", -} - - -OUTBOUND POSTMESSAGE API -======================== - -This API can be used to initiate actions in remote widget instances. - -ACTIONS -======= - -Outbound actions use the "widget_client" API key / name, which must be included -on all requests. - -{ - api: "widget_client", - action: "screenshot", - widgetId: $WIDGET_ID, - data: {} - // additional request fields -} - - -screenshot ----------- - -Request a screenshot from the widget (if supported). -This can currently only be supported by widgets that have access to all of their DOM tree. -For example, widgets that nest further levels of iframes can not support this capability. - -The screenshot is returned as a Blob object. - -Request: - - No additional fields. -Response: -{ - screenshot: {data...} -} -Example: -{ - api: "widget_client", - action: "screenshot", - widgetId: $WIDGET_ID -} - +* See - https://docs.google.com/document/d/1uPF7XWY_dXTKVKV7jZQ2KmsI19wn9-kFRgQ1tFQP7wQ/edit?usp=sharing for +* spec. details / documentation. */ import URL from 'url'; @@ -166,6 +28,8 @@ const WIDGET_API_VERSION = '0.0.1'; // Current API version const SUPPORTED_WIDGET_API_VERSIONS = [ '0.0.1', ]; +const INBOUND_API_NAME = 'fromWidget'; +const OUTBOUND_API_NAME = 'toWidget'; if (!global.mxWidgetMessagingListenerCount) { global.mxWidgetMessagingListenerCount = 0; @@ -293,7 +157,6 @@ export default class WidgetMessaging extends MatrixPostMessageApi { return false; } - /** * Handle widget postMessage events * @param {Event} event Event to handle @@ -308,7 +171,7 @@ export default class WidgetMessaging extends MatrixPostMessageApi { if ( event.origin.length === 0 || !this.trustedEndpoint(event.origin) || - event.data.api !== "widget" || + event.data.api !== INBOUND_API_NAME || !event.data.widgetId ) { return; // don't log this - debugging APIs like to spam postMessage which floods the log otherwise @@ -324,12 +187,12 @@ export default class WidgetMessaging extends MatrixPostMessageApi { this.sendResponse(event, {success: true}); } else if (action === 'supported_api_versions') { this.sendResponse(event, { - api: "widget", + api: INBOUND_API_NAME, supported_versions: SUPPORTED_WIDGET_API_VERSIONS, }); } else if (action === 'api_version') { this.sendResponse(event, { - api: "widget", + api: INBOUND_API_NAME, version: WIDGET_API_VERSION, }); } else if (action === 'sticker_message') { @@ -393,10 +256,9 @@ export default class WidgetMessaging extends MatrixPostMessageApi { getScreenshot() { return new Promise((resolve, reject) => { this.exec({ - api: "widget_client", + api: OUTBOUND_API_NAME, action: "screenshot", }).then(function(response) { - // console.warn("got screenshot", response.screenshot); resolve(response.screenshot); }).catch((error) => { reject(Error("Failed to get screenshot: " + error.message)); @@ -407,10 +269,9 @@ export default class WidgetMessaging extends MatrixPostMessageApi { getCapabilities() { return new Promise((resolve, reject) => { this.exec({ - api: "widget_client", + api: OUTBOUND_API_NAME, action: "capabilities", }).then(function(response) { - // console.warn("got capabilities", response.capabilities); resolve(response.capabilities); }).catch((error) => { reject(Error("Failed to get capabilities: " + error.message)); @@ -419,7 +280,6 @@ export default class WidgetMessaging extends MatrixPostMessageApi { } } - /** * Represents mapping of widget instance to URLs for trusted postMessage communication. */ From d755b8284c40a95e96c1e6f30dd64c07e00af1e2 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Fri, 23 Feb 2018 15:22:56 +0000 Subject: [PATCH 094/170] Remove logging and cleanup. --- src/components/views/elements/AppTile.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index cc11a8542a..07bb811667 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -74,7 +74,6 @@ export default class AppTile extends React.Component { }; } - /** * Does the widget support a given capability * @param {[type]} capability Capability to check for @@ -112,7 +111,6 @@ export default class AppTile extends React.Component { return u.format(); } - /** * Returns true if specified url is a scalar URL, typically https://scalar.vector.im/api * @param {[type]} url URL to check @@ -164,7 +162,6 @@ export default class AppTile extends React.Component { componentWillUnmount() { // Widget action listeners - console.warn('Removing widget event listener', this.dispatcherRef); dis.unregister(this.dispatcherRef); // Widget postMessage listeners @@ -339,7 +336,6 @@ export default class AppTile extends React.Component { * Called when widget iframe has finished loading */ _onLoaded() { - console.warn("App frame loaded", this.props.id); this.widgetMessaging = new WidgetMessaging(this.props.id, this.refs.appFrame.contentWindow); this.widgetMessaging.startListening(); this.widgetMessaging.addEndpoint(this.props.id, this.props.url); From 9b667f2c3820881f35a943ed0f7091aa5325e23e Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Fri, 23 Feb 2018 15:26:47 +0000 Subject: [PATCH 095/170] Reduce logging. --- src/components/views/rooms/Stickerpack.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/components/views/rooms/Stickerpack.js b/src/components/views/rooms/Stickerpack.js index 7b3508b9a0..2163d89f76 100644 --- a/src/components/views/rooms/Stickerpack.js +++ b/src/components/views/rooms/Stickerpack.js @@ -93,7 +93,6 @@ export default class Stickerpack extends React.Component { _onWidgetAction(payload) { if (payload.action === "user_widget_updated") { - console.warn("user widget updated"); this._getStickerPickerWidget(); return; } @@ -103,7 +102,6 @@ export default class Stickerpack extends React.Component { // Stickers // TODO - Add support for stickerpacks from multiple app stores. // Render content from multiple stickerpack sources, each within their own iframe, within the stickerpack UI element. - console.warn("Checking for sticker picker widgets"); const stickerpackWidget = Widgets.getStickerpackWidgets()[0]; let stickersContent; @@ -111,7 +109,6 @@ export default class Stickerpack extends React.Component { if (stickerpackWidget && stickerpackWidget.content && stickerpackWidget.content.url) { // Set default name stickerpackWidget.content.name = stickerpackWidget.name || "Stickerpack"; - console.warn('Stickerpack widget', stickerpackWidget); this.widgetId = stickerpackWidget.id; stickersContent = ( @@ -205,7 +202,6 @@ export default class Stickerpack extends React.Component { */ onFinished() { this.setState({showStickers: false}); - console.warn("finshed"); } /** From 9ae89e2b43cd577f89d66c60523c8cb8a985d624 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Fri, 23 Feb 2018 15:27:55 +0000 Subject: [PATCH 096/170] Reduce logging. --- src/utils/widgets.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/utils/widgets.js b/src/utils/widgets.js index 2c7901a18f..a70a4f0406 100644 --- a/src/utils/widgets.js +++ b/src/utils/widgets.js @@ -50,9 +50,7 @@ function getUserWidgets() { */ function getStickerpackWidgets() { const widgets = getUserWidgets(); - console.warn("widgets", widgets); const stickerpackWidgets = widgets.filter((widget) => widget.type='stickerpack'); - console.warn('Stickerpack widgets', stickerpackWidgets); return stickerpackWidgets; } From 86461bc88f7b663fd69d327da5abd0a6f80df860 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Sat, 24 Feb 2018 00:10:28 +0000 Subject: [PATCH 098/170] Disable all widget assets on widget removal. --- src/ScalarAuthClient.js | 27 +++++++++++++++++++++++ src/components/views/rooms/Stickerpack.js | 10 +++++++++ 2 files changed, 37 insertions(+) diff --git a/src/ScalarAuthClient.js b/src/ScalarAuthClient.js index c3fcf80308..fea7ee9aa4 100644 --- a/src/ScalarAuthClient.js +++ b/src/ScalarAuthClient.js @@ -148,6 +148,33 @@ class ScalarAuthClient { return defer.promise; } + disableWidgetAssets(widgetType, widgetId) { + let url = SdkConfig.get().integrations_rest_url + '/widgets/set_assets_state'; + url = this.getStarterLink(url); + return new Promise((resolve, reject) => { + request({ + method: 'GET', + uri: url, + json: true, + qs: { + 'widget_type': widgetType, + 'widget_id': widgetId, + 'state': 'disable', + }, + }, (err, response, body) => { + if (err) { + reject(err); + } else if (response.statusCode / 100 !== 2) { + reject({statusCode: response.statusCode}); + } else if (!body) { + reject(new Error("Failed to set widget assets state")); + } else { + resolve(); + } + }); + }); + } + getScalarInterfaceUrlForRoom(room, screen, id) { const roomId = room.roomId; const roomName = room.name; diff --git a/src/components/views/rooms/Stickerpack.js b/src/components/views/rooms/Stickerpack.js index 2163d89f76..f20c581171 100644 --- a/src/components/views/rooms/Stickerpack.js +++ b/src/components/views/rooms/Stickerpack.js @@ -55,6 +55,15 @@ export default class Stickerpack extends React.Component { _removeStickerpackWidgets() { console.warn('Removing stickerpack widgets'); + if (this.widgetId) { + this.scalarClient.disableWidgetAssets('stickerpack', this.widgetId).then(() => { + console.warn('Assets disabled'); + }).catch((err) => { + console.error('Failed to disable assets'); + }); + } else { + console.warn('No widget ID specified, not disabling assets'); + } Widgets.removeStickerpackWidgets(); this._getStickerPickerWidget(); this.stickersMenu.close(); @@ -151,6 +160,7 @@ export default class Stickerpack extends React.Component { // Default content to show if stickerpack widget not added console.warn("No available sticker picker widgets"); stickersContent = this.defaultStickersContent; + this.widgetId = null; this.forceUpdate(); } this.setState({ From ee4310cc41e26482fdf2e2444c4dee2023f583d7 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Sun, 25 Feb 2018 21:47:23 +0000 Subject: [PATCH 099/170] Avoid potential NPE. --- src/ScalarMessaging.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index abdea55506..7a9f85a9e0 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -335,7 +335,10 @@ function setWidget(event, roomId) { if (userWidget) { const client = MatrixClientPeg.get(); - const userWidgets = client.getAccountData('m.widgets').getContent() || {}; + let userWidgets = {}; + if (client.getAccountData('m.widgets')) { + userWidgets = client.getAccountData('m.widgets').getContent(); + } // Delete existing widget with ID try { From e249e3d6223624c5027bda839f82fd248be1ea01 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Sun, 25 Feb 2018 22:10:38 +0000 Subject: [PATCH 100/170] Correct stickerpicker naming, --- src/components/views/rooms/MessageComposer.js | 4 +-- .../{Stickerpack.js => Stickerpicker.js} | 36 +++++++++---------- src/utils/widgets.js | 20 +++++------ 3 files changed, 30 insertions(+), 30 deletions(-) rename src/components/views/rooms/{Stickerpack.js => Stickerpicker.js} (87%) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index e210442c50..70971e2299 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -24,7 +24,7 @@ import sdk from '../../../index'; import dis from '../../../dispatcher'; import RoomViewStore from '../../../stores/RoomViewStore'; import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore"; -import Stickerpack from './Stickerpack'; +import Stickerpicker from './Stickerpicker'; export default class MessageComposer extends React.Component { constructor(props, context) { @@ -344,7 +344,7 @@ export default class MessageComposer extends React.Component { hangupButton, callButton, videoCallButton, - , + , ); } else { controls.push( diff --git a/src/components/views/rooms/Stickerpack.js b/src/components/views/rooms/Stickerpicker.js similarity index 87% rename from src/components/views/rooms/Stickerpack.js rename to src/components/views/rooms/Stickerpicker.js index f20c581171..780a48d848 100644 --- a/src/components/views/rooms/Stickerpack.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -26,14 +26,14 @@ import SdkConfig from '../../../SdkConfig'; import ScalarAuthClient from '../../../ScalarAuthClient'; import dis from '../../../dispatcher'; -export default class Stickerpack extends React.Component { +export default class Stickerpicker extends React.Component { constructor(props) { super(props); this.onShowStickersClick = this.onShowStickersClick.bind(this); this.onHideStickersClick = this.onHideStickersClick.bind(this); this.onFinished = this.onFinished.bind(this); this._launchManageIntegrations = this._launchManageIntegrations.bind(this); - this._removeStickerpackWidgets = this._removeStickerpackWidgets.bind(this); + this._removeStickerpickerWidgets = this._removeStickerpickerWidgets.bind(this); this._onWidgetAction = this._onWidgetAction.bind(this); this.defaultStickersContent = ( @@ -53,8 +53,8 @@ export default class Stickerpack extends React.Component { }; } - _removeStickerpackWidgets() { - console.warn('Removing stickerpack widgets'); + _removeStickerpickerWidgets() { + console.warn('Removing Stickerpicker widgets'); if (this.widgetId) { this.scalarClient.disableWidgetAssets('stickerpack', this.widgetId).then(() => { console.warn('Assets disabled'); @@ -64,7 +64,7 @@ export default class Stickerpack extends React.Component { } else { console.warn('No widget ID specified, not disabling assets'); } - Widgets.removeStickerpackWidgets(); + Widgets.removeStickerpickerWidgets(); this._getStickerPickerWidget(); this.stickersMenu.close(); } @@ -109,16 +109,16 @@ export default class Stickerpack extends React.Component { _getStickerPickerWidget() { // Stickers - // TODO - Add support for stickerpacks from multiple app stores. - // Render content from multiple stickerpack sources, each within their own iframe, within the stickerpack UI element. - const stickerpackWidget = Widgets.getStickerpackWidgets()[0]; + // TODO - Add support for Stickerpickers from multiple app stores. + // Render content from multiple stickerpack sources, each within their own iframe, within the stickerpicker UI element. + const stickerpickerWidget = Widgets.getStickerpickerWidgets()[0]; let stickersContent; // Load stickerpack content - if (stickerpackWidget && stickerpackWidget.content && stickerpackWidget.content.url) { + if (stickerpickerWidget && stickerpickerWidget.content && stickerpickerWidget.content.url) { // Set default name - stickerpackWidget.content.name = stickerpackWidget.name || "Stickerpack"; - this.widgetId = stickerpackWidget.id; + stickerpickerWidget.content.name = stickerpickerWidget.name || "Stickerpack"; + this.widgetId = stickerpickerWidget.id; stickersContent = (
@@ -157,7 +157,7 @@ export default class Stickerpack extends React.Component {
); } else { - // Default content to show if stickerpack widget not added + // Default content to show if stickerpicker widget not added console.warn("No available sticker picker widgets"); stickersContent = this.defaultStickersContent; this.widgetId = null; diff --git a/src/utils/widgets.js b/src/utils/widgets.js index a70a4f0406..da68abb4a9 100644 --- a/src/utils/widgets.js +++ b/src/utils/widgets.js @@ -45,26 +45,26 @@ function getUserWidgets() { } /** - * Get active stickerpack widgets (stickerpacks are user widgets by nature) - * @return {[object]} Array containing current / active stickerpack widgets + * Get active stickerpicker widgets (stickerpickers are user widgets by nature) + * @return {[object]} Array containing current / active stickerpicker widgets */ -function getStickerpackWidgets() { +function getStickerpickerWidgets() { const widgets = getUserWidgets(); - const stickerpackWidgets = widgets.filter((widget) => widget.type='stickerpack'); - return stickerpackWidgets; + const stickerpickerWidgets = widgets.filter((widget) => widget.type='m.stickerpicker'); + return stickerpickerWidgets; } /** - * Remove all stickerpack widgets (stickerpacks are user widgets by nature) + * Remove all stickerpicker widgets (stickerpickers are user widgets by nature) */ -function removeStickerpackWidgets() { +function removeStickerpickerWidgets() { const client = MatrixClientPeg.get(); if (!client) { throw new Error('User not logged in'); } const userWidgets = client.getAccountData('m.widgets').getContent() || {}; Object.entries(userWidgets).forEach(([key, widget]) => { - if (widget.type === 'stickerpack') { + if (widget.type === 'm.stickerpicker') { delete userWidgets[key]; } }); @@ -76,6 +76,6 @@ export default { getWidgets, getRoomWidgets, getUserWidgets, - getStickerpackWidgets, - removeStickerpackWidgets, + getStickerpickerWidgets, + removeStickerpickerWidgets, }; From c93faf7de7f73850e608aab4635860286270f446 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Sun, 25 Feb 2018 22:21:30 +0000 Subject: [PATCH 101/170] Fix promise wrapping. --- src/WidgetMessaging.js | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/src/WidgetMessaging.js b/src/WidgetMessaging.js index 75a9960987..7d240137a7 100644 --- a/src/WidgetMessaging.js +++ b/src/WidgetMessaging.js @@ -22,7 +22,6 @@ limitations under the License. import URL from 'url'; import dis from './dispatcher'; import MatrixPostMessageApi from './MatrixPostMessageApi'; -import Promise from 'bluebird'; const WIDGET_API_VERSION = '0.0.1'; // Current API version const SUPPORTED_WIDGET_API_VERSIONS = [ @@ -251,32 +250,26 @@ export default class WidgetMessaging extends MatrixPostMessageApi { /** * Request a screenshot from a widget - * @return {Promise} To be resolved when screenshot has been generated + * @return {Promise} To be resolved with screenshot data when it has been generated */ getScreenshot() { - return new Promise((resolve, reject) => { - this.exec({ + return this.exec({ api: OUTBOUND_API_NAME, action: "screenshot", - }).then(function(response) { - resolve(response.screenshot); - }).catch((error) => { - reject(Error("Failed to get screenshot: " + error.message)); - }); - }); + }).then((response) => response.screenshot) + .catch((error) => new Error("Failed to get screenshot: " + error.message)); } + /** + * Request capabilities required by the widget + * @return {Promise} To be resolved with an array of requested widget capabilities + */ getCapabilities() { - return new Promise((resolve, reject) => { - this.exec({ + return this.exec({ api: OUTBOUND_API_NAME, action: "capabilities", - }).then(function(response) { - resolve(response.capabilities); - }).catch((error) => { - reject(Error("Failed to get capabilities: " + error.message)); - }); - }); + }).then((response) => response.capabilities) + .catch((error) => new Error("Failed to get capabilities: " + error.message)); } } From 2b0790b32bb3ddbf32871aa2e6d662ea42ab5de8 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Sun, 25 Feb 2018 22:36:59 +0000 Subject: [PATCH 102/170] Fix PropTypes. --- src/components/views/elements/AppTile.js | 30 ++++++++++++------------ 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 8abd5961bc..6c9ea55142 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -587,30 +587,30 @@ export default class AppTile extends React.Component { AppTile.displayName ='AppTile'; AppTile.propTypes = { - id: React.PropTypes.string.isRequired, - url: React.PropTypes.string.isRequired, - name: React.PropTypes.string.isRequired, - room: React.PropTypes.object.isRequired, - type: React.PropTypes.string.isRequired, + id: PropTypes.string.isRequired, + url: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, + room: PropTypes.object.isRequired, + type: PropTypes.string.isRequired, // Specifying 'fullWidth' as true will render the app tile to fill the width of the app drawer continer. // This should be set to true when there is only one widget in the app drawer, otherwise it should be false. - fullWidth: React.PropTypes.bool, + fullWidth: PropTypes.bool, // UserId of the current user - userId: React.PropTypes.string.isRequired, + userId: PropTypes.string.isRequired, // UserId of the entity that added / modified the widget - creatorUserId: React.PropTypes.string, - waitForIframeLoad: React.PropTypes.bool, - showMenubar: React.PropTypes.bool, + creatorUserId: PropTypes.string, + waitForIframeLoad: PropTypes.bool, + showMenubar: PropTypes.bool, // Should the AppTile render itself - show: React.PropTypes.bool, + show: PropTypes.bool, // Optional onEditClickHandler (overrides default behaviour) - onEditClick: React.PropTypes.func, + onEditClick: PropTypes.func, // Optional onDeleteClickHandler (overrides default behaviour) - onDeleteClick: React.PropTypes.func, + onDeleteClick: PropTypes.func, // Optionally hide the tile title - showTitle: React.PropTypes.bool, + showTitle: PropTypes.bool, // Optionally hide the tile minimise icon - showMinimise: React.PropTypes.bool, + showMinimise: PropTypes.bool, }; AppTile.defaultProps = { From 20a442c9626d55bb71621313b1d6385d394e3d47 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Sun, 25 Feb 2018 23:00:46 +0000 Subject: [PATCH 103/170] Add comment. --- src/ScalarAuthClient.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/ScalarAuthClient.js b/src/ScalarAuthClient.js index fea7ee9aa4..c7e439bf2e 100644 --- a/src/ScalarAuthClient.js +++ b/src/ScalarAuthClient.js @@ -148,6 +148,14 @@ class ScalarAuthClient { return defer.promise; } + /** + * Mark all assets associated with the specified widget as "disabled" in the + * integration manager database. + * This can be useful to temporarily prevent purchased assets from being displayed. + * @param {string} widgetType [description] + * @param {string} widgetId [description] + * @return {Promise} Resolves on completion + */ disableWidgetAssets(widgetType, widgetId) { let url = SdkConfig.get().integrations_rest_url + '/widgets/set_assets_state'; url = this.getStarterLink(url); From d3de44e6ebd062c4dec603cc69918a05b0781ade Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Mon, 26 Feb 2018 13:26:49 +0000 Subject: [PATCH 104/170] Global interface to start integration manager. --- src/IntegrationManager.js | 78 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 src/IntegrationManager.js diff --git a/src/IntegrationManager.js b/src/IntegrationManager.js new file mode 100644 index 0000000000..fcc97a1044 --- /dev/null +++ b/src/IntegrationManager.js @@ -0,0 +1,78 @@ +/* +Copyright 2017 New Vector 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. +*/ +import Modal from './Modal'; +import sdk from './index'; +import SdkConfig from './SdkConfig'; +import ScalarMessaging from './ScalarMessaging'; +import ScalarAuthClient from './ScalarAuthClient'; + +let currentRoomId = "!JWyCNPOtOmEXOylMBv:matrix.org"; + +if (!global.im) { + global.im = {}; +} + +export default class IntegrationManager { + static async _init() { + if (!global.im.client || !global.im.connected) { + if (SdkConfig.get().integrations_ui_url && SdkConfig.get().integrations_rest_url) { + ScalarMessaging.startListening(); + global.im.client = new ScalarAuthClient(); + + await global.im.client.connect().then(() => { + global.im.connected = true; + }).catch((e) => { + console.error("Failed to connect to integrations server", e); + global.im.error = e; + }); + } else { + console.error('Invalid integration manager config', SdkConfig.get()); + } + } + } + + /** + * Launch the integrations manager on the stickers integration page + * @param {string} integType integration / widget type + * @param {string} integId integration / widget ID + * @param {function} onClose Callback to invoke on integration manager close + */ + static async open(integType, integId, onClose) { + await IntegrationManager._init(); + const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager"); + console.warn("IM", global.im); + if (global.im.error || !(global.im.client && global.im.client.hasCredentials())) { + console.error("Scalar error", global.im); + return; + } + integType = 'type_' + integType; + console.warn("Launching integration manager", currentRoomId, integType, integId); + const src = (global.im.client && global.im.client.hasCredentials()) ? + global.im.client.getScalarInterfaceUrlForRoom( + currentRoomId, + integType, + integId, + ) : + null; + Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, { + src: src, + }, "mx_IntegrationsManager"); + + if (onClose) { + onClose(); + } + } +} From 14d52c9f250c970e358e702ba0c76f8b6e32d208 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Mon, 26 Feb 2018 13:29:16 +0000 Subject: [PATCH 105/170] Open integration manager from widget postMessage. --- src/WidgetMessaging.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/WidgetMessaging.js b/src/WidgetMessaging.js index 7d240137a7..edef56cee4 100644 --- a/src/WidgetMessaging.js +++ b/src/WidgetMessaging.js @@ -22,6 +22,7 @@ limitations under the License. import URL from 'url'; import dis from './dispatcher'; import MatrixPostMessageApi from './MatrixPostMessageApi'; +import IntegrationManager from './IntegrationManager'; const WIDGET_API_VERSION = '0.0.1'; // Current API version const SUPPORTED_WIDGET_API_VERSIONS = [ @@ -196,6 +197,11 @@ export default class WidgetMessaging extends MatrixPostMessageApi { }); } else if (action === 'sticker_message') { dis.dispatch({action: 'sticker_message', data: event.data.widgetData, widgetId: event.data.widgetId}); + } else if (action === 'integration_manager_open') { + const data = event.data.widgetData; + const integType = (data && data.integType) ? data.integType : null; + const integId = (data && data.integId) ? data.integId : null; + IntegrationManager.open(integType, integId); } else { console.warn("Widget postMessage event unhandled"); this.sendError(event, {message: "The postMessage was unhandled"}); From 707e3f3382becd35f5e68ede8bb2c47f851f0ba9 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Mon, 26 Feb 2018 13:32:27 +0000 Subject: [PATCH 106/170] Temp. revert unintended commit. --- src/IntegrationManager.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/IntegrationManager.js b/src/IntegrationManager.js index fcc97a1044..dde3294536 100644 --- a/src/IntegrationManager.js +++ b/src/IntegrationManager.js @@ -19,8 +19,6 @@ import SdkConfig from './SdkConfig'; import ScalarMessaging from './ScalarMessaging'; import ScalarAuthClient from './ScalarAuthClient'; -let currentRoomId = "!JWyCNPOtOmEXOylMBv:matrix.org"; - if (!global.im) { global.im = {}; } @@ -53,14 +51,13 @@ export default class IntegrationManager { static async open(integType, integId, onClose) { await IntegrationManager._init(); const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager"); - console.warn("IM", global.im); if (global.im.error || !(global.im.client && global.im.client.hasCredentials())) { console.error("Scalar error", global.im); return; } integType = 'type_' + integType; - console.warn("Launching integration manager", currentRoomId, integType, integId); const src = (global.im.client && global.im.client.hasCredentials()) ? + // FIXME -- Currently broken. Get current room ID global.im.client.getScalarInterfaceUrlForRoom( currentRoomId, integType, From 73c8ef50d104b995701db117b369a37f1bf76433 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Mon, 26 Feb 2018 13:37:53 +0000 Subject: [PATCH 107/170] Fix current roomID. --- src/IntegrationManager.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/IntegrationManager.js b/src/IntegrationManager.js index dde3294536..35b3baafbd 100644 --- a/src/IntegrationManager.js +++ b/src/IntegrationManager.js @@ -18,6 +18,7 @@ import sdk from './index'; import SdkConfig from './SdkConfig'; import ScalarMessaging from './ScalarMessaging'; import ScalarAuthClient from './ScalarAuthClient'; +import RoomViewStore from './stores/RoomViewStore'; if (!global.im) { global.im = {}; @@ -56,14 +57,14 @@ export default class IntegrationManager { return; } integType = 'type_' + integType; + console.warn("Current room", RoomViewStore.getRoomId()); const src = (global.im.client && global.im.client.hasCredentials()) ? - // FIXME -- Currently broken. Get current room ID - global.im.client.getScalarInterfaceUrlForRoom( - currentRoomId, - integType, - integId, - ) : - null; + global.im.client.getScalarInterfaceUrlForRoom( + RoomViewStore.getRoomId(), + integType, + integId, + ) : + null; Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, { src: src, }, "mx_IntegrationsManager"); From b64736aa44910a4cad4e449dc3f81c2839b95173 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Mon, 26 Feb 2018 13:43:16 +0000 Subject: [PATCH 108/170] Add listener to close stickerpicker. --- src/IntegrationManager.js | 1 - src/WidgetMessaging.js | 3 +++ src/components/views/rooms/Stickerpicker.js | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/IntegrationManager.js b/src/IntegrationManager.js index 35b3baafbd..d85b89f744 100644 --- a/src/IntegrationManager.js +++ b/src/IntegrationManager.js @@ -57,7 +57,6 @@ export default class IntegrationManager { return; } integType = 'type_' + integType; - console.warn("Current room", RoomViewStore.getRoomId()); const src = (global.im.client && global.im.client.hasCredentials()) ? global.im.client.getScalarInterfaceUrlForRoom( RoomViewStore.getRoomId(), diff --git a/src/WidgetMessaging.js b/src/WidgetMessaging.js index edef56cee4..50013a1c30 100644 --- a/src/WidgetMessaging.js +++ b/src/WidgetMessaging.js @@ -198,6 +198,9 @@ export default class WidgetMessaging extends MatrixPostMessageApi { } else if (action === 'sticker_message') { dis.dispatch({action: 'sticker_message', data: event.data.widgetData, widgetId: event.data.widgetId}); } else if (action === 'integration_manager_open') { + // Close the stickerpicker + dis.dispatch({action: 'stickerpicker_close'}); + // Open the integration manager const data = event.data.widgetData; const integType = (data && data.integType) ? data.integType : null; const integId = (data && data.integId) ? data.integId : null; diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index 780a48d848..fb9e7dc5f0 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -104,6 +104,8 @@ export default class Stickerpicker extends React.Component { if (payload.action === "user_widget_updated") { this._getStickerPickerWidget(); return; + } else if (payload.action === "stickerpicker_close") { + this.stickersMenu.close(); } } From 5ca0fc3ab5a37307c0a5f530db44ae035a0e47b8 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Mon, 26 Feb 2018 14:01:33 +0000 Subject: [PATCH 109/170] Make MStickerBody extend MImageBody. --- src/components/views/messages/MImageBody.js | 115 +++++---- src/components/views/messages/MStickerBody.js | 218 ++---------------- 2 files changed, 82 insertions(+), 251 deletions(-) diff --git a/src/components/views/messages/MImageBody.js b/src/components/views/messages/MImageBody.js index f5515fad90..55d5a18a25 100644 --- a/src/components/views/messages/MImageBody.js +++ b/src/components/views/messages/MImageBody.js @@ -30,35 +30,45 @@ import Promise from 'bluebird'; import { _t } from '../../../languageHandler'; import SettingsStore from "../../../settings/SettingsStore"; -module.exports = React.createClass({ - displayName: 'MImageBody', +export default class extends React.Component { + displayName: 'MImageBody' - propTypes: { + static propTypes = { /* the MatrixEvent to show */ mxEvent: PropTypes.object.isRequired, /* called when the image has loaded */ onWidgetLoad: PropTypes.func.isRequired, - }, + } - contextTypes: { + static contextTypes = { matrixClient: PropTypes.instanceOf(MatrixClient), - }, + } - getInitialState: function() { - return { + constructor(props) { + super(props); + + this.onAction = this.onAction.bind(this); + this.onImageEnter = this.onImageEnter.bind(this); + this.onImageLeave = this.onImageLeave.bind(this); + this.onClientSync = this.onClientSync.bind(this); + this.onClick = this.onClick.bind(this); + this.fixupHeight = this.fixupHeight.bind(this); + this._isGif = this._isGif.bind(this); + + this.state = { decryptedUrl: null, decryptedThumbnailUrl: null, decryptedBlob: null, error: null, imgError: false, }; - }, + } componentWillMount() { this.unmounted = false; this.context.matrixClient.on('sync', this.onClientSync); - }, + } onClientSync(syncState, prevState) { if (this.unmounted) return; @@ -71,9 +81,9 @@ module.exports = React.createClass({ imgError: false, }); } - }, + } - onClick: function onClick(ev) { + onClick(ev) { if (ev.button == 0 && !ev.metaKey) { ev.preventDefault(); const content = this.props.mxEvent.getContent(); @@ -93,49 +103,49 @@ module.exports = React.createClass({ Modal.createDialog(ImageView, params, "mx_Dialog_lightbox"); } - }, + } - _isGif: function() { + _isGif() { const content = this.props.mxEvent.getContent(); return ( content && content.info && content.info.mimetype === "image/gif" ); - }, + } - onImageEnter: function(e) { + onImageEnter(e) { if (!this._isGif() || SettingsStore.getValue("autoplayGifsAndVideos")) { return; } const imgElement = e.target; imgElement.src = this._getContentUrl(); - }, + } - onImageLeave: function(e) { + onImageLeave(e) { if (!this._isGif() || SettingsStore.getValue("autoplayGifsAndVideos")) { return; } const imgElement = e.target; imgElement.src = this._getThumbUrl(); - }, + } - onImageError: function() { + onImageError() { this.setState({ imgError: true, }); - }, + } - _getContentUrl: function() { + _getContentUrl() { const content = this.props.mxEvent.getContent(); if (content.file !== undefined) { return this.state.decryptedUrl; } else { return this.context.matrixClient.mxcUrlToHttp(content.url); } - }, + } - _getThumbUrl: function() { + _getThumbUrl() { const content = this.props.mxEvent.getContent(); if (content.file !== undefined) { // Don't use the thumbnail for clients wishing to autoplay gifs. @@ -146,9 +156,9 @@ module.exports = React.createClass({ } else { return this.context.matrixClient.mxcUrlToHttp(content.url, 800, 600); } - }, + } - componentDidMount: function() { + componentDidMount() { this.dispatcherRef = dis.register(this.onAction); this.fixupHeight(); const content = this.props.mxEvent.getContent(); @@ -182,23 +192,23 @@ module.exports = React.createClass({ }); }).done(); } - }, + } - componentWillUnmount: function() { + componentWillUnmount() { this.unmounted = true; dis.unregister(this.dispatcherRef); this.context.matrixClient.removeListener('sync', this.onClientSync); - }, + } - onAction: function(payload) { + onAction(payload) { if (payload.action === "timeline_resize") { this.fixupHeight(); } - }, + } - fixupHeight: function() { + fixupHeight() { if (!this.refs.image) { - console.warn("Refusing to fix up height on MImageBody with no image element"); + console.warn(`Refusing to fix up height on ${this.displayName} with no image element`); return; } @@ -214,10 +224,25 @@ module.exports = React.createClass({ } this.refs.image.style.height = thumbHeight + "px"; // console.log("Image height now", thumbHeight); - }, + } - render: function() { - const TintableSvg = sdk.getComponent("elements.TintableSvg"); + _messageContent(contentUrl, thumbUrl, content) { + return ( + + + {content.body} + + + + ); + } + + render() { const content = this.props.mxEvent.getContent(); if (this.state.error !== null) { @@ -265,19 +290,7 @@ module.exports = React.createClass({ } if (thumbUrl) { - return ( - - - {content.body} - - - - ); + return this._messageContent(contentUrl, thumbUrl, content); } else if (content.body) { return ( @@ -291,5 +304,5 @@ module.exports = React.createClass({ ); } - }, -}); + } +} diff --git a/src/components/views/messages/MStickerBody.js b/src/components/views/messages/MStickerBody.js index bd86eed568..95f5d827bb 100644 --- a/src/components/views/messages/MStickerBody.js +++ b/src/components/views/messages/MStickerBody.js @@ -16,209 +16,27 @@ limitations under the License. 'use strict'; -import React from 'react'; -import MatrixClientPeg from '../../../MatrixClientPeg'; -import ImageUtils from '../../../ImageUtils'; -import dis from '../../../dispatcher'; -import { decryptFile, readBlobAsDataUri } from '../../../utils/DecryptFile'; -import Promise from 'bluebird'; -import { _t } from '../../../languageHandler'; -import SettingsStore from "../../../settings/SettingsStore"; +import MImageBody from "./MImageBody"; -module.exports = React.createClass({ - displayName: 'MStickerBody', +export default class MStickerBody extends MImageBody { + displayName: 'MStickerBody' - propTypes: { - /* the MatrixEvent to show */ - mxEvent: React.PropTypes.object.isRequired, + constructor(props) { + super(props); + } - /* called when the image has loaded */ - onWidgetLoad: React.PropTypes.func.isRequired, - }, - - getInitialState: function() { - return { - decryptedUrl: null, - decryptedThumbnailUrl: null, - decryptedBlob: null, - error: null, - }; - }, - - _isGif: function() { - const content = this.props.mxEvent.getContent(); + _messageContent(contentUrl, thumbUrl, content) { return ( - content && - content.info && - content.info.mimetype === "image/gif" + + {content.body} + ); - }, + } - onImageEnter: function(e) { - if (!this._isGif() || SettingsStore.getValue("autoplayGifsAndVideos")) { - return; - } - const imgElement = e.target; - imgElement.src = this._getContentUrl(); - }, - - onImageLeave: function(e) { - if (!this._isGif() || SettingsStore.getValue("autoplayGifsAndVideos")) { - return; - } - const imgElement = e.target; - imgElement.src = this._getThumbUrl(); - }, - - _getContentUrl: function() { - const content = this.props.mxEvent.getContent(); - if (content.file !== undefined) { - return this.state.decryptedUrl; - } else { - return MatrixClientPeg.get().mxcUrlToHttp(content.url); - } - }, - - _getThumbUrl: function() { - const content = this.props.mxEvent.getContent(); - if (content.file !== undefined) { - // Don't use the thumbnail for clients wishing to autoplay gifs. - if (this.state.decryptedThumbnailUrl) { - return this.state.decryptedThumbnailUrl; - } - return this.state.decryptedUrl; - } else { - return MatrixClientPeg.get().mxcUrlToHttp(content.url, 800, 600); - } - }, - - componentDidMount: function() { - this.dispatcherRef = dis.register(this.onAction); - this.fixupHeight(); - const content = this.props.mxEvent.getContent(); - if (content.file !== undefined && this.state.decryptedUrl === null) { - let thumbnailPromise = Promise.resolve(null); - if (content.info.thumbnail_file) { - thumbnailPromise = decryptFile( - content.info.thumbnail_file, - ).then(function(blob) { - return readBlobAsDataUri(blob); - }); - } - let decryptedBlob; - thumbnailPromise.then((thumbnailUrl) => { - return decryptFile(content.file).then(function(blob) { - decryptedBlob = blob; - return readBlobAsDataUri(blob); - }).then((contentUrl) => { - this.setState({ - decryptedUrl: contentUrl, - decryptedThumbnailUrl: thumbnailUrl, - decryptedBlob: decryptedBlob, - }); - this.props.onWidgetLoad(); - }); - }).catch((err) => { - console.warn("Unable to decrypt attachment: ", err); - // Set a placeholder image when we can't decrypt the image. - this.setState({ - error: err, - }); - }).done(); - } - }, - - componentWillUnmount: function() { - dis.unregister(this.dispatcherRef); - }, - - onAction: function(payload) { - if (payload.action === "timeline_resize") { - this.fixupHeight(); - } - }, - - fixupHeight: function() { - if (!this.refs.image) { - console.warn("Refusing to fix up height on MStickerBody with no image element"); - return; - } - - const content = this.props.mxEvent.getContent(); - const timelineWidth = this.refs.body.offsetWidth; - const maxHeight = 600; // let images take up as much width as they can so long as the height doesn't exceed 600px. - // the alternative here would be 600*timelineWidth/800; to scale them down to fit inside a 4:3 bounding box - - //console.log("trying to fit image into timelineWidth of " + this.refs.body.offsetWidth + " or " + this.refs.body.clientWidth); - let thumbHeight = null; - if (content.info) { - thumbHeight = ImageUtils.thumbHeight(content.info.w, content.info.h, timelineWidth, maxHeight); - } - this.refs.image.style.height = thumbHeight + "px"; - // console.log("Image height now", thumbHeight); - }, - - render: function() { - const content = this.props.mxEvent.getContent(); - - if (this.state.error !== null) { - return ( - - - { _t("Error decrypting image") } - - ); - } - - if (content.file !== undefined && this.state.decryptedUrl === null) { - // Need to decrypt the attachment - // The attachment is decrypted in componentDidMount. - // For now add an img tag with a spinner. - return ( - -
- {content.body} -
-
- ); - } - - const contentUrl = this._getContentUrl(); - let thumbUrl; - if (this._isGif() && SettingsStore.getValue("autoplayGifsAndVideos")) { - thumbUrl = contentUrl; - } else { - thumbUrl = this._getThumbUrl(); - } - - if (thumbUrl) { - return ( - - {content.body} - - ); - } else if (content.body) { - return ( - - { _t("Image '%(Body)s' cannot be displayed.", {Body: content.body}) } - - ); - } else { - return ( - - { _t("This image cannot be displayed.") } - - ); - } - }, -}); + onClick() { + } +} From 8e7564b9a388b7e63432139e3c3f8e443acb478f Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Mon, 26 Feb 2018 17:47:52 +0000 Subject: [PATCH 110/170] Wrap the close menu trigger in a timeout --- src/components/views/rooms/Stickerpicker.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index fb9e7dc5f0..656d2826b4 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -231,7 +231,9 @@ export default class Stickerpicker extends React.Component { Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, { src: src, }, "mx_IntegrationsManager"); - this.stickersMenu.close(); + + // Wrap this in a timeout in order to avoid the DOM node from being pulled from under its feet + setTimeout(() => this.stickersMenu.close()); } render() { From ef4d13715a3f2fffee32f5400dba5d862ba7f80d Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Tue, 27 Feb 2018 11:29:14 +0000 Subject: [PATCH 111/170] Wrap menu close in timeout to avoid element disappearing unexpectedly. --- src/components/views/rooms/Stickerpicker.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index 656d2826b4..37d331943a 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -66,7 +66,7 @@ export default class Stickerpicker extends React.Component { } Widgets.removeStickerpickerWidgets(); this._getStickerPickerWidget(); - this.stickersMenu.close(); + setTimeout(() => this.stickersMenu.close()); } componentDidMount() { @@ -105,7 +105,7 @@ export default class Stickerpicker extends React.Component { this._getStickerPickerWidget(); return; } else if (payload.action === "stickerpicker_close") { - this.stickersMenu.close(); + setTimeout(() => this.stickersMenu.close()); } } @@ -206,7 +206,7 @@ export default class Stickerpicker extends React.Component { * @param {Event} ev Event that triggered the function call */ onHideStickersClick(ev) { - this.stickersMenu.close(); + setTimeout(() => this.stickersMenu.close()); } /** From 57c98d96a577d0d1a2d5fd811def22cc244361d0 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Tue, 27 Feb 2018 13:40:21 +0000 Subject: [PATCH 112/170] Update widget type. --- src/components/views/rooms/Stickerpicker.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index 37d331943a..f75cf50804 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -26,6 +26,8 @@ import SdkConfig from '../../../SdkConfig'; import ScalarAuthClient from '../../../ScalarAuthClient'; import dis from '../../../dispatcher'; +const widgetType = 'm.stickerpicker'; + export default class Stickerpicker extends React.Component { constructor(props) { super(props); @@ -56,7 +58,7 @@ export default class Stickerpicker extends React.Component { _removeStickerpickerWidgets() { console.warn('Removing Stickerpicker widgets'); if (this.widgetId) { - this.scalarClient.disableWidgetAssets('stickerpack', this.widgetId).then(() => { + this.scalarClient.disableWidgetAssets(widgetType, this.widgetId).then(() => { console.warn('Assets disabled'); }).catch((err) => { console.error('Failed to disable assets'); @@ -224,7 +226,7 @@ export default class Stickerpicker extends React.Component { const src = (this.scalarClient !== null && this.scalarClient.hasCredentials()) ? this.scalarClient.getScalarInterfaceUrlForRoom( this.props.room, - 'type_stickerpack', + 'type_' + widgetType, this.widgetId, ) : null; From 0fdbddf8fd80a532d0fff084eab8098ea282986c Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Tue, 27 Feb 2018 23:07:59 +0000 Subject: [PATCH 113/170] Show sticker description as a tooltip, on hover. --- src/components/views/messages/MStickerBody.js | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/components/views/messages/MStickerBody.js b/src/components/views/messages/MStickerBody.js index 95f5d827bb..130b591b56 100644 --- a/src/components/views/messages/MStickerBody.js +++ b/src/components/views/messages/MStickerBody.js @@ -17,22 +17,49 @@ limitations under the License. 'use strict'; import MImageBody from "./MImageBody"; +import sdk from '../../../index'; export default class MStickerBody extends MImageBody { displayName: 'MStickerBody' constructor(props) { super(props); + + this._onMouseEnter = this._onMouseEnter.bind(this); + this._onMouseLeave = this._onMouseLeave.bind(this); + } + + _onMouseEnter() { + this.setState({showTooltip: true}); + } + + _onMouseLeave() { + this.setState({showTooltip: false}); } _messageContent(contentUrl, thumbUrl, content) { + let tooltip; + const tooltipBody = ( + this.props.mxEvent && + this.props.mxEvent.getContent() && + this.props.mxEvent.getContent().body) ? + this.props.mxEvent.getContent().body : null; + if (this.state.showTooltip && tooltipBody) { + const RoomTooltip = sdk.getComponent("rooms.RoomTooltip"); + tooltip = ; + } + return ( {content.body} + onMouseEnter={this._onMouseEnter} + onMouseLeave={this._onMouseLeave} + /> + { tooltip } ); } From f3c928a4fcf8e860e39f17d578c5b9272d34bc19 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Wed, 28 Feb 2018 13:43:19 +0000 Subject: [PATCH 115/170] Lint. --- src/components/views/messages/MStickerBody.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/messages/MStickerBody.js b/src/components/views/messages/MStickerBody.js index 130b591b56..9873717378 100644 --- a/src/components/views/messages/MStickerBody.js +++ b/src/components/views/messages/MStickerBody.js @@ -48,7 +48,7 @@ export default class MStickerBody extends MImageBody { const RoomTooltip = sdk.getComponent("rooms.RoomTooltip"); tooltip = ; + label={tooltipBody} />; } return ( From 7755a3ce9002a145ff88836f1d35ff5c4ba42be3 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Tue, 6 Mar 2018 10:48:32 +0000 Subject: [PATCH 116/170] Nest sticker image element for correct positioning of tooltips. --- src/components/views/messages/MStickerBody.js | 16 +- yarn.lock | 4392 +++++++++++++++++ 2 files changed, 4401 insertions(+), 7 deletions(-) create mode 100644 yarn.lock diff --git a/src/components/views/messages/MStickerBody.js b/src/components/views/messages/MStickerBody.js index 9873717378..af39b1bd2d 100644 --- a/src/components/views/messages/MStickerBody.js +++ b/src/components/views/messages/MStickerBody.js @@ -53,13 +53,15 @@ export default class MStickerBody extends MImageBody { return ( - {content.body} - { tooltip } +
+ {content.body} + { tooltip } +
); } diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000000..27533e876b --- /dev/null +++ b/yarn.lock @@ -0,0 +1,4392 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + +accepts@1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca" + dependencies: + mime-types "~2.1.11" + negotiator "0.6.1" + +acorn-jsx@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" + dependencies: + acorn "^3.0.4" + +acorn@^3.0.0, acorn@^3.0.4: + version "3.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" + +acorn@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.5.0.tgz#1abb587fbf051f94e3de20e6b26ef910b1828298" + +after@0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" + +ajv-keywords@^1.0.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" + +ajv@^4.7.0, ajv@^4.9.1: + version "4.11.8" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" + dependencies: + co "^4.6.0" + json-stable-stringify "^1.0.1" + +ajv@^5.1.0: + version "5.5.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" + dependencies: + co "^4.6.0" + fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.3.0" + +align-text@^0.1.1, align-text@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" + dependencies: + kind-of "^3.0.2" + longest "^1.0.1" + repeat-string "^1.5.2" + +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + +another-json@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/another-json/-/another-json-0.2.0.tgz#b5f4019c973b6dd5c6506a2d93469cb6d32aeedc" + +ansi-escapes@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + dependencies: + color-convert "^1.9.0" + +anymatch@^1.3.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" + dependencies: + micromatch "^2.1.5" + normalize-path "^2.0.0" + +aproba@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + +are-we-there-yet@~1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d" + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + dependencies: + sprintf-js "~1.0.2" + +arr-diff@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" + dependencies: + arr-flatten "^1.0.1" + +arr-flatten@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + +array-includes@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.0.3.tgz#184b48f62d92d7452bb31b323165c7f8bd02266d" + dependencies: + define-properties "^1.1.2" + es-abstract "^1.7.0" + +array-slice@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5" + +array-union@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + dependencies: + array-uniq "^1.0.1" + +array-uniq@^1.0.1, array-uniq@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + +array-unique@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" + +arraybuffer.slice@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz#f33b2159f0532a3f3107a272c0ccfbd1ad2979ca" + +arrify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + +asap@~2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + +asn1@~0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + +assert-plus@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" + +assert@^1.1.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" + dependencies: + util "0.10.3" + +async-each@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" + +async@^0.9.0, async@~0.9.0: + version "0.9.2" + resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" + +async@^1.3.0: + version "1.5.2" + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + +async@~0.2.6: + version "0.2.10" + resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + +aws-sign2@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + +aws4@^1.2.1, aws4@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" + +babel-cli@^6.5.2: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-cli/-/babel-cli-6.26.0.tgz#502ab54874d7db88ad00b887a06383ce03d002f1" + dependencies: + babel-core "^6.26.0" + babel-polyfill "^6.26.0" + babel-register "^6.26.0" + babel-runtime "^6.26.0" + commander "^2.11.0" + convert-source-map "^1.5.0" + fs-readdir-recursive "^1.0.0" + glob "^7.1.2" + lodash "^4.17.4" + output-file-sync "^1.1.2" + path-is-absolute "^1.0.1" + slash "^1.0.0" + source-map "^0.5.6" + v8flags "^2.1.1" + optionalDependencies: + chokidar "^1.6.1" + +babel-code-frame@^6.16.0, babel-code-frame@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +babel-core@^6.14.0, babel-core@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.0.tgz#af32f78b31a6fcef119c87b0fd8d9753f03a0bb8" + dependencies: + babel-code-frame "^6.26.0" + babel-generator "^6.26.0" + babel-helpers "^6.24.1" + babel-messages "^6.23.0" + babel-register "^6.26.0" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + convert-source-map "^1.5.0" + debug "^2.6.8" + json5 "^0.5.1" + lodash "^4.17.4" + minimatch "^3.0.4" + path-is-absolute "^1.0.1" + private "^0.1.7" + slash "^1.0.0" + source-map "^0.5.6" + +babel-eslint@^6.1.2: + version "6.1.2" + resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-6.1.2.tgz#5293419fe3672d66598d327da9694567ba6a5f2f" + dependencies: + babel-traverse "^6.0.20" + babel-types "^6.0.19" + babylon "^6.0.18" + lodash.assign "^4.0.0" + lodash.pickby "^4.0.0" + +babel-generator@^6.26.0: + version "6.26.1" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" + dependencies: + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.17.4" + source-map "^0.5.7" + trim-right "^1.0.1" + +babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" + dependencies: + babel-helper-explode-assignable-expression "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-builder-react-jsx@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz#39ff8313b75c8b65dceff1f31d383e0ff2a408a0" + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + esutils "^2.0.2" + +babel-helper-call-delegate@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-define-map@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-explode-assignable-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-function-name@^6.24.1, babel-helper-function-name@^6.8.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" + dependencies: + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-get-function-arity@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-hoist-variables@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-optimise-call-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-regex@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-remap-async-to-generator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-replace-supers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" + dependencies: + babel-helper-optimise-call-expression "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helpers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-loader@^6.2.5: + version "6.4.1" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-6.4.1.tgz#0b34112d5b0748a8dcdbf51acf6f9bd42d50b8ca" + dependencies: + find-cache-dir "^0.1.1" + loader-utils "^0.2.16" + mkdirp "^0.5.1" + object-assign "^4.0.1" + +babel-messages@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-add-module-exports@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-0.2.1.tgz#9ae9a1f4a8dc67f0cdec4f4aeda1e43a5ff65e25" + +babel-plugin-check-es2015-constants@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-syntax-async-functions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" + +babel-plugin-syntax-class-properties@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de" + +babel-plugin-syntax-exponentiation-operator@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" + +babel-plugin-syntax-flow@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz#4c3ab20a2af26aa20cd25995c398c4eb70310c8d" + +babel-plugin-syntax-jsx@^6.3.13, babel-plugin-syntax-jsx@^6.8.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" + +babel-plugin-syntax-object-rest-spread@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" + +babel-plugin-syntax-trailing-function-commas@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" + +babel-plugin-transform-async-to-bluebird@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-bluebird/-/babel-plugin-transform-async-to-bluebird-1.1.1.tgz#46ea3e7c5af629782ac9f1ed1b7cd38f8425afd4" + dependencies: + babel-helper-function-name "^6.8.0" + babel-plugin-syntax-async-functions "^6.8.0" + babel-template "^6.9.0" + babel-traverse "^6.10.4" + +babel-plugin-transform-async-to-generator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" + dependencies: + babel-helper-remap-async-to-generator "^6.24.1" + babel-plugin-syntax-async-functions "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-class-properties@^6.16.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac" + dependencies: + babel-helper-function-name "^6.24.1" + babel-plugin-syntax-class-properties "^6.8.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-arrow-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoping@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" + dependencies: + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-plugin-transform-es2015-classes@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" + dependencies: + babel-helper-define-map "^6.24.1" + babel-helper-function-name "^6.24.1" + babel-helper-optimise-call-expression "^6.24.1" + babel-helper-replace-supers "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-computed-properties@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-destructuring@^6.22.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-duplicate-keys@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-for-of@^6.22.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-function-name@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-modules-amd@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" + dependencies: + babel-plugin-transform-es2015-modules-commonjs "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-commonjs@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz#0d8394029b7dc6abe1a97ef181e00758dd2e5d8a" + dependencies: + babel-plugin-transform-strict-mode "^6.24.1" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-types "^6.26.0" + +babel-plugin-transform-es2015-modules-systemjs@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-umd@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" + dependencies: + babel-plugin-transform-es2015-modules-amd "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-object-super@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" + dependencies: + babel-helper-replace-supers "^6.24.1" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-parameters@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" + dependencies: + babel-helper-call-delegate "^6.24.1" + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-shorthand-properties@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-spread@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-sticky-regex@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-template-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-typeof-symbol@^6.22.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-unicode-regex@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + regexpu-core "^2.0.0" + +babel-plugin-transform-exponentiation-operator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" + dependencies: + babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" + babel-plugin-syntax-exponentiation-operator "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-flow-strip-types@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz#84cb672935d43714fdc32bce84568d87441cf7cf" + dependencies: + babel-plugin-syntax-flow "^6.18.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-object-rest-spread@^6.16.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06" + dependencies: + babel-plugin-syntax-object-rest-spread "^6.8.0" + babel-runtime "^6.26.0" + +babel-plugin-transform-react-display-name@^6.23.0: + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz#67e2bf1f1e9c93ab08db96792e05392bf2cc28d1" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-react-jsx-self@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz#df6d80a9da2612a121e6ddd7558bcbecf06e636e" + dependencies: + babel-plugin-syntax-jsx "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-react-jsx-source@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz#66ac12153f5cd2d17b3c19268f4bf0197f44ecd6" + dependencies: + babel-plugin-syntax-jsx "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-react-jsx@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz#840a028e7df460dfc3a2d29f0c0d91f6376e66a3" + dependencies: + babel-helper-builder-react-jsx "^6.24.1" + babel-plugin-syntax-jsx "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-regenerator@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" + dependencies: + regenerator-transform "^0.10.0" + +babel-plugin-transform-runtime@^6.15.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.23.0.tgz#88490d446502ea9b8e7efb0fe09ec4d99479b1ee" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-strict-mode@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-polyfill@^6.26.0, babel-polyfill@^6.5.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153" + dependencies: + babel-runtime "^6.26.0" + core-js "^2.5.0" + regenerator-runtime "^0.10.5" + +babel-preset-es2015@^6.14.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939" + dependencies: + babel-plugin-check-es2015-constants "^6.22.0" + babel-plugin-transform-es2015-arrow-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoping "^6.24.1" + babel-plugin-transform-es2015-classes "^6.24.1" + babel-plugin-transform-es2015-computed-properties "^6.24.1" + babel-plugin-transform-es2015-destructuring "^6.22.0" + babel-plugin-transform-es2015-duplicate-keys "^6.24.1" + babel-plugin-transform-es2015-for-of "^6.22.0" + babel-plugin-transform-es2015-function-name "^6.24.1" + babel-plugin-transform-es2015-literals "^6.22.0" + babel-plugin-transform-es2015-modules-amd "^6.24.1" + babel-plugin-transform-es2015-modules-commonjs "^6.24.1" + babel-plugin-transform-es2015-modules-systemjs "^6.24.1" + babel-plugin-transform-es2015-modules-umd "^6.24.1" + babel-plugin-transform-es2015-object-super "^6.24.1" + babel-plugin-transform-es2015-parameters "^6.24.1" + babel-plugin-transform-es2015-shorthand-properties "^6.24.1" + babel-plugin-transform-es2015-spread "^6.22.0" + babel-plugin-transform-es2015-sticky-regex "^6.24.1" + babel-plugin-transform-es2015-template-literals "^6.22.0" + babel-plugin-transform-es2015-typeof-symbol "^6.22.0" + babel-plugin-transform-es2015-unicode-regex "^6.24.1" + babel-plugin-transform-regenerator "^6.24.1" + +babel-preset-es2016@^6.11.3: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-preset-es2016/-/babel-preset-es2016-6.24.1.tgz#f900bf93e2ebc0d276df9b8ab59724ebfd959f8b" + dependencies: + babel-plugin-transform-exponentiation-operator "^6.24.1" + +babel-preset-es2017@^6.14.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-preset-es2017/-/babel-preset-es2017-6.24.1.tgz#597beadfb9f7f208bcfd8a12e9b2b29b8b2f14d1" + dependencies: + babel-plugin-syntax-trailing-function-commas "^6.22.0" + babel-plugin-transform-async-to-generator "^6.24.1" + +babel-preset-flow@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz#e71218887085ae9a24b5be4169affb599816c49d" + dependencies: + babel-plugin-transform-flow-strip-types "^6.22.0" + +babel-preset-react@^6.11.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-preset-react/-/babel-preset-react-6.24.1.tgz#ba69dfaea45fc3ec639b6a4ecea6e17702c91380" + dependencies: + babel-plugin-syntax-jsx "^6.3.13" + babel-plugin-transform-react-display-name "^6.23.0" + babel-plugin-transform-react-jsx "^6.24.1" + babel-plugin-transform-react-jsx-self "^6.22.0" + babel-plugin-transform-react-jsx-source "^6.22.0" + babel-preset-flow "^6.23.0" + +babel-register@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" + dependencies: + babel-core "^6.26.0" + babel-runtime "^6.26.0" + core-js "^2.5.0" + home-or-tmp "^2.0.0" + lodash "^4.17.4" + mkdirp "^0.5.1" + source-map-support "^0.4.15" + +babel-runtime@^6.11.6, babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babel-template@^6.24.1, babel-template@^6.26.0, babel-template@^6.9.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" + dependencies: + babel-runtime "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + lodash "^4.17.4" + +babel-traverse@^6.0.20, babel-traverse@^6.10.4, babel-traverse@^6.24.1, babel-traverse@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" + dependencies: + babel-code-frame "^6.26.0" + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + debug "^2.6.8" + globals "^9.18.0" + invariant "^2.2.2" + lodash "^4.17.4" + +babel-types@^6.0.19, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + +babylon@^6.0.18, babylon@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + +backo2@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + +base64-arraybuffer@0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8" + +base64-js@^1.0.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.3.tgz#fb13668233d9614cf5fb4bce95a9ba4096cdf801" + +base64id@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/base64id/-/base64id-1.0.0.tgz#47688cb99bb6804f0e06d3e763b1c32e57d8e6b6" + +bcrypt-pbkdf@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" + dependencies: + tweetnacl "^0.14.3" + +better-assert@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/better-assert/-/better-assert-1.0.2.tgz#40866b9e1b9e0b55b481894311e68faffaebc522" + dependencies: + callsite "1.0.0" + +big.js@^3.1.3: + version "3.2.0" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" + +binary-extensions@^1.0.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205" + +blob@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.4.tgz#bcf13052ca54463f30f9fc7e95b9a47630a94921" + +block-stream@*: + version "0.0.9" + resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" + dependencies: + inherits "~2.0.0" + +bluebird@^3.3.0, bluebird@^3.5.0: + version "3.5.1" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" + +blueimp-canvas-to-blob@^3.5.0: + version "3.14.0" + resolved "https://registry.yarnpkg.com/blueimp-canvas-to-blob/-/blueimp-canvas-to-blob-3.14.0.tgz#ea075ffbfb1436607b0c75e951fb1ceb3ca0288e" + +body-parser@^1.16.1: + version "1.18.2" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.2.tgz#87678a19d84b47d859b83199bd59bce222b10454" + dependencies: + bytes "3.0.0" + content-type "~1.0.4" + debug "2.6.9" + depd "~1.1.1" + http-errors "~1.6.2" + iconv-lite "0.4.19" + on-finished "~2.3.0" + qs "6.5.1" + raw-body "2.3.2" + type-is "~1.6.15" + +boom@2.x.x: + version "2.10.1" + resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" + dependencies: + hoek "2.x.x" + +boom@4.x.x: + version "4.3.1" + resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31" + dependencies: + hoek "4.x.x" + +boom@5.x.x: + version "5.2.0" + resolved "https://registry.yarnpkg.com/boom/-/boom-5.2.0.tgz#5dd9da6ee3a5f302077436290cb717d3f4a54e02" + dependencies: + hoek "4.x.x" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^0.1.2: + version "0.1.5" + resolved "https://registry.yarnpkg.com/braces/-/braces-0.1.5.tgz#c085711085291d8b75fdd74eab0f8597280711e6" + dependencies: + expand-range "^0.1.0" + +braces@^1.8.2: + version "1.8.5" + resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" + dependencies: + expand-range "^1.8.1" + preserve "^0.2.0" + repeat-element "^1.1.2" + +browser-encrypt-attachment@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/browser-encrypt-attachment/-/browser-encrypt-attachment-0.3.0.tgz#205a94caadf0dc7e81413941812f655bd190ff1c" + +browser-request@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/browser-request/-/browser-request-0.3.3.tgz#9ece5b5aca89a29932242e18bf933def9876cc17" + +browserify-aes@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-0.4.0.tgz#067149b668df31c4b58533e02d01e806d8608e2c" + dependencies: + inherits "^2.0.1" + +browserify-zlib@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz#bb35f8a519f600e0fa6b8485241c979d0141fb2d" + dependencies: + pako "~0.2.0" + +buffer@^4.9.0: + version "4.9.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + isarray "^1.0.0" + +builtin-status-codes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + +caller-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" + dependencies: + callsites "^0.2.0" + +callsite@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20" + +callsites@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" + +camelcase@^1.0.2: + version "1.2.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + +center-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" + dependencies: + align-text "^0.1.3" + lazy-cache "^1.0.3" + +chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +"chalk@^1.1.3 || 2.x", chalk@^2.3.0, chalk@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65" + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chokidar@^1.0.0, chokidar@^1.4.1, chokidar@^1.6.1: + version "1.7.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" + dependencies: + anymatch "^1.3.0" + async-each "^1.0.0" + glob-parent "^2.0.0" + inherits "^2.0.1" + is-binary-path "^1.0.0" + is-glob "^2.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.0.0" + optionalDependencies: + fsevents "^1.0.0" + +circular-json@^0.3.1: + version "0.3.3" + resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" + +classnames@^2.1.2: + version "2.2.5" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d" + +cli-cursor@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" + dependencies: + restore-cursor "^1.0.1" + +cli-width@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" + +cliui@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" + dependencies: + center-align "^0.1.1" + right-align "^0.1.1" + wordwrap "0.0.2" + +clone@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.3.tgz#298d7e2231660f40c003c2ed3140decf3f53085f" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + +color-convert@^1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" + dependencies: + color-name "^1.1.1" + +color-name@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + +colors@^1.1.0, colors@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" + +combine-lists@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/combine-lists/-/combine-lists-1.0.1.tgz#458c07e09e0d900fc28b70a3fec2dacd1d2cb7f6" + dependencies: + lodash "^4.5.0" + +combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" + dependencies: + delayed-stream "~1.0.0" + +commander@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-0.6.1.tgz#fa68a14f6a945d54dbbe50d8cdb3320e9e3b1a06" + +commander@2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.3.0.tgz#fd430e889832ec353b9acd1de217c11cb3eef873" + +commander@^2.11.0: + version "2.14.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.14.1.tgz#2235123e37af8ca3c65df45b026dbd357b01b9aa" + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + +commonmark@^0.28.1: + version "0.28.1" + resolved "https://registry.yarnpkg.com/commonmark/-/commonmark-0.28.1.tgz#06eab8d52338b839fa1a2d75af0085eed1b1beae" + dependencies: + entities "~ 1.1.1" + mdurl "~ 1.0.1" + minimist "~ 1.2.0" + string.prototype.repeat "^0.2.0" + +component-bind@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1" + +component-emitter@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.1.2.tgz#296594f2753daa63996d2af08d15a95116c9aec3" + +component-emitter@1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" + +component-inherit@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +concat-stream@^1.5.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.1.tgz#261b8f518301f1d834e36342b9fea095d2620a26" + dependencies: + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +connect@^3.6.0: + version "3.6.6" + resolved "https://registry.yarnpkg.com/connect/-/connect-3.6.6.tgz#09eff6c55af7236e137135a72574858b6786f524" + dependencies: + debug "2.6.9" + finalhandler "1.1.0" + parseurl "~1.3.2" + utils-merge "1.0.1" + +console-browserify@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" + dependencies: + date-now "^0.1.4" + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + +constants-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + +content-type@^1.0.2, content-type@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + +convert-source-map@^1.5.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" + +cookie@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" + +core-js@^1.0.0: + version "1.2.7" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" + +core-js@^2.2.0, core-js@^2.4.0, core-js@^2.5.0: + version "2.5.3" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e" + +core-util-is@1.0.2, core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +counterpart@^0.18.0: + version "0.18.6" + resolved "https://registry.yarnpkg.com/counterpart/-/counterpart-0.18.6.tgz#cf6b60d8ef99a4b44b8bf6445fa99b4bd1b2f9dd" + dependencies: + date-names "^0.1.11" + except "^0.1.3" + extend "^3.0.0" + pluralizers "^0.1.7" + sprintf-js "^1.0.3" + +create-react-class@^15.6.0: + version "15.6.3" + resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.6.3.tgz#2d73237fb3f970ae6ebe011a9e66f46dbca80036" + dependencies: + fbjs "^0.8.9" + loose-envify "^1.3.1" + object-assign "^4.1.1" + +cryptiles@2.x.x: + version "2.0.5" + resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" + dependencies: + boom "2.x.x" + +cryptiles@3.x.x: + version "3.1.2" + resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-3.1.2.tgz#a89fbb220f5ce25ec56e8c4aa8a4fd7b5b0d29fe" + dependencies: + boom "5.x.x" + +crypto-browserify@3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.3.0.tgz#b9fc75bb4a0ed61dcf1cd5dae96eb30c9c3e506c" + dependencies: + browserify-aes "0.4.0" + pbkdf2-compat "2.0.1" + ripemd160 "0.2.0" + sha.js "2.2.6" + +custom-event@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" + +d@1: + version "1.0.0" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" + dependencies: + es5-ext "^0.10.9" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + dependencies: + assert-plus "^1.0.0" + +date-names@^0.1.11: + version "0.1.12" + resolved "https://registry.yarnpkg.com/date-names/-/date-names-0.1.12.tgz#e60fe316de1547c9d9e7f14bd350130e4b7f9ef8" + +date-now@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" + +debug@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" + dependencies: + ms "0.7.1" + +debug@2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.3.3.tgz#40c453e67e6e13c901ddec317af8986cda9eff8c" + dependencies: + ms "0.7.2" + +debug@2.6.9, debug@^2.1.1, debug@^2.2.0, debug@^2.6.8: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + dependencies: + ms "2.0.0" + +decamelize@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + +deep-extend@~0.4.0: + version "0.4.2" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" + +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + +define-properties@^1.1.2, define-properties@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" + dependencies: + foreach "^2.0.5" + object-keys "^1.0.8" + +del@^2.0.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" + dependencies: + globby "^5.0.0" + is-path-cwd "^1.0.0" + is-path-in-cwd "^1.0.0" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + rimraf "^2.2.8" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + +depd@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359" + +depd@~1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + +detect-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" + dependencies: + repeating "^2.0.0" + +detect-libc@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + +di@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" + +diff@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf" + +doctrine@^2.0.0, doctrine@^2.0.2: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + dependencies: + esutils "^2.0.2" + +dom-serialize@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b" + dependencies: + custom-event "~1.0.0" + ent "~2.2.0" + extend "^3.0.0" + void-elements "^2.0.0" + +dom-serializer@0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" + dependencies: + domelementtype "~1.1.1" + entities "~1.1.1" + +domain-browser@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" + +domelementtype@1, domelementtype@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" + +domelementtype@~1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" + +domhandler@^2.3.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.1.tgz#892e47000a99be55bbf3774ffea0561d8879c259" + dependencies: + domelementtype "1" + +domutils@^1.5.1: + version "1.7.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" + dependencies: + dom-serializer "0" + domelementtype "1" + +draft-js-export-html@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/draft-js-export-html/-/draft-js-export-html-0.6.0.tgz#cc80f0544c43d0a7fedbc53c0cb0914e8090f769" + dependencies: + draft-js-utils ">=0.2.0" + +draft-js-export-markdown@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/draft-js-export-markdown/-/draft-js-export-markdown-0.3.0.tgz#86390e03ceaf1d347fc616867ab7f535eb76bf42" + dependencies: + draft-js-utils ">=0.2.0" + +draft-js-utils@>=0.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/draft-js-utils/-/draft-js-utils-1.2.0.tgz#f5cb23eb167325ffed3d79882fdc317721d2fd12" + +draft-js@^0.11.0-alpha: + version "0.11.0-alpha" + resolved "https://registry.yarnpkg.com/draft-js/-/draft-js-0.11.0-alpha.tgz#32db2108f927e9b8446da1f79e4475c2b7f868ae" + dependencies: + fbjs "^0.8.12" + immutable "~3.7.4" + object-assign "^4.1.0" + +ecc-jsbn@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" + dependencies: + jsbn "~0.1.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + +emojione@2.2.7: + version "2.2.7" + resolved "https://registry.yarnpkg.com/emojione/-/emojione-2.2.7.tgz#46457cf6b9b2f8da13ae8a2e4e547de06ee15e96" + +emojis-list@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" + +encodeurl@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + +encoding@^0.1.11: + version "0.1.12" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" + dependencies: + iconv-lite "~0.4.13" + +engine.io-client@1.8.3: + version "1.8.3" + resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-1.8.3.tgz#1798ed93451246453d4c6f635d7a201fe940d5ab" + dependencies: + component-emitter "1.2.1" + component-inherit "0.0.3" + debug "2.3.3" + engine.io-parser "1.3.2" + has-cors "1.1.0" + indexof "0.0.1" + parsejson "0.0.3" + parseqs "0.0.5" + parseuri "0.0.5" + ws "1.1.2" + xmlhttprequest-ssl "1.5.3" + yeast "0.1.2" + +engine.io-parser@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-1.3.2.tgz#937b079f0007d0893ec56d46cb220b8cb435220a" + dependencies: + after "0.8.2" + arraybuffer.slice "0.0.6" + base64-arraybuffer "0.1.5" + blob "0.0.4" + has-binary "0.1.7" + wtf-8 "1.0.0" + +engine.io@1.8.3: + version "1.8.3" + resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-1.8.3.tgz#8de7f97895d20d39b85f88eeee777b2bd42b13d4" + dependencies: + accepts "1.3.3" + base64id "1.0.0" + cookie "0.3.1" + debug "2.3.3" + engine.io-parser "1.3.2" + ws "1.1.2" + +enhanced-resolve@~0.9.0: + version "0.9.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz#4d6e689b3725f86090927ccc86cd9f1635b89e2e" + dependencies: + graceful-fs "^4.1.2" + memory-fs "^0.2.0" + tapable "^0.1.8" + +ent@~2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" + +entities@^1.1.1, "entities@~ 1.1.1", entities@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" + +errno@^0.1.3: + version "0.1.7" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" + dependencies: + prr "~1.0.1" + +es-abstract@^1.6.1, es-abstract@^1.7.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.10.0.tgz#1ecb36c197842a00d8ee4c2dfd8646bb97d60864" + dependencies: + es-to-primitive "^1.1.1" + function-bind "^1.1.1" + has "^1.0.1" + is-callable "^1.1.3" + is-regex "^1.0.4" + +es-to-primitive@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d" + dependencies: + is-callable "^1.1.1" + is-date-object "^1.0.1" + is-symbol "^1.0.1" + +es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14: + version "0.10.39" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.39.tgz#fca21b67559277ca4ac1a1ed7048b107b6f76d87" + dependencies: + es6-iterator "~2.0.3" + es6-symbol "~3.1.1" + +es6-iterator@^2.0.1, es6-iterator@~2.0.1, es6-iterator@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-map@^0.1.3: + version "0.1.5" + resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" + dependencies: + d "1" + es5-ext "~0.10.14" + es6-iterator "~2.0.1" + es6-set "~0.1.5" + es6-symbol "~3.1.1" + event-emitter "~0.3.5" + +es6-set@~0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" + dependencies: + d "1" + es5-ext "~0.10.14" + es6-iterator "~2.0.1" + es6-symbol "3.1.1" + event-emitter "~0.3.5" + +es6-symbol@3.1.1, es6-symbol@^3.1.1, es6-symbol@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" + dependencies: + d "1" + es5-ext "~0.10.14" + +es6-weak-map@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f" + dependencies: + d "1" + es5-ext "^0.10.14" + es6-iterator "^2.0.1" + es6-symbol "^3.1.1" + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + +escape-string-regexp@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz#4dbc2fe674e71949caf3fb2695ce7f2dc1d9a8d1" + +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +escope@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" + dependencies: + es6-map "^0.1.3" + es6-weak-map "^2.0.1" + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-config-google@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/eslint-config-google/-/eslint-config-google-0.7.1.tgz#5598f8498e9e078420f34b80495b8d959f651fb2" + +eslint-plugin-babel@^4.0.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-babel/-/eslint-plugin-babel-4.1.2.tgz#79202a0e35757dd92780919b2336f1fa2fe53c1e" + +eslint-plugin-flowtype@^2.30.0: + version "2.46.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.46.1.tgz#c4f81d580cd89c82bc3a85a1ccf4ae3a915143a4" + dependencies: + lodash "^4.15.0" + +eslint-plugin-react@^7.4.0: + version "7.7.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.7.0.tgz#f606c719dbd8a1a2b3d25c16299813878cca0160" + dependencies: + doctrine "^2.0.2" + has "^1.0.1" + jsx-ast-utils "^2.0.1" + prop-types "^15.6.0" + +eslint@^3.13.1: + version "3.19.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.19.0.tgz#c8fc6201c7f40dd08941b87c085767386a679acc" + dependencies: + babel-code-frame "^6.16.0" + chalk "^1.1.3" + concat-stream "^1.5.2" + debug "^2.1.1" + doctrine "^2.0.0" + escope "^3.6.0" + espree "^3.4.0" + esquery "^1.0.0" + estraverse "^4.2.0" + esutils "^2.0.2" + file-entry-cache "^2.0.0" + glob "^7.0.3" + globals "^9.14.0" + ignore "^3.2.0" + imurmurhash "^0.1.4" + inquirer "^0.12.0" + is-my-json-valid "^2.10.0" + is-resolvable "^1.0.0" + js-yaml "^3.5.1" + json-stable-stringify "^1.0.0" + levn "^0.3.0" + lodash "^4.0.0" + mkdirp "^0.5.0" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.1" + pluralize "^1.2.1" + progress "^1.1.8" + require-uncached "^1.0.2" + shelljs "^0.7.5" + strip-bom "^3.0.0" + strip-json-comments "~2.0.1" + table "^3.7.8" + text-table "~0.2.0" + user-home "^2.0.0" + +espree@^3.4.0: + version "3.5.4" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" + dependencies: + acorn "^5.5.0" + acorn-jsx "^3.0.0" + +esprima@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" + +esquery@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.0.tgz#cfba8b57d7fba93f17298a8a006a04cda13d80fa" + dependencies: + estraverse "^4.0.0" + +esrecurse@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" + dependencies: + estraverse "^4.1.0" + +estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" + +estree-walker@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.5.1.tgz#64fc375053abc6f57d73e9bd2f004644ad3c5854" + +esutils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + +event-emitter@~0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + dependencies: + d "1" + es5-ext "~0.10.14" + +eventemitter3@1.x.x: + version "1.2.0" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.2.0.tgz#1c86991d816ad1e504750e73874224ecf3bec508" + +events@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" + +except@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/except/-/except-0.1.3.tgz#98261c91958551536b44482238e9783fb73d292a" + dependencies: + indexof "0.0.1" + +exit-hook@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" + +expand-braces@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/expand-braces/-/expand-braces-0.1.2.tgz#488b1d1d2451cb3d3a6b192cfc030f44c5855fea" + dependencies: + array-slice "^0.2.3" + array-unique "^0.2.1" + braces "^0.1.2" + +expand-brackets@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" + dependencies: + is-posix-bracket "^0.1.0" + +expand-range@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-0.1.1.tgz#4cb8eda0993ca56fa4f41fc42f3cbb4ccadff044" + dependencies: + is-number "^0.1.1" + repeat-string "^0.2.2" + +expand-range@^1.8.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" + dependencies: + fill-range "^2.1.0" + +expect@^1.16.0: + version "1.20.2" + resolved "https://registry.yarnpkg.com/expect/-/expect-1.20.2.tgz#d458fe4c56004036bae3232416a3f6361f04f965" + dependencies: + define-properties "~1.1.2" + has "^1.0.1" + is-equal "^1.5.1" + is-regex "^1.0.3" + object-inspect "^1.1.0" + object-keys "^1.0.9" + tmatch "^2.0.1" + +extend@^3.0.0, extend@~3.0.0, extend@~3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" + +extglob@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" + dependencies: + is-extglob "^1.0.0" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + +fast-deep-equal@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + +fast-levenshtein@~2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + +fbemitter@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/fbemitter/-/fbemitter-2.1.1.tgz#523e14fdaf5248805bb02f62efc33be703f51865" + dependencies: + fbjs "^0.8.4" + +fbjs@0.1.0-alpha.7: + version "0.1.0-alpha.7" + resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.1.0-alpha.7.tgz#ad4308b8f232fb3c73603349ea725d1e9c39323c" + dependencies: + core-js "^1.0.0" + promise "^7.0.3" + whatwg-fetch "^0.9.0" + +fbjs@^0.8.12, fbjs@^0.8.16, fbjs@^0.8.4, fbjs@^0.8.9: + version "0.8.16" + resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db" + dependencies: + core-js "^1.0.0" + isomorphic-fetch "^2.1.1" + loose-envify "^1.0.0" + object-assign "^4.1.0" + promise "^7.1.1" + setimmediate "^1.0.5" + ua-parser-js "^0.7.9" + +figures@^1.3.5: + version "1.7.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" + dependencies: + escape-string-regexp "^1.0.5" + object-assign "^4.1.0" + +file-entry-cache@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" + dependencies: + flat-cache "^1.2.1" + object-assign "^4.0.1" + +file-saver@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-1.3.3.tgz#cdd4c44d3aa264eac2f68ec165bc791c34af1232" + +filename-regex@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" + +filesize@3.5.6: + version "3.5.6" + resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.5.6.tgz#5fd98f3eac94ec9516ef8ed5782fad84a01a0a1a" + +fill-range@^2.1.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" + dependencies: + is-number "^2.1.0" + isobject "^2.0.0" + randomatic "^1.1.3" + repeat-element "^1.1.2" + repeat-string "^1.5.2" + +finalhandler@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.0.tgz#ce0b6855b45853e791b2fcc680046d88253dd7f5" + dependencies: + debug "2.6.9" + encodeurl "~1.0.1" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.2" + statuses "~1.3.1" + unpipe "~1.0.0" + +find-cache-dir@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9" + dependencies: + commondir "^1.0.1" + mkdirp "^0.5.1" + pkg-dir "^1.0.0" + +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + +flat-cache@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" + dependencies: + circular-json "^0.3.1" + del "^2.0.2" + graceful-fs "^4.1.2" + write "^0.2.1" + +flow-parser@^0.57.3: + version "0.57.3" + resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.57.3.tgz#b8d241a1b1cbae043afa7976e39f269988d8fe34" + +flux@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/flux/-/flux-2.1.1.tgz#2c6ac652d4337488968489c6586f3aff26a38ea4" + dependencies: + fbemitter "^2.0.0" + fbjs "0.1.0-alpha.7" + immutable "^3.7.4" + +for-in@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + +for-own@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" + dependencies: + for-in "^1.0.1" + +foreach@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" + +foreachasync@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/foreachasync/-/foreachasync-3.0.0.tgz#5502987dc8714be3392097f32e0071c9dee07cf6" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + +form-data@~2.1.1: + version "2.1.4" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.5" + mime-types "^2.1.12" + +form-data@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" + dependencies: + asynckit "^0.4.0" + combined-stream "1.0.6" + mime-types "^2.1.12" + +formatio@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.1.1.tgz#5ed3ccd636551097383465d996199100e86161e9" + dependencies: + samsam "~1.1" + +fs-access@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fs-access/-/fs-access-1.0.1.tgz#d6a87f262271cefebec30c553407fb995da8777a" + dependencies: + null-check "^1.0.0" + +fs-readdir-recursive@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +fsevents@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.1.3.tgz#11f82318f5fe7bb2cd22965a108e9306208216d8" + dependencies: + nan "^2.3.0" + node-pre-gyp "^0.6.39" + +fstream-ignore@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105" + dependencies: + fstream "^1.0.0" + inherits "2" + minimatch "^3.0.0" + +fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2: + version "1.0.11" + resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" + dependencies: + graceful-fs "^4.1.2" + inherits "~2.0.0" + mkdirp ">=0.5 0" + rimraf "2" + +function-bind@^1.0.2, function-bind@^1.1.0, function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + +fuse.js@^2.2.0: + version "2.7.4" + resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-2.7.4.tgz#96e420fde7ef011ac49c258a621314fe576536f9" + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +gemini-scrollbar@matrix-org/gemini-scrollbar#b302279: + version "1.4.3" + resolved "https://codeload.github.com/matrix-org/gemini-scrollbar/tar.gz/b302279810d05319ac5ff1bd34910bff32325c7b" + +generate-function@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" + +generate-object-property@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" + dependencies: + is-property "^1.0.0" + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + dependencies: + assert-plus "^1.0.0" + +glob-base@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" + dependencies: + glob-parent "^2.0.0" + is-glob "^2.0.0" + +glob-parent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" + dependencies: + is-glob "^2.0.0" + +glob@3.2.11: + version "3.2.11" + resolved "https://registry.yarnpkg.com/glob/-/glob-3.2.11.tgz#4a973f635b9190f715d10987d5c00fd2815ebe3d" + dependencies: + inherits "2" + minimatch "0.3" + +glob@^5.0.14: + version "5.0.15" + resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^9.14.0, globals@^9.18.0: + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + +globby@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" + dependencies: + array-union "^1.0.1" + arrify "^1.0.0" + glob "^7.0.3" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +graceful-fs@^4.1.2, graceful-fs@^4.1.4: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + +growl@1.9.2: + version "1.9.2" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" + +har-schema@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + +har-validator@~4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" + dependencies: + ajv "^4.9.1" + har-schema "^1.0.5" + +har-validator@~5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" + dependencies: + ajv "^5.1.0" + har-schema "^2.0.0" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + dependencies: + ansi-regex "^2.0.0" + +has-binary@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/has-binary/-/has-binary-0.1.7.tgz#68e61eb16210c9545a0a5cce06a873912fe1e68c" + dependencies: + isarray "0.0.1" + +has-cors@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39" + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + +has@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" + dependencies: + function-bind "^1.0.2" + +hawk@3.1.3, hawk@~3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" + dependencies: + boom "2.x.x" + cryptiles "2.x.x" + hoek "2.x.x" + sntp "1.x.x" + +hawk@~6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/hawk/-/hawk-6.0.2.tgz#af4d914eb065f9b5ce4d9d11c1cb2126eecc3038" + dependencies: + boom "4.x.x" + cryptiles "3.x.x" + hoek "4.x.x" + sntp "2.x.x" + +highlight.js@^8.9.1: + version "8.9.1" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-8.9.1.tgz#b8a9c5493212a9392f0222b649c9611497ebfb88" + +hoek@2.x.x: + version "2.16.3" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" + +hoek@4.x.x: + version "4.2.1" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb" + +hoist-non-react-statics@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.0.tgz#d2ca2dfc19c5a91c5a6615ce8e564ef0347e2a40" + +home-or-tmp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.1" + +htmlparser2@^3.9.0: + version "3.9.2" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338" + dependencies: + domelementtype "^1.3.0" + domhandler "^2.3.0" + domutils "^1.5.1" + entities "^1.1.1" + inherits "^2.0.1" + readable-stream "^2.0.2" + +http-errors@1.6.2, http-errors@~1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736" + dependencies: + depd "1.1.1" + inherits "2.0.3" + setprototypeof "1.0.3" + statuses ">= 1.3.1 < 2" + +http-proxy@^1.13.0: + version "1.16.2" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.16.2.tgz#06dff292952bf64dbe8471fa9df73066d4f37742" + dependencies: + eventemitter3 "1.x.x" + requires-port "1.x.x" + +http-signature@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" + dependencies: + assert-plus "^0.2.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +https-browserify@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.1.tgz#3f91365cabe60b77ed0ebba24b454e3e09d95a82" + +iconv-lite@0.4.19, iconv-lite@~0.4.13: + version "0.4.19" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" + +ieee754@^1.1.4: + version "1.1.8" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4" + +ignore@^3.2.0: + version "3.3.7" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021" + +immutable@^3.7.4: + version "3.8.2" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.8.2.tgz#c2439951455bb39913daf281376f1530e104adf3" + +immutable@~3.7.4: + version "3.7.6" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.7.6.tgz#13b4d3cb12befa15482a26fe1b2ebae640071e4b" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + +indexof@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +inherits@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + +ini@~1.3.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + +inquirer@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" + dependencies: + ansi-escapes "^1.1.0" + ansi-regex "^2.0.0" + chalk "^1.0.0" + cli-cursor "^1.0.1" + cli-width "^2.0.0" + figures "^1.3.5" + lodash "^4.3.0" + readline2 "^1.0.1" + run-async "^0.1.0" + rx-lite "^3.1.2" + string-width "^1.0.1" + strip-ansi "^3.0.0" + through "^2.3.6" + +interpret@^0.6.4: + version "0.6.6" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-0.6.6.tgz#fecd7a18e7ce5ca6abfb953e1f86213a49f1625b" + +interpret@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" + +invariant@^2.0.0, invariant@^2.2.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.3.tgz#1a827dfde7dcbd7c323f0ca826be8fa7c5e9d688" + dependencies: + loose-envify "^1.0.0" + +is-arrow-function@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-arrow-function/-/is-arrow-function-2.0.3.tgz#29be2c2d8d9450852b8bbafb635ba7b8d8e87ec2" + dependencies: + is-callable "^1.0.4" + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + dependencies: + binary-extensions "^1.0.0" + +is-boolean-object@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.0.0.tgz#98f8b28030684219a95f375cfbd88ce3405dff93" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + +is-callable@^1.0.4, is-callable@^1.1.1, is-callable@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2" + +is-date-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + +is-dotfile@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" + +is-equal-shallow@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" + dependencies: + is-primitive "^2.0.0" + +is-equal@^1.5.1: + version "1.5.5" + resolved "https://registry.yarnpkg.com/is-equal/-/is-equal-1.5.5.tgz#5e85f1957e052883247feb386965a3bba15fbb3d" + dependencies: + has "^1.0.1" + is-arrow-function "^2.0.3" + is-boolean-object "^1.0.0" + is-callable "^1.1.3" + is-date-object "^1.0.1" + is-generator-function "^1.0.6" + is-number-object "^1.0.3" + is-regex "^1.0.3" + is-string "^1.0.4" + is-symbol "^1.0.1" + object.entries "^1.0.4" + +is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + +is-extglob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" + +is-finite@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + +is-generator-function@^1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.7.tgz#d2132e529bb0000a7f80794d4bdf5cd5e5813522" + +is-glob@^2.0.0, is-glob@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" + dependencies: + is-extglob "^1.0.0" + +is-my-ip-valid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz#7b351b8e8edd4d3995d4d066680e664d94696824" + +is-my-json-valid@^2.10.0: + version "2.17.2" + resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz#6b2103a288e94ef3de5cf15d29dd85fc4b78d65c" + dependencies: + generate-function "^2.0.0" + generate-object-property "^1.1.0" + is-my-ip-valid "^1.0.0" + jsonpointer "^4.0.0" + xtend "^4.0.0" + +is-number-object@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.3.tgz#f265ab89a9f445034ef6aff15a8f00b00f551799" + +is-number@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-0.1.1.tgz#69a7af116963d47206ec9bd9b48a14216f1e3806" + +is-number@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" + dependencies: + kind-of "^3.0.2" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + dependencies: + kind-of "^3.0.2" + +is-path-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" + +is-path-in-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc" + dependencies: + is-path-inside "^1.0.0" + +is-path-inside@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" + dependencies: + path-is-inside "^1.0.1" + +is-posix-bracket@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" + +is-primitive@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" + +is-property@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" + +is-regex@^1.0.3, is-regex@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + dependencies: + has "^1.0.1" + +is-resolvable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" + +is-stream@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + +is-string@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.4.tgz#cc3a9b69857d621e963725a24caeec873b826e64" + +is-symbol@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + +isbinaryfile@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.2.tgz#4a3e974ec0cba9004d3fc6cde7209ea69368a621" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + dependencies: + isarray "1.0.0" + +isomorphic-fetch@^2.1.1, isomorphic-fetch@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" + dependencies: + node-fetch "^1.0.1" + whatwg-fetch ">=0.10.0" + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + +jade@0.26.3: + version "0.26.3" + resolved "https://registry.yarnpkg.com/jade/-/jade-0.26.3.tgz#8f10d7977d8d79f2f6ff862a81b0513ccb25686c" + dependencies: + commander "0.6.1" + mkdirp "0.3.0" + +"jquery@>= 1.4.3", jquery@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca" + +js-tokens@^3.0.0, js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + +js-yaml@^3.5.1: + version "3.11.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.11.0.tgz#597c1a8bd57152f26d622ce4117851a51f5ebaef" + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + +jsesc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + +json-loader@^0.5.3: + version "0.5.7" + resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d" + +json-schema-traverse@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + +json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + dependencies: + jsonify "~0.0.0" + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + +json3@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" + +json5@^0.5.0, json5@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + +jsonpointer@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +jsx-ast-utils@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz#e801b1b39985e20fffc87b40e3748080e2dcac7f" + dependencies: + array-includes "^3.0.3" + +karma-chrome-launcher@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/karma-chrome-launcher/-/karma-chrome-launcher-0.2.3.tgz#4c6d700d163a9d34c618efd87918be49e7a4a8c9" + dependencies: + fs-access "^1.0.0" + which "^1.2.1" + +karma-cli@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/karma-cli/-/karma-cli-0.1.2.tgz#cacea84371ece19876265c8fa102ebbb9fee4a8c" + dependencies: + resolve "^1.1.6" + +karma-junit-reporter@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/karma-junit-reporter/-/karma-junit-reporter-0.4.2.tgz#492a236728fe4c92aacf419fcd0110a4327e9d7f" + dependencies: + path-is-absolute "^1.0.0" + xmlbuilder "3.1.0" + +karma-logcapture-reporter@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/karma-logcapture-reporter/-/karma-logcapture-reporter-0.0.1.tgz#bf1b0b1c915e0de295a15fe2f0179d4281bacddc" + +karma-mocha@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/karma-mocha/-/karma-mocha-0.2.2.tgz#388ed917da15dcb196d1b915c1934ef803193f8e" + +karma-sourcemap-loader@^0.3.7: + version "0.3.7" + resolved "https://registry.yarnpkg.com/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz#91322c77f8f13d46fed062b042e1009d4c4505d8" + dependencies: + graceful-fs "^4.1.2" + +karma-spec-reporter@^0.0.31: + version "0.0.31" + resolved "https://registry.yarnpkg.com/karma-spec-reporter/-/karma-spec-reporter-0.0.31.tgz#4830dc7148a155c7d7a186e632339a0d80fadec3" + dependencies: + colors "^1.1.2" + +karma-summary-reporter@^1.3.3: + version "1.5.0" + resolved "https://registry.yarnpkg.com/karma-summary-reporter/-/karma-summary-reporter-1.5.0.tgz#dc570299c7074774e388e10fa5f9e58f7a45ec14" + dependencies: + chalk "^1.1.3 || 2.x" + +karma-webpack@^1.7.0: + version "1.8.1" + resolved "https://registry.yarnpkg.com/karma-webpack/-/karma-webpack-1.8.1.tgz#39d5fd2edeea3cc3ef5b405989b37d5b0e6a3b4e" + dependencies: + async "~0.9.0" + loader-utils "^0.2.5" + lodash "^3.8.0" + source-map "^0.1.41" + webpack-dev-middleware "^1.0.11" + +karma@^1.7.0: + version "1.7.1" + resolved "https://registry.yarnpkg.com/karma/-/karma-1.7.1.tgz#85cc08e9e0a22d7ce9cca37c4a1be824f6a2b1ae" + dependencies: + bluebird "^3.3.0" + body-parser "^1.16.1" + chokidar "^1.4.1" + colors "^1.1.0" + combine-lists "^1.0.0" + connect "^3.6.0" + core-js "^2.2.0" + di "^0.0.1" + dom-serialize "^2.2.0" + expand-braces "^0.1.1" + glob "^7.1.1" + graceful-fs "^4.1.2" + http-proxy "^1.13.0" + isbinaryfile "^3.0.0" + lodash "^3.8.0" + log4js "^0.6.31" + mime "^1.3.4" + minimatch "^3.0.2" + optimist "^0.6.1" + qjobs "^1.1.4" + range-parser "^1.2.0" + rimraf "^2.6.0" + safe-buffer "^5.0.1" + socket.io "1.7.3" + source-map "^0.5.3" + tmp "0.0.31" + useragent "^2.1.12" + +kind-of@^3.0.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + dependencies: + is-buffer "^1.1.5" + +lazy-cache@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" + +levn@^0.3.0, levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +linkifyjs@^2.1.3: + version "2.1.6" + resolved "https://registry.yarnpkg.com/linkifyjs/-/linkifyjs-2.1.6.tgz#f1cc88a86ff8863196615857fd47eb193c0a26cb" + optionalDependencies: + jquery "^3.3.1" + react "^16.2.0" + react-dom "^16.2.0" + +loader-utils@^0.2.11, loader-utils@^0.2.16, loader-utils@^0.2.5, loader-utils@~0.2.2: + version "0.2.17" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" + dependencies: + big.js "^3.1.3" + emojis-list "^2.0.0" + json5 "^0.5.0" + object-assign "^4.0.1" + +lodash-es@^4.17.5, lodash-es@^4.2.1: + version "4.17.5" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.5.tgz#9fc6e737b1c4d151d8f9cae2247305d552ce748f" + +lodash.assign@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" + +lodash.clonedeep@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + +lodash.escaperegexp@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347" + +lodash.isplainobject@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + +lodash.mergewith@^4.6.0: + version "4.6.1" + resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz#639057e726c3afbdb3e7d42741caa8d6e4335927" + +lodash.pickby@^4.0.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.pickby/-/lodash.pickby-4.6.0.tgz#7dea21d8c18d7703a27c704c15d3b84a67e33aff" + +lodash@^3.5.0, lodash@^3.8.0: + version "3.10.1" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" + +lodash@^4.0.0, lodash@^4.13.1, lodash@^4.15.0, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.5.0: + version "4.17.5" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" + +log4js@^0.6.31: + version "0.6.38" + resolved "https://registry.yarnpkg.com/log4js/-/log4js-0.6.38.tgz#2c494116695d6fb25480943d3fc872e662a522fd" + dependencies: + readable-stream "~1.0.2" + semver "~4.3.3" + +lolex@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.3.2.tgz#7c3da62ffcb30f0f5a80a2566ca24e45d8a01f31" + +longest@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" + +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" + dependencies: + js-tokens "^3.0.0" + +lru-cache@2: + version "2.7.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952" + +lru-cache@4.1.x: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +matrix-js-sdk@0.9.2: + version "0.9.2" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-0.9.2.tgz#2a521bddcf637cbefde9138784e627ea43645b77" + dependencies: + another-json "^0.2.0" + babel-runtime "^6.26.0" + bluebird "^3.5.0" + browser-request "^0.3.3" + content-type "^1.0.2" + request "^2.53.0" + +matrix-react-test-utils@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/matrix-react-test-utils/-/matrix-react-test-utils-0.1.1.tgz#b548844d0ebe338ea1b9c8f16474c30d17c3bdf4" + dependencies: + react "^15.6.1" + react-dom "^15.6.1" + +"mdurl@~ 1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + +memoize-one@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-3.0.1.tgz#7b599850bb41be8beed305f4eefd963c8cea9a0a" + +memory-fs@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.2.0.tgz#f2bb25368bc121e391c2520de92969caee0a0290" + +memory-fs@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.3.0.tgz#7bcc6b629e3a43e871d7e29aca6ae8a7f15cbb20" + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +memory-fs@~0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +micromatch@^2.1.5: + version "2.3.11" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" + dependencies: + arr-diff "^2.0.0" + array-unique "^0.2.1" + braces "^1.8.2" + expand-brackets "^0.1.4" + extglob "^0.3.1" + filename-regex "^2.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.1" + kind-of "^3.0.2" + normalize-path "^2.0.1" + object.omit "^2.0.0" + parse-glob "^3.0.4" + regex-cache "^0.4.2" + +mime-db@~1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" + +mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.7: + version "2.1.18" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" + dependencies: + mime-db "~1.33.0" + +mime@^1.3.4, mime@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + +minimatch@0.3: + version "0.3.0" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.3.0.tgz#275d8edaac4f1bb3326472089e7949c8394699dd" + dependencies: + lru-cache "2" + sigmund "~1.0.0" + +"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +minimist@^1.2.0, "minimist@~ 1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + +minimist@~0.0.1: + version "0.0.10" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" + +mkdirp@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" + +mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +mocha@^2.4.5: + version "2.5.3" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-2.5.3.tgz#161be5bdeb496771eb9b35745050b622b5aefc58" + dependencies: + commander "2.3.0" + debug "2.2.0" + diff "1.4.0" + escape-string-regexp "1.0.2" + glob "3.2.11" + growl "1.9.2" + jade "0.26.3" + mkdirp "0.5.1" + supports-color "1.2.0" + to-iso-string "0.0.2" + +ms@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" + +ms@0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + +mute-stream@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0" + +nan@^2.3.0: + version "2.9.2" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.9.2.tgz#f564d75f5f8f36a6d9456cca7a6c4fe488ab7866" + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + +negotiator@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" + +node-fetch@^1.0.1: + version "1.7.3" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" + dependencies: + encoding "^0.1.11" + is-stream "^1.0.1" + +node-libs-browser@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-0.7.0.tgz#3e272c0819e308935e26674408d7af0e1491b83b" + dependencies: + assert "^1.1.1" + browserify-zlib "^0.1.4" + buffer "^4.9.0" + console-browserify "^1.1.0" + constants-browserify "^1.0.0" + crypto-browserify "3.3.0" + domain-browser "^1.1.1" + events "^1.0.0" + https-browserify "0.0.1" + os-browserify "^0.2.0" + path-browserify "0.0.0" + process "^0.11.0" + punycode "^1.2.4" + querystring-es3 "^0.2.0" + readable-stream "^2.0.5" + stream-browserify "^2.0.1" + stream-http "^2.3.1" + string_decoder "^0.10.25" + timers-browserify "^2.0.2" + tty-browserify "0.0.0" + url "^0.11.0" + util "^0.10.3" + vm-browserify "0.0.4" + +node-pre-gyp@^0.6.39: + version "0.6.39" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz#c00e96860b23c0e1420ac7befc5044e1d78d8649" + dependencies: + detect-libc "^1.0.2" + hawk "3.1.3" + mkdirp "^0.5.1" + nopt "^4.0.1" + npmlog "^4.0.2" + rc "^1.1.7" + request "2.81.0" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^2.2.1" + tar-pack "^3.4.0" + +nopt@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" + dependencies: + abbrev "1" + osenv "^0.1.4" + +normalize-path@^2.0.0, normalize-path@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + dependencies: + remove-trailing-separator "^1.0.1" + +npmlog@^4.0.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +null-check@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/null-check/-/null-check-1.0.0.tgz#977dffd7176012b9ec30d2a39db5cf72a0439edd" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + +oauth-sign@~0.8.1, oauth-sign@~0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" + +object-assign@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0" + +object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + +object-component@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291" + +object-inspect@^1.1.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.5.0.tgz#9d876c11e40f485c79215670281b767488f9bfe3" + +object-keys@^1.0.8, object-keys@^1.0.9: + version "1.0.11" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d" + +object.entries@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.0.4.tgz#1bf9a4dd2288f5b33f3a993d257661f05d161a5f" + dependencies: + define-properties "^1.1.2" + es-abstract "^1.6.1" + function-bind "^1.1.0" + has "^1.0.1" + +object.omit@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" + dependencies: + for-own "^0.1.4" + is-extendable "^0.1.1" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + dependencies: + ee-first "1.1.1" + +once@^1.3.0, once@^1.3.3: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +onetime@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" + +optimist@^0.6.1, optimist@~0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" + dependencies: + minimist "~0.0.1" + wordwrap "~0.0.2" + +optionator@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.4" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + wordwrap "~1.0.0" + +options@>=0.0.5: + version "0.0.6" + resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f" + +os-browserify@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.2.1.tgz#63fc4ccee5d2d7763d26bbf8601078e6c2e0044f" + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + +os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + +osenv@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +output-file-sync@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/output-file-sync/-/output-file-sync-1.1.2.tgz#d0a33eefe61a205facb90092e826598d5245ce76" + dependencies: + graceful-fs "^4.1.4" + mkdirp "^0.5.1" + object-assign "^4.1.0" + +pako@~0.2.0: + version "0.2.9" + resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" + +parallelshell@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/parallelshell/-/parallelshell-3.0.2.tgz#fffc55aaa145bdd44b5381cf7fd5e521fc21aa7b" + +parse-glob@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" + dependencies: + glob-base "^0.3.0" + is-dotfile "^1.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.0" + +parsejson@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/parsejson/-/parsejson-0.0.3.tgz#ab7e3759f209ece99437973f7d0f1f64ae0e64ab" + dependencies: + better-assert "~1.0.0" + +parseqs@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d" + dependencies: + better-assert "~1.0.0" + +parseuri@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.5.tgz#80204a50d4dbb779bfdc6ebe2778d90e4bce320a" + dependencies: + better-assert "~1.0.0" + +parseurl@~1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" + +path-browserify@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" + +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + dependencies: + pinkie-promise "^2.0.0" + +path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +path-is-inside@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + +path-parse@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" + +pbkdf2-compat@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pbkdf2-compat/-/pbkdf2-compat-2.0.1.tgz#b6e0c8fa99494d94e0511575802a59a5c142f288" + +performance-now@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + +pkg-dir@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" + dependencies: + find-up "^1.0.0" + +pluralize@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" + +pluralizers@^0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/pluralizers/-/pluralizers-0.1.7.tgz#8d38dd0a1b660e739b10ab2eab10b684c9d50142" + +postcss@^6.0.14: + version "6.0.19" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.19.tgz#76a78386f670b9d9494a655bf23ac012effd1555" + dependencies: + chalk "^2.3.1" + source-map "^0.6.1" + supports-color "^5.2.0" + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + +preserve@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" + +private@^0.1.6, private@^0.1.7: + version "0.1.8" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + +process-nextick-args@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" + +process@^0.11.0: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + +progress@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" + +promise@^7.0.3, promise@^7.1.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" + dependencies: + asap "~2.0.3" + +prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0: + version "15.6.1" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.1.tgz#36644453564255ddda391191fb3a125cbdf654ca" + dependencies: + fbjs "^0.8.16" + loose-envify "^1.3.1" + object-assign "^4.1.1" + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + +punycode@^1.2.4, punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + +qjobs@^1.1.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.2.0.tgz#c45e9c61800bd087ef88d7e256423bdd49e5d071" + +qs@6.5.1, qs@~6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" + +qs@~6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" + +querystring-es3@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" + +querystring@0.2.0, querystring@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + +raf-schd@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/raf-schd/-/raf-schd-2.1.0.tgz#64d645723380ec25cc1714e909b953ef1cf254bf" + +raf@^3.1.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.0.tgz#a28876881b4bc2ca9117d4138163ddb80f781575" + dependencies: + performance-now "^2.1.0" + +randomatic@^1.1.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +range-parser@^1.0.3, range-parser@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" + +raw-body@2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89" + dependencies: + bytes "3.0.0" + http-errors "1.6.2" + iconv-lite "0.4.19" + unpipe "1.0.0" + +rc@^1.1.7: + version "1.2.5" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.5.tgz#275cd687f6e3b36cc756baa26dfee80a790301fd" + dependencies: + deep-extend "~0.4.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +react-addons-css-transition-group@15.3.2: + version "15.3.2" + resolved "https://registry.yarnpkg.com/react-addons-css-transition-group/-/react-addons-css-transition-group-15.3.2.tgz#d8fa52bec9bb61bdfde8b9e4652b80297cbff667" + +react-addons-test-utils@^15.4.0: + version "15.6.2" + resolved "https://registry.yarnpkg.com/react-addons-test-utils/-/react-addons-test-utils-15.6.2.tgz#c12b6efdc2247c10da7b8770d185080a7b047156" + +react-beautiful-dnd@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/react-beautiful-dnd/-/react-beautiful-dnd-4.0.1.tgz#3b0a49bf6be75af351176c904f012611dd292b81" + dependencies: + babel-runtime "^6.26.0" + invariant "^2.2.2" + memoize-one "^3.0.1" + prop-types "^15.6.0" + raf-schd "^2.1.0" + react-motion "^0.5.2" + react-redux "^5.0.6" + redux "^3.7.2" + redux-thunk "^2.2.0" + reselect "^3.0.1" + +react-dom@^15.4.0, react-dom@^15.6.1: + version "15.6.2" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-15.6.2.tgz#41cfadf693b757faf2708443a1d1fd5a02bef730" + dependencies: + fbjs "^0.8.9" + loose-envify "^1.1.0" + object-assign "^4.1.0" + prop-types "^15.5.10" + +react-dom@^16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.2.0.tgz#69003178601c0ca19b709b33a83369fe6124c044" + dependencies: + fbjs "^0.8.16" + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.0" + +react-gemini-scrollbar@matrix-org/react-gemini-scrollbar#5e97aef: + version "2.1.5" + resolved "https://codeload.github.com/matrix-org/react-gemini-scrollbar/tar.gz/5e97aef7e034efc8db1431f4b0efe3b26e249ae9" + dependencies: + gemini-scrollbar matrix-org/gemini-scrollbar#b302279 + +react-motion@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/react-motion/-/react-motion-0.5.2.tgz#0dd3a69e411316567927917c6626551ba0607316" + dependencies: + performance-now "^0.2.0" + prop-types "^15.5.8" + raf "^3.1.0" + +react-redux@^5.0.6: + version "5.0.7" + resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.7.tgz#0dc1076d9afb4670f993ffaef44b8f8c1155a4c8" + dependencies: + hoist-non-react-statics "^2.5.0" + invariant "^2.0.0" + lodash "^4.17.5" + lodash-es "^4.17.5" + loose-envify "^1.1.0" + prop-types "^15.6.0" + +react@^15.4.0, react@^15.6.1: + version "15.6.2" + resolved "https://registry.yarnpkg.com/react/-/react-15.6.2.tgz#dba0434ab439cfe82f108f0f511663908179aa72" + dependencies: + create-react-class "^15.6.0" + fbjs "^0.8.9" + loose-envify "^1.1.0" + object-assign "^4.1.0" + prop-types "^15.5.10" + +react@^16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/react/-/react-16.2.0.tgz#a31bd2dab89bff65d42134fa187f24d054c273ba" + dependencies: + fbjs "^0.8.16" + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.0" + +readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.2.2, readable-stream@^2.3.3: + version "2.3.5" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.5.tgz#b4f85003a938cbb6ecbce2a124fb1012bd1a838d" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.0.3" + util-deprecate "~1.0.1" + +readable-stream@~1.0.2: + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readdirp@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78" + dependencies: + graceful-fs "^4.1.2" + minimatch "^3.0.2" + readable-stream "^2.0.2" + set-immediate-shim "^1.0.1" + +readline2@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + mute-stream "0.0.5" + +rechoir@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + dependencies: + resolve "^1.1.6" + +redux-thunk@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.2.0.tgz#e615a16e16b47a19a515766133d1e3e99b7852e5" + +redux@^3.7.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/redux/-/redux-3.7.2.tgz#06b73123215901d25d065be342eb026bc1c8537b" + dependencies: + lodash "^4.2.1" + lodash-es "^4.2.1" + loose-envify "^1.1.0" + symbol-observable "^1.0.3" + +regenerate@^1.2.1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.3.tgz#0c336d3980553d755c39b586ae3b20aa49c82b7f" + +regenerator-runtime@^0.10.5: + version "0.10.5" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + +regenerator-transform@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" + dependencies: + babel-runtime "^6.18.0" + babel-types "^6.19.0" + private "^0.1.6" + +regex-cache@^0.4.2: + version "0.4.4" + resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" + dependencies: + is-equal-shallow "^0.1.3" + +regexpu-core@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" + dependencies: + regenerate "^1.2.1" + regjsgen "^0.2.0" + regjsparser "^0.1.4" + +regjsgen@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" + +regjsparser@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" + dependencies: + jsesc "~0.5.0" + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + +repeat-element@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" + +repeat-string@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-0.2.2.tgz#c7a8d3236068362059a7e4651fc6884e8b1fb4ae" + +repeat-string@^1.5.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + dependencies: + is-finite "^1.0.0" + +request@2.81.0: + version "2.81.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" + dependencies: + aws-sign2 "~0.6.0" + aws4 "^1.2.1" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.0" + forever-agent "~0.6.1" + form-data "~2.1.1" + har-validator "~4.2.1" + hawk "~3.1.3" + http-signature "~1.1.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.7" + oauth-sign "~0.8.1" + performance-now "^0.2.0" + qs "~6.4.0" + safe-buffer "^5.0.1" + stringstream "~0.0.4" + tough-cookie "~2.3.0" + tunnel-agent "^0.6.0" + uuid "^3.0.0" + +request@^2.53.0: + version "2.83.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.6.0" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.1" + forever-agent "~0.6.1" + form-data "~2.3.1" + har-validator "~5.0.3" + hawk "~6.0.2" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.17" + oauth-sign "~0.8.2" + performance-now "^2.1.0" + qs "~6.5.1" + safe-buffer "^5.1.1" + stringstream "~0.0.5" + tough-cookie "~2.3.3" + tunnel-agent "^0.6.0" + uuid "^3.1.0" + +require-json@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/require-json/-/require-json-0.0.1.tgz#3c8914f93d7442de8cbf4e681ac62a72aa3367fe" + +require-uncached@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" + dependencies: + caller-path "^0.1.0" + resolve-from "^1.0.0" + +requires-port@1.x.x: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + +reselect@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/reselect/-/reselect-3.0.1.tgz#efdaa98ea7451324d092b2b2163a6a1d7a9a2147" + +resolve-from@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" + +resolve@^1.1.6: + version "1.5.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" + dependencies: + path-parse "^1.0.5" + +restore-cursor@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" + dependencies: + exit-hook "^1.0.0" + onetime "^1.0.0" + +right-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" + dependencies: + align-text "^0.1.1" + +rimraf@2, rimraf@^2.2.8, rimraf@^2.4.3, rimraf@^2.5.1, rimraf@^2.6.0, rimraf@^2.6.1: + version "2.6.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" + dependencies: + glob "^7.0.5" + +ripemd160@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-0.2.0.tgz#2bf198bde167cacfa51c0a928e84b68bbe171fce" + +run-async@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389" + dependencies: + once "^1.3.0" + +rx-lite@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" + +safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" + +samsam@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.2.tgz#bec11fdc83a9fda063401210e40176c3024d1567" + +samsam@~1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.3.tgz#9f5087419b4d091f232571e7fa52e90b0f552621" + +sanitize-html@^1.14.1: + version "1.18.2" + resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-1.18.2.tgz#61877ba5a910327e42880a28803c2fbafa8e4642" + dependencies: + chalk "^2.3.0" + htmlparser2 "^3.9.0" + lodash.clonedeep "^4.5.0" + lodash.escaperegexp "^4.1.2" + lodash.isplainobject "^4.0.6" + lodash.isstring "^4.0.1" + lodash.mergewith "^4.6.0" + postcss "^6.0.14" + srcset "^1.0.0" + xtend "^4.0.0" + +semver@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" + +semver@~4.3.3: + version "4.3.6" + resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" + +set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + +set-immediate-shim@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" + +setimmediate@^1.0.4, setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + +setprototypeof@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04" + +sha.js@2.2.6: + version "2.2.6" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.2.6.tgz#17ddeddc5f722fb66501658895461977867315ba" + +shelljs@^0.7.5: + version "0.7.8" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" + dependencies: + glob "^7.0.0" + interpret "^1.0.0" + rechoir "^0.6.2" + +sigmund@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" + +signal-exit@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + +sinon@^1.17.3: + version "1.17.7" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-1.17.7.tgz#4542a4f49ba0c45c05eb2e9dd9d203e2b8efe0bf" + dependencies: + formatio "1.1.1" + lolex "1.3.2" + samsam "1.1.2" + util ">=0.10.3 <1" + +slash@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + +slice-ansi@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" + +sntp@1.x.x: + version "1.0.9" + resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" + dependencies: + hoek "2.x.x" + +sntp@2.x.x: + version "2.1.0" + resolved "https://registry.yarnpkg.com/sntp/-/sntp-2.1.0.tgz#2c6cec14fedc2222739caf9b5c3d85d1cc5a2cc8" + dependencies: + hoek "4.x.x" + +socket.io-adapter@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-0.5.0.tgz#cb6d4bb8bec81e1078b99677f9ced0046066bb8b" + dependencies: + debug "2.3.3" + socket.io-parser "2.3.1" + +socket.io-client@1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-1.7.3.tgz#b30e86aa10d5ef3546601c09cde4765e381da377" + dependencies: + backo2 "1.0.2" + component-bind "1.0.0" + component-emitter "1.2.1" + debug "2.3.3" + engine.io-client "1.8.3" + has-binary "0.1.7" + indexof "0.0.1" + object-component "0.0.3" + parseuri "0.0.5" + socket.io-parser "2.3.1" + to-array "0.1.4" + +socket.io-parser@2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-2.3.1.tgz#dd532025103ce429697326befd64005fcfe5b4a0" + dependencies: + component-emitter "1.1.2" + debug "2.2.0" + isarray "0.0.1" + json3 "3.3.2" + +socket.io@1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-1.7.3.tgz#b8af9caba00949e568e369f1327ea9be9ea2461b" + dependencies: + debug "2.3.3" + engine.io "1.8.3" + has-binary "0.1.7" + object-assign "4.1.0" + socket.io-adapter "0.5.0" + socket.io-client "1.7.3" + socket.io-parser "2.3.1" + +source-list-map@~0.1.7: + version "0.1.8" + resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-0.1.8.tgz#c550b2ab5427f6b3f21f5afead88c4f5587b2106" + +source-map-loader@^0.1.5: + version "0.1.6" + resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-0.1.6.tgz#c09903da6d73b9e53b7ed8ee5245597051e98e91" + dependencies: + async "^0.9.0" + loader-utils "~0.2.2" + source-map "~0.1.33" + +source-map-support@^0.4.15: + version "0.4.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" + dependencies: + source-map "^0.5.6" + +source-map@^0.1.41, source-map@~0.1.33: + version "0.1.43" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" + dependencies: + amdefine ">=0.0.4" + +source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + +source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + +source-map@~0.4.1: + version "0.4.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" + dependencies: + amdefine ">=0.0.4" + +sprintf-js@^1.0.3: + version "1.1.1" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.1.tgz#36be78320afe5801f6cea3ee78b6e5aab940ea0c" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + +srcset@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/srcset/-/srcset-1.0.0.tgz#a5669de12b42f3b1d5e83ed03c71046fc48f41ef" + dependencies: + array-uniq "^1.0.2" + number-is-nan "^1.0.0" + +sshpk@^1.7.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + dashdash "^1.12.0" + getpass "^0.1.1" + optionalDependencies: + bcrypt-pbkdf "^1.0.0" + ecc-jsbn "~0.1.1" + jsbn "~0.1.0" + tweetnacl "~0.14.0" + +"statuses@>= 1.3.1 < 2": + version "1.4.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" + +statuses@~1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" + +stream-browserify@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" + dependencies: + inherits "~2.0.1" + readable-stream "^2.0.2" + +stream-http@^2.3.1: + version "2.8.0" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.0.tgz#fd86546dac9b1c91aff8fc5d287b98fafb41bc10" + dependencies: + builtin-status-codes "^3.0.0" + inherits "^2.0.1" + readable-stream "^2.3.3" + to-arraybuffer "^1.0.0" + xtend "^4.0.0" + +string-width@^1.0.1, string-width@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +string-width@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string.prototype.repeat@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/string.prototype.repeat/-/string.prototype.repeat-0.2.0.tgz#aba36de08dcee6a5a337d49b2ea1da1b28fc0ecf" + +string_decoder@^0.10.25, string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + +string_decoder@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" + dependencies: + safe-buffer "~5.1.0" + +stringstream@~0.0.4, stringstream@~0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + dependencies: + ansi-regex "^3.0.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + +supports-color@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-1.2.0.tgz#ff1ed1e61169d06b3cf2d588e188b18d8847e17e" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + +supports-color@^3.1.0: + version "3.2.3" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + dependencies: + has-flag "^1.0.0" + +supports-color@^5.2.0, supports-color@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.3.0.tgz#5b24ac15db80fa927cf5227a4a33fd3c4c7676c0" + dependencies: + has-flag "^3.0.0" + +symbol-observable@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" + +table@^3.7.8: + version "3.8.3" + resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f" + dependencies: + ajv "^4.7.0" + ajv-keywords "^1.0.0" + chalk "^1.1.1" + lodash "^4.0.0" + slice-ansi "0.0.4" + string-width "^2.0.0" + +tapable@^0.1.8, tapable@~0.1.8: + version "0.1.10" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.1.10.tgz#29c35707c2b70e50d07482b5d202e8ed446dafd4" + +tar-pack@^3.4.0: + version "3.4.1" + resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.1.tgz#e1dbc03a9b9d3ba07e896ad027317eb679a10a1f" + dependencies: + debug "^2.2.0" + fstream "^1.0.10" + fstream-ignore "^1.0.5" + once "^1.3.3" + readable-stream "^2.1.4" + rimraf "^2.5.1" + tar "^2.2.1" + uid-number "^0.0.6" + +tar@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" + dependencies: + block-stream "*" + fstream "^1.0.2" + inherits "2" + +text-encoding-utf-8@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz#585b62197b0ae437e3c7b5d0af27ac1021e10d13" + +text-table@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + +through@^2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + +time-stamp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-2.0.0.tgz#95c6a44530e15ba8d6f4a3ecb8c3a3fac46da357" + +timers-browserify@^2.0.2: + version "2.0.6" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.6.tgz#241e76927d9ca05f4d959819022f5b3664b64bae" + dependencies: + setimmediate "^1.0.4" + +tmatch@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/tmatch/-/tmatch-2.0.1.tgz#0c56246f33f30da1b8d3d72895abaf16660f38cf" + +tmp@0.0.31: + version "0.0.31" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7" + dependencies: + os-tmpdir "~1.0.1" + +tmp@0.0.x: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + dependencies: + os-tmpdir "~1.0.2" + +to-array@0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890" + +to-arraybuffer@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" + +to-fast-properties@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + +to-iso-string@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/to-iso-string/-/to-iso-string-0.0.2.tgz#4dc19e664dfccbe25bd8db508b00c6da158255d1" + +tough-cookie@~2.3.0, tough-cookie@~2.3.3: + version "2.3.4" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" + dependencies: + punycode "^1.4.1" + +trim-right@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + +tty-browserify@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + dependencies: + prelude-ls "~1.1.2" + +type-is@~1.6.15: + version "1.6.16" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" + dependencies: + media-typer "0.3.0" + mime-types "~2.1.18" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + +ua-parser-js@^0.7.9: + version "0.7.17" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac" + +uglify-js@~2.7.3: + version "2.7.5" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.7.5.tgz#4612c0c7baaee2ba7c487de4904ae122079f2ca8" + dependencies: + async "~0.2.6" + source-map "~0.5.1" + uglify-to-browserify "~1.0.0" + yargs "~3.10.0" + +uglify-to-browserify@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" + +uid-number@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" + +ultron@1.0.x: + version "1.0.2" + resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa" + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + +url@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + dependencies: + punycode "1.3.2" + querystring "0.2.0" + +user-home@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190" + +user-home@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f" + dependencies: + os-homedir "^1.0.0" + +useragent@^2.1.12: + version "2.3.0" + resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.3.0.tgz#217f943ad540cb2128658ab23fc960f6a88c9972" + dependencies: + lru-cache "4.1.x" + tmp "0.0.x" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + +util@0.10.3, "util@>=0.10.3 <1", util@^0.10.3: + version "0.10.3" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" + dependencies: + inherits "2.0.1" + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + +uuid@^3.0.0, uuid@^3.1.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" + +v8flags@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.1.1.tgz#aab1a1fa30d45f88dd321148875ac02c0b55e5b4" + dependencies: + user-home "^1.1.1" + +velocity-vector@vector-im/velocity#059e3b2: + version "1.2.3" + resolved "https://codeload.github.com/vector-im/velocity/tar.gz/059e3b2348f1110888d033974d3109fd5a3af00f" + dependencies: + jquery ">= 1.4.3" + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +vm-browserify@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" + dependencies: + indexof "0.0.1" + +void-elements@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" + +walk@^2.3.9: + version "2.3.9" + resolved "https://registry.yarnpkg.com/walk/-/walk-2.3.9.tgz#31b4db6678f2ae01c39ea9fb8725a9031e558a7b" + dependencies: + foreachasync "^3.0.0" + +watchpack@^0.2.1: + version "0.2.9" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-0.2.9.tgz#62eaa4ab5e5ba35fdfc018275626e3c0f5e3fb0b" + dependencies: + async "^0.9.0" + chokidar "^1.0.0" + graceful-fs "^4.1.2" + +webpack-core@~0.6.9: + version "0.6.9" + resolved "https://registry.yarnpkg.com/webpack-core/-/webpack-core-0.6.9.tgz#fc571588c8558da77be9efb6debdc5a3b172bdc2" + dependencies: + source-list-map "~0.1.7" + source-map "~0.4.1" + +webpack-dev-middleware@^1.0.11: + version "1.12.2" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz#f8fc1120ce3b4fc5680ceecb43d777966b21105e" + dependencies: + memory-fs "~0.4.1" + mime "^1.5.0" + path-is-absolute "^1.0.0" + range-parser "^1.0.3" + time-stamp "^2.0.0" + +webpack@^1.12.14: + version "1.15.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-1.15.0.tgz#4ff31f53db03339e55164a9d468ee0324968fe98" + dependencies: + acorn "^3.0.0" + async "^1.3.0" + clone "^1.0.2" + enhanced-resolve "~0.9.0" + interpret "^0.6.4" + loader-utils "^0.2.11" + memory-fs "~0.3.0" + mkdirp "~0.5.0" + node-libs-browser "^0.7.0" + optimist "~0.6.0" + supports-color "^3.1.0" + tapable "~0.1.8" + uglify-js "~2.7.3" + watchpack "^0.2.1" + webpack-core "~0.6.9" + +whatwg-fetch@>=0.10.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84" + +whatwg-fetch@^0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-0.9.0.tgz#0e3684c6cb9995b43efc9df03e4c365d95fd9cc0" + +whatwg-fetch@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-1.1.1.tgz#ac3c9d39f320c6dce5339969d054ef43dd333319" + +which@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" + dependencies: + isexe "^2.0.0" + +wide-align@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710" + dependencies: + string-width "^1.0.2" + +window-size@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" + +wordwrap@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" + +wordwrap@~0.0.2: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + +wordwrap@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +write@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" + dependencies: + mkdirp "^0.5.1" + +ws@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.2.tgz#8a244fa052401e08c9886cf44a85189e1fd4067f" + dependencies: + options ">=0.0.5" + ultron "1.0.x" + +wtf-8@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wtf-8/-/wtf-8-1.0.0.tgz#392d8ba2d0f1c34d1ee2d630f15d0efb68e1048a" + +xmlbuilder@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-3.1.0.tgz#2c86888f2d4eade850fa38ca7f7223f7209516e1" + dependencies: + lodash "^3.5.0" + +xmlhttprequest-ssl@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz#185a888c04eca46c3e4070d99f7b49de3528992d" + +xtend@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + +yargs@~3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" + dependencies: + camelcase "^1.0.2" + cliui "^2.1.0" + decamelize "^1.0.0" + window-size "0.1.0" + +yeast@0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" From d5465cf2fa05d51da6f4fa941bf70f16851b9164 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Tue, 6 Mar 2018 10:55:59 +0000 Subject: [PATCH 117/170] Prefix and clarify global variable naming. --- src/IntegrationManager.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/IntegrationManager.js b/src/IntegrationManager.js index d85b89f744..fdc45660a0 100644 --- a/src/IntegrationManager.js +++ b/src/IntegrationManager.js @@ -20,22 +20,22 @@ import ScalarMessaging from './ScalarMessaging'; import ScalarAuthClient from './ScalarAuthClient'; import RoomViewStore from './stores/RoomViewStore'; -if (!global.im) { - global.im = {}; +if (!global.mxIntegrationManager) { + global.mxIntegrationManager = {}; } export default class IntegrationManager { static async _init() { - if (!global.im.client || !global.im.connected) { + if (!global.mxIntegrationManager.client || !global.mxIntegrationManager.connected) { if (SdkConfig.get().integrations_ui_url && SdkConfig.get().integrations_rest_url) { ScalarMessaging.startListening(); - global.im.client = new ScalarAuthClient(); + global.mxIntegrationManager.client = new ScalarAuthClient(); - await global.im.client.connect().then(() => { - global.im.connected = true; + await global.mxIntegrationManager.client.connect().then(() => { + global.mxIntegrationManager.connected = true; }).catch((e) => { console.error("Failed to connect to integrations server", e); - global.im.error = e; + global.mxIntegrationManager.error = e; }); } else { console.error('Invalid integration manager config', SdkConfig.get()); @@ -52,13 +52,13 @@ export default class IntegrationManager { static async open(integType, integId, onClose) { await IntegrationManager._init(); const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager"); - if (global.im.error || !(global.im.client && global.im.client.hasCredentials())) { - console.error("Scalar error", global.im); + if (global.mxIntegrationManager.error || !(global.mxIntegrationManager.client && global.mxIntegrationManager.client.hasCredentials())) { + console.error("Scalar error", global.mxIntegrationManager); return; } integType = 'type_' + integType; - const src = (global.im.client && global.im.client.hasCredentials()) ? - global.im.client.getScalarInterfaceUrlForRoom( + const src = (global.mxIntegrationManager.client && global.mxIntegrationManager.client.hasCredentials()) ? + global.mxIntegrationManager.client.getScalarInterfaceUrlForRoom( RoomViewStore.getRoomId(), integType, integId, From b529edb5cc732b6c7eea7372f4199b7038aab471 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Tue, 6 Mar 2018 11:02:36 +0000 Subject: [PATCH 118/170] Linting --- src/IntegrationManager.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/IntegrationManager.js b/src/IntegrationManager.js index fdc45660a0..e9486138c7 100644 --- a/src/IntegrationManager.js +++ b/src/IntegrationManager.js @@ -52,7 +52,8 @@ export default class IntegrationManager { static async open(integType, integId, onClose) { await IntegrationManager._init(); const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager"); - if (global.mxIntegrationManager.error || !(global.mxIntegrationManager.client && global.mxIntegrationManager.client.hasCredentials())) { + if (global.mxIntegrationManager.error || + !(global.mxIntegrationManager.client && global.mxIntegrationManager.client.hasCredentials())) { console.error("Scalar error", global.mxIntegrationManager); return; } From 7f91b475981df108843e42074446f8728371c456 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Wed, 7 Mar 2018 11:52:42 +0000 Subject: [PATCH 119/170] Move sticker picker icon. --- src/components/views/rooms/MessageComposer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 70971e2299..0f98e6b526 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -340,11 +340,11 @@ export default class MessageComposer extends React.Component { onContentChanged={this.onInputContentChanged} onInputStateChanged={this.onInputStateChanged} />, formattingButton, + , uploadButton, hangupButton, callButton, videoCallButton, - , ); } else { controls.push( From b2bb15beb3931e26ba8b1c49babe2c9f90ed0a7a Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Wed, 7 Mar 2018 11:59:44 +0000 Subject: [PATCH 120/170] Remove accidentally checked in yarn.lock --- yarn.lock | 4392 ----------------------------------------------------- 1 file changed, 4392 deletions(-) delete mode 100644 yarn.lock diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index 27533e876b..0000000000 --- a/yarn.lock +++ /dev/null @@ -1,4392 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - -accepts@1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca" - dependencies: - mime-types "~2.1.11" - negotiator "0.6.1" - -acorn-jsx@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" - dependencies: - acorn "^3.0.4" - -acorn@^3.0.0, acorn@^3.0.4: - version "3.3.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" - -acorn@^5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.5.0.tgz#1abb587fbf051f94e3de20e6b26ef910b1828298" - -after@0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" - -ajv-keywords@^1.0.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" - -ajv@^4.7.0, ajv@^4.9.1: - version "4.11.8" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" - dependencies: - co "^4.6.0" - json-stable-stringify "^1.0.1" - -ajv@^5.1.0: - version "5.5.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" - dependencies: - co "^4.6.0" - fast-deep-equal "^1.0.0" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.3.0" - -align-text@^0.1.1, align-text@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" - dependencies: - kind-of "^3.0.2" - longest "^1.0.1" - repeat-string "^1.5.2" - -amdefine@>=0.0.4: - version "1.0.1" - resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" - -another-json@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/another-json/-/another-json-0.2.0.tgz#b5f4019c973b6dd5c6506a2d93469cb6d32aeedc" - -ansi-escapes@^1.1.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - dependencies: - color-convert "^1.9.0" - -anymatch@^1.3.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" - dependencies: - micromatch "^2.1.5" - normalize-path "^2.0.0" - -aproba@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - -are-we-there-yet@~1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d" - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - dependencies: - sprintf-js "~1.0.2" - -arr-diff@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" - dependencies: - arr-flatten "^1.0.1" - -arr-flatten@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - -array-includes@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.0.3.tgz#184b48f62d92d7452bb31b323165c7f8bd02266d" - dependencies: - define-properties "^1.1.2" - es-abstract "^1.7.0" - -array-slice@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5" - -array-union@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - dependencies: - array-uniq "^1.0.1" - -array-uniq@^1.0.1, array-uniq@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - -array-unique@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" - -arraybuffer.slice@0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz#f33b2159f0532a3f3107a272c0ccfbd1ad2979ca" - -arrify@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - -asap@~2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - -asn1@~0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - -assert-plus@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" - -assert@^1.1.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" - dependencies: - util "0.10.3" - -async-each@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" - -async@^0.9.0, async@~0.9.0: - version "0.9.2" - resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" - -async@^1.3.0: - version "1.5.2" - resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - -async@~0.2.6: - version "0.2.10" - resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - -aws-sign2@~0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" - -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - -aws4@^1.2.1, aws4@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" - -babel-cli@^6.5.2: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-cli/-/babel-cli-6.26.0.tgz#502ab54874d7db88ad00b887a06383ce03d002f1" - dependencies: - babel-core "^6.26.0" - babel-polyfill "^6.26.0" - babel-register "^6.26.0" - babel-runtime "^6.26.0" - commander "^2.11.0" - convert-source-map "^1.5.0" - fs-readdir-recursive "^1.0.0" - glob "^7.1.2" - lodash "^4.17.4" - output-file-sync "^1.1.2" - path-is-absolute "^1.0.1" - slash "^1.0.0" - source-map "^0.5.6" - v8flags "^2.1.1" - optionalDependencies: - chokidar "^1.6.1" - -babel-code-frame@^6.16.0, babel-code-frame@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" - dependencies: - chalk "^1.1.3" - esutils "^2.0.2" - js-tokens "^3.0.2" - -babel-core@^6.14.0, babel-core@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.0.tgz#af32f78b31a6fcef119c87b0fd8d9753f03a0bb8" - dependencies: - babel-code-frame "^6.26.0" - babel-generator "^6.26.0" - babel-helpers "^6.24.1" - babel-messages "^6.23.0" - babel-register "^6.26.0" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - convert-source-map "^1.5.0" - debug "^2.6.8" - json5 "^0.5.1" - lodash "^4.17.4" - minimatch "^3.0.4" - path-is-absolute "^1.0.1" - private "^0.1.7" - slash "^1.0.0" - source-map "^0.5.6" - -babel-eslint@^6.1.2: - version "6.1.2" - resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-6.1.2.tgz#5293419fe3672d66598d327da9694567ba6a5f2f" - dependencies: - babel-traverse "^6.0.20" - babel-types "^6.0.19" - babylon "^6.0.18" - lodash.assign "^4.0.0" - lodash.pickby "^4.0.0" - -babel-generator@^6.26.0: - version "6.26.1" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" - dependencies: - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - detect-indent "^4.0.0" - jsesc "^1.3.0" - lodash "^4.17.4" - source-map "^0.5.7" - trim-right "^1.0.1" - -babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" - dependencies: - babel-helper-explode-assignable-expression "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-builder-react-jsx@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz#39ff8313b75c8b65dceff1f31d383e0ff2a408a0" - dependencies: - babel-runtime "^6.26.0" - babel-types "^6.26.0" - esutils "^2.0.2" - -babel-helper-call-delegate@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" - dependencies: - babel-helper-hoist-variables "^6.24.1" - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-define-map@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-helper-explode-assignable-expression@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" - dependencies: - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-function-name@^6.24.1, babel-helper-function-name@^6.8.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" - dependencies: - babel-helper-get-function-arity "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-get-function-arity@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-hoist-variables@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-optimise-call-expression@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-regex@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" - dependencies: - babel-runtime "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-helper-remap-async-to-generator@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-replace-supers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" - dependencies: - babel-helper-optimise-call-expression "^6.24.1" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helpers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-loader@^6.2.5: - version "6.4.1" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-6.4.1.tgz#0b34112d5b0748a8dcdbf51acf6f9bd42d50b8ca" - dependencies: - find-cache-dir "^0.1.1" - loader-utils "^0.2.16" - mkdirp "^0.5.1" - object-assign "^4.0.1" - -babel-messages@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-add-module-exports@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-0.2.1.tgz#9ae9a1f4a8dc67f0cdec4f4aeda1e43a5ff65e25" - -babel-plugin-check-es2015-constants@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-syntax-async-functions@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" - -babel-plugin-syntax-class-properties@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de" - -babel-plugin-syntax-exponentiation-operator@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" - -babel-plugin-syntax-flow@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz#4c3ab20a2af26aa20cd25995c398c4eb70310c8d" - -babel-plugin-syntax-jsx@^6.3.13, babel-plugin-syntax-jsx@^6.8.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" - -babel-plugin-syntax-object-rest-spread@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" - -babel-plugin-syntax-trailing-function-commas@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" - -babel-plugin-transform-async-to-bluebird@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-bluebird/-/babel-plugin-transform-async-to-bluebird-1.1.1.tgz#46ea3e7c5af629782ac9f1ed1b7cd38f8425afd4" - dependencies: - babel-helper-function-name "^6.8.0" - babel-plugin-syntax-async-functions "^6.8.0" - babel-template "^6.9.0" - babel-traverse "^6.10.4" - -babel-plugin-transform-async-to-generator@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" - dependencies: - babel-helper-remap-async-to-generator "^6.24.1" - babel-plugin-syntax-async-functions "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-class-properties@^6.16.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac" - dependencies: - babel-helper-function-name "^6.24.1" - babel-plugin-syntax-class-properties "^6.8.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-arrow-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-block-scoping@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" - dependencies: - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-plugin-transform-es2015-classes@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" - dependencies: - babel-helper-define-map "^6.24.1" - babel-helper-function-name "^6.24.1" - babel-helper-optimise-call-expression "^6.24.1" - babel-helper-replace-supers "^6.24.1" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-computed-properties@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-destructuring@^6.22.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-duplicate-keys@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-for-of@^6.22.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-function-name@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-literals@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-modules-amd@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" - dependencies: - babel-plugin-transform-es2015-modules-commonjs "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-commonjs@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz#0d8394029b7dc6abe1a97ef181e00758dd2e5d8a" - dependencies: - babel-plugin-transform-strict-mode "^6.24.1" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-types "^6.26.0" - -babel-plugin-transform-es2015-modules-systemjs@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" - dependencies: - babel-helper-hoist-variables "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-umd@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" - dependencies: - babel-plugin-transform-es2015-modules-amd "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-object-super@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" - dependencies: - babel-helper-replace-supers "^6.24.1" - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-parameters@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" - dependencies: - babel-helper-call-delegate "^6.24.1" - babel-helper-get-function-arity "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-shorthand-properties@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-spread@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-sticky-regex@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" - dependencies: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-template-literals@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-typeof-symbol@^6.22.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-unicode-regex@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" - dependencies: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - regexpu-core "^2.0.0" - -babel-plugin-transform-exponentiation-operator@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" - dependencies: - babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" - babel-plugin-syntax-exponentiation-operator "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-flow-strip-types@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz#84cb672935d43714fdc32bce84568d87441cf7cf" - dependencies: - babel-plugin-syntax-flow "^6.18.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-object-rest-spread@^6.16.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06" - dependencies: - babel-plugin-syntax-object-rest-spread "^6.8.0" - babel-runtime "^6.26.0" - -babel-plugin-transform-react-display-name@^6.23.0: - version "6.25.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz#67e2bf1f1e9c93ab08db96792e05392bf2cc28d1" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-react-jsx-self@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz#df6d80a9da2612a121e6ddd7558bcbecf06e636e" - dependencies: - babel-plugin-syntax-jsx "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-react-jsx-source@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz#66ac12153f5cd2d17b3c19268f4bf0197f44ecd6" - dependencies: - babel-plugin-syntax-jsx "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-react-jsx@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz#840a028e7df460dfc3a2d29f0c0d91f6376e66a3" - dependencies: - babel-helper-builder-react-jsx "^6.24.1" - babel-plugin-syntax-jsx "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-regenerator@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" - dependencies: - regenerator-transform "^0.10.0" - -babel-plugin-transform-runtime@^6.15.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.23.0.tgz#88490d446502ea9b8e7efb0fe09ec4d99479b1ee" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-strict-mode@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-polyfill@^6.26.0, babel-polyfill@^6.5.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153" - dependencies: - babel-runtime "^6.26.0" - core-js "^2.5.0" - regenerator-runtime "^0.10.5" - -babel-preset-es2015@^6.14.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939" - dependencies: - babel-plugin-check-es2015-constants "^6.22.0" - babel-plugin-transform-es2015-arrow-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoping "^6.24.1" - babel-plugin-transform-es2015-classes "^6.24.1" - babel-plugin-transform-es2015-computed-properties "^6.24.1" - babel-plugin-transform-es2015-destructuring "^6.22.0" - babel-plugin-transform-es2015-duplicate-keys "^6.24.1" - babel-plugin-transform-es2015-for-of "^6.22.0" - babel-plugin-transform-es2015-function-name "^6.24.1" - babel-plugin-transform-es2015-literals "^6.22.0" - babel-plugin-transform-es2015-modules-amd "^6.24.1" - babel-plugin-transform-es2015-modules-commonjs "^6.24.1" - babel-plugin-transform-es2015-modules-systemjs "^6.24.1" - babel-plugin-transform-es2015-modules-umd "^6.24.1" - babel-plugin-transform-es2015-object-super "^6.24.1" - babel-plugin-transform-es2015-parameters "^6.24.1" - babel-plugin-transform-es2015-shorthand-properties "^6.24.1" - babel-plugin-transform-es2015-spread "^6.22.0" - babel-plugin-transform-es2015-sticky-regex "^6.24.1" - babel-plugin-transform-es2015-template-literals "^6.22.0" - babel-plugin-transform-es2015-typeof-symbol "^6.22.0" - babel-plugin-transform-es2015-unicode-regex "^6.24.1" - babel-plugin-transform-regenerator "^6.24.1" - -babel-preset-es2016@^6.11.3: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-es2016/-/babel-preset-es2016-6.24.1.tgz#f900bf93e2ebc0d276df9b8ab59724ebfd959f8b" - dependencies: - babel-plugin-transform-exponentiation-operator "^6.24.1" - -babel-preset-es2017@^6.14.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-es2017/-/babel-preset-es2017-6.24.1.tgz#597beadfb9f7f208bcfd8a12e9b2b29b8b2f14d1" - dependencies: - babel-plugin-syntax-trailing-function-commas "^6.22.0" - babel-plugin-transform-async-to-generator "^6.24.1" - -babel-preset-flow@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz#e71218887085ae9a24b5be4169affb599816c49d" - dependencies: - babel-plugin-transform-flow-strip-types "^6.22.0" - -babel-preset-react@^6.11.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-react/-/babel-preset-react-6.24.1.tgz#ba69dfaea45fc3ec639b6a4ecea6e17702c91380" - dependencies: - babel-plugin-syntax-jsx "^6.3.13" - babel-plugin-transform-react-display-name "^6.23.0" - babel-plugin-transform-react-jsx "^6.24.1" - babel-plugin-transform-react-jsx-self "^6.22.0" - babel-plugin-transform-react-jsx-source "^6.22.0" - babel-preset-flow "^6.23.0" - -babel-register@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" - dependencies: - babel-core "^6.26.0" - babel-runtime "^6.26.0" - core-js "^2.5.0" - home-or-tmp "^2.0.0" - lodash "^4.17.4" - mkdirp "^0.5.1" - source-map-support "^0.4.15" - -babel-runtime@^6.11.6, babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - -babel-template@^6.24.1, babel-template@^6.26.0, babel-template@^6.9.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" - dependencies: - babel-runtime "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - lodash "^4.17.4" - -babel-traverse@^6.0.20, babel-traverse@^6.10.4, babel-traverse@^6.24.1, babel-traverse@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" - dependencies: - babel-code-frame "^6.26.0" - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - debug "^2.6.8" - globals "^9.18.0" - invariant "^2.2.2" - lodash "^4.17.4" - -babel-types@^6.0.19, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" - dependencies: - babel-runtime "^6.26.0" - esutils "^2.0.2" - lodash "^4.17.4" - to-fast-properties "^1.0.3" - -babylon@^6.0.18, babylon@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - -backo2@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - -base64-arraybuffer@0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8" - -base64-js@^1.0.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.3.tgz#fb13668233d9614cf5fb4bce95a9ba4096cdf801" - -base64id@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/base64id/-/base64id-1.0.0.tgz#47688cb99bb6804f0e06d3e763b1c32e57d8e6b6" - -bcrypt-pbkdf@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" - dependencies: - tweetnacl "^0.14.3" - -better-assert@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/better-assert/-/better-assert-1.0.2.tgz#40866b9e1b9e0b55b481894311e68faffaebc522" - dependencies: - callsite "1.0.0" - -big.js@^3.1.3: - version "3.2.0" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" - -binary-extensions@^1.0.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205" - -blob@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.4.tgz#bcf13052ca54463f30f9fc7e95b9a47630a94921" - -block-stream@*: - version "0.0.9" - resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - dependencies: - inherits "~2.0.0" - -bluebird@^3.3.0, bluebird@^3.5.0: - version "3.5.1" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" - -blueimp-canvas-to-blob@^3.5.0: - version "3.14.0" - resolved "https://registry.yarnpkg.com/blueimp-canvas-to-blob/-/blueimp-canvas-to-blob-3.14.0.tgz#ea075ffbfb1436607b0c75e951fb1ceb3ca0288e" - -body-parser@^1.16.1: - version "1.18.2" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.2.tgz#87678a19d84b47d859b83199bd59bce222b10454" - dependencies: - bytes "3.0.0" - content-type "~1.0.4" - debug "2.6.9" - depd "~1.1.1" - http-errors "~1.6.2" - iconv-lite "0.4.19" - on-finished "~2.3.0" - qs "6.5.1" - raw-body "2.3.2" - type-is "~1.6.15" - -boom@2.x.x: - version "2.10.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" - dependencies: - hoek "2.x.x" - -boom@4.x.x: - version "4.3.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31" - dependencies: - hoek "4.x.x" - -boom@5.x.x: - version "5.2.0" - resolved "https://registry.yarnpkg.com/boom/-/boom-5.2.0.tgz#5dd9da6ee3a5f302077436290cb717d3f4a54e02" - dependencies: - hoek "4.x.x" - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^0.1.2: - version "0.1.5" - resolved "https://registry.yarnpkg.com/braces/-/braces-0.1.5.tgz#c085711085291d8b75fdd74eab0f8597280711e6" - dependencies: - expand-range "^0.1.0" - -braces@^1.8.2: - version "1.8.5" - resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" - dependencies: - expand-range "^1.8.1" - preserve "^0.2.0" - repeat-element "^1.1.2" - -browser-encrypt-attachment@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/browser-encrypt-attachment/-/browser-encrypt-attachment-0.3.0.tgz#205a94caadf0dc7e81413941812f655bd190ff1c" - -browser-request@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/browser-request/-/browser-request-0.3.3.tgz#9ece5b5aca89a29932242e18bf933def9876cc17" - -browserify-aes@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-0.4.0.tgz#067149b668df31c4b58533e02d01e806d8608e2c" - dependencies: - inherits "^2.0.1" - -browserify-zlib@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz#bb35f8a519f600e0fa6b8485241c979d0141fb2d" - dependencies: - pako "~0.2.0" - -buffer@^4.9.0: - version "4.9.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - isarray "^1.0.0" - -builtin-status-codes@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" - -bytes@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - -caller-path@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" - dependencies: - callsites "^0.2.0" - -callsite@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20" - -callsites@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" - -camelcase@^1.0.2: - version "1.2.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" - -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - -center-align@^0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" - dependencies: - align-text "^0.1.3" - lazy-cache "^1.0.3" - -chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -"chalk@^1.1.3 || 2.x", chalk@^2.3.0, chalk@^2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65" - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chokidar@^1.0.0, chokidar@^1.4.1, chokidar@^1.6.1: - version "1.7.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" - dependencies: - anymatch "^1.3.0" - async-each "^1.0.0" - glob-parent "^2.0.0" - inherits "^2.0.1" - is-binary-path "^1.0.0" - is-glob "^2.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.0.0" - optionalDependencies: - fsevents "^1.0.0" - -circular-json@^0.3.1: - version "0.3.3" - resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" - -classnames@^2.1.2: - version "2.2.5" - resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d" - -cli-cursor@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" - dependencies: - restore-cursor "^1.0.1" - -cli-width@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" - -cliui@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" - dependencies: - center-align "^0.1.1" - right-align "^0.1.1" - wordwrap "0.0.2" - -clone@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.3.tgz#298d7e2231660f40c003c2ed3140decf3f53085f" - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - -color-convert@^1.9.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" - dependencies: - color-name "^1.1.1" - -color-name@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - -colors@^1.1.0, colors@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" - -combine-lists@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/combine-lists/-/combine-lists-1.0.1.tgz#458c07e09e0d900fc28b70a3fec2dacd1d2cb7f6" - dependencies: - lodash "^4.5.0" - -combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5: - version "1.0.6" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" - dependencies: - delayed-stream "~1.0.0" - -commander@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-0.6.1.tgz#fa68a14f6a945d54dbbe50d8cdb3320e9e3b1a06" - -commander@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.3.0.tgz#fd430e889832ec353b9acd1de217c11cb3eef873" - -commander@^2.11.0: - version "2.14.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.14.1.tgz#2235123e37af8ca3c65df45b026dbd357b01b9aa" - -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - -commonmark@^0.28.1: - version "0.28.1" - resolved "https://registry.yarnpkg.com/commonmark/-/commonmark-0.28.1.tgz#06eab8d52338b839fa1a2d75af0085eed1b1beae" - dependencies: - entities "~ 1.1.1" - mdurl "~ 1.0.1" - minimist "~ 1.2.0" - string.prototype.repeat "^0.2.0" - -component-bind@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1" - -component-emitter@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.1.2.tgz#296594f2753daa63996d2af08d15a95116c9aec3" - -component-emitter@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" - -component-inherit@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - -concat-stream@^1.5.2: - version "1.6.1" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.1.tgz#261b8f518301f1d834e36342b9fea095d2620a26" - dependencies: - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - -connect@^3.6.0: - version "3.6.6" - resolved "https://registry.yarnpkg.com/connect/-/connect-3.6.6.tgz#09eff6c55af7236e137135a72574858b6786f524" - dependencies: - debug "2.6.9" - finalhandler "1.1.0" - parseurl "~1.3.2" - utils-merge "1.0.1" - -console-browserify@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" - dependencies: - date-now "^0.1.4" - -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - -constants-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" - -content-type@^1.0.2, content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - -convert-source-map@^1.5.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" - -cookie@0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" - -core-js@^1.0.0: - version "1.2.7" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" - -core-js@^2.2.0, core-js@^2.4.0, core-js@^2.5.0: - version "2.5.3" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e" - -core-util-is@1.0.2, core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - -counterpart@^0.18.0: - version "0.18.6" - resolved "https://registry.yarnpkg.com/counterpart/-/counterpart-0.18.6.tgz#cf6b60d8ef99a4b44b8bf6445fa99b4bd1b2f9dd" - dependencies: - date-names "^0.1.11" - except "^0.1.3" - extend "^3.0.0" - pluralizers "^0.1.7" - sprintf-js "^1.0.3" - -create-react-class@^15.6.0: - version "15.6.3" - resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.6.3.tgz#2d73237fb3f970ae6ebe011a9e66f46dbca80036" - dependencies: - fbjs "^0.8.9" - loose-envify "^1.3.1" - object-assign "^4.1.1" - -cryptiles@2.x.x: - version "2.0.5" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" - dependencies: - boom "2.x.x" - -cryptiles@3.x.x: - version "3.1.2" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-3.1.2.tgz#a89fbb220f5ce25ec56e8c4aa8a4fd7b5b0d29fe" - dependencies: - boom "5.x.x" - -crypto-browserify@3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.3.0.tgz#b9fc75bb4a0ed61dcf1cd5dae96eb30c9c3e506c" - dependencies: - browserify-aes "0.4.0" - pbkdf2-compat "2.0.1" - ripemd160 "0.2.0" - sha.js "2.2.6" - -custom-event@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" - -d@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" - dependencies: - es5-ext "^0.10.9" - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - dependencies: - assert-plus "^1.0.0" - -date-names@^0.1.11: - version "0.1.12" - resolved "https://registry.yarnpkg.com/date-names/-/date-names-0.1.12.tgz#e60fe316de1547c9d9e7f14bd350130e4b7f9ef8" - -date-now@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" - -debug@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" - dependencies: - ms "0.7.1" - -debug@2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.3.3.tgz#40c453e67e6e13c901ddec317af8986cda9eff8c" - dependencies: - ms "0.7.2" - -debug@2.6.9, debug@^2.1.1, debug@^2.2.0, debug@^2.6.8: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - dependencies: - ms "2.0.0" - -decamelize@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - -deep-extend@~0.4.0: - version "0.4.2" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" - -deep-is@~0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" - -define-properties@^1.1.2, define-properties@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" - dependencies: - foreach "^2.0.5" - object-keys "^1.0.8" - -del@^2.0.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" - dependencies: - globby "^5.0.0" - is-path-cwd "^1.0.0" - is-path-in-cwd "^1.0.0" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - rimraf "^2.2.8" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - -depd@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359" - -depd@~1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - -detect-indent@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" - dependencies: - repeating "^2.0.0" - -detect-libc@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - -di@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" - -diff@1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf" - -doctrine@^2.0.0, doctrine@^2.0.2: - version "2.1.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" - dependencies: - esutils "^2.0.2" - -dom-serialize@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b" - dependencies: - custom-event "~1.0.0" - ent "~2.2.0" - extend "^3.0.0" - void-elements "^2.0.0" - -dom-serializer@0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" - dependencies: - domelementtype "~1.1.1" - entities "~1.1.1" - -domain-browser@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" - -domelementtype@1, domelementtype@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" - -domelementtype@~1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" - -domhandler@^2.3.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.1.tgz#892e47000a99be55bbf3774ffea0561d8879c259" - dependencies: - domelementtype "1" - -domutils@^1.5.1: - version "1.7.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" - dependencies: - dom-serializer "0" - domelementtype "1" - -draft-js-export-html@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/draft-js-export-html/-/draft-js-export-html-0.6.0.tgz#cc80f0544c43d0a7fedbc53c0cb0914e8090f769" - dependencies: - draft-js-utils ">=0.2.0" - -draft-js-export-markdown@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/draft-js-export-markdown/-/draft-js-export-markdown-0.3.0.tgz#86390e03ceaf1d347fc616867ab7f535eb76bf42" - dependencies: - draft-js-utils ">=0.2.0" - -draft-js-utils@>=0.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/draft-js-utils/-/draft-js-utils-1.2.0.tgz#f5cb23eb167325ffed3d79882fdc317721d2fd12" - -draft-js@^0.11.0-alpha: - version "0.11.0-alpha" - resolved "https://registry.yarnpkg.com/draft-js/-/draft-js-0.11.0-alpha.tgz#32db2108f927e9b8446da1f79e4475c2b7f868ae" - dependencies: - fbjs "^0.8.12" - immutable "~3.7.4" - object-assign "^4.1.0" - -ecc-jsbn@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" - dependencies: - jsbn "~0.1.0" - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - -emojione@2.2.7: - version "2.2.7" - resolved "https://registry.yarnpkg.com/emojione/-/emojione-2.2.7.tgz#46457cf6b9b2f8da13ae8a2e4e547de06ee15e96" - -emojis-list@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" - -encodeurl@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - -encoding@^0.1.11: - version "0.1.12" - resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" - dependencies: - iconv-lite "~0.4.13" - -engine.io-client@1.8.3: - version "1.8.3" - resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-1.8.3.tgz#1798ed93451246453d4c6f635d7a201fe940d5ab" - dependencies: - component-emitter "1.2.1" - component-inherit "0.0.3" - debug "2.3.3" - engine.io-parser "1.3.2" - has-cors "1.1.0" - indexof "0.0.1" - parsejson "0.0.3" - parseqs "0.0.5" - parseuri "0.0.5" - ws "1.1.2" - xmlhttprequest-ssl "1.5.3" - yeast "0.1.2" - -engine.io-parser@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-1.3.2.tgz#937b079f0007d0893ec56d46cb220b8cb435220a" - dependencies: - after "0.8.2" - arraybuffer.slice "0.0.6" - base64-arraybuffer "0.1.5" - blob "0.0.4" - has-binary "0.1.7" - wtf-8 "1.0.0" - -engine.io@1.8.3: - version "1.8.3" - resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-1.8.3.tgz#8de7f97895d20d39b85f88eeee777b2bd42b13d4" - dependencies: - accepts "1.3.3" - base64id "1.0.0" - cookie "0.3.1" - debug "2.3.3" - engine.io-parser "1.3.2" - ws "1.1.2" - -enhanced-resolve@~0.9.0: - version "0.9.1" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz#4d6e689b3725f86090927ccc86cd9f1635b89e2e" - dependencies: - graceful-fs "^4.1.2" - memory-fs "^0.2.0" - tapable "^0.1.8" - -ent@~2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" - -entities@^1.1.1, "entities@~ 1.1.1", entities@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" - -errno@^0.1.3: - version "0.1.7" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" - dependencies: - prr "~1.0.1" - -es-abstract@^1.6.1, es-abstract@^1.7.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.10.0.tgz#1ecb36c197842a00d8ee4c2dfd8646bb97d60864" - dependencies: - es-to-primitive "^1.1.1" - function-bind "^1.1.1" - has "^1.0.1" - is-callable "^1.1.3" - is-regex "^1.0.4" - -es-to-primitive@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d" - dependencies: - is-callable "^1.1.1" - is-date-object "^1.0.1" - is-symbol "^1.0.1" - -es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14: - version "0.10.39" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.39.tgz#fca21b67559277ca4ac1a1ed7048b107b6f76d87" - dependencies: - es6-iterator "~2.0.3" - es6-symbol "~3.1.1" - -es6-iterator@^2.0.1, es6-iterator@~2.0.1, es6-iterator@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" - dependencies: - d "1" - es5-ext "^0.10.35" - es6-symbol "^3.1.1" - -es6-map@^0.1.3: - version "0.1.5" - resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" - dependencies: - d "1" - es5-ext "~0.10.14" - es6-iterator "~2.0.1" - es6-set "~0.1.5" - es6-symbol "~3.1.1" - event-emitter "~0.3.5" - -es6-set@~0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" - dependencies: - d "1" - es5-ext "~0.10.14" - es6-iterator "~2.0.1" - es6-symbol "3.1.1" - event-emitter "~0.3.5" - -es6-symbol@3.1.1, es6-symbol@^3.1.1, es6-symbol@~3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" - dependencies: - d "1" - es5-ext "~0.10.14" - -es6-weak-map@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f" - dependencies: - d "1" - es5-ext "^0.10.14" - es6-iterator "^2.0.1" - es6-symbol "^3.1.1" - -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - -escape-string-regexp@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz#4dbc2fe674e71949caf3fb2695ce7f2dc1d9a8d1" - -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - -escope@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" - dependencies: - es6-map "^0.1.3" - es6-weak-map "^2.0.1" - esrecurse "^4.1.0" - estraverse "^4.1.1" - -eslint-config-google@^0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/eslint-config-google/-/eslint-config-google-0.7.1.tgz#5598f8498e9e078420f34b80495b8d959f651fb2" - -eslint-plugin-babel@^4.0.1: - version "4.1.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-babel/-/eslint-plugin-babel-4.1.2.tgz#79202a0e35757dd92780919b2336f1fa2fe53c1e" - -eslint-plugin-flowtype@^2.30.0: - version "2.46.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.46.1.tgz#c4f81d580cd89c82bc3a85a1ccf4ae3a915143a4" - dependencies: - lodash "^4.15.0" - -eslint-plugin-react@^7.4.0: - version "7.7.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.7.0.tgz#f606c719dbd8a1a2b3d25c16299813878cca0160" - dependencies: - doctrine "^2.0.2" - has "^1.0.1" - jsx-ast-utils "^2.0.1" - prop-types "^15.6.0" - -eslint@^3.13.1: - version "3.19.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.19.0.tgz#c8fc6201c7f40dd08941b87c085767386a679acc" - dependencies: - babel-code-frame "^6.16.0" - chalk "^1.1.3" - concat-stream "^1.5.2" - debug "^2.1.1" - doctrine "^2.0.0" - escope "^3.6.0" - espree "^3.4.0" - esquery "^1.0.0" - estraverse "^4.2.0" - esutils "^2.0.2" - file-entry-cache "^2.0.0" - glob "^7.0.3" - globals "^9.14.0" - ignore "^3.2.0" - imurmurhash "^0.1.4" - inquirer "^0.12.0" - is-my-json-valid "^2.10.0" - is-resolvable "^1.0.0" - js-yaml "^3.5.1" - json-stable-stringify "^1.0.0" - levn "^0.3.0" - lodash "^4.0.0" - mkdirp "^0.5.0" - natural-compare "^1.4.0" - optionator "^0.8.2" - path-is-inside "^1.0.1" - pluralize "^1.2.1" - progress "^1.1.8" - require-uncached "^1.0.2" - shelljs "^0.7.5" - strip-bom "^3.0.0" - strip-json-comments "~2.0.1" - table "^3.7.8" - text-table "~0.2.0" - user-home "^2.0.0" - -espree@^3.4.0: - version "3.5.4" - resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" - dependencies: - acorn "^5.5.0" - acorn-jsx "^3.0.0" - -esprima@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" - -esquery@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.0.tgz#cfba8b57d7fba93f17298a8a006a04cda13d80fa" - dependencies: - estraverse "^4.0.0" - -esrecurse@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" - dependencies: - estraverse "^4.1.0" - -estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" - -estree-walker@^0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.5.1.tgz#64fc375053abc6f57d73e9bd2f004644ad3c5854" - -esutils@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" - -event-emitter@~0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" - dependencies: - d "1" - es5-ext "~0.10.14" - -eventemitter3@1.x.x: - version "1.2.0" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.2.0.tgz#1c86991d816ad1e504750e73874224ecf3bec508" - -events@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" - -except@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/except/-/except-0.1.3.tgz#98261c91958551536b44482238e9783fb73d292a" - dependencies: - indexof "0.0.1" - -exit-hook@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" - -expand-braces@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/expand-braces/-/expand-braces-0.1.2.tgz#488b1d1d2451cb3d3a6b192cfc030f44c5855fea" - dependencies: - array-slice "^0.2.3" - array-unique "^0.2.1" - braces "^0.1.2" - -expand-brackets@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" - dependencies: - is-posix-bracket "^0.1.0" - -expand-range@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-0.1.1.tgz#4cb8eda0993ca56fa4f41fc42f3cbb4ccadff044" - dependencies: - is-number "^0.1.1" - repeat-string "^0.2.2" - -expand-range@^1.8.1: - version "1.8.2" - resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" - dependencies: - fill-range "^2.1.0" - -expect@^1.16.0: - version "1.20.2" - resolved "https://registry.yarnpkg.com/expect/-/expect-1.20.2.tgz#d458fe4c56004036bae3232416a3f6361f04f965" - dependencies: - define-properties "~1.1.2" - has "^1.0.1" - is-equal "^1.5.1" - is-regex "^1.0.3" - object-inspect "^1.1.0" - object-keys "^1.0.9" - tmatch "^2.0.1" - -extend@^3.0.0, extend@~3.0.0, extend@~3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" - -extglob@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" - dependencies: - is-extglob "^1.0.0" - -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - -extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - -fast-deep-equal@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" - -fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - -fast-levenshtein@~2.0.4: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - -fbemitter@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/fbemitter/-/fbemitter-2.1.1.tgz#523e14fdaf5248805bb02f62efc33be703f51865" - dependencies: - fbjs "^0.8.4" - -fbjs@0.1.0-alpha.7: - version "0.1.0-alpha.7" - resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.1.0-alpha.7.tgz#ad4308b8f232fb3c73603349ea725d1e9c39323c" - dependencies: - core-js "^1.0.0" - promise "^7.0.3" - whatwg-fetch "^0.9.0" - -fbjs@^0.8.12, fbjs@^0.8.16, fbjs@^0.8.4, fbjs@^0.8.9: - version "0.8.16" - resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db" - dependencies: - core-js "^1.0.0" - isomorphic-fetch "^2.1.1" - loose-envify "^1.0.0" - object-assign "^4.1.0" - promise "^7.1.1" - setimmediate "^1.0.5" - ua-parser-js "^0.7.9" - -figures@^1.3.5: - version "1.7.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" - dependencies: - escape-string-regexp "^1.0.5" - object-assign "^4.1.0" - -file-entry-cache@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" - dependencies: - flat-cache "^1.2.1" - object-assign "^4.0.1" - -file-saver@^1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-1.3.3.tgz#cdd4c44d3aa264eac2f68ec165bc791c34af1232" - -filename-regex@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" - -filesize@3.5.6: - version "3.5.6" - resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.5.6.tgz#5fd98f3eac94ec9516ef8ed5782fad84a01a0a1a" - -fill-range@^2.1.0: - version "2.2.3" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" - dependencies: - is-number "^2.1.0" - isobject "^2.0.0" - randomatic "^1.1.3" - repeat-element "^1.1.2" - repeat-string "^1.5.2" - -finalhandler@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.0.tgz#ce0b6855b45853e791b2fcc680046d88253dd7f5" - dependencies: - debug "2.6.9" - encodeurl "~1.0.1" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.2" - statuses "~1.3.1" - unpipe "~1.0.0" - -find-cache-dir@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9" - dependencies: - commondir "^1.0.1" - mkdirp "^0.5.1" - pkg-dir "^1.0.0" - -find-up@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - dependencies: - path-exists "^2.0.0" - pinkie-promise "^2.0.0" - -flat-cache@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" - dependencies: - circular-json "^0.3.1" - del "^2.0.2" - graceful-fs "^4.1.2" - write "^0.2.1" - -flow-parser@^0.57.3: - version "0.57.3" - resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.57.3.tgz#b8d241a1b1cbae043afa7976e39f269988d8fe34" - -flux@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/flux/-/flux-2.1.1.tgz#2c6ac652d4337488968489c6586f3aff26a38ea4" - dependencies: - fbemitter "^2.0.0" - fbjs "0.1.0-alpha.7" - immutable "^3.7.4" - -for-in@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - -for-own@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" - dependencies: - for-in "^1.0.1" - -foreach@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" - -foreachasync@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/foreachasync/-/foreachasync-3.0.0.tgz#5502987dc8714be3392097f32e0071c9dee07cf6" - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - -form-data@~2.1.1: - version "2.1.4" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.5" - mime-types "^2.1.12" - -form-data@~2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" - dependencies: - asynckit "^0.4.0" - combined-stream "1.0.6" - mime-types "^2.1.12" - -formatio@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.1.1.tgz#5ed3ccd636551097383465d996199100e86161e9" - dependencies: - samsam "~1.1" - -fs-access@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/fs-access/-/fs-access-1.0.1.tgz#d6a87f262271cefebec30c553407fb995da8777a" - dependencies: - null-check "^1.0.0" - -fs-readdir-recursive@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - -fsevents@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.1.3.tgz#11f82318f5fe7bb2cd22965a108e9306208216d8" - dependencies: - nan "^2.3.0" - node-pre-gyp "^0.6.39" - -fstream-ignore@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105" - dependencies: - fstream "^1.0.0" - inherits "2" - minimatch "^3.0.0" - -fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2: - version "1.0.11" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" - dependencies: - graceful-fs "^4.1.2" - inherits "~2.0.0" - mkdirp ">=0.5 0" - rimraf "2" - -function-bind@^1.0.2, function-bind@^1.1.0, function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - -fuse.js@^2.2.0: - version "2.7.4" - resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-2.7.4.tgz#96e420fde7ef011ac49c258a621314fe576536f9" - -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - -gemini-scrollbar@matrix-org/gemini-scrollbar#b302279: - version "1.4.3" - resolved "https://codeload.github.com/matrix-org/gemini-scrollbar/tar.gz/b302279810d05319ac5ff1bd34910bff32325c7b" - -generate-function@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" - -generate-object-property@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" - dependencies: - is-property "^1.0.0" - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - dependencies: - assert-plus "^1.0.0" - -glob-base@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" - dependencies: - glob-parent "^2.0.0" - is-glob "^2.0.0" - -glob-parent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" - dependencies: - is-glob "^2.0.0" - -glob@3.2.11: - version "3.2.11" - resolved "https://registry.yarnpkg.com/glob/-/glob-3.2.11.tgz#4a973f635b9190f715d10987d5c00fd2815ebe3d" - dependencies: - inherits "2" - minimatch "0.3" - -glob@^5.0.14: - version "5.0.15" - resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^9.14.0, globals@^9.18.0: - version "9.18.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" - -globby@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" - dependencies: - array-union "^1.0.1" - arrify "^1.0.0" - glob "^7.0.3" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -graceful-fs@^4.1.2, graceful-fs@^4.1.4: - version "4.1.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" - -growl@1.9.2: - version "1.9.2" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" - -har-schema@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" - -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - -har-validator@~4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" - dependencies: - ajv "^4.9.1" - har-schema "^1.0.5" - -har-validator@~5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" - dependencies: - ajv "^5.1.0" - har-schema "^2.0.0" - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - dependencies: - ansi-regex "^2.0.0" - -has-binary@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/has-binary/-/has-binary-0.1.7.tgz#68e61eb16210c9545a0a5cce06a873912fe1e68c" - dependencies: - isarray "0.0.1" - -has-cors@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39" - -has-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - -has@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" - dependencies: - function-bind "^1.0.2" - -hawk@3.1.3, hawk@~3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" - dependencies: - boom "2.x.x" - cryptiles "2.x.x" - hoek "2.x.x" - sntp "1.x.x" - -hawk@~6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-6.0.2.tgz#af4d914eb065f9b5ce4d9d11c1cb2126eecc3038" - dependencies: - boom "4.x.x" - cryptiles "3.x.x" - hoek "4.x.x" - sntp "2.x.x" - -highlight.js@^8.9.1: - version "8.9.1" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-8.9.1.tgz#b8a9c5493212a9392f0222b649c9611497ebfb88" - -hoek@2.x.x: - version "2.16.3" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" - -hoek@4.x.x: - version "4.2.1" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb" - -hoist-non-react-statics@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.0.tgz#d2ca2dfc19c5a91c5a6615ce8e564ef0347e2a40" - -home-or-tmp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.1" - -htmlparser2@^3.9.0: - version "3.9.2" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338" - dependencies: - domelementtype "^1.3.0" - domhandler "^2.3.0" - domutils "^1.5.1" - entities "^1.1.1" - inherits "^2.0.1" - readable-stream "^2.0.2" - -http-errors@1.6.2, http-errors@~1.6.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736" - dependencies: - depd "1.1.1" - inherits "2.0.3" - setprototypeof "1.0.3" - statuses ">= 1.3.1 < 2" - -http-proxy@^1.13.0: - version "1.16.2" - resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.16.2.tgz#06dff292952bf64dbe8471fa9df73066d4f37742" - dependencies: - eventemitter3 "1.x.x" - requires-port "1.x.x" - -http-signature@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" - dependencies: - assert-plus "^0.2.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -https-browserify@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.1.tgz#3f91365cabe60b77ed0ebba24b454e3e09d95a82" - -iconv-lite@0.4.19, iconv-lite@~0.4.13: - version "0.4.19" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" - -ieee754@^1.1.4: - version "1.1.8" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4" - -ignore@^3.2.0: - version "3.3.7" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021" - -immutable@^3.7.4: - version "3.8.2" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.8.2.tgz#c2439951455bb39913daf281376f1530e104adf3" - -immutable@~3.7.4: - version "3.7.6" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.7.6.tgz#13b4d3cb12befa15482a26fe1b2ebae640071e4b" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - -indexof@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - -inherits@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" - -ini@~1.3.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - -inquirer@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" - dependencies: - ansi-escapes "^1.1.0" - ansi-regex "^2.0.0" - chalk "^1.0.0" - cli-cursor "^1.0.1" - cli-width "^2.0.0" - figures "^1.3.5" - lodash "^4.3.0" - readline2 "^1.0.1" - run-async "^0.1.0" - rx-lite "^3.1.2" - string-width "^1.0.1" - strip-ansi "^3.0.0" - through "^2.3.6" - -interpret@^0.6.4: - version "0.6.6" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-0.6.6.tgz#fecd7a18e7ce5ca6abfb953e1f86213a49f1625b" - -interpret@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" - -invariant@^2.0.0, invariant@^2.2.2: - version "2.2.3" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.3.tgz#1a827dfde7dcbd7c323f0ca826be8fa7c5e9d688" - dependencies: - loose-envify "^1.0.0" - -is-arrow-function@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-arrow-function/-/is-arrow-function-2.0.3.tgz#29be2c2d8d9450852b8bbafb635ba7b8d8e87ec2" - dependencies: - is-callable "^1.0.4" - -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - dependencies: - binary-extensions "^1.0.0" - -is-boolean-object@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.0.0.tgz#98f8b28030684219a95f375cfbd88ce3405dff93" - -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - -is-callable@^1.0.4, is-callable@^1.1.1, is-callable@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2" - -is-date-object@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" - -is-dotfile@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" - -is-equal-shallow@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" - dependencies: - is-primitive "^2.0.0" - -is-equal@^1.5.1: - version "1.5.5" - resolved "https://registry.yarnpkg.com/is-equal/-/is-equal-1.5.5.tgz#5e85f1957e052883247feb386965a3bba15fbb3d" - dependencies: - has "^1.0.1" - is-arrow-function "^2.0.3" - is-boolean-object "^1.0.0" - is-callable "^1.1.3" - is-date-object "^1.0.1" - is-generator-function "^1.0.6" - is-number-object "^1.0.3" - is-regex "^1.0.3" - is-string "^1.0.4" - is-symbol "^1.0.1" - object.entries "^1.0.4" - -is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - -is-extglob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - -is-finite@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - -is-generator-function@^1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.7.tgz#d2132e529bb0000a7f80794d4bdf5cd5e5813522" - -is-glob@^2.0.0, is-glob@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - dependencies: - is-extglob "^1.0.0" - -is-my-ip-valid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz#7b351b8e8edd4d3995d4d066680e664d94696824" - -is-my-json-valid@^2.10.0: - version "2.17.2" - resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz#6b2103a288e94ef3de5cf15d29dd85fc4b78d65c" - dependencies: - generate-function "^2.0.0" - generate-object-property "^1.1.0" - is-my-ip-valid "^1.0.0" - jsonpointer "^4.0.0" - xtend "^4.0.0" - -is-number-object@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.3.tgz#f265ab89a9f445034ef6aff15a8f00b00f551799" - -is-number@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-0.1.1.tgz#69a7af116963d47206ec9bd9b48a14216f1e3806" - -is-number@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - dependencies: - kind-of "^3.0.2" - -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - dependencies: - kind-of "^3.0.2" - -is-path-cwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" - -is-path-in-cwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc" - dependencies: - is-path-inside "^1.0.0" - -is-path-inside@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" - dependencies: - path-is-inside "^1.0.1" - -is-posix-bracket@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" - -is-primitive@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" - -is-property@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" - -is-regex@^1.0.3, is-regex@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - dependencies: - has "^1.0.1" - -is-resolvable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" - -is-stream@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - -is-string@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.4.tgz#cc3a9b69857d621e963725a24caeec873b826e64" - -is-symbol@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" - -is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - -isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - -isbinaryfile@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.2.tgz#4a3e974ec0cba9004d3fc6cde7209ea69368a621" - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - dependencies: - isarray "1.0.0" - -isomorphic-fetch@^2.1.1, isomorphic-fetch@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" - dependencies: - node-fetch "^1.0.1" - whatwg-fetch ">=0.10.0" - -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - -jade@0.26.3: - version "0.26.3" - resolved "https://registry.yarnpkg.com/jade/-/jade-0.26.3.tgz#8f10d7977d8d79f2f6ff862a81b0513ccb25686c" - dependencies: - commander "0.6.1" - mkdirp "0.3.0" - -"jquery@>= 1.4.3", jquery@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca" - -js-tokens@^3.0.0, js-tokens@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - -js-yaml@^3.5.1: - version "3.11.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.11.0.tgz#597c1a8bd57152f26d622ce4117851a51f5ebaef" - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - -jsesc@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" - -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - -json-loader@^0.5.3: - version "0.5.7" - resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d" - -json-schema-traverse@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" - -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - -json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - dependencies: - jsonify "~0.0.0" - -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - -json3@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" - -json5@^0.5.0, json5@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - -jsonify@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - -jsonpointer@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" - -jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.2.3" - verror "1.10.0" - -jsx-ast-utils@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz#e801b1b39985e20fffc87b40e3748080e2dcac7f" - dependencies: - array-includes "^3.0.3" - -karma-chrome-launcher@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/karma-chrome-launcher/-/karma-chrome-launcher-0.2.3.tgz#4c6d700d163a9d34c618efd87918be49e7a4a8c9" - dependencies: - fs-access "^1.0.0" - which "^1.2.1" - -karma-cli@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/karma-cli/-/karma-cli-0.1.2.tgz#cacea84371ece19876265c8fa102ebbb9fee4a8c" - dependencies: - resolve "^1.1.6" - -karma-junit-reporter@^0.4.1: - version "0.4.2" - resolved "https://registry.yarnpkg.com/karma-junit-reporter/-/karma-junit-reporter-0.4.2.tgz#492a236728fe4c92aacf419fcd0110a4327e9d7f" - dependencies: - path-is-absolute "^1.0.0" - xmlbuilder "3.1.0" - -karma-logcapture-reporter@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/karma-logcapture-reporter/-/karma-logcapture-reporter-0.0.1.tgz#bf1b0b1c915e0de295a15fe2f0179d4281bacddc" - -karma-mocha@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/karma-mocha/-/karma-mocha-0.2.2.tgz#388ed917da15dcb196d1b915c1934ef803193f8e" - -karma-sourcemap-loader@^0.3.7: - version "0.3.7" - resolved "https://registry.yarnpkg.com/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz#91322c77f8f13d46fed062b042e1009d4c4505d8" - dependencies: - graceful-fs "^4.1.2" - -karma-spec-reporter@^0.0.31: - version "0.0.31" - resolved "https://registry.yarnpkg.com/karma-spec-reporter/-/karma-spec-reporter-0.0.31.tgz#4830dc7148a155c7d7a186e632339a0d80fadec3" - dependencies: - colors "^1.1.2" - -karma-summary-reporter@^1.3.3: - version "1.5.0" - resolved "https://registry.yarnpkg.com/karma-summary-reporter/-/karma-summary-reporter-1.5.0.tgz#dc570299c7074774e388e10fa5f9e58f7a45ec14" - dependencies: - chalk "^1.1.3 || 2.x" - -karma-webpack@^1.7.0: - version "1.8.1" - resolved "https://registry.yarnpkg.com/karma-webpack/-/karma-webpack-1.8.1.tgz#39d5fd2edeea3cc3ef5b405989b37d5b0e6a3b4e" - dependencies: - async "~0.9.0" - loader-utils "^0.2.5" - lodash "^3.8.0" - source-map "^0.1.41" - webpack-dev-middleware "^1.0.11" - -karma@^1.7.0: - version "1.7.1" - resolved "https://registry.yarnpkg.com/karma/-/karma-1.7.1.tgz#85cc08e9e0a22d7ce9cca37c4a1be824f6a2b1ae" - dependencies: - bluebird "^3.3.0" - body-parser "^1.16.1" - chokidar "^1.4.1" - colors "^1.1.0" - combine-lists "^1.0.0" - connect "^3.6.0" - core-js "^2.2.0" - di "^0.0.1" - dom-serialize "^2.2.0" - expand-braces "^0.1.1" - glob "^7.1.1" - graceful-fs "^4.1.2" - http-proxy "^1.13.0" - isbinaryfile "^3.0.0" - lodash "^3.8.0" - log4js "^0.6.31" - mime "^1.3.4" - minimatch "^3.0.2" - optimist "^0.6.1" - qjobs "^1.1.4" - range-parser "^1.2.0" - rimraf "^2.6.0" - safe-buffer "^5.0.1" - socket.io "1.7.3" - source-map "^0.5.3" - tmp "0.0.31" - useragent "^2.1.12" - -kind-of@^3.0.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - dependencies: - is-buffer "^1.1.5" - -lazy-cache@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" - -levn@^0.3.0, levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - -linkifyjs@^2.1.3: - version "2.1.6" - resolved "https://registry.yarnpkg.com/linkifyjs/-/linkifyjs-2.1.6.tgz#f1cc88a86ff8863196615857fd47eb193c0a26cb" - optionalDependencies: - jquery "^3.3.1" - react "^16.2.0" - react-dom "^16.2.0" - -loader-utils@^0.2.11, loader-utils@^0.2.16, loader-utils@^0.2.5, loader-utils@~0.2.2: - version "0.2.17" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" - dependencies: - big.js "^3.1.3" - emojis-list "^2.0.0" - json5 "^0.5.0" - object-assign "^4.0.1" - -lodash-es@^4.17.5, lodash-es@^4.2.1: - version "4.17.5" - resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.5.tgz#9fc6e737b1c4d151d8f9cae2247305d552ce748f" - -lodash.assign@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" - -lodash.clonedeep@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" - -lodash.escaperegexp@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347" - -lodash.isplainobject@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" - -lodash.isstring@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" - -lodash.mergewith@^4.6.0: - version "4.6.1" - resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz#639057e726c3afbdb3e7d42741caa8d6e4335927" - -lodash.pickby@^4.0.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.pickby/-/lodash.pickby-4.6.0.tgz#7dea21d8c18d7703a27c704c15d3b84a67e33aff" - -lodash@^3.5.0, lodash@^3.8.0: - version "3.10.1" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" - -lodash@^4.0.0, lodash@^4.13.1, lodash@^4.15.0, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.5.0: - version "4.17.5" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" - -log4js@^0.6.31: - version "0.6.38" - resolved "https://registry.yarnpkg.com/log4js/-/log4js-0.6.38.tgz#2c494116695d6fb25480943d3fc872e662a522fd" - dependencies: - readable-stream "~1.0.2" - semver "~4.3.3" - -lolex@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.3.2.tgz#7c3da62ffcb30f0f5a80a2566ca24e45d8a01f31" - -longest@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" - -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" - dependencies: - js-tokens "^3.0.0" - -lru-cache@2: - version "2.7.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952" - -lru-cache@4.1.x: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" - dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" - -matrix-js-sdk@0.9.2: - version "0.9.2" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-0.9.2.tgz#2a521bddcf637cbefde9138784e627ea43645b77" - dependencies: - another-json "^0.2.0" - babel-runtime "^6.26.0" - bluebird "^3.5.0" - browser-request "^0.3.3" - content-type "^1.0.2" - request "^2.53.0" - -matrix-react-test-utils@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/matrix-react-test-utils/-/matrix-react-test-utils-0.1.1.tgz#b548844d0ebe338ea1b9c8f16474c30d17c3bdf4" - dependencies: - react "^15.6.1" - react-dom "^15.6.1" - -"mdurl@~ 1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - -memoize-one@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-3.0.1.tgz#7b599850bb41be8beed305f4eefd963c8cea9a0a" - -memory-fs@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.2.0.tgz#f2bb25368bc121e391c2520de92969caee0a0290" - -memory-fs@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.3.0.tgz#7bcc6b629e3a43e871d7e29aca6ae8a7f15cbb20" - dependencies: - errno "^0.1.3" - readable-stream "^2.0.1" - -memory-fs@~0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" - dependencies: - errno "^0.1.3" - readable-stream "^2.0.1" - -micromatch@^2.1.5: - version "2.3.11" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" - dependencies: - arr-diff "^2.0.0" - array-unique "^0.2.1" - braces "^1.8.2" - expand-brackets "^0.1.4" - extglob "^0.3.1" - filename-regex "^2.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.1" - kind-of "^3.0.2" - normalize-path "^2.0.1" - object.omit "^2.0.0" - parse-glob "^3.0.4" - regex-cache "^0.4.2" - -mime-db@~1.33.0: - version "1.33.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" - -mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.7: - version "2.1.18" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" - dependencies: - mime-db "~1.33.0" - -mime@^1.3.4, mime@^1.5.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - -minimatch@0.3: - version "0.3.0" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.3.0.tgz#275d8edaac4f1bb3326472089e7949c8394699dd" - dependencies: - lru-cache "2" - sigmund "~1.0.0" - -"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - dependencies: - brace-expansion "^1.1.7" - -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - -minimist@^1.2.0, "minimist@~ 1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - -minimist@~0.0.1: - version "0.0.10" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" - -mkdirp@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" - -mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - dependencies: - minimist "0.0.8" - -mocha@^2.4.5: - version "2.5.3" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-2.5.3.tgz#161be5bdeb496771eb9b35745050b622b5aefc58" - dependencies: - commander "2.3.0" - debug "2.2.0" - diff "1.4.0" - escape-string-regexp "1.0.2" - glob "3.2.11" - growl "1.9.2" - jade "0.26.3" - mkdirp "0.5.1" - supports-color "1.2.0" - to-iso-string "0.0.2" - -ms@0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" - -ms@0.7.2: - version "0.7.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - -mute-stream@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0" - -nan@^2.3.0: - version "2.9.2" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.9.2.tgz#f564d75f5f8f36a6d9456cca7a6c4fe488ab7866" - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - -negotiator@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" - -node-fetch@^1.0.1: - version "1.7.3" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" - dependencies: - encoding "^0.1.11" - is-stream "^1.0.1" - -node-libs-browser@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-0.7.0.tgz#3e272c0819e308935e26674408d7af0e1491b83b" - dependencies: - assert "^1.1.1" - browserify-zlib "^0.1.4" - buffer "^4.9.0" - console-browserify "^1.1.0" - constants-browserify "^1.0.0" - crypto-browserify "3.3.0" - domain-browser "^1.1.1" - events "^1.0.0" - https-browserify "0.0.1" - os-browserify "^0.2.0" - path-browserify "0.0.0" - process "^0.11.0" - punycode "^1.2.4" - querystring-es3 "^0.2.0" - readable-stream "^2.0.5" - stream-browserify "^2.0.1" - stream-http "^2.3.1" - string_decoder "^0.10.25" - timers-browserify "^2.0.2" - tty-browserify "0.0.0" - url "^0.11.0" - util "^0.10.3" - vm-browserify "0.0.4" - -node-pre-gyp@^0.6.39: - version "0.6.39" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz#c00e96860b23c0e1420ac7befc5044e1d78d8649" - dependencies: - detect-libc "^1.0.2" - hawk "3.1.3" - mkdirp "^0.5.1" - nopt "^4.0.1" - npmlog "^4.0.2" - rc "^1.1.7" - request "2.81.0" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^2.2.1" - tar-pack "^3.4.0" - -nopt@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - dependencies: - abbrev "1" - osenv "^0.1.4" - -normalize-path@^2.0.0, normalize-path@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - dependencies: - remove-trailing-separator "^1.0.1" - -npmlog@^4.0.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - -null-check@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/null-check/-/null-check-1.0.0.tgz#977dffd7176012b9ec30d2a39db5cf72a0439edd" - -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - -oauth-sign@~0.8.1, oauth-sign@~0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" - -object-assign@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0" - -object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - -object-component@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291" - -object-inspect@^1.1.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.5.0.tgz#9d876c11e40f485c79215670281b767488f9bfe3" - -object-keys@^1.0.8, object-keys@^1.0.9: - version "1.0.11" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d" - -object.entries@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.0.4.tgz#1bf9a4dd2288f5b33f3a993d257661f05d161a5f" - dependencies: - define-properties "^1.1.2" - es-abstract "^1.6.1" - function-bind "^1.1.0" - has "^1.0.1" - -object.omit@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" - dependencies: - for-own "^0.1.4" - is-extendable "^0.1.1" - -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - dependencies: - ee-first "1.1.1" - -once@^1.3.0, once@^1.3.3: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - dependencies: - wrappy "1" - -onetime@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" - -optimist@^0.6.1, optimist@~0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" - dependencies: - minimist "~0.0.1" - wordwrap "~0.0.2" - -optionator@^0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.4" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - wordwrap "~1.0.0" - -options@>=0.0.5: - version "0.0.6" - resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f" - -os-browserify@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.2.1.tgz#63fc4ccee5d2d7763d26bbf8601078e6c2e0044f" - -os-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - -os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - -osenv@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" - -output-file-sync@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/output-file-sync/-/output-file-sync-1.1.2.tgz#d0a33eefe61a205facb90092e826598d5245ce76" - dependencies: - graceful-fs "^4.1.4" - mkdirp "^0.5.1" - object-assign "^4.1.0" - -pako@~0.2.0: - version "0.2.9" - resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" - -parallelshell@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/parallelshell/-/parallelshell-3.0.2.tgz#fffc55aaa145bdd44b5381cf7fd5e521fc21aa7b" - -parse-glob@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" - dependencies: - glob-base "^0.3.0" - is-dotfile "^1.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.0" - -parsejson@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/parsejson/-/parsejson-0.0.3.tgz#ab7e3759f209ece99437973f7d0f1f64ae0e64ab" - dependencies: - better-assert "~1.0.0" - -parseqs@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d" - dependencies: - better-assert "~1.0.0" - -parseuri@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.5.tgz#80204a50d4dbb779bfdc6ebe2778d90e4bce320a" - dependencies: - better-assert "~1.0.0" - -parseurl@~1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" - -path-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" - -path-exists@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - dependencies: - pinkie-promise "^2.0.0" - -path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - -path-is-inside@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - -path-parse@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" - -pbkdf2-compat@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pbkdf2-compat/-/pbkdf2-compat-2.0.1.tgz#b6e0c8fa99494d94e0511575802a59a5c142f288" - -performance-now@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" - -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - -pify@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - -pkg-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" - dependencies: - find-up "^1.0.0" - -pluralize@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" - -pluralizers@^0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/pluralizers/-/pluralizers-0.1.7.tgz#8d38dd0a1b660e739b10ab2eab10b684c9d50142" - -postcss@^6.0.14: - version "6.0.19" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.19.tgz#76a78386f670b9d9494a655bf23ac012effd1555" - dependencies: - chalk "^2.3.1" - source-map "^0.6.1" - supports-color "^5.2.0" - -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - -preserve@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" - -private@^0.1.6, private@^0.1.7: - version "0.1.8" - resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" - -process-nextick-args@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" - -process@^0.11.0: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - -progress@^1.1.8: - version "1.1.8" - resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" - -promise@^7.0.3, promise@^7.1.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" - dependencies: - asap "~2.0.3" - -prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0: - version "15.6.1" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.1.tgz#36644453564255ddda391191fb3a125cbdf654ca" - dependencies: - fbjs "^0.8.16" - loose-envify "^1.3.1" - object-assign "^4.1.1" - -prr@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" - -pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - -punycode@^1.2.4, punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - -qjobs@^1.1.4: - version "1.2.0" - resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.2.0.tgz#c45e9c61800bd087ef88d7e256423bdd49e5d071" - -qs@6.5.1, qs@~6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" - -qs@~6.4.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" - -querystring-es3@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" - -querystring@0.2.0, querystring@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - -raf-schd@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/raf-schd/-/raf-schd-2.1.0.tgz#64d645723380ec25cc1714e909b953ef1cf254bf" - -raf@^3.1.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.0.tgz#a28876881b4bc2ca9117d4138163ddb80f781575" - dependencies: - performance-now "^2.1.0" - -randomatic@^1.1.3: - version "1.1.7" - resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - -range-parser@^1.0.3, range-parser@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" - -raw-body@2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89" - dependencies: - bytes "3.0.0" - http-errors "1.6.2" - iconv-lite "0.4.19" - unpipe "1.0.0" - -rc@^1.1.7: - version "1.2.5" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.5.tgz#275cd687f6e3b36cc756baa26dfee80a790301fd" - dependencies: - deep-extend "~0.4.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -react-addons-css-transition-group@15.3.2: - version "15.3.2" - resolved "https://registry.yarnpkg.com/react-addons-css-transition-group/-/react-addons-css-transition-group-15.3.2.tgz#d8fa52bec9bb61bdfde8b9e4652b80297cbff667" - -react-addons-test-utils@^15.4.0: - version "15.6.2" - resolved "https://registry.yarnpkg.com/react-addons-test-utils/-/react-addons-test-utils-15.6.2.tgz#c12b6efdc2247c10da7b8770d185080a7b047156" - -react-beautiful-dnd@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/react-beautiful-dnd/-/react-beautiful-dnd-4.0.1.tgz#3b0a49bf6be75af351176c904f012611dd292b81" - dependencies: - babel-runtime "^6.26.0" - invariant "^2.2.2" - memoize-one "^3.0.1" - prop-types "^15.6.0" - raf-schd "^2.1.0" - react-motion "^0.5.2" - react-redux "^5.0.6" - redux "^3.7.2" - redux-thunk "^2.2.0" - reselect "^3.0.1" - -react-dom@^15.4.0, react-dom@^15.6.1: - version "15.6.2" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-15.6.2.tgz#41cfadf693b757faf2708443a1d1fd5a02bef730" - dependencies: - fbjs "^0.8.9" - loose-envify "^1.1.0" - object-assign "^4.1.0" - prop-types "^15.5.10" - -react-dom@^16.2.0: - version "16.2.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.2.0.tgz#69003178601c0ca19b709b33a83369fe6124c044" - dependencies: - fbjs "^0.8.16" - loose-envify "^1.1.0" - object-assign "^4.1.1" - prop-types "^15.6.0" - -react-gemini-scrollbar@matrix-org/react-gemini-scrollbar#5e97aef: - version "2.1.5" - resolved "https://codeload.github.com/matrix-org/react-gemini-scrollbar/tar.gz/5e97aef7e034efc8db1431f4b0efe3b26e249ae9" - dependencies: - gemini-scrollbar matrix-org/gemini-scrollbar#b302279 - -react-motion@^0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/react-motion/-/react-motion-0.5.2.tgz#0dd3a69e411316567927917c6626551ba0607316" - dependencies: - performance-now "^0.2.0" - prop-types "^15.5.8" - raf "^3.1.0" - -react-redux@^5.0.6: - version "5.0.7" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.7.tgz#0dc1076d9afb4670f993ffaef44b8f8c1155a4c8" - dependencies: - hoist-non-react-statics "^2.5.0" - invariant "^2.0.0" - lodash "^4.17.5" - lodash-es "^4.17.5" - loose-envify "^1.1.0" - prop-types "^15.6.0" - -react@^15.4.0, react@^15.6.1: - version "15.6.2" - resolved "https://registry.yarnpkg.com/react/-/react-15.6.2.tgz#dba0434ab439cfe82f108f0f511663908179aa72" - dependencies: - create-react-class "^15.6.0" - fbjs "^0.8.9" - loose-envify "^1.1.0" - object-assign "^4.1.0" - prop-types "^15.5.10" - -react@^16.2.0: - version "16.2.0" - resolved "https://registry.yarnpkg.com/react/-/react-16.2.0.tgz#a31bd2dab89bff65d42134fa187f24d054c273ba" - dependencies: - fbjs "^0.8.16" - loose-envify "^1.1.0" - object-assign "^4.1.1" - prop-types "^15.6.0" - -readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.2.2, readable-stream@^2.3.3: - version "2.3.5" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.5.tgz#b4f85003a938cbb6ecbce2a124fb1012bd1a838d" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.0.3" - util-deprecate "~1.0.1" - -readable-stream@~1.0.2: - version "1.0.34" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -readdirp@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78" - dependencies: - graceful-fs "^4.1.2" - minimatch "^3.0.2" - readable-stream "^2.0.2" - set-immediate-shim "^1.0.1" - -readline2@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35" - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - mute-stream "0.0.5" - -rechoir@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - dependencies: - resolve "^1.1.6" - -redux-thunk@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.2.0.tgz#e615a16e16b47a19a515766133d1e3e99b7852e5" - -redux@^3.7.2: - version "3.7.2" - resolved "https://registry.yarnpkg.com/redux/-/redux-3.7.2.tgz#06b73123215901d25d065be342eb026bc1c8537b" - dependencies: - lodash "^4.2.1" - lodash-es "^4.2.1" - loose-envify "^1.1.0" - symbol-observable "^1.0.3" - -regenerate@^1.2.1: - version "1.3.3" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.3.tgz#0c336d3980553d755c39b586ae3b20aa49c82b7f" - -regenerator-runtime@^0.10.5: - version "0.10.5" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" - -regenerator-runtime@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - -regenerator-transform@^0.10.0: - version "0.10.1" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" - dependencies: - babel-runtime "^6.18.0" - babel-types "^6.19.0" - private "^0.1.6" - -regex-cache@^0.4.2: - version "0.4.4" - resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" - dependencies: - is-equal-shallow "^0.1.3" - -regexpu-core@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" - dependencies: - regenerate "^1.2.1" - regjsgen "^0.2.0" - regjsparser "^0.1.4" - -regjsgen@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" - -regjsparser@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" - dependencies: - jsesc "~0.5.0" - -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - -repeat-element@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" - -repeat-string@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-0.2.2.tgz#c7a8d3236068362059a7e4651fc6884e8b1fb4ae" - -repeat-string@^1.5.2: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - -repeating@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - dependencies: - is-finite "^1.0.0" - -request@2.81.0: - version "2.81.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" - dependencies: - aws-sign2 "~0.6.0" - aws4 "^1.2.1" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.0" - forever-agent "~0.6.1" - form-data "~2.1.1" - har-validator "~4.2.1" - hawk "~3.1.3" - http-signature "~1.1.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.7" - oauth-sign "~0.8.1" - performance-now "^0.2.0" - qs "~6.4.0" - safe-buffer "^5.0.1" - stringstream "~0.0.4" - tough-cookie "~2.3.0" - tunnel-agent "^0.6.0" - uuid "^3.0.0" - -request@^2.53.0: - version "2.83.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.6.0" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.1" - forever-agent "~0.6.1" - form-data "~2.3.1" - har-validator "~5.0.3" - hawk "~6.0.2" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.17" - oauth-sign "~0.8.2" - performance-now "^2.1.0" - qs "~6.5.1" - safe-buffer "^5.1.1" - stringstream "~0.0.5" - tough-cookie "~2.3.3" - tunnel-agent "^0.6.0" - uuid "^3.1.0" - -require-json@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/require-json/-/require-json-0.0.1.tgz#3c8914f93d7442de8cbf4e681ac62a72aa3367fe" - -require-uncached@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" - dependencies: - caller-path "^0.1.0" - resolve-from "^1.0.0" - -requires-port@1.x.x: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - -reselect@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/reselect/-/reselect-3.0.1.tgz#efdaa98ea7451324d092b2b2163a6a1d7a9a2147" - -resolve-from@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" - -resolve@^1.1.6: - version "1.5.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" - dependencies: - path-parse "^1.0.5" - -restore-cursor@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" - dependencies: - exit-hook "^1.0.0" - onetime "^1.0.0" - -right-align@^0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" - dependencies: - align-text "^0.1.1" - -rimraf@2, rimraf@^2.2.8, rimraf@^2.4.3, rimraf@^2.5.1, rimraf@^2.6.0, rimraf@^2.6.1: - version "2.6.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" - dependencies: - glob "^7.0.5" - -ripemd160@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-0.2.0.tgz#2bf198bde167cacfa51c0a928e84b68bbe171fce" - -run-async@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389" - dependencies: - once "^1.3.0" - -rx-lite@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" - -safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" - -samsam@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.2.tgz#bec11fdc83a9fda063401210e40176c3024d1567" - -samsam@~1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.3.tgz#9f5087419b4d091f232571e7fa52e90b0f552621" - -sanitize-html@^1.14.1: - version "1.18.2" - resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-1.18.2.tgz#61877ba5a910327e42880a28803c2fbafa8e4642" - dependencies: - chalk "^2.3.0" - htmlparser2 "^3.9.0" - lodash.clonedeep "^4.5.0" - lodash.escaperegexp "^4.1.2" - lodash.isplainobject "^4.0.6" - lodash.isstring "^4.0.1" - lodash.mergewith "^4.6.0" - postcss "^6.0.14" - srcset "^1.0.0" - xtend "^4.0.0" - -semver@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" - -semver@~4.3.3: - version "4.3.6" - resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" - -set-blocking@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - -set-immediate-shim@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" - -setimmediate@^1.0.4, setimmediate@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - -setprototypeof@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04" - -sha.js@2.2.6: - version "2.2.6" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.2.6.tgz#17ddeddc5f722fb66501658895461977867315ba" - -shelljs@^0.7.5: - version "0.7.8" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" - dependencies: - glob "^7.0.0" - interpret "^1.0.0" - rechoir "^0.6.2" - -sigmund@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" - -signal-exit@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - -sinon@^1.17.3: - version "1.17.7" - resolved "https://registry.yarnpkg.com/sinon/-/sinon-1.17.7.tgz#4542a4f49ba0c45c05eb2e9dd9d203e2b8efe0bf" - dependencies: - formatio "1.1.1" - lolex "1.3.2" - samsam "1.1.2" - util ">=0.10.3 <1" - -slash@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" - -slice-ansi@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" - -sntp@1.x.x: - version "1.0.9" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" - dependencies: - hoek "2.x.x" - -sntp@2.x.x: - version "2.1.0" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-2.1.0.tgz#2c6cec14fedc2222739caf9b5c3d85d1cc5a2cc8" - dependencies: - hoek "4.x.x" - -socket.io-adapter@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-0.5.0.tgz#cb6d4bb8bec81e1078b99677f9ced0046066bb8b" - dependencies: - debug "2.3.3" - socket.io-parser "2.3.1" - -socket.io-client@1.7.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-1.7.3.tgz#b30e86aa10d5ef3546601c09cde4765e381da377" - dependencies: - backo2 "1.0.2" - component-bind "1.0.0" - component-emitter "1.2.1" - debug "2.3.3" - engine.io-client "1.8.3" - has-binary "0.1.7" - indexof "0.0.1" - object-component "0.0.3" - parseuri "0.0.5" - socket.io-parser "2.3.1" - to-array "0.1.4" - -socket.io-parser@2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-2.3.1.tgz#dd532025103ce429697326befd64005fcfe5b4a0" - dependencies: - component-emitter "1.1.2" - debug "2.2.0" - isarray "0.0.1" - json3 "3.3.2" - -socket.io@1.7.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-1.7.3.tgz#b8af9caba00949e568e369f1327ea9be9ea2461b" - dependencies: - debug "2.3.3" - engine.io "1.8.3" - has-binary "0.1.7" - object-assign "4.1.0" - socket.io-adapter "0.5.0" - socket.io-client "1.7.3" - socket.io-parser "2.3.1" - -source-list-map@~0.1.7: - version "0.1.8" - resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-0.1.8.tgz#c550b2ab5427f6b3f21f5afead88c4f5587b2106" - -source-map-loader@^0.1.5: - version "0.1.6" - resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-0.1.6.tgz#c09903da6d73b9e53b7ed8ee5245597051e98e91" - dependencies: - async "^0.9.0" - loader-utils "~0.2.2" - source-map "~0.1.33" - -source-map-support@^0.4.15: - version "0.4.18" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" - dependencies: - source-map "^0.5.6" - -source-map@^0.1.41, source-map@~0.1.33: - version "0.1.43" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" - dependencies: - amdefine ">=0.0.4" - -source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - -source-map@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - -source-map@~0.4.1: - version "0.4.4" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" - dependencies: - amdefine ">=0.0.4" - -sprintf-js@^1.0.3: - version "1.1.1" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.1.tgz#36be78320afe5801f6cea3ee78b6e5aab940ea0c" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - -srcset@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/srcset/-/srcset-1.0.0.tgz#a5669de12b42f3b1d5e83ed03c71046fc48f41ef" - dependencies: - array-uniq "^1.0.2" - number-is-nan "^1.0.0" - -sshpk@^1.7.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - dashdash "^1.12.0" - getpass "^0.1.1" - optionalDependencies: - bcrypt-pbkdf "^1.0.0" - ecc-jsbn "~0.1.1" - jsbn "~0.1.0" - tweetnacl "~0.14.0" - -"statuses@>= 1.3.1 < 2": - version "1.4.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" - -statuses@~1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" - -stream-browserify@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" - dependencies: - inherits "~2.0.1" - readable-stream "^2.0.2" - -stream-http@^2.3.1: - version "2.8.0" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.0.tgz#fd86546dac9b1c91aff8fc5d287b98fafb41bc10" - dependencies: - builtin-status-codes "^3.0.0" - inherits "^2.0.1" - readable-stream "^2.3.3" - to-arraybuffer "^1.0.0" - xtend "^4.0.0" - -string-width@^1.0.1, string-width@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -string-width@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string.prototype.repeat@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/string.prototype.repeat/-/string.prototype.repeat-0.2.0.tgz#aba36de08dcee6a5a337d49b2ea1da1b28fc0ecf" - -string_decoder@^0.10.25, string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - -string_decoder@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" - dependencies: - safe-buffer "~5.1.0" - -stringstream@~0.0.4, stringstream@~0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - dependencies: - ansi-regex "^3.0.0" - -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - -supports-color@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-1.2.0.tgz#ff1ed1e61169d06b3cf2d588e188b18d8847e17e" - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - -supports-color@^3.1.0: - version "3.2.3" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" - dependencies: - has-flag "^1.0.0" - -supports-color@^5.2.0, supports-color@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.3.0.tgz#5b24ac15db80fa927cf5227a4a33fd3c4c7676c0" - dependencies: - has-flag "^3.0.0" - -symbol-observable@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" - -table@^3.7.8: - version "3.8.3" - resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f" - dependencies: - ajv "^4.7.0" - ajv-keywords "^1.0.0" - chalk "^1.1.1" - lodash "^4.0.0" - slice-ansi "0.0.4" - string-width "^2.0.0" - -tapable@^0.1.8, tapable@~0.1.8: - version "0.1.10" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.1.10.tgz#29c35707c2b70e50d07482b5d202e8ed446dafd4" - -tar-pack@^3.4.0: - version "3.4.1" - resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.1.tgz#e1dbc03a9b9d3ba07e896ad027317eb679a10a1f" - dependencies: - debug "^2.2.0" - fstream "^1.0.10" - fstream-ignore "^1.0.5" - once "^1.3.3" - readable-stream "^2.1.4" - rimraf "^2.5.1" - tar "^2.2.1" - uid-number "^0.0.6" - -tar@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" - dependencies: - block-stream "*" - fstream "^1.0.2" - inherits "2" - -text-encoding-utf-8@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz#585b62197b0ae437e3c7b5d0af27ac1021e10d13" - -text-table@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - -through@^2.3.6: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - -time-stamp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-2.0.0.tgz#95c6a44530e15ba8d6f4a3ecb8c3a3fac46da357" - -timers-browserify@^2.0.2: - version "2.0.6" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.6.tgz#241e76927d9ca05f4d959819022f5b3664b64bae" - dependencies: - setimmediate "^1.0.4" - -tmatch@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/tmatch/-/tmatch-2.0.1.tgz#0c56246f33f30da1b8d3d72895abaf16660f38cf" - -tmp@0.0.31: - version "0.0.31" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7" - dependencies: - os-tmpdir "~1.0.1" - -tmp@0.0.x: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - dependencies: - os-tmpdir "~1.0.2" - -to-array@0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890" - -to-arraybuffer@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" - -to-fast-properties@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - -to-iso-string@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/to-iso-string/-/to-iso-string-0.0.2.tgz#4dc19e664dfccbe25bd8db508b00c6da158255d1" - -tough-cookie@~2.3.0, tough-cookie@~2.3.3: - version "2.3.4" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" - dependencies: - punycode "^1.4.1" - -trim-right@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - -tty-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - dependencies: - safe-buffer "^5.0.1" - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - dependencies: - prelude-ls "~1.1.2" - -type-is@~1.6.15: - version "1.6.16" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" - dependencies: - media-typer "0.3.0" - mime-types "~2.1.18" - -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - -ua-parser-js@^0.7.9: - version "0.7.17" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac" - -uglify-js@~2.7.3: - version "2.7.5" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.7.5.tgz#4612c0c7baaee2ba7c487de4904ae122079f2ca8" - dependencies: - async "~0.2.6" - source-map "~0.5.1" - uglify-to-browserify "~1.0.0" - yargs "~3.10.0" - -uglify-to-browserify@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" - -uid-number@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" - -ultron@1.0.x: - version "1.0.2" - resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa" - -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - -url@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - dependencies: - punycode "1.3.2" - querystring "0.2.0" - -user-home@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190" - -user-home@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f" - dependencies: - os-homedir "^1.0.0" - -useragent@^2.1.12: - version "2.3.0" - resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.3.0.tgz#217f943ad540cb2128658ab23fc960f6a88c9972" - dependencies: - lru-cache "4.1.x" - tmp "0.0.x" - -util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - -util@0.10.3, "util@>=0.10.3 <1", util@^0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - dependencies: - inherits "2.0.1" - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - -uuid@^3.0.0, uuid@^3.1.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" - -v8flags@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.1.1.tgz#aab1a1fa30d45f88dd321148875ac02c0b55e5b4" - dependencies: - user-home "^1.1.1" - -velocity-vector@vector-im/velocity#059e3b2: - version "1.2.3" - resolved "https://codeload.github.com/vector-im/velocity/tar.gz/059e3b2348f1110888d033974d3109fd5a3af00f" - dependencies: - jquery ">= 1.4.3" - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - -vm-browserify@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" - dependencies: - indexof "0.0.1" - -void-elements@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" - -walk@^2.3.9: - version "2.3.9" - resolved "https://registry.yarnpkg.com/walk/-/walk-2.3.9.tgz#31b4db6678f2ae01c39ea9fb8725a9031e558a7b" - dependencies: - foreachasync "^3.0.0" - -watchpack@^0.2.1: - version "0.2.9" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-0.2.9.tgz#62eaa4ab5e5ba35fdfc018275626e3c0f5e3fb0b" - dependencies: - async "^0.9.0" - chokidar "^1.0.0" - graceful-fs "^4.1.2" - -webpack-core@~0.6.9: - version "0.6.9" - resolved "https://registry.yarnpkg.com/webpack-core/-/webpack-core-0.6.9.tgz#fc571588c8558da77be9efb6debdc5a3b172bdc2" - dependencies: - source-list-map "~0.1.7" - source-map "~0.4.1" - -webpack-dev-middleware@^1.0.11: - version "1.12.2" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz#f8fc1120ce3b4fc5680ceecb43d777966b21105e" - dependencies: - memory-fs "~0.4.1" - mime "^1.5.0" - path-is-absolute "^1.0.0" - range-parser "^1.0.3" - time-stamp "^2.0.0" - -webpack@^1.12.14: - version "1.15.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-1.15.0.tgz#4ff31f53db03339e55164a9d468ee0324968fe98" - dependencies: - acorn "^3.0.0" - async "^1.3.0" - clone "^1.0.2" - enhanced-resolve "~0.9.0" - interpret "^0.6.4" - loader-utils "^0.2.11" - memory-fs "~0.3.0" - mkdirp "~0.5.0" - node-libs-browser "^0.7.0" - optimist "~0.6.0" - supports-color "^3.1.0" - tapable "~0.1.8" - uglify-js "~2.7.3" - watchpack "^0.2.1" - webpack-core "~0.6.9" - -whatwg-fetch@>=0.10.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84" - -whatwg-fetch@^0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-0.9.0.tgz#0e3684c6cb9995b43efc9df03e4c365d95fd9cc0" - -whatwg-fetch@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-1.1.1.tgz#ac3c9d39f320c6dce5339969d054ef43dd333319" - -which@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" - dependencies: - isexe "^2.0.0" - -wide-align@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710" - dependencies: - string-width "^1.0.2" - -window-size@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" - -wordwrap@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" - -wordwrap@~0.0.2: - version "0.0.3" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" - -wordwrap@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - -write@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" - dependencies: - mkdirp "^0.5.1" - -ws@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.2.tgz#8a244fa052401e08c9886cf44a85189e1fd4067f" - dependencies: - options ">=0.0.5" - ultron "1.0.x" - -wtf-8@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wtf-8/-/wtf-8-1.0.0.tgz#392d8ba2d0f1c34d1ee2d630f15d0efb68e1048a" - -xmlbuilder@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-3.1.0.tgz#2c86888f2d4eade850fa38ca7f7223f7209516e1" - dependencies: - lodash "^3.5.0" - -xmlhttprequest-ssl@1.5.3: - version "1.5.3" - resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz#185a888c04eca46c3e4070d99f7b49de3528992d" - -xtend@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - -yargs@~3.10.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" - dependencies: - camelcase "^1.0.2" - cliui "^2.1.0" - decamelize "^1.0.0" - window-size "0.1.0" - -yeast@0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" From c59dd5b840840ccbec02b7d8b252f02317313dfd Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 8 Mar 2018 12:31:01 +0000 Subject: [PATCH 121/170] Add placeholders for sticker images (and fancy transitions). --- src/components/views/messages/MImageBody.js | 6 ++ src/components/views/messages/MStickerBody.js | 79 +++++++++++++++++-- 2 files changed, 79 insertions(+), 6 deletions(-) diff --git a/src/components/views/messages/MImageBody.js b/src/components/views/messages/MImageBody.js index 55d5a18a25..ceede48554 100644 --- a/src/components/views/messages/MImageBody.js +++ b/src/components/views/messages/MImageBody.js @@ -192,6 +192,12 @@ export default class extends React.Component { }); }).done(); } + this._afterComponentDidMount(); + } + + // To be overridden by subclasses (e.g. MStickerBody) for further + // initialisation after componentDidMount + _afterComponentDidMount() { } componentWillUnmount() { diff --git a/src/components/views/messages/MStickerBody.js b/src/components/views/messages/MStickerBody.js index af39b1bd2d..ad6326a6a2 100644 --- a/src/components/views/messages/MStickerBody.js +++ b/src/components/views/messages/MStickerBody.js @@ -16,8 +16,9 @@ limitations under the License. 'use strict'; -import MImageBody from "./MImageBody"; +import MImageBody from './MImageBody'; import sdk from '../../../index'; +import TintableSVG from '../elements/TintableSvg'; export default class MStickerBody extends MImageBody { displayName: 'MStickerBody' @@ -27,6 +28,7 @@ export default class MStickerBody extends MImageBody { this._onMouseEnter = this._onMouseEnter.bind(this); this._onMouseLeave = this._onMouseLeave.bind(this); + this._onImageLoad = this._onImageLoad.bind(this); } _onMouseEnter() { @@ -37,6 +39,36 @@ export default class MStickerBody extends MImageBody { this.setState({showTooltip: false}); } + _onImageLoad() { + this.setState({ + placeholderClasses: 'mx_MStickerBody_placeholder_invisible', + }); + setTimeout(() => { + this.setState({ + placeholderVisible: false, + thumbnailClasses: 'mx_MStickerBody_thumbnail_visible', + }); + }, 500); + } + + _afterComponentDidMount() { + if (this.refs.image.complete) { + // Image already loaded + this.setState({ + placeholderVisible: false, + placeholderClasses: '.mx_MStickerBody_placeholder_invisible', + thumbnailClasses: 'mx_MStickerBody_thumbnail_visible', + }); + } else { + // Image not already loaded + this.setState({ + placeholderVisible: true, + placeholderClasses: '', + thumbnailClasses: '', + }); + } + } + _messageContent(contentUrl, thumbUrl, content) { let tooltip; const tooltipBody = ( @@ -45,18 +77,53 @@ export default class MStickerBody extends MImageBody { this.props.mxEvent.getContent().body) ? this.props.mxEvent.getContent().body : null; if (this.state.showTooltip && tooltipBody) { - const RoomTooltip = sdk.getComponent("rooms.RoomTooltip"); + const RoomTooltip = sdk.getComponent('rooms.RoomTooltip'); tooltip = ; } + const gutterSize = 0; + let placeholderSize = 75; + let placeholderFixupHeight = '100px'; + let placeholderTop = 0; + let placeholderLeft = 0; + + if (content.info) { + placeholderTop = Math.floor((content.info.h/2) - (placeholderSize/2)) + 'px'; + placeholderLeft = Math.floor((content.info.w/2) - (placeholderSize/2) + gutterSize) + 'px'; + placeholderFixupHeight = content.info.h + 'px'; + } + + placeholderSize = placeholderSize + 'px'; + console.warn('placeholder classes', this.state.placeholderClasses); + return ( - -
- +
+ +
+ +
+ {content.body} From 3ab8b1f8662fcc6c537ba78fbf23de0851feba46 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 8 Mar 2018 17:20:42 +0000 Subject: [PATCH 122/170] Hide sticker picker delete button and show minimise button. --- src/components/views/elements/AppTile.js | 22 ++++++++++++++++--- src/components/views/messages/MStickerBody.js | 1 - src/components/views/rooms/Stickerpicker.js | 5 ++++- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 6c9ea55142..0d209b1293 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -49,6 +49,7 @@ export default class AppTile extends React.Component { this._onDeleteClick = this._onDeleteClick.bind(this); this._onSnapshotClick = this._onSnapshotClick.bind(this); this.onClickMenuBar = this.onClickMenuBar.bind(this); + this._onMinimiseClick = this._onMinimiseClick.bind(this); } /** @@ -448,6 +449,12 @@ export default class AppTile extends React.Component { ); } + _onMinimiseClick(e) { + if (this.props.onMinimiseClick) { + this.props.onMinimiseClick(); + } + } + render() { let appTileBody; @@ -536,13 +543,14 @@ export default class AppTile extends React.Component {
{ this.props.showMenubar &&
- + { this.props.showMinimise && } { this.props.showTitle && this._getTileTitle() } @@ -568,14 +576,14 @@ export default class AppTile extends React.Component { /> } { /* Delete widget */ } - + /> }
} { appTileBody } @@ -607,10 +615,16 @@ AppTile.propTypes = { onEditClick: PropTypes.func, // Optional onDeleteClickHandler (overrides default behaviour) onDeleteClick: PropTypes.func, + // Optional onMinimiseClickHandler + onMinimiseClick: PropTypes.func, // Optionally hide the tile title showTitle: PropTypes.bool, // Optionally hide the tile minimise icon showMinimise: PropTypes.bool, + // Optionally handle minimise button pointer events (default false) + handleMinimisePointerEvents: PropTypes.bool, + // Optionally hide the delete icon + showDelete: PropTypes.bool, }; AppTile.defaultProps = { @@ -619,4 +633,6 @@ AppTile.defaultProps = { showMenubar: true, showTitle: true, showMinimise: true, + showDelete: true, + handleMinimisePointerEvents: false, }; diff --git a/src/components/views/messages/MStickerBody.js b/src/components/views/messages/MStickerBody.js index ad6326a6a2..71a808a3b7 100644 --- a/src/components/views/messages/MStickerBody.js +++ b/src/components/views/messages/MStickerBody.js @@ -96,7 +96,6 @@ export default class MStickerBody extends MImageBody { } placeholderSize = placeholderSize + 'px'; - console.warn('placeholder classes', this.state.placeholderClasses); return (
From fdec4b36c928f803db9f0ab686fb02c35cdff9bc Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 8 Mar 2018 17:25:28 +0000 Subject: [PATCH 123/170] Hide padding if last control. --- src/components/views/elements/AppTile.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 0d209b1293..01008b4f8e 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -568,7 +568,8 @@ export default class AppTile extends React.Component { { /* Edit widget */ } { showEditButton && Date: Thu, 8 Mar 2018 17:33:07 +0000 Subject: [PATCH 124/170] Fix context menu offset. --- src/components/views/rooms/Stickerpicker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index 11074976d9..76ef0a8753 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -187,7 +187,7 @@ export default class Stickerpicker extends React.Component { const buttonRect = e.target.getBoundingClientRect(); // The window X and Y offsets are to adjust position when zoomed in to page - const x = buttonRect.right + window.pageXOffset - 37; + const x = buttonRect.right + window.pageXOffset - 42; const y = (buttonRect.top + (buttonRect.height / 2) + window.pageYOffset) - 19; // const self = this; this.stickersMenu = ContextualMenu.createMenu(GenericElementContextMenu, { From e7c19fd83b271a1895266e5418c9bcdfeec3a498 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 8 Mar 2018 23:12:12 +0000 Subject: [PATCH 125/170] Don't render placeholder when image is visible. --- src/components/views/messages/MStickerBody.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/messages/MStickerBody.js b/src/components/views/messages/MStickerBody.js index 71a808a3b7..8b5e0d1043 100644 --- a/src/components/views/messages/MStickerBody.js +++ b/src/components/views/messages/MStickerBody.js @@ -103,7 +103,7 @@ export default class MStickerBody extends MImageBody { height: placeholderFixupHeight, }}>
- + { this.state.placeholderVisible &&
-
+
} Date: Fri, 9 Mar 2018 09:15:16 +0000 Subject: [PATCH 126/170] Use getUserWidgets where possible. --- src/ScalarMessaging.js | 7 ++----- src/utils/widgets.js | 18 ++++++++++++++---- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index 7a9f85a9e0..2411fc6e6d 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -335,10 +335,7 @@ function setWidget(event, roomId) { if (userWidget) { const client = MatrixClientPeg.get(); - let userWidgets = {}; - if (client.getAccountData('m.widgets')) { - userWidgets = client.getAccountData('m.widgets').getContent(); - } + const userWidgets = Widgets.getUserWidgets(); // Delete existing widget with ID try { @@ -408,7 +405,7 @@ function getWidgets(event, roomId) { } // Add user widgets (not linked to a specific room) - const userWidgets = Widgets.getUserWidgets(); + const userWidgets = Widgets.getUserWidgetsArray(); widgetStateEvents = widgetStateEvents.concat(userWidgets); sendResponse(event, widgetStateEvents); diff --git a/src/utils/widgets.js b/src/utils/widgets.js index da68abb4a9..c2eae88b17 100644 --- a/src/utils/widgets.js +++ b/src/utils/widgets.js @@ -7,7 +7,7 @@ import MatrixClientPeg from '../MatrixClientPeg'; */ function getWidgets(room) { const widgets = getRoomWidgets(room); - widgets.concat(getUserWidgets()); + widgets.concat(getUserWidgetsArray()); return widgets; } @@ -29,7 +29,7 @@ function getRoomWidgets(room) { /** * Get user specific widgets (not linked to a specific room) - * @return {[object]} Array containing current / active user widgets + * @return {object} Event content object containing current / active user widgets */ function getUserWidgets() { const client = MatrixClientPeg.get(); @@ -41,7 +41,16 @@ function getUserWidgets() { if (userWidgets && userWidgets.getContent()) { userWidgetContent = userWidgets.getContent(); } - return Object.keys(userWidgetContent).map((key) => userWidgetContent[key]); + return userWidgetContent; +} + +/** + * Get user specific widgets (not linked to a specific room) as an array + * @return {[object]} Array containing current / active user widgets + */ +function getUserWidgetsArray() { + const userWidgetContent = getUserWidgets(); + return Object.keys(userWidgetContent).map((key) => userWidgetContent[key]); } /** @@ -49,7 +58,7 @@ function getUserWidgets() { * @return {[object]} Array containing current / active stickerpicker widgets */ function getStickerpickerWidgets() { - const widgets = getUserWidgets(); + const widgets = getUserWidgetsArray(); const stickerpickerWidgets = widgets.filter((widget) => widget.type='m.stickerpicker'); return stickerpickerWidgets; } @@ -76,6 +85,7 @@ export default { getWidgets, getRoomWidgets, getUserWidgets, + getUserWidgetsArray, getStickerpickerWidgets, removeStickerpickerWidgets, }; From 7e062090dec9e37de11e86868dd5cfb85143aad5 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Fri, 9 Mar 2018 21:12:56 +0000 Subject: [PATCH 127/170] Cleanup timeout before unmount. --- src/components/views/messages/MImageBody.js | 6 ++++++ src/components/views/messages/MStickerBody.js | 10 +++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/components/views/messages/MImageBody.js b/src/components/views/messages/MImageBody.js index ceede48554..6a95b3c16e 100644 --- a/src/components/views/messages/MImageBody.js +++ b/src/components/views/messages/MImageBody.js @@ -204,6 +204,12 @@ export default class extends React.Component { this.unmounted = true; dis.unregister(this.dispatcherRef); this.context.matrixClient.removeListener('sync', this.onClientSync); + this._afterComponentWillUnmount(); + } + + // To be overridden by subclasses (e.g. MStickerBody) for further + // cleanup after componentWillUnmount + _afterComponentWillUnmount() { } onAction(payload) { diff --git a/src/components/views/messages/MStickerBody.js b/src/components/views/messages/MStickerBody.js index 8b5e0d1043..e1039ae66b 100644 --- a/src/components/views/messages/MStickerBody.js +++ b/src/components/views/messages/MStickerBody.js @@ -43,12 +43,13 @@ export default class MStickerBody extends MImageBody { this.setState({ placeholderClasses: 'mx_MStickerBody_placeholder_invisible', }); - setTimeout(() => { + const hidePlaceholderTimer = setTimeout(() => { this.setState({ placeholderVisible: false, thumbnailClasses: 'mx_MStickerBody_thumbnail_visible', }); }, 500); + this.setState({hidePlaceholderTimer}); } _afterComponentDidMount() { @@ -69,6 +70,13 @@ export default class MStickerBody extends MImageBody { } } + _afterComponentWillUnmount() { + if (this.state.hidePlaceholderTimer) { + clearTimeout(this.state.hidePlaceholderTimer); + this.setState({hidePlaceholderTimer: null}); + } + } + _messageContent(contentUrl, thumbUrl, content) { let tooltip; const tooltipBody = ( From 46f46ee2946b8a6253ebcbb2d893b25e2255a2de Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Fri, 9 Mar 2018 23:04:00 +0000 Subject: [PATCH 128/170] Simplify request mapping. --- src/MatrixPostMessageApi.js | 72 +++++++++++-------------------------- 1 file changed, 20 insertions(+), 52 deletions(-) diff --git a/src/MatrixPostMessageApi.js b/src/MatrixPostMessageApi.js index d6417f8764..303c7f596d 100644 --- a/src/MatrixPostMessageApi.js +++ b/src/MatrixPostMessageApi.js @@ -16,36 +16,6 @@ limitations under the License. import Promise from "bluebird"; -function defer() { - let resolve; - let reject; - let isPending = true; - const promise = new Promise(function(...args) { - resolve = args[0]; - reject = args[1]; - }); - return { - resolve: function(...args) { - if (!isPending) { - return; - } - isPending = false; - resolve(args[0]); - }, - reject: function(...args) { - if (!isPending) { - return; - } - isPending = false; - reject(args[0]); - }, - isPending: function() { - return isPending; - }, - promise: promise, - }; -} - // NOTE: PostMessageApi only handles message events with a data payload with a // response field export default class PostMessageApi { @@ -53,8 +23,8 @@ export default class PostMessageApi { this._window = targetWindow || window.parent; // default to parent window this._timeoutMs = timeoutMs || 5000; // default to 5s timer this._counter = 0; - this._pending = { - // $ID: Deferred + this._requestMap = { + // $ID: {resolve, reject} }; } @@ -82,15 +52,12 @@ export default class PostMessageApi { if (payload.response === undefined) { return; } - const deferred = self._pending[payload._id]; - if (!deferred) { + const promise = self._requestMap[payload._id]; + if (!promise) { return; } - if (!deferred.isPending()) { - return; - } - delete self._pending[payload._id]; - deferred.resolve(payload); + delete self._requestMap[payload._id]; + promise.resolve(payload); }; return this._onMsgCallback; } @@ -99,19 +66,20 @@ export default class PostMessageApi { this._counter += 1; target = target || "*"; action._id = Date.now() + "-" + Math.random().toString(36) + "-" + this._counter; - const d = defer(); - this._pending[action._id] = d; - this._window.postMessage(action, target); - if (this._timeoutMs > 0) { - setTimeout(function() { - if (!d.isPending()) { - return; - } - console.error("postMessage request timed out. Sent object: " + JSON.stringify(action)); - d.reject(new Error("Timed out")); - }, this._timeoutMs); - } - return d.promise; + return new Promise((resolve, reject) => { + this._requestMap[action._id] = {resolve, reject}; + this._window.postMessage(action, target); + + if (this._timeoutMs > 0) { + setTimeout(() => { + if (!this._requestMap[action._id]) { + return; + } + console.error("postMessage request timed out. Sent object: " + JSON.stringify(action)); + this._requestMap[action._id].reject(new Error("Timed out")); + }, this._timeoutMs); + } + }); } } From b2d23b6999333ae1922cfa66857e0311944c6392 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Mon, 12 Mar 2018 13:56:02 +0000 Subject: [PATCH 129/170] Switch to 'm.sticker' message events. Allow whitelisting of wisget capabilities. --- src/WidgetMessaging.js | 4 +- src/components/structures/FilePanel.js | 2 +- src/components/views/elements/AppTile.js | 43 +++++++++++++++---- src/components/views/messages/MessageEvent.js | 2 +- src/components/views/rooms/EventTile.js | 2 +- src/components/views/rooms/Stickerpicker.js | 1 + 6 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/WidgetMessaging.js b/src/WidgetMessaging.js index 50013a1c30..93fee6133b 100644 --- a/src/WidgetMessaging.js +++ b/src/WidgetMessaging.js @@ -195,8 +195,8 @@ export default class WidgetMessaging extends MatrixPostMessageApi { api: INBOUND_API_NAME, version: WIDGET_API_VERSION, }); - } else if (action === 'sticker_message') { - dis.dispatch({action: 'sticker_message', data: event.data.widgetData, widgetId: event.data.widgetId}); + } else if (action === 'm.sticker') { + dis.dispatch({action: 'm.sticker', data: event.data.widgetData, widgetId: event.data.widgetId}); } else if (action === 'integration_manager_open') { // Close the stickerpicker dis.dispatch({action: 'stickerpicker_close'}); diff --git a/src/components/structures/FilePanel.js b/src/components/structures/FilePanel.js index bd03683830..3249cae22c 100644 --- a/src/components/structures/FilePanel.js +++ b/src/components/structures/FilePanel.js @@ -69,7 +69,7 @@ const FilePanel = React.createClass({ "timeline": { "contains_url": true, "not_types": [ - "m.room.sticker", + "m.sticker", ], }, }, diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 01008b4f8e..e408d752a8 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -72,7 +72,9 @@ export default class AppTile extends React.Component { error: null, deleting: false, widgetPageTitle: newProps.widgetPageTitle, - capabilities: [], + allowedCapabilities: (this.props.whitelistCapabilities && this.props.whitelistCapabilities.length > 0) ? + this.props.whitelistCapabilities : [], + requestedCapabilities: [], }; } @@ -82,7 +84,7 @@ export default class AppTile extends React.Component { * @return {Boolean} True if capability supported */ _hasCapability(capability) { - return this.state.capabilities.some((c) => {return c === capability;}); + return this.state.allowedCapabilities.some((c) => {return c === capability;}); } /** @@ -341,10 +343,27 @@ export default class AppTile extends React.Component { this.widgetMessaging = new WidgetMessaging(this.props.id, this.refs.appFrame.contentWindow); this.widgetMessaging.startListening(); this.widgetMessaging.addEndpoint(this.props.id, this.props.url); - this.widgetMessaging.getCapabilities().then((capabilities) => { - console.log("Got widget capabilities", this.props.id, capabilities); - capabilities = capabilities || []; - this.setState({capabilities}); + this.widgetMessaging.getCapabilities().then((requestedCapabilities) => { + console.log(`Widget ${this.props.id} requested capabilities:`, requestedCapabilities); + requestedCapabilities = requestedCapabilities || []; + + // Allow whitelisted capabilities + const requestedWhitelistCapabilies = + requestedCapabilities.filter(function(e) { + return this.indexOf(e)>=0; + }, this.props.whitelistCapabilities); + console.warn(`Widget ${this.props.id} allowing requested, whitelisted properties:`, + requestedWhitelistCapabilies); + + // TODO -- Add UI to warn about and optionally allow requested capabilities + this.setState({ + requestedCapabilities, + allowedCapabilities: this.state.allowedCapabilities.concat(requestedWhitelistCapabilies), + }); + + if (this.props.onCapabilityRequest) { + this.props.onCapabilityRequest(requestedCapabilities); + } }).catch((err) => { console.log("Failed to get widget capabilities", this.widgetId, err); }); @@ -354,8 +373,8 @@ export default class AppTile extends React.Component { _onWidgetAction(payload) { if (payload.widgetId === this.props.id) { switch (payload.action) { - case 'sticker_message': - if (this._hasCapability('sticker_message')) { + case 'm.sticker': + if (this._hasCapability('m.sticker')) { dis.dispatch({action: 'post_sticker_message', data: payload.data}); } else { console.warn('Ignoring sticker message. Invalid capability'); @@ -626,6 +645,13 @@ AppTile.propTypes = { handleMinimisePointerEvents: PropTypes.bool, // Optionally hide the delete icon showDelete: PropTypes.bool, + // Widget apabilities to allow by default (without user confirmation) + // NOTE -- Use with caution. This is intended to aid better integration / UX + // basic widget capabilities, e.g. injecting sticker message events. + whitelistCapabilities: PropTypes.array, + // Optional function to be called on widget capability request + // Called with an array of the requested capabilities + onCapabilityRequest: PropTypes.func, }; AppTile.defaultProps = { @@ -636,4 +662,5 @@ AppTile.defaultProps = { showMinimise: true, showDelete: true, handleMinimisePointerEvents: false, + whitelistCapabilities: [], }; diff --git a/src/components/views/messages/MessageEvent.js b/src/components/views/messages/MessageEvent.js index 080a756db7..7358e297c7 100644 --- a/src/components/views/messages/MessageEvent.js +++ b/src/components/views/messages/MessageEvent.js @@ -65,7 +65,7 @@ module.exports = React.createClass({ let BodyType = UnknownBody; if (msgtype && bodyTypes[msgtype]) { BodyType = bodyTypes[msgtype]; - } else if (this.props.mxEvent.getType() === 'm.room.sticker') { + } else if (this.props.mxEvent.getType() === 'm.sticker') { BodyType = sdk.getComponent('messages.MStickerBody'); } else if (content.url) { // Fallback to MFileBody if there's a content URL diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index 50c8ddd67e..0d587b0e7b 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -36,7 +36,7 @@ const ObjectUtils = require('../../../ObjectUtils'); const eventTileTypes = { 'm.room.message': 'messages.MessageEvent', - 'm.room.sticker': 'messages.MessageEvent', + 'm.sticker': 'messages.MessageEvent', 'm.call.invite': 'messages.TextualEvent', 'm.call.answer': 'messages.TextualEvent', 'm.call.hangup': 'messages.TextualEvent', diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index 76ef0a8753..1171ad1ee0 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -159,6 +159,7 @@ export default class Stickerpicker extends React.Component { showDelete={false} onMinimiseClick={this.onHideStickersClick} handleMinimisePointerEvents={true} + whitelistCapabilities={['m.sticker']} />
From a81269cba850f6def5bb50bfcd3eeb9dc4efd538 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Tue, 13 Mar 2018 10:07:27 +0000 Subject: [PATCH 130/170] Check if user widget. --- src/ScalarMessaging.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index 2411fc6e6d..fdb163d81d 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -628,12 +628,14 @@ const onMessage = function(event) { // Get and set user widgets (not associated with a specific room) // If roomId is specified, it must be validated, so room-based widgets agreed // handled further down. - if (event.data.action === "get_widgets") { - getWidgets(event, null); - return; - } else if (event.data.action === "set_widget") { - setWidget(event, null); - return; + if (event.data.userWidget) { + if (event.data.action === "get_widgets") { + getWidgets(event, null); + return; + } else if (event.data.action === "set_widget") { + setWidget(event, null); + return; + } } if (!roomId) { @@ -661,10 +663,10 @@ const onMessage = function(event) { // Get and set room-based widgets if (event.data.action === "get_widgets") { - getWidgets(event, null); + getWidgets(event, roomId); return; } else if (event.data.action === "set_widget") { - setWidget(event, null); + setWidget(event, roomId); return; } From de3329400090302b2c4ac7c794a62e82adc5b098 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Tue, 13 Mar 2018 10:07:49 +0000 Subject: [PATCH 131/170] Center loading spinner. --- src/components/views/elements/AppTile.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index e408d752a8..afed9289f8 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -496,7 +496,7 @@ export default class AppTile extends React.Component { if (this.props.show) { const loadingElement = ( -
+
); @@ -511,7 +511,7 @@ export default class AppTile extends React.Component { ); } else { appTileBody = ( -
+
{ this.state.loading && loadingElement } { /* The "is" attribute in the following iframe tag is needed in order to enable rendering of the From 53b716bad648f2ad3148e31816a5ecf9f61f4b48 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Tue, 13 Mar 2018 10:51:01 +0000 Subject: [PATCH 132/170] Throw capability request exception. --- src/WidgetMessaging.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/WidgetMessaging.js b/src/WidgetMessaging.js index 93fee6133b..bae71bdc8f 100644 --- a/src/WidgetMessaging.js +++ b/src/WidgetMessaging.js @@ -277,8 +277,7 @@ export default class WidgetMessaging extends MatrixPostMessageApi { return this.exec({ api: OUTBOUND_API_NAME, action: "capabilities", - }).then((response) => response.capabilities) - .catch((error) => new Error("Failed to get capabilities: " + error.message)); + }).then((response) => response.capabilities); } } From f820374f9fd27433eb831192e83765998d2a08f4 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Tue, 13 Mar 2018 11:01:51 +0000 Subject: [PATCH 133/170] Logging. --- src/components/views/elements/AppTile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index afed9289f8..b29b2ae8a2 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -365,7 +365,7 @@ export default class AppTile extends React.Component { this.props.onCapabilityRequest(requestedCapabilities); } }).catch((err) => { - console.log("Failed to get widget capabilities", this.widgetId, err); + console.log(`Failed to get capabilities for widget type ${this.props.type}`, this.props.id, err); }); this.setState({loading: false}); } From 7d13edc67a84f746a62f9324ab947fe69733058f Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Tue, 13 Mar 2018 11:58:18 +0000 Subject: [PATCH 134/170] Get user widgets by default (if roomID is not specified). --- src/ScalarMessaging.js | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index fdb163d81d..351c178da4 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -624,24 +624,22 @@ const onMessage = function(event) { const roomId = event.data.room_id; const userId = event.data.user_id; - // These APIs don't require roomId - // Get and set user widgets (not associated with a specific room) - // If roomId is specified, it must be validated, so room-based widgets agreed - // handled further down. - if (event.data.userWidget) { + if (!roomId) { + // These APIs don't require roomId + // Get and set user widgets (not associated with a specific room) + // If roomId is specified, it must be validated, so room-based widgets agreed + // handled further down. if (event.data.action === "get_widgets") { getWidgets(event, null); return; } else if (event.data.action === "set_widget") { setWidget(event, null); return; + } else { + sendError(event, _t('Missing room_id in request')); + return; } } - - if (!roomId) { - sendError(event, _t('Missing room_id in request')); - return; - } let promise = Promise.resolve(currentRoomId); if (!currentRoomId) { if (!currentRoomAlias) { From 8b311c706c0b0aa8c8b105cb7597f638094117d3 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Tue, 13 Mar 2018 11:58:47 +0000 Subject: [PATCH 135/170] Null guard widget listener --- src/components/views/elements/AppTile.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index b29b2ae8a2..bedc9b09b9 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -170,8 +170,10 @@ export default class AppTile extends React.Component { // Widget postMessage listeners try { - this.widgetMessaging.stopListening(); - this.widgetMessaging.removeEndpoint(this.props.id, this.props.url); + if (this.widgetMessaging) { + this.widgetMessaging.stopListening(); + this.widgetMessaging.removeEndpoint(this.props.id, this.props.url); + } } catch (e) { console.error('Failed to stop listening for widgetMessaging events', e.message); } From 66ea78de6562468d07c916eb922b6047790bc5e5 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Tue, 13 Mar 2018 11:59:15 +0000 Subject: [PATCH 136/170] Clean up whitelisted permission addition / logging. --- src/components/views/elements/AppTile.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index bedc9b09b9..02f6beba9e 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -350,12 +350,18 @@ export default class AppTile extends React.Component { requestedCapabilities = requestedCapabilities || []; // Allow whitelisted capabilities - const requestedWhitelistCapabilies = - requestedCapabilities.filter(function(e) { + let requestedWhitelistCapabilies = []; + + if (this.props.whitelistCapabilities && this.props.whitelistCapabilities.length > 0) { + requestedWhitelistCapabilies = requestedCapabilities.filter(function(e) { return this.indexOf(e)>=0; }, this.props.whitelistCapabilities); - console.warn(`Widget ${this.props.id} allowing requested, whitelisted properties:`, - requestedWhitelistCapabilies); + + if (requestedWhitelistCapabilies.length > 0 ) { + console.warn(`Widget ${this.props.id} allowing requested, whitelisted properties:`, + requestedWhitelistCapabilies); + } + } // TODO -- Add UI to warn about and optionally allow requested capabilities this.setState({ From 83412acbe7c1b3a593b4a1dae66faa1948c2f472 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Wed, 14 Mar 2018 11:11:21 +0000 Subject: [PATCH 137/170] Display sticker content (URL), rather than thumbnail. --- src/components/views/messages/MStickerBody.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/views/messages/MStickerBody.js b/src/components/views/messages/MStickerBody.js index e1039ae66b..83d8309cf9 100644 --- a/src/components/views/messages/MStickerBody.js +++ b/src/components/views/messages/MStickerBody.js @@ -46,7 +46,7 @@ export default class MStickerBody extends MImageBody { const hidePlaceholderTimer = setTimeout(() => { this.setState({ placeholderVisible: false, - thumbnailClasses: 'mx_MStickerBody_thumbnail_visible', + imageClasses: 'mx_MStickerBody_image_visible', }); }, 500); this.setState({hidePlaceholderTimer}); @@ -58,14 +58,14 @@ export default class MStickerBody extends MImageBody { this.setState({ placeholderVisible: false, placeholderClasses: '.mx_MStickerBody_placeholder_invisible', - thumbnailClasses: 'mx_MStickerBody_thumbnail_visible', + imageClasses: 'mx_MStickerBody_image_visible', }); } else { // Image not already loaded this.setState({ placeholderVisible: true, placeholderClasses: '', - thumbnailClasses: '', + imageClasses: '', }); } } @@ -110,7 +110,7 @@ export default class MStickerBody extends MImageBody { style={{ height: placeholderFixupHeight, }}> -
+
{ this.state.placeholderVisible &&
} {content.body} Date: Fri, 16 Mar 2018 10:20:14 +0000 Subject: [PATCH 138/170] Allow react performance profiling on widget iframes. --- src/components/views/elements/AppTile.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 02f6beba9e..e7f44a8840 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -36,6 +36,7 @@ import WidgetUtils from '../../../WidgetUtils'; import dis from '../../../dispatcher'; const ALLOWED_APP_URL_SCHEMES = ['https:', 'http:']; +const ENABLE_REACT_PERF = false; export default class AppTile extends React.Component { constructor(props) { @@ -452,7 +453,11 @@ export default class AppTile extends React.Component { } _getSafeUrl() { - const parsedWidgetUrl = url.parse(this.state.widgetUrl); + const parsedWidgetUrl = url.parse(this.state.widgetUrl, true); + if (ENABLE_REACT_PERF) { + parsedWidgetUrl.search = null; + parsedWidgetUrl.query.react_perf = true; + } let safeWidgetUrl = ''; if (ALLOWED_APP_URL_SCHEMES.indexOf(parsedWidgetUrl.protocol) !== -1) { safeWidgetUrl = url.format(parsedWidgetUrl); From 4ac9653ab93ceed990b0c914d78113823bc756c8 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Wed, 28 Mar 2018 12:22:06 +0100 Subject: [PATCH 140/170] Refactor widget postMessage API. --- src/FromWidgetPostMessageApi.js | 201 ++++++++++++++++ src/MatrixPostMessageApi.js | 85 ------- src/ToWidgetPostMessageApi.js | 86 +++++++ src/WidgetMessaging.js | 278 ++++------------------- src/WidgetMessagingEndpoint.js | 37 +++ src/components/views/elements/AppTile.js | 35 +-- 6 files changed, 386 insertions(+), 336 deletions(-) create mode 100644 src/FromWidgetPostMessageApi.js delete mode 100644 src/MatrixPostMessageApi.js create mode 100644 src/ToWidgetPostMessageApi.js create mode 100644 src/WidgetMessagingEndpoint.js diff --git a/src/FromWidgetPostMessageApi.js b/src/FromWidgetPostMessageApi.js new file mode 100644 index 0000000000..ad1f1acbbd --- /dev/null +++ b/src/FromWidgetPostMessageApi.js @@ -0,0 +1,201 @@ +/* +Copyright 2018 New Vector 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. +*/ + +import URL from 'url'; +import dis from './dispatcher'; +import IntegrationManager from './IntegrationManager'; +import WidgetMessagingEndpoint from './WidgetMessagingEndpoint'; + +const WIDGET_API_VERSION = '0.0.1'; // Current API version +const SUPPORTED_WIDGET_API_VERSIONS = [ + '0.0.1', +]; +const INBOUND_API_NAME = 'fromWidget'; + +// Listen for and handle incomming requests using the 'fromWidget' postMessage +// API and initiate responses +export default class FromWidgetPostMessageApi { + constructor() { + this.widgetMessagingEndpoints = []; + + this.start = this.start.bind(this); + this.stop = this.stop.bind(this); + this.onPostMessage = this.onPostMessage.bind(this); + } + + start() { + window.addEventListener('message', this.onPostMessage); + } + + stop() { + window.removeEventListener('message', this.onPostMessage); + } + + /** + * Register a widget endpoint for trusted postMessage communication + * @param {string} widgetId Unique widget identifier + * @param {string} endpointUrl Widget wurl origin (protocol + (optional port) + host) + */ + addEndpoint(widgetId, endpointUrl) { + const u = URL.parse(endpointUrl); + if (!u || !u.protocol || !u.host) { + console.warn('Add FromWidgetPostMessageApi endpoint - Invalid origin:', endpointUrl); + return; + } + + const origin = u.protocol + '//' + u.host; + const endpoint = new WidgetMessagingEndpoint(widgetId, origin); + if (this.widgetMessagingEndpoints.some(function(ep) { + return (ep.widgetId === widgetId && ep.endpointUrl === endpointUrl); + })) { + // Message endpoint already registered + console.warn('Add FromWidgetPostMessageApi - Endpoint already registered'); + return; + } else { + console.warn(`Adding fromWidget messaging endpoint for ${widgetId}`, endpoint); + this.widgetMessagingEndpoints.push(endpoint); + } + } + + /** + * De-register a widget endpoint from trusted communication sources + * @param {string} widgetId Unique widget identifier + * @param {string} endpointUrl Widget wurl origin (protocol + (optional port) + host) + * @return {boolean} True if endpoint was successfully removed + */ + removeEndpoint(widgetId, endpointUrl) { + const u = URL.parse(endpointUrl); + if (!u || !u.protocol || !u.host) { + console.warn('Remove widget messaging endpoint - Invalid origin'); + return; + } + + const origin = u.protocol + '//' + u.host; + if (this.widgetMessagingEndpoints && this.widgetMessagingEndpoints.length > 0) { + const length = this.widgetMessagingEndpoints.length; + this.widgetMessagingEndpoints = this.widgetMessagingEndpoints. + filter(function(endpoint) { + return (endpoint.widgetId != widgetId || endpoint.endpointUrl != origin); + }); + return (length > this.widgetMessagingEndpoints.length); + } + return false; + } + + /** + * Handle widget postMessage events + * Messages are only handled where a valid, registered messaging endpoints + * @param {Event} event Event to handle + * @return {undefined} + */ + onPostMessage(event) { + if (!event.origin) { // Handle chrome + event.origin = event.originalEvent.origin; + } + + // Event origin is empty string if undefined + if ( + event.origin.length === 0 || + !this.trustedEndpoint(event.origin) || + event.data.api !== INBOUND_API_NAME || + !event.data.widgetId + ) { + return; // don't log this - debugging APIs like to spam postMessage which floods the log otherwise + } + + const action = event.data.action; + const widgetId = event.data.widgetId; + if (action === 'content_loaded') { + console.warn('Widget reported content loaded for', widgetId); + dis.dispatch({ + action: 'widget_content_loaded', + widgetId: widgetId, + }); + this.sendResponse(event, {success: true}); + } else if (action === 'supported_api_versions') { + this.sendResponse(event, { + api: INBOUND_API_NAME, + supported_versions: SUPPORTED_WIDGET_API_VERSIONS, + }); + } else if (action === 'api_version') { + this.sendResponse(event, { + api: INBOUND_API_NAME, + version: WIDGET_API_VERSION, + }); + } else if (action === 'm.sticker') { + // console.warn('Got sticker message from widget', widgetId); + dis.dispatch({action: 'm.sticker', data: event.data.widgetData, widgetId: event.data.widgetId}); + } else if (action === 'integration_manager_open') { + // Close the stickerpicker + dis.dispatch({action: 'stickerpicker_close'}); + // Open the integration manager + const data = event.data.widgetData; + const integType = (data && data.integType) ? data.integType : null; + const integId = (data && data.integId) ? data.integId : null; + IntegrationManager.open(integType, integId); + } else { + console.warn('Widget postMessage event unhandled'); + this.sendError(event, {message: 'The postMessage was unhandled'}); + } + } + + /** + * Check if message origin is registered as trusted + * @param {string} origin PostMessage origin to check + * @return {boolean} True if trusted + */ + trustedEndpoint(origin) { + if (!origin) { + return false; + } + + return this.widgetMessagingEndpoints.some((endpoint) => { + // TODO / FIXME -- Should this also check the widgetId? + return endpoint.endpointUrl === origin; + }); + } + + /** + * Send a postmessage response to a postMessage request + * @param {Event} event The original postMessage request event + * @param {Object} res Response data + */ + sendResponse(event, res) { + const data = JSON.parse(JSON.stringify(event.data)); + data.response = res; + event.source.postMessage(data, event.origin); + } + + /** + * Send an error response to a postMessage request + * @param {Event} event The original postMessage request event + * @param {string} msg Error message + * @param {Error} nestedError Nested error event (optional) + */ + sendError(event, msg, nestedError) { + console.error('Action:' + event.data.action + ' failed with message: ' + msg); + const data = JSON.parse(JSON.stringify(event.data)); + data.response = { + error: { + message: msg, + }, + }; + if (nestedError) { + data.response.error._error = nestedError; + } + event.source.postMessage(data, event.origin); + } +} diff --git a/src/MatrixPostMessageApi.js b/src/MatrixPostMessageApi.js deleted file mode 100644 index 303c7f596d..0000000000 --- a/src/MatrixPostMessageApi.js +++ /dev/null @@ -1,85 +0,0 @@ -/* -Copyright 2017 New Vector 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. -*/ - -import Promise from "bluebird"; - -// NOTE: PostMessageApi only handles message events with a data payload with a -// response field -export default class PostMessageApi { - constructor(targetWindow, timeoutMs) { - this._window = targetWindow || window.parent; // default to parent window - this._timeoutMs = timeoutMs || 5000; // default to 5s timer - this._counter = 0; - this._requestMap = { - // $ID: {resolve, reject} - }; - } - - start() { - addEventListener('message', this.getOnMessageCallback()); - } - - stop() { - removeEventListener('message', this.getOnMessageCallback()); - } - - // Somewhat convoluted so we can successfully capture the PostMessageApi 'this' instance. - getOnMessageCallback() { - if (this._onMsgCallback) { - return this._onMsgCallback; - } - const self = this; - this._onMsgCallback = function(ev) { - // THIS IS ALL UNSAFE EXECUTION. - // We do not verify who the sender of `ev` is! - const payload = ev.data; - // NOTE: Workaround for running in a mobile WebView where a - // postMessage immediately triggers this callback even though it is - // not the response. - if (payload.response === undefined) { - return; - } - const promise = self._requestMap[payload._id]; - if (!promise) { - return; - } - delete self._requestMap[payload._id]; - promise.resolve(payload); - }; - return this._onMsgCallback; - } - - exec(action, target) { - this._counter += 1; - target = target || "*"; - action._id = Date.now() + "-" + Math.random().toString(36) + "-" + this._counter; - - return new Promise((resolve, reject) => { - this._requestMap[action._id] = {resolve, reject}; - this._window.postMessage(action, target); - - if (this._timeoutMs > 0) { - setTimeout(() => { - if (!this._requestMap[action._id]) { - return; - } - console.error("postMessage request timed out. Sent object: " + JSON.stringify(action)); - this._requestMap[action._id].reject(new Error("Timed out")); - }, this._timeoutMs); - } - }); - } -} diff --git a/src/ToWidgetPostMessageApi.js b/src/ToWidgetPostMessageApi.js new file mode 100644 index 0000000000..ccaa0207c1 --- /dev/null +++ b/src/ToWidgetPostMessageApi.js @@ -0,0 +1,86 @@ +/* +Copyright 2018 New Vector 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. +*/ + +import Promise from "bluebird"; + +// const OUTBOUND_API_NAME = 'toWidget'; + +// Initiate requests using the "toWidget" postMessage API and handle responses +// NOTE: ToWidgetPostMessageApi only handles message events with a data payload with a +// response field +export default class ToWidgetPostMessageApi { + constructor(timeoutMs) { + this._timeoutMs = timeoutMs || 5000; // default to 5s timer + this._counter = 0; + this._requestMap = { + // $ID: {resolve, reject} + }; + this.start = this.start.bind(this); + this.stop = this.stop.bind(this); + this.onPostMessage = this.onPostMessage.bind(this); + } + + start() { + window.addEventListener('message', this.onPostMessage); + } + + stop() { + window.removeEventListener('message', this.onPostMessage); + } + + onPostMessage(ev) { + // THIS IS ALL UNSAFE EXECUTION. + // We do not verify who the sender of `ev` is! + const payload = ev.data; + // NOTE: Workaround for running in a mobile WebView where a + // postMessage immediately triggers this callback even though it is + // not the response. + if (payload.response === undefined) { + return; + } + const promise = this._requestMap[payload._id]; + if (!promise) { + return; + } + delete this._requestMap[payload._id]; + promise.resolve(payload); + } + + // Initiate outbound requests (toWidget) + exec(action, targetWindow, targetOrigin) { + targetWindow = targetWindow || window.parent; // default to parent window + targetOrigin = targetOrigin || "*"; + this._counter += 1; + action._id = Date.now() + "-" + Math.random().toString(36) + "-" + this._counter; + + return new Promise((resolve, reject) => { + this._requestMap[action._id] = {resolve, reject}; + targetWindow.postMessage(action, targetOrigin); + + if (this._timeoutMs > 0) { + setTimeout(() => { + if (!this._requestMap[action._id]) { + return; + } + console.error("postMessage request timed out. Sent object: " + JSON.stringify(action), + this._requestMap); + this._requestMap[action._id].reject(new Error("Timed out")); + delete this._requestMap[action._id]; + }, this._timeoutMs); + } + }); + } +} diff --git a/src/WidgetMessaging.js b/src/WidgetMessaging.js index bae71bdc8f..effd96dacf 100644 --- a/src/WidgetMessaging.js +++ b/src/WidgetMessaging.js @@ -19,38 +19,33 @@ limitations under the License. * spec. details / documentation. */ -import URL from 'url'; -import dis from './dispatcher'; -import MatrixPostMessageApi from './MatrixPostMessageApi'; -import IntegrationManager from './IntegrationManager'; +import FromWidgetPostMessageApi from './FromWidgetPostMessageApi'; +import ToWidgetPostMessageApi from './ToWidgetPostMessageApi'; + +if (!global.mxFromWidgetMessaging) { + global.mxFromWidgetMessaging = new FromWidgetPostMessageApi(); + global.mxFromWidgetMessaging.start(); +} +if (!global.mxToWidgetMessaging) { + global.mxToWidgetMessaging = new ToWidgetPostMessageApi(); + global.mxToWidgetMessaging.start(); +} -const WIDGET_API_VERSION = '0.0.1'; // Current API version -const SUPPORTED_WIDGET_API_VERSIONS = [ - '0.0.1', -]; -const INBOUND_API_NAME = 'fromWidget'; const OUTBOUND_API_NAME = 'toWidget'; -if (!global.mxWidgetMessagingListenerCount) { - global.mxWidgetMessagingListenerCount = 0; -} -if (!global.mxWidgetMessagingMessageEndpoints) { - global.mxWidgetMessagingMessageEndpoints = []; -} - -export default class WidgetMessaging extends MatrixPostMessageApi { - constructor(widgetId, targetWindow) { - super(targetWindow); +export default class WidgetMessaging { + constructor(widgetId, widgetUrl, target) { this.widgetId = widgetId; - - this.startListening = this.startListening.bind(this); - this.stopListening = this.stopListening.bind(this); - this.onMessage = this.onMessage.bind(this); + this.widgetUrl = widgetUrl; + this.target = target; + this.fromWidget = global.mxFromWidgetMessaging; + this.toWidget = global.mxToWidgetMessaging; + this.start(); } - exec(action) { - return super.exec(action).then((data) => { - // check for errors and reject if found + messageToWidget(action) { + return this.toWidget.exec(action, this.target).then((data) => { + // Check for errors and reject if found if (data.response === undefined) { // null is valid throw new Error("Missing 'response' field"); } @@ -65,208 +60,23 @@ export default class WidgetMessaging extends MatrixPostMessageApi { // We can't aggressively sanitize [A-z0-9] since it might be a translation. throw new Error(msg); } - // return the response field for the request + // Return the response field for the request return data.response; }); } - /** - * Register widget message event listeners - */ - startListening() { - if (global.mxWidgetMessagingListenerCount === 0) { - // Start postMessage API listener - this.start(); - // Start widget specific listener - window.addEventListener("message", this.onMessage, false); - } - global.mxWidgetMessagingListenerCount += 1; - } - - /** - * De-register widget message event listeners - */ - stopListening() { - global.mxWidgetMessagingListenerCount -= 1; - if (global.mxWidgetMessagingListenerCount === 0) { - // Stop widget specific listener - window.removeEventListener("message", this.onMessage, false); - // Stop postMessage API listener - this.stop(); - } - if (global.mxWidgetMessagingListenerCount < 0) { - // Make an error so we get a stack trace - const e = new Error( - "WidgetMessaging: mismatched startListening / stopListening detected." + - " Negative count", - ); - console.error(e); - } - } - - /** - * Register a widget endpoint for trusted postMessage communication - * @param {string} widgetId Unique widget identifier - * @param {string} endpointUrl Widget wurl origin (protocol + (optional port) + host) - */ - addEndpoint(widgetId, endpointUrl) { - const u = URL.parse(endpointUrl); - if (!u || !u.protocol || !u.host) { - console.warn("Invalid origin:", endpointUrl); - return; - } - - const origin = u.protocol + '//' + u.host; - const endpoint = new WidgetMessageEndpoint(widgetId, origin); - if (global.mxWidgetMessagingMessageEndpoints) { - if (global.mxWidgetMessagingMessageEndpoints.some(function(ep) { - return (ep.widgetId === widgetId && ep.endpointUrl === endpointUrl); - })) { - // Message endpoint already registered - console.warn("Endpoint already registered"); - return; - } else { - // console.warn(`Adding widget messaging endpoint for ${widgetId}`); - global.mxWidgetMessagingMessageEndpoints.push(endpoint); - } - } - } - - /** - * De-register a widget endpoint from trusted communication sources - * @param {string} widgetId Unique widget identifier - * @param {string} endpointUrl Widget wurl origin (protocol + (optional port) + host) - * @return {boolean} True if endpoint was successfully removed - */ - removeEndpoint(widgetId, endpointUrl) { - const u = URL.parse(endpointUrl); - if (!u || !u.protocol || !u.host) { - console.warn("Invalid origin"); - return; - } - - const origin = u.protocol + '//' + u.host; - if (global.mxWidgetMessagingMessageEndpoints && global.mxWidgetMessagingMessageEndpoints.length > 0) { - const length = global.mxWidgetMessagingMessageEndpoints.length; - global.mxWidgetMessagingMessageEndpoints = global.mxWidgetMessagingMessageEndpoints. - filter(function(endpoint) { - return (endpoint.widgetId != widgetId || endpoint.endpointUrl != origin); - }); - return (length > global.mxWidgetMessagingMessageEndpoints.length); - } - return false; - } - - /** - * Handle widget postMessage events - * @param {Event} event Event to handle - * @return {undefined} - */ - onMessage(event) { - if (!event.origin) { // Handle chrome - event.origin = event.originalEvent.origin; - } - - // Event origin is empty string if undefined - if ( - event.origin.length === 0 || - !this.trustedEndpoint(event.origin) || - event.data.api !== INBOUND_API_NAME || - !event.data.widgetId - ) { - return; // don't log this - debugging APIs like to spam postMessage which floods the log otherwise - } - - const action = event.data.action; - const widgetId = event.data.widgetId; - if (action === 'content_loaded') { - dis.dispatch({ - action: 'widget_content_loaded', - widgetId: widgetId, - }); - this.sendResponse(event, {success: true}); - } else if (action === 'supported_api_versions') { - this.sendResponse(event, { - api: INBOUND_API_NAME, - supported_versions: SUPPORTED_WIDGET_API_VERSIONS, - }); - } else if (action === 'api_version') { - this.sendResponse(event, { - api: INBOUND_API_NAME, - version: WIDGET_API_VERSION, - }); - } else if (action === 'm.sticker') { - dis.dispatch({action: 'm.sticker', data: event.data.widgetData, widgetId: event.data.widgetId}); - } else if (action === 'integration_manager_open') { - // Close the stickerpicker - dis.dispatch({action: 'stickerpicker_close'}); - // Open the integration manager - const data = event.data.widgetData; - const integType = (data && data.integType) ? data.integType : null; - const integId = (data && data.integId) ? data.integId : null; - IntegrationManager.open(integType, integId); - } else { - console.warn("Widget postMessage event unhandled"); - this.sendError(event, {message: "The postMessage was unhandled"}); - } - } - - /** - * Check if message origin is registered as trusted - * @param {string} origin PostMessage origin to check - * @return {boolean} True if trusted - */ - trustedEndpoint(origin) { - if (!origin) { - return false; - } - - return global.mxWidgetMessagingMessageEndpoints.some((endpoint) => { - return endpoint.endpointUrl === origin; - }); - } - - /** - * Send a postmessage response to a postMessage request - * @param {Event} event The original postMessage request event - * @param {Object} res Response data - */ - sendResponse(event, res) { - const data = JSON.parse(JSON.stringify(event.data)); - data.response = res; - event.source.postMessage(data, event.origin); - } - - /** - * Send an error response to a postMessage request - * @param {Event} event The original postMessage request event - * @param {string} msg Error message - * @param {Error} nestedError Nested error event (optional) - */ - sendError(event, msg, nestedError) { - console.error("Action:" + event.data.action + " failed with message: " + msg); - const data = JSON.parse(JSON.stringify(event.data)); - data.response = { - error: { - message: msg, - }, - }; - if (nestedError) { - data.response.error._error = nestedError; - } - event.source.postMessage(data, event.origin); - } - /** * Request a screenshot from a widget * @return {Promise} To be resolved with screenshot data when it has been generated */ getScreenshot() { - return this.exec({ + console.warn('Requesting screenshot for', this.widgetId); + return this.messageToWidget({ api: OUTBOUND_API_NAME, action: "screenshot", - }).then((response) => response.screenshot) - .catch((error) => new Error("Failed to get screenshot: " + error.message)); + }) + .catch((error) => new Error("Failed to get screenshot: " + error.message)) + .then((response) => response.screenshot); } /** @@ -274,30 +84,22 @@ export default class WidgetMessaging extends MatrixPostMessageApi { * @return {Promise} To be resolved with an array of requested widget capabilities */ getCapabilities() { - return this.exec({ + console.warn('Requesting capabilities for', this.widgetId); + return this.messageToWidget({ api: OUTBOUND_API_NAME, action: "capabilities", - }).then((response) => response.capabilities); + }).then((response) => { + console.warn('Got capabilities for', this.widgetId, response.capabilities); + return response.capabilities; + }); } -} -/** - * Represents mapping of widget instance to URLs for trusted postMessage communication. - */ -class WidgetMessageEndpoint { - /** - * Mapping of widget instance to URL for trusted postMessage communication. - * @param {string} widgetId Unique widget identifier - * @param {string} endpointUrl Widget wurl origin. - */ - constructor(widgetId, endpointUrl) { - if (!widgetId) { - throw new Error("No widgetId specified in widgetMessageEndpoint constructor"); - } - if (!endpointUrl) { - throw new Error("No endpoint specified in widgetMessageEndpoint constructor"); - } - this.widgetId = widgetId; - this.endpointUrl = endpointUrl; + + start() { + this.fromWidget.addEndpoint(this.widgetId, this.widgetUrl); + } + + stop() { + this.fromWidget.removeEndpoint(this.widgetId, this.widgetUrl); } } diff --git a/src/WidgetMessagingEndpoint.js b/src/WidgetMessagingEndpoint.js new file mode 100644 index 0000000000..9114e12137 --- /dev/null +++ b/src/WidgetMessagingEndpoint.js @@ -0,0 +1,37 @@ +/* +Copyright 2018 New Vector 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. +*/ + + +/** + * Represents mapping of widget instance to URLs for trusted postMessage communication. + */ +export default class WidgetMessageEndpoint { + /** + * Mapping of widget instance to URL for trusted postMessage communication. + * @param {string} widgetId Unique widget identifier + * @param {string} endpointUrl Widget wurl origin. + */ + constructor(widgetId, endpointUrl) { + if (!widgetId) { + throw new Error("No widgetId specified in widgetMessageEndpoint constructor"); + } + if (!endpointUrl) { + throw new Error("No endpoint specified in widgetMessageEndpoint constructor"); + } + this.widgetId = widgetId; + this.endpointUrl = endpointUrl; + } +} diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index e7f44a8840..a9613530ec 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -51,6 +51,7 @@ export default class AppTile extends React.Component { this._onSnapshotClick = this._onSnapshotClick.bind(this); this.onClickMenuBar = this.onClickMenuBar.bind(this); this._onMinimiseClick = this._onMinimiseClick.bind(this); + this._onInitialLoad = this._onInitialLoad.bind(this); } /** @@ -172,8 +173,7 @@ export default class AppTile extends React.Component { // Widget postMessage listeners try { if (this.widgetMessaging) { - this.widgetMessaging.stopListening(); - this.widgetMessaging.removeEndpoint(this.props.id, this.props.url); + this.widgetMessaging.stop(); } } catch (e) { console.error('Failed to stop listening for widgetMessaging events', e.message); @@ -290,14 +290,16 @@ export default class AppTile extends React.Component { _onSnapshotClick(e) { console.warn("Requesting widget snapshot"); - this.widgetMessaging.getScreenshot().then((screenshot) => { - dis.dispatch({ - action: 'picture_snapshot', - file: screenshot, - }, true); - }).catch((err) => { - console.error("Failed to get screenshot", err); - }); + this.widgetMessaging.getScreenshot() + .catch((err) => { + console.error("Failed to get screenshot", err); + }) + .then((screenshot) => { + dis.dispatch({ + action: 'picture_snapshot', + file: screenshot, + }, true); + }); } /* If user has permission to modify widgets, delete the widget, @@ -343,9 +345,16 @@ export default class AppTile extends React.Component { * Called when widget iframe has finished loading */ _onLoaded() { - this.widgetMessaging = new WidgetMessaging(this.props.id, this.refs.appFrame.contentWindow); - this.widgetMessaging.startListening(); - this.widgetMessaging.addEndpoint(this.props.id, this.props.url); + if (!this.widgetMessaging) { + this._onInitialLoad(); + } + } + + /** + * Called on initial load of the widget iframe + */ + _onInitialLoad() { + this.widgetMessaging = new WidgetMessaging(this.props.id, this.props.url, this.refs.appFrame.contentWindow); this.widgetMessaging.getCapabilities().then((requestedCapabilities) => { console.log(`Widget ${this.props.id} requested capabilities:`, requestedCapabilities); requestedCapabilities = requestedCapabilities || []; From b4e70e30f33dce2c30e92458ba5793cbb70501af Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Wed, 28 Mar 2018 19:21:49 +0100 Subject: [PATCH 141/170] Expects object, not naked ID. --- src/IntegrationManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/IntegrationManager.js b/src/IntegrationManager.js index e9486138c7..4cdf57f5c7 100644 --- a/src/IntegrationManager.js +++ b/src/IntegrationManager.js @@ -60,7 +60,7 @@ export default class IntegrationManager { integType = 'type_' + integType; const src = (global.mxIntegrationManager.client && global.mxIntegrationManager.client.hasCredentials()) ? global.mxIntegrationManager.client.getScalarInterfaceUrlForRoom( - RoomViewStore.getRoomId(), + {roomId: RoomViewStore.getRoomId()}, integType, integId, ) : From 5fc9b8a6b8c436014352c5fc5f99df4a5ed7e056 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 29 Mar 2018 16:23:20 +0100 Subject: [PATCH 142/170] Indentation. --- src/ContentMessages.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ContentMessages.js b/src/ContentMessages.js index 47ad87a8d7..33009d502b 100644 --- a/src/ContentMessages.js +++ b/src/ContentMessages.js @@ -276,9 +276,9 @@ class ContentMessages { } sendStickerContentToRoom(url, roomId, info, text, matrixClient) { - return MatrixClientPeg.get().sendStickerMessage(roomId, url, info, text).catch((e) => { - console.warn(`Failed to send content with URL ${url} to room ${roomId}`, e); - }); + return MatrixClientPeg.get().sendStickerMessage(roomId, url, info, text).catch((e) => { + console.warn(`Failed to send content with URL ${url} to room ${roomId}`, e); + }); } sendContentToRoom(file, roomId, matrixClient) { From a1581ad2dc4cbb196867a1fd2c66f60e04d2bef6 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 29 Mar 2018 16:24:03 +0100 Subject: [PATCH 143/170] Don't swallow error. --- src/ContentMessages.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ContentMessages.js b/src/ContentMessages.js index 33009d502b..7fe625f8b9 100644 --- a/src/ContentMessages.js +++ b/src/ContentMessages.js @@ -278,6 +278,7 @@ class ContentMessages { sendStickerContentToRoom(url, roomId, info, text, matrixClient) { return MatrixClientPeg.get().sendStickerMessage(roomId, url, info, text).catch((e) => { console.warn(`Failed to send content with URL ${url} to room ${roomId}`, e); + throw e; }); } From 23a52bdb4cbc54b0988e241651006682b0ac7109 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 29 Mar 2018 16:46:22 +0100 Subject: [PATCH 144/170] Indentation. --- src/components/structures/RoomView.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index a6b4c272b4..f531b94788 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -937,12 +937,12 @@ module.exports = React.createClass({ } ContentMessages.sendStickerContentToRoom(url, this.state.room.roomId, info, text, MatrixClientPeg.get()) - .done(undefined, (error) => { - if (error.name === "UnknownDeviceError") { - // Let the staus bar handle this - return; - } - }); + .done(undefined, (error) => { + if (error.name === "UnknownDeviceError") { + // Let the staus bar handle this + return; + } + }); }, onSearch: function(term, scope) { From 35fcb2c9abddd1cf1e14875f548b647c557039c1 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 29 Mar 2018 16:56:02 +0100 Subject: [PATCH 145/170] Catch rather than 'done' error handler. --- src/components/structures/RoomView.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index f531b94788..6fc16b9760 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -916,7 +916,7 @@ module.exports = React.createClass({ ContentMessages.sendContentToRoom( file, this.state.room.roomId, MatrixClientPeg.get(), - ).done(undefined, (error) => { + ).catch((error) => { if (error.name === "UnknownDeviceError") { // Let the staus bar handle this return; @@ -925,7 +925,8 @@ module.exports = React.createClass({ console.error("Failed to upload file " + file + " " + error); Modal.createTrackedDialog('Failed to upload file', '', ErrorDialog, { title: _t('Failed to upload file'), - description: ((error && error.message) ? error.message : _t("Server may be unavailable, overloaded, or the file too big")), + description: ((error && error.message) + ? error.message : _t("Server may be unavailable, overloaded, or the file too big")), }); }); }, From aefccb134c294efcf2ee77d308c27ab62ec15706 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 29 Mar 2018 16:56:25 +0100 Subject: [PATCH 146/170] Ensure deleting is set to false. --- src/components/views/elements/AppTile.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index a9613530ec..98b68bd890 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -330,6 +330,7 @@ export default class AppTile extends React.Component { this.props.id, ).catch((e) => { console.error('Failed to delete widget', e); + }).finally(() => { this.setState({deleting: false}); }); }, From cafbd2904ecb033db63c4d45b934c8c3eff397f3 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 29 Mar 2018 16:57:21 +0100 Subject: [PATCH 147/170] Remove unused ref. --- src/components/views/messages/MStickerBody.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/messages/MStickerBody.js b/src/components/views/messages/MStickerBody.js index 83d8309cf9..ef2c2106cc 100644 --- a/src/components/views/messages/MStickerBody.js +++ b/src/components/views/messages/MStickerBody.js @@ -106,7 +106,7 @@ export default class MStickerBody extends MImageBody { placeholderSize = placeholderSize + 'px'; return ( - From f38329826729d440f95292e42c258abc52b4dec0 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 29 Mar 2018 17:08:07 +0100 Subject: [PATCH 148/170] Remove duplicate event handler. --- src/components/views/messages/MStickerBody.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/views/messages/MStickerBody.js b/src/components/views/messages/MStickerBody.js index ef2c2106cc..5b44789445 100644 --- a/src/components/views/messages/MStickerBody.js +++ b/src/components/views/messages/MStickerBody.js @@ -50,6 +50,9 @@ export default class MStickerBody extends MImageBody { }); }, 500); this.setState({hidePlaceholderTimer}); + if (this.props.onWidgetLoad) { + this.props.onWidgetLoad(); + } } _afterComponentDidMount() { @@ -129,7 +132,6 @@ export default class MStickerBody extends MImageBody { src={contentUrl} ref='image' alt={content.body} - onLoad={this.props.onWidgetLoad} onLoad={this._onImageLoad} onMouseEnter={this._onMouseEnter} onMouseLeave={this._onMouseLeave} From 9c10d243e85d367aff06f6b4d3f0dd53d118f28b Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 29 Mar 2018 17:09:03 +0100 Subject: [PATCH 149/170] Add comment. --- src/components/views/messages/MStickerBody.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/views/messages/MStickerBody.js b/src/components/views/messages/MStickerBody.js index 5b44789445..8ae5bdd2c4 100644 --- a/src/components/views/messages/MStickerBody.js +++ b/src/components/views/messages/MStickerBody.js @@ -142,6 +142,7 @@ export default class MStickerBody extends MImageBody { ); } + // Empty to prevent default behaviour of MImageBody onClick() { } } From 38c8bc7d9aca9b2241d79b88b01cd5e86cc27a83 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 29 Mar 2018 17:25:07 +0100 Subject: [PATCH 150/170] Consistent function naming. --- src/components/views/rooms/Stickerpicker.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index 1171ad1ee0..e531212baf 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -31,12 +31,12 @@ const widgetType = 'm.stickerpicker'; export default class Stickerpicker extends React.Component { constructor(props) { super(props); - this.onShowStickersClick = this.onShowStickersClick.bind(this); - this.onHideStickersClick = this.onHideStickersClick.bind(this); - this.onFinished = this.onFinished.bind(this); + this._onShowStickersClick = this._onShowStickersClick.bind(this); + this._onHideStickersClick = this._onHideStickersClick.bind(this); this._launchManageIntegrations = this._launchManageIntegrations.bind(this); this._removeStickerpickerWidgets = this._removeStickerpickerWidgets.bind(this); this._onWidgetAction = this._onWidgetAction.bind(this); + this.onFinished = this.onFinished.bind(this); this.defaultStickersContent = (
@@ -157,7 +157,7 @@ export default class Stickerpicker extends React.Component { showTitle={false} showMinimise={true} showDelete={false} - onMinimiseClick={this.onHideStickersClick} + onMinimiseClick={this._onHideStickersClick} handleMinimisePointerEvents={true} whitelistCapabilities={['m.sticker']} /> @@ -182,7 +182,7 @@ export default class Stickerpicker extends React.Component { * If no stickerpacks have been added, show a link to the integration manager add sticker packs page. * @param {Event} e Event that triggered the function */ - onShowStickersClick(e) { + _onShowStickersClick(e) { this._getStickerPickerWidget(); const GenericElementContextMenu = sdk.getComponent('context_menus.GenericElementContextMenu'); const buttonRect = e.target.getBoundingClientRect(); @@ -211,7 +211,7 @@ export default class Stickerpicker extends React.Component { * Trigger hiding of the sticker picker overlay * @param {Event} ev Event that triggered the function call */ - onHideStickersClick(ev) { + _onHideStickersClick(ev) { setTimeout(() => this.stickersMenu.close()); } @@ -252,7 +252,7 @@ export default class Stickerpicker extends React.Component { id='stickersButton' key="controls_hide_stickers" className="mx_MessageComposer_stickers mx_Stickers_hideStickers" - onClick={this.onHideStickersClick} + onClick={this._onHideStickersClick} ref='target' title={_t("Hide Stickers")}> @@ -264,7 +264,7 @@ export default class Stickerpicker extends React.Component { id='stickersButton' key="constrols_show_stickers" className="mx_MessageComposer_stickers" - onClick={this.onShowStickersClick} + onClick={this._onShowStickersClick} title={_t("Show Stickers")}>
; From e21cc14e5b6e8ee1c9e228ca65a484167023fe90 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 29 Mar 2018 17:26:19 +0100 Subject: [PATCH 151/170] Comment. --- src/components/views/rooms/Stickerpicker.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index e531212baf..2759bd51b8 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -68,6 +68,7 @@ export default class Stickerpicker extends React.Component { } Widgets.removeStickerpickerWidgets(); this._getStickerPickerWidget(); + // Wrap this in a timeout in order to avoid the DOM node from being pulled from under its feet setTimeout(() => this.stickersMenu.close()); } From 67f755efcbdd1136646ab25c75d3e89d0f96dc8d Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 29 Mar 2018 17:26:54 +0100 Subject: [PATCH 152/170] Comment. --- src/components/views/rooms/Stickerpicker.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index 2759bd51b8..12917e209d 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -108,7 +108,8 @@ export default class Stickerpicker extends React.Component { this._getStickerPickerWidget(); return; } else if (payload.action === "stickerpicker_close") { - setTimeout(() => this.stickersMenu.close()); + // Wrap this in a timeout in order to avoid the DOM node from being pulled from under its feet + setTimeout(() => this.stickersMenu.close()); } } From c8f9586c9bbb939b4c272503e9adbc71c7041ec6 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 29 Mar 2018 17:35:21 +0100 Subject: [PATCH 153/170] Check for valid reference. --- src/components/views/rooms/Stickerpicker.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index 12917e209d..fe99a18d92 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -90,7 +90,9 @@ export default class Stickerpicker extends React.Component { } componentWillUnmount() { - dis.unregister(this.dispatcherRef); + if (this.dispatcherRef) { + dis.unregister(this.dispatcherRef); + } } _imError(errorMsg, e) { From 6181ca642f5454380600a332519959c9ca4337b7 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 29 Mar 2018 17:47:53 +0100 Subject: [PATCH 154/170] "Stickerpack" translation. --- src/components/views/rooms/Stickerpicker.js | 2 +- src/i18n/strings/en_EN.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index fe99a18d92..e589b391d6 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -125,7 +125,7 @@ export default class Stickerpicker extends React.Component { // Load stickerpack content if (stickerpickerWidget && stickerpickerWidget.content && stickerpickerWidget.content.url) { // Set default name - stickerpickerWidget.content.name = stickerpickerWidget.name || "Stickerpack"; + stickerpickerWidget.content.name = stickerpickerWidget.name || _t("Stickerpack"); this.widgetId = stickerpickerWidget.id; stickersContent = ( diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index a1539cc665..50008c3202 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -256,6 +256,7 @@ "Cannot add any more widgets": "Cannot add any more widgets", "The maximum permitted number of widgets have already been added to this room.": "The maximum permitted number of widgets have already been added to this room.", "Add a widget": "Add a widget", + "Stickerpack": "Stickerpack", "You don't currently have any stickerpacks enabled": "You don't currently have any stickerpacks enabled", "Click": "Click", "here": "here", From b1e7dcf21645d3dc9ce365426cb0f3e621d297c4 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 29 Mar 2018 17:52:34 +0100 Subject: [PATCH 155/170] Cleanup / simplify code. --- src/utils/widgets.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/utils/widgets.js b/src/utils/widgets.js index c2eae88b17..edbe78fd58 100644 --- a/src/utils/widgets.js +++ b/src/utils/widgets.js @@ -49,8 +49,7 @@ function getUserWidgets() { * @return {[object]} Array containing current / active user widgets */ function getUserWidgetsArray() { - const userWidgetContent = getUserWidgets(); - return Object.keys(userWidgetContent).map((key) => userWidgetContent[key]); + return Object.values(getUserWidgets()); } /** From 3d9bdb90ca5ae013458c344239a4519766e031a4 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 29 Mar 2018 17:56:12 +0100 Subject: [PATCH 156/170] Consistent async / await / promises. --- src/IntegrationManager.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/IntegrationManager.js b/src/IntegrationManager.js index 4cdf57f5c7..60b0fb534d 100644 --- a/src/IntegrationManager.js +++ b/src/IntegrationManager.js @@ -25,13 +25,13 @@ if (!global.mxIntegrationManager) { } export default class IntegrationManager { - static async _init() { + static _init() { if (!global.mxIntegrationManager.client || !global.mxIntegrationManager.connected) { if (SdkConfig.get().integrations_ui_url && SdkConfig.get().integrations_rest_url) { ScalarMessaging.startListening(); global.mxIntegrationManager.client = new ScalarAuthClient(); - await global.mxIntegrationManager.client.connect().then(() => { + return global.mxIntegrationManager.client.connect().then(() => { global.mxIntegrationManager.connected = true; }).catch((e) => { console.error("Failed to connect to integrations server", e); From 5ba18b5ee2088352be6705221bf398692fd8ac84 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 29 Mar 2018 18:13:23 +0100 Subject: [PATCH 157/170] Avoid redefining function parameter --- src/IntegrationManager.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/IntegrationManager.js b/src/IntegrationManager.js index 60b0fb534d..6d488d91df 100644 --- a/src/IntegrationManager.js +++ b/src/IntegrationManager.js @@ -45,11 +45,11 @@ export default class IntegrationManager { /** * Launch the integrations manager on the stickers integration page - * @param {string} integType integration / widget type + * @param {string} integName integration / widget type * @param {string} integId integration / widget ID * @param {function} onClose Callback to invoke on integration manager close */ - static async open(integType, integId, onClose) { + static async open(integName, integId, onClose) { await IntegrationManager._init(); const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager"); if (global.mxIntegrationManager.error || @@ -57,7 +57,7 @@ export default class IntegrationManager { console.error("Scalar error", global.mxIntegrationManager); return; } - integType = 'type_' + integType; + const integType = 'type_' + integName; const src = (global.mxIntegrationManager.client && global.mxIntegrationManager.client.hasCredentials()) ? global.mxIntegrationManager.client.getScalarInterfaceUrlForRoom( {roomId: RoomViewStore.getRoomId()}, From 20cbc016987e144ae1b46fe9468503569fde6f64 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 29 Mar 2018 18:32:49 +0100 Subject: [PATCH 158/170] Add callback handler for integration manager close. --- src/IntegrationManager.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/IntegrationManager.js b/src/IntegrationManager.js index 6d488d91df..eb45a1f425 100644 --- a/src/IntegrationManager.js +++ b/src/IntegrationManager.js @@ -47,9 +47,9 @@ export default class IntegrationManager { * Launch the integrations manager on the stickers integration page * @param {string} integName integration / widget type * @param {string} integId integration / widget ID - * @param {function} onClose Callback to invoke on integration manager close + * @param {function} onFinished Callback to invoke on integration manager close */ - static async open(integName, integId, onClose) { + static async open(integName, integId, onFinished) { await IntegrationManager._init(); const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager"); if (global.mxIntegrationManager.error || @@ -67,10 +67,7 @@ export default class IntegrationManager { null; Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, { src: src, + onFinished: onFinished, }, "mx_IntegrationsManager"); - - if (onClose) { - onClose(); - } } } From 9a3f3562e12c05178048ce89feb91000a008dfee Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 29 Mar 2018 20:07:26 +0100 Subject: [PATCH 159/170] Wait for setAccountData to complete. --- src/ScalarMessaging.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index 351c178da4..dad1bdf6f6 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -355,12 +355,13 @@ function setWidget(event, roomId) { }; } - client.setAccountData('m.widgets', userWidgets); - sendResponse(event, { - success: true, - }); + client.setAccountData('m.widgets', userWidgets).then(() => { + sendResponse(event, { + success: true, + }); - dis.dispatch({ action: "user_widget_updated" }); + dis.dispatch({ action: "user_widget_updated" }); + }); } else { // Room widget if (!roomId) { sendError(event, _t('Missing roomId.'), null); From 93804e80b864719bed8a4bc88e502a2effeb3330 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 29 Mar 2018 20:37:24 +0100 Subject: [PATCH 160/170] Return promise --- src/utils/widgets.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/widgets.js b/src/utils/widgets.js index edbe78fd58..62f841c9c2 100644 --- a/src/utils/widgets.js +++ b/src/utils/widgets.js @@ -76,7 +76,7 @@ function removeStickerpickerWidgets() { delete userWidgets[key]; } }); - client.setAccountData('m.widgets', userWidgets); + return client.setAccountData('m.widgets', userWidgets); } From 2e6d6c83cdcf26dc55425fde2258b7ffdfd15b73 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 29 Mar 2018 21:16:12 +0100 Subject: [PATCH 161/170] Add back in body 'ref' --- src/components/views/messages/MStickerBody.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/views/messages/MStickerBody.js b/src/components/views/messages/MStickerBody.js index 8ae5bdd2c4..08ddb6de20 100644 --- a/src/components/views/messages/MStickerBody.js +++ b/src/components/views/messages/MStickerBody.js @@ -108,8 +108,9 @@ export default class MStickerBody extends MImageBody { placeholderSize = placeholderSize + 'px'; + // Body 'ref' required by MImageBody return ( - From 003cf6138865f76ac5600c6f5a311319a69f1879 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 29 Mar 2018 21:16:35 +0100 Subject: [PATCH 162/170] Handle remove sticker picker errors. --- src/components/views/rooms/Stickerpicker.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index e589b391d6..32bf284c19 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -66,10 +66,14 @@ export default class Stickerpicker extends React.Component { } else { console.warn('No widget ID specified, not disabling assets'); } - Widgets.removeStickerpickerWidgets(); - this._getStickerPickerWidget(); + // Wrap this in a timeout in order to avoid the DOM node from being pulled from under its feet setTimeout(() => this.stickersMenu.close()); + Widgets.removeStickerpickerWidgets().then(() => { + this._getStickerPickerWidget(); + }).catch((e) => { + console.error('Failed to remove sticker picker widget', e); + }); } componentDidMount() { From ff0834ad9d1f50b951e363bcfd9615d62edf421d Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 29 Mar 2018 21:31:09 +0100 Subject: [PATCH 163/170] Add comment. --- src/components/structures/MessagePanel.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index 248c874fa8..773c9710dd 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -450,7 +450,12 @@ module.exports = React.createClass({ if (prevEvent !== null && prevEvent.sender && mxEv.sender && mxEv.sender.userId === prevEvent.sender.userId - && Boolean(mxEv.getContent().body) == Boolean(prevEvent.getContent().body)) { + // The preferred way of checking for 'continuation messages' is by + // checking whether subsiquent messages from the same user have a + // message body. This is because all messages intended to be displayed + // should have a 'body' whereas some (non-m.room) messages (such as + // m.sticker) may not have a message 'type'. + && Boolean(mxEv.getContent().body) == Boolean(prevEvent.getContent().body)) { continuation = true; } From 9cc3d3c9bbaa4b8b8d7d54a11b2742fde09f440a Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 29 Mar 2018 21:48:03 +0100 Subject: [PATCH 164/170] Move default sticker content into generator function. --- src/components/views/rooms/Stickerpicker.js | 26 +++++++++++---------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index 32bf284c19..63ebfe3496 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -1,6 +1,5 @@ /* -Copyright 2015, 2016 OpenMarket Ltd -Copyright 2017 New Vector Ltd +Copyright 2018 New Vector Ltd Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -38,21 +37,24 @@ export default class Stickerpicker extends React.Component { this._onWidgetAction = this._onWidgetAction.bind(this); this.onFinished = this.onFinished.bind(this); - this.defaultStickersContent = ( + this.popoverWidth = 300; + this.popoverHeight = 300; + + this.state = { + stickersContent: this.defaultStickersContent(), + showStickers: false, + imError: null, + }; + } + + defaultStickersContent() { + return (

{ _t("You don't currently have any stickerpacks enabled") }

{ _t("Click") } { _t("here") } { _t("to add some!") }

{_t('Add
); - this.popoverWidth = 300; - this.popoverHeight = 300; - - this.state = { - stickersContent: this.defaultStickersContent, - showStickers: false, - imError: null, - }; } _removeStickerpickerWidgets() { @@ -175,7 +177,7 @@ export default class Stickerpicker extends React.Component { } else { // Default content to show if stickerpicker widget not added console.warn("No available sticker picker widgets"); - stickersContent = this.defaultStickersContent; + stickersContent = this.defaultStickersContent(); this.widgetId = null; this.forceUpdate(); } From 557a45e89007ed97ccec6c11ade572fcbda82641 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Thu, 29 Mar 2018 22:22:57 +0100 Subject: [PATCH 165/170] Remove inline styling. --- src/components/views/rooms/Stickerpicker.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index 63ebfe3496..1a74da9a8b 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -135,12 +135,7 @@ export default class Stickerpicker extends React.Component { this.widgetId = stickerpickerWidget.id; stickersContent = ( -
+
Date: Mon, 2 Apr 2018 10:02:41 +0100 Subject: [PATCH 166/170] Fix user widget event type. Add comments for clarity. --- src/ScalarMessaging.js | 6 +++++- src/WidgetUtils.js | 2 +- src/utils/widgets.js | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index dad1bdf6f6..123d02159e 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -350,7 +350,7 @@ function setWidget(event, roomId) { content: content, sender: client.getUserId(), stateKey: widgetId, - type: 'im.vector.modular.widgets', + type: 'm.widget', id: widgetId, }; } @@ -370,6 +370,8 @@ function setWidget(event, roomId) { if (widgetUrl === null) { // widget is being deleted content = {}; } + // TODO - Room widgets need to be moved to 'm.widget' state events + // https://docs.google.com/document/d/1uPF7XWY_dXTKVKV7jZQ2KmsI19wn9-kFRgQ1tFQP7wQ/edit?usp=sharing client.sendStateEvent(roomId, "im.vector.modular.widgets", content, widgetId).done(() => { sendResponse(event, { success: true, @@ -394,6 +396,8 @@ function getWidgets(event, roomId) { sendError(event, _t('This room is not recognised.')); return; } + // TODO - Room widgets need to be moved to 'm.widget' state events + // https://docs.google.com/document/d/1uPF7XWY_dXTKVKV7jZQ2KmsI19wn9-kFRgQ1tFQP7wQ/edit?usp=sharing const stateEvents = room.currentState.getStateEvents("im.vector.modular.widgets"); // Only return widgets which have required fields if (room) { diff --git a/src/WidgetUtils.js b/src/WidgetUtils.js index 34c998978d..5f45a8c58c 100644 --- a/src/WidgetUtils.js +++ b/src/WidgetUtils.js @@ -17,8 +17,8 @@ limitations under the License. import MatrixClientPeg from './MatrixClientPeg'; export default class WidgetUtils { - /* Returns true if user is able to send state events to modify widgets in this room + * (Does not apply to non-room-based / user widgets) * @param roomId -- The ID of the room to check * @return Boolean -- true if the user can modify widgets in this room * @throws Error -- specifies the error reason diff --git a/src/utils/widgets.js b/src/utils/widgets.js index 62f841c9c2..0d7f5dbf3f 100644 --- a/src/utils/widgets.js +++ b/src/utils/widgets.js @@ -64,6 +64,7 @@ function getStickerpickerWidgets() { /** * Remove all stickerpicker widgets (stickerpickers are user widgets by nature) + * @return {Promise} Resolves on account data updated */ function removeStickerpickerWidgets() { const client = MatrixClientPeg.get(); From d83b6f1cf8891b85b1166badf68920308657b337 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Mon, 2 Apr 2018 10:18:35 +0100 Subject: [PATCH 167/170] Use AccessibleButton. --- src/components/views/rooms/Stickerpicker.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index 1a74da9a8b..17fd839944 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -24,6 +24,7 @@ import sdk from '../../../index'; import SdkConfig from '../../../SdkConfig'; import ScalarAuthClient from '../../../ScalarAuthClient'; import dis from '../../../dispatcher'; +import AccessibleButton from '../elements/AccessibleButton'; const widgetType = 'm.stickerpicker'; @@ -49,11 +50,12 @@ export default class Stickerpicker extends React.Component { defaultStickersContent() { return ( -
+

{ _t("You don't currently have any stickerpacks enabled") }

-

{ _t("Click") } { _t("here") } { _t("to add some!") }

+

Add some now

{_t('Add -
+ ); } From 49bea1a35b61b18ed127c457e8cb71213259eb34 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Mon, 2 Apr 2018 10:56:45 +0100 Subject: [PATCH 168/170] Move stickerpicker content out of state in to generator function. --- src/components/views/rooms/Stickerpicker.js | 64 ++++++++++++--------- 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index 17fd839944..1a204b45d5 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -36,29 +36,17 @@ export default class Stickerpicker extends React.Component { this._launchManageIntegrations = this._launchManageIntegrations.bind(this); this._removeStickerpickerWidgets = this._removeStickerpickerWidgets.bind(this); this._onWidgetAction = this._onWidgetAction.bind(this); - this.onFinished = this.onFinished.bind(this); + this._onFinished = this._onFinished.bind(this); this.popoverWidth = 300; this.popoverHeight = 300; this.state = { - stickersContent: this.defaultStickersContent(), showStickers: false, imError: null, }; } - defaultStickersContent() { - return ( - -

{ _t("You don't currently have any stickerpacks enabled") }

-

Add some now

- {_t('Add -
- ); - } - _removeStickerpickerWidgets() { console.warn('Removing Stickerpicker widgets'); if (this.widgetId) { @@ -74,7 +62,7 @@ export default class Stickerpicker extends React.Component { // Wrap this in a timeout in order to avoid the DOM node from being pulled from under its feet setTimeout(() => this.stickersMenu.close()); Widgets.removeStickerpickerWidgets().then(() => { - this._getStickerPickerWidget(); + this._getStickerpickerContent(); }).catch((e) => { console.error('Failed to remove sticker picker widget', e); }); @@ -92,9 +80,9 @@ export default class Stickerpicker extends React.Component { } if (!this.state.imError) { - this._getStickerPickerWidget(); this.dispatcherRef = dis.register(this._onWidgetAction); } + this._getStickerpickerContent(); } componentWillUnmount() { @@ -105,28 +93,52 @@ export default class Stickerpicker extends React.Component { _imError(errorMsg, e) { console.error(errorMsg, e); - const imErrorContent =

{ errorMsg }

; this.setState({ showStickers: false, imError: errorMsg, - stickersContent: imErrorContent, }); } _onWidgetAction(payload) { if (payload.action === "user_widget_updated") { - this._getStickerPickerWidget(); + this._getStickerpickerContent(); return; } else if (payload.action === "stickerpicker_close") { - // Wrap this in a timeout in order to avoid the DOM node from being pulled from under its feet + // Wrap this in a timeout in order to avoid the DOM node from being + // pulled from under its feet setTimeout(() => this.stickersMenu.close()); } } - _getStickerPickerWidget() { + _defaultStickerpickerContent() { + return ( + +

{ _t("You don't currently have any stickerpacks enabled") }

+

Add some now

+ {_t('Add +
+ ); + } + + _errorStickerpickerContent() { + return ( +
+

{ this.state.imError }

+
+ ); + } + + _getStickerpickerContent() { + // Handle Integration Manager errors + if (this.state._imError) { + return this._errorStickerpickerContent(); + } + // Stickers // TODO - Add support for Stickerpickers from multiple app stores. - // Render content from multiple stickerpack sources, each within their own iframe, within the stickerpicker UI element. + // Render content from multiple stickerpack sources, each within their + // own iframe, within the stickerpicker UI element. const stickerpickerWidget = Widgets.getStickerpickerWidgets()[0]; let stickersContent; @@ -180,8 +192,8 @@ export default class Stickerpicker extends React.Component { } this.setState({ showStickers: false, - stickersContent: stickersContent, }); + return stickersContent; } /** @@ -190,7 +202,7 @@ export default class Stickerpicker extends React.Component { * @param {Event} e Event that triggered the function */ _onShowStickersClick(e) { - this._getStickerPickerWidget(); + this._getStickerpickerContent(); const GenericElementContextMenu = sdk.getComponent('context_menus.GenericElementContextMenu'); const buttonRect = e.target.getBoundingClientRect(); @@ -205,8 +217,8 @@ export default class Stickerpicker extends React.Component { top: y, menuWidth: this.popoverWidth, menuHeight: this.popoverHeight, - element: this.state.stickersContent, - onFinished: this.onFinished, + element: this._getStickerpickerContent(), + onFinished: this._onFinished, menuPaddingTop: 0, }); @@ -225,7 +237,7 @@ export default class Stickerpicker extends React.Component { /** * The stickers picker was hidden */ - onFinished() { + _onFinished() { this.setState({showStickers: false}); } From 8241afe87dbf55975163cae548c0ef7506251492 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Mon, 2 Apr 2018 20:25:24 +0100 Subject: [PATCH 169/170] Fix content references --- src/components/views/rooms/Stickerpicker.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index 1a204b45d5..e45f0e8f1b 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -62,7 +62,7 @@ export default class Stickerpicker extends React.Component { // Wrap this in a timeout in order to avoid the DOM node from being pulled from under its feet setTimeout(() => this.stickersMenu.close()); Widgets.removeStickerpickerWidgets().then(() => { - this._getStickerpickerContent(); + this.forceUpdate(); }).catch((e) => { console.error('Failed to remove sticker picker widget', e); }); @@ -82,7 +82,6 @@ export default class Stickerpicker extends React.Component { if (!this.state.imError) { this.dispatcherRef = dis.register(this._onWidgetAction); } - this._getStickerpickerContent(); } componentWillUnmount() { @@ -101,8 +100,7 @@ export default class Stickerpicker extends React.Component { _onWidgetAction(payload) { if (payload.action === "user_widget_updated") { - this._getStickerpickerContent(); - return; + this.forceUpdate(); } else if (payload.action === "stickerpicker_close") { // Wrap this in a timeout in order to avoid the DOM node from being // pulled from under its feet @@ -186,7 +184,7 @@ export default class Stickerpicker extends React.Component { } else { // Default content to show if stickerpicker widget not added console.warn("No available sticker picker widgets"); - stickersContent = this.defaultStickersContent(); + stickersContent = this._defaultStickerpickerContent(); this.widgetId = null; this.forceUpdate(); } @@ -202,7 +200,6 @@ export default class Stickerpicker extends React.Component { * @param {Event} e Event that triggered the function */ _onShowStickersClick(e) { - this._getStickerpickerContent(); const GenericElementContextMenu = sdk.getComponent('context_menus.GenericElementContextMenu'); const buttonRect = e.target.getBoundingClientRect(); From b109c9304c7ecdb1fa68c46a8aa4fc786bcb8ba8 Mon Sep 17 00:00:00 2001 From: Richard Lewis Date: Mon, 2 Apr 2018 22:24:46 +0100 Subject: [PATCH 170/170] Put stickers behind labs flag. --- src/components/views/rooms/MessageComposer.js | 7 ++++++- src/i18n/strings/en_EN.json | 1 + src/settings/Settings.js | 6 ++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 0f98e6b526..ff46f7423e 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -329,6 +329,11 @@ export default class MessageComposer extends React.Component { } } + let stickerpickerButton; + if (SettingsStore.isFeatureEnabled('feature_sticker_messages')) { + stickerpickerButton = ; + } + controls.push( this.messageComposerInput = c} @@ -340,7 +345,7 @@ export default class MessageComposer extends React.Component { onContentChanged={this.onInputContentChanged} onInputStateChanged={this.onInputStateChanged} />, formattingButton, - , + stickerpickerButton, uploadButton, hangupButton, callButton, diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 50008c3202..8aac4e60d0 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -257,6 +257,7 @@ "The maximum permitted number of widgets have already been added to this room.": "The maximum permitted number of widgets have already been added to this room.", "Add a widget": "Add a widget", "Stickerpack": "Stickerpack", + "Sticker Messages": "Sticker Messages", "You don't currently have any stickerpacks enabled": "You don't currently have any stickerpacks enabled", "Click": "Click", "here": "here", diff --git a/src/settings/Settings.js b/src/settings/Settings.js index cd37c00fa8..7acaa8009f 100644 --- a/src/settings/Settings.js +++ b/src/settings/Settings.js @@ -100,6 +100,12 @@ export const SETTINGS = { supportedLevels: LEVELS_FEATURE, default: false, }, + "feature_sticker_messages": { + isFeature: true, + displayName: _td("Sticker Messages"), + supportedLevels: LEVELS_FEATURE, + default: false, + }, "MessageComposerInput.dontSuggestEmoji": { supportedLevels: LEVELS_ACCOUNT_SETTINGS, displayName: _td('Disable Emoji suggestions while typing'),