diff --git a/cypress/e2e/widgets/layout.spec.ts b/cypress/e2e/widgets/layout.spec.ts
new file mode 100644
index 00000000000..25264c66224
--- /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 601cc9ee346..15eb0428779 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}