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

Commit 11096b2

Browse files
authored
Expose apps/widgets (#12071)
* Expose apps/widgets Signed-off-by: Charly Nguyen <[email protected]> * Bump @matrix-org/react-sdk-module-api from 2.2.1 to 2.3.0 Signed-off-by: Charly Nguyen <[email protected]> --------- Signed-off-by: Charly Nguyen <[email protected]>
1 parent 783007b commit 11096b2

File tree

10 files changed

+158
-6
lines changed

10 files changed

+158
-6
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
"@matrix-org/emojibase-bindings": "^1.1.2",
7070
"@matrix-org/matrix-wysiwyg": "2.17.0",
7171
"@matrix-org/olm": "3.2.15",
72-
"@matrix-org/react-sdk-module-api": "^2.2.1",
72+
"@matrix-org/react-sdk-module-api": "^2.3.0",
7373
"@matrix-org/spec": "^1.7.0",
7474
"@sentry/browser": "^7.0.0",
7575
"@testing-library/react-hooks": "^8.0.1",

src/modules/ProxiedModuleApi.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ import { Action } from "../dispatcher/actions";
3838
import { OverwriteLoginPayload } from "../dispatcher/payloads/OverwriteLoginPayload";
3939
import { ActionPayload } from "../dispatcher/payloads";
4040
import SettingsStore from "../settings/SettingsStore";
41+
import WidgetStore, { IApp } from "../stores/WidgetStore";
42+
import { Container, WidgetLayoutStore } from "../stores/widgets/WidgetLayoutStore";
4143

4244
/**
4345
* Glue between the `ModuleApi` interface and the react-sdk. Anticipates one instance
@@ -218,4 +220,38 @@ export class ProxiedModuleApi implements ModuleApi {
218220
if (!maybeObj || !(typeof maybeObj === "object")) return undefined;
219221
return maybeObj[key];
220222
}
223+
224+
/**
225+
* @override
226+
*/
227+
public getApps(roomId: string): IApp[] {
228+
return WidgetStore.instance.getApps(roomId);
229+
}
230+
231+
/**
232+
* @override
233+
*/
234+
public getAppAvatarUrl(app: IApp, width?: number, height?: number, resizeMethod?: string): string | null {
235+
if (!app.avatar_url) return null;
236+
// eslint-disable-next-line no-restricted-properties
237+
return MatrixClientPeg.safeGet().mxcUrlToHttp(app.avatar_url, width, height, resizeMethod);
238+
}
239+
240+
/**
241+
* @override
242+
*/
243+
public isAppInContainer(app: IApp, container: Container, roomId: string): boolean {
244+
const room = MatrixClientPeg.safeGet().getRoom(roomId);
245+
if (!room) return false;
246+
return WidgetLayoutStore.instance.isInContainer(room, app, container);
247+
}
248+
249+
/**
250+
* @override
251+
*/
252+
public moveAppToContainer(app: IApp, container: Container, roomId: string): void {
253+
const room = MatrixClientPeg.safeGet().getRoom(roomId);
254+
if (!room) return;
255+
WidgetLayoutStore.instance.moveToContainer(room, app, container);
256+
}
221257
}

test/components/views/rooms/wysiwyg_composer/utils/autocomplete-test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ const createMockCompletion = (props: Partial<ICompletion>): ICompletion => {
4141
};
4242

4343
jest.mock("../../../../../../src/Avatar");
44+
jest.mock("../../../../../../src/stores/WidgetStore");
45+
jest.mock("../../../../../../src/stores/widgets/WidgetLayoutStore");
4446

4547
beforeEach(() => jest.clearAllMocks());
4648
afterAll(() => jest.restoreAllMocks());

test/components/views/settings/AddPrivilegedUsers-test.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import UserProvider from "../../../../src/autocomplete/UserProvider";
3030
import { ICompletion } from "../../../../src/autocomplete/Autocompleter";
3131

3232
jest.mock("../../../../src/autocomplete/UserProvider");
33+
jest.mock("../../../../src/stores/WidgetStore");
34+
jest.mock("../../../../src/stores/widgets/WidgetLayoutStore");
3335

3436
const completions: ICompletion[] = [
3537
{

test/modules/ProxiedModuleApi-test.tsx

Lines changed: 104 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,18 @@ import { AccountAuthInfo } from "@matrix-org/react-sdk-module-api/lib/types/Acco
2020
import { DialogContent, DialogProps } from "@matrix-org/react-sdk-module-api/lib/components/DialogContent";
2121
import { screen, within } from "@testing-library/react";
2222
import userEvent from "@testing-library/user-event";
23+
import { MatrixClient } from "matrix-js-sdk/src/matrix";
24+
import { Mocked } from "jest-mock";
2325

2426
import { ProxiedModuleApi } from "../../src/modules/ProxiedModuleApi";
25-
import { stubClient } from "../test-utils";
27+
import { getMockClientWithEventEmitter, mkRoom, stubClient } from "../test-utils";
2628
import { setLanguage } from "../../src/languageHandler";
2729
import { ModuleRunner } from "../../src/modules/ModuleRunner";
2830
import { registerMockModule } from "./MockModule";
2931
import defaultDispatcher from "../../src/dispatcher/dispatcher";
3032
import { Action } from "../../src/dispatcher/actions";
33+
import WidgetStore, { IApp } from "../../src/stores/WidgetStore";
34+
import { Container, WidgetLayoutStore } from "../../src/stores/widgets/WidgetLayoutStore";
3135

3236
describe("ProxiedApiModule", () => {
3337
afterEach(() => {
@@ -254,4 +258,103 @@ describe("ProxiedApiModule", () => {
254258
expect(dialog).not.toBeInTheDocument();
255259
});
256260
});
261+
262+
describe("getApps", () => {
263+
it("should return apps from the widget store", () => {
264+
const api = new ProxiedModuleApi();
265+
const app = {} as unknown as IApp;
266+
const apps: IApp[] = [app];
267+
268+
jest.spyOn(WidgetStore.instance, "getApps").mockReturnValue(apps);
269+
expect(api.getApps("!room:example.com")).toEqual(apps);
270+
});
271+
});
272+
273+
describe("getAppAvatarUrl", () => {
274+
const app = {} as unknown as IApp;
275+
const avatarUrl = "https://example.com/avatar.png";
276+
277+
let api: ProxiedModuleApi;
278+
let client: Mocked<MatrixClient>;
279+
280+
beforeEach(() => {
281+
api = new ProxiedModuleApi();
282+
client = getMockClientWithEventEmitter({ mxcUrlToHttp: jest.fn().mockReturnValue(avatarUrl) });
283+
});
284+
285+
it("should return null if the app has no avatar URL", () => {
286+
expect(api.getAppAvatarUrl(app)).toBeNull();
287+
});
288+
289+
it("should return the app avatar URL", () => {
290+
expect(api.getAppAvatarUrl({ ...app, avatar_url: avatarUrl })).toBe(avatarUrl);
291+
});
292+
293+
it("should support optional thumbnail params", () => {
294+
api.getAppAvatarUrl({ ...app, avatar_url: avatarUrl }, 1, 2, "3");
295+
// eslint-disable-next-line no-restricted-properties
296+
expect(client.mxcUrlToHttp).toHaveBeenCalledWith(avatarUrl, 1, 2, "3");
297+
});
298+
});
299+
300+
describe("isAppInContainer", () => {
301+
const app = {} as unknown as IApp;
302+
const roomId = "!room:example.com";
303+
304+
let api: ProxiedModuleApi;
305+
let client: MatrixClient;
306+
307+
beforeEach(() => {
308+
api = new ProxiedModuleApi();
309+
client = stubClient();
310+
311+
jest.spyOn(WidgetLayoutStore.instance, "isInContainer");
312+
});
313+
314+
it("should return false if there is no room", () => {
315+
client.getRoom = jest.fn().mockReturnValue(null);
316+
317+
expect(api.isAppInContainer(app, Container.Top, roomId)).toBe(false);
318+
expect(WidgetLayoutStore.instance.isInContainer).not.toHaveBeenCalled();
319+
});
320+
321+
it("should return false if the app is not in the container", () => {
322+
jest.spyOn(WidgetLayoutStore.instance, "isInContainer").mockReturnValue(false);
323+
expect(api.isAppInContainer(app, Container.Top, roomId)).toBe(false);
324+
});
325+
326+
it("should return true if the app is in the container", () => {
327+
jest.spyOn(WidgetLayoutStore.instance, "isInContainer").mockReturnValue(true);
328+
expect(api.isAppInContainer(app, Container.Top, roomId)).toBe(true);
329+
});
330+
});
331+
332+
describe("moveAppToContainer", () => {
333+
const app = {} as unknown as IApp;
334+
const roomId = "!room:example.com";
335+
336+
let api: ProxiedModuleApi;
337+
let client: MatrixClient;
338+
339+
beforeEach(() => {
340+
api = new ProxiedModuleApi();
341+
client = stubClient();
342+
343+
jest.spyOn(WidgetLayoutStore.instance, "moveToContainer");
344+
});
345+
346+
it("should not move if there is no room", () => {
347+
client.getRoom = jest.fn().mockReturnValue(null);
348+
api.moveAppToContainer(app, Container.Top, roomId);
349+
expect(WidgetLayoutStore.instance.moveToContainer).not.toHaveBeenCalled();
350+
});
351+
352+
it("should move if there is a room", () => {
353+
const room = mkRoom(client, roomId);
354+
client.getRoom = jest.fn().mockReturnValue(room);
355+
356+
api.moveAppToContainer(app, Container.Top, roomId);
357+
expect(WidgetLayoutStore.instance.moveToContainer).toHaveBeenCalledWith(room, app, Container.Top);
358+
});
359+
});
257360
});

test/stores/AutoRageshakeStore-test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ import AutoRageshakeStore from "../../src/stores/AutoRageshakeStore";
2929
import { mkEvent, stubClient } from "../test-utils";
3030

3131
jest.mock("../../src/rageshake/submit-rageshake");
32+
jest.mock("../../src/stores/WidgetStore");
33+
jest.mock("../../src/stores/widgets/WidgetLayoutStore");
3234

3335
describe("AutoRageshakeStore", () => {
3436
const roomId = "!room:example.com";

test/stores/RoomViewStore-test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ jest.mock("../../src/utils/DMRoomMap", () => {
8484
};
8585
});
8686

87+
jest.mock("../../src/stores/WidgetStore");
88+
jest.mock("../../src/stores/widgets/WidgetLayoutStore");
89+
8790
describe("RoomViewStore", function () {
8891
const userId = "@alice:server";
8992
const roomId = "!randomcharacters:aser.ver";

test/utils/SearchInput-test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import { parsePermalink } from "../../src/utils/permalinks/Permalinks";
1919
import { transformSearchTerm } from "../../src/utils/SearchInput";
2020

2121
jest.mock("../../src/utils/permalinks/Permalinks");
22+
jest.mock("../../src/stores/WidgetStore");
23+
jest.mock("../../src/stores/widgets/WidgetLayoutStore");
2224

2325
describe("transforming search term", () => {
2426
it("should return the primaryEntityId if the search term was a permalink", () => {

test/voice-broadcast/components/VoiceBroadcastBody-test.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ jest.mock("../../../src/voice-broadcast/components/molecules/VoiceBroadcastPlayb
4444

4545
jest.mock("../../../src/utils/permalinks/Permalinks");
4646
jest.mock("../../../src/utils/MediaEventHelper");
47+
jest.mock("../../../src/stores/WidgetStore");
48+
jest.mock("../../../src/stores/widgets/WidgetLayoutStore");
4749

4850
describe("VoiceBroadcastBody", () => {
4951
const roomId = "!room:example.com";

yarn.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1847,10 +1847,10 @@
18471847
resolved "https://registry.yarnpkg.com/@matrix-org/olm/-/olm-3.2.15.tgz#55f3c1b70a21bbee3f9195cecd6846b1083451ec"
18481848
integrity sha512-S7lOrndAK9/8qOtaTq/WhttJC/o4GAzdfK0MUPpo8ApzsJEC0QjtwrkC3KBXdFP1cD1MXi/mlKR7aaoVMKgs6Q==
18491849

1850-
"@matrix-org/react-sdk-module-api@^2.2.1":
1851-
version "2.2.1"
1852-
resolved "https://registry.yarnpkg.com/@matrix-org/react-sdk-module-api/-/react-sdk-module-api-2.2.1.tgz#308bcb42a780200d3e7994235376784b51819379"
1853-
integrity sha512-+MXTMEapzGmhArUt86GYDQirOvm19+wvQLDApmHpUQvSZvYm7wOo1EwR9FFvSKve53fu+v6gI1grnj7YLzGQ9Q==
1850+
"@matrix-org/react-sdk-module-api@^2.3.0":
1851+
version "2.3.0"
1852+
resolved "https://registry.yarnpkg.com/@matrix-org/react-sdk-module-api/-/react-sdk-module-api-2.3.0.tgz#85be5cfc73be0494c13d4dc9050cb70c58d7a08b"
1853+
integrity sha512-x/ie44yaXNtE5AKcmQiW5yINVEIJ7IjjEc35vj6j52fM8tZ9XbJx9PANKSWsdd0NJp3OqyaeHftmN6ESfx4YoQ==
18541854
dependencies:
18551855
"@babel/runtime" "^7.17.9"
18561856

0 commit comments

Comments
 (0)