From 191b0a1517aaf493c46c38373533d8588692ff0c Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Wed, 5 Oct 2022 22:58:27 +0200 Subject: [PATCH] Fix applying programmatically set height for "top" room layout (#9339) * Fix applying programmatically set height for "top" room layout When applying a room layout automatically (e.g. via `io.element.widgets.layout` state event), in cases the layout mode container it set to "top", the height was previously not correctly updated. Signed-off-by: Oliver Sand * Add cypress tests Signed-off-by: Oliver Sand --- cypress/e2e/widgets/layout.spec.ts | 121 ++++++++++++++++++++++ src/components/views/rooms/AppsDrawer.tsx | 18 ++-- 2 files changed, 131 insertions(+), 8 deletions(-) create mode 100644 cypress/e2e/widgets/layout.spec.ts diff --git a/cypress/e2e/widgets/layout.spec.ts b/cypress/e2e/widgets/layout.spec.ts new file mode 100644 index 0000000000..25264c6622 --- /dev/null +++ b/cypress/e2e/widgets/layout.spec.ts @@ -0,0 +1,121 @@ +/* +Copyright 2022 Oliver Sand +Copyright 2022 Nordeck IT + Consulting GmbH. + +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 { IWidget } from "matrix-widget-api"; + +import { SynapseInstance } from "../../plugins/synapsedocker"; + +const ROOM_NAME = 'Test Room'; +const WIDGET_ID = "fake-widget"; +const WIDGET_HTML = ` + + + Fake Widget + + + Hello World + + +`; + +describe('Widget Layout', () => { + let widgetUrl: string; + let synapse: SynapseInstance; + let roomId: string; + + beforeEach(() => { + cy.startSynapse("default").then(data => { + synapse = data; + + cy.initTestUser(synapse, "Sally"); + }); + cy.serveHtmlFile(WIDGET_HTML).then(url => { + widgetUrl = url; + }); + + cy.createRoom({ + name: ROOM_NAME, + }).then((id) => { + roomId = id; + + // setup widget via state event + cy.getClient().then(async matrixClient => { + const content: IWidget = { + id: WIDGET_ID, + creatorUserId: 'somebody', + type: 'widget', + name: 'widget', + url: widgetUrl, + }; + await matrixClient.sendStateEvent(roomId, 'im.vector.modular.widgets', content, WIDGET_ID); + }).as('widgetEventSent'); + + // set initial layout + cy.getClient().then(async matrixClient => { + const content = { + widgets: { + [WIDGET_ID]: { + container: 'top', index: 1, width: 100, height: 0, + }, + }, + }; + await matrixClient.sendStateEvent(roomId, 'io.element.widgets.layout', content, ""); + }).as('layoutEventSent'); + }); + + cy.all([ + cy.get("@widgetEventSent"), + cy.get("@layoutEventSent"), + ]).then(() => { + // open the room + cy.viewRoomByName(ROOM_NAME); + }); + }); + + afterEach(() => { + cy.stopSynapse(synapse); + cy.stopWebServers(); + }); + + it('manually resize the height of the top container layout', () => { + cy.get('iframe[title="widget"]').invoke('height').should('be.lessThan', 250); + + cy.get('.mx_AppsContainer_resizerHandle') + .trigger('mousedown') + .trigger('mousemove', { clientX: 0, clientY: 550, force: true }) + .trigger('mouseup', { clientX: 0, clientY: 550, force: true }); + + cy.get('iframe[title="widget"]').invoke('height').should('be.greaterThan', 400); + }); + + it('programatically resize the height of the top container layout', () => { + cy.get('iframe[title="widget"]').invoke('height').should('be.lessThan', 250); + + cy.getClient().then(async matrixClient => { + const content = { + widgets: { + [WIDGET_ID]: { + container: 'top', index: 1, width: 100, height: 100, + }, + }, + }; + await matrixClient.sendStateEvent(roomId, 'io.element.widgets.layout', content, ""); + }); + + cy.get('iframe[title="widget"]').invoke('height').should('be.greaterThan', 400); + }); +}); diff --git a/src/components/views/rooms/AppsDrawer.tsx b/src/components/views/rooms/AppsDrawer.tsx index 601cc9ee34..15eb042877 100644 --- a/src/components/views/rooms/AppsDrawer.tsx +++ b/src/components/views/rooms/AppsDrawer.tsx @@ -31,7 +31,6 @@ import Resizer from "../../../resizer/resizer"; import PercentageDistributor from "../../../resizer/distributors/percentage"; import { Container, WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore"; import { clamp, percentageOf, percentageWithin } from "../../../utils/numbers"; -import { useStateCallback } from "../../../hooks/useStateCallback"; import UIStore from "../../../stores/UIStore"; import { IApp } from "../../../stores/WidgetStore"; import { ActionPayload } from "../../../dispatcher/payloads"; @@ -330,13 +329,8 @@ const PersistentVResizer: React.FC = ({ defaultHeight = 280; } - const [height, setHeight] = useStateCallback(defaultHeight, newHeight => { - newHeight = percentageOf(newHeight, minHeight, maxHeight) * 100; - WidgetLayoutStore.instance.setContainerHeight(room, Container.Top, newHeight); - }); - return { @@ -346,7 +340,15 @@ const PersistentVResizer: React.FC = ({ resizeNotifier.notifyTimelineHeightChanged(); }} onResizeStop={(e, dir, ref, d) => { - setHeight(height + d.height); + let newHeight = defaultHeight + d.height; + newHeight = percentageOf(newHeight, minHeight, maxHeight) * 100; + + WidgetLayoutStore.instance.setContainerHeight( + room, + Container.Top, + newHeight, + ); + resizeNotifier.stopResizing(); }} handleWrapperClass={handleWrapperClass}