frontend: Improve webcomponent event and command types
This commit is contained in:
parent
e75b21fa49
commit
326ee174c6
@ -25,7 +25,8 @@ import {
|
||||
RoomService,
|
||||
SessionStorageService
|
||||
} from '../../services';
|
||||
import { OpenViduMeetMessage, WebComponentEventType } from 'webcomponent/src/types/message.type';
|
||||
import { OutboundEventMessage } from 'webcomponent/src/models/message.type';
|
||||
import { WebComponentEvent } from 'webcomponent/src/models/event.model';
|
||||
|
||||
@Component({
|
||||
selector: 'app-video-room',
|
||||
@ -114,11 +115,11 @@ export class VideoRoomComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
onParticipantConnected(event: ParticipantModel) {
|
||||
const message: OpenViduMeetMessage = {
|
||||
eventType: WebComponentEventType.LOCAL_PARTICIPANT_CONNECTED,
|
||||
const message: OutboundEventMessage = {
|
||||
event: WebComponentEvent.JOIN,
|
||||
payload: {
|
||||
roomId: event.getProperties().room?.name,
|
||||
participantName: event.name
|
||||
roomId: event.getProperties().room?.name || '',
|
||||
participantName: event.name!
|
||||
}
|
||||
};
|
||||
this.wcManagerService.sendMessageToParent(message);
|
||||
@ -129,8 +130,8 @@ export class VideoRoomComponent implements OnInit, OnDestroy {
|
||||
const redirectURL = this.ctxService.getLeaveRedirectURL() || '/disconnected';
|
||||
const isExternalURL = /^https?:\/\//.test(redirectURL);
|
||||
|
||||
const message: OpenViduMeetMessage = {
|
||||
eventType: WebComponentEventType.LOCAL_PARTICIPANT_LEFT,
|
||||
const message: OutboundEventMessage = {
|
||||
event: WebComponentEvent.LEFT,
|
||||
payload: {
|
||||
roomId: event.roomName,
|
||||
participantName: event.participantName
|
||||
|
||||
@ -8,12 +8,8 @@ import {
|
||||
OpenViduService,
|
||||
LoggerService
|
||||
} from 'projects/shared-meet-components/src/public-api';
|
||||
import {
|
||||
OpenViduMeetMessage,
|
||||
ParentMessage,
|
||||
WebComponentActionType,
|
||||
WebComponentEventType
|
||||
} from 'webcomponent/src/types/message.type';
|
||||
import { WebComponentCommand } from 'webcomponent/src/models/command.model';
|
||||
import { OutboundEventMessage, InboundCommandMessage } from 'webcomponent/src/models/message.type';
|
||||
|
||||
/**
|
||||
* Service to manage the commands from OpenVidu Meet WebComponent/Iframe.
|
||||
@ -43,12 +39,12 @@ export class WebComponentManagerService {
|
||||
this.isListenerStarted = true;
|
||||
// Listen for messages from the iframe
|
||||
window.addEventListener('message', async (event) => {
|
||||
const message: ParentMessage = event.data;
|
||||
const message: InboundCommandMessage = event.data;
|
||||
const parentDomain = this.contextService.getParentDomain();
|
||||
const { action, payload } = message;
|
||||
const { command, payload } = message;
|
||||
|
||||
if (!parentDomain) {
|
||||
if (action === WebComponentActionType.INITIALIZE) {
|
||||
if (command === WebComponentCommand.INITIALIZE) {
|
||||
if (!payload || !('domain' in payload)) {
|
||||
console.error('Parent domain not provided in message payload');
|
||||
return;
|
||||
@ -66,19 +62,19 @@ export class WebComponentManagerService {
|
||||
|
||||
console.debug('Message received from parent:', event.data);
|
||||
// TODO: reject if room is not connected
|
||||
switch (action) {
|
||||
case WebComponentActionType.END_MEETING:
|
||||
switch (command) {
|
||||
case WebComponentCommand.END_MEETING:
|
||||
// Moderator only
|
||||
if (this.contextService.isModeratorParticipant()) {
|
||||
const roomId = this.contextService.getRoomId();
|
||||
await this.httpService.endMeeting(roomId);
|
||||
}
|
||||
break;
|
||||
case WebComponentActionType.TOGGLE_CHAT:
|
||||
// Toggle chat
|
||||
this.panelService.togglePanel(PanelType.CHAT);
|
||||
break;
|
||||
case WebComponentActionType.LEAVE_ROOM:
|
||||
// case WebComponentCommand.TOGGLE_CHAT:
|
||||
// Toggle chat
|
||||
// this.panelService.togglePanel(PanelType.CHAT);
|
||||
// break;
|
||||
case WebComponentCommand.LEAVE_ROOM:
|
||||
// Leave room.
|
||||
await this.openviduService.disconnectRoom();
|
||||
break;
|
||||
@ -94,7 +90,7 @@ export class WebComponentManagerService {
|
||||
window.removeEventListener('message', this.startCommandsListener);
|
||||
}
|
||||
|
||||
sendMessageToParent(event: OpenViduMeetMessage /*| RoomDisconnectedEvent*/) {
|
||||
sendMessageToParent(event: OutboundEventMessage) {
|
||||
if (!this.contextService.isEmbeddedMode()) return;
|
||||
this.log.d('Sending message to parent :', event);
|
||||
const origin = this.contextService.getParentDomain();
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { ParentMessage } from '../types/message.type';
|
||||
import { InboundCommandMessage } from '../models/message.type';
|
||||
|
||||
/**
|
||||
* Handles sending messages to the iframe.
|
||||
@ -12,7 +12,7 @@ export class CommandsManager {
|
||||
this.allowedOrigin = allowedOrigin;
|
||||
}
|
||||
|
||||
public sendMessage(message: ParentMessage, targetOrigin?: string): void {
|
||||
public sendMessage(message: InboundCommandMessage, targetOrigin?: string): void {
|
||||
targetOrigin = targetOrigin || this.allowedOrigin;
|
||||
this.iframe.contentWindow?.postMessage(message, targetOrigin);
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { OpenViduMeetMessage } from '../types/message.type';
|
||||
import { OutboundEventMessage } from '../models/message.type';
|
||||
|
||||
export class EventsManager {
|
||||
private element: HTMLElement;
|
||||
@ -12,9 +12,9 @@ export class EventsManager {
|
||||
}
|
||||
|
||||
private handleMessage(event: MessageEvent) {
|
||||
const message: OpenViduMeetMessage = event.data;
|
||||
const message: OutboundEventMessage = event.data;
|
||||
// Validate message origin (security measure)
|
||||
if (!message || !message.eventType) {
|
||||
if (!message || !message.event) {
|
||||
// console.warn('Invalid message:', message);
|
||||
return;
|
||||
}
|
||||
@ -22,8 +22,8 @@ export class EventsManager {
|
||||
this.dispatchEvent(message);
|
||||
}
|
||||
|
||||
private dispatchEvent(message: OpenViduMeetMessage) {
|
||||
const event = new CustomEvent(message.eventType, {
|
||||
private dispatchEvent(message: OutboundEventMessage) {
|
||||
const event = new CustomEvent(message.event, {
|
||||
detail: message.payload,
|
||||
bubbles: true,
|
||||
composed: true
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { ParentMessage, WebComponentActionType } from '../types/message.type';
|
||||
import { WebComponentCommand } from '../models/command.model';
|
||||
import { InboundCommandMessage } from '../models/message.type';
|
||||
import { CommandsManager } from './CommandsManager';
|
||||
import { EventsManager } from './EventsManager';
|
||||
|
||||
@ -68,8 +69,8 @@ export class OpenViduMeet extends HTMLElement {
|
||||
this.shadowRoot?.appendChild(style);
|
||||
this.shadowRoot?.appendChild(this.iframe);
|
||||
this.iframe.onload = () => {
|
||||
const message: ParentMessage = {
|
||||
action: WebComponentActionType.INITIALIZE,
|
||||
const message: InboundCommandMessage = {
|
||||
command: WebComponentCommand.INITIALIZE,
|
||||
payload: { domain: window.location.origin }
|
||||
};
|
||||
this.commandsManager.sendMessage(message);
|
||||
@ -101,17 +102,17 @@ export class OpenViduMeet extends HTMLElement {
|
||||
// Public methods
|
||||
|
||||
public endMeeting() {
|
||||
const message: ParentMessage = { action: WebComponentActionType.END_MEETING };
|
||||
const message: InboundCommandMessage = { command: WebComponentCommand.END_MEETING };
|
||||
this.commandsManager.sendMessage(message);
|
||||
}
|
||||
|
||||
public leaveRoom() {
|
||||
const message: ParentMessage = { action: WebComponentActionType.LEAVE_ROOM };
|
||||
const message: InboundCommandMessage = { command: WebComponentCommand.LEAVE_ROOM };
|
||||
this.commandsManager.sendMessage(message);
|
||||
}
|
||||
|
||||
public toggleChat() {
|
||||
const message: ParentMessage = { action: WebComponentActionType.TOGGLE_CHAT };
|
||||
this.commandsManager.sendMessage(message);
|
||||
}
|
||||
// public toggleChat() {
|
||||
// const message: ParentMessage = { action: WebComponentActionType.TOGGLE_CHAT };
|
||||
// this.commandsManager.sendMessage(message);
|
||||
// }
|
||||
}
|
||||
|
||||
49
frontend/webcomponent/src/models/command.model.ts
Normal file
49
frontend/webcomponent/src/models/command.model.ts
Normal file
@ -0,0 +1,49 @@
|
||||
/**
|
||||
* All available commands that can be sent to the WebComponent.
|
||||
*/
|
||||
export enum WebComponentCommand {
|
||||
/**
|
||||
* Initializes the WebComponent with the given configuration.
|
||||
* @private
|
||||
*/
|
||||
INITIALIZE = 'INITIALIZE',
|
||||
|
||||
/**
|
||||
* Ends the current meeting for all participants.
|
||||
* This command is only available for the moderator.
|
||||
*/
|
||||
END_MEETING = 'END_MEETING',
|
||||
/**
|
||||
* Disconnects the local participant from the current room.
|
||||
*/
|
||||
LEAVE_ROOM = 'LEAVE_ROOM'
|
||||
// TOGGLE_CHAT = 'TOGGLE_CHAT'
|
||||
}
|
||||
|
||||
/**
|
||||
* Type definitions for command payloads.
|
||||
* Each property corresponds to a command in {@link WebComponentCommand}.
|
||||
* @category Communication
|
||||
*/
|
||||
export interface CommandPayloads {
|
||||
/**
|
||||
* Payload for the INITIALIZE command.
|
||||
* @private
|
||||
*/
|
||||
[WebComponentCommand.INITIALIZE]: {
|
||||
domain: string;
|
||||
};
|
||||
[WebComponentCommand.END_MEETING]: void;
|
||||
[WebComponentCommand.LEAVE_ROOM]: void;
|
||||
// [WebComponentCommand.TOGGLE_CHAT]: void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type-safe payload for a specific command.
|
||||
* This type allows TypeScript to infer the correct payload type based on the command.
|
||||
* @category Type Helpers
|
||||
* @private
|
||||
*/
|
||||
export type CommandPayloadFor<T extends WebComponentCommand> = T extends keyof CommandPayloads
|
||||
? CommandPayloads[T]
|
||||
: never;
|
||||
45
frontend/webcomponent/src/models/event.model.ts
Normal file
45
frontend/webcomponent/src/models/event.model.ts
Normal file
@ -0,0 +1,45 @@
|
||||
/**
|
||||
* All available events that can be emitted by the WebComponent.
|
||||
* @category Communication
|
||||
*/
|
||||
export enum WebComponentEvent {
|
||||
/**
|
||||
* Event emitted when the local participant joins the room.
|
||||
*/
|
||||
JOIN = 'JOIN',
|
||||
/**
|
||||
* Event emitted when the local participant leaves the room.
|
||||
*/
|
||||
LEFT = 'LEFT',
|
||||
/**
|
||||
* Event emitted when a moderator ends the meeting.
|
||||
*/
|
||||
MEETING_ENDED = 'MEETING_ENDED'
|
||||
}
|
||||
|
||||
/**
|
||||
* Type definitions for event payloads.
|
||||
* Each property corresponds to an event in {@link WebComponentEvent}.
|
||||
* @category Communication
|
||||
*/
|
||||
export interface EventPayloads {
|
||||
[WebComponentEvent.JOIN]: {
|
||||
roomId: string;
|
||||
participantName: string;
|
||||
};
|
||||
[WebComponentEvent.LEFT]: {
|
||||
roomId: string;
|
||||
participantName: string;
|
||||
};
|
||||
[WebComponentEvent.MEETING_ENDED]: {
|
||||
roomId: string;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type-safe payload for a specific event.
|
||||
* This type allows TypeScript to infer the correct payload type based on the event.
|
||||
* @category Type Helpers
|
||||
* @private
|
||||
*/
|
||||
export type EventPayloadFor<T extends WebComponentEvent> = T extends keyof EventPayloads ? EventPayloads[T] : never;
|
||||
62
frontend/webcomponent/src/models/message.type.ts
Normal file
62
frontend/webcomponent/src/models/message.type.ts
Normal file
@ -0,0 +1,62 @@
|
||||
import { CommandPayloadFor, WebComponentCommand } from './command.model';
|
||||
import { EventPayloadFor, WebComponentEvent } from './event.model';
|
||||
|
||||
/**
|
||||
* Represents all possible messages exchanged between the host application and WebComponent.
|
||||
* @category Communication
|
||||
*/
|
||||
export type WebComponentMessage = InboundCommandMessage<WebComponentCommand> | OutboundEventMessage<WebComponentEvent>;
|
||||
|
||||
/**
|
||||
* Message sent from the host application to the WebComponent.
|
||||
* Contains a command with an optional type-safe payload.
|
||||
* @category Communication
|
||||
*/
|
||||
export interface InboundCommandMessage<T extends WebComponentCommand = WebComponentCommand> {
|
||||
/** The command to execute in the WebComponent */
|
||||
command: T;
|
||||
/** Optional payload with additional data for the command */
|
||||
payload?: CommandPayloadFor<T>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Message sent from the WebComponent to the host application.
|
||||
* Contains an event type with an optional type-safe payload.
|
||||
* @category Communication
|
||||
*/
|
||||
export interface OutboundEventMessage<T extends WebComponentEvent = WebComponentEvent> {
|
||||
/** The type of event being emitted */
|
||||
event: T;
|
||||
/** Optional payload with additional data about the event */
|
||||
payload?: EventPayloadFor<T>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to create a properly typed command message.
|
||||
* @param command The command to send
|
||||
* @param payload The payload for the command
|
||||
* @returns A properly formatted command message
|
||||
* @category Utilities
|
||||
* @private
|
||||
*/
|
||||
export function createCommandMessage<T extends WebComponentCommand>(
|
||||
command: T,
|
||||
payload?: CommandPayloadFor<T>
|
||||
): InboundCommandMessage<T> {
|
||||
return { command, payload };
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to create a properly typed event message.
|
||||
* @param event The event type
|
||||
* @param payload The payload for the event
|
||||
* @returns A properly formatted event message
|
||||
* @category Utilities
|
||||
* @private
|
||||
*/
|
||||
export function createEventMessage<T extends WebComponentEvent>(
|
||||
event: T,
|
||||
payload?: EventPayloadFor<T>
|
||||
): OutboundEventMessage<T> {
|
||||
return { event, payload };
|
||||
}
|
||||
@ -1,29 +0,0 @@
|
||||
export type WebComponentMessage = ParentMessage | OpenViduMeetMessage;
|
||||
|
||||
/**
|
||||
* Message sent from the parent to the OpenViduMeet component.
|
||||
*/
|
||||
export interface ParentMessage {
|
||||
action: WebComponentActionType;
|
||||
payload?: Record<string, any>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Message sent from the OpenViduMeet component to the parent.
|
||||
*/
|
||||
export interface OpenViduMeetMessage {
|
||||
eventType: WebComponentEventType;
|
||||
payload?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export enum WebComponentActionType {
|
||||
INITIALIZE = 'initialize',
|
||||
END_MEETING = 'endMeeting',
|
||||
LEAVE_ROOM = 'leaveRoom',
|
||||
TOGGLE_CHAT = 'toggleChat'
|
||||
}
|
||||
|
||||
export enum WebComponentEventType {
|
||||
LOCAL_PARTICIPANT_CONNECTED = 'join',
|
||||
LOCAL_PARTICIPANT_LEFT = 'left'
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user