From 2de0b661c8c3489431b401778ea979b9a068bd53 Mon Sep 17 00:00:00 2001 From: Lotus Bot Date: Fri, 22 May 2026 21:51:17 -0400 Subject: [PATCH] fix: override cancelScheduledDelayedEvent/restart/send in CallWidgetDriver The base WidgetDriver throws Failed to override function for these methods. ClientWidgetApi routes update_delayed_event widget actions to cancelScheduledDelayedEvent, restartScheduledDelayedEvent, or sendScheduledDelayedEvent. Without these overrides every delayed-event refresh from element-call fails, causing MembershipManager to drop the call after retries. Also make listenAction auto-call preventDefault so io.element.join and other custom widget actions return success. Add set_always_on_screen handler so element-call PiP requests are acknowledged. --- src/app/plugins/call/CallEmbed.ts | 11 ++++++++++- src/app/plugins/call/CallWidgetDriver.ts | 12 ++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/app/plugins/call/CallEmbed.ts b/src/app/plugins/call/CallEmbed.ts index 81671c068..6c44d7c58 100644 --- a/src/app/plugins/call/CallEmbed.ts +++ b/src/app/plugins/call/CallEmbed.ts @@ -12,6 +12,7 @@ import { IRoomEvent, IWidget, Widget, + WidgetApiFromWidgetAction, WidgetApiToWidgetAction, WidgetDriver, } from 'matrix-widget-api'; @@ -248,6 +249,10 @@ export class CallEmbed { this.disposables.push( this.listenAction(ElementWidgetActions.JoinCall, this.onCallJoined.bind(this)), ); + // Acknowledge set_always_on_screen; we manage PiP ourselves so just return success + this.disposables.push( + this.listenAction(WidgetApiFromWidgetAction.UpdateAlwaysOnScreen, () => {}), + ); // Populate the map of "read up to" events for this widget with the current event in every room. // This is a bit inefficient, but should be okay. We do this for all rooms in case the widget @@ -460,7 +465,11 @@ export class CallEmbed { } public listenAction(type: string, callback: (event: CustomEvent) => void) { - return this.listenEvent(`action:${type}`, callback); + const wrapped = (ev: CustomEvent) => { + ev.preventDefault(); + callback(ev); + }; + return this.listenEvent(`action:${type}`, wrapped); } public listenEvent(type: string, callback: (event: T) => void) { diff --git a/src/app/plugins/call/CallWidgetDriver.ts b/src/app/plugins/call/CallWidgetDriver.ts index fca80de81..a3ff2ef87 100644 --- a/src/app/plugins/call/CallWidgetDriver.ts +++ b/src/app/plugins/call/CallWidgetDriver.ts @@ -148,6 +148,18 @@ export class CallWidgetDriver extends WidgetDriver { await client._unstable_updateDelayedEvent(delayId, action); } + public async cancelScheduledDelayedEvent(delayId: string): Promise { + await this.mx._unstable_cancelScheduledDelayedEvent(delayId); + } + + public async restartScheduledDelayedEvent(delayId: string): Promise { + await this.mx._unstable_restartScheduledDelayedEvent(delayId); + } + + public async sendScheduledDelayedEvent(delayId: string): Promise { + await this.mx._unstable_sendScheduledDelayedEvent(delayId); + } + public async sendToDevice( eventType: string, encrypted: boolean,