Merge remote-tracking branch 'origin/livekit' into hs/reactions-viewcallmodel

This commit is contained in:
Half-Shot
2024-12-16 15:46:09 +00:00
49 changed files with 833 additions and 570 deletions

View File

@@ -62,7 +62,6 @@
"developer_tab_title": "Разработчик",
"feedback_tab_h4": "Изпрати обратна връзка",
"feedback_tab_send_logs_label": "Включи debug логове",
"more_tab_title": "Още",
"speaker_device_selection_label": "Говорител"
},
"unauthenticated_view_body": "Все още не сте регистрирани? <2>Създайте акаунт</2>",

View File

@@ -60,12 +60,9 @@
"return_home_button": "Vrátit se na domácí obrazovku",
"screenshare_button_label": "Sdílet obrazovku",
"settings": {
"developer_settings_label": "Vývojářské nastavení",
"developer_settings_label_description": "Zobrazit vývojářské nastavení.",
"developer_tab_title": "Vývojář",
"feedback_tab_h4": "Dát feedback",
"feedback_tab_send_logs_label": "Zahrnout ladící záznamy",
"more_tab_title": "Více",
"speaker_device_selection_label": "Reproduktor"
},
"unauthenticated_view_body": "Nejste registrovaní? <2>Vytvořit účet</2>",

View File

@@ -147,10 +147,9 @@
"screenshare_button_label": "Bildschirm teilen",
"settings": {
"audio_tab": {
"effect_volume_description": "Lautstärke anpassen, mit der Reaktionen und Handmeldungen abgespielt werden",
"effect_volume_label": "Lautstärke der Soundeffekte"
},
"developer_settings_label": "Entwicklereinstellungen",
"developer_settings_label_description": "Zeige die Entwicklereinstellungen im Einstellungsfenster.",
"developer_tab_title": "Entwickler",
"feedback_tab_body": "Falls du auf Probleme stößt oder einfach nur eine Rückmeldung geben möchtest, sende uns bitte eine kurze Beschreibung.",
"feedback_tab_description_label": "Deine Rückmeldung",
@@ -158,19 +157,13 @@
"feedback_tab_send_logs_label": "Debug-Protokolle anhängen",
"feedback_tab_thank_you": "Danke, wir haben deine Rückmeldung erhalten!",
"feedback_tab_title": "Rückmeldung",
"more_tab_title": "Mehr",
"opt_in_description": "<0></0><1></1>Du kannst deine Zustimmung durch Abwählen dieses Kästchens zurückziehen. Falls du dich aktuell in einem Anruf befindest, wird diese Einstellung nach dem Ende des Anrufs wirksam.",
"preferences_tab": {
"reactions_play_sound_description": "Einen Soundeffekt abspielen, wenn jemand eine Reaktion sendet",
"reactions_play_sound_label": "Reaktionstöne abspielen",
"reactions_show_description": "Zeige eine Animation, wenn jemand eine Reaktion sendet.",
"reactions_show_label": "Reaktionen anzeigen",
"reactions_title": "Reaktionen"
"reactions_show_label": "Reaktionen anzeigen"
},
"preferences_tab_body": "Hier können zusätzliche Optionen für individuelle Anforderungen eingestellt werden",
"preferences_tab_h4": "Einstellungen",
"preferences_tab_show_hand_raised_timer_description": "Einen Timer zur Handmeldung anzeigen",
"preferences_tab_show_hand_raised_timer_label": "Dauer der Handmeldung anzeigen",
"speaker_device_selection_label": "Lautsprecher"
},
"star_rating_input_label_one": "{{count}} Stern",

View File

@@ -67,8 +67,6 @@
"return_home_button": "Επιστροφή στην αρχική οθόνη",
"screenshare_button_label": "Κοινή χρήση οθόνης",
"settings": {
"developer_settings_label": "Ρυθμίσεις προγραμματιστή",
"developer_settings_label_description": "Εμφάνιση ρυθμίσεων προγραμματιστή στο παράθυρο ρυθμίσεων.",
"developer_tab_title": "Προγραμματιστής",
"feedback_tab_body": "Εάν αντιμετωπίζετε προβλήματα ή απλά θέλετε να μας δώσετε κάποια σχόλια, παρακαλούμε στείλτε μας μια σύντομη περιγραφή παρακάτω.",
"feedback_tab_description_label": "Τα σχόλιά σας",
@@ -76,7 +74,6 @@
"feedback_tab_send_logs_label": "Να συμπεριληφθούν αρχεία καταγραφής",
"feedback_tab_thank_you": "Ευχαριστούμε, λάβαμε τα σχόλιά σας!",
"feedback_tab_title": "Ανατροφοδότηση",
"more_tab_title": "Περισσότερα",
"opt_in_description": "<0></0><1></1>Μπορείτε να ανακαλέσετε τη συγκατάθεσή σας αποεπιλέγοντας αυτό το πλαίσιο. Εάν βρίσκεστε σε κλήση, η ρύθμιση αυτή θα τεθεί σε ισχύ στο τέλος της.",
"speaker_device_selection_label": "Ηχείο"
},

View File

@@ -48,13 +48,11 @@
"audio": "Audio",
"avatar": "Avatar",
"back": "Back",
"camera": "Camera",
"display_name": "Display name",
"encrypted": "Encrypted",
"error": "Error",
"home": "Home",
"loading": "Loading…",
"microphone": "Microphone",
"next": "Next",
"options": "Options",
"password": "Password",
@@ -74,7 +72,8 @@
"device_id": "Device ID: {{id}}",
"duplicate_tiles_label": "Number of additional tile copies per participant",
"hostname": "Hostname: {{hostname}}",
"matrix_id": "Matrix ID: {{id}}"
"matrix_id": "Matrix ID: {{id}}",
"show_non_member_tiles": "Show tiles for non-member media"
},
"disconnected_banner": "Connectivity to the server has been lost.",
"full_screen_view_description": "<0>Submitting debug logs will help us track down the problem.</0>",
@@ -152,6 +151,16 @@
"effect_volume_label": "Sound effect volume"
},
"developer_tab_title": "Developer",
"devices": {
"camera": "Camera",
"camera_numbered": "Camera {{n}}",
"default": "Default",
"default_named": "Default <2>({{name}})</2>",
"microphone": "Microphone",
"microphone_numbered": "Microphone {{n}}",
"speaker": "Speaker",
"speaker_numbered": "Speaker {{n}}"
},
"feedback_tab_body": "If you are experiencing issues or simply would like to provide some feedback, please send us a short description below.",
"feedback_tab_description_label": "Your feedback",
"feedback_tab_h4": "Submit feedback",
@@ -162,15 +171,14 @@
"preferences_tab": {
"developer_mode_label": "Developer mode",
"developer_mode_label_description": "Enable developer mode and show developer settings tab.",
"introduction": "Here you can configure extra options for an improved experience.",
"reactions_play_sound_description": "Play a sound effect when anyone sends a reaction into a call.",
"reactions_play_sound_label": "Play reaction sounds",
"reactions_show_description": "Show an animation when anyone sends a reaction.",
"reactions_show_label": "Show reactions"
},
"preferences_tab_body": "Here you can configure extra options for an improved experience.",
"preferences_tab_show_hand_raised_timer_description": "Show a timer when a participant raises their hand",
"preferences_tab_show_hand_raised_timer_label": "Show hand raise duration",
"speaker_device_selection_label": "Speaker"
"reactions_show_label": "Show reactions",
"show_hand_raised_timer_description": "Show a timer when a participant raises their hand",
"show_hand_raised_timer_label": "Show hand raise duration"
}
},
"star_rating_input_label_one": "{{count}} star",
"star_rating_input_label_other": "{{count}} stars",

View File

@@ -67,8 +67,6 @@
"room_auth_view_eula_caption": "Al hacer clic en \"Unirse a la llamada ahora\", aceptas nuestro <2>Contrato de Licencia de Usuario Final (CLUF)</2>",
"screenshare_button_label": "Compartir pantalla",
"settings": {
"developer_settings_label": "Ajustes de desarrollador",
"developer_settings_label_description": "Muestra los ajustes de desarrollador en la ventana de ajustes.",
"developer_tab_title": "Desarrollador",
"feedback_tab_body": "Si tienes algún problema o simplemente quieres darnos tu opinión, por favor envíanos una breve descripción.",
"feedback_tab_description_label": "Tus comentarios",
@@ -76,7 +74,6 @@
"feedback_tab_send_logs_label": "Incluir registros de depuración",
"feedback_tab_thank_you": "¡Gracias, hemos recibido tus comentarios!",
"feedback_tab_title": "Danos tu opinión",
"more_tab_title": "Más",
"opt_in_description": "<0></0><1></1>Puedes retirar tu consentimiento desmarcando esta casilla. Si estás en una llamada, este ajuste se aplicará al final de esta.",
"speaker_device_selection_label": "Altavoz"
},

View File

@@ -97,8 +97,6 @@
"room_auth_view_eula_caption": "Klõpsides „Liitu kõnega kohe“, nõustud sa meie <2>Lõppkasutaja litsentsilepinguga (EULA)</2>",
"screenshare_button_label": "Jaga ekraani",
"settings": {
"developer_settings_label": "Arendaja seadistused",
"developer_settings_label_description": "Näita seadistuste aknas arendajale vajalikke seadeid.",
"developer_tab_title": "Arendaja",
"feedback_tab_body": "Kui selle rakenduse kasutamisel tekib sul probleeme või lihtsalt soovid oma arvamust avaldada, siis palun täida alljärgnev lühike kirjeldus.",
"feedback_tab_description_label": "Sinu tagasiside",
@@ -106,7 +104,6 @@
"feedback_tab_send_logs_label": "Lisa veatuvastuslogid",
"feedback_tab_thank_you": "Tänud, me oleme sinu tagasiside kätte saanud!",
"feedback_tab_title": "Tagasiside",
"more_tab_title": "Rohkem",
"opt_in_description": "<0></0><1></1>Sa võid selle valiku eelmaldamisega alati oma nõusoleku tagasi võtta. Kui sul parasjagu on kõne pooleli, siis seadistuste muudatus jõustub pärast kõne lõppu.",
"speaker_device_selection_label": "Kõlar"
},

View File

@@ -64,7 +64,6 @@
"developer_tab_title": "توسعه دهنده",
"feedback_tab_h4": "بازخورد ارائه دهید",
"feedback_tab_send_logs_label": "شامل لاگ‌های عیب‌یابی",
"more_tab_title": "بیشتر",
"speaker_device_selection_label": "بلندگو"
},
"unauthenticated_view_body": "هنوز ثبت‌نام نکرده‌اید؟ <2>ساخت حساب کاربری</2>",

View File

@@ -95,8 +95,6 @@
"room_auth_view_eula_caption": "En cliquant sur « Rejoindre lappel maintenant », vous acceptez notre <2>Contrat de Licence Utilisateur Final (CLUF)</2>",
"screenshare_button_label": "Partage décran",
"settings": {
"developer_settings_label": "Paramètres développeurs",
"developer_settings_label_description": "Affiche les paramètres développeurs dans la fenêtre des paramètres.",
"developer_tab_title": "Développeur",
"feedback_tab_body": "Si vous rencontrez des problèmes, ou vous voulez simplement faire un commentaire, faites-en une courte description ci-dessous.",
"feedback_tab_description_label": "Votre commentaire",
@@ -104,7 +102,6 @@
"feedback_tab_send_logs_label": "Inclure les journaux de débogage",
"feedback_tab_thank_you": "Merci, nous avons reçu vos commentaires !",
"feedback_tab_title": "Commentaires",
"more_tab_title": "Plus",
"opt_in_description": "<0></0><1></1>Vous pouvez retirer votre consentement en décochant cette case. Si vous êtes actuellement en communication, ce paramètre prendra effet à la fin de lappel.",
"speaker_device_selection_label": "Intervenant"
},

View File

@@ -96,8 +96,6 @@
"room_auth_view_eula_caption": "Dengan mengeklik \"Bergabung ke panggilan sekarang\", Anda menyetujui <2>Perjanjian Lisensi Pengguna Akhir (EULA)</2> kami",
"screenshare_button_label": "Bagikan layar",
"settings": {
"developer_settings_label": "Pengaturan Pengembang",
"developer_settings_label_description": "Ekspos pengaturan pengembang dalam jendela pengaturan.",
"developer_tab_title": "Pengembang",
"feedback_tab_body": "Jika Anda mengalami masalah atau hanya ingin memberikan masukan, silakan kirimkan kami deskripsi pendek di bawah.",
"feedback_tab_description_label": "Masukan Anda",
@@ -105,7 +103,6 @@
"feedback_tab_send_logs_label": "Termasuk catatan pengawakutuan",
"feedback_tab_thank_you": "Terima kasih, kami telah menerima masukan Anda!",
"feedback_tab_title": "Masukan",
"more_tab_title": "Lainnya",
"opt_in_description": "<0></0><1></1>Anda dapat mengurungkan kembali izin dengan mencentang kotak ini. Jika Anda saat ini dalam panggilan, pengaturan ini akan diterapkan di akhir panggilan.",
"speaker_device_selection_label": "Pembicara"
},

View File

@@ -94,15 +94,12 @@
"room_auth_view_eula_caption": "Cliccando \"Entra in chiamata ora\", accetti il nostro <2>accordo di licenza con l'utente finale (EULA)</2>",
"screenshare_button_label": "Condividi schermo",
"settings": {
"developer_settings_label": "Impostazioni per sviluppatori",
"developer_settings_label_description": "Mostra le impostazioni per sviluppatori nella finestra delle impostazioni.",
"developer_tab_title": "Sviluppatore",
"feedback_tab_body": "Se stai riscontrando problemi o semplicemente vuoi dare un'opinione, inviaci una breve descrizione qua sotto.",
"feedback_tab_description_label": "Il tuo commento",
"feedback_tab_h4": "Invia commento",
"feedback_tab_send_logs_label": "Includi registri di debug",
"feedback_tab_thank_you": "Grazie, abbiamo ricevuto il tuo commento!",
"more_tab_title": "Altro",
"opt_in_description": "<0></0><1></1>Puoi revocare il consenso deselezionando questa casella. Se attualmente sei in una chiamata, avrà effetto al termine di essa.",
"speaker_device_selection_label": "Altoparlante"
},

View File

@@ -75,8 +75,6 @@
"room_auth_view_eula_caption": "Klikšķināšana uz \"Pievienoties zvanam tagad\" apliecina piekrišanu mūsu <2>galalietotāja licencēšanas nolīgumam (GLLN)</2>",
"screenshare_button_label": "Kopīgot ekrānu",
"settings": {
"developer_settings_label": "Izstrādātāja iestatījumi",
"developer_settings_label_description": "Izstādīt izstrādātāja iestatījumus iestatījumu logā.",
"developer_tab_title": "Izstrādātājs",
"feedback_tab_body": "Ja tiek piedzīvoti sarežģījumi vai vienkārši ir vēlme sniegt kādu atsauksmi, lūgums zemāk nosūtīt mums īsu aprakstu.",
"feedback_tab_description_label": "Tava atsauksme",
@@ -84,7 +82,6 @@
"feedback_tab_send_logs_label": "Iekļaut atkļūdošanas žurnāla ierakstus",
"feedback_tab_thank_you": "Paldies, mēs saņēmām atsauksmi!",
"feedback_tab_title": "Atsauksmes",
"more_tab_title": "Vairāk",
"opt_in_description": "<0></0><1></1>Savu piekrišanu var atsaukt ar atzīmes noņemšanu no šīs rūtiņas. Ja pašreiz atrodies zvanā, šis iestatījums stāsies spēkā zvana beigās.",
"speaker_device_selection_label": "Runātājs"
},

View File

@@ -99,8 +99,6 @@
"room_auth_view_eula_caption": "Klikając \"Dołącz teraz do rozmowy\", zgadzasz się na naszą <2>Umowę licencyjną (EULA)</2>",
"screenshare_button_label": "Udostępnij ekran",
"settings": {
"developer_settings_label": "Opcje programisty",
"developer_settings_label_description": "Wyświetl opcje programisty w oknie ustawień.",
"developer_tab_title": "Programista",
"feedback_tab_body": "Jeśli posiadasz problemy lub chciałbyś zgłosić swoją opinię, wyślij nam krótki opis.",
"feedback_tab_description_label": "Twoje opinie",
@@ -108,7 +106,6 @@
"feedback_tab_send_logs_label": "Dołącz dzienniki debugowania",
"feedback_tab_thank_you": "Dziękujemy, otrzymaliśmy Twoją opinię!",
"feedback_tab_title": "Opinia użytkownika",
"more_tab_title": "Więcej",
"opt_in_description": "<0></0><1></1>Możesz wycofać swoją zgodę poprzez odznaczenie tego pola. Jeśli już jesteś w trakcie rozmowy, opcja zostanie zastosowana po jej zakończeniu.",
"speaker_device_selection_label": "Głośnik"
},

View File

@@ -148,8 +148,6 @@
"effect_volume_description": "Reglați volumul la care reacționează reacțiile și efectele ridicate de mână",
"effect_volume_label": "Volumul efectului sonor"
},
"developer_settings_label": "Setări pentru dezvoltatori",
"developer_settings_label_description": "Expuneți setările dezvoltatorului în fereastra de setări.",
"developer_tab_title": "dezvoltator",
"feedback_tab_body": "Dacă întâmpinați probleme sau pur și simplu doriți să oferiți feedback, vă rugăm să ne trimiteți o scurtă descriere mai jos.",
"feedback_tab_description_label": "Feedback-ul tău",
@@ -157,19 +155,13 @@
"feedback_tab_send_logs_label": "Includeți jurnale de depanare",
"feedback_tab_thank_you": "Vă mulțumim, am primit feedback-ul dvs.!",
"feedback_tab_title": "Feedback",
"more_tab_title": "Mai mult",
"opt_in_description": "<0></0><1></1>Puteți retrage consimțământul debifând această casetă. Dacă sunteți în prezent la un apel, această setare va intra în vigoare la sfârșitul apelului.",
"preferences_tab": {
"reactions_play_sound_description": "Redați un efect sonor atunci când cineva trimite o reacție la un apel.",
"reactions_play_sound_label": "Redați sunete de reacție",
"reactions_show_description": "Afișați o animație atunci când cineva trimite o reacție.",
"reactions_show_label": "Afișați reacțiile",
"reactions_title": "Reacții"
"reactions_show_label": "Afișați reacțiile"
},
"preferences_tab_body": "Aici puteți configura opțiuni suplimentare pentru o experiență îmbunătățită",
"preferences_tab_h4": "preferinte",
"preferences_tab_show_hand_raised_timer_description": "Afișați un cronometru atunci când un participant ridică mâna",
"preferences_tab_show_hand_raised_timer_label": "Afișați durata ridicării mâinii",
"speaker_device_selection_label": "vorbitor"
},
"start_new_call": "Începe un nou apel",

View File

@@ -69,8 +69,6 @@
"return_home_button": "Вернуться в Начало",
"screenshare_button_label": "Поделиться экраном",
"settings": {
"developer_settings_label": "Настройки Разработчика",
"developer_settings_label_description": "Раскрыть настройки разработчика в окне настроек.",
"developer_tab_title": "Разработчику",
"feedback_tab_body": "Если у вас возникли проблемы или вы просто хотите оставить отзыв, отправьте нам краткое описание ниже.",
"feedback_tab_description_label": "Ваш отзыв",
@@ -78,7 +76,6 @@
"feedback_tab_send_logs_label": "Приложить журнал отладки",
"feedback_tab_thank_you": "Спасибо. Мы получили ваш отзыв!",
"feedback_tab_title": "Отзыв",
"more_tab_title": "Больше",
"opt_in_description": "<0></0><1></1>Вы можете отозвать согласие, сняв этот флажок. Если вы в данный момент находитесь в разговоре, эта настройка вступит в силу по окончании разговора.",
"speaker_device_selection_label": "Динамик"
},

View File

@@ -97,8 +97,6 @@
"room_auth_view_eula_caption": "Kliknutím na \"Pripojiť sa k hovoru teraz\" súhlasíte s našou <2>Licenčnou zmluvou s koncovým používateľom (EULA)</2>",
"screenshare_button_label": "Zdieľať obrazovku",
"settings": {
"developer_settings_label": "Nastavenia pre vývojárov",
"developer_settings_label_description": "Zobraziť nastavenia pre vývojárov v okne nastavení.",
"developer_tab_title": "Vývojár",
"feedback_tab_body": "Ak máte problémy alebo jednoducho chcete poskytnúť spätnú väzbu, pošlite nám krátky popis nižšie.",
"feedback_tab_description_label": "Vaša spätná väzba",
@@ -106,7 +104,6 @@
"feedback_tab_send_logs_label": "Zahrnúť záznamy o ladení",
"feedback_tab_thank_you": "Ďakujeme, dostali sme vašu spätnú väzbu!",
"feedback_tab_title": "Spätná väzba",
"more_tab_title": "Viac",
"opt_in_description": "<0></0><1></1>Súhlas môžete odvolať zrušením označenia tohto políčka. Ak práve prebieha hovor, toto nastavenie nadobudne platnosť po skončení hovoru.",
"speaker_device_selection_label": "Reproduktor"
},

View File

@@ -52,8 +52,7 @@
"settings": {
"developer_tab_title": "Geliştirici",
"feedback_tab_h4": "Geri bildirim ver",
"feedback_tab_send_logs_label": "Hata ayıklama kütüğünü dahil et",
"more_tab_title": "Daha"
"feedback_tab_send_logs_label": "Hata ayıklama kütüğünü dahil et"
},
"unauthenticated_view_body": "Kaydolmadınız mı? <2>Hesap açın</2>",
"unauthenticated_view_login_button": "Hesabınıza girin"

View File

@@ -99,8 +99,6 @@
"room_auth_view_eula_caption": "Натискаючи \"Приєднатися до виклику зараз\", ви погоджуєтеся з нашою <2>Ліцензійною угодою з кінцевим користувачем (EULA)</2>",
"screenshare_button_label": "Поділитися екраном",
"settings": {
"developer_settings_label": "Налаштування розробника",
"developer_settings_label_description": "Відкрийте налаштування розробника у вікні налаштувань.",
"developer_tab_title": "Розробнику",
"feedback_tab_body": "Якщо у вас виникли проблеми або ви просто хочете залишити відгук, надішліть нам короткий опис нижче.",
"feedback_tab_description_label": "Ваш відгук",
@@ -108,7 +106,6 @@
"feedback_tab_send_logs_label": "Долучити журнали налагодження",
"feedback_tab_thank_you": "Дякуємо, ми отримали ваш відгук!",
"feedback_tab_title": "Відгук",
"more_tab_title": "Докладніше",
"opt_in_description": "<0></0><1></1>Ви можете відкликати згоду, прибравши цей прапорець. Якщо ви зараз розмовляєте, це налаштування застосується після завершення виклику.",
"speaker_device_selection_label": "Динамік"
},

View File

@@ -55,7 +55,6 @@
"register_confirm_password_label": "Xác nhận mật khẩu",
"screenshare_button_label": "Chia sẻ màn hình",
"settings": {
"developer_settings_label": "Cài đặt phát triển",
"developer_tab_title": "Nhà phát triển",
"feedback_tab_description_label": "Phản hồi của bạn",
"feedback_tab_h4": "Gửi phản hồi",

View File

@@ -92,8 +92,6 @@
"room_auth_view_eula_caption": "点击 \"加入通话\",即表示您同意我们的<2>最终用户许可协议 (EULA)</2>",
"screenshare_button_label": "屏幕共享",
"settings": {
"developer_settings_label": "开发者设置",
"developer_settings_label_description": "在设置中显示开发者设置。",
"developer_tab_title": "开发者",
"feedback_tab_body": "如果遇到问题或想提供一些反馈意见,请在下面向我们发送简短描述。",
"feedback_tab_description_label": "您的反馈",
@@ -101,7 +99,6 @@
"feedback_tab_send_logs_label": "包含调试日志",
"feedback_tab_thank_you": "谢谢,我们收到了反馈!",
"feedback_tab_title": "反馈",
"more_tab_title": "更多",
"opt_in_description": "<0></0><1></1>您可以取消选中复选框来撤回同意。如果正在通话中,此设置将在通话结束时生效。",
"speaker_device_selection_label": "发言人"
},

View File

@@ -99,8 +99,6 @@
"room_auth_view_eula_caption": "點擊「立刻加入通話」即表示您同意我們的<2>終端使用者授權協議 (EULA)</2>",
"screenshare_button_label": "分享畫面",
"settings": {
"developer_settings_label": "開發者設定",
"developer_settings_label_description": "在設定視窗中顯示開發者設定。",
"developer_tab_title": "開發者",
"feedback_tab_body": "若您遇到問題或只是想提供一些回饋,請在下方傳送簡短說明給我們。",
"feedback_tab_description_label": "您的回饋",
@@ -108,7 +106,6 @@
"feedback_tab_send_logs_label": "包含除錯紀錄",
"feedback_tab_thank_you": "感謝,我們已經收到您的回饋了!",
"feedback_tab_title": "回饋",
"more_tab_title": "更多",
"opt_in_description": "<0></0><1></1>您可以透過取消核取此方塊來撤回同意。若您目前正在通話中,此設定將在通話結束時生效。",
"speaker_device_selection_label": "發言者"
},

View File

@@ -24,7 +24,6 @@ import {
createContext,
forwardRef,
memo,
useCallback,
useContext,
useEffect,
useMemo,
@@ -54,7 +53,6 @@ interface Tile<Model> {
id: string;
model: Model;
onDrag: DragCallback | undefined;
setVisible: (visible: boolean) => void;
}
type PlacedTile<Model> = Tile<Model> & Rect;
@@ -88,7 +86,6 @@ interface SlotProps<Model> extends Omit<ComponentProps<"div">, "onDrag"> {
id: string;
model: Model;
onDrag?: DragCallback;
onVisibilityChange?: (visible: boolean) => void;
style?: CSSProperties;
className?: string;
}
@@ -115,24 +112,47 @@ function offset(element: HTMLElement, relativeTo: Element): Offset {
}
}
export type VisibleTilesCallback = (visibleTiles: number) => void;
interface LayoutContext {
setGeneration: Dispatch<SetStateAction<number | null>>;
setVisibleTilesCallback: Dispatch<
SetStateAction<VisibleTilesCallback | null>
>;
}
const LayoutContext = createContext<LayoutContext | null>(null);
function useLayoutContext(): LayoutContext {
const context = useContext(LayoutContext);
if (context === null)
throw new Error("useUpdateLayout called outside a Grid layout context");
return context;
}
/**
* Enables Grid to react to layout changes. You must call this in your Layout
* component or else Grid will not be reactive.
*/
export function useUpdateLayout(): void {
const context = useContext(LayoutContext);
if (context === null)
throw new Error("useUpdateLayout called outside a Grid layout context");
const { setGeneration } = useLayoutContext();
// On every render, tell Grid that the layout may have changed
useEffect(() =>
context.setGeneration((prev) => (prev === null ? 0 : prev + 1)),
useEffect(() => setGeneration((prev) => (prev === null ? 0 : prev + 1)));
}
/**
* Asks Grid to call a callback whenever the number of visible tiles may have
* changed.
*/
export function useVisibleTiles(callback: VisibleTilesCallback): void {
const { setVisibleTilesCallback } = useLayoutContext();
useEffect(
() => setVisibleTilesCallback(() => callback),
[callback, setVisibleTilesCallback],
);
useEffect(
() => (): void => setVisibleTilesCallback(null),
[setVisibleTilesCallback],
);
}
@@ -245,39 +265,20 @@ export function Grid<
const windowHeight = useObservableEagerState(windowHeightObservable);
const [layoutRoot, setLayoutRoot] = useState<HTMLElement | null>(null);
const [generation, setGeneration] = useState<number | null>(null);
const [visibleTilesCallback, setVisibleTilesCallback] =
useState<VisibleTilesCallback | null>(null);
const tiles = useInitial(() => new Map<string, Tile<TileModel>>());
const prefersReducedMotion = usePrefersReducedMotion();
const Slot: FC<SlotProps<TileModel>> = useMemo(
() =>
function Slot({
id,
model,
onDrag,
onVisibilityChange,
style,
className,
...props
}) {
function Slot({ id, model, onDrag, style, className, ...props }) {
const ref = useRef<HTMLDivElement | null>(null);
const prevVisible = useRef<boolean | null>(null);
const setVisible = useCallback(
(visible: boolean) => {
if (
onVisibilityChange !== undefined &&
visible !== prevVisible.current
) {
onVisibilityChange(visible);
prevVisible.current = visible;
}
},
[onVisibilityChange],
);
useEffect(() => {
tiles.set(id, { id, model, onDrag, setVisible });
tiles.set(id, { id, model, onDrag });
return (): void => void tiles.delete(id);
}, [id, model, onDrag, setVisible]);
}, [id, model, onDrag]);
return (
<div
@@ -307,7 +308,10 @@ export function Grid<
[],
);
const context: LayoutContext = useMemo(() => ({ setGeneration }), []);
const context: LayoutContext = useMemo(
() => ({ setGeneration, setVisibleTilesCallback }),
[setVisibleTilesCallback],
);
// Combine the tile definitions and slots together to create placed tiles
const placedTiles = useMemo(() => {
@@ -342,9 +346,11 @@ export function Grid<
);
useEffect(() => {
for (const tile of placedTiles)
tile.setVisible(tile.y + tile.height <= visibleHeight);
}, [placedTiles, visibleHeight]);
visibleTilesCallback?.(
placedTiles.filter((tile) => tile.y + tile.height <= visibleHeight)
.length,
);
}, [placedTiles, visibleTilesCallback, visibleHeight]);
// Drag state is stored in a ref rather than component state, because we use
// react-spring's imperative API during gestures to improve responsiveness

View File

@@ -13,7 +13,7 @@ import { type GridLayout as GridLayoutModel } from "../state/CallViewModel";
import styles from "./GridLayout.module.css";
import { useInitial } from "../useInitial";
import { type CallLayout, arrangeTiles } from "./CallLayout";
import { type DragCallback, useUpdateLayout } from "./Grid";
import { type DragCallback, useUpdateLayout, useVisibleTiles } from "./Grid";
interface GridCSSProperties extends CSSProperties {
"--gap": string;
@@ -73,6 +73,7 @@ export const makeGridLayout: CallLayout<GridLayoutModel> = ({
// The scrolling part of the layout is where all the grid tiles live
scrolling: forwardRef(function GridLayout({ model, Slot }, ref) {
useUpdateLayout();
useVisibleTiles(model.setVisibleTiles);
const { width, height: minHeight } = useObservableEagerState(minBounds);
const { gap, tileWidth, tileHeight } = useMemo(
() => arrangeTiles(width, minHeight, model.grid.length),
@@ -93,13 +94,7 @@ export const makeGridLayout: CallLayout<GridLayoutModel> = ({
}
>
{model.grid.map((m) => (
<Slot
key={m.id}
className={styles.slot}
id={m.id}
model={m}
onVisibilityChange={m.setVisible}
/>
<Slot key={m.id} className={styles.slot} id={m.id} model={m} />
))}
</div>
);

View File

@@ -52,7 +52,6 @@ export const makeOneOnOneLayout: CallLayout<OneOnOneLayoutModel> = ({
<Slot
id={model.remote.id}
model={model.remote}
onVisibilityChange={model.remote.setVisible}
className={styles.container}
style={{ width: tileWidth, height: tileHeight }}
>
@@ -61,7 +60,6 @@ export const makeOneOnOneLayout: CallLayout<OneOnOneLayoutModel> = ({
id={model.local.id}
model={model.local}
onDrag={onDragLocalTile}
onVisibilityChange={model.local.setVisible}
data-block-alignment={pipAlignmentValue.block}
data-inline-alignment={pipAlignmentValue.inline}
/>

View File

@@ -63,7 +63,6 @@ export const makeSpotlightExpandedLayout: CallLayout<
id={model.pip.id}
model={model.pip}
onDrag={onDragPip}
onVisibilityChange={model.pip.setVisible}
data-block-alignment={pipAlignmentValue.block}
data-inline-alignment={pipAlignmentValue.inline}
/>

View File

@@ -12,7 +12,7 @@ import classNames from "classnames";
import { type CallLayout } from "./CallLayout";
import { type SpotlightLandscapeLayout as SpotlightLandscapeLayoutModel } from "../state/CallViewModel";
import styles from "./SpotlightLandscapeLayout.module.css";
import { useUpdateLayout } from "./Grid";
import { useUpdateLayout, useVisibleTiles } from "./Grid";
/**
* An implementation of the "spotlight landscape" layout, in which the spotlight
@@ -50,6 +50,7 @@ export const makeSpotlightLandscapeLayout: CallLayout<
ref,
) {
useUpdateLayout();
useVisibleTiles(model.setVisibleTiles);
useObservableEagerState(minBounds);
const withIndicators =
useObservableEagerState(model.spotlight.media).length > 1;
@@ -63,13 +64,7 @@ export const makeSpotlightLandscapeLayout: CallLayout<
/>
<div className={styles.grid}>
{model.grid.map((m) => (
<Slot
key={m.id}
className={styles.slot}
id={m.id}
model={m}
onVisibilityChange={m.setVisible}
/>
<Slot key={m.id} className={styles.slot} id={m.id} model={m} />
))}
</div>
</div>

View File

@@ -12,7 +12,7 @@ import classNames from "classnames";
import { type CallLayout, arrangeTiles } from "./CallLayout";
import { type SpotlightPortraitLayout as SpotlightPortraitLayoutModel } from "../state/CallViewModel";
import styles from "./SpotlightPortraitLayout.module.css";
import { useUpdateLayout } from "./Grid";
import { useUpdateLayout, useVisibleTiles } from "./Grid";
interface GridCSSProperties extends CSSProperties {
"--grid-gap": string;
@@ -54,6 +54,7 @@ export const makeSpotlightPortraitLayout: CallLayout<
ref,
) {
useUpdateLayout();
useVisibleTiles(model.setVisibleTiles);
const { width } = useObservableEagerState(minBounds);
const { gap, tileWidth, tileHeight } = arrangeTiles(
width,
@@ -84,13 +85,7 @@ export const makeSpotlightPortraitLayout: CallLayout<
/>
<div className={styles.grid}>
{model.grid.map((m) => (
<Slot
key={m.id}
className={styles.slot}
id={m.id}
model={m}
onVisibilityChange={m.setVisible}
/>
<Slot key={m.id} className={styles.slot} id={m.id} model={m} />
))}
</div>
</div>

View File

@@ -16,7 +16,8 @@ import {
useState,
} from "react";
import { createMediaDeviceObserver } from "@livekit/components-core";
import { type Observable } from "rxjs";
import { map, startWith } from "rxjs";
import { useObservableEagerState } from "observable-hooks";
import { logger } from "matrix-js-sdk/src/logger";
import {
@@ -26,11 +27,25 @@ import {
videoInput as videoInputSetting,
type Setting,
} from "../settings/settings";
import { isFirefox } from "../Platform";
export type DeviceLabel =
| { type: "name"; name: string }
| { type: "number"; number: number }
| { type: "default"; name: string | null };
export interface MediaDevice {
available: MediaDeviceInfo[];
/**
* A map from available device IDs to labels.
*/
available: Map<string, DeviceLabel>;
selectedId: string | undefined;
/**
* The group ID of the selected device.
*/
// This is exposed sort of ad-hoc because it's only needed for knowing when to
// restart the tracks of default input devices, and ideally this behavior
// would be encapsulated somehow…
selectedGroupId: string | undefined;
select: (deviceId: string) => void;
}
@@ -42,26 +57,10 @@ export interface MediaDevices {
stopUsingDeviceNames: () => void;
}
// Cargo-culted from @livekit/components-react
function useObservableState<T>(
observable: Observable<T> | undefined,
startWith: T,
): T {
const [state, setState] = useState<T>(startWith);
useEffect(() => {
// observable state doesn't run in SSR
if (typeof window === "undefined" || !observable) return;
const subscription = observable.subscribe(setState);
return (): void => subscription.unsubscribe();
}, [observable]);
return state;
}
function useMediaDevice(
kind: MediaDeviceKind,
setting: Setting<string | undefined>,
usingNames: boolean,
alwaysDefault: boolean = false,
): MediaDevice {
// Make sure we don't needlessly reset to a device observer without names,
// once permissions are already given
@@ -81,43 +80,91 @@ function useMediaDevice(
kind,
() => logger.error("Error creating MediaDeviceObserver"),
requestPermissions,
),
).pipe(startWith([])),
[kind, requestPermissions],
);
const available = useObservableState(deviceObserver, []);
const [preferredId, select] = useSetting(setting);
const available = useObservableEagerState(
useMemo(
() =>
deviceObserver.pipe(
map((availableRaw) => {
// Sometimes browsers (particularly Firefox) can return multiple device
// entries for the exact same device ID; using a map deduplicates them
let available = new Map<string, DeviceLabel>(
availableRaw.map((d, i) => [
d.deviceId,
d.label
? { type: "name", name: d.label }
: { type: "number", number: i + 1 },
]),
);
// Create a virtual default audio output for browsers that don't have one.
// Its device ID must be the empty string because that's what setSinkId
// recognizes.
if (
kind === "audiooutput" &&
available.size &&
!available.has("") &&
!available.has("default")
)
available = new Map([
["", { type: "default", name: availableRaw[0]?.label || null }],
...available,
]);
// Note: creating virtual default input devices would be another problem
// entirely, because requesting a media stream from deviceId "" won't
// automatically track the default device.
return available;
}),
),
[kind, deviceObserver],
),
);
return useMemo(() => {
let selectedId: string | undefined = undefined;
if (!alwaysDefault && available) {
const [preferredId, select] = useSetting(setting);
const selectedId = useMemo(() => {
if (available.size) {
// If the preferred device is available, use it. Or if every available
// device ID is falsy, the browser is probably just being paranoid about
// fingerprinting and we should still try using the preferred device.
// Worst case it is not available and the browser will gracefully fall
// back to some other device for us when requesting the media stream.
// Otherwise, select the first available device.
selectedId =
available.some((d) => d.deviceId === preferredId) ||
available.every((d) => d.deviceId === "")
? preferredId
: available.at(0)?.deviceId;
return (preferredId !== undefined && available.has(preferredId)) ||
(available.size === 1 && available.has(""))
? preferredId
: available.keys().next().value;
}
return undefined;
}, [available, preferredId]);
const selectedGroupId = useObservableEagerState(
useMemo(
() =>
deviceObserver.pipe(
map(
(availableRaw) =>
availableRaw.find((d) => d.deviceId === selectedId)?.groupId,
),
),
[deviceObserver, selectedId],
),
);
return {
available: available
? // Sometimes browsers (particularly Firefox) can return multiple
// device entries for the exact same device ID; deduplicate them
[...new Map(available.map((d) => [d.deviceId, d])).values()]
: [],
return useMemo(
() => ({
available,
selectedId,
selectedGroupId,
select,
};
}, [available, preferredId, select, alwaysDefault]);
}),
[available, selectedId, selectedGroupId, select],
);
}
export const deviceStub: MediaDevice = {
available: [],
available: new Map(),
selectedId: undefined,
selectedGroupId: undefined,
select: () => {},
};
export const devicesStub: MediaDevices = {
@@ -139,15 +186,6 @@ export const MediaDevicesProvider: FC<Props> = ({ children }) => {
const [numCallersUsingNames, setNumCallersUsingNames] = useState(0);
const usingNames = numCallersUsingNames > 0;
// Setting the audio device to something other than 'undefined' breaks echo-cancellation
// and even can introduce multiple different output devices for one call.
const alwaysUseDefaultAudio = isFirefox();
// On FF we dont need to query the names
// (call enumerateDevices + create meadia stream to trigger permissions)
// for ouput devices because the selector wont be shown on FF.
const useOutputNames = usingNames && !isFirefox();
const audioInput = useMediaDevice(
"audioinput",
audioInputSetting,
@@ -156,8 +194,7 @@ export const MediaDevicesProvider: FC<Props> = ({ children }) => {
const audioOutput = useMediaDevice(
"audiooutput",
audioOutputSetting,
useOutputNames,
alwaysUseDefaultAudio,
usingNames,
);
const videoInput = useMediaDevice(
"videoinput",

View File

@@ -7,7 +7,7 @@ Please see LICENSE in the repository root for full details.
import {
ConnectionState,
type E2EEOptions,
type E2EEManagerOptions,
ExternalE2EEKeyProvider,
Room,
type RoomOptions,
@@ -45,7 +45,7 @@ export function useLiveKit(
sfuConfig: SFUConfig | undefined,
e2eeSystem: EncryptionSystem,
): UseLivekitResult {
const e2eeOptions = useMemo((): E2EEOptions | undefined => {
const e2eeOptions = useMemo((): E2EEManagerOptions | undefined => {
if (e2eeSystem.kind === E2eeType.NONE) return undefined;
if (e2eeSystem.kind === E2eeType.PER_PARTICIPANT) {
@@ -290,18 +290,14 @@ export function useLiveKit(
room.localParticipant.audioTrackPublications.values(),
).find((d) => d.source === Track.Source.Microphone)?.track;
const defaultDevice = device.available.find(
(d) => d.deviceId === "default",
);
if (
defaultDevice &&
activeMicTrack &&
// only restart if the stream is still running: LiveKit will detect
// when a track stops & restart appropriately, so this is not our job.
// Plus, we need to avoid restarting again if the track is already in
// the process of being restarted.
activeMicTrack.mediaStreamTrack.readyState !== "ended" &&
defaultDevice.groupId !==
device.selectedGroupId !==
activeMicTrack.mediaStreamTrack.getSettings().groupId
) {
// It's different, so restart the track, ie. cause Livekit to do another

View File

@@ -134,7 +134,6 @@ export const ActiveCall: FC<ActiveCallProps> = (props) => {
useEffect(() => {
if (livekitRoom !== undefined && reader !== undefined) {
console.log("Creating new VM");
const vm = new CallViewModel(
props.rtcSession,
livekitRoom,

View File

@@ -6,13 +6,13 @@ Please see LICENSE in the repository root for full details.
*/
import { afterAll, afterEach, describe, expect, it, vi } from "vitest";
import React, { type ReactNode } from "react";
import { beforeEach } from "vitest";
import { type ReactNode } from "react";
import { render, screen } from "@testing-library/react";
import { MemoryRouter } from "react-router-dom";
import { useMuteStates } from "./MuteStates";
import {
type DeviceLabel,
type MediaDevice,
type MediaDevices,
MediaDevicesContext,
@@ -63,10 +63,11 @@ const mockCamera: MediaDeviceInfo = {
},
};
function mockDevices(available: MediaDeviceInfo[]): MediaDevice {
function mockDevices(available: Map<string, DeviceLabel>): MediaDevice {
return {
available,
selectedId: "",
selectedGroupId: "",
select: (): void => {},
};
}
@@ -83,25 +84,29 @@ function mockMediaDevices(
} = { microphone: true, speaker: true, camera: true },
): MediaDevices {
return {
audioInput: mockDevices(microphone ? [mockMicrophone] : []),
audioOutput: mockDevices(speaker ? [mockSpeaker] : []),
videoInput: mockDevices(camera ? [mockCamera] : []),
audioInput: mockDevices(
microphone
? new Map([[mockMicrophone.deviceId, mockMicrophone]])
: new Map(),
),
audioOutput: mockDevices(
speaker ? new Map([[mockSpeaker.deviceId, mockSpeaker]]) : new Map(),
),
videoInput: mockDevices(
camera ? new Map([[mockCamera.deviceId, mockCamera]]) : new Map(),
),
startUsingDeviceNames: (): void => {},
stopUsingDeviceNames: (): void => {},
};
}
describe("useMuteStates", () => {
beforeEach(() => {
vi.spyOn(React, "useContext").mockReturnValue({});
});
afterEach(() => {
vi.restoreAllMocks();
vi.clearAllMocks();
});
afterAll(() => {
vi.clearAllMocks();
vi.resetAllMocks();
});
it("disabled when no input devices", () => {

View File

@@ -58,12 +58,12 @@ function useMuteState(
): MuteState {
const [enabled, setEnabled] = useReactiveState<boolean | undefined>(
(prev) =>
device.available.length > 0 ? (prev ?? enabledByDefault()) : undefined,
device.available.size > 0 ? (prev ?? enabledByDefault()) : undefined,
[device],
);
return useMemo(
() =>
device.available.length === 0
device.available.size === 0
? deviceUnavailable
: {
enabled: enabled ?? false,

View File

@@ -13,6 +13,7 @@ import {
useSetting,
duplicateTiles as duplicateTilesSetting,
debugTileLayout as debugTileLayoutSetting,
showNonMemberTiles as showNonMemberTilesSetting,
} from "./settings";
import type { MatrixClient } from "matrix-js-sdk/src/client";
@@ -26,6 +27,9 @@ export const DeveloperSettingsTab: FC<Props> = ({ client }) => {
const [debugTileLayout, setDebugTileLayout] = useSetting(
debugTileLayoutSetting,
);
const [showNonMemberTiles, setShowNonMemberTiles] = useSetting(
showNonMemberTilesSetting,
);
return (
<>
@@ -85,6 +89,20 @@ export const DeveloperSettingsTab: FC<Props> = ({ client }) => {
}
/>
</FieldRow>
<FieldRow>
<InputField
id="showNonMemberTiles"
type="checkbox"
label={t("developer_mode.show_non_member_tiles")}
checked={!!showNonMemberTiles}
onChange={useCallback(
(event: ChangeEvent<HTMLInputElement>): void => {
setShowNonMemberTiles(event.target.checked);
},
[setShowNonMemberTiles],
)}
/>
</FieldRow>
</>
);
};

View File

@@ -16,3 +16,7 @@
flex-direction: column;
gap: var(--cpd-space-4x);
}
.secondary {
color: var(--cpd-color-text-secondary);
}

View File

@@ -5,7 +5,14 @@ SPDX-License-Identifier: AGPL-3.0-only
Please see LICENSE in the repository root for full details.
*/
import { type ChangeEvent, type FC, useCallback, useId } from "react";
import {
type ChangeEvent,
type FC,
type ReactElement,
type ReactNode,
useCallback,
useId,
} from "react";
import {
Heading,
InlineField,
@@ -13,16 +20,23 @@ import {
RadioControl,
Separator,
} from "@vector-im/compound-web";
import { Trans, useTranslation } from "react-i18next";
import { type MediaDevice } from "../livekit/MediaDevicesContext";
import styles from "./DeviceSelection.module.css";
interface Props {
devices: MediaDevice;
caption: string;
title: string;
numberedLabel: (number: number) => string;
}
export const DeviceSelection: FC<Props> = ({ devices, caption }) => {
export const DeviceSelection: FC<Props> = ({
devices,
title,
numberedLabel,
}) => {
const { t } = useTranslation();
const groupId = useId();
const onChange = useCallback(
(e: ChangeEvent<HTMLInputElement>) => {
@@ -31,7 +45,7 @@ export const DeviceSelection: FC<Props> = ({ devices, caption }) => {
[devices],
);
if (devices.available.length == 0) return null;
if (devices.available.size == 0) return null;
return (
<div className={styles.selection}>
@@ -42,29 +56,53 @@ export const DeviceSelection: FC<Props> = ({ devices, caption }) => {
as="h4"
className={styles.title}
>
{caption}
{title}
</Heading>
<Separator className={styles.separator} />
<div className={styles.options}>
{devices.available.map(({ deviceId, label }, index) => (
<InlineField
key={deviceId}
name={groupId}
control={
<RadioControl
checked={deviceId === devices.selectedId}
onChange={onChange}
value={deviceId}
/>
}
>
<Label>
{!!label && label.trim().length > 0
? label
: `${caption} ${index + 1}`}
</Label>
</InlineField>
))}
{[...devices.available].map(([id, label]) => {
let labelText: ReactNode;
switch (label.type) {
case "name":
labelText = label.name;
break;
case "number":
labelText = numberedLabel(label.number);
break;
case "default":
labelText =
label.name === null ? (
t("settings.devices.default")
) : (
<Trans
i18nKey="settings.devices.default_named"
name={label.name}
>
Default{" "}
<span className={styles.secondary}>
({{ name: label.name } as unknown as ReactElement})
</span>
</Trans>
);
break;
}
return (
<InlineField
key={id}
name={groupId}
control={
<RadioControl
checked={id === devices.selectedId}
onChange={onChange}
value={id}
/>
}
>
<Label>{labelText}</Label>
</InlineField>
);
})}
</div>
</div>
);

View File

@@ -41,13 +41,13 @@ export const PreferencesSettingsTab: FC = () => {
return (
<div>
<Text>{t("settings.preferences_tab_body")}</Text>
<Text>{t("settings.preferences_tab.introduction")}</Text>
<FieldRow>
<InputField
id="showHandRaisedTimer"
label={t("settings.preferences_tab_show_hand_raised_timer_label")}
label={t("settings.preferences_tab.show_hand_raised_timer_label")}
description={t(
"settings.preferences_tab_show_hand_raised_timer_description",
"settings.preferences_tab.show_hand_raised_timer_description",
)}
type="checkbox"
checked={showHandRaisedTimer}

View File

@@ -25,7 +25,6 @@ import {
soundEffectVolumeSetting,
developerMode,
} from "./settings";
import { isFirefox } from "../Platform";
import { PreferencesSettingsTab } from "./PreferencesSettingsTab";
import { Slider } from "../Slider";
import { DeviceSelection } from "./DeviceSelection";
@@ -76,14 +75,16 @@ export const SettingsModal: FC<Props> = ({
<Form>
<DeviceSelection
devices={devices.audioInput}
caption={t("common.microphone")}
title={t("settings.devices.microphone")}
numberedLabel={(n) =>
t("settings.devices.microphone_numbered", { n })
}
/>
<DeviceSelection
devices={devices.audioOutput}
title={t("settings.devices.speaker")}
numberedLabel={(n) => t("settings.devices.speaker_numbered", { n })}
/>
{!isFirefox() && (
<DeviceSelection
devices={devices.audioOutput}
caption={t("settings.speaker_device_selection_label")}
/>
)}
<div className={styles.volumeSlider}>
<label>{t("settings.audio_tab.effect_volume_label")}</label>
<p>{t("settings.audio_tab.effect_volume_description")}</p>
@@ -109,7 +110,8 @@ export const SettingsModal: FC<Props> = ({
<Form>
<DeviceSelection
devices={devices.videoInput}
caption={t("common.camera")}
title={t("settings.devices.camera")}
numberedLabel={(n) => t("settings.devices.camera_numbered", { n })}
/>
</Form>
),

View File

@@ -72,6 +72,10 @@ export const developerMode = new Setting("developer-settings-tab", false);
export const duplicateTiles = new Setting("duplicate-tiles", 0);
export const showNonMemberTiles = new Setting<boolean>(
"show-non-member-tiles",
false,
);
export const debugTileLayout = new Setting("debug-tile-layout", false);
export const audioInput = new Setting<string | undefined>(

View File

@@ -48,6 +48,7 @@ import {
} from "../livekit/useECConnectionState";
import { E2eeType } from "../e2ee/e2eeType";
import type { RaisedHandInfo } from "../reactions";
import { showNonMemberTiles } from "../settings/settings";
vi.mock("@livekit/components-core");
@@ -385,16 +386,16 @@ test("screen sharing activates spotlight layout", () => {
test("participants stay in the same order unless to appear/disappear", () => {
withTestScheduler(({ hot, schedule, expectObservable }) => {
const modeInputMarbles = " a";
const visibilityInputMarbles = "a";
// First Bob speaks, then Dave, then Alice
const aSpeakingInputMarbles = "n- 1998ms - 1999ms y";
const bSpeakingInputMarbles = "ny 1998ms n 1999ms -";
const dSpeakingInputMarbles = "n- 1998ms y 1999ms n";
const aSpeakingInputMarbles = " n- 1998ms - 1999ms y";
const bSpeakingInputMarbles = " ny 1998ms n 1999ms -";
const dSpeakingInputMarbles = " n- 1998ms y 1999ms n";
// Nothing should change when Bob speaks, because Bob is already on screen.
// When Dave speaks he should switch with Alice because she's the one who
// hasn't spoken at all. Then when Alice speaks, she should return to her
// place at the top.
const expectedLayoutMarbles = "a 1999ms b 1999ms a 57999ms c 1999ms a";
const expectedLayoutMarbles = " a 1999ms b 1999ms a 57999ms c 1999ms a";
withCallViewModel(
of([aliceParticipant, bobParticipant, daveParticipant]),
@@ -406,15 +407,12 @@ test("participants stay in the same order unless to appear/disappear", () => {
[daveParticipant, hot(dSpeakingInputMarbles, { y: true, n: false })],
]),
(vm) => {
schedule(modeInputMarbles, {
schedule(visibilityInputMarbles, {
a: () => {
// We imagine that only three tiles (the first three) will be visible
// on screen at a time
vm.layout.subscribe((layout) => {
if (layout.type === "grid") {
for (let i = 0; i < layout.grid.length; i++)
layout.grid[i].setVisible(i < 3);
}
if (layout.type === "grid") layout.setVisibleTiles(3);
});
},
});
@@ -444,6 +442,56 @@ test("participants stay in the same order unless to appear/disappear", () => {
});
});
test("participants adjust order when space becomes constrained", () => {
withTestScheduler(({ hot, schedule, expectObservable }) => {
// Start with all tiles on screen then shrink to 3
const visibilityInputMarbles = "a-b";
// Bob and Dave speak
const bSpeakingInputMarbles = " ny";
const dSpeakingInputMarbles = " ny";
// Nothing should change when Bob or Dave initially speak, because they are
// on screen. When the screen becomes smaller Alice should move off screen
// to make way for the speakers (specifically, she should swap with Dave).
const expectedLayoutMarbles = " a-b";
withCallViewModel(
of([aliceParticipant, bobParticipant, daveParticipant]),
of([aliceRtcMember, bobRtcMember, daveRtcMember]),
of(ConnectionState.Connected),
new Map([
[bobParticipant, hot(bSpeakingInputMarbles, { y: true, n: false })],
[daveParticipant, hot(dSpeakingInputMarbles, { y: true, n: false })],
]),
(vm) => {
let setVisibleTiles: ((value: number) => void) | null = null;
vm.layout.subscribe((layout) => {
if (layout.type === "grid") setVisibleTiles = layout.setVisibleTiles;
});
schedule(visibilityInputMarbles, {
a: () => setVisibleTiles!(Infinity),
b: () => setVisibleTiles!(3),
});
expectObservable(summarizeLayout(vm.layout)).toBe(
expectedLayoutMarbles,
{
a: {
type: "grid",
spotlight: undefined,
grid: ["local:0", `${aliceId}:0`, `${bobId}:0`, `${daveId}:0`],
},
b: {
type: "grid",
spotlight: undefined,
grid: ["local:0", `${daveId}:0`, `${bobId}:0`, `${aliceId}:0`],
},
},
);
},
);
});
});
test("spotlight speakers swap places", () => {
withTestScheduler(({ hot, schedule, expectObservable }) => {
// Go immediately into spotlight mode for the test
@@ -648,6 +696,53 @@ test("participants must have a MatrixRTCSession to be visible", () => {
});
});
test("shows participants without MatrixRTCSession when enabled in settings", () => {
try {
// enable the setting:
showNonMemberTiles.setValue(true);
withTestScheduler(({ hot, expectObservable }) => {
const scenarioInputMarbles = " abc";
const expectedLayoutMarbles = "abc";
withCallViewModel(
hot(scenarioInputMarbles, {
a: [],
b: [aliceParticipant],
c: [aliceParticipant, bobParticipant],
}),
of([]), // No one joins the MatrixRTC session
of(ConnectionState.Connected),
new Map(),
(vm) => {
vm.setGridMode("grid");
expectObservable(summarizeLayout(vm.layout)).toBe(
expectedLayoutMarbles,
{
a: {
type: "grid",
spotlight: undefined,
grid: ["local:0"],
},
b: {
type: "one-on-one",
local: "local:0",
remote: `${aliceId}:0`,
},
c: {
type: "grid",
spotlight: undefined,
grid: ["local:0", `${aliceId}:0`, `${bobId}:0`],
},
},
);
},
);
});
} finally {
showNonMemberTiles.setValue(showNonMemberTiles.defaultValue);
}
});
it("should show at least one tile per MatrixRTCSession", () => {
withTestScheduler(({ hot, expectObservable }) => {
// iterate through some combinations of MatrixRTC memberships
@@ -714,8 +809,7 @@ it("should rank raised hands above video feeds and below speakers and presenters
// on screen at a time
vm.layout.subscribe((layout) => {
if (layout.type === "grid") {
for (let i = 0; i < layout.grid.length; i++)
layout.grid[i].setVisible(i <= 1);
layout.setVisibleTiles(2);
}
});
},

View File

@@ -73,6 +73,7 @@ import {
duplicateTiles,
playReactionsSound,
showReactions,
showNonMemberTiles,
} from "../settings/settings";
import { isFirefox } from "../Platform";
import { setPipEnabled } from "../controls";
@@ -92,6 +93,7 @@ import {
type ReactionInfo,
type ReactionOption,
} from "../reactions";
import { shallowEquals } from "../utils/array";
// How long we wait after a focus switch before showing the real participant
// list again
@@ -152,18 +154,21 @@ export interface GridLayout {
type: "grid";
spotlight?: SpotlightTileViewModel;
grid: GridTileViewModel[];
setVisibleTiles: (value: number) => void;
}
export interface SpotlightLandscapeLayout {
type: "spotlight-landscape";
spotlight: SpotlightTileViewModel;
grid: GridTileViewModel[];
setVisibleTiles: (value: number) => void;
}
export interface SpotlightPortraitLayout {
type: "spotlight-portrait";
spotlight: SpotlightTileViewModel;
grid: GridTileViewModel[];
setVisibleTiles: (value: number) => void;
}
export interface SpotlightExpandedLayout {
@@ -236,7 +241,6 @@ enum SortingBin {
interface LayoutScanState {
layout: Layout | null;
tiles: TileStore;
visibleTiles: Set<GridTileViewModel>;
}
class UserMedia {
@@ -466,6 +470,7 @@ export class CallViewModel extends ViewModel {
this.matrixRTCSession,
MatrixRTCSessionEvent.MembershipsChanged,
).pipe(startWith(null)),
showNonMemberTiles.value,
]).pipe(
scan(
(
@@ -475,6 +480,7 @@ export class CallViewModel extends ViewModel {
{ participant: localParticipant },
duplicateTiles,
_membershipsChanged,
showNonMemberTiles,
],
) => {
const newItems = new Map(
@@ -514,9 +520,17 @@ export class CallViewModel extends ViewModel {
}
for (let i = 0; i < 1 + duplicateTiles; i++) {
const indexedMediaId = `${livekitParticipantId}:${i}`;
const prevMedia = prevItems.get(indexedMediaId);
let prevMedia = prevItems.get(indexedMediaId);
if (prevMedia && prevMedia instanceof UserMedia) {
prevMedia.updateParticipant(participant);
if (prevMedia.vm.member === undefined) {
// We have a previous media created because of the `debugShowNonMember` flag.
// In this case we actually replace the media item.
// This "hack" never occurs if we do not use the `debugShowNonMember` debugging
// option and if we always find a room member for each rtc member (which also
// only fails if we have a fundamental problem)
prevMedia = undefined;
}
}
yield [
indexedMediaId,
@@ -558,7 +572,57 @@ export class CallViewModel extends ViewModel {
}.bind(this)(),
);
return newItems;
// Generate non member items (items without a corresponding MatrixRTC member)
// Those items should not be rendered, they are participants in LiveKit that do not have a corresponding
// MatrixRTC members. This cannot be any good:
// - A malicious user impersonates someone
// - Someone injects abusive content
// - The user cannot have encryption keys so it makes no sense to participate
// We can only trust users that have a MatrixRTC member event.
//
// This is still available as a debug option. This can be useful
// - If one wants to test scalability using the LiveKit CLI.
// - If an experimental project does not yet do the MatrixRTC bits.
// - If someone wants to debug if the LiveKit connection works but MatrixRTC room state failed to arrive.
const newNonMemberItems = showNonMemberTiles
? new Map(
function* (this: CallViewModel): Iterable<[string, MediaItem]> {
for (const participant of remoteParticipants) {
for (let i = 0; i < 1 + duplicateTiles; i++) {
const maybeNonMemberParticipantId =
participant.identity + ":" + i;
if (!newItems.has(maybeNonMemberParticipantId)) {
const nonMemberId = maybeNonMemberParticipantId;
yield [
nonMemberId,
prevItems.get(nonMemberId) ??
new UserMedia(
nonMemberId,
undefined,
participant,
this.encryptionSystem,
this.livekitRoom,
of(null),
of(null),
),
];
}
}
}
}.bind(this)(),
)
: new Map();
if (newNonMemberItems.size > 0) {
logger.debug("Added NonMember items: ", newNonMemberItems);
}
const combinedNew = new Map([
...newNonMemberItems.entries(),
...newItems.entries(),
]);
for (const [id, t] of prevItems) if (!combinedNew.has(id)) t.destroy();
return combinedNew;
},
new Map<string, MediaItem>(),
),
@@ -674,6 +738,8 @@ export class CallViewModel extends ViewModel {
bins.sort(([, bin1], [, bin2]) => bin1 - bin2).map(([m]) => m.vm),
);
}),
distinctUntilChanged(shallowEquals),
this.scope.state(),
);
private readonly spotlight: Observable<MediaViewModel[]> =
@@ -687,6 +753,7 @@ export class CallViewModel extends ViewModel {
map((speaker) => (speaker ? [speaker] : [])),
);
}),
distinctUntilChanged(shallowEquals),
this.scope.state(),
);
@@ -920,62 +987,53 @@ export class CallViewModel extends ViewModel {
this.scope.state(),
);
// There is a cyclical dependency here: the layout algorithms want to know
// which tiles are on screen, but to know which tiles are on screen we have to
// first render a layout. To deal with this we assume initially that no tiles
// are visible, and loop the data back into the layouts with a Subject.
private readonly visibleTiles = new Subject<number>();
private readonly setVisibleTiles = (value: number): void =>
this.visibleTiles.next(value);
public readonly layoutInternals: Observable<
LayoutScanState & { layout: Layout }
> = this.layoutMedia.pipe(
// Each layout will produce a set of tiles, and these tiles have an
// observable indicating whether they're visible. We loop this information
// back into the layout process by using switchScan.
switchScan<
LayoutMedia,
LayoutScanState,
Observable<LayoutScanState & { layout: Layout }>
> = combineLatest([
this.layoutMedia,
this.visibleTiles.pipe(startWith(0), distinctUntilChanged()),
]).pipe(
scan<
[LayoutMedia, number],
LayoutScanState & { layout: Layout },
LayoutScanState
>(
({ tiles: prevTiles, visibleTiles }, media) => {
({ tiles: prevTiles }, [media, visibleTiles]) => {
let layout: Layout;
let newTiles: TileStore;
switch (media.type) {
case "grid":
case "spotlight-landscape":
case "spotlight-portrait":
[layout, newTiles] = gridLikeLayout(media, visibleTiles, prevTiles);
break;
case "spotlight-expanded":
[layout, newTiles] = spotlightExpandedLayout(
[layout, newTiles] = gridLikeLayout(
media,
visibleTiles,
this.setVisibleTiles,
prevTiles,
);
break;
case "spotlight-expanded":
[layout, newTiles] = spotlightExpandedLayout(media, prevTiles);
break;
case "one-on-one":
[layout, newTiles] = oneOnOneLayout(media, visibleTiles, prevTiles);
[layout, newTiles] = oneOnOneLayout(media, prevTiles);
break;
case "pip":
[layout, newTiles] = pipLayout(media, visibleTiles, prevTiles);
[layout, newTiles] = pipLayout(media, prevTiles);
break;
}
// Take all of the 'visible' observables and combine them into one big
// observable array
const visibilities =
newTiles.gridTiles.length === 0
? of([])
: combineLatest(newTiles.gridTiles.map((tile) => tile.visible));
return visibilities.pipe(
map((visibilities) => ({
layout: layout,
tiles: newTiles,
visibleTiles: new Set(
newTiles.gridTiles.filter((_tile, i) => visibilities[i]),
),
})),
);
},
{
layout: null,
tiles: TileStore.empty(),
visibleTiles: new Set(),
return { layout, tiles: newTiles };
},
{ layout: null, tiles: TileStore.empty() },
),
this.scope.state(),
);

View File

@@ -7,7 +7,6 @@ Please see LICENSE in the repository root for full details.
import { type Layout, type LayoutMedia } from "./CallViewModel";
import { type TileStore } from "./TileStore";
import { type GridTileViewModel } from "./TileViewModel";
export type GridLikeLayoutType =
| "grid"
@@ -20,7 +19,8 @@ export type GridLikeLayoutType =
*/
export function gridLikeLayout(
media: LayoutMedia & { type: GridLikeLayoutType },
visibleTiles: Set<GridTileViewModel>,
visibleTiles: number,
setVisibleTiles: (value: number) => void,
prevTiles: TileStore,
): [Layout & { type: GridLikeLayoutType }, TileStore] {
const update = prevTiles.from(visibleTiles);
@@ -37,6 +37,7 @@ export function gridLikeLayout(
type: media.type,
spotlight: tiles.spotlightTile,
grid: tiles.gridTiles,
setVisibleTiles,
} as Layout & { type: GridLikeLayoutType },
tiles,
];

View File

@@ -7,17 +7,15 @@ Please see LICENSE in the repository root for full details.
import { type OneOnOneLayout, type OneOnOneLayoutMedia } from "./CallViewModel";
import { type TileStore } from "./TileStore";
import { type GridTileViewModel } from "./TileViewModel";
/**
* Produces a one-on-one layout with the given media.
*/
export function oneOnOneLayout(
media: OneOnOneLayoutMedia,
visibleTiles: Set<GridTileViewModel>,
prevTiles: TileStore,
): [OneOnOneLayout, TileStore] {
const update = prevTiles.from(visibleTiles);
const update = prevTiles.from(2);
update.registerGridTile(media.local);
update.registerGridTile(media.remote);
const tiles = update.build();

View File

@@ -7,17 +7,15 @@ Please see LICENSE in the repository root for full details.
import { type PipLayout, type PipLayoutMedia } from "./CallViewModel";
import { type TileStore } from "./TileStore";
import { type GridTileViewModel } from "./TileViewModel";
/**
* Produces a picture-in-picture layout with the given media.
*/
export function pipLayout(
media: PipLayoutMedia,
visibleTiles: Set<GridTileViewModel>,
prevTiles: TileStore,
): [PipLayout, TileStore] {
const update = prevTiles.from(visibleTiles);
const update = prevTiles.from(0);
update.registerSpotlight(media.spotlight, true);
const tiles = update.build();
return [

View File

@@ -10,17 +10,15 @@ import {
type SpotlightExpandedLayoutMedia,
} from "./CallViewModel";
import { type TileStore } from "./TileStore";
import { type GridTileViewModel } from "./TileViewModel";
/**
* Produces an expanded spotlight layout with the given media.
*/
export function spotlightExpandedLayout(
media: SpotlightExpandedLayoutMedia,
visibleTiles: Set<GridTileViewModel>,
prevTiles: TileStore,
): [SpotlightExpandedLayout, TileStore] {
const update = prevTiles.from(visibleTiles);
const update = prevTiles.from(1);
update.registerSpotlight(media.spotlight, true);
if (media.pip !== undefined) update.registerGridTile(media.pip);
const tiles = update.build();

View File

@@ -101,7 +101,7 @@ export class TileStore {
* Creates a builder which can be used to update the collection, passing
* ownership of the tiles to the updated collection.
*/
public from(visibleTiles: Set<GridTileViewModel>): TileStoreBuilder {
public from(visibleTiles: number): TileStoreBuilder {
return new TileStoreBuilder(
this.spotlight,
this.grid,
@@ -146,7 +146,7 @@ export class TileStoreBuilder {
spotlight: SpotlightTileData | null,
grid: GridTileData[],
) => TileStore,
private readonly visibleTiles: Set<GridTileViewModel>,
private readonly visibleTiles: number,
/**
* A number incremented on each update, just for debugging purposes.
*/
@@ -204,10 +204,8 @@ export class TileStoreBuilder {
const prev = this.prevGridByMedia.get(this.spotlight.media[0]);
if (prev !== undefined) {
const [entry, prevIndex] = prev;
const previouslyVisible = this.visibleTiles.has(entry.vm);
const nowVisible = this.visibleTiles.has(
this.prevGrid[this.numGridEntries]?.vm,
);
const previouslyVisible = prevIndex < this.visibleTiles;
const nowVisible = this.numGridEntries < this.visibleTiles;
// If it doesn't need to move between the visible/invisible sections of
// the grid, then we can keep it where it was and swap the media
@@ -236,17 +234,15 @@ export class TileStoreBuilder {
const prev = this.prevGridByMedia.get(media);
if (prev === undefined) {
// Create a new tile
(this.visibleTiles.has(this.prevGrid[this.numGridEntries]?.vm)
(this.numGridEntries < this.visibleTiles
? this.visibleGridEntries
: this.invisibleGridEntries
).push(new GridTileData(media));
} else {
// Reuse the existing tile
const [entry, prevIndex] = prev;
const previouslyVisible = this.visibleTiles.has(entry.vm);
const nowVisible = this.visibleTiles.has(
this.prevGrid[this.numGridEntries]?.vm,
);
const previouslyVisible = prevIndex < this.visibleTiles;
const nowVisible = this.numGridEntries < this.visibleTiles;
// If it doesn't need to move between the visible/invisible sections of
// the grid, then we can keep it exactly where it was previously
if (previouslyVisible === nowVisible)

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
Please see LICENSE in the repository root for full details.
*/
import { BehaviorSubject, type Observable } from "rxjs";
import { type Observable } from "rxjs";
import { ViewModel } from "./ViewModel";
import { type MediaViewModel, type UserMediaViewModel } from "./MediaViewModel";
@@ -18,14 +18,6 @@ function createId(): string {
export class GridTileViewModel extends ViewModel {
public readonly id = createId();
private readonly visible_ = new BehaviorSubject(false);
/**
* Whether the tile is visible within the current viewport.
*/
public readonly visible: Observable<boolean> = this.visible_;
public setVisible = (value: boolean): void => this.visible_.next(value);
public constructor(public readonly media: Observable<UserMediaViewModel>) {
super();
}

View File

@@ -101,7 +101,8 @@ test("will use the correct device", () => {
audioInput: deviceStub,
audioOutput: {
selectedId: "chosen-device",
available: [],
selectedGroupId: "",
available: new Map(),
select: () => {},
},
videoInput: deviceStub,

16
src/utils/array.ts Normal file
View File

@@ -0,0 +1,16 @@
/*
Copyright 2024 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only
Please see LICENSE in the repository root for full details.
*/
/**
* Determine whether two arrays are equal by shallow comparison.
*/
export function shallowEquals<A>(first: A[], second: A[]): boolean {
if (first.length !== second.length) return false;
for (let i = 0; i < first.length; i++)
if (first[i] !== second[i]) return false;
return true;
}

557
yarn.lock
View File

@@ -1954,17 +1954,17 @@
resolved "https://registry.yarnpkg.com/@livekit/mutex/-/mutex-1.0.0.tgz#9493102d92ff75dfb0445eccc46c7c7ac189d385"
integrity sha512-aiUhoThBNF9UyGTxEURFzJLhhPLIVTnQiEVMjRhPnfHNKLfo2JY9xovHKIus7B78UD5hsP6DlgpmAsjrz4U0Iw==
"@livekit/protocol@1.24.0":
version "1.24.0"
resolved "https://registry.yarnpkg.com/@livekit/protocol/-/protocol-1.24.0.tgz#b23acab25c11027bf26c1b42f9b782682f2da585"
integrity sha512-9dCsqnkMn7lvbI4NGh18zhLDsrXyUcpS++TEFgEk5Xv1WM3R2kT3EzqgL1P/mr3jaabM6rJ8wZA/KJLuQNpF5w==
"@livekit/protocol@1.29.4":
version "1.29.4"
resolved "https://registry.yarnpkg.com/@livekit/protocol/-/protocol-1.29.4.tgz#346906d080bc8207a80570b45db91153a495e0dc"
integrity sha512-dsqxvABHilrMA0BU5m1w8cMWSVeDjV2ZUIUDClNQZju3c30DLMfEYDHU5nmXDfaaHjNIgoRbYR7upJMozG8JJg==
dependencies:
"@bufbuild/protobuf" "^1.10.0"
"@matrix-org/matrix-sdk-crypto-wasm@^9.0.0":
version "9.1.0"
resolved "https://registry.yarnpkg.com/@matrix-org/matrix-sdk-crypto-wasm/-/matrix-sdk-crypto-wasm-9.1.0.tgz#f889653eb4fafaad2a963654d586bd34de62acd5"
integrity sha512-CtPoNcoRW6ehwxpRQAksG3tR+NJ7k4DV02nMFYTDwQtie1V4R8OTY77BjEIs97NOblhtS26jU8m1lWsOBEz0Og==
"@matrix-org/matrix-sdk-crypto-wasm@^11.0.0":
version "11.0.0"
resolved "https://registry.yarnpkg.com/@matrix-org/matrix-sdk-crypto-wasm/-/matrix-sdk-crypto-wasm-11.0.0.tgz#c49a1a0d1e367d3c00a2144a4ab23caee0b1eec2"
integrity sha512-a7NUH8Kjc8hwzNCPpkOGXoceFqWJiWvA8OskXeDrKyODJuDz4yKrZ/nvgaVRfQe45Ab5UC1ZXYqaME+ChlJuqg==
"@matrix-org/olm@3.2.15":
version "3.2.15"
@@ -2340,6 +2340,11 @@
resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.0.tgz#42ef83b3b56dccad5d703ae8c42919a68798bbe2"
integrity sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==
"@radix-ui/primitive@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.1.tgz#fc169732d755c7fbad33ba8d0cd7fd10c90dc8e3"
integrity sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==
"@radix-ui/react-arrow@1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz#744f388182d360b86285217e43b6c63633f39e7a"
@@ -2357,11 +2362,26 @@
"@radix-ui/react-primitive" "2.0.0"
"@radix-ui/react-slot" "1.1.0"
"@radix-ui/react-collection@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.1.1.tgz#be2c7e01d3508e6d4b6d838f492e7d182f17d3b0"
integrity sha512-LwT3pSho9Dljg+wY2KN2mrrh6y3qELfftINERIzBUO9e0N+t0oMTyn3k9iv+ZqgrwGkRnLpNJrsMv9BZlt2yuA==
dependencies:
"@radix-ui/react-compose-refs" "1.1.1"
"@radix-ui/react-context" "1.1.1"
"@radix-ui/react-primitive" "2.0.1"
"@radix-ui/react-slot" "1.1.1"
"@radix-ui/react-compose-refs@1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz#656432461fc8283d7b591dcf0d79152fae9ecc74"
integrity sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==
"@radix-ui/react-compose-refs@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz#6f766faa975f8738269ebb8a23bad4f5a8d2faec"
integrity sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==
"@radix-ui/react-context-menu@^2.2.1":
version "2.2.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-context-menu/-/react-context-menu-2.2.2.tgz#efcddc559fc3011721b65148f062d04027f76c7a"
@@ -2385,21 +2405,21 @@
integrity sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==
"@radix-ui/react-dialog@^1.0.4", "@radix-ui/react-dialog@^1.1.1":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.1.2.tgz#d9345575211d6f2d13e209e84aec9a8584b54d6c"
integrity sha512-Yj4dZtqa2o+kG61fzB0H2qUvmwBA2oyQroGLyNtBj1beo1khoQ3q1a2AO8rrQYjd8256CO9+N8L9tvsS+bnIyA==
version "1.1.3"
resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.1.3.tgz#87cf49f619a6a0f6219980678be0f7c31978dee1"
integrity sha512-ujGvqQNkZ0J7caQyl8XuZRj2/TIrYcOGwqz5TeD1OMcCdfBuEMP0D12ve+8J5F9XuNUth3FAKFWo/wt0E/GJrQ==
dependencies:
"@radix-ui/primitive" "1.1.0"
"@radix-ui/react-compose-refs" "1.1.0"
"@radix-ui/primitive" "1.1.1"
"@radix-ui/react-compose-refs" "1.1.1"
"@radix-ui/react-context" "1.1.1"
"@radix-ui/react-dismissable-layer" "1.1.1"
"@radix-ui/react-dismissable-layer" "1.1.2"
"@radix-ui/react-focus-guards" "1.1.1"
"@radix-ui/react-focus-scope" "1.1.0"
"@radix-ui/react-focus-scope" "1.1.1"
"@radix-ui/react-id" "1.1.0"
"@radix-ui/react-portal" "1.1.2"
"@radix-ui/react-presence" "1.1.1"
"@radix-ui/react-primitive" "2.0.0"
"@radix-ui/react-slot" "1.1.0"
"@radix-ui/react-portal" "1.1.3"
"@radix-ui/react-presence" "1.1.2"
"@radix-ui/react-primitive" "2.0.1"
"@radix-ui/react-slot" "1.1.1"
"@radix-ui/react-use-controllable-state" "1.1.0"
aria-hidden "^1.1.1"
react-remove-scroll "2.6.0"
@@ -2420,6 +2440,17 @@
"@radix-ui/react-use-callback-ref" "1.1.0"
"@radix-ui/react-use-escape-keydown" "1.1.0"
"@radix-ui/react-dismissable-layer@1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.2.tgz#771594b202f32bc8ffeb278c565f10c513814aee"
integrity sha512-kEHnlhv7wUggvhuJPkyw4qspXLJOdYoAP4dO2c8ngGuXTq1w/HZp1YeVB+NQ2KbH1iEG+pvOCGYSqh9HZOz6hg==
dependencies:
"@radix-ui/primitive" "1.1.1"
"@radix-ui/react-compose-refs" "1.1.1"
"@radix-ui/react-primitive" "2.0.1"
"@radix-ui/react-use-callback-ref" "1.1.0"
"@radix-ui/react-use-escape-keydown" "1.1.0"
"@radix-ui/react-dropdown-menu@^2.1.1":
version "2.1.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.2.tgz#acc49577130e3c875ef0133bd1e271ea3392d924"
@@ -2447,6 +2478,15 @@
"@radix-ui/react-primitive" "2.0.0"
"@radix-ui/react-use-callback-ref" "1.1.0"
"@radix-ui/react-focus-scope@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.1.tgz#5c602115d1db1c4fcfa0fae4c3b09bb8919853cb"
integrity sha512-01omzJAYRxXdG2/he/+xy+c8a8gCydoQ1yOxnWNcRhrrBW5W+RQJ22EK1SaO8tb3WoUsuEw7mJjBozPzihDFjA==
dependencies:
"@radix-ui/react-compose-refs" "1.1.1"
"@radix-ui/react-primitive" "2.0.1"
"@radix-ui/react-use-callback-ref" "1.1.0"
"@radix-ui/react-form@^0.1.0":
version "0.1.0"
resolved "https://registry.yarnpkg.com/@radix-ui/react-form/-/react-form-0.1.0.tgz#7111a6aa54a2bde0d11fb72643f9ffc871ac58ad"
@@ -2521,6 +2561,14 @@
"@radix-ui/react-primitive" "2.0.0"
"@radix-ui/react-use-layout-effect" "1.1.0"
"@radix-ui/react-portal@1.1.3":
version "1.1.3"
resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.3.tgz#b0ea5141103a1671b715481b13440763d2ac4440"
integrity sha512-NciRqhXnGojhT93RPyDaMPfLH3ZSl4jjIFbZQ1b/vxvZEdHsBZ49wP9w8L3HzUQwep01LcWtkUvm0OVB5JAHTw==
dependencies:
"@radix-ui/react-primitive" "2.0.1"
"@radix-ui/react-use-layout-effect" "1.1.0"
"@radix-ui/react-presence@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.1.tgz#98aba423dba5e0c687a782c0669dcd99de17f9b1"
@@ -2529,6 +2577,14 @@
"@radix-ui/react-compose-refs" "1.1.0"
"@radix-ui/react-use-layout-effect" "1.1.0"
"@radix-ui/react-presence@1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.2.tgz#bb764ed8a9118b7ec4512da5ece306ded8703cdc"
integrity sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==
dependencies:
"@radix-ui/react-compose-refs" "1.1.1"
"@radix-ui/react-use-layout-effect" "1.1.0"
"@radix-ui/react-primitive@2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz#fe05715faa9203a223ccc0be15dc44b9f9822884"
@@ -2536,6 +2592,13 @@
dependencies:
"@radix-ui/react-slot" "1.1.0"
"@radix-ui/react-primitive@2.0.1":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz#6d9efc550f7520135366f333d1e820cf225fad9e"
integrity sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==
dependencies:
"@radix-ui/react-slot" "1.1.1"
"@radix-ui/react-progress@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@radix-ui/react-progress/-/react-progress-1.1.0.tgz#28c267885ec154fc557ec7a66cb462787312f7e2"
@@ -2567,17 +2630,17 @@
"@radix-ui/react-primitive" "2.0.0"
"@radix-ui/react-slider@^1.1.2":
version "1.2.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-slider/-/react-slider-1.2.1.tgz#acb0804309890f3cd7a224b2b0c4c4704f32921b"
integrity sha512-bEzQoDW0XP+h/oGbutF5VMWJPAl/UU8IJjr7h02SOHDIIIxq+cep8nItVNoBV+OMmahCdqdF38FTpmXoqQUGvw==
version "1.2.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-slider/-/react-slider-1.2.2.tgz#4ca883e3f0dea7b97d43c6cbc6c4305c64e75a86"
integrity sha512-sNlU06ii1/ZcbHf8I9En54ZPW0Vil/yPVg4vQMcFNjrIx51jsHbFl1HYHQvCIWJSr1q0ZmA+iIs/ZTv8h7HHSA==
dependencies:
"@radix-ui/number" "1.1.0"
"@radix-ui/primitive" "1.1.0"
"@radix-ui/react-collection" "1.1.0"
"@radix-ui/react-compose-refs" "1.1.0"
"@radix-ui/primitive" "1.1.1"
"@radix-ui/react-collection" "1.1.1"
"@radix-ui/react-compose-refs" "1.1.1"
"@radix-ui/react-context" "1.1.1"
"@radix-ui/react-direction" "1.1.0"
"@radix-ui/react-primitive" "2.0.0"
"@radix-ui/react-primitive" "2.0.1"
"@radix-ui/react-use-controllable-state" "1.1.0"
"@radix-ui/react-use-layout-effect" "1.1.0"
"@radix-ui/react-use-previous" "1.1.0"
@@ -2590,6 +2653,13 @@
dependencies:
"@radix-ui/react-compose-refs" "1.1.0"
"@radix-ui/react-slot@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.1.1.tgz#ab9a0ffae4027db7dc2af503c223c978706affc3"
integrity sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==
dependencies:
"@radix-ui/react-compose-refs" "1.1.1"
"@radix-ui/react-use-callback-ref@1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz#bce938ca413675bc937944b0d01ef6f4a6dc5bf1"
@@ -2634,11 +2704,11 @@
"@radix-ui/react-use-layout-effect" "1.1.0"
"@radix-ui/react-visually-hidden@^1.0.3":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.0.tgz#ad47a8572580f7034b3807c8e6740cd41038a5a2"
integrity sha512-N8MDZqtgCgG5S3aV60INAB475osJousYpZ4cTJ2cFbMpdHS5Y6loLTH8LPtkj2QN0x93J30HT/M3qJXM0+lyeQ==
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.1.tgz#f7b48c1af50dfdc366e92726aee6d591996c5752"
integrity sha512-vVfA2IZ9q/J+gEamvj761Oq1FpWgCDaNOOIfbPVp2MVPLEomUr5+Vf7kJGwQ24YxZSlQVar7Bes8kyTo5Dshpg==
dependencies:
"@radix-ui/react-primitive" "2.0.0"
"@radix-ui/react-primitive" "2.0.1"
"@radix-ui/rect@1.1.0":
version "1.1.0"
@@ -2704,231 +2774,236 @@
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.25.0.tgz#3e7eda4c0c1de6d2415343002d742ff95e38dca7"
integrity sha512-CC/ZqFZwlAIbU1wUPisHyV/XRc5RydFrNLtgl3dGYskdwPZdt4HERtKm50a/+DtTlKeCq9IXFEWR+P6blwjqBA==
"@rollup/rollup-android-arm-eabi@4.28.0":
version "4.28.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.28.0.tgz#462e7ecdd60968bc9eb95a20d185e74f8243ec1b"
integrity sha512-wLJuPLT6grGZsy34g4N1yRfYeouklTgPhH1gWXCYspenKYD0s3cR99ZevOGw5BexMNywkbV3UkjADisozBmpPQ==
"@rollup/rollup-android-arm-eabi@4.28.1":
version "4.28.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.28.1.tgz#7f4c4d8cd5ccab6e95d6750dbe00321c1f30791e"
integrity sha512-2aZp8AES04KI2dy3Ss6/MDjXbwBzj+i0GqKtWXgw2/Ma6E4jJvujryO6gJAghIRVz7Vwr9Gtl/8na3nDUKpraQ==
"@rollup/rollup-android-arm64@4.25.0":
version "4.25.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.25.0.tgz#04f679231acf7284f1f8a1f7250d0e0944865ba8"
integrity sha512-/Y76tmLGUJqVBXXCfVS8Q8FJqYGhgH4wl4qTA24E9v/IJM0XvJCGQVSW1QZ4J+VURO9h8YCa28sTFacZXwK7Rg==
"@rollup/rollup-android-arm64@4.28.0":
version "4.28.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.28.0.tgz#78a2b8a8a55f71a295eb860a654ae90a2b168f40"
integrity sha512-eiNkznlo0dLmVG/6wf+Ifi/v78G4d4QxRhuUl+s8EWZpDewgk7PX3ZyECUXU0Zq/Ca+8nU8cQpNC4Xgn2gFNDA==
"@rollup/rollup-android-arm64@4.28.1":
version "4.28.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.28.1.tgz#17ea71695fb1518c2c324badbe431a0bd1879f2d"
integrity sha512-EbkK285O+1YMrg57xVA+Dp0tDBRB93/BZKph9XhMjezf6F4TpYjaUSuPt5J0fZXlSag0LmZAsTmdGGqPp4pQFA==
"@rollup/rollup-darwin-arm64@4.25.0":
version "4.25.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.25.0.tgz#ecea723041621747d0772af93b54752edf26467a"
integrity sha512-YVT6L3UrKTlC0FpCZd0MGA7NVdp7YNaEqkENbWQ7AOVOqd/7VzyHpgIpc1mIaxRAo1ZsJRH45fq8j4N63I/vvg==
"@rollup/rollup-darwin-arm64@4.28.0":
version "4.28.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.28.0.tgz#5b783af714f434f1e66e3cdfa3817e0b99216d84"
integrity sha512-lmKx9yHsppblnLQZOGxdO66gT77bvdBtr/0P+TPOseowE7D9AJoBw8ZDULRasXRWf1Z86/gcOdpBrV6VDUY36Q==
"@rollup/rollup-darwin-arm64@4.28.1":
version "4.28.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.28.1.tgz#dac0f0d0cfa73e7d5225ae6d303c13c8979e7999"
integrity sha512-prduvrMKU6NzMq6nxzQw445zXgaDBbMQvmKSJaxpaZ5R1QDM8w+eGxo6Y/jhT/cLoCvnZI42oEqf9KQNYz1fqQ==
"@rollup/rollup-darwin-x64@4.25.0":
version "4.25.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.25.0.tgz#28e6e0687092f31e20982fc104779d48c643fc21"
integrity sha512-ZRL+gexs3+ZmmWmGKEU43Bdn67kWnMeWXLFhcVv5Un8FQcx38yulHBA7XR2+KQdYIOtD0yZDWBCudmfj6lQJoA==
"@rollup/rollup-darwin-x64@4.28.0":
version "4.28.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.28.0.tgz#f72484e842521a5261978034e18e20f778a2850d"
integrity sha512-8hxgfReVs7k9Js1uAIhS6zq3I+wKQETInnWQtgzt8JfGx51R1N6DRVy3F4o0lQwumbErRz52YqwjfvuwRxGv1w==
"@rollup/rollup-darwin-x64@4.28.1":
version "4.28.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.28.1.tgz#8f63baa1d31784904a380d2e293fa1ddf53dd4a2"
integrity sha512-WsvbOunsUk0wccO/TV4o7IKgloJ942hVFK1CLatwv6TJspcCZb9umQkPdvB7FihmdxgaKR5JyxDjWpCOp4uZlQ==
"@rollup/rollup-freebsd-arm64@4.25.0":
version "4.25.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.25.0.tgz#99e9173b8aef3d1ef086983da70413988206e530"
integrity sha512-xpEIXhiP27EAylEpreCozozsxWQ2TJbOLSivGfXhU4G1TBVEYtUPi2pOZBnvGXHyOdLAUUhPnJzH3ah5cqF01g==
"@rollup/rollup-freebsd-arm64@4.28.0":
version "4.28.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.28.0.tgz#3c919dff72b2fe344811a609c674a8347b033f62"
integrity sha512-lA1zZB3bFx5oxu9fYud4+g1mt+lYXCoch0M0V/xhqLoGatbzVse0wlSQ1UYOWKpuSu3gyN4qEc0Dxf/DII1bhQ==
"@rollup/rollup-freebsd-arm64@4.28.1":
version "4.28.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.28.1.tgz#30ed247e0df6e8858cdc6ae4090e12dbeb8ce946"
integrity sha512-HTDPdY1caUcU4qK23FeeGxCdJF64cKkqajU0iBnTVxS8F7H/7BewvYoG+va1KPSL63kQ1PGNyiwKOfReavzvNA==
"@rollup/rollup-freebsd-x64@4.25.0":
version "4.25.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.25.0.tgz#f3a1ef941f8d3c6b2b036484c69a7b2d3d9ebbd7"
integrity sha512-sC5FsmZGlJv5dOcURrsnIK7ngc3Kirnx3as2XU9uER+zjfyqIjdcMVgzy4cOawhsssqzoAX19qmxgJ8a14Qrqw==
"@rollup/rollup-freebsd-x64@4.28.0":
version "4.28.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.28.0.tgz#b62a3a8365b363b3fdfa6da11a9188b6ab4dca7c"
integrity sha512-aI2plavbUDjCQB/sRbeUZWX9qp12GfYkYSJOrdYTL/C5D53bsE2/nBPuoiJKoWp5SN78v2Vr8ZPnB+/VbQ2pFA==
"@rollup/rollup-freebsd-x64@4.28.1":
version "4.28.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.28.1.tgz#57846f382fddbb508412ae07855b8a04c8f56282"
integrity sha512-m/uYasxkUevcFTeRSM9TeLyPe2QDuqtjkeoTpP9SW0XxUWfcYrGDMkO/m2tTw+4NMAF9P2fU3Mw4ahNvo7QmsQ==
"@rollup/rollup-linux-arm-gnueabihf@4.25.0":
version "4.25.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.25.0.tgz#9ba6adcc33f26f2a0c6ee658f0bbda4de8da2f75"
integrity sha512-uD/dbLSs1BEPzg564TpRAQ/YvTnCds2XxyOndAO8nJhaQcqQGFgv/DAVko/ZHap3boCvxnzYMa3mTkV/B/3SWA==
"@rollup/rollup-linux-arm-gnueabihf@4.28.0":
version "4.28.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.28.0.tgz#0d02cc55bd229bd8ca5c54f65f916ba5e0591c94"
integrity sha512-WXveUPKtfqtaNvpf0iOb0M6xC64GzUX/OowbqfiCSXTdi/jLlOmH0Ba94/OkiY2yTGTwteo4/dsHRfh5bDCZ+w==
"@rollup/rollup-linux-arm-gnueabihf@4.28.1":
version "4.28.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.28.1.tgz#378ca666c9dae5e6f94d1d351e7497c176e9b6df"
integrity sha512-QAg11ZIt6mcmzpNE6JZBpKfJaKkqTm1A9+y9O+frdZJEuhQxiugM05gnCWiANHj4RmbgeVJpTdmKRmH/a+0QbA==
"@rollup/rollup-linux-arm-musleabihf@4.25.0":
version "4.25.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.25.0.tgz#62f2426fa9016ec884f4fa779d7b62d5ba02a41a"
integrity sha512-ZVt/XkrDlQWegDWrwyC3l0OfAF7yeJUF4fq5RMS07YM72BlSfn2fQQ6lPyBNjt+YbczMguPiJoCfaQC2dnflpQ==
"@rollup/rollup-linux-arm-musleabihf@4.28.0":
version "4.28.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.28.0.tgz#c51d379263201e88a60e92bd8e90878f0c044425"
integrity sha512-yLc3O2NtOQR67lI79zsSc7lk31xjwcaocvdD1twL64PK1yNaIqCeWI9L5B4MFPAVGEVjH5k1oWSGuYX1Wutxpg==
"@rollup/rollup-linux-arm-musleabihf@4.28.1":
version "4.28.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.28.1.tgz#a692eff3bab330d5c33a5d5813a090c15374cddb"
integrity sha512-dRP9PEBfolq1dmMcFqbEPSd9VlRuVWEGSmbxVEfiq2cs2jlZAl0YNxFzAQS2OrQmsLBLAATDMb3Z6MFv5vOcXg==
"@rollup/rollup-linux-arm64-gnu@4.25.0":
version "4.25.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.25.0.tgz#f98ec111a231d35e0c6d3404e3d80f67f9d5b9f8"
integrity sha512-qboZ+T0gHAW2kkSDPHxu7quaFaaBlynODXpBVnPxUgvWYaE84xgCKAPEYE+fSMd3Zv5PyFZR+L0tCdYCMAtG0A==
"@rollup/rollup-linux-arm64-gnu@4.28.0":
version "4.28.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.28.0.tgz#93ce2addc337b5cfa52b84f8e730d2e36eb4339b"
integrity sha512-+P9G9hjEpHucHRXqesY+3X9hD2wh0iNnJXX/QhS/J5vTdG6VhNYMxJ2rJkQOxRUd17u5mbMLHM7yWGZdAASfcg==
"@rollup/rollup-linux-arm64-gnu@4.28.1":
version "4.28.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.28.1.tgz#6b1719b76088da5ac1ae1feccf48c5926b9e3db9"
integrity sha512-uGr8khxO+CKT4XU8ZUH1TTEUtlktK6Kgtv0+6bIFSeiSlnGJHG1tSFSjm41uQ9sAO/5ULx9mWOz70jYLyv1QkA==
"@rollup/rollup-linux-arm64-musl@4.25.0":
version "4.25.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.25.0.tgz#4b36ffb8359f959f2c29afd187603c53368b6723"
integrity sha512-ndWTSEmAaKr88dBuogGH2NZaxe7u2rDoArsejNslugHZ+r44NfWiwjzizVS1nUOHo+n1Z6qV3X60rqE/HlISgw==
"@rollup/rollup-linux-arm64-musl@4.28.0":
version "4.28.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.28.0.tgz#730af6ddc091a5ba5baac28a3510691725dc808b"
integrity sha512-1xsm2rCKSTpKzi5/ypT5wfc+4bOGa/9yI/eaOLW0oMs7qpC542APWhl4A37AENGZ6St6GBMWhCCMM6tXgTIplw==
"@rollup/rollup-linux-arm64-musl@4.28.1":
version "4.28.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.28.1.tgz#865baf5b6f5ff67acb32e5a359508828e8dc5788"
integrity sha512-QF54q8MYGAqMLrX2t7tNpi01nvq5RI59UBNx+3+37zoKX5KViPo/gk2QLhsuqok05sSCRluj0D00LzCwBikb0A==
"@rollup/rollup-linux-loongarch64-gnu@4.28.1":
version "4.28.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.28.1.tgz#23c6609ba0f7fa7a7f2038b6b6a08555a5055a87"
integrity sha512-vPul4uodvWvLhRco2w0GcyZcdyBfpfDRgNKU+p35AWEbJ/HPs1tOUrkSueVbBS0RQHAf/A+nNtDpvw95PeVKOA==
"@rollup/rollup-linux-powerpc64le-gnu@4.25.0":
version "4.25.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.25.0.tgz#52f4b39e6783505d168a745b79d86474fde71680"
integrity sha512-BVSQvVa2v5hKwJSy6X7W1fjDex6yZnNKy3Kx1JGimccHft6HV0THTwNtC2zawtNXKUu+S5CjXslilYdKBAadzA==
"@rollup/rollup-linux-powerpc64le-gnu@4.28.0":
version "4.28.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.28.0.tgz#b5565aac20b4de60ca1e557f525e76478b5436af"
integrity sha512-zgWxMq8neVQeXL+ouSf6S7DoNeo6EPgi1eeqHXVKQxqPy1B2NvTbaOUWPn/7CfMKL7xvhV0/+fq/Z/J69g1WAQ==
"@rollup/rollup-linux-powerpc64le-gnu@4.28.1":
version "4.28.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.28.1.tgz#652ef0d9334a9f25b9daf85731242801cb0fc41c"
integrity sha512-pTnTdBuC2+pt1Rmm2SV7JWRqzhYpEILML4PKODqLz+C7Ou2apEV52h19CR7es+u04KlqplggmN9sqZlekg3R1A==
"@rollup/rollup-linux-riscv64-gnu@4.25.0":
version "4.25.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.25.0.tgz#49195be7e6a7d68d482b12461e2ea914e31ff977"
integrity sha512-G4hTREQrIdeV0PE2JruzI+vXdRnaK1pg64hemHq2v5fhv8C7WjVaeXc9P5i4Q5UC06d/L+zA0mszYIKl+wY8oA==
"@rollup/rollup-linux-riscv64-gnu@4.28.0":
version "4.28.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.28.0.tgz#d488290bf9338bad4ae9409c4aa8a1728835a20b"
integrity sha512-VEdVYacLniRxbRJLNtzwGt5vwS0ycYshofI7cWAfj7Vg5asqj+pt+Q6x4n+AONSZW/kVm+5nklde0qs2EUwU2g==
"@rollup/rollup-linux-riscv64-gnu@4.28.1":
version "4.28.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.28.1.tgz#1eb6651839ee6ebca64d6cc64febbd299e95e6bd"
integrity sha512-vWXy1Nfg7TPBSuAncfInmAI/WZDd5vOklyLJDdIRKABcZWojNDY0NJwruY2AcnCLnRJKSaBgf/GiJfauu8cQZA==
"@rollup/rollup-linux-s390x-gnu@4.25.0":
version "4.25.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.25.0.tgz#4b8d50a205eac7b46cdcb9c50d4a6ae5994c02e0"
integrity sha512-9T/w0kQ+upxdkFL9zPVB6zy9vWW1deA3g8IauJxojN4bnz5FwSsUAD034KpXIVX5j5p/rn6XqumBMxfRkcHapQ==
"@rollup/rollup-linux-s390x-gnu@4.28.0":
version "4.28.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.28.0.tgz#eb2e3f3a06acf448115045c11a5a96868c95a556"
integrity sha512-LQlP5t2hcDJh8HV8RELD9/xlYtEzJkm/aWGsauvdO2ulfl3QYRjqrKW+mGAIWP5kdNCBheqqqYIGElSRCaXfpw==
"@rollup/rollup-linux-s390x-gnu@4.28.1":
version "4.28.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.28.1.tgz#015c52293afb3ff2a293cf0936b1d43975c1e9cd"
integrity sha512-/yqC2Y53oZjb0yz8PVuGOQQNOTwxcizudunl/tFs1aLvObTclTwZ0JhXF2XcPT/zuaymemCDSuuUPXJJyqeDOg==
"@rollup/rollup-linux-x64-gnu@4.25.0":
version "4.25.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.25.0.tgz#dfcceebc5ccac7fc2db19471996026258c81b55f"
integrity sha512-ThcnU0EcMDn+J4B9LD++OgBYxZusuA7iemIIiz5yzEcFg04VZFzdFjuwPdlURmYPZw+fgVrFzj4CA64jSTG4Ig==
"@rollup/rollup-linux-x64-gnu@4.28.0":
version "4.28.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.28.0.tgz#065952ef2aea7e837dc7e02aa500feeaff4fc507"
integrity sha512-Nl4KIzteVEKE9BdAvYoTkW19pa7LR/RBrT6F1dJCV/3pbjwDcaOq+edkP0LXuJ9kflW/xOK414X78r+K84+msw==
"@rollup/rollup-linux-x64-gnu@4.28.1":
version "4.28.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.28.1.tgz#b83001b5abed2bcb5e2dbeec6a7e69b194235c1e"
integrity sha512-fzgeABz7rrAlKYB0y2kSEiURrI0691CSL0+KXwKwhxvj92VULEDQLpBYLHpF49MSiPG4sq5CK3qHMnb9tlCjBw==
"@rollup/rollup-linux-x64-musl@4.25.0":
version "4.25.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.25.0.tgz#192f78bad8429711d63a31dc0a7d3312e2df850e"
integrity sha512-zx71aY2oQxGxAT1JShfhNG79PnjYhMC6voAjzpu/xmMjDnKNf6Nl/xv7YaB/9SIa9jDYf8RBPWEnjcdlhlv1rQ==
"@rollup/rollup-linux-x64-musl@4.28.0":
version "4.28.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.28.0.tgz#3435d484d05f5c4d1ffd54541b4facce2887103a"
integrity sha512-eKpJr4vBDOi4goT75MvW+0dXcNUqisK4jvibY9vDdlgLx+yekxSm55StsHbxUsRxSTt3JEQvlr3cGDkzcSP8bw==
"@rollup/rollup-linux-x64-musl@4.28.1":
version "4.28.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.28.1.tgz#6cc7c84cd4563737f8593e66f33b57d8e228805b"
integrity sha512-xQTDVzSGiMlSshpJCtudbWyRfLaNiVPXt1WgdWTwWz9n0U12cI2ZVtWe/Jgwyv/6wjL7b66uu61Vg0POWVfz4g==
"@rollup/rollup-win32-arm64-msvc@4.25.0":
version "4.25.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.25.0.tgz#f4ec076579634f780b4e5896ae7f59f3e38e0c60"
integrity sha512-JT8tcjNocMs4CylWY/CxVLnv8e1lE7ff1fi6kbGocWwxDq9pj30IJ28Peb+Y8yiPNSF28oad42ApJB8oUkwGww==
"@rollup/rollup-win32-arm64-msvc@4.28.0":
version "4.28.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.28.0.tgz#69682a2a10d9fedc334f87583cfca83c39c08077"
integrity sha512-Vi+WR62xWGsE/Oj+mD0FNAPY2MEox3cfyG0zLpotZdehPFXwz6lypkGs5y38Jd/NVSbOD02aVad6q6QYF7i8Bg==
"@rollup/rollup-win32-arm64-msvc@4.28.1":
version "4.28.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.28.1.tgz#631ffeee094d71279fcd1fe8072bdcf25311bc11"
integrity sha512-wSXmDRVupJstFP7elGMgv+2HqXelQhuNf+IS4V+nUpNVi/GUiBgDmfwD0UGN3pcAnWsgKG3I52wMOBnk1VHr/A==
"@rollup/rollup-win32-ia32-msvc@4.25.0":
version "4.25.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.25.0.tgz#5458eab1929827e4f805cefb90bd09ecf7eeed2b"
integrity sha512-dRLjLsO3dNOfSN6tjyVlG+Msm4IiZnGkuZ7G5NmpzwF9oOc582FZG05+UdfTbz5Jd4buK/wMb6UeHFhG18+OEg==
"@rollup/rollup-win32-ia32-msvc@4.28.0":
version "4.28.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.28.0.tgz#b64470f9ac79abb386829c56750b9a4711be3332"
integrity sha512-kN/Vpip8emMLn/eOza+4JwqDZBL6MPNpkdaEsgUtW1NYN3DZvZqSQrbKzJcTL6hd8YNmFTn7XGWMwccOcJBL0A==
"@rollup/rollup-win32-ia32-msvc@4.28.1":
version "4.28.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.28.1.tgz#06d1d60d5b9f718e8a6c4a43f82e3f9e3254587f"
integrity sha512-ZkyTJ/9vkgrE/Rk9vhMXhf8l9D+eAhbAVbsGsXKy2ohmJaWg0LPQLnIxRdRp/bKyr8tXuPlXhIoGlEB5XpJnGA==
"@rollup/rollup-win32-x64-msvc@4.25.0":
version "4.25.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.25.0.tgz#93415e7e707e4b156d77c5950b983b58f4bc33f3"
integrity sha512-/RqrIFtLB926frMhZD0a5oDa4eFIbyNEwLLloMTEjmqfwZWXywwVVOVmwTsuyhC9HKkVEZcOOi+KV4U9wmOdlg==
"@rollup/rollup-win32-x64-msvc@4.28.0":
version "4.28.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.28.0.tgz#cb313feef9ac6e3737067fdf34f42804ac65a6f2"
integrity sha512-Bvno2/aZT6usSa7lRDL2+hMjVAGjuqaymF1ApZm31JXzniR/hvr14jpU+/z4X6Gt5BPlzosscyJZGUvguXIqeQ==
"@rollup/rollup-win32-x64-msvc@4.28.1":
version "4.28.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.28.1.tgz#4dff5c4259ebe6c5b4a8f2c5bc3829b7a8447ff0"
integrity sha512-ZvK2jBafvttJjoIdKm/Q/Bh7IJ1Ose9IBOwpOXcOvW3ikGTQGmKDgxTC6oCAzW6PynbkKP8+um1du81XJHZ0JA==
"@rtsao/scc@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8"
integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==
"@sentry-internal/browser-utils@8.43.0":
version "8.43.0"
resolved "https://registry.yarnpkg.com/@sentry-internal/browser-utils/-/browser-utils-8.43.0.tgz#b064908a537d1cc17d8ddaf0f4c5d712557cbf40"
integrity sha512-5WhJZ3SA5sZVDBwOsChDd5JCzYcwBX7sEqBqEcm3pFru6TUihEnFIJmDIbreIyrQMwUhs3dTxnfnidgjr5z1Ag==
"@sentry-internal/browser-utils@8.45.0":
version "8.45.0"
resolved "https://registry.yarnpkg.com/@sentry-internal/browser-utils/-/browser-utils-8.45.0.tgz#8e9217b8e8a4242c9a8244dce648289eaa1e38a0"
integrity sha512-MX/E/C+W5I9jkGD1PsbZ2hpCc7YuizNKmEbuGPxQPfUSIPrdE2wpo6ZfIhEbxq9m/trl1oRCN4PXi3BB7dlYYg==
dependencies:
"@sentry/core" "8.43.0"
"@sentry/core" "8.45.0"
"@sentry-internal/feedback@8.43.0":
version "8.43.0"
resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-8.43.0.tgz#9477b999c9bca62335eb944a6f7246a96beb0111"
integrity sha512-rcGR2kzFu4vLXBQbI9eGJwjyToyjl36O2q/UKbiZBNJ5IFtDvKRLke6jIHq/YqiHPfFGpVtq5M/lYduDfA/eaQ==
"@sentry-internal/feedback@8.45.0":
version "8.45.0"
resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-8.45.0.tgz#cfd7f54d5089682a2768c1229a5efcda4d9561fe"
integrity sha512-WerpfkKrKPAlnQuqjEgKXZtrx68cla7GyOkNOeL40JQbY4/By4Qjx1atUOmgk/FdjrCLPw+jQQY9pXRpMRqqRw==
dependencies:
"@sentry/core" "8.43.0"
"@sentry/core" "8.45.0"
"@sentry-internal/replay-canvas@8.43.0":
version "8.43.0"
resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-8.43.0.tgz#f5672a08c9eb588afa0bf36f07b9f5c29b5c9920"
integrity sha512-rL8G7E1GtozH8VNalRrBQNjYDJ5ChWS/vpQI5hUG11PZfvQFXEVatLvT3uO2l0xIlHm4idTsHOSLTe/usxnogQ==
"@sentry-internal/replay-canvas@8.45.0":
version "8.45.0"
resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-8.45.0.tgz#46f39402ff0cfee4ae05191af20b4e4fac6f474c"
integrity sha512-LZ8kBuzO5gutDiWnCyYEzBMDLq9PIllcsWsXRpKoau0Zqs3DbyRolI11dNnxmUSh7UW21FksxBpqn5yPmUMbag==
dependencies:
"@sentry-internal/replay" "8.43.0"
"@sentry/core" "8.43.0"
"@sentry-internal/replay" "8.45.0"
"@sentry/core" "8.45.0"
"@sentry-internal/replay@8.43.0":
version "8.43.0"
resolved "https://registry.yarnpkg.com/@sentry-internal/replay/-/replay-8.43.0.tgz#4e2e3844f52b47b16bf816d21857921bbfe85d62"
integrity sha512-geV5/zejLfGGwWHjylzrb1w8NI3U37GMG9/53nmv13FmTXUDF5XF2lh41KXFVYwvp7Ha4bd1FRQ9IU9YtBWskw==
"@sentry-internal/replay@8.45.0":
version "8.45.0"
resolved "https://registry.yarnpkg.com/@sentry-internal/replay/-/replay-8.45.0.tgz#e94d250de235491888694f7cf0f637114adb4b9a"
integrity sha512-SOFwFpzx0B6lxhLl2hBnxvybo7gdB5TMY8dOHMwXgk5A2+BXvSpvWXnr33yqUlBmC8R3LeFTB3C0plzM5lhkJg==
dependencies:
"@sentry-internal/browser-utils" "8.43.0"
"@sentry/core" "8.43.0"
"@sentry-internal/browser-utils" "8.45.0"
"@sentry/core" "8.45.0"
"@sentry/babel-plugin-component-annotate@2.22.7":
version "2.22.7"
resolved "https://registry.yarnpkg.com/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-2.22.7.tgz#604c7e33d48528a13477e7af597c4d5fca51b8bd"
integrity sha512-aa7XKgZMVl6l04NY+3X7BP7yvQ/s8scn8KzQfTLrGRarziTlMGrsCOBQtCNWXOPEbtxAIHpZ9dsrAn5EJSivOQ==
"@sentry/browser@8.43.0":
version "8.43.0"
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-8.43.0.tgz#4eec67bc6fb278727304045b612ac392674cade6"
integrity sha512-LGvLLnfmR8+AEgFmd7Q7KHiOTiV0P1Lvio2ENDELhEqJOIiICauttibVmig+AW02qg4kMeywvleMsUYaZv2RVA==
"@sentry/browser@8.45.0":
version "8.45.0"
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-8.45.0.tgz#2e8f7b8b1a7860863aae4d716b9748a21789f0e0"
integrity sha512-Y+BcfpXY1eEkOYOzgLGkx1YH940uMAymYOxfSZSvC+Vx6xHuaGT05mIFef/aeZbyu2AUs6JjdvD1BRBZlHg78w==
dependencies:
"@sentry-internal/browser-utils" "8.43.0"
"@sentry-internal/feedback" "8.43.0"
"@sentry-internal/replay" "8.43.0"
"@sentry-internal/replay-canvas" "8.43.0"
"@sentry/core" "8.43.0"
"@sentry-internal/browser-utils" "8.45.0"
"@sentry-internal/feedback" "8.45.0"
"@sentry-internal/replay" "8.45.0"
"@sentry-internal/replay-canvas" "8.45.0"
"@sentry/core" "8.45.0"
"@sentry/bundler-plugin-core@2.22.7":
version "2.22.7"
@@ -2998,18 +3073,18 @@
"@sentry/cli-win32-i686" "2.39.1"
"@sentry/cli-win32-x64" "2.39.1"
"@sentry/core@8.43.0":
version "8.43.0"
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-8.43.0.tgz#e96a489e87a9999199f5ac27d8860da37c1fa8b4"
integrity sha512-ktyovtjkTMNud+kC/XfqHVCoQKreIKgx/hgeRvzPwuPyd1t1KzYmRL3DBkbcWVnyOPpVTHn+RsEI1eRcVYHtvw==
"@sentry/core@8.45.0":
version "8.45.0"
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-8.45.0.tgz#a03a1b666989898ce7fb33f9ec279ea08450b317"
integrity sha512-4YTuBipWSh4JrtSYS5GxUQBAcAgOIkEoFfFbwVcr3ivijOacJLRXTBn3rpcy1CKjBq0PHDGR+2RGRYC+bNAMxg==
"@sentry/react@^8.0.0":
version "8.43.0"
resolved "https://registry.yarnpkg.com/@sentry/react/-/react-8.43.0.tgz#ad49bd16b0b1897613ef5cbd2f0a49b2b41f98a9"
integrity sha512-PsTzLrYio/FOJU537Y5Gj9jJi7OMHEjdttsC9INUxy5062LOd8ObtHsjE0mopLaSYEwUfSROQOBZCwmISh8ByQ==
version "8.45.0"
resolved "https://registry.yarnpkg.com/@sentry/react/-/react-8.45.0.tgz#9a1bfbbbb3575fffb92796acc28ad5bb93a6855a"
integrity sha512-xuJBDATJKAHOxpR5IBfGFWJxXb05GMPGGpk8UoWai1Mh50laAQ0/WW+5sDAKrCjXoA+JZ6fb3DP8EE2X93n1nw==
dependencies:
"@sentry/browser" "8.43.0"
"@sentry/core" "8.43.0"
"@sentry/browser" "8.45.0"
"@sentry/core" "8.45.0"
hoist-non-react-statics "^3.3.2"
"@sentry/vite-plugin@^2.0.0":
@@ -3273,9 +3348,9 @@
undici-types "~6.19.8"
"@types/node@^22.0.0":
version "22.10.1"
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.1.tgz#41ffeee127b8975a05f8c4f83fb89bcb2987d766"
integrity sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==
version "22.10.2"
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.2.tgz#a485426e6d1fdafc7b0d4c7b24e2c78182ddabb9"
integrity sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==
dependencies:
undici-types "~6.20.0"
@@ -3302,9 +3377,9 @@
"@types/node" "*"
"@types/react-dom@^18.3.0":
version "18.3.3"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.3.tgz#3654138d0da1b0c7916f6ed0dc1cc2b576d47650"
integrity sha512-uTYkxTLkYp41nq/ULXyXMtkNT1vu5fXJoqad6uTNCOGat5t9cLgF4vMNLBXsTOXpdOI44XzKPY1M5RRm0bQHuw==
version "18.3.5"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.5.tgz#45f9f87398c5dcea085b715c58ddcf1faf65f716"
integrity sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==
"@types/react-router-dom@^5.3.3":
version "5.3.3"
@@ -4040,7 +4115,17 @@ broccoli-plugin@^4.0.7:
rimraf "^3.0.2"
symlink-or-copy "^1.3.1"
browserslist@^4.23.1, browserslist@^4.23.3, browserslist@^4.24.0, browserslist@^4.24.2:
browserslist@^4.23.1, browserslist@^4.23.3:
version "4.24.3"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.3.tgz#5fc2725ca8fb3c1432e13dac278c7cc103e026d2"
integrity sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA==
dependencies:
caniuse-lite "^1.0.30001688"
electron-to-chromium "^1.5.73"
node-releases "^2.0.19"
update-browserslist-db "^1.1.1"
browserslist@^4.24.0, browserslist@^4.24.2:
version "4.24.2"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.2.tgz#f5845bc91069dbd55ee89faf9822e1d885d16580"
integrity sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==
@@ -4106,15 +4191,10 @@ camelcase@^6.2.0:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
caniuse-lite@^1.0.30001646:
version "1.0.30001680"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001680.tgz#5380ede637a33b9f9f1fc6045ea99bd142f3da5e"
integrity sha512-rPQy70G6AGUMnbwS1z6Xg+RkHYPAi18ihs47GH0jcxIG7wArmPgY3XbS2sRdBbxJljp3thdT8BIqv9ccCypiPA==
caniuse-lite@^1.0.30001669:
version "1.0.30001687"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001687.tgz#d0ac634d043648498eedf7a3932836beba90ebae"
integrity sha512-0S/FDhf4ZiqrTUiQ39dKeUjYRjkv7lOZU1Dgif2rIqrTzX/1wV2hfKu9TOm1IHkdSijfLswxTFzl/cvir+SLSQ==
caniuse-lite@^1.0.30001646, caniuse-lite@^1.0.30001669, caniuse-lite@^1.0.30001688:
version "1.0.30001688"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001688.tgz#f9d3ede749f083ce0db4c13db9d828adaf2e8d0a"
integrity sha512-Nmqpru91cuABu/DTCXbM2NSRHzM2uVHfPnhJ/1zEAJx/ILBRVmz3pzH4N7DZqbdG0gWClsCC05Oj0mJ/1AWMbA==
caseless@~0.12.0:
version "0.12.0"
@@ -4405,10 +4485,10 @@ css-blank-pseudo@^7.0.1:
dependencies:
postcss-selector-parser "^7.0.0"
css-has-pseudo@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/css-has-pseudo/-/css-has-pseudo-7.0.1.tgz#adbb51821e51f7a7c1d2df4d12827870cc311137"
integrity sha512-EOcoyJt+OsuKfCADgLT7gADZI5jMzIe/AeI6MeAYKiFBDmNmM7kk46DtSfMj5AohUJisqVzopBpnQTlvbyaBWg==
css-has-pseudo@^7.0.2:
version "7.0.2"
resolved "https://registry.yarnpkg.com/css-has-pseudo/-/css-has-pseudo-7.0.2.tgz#fb42e8de7371f2896961e1f6308f13c2c7019b72"
integrity sha512-nzol/h+E0bId46Kn2dQH5VElaknX2Sr0hFuB/1EomdC7j+OISt2ZzK7EHX9DZDY53WbIVAR7FYKSO2XnSf07MQ==
dependencies:
"@csstools/selector-specificity" "^5.0.0"
postcss-selector-parser "^7.0.0"
@@ -4440,10 +4520,10 @@ css.escape@^1.5.1:
resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb"
integrity sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==
cssdb@^8.2.1:
version "8.2.1"
resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-8.2.1.tgz#62a5d9a41e2c86f1d7c35981098fc5ce47c5766c"
integrity sha512-KwEPys7lNsC8OjASI8RrmwOYYDcm0JOW9zQhcV83ejYcQkirTEyeAGui8aO2F5PiS6SLpxuTzl6qlMElIdsgIg==
cssdb@^8.2.3:
version "8.2.3"
resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-8.2.3.tgz#7e6980bb5a785a9b4eb2a21bd38d50624b56cb46"
integrity sha512-9BDG5XmJrJQQnJ51VFxXCAtpZ5ebDlAREmO8sxMOVU0aSxN/gocbctjIG5LMh3WBUq+xTlb/jw2LoljBEqraTA==
cssesc@^3.0.0:
version "3.0.0"
@@ -4703,10 +4783,10 @@ easy-table@1.2.0:
optionalDependencies:
wcwidth "^1.0.1"
electron-to-chromium@^1.5.41:
version "1.5.72"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.72.tgz#a732805986d3a5b5fedd438ddf4616c7d78ac2df"
integrity sha512-ZpSAUOZ2Izby7qnZluSrAlGgGQzucmFbN0n64dYzocYxnxV5ufurpj3VgEe4cUp7ir9LmeLxNYo8bVnlM8bQHw==
electron-to-chromium@^1.5.41, electron-to-chromium@^1.5.73:
version "1.5.73"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.73.tgz#f32956ce40947fa3c8606726a96cd8fb5bb5f720"
integrity sha512-8wGNxG9tAG5KhGd3eeA0o6ixhiNdgr0DcHWm85XPCphwZgD1lIEoi6t3VERayWao7SF7AAZTw6oARGJeVjH8Kg==
emoji-regex@^8.0.0:
version "8.0.0"
@@ -5867,13 +5947,6 @@ interpret@^1.0.0:
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e"
integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==
invariant@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==
dependencies:
loose-envify "^1.0.0"
is-array-buffer@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98"
@@ -6294,9 +6367,9 @@ kleur@^3.0.3:
integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
knip@^5.27.2:
version "5.39.2"
resolved "https://registry.yarnpkg.com/knip/-/knip-5.39.2.tgz#1faacd8d8ef36b509b2f6e396cce85b645abb04e"
integrity sha512-BuvuWRllLWV/r2G4m9ggNH+DZ6gouP/dhtJPXVlMbWNF++w9/EfrF6k2g7YBKCwjzCC+PXmYtpH8S2t8RjnY4Q==
version "5.40.0"
resolved "https://registry.yarnpkg.com/knip/-/knip-5.40.0.tgz#6da9113d9d0c696fc3e5dc3f3a281db57b4b828a"
integrity sha512-EzBfQDz4YBzYnMLueWnaaVr15mneqZs1c3RanttciuVuRcodlNjzAmR2nch/khlRdVABAxAdMGFxfSvhvcH1NA==
dependencies:
"@nodelib/fs.walk" "1.2.8"
"@snyk/github-codeowners" "1.1.0"
@@ -6351,12 +6424,12 @@ lines-and-columns@^1.1.6:
integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
livekit-client@^2.5.7:
version "2.7.0"
resolved "https://registry.yarnpkg.com/livekit-client/-/livekit-client-2.7.0.tgz#d7a80aff4ad335dd093b0c90d0d715466539651a"
integrity sha512-4vjfSReFNAUD+2oLUz9qFRWztJaI/+AexpOmCgizNsPYpvvqgAvEGxapnhuAug9uP7JVYaKPXaTCq90MWZoDHg==
version "2.7.5"
resolved "https://registry.yarnpkg.com/livekit-client/-/livekit-client-2.7.5.tgz#2c8e5956c1fda5844799f5a864ac87c803ca1a43"
integrity sha512-sPhHYwXvG75y1LDC50dDC9k6Z49L2vc/HcMRhzhi7yBca6ofPEebpB0bmPOry4ovrnFA+a8TL1pFR2mko1/clw==
dependencies:
"@livekit/mutex" "1.0.0"
"@livekit/protocol" "1.24.0"
"@livekit/protocol" "1.29.4"
events "^3.3.0"
loglevel "^1.8.0"
sdp-transform "^2.14.1"
@@ -6414,7 +6487,7 @@ long@^5.0.0:
resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1"
integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
@@ -6494,11 +6567,11 @@ matrix-events-sdk@0.0.1:
integrity sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA==
matrix-js-sdk@matrix-org/matrix-js-sdk#develop:
version "34.12.0"
resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/edac6a9983bd604c17535a9ae673dc979c7b61c4"
version "34.13.0"
resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/d1de32ea2773df4c6f8a956678bbd19b6d022475"
dependencies:
"@babel/runtime" "^7.12.5"
"@matrix-org/matrix-sdk-crypto-wasm" "^9.0.0"
"@matrix-org/matrix-sdk-crypto-wasm" "^11.0.0"
"@matrix-org/olm" "3.2.15"
another-json "^0.2.0"
bs58 "^6.0.0"
@@ -6603,9 +6676,9 @@ ms@^2.1.1, ms@^2.1.3:
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
nanoid@^3.3.7:
version "3.3.7"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8"
integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==
version "3.3.8"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf"
integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==
natural-compare@^1.4.0:
version "1.4.0"
@@ -6632,7 +6705,7 @@ node-fetch@^2.6.7:
dependencies:
whatwg-url "^5.0.0"
node-releases@^2.0.18:
node-releases@^2.0.18, node-releases@^2.0.19:
version "2.0.19"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314"
integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==
@@ -7133,9 +7206,9 @@ postcss-place@^10.0.0:
postcss-value-parser "^4.2.0"
postcss-preset-env@^10.0.0:
version "10.1.1"
resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-10.1.1.tgz#6ee631272353fb1c4a9711943e9b80a178ffce44"
integrity sha512-wqqsnBFD6VIwcHHRbhjTOcOi4qRVlB26RwSr0ordPj7OubRRxdWebv/aLjKLRR8zkZrbxZyuus03nOIgC5elMQ==
version "10.1.2"
resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-10.1.2.tgz#ea9c25d92045ef06edd78f9945d2586107aab3e3"
integrity sha512-OqUBZ9ByVfngWhMNuBEMy52Izj07oIFA6K/EOGBlaSv+P12MiE1+S2cqXtS1VuW82demQ/Tzc7typYk3uHunkA==
dependencies:
"@csstools/postcss-cascade-layers" "^5.0.1"
"@csstools/postcss-color-function" "^4.0.6"
@@ -7172,9 +7245,9 @@ postcss-preset-env@^10.0.0:
autoprefixer "^10.4.19"
browserslist "^4.23.1"
css-blank-pseudo "^7.0.1"
css-has-pseudo "^7.0.1"
css-has-pseudo "^7.0.2"
css-prefers-color-scheme "^10.0.0"
cssdb "^8.2.1"
cssdb "^8.2.3"
postcss-attribute-case-insensitive "^7.0.1"
postcss-clamp "^4.1.0"
postcss-color-functional-notation "^7.0.6"
@@ -7386,9 +7459,9 @@ react-error-boundary@^3.1.0:
"@babel/runtime" "^7.12.5"
react-i18next@^15.0.0:
version "15.1.4"
resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-15.1.4.tgz#65c03c31a5e42202000652e163f22f23a9306a60"
integrity sha512-2tai71gmehbvl9ZIqPMqlCCkm/cbeV1G4STpmM3C8Uzo6T2l8jDvZxEVSsQKt8blP9X34iRFP/k1ROqG2296MQ==
version "15.2.0"
resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-15.2.0.tgz#6b51650e1e93eb4d235a4d533fcf61b3bbf4ea10"
integrity sha512-iJNc8111EaDtVTVMKigvBtPHyrJV+KblWG73cUxqp+WmJCcwkzhWNFXmkAD5pwP2Z4woeDj/oXDdbjDsb3Gutg==
dependencies:
"@babel/runtime" "^7.25.0"
html-parse-stringify "^3.0.1"
@@ -7409,11 +7482,11 @@ react-refresh@^0.14.2:
integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==
react-remove-scroll-bar@^2.3.6:
version "2.3.6"
resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz#3e585e9d163be84a010180b18721e851ac81a29c"
integrity sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==
version "2.3.8"
resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz#99c20f908ee467b385b68a3469b4a3e750012223"
integrity sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==
dependencies:
react-style-singleton "^2.2.1"
react-style-singleton "^2.2.2"
tslib "^2.0.0"
react-remove-scroll@2.6.0:
@@ -7455,13 +7528,12 @@ react-router@5.3.4:
tiny-invariant "^1.0.2"
tiny-warning "^1.0.0"
react-style-singleton@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.1.tgz#f99e420492b2d8f34d38308ff660b60d0b1205b4"
integrity sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==
react-style-singleton@^2.2.1, react-style-singleton@^2.2.2:
version "2.2.3"
resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.3.tgz#4265608be69a4d70cfe3047f2c6c88b2c3ace388"
integrity sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==
dependencies:
get-nonce "^1.0.0"
invariant "^2.2.4"
tslib "^2.0.0"
react-use-clipboard@^1.0.7:
@@ -7753,30 +7825,31 @@ rollup@^4.20.0:
fsevents "~2.3.2"
rollup@^4.23.0:
version "4.28.0"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.28.0.tgz#eb8d28ed43ef60a18f21d0734d230ee79dd0de77"
integrity sha512-G9GOrmgWHBma4YfCcX8PjH0qhXSdH8B4HDE2o4/jaxj93S4DPCIDoLcXz99eWMji4hB29UFCEd7B2gwGJDR9cQ==
version "4.28.1"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.28.1.tgz#7718ba34d62b449dfc49adbfd2f312b4fe0df4de"
integrity sha512-61fXYl/qNVinKmGSTHAZ6Yy8I3YIJC/r2m9feHo6SwVAVcLT5MPwOUFe7EuURA/4m0NR8lXG4BBXuo/IZEsjMg==
dependencies:
"@types/estree" "1.0.6"
optionalDependencies:
"@rollup/rollup-android-arm-eabi" "4.28.0"
"@rollup/rollup-android-arm64" "4.28.0"
"@rollup/rollup-darwin-arm64" "4.28.0"
"@rollup/rollup-darwin-x64" "4.28.0"
"@rollup/rollup-freebsd-arm64" "4.28.0"
"@rollup/rollup-freebsd-x64" "4.28.0"
"@rollup/rollup-linux-arm-gnueabihf" "4.28.0"
"@rollup/rollup-linux-arm-musleabihf" "4.28.0"
"@rollup/rollup-linux-arm64-gnu" "4.28.0"
"@rollup/rollup-linux-arm64-musl" "4.28.0"
"@rollup/rollup-linux-powerpc64le-gnu" "4.28.0"
"@rollup/rollup-linux-riscv64-gnu" "4.28.0"
"@rollup/rollup-linux-s390x-gnu" "4.28.0"
"@rollup/rollup-linux-x64-gnu" "4.28.0"
"@rollup/rollup-linux-x64-musl" "4.28.0"
"@rollup/rollup-win32-arm64-msvc" "4.28.0"
"@rollup/rollup-win32-ia32-msvc" "4.28.0"
"@rollup/rollup-win32-x64-msvc" "4.28.0"
"@rollup/rollup-android-arm-eabi" "4.28.1"
"@rollup/rollup-android-arm64" "4.28.1"
"@rollup/rollup-darwin-arm64" "4.28.1"
"@rollup/rollup-darwin-x64" "4.28.1"
"@rollup/rollup-freebsd-arm64" "4.28.1"
"@rollup/rollup-freebsd-x64" "4.28.1"
"@rollup/rollup-linux-arm-gnueabihf" "4.28.1"
"@rollup/rollup-linux-arm-musleabihf" "4.28.1"
"@rollup/rollup-linux-arm64-gnu" "4.28.1"
"@rollup/rollup-linux-arm64-musl" "4.28.1"
"@rollup/rollup-linux-loongarch64-gnu" "4.28.1"
"@rollup/rollup-linux-powerpc64le-gnu" "4.28.1"
"@rollup/rollup-linux-riscv64-gnu" "4.28.1"
"@rollup/rollup-linux-s390x-gnu" "4.28.1"
"@rollup/rollup-linux-x64-gnu" "4.28.1"
"@rollup/rollup-linux-x64-musl" "4.28.1"
"@rollup/rollup-win32-arm64-msvc" "4.28.1"
"@rollup/rollup-win32-ia32-msvc" "4.28.1"
"@rollup/rollup-win32-x64-msvc" "4.28.1"
fsevents "~2.3.2"
rrweb-cssom@^0.7.1:
@@ -7856,9 +7929,9 @@ safe-regex-test@^1.0.3:
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
sass@^1.42.1:
version "1.82.0"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.82.0.tgz#30da277af3d0fa6042e9ceabd0d984ed6d07df70"
integrity sha512-j4GMCTa8elGyN9A7x7bEglx0VgSpNUG4W4wNedQ33wSMdnkqQCT8HTwOaVSV4e6yQovcu/3Oc4coJP/l0xhL2Q==
version "1.83.0"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.83.0.tgz#e36842c0b88a94ed336fd16249b878a0541d536f"
integrity sha512-qsSxlayzoOjdvXMVLkzF84DJFc2HZEL/rFyGIKbbilYtAvlCxyuzUeff9LawTn4btVnLKg75Z8MMr1lxU1lfGw==
dependencies:
chokidar "^4.0.0"
immutable "^5.0.2"
@@ -8654,9 +8727,9 @@ use-callback-ref@^1.3.0:
tslib "^2.0.0"
use-sidecar@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.1.2.tgz#2f43126ba2d7d7e117aa5855e5d8f0276dfe73c2"
integrity sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==
version "1.1.3"
resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.1.3.tgz#10e7fd897d130b896e2c546c63a5e8233d00efdb"
integrity sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==
dependencies:
detect-node-es "^1.1.0"
tslib "^2.0.0"
@@ -8801,9 +8874,9 @@ vite@^5.0.0:
fsevents "~2.3.3"
vite@^6.0.0:
version "6.0.2"
resolved "https://registry.yarnpkg.com/vite/-/vite-6.0.2.tgz#7a22630c73c7b663335ddcdb2390971ffbc14993"
integrity sha512-XdQ+VsY2tJpBsKGs0wf3U/+azx8BBpYRHFAyKm5VeEZNOJZRB63q7Sc8Iup3k0TrN3KO6QgyzFf+opSbfY1y0g==
version "6.0.3"
resolved "https://registry.yarnpkg.com/vite/-/vite-6.0.3.tgz#cc01f403e326a9fc1e064235df8a6de084c8a491"
integrity sha512-Cmuo5P0ENTN6HxLSo6IHsjCLn/81Vgrp81oaiFFMRa8gGDj5xEjIcEpf2ZymZtZR8oU0P2JX5WuUp/rlXcHkAw==
dependencies:
esbuild "^0.24.0"
postcss "^8.4.49"
@@ -9145,6 +9218,6 @@ zod-validation-error@^3.0.3:
integrity sha512-ZOPR9SVY6Pb2qqO5XHt+MkkTRxGXb4EVtnjc9JpXUOtUB1T9Ru7mZOT361AN3MsetVe7R0a1KZshJDZdgp9miQ==
zod@^3.22.4:
version "3.24.0"
resolved "https://registry.yarnpkg.com/zod/-/zod-3.24.0.tgz#babb32313f7c5f4a99812feee806d186b4f76bde"
integrity sha512-Hz+wiY8yD0VLA2k/+nsg2Abez674dDGTai33SwNvMPuf9uIrBC9eFgIMQxBBbHFxVXi8W+5nX9DcAh9YNSQm/w==
version "3.24.1"
resolved "https://registry.yarnpkg.com/zod/-/zod-3.24.1.tgz#27445c912738c8ad1e9de1bea0359fa44d9d35ee"
integrity sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==