@livo-tv/sdk 1.2.0 → 1.2.1

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.
@@ -2212,7 +2212,7 @@ function BubbleGroup({ className, ...props }) {
2212
2212
  );
2213
2213
  }
2214
2214
  var bubbleVariants = classVarianceAuthority.cva(
2215
- "group/bubble relative flex w-fit max-w-[80%] min-w-0 flex-col gap-1 group-data-[align=end]/message:self-end data-[align=end]:self-end data-[variant=ghost]:max-w-full",
2215
+ "group/bubble relative flex w-max max-w-[80%] flex-col gap-1 group-data-[align=end]/message:self-end data-[align=end]:self-end data-[variant=ghost]:max-w-full",
2216
2216
  {
2217
2217
  variants: {
2218
2218
  variant: {
@@ -2257,7 +2257,7 @@ function BubbleContent({
2257
2257
  props: mergeProps.mergeProps(
2258
2258
  {
2259
2259
  className: cn(
2260
- "w-fit max-w-full min-w-0 overflow-hidden rounded-xl border border-transparent px-3 py-2 text-sm leading-relaxed wrap-break-word group-data-[align=end]/bubble:self-end [button]:text-left [button,a]:transition-colors [button,a]:outline-none [button,a]:focus-visible:border-ring [button,a]:focus-visible:ring-3 [button,a]:focus-visible:ring-ring/50",
2260
+ "w-max max-w-full overflow-hidden rounded-xl border border-transparent px-3 py-2 text-sm leading-relaxed break-words group-data-[align=end]/bubble:self-end [button]:text-left [button,a]:transition-colors [button,a]:outline-none [button,a]:focus-visible:border-ring [button,a]:focus-visible:ring-3 [button,a]:focus-visible:ring-ring/50",
2261
2261
  className
2262
2262
  )
2263
2263
  },
@@ -2609,7 +2609,7 @@ function StudioSidePanel({
2609
2609
  const panelists = participants.filter((row) => isOnStage(row.stageStatus));
2610
2610
  const audience = participants.filter((row) => !isOnStage(row.stageStatus));
2611
2611
  return /* @__PURE__ */ jsxRuntime.jsxs("aside", { className: "bg-background flex min-h-0 w-full flex-1 flex-col border-t md:w-80 md:flex-none md:border-l md:border-t-0", children: [
2612
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex border-b", children: [
2612
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex", children: [
2613
2613
  /* @__PURE__ */ jsxRuntime.jsxs(
2614
2614
  Button,
2615
2615
  {
@@ -3263,14 +3263,24 @@ function StudioToolbar({
3263
3263
  children: selfStageStatus === "ON_STAGE" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.EyeOff, {}) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, {})
3264
3264
  }
3265
3265
  ) : null,
3266
- session.role === "guest" && stageEnabled && selfStageStatus !== "ON_STAGE" ? /* @__PURE__ */ jsxRuntime.jsx(
3266
+ session.role === "guest" && stageEnabled ? /* @__PURE__ */ jsxRuntime.jsx(
3267
3267
  ControlIcon,
3268
3268
  {
3269
- label: selfStageStatus === "REQUESTED_TO_JOIN_STAGE" ? labels.stageRequested : labels.askToGoOnAir,
3269
+ label: selfStageStatus === "ON_STAGE" ? labels.goOffAir : selfStageStatus === "REQUESTED_TO_JOIN_STAGE" ? labels.stageRequested : labels.askToGoOnAir,
3270
3270
  pressed: selfStageStatus === "REQUESTED_TO_JOIN_STAGE",
3271
- disabled: selfStageStatus === "REQUESTED_TO_JOIN_STAGE",
3272
- onClick: onAskStage,
3273
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Users, {})
3271
+ disabled: selfStageStatus === "REQUESTED_TO_JOIN_STAGE" || selfStageStatus === "ON_STAGE" && !canLeaveStage,
3272
+ onClick: () => {
3273
+ if (selfStageStatus === "ON_STAGE") {
3274
+ if (!canLeaveStage) {
3275
+ sonner.toast.message(labels.offAirLastVisible);
3276
+ return;
3277
+ }
3278
+ onLeaveStage();
3279
+ return;
3280
+ }
3281
+ onAskStage();
3282
+ },
3283
+ children: selfStageStatus === "ON_STAGE" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.EyeOff, {}) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, {})
3274
3284
  }
3275
3285
  ) : null,
3276
3286
  showScreenControl ? canShareFreely ? /* @__PURE__ */ jsxRuntime.jsx(
@@ -5279,7 +5289,15 @@ function studioMeetingFromRtk(raw) {
5279
5289
  notifyStage();
5280
5290
  return;
5281
5291
  }
5282
- await meeting.stage?.join?.();
5292
+ try {
5293
+ await meeting.stage?.join?.();
5294
+ } catch {
5295
+ const userId = meeting.self?.userId;
5296
+ if (userId) {
5297
+ await meeting.stage?.grantAccess?.([userId]);
5298
+ }
5299
+ await meeting.stage?.join?.();
5300
+ }
5283
5301
  joinedStageLocally = true;
5284
5302
  await republishCameraIfOn();
5285
5303
  notifyStage();
@@ -5569,7 +5587,11 @@ function useRealtimeKitMeeting(authToken, generation = 0) {
5569
5587
  const [meeting, setMeeting] = react.useState(null);
5570
5588
  const [error, setError] = react.useState(null);
5571
5589
  react.useEffect(() => {
5572
- if (!authToken) return;
5590
+ if (!authToken) {
5591
+ setMeeting(null);
5592
+ setError(null);
5593
+ return;
5594
+ }
5573
5595
  let cancelled = false;
5574
5596
  let handle = null;
5575
5597
  setError(null);
@@ -5914,9 +5936,9 @@ function LivoGuestStudio({
5914
5936
  setError(err instanceof Error ? err.message : lobbyLabels.joinError);
5915
5937
  setWaitingForHost(false);
5916
5938
  }
5917
- setJoining(false);
5918
5939
  } finally {
5919
5940
  joinInFlight.current = false;
5941
+ setJoining(false);
5920
5942
  }
5921
5943
  }, [apiUrl, displayName, guestId, lobbyLabels, token]);
5922
5944
  react.useEffect(() => {
@@ -5992,6 +6014,10 @@ function LivoGuestStudio({
5992
6014
  onRejoin: () => {
5993
6015
  setSession(null);
5994
6016
  setSessionGen((n) => n + 1);
6017
+ setJoining(false);
6018
+ setWaitingForHost(false);
6019
+ setError(null);
6020
+ joinInFlight.current = false;
5995
6021
  },
5996
6022
  reducedMotion,
5997
6023
  labels,