%(homeserverDomain)s
) to configure a TURN server in order for calls to work reliably.": "Požádejte správce svého homeserveru (%(homeserverDomain)s
) jestli by nemohl nakonfigurovat TURN server, aby volání fungovala spolehlivě.",
+ "Please ask the administrator of your homeserver (%(homeserverDomain)s
) to configure a TURN server in order for calls to work reliably.": "Požádejte správce svého domovského serveru (%(homeserverDomain)s
) jestli by nemohl nakonfigurovat TURN server, aby volání fungovala spolehlivě.",
"Alternatively, you can try to use the public server at turn.matrix.org
, but this will not be as reliable, and it will share your IP address with that server. You can also manage this in Settings.": "Můžete také zkusit použít veřejný server na adrese turn.matrix.org
, ale ten nebude tak spolehlivý a bude sdílet vaši IP adresu s tímto serverem. To můžete spravovat také v Nastavení.",
"Try using turn.matrix.org": "Zkuste použít turn.matrix.org",
"Messages": "Zprávy",
@@ -1441,7 +1441,7 @@
"Manually Verify by Text": "Manuální textové ověření",
"Interactively verify by Emoji": "Interaktivní ověření s emotikonami",
"Support adding custom themes": "Umožnit přidání vlastního vzhledu",
- "Manually verify all remote sessions": "Manuálně ověřit všechny relace",
+ "Manually verify all remote sessions": "Ručně ověřit všechny relace",
"cached locally": "uložen lokálně",
"not found locally": "nenalezen lolálně",
"Individually verify each session used by a user to mark it as trusted, not trusting cross-signed devices.": "Individuálně ověřit každou uživatelovu relaci a označit jí za důvěryhodnou, bez důvěry v křížový podpis.",
@@ -3635,5 +3635,34 @@
"Notifications silenced": "Oznámení ztlumena",
"Yes, stop broadcast": "Ano, zastavit vysílání",
"Are you sure you want to stop your live broadcast?This will end the broadcast and the full recording will be available in the room.": "Opravdu chcete ukončit živé vysílání? Tím se vysílání ukončí a v místnosti bude k dispozici celý záznam.",
- "Stop live broadcasting?": "Ukončit živé vysílání?"
+ "Stop live broadcasting?": "Ukončit živé vysílání?",
+ "Someone else is already recording a voice broadcast. Wait for their voice broadcast to end to start a new one.": "Hlasové vysílání už nahrává někdo jiný. Počkejte, až jeho hlasové vysílání skončí, a spusťte nové.",
+ "You don't have the required permissions to start a voice broadcast in this room. Contact a room administrator to upgrade your permissions.": "Nemáte potřebná oprávnění ke spuštění hlasového vysílání v této místnosti. Obraťte se na správce místnosti, aby vám zvýšil oprávnění.",
+ "You are already recording a voice broadcast. Please end your current voice broadcast to start a new one.": "Již nahráváte hlasové vysílání. Ukončete prosím aktuální hlasové vysílání a spusťte nové.",
+ "Can't start a new voice broadcast": "Nelze spustit nové hlasové vysílání",
+ "Completing set up of your new device": "Dokončování nastavení nového zařízení",
+ "Waiting for device to sign in": "Čekání na přihlášení zařízení",
+ "Connecting...": "Připojování...",
+ "Review and approve the sign in": "Zkontrolovat a schválit přihlášení",
+ "Select 'Scan QR code'": "Vyberte \"Naskenovat QR kód\"",
+ "Start at the sign in screen": "Začněte na přihlašovací obrazovce",
+ "Scan the QR code below with your device that's signed out.": "Níže uvedený QR kód naskenujte pomocí přihlašovaného zařízení.",
+ "By approving access for this device, it will have full access to your account.": "Schválením přístupu tohoto zařízení získá zařízení plný přístup k vašemu účtu.",
+ "Check that the code below matches with your other device:": "Zkontrolujte, zda se níže uvedený kód shoduje s vaším dalším zařízením:",
+ "Devices connected": "Zařízení byla propojena",
+ "The homeserver doesn't support signing in another device.": "Domovský server nepodporuje přihlášení pomocí jiného zařízení.",
+ "An unexpected error occurred.": "Došlo k neočekávané chybě.",
+ "The request was cancelled.": "Požadavek byl zrušen.",
+ "The other device isn't signed in.": "Druhé zařízení není přihlášeno.",
+ "The other device is already signed in.": "Druhé zařízení je již přihlášeno.",
+ "The request was declined on the other device.": "Požadavek byl na druhém zařízení odmítnut.",
+ "Linking with this device is not supported.": "Propojení s tímto zařízením není podporováno.",
+ "The scanned code is invalid.": "Naskenovaný kód je neplatný.",
+ "The linking wasn't completed in the required time.": "Propojení nebylo dokončeno v požadovaném čase.",
+ "Sign in new device": "Přihlásit nové zařízení",
+ "Show QR code": "Zobrazit QR kód",
+ "You can use this device to sign in a new device with a QR code. You will need to scan the QR code shown on this device with your device that's signed out.": "Toto zařízení můžete použít k přihlášení nového zařízení pomocí QR kódu. QR kód zobrazený na tomto zařízení musíte naskenovat pomocí odhlášeného zařízení.",
+ "Sign in with QR code": "Přihlásit se pomocí QR kódu",
+ "Browser": "Prohlížeč",
+ "Allow a QR code to be shown in session manager to sign in another device (requires compatible homeserver)": "Povolit zobrazení QR kódu ve správci relací pro přihlášení do jiného zařízení (vyžaduje kompatibilní domovský server)"
}
diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json
index 5b07a37cec..60586e4088 100644
--- a/src/i18n/strings/de_DE.json
+++ b/src/i18n/strings/de_DE.json
@@ -919,7 +919,7 @@
"Only continue if you trust the owner of the server.": "Fahre nur fort, wenn du den Server-Betreibenden vertraust.",
"Trust": "Vertrauen",
"Custom (%(level)s)": "Benutzerdefiniert (%(level)s)",
- "Sends a message as plain text, without interpreting it as markdown": "Verschickt eine Nachricht in Rohtext, ohne sie als Markdown darzustellen",
+ "Sends a message as plain text, without interpreting it as markdown": "Sendet eine Nachricht als Klartext, ohne sie als Markdown darzustellen",
"Use an identity server to invite by email. Manage in Settings.": "Verwende einen Identitäts-Server, um per E-Mail einladen zu können. Lege einen in den Einstellungen fest.",
"%(name)s (%(userId)s)": "%(name)s (%(userId)s)",
"Try out new ways to ignore people (experimental)": "Verwende neue Möglichkeiten, Menschen zu blockieren",
@@ -1166,7 +1166,7 @@
"%(creator)s created and configured the room.": "%(creator)s hat den Raum erstellt und konfiguriert.",
"Keep a copy of it somewhere secure, like a password manager or even a safe.": "Bewahre eine Kopie an einem sicheren Ort, wie einem Passwort-Manager oder in einem Safe auf.",
"Copy": "Kopieren",
- "Sends a message as html, without interpreting it as markdown": "Verschickt eine Nachricht im HTML-Format, ohne sie als Markdown zu darzustellen",
+ "Sends a message as html, without interpreting it as markdown": "Sendet eine Nachricht als HTML, ohne sie als Markdown darzustellen",
"Show rooms with unread notifications first": "Zeige Räume mit ungelesenen Benachrichtigungen zuerst an",
"Show shortcuts to recently viewed rooms above the room list": "Kürzlich besuchte Räume anzeigen",
"Use Single Sign On to continue": "Einmalanmeldung zum Fortfahren nutzen",
@@ -3624,11 +3624,40 @@
"resume voice broadcast": "Sprachübertragung fortsetzen",
"Italic": "Kursiv",
"Underline": "Unterstrichen",
- "Try out the rich text editor (plain text mode coming soon)": "Probiere den Rich-Text-Editor aus (bald auch mit Plain-Text-Modus)",
+ "Try out the rich text editor (plain text mode coming soon)": "Probiere den Textverarbeitungs-Editor (bald auch mit Klartext-Modus)",
"You have already joined this call from another device": "Du nimmst an diesem Anruf bereits mit einem anderen Gerät teil",
"stop voice broadcast": "Sprachübertragung beenden",
"Notifications silenced": "Benachrichtigungen stummgeschaltet",
"Are you sure you want to stop your live broadcast?This will end the broadcast and the full recording will be available in the room.": "Willst du die Sprachübertragung wirklich beenden? Damit endet auch die Aufnahme.",
"Yes, stop broadcast": "Ja, Sprachübertragung beenden",
- "Stop live broadcasting?": "Sprachübertragung beenden?"
+ "Stop live broadcasting?": "Sprachübertragung beenden?",
+ "Sign in with QR code": "Mit QR-Code anmelden",
+ "Browser": "Browser",
+ "Allow a QR code to be shown in session manager to sign in another device (requires compatible homeserver)": "Erlaube es andere Geräte mittels QR-Code in der Sitzungsverwaltung anzumelden (kompatibler Heim-Server benötigt)",
+ "Completing set up of your new device": "Schließe Anmeldung deines neuen Gerätes ab",
+ "Waiting for device to sign in": "Warte auf Anmeldung des Gerätes",
+ "Connecting...": "Verbinde …",
+ "Review and approve the sign in": "Überprüfe und genehmige die Anmeldung",
+ "Select 'Scan QR code'": "Wähle „QR-Code einlesen“",
+ "Start at the sign in screen": "Beginne auf dem Anmeldebildschirm",
+ "Scan the QR code below with your device that's signed out.": "Lese den folgenden QR-Code mit deinem nicht angemeldeten Gerät ein.",
+ "By approving access for this device, it will have full access to your account.": "Indem du den Zugriff dieses Gerätes bestätigst, erhält es vollen Zugang zu deinem Account.",
+ "Check that the code below matches with your other device:": "Überprüfe, dass der unten angezeigte Code mit deinem anderen Gerät übereinstimmt:",
+ "Devices connected": "Geräte verbunden",
+ "The homeserver doesn't support signing in another device.": "Der Heim-Server unterstützt die Anmeldung eines anderen Gerätes nicht.",
+ "An unexpected error occurred.": "Ein unerwarteter Fehler ist aufgetreten.",
+ "The request was cancelled.": "Die Anfrage wurde abgebrochen.",
+ "The other device isn't signed in.": "Das andere Gerät ist nicht angemeldet.",
+ "The other device is already signed in.": "Das andere Gerät ist bereits angemeldet.",
+ "The request was declined on the other device.": "Die Anfrage wurde auf dem anderen Gerät abgelehnt.",
+ "Linking with this device is not supported.": "Die Verbindung mit diesem Gerät wird nicht unterstützt.",
+ "The scanned code is invalid.": "Der gescannte Code ist ungültig.",
+ "The linking wasn't completed in the required time.": "Die Verbindung konnte nicht in der erforderlichen Zeit hergestellt werden.",
+ "Sign in new device": "Neues Gerät anmelden",
+ "Show QR code": "QR-Code anzeigen",
+ "Someone else is already recording a voice broadcast. Wait for their voice broadcast to end to start a new one.": "Jemand anderes nimmt bereits eine Sprachübertragung auf. Warte auf das Ende der Übertragung, bevor du eine neue startest.",
+ "You don't have the required permissions to start a voice broadcast in this room. Contact a room administrator to upgrade your permissions.": "Du hast nicht die nötigen Berechtigungen, um eine Sprachübertragung in diesem Raum zu starten. Kontaktiere einen Raumadministrator, um deine Berechtigungen anzupassen.",
+ "You are already recording a voice broadcast. Please end your current voice broadcast to start a new one.": "Du zeichnest bereits eine Sprachübertragung auf. Bitte beende die laufende Übertragung, um eine neue zu beginnen.",
+ "Can't start a new voice broadcast": "Sprachübertragung kann nicht gestartet werden",
+ "You can use this device to sign in a new device with a QR code. You will need to scan the QR code shown on this device with your device that's signed out.": "Du kannst dieses Gerät verwenden, um ein neues Gerät per QR-Code anzumelden. Dazu musst du den auf diesem Gerät angezeigten QR-Code mit deinem nicht angemeldeten Gerät einlesen."
}
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index f322c5de8d..f40e165804 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -644,10 +644,10 @@
"Stop live broadcasting?": "Stop live broadcasting?",
"Are you sure you want to stop your live broadcast?This will end the broadcast and the full recording will be available in the room.": "Are you sure you want to stop your live broadcast?This will end the broadcast and the full recording will be available in the room.",
"Yes, stop broadcast": "Yes, stop broadcast",
- "Live": "Live",
- "pause voice broadcast": "pause voice broadcast",
+ "play voice broadcast": "play voice broadcast",
"resume voice broadcast": "resume voice broadcast",
- "stop voice broadcast": "stop voice broadcast",
+ "pause voice broadcast": "pause voice broadcast",
+ "Live": "Live",
"Voice broadcast": "Voice broadcast",
"Cannot reach homeserver": "Cannot reach homeserver",
"Ensure you have a stable internet connection, or get in touch with the server admin": "Ensure you have a stable internet connection, or get in touch with the server admin",
diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json
index f6a6e49b25..fabcc93019 100644
--- a/src/i18n/strings/et.json
+++ b/src/i18n/strings/et.json
@@ -3631,5 +3631,37 @@
"New session manager": "Uus sessioonihaldur",
"Use new session manager": "Kasuta uut sessioonihaldurit",
"Try out the rich text editor (plain text mode coming soon)": "Proovi vormindatud teksti alusel töötavat tekstitoimetit (varsti lisandub ka vormindamata teksti režiim)",
- "Notifications silenced": "Teavitused on summutatud"
+ "Notifications silenced": "Teavitused on summutatud",
+ "Completing set up of your new device": "Lõpetame uue seadme seadistamise",
+ "Waiting for device to sign in": "Ootame, et teine seade logiks võrku",
+ "Connecting...": "Ühendamisel…",
+ "Review and approve the sign in": "Vaata üle ja kinnita sisselogimine Matrixi'i võrku",
+ "Select 'Scan QR code'": "Vali „Loe QR-koodi“",
+ "Start at the sign in screen": "Alusta sisselogimisvaatest",
+ "Scan the QR code below with your device that's signed out.": "Loe QR-koodi seadmega, kus sa oled Matrix'i võrgust välja loginud.",
+ "By approving access for this device, it will have full access to your account.": "Lubades ligipääsu sellele seadmele, annad talle ka täismahulise ligipääsu oma kasutajakontole.",
+ "Check that the code below matches with your other device:": "Kontrolli, et järgnev kood klapib teises seadmes kuvatava koodiga:",
+ "Devices connected": "Seadmed on ühendatud",
+ "The homeserver doesn't support signing in another device.": "Koduserver ei toeta muude seadmete võrku logimise võimalust.",
+ "An unexpected error occurred.": "Tekkis teadmata viga.",
+ "The request was cancelled.": "Päring katkestati.",
+ "The other device isn't signed in.": "Teine seade ei ole võrku loginud.",
+ "The other device is already signed in.": "Teine seade on juba võrku loginud.",
+ "The request was declined on the other device.": "Teine seade lükkas päringu tagasi.",
+ "Linking with this device is not supported.": "Sidumine selle seadmega ei ole toetatud.",
+ "The scanned code is invalid.": "Skaneeritud QR-kood on vigane.",
+ "The linking wasn't completed in the required time.": "Sidumine ei lõppenud etteantud aja jooksul.",
+ "Sign in new device": "Logi sisse uus seade",
+ "Show QR code": "Näita QR-koodi",
+ "Sign in with QR code": "Logi sisse QR-koodi abil",
+ "Browser": "Brauser",
+ "You can use this device to sign in a new device with a QR code. You will need to scan the QR code shown on this device with your device that's signed out.": "Sa saad kasutada seda seadet mõne muu seadme logimiseks Matrix'i võrku QR-koodi alusel. Selleks skaneeri võrgust väljalogitud seadmega seda QR-koodi.",
+ "Allow a QR code to be shown in session manager to sign in another device (requires compatible homeserver)": "Teise seadme sisselogimiseks luba QR-koodi kuvamine sessioonihalduris (eeldab, et koduserver sellist võimalust toetab)",
+ "Yes, stop broadcast": "Jah, lõpeta",
+ "Are you sure you want to stop your live broadcast?This will end the broadcast and the full recording will be available in the room.": "Kas sa oled kindel, et soovid otseeetri lõpetada? Sellega ringhäälingukõne salvestamine lõppeb ja salvestis on kättesaadav kõigile jututoas.",
+ "Stop live broadcasting?": "Kas lõpetame otseeetri?",
+ "Someone else is already recording a voice broadcast. Wait for their voice broadcast to end to start a new one.": "Keegi juba salvestab ringhäälingukõnet. Uue ringhäälingukõne salvestamiseks palun oota, kuni see teine ringhäälingukõne on lõppenud.",
+ "You don't have the required permissions to start a voice broadcast in this room. Contact a room administrator to upgrade your permissions.": "Sul pole piisavalt õigusi selles jututoas ringhäälingukõne algatamiseks. Õiguste lisamiseks palun võta ühendust jututoa haldajaga.",
+ "You are already recording a voice broadcast. Please end your current voice broadcast to start a new one.": "Sa juba salvestad ringhäälingukõnet. Uue alustamiseks palun lõpeta eelmine salvestus.",
+ "Can't start a new voice broadcast": "Uue ringhäälingukõne alustamine pole võimalik"
}
diff --git a/src/i18n/strings/hu.json b/src/i18n/strings/hu.json
index bba23baba9..de6d822e02 100644
--- a/src/i18n/strings/hu.json
+++ b/src/i18n/strings/hu.json
@@ -3631,5 +3631,33 @@
"You do not have sufficient permissions to change this.": "Nincs megfelelő jogosultság a megváltoztatáshoz.",
"%(brand)s is end-to-end encrypted, but is currently limited to smaller numbers of users.": "%(brand)s végpontok között titkosított de jelenleg csak kevés számú résztvevővel működik.",
"Enable %(brand)s as an additional calling option in this room": "%(brand)s engedélyezése mint további opció hívásokhoz a szobában",
- "Notifications silenced": "Értesítések elnémítva"
+ "Notifications silenced": "Értesítések elnémítva",
+ "Stop live broadcasting?": "Megszakítja az élő közvetítést?",
+ "Someone else is already recording a voice broadcast. Wait for their voice broadcast to end to start a new one.": "Valaki már elindított egy hang közvetítést. Várja meg a közvetítés végét az új indításához.",
+ "You don't have the required permissions to start a voice broadcast in this room. Contact a room administrator to upgrade your permissions.": "Nincs jogosultsága hang közvetítést indítani ebben a szobában. Vegye fel a kapcsolatot a szoba adminisztrátorával a szükséges jogosultság megszerzéséhez.",
+ "You are already recording a voice broadcast. Please end your current voice broadcast to start a new one.": "Egy hang közvetítés már folyamatban van. Először fejezze be a jelenlegi közvetítést egy új indításához.",
+ "Can't start a new voice broadcast": "Az új hang közvetítés nem indítható el",
+ "Completing set up of your new device": "Új eszköz beállításának elvégzése",
+ "Waiting for device to sign in": "Várakozás a másik eszköz bejelentkezésére",
+ "Connecting...": "Kapcsolás…",
+ "Select 'Scan QR code'": "Válassza ezt: „QR kód beolvasása”",
+ "Start at the sign in screen": "Kezdje a bejelentkező képernyőn",
+ "Scan the QR code below with your device that's signed out.": "A kijelentkezett eszközzel olvasd be a QR kódot alább.",
+ "By approving access for this device, it will have full access to your account.": "Ennek az eszköznek a hozzáférés engedélyezése után az eszköznek teljes hozzáférése lesz a fiókjához.",
+ "Check that the code below matches with your other device:": "Ellenőrizze, hogy az alábbi kód megegyezik a másik eszközödön lévővel:",
+ "Devices connected": "Összekötött eszközök",
+ "The homeserver doesn't support signing in another device.": "A matrix szerver nem támogatja más eszköz bejelentkeztetését.",
+ "An unexpected error occurred.": "Nemvárt hiba történt.",
+ "The request was cancelled.": "A kérés megszakítva.",
+ "The other device isn't signed in.": "A másik eszköz még nincs bejelentkezve.",
+ "The other device is already signed in.": "A másik eszköz már bejelentkezett.",
+ "The request was declined on the other device.": "A kérést elutasították a másik eszközön.",
+ "Linking with this device is not supported.": "Összekötés ezzel az eszközzel nem támogatott.",
+ "The scanned code is invalid.": "A beolvasott kód érvénytelen.",
+ "The linking wasn't completed in the required time.": "Az összekötés az elvárt időn belül nem fejeződött be.",
+ "Sign in new device": "Új eszköz bejelentkeztetése",
+ "Show QR code": "QR kód beolvasása",
+ "Sign in with QR code": "Belépés QR kóddal",
+ "Browser": "Böngésző",
+ "Yes, stop broadcast": "Igen, közvetítés megállítása"
}
diff --git a/src/i18n/strings/it.json b/src/i18n/strings/it.json
index 08ea1f9234..6c4c692e65 100644
--- a/src/i18n/strings/it.json
+++ b/src/i18n/strings/it.json
@@ -2267,8 +2267,8 @@
"Value": "Valore",
"Setting ID": "ID impostazione",
"Show chat effects (animations when receiving e.g. confetti)": "Mostra effetti chat (animazioni quando si ricevono ad es. coriandoli)",
- "Original event source": "Fonte dell'evento originale",
- "Decrypted event source": "Fonte dell'evento decifrato",
+ "Original event source": "Sorgente dell'evento originale",
+ "Decrypted event source": "Sorgente dell'evento decifrato",
"Inviting...": "Invito...",
"Invite by username": "Invita per nome utente",
"Invite your teammates": "Invita la tua squadra",
@@ -3635,5 +3635,8 @@
"stop voice broadcast": "ferma broadcast voce",
"Yes, stop broadcast": "Sì, ferma il broadcast",
"Are you sure you want to stop your live broadcast?This will end the broadcast and the full recording will be available in the room.": "Vuoi davvero fermare il tuo broadcast in diretta? Verrà terminato il broadcast e la registrazione completa sarà disponibile nella stanza.",
- "Stop live broadcasting?": "Fermare il broadcast in diretta?"
+ "Stop live broadcasting?": "Fermare il broadcast in diretta?",
+ "You don't have the required permissions to start a voice broadcast in this room. Contact a room administrator to upgrade your permissions.": "Non hai l'autorizzazione necessaria per iniziare un broadcast vocale in questa stanza. Contatta un amministratore della stanza per aggiornare le tue autorizzazioni.",
+ "You are already recording a voice broadcast. Please end your current voice broadcast to start a new one.": "Stai già registrando un broadcast vocale. Termina quello in corso per iniziarne uno nuovo.",
+ "Can't start a new voice broadcast": "Impossibile iniziare un nuovo broadcast vocale"
}
diff --git a/src/i18n/strings/sk.json b/src/i18n/strings/sk.json
index 0a7596d94e..dd4555caf6 100644
--- a/src/i18n/strings/sk.json
+++ b/src/i18n/strings/sk.json
@@ -3632,5 +3632,37 @@
"stop voice broadcast": "zastaviť hlasové vysielanie",
"resume voice broadcast": "obnoviť hlasové vysielanie",
"pause voice broadcast": "pozastaviť hlasové vysielanie",
- "Notifications silenced": "Oznámenia stlmené"
+ "Notifications silenced": "Oznámenia stlmené",
+ "Completing set up of your new device": "Dokončenie nastavenia nového zariadenia",
+ "Waiting for device to sign in": "Čaká sa na prihlásenie zariadenia",
+ "Connecting...": "Pripájanie…",
+ "Review and approve the sign in": "Skontrolujte a schváľte prihlásenie",
+ "Select 'Scan QR code'": "Vyberte možnosť \"Skenovať QR kód\"",
+ "Start at the sign in screen": "Začnite na prihlasovacej obrazovke",
+ "Scan the QR code below with your device that's signed out.": "Naskenujte nižšie uvedený QR kód pomocou zariadenia, ktoré je odhlásené.",
+ "By approving access for this device, it will have full access to your account.": "Schválením prístupu pre toto zariadenie bude mať plný prístup k vášmu účtu.",
+ "Check that the code below matches with your other device:": "Skontrolujte, či sa nižšie uvedený kód zhoduje s vaším druhým zariadením:",
+ "Devices connected": "Zariadenia pripojené",
+ "The homeserver doesn't support signing in another device.": "Domovský server nepodporuje prihlasovanie do iného zariadenia.",
+ "An unexpected error occurred.": "Vyskytla sa neočakávaná chyba.",
+ "The request was cancelled.": "Žiadosť bola zrušená.",
+ "The other device isn't signed in.": "Druhé zariadenie nie je prihlásené.",
+ "The other device is already signed in.": "Druhé zariadenie je už prihlásené.",
+ "The request was declined on the other device.": "Žiadosť bola na druhom zariadení zamietnutá.",
+ "Linking with this device is not supported.": "Prepojenie s týmto zariadením nie je podporované.",
+ "The scanned code is invalid.": "Naskenovaný kód je neplatný.",
+ "The linking wasn't completed in the required time.": "Prepojenie nebolo dokončené v požadovanom čase.",
+ "Sign in new device": "Prihlásiť nové zariadenie",
+ "Show QR code": "Zobraziť QR kód",
+ "You can use this device to sign in a new device with a QR code. You will need to scan the QR code shown on this device with your device that's signed out.": "Toto zariadenie môžete použiť na prihlásenie nového zariadenia pomocou QR kódu. QR kód zobrazený na tomto zariadení musíte naskenovať pomocou zariadenia, ktoré je odhlásené.",
+ "Sign in with QR code": "Prihlásiť sa pomocou QR kódu",
+ "Browser": "Prehliadač",
+ "Allow a QR code to be shown in session manager to sign in another device (requires compatible homeserver)": "Umožniť zobrazenie QR kódu v správcovi relácií na prihlásenie do iného zariadenia (vyžaduje kompatibilný domovský server)",
+ "Yes, stop broadcast": "Áno, zastaviť vysielanie",
+ "Are you sure you want to stop your live broadcast?This will end the broadcast and the full recording will be available in the room.": "Určite chcete zastaviť vaše vysielanie naživo? Tým sa vysielanie ukončí a v miestnosti bude k dispozícii celý záznam.",
+ "Stop live broadcasting?": "Zastaviť vysielanie naživo?",
+ "Someone else is already recording a voice broadcast. Wait for their voice broadcast to end to start a new one.": "Niekto iný už nahráva hlasové vysielanie. Počkajte, kým sa skončí jeho hlasové vysielanie, a potom spustite nové.",
+ "You don't have the required permissions to start a voice broadcast in this room. Contact a room administrator to upgrade your permissions.": "Nemáte požadované oprávnenia na spustenie hlasového vysielania v tejto miestnosti. Obráťte sa na správcu miestnosti, aby vám rozšíril oprávnenia.",
+ "You are already recording a voice broadcast. Please end your current voice broadcast to start a new one.": "Už nahrávate hlasové vysielanie. Ukončite aktuálne hlasové vysielanie a spustite nové.",
+ "Can't start a new voice broadcast": "Nemôžete spustiť nové hlasové vysielanie"
}
diff --git a/src/i18n/strings/uk.json b/src/i18n/strings/uk.json
index 04b1c056e9..0d2adc0ad8 100644
--- a/src/i18n/strings/uk.json
+++ b/src/i18n/strings/uk.json
@@ -3632,5 +3632,37 @@
"pause voice broadcast": "призупинити голосове мовлення",
"You have already joined this call from another device": "Ви вже приєдналися до цього виклику з іншого пристрою",
"stop voice broadcast": "припинити голосове мовлення",
- "Notifications silenced": "Сповіщення стишено"
+ "Notifications silenced": "Сповіщення стишено",
+ "Sign in with QR code": "Увійти за допомогою QR-коду",
+ "Browser": "Браузер",
+ "Allow a QR code to be shown in session manager to sign in another device (requires compatible homeserver)": "Дозволити показ QR-коду в менеджері сеансів для входу на іншому пристрої (потрібен сумісний домашній сервер)",
+ "Yes, stop broadcast": "Так, припинити мовлення",
+ "Are you sure you want to stop your live broadcast?This will end the broadcast and the full recording will be available in the room.": "Ви впевнені, що хочете припинити голосове мовлення? На цьому трансляція завершиться, і повний запис буде доступний у кімнаті.",
+ "Stop live broadcasting?": "Припинити голосове мовлення?",
+ "Someone else is already recording a voice broadcast. Wait for their voice broadcast to end to start a new one.": "Хтось інший вже записує голосову трансляцію. Зачекайте, поки вона завершиться, щоб почати нову.",
+ "You don't have the required permissions to start a voice broadcast in this room. Contact a room administrator to upgrade your permissions.": "Ви не маєте необхідних дозволів для початку голосового мовлення в цій кімнаті. Зверніться до адміністратора кімнати, щоб оновити ваші дозволи.",
+ "You are already recording a voice broadcast. Please end your current voice broadcast to start a new one.": "Ви вже записуєте голосову трансляцію. Завершіть поточну трансляцію, щоб розпочати нову.",
+ "Can't start a new voice broadcast": "Не вдалося розпочати нову голосове мовлення",
+ "Completing set up of your new device": "Завершення налаштування нового пристрою",
+ "Waiting for device to sign in": "Очікування входу з пристрою",
+ "Connecting...": "З'єднання...",
+ "Review and approve the sign in": "Розглянути та схвалити вхід",
+ "Select 'Scan QR code'": "Виберіть «Сканувати QR-код»",
+ "Start at the sign in screen": "Почніть з екрана входу",
+ "Scan the QR code below with your device that's signed out.": "Скануйте QR-код знизу своїм пристроєм, на якому ви вийшли.",
+ "By approving access for this device, it will have full access to your account.": "Затвердивши доступ для цього пристрою, ви надасте йому повний доступ до вашого облікового запису.",
+ "Check that the code below matches with your other device:": "Перевірте, чи збігається наведений внизу код з кодом на вашому іншому пристрої:",
+ "Devices connected": "Пристрої під'єднано",
+ "The homeserver doesn't support signing in another device.": "Домашній сервер не підтримує вхід на іншому пристрої.",
+ "An unexpected error occurred.": "Виникла непередбачувана помилка.",
+ "The request was cancelled.": "Запит було скасовано.",
+ "The other device isn't signed in.": "На іншому пристрої вхід не виконано.",
+ "The other device is already signed in.": "На іншому пристрої вхід було виконано.",
+ "The request was declined on the other device.": "На іншому пристрої запит відхилено.",
+ "Linking with this device is not supported.": "Зв'язок з цим пристроєм не підтримується.",
+ "The scanned code is invalid.": "Сканований код недійсний.",
+ "The linking wasn't completed in the required time.": "У встановлені терміни з'єднання не було виконано.",
+ "Sign in new device": "Увійти на новому пристрої",
+ "Show QR code": "Показати QR-код",
+ "You can use this device to sign in a new device with a QR code. You will need to scan the QR code shown on this device with your device that's signed out.": "Ви можете використовувати цей пристрій для входу на новому пристрої за допомогою QR-коду. Вам потрібно буде сканувати QR-код, показаний на цьому пристрої, своїм пристроєм, на якому ви вийшли."
}
diff --git a/src/models/Call.ts b/src/models/Call.ts
index fd207cf1be..ed9e227d24 100644
--- a/src/models/Call.ts
+++ b/src/models/Call.ts
@@ -43,6 +43,8 @@ import { WidgetMessagingStore, WidgetMessagingStoreEvent } from "../stores/widge
import ActiveWidgetStore, { ActiveWidgetStoreEvent } from "../stores/ActiveWidgetStore";
import PlatformPeg from "../PlatformPeg";
import { getCurrentLanguage } from "../languageHandler";
+import DesktopCapturerSourcePicker from "../components/views/elements/DesktopCapturerSourcePicker";
+import Modal from "../Modal";
const TIMEOUT_MS = 16000;
@@ -639,10 +641,6 @@ export class ElementCall extends Call {
baseUrl: client.baseUrl,
lang: getCurrentLanguage().replace("_", "-"),
});
- // Currently, the screen-sharing support is the same is it is for Jitsi
- if (!PlatformPeg.get().supportsJitsiScreensharing()) {
- params.append("hideScreensharing", "");
- }
url.hash = `#?${params.toString()}`;
// To use Element Call without touching room state, we create a virtual
@@ -818,6 +816,7 @@ export class ElementCall extends Call {
this.messaging!.on(`action:${ElementWidgetActions.HangupCall}`, this.onHangup);
this.messaging!.on(`action:${ElementWidgetActions.TileLayout}`, this.onTileLayout);
this.messaging!.on(`action:${ElementWidgetActions.SpotlightLayout}`, this.onSpotlightLayout);
+ this.messaging!.on(`action:${ElementWidgetActions.Screenshare}`, this.onScreenshare);
}
protected async performDisconnection(): Promise+ You are already recording a voice broadcast. Please end your current voice broadcast to start a new one. +
, + "hasCloseButton": true, + "title": "Can't start a new voice broadcast", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + ], +} +`; + +exports[`startNewVoiceBroadcastRecording when the current user is allowed to send voice broadcast info state events when there is already a current voice broadcast should show an info dialog 1`] = ` [MockFunction] { "calls": Array [ Array [ diff --git a/test/voice-broadcast/utils/findRoomLiveVoiceBroadcastFromUserAndDevice-test.ts b/test/voice-broadcast/utils/findRoomLiveVoiceBroadcastFromUserAndDevice-test.ts new file mode 100644 index 0000000000..0fa04963ae --- /dev/null +++ b/test/voice-broadcast/utils/findRoomLiveVoiceBroadcastFromUserAndDevice-test.ts @@ -0,0 +1,127 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +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 { mocked } from "jest-mock"; +import { MatrixClient, MatrixEvent, Room } from "matrix-js-sdk/src/matrix"; + +import { + findRoomLiveVoiceBroadcastFromUserAndDevice, + VoiceBroadcastInfoEventType, + VoiceBroadcastInfoState, +} from "../../../src/voice-broadcast"; +import { mkEvent, stubClient } from "../../test-utils"; +import { mkVoiceBroadcastInfoStateEvent } from "./test-utils"; + +describe("findRoomLiveVoiceBroadcastFromUserAndDevice", () => { + const roomId = "!room:example.com"; + let client: MatrixClient; + let room: Room; + + const itShouldReturnNull = () => { + it("should return null", () => { + expect(findRoomLiveVoiceBroadcastFromUserAndDevice( + room, + client.getUserId(), + client.getDeviceId(), + )).toBeNull(); + }); + }; + + beforeAll(() => { + client = stubClient(); + room = new Room(roomId, client, client.getUserId()); + jest.spyOn(room.currentState, "getStateEvents"); + mocked(client.getRoom).mockImplementation((getRoomId: string) => { + if (getRoomId === roomId) return room; + }); + }); + + describe("when there is no info event", () => { + itShouldReturnNull(); + }); + + describe("when there is an info event without content", () => { + beforeEach(() => { + room.currentState.setStateEvents([ + mkEvent({ + event: true, + type: VoiceBroadcastInfoEventType, + room: roomId, + user: client.getUserId(), + content: {}, + }), + ]); + }); + + itShouldReturnNull(); + }); + + describe("when there is a stopped info event", () => { + beforeEach(() => { + room.currentState.setStateEvents([ + mkVoiceBroadcastInfoStateEvent( + roomId, + VoiceBroadcastInfoState.Stopped, + client.getUserId(), + client.getDeviceId(), + ), + ]); + }); + + itShouldReturnNull(); + }); + + describe("when there is a started info event from another device", () => { + beforeEach(() => { + const event = mkVoiceBroadcastInfoStateEvent( + roomId, + VoiceBroadcastInfoState.Stopped, + client.getUserId(), + "JKL123", + ); + room.currentState.setStateEvents([event]); + }); + + itShouldReturnNull(); + }); + + describe("when there is a started info event", () => { + let event: MatrixEvent; + + beforeEach(() => { + event = mkVoiceBroadcastInfoStateEvent( + roomId, + VoiceBroadcastInfoState.Started, + client.getUserId(), + client.getDeviceId(), + ); + room.currentState.setStateEvents([event]); + }); + + it("should return this event", () => { + expect(room.currentState.getStateEvents).toHaveBeenCalledWith( + VoiceBroadcastInfoEventType, + client.getUserId(), + ); + + expect(findRoomLiveVoiceBroadcastFromUserAndDevice( + room, + client.getUserId(), + client.getDeviceId(), + )).toBe(event); + }); + }); +}); diff --git a/test/voice-broadcast/utils/getChunkLength-test.ts b/test/voice-broadcast/utils/getChunkLength-test.ts new file mode 100644 index 0000000000..c2d761c18b --- /dev/null +++ b/test/voice-broadcast/utils/getChunkLength-test.ts @@ -0,0 +1,60 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +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 { mocked } from "jest-mock"; + +import SdkConfig, { DEFAULTS } from "../../../src/SdkConfig"; +import { getChunkLength } from "../../../src/voice-broadcast/utils/getChunkLength"; + +jest.mock("../../../src/SdkConfig"); + +describe("getChunkLength", () => { + afterEach(() => { + jest.resetAllMocks(); + }); + + describe("when there is a value provided by Sdk config", () => { + beforeEach(() => { + mocked(SdkConfig.get).mockReturnValue({ chunk_length: 42 }); + }); + + it("should return this value", () => { + expect(getChunkLength()).toBe(42); + }); + }); + + describe("when Sdk config does not provide a value", () => { + beforeEach(() => { + DEFAULTS.voice_broadcast = { + chunk_length: 23, + }; + }); + + it("should return this value", () => { + expect(getChunkLength()).toBe(23); + }); + }); + + describe("if there are no defaults", () => { + beforeEach(() => { + DEFAULTS.voice_broadcast = undefined; + }); + + it("should return the fallback value", () => { + expect(getChunkLength()).toBe(120); + }); + }); +}); diff --git a/test/voice-broadcast/utils/hasRoomLiveVoiceBroadcast-test.ts b/test/voice-broadcast/utils/hasRoomLiveVoiceBroadcast-test.ts index c9fbc5f09e..40b50ec883 100644 --- a/test/voice-broadcast/utils/hasRoomLiveVoiceBroadcast-test.ts +++ b/test/voice-broadcast/utils/hasRoomLiveVoiceBroadcast-test.ts @@ -35,7 +35,12 @@ describe("hasRoomLiveVoiceBroadcast", () => { sender: string, ) => { room.currentState.setStateEvents([ - mkVoiceBroadcastInfoStateEvent(room.roomId, state, sender), + mkVoiceBroadcastInfoStateEvent( + room.roomId, + state, + sender, + "ASD123", + ), ]); }; diff --git a/test/voice-broadcast/utils/resumeVoiceBroadcastInRoom-test.ts b/test/voice-broadcast/utils/resumeVoiceBroadcastInRoom-test.ts new file mode 100644 index 0000000000..8d435fb62e --- /dev/null +++ b/test/voice-broadcast/utils/resumeVoiceBroadcastInRoom-test.ts @@ -0,0 +1,110 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +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 { mocked } from "jest-mock"; +import { MatrixClient, MatrixEvent, Room } from "matrix-js-sdk/src/matrix"; + +import { + resumeVoiceBroadcastInRoom, + VoiceBroadcastInfoState, + VoiceBroadcastRecording, + VoiceBroadcastRecordingsStore, +} from "../../../src/voice-broadcast"; +import { stubClient } from "../../test-utils"; +import { mkVoiceBroadcastInfoStateEvent } from "../utils/test-utils"; + +const mockRecording = jest.fn(); + +jest.mock("../../../src/voice-broadcast/models/VoiceBroadcastRecording", () => ({ + ...jest.requireActual("../../../src/voice-broadcast/models/VoiceBroadcastRecording") as object, + VoiceBroadcastRecording: jest.fn().mockImplementation(() => mockRecording), +})); + +describe("resumeVoiceBroadcastInRoom", () => { + let client: MatrixClient; + const roomId = "!room:example.com"; + let room: Room; + let startedInfoEvent: MatrixEvent; + let stoppedInfoEvent: MatrixEvent; + + const itShouldStartAPausedRecording = () => { + it("should start a paused recording", () => { + expect(VoiceBroadcastRecording).toHaveBeenCalledWith( + startedInfoEvent, + client, + VoiceBroadcastInfoState.Paused, + ); + expect(VoiceBroadcastRecordingsStore.instance().setCurrent).toHaveBeenCalledWith(mockRecording); + }); + }; + + beforeEach(() => { + client = stubClient(); + room = new Room(roomId, client, client.getUserId()); + jest.spyOn(room, "findEventById"); + jest.spyOn(VoiceBroadcastRecordingsStore.instance(), "setCurrent").mockImplementation(); + + startedInfoEvent = mkVoiceBroadcastInfoStateEvent( + roomId, + VoiceBroadcastInfoState.Started, + client.getUserId(), + client.getDeviceId(), + ); + + stoppedInfoEvent = mkVoiceBroadcastInfoStateEvent( + roomId, + VoiceBroadcastInfoState.Stopped, + client.getUserId(), + client.getDeviceId(), + startedInfoEvent, + ); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + describe("when called with a stopped info event", () => { + describe("and there is a related event", () => { + beforeEach(() => { + mocked(room.findEventById).mockReturnValue(startedInfoEvent); + resumeVoiceBroadcastInRoom(stoppedInfoEvent, room, client); + }); + + itShouldStartAPausedRecording(); + }); + + describe("and there is no related event", () => { + beforeEach(() => { + mocked(room.findEventById).mockReturnValue(null); + resumeVoiceBroadcastInRoom(stoppedInfoEvent, room, client); + }); + + it("should not start a broadcast", () => { + expect(VoiceBroadcastRecording).not.toHaveBeenCalled(); + expect(VoiceBroadcastRecordingsStore.instance().setCurrent).not.toHaveBeenCalled(); + }); + }); + }); + + describe("when called with a started info event", () => { + beforeEach(() => { + resumeVoiceBroadcastInRoom(startedInfoEvent, room, client); + }); + + itShouldStartAPausedRecording(); + }); +}); diff --git a/test/voice-broadcast/utils/startNewVoiceBroadcastRecording-test.ts b/test/voice-broadcast/utils/startNewVoiceBroadcastRecording-test.ts index a320bca2eb..b19ea3c691 100644 --- a/test/voice-broadcast/utils/startNewVoiceBroadcastRecording-test.ts +++ b/test/voice-broadcast/utils/startNewVoiceBroadcastRecording-test.ts @@ -67,9 +67,15 @@ describe("startNewVoiceBroadcastRecording", () => { recordingsStore = { setCurrent: jest.fn(), + getCurrent: jest.fn(), } as unknown as VoiceBroadcastRecordingsStore; - infoEvent = mkVoiceBroadcastInfoStateEvent(roomId, VoiceBroadcastInfoState.Started, client.getUserId()); + infoEvent = mkVoiceBroadcastInfoStateEvent( + roomId, + VoiceBroadcastInfoState.Started, + client.getUserId(), + client.getDeviceId(), + ); otherEvent = mkEvent({ event: true, type: EventType.RoomMember, @@ -121,7 +127,7 @@ describe("startNewVoiceBroadcastRecording", () => { roomId, VoiceBroadcastInfoEventType, { - chunk_length: 300, + chunk_length: 120, device_id: client.getDeviceId(), state: VoiceBroadcastInfoState.Started, }, @@ -132,10 +138,33 @@ describe("startNewVoiceBroadcastRecording", () => { }); }); - describe("when there already is a live broadcast of the current user", () => { + describe("when there is already a current voice broadcast", () => { + beforeEach(async () => { + mocked(recordingsStore.getCurrent).mockReturnValue( + new VoiceBroadcastRecording(infoEvent, client), + ); + + result = await startNewVoiceBroadcastRecording(room, client, recordingsStore); + }); + + it("should not start a voice broadcast", () => { + expect(result).toBeNull(); + }); + + it("should show an info dialog", () => { + expect(Modal.createDialog).toMatchSnapshot(); + }); + }); + + describe("when there already is a live broadcast of the current user in the room", () => { beforeEach(async () => { room.currentState.setStateEvents([ - mkVoiceBroadcastInfoStateEvent(roomId, VoiceBroadcastInfoState.Running, client.getUserId()), + mkVoiceBroadcastInfoStateEvent( + roomId, + VoiceBroadcastInfoState.Running, + client.getUserId(), + client.getDeviceId(), + ), ]); result = await startNewVoiceBroadcastRecording(room, client, recordingsStore); @@ -153,7 +182,12 @@ describe("startNewVoiceBroadcastRecording", () => { describe("when there already is a live broadcast of another user", () => { beforeEach(async () => { room.currentState.setStateEvents([ - mkVoiceBroadcastInfoStateEvent(roomId, VoiceBroadcastInfoState.Running, otherUserId), + mkVoiceBroadcastInfoStateEvent( + roomId, + VoiceBroadcastInfoState.Running, + otherUserId, + "ASD123", + ), ]); result = await startNewVoiceBroadcastRecording(room, client, recordingsStore); diff --git a/test/voice-broadcast/utils/test-utils.ts b/test/voice-broadcast/utils/test-utils.ts index 2a73877474..09a2ba0ed3 100644 --- a/test/voice-broadcast/utils/test-utils.ts +++ b/test/voice-broadcast/utils/test-utils.ts @@ -22,16 +22,29 @@ import { mkEvent } from "../../test-utils"; export const mkVoiceBroadcastInfoStateEvent = ( roomId: string, state: VoiceBroadcastInfoState, - sender: string, + senderId: string, + senderDeviceId: string, + startedInfoEvent?: MatrixEvent, ): MatrixEvent => { + const relationContent = {}; + + if (startedInfoEvent) { + relationContent["m.relates_to"] = { + event_id: startedInfoEvent.getId(), + rel_type: "m.reference", + }; + } + return mkEvent({ event: true, room: roomId, - user: sender, + user: senderId, type: VoiceBroadcastInfoEventType, - skey: sender, + skey: senderId, content: { state, + device_id: senderDeviceId, + ...relationContent, }, }); };