From 5989a21dfb97e0804b94bae503b2637e6d2dd7d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Tue, 13 Oct 2020 16:02:05 +0200 Subject: [PATCH 1/7] event-index: Pass the user/device id pair when initializing the event index. --- src/indexing/BaseEventIndexManager.ts | 5 ++++- src/indexing/EventIndexPeg.js | 9 +++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/indexing/BaseEventIndexManager.ts b/src/indexing/BaseEventIndexManager.ts index 64cf01bd6e..df14f84622 100644 --- a/src/indexing/BaseEventIndexManager.ts +++ b/src/indexing/BaseEventIndexManager.ts @@ -105,10 +105,13 @@ export default abstract class BaseEventIndexManager { /** * Initialize the event index for the given user. * + * @param {string} user_id The event that should be added to the index. + * @param {string} device_id The profile of the event sender at the + * * @return {Promise} A promise that will resolve when the event index is * initialized. */ - async initEventIndex(): Promise { + async initEventIndex(user_id: string, device_id: string): Promise { throw new Error("Unimplemented"); } diff --git a/src/indexing/EventIndexPeg.js b/src/indexing/EventIndexPeg.js index 58e8430825..6acc6caa10 100644 --- a/src/indexing/EventIndexPeg.js +++ b/src/indexing/EventIndexPeg.js @@ -21,6 +21,7 @@ limitations under the License. import PlatformPeg from "../PlatformPeg"; import EventIndex from "../indexing/EventIndex"; +import {MatrixClientPeg} from "../MatrixClientPeg"; import SettingsStore from '../settings/SettingsStore'; import {SettingLevel} from "../settings/SettingLevel"; @@ -70,9 +71,13 @@ class EventIndexPeg { async initEventIndex() { const index = new EventIndex(); const indexManager = PlatformPeg.get().getEventIndexingManager(); + const client = MatrixClientPeg.get(); + + const user_id = client.getUserId(); + const device_id = client.getDeviceId(); try { - await indexManager.initEventIndex(); + await indexManager.initEventIndex(user_id, device_id); const userVersion = await indexManager.getUserVersion(); const eventIndexIsEmpty = await indexManager.isEventIndexEmpty(); @@ -83,7 +88,7 @@ class EventIndexPeg { await indexManager.closeEventIndex(); await this.deleteEventIndex(); - await indexManager.initEventIndex(); + await indexManager.initEventIndex(user_id, device_id); await indexManager.setUserVersion(INDEX_VERSION); } From 860b1b46e0440293af0460434cf16b1760e3288c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Tue, 13 Oct 2020 17:03:58 +0200 Subject: [PATCH 2/7] event-index: Use camel case for the user/device id. --- src/indexing/BaseEventIndexManager.ts | 6 +++--- src/indexing/EventIndexPeg.js | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/indexing/BaseEventIndexManager.ts b/src/indexing/BaseEventIndexManager.ts index df14f84622..2474406618 100644 --- a/src/indexing/BaseEventIndexManager.ts +++ b/src/indexing/BaseEventIndexManager.ts @@ -105,13 +105,13 @@ export default abstract class BaseEventIndexManager { /** * Initialize the event index for the given user. * - * @param {string} user_id The event that should be added to the index. - * @param {string} device_id The profile of the event sender at the + * @param {string} userId The event that should be added to the index. + * @param {string} deviceId The profile of the event sender at the * * @return {Promise} A promise that will resolve when the event index is * initialized. */ - async initEventIndex(user_id: string, device_id: string): Promise { + async initEventIndex(userId: string, deviceId: string): Promise { throw new Error("Unimplemented"); } diff --git a/src/indexing/EventIndexPeg.js b/src/indexing/EventIndexPeg.js index 6acc6caa10..443daa8f43 100644 --- a/src/indexing/EventIndexPeg.js +++ b/src/indexing/EventIndexPeg.js @@ -73,11 +73,11 @@ class EventIndexPeg { const indexManager = PlatformPeg.get().getEventIndexingManager(); const client = MatrixClientPeg.get(); - const user_id = client.getUserId(); - const device_id = client.getDeviceId(); + const userId = client.getUserId(); + const deviceId = client.getDeviceId(); try { - await indexManager.initEventIndex(user_id, device_id); + await indexManager.initEventIndex(userId, deviceId); const userVersion = await indexManager.getUserVersion(); const eventIndexIsEmpty = await indexManager.isEventIndexEmpty(); @@ -88,7 +88,7 @@ class EventIndexPeg { await indexManager.closeEventIndex(); await this.deleteEventIndex(); - await indexManager.initEventIndex(user_id, device_id); + await indexManager.initEventIndex(userId, deviceId); await indexManager.setUserVersion(INDEX_VERSION); } From a2b61796afb5692fb433de04b4ced72200b720eb Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 13 Oct 2020 10:30:52 +0100 Subject: [PATCH 3/7] Improve LHS resize performance Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/LoggedInView.tsx | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/components/structures/LoggedInView.tsx b/src/components/structures/LoggedInView.tsx index 79f2916200..23c91d7ee0 100644 --- a/src/components/structures/LoggedInView.tsx +++ b/src/components/structures/LoggedInView.tsx @@ -218,6 +218,7 @@ class LoggedInView extends React.Component { vertical: "mx_ResizeHandle_vertical", reverse: "mx_ResizeHandle_reverse", }; + let size; const collapseConfig = { toggleSize: 260 - 50, onCollapsed: (collapsed) => { @@ -228,21 +229,19 @@ class LoggedInView extends React.Component { dis.dispatch({action: "show_left_panel"}, true); } }, - onResized: (size) => { - window.localStorage.setItem("mx_lhs_size", '' + size); + onResized: (_size) => { + size = _size; this.props.resizeNotifier.notifyLeftHandleResized(); }, onResizeStart: () => { this.props.resizeNotifier.startResizing(); }, onResizeStop: () => { + window.localStorage.setItem("mx_lhs_size", '' + size); this.props.resizeNotifier.stopResizing(); }, }; - const resizer = new Resizer( - this._resizeContainer.current, - CollapseDistributor, - collapseConfig); + const resizer = new Resizer(this._resizeContainer.current, CollapseDistributor, collapseConfig); resizer.setClassNames(classNames); return resizer; } From bb52bad0995380b9e52ce785a640e925f74de115 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 13 Oct 2020 16:23:49 +0100 Subject: [PATCH 4/7] Remove stale props and CSS classes Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- res/css/views/rooms/_AppsDrawer.scss | 79 ------------------------ src/components/structures/RoomView.tsx | 1 - src/components/views/rooms/AppsDrawer.js | 3 - src/components/views/rooms/AuxPanel.js | 3 - 4 files changed, 86 deletions(-) diff --git a/res/css/views/rooms/_AppsDrawer.scss b/res/css/views/rooms/_AppsDrawer.scss index 451704bd88..6e3ffbe5f0 100644 --- a/res/css/views/rooms/_AppsDrawer.scss +++ b/res/css/views/rooms/_AppsDrawer.scss @@ -50,10 +50,6 @@ $MiniAppTileHeight: 200px; } } -.mx_AppsDrawer_hidden { - display: none; -} - .mx_AppsContainer { display: flex; flex-direction: row; @@ -78,15 +74,6 @@ $MiniAppTileHeight: 200px; font-size: $font-12px; } -.mx_SetAppURLDialog_input { - border-radius: 3px; - border: 1px solid $input-border-color; - padding: 9px; - color: $primary-hairline-color; - background-color: $primary-bg-color; - font-size: $font-15px; -} - .mx_AppTile { width: 50%; border: 5px solid $widget-menu-bar-bg-color; @@ -242,72 +229,6 @@ $MiniAppTileHeight: 200px; display: block; } -.mx_AppTileMenuBarWidgetPadding { - margin-right: 5px; -} - -.mx_AppIconTile { - background-color: $lightbox-bg-color; - border: 1px solid rgba(0, 0, 0, 0); - width: 200px; - box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2); - transition: 0.3s; - border-radius: 3px; - margin: 5px; - display: inline-block; -} - -.mx_AppIconTile.mx_AppIconTile_active { - color: $accent-color; - border-color: $accent-color; -} - -.mx_AppIconTile:hover { - border: 1px solid $accent-color; - box-shadow: 0 0 10px 5px rgba(200, 200, 200, 0.5); -} - -.mx_AppIconTile_content { - padding: 2px 16px; - height: 60px; - overflow: hidden; -} - -.mx_AppIconTile_content h4 { - margin-top: 5px; - margin-bottom: 2px; -} - -.mx_AppIconTile_content p { - margin-top: 0; - margin-bottom: 5px; - font-size: smaller; -} - -.mx_AppIconTile_image { - padding: 10px; - max-width: 100px; - max-height: 100px; - width: auto; - height: auto; -} - -.mx_AppIconTile_imageContainer { - text-align: center; - width: 100%; - background-color: white; - border-radius: 3px 3px 0 0; - height: 155px; - display: flex; - justify-content: center; - align-items: center; -} - -form.mx_Custom_Widget_Form div { - margin-top: 10px; - margin-bottom: 10px; -} - .mx_AppPermissionWarning { text-align: center; background-color: $widget-menu-bar-bg-color; diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index fcb2d274c1..bfe823b2f9 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -1853,7 +1853,6 @@ export default class RoomView extends React.Component { draggingFile={this.state.draggingFile} maxHeight={this.state.auxPanelMaxHeight} showApps={this.state.showApps} - hideAppsDrawer={false} onResize={this.onResize} resizeNotifier={this.props.resizeNotifier} > diff --git a/src/components/views/rooms/AppsDrawer.js b/src/components/views/rooms/AppsDrawer.js index a67338b9d5..a360016ba6 100644 --- a/src/components/views/rooms/AppsDrawer.js +++ b/src/components/views/rooms/AppsDrawer.js @@ -40,12 +40,10 @@ export default class AppsDrawer extends React.Component { room: PropTypes.object.isRequired, resizeNotifier: PropTypes.instanceOf(ResizeNotifier).isRequired, showApps: PropTypes.bool, // Should apps be rendered - hide: PropTypes.bool, // If rendered, should apps drawer be visible }; static defaultProps = { showApps: true, - hide: false, }; constructor(props) { @@ -173,7 +171,6 @@ export default class AppsDrawer extends React.Component { const classes = classNames({ "mx_AppsDrawer": true, - "mx_AppsDrawer_hidden": this.props.hide, "mx_AppsDrawer_fullWidth": apps.length < 2, "mx_AppsDrawer_minimised": !this.props.showApps, }); diff --git a/src/components/views/rooms/AuxPanel.js b/src/components/views/rooms/AuxPanel.js index b7ed457a74..a088418d5e 100644 --- a/src/components/views/rooms/AuxPanel.js +++ b/src/components/views/rooms/AuxPanel.js @@ -37,7 +37,6 @@ export default class AuxPanel extends React.Component { room: PropTypes.object.isRequired, userId: PropTypes.string.isRequired, showApps: PropTypes.bool, // Render apps - hideAppsDrawer: PropTypes.bool, // Do not display apps drawer and content (may still be rendered) // set to true to show the file drop target draggingFile: PropTypes.bool, @@ -54,7 +53,6 @@ export default class AuxPanel extends React.Component { static defaultProps = { showApps: true, - hideAppsDrawer: false, }; constructor(props) { @@ -170,7 +168,6 @@ export default class AuxPanel extends React.Component { userId={this.props.userId} maxHeight={this.props.maxHeight} showApps={this.props.showApps} - hide={this.props.hideAppsDrawer} resizeNotifier={this.props.resizeNotifier} />; } From 40038a6100de92e3629c48577cb1e50386e457bc Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 13 Oct 2020 14:39:27 -0600 Subject: [PATCH 5/7] Run templating on the popout URL too Fixes https://github.com/vector-im/element-web/issues/15443 --- src/stores/widgets/StopGapWidget.ts | 42 +++++++++++++++++------------ 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/src/stores/widgets/StopGapWidget.ts b/src/stores/widgets/StopGapWidget.ts index 1eb4f9cd27..f7d6d1853e 100644 --- a/src/stores/widgets/StopGapWidget.ts +++ b/src/stores/widgets/StopGapWidget.ts @@ -74,6 +74,16 @@ class ElementWidget extends Widget { return super.templateUrl; } + public get popoutTemplateUrl(): string { + if (WidgetType.JITSI.matches(this.type)) { + return WidgetUtils.getLocalJitsiWrapperUrl({ + forLocalRender: false, // The only important difference between this and templateUrl() + auth: super.rawData?.auth, + }); + } + return this.templateUrl; // use this instead of super to ensure we get appropriate templating + } + public get rawData(): IWidgetData { let conferenceId = super.rawData['conferenceId']; if (conferenceId === undefined) { @@ -94,8 +104,8 @@ class ElementWidget extends Widget { }; } - public getCompleteUrl(params: ITemplateParams): string { - return runTemplate(this.templateUrl, { + public getCompleteUrl(params: ITemplateParams, asPopout=false): string { + return runTemplate(asPopout ? this.popoutTemplateUrl : this.templateUrl, { // we need to supply a whole widget to the template, but don't have // easy access to the definition the superclass is using, so be sad // and gutwrench it. @@ -109,7 +119,7 @@ class ElementWidget extends Widget { export class StopGapWidget extends EventEmitter { private messaging: ClientWidgetApi; - private mockWidget: Widget; + private mockWidget: ElementWidget; private scalarToken: string; constructor(private appTileProps: IAppTileProps) { @@ -133,12 +143,23 @@ export class StopGapWidget extends EventEmitter { * The URL to use in the iframe */ public get embedUrl(): string { + return this.runUrlTemplate({asPopout: false}); + } + + /** + * The URL to use in the popout + */ + public get popoutUrl(): string { + return this.runUrlTemplate({asPopout: true}); + } + + private runUrlTemplate(opts: {asPopout: boolean} = {asPopout: false}): string { const templated = this.mockWidget.getCompleteUrl({ currentRoomId: RoomViewStore.getRoomId(), currentUserId: MatrixClientPeg.get().getUserId(), userDisplayName: OwnProfileStore.instance.displayName, userHttpAvatarUrl: OwnProfileStore.instance.getHttpAvatarUrl(), - }); + }, opts?.asPopout); // Add in some legacy support sprinkles // TODO: Replace these with proper widget params @@ -158,19 +179,6 @@ export class StopGapWidget extends EventEmitter { return parsed.toString().replace(/%24/g, '$'); } - /** - * The URL to use in the popout - */ - public get popoutUrl(): string { - if (WidgetType.JITSI.matches(this.mockWidget.type)) { - return WidgetUtils.getLocalJitsiWrapperUrl({ - forLocalRender: false, - auth: this.mockWidget.rawData?.auth, - }); - } - return this.embedUrl; - } - public get isManagedByManager(): boolean { return !!this.scalarToken; } From 294c35347c89fe2e938258334c1de483b53b0832 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 13 Oct 2020 14:55:44 -0600 Subject: [PATCH 6/7] Ensure widgets are destroyed cleanly when minimized Fixes https://github.com/vector-im/element-web/issues/15444 (an artifact of joining a call then minimizing the widget) Also fixes other issues relating to widgets not loading when being minimized/maximized. --- src/components/views/elements/AppTile.js | 9 ++++++++- src/components/views/elements/PersistentApp.js | 5 +++++ src/stores/widgets/StopGapWidget.ts | 4 ++-- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index fda2652d12..c732d8ec95 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -240,10 +240,14 @@ export default class AppTile extends React.Component { this.iframe.src = 'about:blank'; } + if (WidgetType.JITSI.matches(this.props.app.type)) { + dis.dispatch({action: 'hangup_conference'}); + } + // Delete the widget from the persisted store for good measure. PersistedElement.destroyElement(this._persistKey); - this._sgWidget.stop(); + this._sgWidget.stop({forceDestroy: true}); } /* If user has permission to modify widgets, delete the widget, @@ -387,6 +391,9 @@ export default class AppTile extends React.Component { if (this.props.show) { // if we were being shown, end the widget as we're about to be minimized. this._endWidgetActions(); + } else { + // restart the widget actions + this._resetWidget(this.props); } dis.dispatch({ action: 'appsDrawer', diff --git a/src/components/views/elements/PersistentApp.js b/src/components/views/elements/PersistentApp.js index a3e413151a..8b2aa5c87c 100644 --- a/src/components/views/elements/PersistentApp.js +++ b/src/components/views/elements/PersistentApp.js @@ -58,6 +58,11 @@ export default class PersistentApp extends React.Component { const persistentWidgetInRoomId = ActiveWidgetStore.getRoomId(this.state.persistentWidgetId); if (this.state.roomId !== persistentWidgetInRoomId) { const persistentWidgetInRoom = MatrixClientPeg.get().getRoom(persistentWidgetInRoomId); + + // Sanity check the room - the widget may have been destroyed between render cycles, and + // thus no room is associated anymore. + if (!persistentWidgetInRoom) return null; + // get the widget data const appEvent = WidgetUtils.getRoomWidgets(persistentWidgetInRoom).find((ev) => { return ev.getStateKey() === ActiveWidgetStore.getPersistentWidgetId(); diff --git a/src/stores/widgets/StopGapWidget.ts b/src/stores/widgets/StopGapWidget.ts index f7d6d1853e..998dd2afb3 100644 --- a/src/stores/widgets/StopGapWidget.ts +++ b/src/stores/widgets/StopGapWidget.ts @@ -283,8 +283,8 @@ export class StopGapWidget extends EventEmitter { } } - public stop() { - if (ActiveWidgetStore.getPersistentWidgetId() === this.mockWidget.id) { + public stop(opts = {forceDestroy: false}) { + if (!opts?.forceDestroy && ActiveWidgetStore.getPersistentWidgetId() === this.mockWidget.id) { console.log("Skipping destroy - persistent widget"); return; } From f9ac390842a90f7a0062a623b8c32858d8e294e1 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 13 Oct 2020 14:56:27 -0600 Subject: [PATCH 7/7] Appease the linter --- src/stores/widgets/StopGapWidget.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stores/widgets/StopGapWidget.ts b/src/stores/widgets/StopGapWidget.ts index 998dd2afb3..41b040b8c6 100644 --- a/src/stores/widgets/StopGapWidget.ts +++ b/src/stores/widgets/StopGapWidget.ts @@ -153,7 +153,7 @@ export class StopGapWidget extends EventEmitter { return this.runUrlTemplate({asPopout: true}); } - private runUrlTemplate(opts: {asPopout: boolean} = {asPopout: false}): string { + private runUrlTemplate(opts = {asPopout: false}): string { const templated = this.mockWidget.getCompleteUrl({ currentRoomId: RoomViewStore.getRoomId(), currentUserId: MatrixClientPeg.get().getUserId(),