@livo-tv/sdk 1.2.4 → 1.3.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.
@@ -365,6 +365,7 @@ declare function studioRoomLabels(t: (key: string, values?: Record<string, strin
365
365
  unpinnedToast: string;
366
366
  pinError: string;
367
367
  kickTitle: string;
368
+ kickTitleNamed: string;
368
369
  kickDescription: string;
369
370
  kickConfirm: string;
370
371
  kickError: string;
@@ -365,6 +365,7 @@ declare function studioRoomLabels(t: (key: string, values?: Record<string, strin
365
365
  unpinnedToast: string;
366
366
  pinError: string;
367
367
  kickTitle: string;
368
+ kickTitleNamed: string;
368
369
  kickDescription: string;
369
370
  kickConfirm: string;
370
371
  kickError: string;
@@ -2680,11 +2680,15 @@ function StudioSidePanel({
2680
2680
  onGrantStage,
2681
2681
  onDenyStage,
2682
2682
  onTakeOffAir,
2683
+ onKick,
2683
2684
  guestUrl,
2684
2685
  onShareGuestLink
2685
2686
  }) {
2686
2687
  const panelists = participants.filter((row) => isOnStage(row.stageStatus));
2687
2688
  const audience = participants.filter((row) => !isOnStage(row.stageStatus));
2689
+ const [pendingKick, setPendingKick] = useState(
2690
+ null
2691
+ );
2688
2692
  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: [
2689
2693
  /* @__PURE__ */ jsxs("div", { className: "flex", children: [
2690
2694
  /* @__PURE__ */ jsxs(
@@ -2801,23 +2805,37 @@ function StudioSidePanel({
2801
2805
  /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: labels.panelists }),
2802
2806
  panelists.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-sm", children: labels.noPanelists }) : /* @__PURE__ */ jsx("ul", { className: "space-y-2", children: panelists.map((row) => {
2803
2807
  const userId = row.userId;
2808
+ const showKick = isModerator2 && !row.isSelf && Boolean(row.id);
2804
2809
  return /* @__PURE__ */ jsxs(
2805
2810
  "li",
2806
2811
  {
2807
2812
  className: "space-y-2 rounded-md border p-2",
2808
2813
  children: [
2809
2814
  /* @__PURE__ */ jsx("span", { className: "block truncate text-sm", children: row.name }),
2810
- !row.isSelf && userId ? /* @__PURE__ */ jsx(
2811
- Button,
2812
- {
2813
- type: "button",
2814
- size: "xs",
2815
- variant: "outline",
2816
- className: "w-full",
2817
- onClick: () => onTakeOffAir(userId),
2818
- children: labels.offAir
2819
- }
2820
- ) : null
2815
+ /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
2816
+ !row.isSelf && userId ? /* @__PURE__ */ jsx(
2817
+ Button,
2818
+ {
2819
+ type: "button",
2820
+ size: "xs",
2821
+ variant: "outline",
2822
+ className: "w-full",
2823
+ onClick: () => onTakeOffAir(userId),
2824
+ children: labels.offAir
2825
+ }
2826
+ ) : null,
2827
+ showKick ? /* @__PURE__ */ jsx(
2828
+ Button,
2829
+ {
2830
+ type: "button",
2831
+ size: "xs",
2832
+ variant: "ghost",
2833
+ className: "w-full",
2834
+ onClick: () => setPendingKick(row),
2835
+ children: labels.kick
2836
+ }
2837
+ ) : null
2838
+ ] })
2821
2839
  ]
2822
2840
  },
2823
2841
  row.id
@@ -2828,29 +2846,61 @@ function StudioSidePanel({
2828
2846
  /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: labels.audience }),
2829
2847
  audience.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-sm", children: labels.noAudience }) : /* @__PURE__ */ jsx("ul", { className: "space-y-2", children: audience.map((row) => {
2830
2848
  const userId = row.userId;
2849
+ const showKick = isModerator2 && !row.isSelf && Boolean(row.id);
2831
2850
  return /* @__PURE__ */ jsxs(
2832
2851
  "li",
2833
2852
  {
2834
2853
  className: "space-y-2 rounded-md border p-2",
2835
2854
  children: [
2836
2855
  /* @__PURE__ */ jsx("span", { className: "block truncate text-sm", children: row.name }),
2837
- !row.isSelf && userId ? /* @__PURE__ */ jsx(
2838
- Button,
2839
- {
2840
- type: "button",
2841
- size: "xs",
2842
- variant: "outline",
2843
- className: "w-full",
2844
- onClick: () => onGrantStage(userId),
2845
- children: labels.bringOnAir
2846
- }
2847
- ) : null
2856
+ /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
2857
+ !row.isSelf && userId ? /* @__PURE__ */ jsx(
2858
+ Button,
2859
+ {
2860
+ type: "button",
2861
+ size: "xs",
2862
+ variant: "outline",
2863
+ className: "w-full",
2864
+ onClick: () => onGrantStage(userId),
2865
+ children: labels.bringOnAir
2866
+ }
2867
+ ) : null,
2868
+ showKick ? /* @__PURE__ */ jsx(
2869
+ Button,
2870
+ {
2871
+ type: "button",
2872
+ size: "xs",
2873
+ variant: "ghost",
2874
+ className: "w-full",
2875
+ onClick: () => setPendingKick(row),
2876
+ children: labels.kick
2877
+ }
2878
+ ) : null
2879
+ ] })
2848
2880
  ]
2849
2881
  },
2850
2882
  row.id
2851
2883
  );
2852
2884
  }) })
2853
- ] })
2885
+ ] }),
2886
+ /* @__PURE__ */ jsx(
2887
+ ConfirmAction,
2888
+ {
2889
+ open: pendingKick !== null,
2890
+ onOpenChange: (open) => {
2891
+ if (!open) setPendingKick(null);
2892
+ },
2893
+ triggerLabel: labels.kick,
2894
+ title: pendingKick ? labels.kickTitleNamed.replace("{name}", pendingKick.name) : labels.kickTitle,
2895
+ description: labels.kickDescription,
2896
+ confirmLabel: labels.kickConfirm,
2897
+ onConfirm: () => {
2898
+ const target = pendingKick;
2899
+ setPendingKick(null);
2900
+ if (target) onKick(target.id);
2901
+ }
2902
+ }
2903
+ )
2854
2904
  ] })
2855
2905
  ] });
2856
2906
  }
@@ -4412,6 +4462,7 @@ function StudioRoom({
4412
4462
  const tile = participants.find((row) => row.userId === userId);
4413
4463
  if (tile) void onSetStage(tile, false);
4414
4464
  },
4465
+ onKick: (id) => void onKick(id),
4415
4466
  guestUrl: session.guestUrl,
4416
4467
  onShareGuestLink: () => {
4417
4468
  const url = session.guestUrl;
@@ -5257,6 +5308,14 @@ function studioMeetingFromRtk(raw) {
5257
5308
  await meeting.self.disableVideo?.();
5258
5309
  await meeting.self.enableVideo?.();
5259
5310
  }
5311
+ async function acceptAllowedStageIfOffAir() {
5312
+ if (currentStageStatus() !== "OFF_STAGE") return;
5313
+ if (meeting.self?.permissions?.stageAccess !== "ALLOWED") return;
5314
+ try {
5315
+ await meeting.stage?.requestAccess?.();
5316
+ } catch {
5317
+ }
5318
+ }
5260
5319
  async function runJoinStageAttempts() {
5261
5320
  let lastError;
5262
5321
  for (let attempt = 0; attempt < STAGE_JOIN_MAX_ATTEMPTS; attempt++) {
@@ -5265,6 +5324,11 @@ function studioMeetingFromRtk(raw) {
5265
5324
  return;
5266
5325
  }
5267
5326
  try {
5327
+ await acceptAllowedStageIfOffAir();
5328
+ if (currentStageStatus() === "ON_STAGE") {
5329
+ notifyStage();
5330
+ return;
5331
+ }
5268
5332
  await meeting.stage?.join?.();
5269
5333
  joinedStageLocally = true;
5270
5334
  await republishCameraIfOn();
@@ -5517,6 +5581,10 @@ function studioMeetingFromRtk(raw) {
5517
5581
  async setStageAccess(userId, on) {
5518
5582
  const target = findByUserId(meeting, userId);
5519
5583
  if (isRecorder(target)) return;
5584
+ if (on && meeting.self?.userId === userId && meeting.self?.permissions?.stageAccess === "ALLOWED") {
5585
+ await joinStageWithRetry();
5586
+ return;
5587
+ }
5520
5588
  if (on) await meeting.stage?.grantAccess?.([userId]);
5521
5589
  else await meeting.stage?.kick?.([userId]);
5522
5590
  notifyStage();
@@ -6494,6 +6562,7 @@ function studioRoomLabels(t) {
6494
6562
  unpinnedToast: t("unpinnedToast"),
6495
6563
  pinError: t("pinError"),
6496
6564
  kickTitle: t("kickTitle"),
6565
+ kickTitleNamed: t("kickTitleNamed", { name: "{name}" }),
6497
6566
  kickDescription: t("kickDescription"),
6498
6567
  kickConfirm: t("kickConfirm"),
6499
6568
  kickError: t("kickError"),