@tinyweb_dev/oe-meeting-react 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/INTEGRATION.md +5 -5
- package/README.md +25 -3
- package/dist/index.cjs +125 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +91 -6
- package/dist/index.d.ts +91 -6
- package/dist/index.js +119 -7
- package/dist/index.js.map +1 -1
- package/docs/BACKEND-INTEGRATION.md +92 -3
- package/docs/REACT-INTEGRATION.md +74 -7
- package/docs/RELEASE.md +31 -20
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -3,7 +3,7 @@ import { CSSProperties, Ref } from 'react';
|
|
|
3
3
|
|
|
4
4
|
declare const EMBED_PROTOCOL_VERSION: 1;
|
|
5
5
|
declare const EMBED_MESSAGE_SOURCE: "oemeeting";
|
|
6
|
-
declare const DEFAULT_EMBED_ORIGIN = "https://meet.
|
|
6
|
+
declare const DEFAULT_EMBED_ORIGIN = "https://meet.ocean.edu.vn";
|
|
7
7
|
declare enum EmbedEventType {
|
|
8
8
|
READY = "oemeeting:ready",
|
|
9
9
|
JOINED = "oemeeting:joined",
|
|
@@ -11,7 +11,10 @@ declare enum EmbedEventType {
|
|
|
11
11
|
PARTICIPANT_JOINED = "oemeeting:participant-joined",
|
|
12
12
|
PARTICIPANT_LEFT = "oemeeting:participant-left",
|
|
13
13
|
ENDED = "oemeeting:ended",
|
|
14
|
-
ERROR = "oemeeting:error"
|
|
14
|
+
ERROR = "oemeeting:error",
|
|
15
|
+
STAGE_CHANGED = "oemeeting:stage-changed",
|
|
16
|
+
TRANSCRIPT_STARTED = "oemeeting:transcript-started",
|
|
17
|
+
RECORDING_STARTED = "oemeeting:recording-started"
|
|
15
18
|
}
|
|
16
19
|
declare enum EmbedCommandType {
|
|
17
20
|
COMMAND = "oemeeting:command"
|
|
@@ -19,7 +22,9 @@ declare enum EmbedCommandType {
|
|
|
19
22
|
declare enum EmbedCommandAction {
|
|
20
23
|
LEAVE = "leave",
|
|
21
24
|
TOGGLE_MIC = "toggleMic",
|
|
22
|
-
TOGGLE_CAMERA = "toggleCamera"
|
|
25
|
+
TOGGLE_CAMERA = "toggleCamera",
|
|
26
|
+
OPEN_STAGE = "openStage",
|
|
27
|
+
CLOSE_STAGE = "closeStage"
|
|
23
28
|
}
|
|
24
29
|
declare enum EmbedErrorCode {
|
|
25
30
|
TOKEN_INVALID = "TOKEN_INVALID",
|
|
@@ -28,8 +33,17 @@ declare enum EmbedErrorCode {
|
|
|
28
33
|
ROOM_ACCESS_DENIED = "ROOM_ACCESS_DENIED",
|
|
29
34
|
CONNECTION_FAILED = "CONNECTION_FAILED",
|
|
30
35
|
PROTOCOL_MISMATCH = "PROTOCOL_MISMATCH",
|
|
36
|
+
STAGE_ORIGIN_DENIED = "STAGE_ORIGIN_DENIED",
|
|
37
|
+
STAGE_URL_INVALID = "STAGE_URL_INVALID",
|
|
38
|
+
TRANSCRIPT_START_FAILED = "TRANSCRIPT_START_FAILED",
|
|
39
|
+
RECORDING_START_FAILED = "RECORDING_START_FAILED",
|
|
31
40
|
UNKNOWN = "UNKNOWN"
|
|
32
41
|
}
|
|
42
|
+
/** Open host-owned tool id. Meeting does not catalog values. */
|
|
43
|
+
type StageToolId = string;
|
|
44
|
+
declare const MAX_STAGE_URL_LENGTH = 2048;
|
|
45
|
+
declare const MAX_STAGE_TOOL_ID_LENGTH = 32;
|
|
46
|
+
declare function isStageToolId(value: unknown): value is StageToolId;
|
|
33
47
|
declare enum EmbedQueryParam {
|
|
34
48
|
INSTANCE_ID = "instanceId",
|
|
35
49
|
HOST_ORIGIN = "hostOrigin",
|
|
@@ -38,7 +52,23 @@ declare enum EmbedQueryParam {
|
|
|
38
52
|
EXTERNAL_USER_ID = "externalUserId",
|
|
39
53
|
LANG = "lang",
|
|
40
54
|
AUTO_JOIN = "autoJoin",
|
|
41
|
-
HIDE_LEAVE = "hideLeave"
|
|
55
|
+
HIDE_LEAVE = "hideLeave",
|
|
56
|
+
AUTO_TRANSCRIBE = "autoTranscribe",
|
|
57
|
+
AUTO_RECORD = "autoRecord"
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* What happened to the auto-transcribe request the embed made.
|
|
61
|
+
*
|
|
62
|
+
* `ALREADY_RUNNING` is the normal outcome for every participant after the
|
|
63
|
+
* first, because the transcript is a room-level asset rather than a
|
|
64
|
+
* per-participant one. `DISABLED` means the OE Meeting deployment has
|
|
65
|
+
* transcription turned off.
|
|
66
|
+
*/
|
|
67
|
+
declare enum EmbedCaptureOutcome {
|
|
68
|
+
STARTED = "started",
|
|
69
|
+
ALREADY_RUNNING = "already_running",
|
|
70
|
+
DISABLED = "disabled",
|
|
71
|
+
FAILED = "failed"
|
|
42
72
|
}
|
|
43
73
|
|
|
44
74
|
interface EmbedMessageBase {
|
|
@@ -78,6 +108,38 @@ interface EmbedErrorPayload {
|
|
|
78
108
|
code: EmbedErrorCode | string;
|
|
79
109
|
message: string;
|
|
80
110
|
}
|
|
111
|
+
interface EmbedStageChangedPayload {
|
|
112
|
+
url: string | null;
|
|
113
|
+
title?: string;
|
|
114
|
+
tool?: StageToolId;
|
|
115
|
+
openedBy?: string;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Reported once per meeting when `autoTranscribe` is set. Use `roomSlug` to
|
|
119
|
+
* fetch the transcript from your backend once the meeting ends.
|
|
120
|
+
*
|
|
121
|
+
* `transcriptId` is null when nothing was started (`DISABLED` or `FAILED`);
|
|
122
|
+
* pair a `FAILED` outcome with the `TRANSCRIPT_START_FAILED` error event for
|
|
123
|
+
* the reason.
|
|
124
|
+
*/
|
|
125
|
+
interface EmbedTranscriptStartedPayload {
|
|
126
|
+
roomSlug: string;
|
|
127
|
+
outcome: EmbedCaptureOutcome;
|
|
128
|
+
transcriptId: string | null;
|
|
129
|
+
status: string | null;
|
|
130
|
+
}
|
|
131
|
+
/** Reported after the embed handles an `autoRecord` request. */
|
|
132
|
+
interface EmbedRecordingStartedPayload {
|
|
133
|
+
roomSlug: string;
|
|
134
|
+
outcome: EmbedCaptureOutcome;
|
|
135
|
+
recordingId: string | null;
|
|
136
|
+
status: string | null;
|
|
137
|
+
}
|
|
138
|
+
interface OpenStageInput {
|
|
139
|
+
url: string;
|
|
140
|
+
title?: string;
|
|
141
|
+
tool?: StageToolId;
|
|
142
|
+
}
|
|
81
143
|
type EmbedEventPayloadMap = {
|
|
82
144
|
[EmbedEventType.READY]: EmbedReadyPayload;
|
|
83
145
|
[EmbedEventType.JOINED]: EmbedJoinedPayload;
|
|
@@ -86,6 +148,9 @@ type EmbedEventPayloadMap = {
|
|
|
86
148
|
[EmbedEventType.PARTICIPANT_LEFT]: EmbedParticipantLeftPayload;
|
|
87
149
|
[EmbedEventType.ENDED]: EmbedEndedPayload;
|
|
88
150
|
[EmbedEventType.ERROR]: EmbedErrorPayload;
|
|
151
|
+
[EmbedEventType.STAGE_CHANGED]: EmbedStageChangedPayload;
|
|
152
|
+
[EmbedEventType.TRANSCRIPT_STARTED]: EmbedTranscriptStartedPayload;
|
|
153
|
+
[EmbedEventType.RECORDING_STARTED]: EmbedRecordingStartedPayload;
|
|
89
154
|
};
|
|
90
155
|
type EmbedEventByType<T extends EmbedEventType> = EmbedMessageBase & {
|
|
91
156
|
type: T;
|
|
@@ -100,11 +165,14 @@ type EmbedEventOf<T extends EmbedEventType> = Extract<EmbedEvent, {
|
|
|
100
165
|
type EmbedCommandMessage = EmbedMessageBase & {
|
|
101
166
|
type: 'oemeeting:command';
|
|
102
167
|
action: EmbedCommandAction;
|
|
168
|
+
payload?: OpenStageInput;
|
|
103
169
|
};
|
|
104
170
|
interface OeMeetingHandle {
|
|
105
171
|
leave: () => void;
|
|
106
172
|
toggleMic: () => void;
|
|
107
173
|
toggleCamera: () => void;
|
|
174
|
+
openStage: (input: OpenStageInput) => void;
|
|
175
|
+
closeStage: () => void;
|
|
108
176
|
getIframe: () => HTMLIFrameElement | null;
|
|
109
177
|
}
|
|
110
178
|
interface OeMeetingProps {
|
|
@@ -116,6 +184,15 @@ interface OeMeetingProps {
|
|
|
116
184
|
lang?: string;
|
|
117
185
|
autoJoin?: boolean;
|
|
118
186
|
hideLeave?: boolean;
|
|
187
|
+
/**
|
|
188
|
+
* Start the shared transcript as soon as the embed connects. The transcript
|
|
189
|
+
* is a room-level asset: the first participant to connect starts it and it
|
|
190
|
+
* keeps running after they leave. Retrieve it afterwards from your backend
|
|
191
|
+
* with `GET /external-api/v1.0/rooms/:idOrSlug/transcript`.
|
|
192
|
+
*/
|
|
193
|
+
autoTranscribe?: boolean;
|
|
194
|
+
/** Start the shared room recording as soon as the embed connects. */
|
|
195
|
+
autoRecord?: boolean;
|
|
119
196
|
title?: string;
|
|
120
197
|
width?: number | string;
|
|
121
198
|
height?: number | string;
|
|
@@ -132,6 +209,9 @@ interface OeMeetingProps {
|
|
|
132
209
|
onParticipantLeft?: (event: EmbedEventOf<EmbedEventType.PARTICIPANT_LEFT>) => void;
|
|
133
210
|
onEnded?: (event: EmbedEventOf<EmbedEventType.ENDED>) => void;
|
|
134
211
|
onError?: (event: EmbedEventOf<EmbedEventType.ERROR>) => void;
|
|
212
|
+
onStageChanged?: (event: EmbedEventOf<EmbedEventType.STAGE_CHANGED>) => void;
|
|
213
|
+
onTranscriptStarted?: (event: EmbedEventOf<EmbedEventType.TRANSCRIPT_STARTED>) => void;
|
|
214
|
+
onRecordingStarted?: (event: EmbedEventOf<EmbedEventType.RECORDING_STARTED>) => void;
|
|
135
215
|
onEvent?: (event: EmbedEvent) => void;
|
|
136
216
|
}
|
|
137
217
|
interface BuildEmbedUrlOptions {
|
|
@@ -143,6 +223,8 @@ interface BuildEmbedUrlOptions {
|
|
|
143
223
|
lang?: string;
|
|
144
224
|
autoJoin?: boolean;
|
|
145
225
|
hideLeave?: boolean;
|
|
226
|
+
autoTranscribe?: boolean;
|
|
227
|
+
autoRecord?: boolean;
|
|
146
228
|
instanceId?: string;
|
|
147
229
|
hostOrigin?: string;
|
|
148
230
|
}
|
|
@@ -150,7 +232,7 @@ interface BuildEmbedUrlOptions {
|
|
|
150
232
|
declare const DEFAULT_IFRAME_ALLOW = "camera; microphone; fullscreen; autoplay; display-capture; clipboard-write; encrypted-media";
|
|
151
233
|
declare const OeMeeting: react.ForwardRefExoticComponent<OeMeetingProps & react.RefAttributes<OeMeetingHandle>>;
|
|
152
234
|
|
|
153
|
-
type UseOeMeetingOptions = Pick<OeMeetingProps, 'onReady' | 'onJoined' | 'onLeft' | 'onParticipantJoined' | 'onParticipantLeft' | 'onEnded' | 'onError' | 'onEvent'> & {
|
|
235
|
+
type UseOeMeetingOptions = Pick<OeMeetingProps, 'onReady' | 'onJoined' | 'onLeft' | 'onParticipantJoined' | 'onParticipantLeft' | 'onEnded' | 'onError' | 'onStageChanged' | 'onTranscriptStarted' | 'onRecordingStarted' | 'onEvent'> & {
|
|
154
236
|
instanceId: string;
|
|
155
237
|
targetOrigin: string;
|
|
156
238
|
handleRef?: Ref<OeMeetingHandle>;
|
|
@@ -164,4 +246,7 @@ declare function buildEmbedUrl(options: BuildEmbedUrlOptions): string;
|
|
|
164
246
|
|
|
165
247
|
declare function parseEmbedEvent(data: unknown): EmbedEvent | null;
|
|
166
248
|
|
|
167
|
-
|
|
249
|
+
declare function isValidStageUrl(url: string): boolean;
|
|
250
|
+
declare function normalizeOpenStageInput(input: OpenStageInput): OpenStageInput | null;
|
|
251
|
+
|
|
252
|
+
export { type BuildEmbedUrlOptions, DEFAULT_EMBED_ORIGIN, DEFAULT_IFRAME_ALLOW, EMBED_MESSAGE_SOURCE, EMBED_PROTOCOL_VERSION, EmbedCaptureOutcome, EmbedCommandAction, type EmbedCommandMessage, EmbedCommandType, type EmbedEndedPayload, EmbedErrorCode, type EmbedErrorPayload, type EmbedEvent, type EmbedEventOf, type EmbedEventPayloadMap, EmbedEventType, type EmbedJoinedPayload, type EmbedLeftPayload, type EmbedMessageBase, type EmbedParticipantJoinedPayload, type EmbedParticipantLeftPayload, EmbedQueryParam, type EmbedReadyPayload, type EmbedRecordingStartedPayload, type EmbedStageChangedPayload, type EmbedTranscriptStartedPayload, MAX_STAGE_TOOL_ID_LENGTH, MAX_STAGE_URL_LENGTH, OeMeeting, type OeMeetingHandle, type OeMeetingProps, type OpenStageInput, type StageToolId, buildEmbedUrl, isStageToolId, isValidStageUrl, normalizeOpenStageInput, parseEmbedEvent, useOeMeeting };
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { CSSProperties, Ref } from 'react';
|
|
|
3
3
|
|
|
4
4
|
declare const EMBED_PROTOCOL_VERSION: 1;
|
|
5
5
|
declare const EMBED_MESSAGE_SOURCE: "oemeeting";
|
|
6
|
-
declare const DEFAULT_EMBED_ORIGIN = "https://meet.
|
|
6
|
+
declare const DEFAULT_EMBED_ORIGIN = "https://meet.ocean.edu.vn";
|
|
7
7
|
declare enum EmbedEventType {
|
|
8
8
|
READY = "oemeeting:ready",
|
|
9
9
|
JOINED = "oemeeting:joined",
|
|
@@ -11,7 +11,10 @@ declare enum EmbedEventType {
|
|
|
11
11
|
PARTICIPANT_JOINED = "oemeeting:participant-joined",
|
|
12
12
|
PARTICIPANT_LEFT = "oemeeting:participant-left",
|
|
13
13
|
ENDED = "oemeeting:ended",
|
|
14
|
-
ERROR = "oemeeting:error"
|
|
14
|
+
ERROR = "oemeeting:error",
|
|
15
|
+
STAGE_CHANGED = "oemeeting:stage-changed",
|
|
16
|
+
TRANSCRIPT_STARTED = "oemeeting:transcript-started",
|
|
17
|
+
RECORDING_STARTED = "oemeeting:recording-started"
|
|
15
18
|
}
|
|
16
19
|
declare enum EmbedCommandType {
|
|
17
20
|
COMMAND = "oemeeting:command"
|
|
@@ -19,7 +22,9 @@ declare enum EmbedCommandType {
|
|
|
19
22
|
declare enum EmbedCommandAction {
|
|
20
23
|
LEAVE = "leave",
|
|
21
24
|
TOGGLE_MIC = "toggleMic",
|
|
22
|
-
TOGGLE_CAMERA = "toggleCamera"
|
|
25
|
+
TOGGLE_CAMERA = "toggleCamera",
|
|
26
|
+
OPEN_STAGE = "openStage",
|
|
27
|
+
CLOSE_STAGE = "closeStage"
|
|
23
28
|
}
|
|
24
29
|
declare enum EmbedErrorCode {
|
|
25
30
|
TOKEN_INVALID = "TOKEN_INVALID",
|
|
@@ -28,8 +33,17 @@ declare enum EmbedErrorCode {
|
|
|
28
33
|
ROOM_ACCESS_DENIED = "ROOM_ACCESS_DENIED",
|
|
29
34
|
CONNECTION_FAILED = "CONNECTION_FAILED",
|
|
30
35
|
PROTOCOL_MISMATCH = "PROTOCOL_MISMATCH",
|
|
36
|
+
STAGE_ORIGIN_DENIED = "STAGE_ORIGIN_DENIED",
|
|
37
|
+
STAGE_URL_INVALID = "STAGE_URL_INVALID",
|
|
38
|
+
TRANSCRIPT_START_FAILED = "TRANSCRIPT_START_FAILED",
|
|
39
|
+
RECORDING_START_FAILED = "RECORDING_START_FAILED",
|
|
31
40
|
UNKNOWN = "UNKNOWN"
|
|
32
41
|
}
|
|
42
|
+
/** Open host-owned tool id. Meeting does not catalog values. */
|
|
43
|
+
type StageToolId = string;
|
|
44
|
+
declare const MAX_STAGE_URL_LENGTH = 2048;
|
|
45
|
+
declare const MAX_STAGE_TOOL_ID_LENGTH = 32;
|
|
46
|
+
declare function isStageToolId(value: unknown): value is StageToolId;
|
|
33
47
|
declare enum EmbedQueryParam {
|
|
34
48
|
INSTANCE_ID = "instanceId",
|
|
35
49
|
HOST_ORIGIN = "hostOrigin",
|
|
@@ -38,7 +52,23 @@ declare enum EmbedQueryParam {
|
|
|
38
52
|
EXTERNAL_USER_ID = "externalUserId",
|
|
39
53
|
LANG = "lang",
|
|
40
54
|
AUTO_JOIN = "autoJoin",
|
|
41
|
-
HIDE_LEAVE = "hideLeave"
|
|
55
|
+
HIDE_LEAVE = "hideLeave",
|
|
56
|
+
AUTO_TRANSCRIBE = "autoTranscribe",
|
|
57
|
+
AUTO_RECORD = "autoRecord"
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* What happened to the auto-transcribe request the embed made.
|
|
61
|
+
*
|
|
62
|
+
* `ALREADY_RUNNING` is the normal outcome for every participant after the
|
|
63
|
+
* first, because the transcript is a room-level asset rather than a
|
|
64
|
+
* per-participant one. `DISABLED` means the OE Meeting deployment has
|
|
65
|
+
* transcription turned off.
|
|
66
|
+
*/
|
|
67
|
+
declare enum EmbedCaptureOutcome {
|
|
68
|
+
STARTED = "started",
|
|
69
|
+
ALREADY_RUNNING = "already_running",
|
|
70
|
+
DISABLED = "disabled",
|
|
71
|
+
FAILED = "failed"
|
|
42
72
|
}
|
|
43
73
|
|
|
44
74
|
interface EmbedMessageBase {
|
|
@@ -78,6 +108,38 @@ interface EmbedErrorPayload {
|
|
|
78
108
|
code: EmbedErrorCode | string;
|
|
79
109
|
message: string;
|
|
80
110
|
}
|
|
111
|
+
interface EmbedStageChangedPayload {
|
|
112
|
+
url: string | null;
|
|
113
|
+
title?: string;
|
|
114
|
+
tool?: StageToolId;
|
|
115
|
+
openedBy?: string;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Reported once per meeting when `autoTranscribe` is set. Use `roomSlug` to
|
|
119
|
+
* fetch the transcript from your backend once the meeting ends.
|
|
120
|
+
*
|
|
121
|
+
* `transcriptId` is null when nothing was started (`DISABLED` or `FAILED`);
|
|
122
|
+
* pair a `FAILED` outcome with the `TRANSCRIPT_START_FAILED` error event for
|
|
123
|
+
* the reason.
|
|
124
|
+
*/
|
|
125
|
+
interface EmbedTranscriptStartedPayload {
|
|
126
|
+
roomSlug: string;
|
|
127
|
+
outcome: EmbedCaptureOutcome;
|
|
128
|
+
transcriptId: string | null;
|
|
129
|
+
status: string | null;
|
|
130
|
+
}
|
|
131
|
+
/** Reported after the embed handles an `autoRecord` request. */
|
|
132
|
+
interface EmbedRecordingStartedPayload {
|
|
133
|
+
roomSlug: string;
|
|
134
|
+
outcome: EmbedCaptureOutcome;
|
|
135
|
+
recordingId: string | null;
|
|
136
|
+
status: string | null;
|
|
137
|
+
}
|
|
138
|
+
interface OpenStageInput {
|
|
139
|
+
url: string;
|
|
140
|
+
title?: string;
|
|
141
|
+
tool?: StageToolId;
|
|
142
|
+
}
|
|
81
143
|
type EmbedEventPayloadMap = {
|
|
82
144
|
[EmbedEventType.READY]: EmbedReadyPayload;
|
|
83
145
|
[EmbedEventType.JOINED]: EmbedJoinedPayload;
|
|
@@ -86,6 +148,9 @@ type EmbedEventPayloadMap = {
|
|
|
86
148
|
[EmbedEventType.PARTICIPANT_LEFT]: EmbedParticipantLeftPayload;
|
|
87
149
|
[EmbedEventType.ENDED]: EmbedEndedPayload;
|
|
88
150
|
[EmbedEventType.ERROR]: EmbedErrorPayload;
|
|
151
|
+
[EmbedEventType.STAGE_CHANGED]: EmbedStageChangedPayload;
|
|
152
|
+
[EmbedEventType.TRANSCRIPT_STARTED]: EmbedTranscriptStartedPayload;
|
|
153
|
+
[EmbedEventType.RECORDING_STARTED]: EmbedRecordingStartedPayload;
|
|
89
154
|
};
|
|
90
155
|
type EmbedEventByType<T extends EmbedEventType> = EmbedMessageBase & {
|
|
91
156
|
type: T;
|
|
@@ -100,11 +165,14 @@ type EmbedEventOf<T extends EmbedEventType> = Extract<EmbedEvent, {
|
|
|
100
165
|
type EmbedCommandMessage = EmbedMessageBase & {
|
|
101
166
|
type: 'oemeeting:command';
|
|
102
167
|
action: EmbedCommandAction;
|
|
168
|
+
payload?: OpenStageInput;
|
|
103
169
|
};
|
|
104
170
|
interface OeMeetingHandle {
|
|
105
171
|
leave: () => void;
|
|
106
172
|
toggleMic: () => void;
|
|
107
173
|
toggleCamera: () => void;
|
|
174
|
+
openStage: (input: OpenStageInput) => void;
|
|
175
|
+
closeStage: () => void;
|
|
108
176
|
getIframe: () => HTMLIFrameElement | null;
|
|
109
177
|
}
|
|
110
178
|
interface OeMeetingProps {
|
|
@@ -116,6 +184,15 @@ interface OeMeetingProps {
|
|
|
116
184
|
lang?: string;
|
|
117
185
|
autoJoin?: boolean;
|
|
118
186
|
hideLeave?: boolean;
|
|
187
|
+
/**
|
|
188
|
+
* Start the shared transcript as soon as the embed connects. The transcript
|
|
189
|
+
* is a room-level asset: the first participant to connect starts it and it
|
|
190
|
+
* keeps running after they leave. Retrieve it afterwards from your backend
|
|
191
|
+
* with `GET /external-api/v1.0/rooms/:idOrSlug/transcript`.
|
|
192
|
+
*/
|
|
193
|
+
autoTranscribe?: boolean;
|
|
194
|
+
/** Start the shared room recording as soon as the embed connects. */
|
|
195
|
+
autoRecord?: boolean;
|
|
119
196
|
title?: string;
|
|
120
197
|
width?: number | string;
|
|
121
198
|
height?: number | string;
|
|
@@ -132,6 +209,9 @@ interface OeMeetingProps {
|
|
|
132
209
|
onParticipantLeft?: (event: EmbedEventOf<EmbedEventType.PARTICIPANT_LEFT>) => void;
|
|
133
210
|
onEnded?: (event: EmbedEventOf<EmbedEventType.ENDED>) => void;
|
|
134
211
|
onError?: (event: EmbedEventOf<EmbedEventType.ERROR>) => void;
|
|
212
|
+
onStageChanged?: (event: EmbedEventOf<EmbedEventType.STAGE_CHANGED>) => void;
|
|
213
|
+
onTranscriptStarted?: (event: EmbedEventOf<EmbedEventType.TRANSCRIPT_STARTED>) => void;
|
|
214
|
+
onRecordingStarted?: (event: EmbedEventOf<EmbedEventType.RECORDING_STARTED>) => void;
|
|
135
215
|
onEvent?: (event: EmbedEvent) => void;
|
|
136
216
|
}
|
|
137
217
|
interface BuildEmbedUrlOptions {
|
|
@@ -143,6 +223,8 @@ interface BuildEmbedUrlOptions {
|
|
|
143
223
|
lang?: string;
|
|
144
224
|
autoJoin?: boolean;
|
|
145
225
|
hideLeave?: boolean;
|
|
226
|
+
autoTranscribe?: boolean;
|
|
227
|
+
autoRecord?: boolean;
|
|
146
228
|
instanceId?: string;
|
|
147
229
|
hostOrigin?: string;
|
|
148
230
|
}
|
|
@@ -150,7 +232,7 @@ interface BuildEmbedUrlOptions {
|
|
|
150
232
|
declare const DEFAULT_IFRAME_ALLOW = "camera; microphone; fullscreen; autoplay; display-capture; clipboard-write; encrypted-media";
|
|
151
233
|
declare const OeMeeting: react.ForwardRefExoticComponent<OeMeetingProps & react.RefAttributes<OeMeetingHandle>>;
|
|
152
234
|
|
|
153
|
-
type UseOeMeetingOptions = Pick<OeMeetingProps, 'onReady' | 'onJoined' | 'onLeft' | 'onParticipantJoined' | 'onParticipantLeft' | 'onEnded' | 'onError' | 'onEvent'> & {
|
|
235
|
+
type UseOeMeetingOptions = Pick<OeMeetingProps, 'onReady' | 'onJoined' | 'onLeft' | 'onParticipantJoined' | 'onParticipantLeft' | 'onEnded' | 'onError' | 'onStageChanged' | 'onTranscriptStarted' | 'onRecordingStarted' | 'onEvent'> & {
|
|
154
236
|
instanceId: string;
|
|
155
237
|
targetOrigin: string;
|
|
156
238
|
handleRef?: Ref<OeMeetingHandle>;
|
|
@@ -164,4 +246,7 @@ declare function buildEmbedUrl(options: BuildEmbedUrlOptions): string;
|
|
|
164
246
|
|
|
165
247
|
declare function parseEmbedEvent(data: unknown): EmbedEvent | null;
|
|
166
248
|
|
|
167
|
-
|
|
249
|
+
declare function isValidStageUrl(url: string): boolean;
|
|
250
|
+
declare function normalizeOpenStageInput(input: OpenStageInput): OpenStageInput | null;
|
|
251
|
+
|
|
252
|
+
export { type BuildEmbedUrlOptions, DEFAULT_EMBED_ORIGIN, DEFAULT_IFRAME_ALLOW, EMBED_MESSAGE_SOURCE, EMBED_PROTOCOL_VERSION, EmbedCaptureOutcome, EmbedCommandAction, type EmbedCommandMessage, EmbedCommandType, type EmbedEndedPayload, EmbedErrorCode, type EmbedErrorPayload, type EmbedEvent, type EmbedEventOf, type EmbedEventPayloadMap, EmbedEventType, type EmbedJoinedPayload, type EmbedLeftPayload, type EmbedMessageBase, type EmbedParticipantJoinedPayload, type EmbedParticipantLeftPayload, EmbedQueryParam, type EmbedReadyPayload, type EmbedRecordingStartedPayload, type EmbedStageChangedPayload, type EmbedTranscriptStartedPayload, MAX_STAGE_TOOL_ID_LENGTH, MAX_STAGE_URL_LENGTH, OeMeeting, type OeMeetingHandle, type OeMeetingProps, type OpenStageInput, type StageToolId, buildEmbedUrl, isStageToolId, isValidStageUrl, normalizeOpenStageInput, parseEmbedEvent, useOeMeeting };
|
package/dist/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
// src/embed-protocol.ts
|
|
9
9
|
var EMBED_PROTOCOL_VERSION = 1;
|
|
10
10
|
var EMBED_MESSAGE_SOURCE = "oemeeting";
|
|
11
|
-
var DEFAULT_EMBED_ORIGIN = "https://meet.
|
|
11
|
+
var DEFAULT_EMBED_ORIGIN = "https://meet.ocean.edu.vn";
|
|
12
12
|
var EmbedEventType = /* @__PURE__ */ ((EmbedEventType2) => {
|
|
13
13
|
EmbedEventType2["READY"] = "oemeeting:ready";
|
|
14
14
|
EmbedEventType2["JOINED"] = "oemeeting:joined";
|
|
@@ -17,6 +17,9 @@ var EmbedEventType = /* @__PURE__ */ ((EmbedEventType2) => {
|
|
|
17
17
|
EmbedEventType2["PARTICIPANT_LEFT"] = "oemeeting:participant-left";
|
|
18
18
|
EmbedEventType2["ENDED"] = "oemeeting:ended";
|
|
19
19
|
EmbedEventType2["ERROR"] = "oemeeting:error";
|
|
20
|
+
EmbedEventType2["STAGE_CHANGED"] = "oemeeting:stage-changed";
|
|
21
|
+
EmbedEventType2["TRANSCRIPT_STARTED"] = "oemeeting:transcript-started";
|
|
22
|
+
EmbedEventType2["RECORDING_STARTED"] = "oemeeting:recording-started";
|
|
20
23
|
return EmbedEventType2;
|
|
21
24
|
})(EmbedEventType || {});
|
|
22
25
|
var EmbedCommandType = /* @__PURE__ */ ((EmbedCommandType2) => {
|
|
@@ -27,6 +30,8 @@ var EmbedCommandAction = /* @__PURE__ */ ((EmbedCommandAction2) => {
|
|
|
27
30
|
EmbedCommandAction2["LEAVE"] = "leave";
|
|
28
31
|
EmbedCommandAction2["TOGGLE_MIC"] = "toggleMic";
|
|
29
32
|
EmbedCommandAction2["TOGGLE_CAMERA"] = "toggleCamera";
|
|
33
|
+
EmbedCommandAction2["OPEN_STAGE"] = "openStage";
|
|
34
|
+
EmbedCommandAction2["CLOSE_STAGE"] = "closeStage";
|
|
30
35
|
return EmbedCommandAction2;
|
|
31
36
|
})(EmbedCommandAction || {});
|
|
32
37
|
var EmbedErrorCode = /* @__PURE__ */ ((EmbedErrorCode2) => {
|
|
@@ -36,9 +41,19 @@ var EmbedErrorCode = /* @__PURE__ */ ((EmbedErrorCode2) => {
|
|
|
36
41
|
EmbedErrorCode2["ROOM_ACCESS_DENIED"] = "ROOM_ACCESS_DENIED";
|
|
37
42
|
EmbedErrorCode2["CONNECTION_FAILED"] = "CONNECTION_FAILED";
|
|
38
43
|
EmbedErrorCode2["PROTOCOL_MISMATCH"] = "PROTOCOL_MISMATCH";
|
|
44
|
+
EmbedErrorCode2["STAGE_ORIGIN_DENIED"] = "STAGE_ORIGIN_DENIED";
|
|
45
|
+
EmbedErrorCode2["STAGE_URL_INVALID"] = "STAGE_URL_INVALID";
|
|
46
|
+
EmbedErrorCode2["TRANSCRIPT_START_FAILED"] = "TRANSCRIPT_START_FAILED";
|
|
47
|
+
EmbedErrorCode2["RECORDING_START_FAILED"] = "RECORDING_START_FAILED";
|
|
39
48
|
EmbedErrorCode2["UNKNOWN"] = "UNKNOWN";
|
|
40
49
|
return EmbedErrorCode2;
|
|
41
50
|
})(EmbedErrorCode || {});
|
|
51
|
+
var MAX_STAGE_URL_LENGTH = 2048;
|
|
52
|
+
var MAX_STAGE_TOOL_ID_LENGTH = 32;
|
|
53
|
+
var STAGE_TOOL_ID_PATTERN = /^[a-z][a-z0-9._-]{0,31}$/;
|
|
54
|
+
function isStageToolId(value) {
|
|
55
|
+
return typeof value === "string" && value.length > 0 && value.length <= MAX_STAGE_TOOL_ID_LENGTH && STAGE_TOOL_ID_PATTERN.test(value);
|
|
56
|
+
}
|
|
42
57
|
var EmbedQueryParam = /* @__PURE__ */ ((EmbedQueryParam2) => {
|
|
43
58
|
EmbedQueryParam2["INSTANCE_ID"] = "instanceId";
|
|
44
59
|
EmbedQueryParam2["HOST_ORIGIN"] = "hostOrigin";
|
|
@@ -48,8 +63,17 @@ var EmbedQueryParam = /* @__PURE__ */ ((EmbedQueryParam2) => {
|
|
|
48
63
|
EmbedQueryParam2["LANG"] = "lang";
|
|
49
64
|
EmbedQueryParam2["AUTO_JOIN"] = "autoJoin";
|
|
50
65
|
EmbedQueryParam2["HIDE_LEAVE"] = "hideLeave";
|
|
66
|
+
EmbedQueryParam2["AUTO_TRANSCRIBE"] = "autoTranscribe";
|
|
67
|
+
EmbedQueryParam2["AUTO_RECORD"] = "autoRecord";
|
|
51
68
|
return EmbedQueryParam2;
|
|
52
69
|
})(EmbedQueryParam || {});
|
|
70
|
+
var EmbedCaptureOutcome = /* @__PURE__ */ ((EmbedCaptureOutcome2) => {
|
|
71
|
+
EmbedCaptureOutcome2["STARTED"] = "started";
|
|
72
|
+
EmbedCaptureOutcome2["ALREADY_RUNNING"] = "already_running";
|
|
73
|
+
EmbedCaptureOutcome2["DISABLED"] = "disabled";
|
|
74
|
+
EmbedCaptureOutcome2["FAILED"] = "failed";
|
|
75
|
+
return EmbedCaptureOutcome2;
|
|
76
|
+
})(EmbedCaptureOutcome || {});
|
|
53
77
|
|
|
54
78
|
// src/buildEmbedUrl.ts
|
|
55
79
|
var QUERY_FLAG_ENABLED = "1";
|
|
@@ -80,7 +104,9 @@ function buildEmbedUrl(options) {
|
|
|
80
104
|
["externalUserId" /* EXTERNAL_USER_ID */, options.externalUserId],
|
|
81
105
|
["lang" /* LANG */, options.lang],
|
|
82
106
|
["autoJoin" /* AUTO_JOIN */, toFlag(options.autoJoin)],
|
|
83
|
-
["hideLeave" /* HIDE_LEAVE */, toFlag(options.hideLeave)]
|
|
107
|
+
["hideLeave" /* HIDE_LEAVE */, toFlag(options.hideLeave)],
|
|
108
|
+
["autoTranscribe" /* AUTO_TRANSCRIBE */, toFlag(options.autoTranscribe)],
|
|
109
|
+
["autoRecord" /* AUTO_RECORD */, toFlag(options.autoRecord)]
|
|
84
110
|
];
|
|
85
111
|
for (const [key, value] of entries) {
|
|
86
112
|
if (value !== void 0 && value !== "") {
|
|
@@ -99,6 +125,31 @@ import {
|
|
|
99
125
|
useRef
|
|
100
126
|
} from "react";
|
|
101
127
|
|
|
128
|
+
// src/openStage.ts
|
|
129
|
+
function isValidStageUrl(url) {
|
|
130
|
+
if (url.length === 0 || url.length > MAX_STAGE_URL_LENGTH) return false;
|
|
131
|
+
try {
|
|
132
|
+
const parsed = new URL(url);
|
|
133
|
+
if (parsed.protocol === "https:") return true;
|
|
134
|
+
if (parsed.protocol === "http:") {
|
|
135
|
+
return parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1";
|
|
136
|
+
}
|
|
137
|
+
return false;
|
|
138
|
+
} catch {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function normalizeOpenStageInput(input) {
|
|
143
|
+
const url = input.url.trim();
|
|
144
|
+
if (!isValidStageUrl(url)) return null;
|
|
145
|
+
const title = input.title?.trim();
|
|
146
|
+
return {
|
|
147
|
+
url,
|
|
148
|
+
...title ? { title: title.slice(0, 200) } : {},
|
|
149
|
+
...isStageToolId(input.tool) ? { tool: input.tool } : {}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
102
153
|
// src/parseEmbedEvent.ts
|
|
103
154
|
var EVENT_TYPES = new Set(Object.values(EmbedEventType));
|
|
104
155
|
function isRecord(value) {
|
|
@@ -107,6 +158,13 @@ function isRecord(value) {
|
|
|
107
158
|
function isOptionalString(value) {
|
|
108
159
|
return value === void 0 || typeof value === "string";
|
|
109
160
|
}
|
|
161
|
+
function isNullableString(value) {
|
|
162
|
+
return value === null || typeof value === "string";
|
|
163
|
+
}
|
|
164
|
+
var CAPTURE_OUTCOMES = new Set(Object.values(EmbedCaptureOutcome));
|
|
165
|
+
function isCaptureOutcome(value) {
|
|
166
|
+
return typeof value === "string" && CAPTURE_OUTCOMES.has(value);
|
|
167
|
+
}
|
|
110
168
|
function hasValidPayload(type, payload) {
|
|
111
169
|
switch (type) {
|
|
112
170
|
case "oemeeting:ready" /* READY */:
|
|
@@ -123,6 +181,12 @@ function hasValidPayload(type, payload) {
|
|
|
123
181
|
return typeof payload.roomSlug === "string" && typeof payload.endedAt === "string";
|
|
124
182
|
case "oemeeting:error" /* ERROR */:
|
|
125
183
|
return typeof payload.code === "string" && typeof payload.message === "string";
|
|
184
|
+
case "oemeeting:stage-changed" /* STAGE_CHANGED */:
|
|
185
|
+
return (payload.url === null || typeof payload.url === "string") && isOptionalString(payload.title) && isOptionalString(payload.tool) && isOptionalString(payload.openedBy);
|
|
186
|
+
case "oemeeting:transcript-started" /* TRANSCRIPT_STARTED */:
|
|
187
|
+
return typeof payload.roomSlug === "string" && isCaptureOutcome(payload.outcome) && isNullableString(payload.transcriptId) && isNullableString(payload.status);
|
|
188
|
+
case "oemeeting:recording-started" /* RECORDING_STARTED */:
|
|
189
|
+
return typeof payload.roomSlug === "string" && isCaptureOutcome(payload.outcome) && isNullableString(payload.recordingId) && isNullableString(payload.status);
|
|
126
190
|
}
|
|
127
191
|
}
|
|
128
192
|
function parseEmbedEvent(data) {
|
|
@@ -144,7 +208,8 @@ function postCommand(options) {
|
|
|
144
208
|
version: EMBED_PROTOCOL_VERSION,
|
|
145
209
|
instanceId: options.instanceId,
|
|
146
210
|
type: "oemeeting:command" /* COMMAND */,
|
|
147
|
-
action: options.action
|
|
211
|
+
action: options.action,
|
|
212
|
+
...options.payload ? { payload: options.payload } : {}
|
|
148
213
|
};
|
|
149
214
|
frameWindow.postMessage(message, options.targetOrigin);
|
|
150
215
|
}
|
|
@@ -186,17 +251,27 @@ function useOeMeeting(options) {
|
|
|
186
251
|
case "oemeeting:error" /* ERROR */:
|
|
187
252
|
callbacks.onError?.(embedEvent);
|
|
188
253
|
break;
|
|
254
|
+
case "oemeeting:stage-changed" /* STAGE_CHANGED */:
|
|
255
|
+
callbacks.onStageChanged?.(embedEvent);
|
|
256
|
+
break;
|
|
257
|
+
case "oemeeting:transcript-started" /* TRANSCRIPT_STARTED */:
|
|
258
|
+
callbacks.onTranscriptStarted?.(embedEvent);
|
|
259
|
+
break;
|
|
260
|
+
case "oemeeting:recording-started" /* RECORDING_STARTED */:
|
|
261
|
+
callbacks.onRecordingStarted?.(embedEvent);
|
|
262
|
+
break;
|
|
189
263
|
}
|
|
190
264
|
};
|
|
191
265
|
window.addEventListener("message", onMessage);
|
|
192
266
|
return () => window.removeEventListener("message", onMessage);
|
|
193
267
|
}, [options.instanceId, options.targetOrigin]);
|
|
194
268
|
const send = useCallback(
|
|
195
|
-
(action) => postCommand({
|
|
269
|
+
(action, payload) => postCommand({
|
|
196
270
|
iframe: iframeRef.current,
|
|
197
271
|
instanceId: options.instanceId,
|
|
198
272
|
action,
|
|
199
|
-
targetOrigin: options.targetOrigin
|
|
273
|
+
targetOrigin: options.targetOrigin,
|
|
274
|
+
payload
|
|
200
275
|
}),
|
|
201
276
|
[options.instanceId, options.targetOrigin]
|
|
202
277
|
);
|
|
@@ -209,10 +284,29 @@ function useOeMeeting(options) {
|
|
|
209
284
|
() => send("toggleCamera" /* TOGGLE_CAMERA */),
|
|
210
285
|
[send]
|
|
211
286
|
);
|
|
287
|
+
const openStage = useCallback(
|
|
288
|
+
(input) => {
|
|
289
|
+
const normalized = normalizeOpenStageInput(input);
|
|
290
|
+
if (!normalized) return;
|
|
291
|
+
send("openStage" /* OPEN_STAGE */, normalized);
|
|
292
|
+
},
|
|
293
|
+
[send]
|
|
294
|
+
);
|
|
295
|
+
const closeStage = useCallback(
|
|
296
|
+
() => send("closeStage" /* CLOSE_STAGE */),
|
|
297
|
+
[send]
|
|
298
|
+
);
|
|
212
299
|
const getIframe = useCallback(() => iframeRef.current, []);
|
|
213
300
|
const handle = useMemo(
|
|
214
|
-
() => ({
|
|
215
|
-
|
|
301
|
+
() => ({
|
|
302
|
+
leave,
|
|
303
|
+
toggleMic,
|
|
304
|
+
toggleCamera,
|
|
305
|
+
openStage,
|
|
306
|
+
closeStage,
|
|
307
|
+
getIframe
|
|
308
|
+
}),
|
|
309
|
+
[closeStage, getIframe, leave, openStage, toggleCamera, toggleMic]
|
|
216
310
|
);
|
|
217
311
|
useImperativeHandle(options.handleRef, () => handle, [handle]);
|
|
218
312
|
return { iframeRef, handle };
|
|
@@ -239,6 +333,8 @@ var OeMeeting = forwardRef(
|
|
|
239
333
|
lang,
|
|
240
334
|
autoJoin = true,
|
|
241
335
|
hideLeave,
|
|
336
|
+
autoTranscribe,
|
|
337
|
+
autoRecord,
|
|
242
338
|
title = "OE Meeting room",
|
|
243
339
|
width = "100%",
|
|
244
340
|
height = 640,
|
|
@@ -255,6 +351,9 @@ var OeMeeting = forwardRef(
|
|
|
255
351
|
onParticipantLeft,
|
|
256
352
|
onEnded,
|
|
257
353
|
onError,
|
|
354
|
+
onStageChanged,
|
|
355
|
+
onTranscriptStarted,
|
|
356
|
+
onRecordingStarted,
|
|
258
357
|
onEvent
|
|
259
358
|
} = props;
|
|
260
359
|
const reactId = useId();
|
|
@@ -275,11 +374,15 @@ var OeMeeting = forwardRef(
|
|
|
275
374
|
lang,
|
|
276
375
|
autoJoin,
|
|
277
376
|
hideLeave,
|
|
377
|
+
autoTranscribe,
|
|
378
|
+
autoRecord,
|
|
278
379
|
instanceId,
|
|
279
380
|
hostOrigin
|
|
280
381
|
}),
|
|
281
382
|
[
|
|
282
383
|
autoJoin,
|
|
384
|
+
autoRecord,
|
|
385
|
+
autoTranscribe,
|
|
283
386
|
externalUserId,
|
|
284
387
|
hideLeave,
|
|
285
388
|
hostOrigin,
|
|
@@ -302,6 +405,9 @@ var OeMeeting = forwardRef(
|
|
|
302
405
|
onParticipantLeft,
|
|
303
406
|
onEnded,
|
|
304
407
|
onError,
|
|
408
|
+
onStageChanged,
|
|
409
|
+
onTranscriptStarted,
|
|
410
|
+
onRecordingStarted,
|
|
305
411
|
onEvent
|
|
306
412
|
});
|
|
307
413
|
const wrapperStyle = {
|
|
@@ -345,13 +451,19 @@ export {
|
|
|
345
451
|
DEFAULT_IFRAME_ALLOW,
|
|
346
452
|
EMBED_MESSAGE_SOURCE,
|
|
347
453
|
EMBED_PROTOCOL_VERSION,
|
|
454
|
+
EmbedCaptureOutcome,
|
|
348
455
|
EmbedCommandAction,
|
|
349
456
|
EmbedCommandType,
|
|
350
457
|
EmbedErrorCode,
|
|
351
458
|
EmbedEventType,
|
|
352
459
|
EmbedQueryParam,
|
|
460
|
+
MAX_STAGE_TOOL_ID_LENGTH,
|
|
461
|
+
MAX_STAGE_URL_LENGTH,
|
|
353
462
|
OeMeeting,
|
|
354
463
|
buildEmbedUrl,
|
|
464
|
+
isStageToolId,
|
|
465
|
+
isValidStageUrl,
|
|
466
|
+
normalizeOpenStageInput,
|
|
355
467
|
parseEmbedEvent,
|
|
356
468
|
useOeMeeting
|
|
357
469
|
};
|