@xipkg/calls 0.0.0 → 0.0.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.
- package/dist/index.mjs +51 -73
- package/dist/index.mjs.map +1 -1
- package/package.json +13 -13
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useEffect, useRef, useCallback, useState, useMemo } from 'react';
|
|
2
|
-
import { useCallsNavigation, useRoom, useCalls } from '@xipkg/calls-providers';
|
|
3
|
-
import { useInitUserDevices, useVideoSecurity, useParticipantJoinSync, useVideoBlur, usePersistentUserChoices, useResolveInitiallyDefaultDeviceId, useCannotUseDevice } from '@xipkg/calls-hooks';
|
|
4
|
-
import { useCallStore, useFocusModeStore,
|
|
2
|
+
import { useCallsNavigation, useCallsRuntimeConfig, useRoom, useCalls } from '@xipkg/calls-providers';
|
|
3
|
+
import { useInitUserDevices, useVideoSecurity, useParticipantJoinSync, useParticipantSounds, useVideoBlur, usePersistentUserChoices, useResolveInitiallyDefaultDeviceId, useNoiseCancellation, useCannotUseDevice } from '@xipkg/calls-hooks';
|
|
4
|
+
import { useCallStore, useFocusModeStore, usePermissionsStore, openPermissionsDialog } from '@xipkg/calls-store';
|
|
5
5
|
import { ScrollArea } from '@xipkg/scrollarea';
|
|
6
6
|
import { Button } from '@xipkg/button';
|
|
7
7
|
import { WhiteBoard, ArrowLeft, InfoCircle, Settings, Conference, SoundTwo, Microphone } from '@xipkg/icons';
|
|
@@ -9,15 +9,16 @@ import { Tooltip, TooltipTrigger, TooltipContent } from '@xipkg/tooltip';
|
|
|
9
9
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
10
10
|
import { Avatar, AvatarImage, AvatarFallback } from '@xipkg/avatar';
|
|
11
11
|
import { Track, createLocalVideoTrack, createLocalAudioTrack, facingModeFromLocalTrack } from 'livekit-client';
|
|
12
|
-
import { CallsOnboarding, UpBar, VideoGrid,
|
|
12
|
+
import { CallsOnboarding, UpBar, VideoGrid, DevicesBar, ScreenShareButton, WhiteBoardButton, DisconnectButton, NoiseCancellationSettings, SecureVideo } from '@xipkg/calls-ui';
|
|
13
13
|
import { isSafari } from '@xipkg/calls-utils';
|
|
14
|
-
import {
|
|
14
|
+
import { Toggle } from '@xipkg/toggle';
|
|
15
15
|
import { Label } from '@xipkg/label';
|
|
16
16
|
import { Alert, AlertIcon, AlertContainer, AlertDescription } from '@xipkg/alert';
|
|
17
17
|
import { computeMenuPosition, wasClickOutside } from '@livekit/components-core';
|
|
18
18
|
import { Select, SelectTrigger, SelectValue, SelectContent, SelectGroup, SelectItem } from '@xipkg/select';
|
|
19
19
|
import { useLocalParticipant, usePreviewTracks, usePersistentUserChoices as usePersistentUserChoices$1, useTrackToggle, useMediaDeviceSelect } from '@livekit/components-react';
|
|
20
20
|
import { supportsBackgroundProcessors } from '@livekit/track-processors';
|
|
21
|
+
import { getBaselineAudioCaptureOptions } from '@xipkg/calls-config';
|
|
21
22
|
import { Chat, useChatStore, ChatButton } from '@xipkg/calls-chat';
|
|
22
23
|
import { useHandFocus, RaiseHandButton } from '@xipkg/calls-risehand';
|
|
23
24
|
import { cn } from '@xipkg/utils';
|
|
@@ -111,7 +112,7 @@ var Controls = ({ audioTrack, videoTrack }) => {
|
|
|
111
112
|
}),
|
|
112
113
|
[handleVideoChange]
|
|
113
114
|
);
|
|
114
|
-
return /* @__PURE__ */ jsx("div", { className: "bg-gray-0 border-gray-10 flex h-
|
|
115
|
+
return /* @__PURE__ */ jsx("div", { className: "bg-gray-0 border-gray-10 flex h-[48px] w-[92px] items-center justify-center gap-1 rounded-[16px] border", children: /* @__PURE__ */ jsx(
|
|
115
116
|
DevicesBar,
|
|
116
117
|
{
|
|
117
118
|
microTrack: audioTrack,
|
|
@@ -327,7 +328,7 @@ var UserTile = ({ audioTrack, videoTrack }) => {
|
|
|
327
328
|
}
|
|
328
329
|
);
|
|
329
330
|
};
|
|
330
|
-
var MediaDeviceSelect = ({ devices }) => /* @__PURE__ */ jsx("ul", { children: devices && devices.map((device) => /* @__PURE__ */ jsx("li", { id: device.deviceId, children: /* @__PURE__ */ jsx(SelectItem, { value: device.deviceId ?? "default", children: device.label }) }, device.deviceId)) });
|
|
331
|
+
var MediaDeviceSelect = ({ devices }) => /* @__PURE__ */ jsx("ul", { children: devices && devices.map((device) => /* @__PURE__ */ jsx("li", { id: device.deviceId, children: /* @__PURE__ */ jsx(SelectItem, { className: "h-auto", value: device.deviceId ?? "default", children: device.label }) }, device.deviceId)) });
|
|
331
332
|
var placeholders = {
|
|
332
333
|
audioinput: "\u0412\u0441\u0442\u0440\u043E\u0435\u043D\u043D\u044B\u0439 \u043C\u0438\u043A\u0440\u043E\u0444\u043E\u043D",
|
|
333
334
|
audiooutput: "\u0412\u0441\u0442\u0440\u043E\u0435\u043D\u043D\u044B\u0435 \u0434\u0438\u043D\u0430\u043C\u0438\u043A\u0438",
|
|
@@ -525,7 +526,7 @@ var MediaDevices = ({ audioTrack, videoTrack, noiseCancellation }) => {
|
|
|
525
526
|
[videoTrack, saveVideoInputDeviceId, saveVideoInputEnabled]
|
|
526
527
|
);
|
|
527
528
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
528
|
-
/* @__PURE__ */ jsxs("div", { className: "border-gray-30 flex flex-col justify-between rounded-
|
|
529
|
+
/* @__PURE__ */ jsxs("div", { className: "border-gray-30 bg-gray-0 flex flex-col justify-between rounded-2xl border p-5", children: [
|
|
529
530
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
530
531
|
/* @__PURE__ */ jsxs("div", { className: "mb-8", children: [
|
|
531
532
|
/* @__PURE__ */ jsx("h2", { className: "mb-1 font-sans", children: "\u041A\u0430\u043C\u0435\u0440\u0430" }),
|
|
@@ -567,7 +568,7 @@ var MediaDevices = ({ audioTrack, videoTrack, noiseCancellation }) => {
|
|
|
567
568
|
] }),
|
|
568
569
|
isBlurSupported && /* @__PURE__ */ jsx("div", { className: "my-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
569
570
|
/* @__PURE__ */ jsx(Label, { className: "font-medium text-gray-100", children: "\u0420\u0430\u0437\u043C\u044B\u0442\u0438\u0435 \u0444\u043E\u043D\u0430" }),
|
|
570
|
-
/* @__PURE__ */ jsx(
|
|
571
|
+
/* @__PURE__ */ jsx(Toggle, { checked: blurEnabled, onCheckedChange: saveBlurEnabled })
|
|
571
572
|
] }) }),
|
|
572
573
|
noiseCancellation && /* @__PURE__ */ jsx("div", { className: "my-4", children: /* @__PURE__ */ jsx(NoiseCancellationSettings, { nc: noiseCancellation, hideOffOption: true }) })
|
|
573
574
|
] }),
|
|
@@ -585,6 +586,9 @@ var PreJoin = () => {
|
|
|
585
586
|
saveAudioInputDeviceId,
|
|
586
587
|
saveVideoInputDeviceId
|
|
587
588
|
} = usePersistentUserChoices();
|
|
589
|
+
const {
|
|
590
|
+
noiseCancellation: { featureEnabled: noiseCancellationFeatureEnabled }
|
|
591
|
+
} = useCallsRuntimeConfig();
|
|
588
592
|
const initialUserChoices = useRef(null);
|
|
589
593
|
if (initialUserChoices.current === null) {
|
|
590
594
|
initialUserChoices.current = {
|
|
@@ -598,25 +602,24 @@ var PreJoin = () => {
|
|
|
598
602
|
console.error("PreJoin ERROR:", e);
|
|
599
603
|
}, []);
|
|
600
604
|
useEffect(() => {
|
|
601
|
-
|
|
605
|
+
let cancelled = false;
|
|
606
|
+
const request = async () => {
|
|
602
607
|
try {
|
|
603
|
-
const
|
|
604
|
-
if (
|
|
605
|
-
|
|
606
|
-
video: true,
|
|
607
|
-
audio: true
|
|
608
|
-
});
|
|
609
|
-
stream.getTracks().forEach((track) => track.stop());
|
|
610
|
-
}
|
|
611
|
-
} catch (error) {
|
|
612
|
-
console.log("Permission request failed:", error);
|
|
608
|
+
const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
|
|
609
|
+
if (!cancelled) stream.getTracks().forEach((t) => t.stop());
|
|
610
|
+
} catch {
|
|
613
611
|
}
|
|
614
612
|
};
|
|
615
|
-
|
|
613
|
+
request();
|
|
614
|
+
return () => {
|
|
615
|
+
cancelled = true;
|
|
616
|
+
};
|
|
616
617
|
}, []);
|
|
618
|
+
const baselineAudio = getBaselineAudioCaptureOptions();
|
|
617
619
|
const tracks = usePreviewTracks(
|
|
618
620
|
{
|
|
619
621
|
audio: !!initialUserChoices.current && initialUserChoices.current?.audioEnabled && {
|
|
622
|
+
...baselineAudio,
|
|
620
623
|
deviceId: initialUserChoices.current.audioDeviceId
|
|
621
624
|
},
|
|
622
625
|
video: !!initialUserChoices.current && initialUserChoices.current?.videoEnabled && {
|
|
@@ -654,6 +657,7 @@ var PreJoin = () => {
|
|
|
654
657
|
const createAudioTrack = async () => {
|
|
655
658
|
try {
|
|
656
659
|
const track = await createLocalAudioTrack({
|
|
660
|
+
...getBaselineAudioCaptureOptions(),
|
|
657
661
|
deviceId: { exact: audioDeviceId }
|
|
658
662
|
});
|
|
659
663
|
setDynamicAudioTrack(track);
|
|
@@ -677,47 +681,26 @@ var PreJoin = () => {
|
|
|
677
681
|
}, [dynamicAudioTrack]);
|
|
678
682
|
const videoTrack = dynamicVideoTrack || previewVideoTrack;
|
|
679
683
|
const audioTrack = dynamicAudioTrack || previewAudioTrack;
|
|
680
|
-
useEffect(() => {
|
|
681
|
-
console.log("PreJoin tracks debug:", {
|
|
682
|
-
initialUserChoices: initialUserChoices.current,
|
|
683
|
-
videoEnabled,
|
|
684
|
-
audioEnabled,
|
|
685
|
-
videoDeviceId,
|
|
686
|
-
audioDeviceId,
|
|
687
|
-
tracks: tracks?.map((t) => ({ kind: t.kind, enabled: !t.isMuted })),
|
|
688
|
-
previewVideoTrack: previewVideoTrack ? { enabled: !previewVideoTrack.isMuted } : null,
|
|
689
|
-
previewAudioTrack: previewAudioTrack ? { enabled: !previewAudioTrack.isMuted } : null,
|
|
690
|
-
dynamicVideoTrack: dynamicVideoTrack ? { enabled: !dynamicVideoTrack.isMuted } : null,
|
|
691
|
-
dynamicAudioTrack: dynamicAudioTrack ? { enabled: !dynamicAudioTrack.isMuted } : null,
|
|
692
|
-
finalVideoTrack: videoTrack ? { enabled: !videoTrack.isMuted } : null,
|
|
693
|
-
finalAudioTrack: audioTrack ? { enabled: !audioTrack.isMuted } : null
|
|
694
|
-
});
|
|
695
|
-
}, [
|
|
696
|
-
tracks,
|
|
697
|
-
previewVideoTrack,
|
|
698
|
-
previewAudioTrack,
|
|
699
|
-
dynamicVideoTrack,
|
|
700
|
-
dynamicAudioTrack,
|
|
701
|
-
videoTrack,
|
|
702
|
-
audioTrack,
|
|
703
|
-
videoEnabled,
|
|
704
|
-
audioEnabled,
|
|
705
|
-
videoDeviceId,
|
|
706
|
-
audioDeviceId
|
|
707
|
-
]);
|
|
708
684
|
useResolveInitiallyDefaultDeviceId(audioDeviceId, audioTrack, saveAudioInputDeviceId);
|
|
709
685
|
useResolveInitiallyDefaultDeviceId(videoDeviceId, videoTrack, saveVideoInputDeviceId);
|
|
710
686
|
useVideoBlur(videoTrack);
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
687
|
+
const noiseCancellation = useNoiseCancellation(null, {
|
|
688
|
+
localAudioTrack: audioTrack ?? void 0
|
|
689
|
+
});
|
|
690
|
+
return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(ScrollArea, { className: "h-full w-full", children: /* @__PURE__ */ jsxs("div", { className: "bg-gray-5 h-full min-h-[calc(100dvh)] p-5", children: [
|
|
691
|
+
/* @__PURE__ */ jsx(Header, {}),
|
|
692
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-8 lg:grid-cols-2", children: [
|
|
693
|
+
/* @__PURE__ */ jsx(UserTile, { audioTrack, videoTrack }),
|
|
694
|
+
/* @__PURE__ */ jsx(
|
|
695
|
+
MediaDevices,
|
|
696
|
+
{
|
|
697
|
+
audioTrack,
|
|
698
|
+
videoTrack,
|
|
699
|
+
noiseCancellation: noiseCancellationFeatureEnabled ? noiseCancellation : void 0
|
|
700
|
+
}
|
|
701
|
+
)
|
|
702
|
+
] })
|
|
703
|
+
] }) }) });
|
|
721
704
|
};
|
|
722
705
|
var BottomBar = ({ saveUserChoices = true }) => {
|
|
723
706
|
const { saveAudioInputEnabled, saveVideoInputEnabled } = usePersistentUserChoices$1({
|
|
@@ -754,11 +737,6 @@ var BottomBar = ({ saveUserChoices = true }) => {
|
|
|
754
737
|
const { useCurrentUser } = useCalls().auth;
|
|
755
738
|
const { data: user } = useCurrentUser();
|
|
756
739
|
const isTutor = user?.default_layout === "tutor";
|
|
757
|
-
const {
|
|
758
|
-
chat: isChatEnabled,
|
|
759
|
-
raiseHand: isRiseHandEnabled,
|
|
760
|
-
whiteboard: isWhiteboardEnabled
|
|
761
|
-
} = useFeaturesStore((s) => s.features);
|
|
762
740
|
const showBackToBoardButton = mode === "full" && activeBoardId && activeClassroom && room && token && room.state === "connected";
|
|
763
741
|
const handleBackToBoard = () => {
|
|
764
742
|
if (!activeBoardId || !activeClassroom) {
|
|
@@ -796,9 +774,9 @@ var BottomBar = ({ saveUserChoices = true }) => {
|
|
|
796
774
|
) }),
|
|
797
775
|
/* @__PURE__ */ jsxs("div", { className: "bg-gray-0 border-gray-10 flex h-[48px] items-center justify-center gap-1 rounded-[16px] border p-1", children: [
|
|
798
776
|
/* @__PURE__ */ jsx(ScreenShareButton, {}),
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
777
|
+
isTutor && /* @__PURE__ */ jsx(WhiteBoardButton, {}),
|
|
778
|
+
/* @__PURE__ */ jsx(ChatButton, {}),
|
|
779
|
+
/* @__PURE__ */ jsx(RaiseHandButton, {})
|
|
802
780
|
] })
|
|
803
781
|
] }),
|
|
804
782
|
/* @__PURE__ */ jsxs("div", { className: "relative flex flex-row items-center justify-center gap-4", children: [
|
|
@@ -824,23 +802,23 @@ var BottomBar = ({ saveUserChoices = true }) => {
|
|
|
824
802
|
] }) });
|
|
825
803
|
};
|
|
826
804
|
var ActiveRoom = () => {
|
|
827
|
-
const { chat: isChatEnabled } = useFeaturesStore((s) => s.features);
|
|
828
805
|
useHandFocus();
|
|
829
806
|
useParticipantJoinSync();
|
|
807
|
+
useParticipantSounds();
|
|
830
808
|
const { cameraTrack } = useLocalParticipant();
|
|
831
809
|
const videoTrack = cameraTrack?.track;
|
|
832
810
|
const mode = useCallStore((state) => state.mode);
|
|
833
811
|
const videoTrackForBlur = mode === "full" ? videoTrack : null;
|
|
834
812
|
useVideoBlur(videoTrackForBlur);
|
|
835
|
-
return /* @__PURE__ */
|
|
813
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex h-full min-h-0 flex-col justify-stretch", children: [
|
|
836
814
|
/* @__PURE__ */ jsx(CallsOnboarding, {}),
|
|
837
815
|
/* @__PURE__ */ jsx(UpBar, {}),
|
|
838
|
-
/* @__PURE__ */ jsxs("div", { className: "flex h-full items-center justify-center gap-4 overflow-hidden
|
|
839
|
-
/* @__PURE__ */ jsx("div", { className: "flex h-full w-full justify-center text-center text-gray-100", children: /* @__PURE__ */ jsx(VideoGrid, {}) }),
|
|
840
|
-
|
|
816
|
+
/* @__PURE__ */ jsxs("div", { className: "flex h-full min-h-0 flex-1 items-center justify-center gap-4 overflow-hidden sm:px-4", children: [
|
|
817
|
+
/* @__PURE__ */ jsx("div", { className: "flex h-full min-h-0 w-full min-w-0 justify-center text-center text-gray-100", children: /* @__PURE__ */ jsx(VideoGrid, {}) }),
|
|
818
|
+
/* @__PURE__ */ jsx(Chat, {})
|
|
841
819
|
] }),
|
|
842
820
|
/* @__PURE__ */ jsx(BottomBar, {})
|
|
843
|
-
] })
|
|
821
|
+
] });
|
|
844
822
|
};
|
|
845
823
|
var Call = () => {
|
|
846
824
|
const isStarted = useCallStore((state) => state.isStarted);
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ui/PreJoin/components/Header/Header.tsx","../src/ui/PreJoin/components/UserTile/Controls.tsx","../src/ui/PreJoin/components/UserTile/UserTile.tsx","../src/ui/PreJoin/components/MediaDevices/MediaDeviceSelect.tsx","../src/ui/PreJoin/components/MediaDevices/MediaDeviceMenu.tsx","../src/ui/PreJoin/components/MediaDevices/MediaDevices.tsx","../src/ui/PreJoin/PreJoin.tsx","../src/ui/Bottom/BottomBar.tsx","../src/ui/Room/ActiveRoom.tsx","../src/ui/Call.tsx"],"names":["jsx","useMemo","jsxs","Button","useCalls","usePersistentUserChoices","facingMode","kind","useRef","useCallback","useEffect","useState","Track","useCallStore","useRoom","useCallsNavigation","DevicesBar","Tooltip","TooltipTrigger","TooltipContent","useFeaturesStore","useLocalParticipant","useVideoBlur"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAMO,IAAM,SAAS,MAAM;AAC1B,EAAA,MAAM,aAAa,kBAAA,EAAmB;AACtC,EAAA,MAAM,MAAA,GAAS,WAAW,SAAA,EAAU;AAEpC,EAAA,MAAM,EAAE,IAAA,EAAK,GAAI,QAAA,EAAS;AAC1B,EAAA,MAAM,EAAE,MAAM,SAAA,EAAU,GAAI,KAAK,eAAA,CAAgB,MAAA,CAAO,MAAM,CAAC,CAAA;AAE/D,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,kEAAA,EACb,QAAA,EAAA;AAAA,oBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,kCAAA,EACb,QAAA,EAAA;AAAA,sBAAA,IAAA,CAAC,OAAA,EAAA,EAAQ,eAAe,GAAA,EACtB,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,cAAA,EAAA,EAAe,SAAO,IAAA,EACrB,QAAA,kBAAA,GAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,SAAS,MAAM;AACb,cAAA,IAAI,MAAA,EAAQ;AACV,gBAAA,UAAA,CAAW,oBAAoB,MAAM,CAAA;AAAA,cACvC;AAAA,YACF,CAAA;AAAA,YACA,IAAA,EAAK,QAAA;AAAA,YACL,OAAA,EAAQ,MAAA;AAAA,YACR,SAAA,EAAU,2FAAA;AAAA,YAEV,QAAA,kBAAA,GAAA,CAAC,SAAA,EAAA,EAAU,SAAA,EAAU,eAAA,EAAgB;AAAA;AAAA,SACvC,EACF,CAAA;AAAA,4BACC,cAAA,EAAA,EAAe,IAAA,EAAK,QAAA,EAAS,KAAA,EAAM,SAAQ,QAAA,EAAA,0GAAA,EAE5C;AAAA,OAAA,EACF,CAAA;AAAA,sBACA,GAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,0CAAA,EAA2C,QAAA,EAAA,2IAAA,EAAwB;AAAA,KAAA,EACnF,CAAA;AAAA,oBACA,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,oEAAA,EACV,qBAAW,IAAA,EACd;AAAA,GAAA,EACF,CAAA;AAEJ,CAAA;AC/BO,IAAM,QAAA,GAAW,CAAC,EAAE,UAAA,EAAY,YAAW,KAAqB;AACrE,EAAA,MAAM;AAAA,IACJ,WAAA,EAAa,EAAE,YAAA,EAAc,YAAA,EAAa;AAAA,IAC1C,qBAAA;AAAA,IACA;AAAA,MACE,wBAAA,EAAyB;AAE7B,EAAA,MAAM,iBAAA,GAAoB,WAAA;AAAA,IACxB,OAAO,OAAA,KAAqB;AAM1B,MAAA,qBAAA,CAAsB,OAAO,CAAA;AAC7B,MAAA,IAAI,UAAA,EAAY;AACd,QAAA,IAAI,OAAA,EAAS;AACX,UAAA,OAAA,CAAQ,IAAI,gCAAgC,CAAA;AAC5C,UAAA,MAAM,WAAW,MAAA,EAAO;AAAA,QAC1B,CAAA,MAAO;AACL,UAAA,OAAA,CAAQ,IAAI,8BAA8B,CAAA;AAC1C,UAAA,MAAM,WAAW,IAAA,EAAK;AAAA,QACxB;AACA,QAAA,OAAA,CAAQ,IAAI,0CAAA,EAA4C,EAAE,KAAA,EAAO,UAAA,CAAW,SAAS,CAAA;AAAA,MACvF,CAAA,MAAO;AACL,QAAA,OAAA,CAAQ,IAAI,oCAAoC,CAAA;AAAA,MAClD;AAAA,IACF,CAAA;AAAA,IACA,CAAC,YAAY,qBAAqB;AAAA,GACpC;AAEA,EAAA,MAAM,iBAAA,GAAoB,WAAA;AAAA,IACxB,OAAO,OAAA,KAAqB;AAM1B,MAAA,qBAAA,CAAsB,OAAO,CAAA;AAC7B,MAAA,IAAI,UAAA,EAAY;AACd,QAAA,IAAI,OAAA,EAAS;AACX,UAAA,OAAA,CAAQ,IAAI,gCAAgC,CAAA;AAC5C,UAAA,MAAM,WAAW,MAAA,EAAO;AAAA,QAC1B,CAAA,MAAO;AACL,UAAA,OAAA,CAAQ,IAAI,8BAA8B,CAAA;AAC1C,UAAA,MAAM,WAAW,IAAA,EAAK;AAAA,QACxB;AACA,QAAA,OAAA,CAAQ,IAAI,0CAAA,EAA4C,EAAE,KAAA,EAAO,UAAA,CAAW,SAAS,CAAA;AAAA,MACvF,CAAA,MAAO;AACL,QAAA,OAAA,CAAQ,IAAI,oCAAoC,CAAA;AAAA,MAClD;AAAA,IACF,CAAA;AAAA,IACA,CAAC,YAAY,qBAAqB;AAAA,GACpC;AAEA,EAAA,MAAM,gBAAA,GAAmB,OAAA;AAAA,IACvB,OAAO;AAAA,MACL,QAAA,EAAU,IAAA;AAAA,MACV,MAAA,EAAQ,MAAM,MAAA,CAAO,UAAA;AAAA,MACrB,QAAA,EAAU;AAAA,KACZ,CAAA;AAAA,IACA,CAAC,iBAAiB;AAAA,GACpB;AAEA,EAAA,MAAM,gBAAA,GAAmB,OAAA;AAAA,IACvB,OAAO;AAAA,MACL,QAAA,EAAU,IAAA;AAAA,MACV,MAAA,EAAQ,MAAM,MAAA,CAAO,MAAA;AAAA,MACrB,QAAA,EAAU;AAAA,KACZ,CAAA;AAAA,IACA,CAAC,iBAAiB;AAAA,GACpB;AAEA,EAAA,uBACEA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gGACb,QAAA,kBAAAA,GAAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,UAAA,EAAY,UAAA;AAAA,MACZ,YAAA,EAAc,YAAA;AAAA,MACd,gBAAA;AAAA,MACA,UAAA;AAAA,MACA,YAAA;AAAA,MACA;AAAA;AAAA,GACF,EACF,CAAA;AAEJ,CAAA;ACpFA,IAAM,aAAa,CAAC;AAAA,EAClB,UAAA;AAAA,EACA,UAAA;AAAA,EACA,YAAA;AAAA,EACA,UAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,wBAAA;AAAA,EACA,4BAAA;AAAA,EACA;AACF,CAAA,KAUM;AACJ,EAAA,MAAM,uBAAuB,wBAAA,IAA4B,4BAAA;AAEzD,EAAA,MAAM,WAAA,GAAcC,QAAQ,MAAM;AAChC,IAAA,IAAI,oBAAA,EAAsB;AACxB,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,IAAI,wBAAA,EAA0B;AAC5B,MAAA,OAAO,+BACH,kKAAA,GACA,0GAAA;AAAA,IACN;AACA,IAAA,IAAI,CAAC,YAAA,EAAc;AACjB,MAAA,OAAO,6FAAA;AAAA,IACT;AACA,IAAA,IAAI,CAAC,gBAAA,EAAkB;AACrB,MAAA,OAAO,8EAAA;AAAA,IACT;AACA,IAAA,IAAI,cAAc,YAAA,EAAc;AAC9B,MAAA,OAAO,EAAA;AAAA,IACT;AACA,IAAA,OAAO,mGAAA;AAAA,EACT,CAAA,EAAG;AAAA,IACD,UAAA;AAAA,IACA,YAAA;AAAA,IACA,wBAAA;AAAA,IACA,4BAAA;AAAA,IACA,gBAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,MAAM,uBAAA,GAA0BA,QAAQ,MAAM;AAC5C,IAAA,IAAI,UAAS,EAAG;AACd,MAAA,MAAM,MAAA,GACJ,OAAO,MAAA,KAAW,WAAA,GACb,MAAA,CAAO,QAAA,EAAU,MAAA,EAAQ,OAAA,CAAQ,UAAA,EAAY,EAAE,CAAA,IAAK,EAAA,GACrD,EAAA;AACN,MAAA,OAAO;AAAA,QACL,gGAAqB,MAAM,CAAA,6FAAA,CAAA;AAAA,QAC3B;AAAA,OACF;AAAA,IACF;AACA,IAAA,OAAO;AAAA,MACL,6RAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,sBAAA,GAAyBA,QAAQ,MAAM;AAC3C,IAAA,IAAI,CAAC,4BAAA,IAAgC,CAAC,wBAAA,EAA0B;AAC9D,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,IAAI,4BAA4B,4BAAA,EAA8B;AAC5D,MAAA,OAAO,wKAAA;AAAA,IACT;AACA,IAAA,IAAI,4BAAA,EAA8B;AAChC,MAAA,OAAO,4HAAA;AAAA,IACT;AACA,IAAA,IAAI,wBAAA,EAA0B;AAC5B,MAAA,OAAO,gHAAA;AAAA,IACT;AACA,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,EAAG,CAAC,4BAAA,EAA8B,wBAAwB,CAAC,CAAA;AAE3D,EAAA,MAAM,WAAA,GAAcA,QAAQ,MAAM;AAChC,IAAA,IAAI,CAAC,cAAc,wBAAA,EAA0B;AAC3C,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,uBACED,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,0DACb,QAAA,kBAAAA,GAAAA;AAAA,MAAC,WAAA;AAAA,MAAA;AAAA,QACC,GAAA,EAAK,OAAA;AAAA,QACL,qBAAA,EAAqB,UAAA;AAAA,QACrB,SAAA,EAAU,4BAAA;AAAA,QACV,WAAA,EAAW,IAAA;AAAA,QACX,KAAA,EAAK,IAAA;AAAA,QACL,KAAA,EAAO;AAAA,UACL,OAAA,EAAS,CAAC,YAAA,IAAgB,wBAAA,GAA2B,MAAA,GAAS,MAAA;AAAA,UAC9D,OAAA,EAAS,UAAA,EAAY,OAAA,IAAW,CAAC,mBAAmB,CAAA,GAAI,CAAA;AAAA,UACxD,UAAA,EAAY;AAAA,SACd;AAAA,QACA,uBAAA,EAAuB,IAAA;AAAA,QACvB,qBAAA,EAAqB;AAAA;AAAA,KACvB,EACF,CAAA;AAAA,EAEJ,CAAA,EAAG,CAAC,UAAA,EAAY,UAAA,EAAY,SAAS,YAAA,EAAc,wBAAA,EAA0B,gBAAgB,CAAC,CAAA;AAE9F,EAAA,MAAM,YAAA,GAAeC,QAAQ,MAAM;AACjC,IAAA,IAAI,cAAc,CAAC,UAAA,CAAW,OAAA,IAAW,CAAC,0BAA0B,OAAO,IAAA;AAE3E,IAAA,uBACED,IAAC,KAAA,EAAA,EAAI,SAAA,EAAU,8DACb,QAAA,kBAAAE,IAAAA,CAAC,MAAA,EAAA,EAAO,IAAA,EAAK,KAAA,EACX,QAAA,EAAA;AAAA,sBAAAF,GAAAA;AAAA,QAAC,WAAA;AAAA,QAAA;AAAA,UACC,GAAA,EAAK,sCAAsC,MAAM,CAAA,YAAA,CAAA;AAAA,UACjD,GAAA,EAAI;AAAA;AAAA,OACN;AAAA,sBACAA,GAAAA,CAAC,cAAA,EAAA,EAAe,IAAA,EAAK,KAAA,EAAM,SAAO,IAAA,EAAC;AAAA,KAAA,EACrC,CAAA,EACF,CAAA;AAAA,EAEJ,CAAA,EAAG,CAAC,UAAA,EAAY,MAAA,EAAQ,wBAAwB,CAAC,CAAA;AAEjD,EAAA,uBACEE,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gHAAA,EACb,QAAA,EAAA;AAAA,oBAAAA,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,wBAAA,EACZ,QAAA,EAAA;AAAA,MAAA,WAAA;AAAA,MACA,YAAA;AAAA,MAEA,oBAAA,oBACCA,IAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,yGAAA,EACb,QAAA,EAAA;AAAA,wBAAAF,GAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,gCAAA,EAAiC,QAAA,EAAA,uOAAA,EAE9C,CAAA;AAAA,wBACAA,GAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,mEACX,QAAA,EAAA,uBAAA,CAAwB,GAAA,CAAI,CAAC,WAAA,EAAa,KAAA,qBACzCE,IAAAA,CAAC,IAAA,EAAA,EAAe,WAAU,wBAAA,EACvB,QAAA,EAAA;AAAA,UAAA,KAAA,KAAU,CAAA,IAAK,CAAC,QAAA,EAAS,oBAAKF,GAAAA,CAAC,QAAA,EAAA,EAAS,WAAU,yBAAA,EAA0B,CAAA;AAAA,0BAC7EA,GAAAA,CAAC,MAAA,EAAA,EAAM,QAAA,EAAA,WAAA,EAAY;AAAA,SAAA,EAAA,EAFZ,KAGT,CACD,CAAA,EACH,CAAA;AAAA,wBACAA,GAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,wBAAuB,QAAA,EAAA,4QAAA,EAEpC,CAAA;AAAA,QACC,sBAAA,oBACCA,GAAAA,CAACG,MAAAA,EAAA,EAAO,IAAA,EAAK,GAAA,EAAI,OAAA,EAAQ,OAAA,EAAQ,OAAA,EAAS,qBAAA,EACvC,QAAA,EAAA,sBAAA,EACH;AAAA,OAAA,EAEJ,CAAA;AAAA,MAGD,CAAC,oBAAA,IAAwB,WAAA,oBACxBH,IAAC,KAAA,EAAA,EAAI,SAAA,EAAU,yGAAA,EACb,QAAA,kBAAAA,GAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,gCAAA,EAAkC,uBAAY,CAAA,EAC7D;AAAA,KAAA,EAEJ,CAAA;AAAA,oBAEAA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,0BAAA,EACb,0BAAAA,GAAAA,CAAC,QAAA,EAAA,EAAS,UAAA,EAAwB,UAAA,EAAwB,CAAA,EAC5D;AAAA,GAAA,EACF,CAAA;AAEJ,CAAA;AAOO,IAAM,QAAA,GAAW,CAAC,EAAE,UAAA,EAAY,YAAW,KAAqB;AACrE,EAAA,MAAM,EAAE,IAAA,EAAK,GAAII,QAAAA,EAAS;AAC1B,EAAA,MAAM,EAAE,IAAA,EAAM,IAAA,EAAK,GAAI,KAAK,cAAA,EAAe;AAC3C,EAAA,MAAM,EAAE,MAAA,EAAO,GAAI,IAAA,IAAQ,EAAC;AAE5B,EAAA,MAAM;AAAA,IACJ,WAAA,EAAa,EAAE,YAAA;AAAa,MAC1BC,wBAAAA,EAAyB;AAE7B,EAAA,MAAM,OAAA,GAAU,OAAyB,IAAI,CAAA;AAC7C,EAAA,MAAM,CAAC,gBAAA,EAAkB,mBAAmB,CAAA,GAAI,SAAS,KAAK,CAAA;AAE9D,EAAA,MAAM,wBAAA,GAA2B,mBAAmB,YAAY,CAAA;AAChE,EAAA,MAAM,4BAAA,GAA+B,mBAAmB,YAAY,CAAA;AAEpE,EAAA,MAAM,UAAA,GAAaJ,QAAQ,MAAM;AAC/B,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,MAAM,EAAE,UAAA,EAAAK,WAAAA,EAAW,GAAI,yBAAyB,UAAU,CAAA;AAC1D,MAAA,OAAOA,WAAAA;AAAA,IACT;AACA,IAAA,OAAO,WAAA;AAAA,EACT,CAAA,EAAG,CAAC,UAAU,CAAC,CAAA;AAEf,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,YAAA,EAAc;AACjB,MAAA,mBAAA,CAAoB,KAAK,CAAA;AAAA,IAC3B;AAAA,EACF,CAAA,EAAG,CAAC,YAAY,CAAC,CAAA;AAEjB,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,MAAM,mBAAmB,MAAM;AAC7B,QAAA,mBAAA,CAAoB,KAAK,CAAA;AAAA,MAC3B,CAAA;AAEA,MAAA,MAAM,qBAAqB,MAAM;AAC/B,QAAA,IAAI,YAAA,EAAc;AAChB,UAAA,mBAAA,CAAoB,IAAI,CAAA;AAAA,QAC1B;AAAA,MACF,CAAA;AAEA,MAAA,UAAA,CAAW,EAAA,CAAG,SAAS,gBAAgB,CAAA;AACvC,MAAA,UAAA,CAAW,EAAA,CAAG,WAAW,kBAAkB,CAAA;AAE3C,MAAA,OAAO,MAAM;AACX,QAAA,UAAA,CAAW,GAAA,CAAI,SAAS,gBAAgB,CAAA;AACxC,QAAA,UAAA,CAAW,GAAA,CAAI,WAAW,kBAAkB,CAAA;AAAA,MAC9C,CAAA;AAAA,IACF;AAAA,EACF,CAAA,EAAG,CAAC,UAAA,EAAY,YAAY,CAAC,CAAA;AAE7B,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,iBAAiB,OAAA,CAAQ,OAAA;AAC/B,IAAA,MAAM,iBAAA,GAAoB,UAAA;AAE1B,IAAA,MAAM,oBAAoB,MAAM;AAC9B,MAAA,IAAI,kBAAkB,YAAA,EAAc;AAClC,QAAA,mBAAA,CAAoB,IAAI,CAAA;AACxB,QAAA,cAAA,CAAe,MAAM,OAAA,GAAU,GAAA;AAAA,MACjC,WAAW,cAAA,EAAgB;AACzB,QAAA,cAAA,CAAe,MAAM,OAAA,GAAU,GAAA;AAAA,MACjC;AAAA,IACF,CAAA;AAEA,IAAA,MAAM,mBAAmB,MAAM;AAC7B,MAAA,mBAAA,CAAoB,KAAK,CAAA;AAAA,IAC3B,CAAA;AAEA,IAAA,IAAI,cAAA,IAAkB,qBAAqB,YAAA,EAAc;AACvD,MAAA,iBAAA,CAAkB,OAAO,cAAc,CAAA;AACvC,MAAA,cAAA,CAAe,gBAAA,CAAiB,kBAAkB,iBAAiB,CAAA;AACnE,MAAA,cAAA,CAAe,gBAAA,CAAiB,SAAS,gBAAgB,CAAA;AAAA,IAC3D;AAEA,IAAA,OAAO,MAAM;AACX,MAAA,IAAI,iBAAA,EAAmB;AACrB,QAAA,iBAAA,CAAkB,MAAA,EAAO;AAAA,MAC3B;AACA,MAAA,IAAI,cAAA,EAAgB;AAClB,QAAA,cAAA,CAAe,mBAAA,CAAoB,kBAAkB,iBAAiB,CAAA;AACtE,QAAA,cAAA,CAAe,mBAAA,CAAoB,SAAS,gBAAgB,CAAA;AAC5D,QAAA,cAAA,CAAe,MAAM,OAAA,GAAU,GAAA;AAAA,MACjC;AAAA,IACF,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,UAAA,EAAY,YAAY,CAAC,CAAA;AAE7B,EAAA,uBACEN,GAAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,UAAA;AAAA,MACA,UAAA;AAAA,MACA,YAAA;AAAA,MACA,UAAA;AAAA,MACA,OAAA;AAAA,MACA,QAAQ,MAAA,IAAU,SAAA;AAAA,MAClB,wBAAA;AAAA,MACA,4BAAA;AAAA,MACA;AAAA;AAAA,GACF;AAEJ,CAAA;ACrRO,IAAM,iBAAA,GAAoB,CAAC,EAAE,OAAA,uBAClCA,GAAAA,CAAC,IAAA,EAAA,EACE,QAAA,EAAA,OAAA,IACC,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,qBACXA,GAAAA,CAAC,IAAA,EAAA,EAAyB,EAAA,EAAI,MAAA,CAAO,QAAA,EACnC,QAAA,kBAAAA,GAAAA,CAAC,UAAA,EAAA,EAAW,OAAO,MAAA,CAAO,QAAA,IAAY,SAAA,EAAY,QAAA,EAAA,MAAA,CAAO,KAAA,EAAM,CAAA,EAAA,EADxD,MAAA,CAAO,QAEhB,CACD,CAAA,EACL,CAAA;ACTF,IAAM,YAAA,GAAe;AAAA,EACnB,UAAA,EAAY,+GAAA;AAAA,EACZ,WAAA,EAAa,+GAAA;AAAA,EACb,UAAA,EAAY,mGAAA;AAAA,EACZ,OAAA,EAAS;AACX,CAAA;AAWO,IAAM,kBAAkB,CAAC;AAAA,EAC9B,WAAA;AAAA,EACA,IAAA;AAAA,EACA,gBAAA;AAAA,EACA,oBAAA;AAAA,EACA,QAAA;AAAA,EACA,kBAAA,GAAqB;AACvB,CAAA,KAA4B;AAC1B,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAI,KAAA,CAAM,SAAS,KAAK,CAAA;AAChD,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAI,KAAA,CAAM,SAAkB,IAAI,CAAA;AACxE,EAAA,MAAM,GAAG,kBAAkB,CAAA,GAAI,KAAA,CAAM,SAAS,kBAAkB,CAAA;AAChE,EAAA,MAAM,MAAA,GAAS,KAAA,CAAM,MAAA,CAA0B,IAAI,CAAA;AACnD,EAAA,MAAM,OAAA,GAAU,KAAA,CAAM,MAAA,CAAuB,IAAI,CAAA;AAEjD,EAAA,MAAM,WAAA,GAAc,KAAA,CAAM,WAAA,CAAY,CAAC,CAAA,KAAa;AAClD,IAAA,OAAA,CAAQ,KAAA,CAAM,uBAAuB,CAAC,CAAA;AAAA,EACxC,CAAA,EAAG,EAAE,CAAA;AACL,EAAA,MAAM,EAAE,OAAA,EAAS,oBAAA,EAAqB,GAAI,oBAAA,CAAqB;AAAA,IAC7D,IAAA;AAAA,IACA,IAAA,EAAM,MAAA;AAAA;AAAA,IACN,kBAAA;AAAA,IACA,OAAA,EAAS;AAAA,GACV,CAAA;AAED,EAAA,KAAA,CAAM,gBAAgB,MAAM;AAC1B,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,kBAAA,CAAmB,IAAI,CAAA;AAAA,IACzB;AAAA,EACF,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAEX,EAAA,KAAA,CAAM,gBAAgB,MAAM;AAC1B,IAAA,IAAI,MAAA,CAAO,OAAA,IAAW,OAAA,CAAQ,OAAA,KAAY,WAAW,cAAA,CAAA,EAAiB;AACpE,MAAA,MAAM,oBAAA,GAAuB,CAAC,CAAA,EAAW,CAAA,KAAc;AACrD,QAAA,IAAI,QAAQ,OAAA,EAAS;AACnB,UAAA,OAAA,CAAQ,OAAA,CAAQ,KAAA,CAAM,IAAA,GAAO,CAAA,EAAG,CAAC,CAAA,EAAA,CAAA;AACjC,UAAA,OAAA,CAAQ,OAAA,CAAQ,KAAA,CAAM,GAAA,GAAM,CAAA,EAAG,CAAC,CAAA,EAAA,CAAA;AAAA,QAClC;AAAA,MACF,CAAA;AAEA,MAAA,mBAAA,CAAoB,MAAA,CAAO,OAAA,EAAS,OAAA,CAAQ,OAAA,EAAS,oBAAoB,CAAA;AAAA,IAC3E;AACA,IAAA,iBAAA,CAAkB,KAAK,CAAA;AAAA,EACzB,GAAG,CAAC,MAAA,EAAQ,OAAA,EAAS,cAAA,EAAgB,OAAO,CAAC,CAAA;AAE7C,EAAA,MAAM,qBAAqB,KAAA,CAAM,WAAA;AAAA,IAC/B,CAAC,KAAA,KAAsB;AACrB,MAAA,IAAI,CAAC,QAAQ,OAAA,EAAS;AACpB,QAAA;AAAA,MACF;AACA,MAAA,IAAI,KAAA,CAAM,MAAA,KAAW,MAAA,CAAO,OAAA,EAAS;AACnC,QAAA;AAAA,MACF;AACA,MAAA,IAAI,MAAA,IAAU,eAAA,CAAgB,OAAA,CAAQ,OAAA,EAAS,KAAK,CAAA,EAAG;AACrD,QAAA,SAAA,CAAU,KAAK,CAAA;AAAA,MACjB;AAAA,IACF,CAAA;AAAA,IACA,CAAC,MAAA,EAAQ,OAAA,EAAS,MAAM;AAAA,GAC1B;AAEA,EAAA,KAAA,CAAM,UAAU,MAAM;AACpB,IAAA,QAAA,CAAS,gBAAA,CAA0B,SAAS,kBAAkB,CAAA;AAC9D,IAAA,MAAA,CAAO,gBAAA,CAA2B,QAAA,EAAU,MAAM,iBAAA,CAAkB,IAAI,CAAC,CAAA;AACzE,IAAA,OAAO,MAAM;AACX,MAAA,QAAA,CAAS,mBAAA,CAA6B,SAAS,kBAAkB,CAAA;AACjE,MAAA,MAAA,CAAO,mBAAA,CAA8B,QAAA,EAAU,MAAM,iBAAA,CAAkB,IAAI,CAAC,CAAA;AAAA,IAC9E,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,kBAAA,EAAoB,iBAAiB,CAAC,CAAA;AAE1C,EAAA,MAAM,iBAAiB,MAAM;AAC3B,IAAA,IAAI,gBAAA,KAAqB,EAAA,EAAI,OAAO,YAAA,CAAa,OAAA;AACjD,IAAA,IAAI,CAAC,oBAAoB,IAAA,EAAM;AAC7B,MAAA,OAAO,YAAA,CAAa,IAAI,CAAA,IAAK,YAAA,CAAa,OAAA;AAAA,IAC5C;AACA,IAAA,OAAO,YAAA,CAAa,OAAA;AAAA,EACtB,CAAA;AACA,EAAA,eAAe,kBAAA,CAAmB,UAAkBO,KAAAA,EAAuB;AACzE,IAAA,SAAA,CAAU,KAAK,CAAA;AACf,IAAA,oBAAA,GAAuBA,OAAM,QAAQ,CAAA;AACrC,IAAA,MAAM,qBAAqB,QAAQ,CAAA;AAAA,EACrC;AAEA,EAAA,uBACEP,IAAC,KAAA,EAAA,EAAI,SAAA,EAAW,GAAG,WAAA,GAAc,sCAAA,GAAyC,IAAI,CAAA,CAAA,EAC5E,QAAA,kBAAAE,IAAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,aAAA,EAAe,CAAC,KAAA,KAAU,kBAAA,CAAmB,OAAO,IAAI,CAAA;AAAA,MACxD,YAAA,EAAc,OAAA,EAAS,MAAA,GAAS,CAAA,GAAI,gBAAA,GAAmB,MAAA;AAAA,MACvD,QAAA,EACE,QAAA,IAAY,WAAA,IAAe,CAAC,OAAA,IAAW,OAAA,CAAQ,MAAA,KAAW,CAAA,IAAK,OAAA,CAAQ,CAAC,CAAA,CAAE,QAAA,KAAa,EAAA;AAAA,MAGzF,QAAA,EAAA;AAAA,wBAAAF,GAAAA;AAAA,UAAC,aAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAU,sBAAA;AAAA,YACV,MAAA,kBACEE,IAAAA,CAAC,KAAA,EAAA,EACE,QAAA,EAAA;AAAA,cAAA,IAAA,KAAS,YAAA,oBAAgBF,GAAAA,CAAC,UAAA,EAAA,EAAW,OAAO,EAAA,EAAI,CAAA;AAAA,cAChD,SAAS,aAAA,oBAAiBA,GAAAA,CAAC,QAAA,EAAA,EAAS,OAAO,EAAA,EAAI,CAAA;AAAA,cAC/C,EAAE,SAAS,YAAA,IAAgB,IAAA,KAAS,kCAAkBA,GAAAA,CAAC,UAAA,EAAA,EAAW,KAAA,EAAO,EAAA,EAAI;AAAA,aAAA,EAChF,CAAA;AAAA,YAGF,QAAA,kBAAAA,GAAAA,CAAC,WAAA,EAAA,EAAY,WAAA,EAAa,gBAAe,EAAG;AAAA;AAAA,SAC9C;AAAA,wBACAA,GAAAA;AAAA,UAAC,aAAA;AAAA,UAAA;AAAA,YACC,GAAA,EAAK,CAAC,GAAA,KAAQ,GAAA,EAAK,gBAAA,CAAiB,YAAY,CAAC,CAAA,KAAM,CAAA,CAAE,cAAA,EAAgB,CAAA;AAAA,YACzE,SAAA,EAAU,QAAA;AAAA,YAET,QAAA,EAAA,OAAA,CAAQ,MAAA,KAAW,CAAA,IAAK,OAAA,CAAQ,CAAC,CAAA,CAAE,QAAA,KAAa,EAAA,oBAC/CA,IAAC,WAAA,EAAA,EACC,QAAA,kBAAAA,GAAAA,CAAC,iBAAA,EAAA,EAAkB,SAAkB,CAAA,EACvC;AAAA;AAAA;AAEJ;AAAA;AAAA,GACF,EACF,CAAA;AAEJ,CAAA;ACtHO,IAAM,eAAe,CAAC,EAAE,UAAA,EAAY,UAAA,EAAY,mBAAkB,KAAyB;AAChG,EAAA,MAAM;AAAA,IACJ,WAAA,EAAa,EAAE,aAAA,EAAe,mBAAA,EAAqB,eAAe,WAAA,EAAY;AAAA,IAC9E,sBAAA;AAAA,IACA,uBAAA;AAAA,IACA,sBAAA;AAAA,IACA,qBAAA;AAAA,IACA,qBAAA;AAAA,IACA;AAAA,MACEK,wBAAAA,EAAyB;AAE7B,EAAA,MAAM,EAAE,WAAA,EAAa,KAAA,EAAO,YAAA,KAAiB,YAAA,EAAa;AAC1D,EAAA,MAAM,EAAE,IAAA,EAAK,GAAI,OAAA,EAAQ;AACzB,EAAA,MAAM,gBAAA,GAAmB,mBAAA,CAAoB,CAAC,CAAA,KAAM,EAAE,gBAAgB,CAAA;AACtE,EAAA,MAAM,oBAAA,GAAuB,mBAAA,CAAoB,CAAC,CAAA,KAAM,EAAE,oBAAoB,CAAA;AAE9E,EAAA,MAAM,kBAAkB,4BAAA,EAA6B;AAGrD,EAAA,MAAM,YAAA,GAAe,cAAc,gBAAgB,CAAA,CAAA;AACnD,EAAA,MAAM,iBAAA,GAAoB,cAAc,oBAAoB,CAAA,CAAA;AAC5D,EAAA,MAAM,kBAAA,GAAqB,eAAe,oBAAoB,CAAA,CAAA;AAE9D,EAAA,MAAM,aAAa,YAAY;AAC7B,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,OAAA,CAAQ,MAAM,yCAAyC,CAAA;AACvD,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,IAAA,CAAK,UAAU,WAAA,EAAa;AAC9B,MAAA,OAAA,CAAQ,IAAI,mDAAmD,CAAA;AAE/D,MAAA,WAAA,CAAY,WAAW,IAAI,CAAA;AAC3B,MAAA,WAAA,CAAY,aAAa,IAAI,CAAA;AAC7B,MAAA,WAAA,CAAY,gBAAgB,KAAK,CAAA;AACjC,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,YAAA,EAAc;AAEhB,MAAA;AAAA,IACF;AAGA,IAAA,WAAA,CAAY,gBAAgB,IAAI,CAAA;AAEhC,IAAA,IAAI;AAEF,MAAA,WAAA,CAAY,iBAAiB,aAAa,CAAA;AAC1C,MAAA,WAAA,CAAY,uBAAuB,mBAAmB,CAAA;AACtD,MAAA,WAAA,CAAY,iBAAiB,aAAa,CAAA;AAG1C,MAAA,WAAA,CAAY,cAAA,EAAgB,UAAA,GAAa,CAAC,UAAA,CAAW,UAAU,KAAK,CAAA;AACpE,MAAA,WAAA,CAAY,cAAA,EAAgB,UAAA,GAAa,CAAC,UAAA,CAAW,UAAU,KAAK,CAAA;AAMpE,MAAA,WAAA,CAAY,WAAW,IAAI,CAAA;AAC3B,MAAA,WAAA,CAAY,aAAa,IAAI,CAAA;AAC7B,MAAA,WAAA,CAAY,gBAAgB,KAAK,CAAA;AAAA,IASnC,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,KAAA,CAAM,wBAAwB,KAAK,CAAA;AAG3C,MAAA,WAAA,CAAY,WAAW,KAAK,CAAA;AAC5B,MAAA,WAAA,CAAY,aAAa,KAAK,CAAA;AAC9B,MAAA,WAAA,CAAY,gBAAgB,KAAK,CAAA;AAGjC,MAAA,IAAI,iBAAiB,KAAA,IAAS,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,6BAA6B,CAAA,EAAG;AACnF,QAAA,OAAA,CAAQ,IAAI,uEAAuE,CAAA;AACnF,QAAA;AAAA,MACF;AAGA,MAAA,OAAA,CAAQ,KAAK,qCAAqC,CAAA;AAAA,IACpD;AAAA,EACF,CAAA;AAGA,EAAA,MAAM,uBAAA,GAA0BJ,OAAAA;AAAA,IAC9B,MAAM,OAAO,KAAA,EAAwB,QAAA,KAAqB;AACxD,MAAA,IAAI;AACF,QAAA,sBAAA,CAAuB,QAAQ,CAAA;AAC/B,QAAA,IAAI,UAAA,EAAY;AACd,UAAA,MAAM,UAAA,CAAW,WAAA,CAAY,EAAE,KAAA,EAAO,UAAU,CAAA;AAEhD,UAAA,MAAM,iBAAA,GAAoB,CAAC,UAAA,CAAW,OAAA;AAMtC,UAAA,qBAAA,CAAsB,iBAAiB,CAAA;AAAA,QACzC;AAAA,MACF,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,KAAA,CAAM,sCAAsC,GAAG,CAAA;AAAA,MACzD;AAAA,IACF,CAAA;AAAA,IACA,CAAC,UAAA,EAAY,sBAAA,EAAwB,qBAAqB;AAAA,GAC5D;AAEA,EAAA,MAAM,uBAAA,GAA0BA,OAAAA;AAAA,IAC9B,MAAM,OAAO,KAAA,EAAwB,QAAA,KAAqB;AACxD,MAAA,IAAI;AACF,QAAA,sBAAA,CAAuB,QAAQ,CAAA;AAC/B,QAAA,IAAI,UAAA,EAAY;AACd,UAAA,MAAM,UAAA,CAAW,WAAA,CAAY,EAAE,KAAA,EAAO,UAAU,CAAA;AAEhD,UAAA,MAAM,iBAAA,GAAoB,CAAC,UAAA,CAAW,OAAA;AAMtC,UAAA,qBAAA,CAAsB,iBAAiB,CAAA;AAAA,QACzC;AAAA,MACF,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,KAAA,CAAM,kCAAkC,GAAG,CAAA;AAAA,MACrD;AAAA,IACF,CAAA;AAAA,IACA,CAAC,UAAA,EAAY,sBAAA,EAAwB,qBAAqB;AAAA,GAC5D;AAEA,EAAA,uBACEC,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,qBAAA,EACb,QAAA,EAAA;AAAA,oBAAAA,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,wEAAA,EACb,QAAA,EAAA;AAAA,sBAAAA,KAAC,KAAA,EAAA,EACC,QAAA,EAAA;AAAA,wBAAAA,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,MAAA,EACb,QAAA,EAAA;AAAA,0BAAAF,GAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,gBAAA,EAAiB,QAAA,EAAA,sCAAA,EAAM,CAAA;AAAA,0BACrCA,GAAAA;AAAA,YAAC,eAAA;AAAA,YAAA;AAAA,cAEC,gBAAA,EAAkB,aAAA;AAAA,cAClB,IAAA,EAAK,YAAA;AAAA,cACL,oBAAA,EAAsB,uBAAA;AAAA,cACtB,UAAU,gBAAA,KAAqB;AAAA,aAAA;AAAA,YAJ1B;AAAA;AAKP,SAAA,EACF,CAAA;AAAA,wBACAE,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,MAAA,EACb,QAAA,EAAA;AAAA,0BAAAF,GAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,gBAAA,EAAiB,QAAA,EAAA,0BAAA,EAAI,CAAA;AAAA,0BACnCE,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,qBAAA,EACb,QAAA,EAAA;AAAA,4BAAAF,GAAAA;AAAA,cAAC,eAAA;AAAA,cAAA;AAAA,gBAEC,gBAAA,EAAkB,aAAA;AAAA,gBAClB,IAAA,EAAK,YAAA;AAAA,gBACL,oBAAA,EAAsB,uBAAA;AAAA,gBACtB,UAAU,oBAAA,KAAyB;AAAA,eAAA;AAAA,cAJ9B;AAAA,aAKP;AAAA,4BACAA,GAAAA;AAAA,cAAC,eAAA;AAAA,cAAA;AAAA,gBAEC,gBAAA,EAAkB,mBAAA;AAAA,gBAClB,IAAA,EAAK,aAAA;AAAA,gBACL,oBAAA,EAAsB,CAAC,CAAA,EAAG,EAAA,KAAO,wBAAwB,EAAE,CAAA;AAAA,gBAC3D,UAAU,oBAAA,KAAyB;AAAA,eAAA;AAAA,cAJ9B;AAAA;AAKP,WAAA,EACF;AAAA,SAAA,EACF,CAAA;AAAA,QACC,eAAA,oBACCA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,QACb,QAAA,kBAAAE,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,mCAAA,EACb,QAAA,EAAA;AAAA,0BAAAF,GAAAA,CAAC,KAAA,EAAA,EAAM,SAAA,EAAU,2BAAA,EAA4B,QAAA,EAAA,2EAAA,EAAa,CAAA;AAAA,0BAC1DA,GAAAA,CAAC,MAAA,EAAA,EAAO,OAAA,EAAS,WAAA,EAAa,iBAAiB,eAAA,EAAiB;AAAA,SAAA,EAClE,CAAA,EACF,CAAA;AAAA,QAED,iBAAA,oBACCA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,MAAA,EACb,QAAA,kBAAAA,GAAAA,CAAC,yBAAA,EAAA,EAA0B,EAAA,EAAI,iBAAA,EAAmB,aAAA,EAAa,MAAC,CAAA,EAClE;AAAA,OAAA,EAEJ,CAAA;AAAA,sBACAA,GAAAA,CAACG,MAAAA,EAAA,EAAO,SAAS,MAAM,UAAA,EAAW,EAAG,SAAA,EAAU,QAAA,EAAS,QAAA,EAAU,YAAA,EAC/D,QAAA,EAAA,YAAA,GAAe,0EAAmB,sFAAA,EACrC;AAAA,KAAA,EACF,CAAA;AAAA,oBACAD,IAAAA,CAAC,KAAA,EAAA,EAAM,SAAA,EAAU,8BAAA,EAA+B,SAAQ,OAAA,EACtD,QAAA,EAAA;AAAA,sBAAAF,IAAC,SAAA,EAAA,EACC,QAAA,kBAAAA,IAAC,UAAA,EAAA,EAAW,SAAA,EAAU,kBAAiB,CAAA,EACzC,CAAA;AAAA,sBACAA,IAAC,cAAA,EAAA,EAAe,SAAA,EAAU,UACxB,QAAA,kBAAAA,GAAAA,CAAC,gBAAA,EAAA,EAAiB,QAAA,EAAA,gqCAAA,EAIlB,CAAA,EACF;AAAA,KAAA,EACF;AAAA,GAAA,EACF,CAAA;AAEJ,CAAA;AC3MO,IAAM,UAAU,MAAM;AAC3B,EAAA,MAAM;AAAA,IACJ,WAAA,EAAa,EAAE,YAAA,EAAc,YAAA,EAAc,eAAe,aAAA,EAAc;AAAA,IACxE,sBAAA;AAAA,IACA;AAAA,MACEK,wBAAAA,EAAyB;AAE7B,EAAA,MAAM,kBAAA,GAAqBG,OAKjB,IAAI,CAAA;AAGd,EAAA,IAAI,kBAAA,CAAmB,YAAY,IAAA,EAAM;AACvC,IAAA,kBAAA,CAAmB,OAAA,GAAU;AAAA,MAC3B,YAAA;AAAA,MACA,YAAA;AAAA,MACA,aAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF;AAEA,EAAA,MAAM,OAAA,GAAUC,WAAAA,CAAY,CAAC,CAAA,KAAa;AACxC,IAAA,OAAA,CAAQ,KAAA,CAAM,kBAAkB,CAAC,CAAA;AAAA,EACnC,CAAA,EAAG,EAAE,CAAA;AAGL,EAAAC,UAAU,MAAM;AACd,IAAA,MAAM,qBAAqB,YAAY;AACrC,MAAA,IAAI;AAEF,QAAA,MAAM,WAAA,GAAc,MAAM,SAAA,CAAU,WAAA,CAAY,MAAM,EAAE,IAAA,EAAM,UAA4B,CAAA;AAC1F,QAAA,IAAI,WAAA,CAAY,UAAU,QAAA,EAAU;AAElC,UAAA,MAAM,MAAA,GAAS,MAAM,SAAA,CAAU,YAAA,CAAa,YAAA,CAAa;AAAA,YACvD,KAAA,EAAO,IAAA;AAAA,YACP,KAAA,EAAO;AAAA,WACR,CAAA;AAED,UAAA,MAAA,CAAO,WAAU,CAAE,OAAA,CAAQ,CAAC,KAAA,KAAU,KAAA,CAAM,MAAM,CAAA;AAAA,QACpD;AAAA,MACF,SAAS,KAAA,EAAO;AACd,QAAA,OAAA,CAAQ,GAAA,CAAI,8BAA8B,KAAK,CAAA;AAAA,MACjD;AAAA,IACF,CAAA;AAEA,IAAA,kBAAA,EAAmB;AAAA,EACrB,CAAA,EAAG,EAAE,CAAA;AAGL,EAAA,MAAM,MAAA,GAAS,gBAAA;AAAA,IACb;AAAA,MACE,OAAO,CAAC,CAAC,mBAAmB,OAAA,IAC1B,kBAAA,CAAmB,SAAS,YAAA,IAAgB;AAAA,QAC1C,QAAA,EAAU,mBAAmB,OAAA,CAAQ;AAAA,OACvC;AAAA,MACF,OAAO,CAAC,CAAC,mBAAmB,OAAA,IAC1B,kBAAA,CAAmB,SAAS,YAAA,IAAgB;AAAA,QAC1C,QAAA,EAAU,mBAAmB,OAAA,CAAQ;AAAA;AACvC,KACJ;AAAA,IACA;AAAA,GACF;AAGA,EAAA,MAAM,CAAC,iBAAA,EAAmB,oBAAoB,CAAA,GAAIC,SAAiC,IAAI,CAAA;AACvF,EAAA,MAAM,CAAC,iBAAA,EAAmB,oBAAoB,CAAA,GAAIA,SAAiC,IAAI,CAAA;AAEvF,EAAA,MAAM,iBAAA,GAAoBV,OAAAA;AAAA,IACxB,MAAM,MAAA,EAAQ,MAAA,CAAO,CAAC,KAAA,KAAU,KAAA,CAAM,IAAA,KAASW,KAAAA,CAAM,IAAA,CAAK,KAAK,CAAA,CAAE,CAAC,CAAA;AAAA,IAClE,CAAC,MAAM;AAAA,GACT;AAEA,EAAA,MAAM,iBAAA,GAAoBX,OAAAA;AAAA,IACxB,MAAM,MAAA,EAAQ,MAAA,CAAO,CAAC,KAAA,KAAU,KAAA,CAAM,IAAA,KAASW,KAAAA,CAAM,IAAA,CAAK,KAAK,CAAA,CAAE,CAAC,CAAA;AAAA,IAClE,CAAC,MAAM;AAAA,GACT;AAGA,EAAAF,UAAU,MAAM;AACd,IAAA,MAAM,mBAAmB,YAAY;AACnC,MAAA,IAAI;AACF,QAAA,MAAM,KAAA,GAAQ,MAAM,qBAAA,CAAsB;AAAA,UACxC,QAAA,EAAU,EAAE,KAAA,EAAO,aAAA;AAAc,SAClC,CAAA;AACD,QAAA,oBAAA,CAAqB,KAAK,CAAA;AAAA,MAC5B,SAAS,KAAA,EAAO;AACd,QAAA,OAAA,CAAQ,KAAc,CAAA;AAAA,MACxB;AAAA,IACF,CAAA;AAEA,IAAA,IACE,YAAA,IACA,CAAC,kBAAA,CAAmB,OAAA,EAAS,gBAC7B,CAAC,iBAAA,IACD,CAAC,iBAAA,EACD;AACA,MAAA,gBAAA,EAAiB;AAAA,IACnB;AAAA,EACF,GAAG,CAAC,YAAA,EAAc,eAAe,iBAAA,EAAmB,iBAAA,EAAmB,OAAO,CAAC,CAAA;AAG/E,EAAAA,UAAU,MAAM;AACd,IAAA,MAAM,mBAAmB,YAAY;AACnC,MAAA,IAAI;AACF,QAAA,MAAM,KAAA,GAAQ,MAAM,qBAAA,CAAsB;AAAA,UACxC,QAAA,EAAU,EAAE,KAAA,EAAO,aAAA;AAAc,SAClC,CAAA;AACD,QAAA,oBAAA,CAAqB,KAAK,CAAA;AAAA,MAC5B,SAAS,KAAA,EAAO;AACd,QAAA,OAAA,CAAQ,KAAc,CAAA;AAAA,MACxB;AAAA,IACF,CAAA;AAEA,IAAA,IACE,YAAA,IACA,CAAC,kBAAA,CAAmB,OAAA,EAAS,gBAC7B,CAAC,iBAAA,IACD,CAAC,iBAAA,EACD;AACA,MAAA,gBAAA,EAAiB;AAAA,IACnB;AAAA,EACF,GAAG,CAAC,YAAA,EAAc,eAAe,iBAAA,EAAmB,iBAAA,EAAmB,OAAO,CAAC,CAAA;AAG/E,EAAAA,UAAU,MAAM;AACd,IAAA,OAAO,MAAM;AACX,MAAA,iBAAA,EAAmB,IAAA,EAAK;AAAA,IAC1B,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,iBAAiB,CAAC,CAAA;AAEtB,EAAAA,UAAU,MAAM;AACd,IAAA,OAAO,MAAM;AACX,MAAA,iBAAA,EAAmB,IAAA,EAAK;AAAA,IAC1B,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,iBAAiB,CAAC,CAAA;AAGtB,EAAA,MAAM,aAAa,iBAAA,IAAqB,iBAAA;AACxC,EAAA,MAAM,aAAa,iBAAA,IAAqB,iBAAA;AAGxC,EAAAA,UAAU,MAAM;AACd,IAAA,OAAA,CAAQ,IAAI,uBAAA,EAAyB;AAAA,MACnC,oBAAoB,kBAAA,CAAmB,OAAA;AAAA,MACvC,YAAA;AAAA,MACA,YAAA;AAAA,MACA,aAAA;AAAA,MACA,aAAA;AAAA,MACA,MAAA,EAAQ,MAAA,EAAQ,GAAA,CAAI,CAAC,CAAA,MAAO,EAAE,IAAA,EAAM,CAAA,CAAE,IAAA,EAAM,OAAA,EAAS,CAAC,CAAA,CAAE,SAAQ,CAAE,CAAA;AAAA,MAClE,mBAAmB,iBAAA,GAAoB,EAAE,SAAS,CAAC,iBAAA,CAAkB,SAAQ,GAAI,IAAA;AAAA,MACjF,mBAAmB,iBAAA,GAAoB,EAAE,SAAS,CAAC,iBAAA,CAAkB,SAAQ,GAAI,IAAA;AAAA,MACjF,mBAAmB,iBAAA,GAAoB,EAAE,SAAS,CAAC,iBAAA,CAAkB,SAAQ,GAAI,IAAA;AAAA,MACjF,mBAAmB,iBAAA,GAAoB,EAAE,SAAS,CAAC,iBAAA,CAAkB,SAAQ,GAAI,IAAA;AAAA,MACjF,iBAAiB,UAAA,GAAa,EAAE,SAAS,CAAC,UAAA,CAAW,SAAQ,GAAI,IAAA;AAAA,MACjE,iBAAiB,UAAA,GAAa,EAAE,SAAS,CAAC,UAAA,CAAW,SAAQ,GAAI;AAAA,KAClE,CAAA;AAAA,EACH,CAAA,EAAG;AAAA,IACD,MAAA;AAAA,IACA,iBAAA;AAAA,IACA,iBAAA;AAAA,IACA,iBAAA;AAAA,IACA,iBAAA;AAAA,IACA,UAAA;AAAA,IACA,UAAA;AAAA,IACA,YAAA;AAAA,IACA,YAAA;AAAA,IACA,aAAA;AAAA,IACA;AAAA,GACD,CAAA;AAGD,EAAA,kCAAA,CAAmC,aAAA,EAAe,YAAY,sBAAsB,CAAA;AACpF,EAAA,kCAAA,CAAmC,aAAA,EAAe,YAAY,sBAAsB,CAAA;AAGpF,EAAA,YAAA,CAAa,UAAU,CAAA;AAEvB,EAAA,uBACER,KAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,oBAAAF,GAAAA,CAAC,cAAW,SAAA,EAAU,eAAA,EACpB,0BAAAE,IAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,qBAAA,EACb,QAAA,EAAA;AAAA,sBAAAF,IAAC,MAAA,EAAA,EAAO,CAAA;AAAA,sBACRE,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,uCAAA,EACb,QAAA,EAAA;AAAA,wBAAAF,GAAAA,CAAC,QAAA,EAAA,EAAS,UAAA,EAAwB,UAAA,EAAwB,CAAA;AAAA,wBAC1DA,GAAAA,CAAC,YAAA,EAAA,EAAa,UAAA,EAAwB,UAAA,EAAwB;AAAA,OAAA,EAChE;AAAA,KAAA,EACF,CAAA,EACF,CAAA;AAAA,oBACAA,IAAC,iBAAA,EAAA,EAAkB;AAAA,GAAA,EACrB,CAAA;AAEJ,CAAA;AClMO,IAAM,SAAA,GAAY,CAAC,EAAE,eAAA,GAAkB,MAAK,KAAuB;AACxE,EAAA,MAAM,EAAE,qBAAA,EAAuB,qBAAA,EAAsB,GAAIK,0BAAAA,CAAyB;AAAA,IAChF,aAAa,CAAC;AAAA,GACf,CAAA;AAED,EAAA,MAAM,EAAE,mBAAA,EAAqB,eAAA,EAAiB,eAAA,EAAiB,WAAA,KAC7D,mBAAA,EAAoB;AAEtB,EAAA,MAAM,mBAAmB,cAAA,CAAe;AAAA,IACtC,MAAA,EAAQO,MAAM,MAAA,CAAO,UAAA;AAAA,IACrB,QAAA,EAAU,CAAC,OAAA,EAAkB,eAAA,KAA6B;AACxD,MAAA,IAAI,eAAA,EAAiB;AACnB,QAAA,qBAAA,CAAsB,OAAO,CAAA;AAAA,MAC/B;AAAA,IACF;AAAA,GACD,CAAA;AAED,EAAA,MAAM,eAAe,cAAA,CAAe;AAAA,IAClC,MAAA,EAAQA,MAAM,MAAA,CAAO,MAAA;AAAA,IACrB,QAAA,EAAU,CAAC,OAAA,EAAkB,eAAA,KAA6B;AACxD,MAAA,IAAI,eAAA,EAAiB;AACnB,QAAA,qBAAA,CAAsB,OAAO,CAAA;AAAA,MAC/B;AAAA,IACF;AAAA,GACD,CAAA;AAED,EAAA,MAAM,sBAAA,GAAyBH,YAAY,YAAY;AACrD,IAAA,gBAAA,CAAiB,MAAA,EAAO;AAAA,EAC1B,CAAA,EAAG,CAAC,gBAAgB,CAAC,CAAA;AAErB,EAAA,MAAM,kBAAA,GAAqBA,YAAY,YAAY;AACjD,IAAA,YAAA,CAAa,MAAA,EAAO;AAAA,EACtB,CAAA,EAAG,CAAC,YAAY,CAAC,CAAA;AAEjB,EAAA,MAAM,EAAE,UAAA,EAAW,GAAI,YAAA,EAAa;AACpC,EAAA,MAAM,EAAE,IAAA,EAAM,aAAA,EAAe,eAAA,EAAiB,KAAA,KAAUI,YAAAA,EAAa;AACrE,EAAA,MAAM,WAAA,GAAcA,YAAAA,CAAa,CAAC,KAAA,KAAU,MAAM,WAAW,CAAA;AAC7D,EAAA,MAAM,EAAE,IAAA,EAAK,GAAIC,OAAAA,EAAQ;AACzB,EAAA,MAAM,aAAaC,kBAAAA,EAAmB;AAEtC,EAAA,MAAM,EAAE,cAAA,EAAe,GAAIX,QAAAA,EAAS,CAAE,IAAA;AACtC,EAAA,MAAM,EAAE,IAAA,EAAM,IAAA,EAAK,GAAI,cAAA,EAAe;AACtC,EAAA,MAAM,OAAA,GAAU,MAAM,cAAA,KAAmB,OAAA;AAEzC,EAAA,MAAM;AAAA,IACJ,IAAA,EAAM,aAAA;AAAA,IACN,SAAA,EAAW,iBAAA;AAAA,IACX,UAAA,EAAY;AAAA,GACd,GAAI,gBAAA,CAAiB,CAAC,CAAA,KAAM,EAAE,QAAQ,CAAA;AAEtC,EAAA,MAAM,qBAAA,GACJ,SAAS,MAAA,IACT,aAAA,IACA,mBACA,IAAA,IACA,KAAA,IACA,KAAK,KAAA,KAAU,WAAA;AAEjB,EAAA,MAAM,oBAAoB,MAAM;AAC9B,IAAA,IAAI,CAAC,aAAA,IAAiB,CAAC,eAAA,EAAiB;AACtC,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,CAAC,IAAA,IAAQ,CAAC,KAAA,IAAS,IAAA,CAAK,UAAU,WAAA,EAAa;AACjD,MAAA;AAAA,IACF;AAEA,IAAA,WAAA,CAAY,iBAAiB,KAAK,CAAA;AAClC,IAAA,WAAA,CAAY,QAAQ,SAAS,CAAA;AAE7B,IAAA,UAAA,CAAW,wBAAA,CAAyB,iBAAiB,aAAa,CAAA;AAAA,EACpE,CAAA;AAEA,EAAA,uBACEJ,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,iBAAA,EAAmB,UAAA,IAAc,sBAAsB,CAAA,EACxE,QAAA,kBAAAE,IAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,+CAAA,EACb,QAAA,EAAA;AAAA,oBAAAF,IAAC,KAAA,EAAA,EAAI,CAAA;AAAA,oBACLE,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,qBAAA,EACb,QAAA,EAAA;AAAA,sBAAAF,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,yGAAA,EACb,QAAA,kBAAAA,GAAAA;AAAA,QAACgB,UAAAA;AAAA,QAAA;AAAA,UACC,YAAY,eAAA,EAAiB,KAAA;AAAA,UAC7B,YAAA,EAAc,mBAAA;AAAA,UACd,gBAAA,EAAkB;AAAA,YAChB,QAAA,EAAU,IAAA;AAAA,YACV,MAAA,EAAQJ,MAAM,MAAA,CAAO,UAAA;AAAA,YACrB,QAAA,EAAU;AAAA,WACZ;AAAA,UACA,YAAY,WAAA,EAAa,KAAA;AAAA,UACzB,YAAA,EAAc,eAAA;AAAA,UACd,gBAAA,EAAkB;AAAA,YAChB,QAAA,EAAU,IAAA;AAAA,YACV,MAAA,EAAQA,MAAM,MAAA,CAAO,MAAA;AAAA,YACrB,QAAA,EAAU;AAAA,WACZ;AAAA,UACA,SAAA,EAAU;AAAA;AAAA,OACZ,EACF,CAAA;AAAA,sBACAV,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,oGAAA,EACb,QAAA,EAAA;AAAA,wBAAAF,IAAC,iBAAA,EAAA,EAAkB,CAAA;AAAA,QAClB,mBAAA,IAAuB,OAAA,oBAAWA,GAAAA,CAAC,gBAAA,EAAA,EAAiB,CAAA;AAAA,QACpD,aAAA,oBAAiBA,GAAAA,CAAC,UAAA,EAAA,EAAW,CAAA;AAAA,QAC7B,iBAAA,oBAAqBA,GAAAA,CAAC,eAAA,EAAA,EAAgB;AAAA,OAAA,EACzC;AAAA,KAAA,EACF,CAAA;AAAA,oBACAE,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,0DAAA,EACZ,QAAA,EAAA;AAAA,MAAA,qBAAA,oBACCA,IAAAA,CAACe,OAAAA,EAAA,EAAQ,eAAe,GAAA,EACtB,QAAA,EAAA;AAAA,wBAAAjB,GAAAA,CAACkB,cAAAA,EAAA,EAAe,OAAA,EAAO,MACrB,QAAA,kBAAAhB,IAAAA;AAAA,UAACC,MAAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAK,GAAA;AAAA,YACL,OAAA,EAAQ,SAAA;AAAA,YACR,OAAA,EAAS,iBAAA;AAAA,YACT,SAAA,EAAU,gGAAA;AAAA,YACV,kBAAA,EAAiB,oBAAA;AAAA,YAEjB,QAAA,EAAA;AAAA,8BAAAH,GAAAA,CAAC,UAAA,EAAA,EAAW,SAAA,EAAU,qBAAA,EAAsB,CAAA;AAAA,8BAC5CA,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,oBAAmB,QAAA,EAAA,uCAAA,EAAO;AAAA;AAAA;AAAA,SAC5C,EACF,CAAA;AAAA,wBACAA,IAACmB,cAAAA,EAAA,EAAe,MAAK,KAAA,EAAM,KAAA,EAAM,UAAS,QAAA,EAAA,mNAAA,EAE1C;AAAA,OAAA,EACF,CAAA;AAAA,sBAEFnB,IAAC,KAAA,EAAA,EAAI,SAAA,EAAU,+GACb,QAAA,kBAAAA,GAAAA,CAAC,oBAAiB,CAAA,EACpB;AAAA,KAAA,EACF;AAAA,GAAA,EACF,CAAA,EACF,CAAA;AAEJ,CAAA;AC3IO,IAAM,aAAa,MAAM;AAC9B,EAAA,MAAM,EAAE,MAAM,aAAA,EAAc,GAAIoB,iBAAiB,CAAC,CAAA,KAAM,EAAE,QAAQ,CAAA;AAGlE,EAAA,YAAA,EAAa;AAEb,EAAA,sBAAA,EAAuB;AAEvB,EAAA,MAAM,EAAE,WAAA,EAAY,GAAIC,mBAAAA,EAAoB;AAC5C,EAAA,MAAM,aAAa,WAAA,EAAa,KAAA;AAGhC,EAAA,MAAM,IAAA,GAAOR,YAAAA,CAAa,CAAC,KAAA,KAAU,MAAM,IAAI,CAAA;AAC/C,EAAA,MAAM,iBAAA,GAAoB,IAAA,KAAS,MAAA,GAAS,UAAA,GAAa,IAAA;AACzD,EAAAS,aAAa,iBAAiB,CAAA;AAE9B,EAAA,uBACEtB,GAAAA,CAAC,KAAA,EAAA,EAAI,EAAA,EAAG,0BAAA,EAA2B,SAAA,EAAU,kBAAA,EAC3C,QAAA,kBAAAE,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,sCAAA,EACb,QAAA,EAAA;AAAA,oBAAAF,IAAC,eAAA,EAAA,EAAgB,CAAA;AAAA,oBACjBA,IAAC,KAAA,EAAA,EAAM,CAAA;AAAA,oBACPE,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,mEAAA,EACb,QAAA,EAAA;AAAA,sBAAAF,IAAC,KAAA,EAAA,EAAI,SAAA,EAAU,+DACb,QAAA,kBAAAA,GAAAA,CAAC,aAAU,CAAA,EACb,CAAA;AAAA,MACC,aAAA,oBAAiBA,GAAAA,CAAC,IAAA,EAAA,EAAK;AAAA,KAAA,EAC1B,CAAA;AAAA,oBACAA,IAAC,SAAA,EAAA,EAAU;AAAA,GAAA,EACb,CAAA,EACF,CAAA;AAEJ,CAAA;ACjCO,IAAM,OAAO,MAAM;AACxB,EAAA,MAAM,SAAA,GAAYa,YAAAA,CAAa,CAAC,KAAA,KAAU,MAAM,SAAS,CAAA;AACzD,EAAA,MAAM,SAAA,GAAY,iBAAA,CAAkB,CAAC,CAAA,KAAM,EAAE,SAAS,CAAA;AACtD,EAAA,MAAM,EAAE,QAAA,EAAS,GAAIE,kBAAAA,EAAmB;AAExC,EAAA,kBAAA,EAAmB;AACnB,EAAA,gBAAA,EAAiB;AAEjB,EAAA,MAAM,IAAA,GAAOF,YAAAA,CAAa,CAAC,KAAA,KAAU,MAAM,IAAI,CAAA;AAC/C,EAAA,MAAM,WAAA,GAAcA,YAAAA,CAAa,CAAC,KAAA,KAAU,MAAM,WAAW,CAAA;AAE7D,EAAAH,UAAU,MAAM;AACd,IAAA,MAAM,YAAA,GAAe,iBAAA,CAAkB,IAAA,CAAK,QAAQ,CAAA;AAEpD,IAAA,IAAI,YAAA,IAAgB,SAAS,SAAA,EAAW;AACtC,MAAA,WAAA,CAAY,QAAQ,MAAM,CAAA;AAAA,IAC5B;AAAA,EACF,CAAA,EAAG,CAAC,QAAA,EAAU,IAAA,EAAM,WAAW,CAAC,CAAA;AAEhC,EAAA,uBACEV,GAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAU,QAAA;AAAA,MACV,OACE,SAAA,GACK;AAAA,QACC,iBAAA,EAAmB,KAAA;AAAA,QACnB,oBAAA,EACE;AAAA,OACJ,GACA,MAAA;AAAA,MAGN,QAAA,kBAAAA,IAAC,KAAA,EAAA,EAAI,SAAA,EAAU,+BACZ,QAAA,EAAA,SAAA,mBACCA,IAAC,KAAA,EAAA,EAAI,EAAA,EAAG,4BAA2B,SAAA,EAAU,kBAAA,EAC3C,0BAAAA,GAAAA,CAAC,UAAA,EAAA,EAAW,GACd,CAAA,mBAEAA,GAAAA,CAAC,OAAA,EAAA,EAAQ,CAAA,EAEb;AAAA;AAAA,GACF;AAEJ","file":"index.mjs","sourcesContent":["import { Button } from '@xipkg/button';\nimport { ArrowLeft } from '@xipkg/icons';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@xipkg/tooltip';\nimport { useCalls, useCallsNavigation } from '@xipkg/calls-providers';\n\n/* eslint-disable no-irregular-whitespace */\nexport const Header = () => {\n const navigation = useCallsNavigation();\n const callId = navigation.getCallId();\n\n const { room } = useCalls();\n const { data: classroom } = room.useGetClassroom(Number(callId));\n\n return (\n <div className=\"mb-4 flex flex-col items-start gap-2 sm:flex-row sm:items-center\">\n <div className=\"flex flex-row items-center gap-2\">\n <Tooltip delayDuration={1000}>\n <TooltipTrigger asChild>\n <Button\n onClick={() => {\n if (callId) {\n navigation.navigateToClassroom(callId);\n }\n }}\n type=\"button\"\n variant=\"none\"\n className=\"flex size-[40px] min-h-[40xp] min-w-[40px] items-center justify-center rounded-[12px] p-0\"\n >\n <ArrowLeft className=\"fill-gray-100\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\" align=\"start\">\n Вернуться в кабинет\n </TooltipContent>\n </Tooltip>\n <h1 className=\"text-xl-base font-semibold text-gray-100\">Присоединиться к занятию</h1>\n </div>\n <p className=\"text-s-base text-gray-60 pt-0 pl-12 align-baseline sm:pt-2 sm:pl-0\">\n {classroom?.name}\n </p>\n </div>\n );\n};\n","import { LocalAudioTrack, LocalVideoTrack, Track } from 'livekit-client';\nimport { useCallback, useMemo } from 'react';\n\nimport { DevicesBar } from '@xipkg/calls-ui';\nimport { usePersistentUserChoices } from '@xipkg/calls-hooks';\n\ntype ControlsProps = {\n audioTrack?: LocalAudioTrack;\n videoTrack?: LocalVideoTrack;\n};\n\nexport const Controls = ({ audioTrack, videoTrack }: ControlsProps) => {\n const {\n userChoices: { audioEnabled, videoEnabled },\n saveAudioInputEnabled,\n saveVideoInputEnabled,\n } = usePersistentUserChoices();\n\n const handleAudioChange = useCallback(\n async (enabled: boolean) => {\n // console.log('Controls: handleAudioChange', {\n // enabled,\n // audioTrack: !!audioTrack,\n // currentMuted: audioTrack?.isMuted,\n // });\n saveAudioInputEnabled(enabled);\n if (audioTrack) {\n if (enabled) {\n console.log('Controls: unmuting audio track');\n await audioTrack.unmute();\n } else {\n console.log('Controls: muting audio track');\n await audioTrack.mute();\n }\n console.log('Controls: audio track state after change', { muted: audioTrack.isMuted });\n } else {\n console.log('Controls: no audio track available');\n }\n },\n [audioTrack, saveAudioInputEnabled],\n );\n\n const handleVideoChange = useCallback(\n async (enabled: boolean) => {\n // console.log('Controls: handleVideoChange', {\n // enabled,\n // videoTrack: !!videoTrack,\n // currentMuted: videoTrack?.isMuted,\n // });\n saveVideoInputEnabled(enabled);\n if (videoTrack) {\n if (enabled) {\n console.log('Controls: unmuting video track');\n await videoTrack.unmute();\n } else {\n console.log('Controls: muting video track');\n await videoTrack.mute();\n }\n console.log('Controls: video track state after change', { muted: videoTrack.isMuted });\n } else {\n console.log('Controls: no video track available');\n }\n },\n [videoTrack, saveVideoInputEnabled],\n );\n\n const microTrackToggle = useMemo(\n () => ({\n showIcon: true,\n source: Track.Source.Microphone,\n onChange: handleAudioChange,\n }),\n [handleAudioChange],\n );\n\n const videoTrackToggle = useMemo(\n () => ({\n showIcon: true,\n source: Track.Source.Camera,\n onChange: handleVideoChange,\n }),\n [handleVideoChange],\n );\n\n return (\n <div className=\"bg-gray-0 border-gray-10 flex h-12 w-23 items-center justify-center gap-1 rounded-2xl border\">\n <DevicesBar\n microTrack={audioTrack}\n microEnabled={audioEnabled}\n microTrackToggle={microTrackToggle}\n videoTrack={videoTrack}\n videoEnabled={videoEnabled}\n videoTrackToggle={videoTrackToggle}\n />\n </div>\n );\n};\n","import { Avatar, AvatarFallback, AvatarImage } from '@xipkg/avatar';\nimport { useMemo, useRef, useEffect, useState } from 'react';\nimport { facingModeFromLocalTrack, LocalVideoTrack, LocalAudioTrack } from 'livekit-client';\nimport { Controls } from './Controls';\nimport { useCannotUseDevice, usePersistentUserChoices } from '@xipkg/calls-hooks';\nimport { openPermissionsDialog } from '@xipkg/calls-store';\nimport { Button } from '@xipkg/button';\nimport { SecureVideo } from '@xipkg/calls-ui';\nimport { Settings } from '@xipkg/icons';\nimport { isSafari } from '@xipkg/calls-utils';\nimport { useCalls } from '@xipkg/calls-providers';\n\nconst UserTileUI = ({\n audioTrack,\n videoTrack,\n videoEnabled,\n facingMode,\n videoEl,\n userId,\n isCameraDeniedOrPrompted,\n isMicrophoneDeniedOrPrompted,\n isVideoInitiated,\n}: {\n audioTrack?: LocalAudioTrack;\n videoTrack?: LocalVideoTrack;\n videoEnabled: boolean;\n facingMode: string;\n videoEl: React.RefObject<HTMLVideoElement | null>;\n userId: string;\n isCameraDeniedOrPrompted: boolean;\n isMicrophoneDeniedOrPrompted: boolean;\n isVideoInitiated: boolean;\n}) => {\n const isPermissionsBlocked = isCameraDeniedOrPrompted || isMicrophoneDeniedOrPrompted;\n\n const hintMessage = useMemo(() => {\n if (isPermissionsBlocked) {\n return null;\n }\n if (isCameraDeniedOrPrompted) {\n return isMicrophoneDeniedOrPrompted\n ? 'Камера и микрофон не разрешены'\n : 'Камера не разрешена';\n }\n if (!videoEnabled) {\n return 'Камера отключена';\n }\n if (!isVideoInitiated) {\n return 'Запуск камеры...';\n }\n if (videoTrack && videoEnabled) {\n return '';\n }\n return 'Камера недоступна';\n }, [\n videoTrack,\n videoEnabled,\n isCameraDeniedOrPrompted,\n isMicrophoneDeniedOrPrompted,\n isVideoInitiated,\n isPermissionsBlocked,\n ]);\n\n const permissionsInstructions = useMemo(() => {\n if (isSafari()) {\n const origin =\n typeof window !== 'undefined'\n ? (window.location?.origin?.replace('https://', '') ?? '')\n : '';\n return [\n `Нажмите на иконку ${origin} в адресной строке`,\n 'Снимите запрет на использование камеры и микрофона',\n ];\n }\n return [\n 'Нажмите на значок настроек в адресной строке браузера',\n 'Снимите запрет на использование камеры и микрофона',\n ];\n }, []);\n\n const permissionsButtonLabel = useMemo(() => {\n if (!isMicrophoneDeniedOrPrompted && !isCameraDeniedOrPrompted) {\n return null;\n }\n if (isCameraDeniedOrPrompted && isMicrophoneDeniedOrPrompted) {\n return 'Как разрешить камеру и микрофон';\n }\n if (isMicrophoneDeniedOrPrompted) {\n return 'Как разрешить микрофон';\n }\n if (isCameraDeniedOrPrompted) {\n return 'Как разрешить камеру';\n }\n return null;\n }, [isMicrophoneDeniedOrPrompted, isCameraDeniedOrPrompted]);\n\n const renderVideo = useMemo(() => {\n if (!videoTrack || isCameraDeniedOrPrompted) {\n return null;\n }\n\n return (\n <div className=\"aspect-video h-full w-full transform-[rotateY(180deg)]\">\n <SecureVideo\n ref={videoEl}\n data-lk-facing-mode={facingMode}\n className=\"h-full w-full object-cover\"\n playsInline\n muted\n style={{\n display: !videoEnabled || isCameraDeniedOrPrompted ? 'none' : undefined,\n opacity: videoTrack?.isMuted || !isVideoInitiated ? 0 : 1,\n transition: 'opacity 0.3s ease-in-out',\n }}\n disablePictureInPicture\n disableRemotePlayback\n />\n </div>\n );\n }, [videoTrack, facingMode, videoEl, videoEnabled, isCameraDeniedOrPrompted, isVideoInitiated]);\n\n const renderAvatar = useMemo(() => {\n if (videoTrack && !videoTrack.isMuted && !isCameraDeniedOrPrompted) return null;\n\n return (\n <div className=\"bg-gray-40 flex items-center justify-center rounded-[16px]\">\n <Avatar size=\"xxl\">\n <AvatarImage\n src={`https://api.sovlium.ru/files/users/${userId}/avatar.webp`}\n alt=\"user avatar\"\n />\n <AvatarFallback size=\"xxl\" loading />\n </Avatar>\n </div>\n );\n }, [videoTrack, userId, isCameraDeniedOrPrompted]);\n\n return (\n <div className=\"bg-gray-40 relative flex aspect-video h-full w-full items-center justify-center overflow-hidden rounded-[16px]\">\n <div className=\"relative h-full w-full\">\n {renderVideo}\n {renderAvatar}\n\n {isPermissionsBlocked && (\n <div className=\"bg-opacity-60 absolute inset-0 flex flex-col items-center justify-center gap-4 bg-black p-6 text-center\">\n <p className=\"text-lg font-normal text-white\">\n Хотите, чтобы другие участники услышали вас?\n </p>\n <ol className=\"list-inside list-decimal space-y-2 text-left text-sm text-white\">\n {permissionsInstructions.map((instruction, index) => (\n <li key={index} className=\"flex items-start gap-2\">\n {index === 0 && !isSafari() && <Settings className=\"mt-0.5 h-4 w-4 shrink-0\" />}\n <span>{instruction}</span>\n </li>\n ))}\n </ol>\n <p className=\"text-gray-30 text-sm\">\n Камеру или микрофон можно отключить в любой момент.\n </p>\n {permissionsButtonLabel && (\n <Button size=\"m\" variant=\"ghost\" onClick={openPermissionsDialog}>\n {permissionsButtonLabel}\n </Button>\n )}\n </div>\n )}\n\n {!isPermissionsBlocked && hintMessage && (\n <div className=\"bg-opacity-60 absolute inset-0 flex flex-col items-center justify-center gap-4 bg-black p-6 text-center\">\n <p className=\"text-lg font-normal text-white\">{hintMessage}</p>\n </div>\n )}\n </div>\n\n <div className=\"absolute bottom-5 left-5\">\n <Controls audioTrack={audioTrack} videoTrack={videoTrack} />\n </div>\n </div>\n );\n};\n\ninterface UserTileProps {\n audioTrack?: LocalAudioTrack;\n videoTrack?: LocalVideoTrack;\n}\n\nexport const UserTile = ({ audioTrack, videoTrack }: UserTileProps) => {\n const { auth } = useCalls();\n const { data: user } = auth.useCurrentUser();\n const { userId } = user ?? {};\n\n const {\n userChoices: { videoEnabled },\n } = usePersistentUserChoices();\n\n const videoEl = useRef<HTMLVideoElement>(null);\n const [isVideoInitiated, setIsVideoInitiated] = useState(false);\n\n const isCameraDeniedOrPrompted = useCannotUseDevice('videoinput');\n const isMicrophoneDeniedOrPrompted = useCannotUseDevice('audioinput');\n\n const facingMode = useMemo(() => {\n if (videoTrack) {\n const { facingMode } = facingModeFromLocalTrack(videoTrack);\n return facingMode;\n }\n return 'undefined';\n }, [videoTrack]);\n\n useEffect(() => {\n if (!videoEnabled) {\n setIsVideoInitiated(false);\n }\n }, [videoEnabled]);\n\n useEffect(() => {\n if (videoTrack) {\n const handleTrackMuted = () => {\n setIsVideoInitiated(false);\n };\n\n const handleTrackUnmuted = () => {\n if (videoEnabled) {\n setIsVideoInitiated(true);\n }\n };\n\n videoTrack.on('muted', handleTrackMuted);\n videoTrack.on('unmuted', handleTrackUnmuted);\n\n return () => {\n videoTrack.off('muted', handleTrackMuted);\n videoTrack.off('unmuted', handleTrackUnmuted);\n };\n }\n }, [videoTrack, videoEnabled]);\n\n useEffect(() => {\n const currentVideoEl = videoEl.current;\n const currentVideoTrack = videoTrack;\n\n const handleVideoLoaded = () => {\n if (currentVideoEl && videoEnabled) {\n setIsVideoInitiated(true);\n currentVideoEl.style.opacity = '1';\n } else if (currentVideoEl) {\n currentVideoEl.style.opacity = '0';\n }\n };\n\n const handleVideoError = () => {\n setIsVideoInitiated(false);\n };\n\n if (currentVideoEl && currentVideoTrack && videoEnabled) {\n currentVideoTrack.attach(currentVideoEl);\n currentVideoEl.addEventListener('loadedmetadata', handleVideoLoaded);\n currentVideoEl.addEventListener('error', handleVideoError);\n }\n\n return () => {\n if (currentVideoTrack) {\n currentVideoTrack.detach();\n }\n if (currentVideoEl) {\n currentVideoEl.removeEventListener('loadedmetadata', handleVideoLoaded);\n currentVideoEl.removeEventListener('error', handleVideoError);\n currentVideoEl.style.opacity = '0';\n }\n };\n }, [videoTrack, videoEnabled]);\n\n return (\n <UserTileUI\n audioTrack={audioTrack}\n videoTrack={videoTrack}\n videoEnabled={videoEnabled}\n facingMode={facingMode}\n videoEl={videoEl}\n userId={userId || 'unknown'}\n isCameraDeniedOrPrompted={isCameraDeniedOrPrompted}\n isMicrophoneDeniedOrPrompted={isMicrophoneDeniedOrPrompted}\n isVideoInitiated={isVideoInitiated}\n />\n );\n};\n","import { SelectItem } from '@xipkg/select';\n\nexport type MediaDeviceKind = 'videoinput' | 'audiooutput' | 'audioinput';\n\ntype MediaDeviceSelectPropsT = {\n devices: MediaDeviceInfo[];\n};\n\nexport const MediaDeviceSelect = ({ devices }: MediaDeviceSelectPropsT) => (\n <ul>\n {devices &&\n devices.map((device) => (\n <li key={device.deviceId} id={device.deviceId}>\n <SelectItem value={device.deviceId ?? 'default'}>{device.label}</SelectItem>\n </li>\n ))}\n </ul>\n);\n","import React from 'react';\nimport { computeMenuPosition, wasClickOutside } from '@livekit/components-core';\nimport { Select, SelectContent, SelectGroup, SelectTrigger, SelectValue } from '@xipkg/select';\nimport { Conference, Microphone, SoundTwo } from '@xipkg/icons';\nimport { useMediaDeviceSelect } from '@livekit/components-react';\nimport { MediaDeviceKind, MediaDeviceSelect } from './MediaDeviceSelect';\n\nconst placeholders = {\n audioinput: 'Встроенный микрофон',\n audiooutput: 'Встроенные динамики',\n videoinput: 'Встроенная камера',\n default: 'По умолчанию',\n};\n\nexport interface MediaDeviceMenuProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n disabled?: boolean;\n kind: MediaDeviceKind;\n initialSelection: string | undefined;\n onActiveDeviceChange?: (kind: MediaDeviceKind, deviceId: string) => void;\n warnDisable?: boolean;\n requestPermissions?: boolean;\n}\n\nexport const MediaDeviceMenu = ({\n warnDisable,\n kind,\n initialSelection,\n onActiveDeviceChange,\n disabled,\n requestPermissions = false,\n}: MediaDeviceMenuProps) => {\n const [isOpen, setIsOpen] = React.useState(false);\n const [updateRequired, setUpdateRequired] = React.useState<boolean>(true);\n const [, setNeedPermissions] = React.useState(requestPermissions);\n const button = React.useRef<HTMLButtonElement>(null);\n const tooltip = React.useRef<HTMLDivElement>(null);\n\n const handleError = React.useCallback((e: Error) => {\n console.error('Media device error:', e);\n }, []);\n const { devices, setActiveMediaDevice } = useMediaDeviceSelect({\n kind,\n room: undefined, // Для PreJoin не нужна комната\n requestPermissions,\n onError: handleError,\n });\n\n React.useLayoutEffect(() => {\n if (isOpen) {\n setNeedPermissions(true);\n }\n }, [isOpen]);\n\n React.useLayoutEffect(() => {\n if (button.current && tooltip.current && (devices || updateRequired)) {\n const handlePositionChange = (x: number, y: number) => {\n if (tooltip.current) {\n tooltip.current.style.left = `${x}px`;\n tooltip.current.style.top = `${y}px`;\n }\n };\n\n computeMenuPosition(button.current, tooltip.current, handlePositionChange);\n }\n setUpdateRequired(false);\n }, [button, tooltip, updateRequired, devices]);\n\n const handleClickOutside = React.useCallback(\n (event: MouseEvent) => {\n if (!tooltip.current) {\n return;\n }\n if (event.target === button.current) {\n return;\n }\n if (isOpen && wasClickOutside(tooltip.current, event)) {\n setIsOpen(false);\n }\n },\n [isOpen, tooltip, button],\n );\n\n React.useEffect(() => {\n document.addEventListener<'click'>('click', handleClickOutside);\n window.addEventListener<'resize'>('resize', () => setUpdateRequired(true));\n return () => {\n document.removeEventListener<'click'>('click', handleClickOutside);\n window.removeEventListener<'resize'>('resize', () => setUpdateRequired(true));\n };\n }, [handleClickOutside, setUpdateRequired]);\n\n const getPlaceholder = () => {\n if (initialSelection === '') return placeholders.default;\n if (!initialSelection && kind) {\n return placeholders[kind] || placeholders.default;\n }\n return placeholders.default;\n };\n async function handleActiveChange(deviceId: string, kind: MediaDeviceKind) {\n setIsOpen(false);\n onActiveDeviceChange?.(kind, deviceId);\n await setActiveMediaDevice(deviceId);\n }\n\n return (\n <div className={`${warnDisable ? 'border-orange-80 rounded-lg border-2' : null}`}>\n <Select\n onValueChange={(value) => handleActiveChange(value, kind)}\n defaultValue={devices?.length > 0 ? initialSelection : undefined}\n disabled={\n disabled || warnDisable || !devices || devices.length === 0 || devices[0].deviceId === ''\n }\n >\n <SelectTrigger\n className=\"flex w-full flex-row\"\n before={\n <div>\n {kind === 'videoinput' && <Conference width={14} />}\n {kind === 'audiooutput' && <SoundTwo width={14} />}\n {!(kind === 'videoinput' || kind === 'audiooutput') && <Microphone width={14} />}\n </div>\n }\n >\n <SelectValue placeholder={getPlaceholder()} />\n </SelectTrigger>\n <SelectContent\n ref={(ref) => ref?.addEventListener('touchend', (e) => e.preventDefault())}\n className=\"w-full\"\n >\n {devices.length !== 0 && devices[0].deviceId !== '' && (\n <SelectGroup>\n <MediaDeviceSelect devices={devices} />\n </SelectGroup>\n )}\n </SelectContent>\n </Select>\n </div>\n );\n};\n","import { useMemo } from 'react';\nimport { Button } from '@xipkg/button';\nimport { Switch } from '@xipkg/switcher';\nimport { Label } from '@xipkg/label';\nimport { Alert, AlertIcon, AlertContainer, AlertDescription } from '@xipkg/alert';\nimport { InfoCircle } from '@xipkg/icons';\nimport { MediaDeviceMenu } from './MediaDeviceMenu';\nimport { LocalAudioTrack, LocalVideoTrack } from 'livekit-client';\nimport { UseNoiseCancellationResult, usePersistentUserChoices } from '@xipkg/calls-hooks';\nimport { useCallStore, usePermissionsStore } from '@xipkg/calls-store';\nimport { useRoom } from '@xipkg/calls-providers';\nimport { supportsBackgroundProcessors } from '@livekit/track-processors';\nimport { NoiseCancellationSettings } from '@xipkg/calls-ui';\n\ninterface MediaDevicesProps {\n audioTrack?: LocalAudioTrack;\n videoTrack?: LocalVideoTrack;\n noiseCancellation?: UseNoiseCancellationResult;\n}\n\nexport const MediaDevices = ({ audioTrack, videoTrack, noiseCancellation }: MediaDevicesProps) => {\n const {\n userChoices: { audioDeviceId, audioOutputDeviceId, videoDeviceId, blurEnabled },\n saveAudioInputDeviceId,\n saveAudioOutputDeviceId,\n saveVideoInputDeviceId,\n saveAudioInputEnabled,\n saveVideoInputEnabled,\n saveBlurEnabled,\n } = usePersistentUserChoices();\n\n const { updateStore, token, isConnecting } = useCallStore();\n const { room } = useRoom();\n const cameraPermission = usePermissionsStore((s) => s.cameraPermission);\n const microphonePermission = usePermissionsStore((s) => s.microphonePermission);\n\n const isBlurSupported = supportsBackgroundProcessors();\n\n // Ключи по разрешениям: при смене denied → granted меню перемонтируется и заново запрашивает список устройств\n const videoMenuKey = `videoinput-${cameraPermission}`;\n const audioInputMenuKey = `audioinput-${microphonePermission}`;\n const audioOutputMenuKey = `audiooutput-${microphonePermission}`;\n\n const handleJoin = async () => {\n if (!token) {\n console.error('No token available for joining the call');\n return;\n }\n\n // Проверяем, не подключены ли уже\n if (room.state === 'connected') {\n console.log('Already connected to room, just updating store...');\n // Если уже подключены, просто обновляем store\n updateStore('connect', true);\n updateStore('isStarted', true);\n updateStore('isConnecting', false);\n return;\n }\n\n if (isConnecting) {\n // console.log('Already connecting to room...');\n return;\n }\n\n // Устанавливаем флаг подключения\n updateStore('isConnecting', true);\n\n try {\n // Сохраняем текущие настройки устройств в store\n updateStore('audioDeviceId', audioDeviceId);\n updateStore('audioOutputDeviceId', audioOutputDeviceId);\n updateStore('videoDeviceId', videoDeviceId);\n\n // Сохраняем состояние аудио и видео\n updateStore('audioEnabled', audioTrack ? !audioTrack.isMuted : false);\n updateStore('videoEnabled', videoTrack ? !videoTrack.isMuted : false);\n\n // console.log('Preparing to join room...');\n\n // LiveKitRoom автоматически управляет подключением\n // Нам нужно только установить флаг подключения\n updateStore('connect', true);\n updateStore('isStarted', true);\n updateStore('isConnecting', false);\n\n // console.log('Successfully joined room with devices:', {\n // audioDeviceId,\n // audioOutputDeviceId,\n // videoDeviceId,\n // audioEnabled: audioTrack ? !audioTrack.isMuted : false,\n // videoEnabled: videoTrack ? !videoTrack.isMuted : false,\n // });\n } catch (error) {\n console.error('Failed to join room:', error);\n\n // Сбрасываем состояние при ошибке\n updateStore('connect', false);\n updateStore('isStarted', false);\n updateStore('isConnecting', false);\n\n // Если это ошибка отключения клиента, не показываем пользователю\n if (error instanceof Error && error.message.includes('Client initiated disconnect')) {\n console.log('Connection was cancelled by client - this is normal during navigation');\n return;\n }\n\n // Для других ошибок можно показать уведомление пользователю\n console.warn('Connection failed, please try again');\n }\n };\n\n // Обработчики переключения устройств с обработкой ошибок\n const handleAudioDeviceChange = useMemo(\n () => async (_kind: MediaDeviceKind, deviceId: string) => {\n try {\n saveAudioInputDeviceId(deviceId);\n if (audioTrack) {\n await audioTrack.setDeviceId({ exact: deviceId });\n // Синхронизируем состояние после смены устройства\n const isActuallyEnabled = !audioTrack.isMuted;\n // console.log('MediaDevices: audio device changed, syncing state', {\n // deviceId,\n // trackMuted: audioTrack.isMuted,\n // shouldBeEnabled: isActuallyEnabled,\n // });\n saveAudioInputEnabled(isActuallyEnabled);\n }\n } catch (err) {\n console.error('Failed to switch microphone device', err);\n }\n },\n [audioTrack, saveAudioInputDeviceId, saveAudioInputEnabled],\n );\n\n const handleVideoDeviceChange = useMemo(\n () => async (_kind: MediaDeviceKind, deviceId: string) => {\n try {\n saveVideoInputDeviceId(deviceId);\n if (videoTrack) {\n await videoTrack.setDeviceId({ exact: deviceId });\n // Синхронизируем состояние после смены устройства\n const isActuallyEnabled = !videoTrack.isMuted;\n // console.log('MediaDevices: video device changed, syncing state', {\n // deviceId,\n // trackMuted: videoTrack.isMuted,\n // shouldBeEnabled: isActuallyEnabled,\n // });\n saveVideoInputEnabled(isActuallyEnabled);\n }\n } catch (err) {\n console.error('Failed to switch camera device', err);\n }\n },\n [videoTrack, saveVideoInputDeviceId, saveVideoInputEnabled],\n );\n\n return (\n <div className=\"flex flex-col gap-4\">\n <div className=\"border-gray-30 flex flex-col justify-between rounded-[16px] border p-5\">\n <div>\n <div className=\"mb-8\">\n <h2 className=\"mb-1 font-sans\">Камера</h2>\n <MediaDeviceMenu\n key={videoMenuKey}\n initialSelection={videoDeviceId}\n kind=\"videoinput\"\n onActiveDeviceChange={handleVideoDeviceChange}\n disabled={cameraPermission !== 'granted'}\n />\n </div>\n <div className=\"my-4\">\n <h2 className=\"mb-1 font-sans\">Звук</h2>\n <div className=\"flex flex-col gap-2\">\n <MediaDeviceMenu\n key={audioInputMenuKey}\n initialSelection={audioDeviceId}\n kind=\"audioinput\"\n onActiveDeviceChange={handleAudioDeviceChange}\n disabled={microphonePermission !== 'granted'}\n />\n <MediaDeviceMenu\n key={audioOutputMenuKey}\n initialSelection={audioOutputDeviceId}\n kind=\"audiooutput\"\n onActiveDeviceChange={(_, id) => saveAudioOutputDeviceId(id)}\n disabled={microphonePermission !== 'granted'}\n />\n </div>\n </div>\n {isBlurSupported && (\n <div className=\"my-4\">\n <div className=\"flex items-center justify-between\">\n <Label className=\"font-medium text-gray-100\">Размытие фона</Label>\n <Switch checked={blurEnabled} onCheckedChange={saveBlurEnabled} />\n </div>\n </div>\n )}\n {noiseCancellation && (\n <div className=\"my-4\">\n <NoiseCancellationSettings nc={noiseCancellation} hideOffOption />\n </div>\n )}\n </div>\n <Button onClick={() => handleJoin()} className=\"w-full\" disabled={isConnecting}>\n {isConnecting ? 'Подключение...' : 'Присоединиться'}\n </Button>\n </div>\n <Alert className=\"h-full w-full max-w-[1720px]\" variant=\"brand\">\n <AlertIcon>\n <InfoCircle className=\"fill-brand-100\" />\n </AlertIcon>\n <AlertContainer className=\"h-full\">\n <AlertDescription>\n Перед началом занятия рекомендуется выбрать устройства для видео и звука. Если\n устройства не доступны, проверьте настройки браузера. Необходимое разрешение на\n использование микрофона и камеры будет запрошено автоматически.\n </AlertDescription>\n </AlertContainer>\n </Alert>\n </div>\n );\n};\n","import { ScrollArea } from '@xipkg/scrollarea';\nimport { Header, UserTile, MediaDevices } from './components';\nimport { PermissionsDialog } from '@xipkg/calls-ui';\nimport { useMemo, useRef, useEffect, useCallback, useState } from 'react';\nimport {\n Track,\n LocalVideoTrack,\n LocalAudioTrack,\n createLocalVideoTrack,\n createLocalAudioTrack,\n} from 'livekit-client';\nimport { usePreviewTracks } from '@livekit/components-react';\nimport {\n useVideoBlur,\n useResolveInitiallyDefaultDeviceId,\n usePersistentUserChoices,\n} from '@xipkg/calls-hooks';\n\nexport const PreJoin = () => {\n const {\n userChoices: { audioEnabled, videoEnabled, audioDeviceId, videoDeviceId },\n saveAudioInputDeviceId,\n saveVideoInputDeviceId,\n } = usePersistentUserChoices();\n\n const initialUserChoices = useRef<{\n audioEnabled: boolean;\n videoEnabled: boolean;\n audioDeviceId: string;\n videoDeviceId: string;\n } | null>(null);\n\n // Сохраняем начальные настройки пользователя\n if (initialUserChoices.current === null) {\n initialUserChoices.current = {\n audioEnabled,\n videoEnabled,\n audioDeviceId,\n videoDeviceId,\n };\n }\n\n const onError = useCallback((e: Error) => {\n console.error('PreJoin ERROR:', e);\n }, []);\n\n // Автоматически запрашиваем разрешения при загрузке\n useEffect(() => {\n const requestPermissions = async () => {\n try {\n // Проверяем, есть ли уже разрешения\n const permissions = await navigator.permissions.query({ name: 'camera' as PermissionName });\n if (permissions.state === 'prompt') {\n // Запрашиваем разрешения\n const stream = await navigator.mediaDevices.getUserMedia({\n video: true,\n audio: true,\n });\n // Останавливаем поток, нам нужны только разрешения\n stream.getTracks().forEach((track) => track.stop());\n }\n } catch (error) {\n console.log('Permission request failed:', error);\n }\n };\n\n requestPermissions();\n }, []);\n\n // Preview треки - создаются только если пользователь изначально включил их\n const tracks = usePreviewTracks(\n {\n audio: !!initialUserChoices.current &&\n initialUserChoices.current?.audioEnabled && {\n deviceId: initialUserChoices.current.audioDeviceId,\n },\n video: !!initialUserChoices.current &&\n initialUserChoices.current?.videoEnabled && {\n deviceId: initialUserChoices.current.videoDeviceId,\n },\n },\n onError,\n );\n\n // Динамические треки - создаются \"just-in-time\" когда пользователь включает их\n const [dynamicVideoTrack, setDynamicVideoTrack] = useState<LocalVideoTrack | null>(null);\n const [dynamicAudioTrack, setDynamicAudioTrack] = useState<LocalAudioTrack | null>(null);\n\n const previewVideoTrack = useMemo(\n () => tracks?.filter((track) => track.kind === Track.Kind.Video)[0] as LocalVideoTrack,\n [tracks],\n );\n\n const previewAudioTrack = useMemo(\n () => tracks?.filter((track) => track.kind === Track.Kind.Audio)[0] as LocalAudioTrack,\n [tracks],\n );\n\n // Создаем динамический видео трек если пользователь включил камеру после загрузки\n useEffect(() => {\n const createVideoTrack = async () => {\n try {\n const track = await createLocalVideoTrack({\n deviceId: { exact: videoDeviceId },\n });\n setDynamicVideoTrack(track);\n } catch (error) {\n onError(error as Error);\n }\n };\n\n if (\n videoEnabled &&\n !initialUserChoices.current?.videoEnabled &&\n !previewVideoTrack &&\n !dynamicVideoTrack\n ) {\n createVideoTrack();\n }\n }, [videoEnabled, videoDeviceId, previewVideoTrack, dynamicVideoTrack, onError]);\n\n // Создаем динамический аудио трек если пользователь включил микрофон после загрузки\n useEffect(() => {\n const createAudioTrack = async () => {\n try {\n const track = await createLocalAudioTrack({\n deviceId: { exact: audioDeviceId },\n });\n setDynamicAudioTrack(track);\n } catch (error) {\n onError(error as Error);\n }\n };\n\n if (\n audioEnabled &&\n !initialUserChoices.current?.audioEnabled &&\n !previewAudioTrack &&\n !dynamicAudioTrack\n ) {\n createAudioTrack();\n }\n }, [audioEnabled, audioDeviceId, previewAudioTrack, dynamicAudioTrack, onError]);\n\n // Очистка динамических треков\n useEffect(() => {\n return () => {\n dynamicVideoTrack?.stop();\n };\n }, [dynamicVideoTrack]);\n\n useEffect(() => {\n return () => {\n dynamicAudioTrack?.stop();\n };\n }, [dynamicAudioTrack]);\n\n // Финальные треки (динамические имеют приоритет над preview)\n const videoTrack = dynamicVideoTrack || previewVideoTrack;\n const audioTrack = dynamicAudioTrack || previewAudioTrack;\n\n // Отладочная информация\n useEffect(() => {\n console.log('PreJoin tracks debug:', {\n initialUserChoices: initialUserChoices.current,\n videoEnabled,\n audioEnabled,\n videoDeviceId,\n audioDeviceId,\n tracks: tracks?.map((t) => ({ kind: t.kind, enabled: !t.isMuted })),\n previewVideoTrack: previewVideoTrack ? { enabled: !previewVideoTrack.isMuted } : null,\n previewAudioTrack: previewAudioTrack ? { enabled: !previewAudioTrack.isMuted } : null,\n dynamicVideoTrack: dynamicVideoTrack ? { enabled: !dynamicVideoTrack.isMuted } : null,\n dynamicAudioTrack: dynamicAudioTrack ? { enabled: !dynamicAudioTrack.isMuted } : null,\n finalVideoTrack: videoTrack ? { enabled: !videoTrack.isMuted } : null,\n finalAudioTrack: audioTrack ? { enabled: !audioTrack.isMuted } : null,\n });\n }, [\n tracks,\n previewVideoTrack,\n previewAudioTrack,\n dynamicVideoTrack,\n dynamicAudioTrack,\n videoTrack,\n audioTrack,\n videoEnabled,\n audioEnabled,\n videoDeviceId,\n audioDeviceId,\n ]);\n\n // Разрешаем device ID для треков\n useResolveInitiallyDefaultDeviceId(audioDeviceId, audioTrack, saveAudioInputDeviceId);\n useResolveInitiallyDefaultDeviceId(videoDeviceId, videoTrack, saveVideoInputDeviceId);\n\n // Передаем видеотрек для использования блюра\n useVideoBlur(videoTrack);\n\n return (\n <>\n <ScrollArea className=\"h-full w-full\">\n <div className=\"max-xs:p-4 p-4 pt-1\">\n <Header />\n <div className=\"grid grid-cols-1 gap-8 lg:grid-cols-2\">\n <UserTile audioTrack={audioTrack} videoTrack={videoTrack} />\n <MediaDevices audioTrack={audioTrack} videoTrack={videoTrack} />\n </div>\n </div>\n </ScrollArea>\n <PermissionsDialog />\n </>\n );\n};\n","import {\n ControlBarProps,\n useLocalParticipant,\n usePersistentUserChoices,\n useTrackToggle,\n} from '@livekit/components-react';\nimport { LocalAudioTrack, LocalVideoTrack, Track } from 'livekit-client';\nimport { useCallback } from 'react';\nimport { DisconnectButton, ScreenShareButton, WhiteBoardButton, DevicesBar } from '@xipkg/calls-ui';\nimport { ChatButton, useChatStore } from '@xipkg/calls-chat';\nimport { useCallStore, useFeaturesStore } from '@xipkg/calls-store';\nimport { cn } from '@xipkg/utils';\nimport { WhiteBoard } from '@xipkg/icons';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@xipkg/tooltip';\nimport { Button } from '@xipkg/button';\nimport { useRoom, useCalls, useCallsNavigation } from '@xipkg/calls-providers';\nimport { RaiseHandButton } from '@xipkg/calls-risehand';\n\nexport const BottomBar = ({ saveUserChoices = true }: ControlBarProps) => {\n const { saveAudioInputEnabled, saveVideoInputEnabled } = usePersistentUserChoices({\n preventSave: !saveUserChoices,\n });\n\n const { isMicrophoneEnabled, isCameraEnabled, microphoneTrack, cameraTrack } =\n useLocalParticipant();\n\n const microphoneToggle = useTrackToggle({\n source: Track.Source.Microphone,\n onChange: (enabled: boolean, isUserInitiated: boolean) => {\n if (isUserInitiated) {\n saveAudioInputEnabled(enabled);\n }\n },\n });\n\n const cameraToggle = useTrackToggle({\n source: Track.Source.Camera,\n onChange: (enabled: boolean, isUserInitiated: boolean) => {\n if (isUserInitiated) {\n saveVideoInputEnabled(enabled);\n }\n },\n });\n\n const handleMicrophoneToggle = useCallback(async () => {\n microphoneToggle.toggle();\n }, [microphoneToggle]);\n\n const handleCameraToggle = useCallback(async () => {\n cameraToggle.toggle();\n }, [cameraToggle]);\n\n const { isChatOpen } = useChatStore();\n const { mode, activeBoardId, activeClassroom, token } = useCallStore();\n const updateStore = useCallStore((state) => state.updateStore);\n const { room } = useRoom();\n const navigation = useCallsNavigation();\n\n const { useCurrentUser } = useCalls().auth;\n const { data: user } = useCurrentUser();\n const isTutor = user?.default_layout === 'tutor';\n\n const {\n chat: isChatEnabled,\n raiseHand: isRiseHandEnabled,\n whiteboard: isWhiteboardEnabled,\n } = useFeaturesStore((s) => s.features);\n\n const showBackToBoardButton =\n mode === 'full' &&\n activeBoardId &&\n activeClassroom &&\n room &&\n token &&\n room.state === 'connected';\n\n const handleBackToBoard = () => {\n if (!activeBoardId || !activeClassroom) {\n return;\n }\n\n if (!room || !token || room.state !== 'connected') {\n return;\n }\n\n updateStore('localFullView', false);\n updateStore('mode', 'compact');\n\n navigation.navigateToClassroomBoard(activeClassroom, activeBoardId);\n };\n\n return (\n <div className={cn('relative w-full', isChatOpen && 'invisible sm:visible')}>\n <div className=\"flex w-full flex-row justify-between p-4 pt-1\">\n <div />\n <div className=\"flex flex-row gap-4\">\n <div className=\"bg-gray-0 border-gray-10 flex h-[48px] w-[92px] items-center justify-center gap-1 rounded-[16px] border\">\n <DevicesBar\n microTrack={microphoneTrack?.track as LocalAudioTrack}\n microEnabled={isMicrophoneEnabled}\n microTrackToggle={{\n showIcon: true,\n source: Track.Source.Microphone,\n onChange: handleMicrophoneToggle,\n }}\n videoTrack={cameraTrack?.track as unknown as LocalVideoTrack}\n videoEnabled={isCameraEnabled}\n videoTrackToggle={{\n showIcon: true,\n source: Track.Source.Camera,\n onChange: handleCameraToggle,\n }}\n className=\"relative\"\n />\n </div>\n <div className=\"bg-gray-0 border-gray-10 flex h-[48px] items-center justify-center gap-1 rounded-[16px] border p-1\">\n <ScreenShareButton />\n {isWhiteboardEnabled && isTutor && <WhiteBoardButton />}\n {isChatEnabled && <ChatButton />}\n {isRiseHandEnabled && <RaiseHandButton />}\n </div>\n </div>\n <div className=\"relative flex flex-row items-center justify-center gap-4\">\n {showBackToBoardButton && (\n <Tooltip delayDuration={1000}>\n <TooltipTrigger asChild>\n <Button\n size=\"m\"\n variant=\"default\"\n onClick={handleBackToBoard}\n className=\"bg-brand-100 hover:bg-brand-80 absolute top-1 left-[-132px] m-0 h-10 w-[128px] rounded-xl px-2\"\n data-umami-event=\"call-back-to-board\"\n >\n <WhiteBoard className=\"fill-gray-0 h-5 w-5\" />\n <span className=\"text-gray-0 ml-2\">К доске</span>\n </Button>\n </TooltipTrigger>\n <TooltipContent side=\"top\" align=\"center\">\n Вернуться к доске для совместной работы\n </TooltipContent>\n </Tooltip>\n )}\n <div className=\"bg-gray-0 border-gray-10 flex h-[48px] w-[48px] items-center justify-center gap-1 rounded-[16px] border p-1\">\n <DisconnectButton />\n </div>\n </div>\n </div>\n </div>\n );\n};\n","import { useLocalParticipant } from '@livekit/components-react';\nimport { LocalVideoTrack } from 'livekit-client';\nimport { Chat } from '@xipkg/calls-chat';\nimport { UpBar, VideoGrid, CallsOnboarding } from '@xipkg/calls-ui';\nimport { useCallStore, useFeaturesStore } from '@xipkg/calls-store';\nimport { useVideoBlur, useParticipantJoinSync } from '@xipkg/calls-hooks';\nimport { useHandFocus } from '@xipkg/calls-risehand';\nimport { BottomBar } from '../Bottom/BottomBar';\nimport '@xipkg/calls-ui/video-security.css';\n\nexport const ActiveRoom = () => {\n const { chat: isChatEnabled } = useFeaturesStore((s) => s.features);\n\n // Автоматический фокус на участниках с поднятыми руками\n useHandFocus();\n // Синхронизация состояния при подключении новых участников\n useParticipantJoinSync();\n // Получаем видео трек для применения блюра\n const { cameraTrack } = useLocalParticipant();\n const videoTrack = cameraTrack?.track as LocalVideoTrack | undefined;\n\n // Применяем блюр только в полном режиме\n const mode = useCallStore((state) => state.mode);\n const videoTrackForBlur = mode === 'full' ? videoTrack : null;\n useVideoBlur(videoTrackForBlur);\n\n return (\n <div id=\"videoConferenceContainer\" className=\"bg-gray-0 h-full\">\n <div className=\"flex h-full flex-col justify-stretch\">\n <CallsOnboarding />\n <UpBar />\n <div className=\"flex h-full items-center justify-center gap-4 overflow-hidden p-4\">\n <div className=\"flex h-full w-full justify-center text-center text-gray-100\">\n <VideoGrid />\n </div>\n {isChatEnabled && <Chat />}\n </div>\n <BottomBar />\n </div>\n </div>\n );\n};\n","import { useEffect } from 'react';\nimport { useCallsNavigation } from '@xipkg/calls-providers';\nimport { useInitUserDevices, useVideoSecurity } from '@xipkg/calls-hooks';\nimport { useCallStore, useFocusModeStore } from '@xipkg/calls-store';\nimport { PreJoin } from './PreJoin';\nimport { ActiveRoom } from './Room';\nimport '@xipkg/calls-ui/video-security.css';\n\nexport const Call = () => {\n const isStarted = useCallStore((state) => state.isStarted);\n const focusMode = useFocusModeStore((s) => s.focusMode);\n const { pathname } = useCallsNavigation();\n\n useInitUserDevices();\n useVideoSecurity();\n\n const mode = useCallStore((state) => state.mode);\n const updateStore = useCallStore((state) => state.updateStore);\n\n useEffect(() => {\n const isOnCallPage = /^\\/call\\/[^/]+$/.test(pathname);\n\n if (isOnCallPage && mode === 'compact') {\n updateStore('mode', 'full');\n }\n }, [pathname, mode, updateStore]);\n\n return (\n <div\n className=\"h-full\"\n style={\n focusMode\n ? ({\n '--header-height': '0px',\n '--available-height':\n 'calc(100dvh - 0px - var(--upbar-height) - var(--bottom-bar-height))',\n } as React.CSSProperties)\n : undefined\n }\n >\n <div className=\"flex h-full w-full flex-col\">\n {isStarted ? (\n <div id=\"videoConferenceContainer\" className=\"bg-gray-5 h-full\">\n <ActiveRoom />\n </div>\n ) : (\n <PreJoin />\n )}\n </div>\n </div>\n );\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/ui/PreJoin/components/Header/Header.tsx","../src/ui/PreJoin/components/UserTile/Controls.tsx","../src/ui/PreJoin/components/UserTile/UserTile.tsx","../src/ui/PreJoin/components/MediaDevices/MediaDeviceSelect.tsx","../src/ui/PreJoin/components/MediaDevices/MediaDeviceMenu.tsx","../src/ui/PreJoin/components/MediaDevices/MediaDevices.tsx","../src/ui/PreJoin/PreJoin.tsx","../src/ui/Bottom/BottomBar.tsx","../src/ui/Room/ActiveRoom.tsx","../src/ui/Call.tsx"],"names":["jsx","useMemo","jsxs","Button","useCalls","usePersistentUserChoices","facingMode","kind","useRef","useCallback","useEffect","useState","Track","useCallStore","useRoom","useCallsNavigation","DevicesBar","Tooltip","TooltipTrigger","TooltipContent","useLocalParticipant","useVideoBlur"],"mappings":"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","file":"index.mjs","sourcesContent":["import { Button } from '@xipkg/button';\nimport { ArrowLeft } from '@xipkg/icons';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@xipkg/tooltip';\nimport { useCalls, useCallsNavigation } from '@xipkg/calls-providers';\n\n/* eslint-disable no-irregular-whitespace */\nexport const Header = () => {\n const navigation = useCallsNavigation();\n const callId = navigation.getCallId();\n\n const { room } = useCalls();\n const { data: classroom } = room.useGetClassroom(Number(callId));\n\n return (\n <div className=\"mb-4 flex flex-col items-start gap-2 sm:flex-row sm:items-center\">\n <div className=\"flex flex-row items-center gap-2\">\n <Tooltip delayDuration={1000}>\n <TooltipTrigger asChild>\n <Button\n onClick={() => {\n if (callId) {\n navigation.navigateToClassroom(callId);\n }\n }}\n type=\"button\"\n variant=\"none\"\n className=\"flex size-[40px] min-h-[40xp] min-w-[40px] items-center justify-center rounded-[12px] p-0\"\n >\n <ArrowLeft className=\"fill-gray-100\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\" align=\"start\">\n Вернуться в кабинет\n </TooltipContent>\n </Tooltip>\n <h1 className=\"text-xl-base font-semibold text-gray-100\">Присоединиться к занятию</h1>\n </div>\n <p className=\"text-s-base text-gray-60 pt-0 pl-12 align-baseline sm:pt-2 sm:pl-0\">\n {classroom?.name}\n </p>\n </div>\n );\n};\n","import { LocalAudioTrack, LocalVideoTrack, Track } from 'livekit-client';\nimport { useCallback, useMemo } from 'react';\n\nimport { DevicesBar } from '@xipkg/calls-ui';\nimport { usePersistentUserChoices } from '@xipkg/calls-hooks';\n\ntype ControlsProps = {\n audioTrack?: LocalAudioTrack;\n videoTrack?: LocalVideoTrack;\n};\n\nexport const Controls = ({ audioTrack, videoTrack }: ControlsProps) => {\n const {\n userChoices: { audioEnabled, videoEnabled },\n saveAudioInputEnabled,\n saveVideoInputEnabled,\n } = usePersistentUserChoices();\n\n const handleAudioChange = useCallback(\n async (enabled: boolean) => {\n // console.log('Controls: handleAudioChange', {\n // enabled,\n // audioTrack: !!audioTrack,\n // currentMuted: audioTrack?.isMuted,\n // });\n saveAudioInputEnabled(enabled);\n if (audioTrack) {\n if (enabled) {\n console.log('Controls: unmuting audio track');\n await audioTrack.unmute();\n } else {\n console.log('Controls: muting audio track');\n await audioTrack.mute();\n }\n console.log('Controls: audio track state after change', { muted: audioTrack.isMuted });\n } else {\n console.log('Controls: no audio track available');\n }\n },\n [audioTrack, saveAudioInputEnabled],\n );\n\n const handleVideoChange = useCallback(\n async (enabled: boolean) => {\n // console.log('Controls: handleVideoChange', {\n // enabled,\n // videoTrack: !!videoTrack,\n // currentMuted: videoTrack?.isMuted,\n // });\n saveVideoInputEnabled(enabled);\n if (videoTrack) {\n if (enabled) {\n console.log('Controls: unmuting video track');\n await videoTrack.unmute();\n } else {\n console.log('Controls: muting video track');\n await videoTrack.mute();\n }\n console.log('Controls: video track state after change', { muted: videoTrack.isMuted });\n } else {\n console.log('Controls: no video track available');\n }\n },\n [videoTrack, saveVideoInputEnabled],\n );\n\n const microTrackToggle = useMemo(\n () => ({\n showIcon: true,\n source: Track.Source.Microphone,\n onChange: handleAudioChange,\n }),\n [handleAudioChange],\n );\n\n const videoTrackToggle = useMemo(\n () => ({\n showIcon: true,\n source: Track.Source.Camera,\n onChange: handleVideoChange,\n }),\n [handleVideoChange],\n );\n\n return (\n <div className=\"bg-gray-0 border-gray-10 flex h-[48px] w-[92px] items-center justify-center gap-1 rounded-[16px] border\">\n <DevicesBar\n microTrack={audioTrack}\n microEnabled={audioEnabled}\n microTrackToggle={microTrackToggle}\n videoTrack={videoTrack}\n videoEnabled={videoEnabled}\n videoTrackToggle={videoTrackToggle}\n />\n </div>\n );\n};\n","import { Avatar, AvatarFallback, AvatarImage } from '@xipkg/avatar';\nimport { useMemo, useRef, useEffect, useState } from 'react';\nimport { facingModeFromLocalTrack, LocalVideoTrack, LocalAudioTrack } from 'livekit-client';\nimport { Controls } from './Controls';\nimport { useCannotUseDevice, usePersistentUserChoices } from '@xipkg/calls-hooks';\nimport { openPermissionsDialog } from '@xipkg/calls-store';\nimport { Button } from '@xipkg/button';\nimport { SecureVideo } from '@xipkg/calls-ui';\nimport { Settings } from '@xipkg/icons';\nimport { isSafari } from '@xipkg/calls-utils';\nimport { useCalls } from '@xipkg/calls-providers';\n\nconst UserTileUI = ({\n audioTrack,\n videoTrack,\n videoEnabled,\n facingMode,\n videoEl,\n userId,\n isCameraDeniedOrPrompted,\n isMicrophoneDeniedOrPrompted,\n isVideoInitiated,\n}: {\n audioTrack?: LocalAudioTrack;\n videoTrack?: LocalVideoTrack;\n videoEnabled: boolean;\n facingMode: string;\n videoEl: React.RefObject<HTMLVideoElement | null>;\n userId: string;\n isCameraDeniedOrPrompted: boolean;\n isMicrophoneDeniedOrPrompted: boolean;\n isVideoInitiated: boolean;\n}) => {\n const isPermissionsBlocked = isCameraDeniedOrPrompted || isMicrophoneDeniedOrPrompted;\n\n const hintMessage = useMemo(() => {\n if (isPermissionsBlocked) {\n return null;\n }\n if (isCameraDeniedOrPrompted) {\n return isMicrophoneDeniedOrPrompted\n ? 'Камера и микрофон не разрешены'\n : 'Камера не разрешена';\n }\n if (!videoEnabled) {\n return 'Камера отключена';\n }\n if (!isVideoInitiated) {\n return 'Запуск камеры...';\n }\n if (videoTrack && videoEnabled) {\n return '';\n }\n return 'Камера недоступна';\n }, [\n videoTrack,\n videoEnabled,\n isCameraDeniedOrPrompted,\n isMicrophoneDeniedOrPrompted,\n isVideoInitiated,\n isPermissionsBlocked,\n ]);\n\n const permissionsInstructions = useMemo(() => {\n if (isSafari()) {\n const origin =\n typeof window !== 'undefined'\n ? (window.location?.origin?.replace('https://', '') ?? '')\n : '';\n return [\n `Нажмите на иконку ${origin} в адресной строке`,\n 'Снимите запрет на использование камеры и микрофона',\n ];\n }\n return [\n 'Нажмите на значок настроек в адресной строке браузера',\n 'Снимите запрет на использование камеры и микрофона',\n ];\n }, []);\n\n const permissionsButtonLabel = useMemo(() => {\n if (!isMicrophoneDeniedOrPrompted && !isCameraDeniedOrPrompted) {\n return null;\n }\n if (isCameraDeniedOrPrompted && isMicrophoneDeniedOrPrompted) {\n return 'Как разрешить камеру и микрофон';\n }\n if (isMicrophoneDeniedOrPrompted) {\n return 'Как разрешить микрофон';\n }\n if (isCameraDeniedOrPrompted) {\n return 'Как разрешить камеру';\n }\n return null;\n }, [isMicrophoneDeniedOrPrompted, isCameraDeniedOrPrompted]);\n\n const renderVideo = useMemo(() => {\n if (!videoTrack || isCameraDeniedOrPrompted) {\n return null;\n }\n\n return (\n <div className=\"aspect-video h-full w-full transform-[rotateY(180deg)]\">\n <SecureVideo\n ref={videoEl}\n data-lk-facing-mode={facingMode}\n className=\"h-full w-full object-cover\"\n playsInline\n muted\n style={{\n display: !videoEnabled || isCameraDeniedOrPrompted ? 'none' : undefined,\n opacity: videoTrack?.isMuted || !isVideoInitiated ? 0 : 1,\n transition: 'opacity 0.3s ease-in-out',\n }}\n disablePictureInPicture\n disableRemotePlayback\n />\n </div>\n );\n }, [videoTrack, facingMode, videoEl, videoEnabled, isCameraDeniedOrPrompted, isVideoInitiated]);\n\n const renderAvatar = useMemo(() => {\n if (videoTrack && !videoTrack.isMuted && !isCameraDeniedOrPrompted) return null;\n\n return (\n <div className=\"bg-gray-40 flex items-center justify-center rounded-[16px]\">\n <Avatar size=\"xxl\">\n <AvatarImage\n src={`https://api.sovlium.ru/files/users/${userId}/avatar.webp`}\n alt=\"user avatar\"\n />\n <AvatarFallback size=\"xxl\" loading />\n </Avatar>\n </div>\n );\n }, [videoTrack, userId, isCameraDeniedOrPrompted]);\n\n return (\n <div className=\"bg-gray-40 relative flex aspect-video h-full w-full items-center justify-center overflow-hidden rounded-[16px]\">\n <div className=\"relative h-full w-full\">\n {renderVideo}\n {renderAvatar}\n\n {isPermissionsBlocked && (\n <div className=\"bg-opacity-60 absolute inset-0 flex flex-col items-center justify-center gap-4 bg-black p-6 text-center\">\n <p className=\"text-lg font-normal text-white\">\n Хотите, чтобы другие участники услышали вас?\n </p>\n <ol className=\"list-inside list-decimal space-y-2 text-left text-sm text-white\">\n {permissionsInstructions.map((instruction, index) => (\n <li key={index} className=\"flex items-start gap-2\">\n {index === 0 && !isSafari() && <Settings className=\"mt-0.5 h-4 w-4 shrink-0\" />}\n <span>{instruction}</span>\n </li>\n ))}\n </ol>\n <p className=\"text-gray-30 text-sm\">\n Камеру или микрофон можно отключить в любой момент.\n </p>\n {permissionsButtonLabel && (\n <Button size=\"m\" variant=\"ghost\" onClick={openPermissionsDialog}>\n {permissionsButtonLabel}\n </Button>\n )}\n </div>\n )}\n\n {!isPermissionsBlocked && hintMessage && (\n <div className=\"bg-opacity-60 absolute inset-0 flex flex-col items-center justify-center gap-4 bg-black p-6 text-center\">\n <p className=\"text-lg font-normal text-white\">{hintMessage}</p>\n </div>\n )}\n </div>\n\n <div className=\"absolute bottom-5 left-5\">\n <Controls audioTrack={audioTrack} videoTrack={videoTrack} />\n </div>\n </div>\n );\n};\n\ninterface UserTileProps {\n audioTrack?: LocalAudioTrack;\n videoTrack?: LocalVideoTrack;\n}\n\nexport const UserTile = ({ audioTrack, videoTrack }: UserTileProps) => {\n const { auth } = useCalls();\n const { data: user } = auth.useCurrentUser();\n const { userId } = user ?? {};\n\n const {\n userChoices: { videoEnabled },\n } = usePersistentUserChoices();\n\n const videoEl = useRef<HTMLVideoElement>(null);\n const [isVideoInitiated, setIsVideoInitiated] = useState(false);\n\n const isCameraDeniedOrPrompted = useCannotUseDevice('videoinput');\n const isMicrophoneDeniedOrPrompted = useCannotUseDevice('audioinput');\n\n const facingMode = useMemo(() => {\n if (videoTrack) {\n const { facingMode } = facingModeFromLocalTrack(videoTrack);\n return facingMode;\n }\n return 'undefined';\n }, [videoTrack]);\n\n useEffect(() => {\n if (!videoEnabled) {\n setIsVideoInitiated(false);\n }\n }, [videoEnabled]);\n\n useEffect(() => {\n if (videoTrack) {\n const handleTrackMuted = () => {\n setIsVideoInitiated(false);\n };\n\n const handleTrackUnmuted = () => {\n if (videoEnabled) {\n setIsVideoInitiated(true);\n }\n };\n\n videoTrack.on('muted', handleTrackMuted);\n videoTrack.on('unmuted', handleTrackUnmuted);\n\n return () => {\n videoTrack.off('muted', handleTrackMuted);\n videoTrack.off('unmuted', handleTrackUnmuted);\n };\n }\n }, [videoTrack, videoEnabled]);\n\n useEffect(() => {\n const currentVideoEl = videoEl.current;\n const currentVideoTrack = videoTrack;\n\n const handleVideoLoaded = () => {\n if (currentVideoEl && videoEnabled) {\n setIsVideoInitiated(true);\n currentVideoEl.style.opacity = '1';\n } else if (currentVideoEl) {\n currentVideoEl.style.opacity = '0';\n }\n };\n\n const handleVideoError = () => {\n setIsVideoInitiated(false);\n };\n\n if (currentVideoEl && currentVideoTrack && videoEnabled) {\n currentVideoTrack.attach(currentVideoEl);\n currentVideoEl.addEventListener('loadedmetadata', handleVideoLoaded);\n currentVideoEl.addEventListener('error', handleVideoError);\n }\n\n return () => {\n if (currentVideoTrack) {\n currentVideoTrack.detach();\n }\n if (currentVideoEl) {\n currentVideoEl.removeEventListener('loadedmetadata', handleVideoLoaded);\n currentVideoEl.removeEventListener('error', handleVideoError);\n currentVideoEl.style.opacity = '0';\n }\n };\n }, [videoTrack, videoEnabled]);\n\n return (\n <UserTileUI\n audioTrack={audioTrack}\n videoTrack={videoTrack}\n videoEnabled={videoEnabled}\n facingMode={facingMode}\n videoEl={videoEl}\n userId={userId || 'unknown'}\n isCameraDeniedOrPrompted={isCameraDeniedOrPrompted}\n isMicrophoneDeniedOrPrompted={isMicrophoneDeniedOrPrompted}\n isVideoInitiated={isVideoInitiated}\n />\n );\n};\n","import { SelectItem } from '@xipkg/select';\n\nexport type MediaDeviceKind = 'videoinput' | 'audiooutput' | 'audioinput';\n\ntype MediaDeviceSelectPropsT = {\n devices: MediaDeviceInfo[];\n};\n\nexport const MediaDeviceSelect = ({ devices }: MediaDeviceSelectPropsT) => (\n <ul>\n {devices &&\n devices.map((device) => (\n <li key={device.deviceId} id={device.deviceId}>\n <SelectItem className=\"h-auto\" value={device.deviceId ?? 'default'}>\n {device.label}\n </SelectItem>\n </li>\n ))}\n </ul>\n);\n","import React from 'react';\nimport { computeMenuPosition, wasClickOutside } from '@livekit/components-core';\nimport { Select, SelectContent, SelectGroup, SelectTrigger, SelectValue } from '@xipkg/select';\nimport { Conference, Microphone, SoundTwo } from '@xipkg/icons';\nimport { useMediaDeviceSelect } from '@livekit/components-react';\nimport { MediaDeviceKind, MediaDeviceSelect } from './MediaDeviceSelect';\n\nconst placeholders = {\n audioinput: 'Встроенный микрофон',\n audiooutput: 'Встроенные динамики',\n videoinput: 'Встроенная камера',\n default: 'По умолчанию',\n};\n\nexport interface MediaDeviceMenuProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n disabled?: boolean;\n kind: MediaDeviceKind;\n initialSelection: string | undefined;\n onActiveDeviceChange?: (kind: MediaDeviceKind, deviceId: string) => void;\n warnDisable?: boolean;\n requestPermissions?: boolean;\n}\n\nexport const MediaDeviceMenu = ({\n warnDisable,\n kind,\n initialSelection,\n onActiveDeviceChange,\n disabled,\n requestPermissions = false,\n}: MediaDeviceMenuProps) => {\n const [isOpen, setIsOpen] = React.useState(false);\n const [updateRequired, setUpdateRequired] = React.useState<boolean>(true);\n const [, setNeedPermissions] = React.useState(requestPermissions);\n const button = React.useRef<HTMLButtonElement>(null);\n const tooltip = React.useRef<HTMLDivElement>(null);\n\n const handleError = React.useCallback((e: Error) => {\n console.error('Media device error:', e);\n }, []);\n const { devices, setActiveMediaDevice } = useMediaDeviceSelect({\n kind,\n room: undefined, // Для PreJoin не нужна комната\n requestPermissions,\n onError: handleError,\n });\n\n React.useLayoutEffect(() => {\n if (isOpen) {\n setNeedPermissions(true);\n }\n }, [isOpen]);\n\n React.useLayoutEffect(() => {\n if (button.current && tooltip.current && (devices || updateRequired)) {\n const handlePositionChange = (x: number, y: number) => {\n if (tooltip.current) {\n tooltip.current.style.left = `${x}px`;\n tooltip.current.style.top = `${y}px`;\n }\n };\n\n computeMenuPosition(button.current, tooltip.current, handlePositionChange);\n }\n setUpdateRequired(false);\n }, [button, tooltip, updateRequired, devices]);\n\n const handleClickOutside = React.useCallback(\n (event: MouseEvent) => {\n if (!tooltip.current) {\n return;\n }\n if (event.target === button.current) {\n return;\n }\n if (isOpen && wasClickOutside(tooltip.current, event)) {\n setIsOpen(false);\n }\n },\n [isOpen, tooltip, button],\n );\n\n React.useEffect(() => {\n document.addEventListener<'click'>('click', handleClickOutside);\n window.addEventListener<'resize'>('resize', () => setUpdateRequired(true));\n return () => {\n document.removeEventListener<'click'>('click', handleClickOutside);\n window.removeEventListener<'resize'>('resize', () => setUpdateRequired(true));\n };\n }, [handleClickOutside, setUpdateRequired]);\n\n const getPlaceholder = () => {\n if (initialSelection === '') return placeholders.default;\n if (!initialSelection && kind) {\n return placeholders[kind] || placeholders.default;\n }\n return placeholders.default;\n };\n async function handleActiveChange(deviceId: string, kind: MediaDeviceKind) {\n setIsOpen(false);\n onActiveDeviceChange?.(kind, deviceId);\n await setActiveMediaDevice(deviceId);\n }\n\n return (\n <div className={`${warnDisable ? 'border-orange-80 rounded-lg border-2' : null}`}>\n <Select\n onValueChange={(value) => handleActiveChange(value, kind)}\n defaultValue={devices?.length > 0 ? initialSelection : undefined}\n disabled={\n disabled || warnDisable || !devices || devices.length === 0 || devices[0].deviceId === ''\n }\n >\n <SelectTrigger\n className=\"flex w-full flex-row\"\n before={\n <div>\n {kind === 'videoinput' && <Conference width={14} />}\n {kind === 'audiooutput' && <SoundTwo width={14} />}\n {!(kind === 'videoinput' || kind === 'audiooutput') && <Microphone width={14} />}\n </div>\n }\n >\n <SelectValue placeholder={getPlaceholder()} />\n </SelectTrigger>\n <SelectContent\n ref={(ref) => ref?.addEventListener('touchend', (e) => e.preventDefault())}\n className=\"w-full\"\n >\n {devices.length !== 0 && devices[0].deviceId !== '' && (\n <SelectGroup>\n <MediaDeviceSelect devices={devices} />\n </SelectGroup>\n )}\n </SelectContent>\n </Select>\n </div>\n );\n};\n","import { useMemo } from 'react';\nimport { Button } from '@xipkg/button';\nimport { Toggle } from '@xipkg/toggle';\nimport { Label } from '@xipkg/label';\nimport { Alert, AlertIcon, AlertContainer, AlertDescription } from '@xipkg/alert';\nimport { InfoCircle } from '@xipkg/icons';\nimport { MediaDeviceMenu } from './MediaDeviceMenu';\nimport { LocalAudioTrack, LocalVideoTrack } from 'livekit-client';\nimport { UseNoiseCancellationResult, usePersistentUserChoices } from '@xipkg/calls-hooks';\nimport { useCallStore, usePermissionsStore } from '@xipkg/calls-store';\nimport { useRoom } from '@xipkg/calls-providers';\nimport { supportsBackgroundProcessors } from '@livekit/track-processors';\nimport { NoiseCancellationSettings } from '@xipkg/calls-ui';\n\ninterface MediaDevicesProps {\n audioTrack?: LocalAudioTrack;\n videoTrack?: LocalVideoTrack;\n noiseCancellation?: UseNoiseCancellationResult;\n}\n\nexport const MediaDevices = ({ audioTrack, videoTrack, noiseCancellation }: MediaDevicesProps) => {\n const {\n userChoices: { audioDeviceId, audioOutputDeviceId, videoDeviceId, blurEnabled },\n saveAudioInputDeviceId,\n saveAudioOutputDeviceId,\n saveVideoInputDeviceId,\n saveAudioInputEnabled,\n saveVideoInputEnabled,\n saveBlurEnabled,\n } = usePersistentUserChoices();\n\n const { updateStore, token, isConnecting } = useCallStore();\n const { room } = useRoom();\n const cameraPermission = usePermissionsStore((s) => s.cameraPermission);\n const microphonePermission = usePermissionsStore((s) => s.microphonePermission);\n\n const isBlurSupported = supportsBackgroundProcessors();\n\n // Ключи по разрешениям: при смене denied → granted меню перемонтируется и заново запрашивает список устройств\n const videoMenuKey = `videoinput-${cameraPermission}`;\n const audioInputMenuKey = `audioinput-${microphonePermission}`;\n const audioOutputMenuKey = `audiooutput-${microphonePermission}`;\n\n const handleJoin = async () => {\n if (!token) {\n console.error('No token available for joining the call');\n return;\n }\n\n // Проверяем, не подключены ли уже\n if (room.state === 'connected') {\n console.log('Already connected to room, just updating store...');\n // Если уже подключены, просто обновляем store\n updateStore('connect', true);\n updateStore('isStarted', true);\n updateStore('isConnecting', false);\n return;\n }\n\n if (isConnecting) {\n // console.log('Already connecting to room...');\n return;\n }\n\n // Устанавливаем флаг подключения\n updateStore('isConnecting', true);\n\n try {\n // Сохраняем текущие настройки устройств в store\n updateStore('audioDeviceId', audioDeviceId);\n updateStore('audioOutputDeviceId', audioOutputDeviceId);\n updateStore('videoDeviceId', videoDeviceId);\n\n // Сохраняем состояние аудио и видео\n updateStore('audioEnabled', audioTrack ? !audioTrack.isMuted : false);\n updateStore('videoEnabled', videoTrack ? !videoTrack.isMuted : false);\n\n // console.log('Preparing to join room...');\n\n // LiveKitRoom автоматически управляет подключением\n // Нам нужно только установить флаг подключения\n updateStore('connect', true);\n updateStore('isStarted', true);\n updateStore('isConnecting', false);\n\n // console.log('Successfully joined room with devices:', {\n // audioDeviceId,\n // audioOutputDeviceId,\n // videoDeviceId,\n // audioEnabled: audioTrack ? !audioTrack.isMuted : false,\n // videoEnabled: videoTrack ? !videoTrack.isMuted : false,\n // });\n } catch (error) {\n console.error('Failed to join room:', error);\n\n // Сбрасываем состояние при ошибке\n updateStore('connect', false);\n updateStore('isStarted', false);\n updateStore('isConnecting', false);\n\n // Если это ошибка отключения клиента, не показываем пользователю\n if (error instanceof Error && error.message.includes('Client initiated disconnect')) {\n console.log('Connection was cancelled by client - this is normal during navigation');\n return;\n }\n\n // Для других ошибок можно показать уведомление пользователю\n console.warn('Connection failed, please try again');\n }\n };\n\n // Обработчики переключения устройств с обработкой ошибок\n const handleAudioDeviceChange = useMemo(\n () => async (_kind: MediaDeviceKind, deviceId: string) => {\n try {\n saveAudioInputDeviceId(deviceId);\n if (audioTrack) {\n await audioTrack.setDeviceId({ exact: deviceId });\n // Синхронизируем состояние после смены устройства\n const isActuallyEnabled = !audioTrack.isMuted;\n // console.log('MediaDevices: audio device changed, syncing state', {\n // deviceId,\n // trackMuted: audioTrack.isMuted,\n // shouldBeEnabled: isActuallyEnabled,\n // });\n saveAudioInputEnabled(isActuallyEnabled);\n }\n } catch (err) {\n console.error('Failed to switch microphone device', err);\n }\n },\n [audioTrack, saveAudioInputDeviceId, saveAudioInputEnabled],\n );\n\n const handleVideoDeviceChange = useMemo(\n () => async (_kind: MediaDeviceKind, deviceId: string) => {\n try {\n saveVideoInputDeviceId(deviceId);\n if (videoTrack) {\n await videoTrack.setDeviceId({ exact: deviceId });\n // Синхронизируем состояние после смены устройства\n const isActuallyEnabled = !videoTrack.isMuted;\n // console.log('MediaDevices: video device changed, syncing state', {\n // deviceId,\n // trackMuted: videoTrack.isMuted,\n // shouldBeEnabled: isActuallyEnabled,\n // });\n saveVideoInputEnabled(isActuallyEnabled);\n }\n } catch (err) {\n console.error('Failed to switch camera device', err);\n }\n },\n [videoTrack, saveVideoInputDeviceId, saveVideoInputEnabled],\n );\n\n return (\n <div className=\"flex flex-col gap-4\">\n <div className=\"border-gray-30 bg-gray-0 flex flex-col justify-between rounded-2xl border p-5\">\n <div>\n <div className=\"mb-8\">\n <h2 className=\"mb-1 font-sans\">Камера</h2>\n <MediaDeviceMenu\n key={videoMenuKey}\n initialSelection={videoDeviceId}\n kind=\"videoinput\"\n onActiveDeviceChange={handleVideoDeviceChange}\n disabled={cameraPermission !== 'granted'}\n />\n </div>\n <div className=\"my-4\">\n <h2 className=\"mb-1 font-sans\">Звук</h2>\n <div className=\"flex flex-col gap-2\">\n <MediaDeviceMenu\n key={audioInputMenuKey}\n initialSelection={audioDeviceId}\n kind=\"audioinput\"\n onActiveDeviceChange={handleAudioDeviceChange}\n disabled={microphonePermission !== 'granted'}\n />\n <MediaDeviceMenu\n key={audioOutputMenuKey}\n initialSelection={audioOutputDeviceId}\n kind=\"audiooutput\"\n onActiveDeviceChange={(_, id) => saveAudioOutputDeviceId(id)}\n disabled={microphonePermission !== 'granted'}\n />\n </div>\n </div>\n {isBlurSupported && (\n <div className=\"my-4\">\n <div className=\"flex items-center justify-between\">\n <Label className=\"font-medium text-gray-100\">Размытие фона</Label>\n <Toggle checked={blurEnabled} onCheckedChange={saveBlurEnabled} />\n </div>\n </div>\n )}\n {noiseCancellation && (\n <div className=\"my-4\">\n <NoiseCancellationSettings nc={noiseCancellation} hideOffOption />\n </div>\n )}\n </div>\n <Button onClick={() => handleJoin()} className=\"w-full\" disabled={isConnecting}>\n {isConnecting ? 'Подключение...' : 'Присоединиться'}\n </Button>\n </div>\n <Alert className=\"h-full w-full max-w-[1720px]\" variant=\"brand\">\n <AlertIcon>\n <InfoCircle className=\"fill-brand-100\" />\n </AlertIcon>\n <AlertContainer className=\"h-full\">\n <AlertDescription>\n Перед началом занятия рекомендуется выбрать устройства для видео и звука. Если\n устройства не доступны, проверьте настройки браузера. Необходимое разрешение на\n использование микрофона и камеры будет запрошено автоматически.\n </AlertDescription>\n </AlertContainer>\n </Alert>\n </div>\n );\n};\n","import { ScrollArea } from '@xipkg/scrollarea';\nimport { Header, UserTile, MediaDevices } from './components';\nimport { useMemo, useRef, useEffect, useCallback, useState } from 'react';\nimport {\n Track,\n LocalVideoTrack,\n LocalAudioTrack,\n createLocalVideoTrack,\n createLocalAudioTrack,\n} from 'livekit-client';\nimport { usePreviewTracks } from '@livekit/components-react';\nimport { getBaselineAudioCaptureOptions } from '@xipkg/calls-config';\nimport {\n useVideoBlur,\n useResolveInitiallyDefaultDeviceId,\n usePersistentUserChoices,\n useNoiseCancellation,\n} from '@xipkg/calls-hooks';\nimport { useCallsRuntimeConfig } from '@xipkg/calls-providers';\n\nexport const PreJoin = () => {\n const {\n userChoices: { audioEnabled, videoEnabled, audioDeviceId, videoDeviceId },\n saveAudioInputDeviceId,\n saveVideoInputDeviceId,\n } = usePersistentUserChoices();\n\n const {\n noiseCancellation: { featureEnabled: noiseCancellationFeatureEnabled },\n } = useCallsRuntimeConfig();\n\n const initialUserChoices = useRef<{\n audioEnabled: boolean;\n videoEnabled: boolean;\n audioDeviceId: string;\n videoDeviceId: string;\n } | null>(null);\n\n // Сохраняем начальные настройки пользователя\n if (initialUserChoices.current === null) {\n initialUserChoices.current = {\n audioEnabled,\n videoEnabled,\n audioDeviceId,\n videoDeviceId,\n };\n }\n\n const onError = useCallback((e: Error) => {\n console.error('PreJoin ERROR:', e);\n }, []);\n\n // При входе в PreJoin запрашиваем разрешения — браузер покажет диалог при первом заходе.\n // Если пользователь отклонит или ещё не ответил, useWatchPermissions обновит store и покажем состояние «нет прав» на контролах.\n useEffect(() => {\n let cancelled = false;\n const request = async () => {\n try {\n const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });\n if (!cancelled) stream.getTracks().forEach((t) => t.stop());\n } catch {\n // Отказ или ошибка — состояние обработает useWatchPermissions и UI (перечёркнутые контролы)\n }\n };\n request();\n return () => {\n cancelled = true;\n };\n }, []);\n\n // Preview треки - создаются только если пользователь изначально включил их\n const baselineAudio = getBaselineAudioCaptureOptions();\n const tracks = usePreviewTracks(\n {\n audio: !!initialUserChoices.current &&\n initialUserChoices.current?.audioEnabled && {\n ...baselineAudio,\n deviceId: initialUserChoices.current.audioDeviceId,\n },\n video: !!initialUserChoices.current &&\n initialUserChoices.current?.videoEnabled && {\n deviceId: initialUserChoices.current.videoDeviceId,\n },\n },\n onError,\n );\n\n // Динамические треки - создаются \"just-in-time\" когда пользователь включает их\n const [dynamicVideoTrack, setDynamicVideoTrack] = useState<LocalVideoTrack | null>(null);\n const [dynamicAudioTrack, setDynamicAudioTrack] = useState<LocalAudioTrack | null>(null);\n\n const previewVideoTrack = useMemo(\n () => tracks?.filter((track) => track.kind === Track.Kind.Video)[0] as LocalVideoTrack,\n [tracks],\n );\n\n const previewAudioTrack = useMemo(\n () => tracks?.filter((track) => track.kind === Track.Kind.Audio)[0] as LocalAudioTrack,\n [tracks],\n );\n\n // Создаем динамический видео трек если пользователь включил камеру после загрузки\n useEffect(() => {\n const createVideoTrack = async () => {\n try {\n const track = await createLocalVideoTrack({\n deviceId: { exact: videoDeviceId },\n });\n setDynamicVideoTrack(track);\n } catch (error) {\n onError(error as Error);\n }\n };\n\n if (\n videoEnabled &&\n !initialUserChoices.current?.videoEnabled &&\n !previewVideoTrack &&\n !dynamicVideoTrack\n ) {\n createVideoTrack();\n }\n }, [videoEnabled, videoDeviceId, previewVideoTrack, dynamicVideoTrack, onError]);\n\n // Создаем динамический аудио трек если пользователь включил микрофон после загрузки\n useEffect(() => {\n const createAudioTrack = async () => {\n try {\n const track = await createLocalAudioTrack({\n ...getBaselineAudioCaptureOptions(),\n deviceId: { exact: audioDeviceId },\n });\n setDynamicAudioTrack(track);\n } catch (error) {\n onError(error as Error);\n }\n };\n\n if (\n audioEnabled &&\n !initialUserChoices.current?.audioEnabled &&\n !previewAudioTrack &&\n !dynamicAudioTrack\n ) {\n createAudioTrack();\n }\n }, [audioEnabled, audioDeviceId, previewAudioTrack, dynamicAudioTrack, onError]);\n\n // Очистка динамических треков\n useEffect(() => {\n return () => {\n dynamicVideoTrack?.stop();\n };\n }, [dynamicVideoTrack]);\n\n useEffect(() => {\n return () => {\n dynamicAudioTrack?.stop();\n };\n }, [dynamicAudioTrack]);\n\n // Финальные треки (динамические имеют приоритет над preview)\n const videoTrack = dynamicVideoTrack || previewVideoTrack;\n const audioTrack = dynamicAudioTrack || previewAudioTrack;\n\n // Разрешаем device ID для треков\n useResolveInitiallyDefaultDeviceId(audioDeviceId, audioTrack, saveAudioInputDeviceId);\n useResolveInitiallyDefaultDeviceId(videoDeviceId, videoTrack, saveVideoInputDeviceId);\n\n // Передаем видеотрек для использования блюра\n useVideoBlur(videoTrack);\n\n const noiseCancellation = useNoiseCancellation(null, {\n localAudioTrack: audioTrack ?? undefined,\n });\n\n return (\n <>\n <ScrollArea className=\"h-full w-full\">\n <div className=\"bg-gray-5 h-full min-h-[calc(100dvh)] p-5\">\n <Header />\n <div className=\"grid grid-cols-1 gap-8 lg:grid-cols-2\">\n <UserTile audioTrack={audioTrack} videoTrack={videoTrack} />\n <MediaDevices\n audioTrack={audioTrack}\n videoTrack={videoTrack}\n noiseCancellation={noiseCancellationFeatureEnabled ? noiseCancellation : undefined}\n />\n </div>\n </div>\n </ScrollArea>\n </>\n );\n};\n","import {\n ControlBarProps,\n useLocalParticipant,\n usePersistentUserChoices,\n useTrackToggle,\n} from '@livekit/components-react';\nimport { LocalAudioTrack, LocalVideoTrack, Track } from 'livekit-client';\nimport { useCallback } from 'react';\nimport { DisconnectButton, ScreenShareButton, WhiteBoardButton, DevicesBar } from '@xipkg/calls-ui';\nimport { ChatButton, useChatStore } from '@xipkg/calls-chat';\nimport { useCallStore } from '@xipkg/calls-store';\nimport { cn } from '@xipkg/utils';\nimport { WhiteBoard } from '@xipkg/icons';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@xipkg/tooltip';\nimport { Button } from '@xipkg/button';\nimport { useRoom, useCalls, useCallsNavigation } from '@xipkg/calls-providers';\nimport { RaiseHandButton } from '@xipkg/calls-risehand';\n\nexport const BottomBar = ({ saveUserChoices = true }: ControlBarProps) => {\n const { saveAudioInputEnabled, saveVideoInputEnabled } = usePersistentUserChoices({\n preventSave: !saveUserChoices,\n });\n\n const { isMicrophoneEnabled, isCameraEnabled, microphoneTrack, cameraTrack } =\n useLocalParticipant();\n\n const microphoneToggle = useTrackToggle({\n source: Track.Source.Microphone,\n onChange: (enabled: boolean, isUserInitiated: boolean) => {\n if (isUserInitiated) {\n saveAudioInputEnabled(enabled);\n }\n },\n });\n\n const cameraToggle = useTrackToggle({\n source: Track.Source.Camera,\n onChange: (enabled: boolean, isUserInitiated: boolean) => {\n if (isUserInitiated) {\n saveVideoInputEnabled(enabled);\n }\n },\n });\n\n const handleMicrophoneToggle = useCallback(async () => {\n microphoneToggle.toggle();\n }, [microphoneToggle]);\n\n const handleCameraToggle = useCallback(async () => {\n cameraToggle.toggle();\n }, [cameraToggle]);\n\n const { isChatOpen } = useChatStore();\n const { mode, activeBoardId, activeClassroom, token } = useCallStore();\n const updateStore = useCallStore((state) => state.updateStore);\n const { room } = useRoom();\n const navigation = useCallsNavigation();\n\n const { useCurrentUser } = useCalls().auth;\n const { data: user } = useCurrentUser();\n const isTutor = user?.default_layout === 'tutor';\n\n const showBackToBoardButton =\n mode === 'full' &&\n activeBoardId &&\n activeClassroom &&\n room &&\n token &&\n room.state === 'connected';\n\n const handleBackToBoard = () => {\n if (!activeBoardId || !activeClassroom) {\n return;\n }\n\n if (!room || !token || room.state !== 'connected') {\n return;\n }\n\n updateStore('localFullView', false);\n updateStore('mode', 'compact');\n\n navigation.navigateToClassroomBoard(activeClassroom, activeBoardId);\n };\n\n return (\n <div className={cn('relative w-full', isChatOpen && 'invisible sm:visible')}>\n <div className=\"flex w-full flex-row justify-between p-4 pt-1\">\n <div />\n <div className=\"flex flex-row gap-4\">\n <div className=\"bg-gray-0 border-gray-10 flex h-[48px] w-[92px] items-center justify-center gap-1 rounded-[16px] border\">\n <DevicesBar\n microTrack={microphoneTrack?.track as LocalAudioTrack}\n microEnabled={isMicrophoneEnabled}\n microTrackToggle={{\n showIcon: true,\n source: Track.Source.Microphone,\n onChange: handleMicrophoneToggle,\n }}\n videoTrack={cameraTrack?.track as unknown as LocalVideoTrack}\n videoEnabled={isCameraEnabled}\n videoTrackToggle={{\n showIcon: true,\n source: Track.Source.Camera,\n onChange: handleCameraToggle,\n }}\n className=\"relative\"\n />\n </div>\n <div className=\"bg-gray-0 border-gray-10 flex h-[48px] items-center justify-center gap-1 rounded-[16px] border p-1\">\n <ScreenShareButton />\n {isTutor && <WhiteBoardButton />}\n <ChatButton />\n <RaiseHandButton />\n </div>\n </div>\n <div className=\"relative flex flex-row items-center justify-center gap-4\">\n {showBackToBoardButton && (\n <Tooltip delayDuration={1000}>\n <TooltipTrigger asChild>\n <Button\n size=\"m\"\n variant=\"default\"\n onClick={handleBackToBoard}\n className=\"bg-brand-100 hover:bg-brand-80 absolute top-1 left-[-132px] m-0 h-10 w-[128px] rounded-xl px-2\"\n data-umami-event=\"call-back-to-board\"\n >\n <WhiteBoard className=\"fill-gray-0 h-5 w-5\" />\n <span className=\"text-gray-0 ml-2\">К доске</span>\n </Button>\n </TooltipTrigger>\n <TooltipContent side=\"top\" align=\"center\">\n Вернуться к доске для совместной работы\n </TooltipContent>\n </Tooltip>\n )}\n <div className=\"bg-gray-0 border-gray-10 flex h-[48px] w-[48px] items-center justify-center gap-1 rounded-[16px] border p-1\">\n <DisconnectButton />\n </div>\n </div>\n </div>\n </div>\n );\n};\n","import { useLocalParticipant } from '@livekit/components-react';\nimport { LocalVideoTrack } from 'livekit-client';\nimport { Chat } from '@xipkg/calls-chat';\nimport { UpBar, VideoGrid, CallsOnboarding } from '@xipkg/calls-ui';\nimport { useCallStore } from '@xipkg/calls-store';\nimport { useVideoBlur, useParticipantJoinSync, useParticipantSounds } from '@xipkg/calls-hooks';\nimport { useHandFocus } from '@xipkg/calls-risehand';\nimport { BottomBar } from '../Bottom/BottomBar';\nimport '@xipkg/calls-ui/video-security.css';\n\nexport const ActiveRoom = () => {\n // Автоматический фокус на участниках с поднятыми руками\n useHandFocus();\n // Синхронизация состояния при подключении новых участников\n useParticipantJoinSync();\n useParticipantSounds();\n // Получаем видео трек для применения блюра\n const { cameraTrack } = useLocalParticipant();\n const videoTrack = cameraTrack?.track as LocalVideoTrack | undefined;\n\n // Применяем блюр только в полном режиме\n const mode = useCallStore((state) => state.mode);\n const videoTrackForBlur = mode === 'full' ? videoTrack : null;\n useVideoBlur(videoTrackForBlur);\n\n return (\n <div className=\"flex h-full min-h-0 flex-col justify-stretch\">\n <CallsOnboarding />\n <UpBar />\n <div className=\"flex h-full min-h-0 flex-1 items-center justify-center gap-4 overflow-hidden sm:px-4\">\n <div className=\"flex h-full min-h-0 w-full min-w-0 justify-center text-center text-gray-100\">\n <VideoGrid />\n </div>\n <Chat />\n </div>\n <BottomBar />\n </div>\n );\n};\n","import { useEffect } from 'react';\nimport { useCallsNavigation } from '@xipkg/calls-providers';\nimport { useInitUserDevices, useVideoSecurity } from '@xipkg/calls-hooks';\nimport { useCallStore, useFocusModeStore } from '@xipkg/calls-store';\nimport { PreJoin } from './PreJoin';\nimport { ActiveRoom } from './Room';\nimport '@xipkg/calls-ui/video-security.css';\n\nexport const Call = () => {\n const isStarted = useCallStore((state) => state.isStarted);\n const focusMode = useFocusModeStore((s) => s.focusMode);\n const { pathname } = useCallsNavigation();\n\n useInitUserDevices();\n useVideoSecurity();\n\n const mode = useCallStore((state) => state.mode);\n const updateStore = useCallStore((state) => state.updateStore);\n\n useEffect(() => {\n const isOnCallPage = /^\\/call\\/[^/]+$/.test(pathname);\n\n if (isOnCallPage && mode === 'compact') {\n updateStore('mode', 'full');\n }\n }, [pathname, mode, updateStore]);\n\n return (\n <div\n className={'h-full'}\n style={\n focusMode\n ? ({\n '--header-height': '0px',\n '--available-height':\n 'calc(100dvh - 0px - var(--upbar-height) - var(--bottom-bar-height))',\n } as React.CSSProperties)\n : undefined\n }\n >\n <div className=\"flex h-full w-full flex-col\">\n {isStarted ? (\n <div id=\"videoConferenceContainer\" className=\"bg-gray-5 h-full\">\n <ActiveRoom />\n </div>\n ) : (\n <PreJoin />\n )}\n </div>\n </div>\n );\n};\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xipkg/calls",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -33,20 +33,20 @@
|
|
|
33
33
|
"@xipkg/scrollarea": "2.2.0",
|
|
34
34
|
"@xipkg/label": "2.0.12",
|
|
35
35
|
"@xipkg/alert": "1.1.0",
|
|
36
|
-
"@xipkg/switcher": "3.0.13",
|
|
37
36
|
"@xipkg/select": "2.2.5",
|
|
38
37
|
"@xipkg/tooltip": "2.1.0",
|
|
39
|
-
"@xipkg/icons": "^
|
|
40
|
-
"@xipkg/button": "
|
|
41
|
-
"@xipkg/
|
|
42
|
-
"@xipkg/calls-
|
|
43
|
-
"@xipkg/calls-
|
|
44
|
-
"@xipkg/calls-
|
|
45
|
-
"@xipkg/calls-
|
|
46
|
-
"@xipkg/calls-
|
|
47
|
-
"@xipkg/calls-
|
|
48
|
-
"@xipkg/calls-
|
|
49
|
-
"@xipkg/calls-
|
|
38
|
+
"@xipkg/icons": "^3.0.15",
|
|
39
|
+
"@xipkg/button": "4.1.0",
|
|
40
|
+
"@xipkg/toggle": "^4.1.0",
|
|
41
|
+
"@xipkg/calls-ui": "^0.0.1",
|
|
42
|
+
"@xipkg/calls-utils": "^0.0.1",
|
|
43
|
+
"@xipkg/calls-types": "^0.0.1",
|
|
44
|
+
"@xipkg/calls-config": "^0.0.1",
|
|
45
|
+
"@xipkg/calls-providers": "^0.0.1",
|
|
46
|
+
"@xipkg/calls-store": "^0.0.1",
|
|
47
|
+
"@xipkg/calls-hooks": "^0.0.1",
|
|
48
|
+
"@xipkg/calls-chat": "^0.0.1",
|
|
49
|
+
"@xipkg/calls-risehand": "^0.0.1"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@tanstack/react-query-devtools": "5.73.3",
|