Add framer-motion and motion dependencies; implement animations in ModalContainer and PopupContainer components; enhance PopupWrapper for touch support; update SoundCheckModal and VoiceCheckModal for improved audio testing; refactor Select and ActionsPopover components for animation support.

This commit is contained in:
2025-10-13 15:52:05 +05:00
parent 0e3ad8e065
commit 90e9786ec9
11 changed files with 328 additions and 241 deletions
+39 -50
View File
@@ -168,8 +168,7 @@ function SettingsModal() {
if (device.kind === "videoinput") {
const deviceInfo: MediaDevice = {
deviceId: device.deviceId,
label:
device.label || `${device.kind} (${device.deviceId.slice(0, 8)})`,
label: device.label || `${device.kind} (${device.deviceId})`,
};
videoInputs.push(deviceInfo);
}
@@ -299,8 +298,8 @@ function SettingsModal() {
<VoiceCheckModal
selectedMicrophone={selectedMicrophone}
microphones={microphones}
microphoneVolume={microphoneVolume}
onSelectMicrophone={setSelectedMicrophone}
onClose={() => setModal(null)}
/>
);
};
@@ -312,13 +311,16 @@ function SettingsModal() {
selectedSpeaker={selectedSpeaker}
speakers={speakers}
onSelectSpeaker={setSelectedSpeaker}
onClose={() => setModal(null)}
speakerVolume={speakerVolume}
/>
);
};
return (
<ModalWrapper title="Настройки" className="max-w-[27.778vw]">
<ModalWrapper
title="Настройки"
className="2xl:max-w-[27.778vw] max-w-[400px]"
>
<div className="2xl:space-y-[1.389vw] space-y-5 2xl:-mt-[1.389vw] -mt-5">
<div className="flex">
<Button
@@ -328,17 +330,15 @@ function SettingsModal() {
onClick={() => setMediaType("sound")}
isActive={mediaType === "sound"}
>
<div className="flex 2xl:gap-[0.556vw] items-center">
<div
className={clsx(
"2xl:size-[1.111vw] size-4",
mediaType === "sound" ? "text-[#7B60F3]" : "text-[#7D7D7D]"
)}
>
<SoundIcon />
</div>
<p className="font-medium">Звук</p>
<div
className={clsx(
"2xl:size-[1.111vw] size-4",
mediaType === "sound" ? "text-[#7B60F3]" : "text-[#7D7D7D]"
)}
>
<SoundIcon />
</div>
<p className="font-medium">Звук</p>
</Button>
<Button
variant="menu"
@@ -347,17 +347,15 @@ function SettingsModal() {
onClick={() => setMediaType("video")}
isActive={mediaType === "video"}
>
<div className="flex 2xl:gap-[0.556vw] items-center">
<div
className={clsx(
"2xl:size-[1.111vw] size-4",
mediaType === "video" ? "text-[#7B60F3]" : "text-[#7D7D7D]"
)}
>
<VideoFilledIcon />
</div>
<p className="font-medium">Видео</p>
<div
className={clsx(
"2xl:size-[1.111vw] size-4",
mediaType === "video" ? "text-[#7B60F3]" : "text-[#7D7D7D]"
)}
>
<VideoFilledIcon />
</div>
<p className="font-medium">Видео</p>
</Button>
</div>
{mediaType === "sound" && (
@@ -390,7 +388,7 @@ function SettingsModal() {
</Button>
</div>
) : (
<div className="flex 2xl:gap-[0.556vw]">
<div className="flex 2xl:gap-[0.556vw] gap-2">
<Select
className="flex-1"
options={microphones.map((m) => m.label)}
@@ -407,7 +405,7 @@ function SettingsModal() {
</Button>
</div>
)}
<div className="flex items-center 2xl:gap-[0.833vw]">
<div className="flex items-center 2xl:gap-[0.833vw] gap-3">
<div className="2xl:size-[1.111vw] size-4 text-[#7D7D7D]">
<MicrophoneFilledIcon />
</div>
@@ -450,7 +448,7 @@ function SettingsModal() {
</Button>
</div>
) : (
<div className="flex 2xl:gap-[0.556vw]">
<div className="flex 2xl:gap-[0.556vw] gap-2">
<Select
className="flex-1"
options={speakers.map((s) => s.label)}
@@ -467,7 +465,7 @@ function SettingsModal() {
</Button>
</div>
)}
<div className="flex items-center 2xl:gap-[0.833vw]">
<div className="flex items-center 2xl:gap-[0.833vw] gap-3">
<div className="2xl:size-[1.111vw] size-4 text-[#7D7D7D]">
<SoundIcon />
</div>
@@ -494,28 +492,13 @@ function SettingsModal() {
</div>
<p className="text-s text-[#7D7D7D]">Загрузка камер...</p>
</div>
) : cameras.length === 0 ? (
<div className="bg-[#FEF3F2] 2xl:p-[1.111vw] p-4 2xl:rounded-[1.111vw] rounded-2xl 2xl:space-y-[0.556vw] space-y-2">
<p className="text-s text-[#FF4517]">
Камеры не найдены. Проверьте подключение устройства и
разрешения браузера.
</p>
<Button
variant="secondary"
size="medium"
onClick={loadVideoDevices}
className="w-full"
>
Обновить устройства
</Button>
</div>
) : (
) : cameras.length > 0 ? (
<Select
options={cameras.map((c) => c.label)}
onSelect={setSelectedCamera}
defaultOption={selectedCamera}
/>
)}
) : null}
<video
ref={videoRef}
muted
@@ -526,7 +509,14 @@ function SettingsModal() {
/>
{!isVideoTesting && (
<div className="bg-[#F3F3F3] 2xl:w-[25vw] w-[360px] aspect-[360/202] flex justify-center items-center 2xl:rounded-[1.111vw] rounded-2xl">
{isVideoTestingError && (
{cameras.length === 0 && !isLoadingCameras ? (
<div className="2xl:space-y-[0.556vw] space-y-2 text-center 2xl:px-[1.111vw] px-4">
<p className="title-s font-medium">Камеры не найдены</p>
<p className="text-[#7D7D7D] caption-s font-medium">
Проверьте подключение устройства и разрешения браузера
</p>
</div>
) : isVideoTestingError ? (
<div className="2xl:space-y-[0.556vw] space-y-2">
<p className="title-s font-medium text-center">
Включить видео не удалось
@@ -535,14 +525,13 @@ function SettingsModal() {
Проверьте подключение камеры и разрешения
</p>
</div>
)}
{isVideoTestingLoading && (
) : isVideoTestingLoading ? (
<div className="2xl:space-y-[0.556vw] space-y-2">
<p className="title-s font-medium text-center">
Проверка видео...
</p>
</div>
)}
) : null}
</div>
)}
</div>