diff --git a/config/nginx.conf b/config/nginx.conf
index f7253465..5dc69b2f 100644
--- a/config/nginx.conf
+++ b/config/nginx.conf
@@ -21,5 +21,9 @@ server {
expires 1w;
add_header Cache-Control "public, no-transform";
}
+
+ location /apple-app-site-association {
+ default_type application/json;
+ }
}
diff --git a/package.json b/package.json
index e86faef7..acc6068d 100644
--- a/package.json
+++ b/package.json
@@ -48,7 +48,7 @@
"@sentry/tracing": "^6.13.3",
"@use-gesture/react": "^10.2.11",
"@vector-im/compound-design-tokens": "^0.0.5",
- "@vector-im/compound-web": "^0.2.15",
+ "@vector-im/compound-web": "^0.4.0",
"@vitejs/plugin-basic-ssl": "^1.0.1",
"@vitejs/plugin-react": "^4.0.1",
"classnames": "^2.3.1",
@@ -59,7 +59,7 @@
"i18next-http-backend": "^1.4.4",
"livekit-client": "^1.12.3",
"lodash": "^4.17.21",
- "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#b698217445318f453e0b1086364a33113eaa85d9",
+ "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#6836720e1e1c2cb01d49d6e5fcfc01afc14834ca",
"matrix-widget-api": "^1.3.1",
"mermaid": "^9.0.0",
"normalize.css": "^8.0.1",
diff --git a/public/.well-known/assetlinks.json b/public/.well-known/assetlinks.json
new file mode 100644
index 00000000..0eb37bf0
--- /dev/null
+++ b/public/.well-known/assetlinks.json
@@ -0,0 +1,12 @@
+[
+ {
+ "relation": ["delegate_permission/common.handle_all_urls"],
+ "target": {
+ "namespace": "android_app",
+ "package_name": "io.element.android.x.debug",
+ "sha256_cert_fingerprints": [
+ "B0:B0:51:DC:56:5C:81:2F:E1:7F:6F:3E:94:5B:4D:79:04:71:23:AB:0D:A6:12:86:76:9E:B2:94:91:97:13:0E"
+ ]
+ }
+ }
+]
diff --git a/public/apple-app-site-association b/public/apple-app-site-association
new file mode 100644
index 00000000..b27b5c71
--- /dev/null
+++ b/public/apple-app-site-association
@@ -0,0 +1,15 @@
+{
+ "applinks": {
+ "apps": [],
+ "details": [
+ {
+ "appIDs": [
+ "7J4U792NQT.io.element.elementx",
+ "7J4U792NQT.io.element.elementx.nightly",
+ "7J4U792NQT.io.element.elementx.pr"
+ ],
+ "paths": ["*"]
+ }
+ ]
+ }
+}
diff --git a/public/locales/bg/app.json b/public/locales/bg/app.json
index 8db3295d..79f1d22e 100644
--- a/public/locales/bg/app.json
+++ b/public/locales/bg/app.json
@@ -8,7 +8,6 @@
"Call link copied": "Връзка към разговора бе копирана",
"Call type menu": "Меню \"тип на разговора\"",
"Camera": "Камера",
- "Change layout": "Промени изгледа",
"Close": "Затвори",
"Confirm password": "Потвърди паролата",
"Copied!": "Копирано!",
@@ -16,27 +15,20 @@
"Create account": "Създай акаунт",
"Debug log": "Debug логове",
"Debug log request": "Заявка за debug логове",
- "Details": "Детайли",
"Developer": "Разработчик",
"Display name": "Име/псевдоним",
"Download debug logs": "Изтеглете debug логове",
"Exit full screen": "Излез от цял екран",
"Fetching group call timed out.": "Изтече времето за взимане на груповия разговор.",
- "Freedom": "Свобода",
"Full screen": "Цял екран",
"Go": "Напред",
- "Grid layout menu": "Меню \"решетков изглед\"",
"Home": "Начало",
"Include debug logs": "Включи debug логове",
"Incompatible versions": "Несъвместими версии",
- "Incompatible versions!": "Несъвместими версии!",
"Inspector": "Инспектор",
- "Invite": "Покани",
- "Invite people": "Покани хора",
"Join call": "Влез в разговора",
"Join call now": "Влез в разговора сега",
"Join existing call?": "Присъединяване към съществуващ разговор?",
- "Leave": "Напусни",
"Loading…": "Зареждане…",
"Local volume": "Локална сила на звука",
"Logging in…": "Влизане…",
@@ -44,7 +36,6 @@
"Login to your account": "Влезте в акаунта си",
"Microphone": "Микрофон",
"More": "Още",
- "Mute microphone": "Заглуши микрофона",
"No": "Не",
"Not now, return to home screen": "Не сега, върни се на началния екран",
"Not registered yet? <2>Create an account2>": "Все още не сте регистрирани? <2>Създайте акаунт2>",
@@ -68,13 +59,9 @@
"Sign out": "Излез",
"Speaker": "Говорител",
"Spotlight": "Прожектор",
- "Stop sharing screen": "Спри споделянето на екрана",
"Submit feedback": "Изпрати обратна връзка",
"Take me Home": "Отиди в Начало",
"This call already exists, would you like to join?": "Този разговор вече съществува, искате ли да се присъедините?",
- "Turn off camera": "Изключи камерата",
- "Turn on camera": "Включи камерата",
- "Unmute microphone": "Включи микрофона",
"User menu": "Потребителско меню",
"Username": "Потребителско име",
"Version: {{version}}": "Версия: {{version}}",
@@ -86,6 +73,5 @@
"Walkie-talkie call name": "Име на уоки-токи разговора",
"WebRTC is not supported or is being blocked in this browser.": "WebRTC не се поддържа или се блокира от браузъра.",
"Yes, join call": "Да, присъедини се",
- "Your recent calls": "Скорошните ви разговори",
- "{{names}}, {{name}}": "{{names}}, {{name}}"
+ "Your recent calls": "Скорошните ви разговори"
}
diff --git a/public/locales/cs/app.json b/public/locales/cs/app.json
index 2ceb326a..7d73b9eb 100644
--- a/public/locales/cs/app.json
+++ b/public/locales/cs/app.json
@@ -3,7 +3,6 @@
"Copied!": "Zkopírováno!",
"Confirm password": "Potvrdit heslo",
"Close": "Zavřít",
- "Change layout": "Změnit rozložení",
"Camera": "Kamera",
"Call link copied": "Odkaz na hovor zkopírován",
"Avatar": "Avatar",
@@ -19,13 +18,9 @@
"Version: {{version}}": "Verze: {{version}}",
"Username": "Uživatelské jméno",
"User menu": "Uživatelské menu",
- "Unmute microphone": "Zapnout mikrofon",
- "Turn on camera": "Zapnout kameru",
- "Turn off camera": "Vypnout kameru",
"This call already exists, would you like to join?": "Tento hovor již existuje, chcete se připojit?",
"Take me Home": "Domovská obrazovka",
"Submit feedback": "Dát feedback",
- "Stop sharing screen": "Zastavit sdílení obrazovek",
"Speaker": "Reproduktor",
"Sign out": "Odhlásit se",
"Sign in": "Přihlásit se",
@@ -45,7 +40,6 @@
"Password": "Heslo",
"Not now, return to home screen": "Teď ne, vrátit se na domovskou obrazovku",
"No": "Ne",
- "Mute microphone": "Ztlumit mikrofon",
"More": "Více",
"Microphone": "Mikrofon",
"Login to your account": "Přihlásit se ke svému účtu",
@@ -53,17 +47,12 @@
"Logging in…": "Přihlašování se…",
"Local volume": "Lokální hlasitost",
"Loading…": "Načítání…",
- "Leave": "Opustit hovor",
"Join call now": "Připojit se k hovoru",
"Join call": "Připojit se k hovoru",
- "Invite people": "Pozvat lidi",
- "Invite": "Pozvat",
"Inspector": "Insepktor",
- "Incompatible versions!": "Nekompatibilní verze!",
"Incompatible versions": "Nekompatibilní verze",
"Walkie-talkie call name": "Jméno vysílačkového hovoru",
"Walkie-talkie call": "Vysílačkový hovor",
- "{{names}}, {{name}}": "{{names}}, {{name}}",
"Spotlight": "Soustředěný mód",
"Recaptcha not loaded": "Recaptcha se nenačetla",
"Recaptcha dismissed": "Recaptcha byla zamítnuta",
@@ -72,17 +61,14 @@
"Join existing call?": "Připojit se k existujícimu hovoru?",
"Include debug logs": "Zahrnout ladící záznamy",
"Home": "Domov",
- "Grid layout menu": "Menu rozložení",
"Go": "Pokračovat",
"Full screen": "Zvětšit na celou obrazovku",
- "Freedom": "Volný",
"Fetching group call timed out.": "Vypršel časový limit načítání skupinového hovoru.",
"Exit full screen": "Ukončit režim celé obrazovky",
"Element Call Home": "Domov Element Call",
"Download debug logs": "Stáhnout ladící záznamy",
"Display name": "Zobrazované jméno",
"Developer": "Vývojář",
- "Details": "Detaily",
"Debug log request": "Žádost o protokoly ladění",
"Debug log": "Protokoly ladění",
"Create account": "Vytvořit účet",
diff --git a/public/locales/de/app.json b/public/locales/de/app.json
index 77334685..25e21ff4 100644
--- a/public/locales/de/app.json
+++ b/public/locales/de/app.json
@@ -8,7 +8,6 @@
"Call link copied": "Anruflink kopiert",
"Call type menu": "Anruftyp Menü",
"Camera": "Kamera",
- "Change layout": "Layout ändern",
"Close": "Schließen",
"Confirm password": "Passwort bestätigen",
"Copied!": "Kopiert!",
@@ -16,26 +15,19 @@
"Create account": "Konto erstellen",
"Debug log": "Debug-Protokoll",
"Debug log request": "Debug-Log Anfrage",
- "Details": "Details",
"Developer": "Entwickler",
"Display name": "Anzeigename",
"Download debug logs": "Debug-Protokolle herunterladen",
"Exit full screen": "Vollbildmodus verlassen",
- "Freedom": "Freiraum",
"Full screen": "Vollbild",
"Go": "Los geht’s",
- "Grid layout menu": "Grid-Layout-Menü",
"Home": "Startseite",
"Include debug logs": "Debug-Protokolle einschließen",
"Incompatible versions": "Inkompatible Versionen",
- "Incompatible versions!": "Inkompatible Versionen!",
"Inspector": "Inspektor",
- "Invite": "Einladen",
- "Invite people": "Personen einladen",
"Join call": "Anruf beitreten",
"Join call now": "Anruf beitreten",
"Join existing call?": "An bestehendem Anruf teilnehmen?",
- "Leave": "Verlassen",
"Loading…": "Lade …",
"Local volume": "Lokale Lautstärke",
"Logging in…": "Anmelden …",
@@ -43,7 +35,6 @@
"Login to your account": "Melde dich mit deinem Konto an",
"Microphone": "Mikrofon",
"More": "Mehr",
- "Mute microphone": "Mikrofon stummschalten",
"No": "Nein",
"Not now, return to home screen": "Nicht jetzt, zurück zum Startbildschirm",
"Not registered yet? <2>Create an account2>": "Noch nicht registriert? <2>Konto erstellen2>",
@@ -67,13 +58,9 @@
"Sign out": "Abmelden",
"Speaker": "Wiedergabegerät",
"Spotlight": "Rampenlicht",
- "Stop sharing screen": "Beenden der Bildschirmfreigabe",
"Submit feedback": "Rückmeldung geben",
"Take me Home": "Zurück zur Startseite",
"This call already exists, would you like to join?": "Dieser Aufruf existiert bereits, möchtest Du teilnehmen?",
- "Turn off camera": "Kamera ausschalten",
- "Turn on camera": "Kamera einschalten",
- "Unmute microphone": "Mikrofon aktivieren",
"User menu": "Benutzermenü",
"Username": "Benutzername",
"Version: {{version}}": "Version: {{version}}",
@@ -85,7 +72,6 @@
"WebRTC is not supported or is being blocked in this browser.": "WebRTC wird in diesem Browser nicht unterstützt oder ist blockiert.",
"Yes, join call": "Ja, Anruf beitreten",
"Your recent calls": "Deine letzten Anrufe",
- "{{names}}, {{name}}": "{{names}}, {{name}}",
"Fetching group call timed out.": "Zeitüberschreitung beim Abrufen des Gruppenanrufs.",
"Walkie-talkie call name": "Name des Walkie-Talkie-Anrufs",
"Sending debug logs…": "Sende Debug-Protokolle …",
@@ -118,7 +104,6 @@
"Element Call is temporarily not end-to-end encrypted while we test scalability.": "Element Call ist temporär nicht Ende-zu-Ende-verschlüsselt, während wir die Skalierbarkeit testen.",
"Connectivity to the server has been lost.": "Die Verbindung zum Server wurde getrennt.",
"Enable end-to-end encryption (password protected calls)": "Ende-zu-Ende-Verschlüsselung aktivieren (Passwort geschützte Anrufe)",
- "Password (if none, E2EE is disabled)": "Passwort (falls leer, wird E2EE deaktiviert)",
"End-to-end encryption isn't supported on your browser.": "Ende-zu-Ende-Verschlüsselung wird in deinem Browser nicht unterstützt.",
"Thanks!": "Danke!",
"You were disconnected from the call": "Deine Verbindung wurde getrennt",
diff --git a/public/locales/el/app.json b/public/locales/el/app.json
index 50c7fa94..20f0c200 100644
--- a/public/locales/el/app.json
+++ b/public/locales/el/app.json
@@ -2,7 +2,6 @@
"Version: {{version}}": "Έκδοση: {{version}}",
"User menu": "Μενού χρήστη",
"Submit feedback": "Υποβάλετε σχόλια",
- "Stop sharing screen": "Διακοπή κοινής χρήσης οθόνης",
"Sign in": "Σύνδεση",
"Show call inspector": "Εμφάνιση του επιθεωρητή κλήσης",
"Share screen": "Κοινή χρήση οθόνης",
@@ -13,10 +12,7 @@
"Not registered yet? <2>Create an account2>": "Δεν έχετε εγγραφεί ακόμα; <2>Δημιουργήστε λογαριασμό2>",
"Login to your account": "Συνδεθείτε στον λογαριασμό σας",
"Logging in…": "Σύνδεση…",
- "Invite people": "Προσκαλέστε άτομα",
- "Invite": "Πρόσκληση",
"Inspector": "Επιθεωρητής",
- "Incompatible versions!": "Μη συμβατές εκδόσεις!",
"Incompatible versions": "Μη συμβατές εκδόσεις",
"Display name": "Εμφανιζόμενο όνομα",
"Developer Settings": "Ρυθμίσεις προγραμματιστή",
@@ -26,7 +22,6 @@
"<0>Oops, something's gone wrong.0>": "<0>Ωχ, κάτι πήγε στραβά.0>",
"<0>Create an account0> Or <2>Access as a guest2>": "<0>Δημιουργήστε λογαριασμό0> Ή <2>Συμμετέχετε ως επισκέπτης2>",
"<0>Already have an account?0><1><0>Log in0> Or <2>Access as a guest2>1>": "<0>Έχετε ήδη λογαριασμό;0><1><0>Συνδεθείτε0> Ή <2>Συμμετέχετε ως επισκέπτης2>1>",
- "{{names}}, {{name}}": "{{names}}, {{name}}",
"Your recent calls": "Οι πρόσφατες κλήσεις σας",
"Yes, join call": "Ναι, συμμετοχή στην κλήση",
"WebRTC is not supported or is being blocked in this browser.": "Το WebRTC δεν υποστηρίζεται ή έχει αποκλειστεί σε αυτό το πρόγραμμα περιήγησης.",
@@ -37,8 +32,6 @@
"Video call": "Βίντεο κλήση",
"Video": "Βίντεο",
"Username": "Όνομα χρήστη",
- "Turn on camera": "Ενεργοποιήστε την κάμερα",
- "Turn off camera": "Απενεργοποιήστε την κάμερα",
"This call already exists, would you like to join?": "Αυτή η κλήση υπάρχει ήδη, θα θέλατε να συμμετάσχετε;",
"Speaker": "Ηχείο",
"Sign out": "Αποσύνδεση",
@@ -50,26 +43,22 @@
"Password": "Κωδικός",
"Not now, return to home screen": "Όχι τώρα, επιστροφή στην αρχική οθόνη",
"No": "Όχι",
- "Mute microphone": "Σίγαση μικροφώνου",
"More": "Περισσότερα",
"Microphone": "Μικρόφωνο",
"Login": "Σύνδεση",
"Loading…": "Φόρτωση…",
- "Leave": "Αποχώρηση",
"Join existing call?": "Συμμετοχή στην υπάρχουσα κλήση;",
"Join call now": "Συμμετοχή στην κλήση τώρα",
"Join call": "Συμμετοχή στην κλήση",
"Go": "Μετάβαση",
"Full screen": "Πλήρη οθόνη",
"Exit full screen": "Έξοδος από πλήρη οθόνη",
- "Details": "Λεπτομέρειες",
"Create account": "Δημιουργία λογαριασμού",
"Copy and share this call link": "Αντιγράψτε και μοιραστείτε αυτόν τον σύνδεσμο κλήσης",
"Copy": "Αντιγραφή",
"Copied!": "Αντιγράφηκε!",
"Confirm password": "Επιβεβαίωση κωδικού",
"Close": "Κλείσιμο",
- "Change layout": "Αλλαγή διάταξης",
"Camera": "Κάμερα",
"Audio": "Ήχος",
"Send debug logs": "Αποστολή αρχείων καταγραφής",
@@ -79,7 +68,6 @@
"Local volume": "Τοπική ένταση",
"Home": "Αρχική",
"Show connection stats": "Εμφάνιση στατιστικών σύνδεσης",
- "Unmute microphone": "Κατάργηση σίγασης μικροφώνου",
"Take me Home": "Μετάβαση στην Αρχική",
"{{displayName}} is presenting": "{{displayName}} παρουσιάζει",
"<0>0><1>1>You may withdraw consent by unchecking this box. If you are currently in a call, this setting will take effect at the end of the call.": "<0>0><1>1>Μπορείτε να ανακαλέσετε τη συγκατάθεσή σας αποεπιλέγοντας αυτό το πλαίσιο. Εάν βρίσκεστε σε κλήση, η ρύθμιση αυτή θα τεθεί σε ισχύ στο τέλος της.",
@@ -88,7 +76,6 @@
"<0>Why not finish by setting up a password to keep your account?0><1>You'll be able to keep your name and set an avatar for use on future calls1>": "<0>Γιατί να μην ολοκληρώσετε με τη δημιουργία ενός κωδικού πρόσβασης για τη διατήρηση του λογαριασμού σας;0><1>Θα μπορείτε να διατηρήσετε το όνομά σας και να ορίσετε ένα avatar για χρήση σε μελλοντικές κλήσεις.1>",
"Another user on this call is having an issue. In order to better diagnose these issues we'd like to collect a debug log.": "Ένας άλλος χρήστης σε αυτή την κλήση έχει ένα πρόβλημα. Για την καλύτερη διάγνωση αυτών των προβλημάτων θα θέλαμε να συλλέξουμε ένα αρχείο καταγραφής σφαλμάτων.",
"By participating in this beta, you consent to the collection of anonymous data, which we use to improve the product. You can find more information about which data we track in our <2>Privacy Policy2> and our <5>Cookie Policy5>.": "Συμμετέχοντας σε αυτή τη δοκιμαστική έκδοση, συναινείτε στη συλλογή ανώνυμων δεδομένων, τα οποία χρησιμοποιούμε για τη βελτίωση του προϊόντος. Μπορείτε να βρείτε περισσότερες πληροφορίες σχετικά με το ποια δεδομένα καταγράφουμε στην <2>Πολιτική απορρήτου2> και στην <5>Πολιτική cookies5>.",
- "Grid layout menu": "Μενού διάταξης πλέγματος",
"If you are experiencing issues or simply would like to provide some feedback, please send us a short description below.": "Εάν αντιμετωπίζετε προβλήματα ή απλά θέλετε να μας δώσετε κάποια σχόλια, παρακαλούμε στείλτε μας μια σύντομη περιγραφή παρακάτω.",
"Other users are trying to join this call from incompatible versions. These users should ensure that they have refreshed their browsers:<1>{userLis}1>": "Κάποιοι άλλοι χρήστες προσπαθούν να συμμετάσχουν σε αυτή την κλήση από ασύμβατες εκδόσεις. Αυτοί οι χρήστες θα πρέπει να βεβαιωθούν ότι έχουν κάνει ανανέωση (refresh) την καρτέλα του περιηγητή τους:<1>{userLis}1>",
"Expose developer settings in the settings window.": "Εμφάνιση ρυθμίσεων προγραμματιστή στο παράθυρο ρυθμίσεων.",
@@ -109,7 +96,6 @@
"Submit": "Υποβολή",
"Your feedback": "Τα σχόλιά σας",
"Fetching group call timed out.": "Η ομαδική κλήση έληξε από τέλος χρόνου.",
- "Freedom": "Ελευθερία",
"Spotlight": "Spotlight",
"Element Call Home": "Element Κεντρική Οθόνη Κλήσεων"
}
diff --git a/public/locales/en-GB/app.json b/public/locales/en-GB/app.json
index f2605959..f6a7ed65 100644
--- a/public/locales/en-GB/app.json
+++ b/public/locales/en-GB/app.json
@@ -1,9 +1,11 @@
{
- "{{count}} stars|one": "{{count}} star",
+ "{{count, number}}|one": "{{count, number}}",
+ "{{count, number}}|other": "{{count, number}}",
+ "{{count}} stars|one": "{{count}} stars",
"{{count}} stars|other": "{{count}} stars",
"{{displayName}} is presenting": "{{displayName}} is presenting",
"{{displayName}}, your call has ended.": "{{displayName}}, your call has ended.",
- "{{names}}, {{name}}": "{{names}}, {{name}}",
+ "{{names, list(style: short;)}}": "{{names, list(style: short;)}}",
"<0>0><1>1>You may withdraw consent by unchecking this box. If you are currently in a call, this setting will take effect at the end of the call.": "<0>0><1>1>You may withdraw consent by unchecking this box. If you are currently in a call, this setting will take effect at the end of the call.",
"<0>Already have an account?0><1><0>Log in0> Or <2>Access as a guest2>1>": "<0>Already have an account?0><1><0>Log in0> Or <2>Access as a guest2>1>",
"<0>Create an account0> Or <2>Access as a guest2>": "<0>Create an account0> Or <2>Access as a guest2>",
@@ -22,7 +24,6 @@
"Call link copied": "Call link copied",
"Call type menu": "Call type menu",
"Camera": "Camera",
- "Change layout": "Change layout",
"Close": "Close",
"Confirm password": "Confirm password",
"Connectivity to the server has been lost.": "Connectivity to the server has been lost.",
@@ -32,7 +33,6 @@
"Create account": "Create account",
"Debug log": "Debug log",
"Debug log request": "Debug log request",
- "Details": "Details",
"Developer": "Developer",
"Developer Settings": "Developer Settings",
"Display name": "Display name",
@@ -40,25 +40,20 @@
"Element Call Home": "Element Call Home",
"Element Call is temporarily not end-to-end encrypted while we test scalability.": "Element Call is temporarily not end-to-end encrypted while we test scalability.",
"Enable end-to-end encryption (password protected calls)": "Enable end-to-end encryption (password protected calls)",
+ "Encrypted": "Encrypted",
"End call": "End call",
"End-to-end encryption isn't supported on your browser.": "End-to-end encryption isn't supported on your browser.",
"Exit full screen": "Exit full screen",
"Expose developer settings in the settings window.": "Expose developer settings in the settings window.",
"Feedback": "Feedback",
- "Fetching group call timed out.": "Fetching group call timed out.",
- "Freedom": "Freedom",
"Full screen": "Full screen",
"Go": "Go",
- "Grid layout menu": "Grid layout menu",
+ "Grid": "Grid",
"Home": "Home",
"How did it go?": "How did it go?",
"If you are experiencing issues or simply would like to provide some feedback, please send us a short description below.": "If you are experiencing issues or simply would like to provide some feedback, please send us a short description below.",
"Include debug logs": "Include debug logs",
- "Incompatible versions": "Incompatible versions",
- "Incompatible versions!": "Incompatible versions!",
"Inspector": "Inspector",
- "Invite": "Invite",
- "Invite people": "Invite people",
"Join call": "Join call",
"Join call now": "Join call now",
"Join existing call?": "Join existing call?",
@@ -72,9 +67,9 @@
"Microphone on": "Microphone on",
"More": "More",
"No": "No",
+ "Not encrypted": "Not encrypted",
"Not now, return to home screen": "Not now, return to home screen",
"Not registered yet? <2>Create an account2>": "Not registered yet? <2>Create an account2>",
- "Other users are trying to join this call from incompatible versions. These users should ensure that they have refreshed their browsers:<1>{userLis}1>": "Other users are trying to join this call from incompatible versions. These users should ensure that they have refreshed their browsers:<1>{userLis}1>",
"Password": "Password",
"Passwords must match": "Passwords must match",
"Profile": "Profile",
@@ -91,7 +86,9 @@
"Sending debug logs…": "Sending debug logs…",
"Sending…": "Sending…",
"Settings": "Settings",
+ "Share": "Share",
"Share screen": "Share screen",
+ "Share this call": "Share this call",
"Sharing screen": "Sharing screen",
"Show call inspector": "Show call inspector",
"Show connection stats": "Show connection stats",
@@ -106,7 +103,6 @@
"Thanks, we received your feedback!": "Thanks, we received your feedback!",
"Thanks!": "Thanks!",
"This call already exists, would you like to join?": "This call already exists, would you like to join?",
- "This call is not end-to-end encrypted.": "This call is not end-to-end encrypted.",
"This site is protected by ReCAPTCHA and the Google <2>Privacy Policy2> and <6>Terms of Service6> apply.<9>9>By clicking \"Register\", you agree to our <12>End User Licensing Agreement (EULA)12>": "This site is protected by ReCAPTCHA and the Google <2>Privacy Policy2> and <6>Terms of Service6> apply.<9>9>By clicking \"Register\", you agree to our <12>End User Licensing Agreement (EULA)12>",
"User menu": "User menu",
"Username": "Username",
@@ -119,8 +115,8 @@
"Waiting for other participants…": "Waiting for other participants…",
"Walkie-talkie call": "Walkie-talkie call",
"Walkie-talkie call name": "Walkie-talkie call name",
- "WebRTC is not supported or is being blocked in this browser.": "WebRTC is not supported or is being blocked in this browser.",
"Yes, join call": "Yes, join call",
+ "You": "You",
"You were disconnected from the call": "You were disconnected from the call",
"Your feedback": "Your feedback",
"Your recent calls": "Your recent calls"
diff --git a/public/locales/es/app.json b/public/locales/es/app.json
index ddd7faf4..594ed394 100644
--- a/public/locales/es/app.json
+++ b/public/locales/es/app.json
@@ -16,12 +16,8 @@
"Version: {{version}}": "Versión: {{version}}",
"Username": "Nombre de usuario",
"User menu": "Menú de usuario",
- "Unmute microphone": "Desilenciar el micrófono",
- "Turn on camera": "Encender la cámara",
- "Turn off camera": "Apagar la cámara",
"Take me Home": "Volver al inicio",
"Submit feedback": "Enviar comentarios",
- "Stop sharing screen": "Dejar de compartir pantalla",
"Spotlight": "Foco",
"Speaker": "Altavoz",
"Sign out": "Cerrar sesión",
@@ -44,34 +40,26 @@
"Other users are trying to join this call from incompatible versions. These users should ensure that they have refreshed their browsers:<1>{userLis}1>": "Otros usuarios están intentando unirse a la llamada con versiones incompatibles. Estos usuarios deberán asegurarse de que han refrescado sus navegadores:<1>{userLis}1>",
"Not now, return to home screen": "Ahora no, volver a la pantalla de inicio",
"No": "No",
- "Mute microphone": "Silenciar micrófono",
"More": "Más",
"Microphone": "Micrófono",
"Login": "Iniciar sesión",
"Logging in…": "Iniciando sesión…",
"Local volume": "Volumen local",
"Loading…": "Cargando…",
- "Leave": "Abandonar",
"Join existing call?": "¿Unirse a llamada existente?",
"Join call now": "Unirse a la llamada ahora",
"Join call": "Unirse a la llamada",
- "Invite people": "Invitar a gente",
- "Invite": "Invitar",
"Inspector": "Inspector",
- "Incompatible versions!": "¡Versiones incompatibles!",
"Incompatible versions": "Versiones incompatibles",
"Include debug logs": "Incluir registros de depuración",
"Home": "Inicio",
- "Grid layout menu": "Menú de distribución de cuadrícula",
"Go": "Comenzar",
"Full screen": "Pantalla completa",
- "Freedom": "Libre",
"Fetching group call timed out.": "Se ha agotado el tiempo de espera para obtener la llamada grupal.",
"Exit full screen": "Salir de pantalla completa",
"Download debug logs": "Descargar registros de depuración",
"Display name": "Nombre a mostrar",
"Developer": "Desarrollador",
- "Details": "Detalles",
"Debug log request": "Petición de registros de depuración",
"Debug log": "Registro de depuración",
"Create account": "Crear cuenta",
@@ -79,12 +67,10 @@
"Copied!": "¡Copiado!",
"Confirm password": "Confirmar contraseña",
"Close": "Cerrar",
- "Change layout": "Cambiar distribución",
"Camera": "Cámara",
"Call type menu": "Menú de tipo de llamada",
"Call link copied": "Enlace de la llamada copiado",
"Another user on this call is having an issue. In order to better diagnose these issues we'd like to collect a debug log.": "Otro usuario en esta llamada está teniendo problemas. Para diagnosticar estos problemas nos gustaría recopilar un registro de depuración.",
- "{{names}}, {{name}}": "{{names}}, {{name}}",
"Audio": "Audio",
"Avatar": "Avatar",
"<0>Create an account0> Or <2>Access as a guest2>": "<0>Crear una cuenta0> o <2>Acceder como invitado2>",
diff --git a/public/locales/et/app.json b/public/locales/et/app.json
index 397d056c..b621d610 100644
--- a/public/locales/et/app.json
+++ b/public/locales/et/app.json
@@ -3,24 +3,17 @@
"<0>Join call now0><1>Or1><2>Copy call link and join later2>": "<0>Liitu kõnega kohe0><1> Või1><2>Kopeeri kõne link ja liitu hiljem2>",
"<0>Create an account0> Or <2>Access as a guest2>": "<0>Loo konto0> Või <2>Sisene külalisena2>",
"<0>Already have an account?0><1><0>Log in0> Or <2>Access as a guest2>1>": "<0>On sul juba konto?0><1><0>Logi sisse0> Või <2>Logi sisse külalisena2>1>",
- "{{names}}, {{name}}": "{{names}}, {{name}}",
- "Invite people": "Kutsu inimesi",
- "Invite": "Kutsu",
"Inspector": "Inspektor",
- "Incompatible versions!": "Ühildumatud versioonid!",
"Incompatible versions": "Ühildumatud versioonid",
"Include debug logs": "Lisa veatuvastuslogid",
"Home": "Avavaatesse",
- "Grid layout menu": "Ruudustikvaate menüü",
"Go": "Jätka",
"Full screen": "Täisekraan",
- "Freedom": "Vaba",
"Fetching group call timed out.": "Grupikõne kättesaamine aegus.",
"Exit full screen": "Välju täisekraanivaatest",
"Download debug logs": "Lae alla veatuvastuslogid",
"Display name": "Kuvatav nimi",
"Developer": "Arendaja",
- "Details": "Täpsemalt",
"Debug log request": "Veaotsingulogi päring",
"Debug log": "Veaotsingulogi",
"Create account": "Loo konto",
@@ -28,7 +21,6 @@
"Copied!": "Kopeeritud!",
"Confirm password": "Kinnita salasõna",
"Close": "Sulge",
- "Change layout": "Muuda paigutust",
"Camera": "Kaamera",
"Call type menu": "Kõnetüübi valik",
"Call link copied": "Kõne link on kopeeritud",
@@ -40,7 +32,6 @@
"Not registered yet? <2>Create an account2>": "Sa pole veel registreerunud? <2>Loo kasutajakonto2>",
"Not now, return to home screen": "Mitte praegu, mine tagasi avalehele",
"No": "Ei",
- "Mute microphone": "Summuta mikrofon",
"Your recent calls": "Hiljutised kõned",
"More": "Rohkem",
"Microphone": "Mikrofon",
@@ -49,15 +40,11 @@
"Logging in…": "Sisselogimine …",
"Local volume": "Kohalik helitugevus",
"Loading…": "Laadimine …",
- "Leave": "Lahku",
"Join existing call?": "Liitu juba käimasoleva kõnega?",
"Join call now": "Liitu kõnega kohe",
"Join call": "Kõnega liitumine",
- "Turn on camera": "Lülita kaamera sisse",
- "Turn off camera": "Lülita kaamera välja",
"Take me Home": "Mine avalehele",
"Submit feedback": "Jaga tagasisidet",
- "Stop sharing screen": "Lõpeta ekraani jagamine",
"Spotlight": "Rambivalgus",
"Speaker": "Kõlar",
"Sign out": "Logi välja",
@@ -84,7 +71,6 @@
"Version: {{version}}": "Versioon: {{version}}",
"Username": "Kasutajanimi",
"This call already exists, would you like to join?": "See kõne on juba olemas, kas soovid liituda?",
- "Unmute microphone": "Aktiveeri mikrofon",
"User menu": "Kasutajamenüü",
"Yes, join call": "Jah, liitu kõnega",
"Walkie-talkie call": "Walkie-talkie stiilis kõne",
@@ -122,6 +108,5 @@
"Reconnect": "Ühenda uuesti",
"Thanks!": "Tänud!",
"End-to-end encryption isn't supported on your browser.": "Sinu brauser ei toeta läbivat krüptimist.",
- "Enable end-to-end encryption (password protected calls)": "Võta kasutusele läbiv krüptimine (salasõnaga kaitstud kõned)",
- "Password (if none, E2EE is disabled)": "Salasõna (tühja väärtuse puhul läbivat krüptimist ei kasutata)"
+ "Enable end-to-end encryption (password protected calls)": "Võta kasutusele läbiv krüptimine (salasõnaga kaitstud kõned)"
}
diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json
index 4d6504d5..14075535 100644
--- a/public/locales/fa/app.json
+++ b/public/locales/fa/app.json
@@ -3,8 +3,6 @@
"Video call": "تماس تصویری",
"Video": "ویدیو",
"Username": "نام کاربری",
- "Turn on camera": "روشن کردن دوربین",
- "Turn off camera": "خاموش کردن دوربین",
"Take me Home": "مرا به خانه ببر",
"Speaker": "بلندگو",
"Sign out": "خروج",
@@ -13,27 +11,21 @@
"Profile": "پروفایل",
"Password": "رمز عبور",
"No": "خیر",
- "Mute microphone": "بیصدا کردن میکروفون",
"More": "بیشتر",
"Microphone": "میکروفون",
"Login to your account": "به حساب کاربری خود وارد شوید",
"Login": "ورود",
"Loading…": "بارگزاری…",
- "Leave": "خروج",
"Join existing call?": "پیوست به تماس؟",
"Join call now": "الان به تماس بپیوند",
"Join call": "پیوستن به تماس",
- "Invite people": "دعوت از افراد",
- "Invite": "دعوت",
"Home": "خانه",
"Go": "رفتن",
"Full screen": "تمام صحفه",
- "Freedom": "آزادی",
"Exit full screen": "خروج از حالت تمام صفحه",
"Download debug logs": "دانلود لاگ عیبیابی",
"Display name": "نام نمایشی",
"Developer": "توسعه دهنده",
- "Details": "جزئیات",
"Debug log request": "درخواست لاگ عیبیابی",
"Debug log": "لاگ عیبیابی",
"Create account": "ساخت حساب کاربری",
@@ -41,20 +33,17 @@
"Copied!": "کپی شد!",
"Confirm password": "تایید رمزعبور",
"Close": "بستن",
- "Change layout": "تغییر طرح",
"Camera": "دوربین",
"Call type menu": "منوی نوع تماس",
"Call link copied": "لینک تماس کپی شد",
"Avatar": "آواتار",
"Audio": "صدا",
"Another user on this call is having an issue. In order to better diagnose these issues we'd like to collect a debug log.": "کاربر دیگری در این تماس مشکلی دارد. برای تشخیص بهتر مشکل، بهتر است ما لاگ عیبیابی را جمعآوری کنیم.",
- "{{names}}, {{name}}": "{{names}}, {{name}}",
"<0>Why not finish by setting up a password to keep your account?0><1>You'll be able to keep your name and set an avatar for use on future calls1>": "<0>چرا یک رمز عبور برای حساب کاربری خود تنظیم نمیکنید؟0><1>شما میتوانید نام خود را حفظ کنید و یک آواتار برای تماسهای آینده بسازید1>",
"<0>Create an account0> Or <2>Access as a guest2>": "<0>ساخت حساب کاربری0> Or <2>دسترسی به عنوان میهمان2>",
"<0>Already have an account?0><1><0>Log in0> Or <2>Access as a guest2>1>": "<0>از قبل حساب کاربری دارید؟0><1><0>ورود0> Or <2>به عنوان یک میهمان وارد شوید2>1>",
"Local volume": "حجم داخلی",
"Inspector": "بازرس",
- "Incompatible versions!": "نسخههای ناسازگار!",
"Incompatible versions": "نسخههای ناسازگار",
"Spotlight": "نور افکن",
"Show call inspector": "نمایش بازرس تماس",
@@ -75,7 +64,6 @@
"Not now, return to home screen": "الان نه، به صفحه اصلی برگردید",
"Logging in…": "ورود…",
"Include debug logs": "شامل لاگهای عیبیابی",
- "Grid layout menu": "منوی طرحبندی شبکهای",
"Fetching group call timed out.": "زمان اتصال به مکالمه گروهی تمام شد.",
"Yes, join call": "بله، به تماس بپیوندید",
"WebRTC is not supported or is being blocked in this browser.": "WebRTC (ارتباطات رسانهای بلادرنگ مانند انتقال صدا، ویدئو و داده) در این مرورگر پشتیبانی نمیشود یا در حال مسدود شدن است.",
@@ -85,10 +73,8 @@
"Video call name": "نامِ تماسِ تصویری",
"Version: {{version}}": "نسخه: {{نسخه}}",
"User menu": "فهرست کاربر",
- "Unmute microphone": "ناخموشی میکروفون",
"This call already exists, would you like to join?": "این تماس از قبل وجود دارد، میخواهید بپیوندید؟",
"Submit feedback": "بازخورد ارائه دهید",
- "Stop sharing screen": "توقف اشتراکگذاری صفحه نمایش",
"Element Call Home": "خانهٔ تماس المنت",
"Copy": "رونوشت",
"<0>Join call now0><1>Or1><2>Copy call link and join later2>": "<0>اکنون به تماس پیوسته0><1>یا1><2>پیوند تماس را رونوشت کرده و بعداً بپیوندید2>"
diff --git a/public/locales/fr/app.json b/public/locales/fr/app.json
index af264134..125367e1 100644
--- a/public/locales/fr/app.json
+++ b/public/locales/fr/app.json
@@ -7,7 +7,6 @@
"Call link copied": "Lien de l’appel copié",
"Call type menu": "Menu de type d’appel",
"Camera": "Caméra",
- "Change layout": "Changer la disposition",
"Close": "Fermer",
"Confirm password": "Confirmer le mot de passe",
"Copied!": "Copié !",
@@ -15,25 +14,19 @@
"Create account": "Créer un compte",
"Debug log": "Journal de débogage",
"Debug log request": "Demande d’un journal de débogage",
- "Details": "Informations",
"Developer": "Développeur",
"Display name": "Nom d’affichage",
"Download debug logs": "Télécharger les journaux de débogage",
"Exit full screen": "Quitter le plein écran",
- "Freedom": "Libre",
"Full screen": "Plein écran",
"Go": "Commencer",
- "Grid layout menu": "Menu en grille",
"Home": "Accueil",
"Include debug logs": "Inclure les journaux de débogage",
"Incompatible versions": "Versions incompatibles",
- "Incompatible versions!": "Versions incompatibles !",
"Inspector": "Inspecteur",
- "Invite people": "Inviter des gens",
"Join call": "Rejoindre l’appel",
"Join call now": "Rejoindre l’appel maintenant",
"Join existing call?": "Rejoindre un appel existant ?",
- "Leave": "Partir",
"Loading…": "Chargement…",
"Local volume": "Volume local",
"Logging in…": "Connexion…",
@@ -41,7 +34,6 @@
"Login to your account": "Connectez vous à votre compte",
"Microphone": "Microphone",
"More": "Plus",
- "Mute microphone": "Couper le micro",
"No": "Non",
"Not now, return to home screen": "Pas maintenant, retourner à l’accueil",
"Not registered yet? <2>Create an account2>": "Pas encore de compte ? <2>En créer un2>",
@@ -64,12 +56,10 @@
"Sign in": "Connexion",
"Sign out": "Déconnexion",
"Spotlight": "Premier plan",
- "Stop sharing screen": "Arrêter le partage d’écran",
"Submit feedback": "Envoyer des retours",
"Take me Home": "Retouner à l’accueil",
"This call already exists, would you like to join?": "Cet appel existe déjà, voulez-vous le rejoindre ?",
"Fetching group call timed out.": "Échec de connexion à l’appel de groupe dans le temps imparti.",
- "{{names}}, {{name}}": "{{names}}, {{name}}",
"Your recent calls": "Appels récents",
"Yes, join call": "Oui, rejoindre l’appel",
"WebRTC is not supported or is being blocked in this browser.": "WebRTC n’est pas pris en charge ou est bloqué par ce navigateur.",
@@ -82,11 +72,7 @@
"Version: {{version}}": "Version : {{version}}",
"Username": "Nom d’utilisateur",
"User menu": "Menu utilisateur",
- "Unmute microphone": "Allumer le micro",
- "Turn on camera": "Allumer la caméra",
- "Turn off camera": "Couper la caméra",
"Speaker": "Intervenant",
- "Invite": "Inviter",
"<0>Already have an account?0><1><0>Log in0> Or <2>Access as a guest2>1>": "<0>Vous avez déjà un compte ?0><1><0>Se connecter0> Ou <2>Accès invité2>1>",
"Sending debug logs…": "Envoi des journaux de débogage…",
"<0>Join call now0><1>Or1><2>Copy call link and join later2>": "<0>Rejoindre l’appel maintenant0><1>Ou1><2>Copier le lien de l’appel et rejoindre plus tard2>",
@@ -122,6 +108,5 @@
"You were disconnected from the call": "Vous avez été déconnecté de l’appel",
"Connectivity to the server has been lost.": "La connexion avec le serveur a été perdue.",
"End-to-end encryption isn't supported on your browser.": "Le chiffrement de bout-en-bout n’est pas pris en charge par votre navigateur.",
- "Password (if none, E2EE is disabled)": "Mot de passe (si aucun, le chiffrement E2EE est désactivé)",
"Enable end-to-end encryption (password protected calls)": "Activer le chiffrement de bout-en-bout (appels protégés par mot de passe)"
}
diff --git a/public/locales/id/app.json b/public/locales/id/app.json
index 51e6ddd2..683284d1 100644
--- a/public/locales/id/app.json
+++ b/public/locales/id/app.json
@@ -8,7 +8,6 @@
"Call link copied": "Tautan panggilan disalin",
"Call type menu": "Menu jenis panggilan",
"Camera": "Kamera",
- "Change layout": "Ubah tata letak",
"Close": "Tutup",
"Confirm password": "Konfirmasi kata sandi",
"Copied!": "Disalin!",
@@ -16,27 +15,20 @@
"Create account": "Buat akun",
"Debug log": "Catatan pengawakutuan",
"Debug log request": "Permintaan catatan pengawakutuan",
- "Details": "Detail",
"Developer": "Pengembang",
"Display name": "Nama tampilan",
"Download debug logs": "Unduh catatan pengawakutuan",
"Exit full screen": "Keluar dari layar penuh",
"Fetching group call timed out.": "Waktu pendapatan panggilan grup habis.",
- "Freedom": "Bebas",
"Full screen": "Layar penuh",
"Go": "Bergabung",
- "Grid layout menu": "Menu tata letak kisi",
"Home": "Beranda",
"Include debug logs": "Termasuk catatan pengawakutuan",
"Incompatible versions": "Versi tidak kompatibel",
- "Incompatible versions!": "Versi tidak kompatibel!",
"Inspector": "Inspektur",
- "Invite": "Undang",
- "Invite people": "Undang orang",
"Join call": "Bergabung ke panggilan",
"Join call now": "Bergabung ke panggilan sekarang",
"Join existing call?": "Bergabung ke panggilan yang sudah ada?",
- "Leave": "Keluar",
"Loading…": "Memuat…",
"Local volume": "Volume lokal",
"Logging in…": "Memasuki…",
@@ -44,7 +36,6 @@
"Login to your account": "Masuk ke akun Anda",
"Microphone": "Mikrofon",
"More": "Lainnya",
- "Mute microphone": "Bisukan mikrofon",
"No": "Tidak",
"Not now, return to home screen": "Tidak sekarang, kembali ke layar beranda",
"Not registered yet? <2>Create an account2>": "Belum terdaftar? <2>Buat sebuah akun2>",
@@ -68,13 +59,9 @@
"Sign out": "Keluar",
"Speaker": "Pembicara",
"Spotlight": "Sorotan",
- "Stop sharing screen": "Berhenti membagikan layar",
"Submit feedback": "Kirim masukan",
"Take me Home": "Bawa saya ke Beranda",
"This call already exists, would you like to join?": "Panggilan ini sudah ada, apakah Anda ingin bergabung?",
- "Turn off camera": "Matikan kamera",
- "Turn on camera": "Nyalakan kamera",
- "Unmute microphone": "Suarakan mikrofon",
"User menu": "Menu pengguna",
"Username": "Nama pengguna",
"Version: {{version}}": "Versi: {{version}}",
@@ -87,7 +74,6 @@
"WebRTC is not supported or is being blocked in this browser.": "WebRTC tidak didukung atau diblokir di peramban ini.",
"Yes, join call": "Ya, bergabung ke panggilan",
"Your recent calls": "Panggilan Anda terkini",
- "{{names}}, {{name}}": "{{names}}, {{name}}",
"Sending debug logs…": "Mengirimkan catatan pengawakutuan…",
"<0>Join call now0><1>Or1><2>Copy call link and join later2>": "<0>Bergabung ke panggilan sekarang0><1>Atau1><2>Salin tautan dan bergabung nanti2>",
"Element Call Home": "Beranda Element Call",
@@ -119,7 +105,6 @@
"Connectivity to the server has been lost.": "Koneksi ke server telah hilang.",
"Enable end-to-end encryption (password protected calls)": "Aktifkan enkripsi ujung ke ujung (panggilan terlindungi oleh kata sandi)",
"End-to-end encryption isn't supported on your browser.": "Enkripsi ujung ke ujung tidak didukung di peramban Anda.",
- "Password (if none, E2EE is disabled)": "Kata sandi (jika tidak ada, enkripsi akan dinonaktifkan)",
"Retry sending logs": "Kirim ulang catatan",
"You were disconnected from the call": "Anda terputus dari panggilan",
"Reconnect": "Hubungkan ulang",
diff --git a/public/locales/it/app.json b/public/locales/it/app.json
new file mode 100644
index 00000000..0967ef42
--- /dev/null
+++ b/public/locales/it/app.json
@@ -0,0 +1 @@
+{}
diff --git a/public/locales/ja/app.json b/public/locales/ja/app.json
index e1d01ea8..f9c3f8a8 100644
--- a/public/locales/ja/app.json
+++ b/public/locales/ja/app.json
@@ -9,7 +9,6 @@
"Audio": "音声",
"Confirm password": "パスワードを確認",
"Close": "閉じる",
- "Change layout": "レイアウトを変更",
"Copied!": "コピーしました!",
"Copy and share this call link": "通話リンクをコピーし共有",
"Copy": "コピー",
@@ -21,33 +20,23 @@
"Download debug logs": "デバッグログをダウンロード",
"Display name": "表示名",
"Developer": "開発者",
- "Details": "詳細",
"Full screen": "全画面表示",
"Exit full screen": "全画面表示を終了",
"Include debug logs": "デバッグログを含める",
"Home": "ホーム",
- "Incompatible versions!": "互換性のないバージョンです!",
"Incompatible versions": "互換性のないバージョン",
"Join existing call?": "既存の通話に参加しますか?",
"Join call now": "今すぐ通話に参加",
"Join call": "通話に参加",
- "Invite": "招待",
- "Invite people": "連絡先を招待",
"Not registered yet? <2>Create an account2>": "アカウントがありませんか? <2>アカウントを作成2>",
- "Mute microphone": "マイクをミュート",
"Microphone": "マイク",
"Login": "ログイン",
"Logging in…": "ログインしています…",
"Loading…": "読み込んでいます…",
- "Leave": "退出",
"Version: {{version}}": "バージョン:{{version}}",
"Username": "ユーザー名",
"User menu": "ユーザーメニュー",
- "Unmute microphone": "マイクのミュートを解除",
- "Turn on camera": "カメラをつける",
- "Turn off camera": "カメラを切る",
"Submit feedback": "フィードバックを送信",
- "Stop sharing screen": "画面共有を停止",
"Spotlight": "スポットライト",
"Send debug logs": "デバッグログを送信",
"Sign out": "サインアウト",
@@ -75,10 +64,8 @@
"Your recent calls": "最近の通話",
"WebRTC is not supported or is being blocked in this browser.": "お使いのブラウザでWebRTCがサポートされていないか、またはブロックされています。",
"Login to your account": "アカウントにログイン",
- "Freedom": "自由",
"Remove": "削除",
"No": "いいえ",
"This call already exists, would you like to join?": "この通話は既に存在します。参加しますか?",
- "Take me Home": "ホームに戻る",
- "{{names}}, {{name}}": "{{names}}、{{name}}"
+ "Take me Home": "ホームに戻る"
}
diff --git a/public/locales/ko/app.json b/public/locales/ko/app.json
index 3d07b1ec..edab2c48 100644
--- a/public/locales/ko/app.json
+++ b/public/locales/ko/app.json
@@ -1,5 +1,4 @@
{
"<0>Already have an account?0><1><0>Log in0> Or <2>Access as a guest2>1>": "",
- "<0>Create an account0> Or <2>Access as a guest2>": "",
- "{{names}}, {{name}}": "{{names}}님, {{name}}님"
+ "<0>Create an account0> Or <2>Access as a guest2>": ""
}
diff --git a/public/locales/lv/app.json b/public/locales/lv/app.json
index 15a355f4..ecc993e8 100644
--- a/public/locales/lv/app.json
+++ b/public/locales/lv/app.json
@@ -1,7 +1,6 @@
{
"{{count}} stars|one": "{{count}} zvaigzne",
"{{count}} stars|other": "{{count}} zvaigznes",
- "{{names}}, {{name}}": "{{names}}, {{name}}",
"<0>Already have an account?0><1><0>Log in0> Or <2>Access as a guest2>1>": "<0>Jau ir konts?0><1><0>Pieteikties0> vai <2>Piekļūt kā viesim2>1>",
"<0>Create an account0> Or <2>Access as a guest2>": "<0>Izveidot kontu0> vai <2>Piekļūt kā viesim2>",
"<0>Join call now0><1>Or1><2>Copy call link and join later2>": "<0>Pievienoties zvanam tagad0><1>vai1><2>ievietot zvana saiti starpliktuvē un pievienoties vēlāk2>",
@@ -15,7 +14,6 @@
"Call link copied": "Zvana saite ievietota starpliktuvē",
"Call type menu": "Zvana veida izvēlne",
"Camera": "Kamera",
- "Change layout": "Mainīt izkārtojumu",
"Close": "Aizvērt",
"Confirm password": "Apstiprināt paroli",
"Connectivity to the server has been lost.": "Ir zaudēts savienojums ar serveri.",
@@ -25,7 +23,6 @@
"Create account": "Izveidot kontu",
"Debug log": "Atkļūdošanas žurnāls",
"Debug log request": "Atkļūdošanas žurnāla pieprasījums",
- "Details": "Izvērsums",
"Developer": "Izstrādātājs",
"Developer Settings": "Izstrādātāja iestatījumi",
"Display name": "Attēlojamais vārds",
@@ -35,10 +32,8 @@
"Expose developer settings in the settings window.": "Izstādīt izstrādātāja iestatījumus iestatījumu logā.",
"Feedback": "Atsauksmes",
"Fetching group call timed out.": "Grupas zvana iegūšanā iestājās noildze.",
- "Freedom": "Brīvība",
"Full screen": "Pilnekrāns",
"Go": "Aiziet",
- "Grid layout menu": "Režģa izkārtojuma izvēlne",
"By clicking \"Join call now\", you agree to our <2>End User Licensing Agreement (EULA)2>": "Klikšķināšana uz \"Pievienoties zvanam tagad\" apliecina piekrišanu mūsu <2>galalietotāja licencēšanas nolīgumam (GLLN)2>",
"By participating in this beta, you consent to the collection of anonymous data, which we use to improve the product. You can find more information about which data we track in our <2>Privacy Policy2> and our <5>Cookie Policy5>.": "Piedalīšanās šajā beta apliecina piekrišanu anonīmu datu ievākšanai, ko mēs izmantojam, lai uzlabotu izstrādājumu. Vairāk informācijas par datiem, ko mēs ievācam, var atrast mūsu <2>privātuma nosacījumos2> un <5>sīkdatņu nosacījumos5>.",
"Element Call is temporarily not end-to-end encrypted while we test scalability.": "Element Call īslaicīgi nav pilnīgi šifrēts, kamēr mēs pārbaudām mērogojamību.",
@@ -58,14 +53,10 @@
"How did it go?": "Kā Tev veicās?",
"Include debug logs": "Iekļaut atkļūdošanas žurnāla ierakstus",
"Incompatible versions": "Nesaderīgas versijas",
- "Incompatible versions!": "Nesaderīgas versijas.",
"Inspector": "Inspektors",
- "Invite": "Uzaicināt",
- "Invite people": "Uzaicināt cilvēkus",
"Join call": "Pievienoties zvanam",
"Join call now": "Pievienoties zvanam tagad",
"Join existing call?": "Pievienoties esošam zvanam?",
- "Leave": "Pamest",
"Loading…": "Lādējas…",
"Local volume": "Vietējais skaļums",
"Logging in…": "Piesakās…",
@@ -73,11 +64,9 @@
"Login to your account": "Pieteikties kontā",
"Microphone": "Mikrofons",
"More": "Vairāk",
- "Mute microphone": "Apklusināt mikrofonu",
"No": "Nē",
"Not now, return to home screen": "Ne tagad, atgriezties sākuma ekrānā",
"Password": "Parole",
- "Password (if none, E2EE is disabled)": "Parole (ja nav, pilnīga šifrēšana ir atspējota)",
"Passwords must match": "Parolēm ir jāsakrīt",
"Profile": "Profils",
"Recaptcha dismissed": "ReCaptcha atmesta",
@@ -100,7 +89,6 @@
"Sign out": "Atteikties",
"Speaker": "Runātājs",
"Spotlight": "Starmešu gaisma",
- "Stop sharing screen": "Pārtraukt ekrāna kopīgošanu",
"Submit": "Iesniegt",
"Submit feedback": "Iesniegt atsauksmi",
"Submitting…": "Iesniedz…",
@@ -109,9 +97,6 @@
"Thanks!": "Paldies!",
"This call already exists, would you like to join?": "Šis zvans jau pastāv. Vai vēlies pievienoties?",
"This site is protected by ReCAPTCHA and the Google <2>Privacy Policy2> and <6>Terms of Service6> apply.<9>9>By clicking \"Register\", you agree to our <12>End User Licensing Agreement (EULA)12>": "Šo vietni aizsargā ReCAPTCHA, un ir attiecināmi Google <2>privātuma nosacījumi2> un <6>pakalpojuma noteikumi6>.<9>9>Klikšķināšana uz \"Reģistrēties\" sniedz piekrišanu mūsu <12>galalietotāja licencēšanas nolīgumam (GLLN)12>",
- "Turn off camera": "Izslēgt kameru",
- "Turn on camera": "Ieslēgt kameru",
- "Unmute microphone": "Atsaukt mikrofona apklusināšanu",
"User menu": "Lietotāja izvēlne",
"Username": "Lietotājvārds",
"Video": "Video",
diff --git a/public/locales/pl/app.json b/public/locales/pl/app.json
index 6f8bf3f7..157887d6 100644
--- a/public/locales/pl/app.json
+++ b/public/locales/pl/app.json
@@ -13,13 +13,9 @@
"Version: {{version}}": "Wersja: {{version}}",
"Username": "Nazwa użytkownika",
"User menu": "Menu użytkownika",
- "Unmute microphone": "Wyłącz wyciszenie mikrofonu",
- "Turn on camera": "Włącz kamerę",
- "Turn off camera": "Wyłącz kamerę",
"This call already exists, would you like to join?": "Te połączenie już istnieje, czy chcesz do niego dołączyć?",
"Take me Home": "Zabierz mnie do strony głównej",
"Submit feedback": "Prześlij opinię",
- "Stop sharing screen": "Zatrzymaj udostępnianie ekranu",
"Spotlight": "Centrum uwagi",
"Speaker": "Głośnik",
"Sign out": "Wyloguj się",
@@ -44,33 +40,25 @@
"Not registered yet? <2>Create an account2>": "Nie masz konta? <2>Utwórz je2>",
"Not now, return to home screen": "Nie teraz, powróć do ekranu domowego",
"No": "Nie",
- "Mute microphone": "Wycisz mikrofon",
"More": "Więcej",
"Microphone": "Mikrofon",
"Login to your account": "Zaloguj się do swojego konta",
"Logging in…": "Logowanie…",
"Local volume": "Głośność lokalna",
"Loading…": "Ładowanie…",
- "Leave": "Opuść",
"Join existing call?": "Dołączyć do istniejącego połączenia?",
"Join call now": "Dołącz do połączenia teraz",
"Join call": "Dołącz do połączenia",
- "Invite people": "Zaproś ludzi",
- "Invite": "Zaproś",
"Inspector": "Inspektor",
- "Incompatible versions!": "Niekompatybilne wersje!",
"Incompatible versions": "Niekompatybilne wersje",
"Include debug logs": "Dołącz dzienniki debugowania",
"Home": "Strona domowa",
- "Grid layout menu": "Menu układu siatki",
"Full screen": "Pełny ekran",
- "Freedom": "Wolność",
"Fetching group call timed out.": "Przekroczono limit czasu na uzyskanie połączenia grupowego.",
"Exit full screen": "Opuść pełny ekran",
"Download debug logs": "Pobierz dzienniki debugowania",
"Display name": "Nazwa wyświetlana",
"Developer": "Programista",
- "Details": "Szczegóły",
"Debug log request": "Prośba o dzienniki debugowania",
"Debug log": "Dzienniki debugowania",
"Create account": "Utwórz konto",
@@ -78,7 +66,6 @@
"Copied!": "Skopiowano!",
"Confirm password": "Potwierdź hasło",
"Close": "Zamknij",
- "Change layout": "Zmień układ",
"Camera": "Kamera",
"Call type menu": "Menu typu połączenia",
"Call link copied": "Skopiowano link do połączenia",
@@ -88,7 +75,6 @@
"<0>Why not finish by setting up a password to keep your account?0><1>You'll be able to keep your name and set an avatar for use on future calls1>": "<0>Może zechcesz ustawić hasło, aby zachować swoje konto?0><1>Będziesz w stanie utrzymać swoją nazwę i ustawić awatar do wyświetlania podczas połączeń w przyszłości1>",
"<0>Create an account0> Or <2>Access as a guest2>": "<0>Utwórz konto0> lub <2>Dołącz jako gość2>",
"<0>Already have an account?0><1><0>Log in0> Or <2>Access as a guest2>1>": "<0>Masz już konto?0><1><0>Zaloguj się0> lub <2>Dołącz jako gość2>1>",
- "{{names}}, {{name}}": "{{names}}, {{name}}",
"Copy": "Kopiuj",
"<0>Submitting debug logs will help us track down the problem.0>": "<0>Wysłanie dzienników debuggowania pomoże nam ustalić przyczynę problemu.0>",
"<0>Oops, something's gone wrong.0>": "<0>Ojej, coś poszło nie tak.0>",
@@ -117,7 +103,6 @@
"This site is protected by ReCAPTCHA and the Google <2>Privacy Policy2> and <6>Terms of Service6> apply.<9>9>By clicking \"Register\", you agree to our <12>End User Licensing Agreement (EULA)12>": "Ta witryna jest chroniona przez ReCAPTCHA, więc obowiązują <2>Polityka prywatności2> i <6>Warunki usług6> Google. Klikając \"Zarejestruj\", zgadzasz się na naszą <12>Umowę licencyjną (EULA)12>",
"By clicking \"Join call now\", you agree to our <2>End User Licensing Agreement (EULA)2>": "Klikając \"Dołącz teraz do rozmowy\", zgadzasz się na naszą <2>Umowę licencyjną (EULA)2>",
"End-to-end encryption isn't supported on your browser.": "Szyfrowanie end-to-end nie jest wspierane przez Twoją przeglądarkę.",
- "Password (if none, E2EE is disabled)": "Hasło (brak oznacza, że E2EE jest włączone)",
"Retry sending logs": "Wyślij logi ponownie",
"Thanks!": "Dziękujemy!",
"You were disconnected from the call": "Rozłączono Cię z połączenia",
diff --git a/public/locales/ru/app.json b/public/locales/ru/app.json
index ed9d8df4..9f2be372 100644
--- a/public/locales/ru/app.json
+++ b/public/locales/ru/app.json
@@ -2,14 +2,12 @@
"Register": "Зарегистрироваться",
"Registering…": "Регистрация…",
"Logging in…": "Вход…",
- "{{names}}, {{name}}": "{{names}}, {{name}}",
"Waiting for other participants…": "Ожидание других участников…",
"This call already exists, would you like to join?": "Этот звонок уже существует, хотите присоединиться?",
"Submit feedback": "Отправить отзыв",
"Sending debug logs…": "Отправка журнала отладки…",
"Select an option": "Выберите вариант",
"Other users are trying to join this call from incompatible versions. These users should ensure that they have refreshed their browsers:<1>{userLis}1>": "Другие пользователи пытаются присоединиться с неподдерживаемых версий программы. Этим участникам надо перезагрузить браузер: <1>{userLis}1>",
- "Grid layout menu": "Меню \"Расположение сеткой\"",
"<0>Why not finish by setting up a password to keep your account?0><1>You'll be able to keep your name and set an avatar for use on future calls1>": "<0>Почему бы не задать пароль, тем самым сохранив аккаунт?0><1>Так вы можете оставить своё имя и задать аватар для будущих звонков.1>",
"<0>Create an account0> Or <2>Access as a guest2>": "<0>Создать аккаунт0> или <2>Зайти как гость2>",
"<0>Already have an account?0><1><0>Log in0> Or <2>Access as a guest2>1>": "<0>Уже есть аккаунт?0><1><0>Войти с ним0> или <2>Зайти как гость2>1>",
@@ -24,11 +22,7 @@
"Version: {{version}}": "Версия: {{version}}",
"Username": "Имя пользователя",
"User menu": "Меню пользователя",
- "Unmute microphone": "Включить микрофон",
- "Turn on camera": "Включить камеру",
- "Turn off camera": "Отключить камеру",
"Take me Home": "Перейти в Начало",
- "Stop sharing screen": "Остановить показ экрана",
"Spotlight": "Внимание",
"Speaker": "Динамик",
"Sign out": "Выйти",
@@ -55,36 +49,28 @@
"Not registered yet? <2>Create an account2>": "Ещё не зарегистрированы? <2>Создайте аккаунт2>",
"Not now, return to home screen": "Не сейчас, вернуться в Начало",
"No": "Нет",
- "Mute microphone": "Отключить микрофон",
"More": "Больше",
"Microphone": "Микрофон",
"Login to your account": "Войдите в свой аккаунт",
"Login": "Вход",
"Loading…": "Загрузка…",
- "Leave": "Покинуть",
"Join existing call?": "Присоединиться к существующему звонку?",
"Join call now": "Присоединиться сейчас",
"Join call": "Присоединиться",
- "Invite people": "Пригласить участников",
- "Invite": "Пригласить",
"Inspector": "Инспектор",
- "Incompatible versions!": "Несовместимые версии!",
"Incompatible versions": "Несовместимые версии",
"Home": "Начало",
"Go": "Далее",
"Full screen": "Полноэкранный режим",
- "Freedom": "Свобода",
"Fetching group call timed out.": "Истекло время ожидания для группового звонка.",
"Exit full screen": "Выйти из полноэкранного режима",
"Display name": "Видимое имя",
"Developer": "Разработчику",
- "Details": "Подробности",
"Create account": "Создать аккаунт",
"Copy and share this call link": "Скопируйте и поделитесь этой ссылкой на звонок",
"Copied!": "Скопировано!",
"Confirm password": "Подтвердите пароль",
"Close": "Закрыть",
- "Change layout": "Изменить расположение",
"Camera": "Камера",
"Call link copied": "Ссылка на звонок скопирована",
"Avatar": "Аватар",
diff --git a/public/locales/sk/app.json b/public/locales/sk/app.json
index 0adfd378..8ac28b0b 100644
--- a/public/locales/sk/app.json
+++ b/public/locales/sk/app.json
@@ -7,7 +7,6 @@
"Waiting for other participants…": "Čaká sa na ďalších účastníkov…",
"Take me Home": "Zober ma domov",
"Submit feedback": "Odoslať spätnú väzbu",
- "Stop sharing screen": "Zastaviť zdieľanie obrazovky",
"Show call inspector": "Zobraziť inšpektora hovorov",
"Share screen": "Zdieľať obrazovku",
"Sending…": "Odosielanie…",
@@ -27,27 +26,20 @@
"Not registered yet? <2>Create an account2>": "Ešte nie ste zaregistrovaný? <2>Vytvorte si účet2>",
"Not now, return to home screen": "Teraz nie, vrátiť sa na domovskú obrazovku",
"No": "Nie",
- "Mute microphone": "Stlmiť mikrofón",
"More": "Viac",
"Microphone": "Mikrofón",
"Login to your account": "Prihláste sa do svojho konta",
"Login": "Prihlásiť sa",
"Logging in…": "Prihlasovanie…",
"Loading…": "Načítanie…",
- "Leave": "Opustiť",
"Join existing call?": "Pripojiť sa k existujúcemu hovoru?",
"Join call now": "Pripojiť sa k hovoru teraz",
"Join call": "Pripojiť sa k hovoru",
- "Invite people": "Pozvať ľudí",
- "Invite": "Pozvať",
"Inspector": "Inšpektor",
- "Incompatible versions!": "Nekompatibilné verzie!",
"Incompatible versions": "Nekompatibilné verzie",
"Home": "Domov",
- "Grid layout menu": "Ponuka rozloženia mriežky",
"Go": "Prejsť",
"Full screen": "Zobrazenie na celú obrazovku",
- "Freedom": "Sloboda",
"Exit full screen": "Ukončiť zobrazenie na celú obrazovku",
"Download debug logs": "Stiahnuť záznamy ladenia",
"Your recent calls": "Vaše nedávne hovory",
@@ -61,9 +53,6 @@
"Version: {{version}}": "Verzia: {{version}}",
"Username": "Meno používateľa",
"User menu": "Používateľské menu",
- "Unmute microphone": "Zrušiť stlmenie mikrofónu",
- "Turn on camera": "Zapnúť kameru",
- "Turn off camera": "Vypnúť kameru",
"This call already exists, would you like to join?": "Tento hovor už existuje, chceli by ste sa k nemu pripojiť?",
"Speaker": "Reproduktor",
"Sign out": "Odhlásiť sa",
@@ -71,7 +60,6 @@
"Settings": "Nastavenia",
"Display name": "Zobrazované meno",
"Developer": "Vývojár",
- "Details": "Podrobnosti",
"Debug log request": "Žiadosť o záznam ladenia",
"Debug log": "Záznam o ladení",
"Create account": "Vytvoriť účet",
@@ -80,7 +68,6 @@
"Copied!": "Skopírované!",
"Confirm password": "Potvrdiť heslo",
"Close": "Zatvoriť",
- "Change layout": "Zmeniť rozloženie",
"Camera": "Kamera",
"Call type menu": "Ponuka typu hovoru",
"Call link copied": "Odkaz na hovor skopírovaný",
@@ -91,7 +78,6 @@
"<0>Join call now0><1>Or1><2>Copy call link and join later2>": "<0>Pripojiť sa k hovoru teraz0><1>alebo1><2>Kopírovať odkaz na hovor a pripojiť sa neskôr2>",
"<0>Create an account0> Or <2>Access as a guest2>": "<0>Vytvoriť konto0> Alebo <2>Prihlásiť sa ako hosť2>",
"<0>Already have an account?0><1><0>Log in0> Or <2>Access as a guest2>1>": "<0>Už máte konto?0><1><0>Prihláste sa0> Alebo <2>Prihlásiť sa ako hosť2>1>",
- "{{names}}, {{name}}": "{{names}}, {{name}}",
"<0>Submitting debug logs will help us track down the problem.0>": "<0>Odoslanie záznamov ladenia nám pomôže nájsť problém.0>",
"<0>Oops, something's gone wrong.0>": "<0>Hups, niečo sa pokazilo.0>",
"Expose developer settings in the settings window.": "Zobraziť nastavenia pre vývojárov v okne nastavení.",
@@ -122,6 +108,5 @@
"Thanks!": "Ďakujeme!",
"You were disconnected from the call": "Boli ste odpojení z hovoru",
"Enable end-to-end encryption (password protected calls)": "Povoliť end-to-end šifrovanie (hovory chránené heslom)",
- "End-to-end encryption isn't supported on your browser.": "End-to-end šifrovanie nie je vo vašom prehliadači podporované.",
- "Password (if none, E2EE is disabled)": "Heslo (ak nie je, šifrovanie je vypnuté)"
+ "End-to-end encryption isn't supported on your browser.": "End-to-end šifrovanie nie je vo vašom prehliadači podporované."
}
diff --git a/public/locales/sv/app.json b/public/locales/sv/app.json
new file mode 100644
index 00000000..0967ef42
--- /dev/null
+++ b/public/locales/sv/app.json
@@ -0,0 +1 @@
+{}
diff --git a/public/locales/tr/app.json b/public/locales/tr/app.json
index 1757114b..1b84c80c 100644
--- a/public/locales/tr/app.json
+++ b/public/locales/tr/app.json
@@ -6,7 +6,6 @@
"Call link copied": "Arama bağlantısı kopyalandı",
"Call type menu": "Arama tipi menüsü",
"Camera": "Kamera",
- "Change layout": "Yerleşimi değiştir",
"Close": "Kapat",
"Confirm password": "Parolayı tekrar edin",
"Copied!": "Kopyalandı",
@@ -14,26 +13,20 @@
"Create account": "Hesap aç",
"Debug log": "Hata ayıklama kütüğü",
"Debug log request": "Hata ayıklama kütük istemi",
- "Details": "Ayrıntı",
"Developer": "Geliştirici",
"Display name": "Ekran adı",
"Download debug logs": "Hata ayıklama kütüğünü indir",
"Exit full screen": "Tam ekranı terk et",
"Fetching group call timed out.": "Grup çağrısı zaman aşımına uğradı.",
- "Freedom": "Özgürlük",
"Full screen": "Tam ekran",
"Go": "Git",
- "Grid layout menu": "Izgara plan menü",
"Home": "Ev",
"Include debug logs": "Hata ayıklama kütüğünü dahil et",
"Incompatible versions": "Uyumsuz sürümler",
- "Incompatible versions!": "Sürüm uyumsuz!",
"Inspector": "Denetçi",
- "Invite people": "Kişileri davet et",
"Join call": "Aramaya katıl",
"Join call now": "Aramaya katıl",
"Join existing call?": "Mevcut aramaya katıl?",
- "Leave": "Çık",
"Loading…": "Yükleniyor…",
"Local volume": "Yerel ses seviyesi",
"Logging in…": "Giriliyor…",
@@ -41,7 +34,6 @@
"Login to your account": "Hesabınıza girin",
"Microphone": "Mikrofon",
"More": "Daha",
- "Mute microphone": "Mikrofonu kapat",
"No": "Hayır",
"Not now, return to home screen": "Şimdi değil, ev ekranına dön",
"Not registered yet? <2>Create an account2>": "Kaydolmadınız mı? <2>Hesap açın2>",
@@ -62,11 +54,9 @@
"Show call inspector": "Arama denetçisini göster",
"Sign in": "Gir",
"Sign out": "Çık",
- "Stop sharing screen": "Ekran paylaşmayı terk et",
"Submit feedback": "Geri bildirim ver",
"Take me Home": "Ev ekranına gir",
"This call already exists, would you like to join?": "Bu arama zaten var, katılmak ister misiniz?",
- "{{names}}, {{name}}": "{{names}}, {{name}}",
"<0>Create an account0> Or <2>Access as a guest2>": "<0>Hesap oluştur0> yahut <2>Konuk olarak gir2>",
"<0>Already have an account?0><1><0>Log in0> Or <2>Access as a guest2>1>": "<0>Mevcut hesabınız mı var?0><1><0>Gir0> yahut <2>Konuk girişi2>1>"
}
diff --git a/public/locales/uk/app.json b/public/locales/uk/app.json
index c67d6f1a..f43b27ad 100644
--- a/public/locales/uk/app.json
+++ b/public/locales/uk/app.json
@@ -12,13 +12,9 @@
"Version: {{version}}": "Версія: {{version}}",
"Username": "Ім'я користувача",
"User menu": "Меню користувача",
- "Unmute microphone": "Увімкнути мікрофон",
- "Turn on camera": "Увімкнути камеру",
- "Turn off camera": "Вимкнути камеру",
"This call already exists, would you like to join?": "Цей виклик уже існує, бажаєте приєднатися?",
"Take me Home": "Перейти до Домівки",
"Submit feedback": "Надіслати відгук",
- "Stop sharing screen": "Припинити показ екрана",
"Spotlight": "У центрі уваги",
"Speaker": "Динамік",
"Sign out": "Вийти",
@@ -43,34 +39,26 @@
"Not registered yet? <2>Create an account2>": "Ще не зареєстровані? <2>Створіть обліковий запис2>",
"Not now, return to home screen": "Не зараз, повернутися на екран домівки",
"No": "Ні",
- "Mute microphone": "Заглушити мікрофон",
"More": "Докладніше",
"Microphone": "Мікрофон",
"Login to your account": "Увійдіть до свого облікового запису",
"Login": "Увійти",
"Logging in…": "Вхід…",
"Local volume": "Локальна гучність",
- "Leave": "Вийти",
"Join existing call?": "Приєднатися до наявного виклику?",
"Join call now": "Приєднатися до виклику зараз",
"Join call": "Приєднатися до виклику",
- "Invite people": "Запросити людей",
- "Invite": "Запросити",
"Inspector": "Інспектор",
- "Incompatible versions!": "Несумісні версії!",
"Incompatible versions": "Несумісні версії",
"Include debug logs": "Долучити журнали налагодження",
"Home": "Домівка",
- "Grid layout menu": "Меню у вигляді сітки",
"Go": "Далі",
"Full screen": "Повноекранний режим",
- "Freedom": "Свобода",
"Fetching group call timed out.": "Вичерпано час очікування групового виклику.",
"Exit full screen": "Вийти з повноекранного режиму",
"Download debug logs": "Завантажити журнали налагодження",
"Display name": "Псевдонім",
"Developer": "Розробнику",
- "Details": "Подробиці",
"Debug log request": "Запит журналу налагодження",
"Debug log": "Журнал налагодження",
"Create account": "Створити обліковий запис",
@@ -78,7 +66,6 @@
"Copied!": "Скопійовано!",
"Confirm password": "Підтвердити пароль",
"Close": "Закрити",
- "Change layout": "Змінити макет",
"Camera": "Камера",
"Call type menu": "Меню типу виклику",
"Call link copied": "Посилання на виклик скопійовано",
@@ -88,7 +75,6 @@
"<0>Why not finish by setting up a password to keep your account?0><1>You'll be able to keep your name and set an avatar for use on future calls1>": "<0>Чому б не завершити, налаштувавши пароль для збереження свого облікового запису?0><1>Ви зможете зберегти своє ім'я та встановити аватарку для подальшого користування під час майбутніх викликів1>",
"<0>Create an account0> Or <2>Access as a guest2>": "<0>Створити обліковий запис0> або <2>Отримати доступ як гість2>",
"<0>Already have an account?0><1><0>Log in0> Or <2>Access as a guest2>1>": "<0>Уже маєте обліковий запис?0><1><0>Увійти0> Or <2>Отримати доступ як гість2>1>",
- "{{names}}, {{name}}": "{{names}}, {{name}}",
"<0>Join call now0><1>Or1><2>Copy call link and join later2>": "<0>Приєднатися до виклику зараз0><1>Or1><2>Скопіювати посилання на виклик і приєднатися пізніше2>",
"Element Call Home": "Домівка Element Call",
"Copy": "Копіювати",
@@ -123,5 +109,18 @@
"Thanks!": "Дякуємо!",
"Enable end-to-end encryption (password protected calls)": "Увімкнути наскрізне шифрування (захищені паролем виклики)",
"End-to-end encryption isn't supported on your browser.": "Наскрізне шифрування не підтримується вашим переглядачем.",
- "Password (if none, E2EE is disabled)": "Пароль (якщо немає, наскрізне шифрування вимкнено)"
+ "{{count, number}}|other": "{{count, number}}",
+ "{{names, list(style: short;)}}": "{{names, list(style: short;)}}",
+ "Encrypted": "Зашифровано",
+ "Microphone on": "Мікрофон увімкнено",
+ "Not encrypted": "Не зашифровано",
+ "Share": "Поділитися",
+ "Sharing screen": "Презентація екрана",
+ "Video off": "Відео вимкнено",
+ "Video on": "Відео ввімкнено",
+ "{{count, number}}|one": "{{count, number}}",
+ "End call": "Завершити виклик",
+ "Grid": "Сітка",
+ "Microphone off": "Мікрофон вимкнено",
+ "Share this call": "Поділитися цим викликом"
}
diff --git a/public/locales/vi/app.json b/public/locales/vi/app.json
index 6757c05e..7dab73fc 100644
--- a/public/locales/vi/app.json
+++ b/public/locales/vi/app.json
@@ -1,7 +1,6 @@
{
"Login": "Đăng nhập",
"Join call": "Tham gia cuộc gọi",
- "Mute microphone": "Tắt micrô",
"Password": "Mật khẩu",
"Settings": "Cài đặt",
"Sending…": "Đang gửi…",
@@ -17,18 +16,13 @@
"WebRTC is not supported or is being blocked in this browser.": "WebRTC không được hỗ trợ hay bị chặn trong trình duyệt này.",
"Waiting for other participants…": "Đang đợi những người khác…",
"Version: {{version}}": "Phiên bản: {{version}}",
- "Turn on camera": "Bật máy quay",
- "Turn off camera": "Tắt máy quay",
"Submit feedback": "Gửi phản hồi",
- "Stop sharing screen": "Ngừng chia sẻ màn hình",
"Speaker": "Loa",
"Sign out": "Đăng xuất",
"Share screen": "Chia sẻ màn hình",
"No": "Không",
- "Invite people": "Mời mọi người",
"Join call now": "Tham gia cuộc gọi",
"Create account": "Tạo tài khoản",
- "{{names}}, {{name}}": "{{names}}, {{name}}",
"<0>Create an account0> Or <2>Access as a guest2>": "<0>Tạo tài khoản0> Hay <2>Tham gia dưới tên khác2>",
"<0>Join call now0><1>Or1><2>Copy call link and join later2>": "<0>Tham gia cuộc gọi0><1>hay1><2>Sao chép liên kết cuộc gọi và tham gia sau2>",
"<0>Submitting debug logs will help us track down the problem.0>": "<0>Gửi nhật ký gỡ lỗi sẽ giúp chúng tôi theo dõi vấn đề.0>",
@@ -39,23 +33,18 @@
"Copied!": "Đã sao chép!",
"Confirm password": "Xác nhận mật khẩu",
"Close": "Đóng",
- "Change layout": "Thay đổi bố cục",
"Debug log": "Nhật ký gỡ lỗi",
"Copy": "Sao chép",
"Copy and share this call link": "Sao chép và chia sẻ liên kết cuộc gọi này",
"Display name": "Tên hiển thị",
"Developer Settings": "Cài đặt phát triển",
"Developer": "Nhà phát triển",
- "Details": "Chi tiết",
"Download debug logs": "Tải xuống nhật ký gỡ lỗi",
"Feedback": "Phản hồi",
"Full screen": "Toàn màn hình",
- "Incompatible versions!": "Phiên bản không tương thích!",
"Incompatible versions": "Phiên bản không tương thích",
"Include debug logs": "Kèm theo nhật ký gỡ lỗi",
- "Invite": "Mời",
"Join existing call?": "Tham gia cuộc gọi?",
- "Leave": "Rời",
"Loading…": "Đang tải…",
"Logging in…": "Đang đăng nhập…",
"Login to your account": "Đăng nhập vào tài khoản của bạn",
@@ -72,7 +61,6 @@
"Exit full screen": "Rời chế độ toàn màn hình",
"Profile": "Hồ sơ",
"Registering…": "Đang đăng ký…",
- "Unmute microphone": "Bật micrô",
"This call already exists, would you like to join?": "Cuộc gọi đã tồn tại, bạn có muốn tham gia không?",
"Recaptcha not loaded": "Chưa tải được Recaptcha",
"Debug log request": "Yêu cầu nhật ký gỡ lỗi",
diff --git a/public/locales/zh-Hans/app.json b/public/locales/zh-Hans/app.json
index 3c78b5dc..58f3dbc5 100644
--- a/public/locales/zh-Hans/app.json
+++ b/public/locales/zh-Hans/app.json
@@ -11,13 +11,9 @@
"Version: {{version}}": "版本:{{version}}",
"Username": "用户名",
"User menu": "用户菜单",
- "Unmute microphone": "取消麦克风静音",
- "Turn on camera": "开启摄像头",
- "Turn off camera": "关闭摄像头",
"This call already exists, would you like to join?": "该通话已存在,你想加入吗?",
"Take me Home": "返回主页",
"Submit feedback": "提交反馈",
- "Stop sharing screen": "停止屏幕共享",
"Spotlight": "聚焦模式",
"Speaker": "发言人",
"Sign out": "注销登录",
@@ -28,7 +24,6 @@
"<0>Join call now0><1>Or1><2>Copy call link and join later2>": "<0>现在加入通话0><1>或1><2>复制通话链接并稍后加入2>",
"<0>Create an account0> Or <2>Access as a guest2>": "<0>创建账户0> Or <2>以访客身份继续2>",
"<0>Already have an account?0><1><0>Log in0> Or <2>Access as a guest2>1>": "<0>已有账户?0><1><0>登录0> Or <2>以访客身份继续2>1>",
- "{{names}}, {{name}}": "{{names}}, {{name}}",
"Inspector": "检查器",
"Show call inspector": "显示通话检查器",
"Share screen": "屏幕共享",
@@ -50,7 +45,6 @@
"Not registered yet? <2>Create an account2>": "还没有注册? <2>创建账户<2>",
"Not now, return to home screen": "暂不,先返回主页",
"No": "否",
- "Mute microphone": "麦克风静音",
"More": "更多",
"Microphone": "麦克风",
"Login to your account": "登录你的账户",
@@ -58,27 +52,20 @@
"Logging in…": "登录中……",
"Local volume": "本地音量",
"Loading…": "加载中……",
- "Leave": "离开",
"Join existing call?": "加入现有的通话?",
"Join call now": "现在加入通话",
"Join call": "加入通话",
- "Invite people": "邀请他人",
- "Invite": "邀请",
- "Incompatible versions!": "版本不兼容!",
"Incompatible versions": "不兼容版本",
"Include debug logs": "包含调试日志",
"Home": "主页",
- "Grid layout menu": "网格布局菜单",
"Go": "开始",
"Full screen": "全屏",
- "Freedom": "自由模式",
"Fetching group call timed out.": "获取群组通话超时。",
"Exit full screen": "退出全屏",
"Element Call Home": "Element Call 主页",
"Download debug logs": "下载调试日志",
"Display name": "显示名称",
"Developer": "开发者",
- "Details": "详情",
"Debug log request": "调试日志请求",
"Debug log": "调试日志",
"Create account": "创建账户",
@@ -87,7 +74,6 @@
"Copied!": "已复制!",
"Confirm password": "确认密码",
"Close": "关闭",
- "Change layout": "更改布局",
"Camera": "摄像头",
"Call type menu": "通话类型菜单",
"Call link copied": "链接已复制",
diff --git a/public/locales/zh-Hant/app.json b/public/locales/zh-Hant/app.json
index 48b5ab43..6267fe86 100644
--- a/public/locales/zh-Hant/app.json
+++ b/public/locales/zh-Hant/app.json
@@ -2,7 +2,6 @@
"<0>Join call now0><1>Or1><2>Copy call link and join later2>": "<0>現在加入通話0><1>或1><2>複製通話連結,稍後再加入2>",
"<0>Create an account0> Or <2>Access as a guest2>": "<0>建立帳號0> 或<2>以訪客身份登入2>",
"<0>Already have an account?0><1><0>Log in0> Or <2>Access as a guest2>1>": "<0>已經有帳號?0><1><0>登入0> 或<2>以訪客身份登入2>1>",
- "{{names}}, {{name}}": "{{names}}, {{name}}",
"Expose developer settings in the settings window.": "在設定視窗中顯示開發者設定。",
"Developer Settings": "開發者設定",
"<0>Submitting debug logs will help us track down the problem.0>": "<0>送出除錯紀錄,可幫助我們修正問題。0>",
@@ -19,13 +18,9 @@
"Version: {{version}}": "版本: {{version}}",
"Username": "使用者名稱",
"User menu": "使用者選單",
- "Unmute microphone": "取消麥克風靜音",
- "Turn on camera": "開啟相機",
- "Turn off camera": "關閉相機",
"This call already exists, would you like to join?": "通話已經開始,請問您要加入嗎?",
"Take me Home": "帶我回主畫面",
"Submit feedback": "遞交回覆",
- "Stop sharing screen": "停止分享螢幕畫面",
"Spotlight": "聚焦",
"Speaker": "發言者",
"Sign out": "登出",
@@ -50,7 +45,6 @@
"Not registered yet? <2>Create an account2>": "還沒註冊嗎?<2>建立帳號2>",
"Not now, return to home screen": "現在不行,回到首頁",
"No": "否",
- "Mute microphone": "麥克風靜音",
"More": "更多",
"Microphone": "麥克風",
"Login to your account": "登入您的帳號",
@@ -58,28 +52,21 @@
"Logging in…": "登入中…",
"Local volume": "您的音量",
"Loading…": "載入中…",
- "Leave": "離開",
"Join existing call?": "加入已開始的通話嗎?",
"Join call now": "現在加入通話",
"Join call": "加入通話",
- "Invite people": "邀請夥伴",
- "Invite": "邀請",
"Inspector": "稽查員",
- "Incompatible versions!": "不相容版本!",
"Incompatible versions": "不相容版本",
"Include debug logs": "包含除錯紀錄",
"Home": "首頁",
- "Grid layout menu": "格框式清單",
"Go": "前往",
"Full screen": "全螢幕",
- "Freedom": "自由",
"Fetching group call timed out.": "加入群組對話已逾時。",
"Exit full screen": "退出全螢幕",
"Element Call Home": "Element Call 首頁",
"Download debug logs": "下載偵錯報告",
"Display name": "顯示名稱",
"Developer": "開發者",
- "Details": "詳細說明",
"Debug log request": "請求偵錯報告",
"Debug log": "除錯紀錄",
"Create account": "建立帳號",
@@ -88,7 +75,6 @@
"Copied!": "已複製!",
"Confirm password": "確認密碼",
"Close": "關閉",
- "Change layout": "變更排列",
"Camera": "相機",
"Call type menu": "通話類型選單",
"Call link copied": "已複製通話連結",
@@ -122,6 +108,5 @@
"Thanks!": "感謝!",
"You were disconnected from the call": "您已從通話斷線",
"Enable end-to-end encryption (password protected calls)": "啟用端到端加密(密碼保護通話)",
- "End-to-end encryption isn't supported on your browser.": "您的瀏覽器不支援端到端加密。",
- "Password (if none, E2EE is disabled)": "密碼(若無,就會停用端到端加密)"
+ "End-to-end encryption isn't supported on your browser.": "您的瀏覽器不支援端到端加密。"
}
diff --git a/src/App.tsx b/src/App.tsx
index 8e9c4bf1..1931a8c7 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -25,7 +25,6 @@ import { LoginPage } from "./auth/LoginPage";
import { RegisterPage } from "./auth/RegisterPage";
import { RoomPage } from "./room/RoomPage";
import { ClientProvider } from "./ClientContext";
-import { usePageFocusStyle } from "./usePageFocusStyle";
import { SequenceDiagramViewerPage } from "./SequenceDiagramViewerPage";
import { InspectorContextProvider } from "./room/GroupCallInspector";
import { CrashView, LoadingView } from "./FullScreenView";
@@ -48,8 +47,6 @@ export default function App({ history }: AppProps) {
});
});
- usePageFocusStyle();
-
const errorPage = ;
return (
diff --git a/src/Avatar.module.css b/src/Avatar.module.css
deleted file mode 100644
index accff6ae..00000000
--- a/src/Avatar.module.css
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
-Copyright 2022 New Vector Ltd
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-.avatar {
- position: relative;
- color: var(--stopgap-color-on-solid-accent);
- display: flex;
- align-items: center;
- justify-content: center;
- pointer-events: none;
- font-weight: 600;
- overflow: hidden;
- flex-shrink: 0;
-}
-
-.avatar img {
- width: 100%;
- height: 100%;
- object-fit: cover;
-}
-
-.avatar svg * {
- fill: var(--cpd-color-text-primary);
-}
-
-.avatar span {
- padding-top: 1px;
-}
-
-.xs {
- width: 22px;
- height: 22px;
- border-radius: 22px;
- font-size: 14px;
-}
-
-.sm {
- width: 32px;
- height: 32px;
- border-radius: 32px;
- font-size: 15px;
-}
-
-.md {
- width: 36px;
- height: 36px;
- border-radius: 36px;
- font-size: 20px;
-}
-
-.lg {
- width: 42px;
- height: 42px;
- border-radius: 42px;
- font-size: 24px;
-}
-
-.xl {
- width: 90px;
- height: 90px;
- border-radius: 90px;
- font-size: 48px;
-}
diff --git a/src/Avatar.tsx b/src/Avatar.tsx
index c11d71d4..e23bd909 100644
--- a/src/Avatar.tsx
+++ b/src/Avatar.tsx
@@ -14,23 +14,11 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { useMemo, CSSProperties, HTMLAttributes, FC } from "react";
-import classNames from "classnames";
+import { useMemo, FC } from "react";
+import { Avatar as CompoundAvatar } from "@vector-im/compound-web";
import { getAvatarUrl } from "./matrix-utils";
import { useClient } from "./ClientContext";
-import styles from "./Avatar.module.css";
-
-const backgroundColors = [
- "#5C56F5",
- "#03B381",
- "#368BD6",
- "#AC3BA8",
- "#E64F7A",
- "#FF812D",
- "#2DC2C5",
- "#74D12C",
-];
export enum Size {
XS = "xs",
@@ -48,50 +36,28 @@ export const sizes = new Map([
[Size.XL, 90],
]);
-function hashStringToArrIndex(str: string, arrLength: number) {
- let sum = 0;
-
- for (let i = 0; i < str.length; i++) {
- sum += str.charCodeAt(i);
- }
-
- return sum % arrLength;
-}
-
-interface Props extends HTMLAttributes {
- bgKey?: string;
+interface Props {
+ id: string;
+ name: string;
+ className?: string;
src?: string;
size?: Size | number;
- className?: string;
- style?: CSSProperties;
- fallback: string;
}
export const Avatar: FC = ({
- bgKey,
- src,
- fallback,
- size = Size.MD,
className,
- style = {},
- ...rest
+ id,
+ name,
+ src,
+ size = Size.MD,
}) => {
const { client } = useClient();
- const [sizeClass, sizePx, sizeStyle] = useMemo(
+ const sizePx = useMemo(
() =>
Object.values(Size).includes(size as Size)
- ? [styles[size as string], sizes.get(size as Size), {}]
- : [
- null,
- size as number,
- {
- width: size,
- height: size,
- borderRadius: size,
- fontSize: Math.round((size as number) / 2),
- },
- ],
+ ? sizes.get(size as Size)
+ : (size as number),
[size]
);
@@ -100,28 +66,13 @@ export const Avatar: FC = ({
return src.startsWith("mxc://") ? getAvatarUrl(client, src, sizePx) : src;
}, [client, src, sizePx]);
- const backgroundColor = useMemo(() => {
- const index = hashStringToArrIndex(
- bgKey || fallback || src || "",
- backgroundColors.length
- );
- return backgroundColors[index];
- }, [bgKey, src, fallback]);
-
- /* eslint-disable jsx-a11y/alt-text */
return (
-
+
);
};
diff --git a/src/E2EELock.tsx b/src/E2EELock.tsx
deleted file mode 100644
index 9a9a55e9..00000000
--- a/src/E2EELock.tsx
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
-Copyright 2023 New Vector Ltd
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-import { useTranslation } from "react-i18next";
-import { useCallback } from "react";
-import { useObjectRef } from "@react-aria/utils";
-import { useButton } from "@react-aria/button";
-
-import styles from "./E2EELock.module.css";
-import { ReactComponent as LockOffIcon } from "./icons/LockOff.svg";
-import { TooltipTrigger } from "./Tooltip";
-
-export const E2EELock = () => {
- const { t } = useTranslation();
- const tooltip = useCallback(
- () => t("This call is not end-to-end encrypted."),
- [t]
- );
-
- return (
-
-
-
- );
-};
-
-/**
- * This component is a bit of hack - for some reason for the TooltipTrigger to
- * work, it needs to contain a component which uses the useButton hook; please
- * note that for some reason this also needs to be a separate component and we
- * cannot just use the useButton hook inside the E2EELock.
- */
-const Icon = () => {
- const buttonRef = useObjectRef();
- const { buttonProps } = useButton({}, buttonRef);
-
- return (
-
-
-
- );
-};
diff --git a/src/Facepile.tsx b/src/Facepile.tsx
index 0c9ec239..7ed995ce 100644
--- a/src/Facepile.tsx
+++ b/src/Facepile.tsx
@@ -14,27 +14,20 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { HTMLAttributes, useMemo } from "react";
-import classNames from "classnames";
+import { HTMLAttributes } from "react";
import { MatrixClient } from "matrix-js-sdk/src/client";
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
import { useTranslation } from "react-i18next";
+import { AvatarStack } from "@vector-im/compound-web";
-import styles from "./Facepile.module.css";
-import { Avatar, Size, sizes } from "./Avatar";
-
-const overlapMap: Partial> = {
- [Size.XS]: 2,
- [Size.SM]: 4,
- [Size.MD]: 8,
-};
+import { Avatar, Size } from "./Avatar";
interface Props extends HTMLAttributes {
- className: string;
+ className?: string;
client: MatrixClient;
members: RoomMember[];
max?: number;
- size?: Size;
+ size?: Size | number;
}
export function Facepile({
@@ -47,51 +40,27 @@ export function Facepile({
}: Props) {
const { t } = useTranslation();
- const _size = sizes.get(size)!;
- const _overlap = overlapMap[size]!;
-
- const title = useMemo(() => {
- return members.reduce(
- (prev, curr) =>
- prev === null
- ? curr.name
- : t("{{names}}, {{name}}", { names: prev, name: curr.name }),
- null
- ) as string;
- }, [members, t]);
+ const displayedMembers = members.slice(0, max);
return (
-
);
-}
+};
diff --git a/src/IncompatibleVersionModal.tsx b/src/IncompatibleVersionModal.tsx
deleted file mode 100644
index d11822de..00000000
--- a/src/IncompatibleVersionModal.tsx
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
-Copyright 2022 New Vector Ltd
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-import { Room } from "matrix-js-sdk/src/models/room";
-import { FC, useMemo } from "react";
-import { Trans, useTranslation } from "react-i18next";
-
-import { Modal, ModalContent } from "./Modal";
-import { Body } from "./typography/Typography";
-
-interface Props {
- userIds: Set;
- room: Room;
- onClose: () => void;
-}
-
-export const IncompatibleVersionModal: FC = ({
- userIds,
- room,
- onClose,
- ...rest
-}) => {
- const { t } = useTranslation();
- const userLis = useMemo(
- () => [...userIds].map((u) =>
{room.getMember(u)?.name ?? u}
),
- [userIds, room]
- );
-
- return (
-
-
-
-
- Other users are trying to join this call from incompatible versions.
- These users should ensure that they have refreshed their browsers:
-
{userLis}
-
-
-
-
- );
-};
diff --git a/src/UserMenu.module.css b/src/UserMenu.module.css
index d1db1071..575b71b9 100644
--- a/src/UserMenu.module.css
+++ b/src/UserMenu.module.css
@@ -24,17 +24,3 @@ limitations under the License.
.userButton svg * {
fill: var(--cpd-color-icon-primary);
}
-
-.avatar {
- width: 24px;
- height: 24px;
- font-size: var(--font-size-caption);
-}
-
-@media (min-width: 800px) {
- .avatar {
- width: 32px;
- height: 32px;
- font-size: var(--font-size-body);
- }
-}
diff --git a/src/UserMenu.tsx b/src/UserMenu.tsx
index 9df3309d..515e71f0 100644
--- a/src/UserMenu.tsx
+++ b/src/UserMenu.tsx
@@ -35,6 +35,7 @@ interface UserMenuProps {
preventNavigation: boolean;
isAuthenticated: boolean;
isPasswordlessUser: boolean;
+ userId: string;
displayName: string;
avatarUrl?: string;
onAction: (value: string) => void;
@@ -44,6 +45,7 @@ export function UserMenu({
preventNavigation,
isAuthenticated,
isPasswordlessUser,
+ userId,
displayName,
avatarUrl,
onAction,
@@ -109,10 +111,10 @@ export function UserMenu({
>
{isAuthenticated && (!isPasswordlessUser || avatarUrl) ? (
) : (
diff --git a/src/UserMenuContainer.tsx b/src/UserMenuContainer.tsx
index 6a83133e..a03e5b5a 100644
--- a/src/UserMenuContainer.tsx
+++ b/src/UserMenuContainer.tsx
@@ -67,6 +67,7 @@ export function UserMenuContainer({ preventNavigation = false }: Props) {
isPasswordlessUser={passwordlessUser}
avatarUrl={avatarUrl}
onAction={onAction}
+ userId={client?.getUserId() ?? ""}
displayName={displayName || (userName ? userName.replace("@", "") : "")}
/>
{modalState.isOpen && client && (
diff --git a/src/button/Button.module.css b/src/button/Button.module.css
index b1b712e1..d5cc8b15 100644
--- a/src/button/Button.module.css
+++ b/src/button/Button.module.css
@@ -50,14 +50,14 @@ limitations under the License.
background-color: var(--cpd-color-text-action-accent);
}
-.button:focus,
-.toolbarButton:focus,
-.toolbarButtonSecondary:focus,
-.iconButton:focus,
-.iconCopyButton:focus,
-.secondary:focus,
-.secondaryHangup:focus,
-.copyButton:focus {
+.button:focus-visible,
+.toolbarButton:focus-visible,
+.toolbarButtonSecondary:focus-visible,
+.iconButton:focus-visible,
+.iconCopyButton:focus-visible,
+.secondary:focus-visible,
+.secondaryHangup:focus-visible,
+.copyButton:focus-visible {
outline: auto;
}
@@ -74,7 +74,7 @@ limitations under the License.
background-color: var(--cpd-color-bg-canvas-default);
color: var(--cpd-color-icon-primary);
border: 1px solid var(--cpd-color-gray-400);
- box-shadow: 0px 1px 2px 0px rgba(16, 24, 40, 0.05);
+ box-shadow: var(--subtle-drop-shadow);
}
.toolbarButton.on,
diff --git a/src/button/Button.tsx b/src/button/Button.tsx
index ac02c6ed..2b8049e5 100644
--- a/src/button/Button.tsx
+++ b/src/button/Button.tsx
@@ -13,7 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
-import { forwardRef, useCallback } from "react";
+import { forwardRef } from "react";
import { PressEvent } from "@react-types/shared";
import classNames from "classnames";
import { useButton } from "@react-aria/button";
@@ -27,13 +27,11 @@ import { ReactComponent as VideoCallOffIcon } from "@vector-im/compound-design-t
import { ReactComponent as EndCallIcon } from "@vector-im/compound-design-tokens/icons/end-call.svg";
import { ReactComponent as ShareScreenSolidIcon } from "@vector-im/compound-design-tokens/icons/share-screen-solid.svg";
import { ReactComponent as SettingsSolidIcon } from "@vector-im/compound-design-tokens/icons/settings-solid.svg";
-import { ReactComponent as UserAddSolidIcon } from "@vector-im/compound-design-tokens/icons/user-add-solid.svg";
import { ReactComponent as ChevronDownIcon } from "@vector-im/compound-design-tokens/icons/chevron-down.svg";
import styles from "./Button.module.css";
import { ReactComponent as Fullscreen } from "../icons/Fullscreen.svg";
import { ReactComponent as FullscreenExit } from "../icons/FullscreenExit.svg";
-import { TooltipTrigger } from "../Tooltip";
import { VolumeIcon } from "./VolumeIcon";
export type ButtonVariant =
@@ -146,11 +144,13 @@ export function MicButton({
[index: string]: unknown;
}) {
const { t } = useTranslation();
+ const Icon = muted ? MicOffSolidIcon : MicOnSolidIcon;
+ const label = muted ? t("Microphone off") : t("Microphone on");
return (
-
+
);
@@ -165,11 +165,13 @@ export function VideoButton({
[index: string]: unknown;
}) {
const { t } = useTranslation();
+ const Icon = muted ? VideoCallOffIcon : VideoCallIcon;
+ const label = muted ? t("Video off") : t("Video on");
return (
-
+
);
@@ -186,11 +188,12 @@ export function ScreenshareButton({
[index: string]: unknown;
}) {
const { t } = useTranslation();
+ const label = enabled ? t("Sharing screen") : t("Share screen");
return (
-
+
);
@@ -213,7 +216,7 @@ export function HangupButton({
className={classNames(styles.hangupButton, className)}
{...rest}
>
-
+
);
@@ -232,28 +235,7 @@ export function SettingsButton({
return (
-
- );
-}
-
-export function InviteButton({
- className,
- variant = "toolbar",
- ...rest
-}: {
- className?: string;
- variant?: string;
- // TODO: add all props for
);
}
@@ -288,15 +269,14 @@ export function FullscreenButton({
...rest
}: FullscreenButtonProps) {
const { t } = useTranslation();
- const tooltip = useCallback(() => {
- return fullscreen ? t("Exit full screen") : t("Full screen");
- }, [fullscreen, t]);
+ const Icon = fullscreen ? FullscreenExit : Fullscreen;
+ const label = fullscreen ? t("Exit full screen") : t("Full screen");
return (
-
+
- {fullscreen ? : }
+
-
+
);
}
diff --git a/src/button/ShareButton.tsx b/src/button/ShareButton.tsx
new file mode 100644
index 00000000..2f7f1334
--- /dev/null
+++ b/src/button/ShareButton.tsx
@@ -0,0 +1,31 @@
+/*
+Copyright 2023 New Vector Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import { ComponentPropsWithoutRef, FC } from "react";
+import { Button } from "@vector-im/compound-web";
+import { useTranslation } from "react-i18next";
+import { ReactComponent as UserAddSolidIcon } from "@vector-im/compound-design-tokens/icons/user-add-solid.svg";
+
+export const ShareButton: FC<
+ Omit, "children">
+> = (props) => {
+ const { t } = useTranslation();
+ return (
+
+ {t("Share")}
+
+ );
+};
diff --git a/src/button/VolumeIcon.tsx b/src/button/VolumeIcon.tsx
index 163699f6..00aebb06 100644
--- a/src/button/VolumeIcon.tsx
+++ b/src/button/VolumeIcon.tsx
@@ -15,19 +15,21 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
+import { ComponentPropsWithoutRef, FC } from "react";
+
import { ReactComponent as AudioMuted } from "../icons/AudioMuted.svg";
import { ReactComponent as AudioLow } from "../icons/AudioLow.svg";
import { ReactComponent as Audio } from "../icons/Audio.svg";
-interface Props {
+interface Props extends ComponentPropsWithoutRef<"svg"> {
/**
* Number between 0 and 1
*/
volume: number;
}
-export function VolumeIcon({ volume }: Props) {
- if (volume <= 0) return ;
- if (volume <= 0.5) return ;
- return ;
-}
+export const VolumeIcon: FC = ({ volume, ...rest }) => {
+ if (volume <= 0) return ;
+ if (volume <= 0.5) return ;
+ return ;
+};
diff --git a/src/home/CallList.tsx b/src/home/CallList.tsx
index 1e36360e..a82e4c13 100644
--- a/src/home/CallList.tsx
+++ b/src/home/CallList.tsx
@@ -19,7 +19,6 @@ import { MatrixClient } from "matrix-js-sdk/src/client";
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
import { CopyButton } from "../button";
-import { Facepile } from "../Facepile";
import { Avatar, Size } from "../Avatar";
import styles from "./CallList.module.css";
import { getRoomUrl } from "../matrix-utils";
@@ -30,9 +29,8 @@ import { useRoomSharedKey } from "../e2ee/sharedKeyManagement";
interface CallListProps {
rooms: GroupCallRoom[];
client: MatrixClient;
- disableFacepile?: boolean;
}
-export function CallList({ rooms, client, disableFacepile }: CallListProps) {
+export function CallList({ rooms, client }: CallListProps) {
return (
<>
);
}
+function findMatrixMember(
+ room: MatrixRoom,
+ id: string
+): RoomMember | undefined {
+ if (!id) return undefined;
+
+ const parts = id.split(":");
+ // must be at least 3 parts because we know the first part is a userId which must necessarily contain a colon
+ if (parts.length < 3) {
+ logger.warn(
+ "Livekit participants ID doesn't look like a userId:deviceId combination"
+ );
+ return undefined;
+ }
+
+ parts.pop();
+ const userId = parts.join(":");
+
+ return room.getMember(userId) ?? undefined;
+}
+
function useParticipantTiles(
livekitRoom: Room,
- participants: Map>
+ matrixRoom: MatrixRoom
): TileDescriptor[] {
const sfuParticipants = useParticipants({
room: livekitRoom,
});
const items = useMemo(() => {
- // The IDs of the participants who published membership event to the room (i.e. are present from Matrix perspective).
- const matrixParticipants: Map = new Map(
- [...participants.entries()].flatMap(([user, devicesMap]) => {
- return [...devicesMap.keys()].map((deviceId) => [
- `${user.userId}:${deviceId}`,
- user,
- ]);
- })
- );
-
const hasPresenter =
sfuParticipants.find((p) => p.isScreenShareEnabled) !== undefined;
let allGhosts = true;
@@ -514,7 +504,14 @@ function useParticipantTiles(
: false;
const id = sfuParticipant.identity;
- const member = matrixParticipants.get(id);
+ const member = findMatrixMember(matrixRoom, id);
+ // We always start with a local participant wit the empty string as their ID before we're
+ // connected, this is fine and we'll be in "all ghosts" mode.
+ if (id !== "" && member === undefined) {
+ logger.warn(
+ `Ruh, roh! No matrix member found for SFU participant '${id}': creating g-g-g-ghost!`
+ );
+ }
allGhosts &&= member === undefined;
const userMediaTile = {
@@ -566,7 +563,7 @@ function useParticipantTiles(
// If every item is a ghost, that probably means we're still connecting and
// shouldn't bother showing anything yet
return allGhosts ? [] : tiles;
- }, [participants, sfuParticipants]);
+ }, [matrixRoom, sfuParticipants]);
return items;
}
diff --git a/src/room/LayoutToggle.module.css b/src/room/LayoutToggle.module.css
new file mode 100644
index 00000000..e54e9447
--- /dev/null
+++ b/src/room/LayoutToggle.module.css
@@ -0,0 +1,77 @@
+/*
+Copyright 2023 New Vector Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+.toggle {
+ padding: 2px;
+ border: 1px solid var(--cpd-color-border-interactive-secondary);
+ border-radius: var(--cpd-radius-pill-effect);
+ box-shadow: 0px 0px 40px 0px rgba(0, 0, 0, 0.5);
+ display: flex;
+}
+
+.toggle input {
+ appearance: none;
+ outline: none !important;
+}
+
+.toggle label {
+ display: block;
+ padding: calc(2.5 * var(--cpd-space-1x));
+ cursor: pointer;
+ border-radius: var(--cpd-radius-pill-effect);
+ color: var(--cpd-color-icon-primary);
+ background: var(--cpd-color-bg-action-secondary-rest);
+ box-shadow: var(--small-drop-shadow);
+}
+
+@media (hover: hover) {
+ .toggle label:hover {
+ background: var(--cpd-color-bg-action-secondary-hovered);
+ box-shadow: none;
+ }
+}
+
+.toggle label:active {
+ background: var(--cpd-color-bg-action-secondary-hovered);
+ box-shadow: none;
+}
+
+.toggle input:checked + label {
+ color: var(--cpd-color-icon-on-solid-primary);
+ background: var(--cpd-color-bg-action-primary-rest);
+}
+
+@media (hover: hover) {
+ .toggle input:checked + label:hover {
+ background: var(--cpd-color-bg-action-primary-hovered);
+ }
+}
+
+.toggle input:checked + label:active {
+ background: var(--cpd-color-bg-action-primary-hovered);
+}
+
+.toggle label > svg {
+ display: block;
+}
+
+.toggle label:last-child {
+ margin-inline-start: 5px;
+}
+
+.toggle input:focus-visible + label {
+ outline: auto;
+}
diff --git a/src/room/LayoutToggle.tsx b/src/room/LayoutToggle.tsx
new file mode 100644
index 00000000..5252204b
--- /dev/null
+++ b/src/room/LayoutToggle.tsx
@@ -0,0 +1,75 @@
+/*
+Copyright 2023 New Vector Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import { ChangeEvent, FC, useCallback, useId } from "react";
+import { useTranslation } from "react-i18next";
+import { Tooltip } from "@vector-im/compound-web";
+import { ReactComponent as SpotlightViewIcon } from "@vector-im/compound-design-tokens/icons/spotlight-view.svg";
+import { ReactComponent as GridViewIcon } from "@vector-im/compound-design-tokens/icons/grid-view.svg";
+import classNames from "classnames";
+
+import styles from "./LayoutToggle.module.css";
+
+export type Layout = "spotlight" | "grid";
+
+interface Props {
+ layout: Layout;
+ setLayout: (layout: Layout) => void;
+ className?: string;
+}
+
+export const LayoutToggle: FC = ({ layout, setLayout, className }) => {
+ const { t } = useTranslation();
+
+ const onChange = useCallback(
+ (e: ChangeEvent) => setLayout(e.target.value as Layout),
+ [setLayout]
+ );
+
+ const spotlightId = useId();
+ const gridId = useId();
+
+ return (
+
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/src/room/LobbyView.tsx b/src/room/LobbyView.tsx
index a34595c9..716e1200 100644
--- a/src/room/LobbyView.tsx
+++ b/src/room/LobbyView.tsx
@@ -16,32 +16,39 @@ limitations under the License.
import { useRef, useEffect, FC } from "react";
import { Trans, useTranslation } from "react-i18next";
+import { MatrixClient, RoomMember } from "matrix-js-sdk/src/matrix";
import styles from "./LobbyView.module.css";
import { Button, CopyButton } from "../button";
import { Header, LeftNav, RightNav, RoomHeaderInfo } from "../Header";
import { getRoomUrl } from "../matrix-utils";
-import { UserMenuContainer } from "../UserMenuContainer";
import { Body, Link } from "../typography/Typography";
import { useLocationNavigation } from "../useLocationNavigation";
import { MatrixInfo, VideoPreview } from "./VideoPreview";
import { MuteStates } from "./MuteStates";
import { useRoomSharedKey } from "../e2ee/sharedKeyManagement";
+import { ShareButton } from "../button/ShareButton";
interface Props {
+ client: MatrixClient;
matrixInfo: MatrixInfo;
muteStates: MuteStates;
onEnter: () => void;
isEmbedded: boolean;
hideHeader: boolean;
+ participatingMembers: RoomMember[];
+ onShareClick: (() => void) | null;
}
export const LobbyView: FC = ({
+ client,
matrixInfo,
muteStates,
onEnter,
isEmbedded,
hideHeader,
+ participatingMembers,
+ onShareClick,
}) => {
const { t } = useTranslation();
const roomSharedKey = useRoomSharedKey(matrixInfo.roomId);
@@ -59,10 +66,17 @@ export const LobbyView: FC = ({
{!hideHeader && (
-
+
-
+ {onShareClick !== null && }
)}
diff --git a/src/room/RoomPage.tsx b/src/room/RoomPage.tsx
index ddf92959..50156e70 100644
--- a/src/room/RoomPage.tsx
+++ b/src/room/RoomPage.tsx
@@ -15,8 +15,8 @@ limitations under the License.
*/
import { FC, useEffect, useState, useCallback } from "react";
+import { MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession";
-import type { GroupCall } from "matrix-js-sdk/src/webrtc/groupCall";
import { useClientLegacy } from "../ClientContext";
import { ErrorView, LoadingView } from "../FullScreenView";
import { RoomAuthView } from "./RoomAuthView";
@@ -73,10 +73,10 @@ export const RoomPage: FC = () => {
]);
const groupCallView = useCallback(
- (groupCall: GroupCall) => (
+ (rtcSession: MatrixRTCSession) => (
{
roomId: string;
}
-export const InviteModal: FC = ({ roomId, ...rest }) => {
+export const ShareModal: FC = ({ roomId, ...rest }) => {
const { t } = useTranslation();
const roomSharedKey = useRoomSharedKey(roomId);
return (
= ({ matrixInfo, muteStates }) => {
const devices = useMediaDevices();
+ // Capture the audio options as they were when we first mounted, because
+ // we're not doing anything with the audio anyway so we don't need to
+ // re-open the devices when they change (see below).
const initialAudioOptions = useRef();
initialAudioOptions.current ??= muteStates.audio.enabled && {
deviceId: devices.audioInput.selectedId,
@@ -79,7 +85,9 @@ export const VideoPreview: FC = ({ matrixInfo, muteStates }) => {
// request over with at the same time. But changing the audio settings
// shouldn't cause this hook to recreate the track, which is why we
// reference the initial values here.
- audio: initialAudioOptions.current,
+ // We also pass in a clone because livekit mutates the object passed in,
+ // which would cause the devices to be re-opened on the next render.
+ audio: Object.assign({}, initialAudioOptions.current),
video: muteStates.video.enabled && {
deviceId: devices.videoInput.selectedId,
},
@@ -130,9 +138,10 @@ export const VideoPreview: FC = ({ matrixInfo, muteStates }) => {
{!muteStates.video.enabled && (
)}
diff --git a/src/room/useActiveFocus.ts b/src/room/useActiveFocus.ts
new file mode 100644
index 00000000..a62ffafd
--- /dev/null
+++ b/src/room/useActiveFocus.ts
@@ -0,0 +1,68 @@
+/*
+Copyright 2023 New Vector Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import {
+ MatrixRTCSession,
+ MatrixRTCSessionEvent,
+} from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession";
+import { useCallback, useEffect, useState } from "react";
+import { deepCompare } from "matrix-js-sdk/src/utils";
+
+import { LivekitFocus } from "../livekit/LivekitFocus";
+
+function getActiveFocus(
+ rtcSession: MatrixRTCSession
+): LivekitFocus | undefined {
+ const oldestMembership = rtcSession.getOldestMembership();
+ return oldestMembership?.getActiveFoci()[0] as LivekitFocus;
+}
+
+/**
+ * Gets the currently active (livekit) focus for a MatrixRTC session
+ * This logic is specific to livekit foci where the whole call must use one
+ * and the same focus.
+ */
+export function useActiveFocus(
+ rtcSession: MatrixRTCSession
+): LivekitFocus | undefined {
+ const [activeFocus, setActiveFocus] = useState(() =>
+ getActiveFocus(rtcSession)
+ );
+
+ const onMembershipsChanged = useCallback(() => {
+ const newActiveFocus = getActiveFocus(rtcSession);
+
+ if (!deepCompare(activeFocus, newActiveFocus)) {
+ setActiveFocus(newActiveFocus);
+ }
+ }, [activeFocus, rtcSession]);
+
+ useEffect(() => {
+ rtcSession.on(
+ MatrixRTCSessionEvent.MembershipsChanged,
+ onMembershipsChanged
+ );
+
+ return () => {
+ rtcSession.off(
+ MatrixRTCSessionEvent.MembershipsChanged,
+ onMembershipsChanged
+ );
+ };
+ });
+
+ return activeFocus;
+}
diff --git a/src/room/useGroupCall.ts b/src/room/useGroupCall.ts
deleted file mode 100644
index b02e7113..00000000
--- a/src/room/useGroupCall.ts
+++ /dev/null
@@ -1,644 +0,0 @@
-/*
-Copyright 2022 New Vector Ltd
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-import { useCallback, useEffect, useReducer, useState } from "react";
-import * as Sentry from "@sentry/react";
-import {
- GroupCallEvent,
- GroupCallState,
- GroupCall,
- GroupCallErrorCode,
- GroupCallUnknownDeviceError,
- GroupCallError,
- GroupCallStatsReportEvent,
- GroupCallStatsReport,
-} from "matrix-js-sdk/src/webrtc/groupCall";
-import { CallFeed, CallFeedEvent } from "matrix-js-sdk/src/webrtc/callFeed";
-import { RoomMember } from "matrix-js-sdk/src/models/room-member";
-import { useTranslation } from "react-i18next";
-import { IWidgetApiRequest } from "matrix-widget-api";
-import { MatrixClient, RoomStateEvent } from "matrix-js-sdk";
-import {
- ByteSentStatsReport,
- ConnectionStatsReport,
- SummaryStatsReport,
- CallFeedReport,
-} from "matrix-js-sdk/src/webrtc/stats/statsReport";
-
-import { usePageUnload } from "./usePageUnload";
-import { PosthogAnalytics } from "../analytics/PosthogAnalytics";
-import { TranslatedError, translatedError } from "../TranslatedError";
-import { ElementWidgetActions, ScreenshareStartData, widget } from "../widget";
-import { OTelGroupCallMembership } from "../otel/OTelGroupCallMembership";
-import { ElementCallOpenTelemetry } from "../otel/otel";
-import { checkForParallelCalls } from "./checkForParallelCalls";
-
-enum ConnectionState {
- EstablishingCall = "establishing call", // call hasn't been established yet
- WaitMedia = "wait_media", // call is set up, waiting for ICE to connect
- Connected = "connected", // media is flowing
-}
-
-export interface ParticipantInfo {
- connectionState: ConnectionState;
- presenter: boolean;
-}
-
-interface UseGroupCallReturnType {
- state: GroupCallState;
- localCallFeed?: CallFeed;
- activeSpeaker?: CallFeed;
- userMediaFeeds: CallFeed[];
- microphoneMuted: boolean;
- localVideoMuted: boolean;
- error?: TranslatedError;
- initLocalCallFeed: () => void;
- enter: () => Promise;
- leave: () => void;
- toggleLocalVideoMuted: () => void;
- toggleMicrophoneMuted: () => void;
- toggleScreensharing: () => void;
- setMicrophoneMuted: (muted: boolean) => void;
- requestingScreenshare: boolean;
- isScreensharing: boolean;
- screenshareFeeds: CallFeed[];
- participants: Map>;
- hasLocalParticipant: boolean;
- unencryptedEventsFromUsers: Set;
- otelGroupCallMembership?: OTelGroupCallMembership;
-}
-
-interface State {
- state: GroupCallState;
- localCallFeed?: CallFeed;
- activeSpeaker?: CallFeed;
- userMediaFeeds: CallFeed[];
- error?: TranslatedError;
- microphoneMuted: boolean;
- localVideoMuted: boolean;
- screenshareFeeds: CallFeed[];
- isScreensharing: boolean;
- requestingScreenshare: boolean;
- participants: Map>;
- hasLocalParticipant: boolean;
-}
-
-// This is a bit of a hack, but we keep the opentelemetry tracker object at the file
-// level so that it doesn't pop in & out of existence as react mounts & unmounts
-// components. The right solution is probably for this to live in the js-sdk and have
-// the same lifetime as groupcalls themselves.
-let groupCallOTelMembership: OTelGroupCallMembership | undefined;
-let groupCallOTelMembershipGroupCallId: string;
-
-function getParticipants(
- groupCall: GroupCall
-): Map> {
- const participants = new Map>();
-
- for (const [member, participantsStateMap] of groupCall.participants) {
- const participantInfoMap = new Map();
- participants.set(member, participantInfoMap);
-
- for (const [deviceId, participant] of participantsStateMap) {
- const feed = groupCall.userMediaFeeds.find(
- (f) => f.userId === member.userId && f.deviceId === deviceId
- );
-
- let connectionState: ConnectionState;
- // If we allow calls without media, we have no feeds and cannot read the connection status from them.
- // @TODO: The connection state should generally not be determined by the feed.
- if (
- groupCall.allowCallWithoutVideoAndAudio &&
- !feed &&
- !participant.screensharing
- ) {
- connectionState = ConnectionState.Connected;
- } else {
- connectionState = feed
- ? feed.connected
- ? ConnectionState.Connected
- : ConnectionState.WaitMedia
- : ConnectionState.EstablishingCall;
- }
- participantInfoMap.set(deviceId, {
- connectionState,
- presenter: participant.screensharing,
- });
- }
- }
-
- return participants;
-}
-
-export function useGroupCall(
- groupCall: GroupCall,
- client: MatrixClient
-): UseGroupCallReturnType {
- const [
- {
- state,
- localCallFeed,
- activeSpeaker,
- userMediaFeeds,
- error,
- microphoneMuted,
- localVideoMuted,
- isScreensharing,
- screenshareFeeds,
- participants,
- hasLocalParticipant,
- requestingScreenshare,
- },
- setState,
- ] = useState({
- state: GroupCallState.LocalCallFeedUninitialized,
- userMediaFeeds: [],
- microphoneMuted: false,
- localVideoMuted: false,
- isScreensharing: false,
- screenshareFeeds: [],
- requestingScreenshare: false,
- participants: getParticipants(groupCall),
- hasLocalParticipant: false,
- });
-
- if (groupCallOTelMembershipGroupCallId !== groupCall.groupCallId) {
- if (groupCallOTelMembership) groupCallOTelMembership.dispose();
-
- // If the user disables analytics, this will stay around until they leave the call
- // so analytics will be disabled once they leave.
- if (ElementCallOpenTelemetry.instance) {
- groupCallOTelMembership = new OTelGroupCallMembership(groupCall, client);
- groupCallOTelMembershipGroupCallId = groupCall.groupCallId;
- } else {
- groupCallOTelMembership = undefined;
- }
- }
-
- const [unencryptedEventsFromUsers, addUnencryptedEventUser] = useReducer(
- (state: Set, newVal: string) => {
- return new Set(state).add(newVal);
- },
- new Set()
- );
-
- const updateState = useCallback(
- (state: Partial) => setState((prev) => ({ ...prev, ...state })),
- [setState]
- );
-
- const doNothingMediaActionCallback = useCallback(
- (details: MediaSessionActionDetails) => {},
- []
- );
-
- const leaveCall = useCallback(() => {
- groupCallOTelMembership?.onLeaveCall();
- groupCall.leave();
- }, [groupCall]);
-
- useEffect(() => {
- // disable the media action keys, otherwise audio elements get paused when
- // the user presses media keys or unplugs headphones, etc.
- // Note there are actions for muting / unmuting a microphone & hanging up
- // which we could wire up.
- const mediaActions: MediaSessionAction[] = [
- "play",
- "pause",
- "stop",
- "nexttrack",
- "previoustrack",
- ];
-
- for (const mediaAction of mediaActions) {
- navigator.mediaSession?.setActionHandler(
- mediaAction,
- doNothingMediaActionCallback
- );
- }
-
- return () => {
- for (const mediaAction of mediaActions) {
- navigator.mediaSession?.setActionHandler(mediaAction, null);
- }
- };
- }, [doNothingMediaActionCallback]);
-
- useEffect(() => {
- function onGroupCallStateChanged() {
- updateState({
- state: groupCall.state,
- localCallFeed: groupCall.localCallFeed,
- activeSpeaker: groupCall.activeSpeaker,
- userMediaFeeds: [...groupCall.userMediaFeeds],
- microphoneMuted: groupCall.isMicrophoneMuted(),
- localVideoMuted: groupCall.isLocalVideoMuted(),
- isScreensharing: groupCall.isScreensharing(),
- screenshareFeeds: [...groupCall.screenshareFeeds],
- });
- }
-
- const prevUserMediaFeeds = new Set();
-
- function onUserMediaFeedsChanged(userMediaFeeds: CallFeed[]): void {
- for (const feed of prevUserMediaFeeds) {
- feed.off(CallFeedEvent.ConnectedChanged, onConnectedChanged);
- }
- prevUserMediaFeeds.clear();
-
- for (const feed of userMediaFeeds) {
- feed.on(CallFeedEvent.ConnectedChanged, onConnectedChanged);
- prevUserMediaFeeds.add(feed);
- }
-
- updateState({
- userMediaFeeds: [...userMediaFeeds],
- participants: getParticipants(groupCall),
- });
- }
-
- const prevScreenshareFeeds = new Set();
-
- function onScreenshareFeedsChanged(screenshareFeeds: CallFeed[]): void {
- for (const feed of prevScreenshareFeeds) {
- feed.off(CallFeedEvent.ConnectedChanged, onConnectedChanged);
- }
- prevScreenshareFeeds.clear();
-
- for (const feed of screenshareFeeds) {
- feed.on(CallFeedEvent.ConnectedChanged, onConnectedChanged);
- prevScreenshareFeeds.add(feed);
- }
-
- updateState({
- screenshareFeeds: [...screenshareFeeds],
- });
- }
-
- function onConnectedChanged(connected: boolean): void {
- updateState({
- participants: getParticipants(groupCall),
- });
- }
-
- function onActiveSpeakerChanged(activeSpeaker: CallFeed | undefined): void {
- updateState({
- activeSpeaker: activeSpeaker,
- });
- }
-
- function onLocalMuteStateChanged(
- microphoneMuted: boolean,
- localVideoMuted: boolean
- ): void {
- updateState({
- microphoneMuted,
- localVideoMuted,
- });
- }
-
- function onLocalScreenshareStateChanged(
- isScreensharing: boolean,
- _localScreenshareFeed?: CallFeed,
- localDesktopCapturerSourceId?: string
- ): void {
- updateState({
- isScreensharing,
- });
- }
-
- function onCallsChanged(): void {
- updateState({ participants: getParticipants(groupCall) });
- }
-
- function onParticipantsChanged(): void {
- updateState({
- participants: getParticipants(groupCall),
- hasLocalParticipant: groupCall.hasLocalParticipant(),
- });
- }
-
- function onError(e: GroupCallError): void {
- Sentry.captureException(e);
- if (e.code === GroupCallErrorCode.UnknownDevice) {
- const unknownDeviceError = e as GroupCallUnknownDeviceError;
- addUnencryptedEventUser(unknownDeviceError.userId);
- }
- }
-
- function onConnectionStatsReport(
- report: GroupCallStatsReport
- ): void {
- groupCallOTelMembership?.onConnectionStatsReport(report);
- }
-
- function onByteSentStatsReport(
- report: GroupCallStatsReport
- ): void {
- groupCallOTelMembership?.onByteSentStatsReport(report);
- }
-
- function onSummaryStatsReport(
- report: GroupCallStatsReport
- ): void {
- groupCallOTelMembership?.onSummaryStatsReport(report);
- }
-
- function onCallFeedStatsReport(
- report: GroupCallStatsReport
- ): void {
- groupCallOTelMembership?.onCallFeedStatsReport(report);
- }
-
- groupCall.on(GroupCallEvent.GroupCallStateChanged, onGroupCallStateChanged);
- groupCall.on(GroupCallEvent.UserMediaFeedsChanged, onUserMediaFeedsChanged);
- groupCall.on(
- GroupCallEvent.ScreenshareFeedsChanged,
- onScreenshareFeedsChanged
- );
- groupCall.on(GroupCallEvent.ActiveSpeakerChanged, onActiveSpeakerChanged);
- groupCall.on(GroupCallEvent.LocalMuteStateChanged, onLocalMuteStateChanged);
- groupCall.on(
- GroupCallEvent.LocalScreenshareStateChanged,
- onLocalScreenshareStateChanged
- );
- groupCall.on(GroupCallEvent.CallsChanged, onCallsChanged);
- groupCall.on(GroupCallEvent.ParticipantsChanged, onParticipantsChanged);
- groupCall.on(GroupCallEvent.Error, onError);
- groupCall.on(
- GroupCallStatsReportEvent.ConnectionStats,
- onConnectionStatsReport
- );
- groupCall.on(
- GroupCallStatsReportEvent.ByteSentStats,
- onByteSentStatsReport
- );
- groupCall.on(GroupCallStatsReportEvent.SummaryStats, onSummaryStatsReport);
- groupCall.on(
- GroupCallStatsReportEvent.CallFeedStats,
- onCallFeedStatsReport
- );
-
- groupCall.room.currentState.on(
- RoomStateEvent.Update,
- checkForParallelCalls
- );
-
- updateState({
- error: undefined,
- state: groupCall.state,
- localCallFeed: groupCall.localCallFeed,
- activeSpeaker: groupCall.activeSpeaker,
- userMediaFeeds: [...groupCall.userMediaFeeds],
- microphoneMuted: groupCall.isMicrophoneMuted(),
- localVideoMuted: groupCall.isLocalVideoMuted(),
- isScreensharing: groupCall.isScreensharing(),
- screenshareFeeds: [...groupCall.screenshareFeeds],
- participants: getParticipants(groupCall),
- hasLocalParticipant: groupCall.hasLocalParticipant(),
- });
-
- return () => {
- groupCall.removeListener(
- GroupCallEvent.GroupCallStateChanged,
- onGroupCallStateChanged
- );
- groupCall.removeListener(
- GroupCallEvent.UserMediaFeedsChanged,
- onUserMediaFeedsChanged
- );
- groupCall.removeListener(
- GroupCallEvent.ScreenshareFeedsChanged,
- onScreenshareFeedsChanged
- );
- groupCall.removeListener(
- GroupCallEvent.ActiveSpeakerChanged,
- onActiveSpeakerChanged
- );
- groupCall.removeListener(
- GroupCallEvent.LocalMuteStateChanged,
- onLocalMuteStateChanged
- );
- groupCall.removeListener(
- GroupCallEvent.LocalScreenshareStateChanged,
- onLocalScreenshareStateChanged
- );
- groupCall.removeListener(GroupCallEvent.CallsChanged, onCallsChanged);
- groupCall.removeListener(
- GroupCallEvent.ParticipantsChanged,
- onParticipantsChanged
- );
- groupCall.removeListener(GroupCallEvent.Error, onError);
- groupCall.removeListener(
- GroupCallStatsReportEvent.ConnectionStats,
- onConnectionStatsReport
- );
- groupCall.removeListener(
- GroupCallStatsReportEvent.ByteSentStats,
- onByteSentStatsReport
- );
- groupCall.removeListener(
- GroupCallStatsReportEvent.SummaryStats,
- onSummaryStatsReport
- );
- groupCall.removeListener(
- GroupCallStatsReportEvent.CallFeedStats,
- onCallFeedStatsReport
- );
- groupCall.room.currentState.off(
- RoomStateEvent.Update,
- checkForParallelCalls
- );
- leaveCall();
- };
- }, [groupCall, updateState, leaveCall]);
-
- usePageUnload(() => {
- leaveCall();
- });
-
- const initLocalCallFeed = useCallback(
- () => groupCall.initLocalCallFeed(),
- [groupCall]
- );
-
- const enter = useCallback(async () => {
- if (
- groupCall.state !== GroupCallState.LocalCallFeedUninitialized &&
- groupCall.state !== GroupCallState.LocalCallFeedInitialized
- ) {
- return;
- }
-
- PosthogAnalytics.instance.eventCallEnded.cacheStartCall(new Date());
- PosthogAnalytics.instance.eventCallStarted.track(groupCall.groupCallId);
-
- // This must be called before we start trying to join the call, as we need to
- // have started tracking by the time calls start getting created.
- groupCallOTelMembership?.onJoinCall();
-
- await groupCall.enter().catch((error) => {
- console.error(error);
- updateState({ error });
- });
- }, [groupCall, updateState]);
-
- const toggleLocalVideoMuted = useCallback(() => {
- const toggleToMute = !groupCall.isLocalVideoMuted();
- groupCall.setLocalVideoMuted(toggleToMute);
- groupCallOTelMembership?.onToggleLocalVideoMuted(toggleToMute);
- // TODO: These explict posthog calls should be unnecessary now with the posthog otel exporter?
- PosthogAnalytics.instance.eventMuteCamera.track(
- toggleToMute,
- groupCall.groupCallId
- );
- }, [groupCall]);
-
- const setMicrophoneMuted = useCallback(
- (setMuted: boolean) => {
- groupCall.setMicrophoneMuted(setMuted);
- groupCallOTelMembership?.onSetMicrophoneMuted(setMuted);
- PosthogAnalytics.instance.eventMuteMicrophone.track(
- setMuted,
- groupCall.groupCallId
- );
- },
- [groupCall]
- );
-
- const toggleMicrophoneMuted = useCallback(() => {
- const toggleToMute = !groupCall.isMicrophoneMuted();
- groupCallOTelMembership?.onToggleMicrophoneMuted(toggleToMute);
- setMicrophoneMuted(toggleToMute);
- }, [groupCall, setMicrophoneMuted]);
-
- const toggleScreensharing = useCallback(async () => {
- groupCallOTelMembership?.onToggleScreensharing(!groupCall.isScreensharing);
-
- if (!groupCall.isScreensharing()) {
- // toggling on
- updateState({ requestingScreenshare: true });
-
- try {
- await groupCall.setScreensharingEnabled(true, {
- audio: true,
- throwOnFail: true,
- });
- updateState({ requestingScreenshare: false });
- } catch (e) {
- // this will fail in Electron because getDisplayMedia just throws a permission
- // error, so if we have a widget API, try requesting via that.
- if (widget) {
- const reply = await widget.api.transport.send(
- ElementWidgetActions.ScreenshareRequest,
- {}
- );
- if (!reply.pending) {
- updateState({ requestingScreenshare: false });
- }
- }
- }
- } else {
- // toggling off
- groupCall.setScreensharingEnabled(false);
- }
- }, [groupCall, updateState]);
-
- const onScreenshareStart = useCallback(
- async (ev: CustomEvent) => {
- updateState({ requestingScreenshare: false });
-
- const data = ev.detail.data as unknown as ScreenshareStartData;
-
- await groupCall.setScreensharingEnabled(true, {
- desktopCapturerSourceId: data.desktopCapturerSourceId as string,
- audio: !data.desktopCapturerSourceId,
- });
- await widget?.api.transport.reply(ev.detail, {});
- },
- [groupCall, updateState]
- );
-
- const onScreenshareStop = useCallback(
- async (ev: CustomEvent) => {
- updateState({ requestingScreenshare: false });
- await groupCall.setScreensharingEnabled(false);
- await widget?.api.transport.reply(ev.detail, {});
- },
- [groupCall, updateState]
- );
-
- useEffect(() => {
- if (widget) {
- widget.lazyActions.on(
- ElementWidgetActions.ScreenshareStart,
- onScreenshareStart
- );
- widget.lazyActions.on(
- ElementWidgetActions.ScreenshareStop,
- onScreenshareStop
- );
-
- return () => {
- widget?.lazyActions.off(
- ElementWidgetActions.ScreenshareStart,
- onScreenshareStart
- );
- widget?.lazyActions.off(
- ElementWidgetActions.ScreenshareStop,
- onScreenshareStop
- );
- };
- }
- }, [onScreenshareStart, onScreenshareStop]);
-
- const { t } = useTranslation();
-
- useEffect(() => {
- if (window.RTCPeerConnection === undefined) {
- const error = translatedError(
- "WebRTC is not supported or is being blocked in this browser.",
- t
- );
- console.error(error);
- updateState({ error });
- }
- }, [t, updateState]);
-
- return {
- state,
- localCallFeed,
- activeSpeaker,
- userMediaFeeds,
- microphoneMuted,
- localVideoMuted,
- error,
- initLocalCallFeed,
- enter,
- leave: leaveCall,
- toggleLocalVideoMuted,
- toggleMicrophoneMuted,
- toggleScreensharing,
- setMicrophoneMuted,
- requestingScreenshare,
- isScreensharing,
- screenshareFeeds,
- participants,
- hasLocalParticipant,
- unencryptedEventsFromUsers,
- otelGroupCallMembership: groupCallOTelMembership,
- };
-}
diff --git a/src/room/useLoadGroupCall.ts b/src/room/useLoadGroupCall.ts
index 3436360c..9218bf32 100644
--- a/src/room/useLoadGroupCall.ts
+++ b/src/room/useLoadGroupCall.ts
@@ -15,32 +15,23 @@ limitations under the License.
*/
import { useState, useEffect } from "react";
-import { EventType } from "matrix-js-sdk/src/@types/event";
-import {
- GroupCallType,
- GroupCallIntent,
-} from "matrix-js-sdk/src/webrtc/groupCall";
-import { GroupCallEventHandlerEvent } from "matrix-js-sdk/src/webrtc/groupCallEventHandler";
import { logger } from "matrix-js-sdk/src/logger";
import { ClientEvent, MatrixClient } from "matrix-js-sdk/src/client";
import { SyncState } from "matrix-js-sdk/src/sync";
import { useTranslation } from "react-i18next";
+import { MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession";
import { randomString } from "matrix-js-sdk/src/randomstring";
import type { Room } from "matrix-js-sdk/src/models/room";
import type { GroupCall } from "matrix-js-sdk/src/webrtc/groupCall";
import { setLocalStorageItem } from "../useLocalStorage";
import { isLocalRoomId, createRoom, roomNameFromRoomId } from "../matrix-utils";
-import { translatedError } from "../TranslatedError";
-import { widget } from "../widget";
import { useEnableE2EE } from "../settings/useSetting";
import { getRoomSharedKeyLocalStorageKey } from "../e2ee/sharedKeyManagement";
-const STATS_COLLECT_INTERVAL_TIME_MS = 10000;
-
export type GroupCallLoaded = {
kind: "loaded";
- groupCall: GroupCall;
+ rtcSession: MatrixRTCSession;
};
export type GroupCallLoadFailed = {
@@ -130,61 +121,12 @@ export const useLoadGroupCall = (
}
};
- const fetchOrCreateGroupCall = async (): Promise => {
+ const fetchOrCreateGroupCall = async (): Promise => {
const room = await fetchOrCreateRoom();
logger.debug(`Fetched / joined room ${roomIdOrAlias}`);
- let groupCall = client.getGroupCallForRoom(room.roomId);
- logger.debug("Got group call", groupCall?.groupCallId);
- if (groupCall) {
- groupCall.setGroupCallStatsInterval(STATS_COLLECT_INTERVAL_TIME_MS);
- return groupCall;
- }
-
- if (
- !widget &&
- room.currentState.mayClientSendStateEvent(
- EventType.GroupCallPrefix,
- client
- )
- ) {
- // The call doesn't exist, but we can create it
- console.log(
- `No call found in ${roomIdOrAlias}: creating ${
- createPtt ? "PTT" : "video"
- } call`
- );
- groupCall = await client.createGroupCall(
- room.roomId,
- createPtt ? GroupCallType.Voice : GroupCallType.Video,
- createPtt,
- GroupCallIntent.Room
- );
- groupCall.setGroupCallStatsInterval(STATS_COLLECT_INTERVAL_TIME_MS);
- return groupCall;
- }
-
- // We don't have permission to create the call, so all we can do is wait
- // for one to come in
- return new Promise((resolve, reject) => {
- const onGroupCallIncoming = (groupCall: GroupCall) => {
- if (groupCall?.room.roomId === room.roomId) {
- clearTimeout(timeout);
- groupCall.setGroupCallStatsInterval(STATS_COLLECT_INTERVAL_TIME_MS);
- client.off(
- GroupCallEventHandlerEvent.Incoming,
- onGroupCallIncoming
- );
- resolve(groupCall);
- }
- };
- client.on(GroupCallEventHandlerEvent.Incoming, onGroupCallIncoming);
-
- const timeout = setTimeout(() => {
- client.off(GroupCallEventHandlerEvent.Incoming, onGroupCallIncoming);
- reject(translatedError("Fetching group call timed out.", t));
- }, 30000);
- });
+ const rtcSession = client.matrixRTC.getRoomSession(room);
+ return rtcSession;
};
const waitForClientSyncing = async () => {
@@ -207,7 +149,7 @@ export const useLoadGroupCall = (
waitForClientSyncing()
.then(fetchOrCreateGroupCall)
- .then((groupCall) => setState({ kind: "loaded", groupCall }))
+ .then((rtcSession) => setState({ kind: "loaded", rtcSession }))
.catch((error) => setState({ kind: "failed", error }));
}, [client, roomIdOrAlias, viaServers, createPtt, t, e2eeEnabled]);
diff --git a/src/usePageFocusStyle.module.css b/src/room/useRoomName.ts
similarity index 51%
rename from src/usePageFocusStyle.module.css
rename to src/room/useRoomName.ts
index 7e92738a..575f7714 100644
--- a/src/usePageFocusStyle.module.css
+++ b/src/room/useRoomName.ts
@@ -1,11 +1,11 @@
/*
-Copyright 2022 New Vector Ltd
+Copyright 2023 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
-http://www.apache.org/licenses/LICENSE-2.0
+ http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,6 +14,14 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-.hideFocus * {
- outline: none !important;
+import { Room, RoomEvent } from "matrix-js-sdk/src/matrix";
+import { useState } from "react";
+
+import { useTypedEventEmitter } from "../useEvents";
+
+export function useRoomName(room: Room): string {
+ const [, setNumUpdates] = useState(0);
+ // Whenever the name changes, force an update
+ useTypedEventEmitter(room, RoomEvent.Name, () => setNumUpdates((n) => n + 1));
+ return room.name;
}
diff --git a/src/room/useSentryGroupCallHandler.ts b/src/room/useSentryGroupCallHandler.ts
deleted file mode 100644
index 188a2934..00000000
--- a/src/room/useSentryGroupCallHandler.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
-Copyright 2022 New Vector Ltd
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-import { useEffect } from "react";
-import * as Sentry from "@sentry/react";
-import { GroupCall, GroupCallEvent } from "matrix-js-sdk/src/webrtc/groupCall";
-import { CallEvent, MatrixCall } from "matrix-js-sdk/src/webrtc/call";
-
-export function useSentryGroupCallHandler(groupCall: GroupCall) {
- useEffect(() => {
- function onHangup(call: MatrixCall) {
- if (call.hangupReason === "ice_failed") {
- Sentry.captureException(new Error("Call hangup due to ICE failure."));
- }
- }
-
- function onError(error: Error) {
- Sentry.captureException(error);
- }
-
- if (groupCall) {
- groupCall.on(CallEvent.Hangup, onHangup);
- groupCall.on(GroupCallEvent.Error, onError);
- }
-
- return () => {
- if (groupCall) {
- groupCall.removeListener(CallEvent.Hangup, onHangup);
- groupCall.removeListener(GroupCallEvent.Error, onError);
- }
- };
- }, [groupCall]);
-}
diff --git a/src/rtcSessionHelpers.ts b/src/rtcSessionHelpers.ts
new file mode 100644
index 00000000..3d62f980
--- /dev/null
+++ b/src/rtcSessionHelpers.ts
@@ -0,0 +1,53 @@
+/*
+Copyright 2023 New Vector Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import { MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession";
+
+import { PosthogAnalytics } from "./analytics/PosthogAnalytics";
+import { LivekitFocus } from "./livekit/LivekitFocus";
+import { Config } from "./config/Config";
+
+function makeFocus(livekitAlias: string): LivekitFocus {
+ const urlFromConf = Config.get().livekit!.livekit_service_url;
+ if (!urlFromConf) {
+ throw new Error("No livekit_service_url is configured!");
+ }
+
+ return {
+ type: "livekit",
+ livekit_service_url: urlFromConf,
+ livekit_alias: livekitAlias,
+ };
+}
+
+export function enterRTCSession(rtcSession: MatrixRTCSession) {
+ PosthogAnalytics.instance.eventCallEnded.cacheStartCall(new Date());
+ PosthogAnalytics.instance.eventCallStarted.track(rtcSession.room.roomId);
+
+ // This must be called before we start trying to join the call, as we need to
+ // have started tracking by the time calls start getting created.
+ //groupCallOTelMembership?.onJoinCall();
+
+ // right now we asume everything is a room-scoped call
+ const livekitAlias = rtcSession.room.roomId;
+
+ rtcSession.joinRoomSession([makeFocus(livekitAlias)]);
+}
+
+export function leaveRTCSession(rtcSession: MatrixRTCSession) {
+ //groupCallOTelMembership?.onLeaveCall();
+ rtcSession.leaveRoomSession();
+}
diff --git a/src/settings/ProfileSettingsTab.tsx b/src/settings/ProfileSettingsTab.tsx
index e6a59634..4286a960 100644
--- a/src/settings/ProfileSettingsTab.tsx
+++ b/src/settings/ProfileSettingsTab.tsx
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { useCallback, useEffect, useRef } from "react";
+import { useCallback, useEffect, useMemo, useRef } from "react";
import { MatrixClient } from "matrix-js-sdk/src/client";
import { useTranslation } from "react-i18next";
@@ -29,6 +29,7 @@ interface Props {
export function ProfileSettingsTab({ client }: Props) {
const { t } = useTranslation();
const { error, displayName, avatarUrl, saveProfile } = useProfile(client);
+ const userId = useMemo(() => client.getUserId(), [client]);
const formRef = useRef(null);
@@ -77,12 +78,13 @@ export function ProfileSettingsTab({ client }: Props) {
return (