diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts index a8f132c84b..289bda3f49 100644 --- a/src/@types/global.d.ts +++ b/src/@types/global.d.ts @@ -68,7 +68,8 @@ type ElectronChannel = | "openDesktopCapturerSourcePicker" | "userAccessToken" | "homeserverUrl" - | "serverSupportedVersions"; + | "serverSupportedVersions" + | "showToast"; declare global { // use `number` as the return type in all cases for globalThis.set{Interval,Timeout}, diff --git a/src/vector/platform/ElectronPlatform.tsx b/src/vector/platform/ElectronPlatform.tsx index bef544d15d..579096d5c0 100644 --- a/src/vector/platform/ElectronPlatform.tsx +++ b/src/vector/platform/ElectronPlatform.tsx @@ -18,6 +18,7 @@ import { } from "matrix-js-sdk/src/matrix"; import React from "react"; import { logger } from "matrix-js-sdk/src/logger"; +import { uniqueId } from "lodash"; import BasePlatform, { UpdateCheckStatus, type UpdateStatus } from "../../BasePlatform"; import type BaseEventIndexManager from "../../indexing/BaseEventIndexManager"; @@ -43,6 +44,7 @@ import { SeshatIndexManager } from "./SeshatIndexManager"; import { IPCManager } from "./IPCManager"; import { _t } from "../../languageHandler"; import { BadgeOverlayRenderer } from "../../favicon"; +import GenericToast from "../../components/views/toasts/GenericToast.tsx"; interface SquirrelUpdate { releaseNotes: string; @@ -182,6 +184,25 @@ export default class ElectronPlatform extends BasePlatform { await this.ipc.call("callDisplayMediaCallback", source ?? { id: "", name: "", thumbnailURL: "" }); }); + this.electron.on("showToast", (ev, { title, description, priority = 40 }) => { + const key = uniqueId("electron_showToast_"); + const onPrimaryClick = (): void => { + ToastStore.sharedInstance().dismissToast(key); + }; + + ToastStore.sharedInstance().addOrReplaceToast({ + key, + title, + props: { + description, + primaryLabel: _t("action|dismiss"), + onPrimaryClick, + }, + component: GenericToast, + priority, + }); + }); + BreadcrumbsStore.instance.on(UPDATE_EVENT, this.onBreadcrumbsUpdate); this.initialised = this.initialise(); diff --git a/test/unit-tests/vector/platform/ElectronPlatform-test.ts b/test/unit-tests/vector/platform/ElectronPlatform-test.ts index 7b1669a04e..ec1c18bb46 100644 --- a/test/unit-tests/vector/platform/ElectronPlatform-test.ts +++ b/test/unit-tests/vector/platform/ElectronPlatform-test.ts @@ -21,6 +21,7 @@ import DesktopCapturerSourcePicker from "../../../../src/components/views/elemen import ElectronPlatform from "../../../../src/vector/platform/ElectronPlatform"; import { setupLanguageMock } from "../../../setup/setupLanguage"; import { stubClient } from "../../../test-utils"; +import ToastStore from "../../../../src/stores/ToastStore.ts"; jest.mock("../../../../src/rageshake/rageshake", () => ({ flush: jest.fn(), @@ -127,6 +128,19 @@ describe("ElectronPlatform", () => { expect(plat.ipc.call).toHaveBeenCalledWith("callDisplayMediaCallback", "source"); }); + it("should show a toast when showToast is fired", async () => { + new ElectronPlatform(); + const spy = jest.spyOn(ToastStore.sharedInstance(), "addOrReplaceToast"); + + const [event, handler] = getElectronEventHandlerCall("showToast")!; + handler({} as any, { title: "title", description: "description" }); + + expect(event).toBeTruthy(); + expect(spy).toHaveBeenCalledWith( + expect.objectContaining({ title: "title", props: expect.objectContaining({ description: "description" }) }), + ); + }); + describe("updates", () => { it("dispatches on check updates action", () => { new ElectronPlatform();