mirror of
https://github.com/cinnyapp/cinny.git
synced 2025-11-06 23:30:28 +03:00
Update transport refs to allow us to properly bind listeners for media state and hangup
This commit is contained in:
parent
1e8a69ff23
commit
e76664083d
1 changed files with 78 additions and 58 deletions
|
|
@ -8,23 +8,28 @@ import React, {
|
||||||
useEffect,
|
useEffect,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import { logger } from 'matrix-js-sdk/lib/logger';
|
import { logger } from 'matrix-js-sdk/lib/logger';
|
||||||
import { WidgetApiToWidgetAction, ITransport, WidgetApiAction } from 'matrix-widget-api';
|
import { WidgetApiToWidgetAction, WidgetApiAction, ClientWidgetApi } from 'matrix-widget-api';
|
||||||
|
|
||||||
interface MediaStatePayload {
|
interface MediaStatePayload {
|
||||||
audio_enabled?: boolean;
|
data?: {
|
||||||
video_enabled?: boolean;
|
audio_enabled?: boolean;
|
||||||
|
video_enabled?: boolean;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const WIDGET_MEDIA_STATE_UPDATE_ACTION = 'io.element.device_mute';
|
const WIDGET_MEDIA_STATE_UPDATE_ACTION = 'io.element.device_mute';
|
||||||
const WIDGET_HANGUP_ACTION = 'io.element.hangup';
|
const WIDGET_HANGUP_ACTION = 'im.vector.hangup';
|
||||||
const SET_MEDIA_STATE_ACTION = 'io.element.device_mute';
|
const SET_MEDIA_STATE_ACTION = 'io.element.device_mute';
|
||||||
|
|
||||||
interface CallContextState {
|
interface CallContextState {
|
||||||
activeCallRoomId: string | null;
|
activeCallRoomId: string | null;
|
||||||
setActiveCallRoomId: (roomId: string | null) => void;
|
setActiveCallRoomId: (roomId: string | null) => void;
|
||||||
hangUp: () => void;
|
hangUp: () => void;
|
||||||
activeApiTransport: ITransport | null;
|
activeClientWidgetApi: ClientWidgetApi | null;
|
||||||
registerActiveTransport: (roomId: string | null, transport: ITransport | null) => void;
|
registerActiveClientWidgetApi: (
|
||||||
|
roomId: string | null,
|
||||||
|
clientWidgetApi: ClientWidgetApi | null
|
||||||
|
) => void;
|
||||||
sendWidgetAction: <T = unknown>(
|
sendWidgetAction: <T = unknown>(
|
||||||
action: WidgetApiToWidgetAction | string,
|
action: WidgetApiToWidgetAction | string,
|
||||||
data: T
|
data: T
|
||||||
|
|
@ -49,8 +54,10 @@ const DEFAULT_CHAT_OPENED = false;
|
||||||
|
|
||||||
export function CallProvider({ children }: CallProviderProps) {
|
export function CallProvider({ children }: CallProviderProps) {
|
||||||
const [activeCallRoomId, setActiveCallRoomIdState] = useState<string | null>(null);
|
const [activeCallRoomId, setActiveCallRoomIdState] = useState<string | null>(null);
|
||||||
const [activeApiTransport, setActiveApiTransportState] = useState<ITransport | null>(null);
|
const [activeClientWidgetApi, setActiveClientWidgetApiState] = useState<ClientWidgetApi | null>(
|
||||||
const [transportRoomId, setTransportRoomId] = useState<string | null>(null);
|
null
|
||||||
|
);
|
||||||
|
const [clientWidgetApiRoomId, setClientWidgetApiRoomId] = useState<string | null>(null);
|
||||||
|
|
||||||
const [isAudioEnabled, setIsAudioEnabledState] = useState<boolean>(DEFAULT_AUDIO_ENABLED);
|
const [isAudioEnabled, setIsAudioEnabledState] = useState<boolean>(DEFAULT_AUDIO_ENABLED);
|
||||||
const [isVideoEnabled, setIsVideoEnabledState] = useState<boolean>(DEFAULT_VIDEO_ENABLED);
|
const [isVideoEnabled, setIsVideoEnabledState] = useState<boolean>(DEFAULT_VIDEO_ENABLED);
|
||||||
|
|
@ -74,61 +81,70 @@ export function CallProvider({ children }: CallProviderProps) {
|
||||||
resetMediaState();
|
resetMediaState();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (roomId === null || roomId !== transportRoomId) {
|
if (roomId === null || roomId !== clientWidgetApiRoomId) {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
`CallContext: Clearing active transport because active room changed to ${roomId} or was cleared.`
|
`CallContext: Clearing active clientWidgetApi because active room changed to ${roomId} or was cleared.`
|
||||||
);
|
);
|
||||||
setActiveApiTransportState(null);
|
setActiveClientWidgetApiState(null);
|
||||||
setTransportRoomId(null);
|
setClientWidgetApiRoomId(null);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[transportRoomId, resetMediaState, activeCallRoomId]
|
[clientWidgetApiRoomId, resetMediaState, activeCallRoomId]
|
||||||
);
|
);
|
||||||
|
|
||||||
const hangUp = useCallback(() => {
|
const hangUp = useCallback(() => {
|
||||||
logger.debug(`CallContext: Hang up called.`);
|
logger.debug(`CallContext: Hang up called.`);
|
||||||
|
activeClientWidgetApi?.transport.send(`action:${WIDGET_HANGUP_ACTION}`, {});
|
||||||
setActiveCallRoomIdState(null);
|
setActiveCallRoomIdState(null);
|
||||||
logger.debug(`CallContext: Clearing active transport due to hangup.`);
|
logger.debug(`CallContext: Clearing active clientWidgetApi due to hangup.`);
|
||||||
setActiveApiTransportState(null);
|
setActiveClientWidgetApiState(null);
|
||||||
setTransportRoomId(null);
|
setClientWidgetApiRoomId(null);
|
||||||
resetMediaState();
|
resetMediaState();
|
||||||
}, [resetMediaState]);
|
}, [resetMediaState]);
|
||||||
|
|
||||||
const setActiveTransport = useCallback((transport: ITransport | null, roomId: string | null) => {
|
const setActiveClientWidgetApi = useCallback(
|
||||||
setActiveApiTransportState(transport);
|
(clientWidgetApi: ClientWidgetApi | null, roomId: string | null) => {
|
||||||
setTransportRoomId(roomId);
|
setActiveClientWidgetApiState(clientWidgetApi);
|
||||||
}, []);
|
setClientWidgetApiRoomId(roomId);
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
const registerActiveTransport = useCallback(
|
const registerActiveClientWidgetApi = useCallback(
|
||||||
(roomId: string | null, transport: ITransport | null) => {
|
(roomId: string | null, clientWidgetApi: ClientWidgetApi | null) => {
|
||||||
if (activeApiTransport && activeApiTransport !== transport) {
|
if (activeClientWidgetApi && activeClientWidgetApi !== clientWidgetApi) {
|
||||||
logger.debug(`CallContext: Cleaning up listeners for previous transport instance.`);
|
logger.debug(`CallContext: Cleaning up listeners for previous clientWidgetApi instance.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (roomId && transport) {
|
if (roomId && clientWidgetApi) {
|
||||||
logger.debug(`CallContext: Registering active transport for room ${roomId}.`);
|
logger.debug(`CallContext: Registering active clientWidgetApi for room ${roomId}.`);
|
||||||
setActiveTransport(transport, roomId);
|
setActiveClientWidgetApi(clientWidgetApi, roomId);
|
||||||
} else if (roomId === transportRoomId || roomId === null) {
|
} else if (roomId === clientWidgetApiRoomId || roomId === null) {
|
||||||
logger.debug(`CallContext: Clearing active transport for room ${transportRoomId}.`);
|
logger.debug(
|
||||||
setActiveTransport(null, null);
|
`CallContext: Clearing active clientWidgetApi for room ${clientWidgetApiRoomId}.`
|
||||||
|
);
|
||||||
|
setActiveClientWidgetApi(null, null);
|
||||||
resetMediaState();
|
resetMediaState();
|
||||||
} else {
|
} else {
|
||||||
logger.debug(
|
logger.debug(
|
||||||
`CallContext: Ignoring transport registration/clear request for room ${roomId}, as current transport belongs to ${transportRoomId}.`
|
`CallContext: Ignoring clientWidgetApi registration/clear request for room ${roomId}, as current clientWidgetApi belongs to ${clientWidgetApiRoomId}.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[activeApiTransport, transportRoomId, setActiveTransport, resetMediaState]
|
[activeClientWidgetApi, clientWidgetApiRoomId, setActiveClientWidgetApi, resetMediaState]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!activeApiTransport || !activeCallRoomId || transportRoomId !== activeCallRoomId) {
|
if (!activeClientWidgetApi || !activeCallRoomId || clientWidgetApiRoomId !== activeCallRoomId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const transport = activeApiTransport;
|
const clientWidgetApi = activeClientWidgetApi;
|
||||||
|
|
||||||
const handleHangup = (ev: CustomEvent) => {
|
const handleHangup = (ev: CustomEvent) => {
|
||||||
|
ev.preventDefault();
|
||||||
|
|
||||||
|
clientWidgetApi.transport.reply(ev.detail, {});
|
||||||
logger.warn(
|
logger.warn(
|
||||||
`CallContext: Received hangup action from widget in room ${activeCallRoomId}.`,
|
`CallContext: Received hangup action from widget in room ${activeCallRoomId}.`,
|
||||||
ev
|
ev
|
||||||
|
|
@ -142,7 +158,7 @@ export function CallProvider({ children }: CallProviderProps) {
|
||||||
`CallContext: Received media state update from widget in room ${activeCallRoomId}:`,
|
`CallContext: Received media state update from widget in room ${activeCallRoomId}:`,
|
||||||
ev.detail
|
ev.detail
|
||||||
);
|
);
|
||||||
const { audio_enabled, video_enabled } = ev.detail;
|
const { audio_enabled, video_enabled } = ev.detail.data;
|
||||||
if (typeof audio_enabled === 'boolean' && audio_enabled !== isAudioEnabled) {
|
if (typeof audio_enabled === 'boolean' && audio_enabled !== isAudioEnabled) {
|
||||||
logger.debug(`CallContext: Updating audio enabled state from widget: ${audio_enabled}`);
|
logger.debug(`CallContext: Updating audio enabled state from widget: ${audio_enabled}`);
|
||||||
setIsAudioEnabledState(audio_enabled);
|
setIsAudioEnabledState(audio_enabled);
|
||||||
|
|
@ -153,21 +169,25 @@ export function CallProvider({ children }: CallProviderProps) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
logger.debug(`CallContext: Setting up listeners for transport in room ${activeCallRoomId}`);
|
logger.debug(
|
||||||
transport.on(`action:${WIDGET_HANGUP_ACTION}`, handleHangup); // Use standard hangup action name
|
`CallContext: Setting up listeners for clientWidgetApi in room ${activeCallRoomId}`
|
||||||
transport.on(`action:${WIDGET_MEDIA_STATE_UPDATE_ACTION}`, handleMediaStateUpdate);
|
);
|
||||||
|
clientWidgetApi.on(`action:${WIDGET_HANGUP_ACTION}`, handleHangup); // Use standard hangup action name
|
||||||
|
clientWidgetApi.on(`action:${WIDGET_MEDIA_STATE_UPDATE_ACTION}`, handleMediaStateUpdate);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
logger.debug(`CallContext: Cleaning up listeners for transport in room ${activeCallRoomId}`);
|
logger.debug(
|
||||||
if (transport) {
|
`CallContext: Cleaning up listeners for clientWidgetApi in room ${activeCallRoomId}`
|
||||||
transport.off(`action:${WIDGET_HANGUP_ACTION}`, handleHangup);
|
);
|
||||||
transport.off(`action:${WIDGET_MEDIA_STATE_UPDATE_ACTION}`, handleMediaStateUpdate);
|
if (clientWidgetApi) {
|
||||||
|
clientWidgetApi.off(`action:${WIDGET_HANGUP_ACTION}`, handleHangup);
|
||||||
|
clientWidgetApi.off(`action:${WIDGET_MEDIA_STATE_UPDATE_ACTION}`, handleMediaStateUpdate);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [
|
}, [
|
||||||
activeApiTransport,
|
activeClientWidgetApi,
|
||||||
activeCallRoomId,
|
activeCallRoomId,
|
||||||
transportRoomId,
|
clientWidgetApiRoomId,
|
||||||
hangUp,
|
hangUp,
|
||||||
isChatOpen,
|
isChatOpen,
|
||||||
isAudioEnabled,
|
isAudioEnabled,
|
||||||
|
|
@ -176,30 +196,30 @@ export function CallProvider({ children }: CallProviderProps) {
|
||||||
|
|
||||||
const sendWidgetAction = useCallback(
|
const sendWidgetAction = useCallback(
|
||||||
async <T = unknown,>(action: WidgetApiToWidgetAction | string, data: T): Promise<void> => {
|
async <T = unknown,>(action: WidgetApiToWidgetAction | string, data: T): Promise<void> => {
|
||||||
if (!activeApiTransport) {
|
if (!activeClientWidgetApi) {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
`CallContext: Cannot send action '${action}', no active API transport registered.`
|
`CallContext: Cannot send action '${action}', no active API clientWidgetApi registered.`
|
||||||
);
|
);
|
||||||
return Promise.reject(new Error('No active call transport'));
|
return Promise.reject(new Error('No active call clientWidgetApi'));
|
||||||
}
|
}
|
||||||
if (!transportRoomId || transportRoomId !== activeCallRoomId) {
|
if (!clientWidgetApiRoomId || clientWidgetApiRoomId !== activeCallRoomId) {
|
||||||
logger.warn(
|
logger.debug(
|
||||||
`CallContext: Cannot send action '${action}', transport room (${transportRoomId}) does not match active call room (${activeCallRoomId}). Stale transport?`
|
`CallContext: Cannot send action '${action}', clientWidgetApi room (${clientWidgetApiRoomId}) does not match active call room (${activeCallRoomId}). Stale clientWidgetApi?`
|
||||||
);
|
);
|
||||||
return Promise.reject(new Error('Mismatched active call transport'));
|
return Promise.reject(new Error('Mismatched active call clientWidgetApi'));
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
logger.debug(
|
logger.debug(
|
||||||
`CallContext: Sending action '${action}' via active transport (room: ${transportRoomId}) with data:`,
|
`CallContext: Sending action '${action}' via active clientWidgetApi (room: ${clientWidgetApiRoomId}) with data:`,
|
||||||
data
|
data
|
||||||
);
|
);
|
||||||
await activeApiTransport.send<T>(action as WidgetApiAction, data);
|
await activeClientWidgetApi.transport.send(action as WidgetApiAction, data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(`CallContext: Error sending action '${action}':`, error);
|
logger.error(`CallContext: Error sending action '${action}':`, error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[activeApiTransport, activeCallRoomId, transportRoomId]
|
[activeClientWidgetApi, activeCallRoomId, clientWidgetApiRoomId]
|
||||||
);
|
);
|
||||||
|
|
||||||
const toggleAudio = useCallback(async () => {
|
const toggleAudio = useCallback(async () => {
|
||||||
|
|
@ -246,8 +266,8 @@ export function CallProvider({ children }: CallProviderProps) {
|
||||||
activeCallRoomId,
|
activeCallRoomId,
|
||||||
setActiveCallRoomId,
|
setActiveCallRoomId,
|
||||||
hangUp,
|
hangUp,
|
||||||
activeApiTransport,
|
activeClientWidgetApi,
|
||||||
registerActiveTransport,
|
registerActiveClientWidgetApi,
|
||||||
sendWidgetAction,
|
sendWidgetAction,
|
||||||
isChatOpen,
|
isChatOpen,
|
||||||
isAudioEnabled,
|
isAudioEnabled,
|
||||||
|
|
@ -260,8 +280,8 @@ export function CallProvider({ children }: CallProviderProps) {
|
||||||
activeCallRoomId,
|
activeCallRoomId,
|
||||||
setActiveCallRoomId,
|
setActiveCallRoomId,
|
||||||
hangUp,
|
hangUp,
|
||||||
activeApiTransport,
|
activeClientWidgetApi,
|
||||||
registerActiveTransport,
|
registerActiveClientWidgetApi,
|
||||||
sendWidgetAction,
|
sendWidgetAction,
|
||||||
isChatOpen,
|
isChatOpen,
|
||||||
isAudioEnabled,
|
isAudioEnabled,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue