Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Fix disappearing widget poput button
Browse files Browse the repository at this point in the history
  • Loading branch information
weeman1337 committed Jun 6, 2022
1 parent a7f1a0c commit f89d6a7
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 8 deletions.
26 changes: 21 additions & 5 deletions src/components/views/elements/AppTile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import SettingsStore from "../../../settings/SettingsStore";
import { aboveLeftOf, ContextMenuButton } from "../../structures/ContextMenu";
import PersistedElement, { getPersistKey } from "./PersistedElement";
import { WidgetType } from "../../../widgets/WidgetType";
import { StopGapWidget } from "../../../stores/widgets/StopGapWidget";
import { ElementWidget, StopGapWidget } from "../../../stores/widgets/StopGapWidget";
import { ElementWidgetActions } from "../../../stores/widgets/ElementWidgetActions";
import WidgetContextMenu from "../context_menus/WidgetContextMenu";
import WidgetAvatar from "../avatars/WidgetAvatar";
Expand All @@ -50,6 +50,7 @@ import MatrixClientContext from "../../../contexts/MatrixClientContext";
import { ActionPayload } from "../../../dispatcher/payloads";
import { Action } from '../../../dispatcher/actions';
import { ElementWidgetCapabilities } from '../../../stores/widgets/ElementWidgetCapabilities';
import { WidgetMessagingStore } from '../../../stores/widgets/WidgetMessagingStore';

interface IProps {
app: IApp;
Expand Down Expand Up @@ -196,6 +197,24 @@ export default class AppTile extends React.Component<IProps, IState> {
}
};

private determineInitialRequiresClientState(): boolean {
try {
const mockWidget = new ElementWidget(this.props.app);
const widgetApi = WidgetMessagingStore.instance.getMessaging(mockWidget, this.props.room.roomId);
if (widgetApi) {
// Load value from existing API to prevent resetting the requiresClient value on layout changes.
return widgetApi.hasCapability(ElementWidgetCapabilities.RequiresClient);
}
} catch {
// fallback to true
}

// requiresClient is initially set to true. This avoids the broken state of the popout
// button being visible (for an instance) and then disappearing when the widget is loaded.
// requiresClient <-> hide the popout button
return true;
}

/**
* Set initial component state when the App wUrl (widget URL) is being updated.
* Component props *must* be passed (rather than relying on this.props).
Expand All @@ -214,10 +233,7 @@ export default class AppTile extends React.Component<IProps, IState> {
error: null,
menuDisplayed: false,
widgetPageTitle: this.props.widgetPageTitle,
// requiresClient is initially set to true. This avoids the broken state of the popout
// button being visible (for an instance) and then disappearing when the widget is loaded.
// requiresClient <-> hide the popout button
requiresClient: true,
requiresClient: this.determineInitialRequiresClientState(),
};
}

Expand Down
43 changes: 40 additions & 3 deletions test/components/views/elements/AppTile-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import React from "react";
import TestRenderer from "react-test-renderer";
import { jest } from "@jest/globals";
import { Room } from "matrix-js-sdk/src/models/room";
import { MatrixWidgetType } from "matrix-widget-api";
import { ClientWidgetApi, MatrixWidgetType } from "matrix-widget-api";
import { mount, ReactWrapper } from "enzyme";
import { Optional } from "matrix-events-sdk";

Expand All @@ -39,11 +39,14 @@ import ActiveWidgetStore from "../../../../src/stores/ActiveWidgetStore";
import AppTile from "../../../../src/components/views/elements/AppTile";
import { Container, WidgetLayoutStore } from "../../../../src/stores/widgets/WidgetLayoutStore";
import AppsDrawer from "../../../../src/components/views/rooms/AppsDrawer";
import { ElementWidgetCapabilities } from "../../../../src/stores/widgets/ElementWidgetCapabilities";
import { ElementWidget } from "../../../../src/stores/widgets/StopGapWidget";
import { WidgetMessagingStore } from "../../../../src/stores/widgets/WidgetMessagingStore";

describe("AppTile", () => {
let cli;
let r1;
let r2;
let r1: Room;
let r2: Room;
const resizeNotifier = new ResizeNotifier();
let app1: IApp;
let app2: IApp;
Expand Down Expand Up @@ -328,6 +331,10 @@ describe("AppTile", () => {
moveToContainerSpy = jest.spyOn(WidgetLayoutStore.instance, 'moveToContainer');
});

it("requiresClient should be true", () => {
expect(wrapper.state('requiresClient')).toBe(true);
});

it("clicking 'minimise' should send the widget to the right", () => {
const minimiseButton = wrapper.find('.mx_AppTileMenuBar_iconButton_minimise');
minimiseButton.first().simulate('click');
Expand Down Expand Up @@ -355,5 +362,35 @@ describe("AppTile", () => {
expect(moveToContainerSpy).toHaveBeenCalledWith(r1, app1, Container.Top);
});
});

describe("with an existing widgetApi holding requiresClient = false", () => {
let wrapper: ReactWrapper;

beforeEach(() => {
const api = {
hasCapability: (capability: ElementWidgetCapabilities): boolean => {
return !(capability === ElementWidgetCapabilities.RequiresClient);
},
once: () => {},
} as unknown as ClientWidgetApi;

const mockWidget = new ElementWidget(app1);
WidgetMessagingStore.instance.storeMessaging(mockWidget, r1.roomId, api);

wrapper = mount((
<MatrixClientContext.Provider value={cli}>
<AppTile
key={app1.id}
app={app1}
room={r1}
/>
</MatrixClientContext.Provider>
));
});

it("requiresClient should be false", () => {
expect(wrapper.state('requiresClient')).toBe(false);
});
});
});
});

0 comments on commit f89d6a7

Please sign in to comment.