@livo-tv/sdk 1.6.0 → 1.7.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/dist/studio/index.cjs +293 -236
- package/dist/studio/index.cjs.map +1 -1
- package/dist/studio/index.d.cts +1 -0
- package/dist/studio/index.d.ts +1 -0
- package/dist/studio/index.js +293 -236
- package/dist/studio/index.js.map +1 -1
- package/package.json +1 -1
package/dist/studio/index.cjs
CHANGED
|
@@ -4109,227 +4109,223 @@ function StudioToolbar({
|
|
|
4109
4109
|
const showStageModerator = session.role === "moderator" && canManageStage;
|
|
4110
4110
|
const showStageGuest = session.role === "guest" && stageEnabled;
|
|
4111
4111
|
const captionsLabel = !captionsAvailable ? labels.captions : !captionsReady ? labels.captionsNotReady : captionsOn ? labels.captionsOn : labels.captionsOff;
|
|
4112
|
-
return /* @__PURE__ */ jsxRuntime.jsx("footer", { className: "
|
|
4113
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
MediaSplit,
|
|
4117
|
-
{
|
|
4118
|
-
label: muted ? labels.unmute : labels.mute,
|
|
4119
|
-
pressed: muted,
|
|
4120
|
-
tone: muted ? "danger" : "default",
|
|
4121
|
-
onClick: onToggleMute,
|
|
4122
|
-
pickerLabel: labels.micDevice,
|
|
4123
|
-
options: devices.audio,
|
|
4124
|
-
selected: effective.audio,
|
|
4125
|
-
onSelect: (id) => void onDeviceChange("audio", id),
|
|
4126
|
-
children: muted ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MicOff, {}) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Mic, {})
|
|
4127
|
-
}
|
|
4128
|
-
),
|
|
4129
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4130
|
-
MediaSplit,
|
|
4131
|
-
{
|
|
4132
|
-
label: labels.camera,
|
|
4133
|
-
pressed: cameraOn,
|
|
4134
|
-
onClick: onToggleCamera,
|
|
4135
|
-
pickerLabel: labels.cameraDevice,
|
|
4136
|
-
options: devices.video,
|
|
4137
|
-
selected: effective.video,
|
|
4138
|
-
onSelect: (id) => void onDeviceChange("video", id),
|
|
4139
|
-
children: cameraOn ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Video, {}) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.VideoOff, {})
|
|
4140
|
-
}
|
|
4141
|
-
)
|
|
4142
|
-
] }) : null,
|
|
4143
|
-
showStageModerator ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4144
|
-
ControlIcon,
|
|
4145
|
-
{
|
|
4146
|
-
label: selfStageStatus === "ON_STAGE" ? labels.goOffAir : labels.goOnAir,
|
|
4147
|
-
pressed: selfStageStatus !== "ON_STAGE",
|
|
4148
|
-
disabled: selfStageStatus === "ON_STAGE" && !canLeaveStage,
|
|
4149
|
-
onClick: () => {
|
|
4150
|
-
if (selfStageStatus === "ON_STAGE") {
|
|
4151
|
-
if (!canLeaveStage) {
|
|
4152
|
-
sonner.toast.message(labels.offAirLastVisible);
|
|
4153
|
-
return;
|
|
4154
|
-
}
|
|
4155
|
-
onLeaveStage();
|
|
4156
|
-
return;
|
|
4157
|
-
}
|
|
4158
|
-
onAskStage();
|
|
4159
|
-
},
|
|
4160
|
-
children: selfStageStatus === "ON_STAGE" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.EyeOff, {}) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, {})
|
|
4161
|
-
}
|
|
4162
|
-
) : null,
|
|
4163
|
-
showStageGuest ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4164
|
-
ControlIcon,
|
|
4165
|
-
{
|
|
4166
|
-
label: selfStageStatus === "ON_STAGE" ? labels.goOffAir : selfStageStatus === "REQUESTED_TO_JOIN_STAGE" ? labels.stageRequested : labels.askToGoOnAir,
|
|
4167
|
-
pressed: selfStageStatus === "REQUESTED_TO_JOIN_STAGE",
|
|
4168
|
-
disabled: selfStageStatus === "REQUESTED_TO_JOIN_STAGE" || selfStageStatus === "ON_STAGE" && !canLeaveStage,
|
|
4169
|
-
onClick: () => {
|
|
4170
|
-
if (selfStageStatus === "ON_STAGE") {
|
|
4171
|
-
if (!canLeaveStage) {
|
|
4172
|
-
sonner.toast.message(labels.offAirLastVisible);
|
|
4173
|
-
return;
|
|
4174
|
-
}
|
|
4175
|
-
onLeaveStage();
|
|
4176
|
-
return;
|
|
4177
|
-
}
|
|
4178
|
-
onAskStage();
|
|
4179
|
-
},
|
|
4180
|
-
children: selfStageStatus === "ON_STAGE" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.EyeOff, {}) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, {})
|
|
4181
|
-
}
|
|
4182
|
-
) : null,
|
|
4183
|
-
showScreenControl ? canShareFreely ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4184
|
-
ControlIcon,
|
|
4112
|
+
return /* @__PURE__ */ jsxRuntime.jsx("footer", { className: "border-t px-3 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-center gap-2", children: [
|
|
4113
|
+
showMediaControls ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4114
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4115
|
+
MediaSplit,
|
|
4185
4116
|
{
|
|
4186
|
-
label: labels.
|
|
4187
|
-
pressed:
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4117
|
+
label: muted ? labels.unmute : labels.mute,
|
|
4118
|
+
pressed: muted,
|
|
4119
|
+
tone: muted ? "danger" : "default",
|
|
4120
|
+
onClick: onToggleMute,
|
|
4121
|
+
pickerLabel: labels.micDevice,
|
|
4122
|
+
options: devices.audio,
|
|
4123
|
+
selected: effective.audio,
|
|
4124
|
+
onSelect: (id) => void onDeviceChange("audio", id),
|
|
4125
|
+
children: muted ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MicOff, {}) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Mic, {})
|
|
4192
4126
|
}
|
|
4193
|
-
)
|
|
4194
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4195
|
-
ControlIcon,
|
|
4196
|
-
{
|
|
4197
|
-
label: labels.shareRequested,
|
|
4198
|
-
pressed: true,
|
|
4199
|
-
disabled: true,
|
|
4200
|
-
onClick: () => void 0,
|
|
4201
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MonitorUp, {})
|
|
4202
|
-
}
|
|
4203
|
-
),
|
|
4204
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4205
|
-
ControlIcon,
|
|
4206
|
-
{
|
|
4207
|
-
label: labels.cancelShareRequest,
|
|
4208
|
-
onClick: onCancelShareRequest,
|
|
4209
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, {})
|
|
4210
|
-
}
|
|
4211
|
-
)
|
|
4212
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx(ControlIcon, { label: labels.askToShare, onClick: onAskToShare, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MonitorUp, {}) }) : null,
|
|
4127
|
+
),
|
|
4213
4128
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4214
|
-
|
|
4129
|
+
MediaSplit,
|
|
4215
4130
|
{
|
|
4216
|
-
label:
|
|
4217
|
-
pressed:
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4131
|
+
label: labels.camera,
|
|
4132
|
+
pressed: cameraOn,
|
|
4133
|
+
onClick: onToggleCamera,
|
|
4134
|
+
pickerLabel: labels.cameraDevice,
|
|
4135
|
+
options: devices.video,
|
|
4136
|
+
selected: effective.video,
|
|
4137
|
+
onSelect: (id) => void onDeviceChange("video", id),
|
|
4138
|
+
children: cameraOn ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Video, {}) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.VideoOff, {})
|
|
4221
4139
|
}
|
|
4222
|
-
)
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4140
|
+
)
|
|
4141
|
+
] }) : null,
|
|
4142
|
+
showStageModerator ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4143
|
+
ControlIcon,
|
|
4144
|
+
{
|
|
4145
|
+
label: selfStageStatus === "ON_STAGE" ? labels.goOffAir : labels.goOnAir,
|
|
4146
|
+
pressed: selfStageStatus !== "ON_STAGE",
|
|
4147
|
+
disabled: selfStageStatus === "ON_STAGE" && !canLeaveStage,
|
|
4148
|
+
onClick: () => {
|
|
4149
|
+
if (selfStageStatus === "ON_STAGE") {
|
|
4150
|
+
if (!canLeaveStage) {
|
|
4151
|
+
sonner.toast.message(labels.offAirLastVisible);
|
|
4152
|
+
return;
|
|
4153
|
+
}
|
|
4154
|
+
onLeaveStage();
|
|
4155
|
+
return;
|
|
4237
4156
|
}
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
]
|
|
4157
|
+
onAskStage();
|
|
4158
|
+
},
|
|
4159
|
+
children: selfStageStatus === "ON_STAGE" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.EyeOff, {}) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, {})
|
|
4160
|
+
}
|
|
4161
|
+
) : null,
|
|
4162
|
+
showStageGuest ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4163
|
+
ControlIcon,
|
|
4164
|
+
{
|
|
4165
|
+
label: selfStageStatus === "ON_STAGE" ? labels.goOffAir : selfStageStatus === "REQUESTED_TO_JOIN_STAGE" ? labels.stageRequested : labels.askToGoOnAir,
|
|
4166
|
+
pressed: selfStageStatus === "REQUESTED_TO_JOIN_STAGE",
|
|
4167
|
+
disabled: selfStageStatus === "REQUESTED_TO_JOIN_STAGE" || selfStageStatus === "ON_STAGE" && !canLeaveStage,
|
|
4168
|
+
onClick: () => {
|
|
4169
|
+
if (selfStageStatus === "ON_STAGE") {
|
|
4170
|
+
if (!canLeaveStage) {
|
|
4171
|
+
sonner.toast.message(labels.offAirLastVisible);
|
|
4172
|
+
return;
|
|
4255
4173
|
}
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4174
|
+
onLeaveStage();
|
|
4175
|
+
return;
|
|
4176
|
+
}
|
|
4177
|
+
onAskStage();
|
|
4178
|
+
},
|
|
4179
|
+
children: selfStageStatus === "ON_STAGE" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.EyeOff, {}) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, {})
|
|
4180
|
+
}
|
|
4181
|
+
) : null,
|
|
4182
|
+
showScreenControl ? canShareFreely ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4183
|
+
ControlIcon,
|
|
4184
|
+
{
|
|
4185
|
+
label: labels.screen,
|
|
4186
|
+
pressed: screenOn,
|
|
4187
|
+
disabled: screenPending || !screenAvailable && !screenOn,
|
|
4188
|
+
pending: screenPending,
|
|
4189
|
+
onClick: onToggleScreen,
|
|
4190
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MonitorUp, {})
|
|
4191
|
+
}
|
|
4192
|
+
) : shareGrant === "requested" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4265
4193
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4266
4194
|
ControlIcon,
|
|
4267
4195
|
{
|
|
4268
|
-
label:
|
|
4269
|
-
pressed:
|
|
4270
|
-
|
|
4271
|
-
onClick:
|
|
4272
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.
|
|
4196
|
+
label: labels.shareRequested,
|
|
4197
|
+
pressed: true,
|
|
4198
|
+
disabled: true,
|
|
4199
|
+
onClick: () => void 0,
|
|
4200
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MonitorUp, {})
|
|
4273
4201
|
}
|
|
4274
4202
|
),
|
|
4275
|
-
session.role === "moderator" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4276
|
-
ControlIcon,
|
|
4277
|
-
{
|
|
4278
|
-
label: peopleBadge > 0 ? `${labels.people} (${peopleBadge})` : labels.people,
|
|
4279
|
-
pressed: peopleOpen,
|
|
4280
|
-
badge: peopleBadge,
|
|
4281
|
-
onClick: onTogglePeople,
|
|
4282
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Users, {})
|
|
4283
|
-
}
|
|
4284
|
-
) : null,
|
|
4285
4203
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4286
4204
|
ControlIcon,
|
|
4287
4205
|
{
|
|
4288
|
-
label: labels.
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings, {})
|
|
4206
|
+
label: labels.cancelShareRequest,
|
|
4207
|
+
onClick: onCancelShareRequest,
|
|
4208
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, {})
|
|
4292
4209
|
}
|
|
4293
|
-
)
|
|
4210
|
+
)
|
|
4211
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(ControlIcon, { label: labels.askToShare, onClick: onAskToShare, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MonitorUp, {}) }) : null,
|
|
4212
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4213
|
+
ControlIcon,
|
|
4214
|
+
{
|
|
4215
|
+
label: captionsLabel,
|
|
4216
|
+
pressed: captionsOn,
|
|
4217
|
+
disabled: !captionsAvailable,
|
|
4218
|
+
onClick: onToggleCaptions,
|
|
4219
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Captions, {})
|
|
4220
|
+
}
|
|
4221
|
+
),
|
|
4222
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { children: [
|
|
4294
4223
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4295
|
-
|
|
4296
|
-
{
|
|
4297
|
-
open: settingsOpen,
|
|
4298
|
-
onOpenChange: onCloseSettings,
|
|
4299
|
-
meeting,
|
|
4300
|
-
reducedMotion,
|
|
4301
|
-
cameraOn,
|
|
4302
|
-
labels,
|
|
4303
|
-
captionPrefs,
|
|
4304
|
-
onCaptionPrefsChange,
|
|
4305
|
-
captionsAvailable,
|
|
4306
|
-
effectBackgrounds
|
|
4307
|
-
}
|
|
4308
|
-
),
|
|
4309
|
-
session.role === "guest" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4310
|
-
ConfirmAction,
|
|
4224
|
+
DropdownMenuTrigger,
|
|
4311
4225
|
{
|
|
4312
|
-
|
|
4313
|
-
title: labels.leaveTitle,
|
|
4314
|
-
description: labels.leaveDescription,
|
|
4315
|
-
confirmLabel: labels.leaveConfirm,
|
|
4316
|
-
pending,
|
|
4317
|
-
onConfirm: onLeave,
|
|
4318
|
-
trigger: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4226
|
+
render: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4319
4227
|
Button,
|
|
4320
4228
|
{
|
|
4321
4229
|
type: "button",
|
|
4322
|
-
variant: "destructive",
|
|
4323
4230
|
size: "icon-lg",
|
|
4324
|
-
|
|
4325
|
-
"aria-label": labels.
|
|
4326
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PhoneOff, {})
|
|
4231
|
+
variant: "secondary",
|
|
4232
|
+
"aria-label": labels.more
|
|
4327
4233
|
}
|
|
4328
|
-
)
|
|
4234
|
+
),
|
|
4235
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoreVertical, {})
|
|
4329
4236
|
}
|
|
4330
|
-
)
|
|
4331
|
-
|
|
4332
|
-
|
|
4237
|
+
),
|
|
4238
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuContent, { align: "center", className: "min-w-44", children: [
|
|
4239
|
+
fullscreenSupported ? /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { onClick: () => void enterFullscreen(), children: [
|
|
4240
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Maximize, {}),
|
|
4241
|
+
labels.fullscreen
|
|
4242
|
+
] }) : null,
|
|
4243
|
+
pipSupported ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4244
|
+
DropdownMenuItem,
|
|
4245
|
+
{
|
|
4246
|
+
onClick: () => {
|
|
4247
|
+
if (pipOpen) onClosePip();
|
|
4248
|
+
else onOpenPip();
|
|
4249
|
+
},
|
|
4250
|
+
children: [
|
|
4251
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.PictureInPicture2, {}),
|
|
4252
|
+
pipOpen ? labels.closePip : labels.openPip
|
|
4253
|
+
]
|
|
4254
|
+
}
|
|
4255
|
+
) : null,
|
|
4256
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { onClick: onOpenSettings, children: [
|
|
4257
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings, {}),
|
|
4258
|
+
labels.settings
|
|
4259
|
+
] })
|
|
4260
|
+
] })
|
|
4261
|
+
] }),
|
|
4262
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4263
|
+
ControlIcon,
|
|
4264
|
+
{
|
|
4265
|
+
label: unreadChat > 0 ? `${labels.chat} (${unreadChat})` : labels.chat,
|
|
4266
|
+
pressed: chatOpen,
|
|
4267
|
+
badge: unreadChat,
|
|
4268
|
+
onClick: onToggleChat,
|
|
4269
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageSquare, {})
|
|
4270
|
+
}
|
|
4271
|
+
),
|
|
4272
|
+
session.role === "moderator" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4273
|
+
ControlIcon,
|
|
4274
|
+
{
|
|
4275
|
+
label: peopleBadge > 0 ? `${labels.people} (${peopleBadge})` : labels.people,
|
|
4276
|
+
pressed: peopleOpen,
|
|
4277
|
+
badge: peopleBadge,
|
|
4278
|
+
onClick: onTogglePeople,
|
|
4279
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Users, {})
|
|
4280
|
+
}
|
|
4281
|
+
) : null,
|
|
4282
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4283
|
+
ControlIcon,
|
|
4284
|
+
{
|
|
4285
|
+
label: labels.settings,
|
|
4286
|
+
pressed: settingsOpen,
|
|
4287
|
+
onClick: onOpenSettings,
|
|
4288
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings, {})
|
|
4289
|
+
}
|
|
4290
|
+
),
|
|
4291
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4292
|
+
StudioSettingsDialog,
|
|
4293
|
+
{
|
|
4294
|
+
open: settingsOpen,
|
|
4295
|
+
onOpenChange: onCloseSettings,
|
|
4296
|
+
meeting,
|
|
4297
|
+
reducedMotion,
|
|
4298
|
+
cameraOn,
|
|
4299
|
+
labels,
|
|
4300
|
+
captionPrefs,
|
|
4301
|
+
onCaptionPrefsChange,
|
|
4302
|
+
captionsAvailable,
|
|
4303
|
+
effectBackgrounds
|
|
4304
|
+
}
|
|
4305
|
+
),
|
|
4306
|
+
session.role === "guest" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4307
|
+
ConfirmAction,
|
|
4308
|
+
{
|
|
4309
|
+
triggerLabel: labels.leave,
|
|
4310
|
+
title: labels.leaveTitle,
|
|
4311
|
+
description: labels.leaveDescription,
|
|
4312
|
+
confirmLabel: labels.leaveConfirm,
|
|
4313
|
+
pending,
|
|
4314
|
+
onConfirm: onLeave,
|
|
4315
|
+
trigger: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4316
|
+
Button,
|
|
4317
|
+
{
|
|
4318
|
+
type: "button",
|
|
4319
|
+
variant: "destructive",
|
|
4320
|
+
size: "icon-lg",
|
|
4321
|
+
disabled: pending,
|
|
4322
|
+
"aria-label": labels.leave,
|
|
4323
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PhoneOff, {})
|
|
4324
|
+
}
|
|
4325
|
+
)
|
|
4326
|
+
}
|
|
4327
|
+
) : null
|
|
4328
|
+
] }) }) });
|
|
4333
4329
|
}
|
|
4334
4330
|
function MediaSplit({
|
|
4335
4331
|
label,
|
|
@@ -4342,8 +4338,8 @@ function MediaSplit({
|
|
|
4342
4338
|
onSelect,
|
|
4343
4339
|
children
|
|
4344
4340
|
}) {
|
|
4345
|
-
|
|
4346
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4341
|
+
if (options.length === 0) {
|
|
4342
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4347
4343
|
ControlIcon,
|
|
4348
4344
|
{
|
|
4349
4345
|
label,
|
|
@@ -4352,8 +4348,11 @@ function MediaSplit({
|
|
|
4352
4348
|
onClick,
|
|
4353
4349
|
children
|
|
4354
4350
|
}
|
|
4355
|
-
)
|
|
4356
|
-
|
|
4351
|
+
);
|
|
4352
|
+
}
|
|
4353
|
+
const iconVariant = tone === "danger" ? "destructive" : pressed ? "default" : "secondary";
|
|
4354
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-secondary inline-flex h-10 items-center rounded-full p-0.5", children: [
|
|
4355
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { children: [
|
|
4357
4356
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4358
4357
|
DropdownMenuTrigger,
|
|
4359
4358
|
{
|
|
@@ -4362,8 +4361,8 @@ function MediaSplit({
|
|
|
4362
4361
|
{
|
|
4363
4362
|
type: "button",
|
|
4364
4363
|
size: "icon-xs",
|
|
4365
|
-
variant: "
|
|
4366
|
-
className: "-
|
|
4364
|
+
variant: "ghost",
|
|
4365
|
+
className: "text-muted-foreground hover:text-foreground h-9 w-8 rounded-full hover:bg-transparent",
|
|
4367
4366
|
"aria-label": pickerLabel
|
|
4368
4367
|
}
|
|
4369
4368
|
),
|
|
@@ -4381,7 +4380,28 @@ function MediaSplit({
|
|
|
4381
4380
|
},
|
|
4382
4381
|
option.deviceId
|
|
4383
4382
|
)) })
|
|
4384
|
-
] })
|
|
4383
|
+
] }),
|
|
4384
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
|
|
4385
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4386
|
+
TooltipTrigger,
|
|
4387
|
+
{
|
|
4388
|
+
render: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4389
|
+
Button,
|
|
4390
|
+
{
|
|
4391
|
+
type: "button",
|
|
4392
|
+
size: "icon-lg",
|
|
4393
|
+
variant: iconVariant,
|
|
4394
|
+
className: iconVariant === "secondary" ? "rounded-full bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_10%)] hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_16%)]" : "rounded-full",
|
|
4395
|
+
"aria-label": label,
|
|
4396
|
+
"aria-pressed": pressed,
|
|
4397
|
+
onClick
|
|
4398
|
+
}
|
|
4399
|
+
),
|
|
4400
|
+
children
|
|
4401
|
+
}
|
|
4402
|
+
),
|
|
4403
|
+
/* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { children: label })
|
|
4404
|
+
] })
|
|
4385
4405
|
] });
|
|
4386
4406
|
}
|
|
4387
4407
|
var POLL_MS = 2e3;
|
|
@@ -5027,10 +5047,11 @@ function StudioRoom({
|
|
|
5027
5047
|
]);
|
|
5028
5048
|
const verifyGrantTookEffect = react.useCallback(
|
|
5029
5049
|
(userId, retried = false) => {
|
|
5050
|
+
if (!userId) return;
|
|
5030
5051
|
const id = window.setTimeout(() => {
|
|
5031
|
-
const target = meeting.participants().find((row) => row.userId === userId);
|
|
5032
|
-
if (
|
|
5033
|
-
if (!retried
|
|
5052
|
+
const target = meeting.participants().find((row) => row.userId === userId || row.id === userId);
|
|
5053
|
+
if (target && isOnStage(target.stageStatus)) return;
|
|
5054
|
+
if (!retried) {
|
|
5034
5055
|
void meeting.setStageAccess(userId, true).then(() => {
|
|
5035
5056
|
verifyGrantTookEffect(userId, true);
|
|
5036
5057
|
}).catch(() => {
|
|
@@ -5044,6 +5065,12 @@ function StudioRoom({
|
|
|
5044
5065
|
},
|
|
5045
5066
|
[labels.stageGrantNoEffect, meeting]
|
|
5046
5067
|
);
|
|
5068
|
+
react.useEffect(
|
|
5069
|
+
() => meeting.subscribeStageGrant((userId) => {
|
|
5070
|
+
verifyGrantTookEffect(userId);
|
|
5071
|
+
}),
|
|
5072
|
+
[meeting, verifyGrantTookEffect]
|
|
5073
|
+
);
|
|
5047
5074
|
const onSetStage = react.useCallback(
|
|
5048
5075
|
async (tile, on) => {
|
|
5049
5076
|
const userId = tile.userId;
|
|
@@ -5368,20 +5395,13 @@ function StudioRoom({
|
|
|
5368
5395
|
peopleBadge,
|
|
5369
5396
|
labels,
|
|
5370
5397
|
onAdmitAs: (id, as) => {
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
if (as === "panelist" && guest?.userId) {
|
|
5374
|
-
verifyGrantTookEffect(guest.userId);
|
|
5375
|
-
}
|
|
5398
|
+
void Promise.resolve(meeting.admitAs(id, as)).catch(() => {
|
|
5399
|
+
sonner.toast.error(labels.stageError);
|
|
5376
5400
|
});
|
|
5377
5401
|
},
|
|
5378
5402
|
onAdmitAll: (as) => {
|
|
5379
|
-
|
|
5380
|
-
|
|
5381
|
-
if (as !== "panelist") return;
|
|
5382
|
-
for (const guest of waiting) {
|
|
5383
|
-
if (guest.userId) verifyGrantTookEffect(guest.userId);
|
|
5384
|
-
}
|
|
5403
|
+
void Promise.resolve(meeting.admitAll(as)).catch(() => {
|
|
5404
|
+
sonner.toast.error(labels.stageError);
|
|
5385
5405
|
});
|
|
5386
5406
|
},
|
|
5387
5407
|
onDeny: (id) => {
|
|
@@ -6084,6 +6104,7 @@ function activeSpeakerFrom(payload, fallback) {
|
|
|
6084
6104
|
}
|
|
6085
6105
|
var STAGE_JOIN_RETRY_MS = 1e3;
|
|
6086
6106
|
var STAGE_JOIN_MAX_ATTEMPTS = 3;
|
|
6107
|
+
var STAGE_GRANT_JOIN_MAX_FAILURES = 8;
|
|
6087
6108
|
function isStageDisabledError(error) {
|
|
6088
6109
|
if (!error || typeof error !== "object") return false;
|
|
6089
6110
|
const row = error;
|
|
@@ -6156,12 +6177,15 @@ function studioMeetingFromRtk(raw) {
|
|
|
6156
6177
|
const chatListeners = /* @__PURE__ */ new Set();
|
|
6157
6178
|
const participantListeners = /* @__PURE__ */ new Set();
|
|
6158
6179
|
const stageListeners = /* @__PURE__ */ new Set();
|
|
6180
|
+
const stageGrantListeners = /* @__PURE__ */ new Set();
|
|
6159
6181
|
const pinListeners = /* @__PURE__ */ new Set();
|
|
6160
6182
|
const pendingPanelists = /* @__PURE__ */ new Set();
|
|
6161
6183
|
const chatSend = /* @__PURE__ */ new Map();
|
|
6162
6184
|
const nameOverrides = /* @__PURE__ */ new Map();
|
|
6163
6185
|
let joinStageInFlight = null;
|
|
6164
6186
|
let joinedStageLocally = false;
|
|
6187
|
+
let stageGrantPending = false;
|
|
6188
|
+
let stageGrantJoinFailures = 0;
|
|
6165
6189
|
let lastMeetingError = null;
|
|
6166
6190
|
const historyMessages = [];
|
|
6167
6191
|
let speakerSinkId = null;
|
|
@@ -6260,6 +6284,21 @@ function studioMeetingFromRtk(raw) {
|
|
|
6260
6284
|
function currentStageStatus() {
|
|
6261
6285
|
return meeting.self?.stageStatus ?? meeting.stage?.status;
|
|
6262
6286
|
}
|
|
6287
|
+
function isStageAccepted() {
|
|
6288
|
+
return meeting.self?.stageStatus === "ACCEPTED_TO_JOIN_STAGE" || meeting.stage?.status === "ACCEPTED_TO_JOIN_STAGE";
|
|
6289
|
+
}
|
|
6290
|
+
function clearStageGrantPending() {
|
|
6291
|
+
stageGrantPending = false;
|
|
6292
|
+
stageGrantJoinFailures = 0;
|
|
6293
|
+
}
|
|
6294
|
+
function notifyStageGrant(userId) {
|
|
6295
|
+
if (!userId) return;
|
|
6296
|
+
for (const listener of stageGrantListeners) listener(userId);
|
|
6297
|
+
}
|
|
6298
|
+
function markStageGranted() {
|
|
6299
|
+
stageGrantPending = true;
|
|
6300
|
+
void ensureStageJoined();
|
|
6301
|
+
}
|
|
6263
6302
|
function resolveConnectionState() {
|
|
6264
6303
|
const self = meeting.self;
|
|
6265
6304
|
const roomState = self?.roomState ?? null;
|
|
@@ -6351,22 +6390,21 @@ function studioMeetingFromRtk(raw) {
|
|
|
6351
6390
|
joinStageInFlight = null;
|
|
6352
6391
|
}
|
|
6353
6392
|
}
|
|
6354
|
-
async function
|
|
6393
|
+
async function ensureStageJoined() {
|
|
6355
6394
|
if (currentStageStatus() === "ON_STAGE") {
|
|
6356
|
-
|
|
6395
|
+
clearStageGrantPending();
|
|
6357
6396
|
return;
|
|
6358
6397
|
}
|
|
6398
|
+
if (!stageGrantPending && !isStageAccepted()) return;
|
|
6399
|
+
stageGrantPending = true;
|
|
6400
|
+
if (stageGrantJoinFailures >= STAGE_GRANT_JOIN_MAX_FAILURES) return;
|
|
6359
6401
|
try {
|
|
6360
6402
|
await joinStageWithRetry();
|
|
6403
|
+
if (currentStageStatus() === "ON_STAGE") {
|
|
6404
|
+
clearStageGrantPending();
|
|
6405
|
+
}
|
|
6361
6406
|
} catch {
|
|
6362
|
-
|
|
6363
|
-
}
|
|
6364
|
-
}
|
|
6365
|
-
async function ensureStageJoined() {
|
|
6366
|
-
if (currentStageStatus() !== "ACCEPTED_TO_JOIN_STAGE") return;
|
|
6367
|
-
try {
|
|
6368
|
-
await joinStageWithRetry();
|
|
6369
|
-
} catch {
|
|
6407
|
+
stageGrantJoinFailures += 1;
|
|
6370
6408
|
notifyStage();
|
|
6371
6409
|
}
|
|
6372
6410
|
}
|
|
@@ -6397,6 +6435,7 @@ function studioMeetingFromRtk(raw) {
|
|
|
6397
6435
|
const grantId = takePendingGrantId(joined2);
|
|
6398
6436
|
if (!grantId) return;
|
|
6399
6437
|
await meeting.stage?.grantAccess?.([grantId]);
|
|
6438
|
+
notifyStageGrant(joined2?.userId || grantId);
|
|
6400
6439
|
notifyStage();
|
|
6401
6440
|
}
|
|
6402
6441
|
async function grantPendingIfJoined(participantId, userId) {
|
|
@@ -6405,6 +6444,7 @@ function studioMeetingFromRtk(raw) {
|
|
|
6405
6444
|
if (!grantId) return;
|
|
6406
6445
|
pendingPanelists.delete(participantId);
|
|
6407
6446
|
await meeting.stage?.grantAccess?.([grantId]);
|
|
6447
|
+
notifyStageGrant(already?.userId || grantId);
|
|
6408
6448
|
notifyStage();
|
|
6409
6449
|
}
|
|
6410
6450
|
listen(meeting.self, "videoUpdate", rebindMedia);
|
|
@@ -6454,15 +6494,15 @@ function studioMeetingFromRtk(raw) {
|
|
|
6454
6494
|
listen(meeting.stage, "stageAccessRequestUpdate", notifyStage);
|
|
6455
6495
|
listen(meeting.stage, "newStageRequest", notifyStage);
|
|
6456
6496
|
listen(meeting.stage, "stageRequestApproved", () => {
|
|
6457
|
-
|
|
6497
|
+
markStageGranted();
|
|
6498
|
+
});
|
|
6499
|
+
listen(meeting.stage, "acceptPresentRequests", () => {
|
|
6500
|
+
markStageGranted();
|
|
6458
6501
|
});
|
|
6459
6502
|
listen(meeting.stage, "stageRequestRejected", notifyStage);
|
|
6460
|
-
listen(meeting.stage, "stageStatusUpdate", (
|
|
6461
|
-
if (
|
|
6462
|
-
|
|
6463
|
-
return;
|
|
6464
|
-
}
|
|
6465
|
-
if (status === "ON_STAGE") {
|
|
6503
|
+
listen(meeting.stage, "stageStatusUpdate", () => {
|
|
6504
|
+
if (currentStageStatus() === "ON_STAGE") {
|
|
6505
|
+
clearStageGrantPending();
|
|
6466
6506
|
if (joinedStageLocally) {
|
|
6467
6507
|
joinedStageLocally = false;
|
|
6468
6508
|
notifyStage();
|
|
@@ -6473,12 +6513,17 @@ function studioMeetingFromRtk(raw) {
|
|
|
6473
6513
|
});
|
|
6474
6514
|
return;
|
|
6475
6515
|
}
|
|
6516
|
+
if (isStageAccepted()) {
|
|
6517
|
+
markStageGranted();
|
|
6518
|
+
return;
|
|
6519
|
+
}
|
|
6476
6520
|
notifyStage();
|
|
6477
6521
|
});
|
|
6478
6522
|
return {
|
|
6479
6523
|
async join() {
|
|
6480
6524
|
await meeting.join?.();
|
|
6481
6525
|
await joinStageIfAllowed();
|
|
6526
|
+
await ensureStageJoined();
|
|
6482
6527
|
await applyCurrentVideoEffects();
|
|
6483
6528
|
},
|
|
6484
6529
|
async leave() {
|
|
@@ -6574,7 +6619,12 @@ function studioMeetingFromRtk(raw) {
|
|
|
6574
6619
|
return;
|
|
6575
6620
|
}
|
|
6576
6621
|
if (on) await meeting.stage?.grantAccess?.([userId]);
|
|
6577
|
-
else
|
|
6622
|
+
else {
|
|
6623
|
+
await meeting.stage?.kick?.([userId]);
|
|
6624
|
+
if (meeting.self?.userId === userId) {
|
|
6625
|
+
clearStageGrantPending();
|
|
6626
|
+
}
|
|
6627
|
+
}
|
|
6578
6628
|
notifyStage();
|
|
6579
6629
|
},
|
|
6580
6630
|
async denyStageAccess(userId) {
|
|
@@ -6605,6 +6655,7 @@ function studioMeetingFromRtk(raw) {
|
|
|
6605
6655
|
async leaveStage() {
|
|
6606
6656
|
await meeting.stage?.leave?.();
|
|
6607
6657
|
joinedStageLocally = false;
|
|
6658
|
+
clearStageGrantPending();
|
|
6608
6659
|
notifyStage();
|
|
6609
6660
|
},
|
|
6610
6661
|
stageStatus() {
|
|
@@ -6636,6 +6687,12 @@ function studioMeetingFromRtk(raw) {
|
|
|
6636
6687
|
stageListeners.delete(cb);
|
|
6637
6688
|
};
|
|
6638
6689
|
},
|
|
6690
|
+
subscribeStageGrant(cb) {
|
|
6691
|
+
stageGrantListeners.add(cb);
|
|
6692
|
+
return () => {
|
|
6693
|
+
stageGrantListeners.delete(cb);
|
|
6694
|
+
};
|
|
6695
|
+
},
|
|
6639
6696
|
canManageStage() {
|
|
6640
6697
|
return meeting.self?.permissions?.acceptStageRequests === true;
|
|
6641
6698
|
},
|