@xipkg/calls-compactview 0.1.55 → 0.1.57
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/index.d.ts +13 -2
- package/dist/index.mjs +376 -172
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -10
package/dist/index.mjs
CHANGED
|
@@ -15,7 +15,7 @@ import { Button } from '@xipkg/button';
|
|
|
15
15
|
import { ArrowLeft, ArrowRight, Account, SoundTwo, Users, External, ChevronUp, WhiteBoard, Maximize, MicrophoneOff, RedLine, ChevronBottom, ArrowUp } from '@xipkg/icons';
|
|
16
16
|
import { cn } from '@xipkg/utils';
|
|
17
17
|
import { useTranslation } from 'react-i18next';
|
|
18
|
-
import { ParticipantTile, DevicesBar, LessonRecordButton, ScreenShareButton, DisconnectButton, ScreenShareStageToggle, ParticipantPinToggle, tileOverlayButtonClassName, PermissionsDialog, TrackMutedIndicator, ParticipantName, RaisedHandIndicator,
|
|
18
|
+
import { ParticipantTile, DevicesBar, LessonRecordButton, ScreenShareButton, DisconnectButton, ScreenShareStageToggle, ParticipantPinToggle, tileOverlayButtonClassName, PermissionsDialog, TrackMutedIndicator, ParticipantName, RaisedHandIndicator, VideoTrack, ScreenShareZoom } from '@xipkg/calls-ui';
|
|
19
19
|
import { Tooltip, TooltipTrigger, TooltipContent } from '@xipkg/tooltip';
|
|
20
20
|
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLabel, DropdownMenuItem } from '@xipkg/dropdown';
|
|
21
21
|
import { useChatStore, Chat, ChatButton } from '@xipkg/calls-chat';
|
|
@@ -631,50 +631,70 @@ function CompactNavigationControls({
|
|
|
631
631
|
onPrev,
|
|
632
632
|
onNext,
|
|
633
633
|
currentIndex,
|
|
634
|
-
totalParticipants
|
|
634
|
+
totalParticipants,
|
|
635
|
+
persistent = false
|
|
635
636
|
}) {
|
|
636
637
|
const { t } = useTranslation("calls");
|
|
638
|
+
const hoverOnly = persistent ? "" : "sm:opacity-0 sm:group-hover:opacity-100";
|
|
637
639
|
if (totalParticipants <= 1) {
|
|
638
640
|
return null;
|
|
639
641
|
}
|
|
640
642
|
return /* @__PURE__ */ jsxs("div", { className: "pointer-events-none absolute inset-0", children: [
|
|
641
|
-
/* @__PURE__ */ jsx("div", { className: "pointer-events-auto absolute top-2 left-1/2 -translate-x-1/2", children: /* @__PURE__ */ jsx(
|
|
642
|
-
"
|
|
643
|
-
{
|
|
644
|
-
type: "button",
|
|
645
|
-
onClick: () => {
|
|
646
|
-
},
|
|
647
|
-
className: `h-1.5 w-1.5 rounded-full transition-colors ${index === currentIndex ? "bg-text-primary" : "bg-text-primary/40 hover:bg-text-primary/70"}`,
|
|
648
|
-
"aria-label": t("compactView.participant", { index: index + 1 })
|
|
649
|
-
},
|
|
650
|
-
index
|
|
651
|
-
)) }) }),
|
|
652
|
-
/* @__PURE__ */ jsx("div", { className: "pointer-events-auto absolute top-1/2 left-2 -translate-y-1/2 transition-opacity duration-200 sm:opacity-0 sm:group-hover:opacity-100", children: /* @__PURE__ */ jsxs(
|
|
653
|
-
"button",
|
|
643
|
+
/* @__PURE__ */ jsx("div", { className: "pointer-events-auto absolute top-2 left-1/2 -translate-x-1/2", children: /* @__PURE__ */ jsx(
|
|
644
|
+
"div",
|
|
654
645
|
{
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
646
|
+
className: `bg-background-subtle/80 flex gap-1 rounded-full px-2 py-1 backdrop-blur-sm transition-opacity duration-200 ${hoverOnly}`,
|
|
647
|
+
children: Array.from({ length: totalParticipants }, (_, index) => /* @__PURE__ */ jsx(
|
|
648
|
+
"button",
|
|
649
|
+
{
|
|
650
|
+
type: "button",
|
|
651
|
+
onClick: () => {
|
|
652
|
+
},
|
|
653
|
+
className: `h-1.5 w-1.5 rounded-full transition-colors ${index === currentIndex ? "bg-text-primary" : "bg-text-primary/40 hover:bg-text-primary/70"}`,
|
|
654
|
+
"aria-label": t("compactView.participant", { index: index + 1 })
|
|
655
|
+
},
|
|
656
|
+
index
|
|
657
|
+
))
|
|
663
658
|
}
|
|
664
659
|
) }),
|
|
665
|
-
/* @__PURE__ */ jsx(
|
|
666
|
-
"
|
|
660
|
+
/* @__PURE__ */ jsx(
|
|
661
|
+
"div",
|
|
667
662
|
{
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
663
|
+
className: `pointer-events-auto absolute top-1/2 left-2 -translate-y-1/2 transition-opacity duration-200 ${hoverOnly}`,
|
|
664
|
+
children: /* @__PURE__ */ jsxs(
|
|
665
|
+
"button",
|
|
666
|
+
{
|
|
667
|
+
type: "button",
|
|
668
|
+
disabled: !canPrev,
|
|
669
|
+
onClick: onPrev,
|
|
670
|
+
className: "bg-background-subtle/80 hover:bg-background-subtle fill-icon-primary z-10 flex items-center justify-center rounded-full p-2 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50",
|
|
671
|
+
children: [
|
|
672
|
+
/* @__PURE__ */ jsx(ArrowLeft, { className: "h-4 w-4" }),
|
|
673
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: t("compactView.prevParticipant") })
|
|
674
|
+
]
|
|
675
|
+
}
|
|
676
|
+
)
|
|
676
677
|
}
|
|
677
|
-
)
|
|
678
|
+
),
|
|
679
|
+
/* @__PURE__ */ jsx(
|
|
680
|
+
"div",
|
|
681
|
+
{
|
|
682
|
+
className: `pointer-events-auto absolute top-1/2 right-2 -translate-y-1/2 transition-opacity duration-200 ${hoverOnly}`,
|
|
683
|
+
children: /* @__PURE__ */ jsxs(
|
|
684
|
+
"button",
|
|
685
|
+
{
|
|
686
|
+
type: "button",
|
|
687
|
+
disabled: !canNext,
|
|
688
|
+
onClick: onNext,
|
|
689
|
+
className: "bg-background-subtle/80 hover:bg-background-subtle fill-icon-primary z-10 flex items-center justify-center rounded-full p-2 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50",
|
|
690
|
+
children: [
|
|
691
|
+
/* @__PURE__ */ jsx(ArrowRight, { className: "h-4 w-4" }),
|
|
692
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: t("compactView.nextParticipant") })
|
|
693
|
+
]
|
|
694
|
+
}
|
|
695
|
+
)
|
|
696
|
+
}
|
|
697
|
+
)
|
|
678
698
|
] });
|
|
679
699
|
}
|
|
680
700
|
function CompactMultiViewControls({
|
|
@@ -729,7 +749,9 @@ function CompactCallVideoArea({
|
|
|
729
749
|
multiCanNext,
|
|
730
750
|
onMultiPrev,
|
|
731
751
|
onMultiNext,
|
|
732
|
-
onAudioExpand
|
|
752
|
+
onAudioExpand,
|
|
753
|
+
tileWidth,
|
|
754
|
+
tileHeight
|
|
733
755
|
}) {
|
|
734
756
|
const { t } = useTranslation("calls");
|
|
735
757
|
const pip = usePiP();
|
|
@@ -775,9 +797,9 @@ function CompactCallVideoArea({
|
|
|
775
797
|
!isMobile && compactViewMode === "expanded" && "h-auto"
|
|
776
798
|
),
|
|
777
799
|
style: isMobile ? void 0 : {
|
|
778
|
-
width: COMPACT_PANEL_WIDTH_PX,
|
|
800
|
+
width: tileWidth != null ? "100%" : COMPACT_PANEL_WIDTH_PX,
|
|
779
801
|
touchAction: "none",
|
|
780
|
-
...compactViewMode === "basic" ? { height: TILE_HEIGHT_16_9_PX } : {}
|
|
802
|
+
...compactViewMode === "basic" ? { height: tileHeight ?? TILE_HEIGHT_16_9_PX } : {}
|
|
781
803
|
},
|
|
782
804
|
children: [
|
|
783
805
|
isMobile ? currentParticipant ? /* @__PURE__ */ jsx("div", { className: "relative h-full min-h-0 w-full min-w-0", children: /* @__PURE__ */ jsx(
|
|
@@ -867,7 +889,8 @@ function CompactCallVideoArea({
|
|
|
867
889
|
onPrev,
|
|
868
890
|
onNext,
|
|
869
891
|
currentIndex,
|
|
870
|
-
totalParticipants
|
|
892
|
+
totalParticipants,
|
|
893
|
+
persistent: tileHeight != null
|
|
871
894
|
}
|
|
872
895
|
)
|
|
873
896
|
]
|
|
@@ -883,7 +906,8 @@ function CompactCallBottomBar({
|
|
|
883
906
|
showBackToBoardButton,
|
|
884
907
|
onBackToBoard,
|
|
885
908
|
onMaximize,
|
|
886
|
-
isTutor
|
|
909
|
+
isTutor,
|
|
910
|
+
stageCompact = false
|
|
887
911
|
}) {
|
|
888
912
|
const { t } = useTranslation("calls");
|
|
889
913
|
const screenShareStage = useCallStore((state) => state.screenShareStageIdentity);
|
|
@@ -898,109 +922,120 @@ function CompactCallBottomBar({
|
|
|
898
922
|
"bg-background-surface border-border-default flex items-center justify-center rounded-2xl border p-1",
|
|
899
923
|
withOutShadows ? "" : "shadow-lg"
|
|
900
924
|
);
|
|
901
|
-
return /* @__PURE__ */ jsxs(
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
children: /* @__PURE__ */ jsx(ViewModeIcon, { className: "h-6 w-6" })
|
|
924
|
-
}
|
|
925
|
-
) }),
|
|
926
|
-
/* @__PURE__ */ jsx(TooltipContent, { children: viewModeToggleMeta.label })
|
|
927
|
-
] }) }),
|
|
928
|
-
showBackToBoardButton && /* @__PURE__ */ jsx("div", { className: cn(barCn, "ml-1"), children: /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
929
|
-
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
930
|
-
Button,
|
|
931
|
-
{
|
|
932
|
-
size: "icon",
|
|
933
|
-
variant: "primary",
|
|
934
|
-
className: "h-8 w-8 rounded-xl p-0",
|
|
935
|
-
onClick: onBackToBoard,
|
|
936
|
-
"aria-label": t("compactView.toBoardAria"),
|
|
937
|
-
children: /* @__PURE__ */ jsx(WhiteBoard, { className: "fill-action-primary-text h-6 w-6" })
|
|
938
|
-
}
|
|
939
|
-
) }),
|
|
940
|
-
/* @__PURE__ */ jsx(TooltipContent, { children: t("compactView.toBoardTooltip") })
|
|
941
|
-
] }) }),
|
|
942
|
-
/* @__PURE__ */ jsxs("div", { className: cn(barCn, "ml-auto"), children: [
|
|
943
|
-
/* @__PURE__ */ jsx(LessonRecordButton, { className: "h-8 w-8" }),
|
|
944
|
-
/* @__PURE__ */ jsx(ScreenShareButton, { className: "h-8 w-8" }),
|
|
945
|
-
/* @__PURE__ */ jsx(ChatButton, { className: "h-8 w-8 min-w-8 rounded-xl" }),
|
|
946
|
-
/* @__PURE__ */ jsx(RaiseHandButton, { className: "h-8 w-8 min-w-8" })
|
|
947
|
-
] }),
|
|
948
|
-
/* @__PURE__ */ jsxs("div", { className: cn(barCn, "ml-1"), children: [
|
|
949
|
-
!screenShareStage && (isTutor ? /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
950
|
-
/* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
951
|
-
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
925
|
+
return /* @__PURE__ */ jsxs(
|
|
926
|
+
"div",
|
|
927
|
+
{
|
|
928
|
+
className: cn(
|
|
929
|
+
"flex h-10 shrink-0 flex-row",
|
|
930
|
+
stageCompact ? "max-w-full [scrollbar-width:none] overflow-x-auto [&::-webkit-scrollbar]:hidden [&>*]:shrink-0" : "pb-[max(0px,env(safe-area-inset-bottom))]"
|
|
931
|
+
),
|
|
932
|
+
children: [
|
|
933
|
+
/* @__PURE__ */ jsx("div", { className: barCn, children: /* @__PURE__ */ jsx(
|
|
934
|
+
DevicesBar,
|
|
935
|
+
{
|
|
936
|
+
className: "h-[32px] w-[32px]",
|
|
937
|
+
microTrack: devices.microTrack,
|
|
938
|
+
microEnabled: devices.microEnabled,
|
|
939
|
+
microTrackToggle: devices.microTrackToggle,
|
|
940
|
+
videoTrack: devices.videoTrack,
|
|
941
|
+
videoEnabled: devices.videoEnabled,
|
|
942
|
+
videoTrackToggle: devices.videoTrackToggle
|
|
943
|
+
}
|
|
944
|
+
) }),
|
|
945
|
+
!isMobile && /* @__PURE__ */ jsx("div", { className: cn(barCn, "ml-1"), children: /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
946
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
952
947
|
Button,
|
|
953
948
|
{
|
|
954
949
|
size: "icon",
|
|
955
950
|
variant: "none",
|
|
956
|
-
|
|
957
|
-
|
|
951
|
+
onClick: onViewModeToggle,
|
|
952
|
+
className: "hover:bg-background-page text-text-primary h-8 w-8 rounded-xl p-0",
|
|
953
|
+
"aria-label": viewModeToggleMeta.label,
|
|
954
|
+
children: /* @__PURE__ */ jsx(ViewModeIcon, { className: "h-6 w-6" })
|
|
958
955
|
}
|
|
959
|
-
) })
|
|
960
|
-
/* @__PURE__ */ jsx(TooltipContent, { children:
|
|
961
|
-
] }),
|
|
962
|
-
/* @__PURE__ */
|
|
963
|
-
/* @__PURE__ */ jsx(
|
|
964
|
-
|
|
965
|
-
DropdownMenuItem,
|
|
966
|
-
{
|
|
967
|
-
onClick: () => onMaximize(false),
|
|
968
|
-
className: "text-text-primary cursor-pointer text-sm",
|
|
969
|
-
children: t("compactView.returnOnlyMe")
|
|
970
|
-
}
|
|
971
|
-
),
|
|
972
|
-
/* @__PURE__ */ jsx(
|
|
973
|
-
DropdownMenuItem,
|
|
956
|
+
) }),
|
|
957
|
+
/* @__PURE__ */ jsx(TooltipContent, { children: viewModeToggleMeta.label })
|
|
958
|
+
] }) }),
|
|
959
|
+
showBackToBoardButton && /* @__PURE__ */ jsx("div", { className: cn(barCn, "ml-1"), children: /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
960
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
961
|
+
Button,
|
|
974
962
|
{
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
963
|
+
size: "icon",
|
|
964
|
+
variant: "primary",
|
|
965
|
+
className: "h-8 w-8 rounded-xl p-0",
|
|
966
|
+
onClick: onBackToBoard,
|
|
967
|
+
"aria-label": t("compactView.toBoardAria"),
|
|
968
|
+
children: /* @__PURE__ */ jsx(WhiteBoard, { className: "fill-action-primary-text h-6 w-6" })
|
|
978
969
|
}
|
|
979
|
-
)
|
|
970
|
+
) }),
|
|
971
|
+
/* @__PURE__ */ jsx(TooltipContent, { children: t("compactView.toBoardTooltip") })
|
|
972
|
+
] }) }),
|
|
973
|
+
/* @__PURE__ */ jsxs("div", { className: cn(barCn, "ml-auto"), children: [
|
|
974
|
+
/* @__PURE__ */ jsx(LessonRecordButton, { className: "h-8 w-8" }),
|
|
975
|
+
/* @__PURE__ */ jsx(ScreenShareButton, { className: "h-8 w-8" }),
|
|
976
|
+
/* @__PURE__ */ jsx(ChatButton, { className: "h-8 w-8 min-w-8 rounded-xl" }),
|
|
977
|
+
/* @__PURE__ */ jsx(RaiseHandButton, { className: "h-8 w-8 min-w-8" })
|
|
978
|
+
] }),
|
|
979
|
+
/* @__PURE__ */ jsxs("div", { className: cn(barCn, "ml-1"), children: [
|
|
980
|
+
!screenShareStage && (isTutor ? /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
981
|
+
/* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
982
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
983
|
+
Button,
|
|
984
|
+
{
|
|
985
|
+
size: "icon",
|
|
986
|
+
variant: "none",
|
|
987
|
+
className: "hover:bg-background-page text-text-primary relative m-0 h-8 w-8 rounded-xl p-0",
|
|
988
|
+
children: /* @__PURE__ */ jsx(Maximize, { className: "fill-icon-primary" })
|
|
989
|
+
}
|
|
990
|
+
) }) }),
|
|
991
|
+
/* @__PURE__ */ jsx(TooltipContent, { children: t("compactView.returnToConference") })
|
|
992
|
+
] }),
|
|
993
|
+
/* @__PURE__ */ jsxs(DropdownMenuContent, { side: "top", align: "end", className: "z-1000 min-w-[200px]", children: [
|
|
994
|
+
/* @__PURE__ */ jsx(DropdownMenuLabel, { className: "text-text-secondary text-sm", children: t("compactView.returnMenuLabel") }),
|
|
995
|
+
/* @__PURE__ */ jsx(
|
|
996
|
+
DropdownMenuItem,
|
|
997
|
+
{
|
|
998
|
+
onClick: () => onMaximize(false),
|
|
999
|
+
className: "text-text-primary cursor-pointer text-sm",
|
|
1000
|
+
children: t("compactView.returnOnlyMe")
|
|
1001
|
+
}
|
|
1002
|
+
),
|
|
1003
|
+
/* @__PURE__ */ jsx(
|
|
1004
|
+
DropdownMenuItem,
|
|
1005
|
+
{
|
|
1006
|
+
onClick: () => onMaximize(true),
|
|
1007
|
+
className: "text-text-primary cursor-pointer text-sm",
|
|
1008
|
+
children: t("compactView.returnEveryone")
|
|
1009
|
+
}
|
|
1010
|
+
)
|
|
1011
|
+
] })
|
|
1012
|
+
] }) : /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
1013
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
1014
|
+
Button,
|
|
1015
|
+
{
|
|
1016
|
+
size: "icon",
|
|
1017
|
+
variant: "none",
|
|
1018
|
+
onClick: () => onMaximize(false),
|
|
1019
|
+
className: "hover:bg-background-page text-text-primary relative m-0 h-8 w-8 rounded-xl p-0",
|
|
1020
|
+
children: /* @__PURE__ */ jsx(Maximize, { className: "fill-icon-primary" })
|
|
1021
|
+
}
|
|
1022
|
+
) }),
|
|
1023
|
+
/* @__PURE__ */ jsx(TooltipContent, { children: t("compactView.returnToConference") })
|
|
1024
|
+
] })),
|
|
1025
|
+
/* @__PURE__ */ jsx(DisconnectButton, { className: "h-[32px] w-[32px] rounded-xl" })
|
|
980
1026
|
] })
|
|
981
|
-
]
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
{
|
|
985
|
-
size: "icon",
|
|
986
|
-
variant: "none",
|
|
987
|
-
onClick: () => onMaximize(false),
|
|
988
|
-
className: "hover:bg-background-page text-text-primary relative m-0 h-8 w-8 rounded-xl p-0",
|
|
989
|
-
children: /* @__PURE__ */ jsx(Maximize, { className: "fill-icon-primary" })
|
|
990
|
-
}
|
|
991
|
-
) }),
|
|
992
|
-
/* @__PURE__ */ jsx(TooltipContent, { children: t("compactView.returnToConference") })
|
|
993
|
-
] })),
|
|
994
|
-
/* @__PURE__ */ jsx(DisconnectButton, { className: "h-[32px] w-[32px] rounded-xl" })
|
|
995
|
-
] })
|
|
996
|
-
] });
|
|
1027
|
+
]
|
|
1028
|
+
}
|
|
1029
|
+
);
|
|
997
1030
|
}
|
|
998
1031
|
var CompactCall = ({
|
|
999
1032
|
saveUserChoices = true,
|
|
1000
1033
|
withOutShadows = false,
|
|
1001
|
-
freeDrag = false
|
|
1034
|
+
freeDrag = false,
|
|
1035
|
+
stageFrame = null
|
|
1002
1036
|
}) => {
|
|
1003
1037
|
const isMobile = usePhoneLayout();
|
|
1038
|
+
const lockCompactModes = stageFrame?.lockCompactModes === true;
|
|
1004
1039
|
const { attributes, listeners, setNodeRef, transform } = useDraggable({
|
|
1005
1040
|
id: freeDrag ? "screen-share-stage-compact" : "draggable-call",
|
|
1006
1041
|
disabled: freeDrag ? false : isMobile
|
|
@@ -1141,20 +1176,26 @@ var CompactCall = ({
|
|
|
1141
1176
|
...freeDrag ? listeners : {},
|
|
1142
1177
|
style: {
|
|
1143
1178
|
...style,
|
|
1144
|
-
...isMobile && !freeDrag ? {} : {
|
|
1179
|
+
...isMobile && !freeDrag ? {} : {
|
|
1180
|
+
width: stageFrame?.width ?? COMPACT_PANEL_WIDTH_PX,
|
|
1181
|
+
touchAction: "none",
|
|
1182
|
+
maxWidth: "100%"
|
|
1183
|
+
}
|
|
1145
1184
|
},
|
|
1146
1185
|
className: `compact-call-container flex flex-col ${isMobile && !freeDrag ? "w-full" : "touch-none [&_video]:touch-none"} ${freeDrag ? "cursor-grab active:cursor-grabbing" : ""}`,
|
|
1147
1186
|
children: [
|
|
1148
1187
|
/* @__PURE__ */ jsx(
|
|
1149
1188
|
CompactCallVideoArea,
|
|
1150
1189
|
{
|
|
1151
|
-
isMobile,
|
|
1152
1190
|
isCollapsed,
|
|
1153
1191
|
onCollapsedChange: setIsCollapsed,
|
|
1154
1192
|
withOutShadows,
|
|
1155
1193
|
dragAttributes: freeDrag ? void 0 : attributes,
|
|
1156
1194
|
dragListeners: freeDrag ? void 0 : listeners,
|
|
1157
|
-
compactViewMode,
|
|
1195
|
+
compactViewMode: lockCompactModes ? "basic" : compactViewMode,
|
|
1196
|
+
tileWidth: stageFrame?.width,
|
|
1197
|
+
tileHeight: stageFrame?.tileHeight,
|
|
1198
|
+
isMobile: stageFrame ? false : isMobile,
|
|
1158
1199
|
currentParticipant,
|
|
1159
1200
|
currentAudioTrack: currentAudioTrack ?? null,
|
|
1160
1201
|
totalParticipants,
|
|
@@ -1194,7 +1235,8 @@ var CompactCall = ({
|
|
|
1194
1235
|
deviceGroups: cameraGroups
|
|
1195
1236
|
}
|
|
1196
1237
|
},
|
|
1197
|
-
isMobile,
|
|
1238
|
+
isMobile: lockCompactModes || isMobile && stageFrame == null,
|
|
1239
|
+
stageCompact: lockCompactModes,
|
|
1198
1240
|
compactViewMode,
|
|
1199
1241
|
onViewModeToggle: () => setCompactViewMode(getNextCompactViewMode(compactViewMode)),
|
|
1200
1242
|
showBackToBoardButton: !!showBackToBoardButton,
|
|
@@ -1207,23 +1249,115 @@ var CompactCall = ({
|
|
|
1207
1249
|
}
|
|
1208
1250
|
);
|
|
1209
1251
|
};
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1252
|
+
|
|
1253
|
+
// src/ui/stageLayout.ts
|
|
1254
|
+
var EDGE_PX2 = 12;
|
|
1255
|
+
var CONTROLS_PX = 48;
|
|
1256
|
+
var EMPTY_INSETS = { top: 0, right: 0, bottom: 0, left: 0 };
|
|
1257
|
+
function viewportBox() {
|
|
1258
|
+
const viewport = window.visualViewport;
|
|
1215
1259
|
return {
|
|
1216
|
-
|
|
1217
|
-
|
|
1260
|
+
width: viewport?.width ?? window.innerWidth,
|
|
1261
|
+
height: viewport?.height ?? window.innerHeight,
|
|
1262
|
+
offsetLeft: viewport?.offsetLeft ?? 0,
|
|
1263
|
+
offsetTop: viewport?.offsetTop ?? 0
|
|
1218
1264
|
};
|
|
1219
1265
|
}
|
|
1266
|
+
function readSafeInsets() {
|
|
1267
|
+
if (typeof document === "undefined") return EMPTY_INSETS;
|
|
1268
|
+
const probe = document.createElement("div");
|
|
1269
|
+
probe.style.cssText = "position:fixed;visibility:hidden;pointer-events:none;padding:env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left)";
|
|
1270
|
+
document.body.appendChild(probe);
|
|
1271
|
+
const style = getComputedStyle(probe);
|
|
1272
|
+
const insets = {
|
|
1273
|
+
top: Number.parseFloat(style.paddingTop) || 0,
|
|
1274
|
+
right: Number.parseFloat(style.paddingRight) || 0,
|
|
1275
|
+
bottom: Number.parseFloat(style.paddingBottom) || 0,
|
|
1276
|
+
left: Number.parseFloat(style.paddingLeft) || 0
|
|
1277
|
+
};
|
|
1278
|
+
probe.remove();
|
|
1279
|
+
return insets;
|
|
1280
|
+
}
|
|
1281
|
+
function computeStageFrame() {
|
|
1282
|
+
const box = viewportBox();
|
|
1283
|
+
const insets = readSafeInsets();
|
|
1284
|
+
const landscape = box.width > box.height;
|
|
1285
|
+
const handheld = box.width <= 720 || box.height <= 500;
|
|
1286
|
+
if (!handheld) {
|
|
1287
|
+
const width2 = 400;
|
|
1288
|
+
return {
|
|
1289
|
+
handheld: false,
|
|
1290
|
+
landscape,
|
|
1291
|
+
lockCompactModes: false,
|
|
1292
|
+
width: width2,
|
|
1293
|
+
tileHeight: Math.round(width2 * 9 / 16),
|
|
1294
|
+
insets
|
|
1295
|
+
};
|
|
1296
|
+
}
|
|
1297
|
+
const maxWidth = Math.max(220, box.width - insets.left - insets.right - EDGE_PX2 * 2);
|
|
1298
|
+
const width = Math.min(400, maxWidth);
|
|
1299
|
+
const naturalTile = Math.round(width * 9 / 16);
|
|
1300
|
+
const maxPanel = box.height * 0.36;
|
|
1301
|
+
const tileHeight = landscape ? naturalTile : Math.max(84, Math.min(naturalTile, Math.floor(maxPanel - CONTROLS_PX)));
|
|
1302
|
+
return { handheld: true, landscape, lockCompactModes: !landscape, width, tileHeight, insets };
|
|
1303
|
+
}
|
|
1304
|
+
function sameStageFrame(left, right) {
|
|
1305
|
+
return left.handheld === right.handheld && left.landscape === right.landscape && left.lockCompactModes === right.lockCompactModes && left.width === right.width && left.tileHeight === right.tileHeight && left.insets.top === right.insets.top && left.insets.right === right.insets.right && left.insets.bottom === right.insets.bottom && left.insets.left === right.insets.left;
|
|
1306
|
+
}
|
|
1307
|
+
function clampStagePosition(x, y, width, height, insets) {
|
|
1308
|
+
const box = viewportBox();
|
|
1309
|
+
const minX = box.offsetLeft + insets.left + 8;
|
|
1310
|
+
const minY = box.offsetTop + insets.top + 8;
|
|
1311
|
+
const maxX = Math.max(minX, box.offsetLeft + box.width - insets.right - width - 8);
|
|
1312
|
+
const maxY = Math.max(minY, box.offsetTop + box.height - insets.bottom - height - 8);
|
|
1313
|
+
return {
|
|
1314
|
+
x: Math.min(Math.max(minX, x), maxX),
|
|
1315
|
+
y: Math.min(Math.max(minY, y), maxY)
|
|
1316
|
+
};
|
|
1317
|
+
}
|
|
1318
|
+
function defaultStagePosition(frame) {
|
|
1319
|
+
const box = viewportBox();
|
|
1320
|
+
const panelHeight = frame.tileHeight + CONTROLS_PX + 8;
|
|
1321
|
+
if (!frame.handheld) {
|
|
1322
|
+
return clampStagePosition(
|
|
1323
|
+
EDGE_PX2 + frame.insets.left,
|
|
1324
|
+
EDGE_PX2 + frame.insets.top,
|
|
1325
|
+
frame.width,
|
|
1326
|
+
panelHeight,
|
|
1327
|
+
frame.insets
|
|
1328
|
+
);
|
|
1329
|
+
}
|
|
1330
|
+
const y = box.offsetTop + box.height - frame.insets.bottom - EDGE_PX2 - panelHeight;
|
|
1331
|
+
const x = frame.landscape ? box.offsetLeft + frame.insets.left + EDGE_PX2 : box.offsetLeft + (box.width - frame.width) / 2;
|
|
1332
|
+
return clampStagePosition(x, y, frame.width, panelHeight, frame.insets);
|
|
1333
|
+
}
|
|
1334
|
+
function stagePanelHeight(frame) {
|
|
1335
|
+
return frame.tileHeight + CONTROLS_PX + 8;
|
|
1336
|
+
}
|
|
1337
|
+
var STAGE_GONE_MS = 500;
|
|
1338
|
+
function initialStageFrame() {
|
|
1339
|
+
if (typeof window === "undefined") {
|
|
1340
|
+
return {
|
|
1341
|
+
handheld: false,
|
|
1342
|
+
landscape: false,
|
|
1343
|
+
lockCompactModes: false,
|
|
1344
|
+
width: 400,
|
|
1345
|
+
tileHeight: 225,
|
|
1346
|
+
insets: { top: 0, right: 0, bottom: 0, left: 0 }
|
|
1347
|
+
};
|
|
1348
|
+
}
|
|
1349
|
+
return computeStageFrame();
|
|
1350
|
+
}
|
|
1220
1351
|
var ScreenShareStage = ({ identity }) => {
|
|
1221
1352
|
const { t } = useTranslation("calls");
|
|
1222
1353
|
const updateStore = useCallStore((state) => state.updateStore);
|
|
1223
1354
|
const closePiP = usePiP()?.closePiP;
|
|
1224
1355
|
const overlayRef = useRef(null);
|
|
1225
1356
|
const panelRef = useRef(null);
|
|
1226
|
-
const
|
|
1357
|
+
const movedRef = useRef(false);
|
|
1358
|
+
const landscapeRef = useRef(null);
|
|
1359
|
+
const [frame, setFrame] = useState(initialStageFrame);
|
|
1360
|
+
const [position, setPosition] = useState(() => defaultStagePosition(initialStageFrame()));
|
|
1227
1361
|
const tracks = useTracks([{ source: Track.Source.ScreenShare, withPlaceholder: false }], {
|
|
1228
1362
|
onlySubscribed: false
|
|
1229
1363
|
});
|
|
@@ -1284,34 +1418,58 @@ var ScreenShareStage = ({ identity }) => {
|
|
|
1284
1418
|
};
|
|
1285
1419
|
}, []);
|
|
1286
1420
|
useLayoutEffect(() => {
|
|
1287
|
-
const
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
const
|
|
1291
|
-
|
|
1421
|
+
const sync = () => {
|
|
1422
|
+
const next = computeStageFrame();
|
|
1423
|
+
setFrame((prev) => sameStageFrame(prev, next) ? prev : next);
|
|
1424
|
+
const flipped = landscapeRef.current !== null && landscapeRef.current !== next.landscape;
|
|
1425
|
+
landscapeRef.current = next.landscape;
|
|
1426
|
+
if (flipped) movedRef.current = false;
|
|
1292
1427
|
setPosition((prev) => {
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1428
|
+
if (!movedRef.current) {
|
|
1429
|
+
const placed = defaultStagePosition(next);
|
|
1430
|
+
if (placed.x === prev.x && placed.y === prev.y) return prev;
|
|
1431
|
+
return placed;
|
|
1432
|
+
}
|
|
1433
|
+
const node2 = panelRef.current;
|
|
1434
|
+
const clamped = clampStagePosition(
|
|
1435
|
+
prev.x,
|
|
1436
|
+
prev.y,
|
|
1437
|
+
node2?.offsetWidth ?? next.width,
|
|
1438
|
+
node2?.offsetHeight ?? stagePanelHeight(next),
|
|
1439
|
+
next.insets
|
|
1440
|
+
);
|
|
1441
|
+
if (clamped.x === prev.x && clamped.y === prev.y) return prev;
|
|
1442
|
+
return clamped;
|
|
1296
1443
|
});
|
|
1297
1444
|
};
|
|
1298
|
-
|
|
1299
|
-
const
|
|
1300
|
-
|
|
1301
|
-
window.addEventListener("
|
|
1445
|
+
sync();
|
|
1446
|
+
const viewport = window.visualViewport;
|
|
1447
|
+
window.addEventListener("resize", sync);
|
|
1448
|
+
window.addEventListener("orientationchange", sync);
|
|
1449
|
+
viewport?.addEventListener("resize", sync);
|
|
1450
|
+
viewport?.addEventListener("scroll", sync);
|
|
1451
|
+
const node = panelRef.current;
|
|
1452
|
+
const observer = new ResizeObserver(sync);
|
|
1453
|
+
if (node) observer.observe(node);
|
|
1302
1454
|
return () => {
|
|
1455
|
+
window.removeEventListener("resize", sync);
|
|
1456
|
+
window.removeEventListener("orientationchange", sync);
|
|
1457
|
+
viewport?.removeEventListener("resize", sync);
|
|
1458
|
+
viewport?.removeEventListener("scroll", sync);
|
|
1303
1459
|
observer.disconnect();
|
|
1304
|
-
window.removeEventListener("resize", clamp);
|
|
1305
1460
|
};
|
|
1306
1461
|
}, []);
|
|
1307
1462
|
const handleDragEnd = (event) => {
|
|
1463
|
+
movedRef.current = true;
|
|
1308
1464
|
const node = panelRef.current;
|
|
1465
|
+
const current = computeStageFrame();
|
|
1309
1466
|
setPosition((prev) => {
|
|
1310
1467
|
const next = clampStagePosition(
|
|
1311
1468
|
prev.x + event.delta.x,
|
|
1312
1469
|
prev.y + event.delta.y,
|
|
1313
|
-
node?.offsetWidth ??
|
|
1314
|
-
node?.offsetHeight ??
|
|
1470
|
+
node?.offsetWidth ?? current.width,
|
|
1471
|
+
node?.offsetHeight ?? stagePanelHeight(current),
|
|
1472
|
+
current.insets
|
|
1315
1473
|
);
|
|
1316
1474
|
if (next.x === prev.x && next.y === prev.y) return prev;
|
|
1317
1475
|
return next;
|
|
@@ -1331,7 +1489,14 @@ var ScreenShareStage = ({ identity }) => {
|
|
|
1331
1489
|
className: "screen-share-stage fixed inset-0 z-[2100] bg-black outline-none",
|
|
1332
1490
|
children: [
|
|
1333
1491
|
/* @__PURE__ */ jsxs("div", { className: "relative h-full w-full", children: [
|
|
1334
|
-
track && publication ? /* @__PURE__ */ jsx(
|
|
1492
|
+
track && publication ? frame.handheld ? /* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-black", children: /* @__PURE__ */ jsx(
|
|
1493
|
+
VideoTrack,
|
|
1494
|
+
{
|
|
1495
|
+
trackRef: track,
|
|
1496
|
+
manageSubscription: false,
|
|
1497
|
+
className: "h-full w-full bg-black object-contain"
|
|
1498
|
+
}
|
|
1499
|
+
) }) : /* @__PURE__ */ jsx(ScreenShareZoom, { trackRef: track, className: "rounded-none", children: /* @__PURE__ */ jsx(
|
|
1335
1500
|
VideoTrack,
|
|
1336
1501
|
{
|
|
1337
1502
|
trackRef: track,
|
|
@@ -1339,20 +1504,43 @@ var ScreenShareStage = ({ identity }) => {
|
|
|
1339
1504
|
className: "h-full w-full bg-black object-contain"
|
|
1340
1505
|
}
|
|
1341
1506
|
) }) : null,
|
|
1342
|
-
track ? /* @__PURE__ */ jsxs(
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
"
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1507
|
+
track ? /* @__PURE__ */ jsxs(
|
|
1508
|
+
"div",
|
|
1509
|
+
{
|
|
1510
|
+
className: "bg-background-surface/80 pointer-events-none absolute z-20 flex h-6 max-w-[calc(100%-96px)] items-center gap-1.5 rounded-lg px-1.5 py-1 backdrop-blur",
|
|
1511
|
+
style: frame.handheld ? {
|
|
1512
|
+
top: "max(12px, env(safe-area-inset-top))",
|
|
1513
|
+
left: "max(12px, env(safe-area-inset-left))"
|
|
1514
|
+
} : {
|
|
1515
|
+
bottom: "max(16px, env(safe-area-inset-bottom))",
|
|
1516
|
+
left: "max(16px, env(safe-area-inset-left))"
|
|
1517
|
+
},
|
|
1518
|
+
children: [
|
|
1519
|
+
/* @__PURE__ */ jsx(ScreenShareIcon, { style: { marginRight: "0.25rem" } }),
|
|
1520
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs-base-size text-text-primary truncate leading-[16px]", children: [
|
|
1521
|
+
t("participant.screenSharePrefix"),
|
|
1522
|
+
sharerName ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1523
|
+
"\xA0",
|
|
1524
|
+
sharerName
|
|
1525
|
+
] }) : null
|
|
1526
|
+
] })
|
|
1527
|
+
]
|
|
1528
|
+
}
|
|
1529
|
+
) : null,
|
|
1530
|
+
/* @__PURE__ */ jsxs(
|
|
1531
|
+
"div",
|
|
1532
|
+
{
|
|
1533
|
+
className: "absolute z-40 flex items-center gap-1",
|
|
1534
|
+
style: {
|
|
1535
|
+
top: "max(12px, env(safe-area-inset-top))",
|
|
1536
|
+
right: "max(12px, env(safe-area-inset-right))"
|
|
1537
|
+
},
|
|
1538
|
+
children: [
|
|
1539
|
+
/* @__PURE__ */ jsx(ScreenShareStageToggle, { trackRef: track ?? void 0, inline: true }),
|
|
1540
|
+
track ? /* @__PURE__ */ jsx(ParticipantPinToggle, { trackRef: track, inline: true }) : null
|
|
1541
|
+
]
|
|
1542
|
+
}
|
|
1543
|
+
)
|
|
1356
1544
|
] }),
|
|
1357
1545
|
/* @__PURE__ */ jsx(
|
|
1358
1546
|
DndContext,
|
|
@@ -1367,12 +1555,28 @@ var ScreenShareStage = ({ identity }) => {
|
|
|
1367
1555
|
ref: panelRef,
|
|
1368
1556
|
className: "absolute z-30 w-max",
|
|
1369
1557
|
style: { left: position.x, top: position.y },
|
|
1370
|
-
children: /* @__PURE__ */ jsx(
|
|
1558
|
+
children: /* @__PURE__ */ jsx(
|
|
1559
|
+
CompactCall,
|
|
1560
|
+
{
|
|
1561
|
+
freeDrag: true,
|
|
1562
|
+
stageFrame: frame.handheld ? {
|
|
1563
|
+
width: frame.width,
|
|
1564
|
+
tileHeight: frame.tileHeight,
|
|
1565
|
+
lockCompactModes: frame.lockCompactModes
|
|
1566
|
+
} : null
|
|
1567
|
+
}
|
|
1568
|
+
)
|
|
1371
1569
|
}
|
|
1372
1570
|
)
|
|
1373
1571
|
}
|
|
1374
1572
|
),
|
|
1375
|
-
/* @__PURE__ */ jsx(
|
|
1573
|
+
/* @__PURE__ */ jsx(
|
|
1574
|
+
Chat,
|
|
1575
|
+
{
|
|
1576
|
+
forceSheet: frame.handheld,
|
|
1577
|
+
compactPositionStyle: frame.handheld ? void 0 : { top: 56, right: 16, bottom: 16, zIndex: 20 }
|
|
1578
|
+
}
|
|
1579
|
+
)
|
|
1376
1580
|
]
|
|
1377
1581
|
}
|
|
1378
1582
|
),
|