@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.
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { createContext, useContext, useState, useRef, useEffect, useCallback, useMemo } from 'react';
3
3
  import { createPortal } from 'react-dom';
4
- import { Loader2, Share2, MicOff, Mic, Video, VideoOff, Settings, X, Link2, EyeOff, Eye, Users, MonitorUp, MessageSquare, Maximize, PictureInPicture2, PhoneOff, Undo2, Volume2, XIcon, Pin, MessageSquareOff, MoreVertical } from 'lucide-react';
4
+ import { Loader2, Share2, MicOff, Mic, Video, VideoOff, Settings, X, Link2, EyeOff, Eye, MonitorUp, MessageSquare, Users, Maximize, PictureInPicture2, PhoneOff, Undo2, Volume2, XIcon, Pin, MessageSquareOff, MoreVertical } from 'lucide-react';
5
5
  import { toast } from 'sonner';
6
6
  import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog';
7
7
  import { clsx } from 'clsx';
@@ -2188,7 +2188,7 @@ function BubbleGroup({ className, ...props }) {
2188
2188
  );
2189
2189
  }
2190
2190
  var bubbleVariants = cva(
2191
- "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",
2191
+ "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",
2192
2192
  {
2193
2193
  variants: {
2194
2194
  variant: {
@@ -2233,7 +2233,7 @@ function BubbleContent({
2233
2233
  props: mergeProps(
2234
2234
  {
2235
2235
  className: cn(
2236
- "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",
2236
+ "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",
2237
2237
  className
2238
2238
  )
2239
2239
  },
@@ -2585,7 +2585,7 @@ function StudioSidePanel({
2585
2585
  const panelists = participants.filter((row) => isOnStage(row.stageStatus));
2586
2586
  const audience = participants.filter((row) => !isOnStage(row.stageStatus));
2587
2587
  return /* @__PURE__ */ 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: [
2588
- /* @__PURE__ */ jsxs("div", { className: "flex border-b", children: [
2588
+ /* @__PURE__ */ jsxs("div", { className: "flex", children: [
2589
2589
  /* @__PURE__ */ jsxs(
2590
2590
  Button,
2591
2591
  {
@@ -3239,14 +3239,24 @@ function StudioToolbar({
3239
3239
  children: selfStageStatus === "ON_STAGE" ? /* @__PURE__ */ jsx(EyeOff, {}) : /* @__PURE__ */ jsx(Eye, {})
3240
3240
  }
3241
3241
  ) : null,
3242
- session.role === "guest" && stageEnabled && selfStageStatus !== "ON_STAGE" ? /* @__PURE__ */ jsx(
3242
+ session.role === "guest" && stageEnabled ? /* @__PURE__ */ jsx(
3243
3243
  ControlIcon,
3244
3244
  {
3245
- label: selfStageStatus === "REQUESTED_TO_JOIN_STAGE" ? labels.stageRequested : labels.askToGoOnAir,
3245
+ label: selfStageStatus === "ON_STAGE" ? labels.goOffAir : selfStageStatus === "REQUESTED_TO_JOIN_STAGE" ? labels.stageRequested : labels.askToGoOnAir,
3246
3246
  pressed: selfStageStatus === "REQUESTED_TO_JOIN_STAGE",
3247
- disabled: selfStageStatus === "REQUESTED_TO_JOIN_STAGE",
3248
- onClick: onAskStage,
3249
- children: /* @__PURE__ */ jsx(Users, {})
3247
+ disabled: selfStageStatus === "REQUESTED_TO_JOIN_STAGE" || selfStageStatus === "ON_STAGE" && !canLeaveStage,
3248
+ onClick: () => {
3249
+ if (selfStageStatus === "ON_STAGE") {
3250
+ if (!canLeaveStage) {
3251
+ toast.message(labels.offAirLastVisible);
3252
+ return;
3253
+ }
3254
+ onLeaveStage();
3255
+ return;
3256
+ }
3257
+ onAskStage();
3258
+ },
3259
+ children: selfStageStatus === "ON_STAGE" ? /* @__PURE__ */ jsx(EyeOff, {}) : /* @__PURE__ */ jsx(Eye, {})
3250
3260
  }
3251
3261
  ) : null,
3252
3262
  showScreenControl ? canShareFreely ? /* @__PURE__ */ jsx(
@@ -5255,7 +5265,15 @@ function studioMeetingFromRtk(raw) {
5255
5265
  notifyStage();
5256
5266
  return;
5257
5267
  }
5258
- await meeting.stage?.join?.();
5268
+ try {
5269
+ await meeting.stage?.join?.();
5270
+ } catch {
5271
+ const userId = meeting.self?.userId;
5272
+ if (userId) {
5273
+ await meeting.stage?.grantAccess?.([userId]);
5274
+ }
5275
+ await meeting.stage?.join?.();
5276
+ }
5259
5277
  joinedStageLocally = true;
5260
5278
  await republishCameraIfOn();
5261
5279
  notifyStage();
@@ -5545,7 +5563,11 @@ function useRealtimeKitMeeting(authToken, generation = 0) {
5545
5563
  const [meeting, setMeeting] = useState(null);
5546
5564
  const [error, setError] = useState(null);
5547
5565
  useEffect(() => {
5548
- if (!authToken) return;
5566
+ if (!authToken) {
5567
+ setMeeting(null);
5568
+ setError(null);
5569
+ return;
5570
+ }
5549
5571
  let cancelled = false;
5550
5572
  let handle = null;
5551
5573
  setError(null);
@@ -5890,9 +5912,9 @@ function LivoGuestStudio({
5890
5912
  setError(err instanceof Error ? err.message : lobbyLabels.joinError);
5891
5913
  setWaitingForHost(false);
5892
5914
  }
5893
- setJoining(false);
5894
5915
  } finally {
5895
5916
  joinInFlight.current = false;
5917
+ setJoining(false);
5896
5918
  }
5897
5919
  }, [apiUrl, displayName, guestId, lobbyLabels, token]);
5898
5920
  useEffect(() => {
@@ -5968,6 +5990,10 @@ function LivoGuestStudio({
5968
5990
  onRejoin: () => {
5969
5991
  setSession(null);
5970
5992
  setSessionGen((n) => n + 1);
5993
+ setJoining(false);
5994
+ setWaitingForHost(false);
5995
+ setError(null);
5996
+ joinInFlight.current = false;
5971
5997
  },
5972
5998
  reducedMotion,
5973
5999
  labels,