From 904676913266b2b10cb3f8f20634115e603733ee Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 10 May 2018 16:00:58 +0100 Subject: [PATCH 1/9] Factor out ContextualMenu component --- src/components/structures/ContextualMenu.js | 88 +++++++++++---------- 1 file changed, 47 insertions(+), 41 deletions(-) diff --git a/src/components/structures/ContextualMenu.js b/src/components/structures/ContextualMenu.js index 0e2df890f3..99d1f892b9 100644 --- a/src/components/structures/ContextualMenu.js +++ b/src/components/structures/ContextualMenu.js @@ -26,9 +26,21 @@ import PropTypes from 'prop-types'; // of doing reusable widgets like dialog boxes & menus where we go and // pass in a custom control as the actual body. -module.exports = { - ContextualMenuContainerId: "mx_ContextualMenu_Container", +const ContextualMenuContainerId = "mx_ContextualMenu_Container"; +function getOrCreateContainer() { + let container = document.getElementById(ContextualMenuContainerId); + + if (!container) { + container = document.createElement("div"); + container.id = ContextualMenuContainerId; + document.body.appendChild(container); + } + + return container; +} + +class ContextualMenu extends React.Component { propTypes: { top: PropTypes.number, bottom: PropTypes.number, @@ -45,39 +57,14 @@ module.exports = { menuPaddingRight: PropTypes.number, menuPaddingBottom: PropTypes.number, menuPaddingLeft: PropTypes.number, - }, - - getOrCreateContainer: function() { - let container = document.getElementById(this.ContextualMenuContainerId); - - if (!container) { - container = document.createElement("div"); - container.id = this.ContextualMenuContainerId; - document.body.appendChild(container); - } - - return container; - }, - - createMenu: function(Element, props) { - const self = this; - - const closeMenu = function(...args) { - ReactDOM.unmountComponentAtNode(self.getOrCreateContainer()); - - if (props && props.onFinished) { - props.onFinished.apply(null, args); - } - }; - - // Close the menu on window resize - const windowResize = function() { - closeMenu(); - }; + } + render() { const position = {}; let chevronFace = null; + const props = this.props; + if (props.top) { position.top = props.top; } else { @@ -158,20 +145,39 @@ module.exports = { menuStyle["paddingRight"] = props.menuPaddingRight; } + const ElementClass = props.elementClass; + // 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 = ( -
-
- { chevron } - -
-
- + return
+
+ { chevron } +
- ); +
+ +
; + } +} - ReactDOM.render(menu, this.getOrCreateContainer()); +module.exports = { + createMenu: function(ElementClass, props) { + const closeMenu = function(...args) { + ReactDOM.unmountComponentAtNode(getOrCreateContainer()); + + if (props && props.onFinished) { + props.onFinished.apply(null, args); + } + }; + + const menu = ; + + ReactDOM.render(menu, getOrCreateContainer()); return {close: closeMenu}; }, From 2c2eda1f006c1ddcde13e890ae8f5830d7ac9bf1 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 10 May 2018 17:51:49 +0100 Subject: [PATCH 2/9] Export ContextualMenu component, with added `hasBackground` property , which is only enabled when `createMenu` is used. --- src/components/structures/ContextualMenu.js | 43 +++++++++++---------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/src/components/structures/ContextualMenu.js b/src/components/structures/ContextualMenu.js index 99d1f892b9..17f1a23e14 100644 --- a/src/components/structures/ContextualMenu.js +++ b/src/components/structures/ContextualMenu.js @@ -40,7 +40,7 @@ function getOrCreateContainer() { return container; } -class ContextualMenu extends React.Component { +export default class ContextualMenu extends React.Component { propTypes: { top: PropTypes.number, bottom: PropTypes.number, @@ -57,6 +57,10 @@ class ContextualMenu extends React.Component { menuPaddingRight: PropTypes.number, menuPaddingBottom: PropTypes.number, menuPaddingLeft: PropTypes.number, + + // If true, insert an invisible screen-sized element behind the + // menu that when clicked will close it. + hasBackground: PropTypes.bool, } render() { @@ -154,31 +158,30 @@ class ContextualMenu extends React.Component { { chevron }
-
+ { props.hasBackground &&
} ; } } -module.exports = { - createMenu: function(ElementClass, props) { - const closeMenu = function(...args) { - ReactDOM.unmountComponentAtNode(getOrCreateContainer()); +export function createMenu(ElementClass, props) { + const closeMenu = function(...args) { + ReactDOM.unmountComponentAtNode(getOrCreateContainer()); - if (props && props.onFinished) { - props.onFinished.apply(null, args); - } - }; + if (props && props.onFinished) { + props.onFinished.apply(null, args); + } + }; - const menu = ; + const menu = ; - ReactDOM.render(menu, getOrCreateContainer()); + ReactDOM.render(menu, getOrCreateContainer()); - return {close: closeMenu}; - }, -}; + return {close: closeMenu}; +} From 2dc51c516c5328de992c8ccccd634bda6e33e1fb Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 11 May 2018 14:47:57 +0100 Subject: [PATCH 3/9] Use new ContextualMenu component in Stickerpicker --- src/components/views/rooms/Stickerpicker.js | 93 +++++++++++++-------- 1 file changed, 56 insertions(+), 37 deletions(-) diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index 9b489c3e38..8784599238 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -17,7 +17,6 @@ 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 Modal from '../../../Modal'; import sdk from '../../../index'; @@ -36,6 +35,7 @@ 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._onResize = this._onResize.bind(this); this._onFinished = this._onFinished.bind(this); this.popoverWidth = 300; @@ -44,13 +44,17 @@ export default class Stickerpicker extends React.Component { this.state = { showStickers: false, imError: null, + stickerpickerX: null, + stickerpickerY: null, + stickerpickerWidget: null, + widgetId: null, }; } _removeStickerpickerWidgets() { console.warn('Removing Stickerpicker widgets'); - if (this.widgetId) { - this.scalarClient.disableWidgetAssets(widgetType, this.widgetId).then(() => { + if (this.state.widgetId) { + this.scalarClient.disableWidgetAssets(widgetType, this.state.widgetId).then(() => { console.warn('Assets disabled'); }).catch((err) => { console.error('Failed to disable assets'); @@ -59,8 +63,7 @@ export default class Stickerpicker extends React.Component { console.warn('No widget ID specified, not disabling assets'); } - // Wrap this in a timeout in order to avoid the DOM node from being pulled from under its feet - setTimeout(() => this.stickersMenu.close()); + this.setState({showStickers: false}); Widgets.removeStickerpickerWidgets().then(() => { this.forceUpdate(); }).catch((e) => { @@ -69,6 +72,9 @@ export default class Stickerpicker extends React.Component { } componentDidMount() { + // Close the sticker picker when the window resizes + window.addEventListener('resize', this._onResize); + this.scalarClient = null; if (SdkConfig.get().integrations_ui_url && SdkConfig.get().integrations_rest_url) { this.scalarClient = new ScalarAuthClient(); @@ -82,9 +88,15 @@ export default class Stickerpicker extends React.Component { if (!this.state.imError) { this.dispatcherRef = dis.register(this._onWidgetAction); } + const stickerpickerWidget = Widgets.getStickerpickerWidgets()[0]; + this.setState({ + stickerpickerWidget, + widgetId: stickerpickerWidget ? stickerpickerWidget.id : null, + }); } componentWillUnmount() { + window.removeEventListener('resize', this._onResize); if (this.dispatcherRef) { dis.unregister(this.dispatcherRef); } @@ -102,9 +114,7 @@ export default class Stickerpicker extends React.Component { if (payload.action === "user_widget_updated") { 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 - setTimeout(() => this.stickersMenu.close()); + this.setState({showStickers: false}); } } @@ -137,14 +147,13 @@ export default class Stickerpicker extends React.Component { // 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]; + const stickerpickerWidget = this.state.stickerpickerWidget; let stickersContent; // Load stickerpack content if (stickerpickerWidget && stickerpickerWidget.content && stickerpickerWidget.content.url) { // Set default name stickerpickerWidget.content.name = stickerpickerWidget.name || _t("Stickerpack"); - this.widgetId = stickerpickerWidget.id; stickersContent = (
@@ -187,12 +196,7 @@ export default class Stickerpicker extends React.Component { // Default content to show if stickerpicker widget not added console.warn("No available sticker picker widgets"); stickersContent = this._defaultStickerpickerContent(); - this.widgetId = null; - this.forceUpdate(); } - this.setState({ - showStickers: false, - }); return stickersContent; } @@ -202,29 +206,17 @@ export default class Stickerpicker extends React.Component { * @param {Event} e Event that triggered the function */ _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 - 42; const y = (buttonRect.top + (buttonRect.height / 2) + window.pageYOffset) - 19; - // const self = this; - this.stickersMenu = ContextualMenu.createMenu(GenericElementContextMenu, { - chevronOffset: 10, - chevronFace: 'bottom', - left: x, - top: y, - menuWidth: this.popoverWidth, - menuHeight: this.popoverHeight, - element: this._getStickerpickerContent(), - onFinished: this._onFinished, - menuPaddingTop: 0, - menuPaddingLeft: 0, - menuPaddingRight: 0, + + this.setState({ + showStickers: true, + stickerPickerX: x, + stickerPickerY: y, }); - - - this.setState({showStickers: true}); } /** @@ -232,7 +224,14 @@ export default class Stickerpicker extends React.Component { * @param {Event} ev Event that triggered the function call */ _onHideStickersClick(ev) { - setTimeout(() => this.stickersMenu.close()); + this.setState({showStickers: false}); + } + + /** + * Called when the window is resized + */ + _onResize() { + this.setState({showStickers: false}); } /** @@ -251,20 +250,37 @@ export default class Stickerpicker extends React.Component { this.scalarClient.getScalarInterfaceUrlForRoom( this.props.room, 'type_' + widgetType, - this.widgetId, + this.state.widgetId, ) : null; Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, { src: src, }, "mx_IntegrationsManager"); - // Wrap this in a timeout in order to avoid the DOM node from being pulled from under its feet - setTimeout(() => this.stickersMenu.close()); + this.setState({showStickers: false}); } render() { const TintableSvg = sdk.getComponent("elements.TintableSvg"); + const ContextualMenu = sdk.getComponent('structures.ContextualMenu'); + const GenericElementContextMenu = sdk.getComponent('context_menus.GenericElementContextMenu'); let stickersButton; + + const stickerPicker = ; + if (this.state.showStickers) { // Show hide-stickers button stickersButton = @@ -289,6 +305,9 @@ export default class Stickerpicker extends React.Component {
; } - return stickersButton; + return
+ {stickersButton} + {this.state.showStickers && stickerPicker} +
; } } From 6500797d2aa0b7b61e48bc8464605e5e9c4e4242 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 11 May 2018 14:49:50 +0100 Subject: [PATCH 4/9] Use correct CSS selector in message composer to stop any last div from having its right-padding removed --- res/css/views/rooms/_MessageComposer.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/css/views/rooms/_MessageComposer.scss b/res/css/views/rooms/_MessageComposer.scss index 2e8f07b7ef..0a708a8edc 100644 --- a/res/css/views/rooms/_MessageComposer.scss +++ b/res/css/views/rooms/_MessageComposer.scss @@ -34,7 +34,7 @@ limitations under the License. width: 100%; } -.mx_MessageComposer_row div:last-child{ +.mx_MessageComposer_row > div:last-child{ padding-right: 0; } From 746eeee33cbc0f56061bc7c42d4dd081ae6f2324 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 11 May 2018 15:07:51 +0100 Subject: [PATCH 5/9] Make AppTile in Stickerpicker persistent using PersistedElement --- .../views/elements/PersistedElement.js | 116 ++++++++++++++++++ src/components/views/rooms/Stickerpicker.js | 7 ++ 2 files changed, 123 insertions(+) create mode 100644 src/components/views/elements/PersistedElement.js diff --git a/src/components/views/elements/PersistedElement.js b/src/components/views/elements/PersistedElement.js new file mode 100644 index 0000000000..4d8cd4140e --- /dev/null +++ b/src/components/views/elements/PersistedElement.js @@ -0,0 +1,116 @@ +/* +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. +*/ + +const classNames = require('classnames'); +const React = require('react'); +const ReactDOM = require('react-dom'); +import PropTypes from 'prop-types'; + +// Shamelessly ripped off Modal.js. There's probably a better way +// of doing reusable widgets like dialog boxes & menus where we go and +// pass in a custom control as the actual body. + +const ContainerId = "mx_PersistedElement"; + +function getOrCreateContainer() { + let container = document.getElementById(ContainerId); + + if (!container) { + container = document.createElement("div"); + container.id = ContainerId; + document.body.appendChild(container); + } + + return container; +} + +// Greater than that of the ContextualMenu +const PE_Z_INDEX = 3000; + +/* + * Class of component that renders its children in a separate ReactDOM virtual tree + * in a container element appended to document.body. + * + * This prevents the children from being unmounted when the parent of PersistedElement + * unmounts, allowing them to persist. + * + * When PE is unmounted, it hides the children using CSS. When mounted or updated, the + * children are made visible and are positioned into a div that is given the same + * bounding rect as the parent of PE. + */ +export default class PersistedElement extends React.Component { + constructor() { + super(); + this.collectChildContainer = this.collectChildContainer.bind(this); + this.collectChild = this.collectChild.bind(this); + } + + collectChildContainer(ref) { + this.childContainer = ref; + } + + collectChild(ref) { + this.child = ref; + this.updateChild(); + } + + componentDidMount() { + this.updateChild(); + } + + componentDidUpdate() { + this.updateChild(); + } + + componentWillUnmount() { + this.updateChildVisibility(this.child, false); + } + + updateChild() { + this.updateChildPosition(this.child, this.childContainer); + this.updateChildVisibility(this.child, true); + } + + updateChildVisibility(child, visible) { + if (!child) return; + child.style.display = visible ? 'block' : 'none'; + } + + updateChildPosition(child, parent) { + if (!child || !parent) return; + + const parentRect = parent.getBoundingClientRect(); + Object.assign(child.style, { + position: 'absolute', + top: parentRect.top + 'px', + left: parentRect.left + 'px', + width: parentRect.width + 'px', + height: parentRect.height + 'px', + zIndex: PE_Z_INDEX, + }); + } + + render() { + const content =
+ {this.props.children} +
; + + ReactDOM.render(content, getOrCreateContainer()); + + return
; + } +} + diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index 8784599238..36b99b2422 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -150,6 +150,11 @@ export default class Stickerpicker extends React.Component { const stickerpickerWidget = this.state.stickerpickerWidget; let stickersContent; + // Use a separate ReactDOM tree to render the AppTile separately so that it persists and does + // not unmount when we (a) close the sticker picker (b) switch rooms. It's properties are still + // updated. + const PersistedElement = sdk.getComponent("elements.PersistedElement"); + // Load stickerpack content if (stickerpickerWidget && stickerpickerWidget.content && stickerpickerWidget.content.url) { // Set default name @@ -166,6 +171,7 @@ export default class Stickerpicker extends React.Component { width: this.popoverWidth, }} > + + ); From 4b6378a80d5f415c85eba76bce76c00b3d8050c4 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 11 May 2018 16:22:54 +0100 Subject: [PATCH 6/9] Add API to send visibiliy actions to widgets --- src/WidgetMessaging.js | 10 ++++++++++ src/components/views/elements/AppTile.js | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/src/WidgetMessaging.js b/src/WidgetMessaging.js index effd96dacf..86eaa0b59b 100644 --- a/src/WidgetMessaging.js +++ b/src/WidgetMessaging.js @@ -94,6 +94,16 @@ export default class WidgetMessaging { }); } + sendVisibility(visible) { + return this.messageToWidget({ + api: OUTBOUND_API_NAME, + action: "visibility", + visible, + }) + .catch((error) => { + console.error("Failed to send visibility: ", error); + }); + } start() { this.fromWidget.addEndpoint(this.widgetId, this.widgetUrl); diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 63cf459987..0701117ab3 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -394,6 +394,10 @@ export default class AppTile extends React.Component { }).catch((err) => { console.log(`Failed to get capabilities for widget type ${this.props.type}`, this.props.id, err); }); + + // Allow parents to access widget messaging + if (this.props.collectWidgetMessaging) this.props.collectWidgetMessaging(this.widgetMessaging); + this.setState({loading: false}); } From 8b049b2182b8425144ed16d3ed1485e2bd33f467 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 11 May 2018 16:23:18 +0100 Subject: [PATCH 7/9] When stickerpicker made visible, send visibility over postMessage --- src/components/views/elements/AppTile.js | 19 ++++++++++++++++--- src/components/views/rooms/Stickerpicker.js | 19 ++++++++++++++++++- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 0701117ab3..b5d317ae59 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -167,6 +167,19 @@ export default class AppTile extends React.Component { // Widget action listeners this.dispatcherRef = dis.register(this._onWidgetAction); + + } + + componentDidUpdate() { + // Allow parents to access widget messaging + if (this.props.collectWidgetMessaging) { + this.props.collectWidgetMessaging(new Promise((resolve) => { + if (this.widgetMessaging) resolve(this.widgetMessaging); + + // Expect this to be resolved later + this._exposeWidgetMessaging = resolve; + })); + } } componentWillUnmount() { @@ -357,6 +370,9 @@ export default class AppTile extends React.Component { if (!this.widgetMessaging) { this._onInitialLoad(); } + if (this._exposeWidgetMessaging) { + this._exposeWidgetMessaging(this.widgetMessaging); + } } /** @@ -395,9 +411,6 @@ export default class AppTile extends React.Component { console.log(`Failed to get capabilities for widget type ${this.props.type}`, this.props.id, err); }); - // Allow parents to access widget messaging - if (this.props.collectWidgetMessaging) this.props.collectWidgetMessaging(this.widgetMessaging); - this.setState({loading: false}); } diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index 36b99b2422..75d5e3acf4 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -38,6 +38,8 @@ export default class Stickerpicker extends React.Component { this._onResize = this._onResize.bind(this); this._onFinished = this._onFinished.bind(this); + this._collectWidgetMessaging = this._collectWidgetMessaging.bind(this); + this.popoverWidth = 300; this.popoverHeight = 300; @@ -102,6 +104,14 @@ export default class Stickerpicker extends React.Component { } } + componentDidUpdate(prevProps, prevState) { + if (this._appWidgetMessaging && + prevState.showStickers !== this.state.showStickers + ) { + this._appWidgetMessaging.sendVisibility(this.state.showStickers); + } + } + _imError(errorMsg, e) { console.error(errorMsg, e); this.setState({ @@ -137,6 +147,12 @@ export default class Stickerpicker extends React.Component { ); } + async _collectWidgetMessaging(prom) { + const widgetMessaging = await prom; + this._appWidgetMessaging = widgetMessaging; + this._appWidgetMessaging.sendVisibility(true); + } + _getStickerpickerContent() { // Handle Integration Manager errors if (this.state._imError) { @@ -173,6 +189,7 @@ export default class Stickerpicker extends React.Component { > From 1f2f3474ed6a92b8f1648af8a7dc132a2cbebc80 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 11 May 2018 17:28:12 +0100 Subject: [PATCH 8/9] Delinting --- src/components/structures/ContextualMenu.js | 5 +++-- src/components/views/elements/AppTile.js | 1 - src/components/views/elements/PersistedElement.js | 2 -- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/components/structures/ContextualMenu.js b/src/components/structures/ContextualMenu.js index 17f1a23e14..daac294d12 100644 --- a/src/components/structures/ContextualMenu.js +++ b/src/components/structures/ContextualMenu.js @@ -173,12 +173,13 @@ export function createMenu(ElementClass, props) { } }; + // We only reference closeMenu once per call to createMenu const menu = ; ReactDOM.render(menu, getOrCreateContainer()); diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index b5d317ae59..1b58778be4 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -167,7 +167,6 @@ export default class AppTile extends React.Component { // Widget action listeners this.dispatcherRef = dis.register(this._onWidgetAction); - } componentDidUpdate() { diff --git a/src/components/views/elements/PersistedElement.js b/src/components/views/elements/PersistedElement.js index 4d8cd4140e..c4bac27b4e 100644 --- a/src/components/views/elements/PersistedElement.js +++ b/src/components/views/elements/PersistedElement.js @@ -14,10 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -const classNames = require('classnames'); const React = require('react'); const ReactDOM = require('react-dom'); -import PropTypes from 'prop-types'; // Shamelessly ripped off Modal.js. There's probably a better way // of doing reusable widgets like dialog boxes & menus where we go and From 06898394eb044c22422f246e3202f9d378ad5331 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 11 May 2018 18:06:58 +0100 Subject: [PATCH 9/9] Send visibility only when changed, and messaging is available --- src/components/views/elements/AppTile.js | 7 +------ src/components/views/rooms/Stickerpicker.js | 21 +++++++++++++-------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 1b58778be4..38b6fc200b 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -172,12 +172,7 @@ export default class AppTile extends React.Component { componentDidUpdate() { // Allow parents to access widget messaging if (this.props.collectWidgetMessaging) { - this.props.collectWidgetMessaging(new Promise((resolve) => { - if (this.widgetMessaging) resolve(this.widgetMessaging); - - // Expect this to be resolved later - this._exposeWidgetMessaging = resolve; - })); + this.props.collectWidgetMessaging(this.widgetMessaging); } } diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index 75d5e3acf4..0584cd6b0a 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -105,11 +105,7 @@ export default class Stickerpicker extends React.Component { } componentDidUpdate(prevProps, prevState) { - if (this._appWidgetMessaging && - prevState.showStickers !== this.state.showStickers - ) { - this._appWidgetMessaging.sendVisibility(this.state.showStickers); - } + this._sendVisibilityToWidget(this.state.showStickers); } _imError(errorMsg, e) { @@ -147,10 +143,19 @@ export default class Stickerpicker extends React.Component { ); } - async _collectWidgetMessaging(prom) { - const widgetMessaging = await prom; + _collectWidgetMessaging(widgetMessaging) { this._appWidgetMessaging = widgetMessaging; - this._appWidgetMessaging.sendVisibility(true); + + // Do this now instead of in componentDidMount because we might not have had the + // reference to widgetMessaging when mounting + this._sendVisibilityToWidget(true); + } + + _sendVisibilityToWidget(visible) { + if (this._appWidgetMessaging && visible !== this._prevSentVisibility) { + this._appWidgetMessaging.sendVisibility(visible); + this._prevSentVisibility = visible; + } } _getStickerpickerContent() {