Merge remote-tracking branch 'origin/develop' into task/eric/replace_flatten_with_direct_parent

# Conflicts:
#	matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo034.kt
This commit is contained in:
ericdecanini 2022-07-20 16:44:33 +02:00
commit 9e1235d51f
103 changed files with 592 additions and 249 deletions

View file

@ -770,7 +770,7 @@ ij_kotlin_align_multiline_extends_list = false
ij_kotlin_align_multiline_method_parentheses = false
ij_kotlin_align_multiline_parameters = true
ij_kotlin_align_multiline_parameters_in_calls = false
ij_kotlin_allow_trailing_comma = false
ij_kotlin_allow_trailing_comma = true
ij_kotlin_allow_trailing_comma_on_call_site = false
ij_kotlin_assignment_wrap = off
ij_kotlin_blank_lines_after_class_header = 0

1
changelog.d/6200.bugfix Normal file
View file

@ -0,0 +1 @@
Fixes room not being in space after upgrade

1
changelog.d/6585.bugfix Normal file
View file

@ -0,0 +1 @@
Fix backup saving several times the same keys

1
changelog.d/6587.bugfix Normal file
View file

@ -0,0 +1 @@
Check user power level before sharing live location

1
changelog.d/6596.bugfix Normal file
View file

@ -0,0 +1 @@
[Location Share] - Live is considered as ended while still active

View file

@ -1 +1 @@
مُحادثة آمنة لا مركزية و VoIP. حافظ على بياناتك آمنة من الأطراف الثالثة.
برنامج المراسلة الجماعية - الرسائل المشفرة والدردشة الجماعية ومكالمات الفيديو

View file

@ -1 +1 @@
Element (Riot.im سابقًا)
إيليمنت - تطبيق محادثات أمن

View file

@ -0,0 +1,2 @@
Hlavní změny v této verzi: Podpora UnifiedPush a možnost používat push bez FCM.
Úplný seznam změn: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Hlavní změny v této verzi: Opravy různých chyb a vylepšení stability.
Úplný seznam změn: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Põhilised muutused selles versioonis: võimalus kasutada tõukesõnumite jaoks FCM'i asemel UnifiedPush'i.
Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Põhilised muutused selles versioonis: erinevate vigade parandused ja stabiilsust edendavad kohendused.
Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
تغییرات عمده در این نگارش: استفاده از UnifiedPush و اجازه به کاربر برای داشتن آگاهی‌های ارسالی بدون FCM.
گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
تغییرات عمده در این نگارش: رفع اشکال‌های مختلف و بهبودهای پایداری.
گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Principaux changements pour cette version : Utilisation de UnifiedPush qui permet aux utilisateur dutiliser « push » sans FCM.
Intégralité des changements : https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Principaux changements pour cette version : Plusieurs corrections de bogues et daméliorations de stabilité.
Intégralité des changements : https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Principais cambios nesta versión: melloras na xestión das mensaxes cifradas. Varios arranxos e melloras na estabilidade.
Rexistro completo dos cambios: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Principais cambios nesta versión: varios arranxos e melloras na estabilidade.
Rexistro completo dos cambios: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Principais cambios nesta versión: varios arranxos e melloras na estabilidade.
Rexistro completo dos cambios: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Principais cambios nesta versión: varios arranxos e melloras na estabilidade.
Rexistro completo dos cambios: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Principais cambios nesta versión: varios arranxos e melloras na estabilidade.
Rexistro completo dos cambios: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Principais cambios nesta versión: varios arranxos e melloras na estabilidade.
Rexistro completo dos cambios: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Principais cambios nesta versión: varios arranxos e melloras na estabilidade.
Rexistro completo dos cambios: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Principais cambios nesta versión: varios arranxos e melloras na estabilidade.
Rexistro completo dos cambios: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Principais cambios nesta versión: Utiliza UnifiedPush e permite á usuaria obter notificacións sen FCM.
Rexistro completo dos cambios: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Principais cambios nesta versión: varios arranxos e melloras na estabilidade.
Rexistro completo dos cambios: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,42 @@
Element é tanto unha mensaxería segura e unha app de productividade para o traballo en equipo, perfecta para conversas de grupos con traballo remoto. Esta app de chat usa cifrado de extremo-a-extremo para proporcionar video conferencias seguras, compartición de ficheiros e chamadas de voz.
<b>Características de Element incluídas:</b>
- Ferramentas avanzadas para a comunicación en liña
- Mensaxes completamente cifradas para permitir a comunicación corporativa, incluso para traballo remoto
- Chat descentralizado baseado no sistema de código aberto Matrix
- Compartición segura de ficheiros con datos cifrados na xestión de proxectos
- Chats de vídeo con Voz sobre IP en compartición de pantalla
- Integración doada con outras ferramentas de colaboración en liña, ferramentas de xestión de proxectos, servizos VoIP e outras apps de mensaxería para equipos
Element é completamente diferente a outras apps de mensaxería e traballo en equipo. Funciona grazas a Matrix, unha rede aberta para mensaxería segura e descentralizada. Permite a hospedaxe na infraestructura propia para proporcionar o maior grao de propiedade e control sobre os teus datos e mensaxes.
<b>Mensaxería privada e cifrada</b>
Element protéxete da publicidade non solicitada, minería de datos e burbullas de contido. Tamén protexe os teus datos, chamadas de vídeo e voz cifradas de extremo-a-extremo así como verificación con sinatura dos dispositivos.
Element pon baixo o teu control a túa privacidade permitíndoche comunicarte de xeito seguro con calquera a través da rede Matrix, ou en outras ferramentas de colaboración para empresas ao estar integrada en apps como Slack.
<b>Element na túa infraestructura</b>
Para un maior control sobre os teus datos sensibles e comunicacións, podes hospedar Element ou elexir calquera hóspede baseado en Matrix - un estándar para comunicación descentralizado e de código aberto. Element proporciona privacidade e seguridade así como flexibilidade para a integración.
<b>Os teus datos</b>
Ti decides onde gardas os teus datos e mensaxes. Sen o risco da minería de datos ou acceso por terceiras partes.
Element ponte ao mando de varios xeitos:
1. Consigue unha conta gratuíta no servidor público matrix.org hospedado polos desenvolvedores de Matrix, ou elixe entre miles de servidores públicos xestionados por voluntarias
2. Hospeda a túa conta na túa propia infraestructura IT
3. Crea unha conta nun servidor personalizado simplemente subscribíndote á plataforma de hospedaxe Element Matrix Services
<b>Mensaxería e Colaboración abertas</b>
Podes conversar con calquera na rede Matrix, tanto se usan Element ou outra app Matrix ou incluso unha mensaxería diferente.
<b>Super segura</b>
Cifrado real de extremo-a-extremo (só quen participa na conversa pode descifrar as mensaxes), e verificación con sinatura cruzada dos dispositivos.
<b>Comunicación e integración completas</b>
Mensaxería, chamadas de voz e vídeo, compartición de ficheiros, compartición de pantalla e moitas máis integracións, bots e widgets. Crea salas, comunidades, mantén o contacto e saca adiante o traballo.
<b>Continúa onde o deixaches</b>
Sigue en contacto alá onde estés grazas ao historial sincronizado de mensaxería entre tódolos dispositivos e na web https://app.element.io
<b>Código aberto</b>
Element Android é un proxecto de código aberto, hospedado en GitHub. Informa de fallos e/ou contribúe ao seu desenvolvemento en https://github.com/vector-im/element-android

View file

@ -0,0 +1 @@
Mensaxería en grupo - mensaxería cifrada, chat en grupo e videochamadas

View file

@ -0,0 +1 @@
Element - Mensaxería Segura

View file

@ -0,0 +1,2 @@
Perubahan utama dalam versi ini: Dukungan UnifiedPush, memungkinkan pengguna untuk diberitahukan tanpa FCM.
Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Perubahan utama dalam versi ini: Banyak perbaikan kutu dan perbaikan stabilitas.
Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Modifiche principali in questa versione: utilizza UnifiedPush e consente all'utente di avere notifiche push senza FCM.
Cronologia completa: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Modifiche principali in questa versione: varie correzioni di errori e miglioramenti della stabilità.
Cronologia completa: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Hlavné zmeny v tejto verzii: Použitie UnifiedPush a umožňuje používateľovi používať push bez FCM.
Úplný zoznam zmien: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Hlavné zmeny v tejto verzii: Rôzne opravy chýb a vylepšenia stability.
Úplný zoznam zmien: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Huvudsakliga ändringar i den här versionen: Använd UnifiedPush och tillåt användare att ha push utan FCM.
Full ändringslogg: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Huvudsakliga ändringar i den här versionen: Diverse buggfixar och stabilitetsförbättringar.
Full ändringslogg: https://github.com/vector-im/element-android/releases

View file

@ -1,2 +1,2 @@
Основні зміни в цій версії: поліпшення VoIP (аудіо та відео дзвінки в DM) та виправлення помилок!
Основні зміни в цій версії: поліпшення VoIP (аудіо та відеовиклики у ПП) та виправлення помилок!
Повний журнал змін: https://github.com/vector-im/element-android/releases/tag/v1.1.0

View file

@ -0,0 +1,2 @@
Основні зміни в цій версії: Застосовано UnifiedPush і дозволено користувачам отримувати push-сповіщення без FCM.
Перелік усіх змін: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Основні зміни в цій версії: Усунуто різні вади й поліпшено стабільність.
Перелік усіх змін: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
此版本中的主要變動:使用 UnifiedPush 並允許使用者在沒有 FCM 的情況下推送。
完整的變更紀錄https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
此版本中的主要變動:多個臭蟲修復與穩定性改善。
完整的變更紀錄https://github.com/vector-im/element-android/releases

View file

@ -199,7 +199,7 @@ dependencies {
implementation libs.apache.commonsImaging
// Phone number https://github.com/google/libphonenumber
implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.51'
implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.52'
testImplementation libs.tests.junit
// Note: version sticks to 1.9.2 due to https://github.com/mockk/mockk/issues/281

View file

@ -24,7 +24,6 @@ import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@ -56,7 +55,6 @@ import java.util.concurrent.CountDownLatch
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
@LargeTest
@Ignore
class KeysBackupTest : InstrumentedTest {
@get:Rule val rule = RetryTestRule(3)

View file

@ -33,5 +33,7 @@ enum class VersioningState {
/**
* The room has been upgraded, and the new room has been joined.
*/
UPGRADED_ROOM_JOINED,
UPGRADED_ROOM_JOINED;
fun isUpgraded() = this != NONE
}

View file

@ -37,9 +37,9 @@ import org.matrix.android.sdk.internal.auth.db.PendingSessionData
* This class execute the registration request and is responsible to keep the session of interactive authentication.
*/
internal class DefaultRegistrationWizard(
authAPI: AuthAPI,
private val sessionCreator: SessionCreator,
private val pendingSessionStore: PendingSessionStore
authAPI: AuthAPI,
private val sessionCreator: SessionCreator,
private val pendingSessionStore: PendingSessionStore
) : RegistrationWizard {
private var pendingSessionData: PendingSessionData = pendingSessionStore.getPendingSessionData() ?: error("Pending session data should exist here")
@ -74,20 +74,20 @@ internal class DefaultRegistrationWizard(
initialDeviceDisplayName: String?
): RegistrationResult {
val params = RegistrationParams(
username = userName,
password = password,
initialDeviceDisplayName = initialDeviceDisplayName
username = userName,
password = password,
initialDeviceDisplayName = initialDeviceDisplayName
)
return performRegistrationRequest(params, LoginType.PASSWORD)
.also {
pendingSessionData = pendingSessionData.copy(isRegistrationStarted = true)
.also { pendingSessionStore.savePendingSessionData(it) }
}
.also {
pendingSessionData = pendingSessionData.copy(isRegistrationStarted = true)
.also { pendingSessionStore.savePendingSessionData(it) }
}
}
override suspend fun performReCaptcha(response: String): RegistrationResult {
val safeSession = pendingSessionData.currentSession
?: throw IllegalStateException("developer error, call createAccount() method first")
?: throw IllegalStateException("developer error, call createAccount() method first")
val params = RegistrationParams(auth = AuthParams.createForCaptcha(safeSession, response))
return performRegistrationRequest(params, LoginType.PASSWORD)
@ -95,7 +95,7 @@ internal class DefaultRegistrationWizard(
override suspend fun acceptTerms(): RegistrationResult {
val safeSession = pendingSessionData.currentSession
?: throw IllegalStateException("developer error, call createAccount() method first")
?: throw IllegalStateException("developer error, call createAccount() method first")
val params = RegistrationParams(auth = AuthParams(type = LoginFlowTypes.TERMS, session = safeSession))
return performRegistrationRequest(params, LoginType.PASSWORD)
@ -103,14 +103,14 @@ internal class DefaultRegistrationWizard(
override suspend fun addThreePid(threePid: RegisterThreePid): RegistrationResult {
pendingSessionData = pendingSessionData.copy(currentThreePidData = null)
.also { pendingSessionStore.savePendingSessionData(it) }
.also { pendingSessionStore.savePendingSessionData(it) }
return sendThreePid(threePid)
}
override suspend fun sendAgainThreePid(): RegistrationResult {
val safeCurrentThreePid = pendingSessionData.currentThreePidData?.threePid
?: throw IllegalStateException("developer error, call createAccount() method first")
?: throw IllegalStateException("developer error, call createAccount() method first")
return sendThreePid(safeCurrentThreePid)
}
@ -126,7 +126,7 @@ internal class DefaultRegistrationWizard(
)
pendingSessionData = pendingSessionData.copy(sendAttempt = pendingSessionData.sendAttempt + 1)
.also { pendingSessionStore.savePendingSessionData(it) }
.also { pendingSessionStore.savePendingSessionData(it) }
val params = RegistrationParams(
auth = if (threePid is RegisterThreePid.Email) {
@ -149,7 +149,7 @@ internal class DefaultRegistrationWizard(
)
// Store data
pendingSessionData = pendingSessionData.copy(currentThreePidData = ThreePidData.from(threePid, response, params))
.also { pendingSessionStore.savePendingSessionData(it) }
.also { pendingSessionStore.savePendingSessionData(it) }
// and send the sid a first time
return performRegistrationRequest(params, LoginType.PASSWORD)
@ -157,7 +157,7 @@ internal class DefaultRegistrationWizard(
override suspend fun checkIfEmailHasBeenValidated(delayMillis: Long): RegistrationResult {
val safeParam = pendingSessionData.currentThreePidData?.registrationParams
?: throw IllegalStateException("developer error, no pending three pid")
?: throw IllegalStateException("developer error, no pending three pid")
return performRegistrationRequest(safeParam, LoginType.PASSWORD, delayMillis)
}
@ -168,13 +168,13 @@ internal class DefaultRegistrationWizard(
private suspend fun validateThreePid(code: String): RegistrationResult {
val registrationParams = pendingSessionData.currentThreePidData?.registrationParams
?: throw IllegalStateException("developer error, no pending three pid")
?: throw IllegalStateException("developer error, no pending three pid")
val safeCurrentData = pendingSessionData.currentThreePidData ?: throw IllegalStateException("developer error, call createAccount() method first")
val url = safeCurrentData.addThreePidRegistrationResponse.submitUrl ?: throw IllegalStateException("Missing url to send the code")
val validationBody = ValidationCodeBody(
clientSecret = pendingSessionData.clientSecret,
sid = safeCurrentData.addThreePidRegistrationResponse.sid,
code = code
clientSecret = pendingSessionData.clientSecret,
sid = safeCurrentData.addThreePidRegistrationResponse.sid,
code = code
)
val validationResponse = validateCodeTask.execute(ValidateCodeTask.Params(url, validationBody))
if (validationResponse.isSuccess()) {
@ -189,7 +189,7 @@ internal class DefaultRegistrationWizard(
override suspend fun dummy(): RegistrationResult {
val safeSession = pendingSessionData.currentSession
?: throw IllegalStateException("developer error, call createAccount() method first")
?: throw IllegalStateException("developer error, call createAccount() method first")
val params = RegistrationParams(auth = AuthParams(type = LoginFlowTypes.DUMMY, session = safeSession))
return performRegistrationRequest(params, LoginType.PASSWORD)

View file

@ -21,13 +21,10 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.logger.LoggerTag
import org.matrix.android.sdk.internal.crypto.model.MXInboundMegolmSessionWrapper
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
import timber.log.Timber
import java.util.Timer
import java.util.TimerTask
import javax.inject.Inject
internal data class InboundGroupSessionHolder(
@ -57,18 +54,13 @@ internal class InboundGroupSessionStore @Inject constructor(
if (oldValue != null) {
cryptoCoroutineScope.launch(coroutineDispatchers.crypto) {
Timber.tag(loggerTag.value).v("## Inbound: entryRemoved ${oldValue.wrapper.roomId}-${oldValue.wrapper.senderKey}")
store.storeInboundGroupSessions(listOf(oldValue).map { it.wrapper })
// store.storeInboundGroupSessions(listOf(oldValue).map { it.wrapper })
oldValue.wrapper.session.releaseSession()
}
}
}
}
private val timer = Timer()
private var timerTask: TimerTask? = null
private val dirtySession = mutableListOf<InboundGroupSessionHolder>()
@Synchronized
fun clear() {
sessionCache.evictAll()
@ -90,7 +82,6 @@ internal class InboundGroupSessionStore @Inject constructor(
@Synchronized
fun replaceGroupSession(old: InboundGroupSessionHolder, new: InboundGroupSessionHolder, sessionId: String, senderKey: String) {
Timber.tag(loggerTag.value).v("## Replacing outdated session ${old.wrapper.roomId}-${old.wrapper.senderKey}")
dirtySession.remove(old)
store.removeInboundGroupSession(sessionId, senderKey)
sessionCache.remove(CacheKey(sessionId, senderKey))
@ -107,33 +98,14 @@ internal class InboundGroupSessionStore @Inject constructor(
private fun internalStoreGroupSession(holder: InboundGroupSessionHolder, sessionId: String, senderKey: String) {
Timber.tag(loggerTag.value).v("## Inbound: getInboundGroupSession mark as dirty ${holder.wrapper.roomId}-${holder.wrapper.senderKey}")
// We want to batch this a bit for performances
dirtySession.add(holder)
if (sessionCache[CacheKey(sessionId, senderKey)] == null) {
// first time seen, put it in memory cache while waiting for batch insert
// If it's already known, no need to update cache it's already there
sessionCache.put(CacheKey(sessionId, senderKey), holder)
}
timerTask?.cancel()
timerTask = object : TimerTask() {
override fun run() {
batchSave()
}
}
timer.schedule(timerTask!!, 300)
}
@Synchronized
private fun batchSave() {
val toSave = mutableListOf<InboundGroupSessionHolder>().apply { addAll(dirtySession) }
dirtySession.clear()
cryptoCoroutineScope.launch(coroutineDispatchers.crypto) {
Timber.tag(loggerTag.value).v("## Inbound: getInboundGroupSession batching save of ${toSave.size}")
tryOrNull {
store.storeInboundGroupSessions(toSave.map { it.wrapper })
}
store.storeInboundGroupSessions(listOf(holder.wrapper))
}
}
}

View file

@ -604,14 +604,16 @@ internal class MXOlmDevice @Inject constructor(
* @param sharedHistory MSC3061, this key is sharable on invite
* @return true if the operation succeeds.
*/
fun addInboundGroupSession(sessionId: String,
sessionKey: String,
roomId: String,
senderKey: String,
forwardingCurve25519KeyChain: List<String>,
keysClaimed: Map<String, String>,
exportFormat: Boolean,
sharedHistory: Boolean): AddSessionResult {
fun addInboundGroupSession(
sessionId: String,
sessionKey: String,
roomId: String,
senderKey: String,
forwardingCurve25519KeyChain: List<String>,
keysClaimed: Map<String, String>,
exportFormat: Boolean,
sharedHistory: Boolean
): AddSessionResult {
val candidateSession = tryOrNull("Failed to create inbound session in room $roomId") {
if (exportFormat) {
OlmInboundGroupSession.importSession(sessionKey)
@ -701,8 +703,8 @@ internal class MXOlmDevice @Inject constructor(
val senderKey = megolmSessionData.senderKey ?: continue
val roomId = megolmSessionData.roomId
val candidateSessionToImport = try {
MXInboundMegolmSessionWrapper.newFromMegolmData(megolmSessionData, true)
val candidateSessionToImport = try {
MXInboundMegolmSessionWrapper.newFromMegolmData(megolmSessionData, true)
} catch (e: Throwable) {
Timber.tag(loggerTag.value).e(e, "## importInboundGroupSession() : Failed to import session $senderKey/$sessionId")
continue
@ -806,7 +808,6 @@ internal class MXOlmDevice @Inject constructor(
}
replayAttackMap[messageIndexKey] = eventId
}
inboundGroupSessionStore.storeInBoundGroupSession(sessionHolder, sessionId, senderKey)
val payload = try {
val adapter = MoshiProvider.providesMoshi().adapter<JsonDict>(JSON_DICT_PARAMETERIZED_TYPE)
val payloadString = convertFromUTF8(decryptResult.mDecryptedMessage)

View file

@ -38,6 +38,7 @@ internal class MXMegolmDecryptionFactory @Inject constructor(
outgoingKeyRequestManager,
cryptoStore,
matrixConfiguration,
eventsManager)
eventsManager
)
}
}

View file

@ -250,8 +250,10 @@ internal class MXMegolmEncryption(
* @param sessionInfo the session info
* @param devicesByUser the devices map
*/
private suspend fun shareUserDevicesKey(sessionInfo: MXOutboundSessionInfo,
devicesByUser: Map<String, List<CryptoDeviceInfo>>) {
private suspend fun shareUserDevicesKey(
sessionInfo: MXOutboundSessionInfo,
devicesByUser: Map<String, List<CryptoDeviceInfo>>
) {
val sessionKey = olmDevice.getSessionKey(sessionInfo.sessionId) ?: return Unit.also {
Timber.tag(loggerTag.value).v("shareUserDevicesKey() Failed to share session, failed to export")
}

View file

@ -1349,6 +1349,8 @@ internal class DefaultKeysBackupService @Inject constructor(
// Mark keys as backed up
cryptoStore.markBackupDoneForInboundGroupSessions(olmInboundGroupSessionWrappers)
// we can release the sessions now
olmInboundGroupSessionWrappers.onEach { it.session.releaseSession() }
if (olmInboundGroupSessionWrappers.size < KEY_BACKUP_SEND_KEYS_MAX_COUNT) {
Timber.v("backupKeys: All keys have been backed up")

View file

@ -763,11 +763,17 @@ internal class RealmCryptoStore @Inject constructor(
// } ?: false
val key = OlmInboundGroupSessionEntity.createPrimaryKey(sessionIdentifier, wrapper.sessionData.senderKey)
val existing = realm.where<OlmInboundGroupSessionEntity>()
.equalTo(OlmInboundGroupSessionEntityFields.PRIMARY_KEY, key)
.findFirst()
val realmOlmInboundGroupSession = OlmInboundGroupSessionEntity().apply {
primaryKey = key
store(wrapper)
backedUp = existing?.backedUp ?: false
}
Timber.i("## CRYPTO | shouldShareHistory: ${wrapper.sessionData.sharedHistory} for $key")
Timber.v("## CRYPTO | shouldShareHistory: ${wrapper.sessionData.sharedHistory} for $key")
realm.insertOrUpdate(realmOlmInboundGroupSession)
}
}

View file

@ -17,14 +17,18 @@
package org.matrix.android.sdk.internal.database.migration
import io.realm.DynamicRealm
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields
import org.matrix.android.sdk.internal.database.model.livelocation.LiveLocationShareAggregatedSummaryEntityFields
import org.matrix.android.sdk.internal.util.database.RealmMigrator
/**
* Migrating to:
* Live location sharing aggregated summary: adding new field startOfLiveTimestampMillis.
*/
internal class MigrateSessionTo034(realm: DynamicRealm) : RealmMigrator(realm, 34) {
override fun doMigrate(realm: DynamicRealm) {
realm.schema.get("RoomSummaryEntity")
?.addRealmListField(RoomSummaryEntityFields.DIRECT_PARENT_NAMES.`$`, String::class.java)
?.transform { it.setString(RoomSummaryEntityFields.DIRECT_PARENT_NAMES.`$`, "") }
realm.schema.get("LiveLocationShareAggregatedSummaryEntity")
?.addField(LiveLocationShareAggregatedSummaryEntityFields.START_OF_LIVE_TIMESTAMP_MILLIS, Long::class.java)
?.setNullable(LiveLocationShareAggregatedSummaryEntityFields.START_OF_LIVE_TIMESTAMP_MILLIS, true)
}
}

View file

@ -44,6 +44,8 @@ internal open class LiveLocationShareAggregatedSummaryEntity(
*/
var isActive: Boolean? = null,
var startOfLiveTimestampMillis: Long? = null,
var endOfLiveTimestampMillis: Long? = null,
/**

View file

@ -92,12 +92,14 @@ internal fun LiveLocationShareAggregatedSummaryEntity.Companion.findActiveLiveIn
roomId: String,
userId: String,
ignoredEventId: String,
startOfLiveTimestampThreshold: Long,
): List<LiveLocationShareAggregatedSummaryEntity> {
return LiveLocationShareAggregatedSummaryEntity
.whereRoomId(realm, roomId = roomId)
.equalTo(LiveLocationShareAggregatedSummaryEntityFields.USER_ID, userId)
.equalTo(LiveLocationShareAggregatedSummaryEntityFields.IS_ACTIVE, true)
.notEqualTo(LiveLocationShareAggregatedSummaryEntityFields.EVENT_ID, ignoredEventId)
.lessThan(LiveLocationShareAggregatedSummaryEntityFields.START_OF_LIVE_TIMESTAMP_MILLIS, startOfLiveTimestampThreshold)
.findAll()
.toList()
}

View file

@ -84,11 +84,12 @@ internal class LiveLocationAggregationProcessor @Inject constructor(
val endOfLiveTimestampMillis = content.getBestTimestampMillis()?.let { it + (content.timeout ?: 0) }
Timber.d("updating summary of id=$targetEventId with isActive=$isActive and endTimestamp=$endOfLiveTimestampMillis")
aggregatedSummary.startOfLiveTimestampMillis = content.getBestTimestampMillis()
aggregatedSummary.endOfLiveTimestampMillis = endOfLiveTimestampMillis
aggregatedSummary.isActive = isActive
aggregatedSummary.userId = event.senderId
deactivateAllPreviousBeacons(realm, roomId, event.senderId, targetEventId)
deactivateAllPreviousBeacons(realm, roomId, event.senderId, targetEventId, content.getBestTimestampMillis() ?: 0)
if (isActive) {
scheduleDeactivationAfterTimeout(targetEventId, roomId, endOfLiveTimestampMillis)
@ -182,13 +183,20 @@ internal class LiveLocationAggregationProcessor @Inject constructor(
aggregatedSummary.relatedEventIds = RealmList(*updatedEventIds.toTypedArray())
}
private fun deactivateAllPreviousBeacons(realm: Realm, roomId: String, userId: String, currentEventId: String) {
private fun deactivateAllPreviousBeacons(
realm: Realm,
roomId: String,
userId: String,
currentEventId: String,
currentEventTimestamp: Long
) {
LiveLocationShareAggregatedSummaryEntity
.findActiveLiveInRoomForUser(
realm = realm,
roomId = roomId,
userId = userId,
ignoredEventId = currentEventId
ignoredEventId = currentEventId,
startOfLiveTimestampThreshold = currentEventTimestamp
)
.forEach { it.isActive = false }
}

View file

@ -22,7 +22,7 @@ import timber.log.Timber
/**
* Throws in debug, only log in production.
* As this method does not always throw, next statement should be a return.
*/
*/
internal fun fatalError(message: String) {
if (BuildConfig.DEBUG) {
error(message)

View file

@ -36,6 +36,7 @@ import org.matrix.android.sdk.test.fakes.FakeWorkManagerProvider
import org.matrix.android.sdk.test.fakes.givenEqualTo
import org.matrix.android.sdk.test.fakes.givenFindAll
import org.matrix.android.sdk.test.fakes.givenFindFirst
import org.matrix.android.sdk.test.fakes.givenLessThan
import org.matrix.android.sdk.test.fakes.givenNotEqualTo
private const val A_SESSION_ID = "session_id"
@ -183,6 +184,7 @@ internal class LiveLocationAggregationProcessorTest {
aggregatedEntity.roomId shouldBeEqualTo A_ROOM_ID
aggregatedEntity.userId shouldBeEqualTo A_SENDER_ID
aggregatedEntity.isActive shouldBeEqualTo true
aggregatedEntity.startOfLiveTimestampMillis shouldBeEqualTo A_TIMESTAMP
aggregatedEntity.endOfLiveTimestampMillis shouldBeEqualTo A_TIMESTAMP + A_TIMEOUT_MILLIS
aggregatedEntity.lastLocationContent shouldBeEqualTo null
previousEntities.forEach { entity ->
@ -404,6 +406,7 @@ internal class LiveLocationAggregationProcessorTest {
.givenNotEqualTo(LiveLocationShareAggregatedSummaryEntityFields.EVENT_ID, AN_EVENT_ID)
.givenEqualTo(LiveLocationShareAggregatedSummaryEntityFields.USER_ID, A_SENDER_ID)
.givenEqualTo(LiveLocationShareAggregatedSummaryEntityFields.IS_ACTIVE, true)
.givenLessThan(LiveLocationShareAggregatedSummaryEntityFields.START_OF_LIVE_TIMESTAMP_MILLIS, A_TIMESTAMP)
.givenFindAll(summaryList)
return summaryList
}

View file

@ -101,6 +101,14 @@ inline fun <reified T : RealmModel> RealmQuery<T>.givenIsNotNull(
return this
}
inline fun <reified T : RealmModel> RealmQuery<T>.givenLessThan(
fieldName: String,
value: Long
): RealmQuery<T> {
every { lessThan(fieldName, value) } returns this
return this
}
/**
* Should be called on a mocked RealmObject and not on a real RealmObject so that the underlying final method is mocked.
*/

View file

@ -437,7 +437,7 @@ dependencies {
implementation 'com.facebook.stetho:stetho:1.6.0'
// Phone number https://github.com/google/libphonenumber
implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.51'
implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.52'
// FlowBinding
implementation libs.github.flowBinding

View file

@ -21,11 +21,11 @@ import im.vector.app.features.onboarding.AuthenticationDescription
fun AuthenticationDescription.AuthenticationType.toAnalyticsType() = when (this) {
AuthenticationDescription.AuthenticationType.Password -> Signup.AuthenticationType.Password
AuthenticationDescription.AuthenticationType.Apple -> Signup.AuthenticationType.Apple
AuthenticationDescription.AuthenticationType.Apple -> Signup.AuthenticationType.Apple
AuthenticationDescription.AuthenticationType.Facebook -> Signup.AuthenticationType.Facebook
AuthenticationDescription.AuthenticationType.GitHub -> Signup.AuthenticationType.GitHub
AuthenticationDescription.AuthenticationType.GitLab -> Signup.AuthenticationType.GitLab
AuthenticationDescription.AuthenticationType.Google -> Signup.AuthenticationType.Google
AuthenticationDescription.AuthenticationType.SSO -> Signup.AuthenticationType.SSO
AuthenticationDescription.AuthenticationType.Other -> Signup.AuthenticationType.Other
AuthenticationDescription.AuthenticationType.SSO -> Signup.AuthenticationType.SSO
AuthenticationDescription.AuthenticationType.Other -> Signup.AuthenticationType.Other
}

View file

@ -70,7 +70,7 @@ class AvatarRenderer @Inject constructor(
render(
GlideApp.with(imageView),
matrixItem,
DrawableImageViewTarget(imageView)
DrawableImageViewTarget(imageView),
)
}
@ -103,7 +103,7 @@ class AvatarRenderer @Inject constructor(
render(
glideRequests,
matrixItem,
DrawableImageViewTarget(imageView)
DrawableImageViewTarget(imageView),
)
}
@ -123,7 +123,7 @@ class AvatarRenderer @Inject constructor(
val matrixItem = MatrixItem.UserItem(
// Need an id starting with @
id = "@${mappedContact.displayName}",
displayName = mappedContact.displayName
displayName = mappedContact.displayName,
)
val placeholder = getPlaceholderDrawable(matrixItem)
@ -140,7 +140,7 @@ class AvatarRenderer @Inject constructor(
val matrixItem = MatrixItem.UserItem(
// Need an id starting with @
id = profileInfo.matrixId,
displayName = profileInfo.displayName
displayName = profileInfo.displayName,
)
val placeholder = getPlaceholderDrawable(matrixItem)
@ -215,7 +215,7 @@ class AvatarRenderer @Inject constructor(
.bold()
.endConfig()
.buildRect(matrixItem.firstLetterOfDisplayName(), avatarColor)
.toBitmap(width = iconSize, height = iconSize)
.toBitmap(width = iconSize, height = iconSize),
)
}
}
@ -231,7 +231,7 @@ class AvatarRenderer @Inject constructor(
addPlaceholder: Boolean
) {
val transformations = mutableListOf<Transformation<Bitmap>>(
BlurTransformation(20, sampling)
BlurTransformation(20, sampling),
)
if (colorFilter != null) {
transformations.add(ColorFilterTransformation(colorFilter))

View file

@ -219,7 +219,7 @@ class HomeActivity :
is HomeActivitySharedAction.ShowSpaceSettings -> showSpaceSettings(sharedAction.spaceId)
is HomeActivitySharedAction.OpenSpaceInvite -> openSpaceInvite(sharedAction.spaceId)
HomeActivitySharedAction.SendSpaceFeedBack -> bugReporter.openBugReportScreen(this, ReportType.SPACE_BETA_FEEDBACK)
HomeActivitySharedAction.OnCloseSpace -> onCloseSpace()
HomeActivitySharedAction.OnCloseSpace -> onCloseSpace()
}
}
.launchIn(lifecycleScope)

View file

@ -63,10 +63,10 @@ class EncryptionItemFactory @Inject constructor(
isDirect && RoomLocalEcho.isLocalEchoId(event.root.roomId.orEmpty()) -> {
R.string.direct_room_encryption_enabled_tile_description_future
}
isDirect -> {
isDirect -> {
R.string.direct_room_encryption_enabled_tile_description
}
else -> {
else -> {
R.string.encryption_enabled_tile_description
}
}

View file

@ -84,8 +84,6 @@ class UpgradeRoomViewModelTask @Inject constructor(
// autoJoin = currentInfo.autoJoin ?: false,
suggested = currentInfo.suggested
)
parentSpace.removeChildren(params.roomId)
}
}
} catch (failure: Throwable) {

View file

@ -146,17 +146,17 @@ class RoomListViewModel @AssistedInject constructor(
companion object : MavericksViewModelFactory<RoomListViewModel, RoomListViewState> by hiltMavericksViewModelFactory()
private val roomListSectionBuilder = RoomListSectionBuilder(
session,
stringProvider,
appStateHandler,
viewModelScope,
autoAcceptInvites,
{
updatableQuery = it
},
suggestedRoomJoiningState,
!vectorPreferences.prefSpacesShowAllRoomInHome()
)
session,
stringProvider,
appStateHandler,
viewModelScope,
autoAcceptInvites,
{
updatableQuery = it
},
suggestedRoomJoiningState,
!vectorPreferences.prefSpacesShowAllRoomInHome()
)
val sections: List<RoomsSection> by lazy {
roomListSectionBuilder.buildSections(initialState.displayMode)

View file

@ -85,27 +85,27 @@ class EventHtmlRenderer @Inject constructor(
} else {
builder
}
.usePlugin(
MarkwonInlineParserPlugin.create(
/* Configuring the Markwon inline formatting processor.
* Default settings are all Markdown features. Turn those off, only using the
* inline HTML processor and HTML entities processor.
*/
MarkwonInlineParser.factoryBuilderNoDefaults()
.addInlineProcessor(HtmlInlineProcessor()) // use inline HTML processor
.addInlineProcessor(EntityInlineProcessor()) // use HTML entities processor
.usePlugin(
MarkwonInlineParserPlugin.create(
/* Configuring the Markwon inline formatting processor.
* Default settings are all Markdown features. Turn those off, only using the
* inline HTML processor and HTML entities processor.
*/
MarkwonInlineParser.factoryBuilderNoDefaults()
.addInlineProcessor(HtmlInlineProcessor()) // use inline HTML processor
.addInlineProcessor(EntityInlineProcessor()) // use HTML entities processor
)
)
)
.usePlugin(object : AbstractMarkwonPlugin() {
override fun configureParser(builder: Parser.Builder) {
/* Configuring the Markwon block formatting processor.
* Default settings are all Markdown blocks. Turn those off.
*/
builder.enabledBlockTypes(kotlin.collections.emptySet())
}
})
.textSetter(PrecomputedFutureTextSetterCompat.create())
.build()
.usePlugin(object : AbstractMarkwonPlugin() {
override fun configureParser(builder: Parser.Builder) {
/* Configuring the Markwon block formatting processor.
* Default settings are all Markdown blocks. Turn those off.
*/
builder.enabledBlockTypes(kotlin.collections.emptySet())
}
})
.textSetter(PrecomputedFutureTextSetterCompat.create())
.build()
val plugins: List<MarkwonPlugin> = markwon.plugins

View file

@ -23,5 +23,6 @@ sealed class LocationSharingAction : VectorViewModelAction {
data class PinnedLocationSharing(val locationData: LocationData?) : LocationSharingAction()
data class LocationTargetChange(val locationData: LocationData) : LocationSharingAction()
object ZoomToUserLocation : LocationSharingAction()
object LiveLocationSharingRequested : LocationSharingAction()
data class StartLiveLocationSharing(val durationMillis: Long) : LocationSharingAction()
}

View file

@ -104,6 +104,9 @@ class LocationSharingFragment @Inject constructor(
LocationSharingViewEvents.LocationNotAvailableError -> handleLocationNotAvailableError()
is LocationSharingViewEvents.ZoomToUserLocation -> handleZoomToUserLocationEvent(it)
is LocationSharingViewEvents.StartLiveLocationService -> handleStartLiveLocationService(it)
LocationSharingViewEvents.ChooseLiveLocationDuration -> handleChooseLiveLocationDuration()
LocationSharingViewEvents.ShowLabsFlagPromotion -> handleShowLabsFlagPromotion()
LocationSharingViewEvents.LiveLocationSharingNotEnoughPermission -> handleLiveLocationSharingNotEnoughPermission()
}
}
}
@ -168,6 +171,14 @@ class LocationSharingFragment @Inject constructor(
.show()
}
private fun handleLiveLocationSharingNotEnoughPermission() {
MaterialAlertDialogBuilder(requireActivity())
.setTitle(R.string.live_location_not_enough_permission_dialog_title)
.setMessage(R.string.live_location_not_enough_permission_dialog_description)
.setPositiveButton(R.string.ok, null)
.show()
}
private fun initLocateButton() {
views.mapView.locateButton.setOnClickListener {
viewModel.handle(LocationSharingAction.ZoomToUserLocation)
@ -201,7 +212,7 @@ class LocationSharingFragment @Inject constructor(
viewModel.handle(LocationSharingAction.CurrentUserLocationSharing)
}
views.shareLocationOptionsPicker.optionUserLive.debouncedClicks {
tryStartLiveLocationSharing()
viewModel.handle(LocationSharingAction.LiveLocationSharingRequested)
}
}
@ -212,13 +223,13 @@ class LocationSharingFragment @Inject constructor(
}
}
private fun tryStartLiveLocationSharing() {
if (vectorPreferences.labsEnableLiveLocation()) {
startLiveLocationSharing()
} else {
LiveLocationLabsFlagPromotionBottomSheet.newInstance()
.show(requireActivity().supportFragmentManager, "DISPLAY_LIVE_LOCATION_LABS_FLAG_PROMOTION")
}
private fun handleChooseLiveLocationDuration() {
startLiveLocationSharing()
}
private fun handleShowLabsFlagPromotion() {
LiveLocationLabsFlagPromotionBottomSheet.newInstance()
.show(requireActivity().supportFragmentManager, "DISPLAY_LIVE_LOCATION_LABS_FLAG_PROMOTION")
}
private val foregroundLocationResultLauncher = registerForPermissionsResult { allGranted, deniedPermanently ->

View file

@ -23,4 +23,7 @@ sealed class LocationSharingViewEvents : VectorViewEvents {
object LocationNotAvailableError : LocationSharingViewEvents()
data class ZoomToUserLocation(val userLocation: LocationData) : LocationSharingViewEvents()
data class StartLiveLocationService(val sessionId: String, val roomId: String, val durationMillis: Long) : LocationSharingViewEvents()
object ChooseLiveLocationDuration : LocationSharingViewEvents()
object ShowLabsFlagPromotion : LocationSharingViewEvents()
object LiveLocationSharingNotEnoughPermission : LocationSharingViewEvents()
}

View file

@ -26,6 +26,8 @@ import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider
import im.vector.app.features.location.domain.usecase.CompareLocationsUseCase
import im.vector.app.features.powerlevel.PowerLevelsFlowFactory
import im.vector.app.features.settings.VectorPreferences
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.lastOrNull
@ -36,8 +38,10 @@ import kotlinx.coroutines.flow.sample
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.getUser
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
import org.matrix.android.sdk.api.util.toMatrixItem
import timber.log.Timber
@ -52,6 +56,7 @@ class LocationSharingViewModel @AssistedInject constructor(
private val locationPinProvider: LocationPinProvider,
private val session: Session,
private val compareLocationsUseCase: CompareLocationsUseCase,
private val vectorPreferences: VectorPreferences,
) : VectorViewModel<LocationSharingViewState, LocationSharingAction, LocationSharingViewEvents>(initialState), LocationTracker.Callback {
private val room = session.getRoom(initialState.roomId)!!
@ -70,6 +75,21 @@ class LocationSharingViewModel @AssistedInject constructor(
setUserItem()
updatePin()
compareTargetAndUserLocation()
observePowerLevelsForLiveLocationSharing()
}
private fun observePowerLevelsForLiveLocationSharing() {
PowerLevelsFlowFactory(room).createFlow()
.distinctUntilChanged()
.setOnEach {
val powerLevelsHelper = PowerLevelsHelper(it)
val canShareLiveLocation = EventType.STATE_ROOM_BEACON_INFO
.all { beaconInfoType ->
powerLevelsHelper.isUserAllowedToSend(session.myUserId, true, beaconInfoType)
}
copy(canShareLiveLocation = canShareLiveLocation)
}
}
private fun initLocationTracking() {
@ -130,10 +150,21 @@ class LocationSharingViewModel @AssistedInject constructor(
is LocationSharingAction.PinnedLocationSharing -> handlePinnedLocationSharingAction(action)
is LocationSharingAction.LocationTargetChange -> handleLocationTargetChangeAction(action)
LocationSharingAction.ZoomToUserLocation -> handleZoomToUserLocationAction()
LocationSharingAction.LiveLocationSharingRequested -> handleLiveLocationSharingRequestedAction()
is LocationSharingAction.StartLiveLocationSharing -> handleStartLiveLocationSharingAction(action.durationMillis)
}
}
private fun handleLiveLocationSharingRequestedAction() = withState { state ->
if (!state.canShareLiveLocation) {
_viewEvents.post(LocationSharingViewEvents.LiveLocationSharingNotEnoughPermission)
} else if (vectorPreferences.labsEnableLiveLocation()) {
_viewEvents.post(LocationSharingViewEvents.ChooseLiveLocationDuration)
} else {
_viewEvents.post(LocationSharingViewEvents.ShowLabsFlagPromotion)
}
}
private fun handleCurrentUserLocationSharingAction() = withState { state ->
shareLocation(state.lastKnownUserLocation, isUserLocation = true)
}

View file

@ -34,7 +34,8 @@ data class LocationSharingViewState(
val userItem: MatrixItem.UserItem? = null,
val areTargetAndUserLocationEqual: Boolean? = null,
val lastKnownUserLocation: LocationData? = null,
val locationTargetDrawable: Drawable? = null
val locationTargetDrawable: Drawable? = null,
val canShareLiveLocation: Boolean = false,
) : MavericksState {
constructor(locationSharingArgs: LocationSharingArgs) : this(

View file

@ -29,7 +29,7 @@ import im.vector.app.databinding.BottomSheetLiveLocationLabsFlagPromotionBinding
* This should not be shown if the user already enabled the labs flag.
*/
class LiveLocationLabsFlagPromotionBottomSheet :
VectorBaseBottomSheetDialogFragment<BottomSheetLiveLocationLabsFlagPromotionBinding>() {
VectorBaseBottomSheetDialogFragment<BottomSheetLiveLocationLabsFlagPromotionBinding>() {
override val showExpanded = true

View file

@ -41,12 +41,12 @@ sealed interface AuthenticationDescription : Parcelable {
}
fun SsoIdentityProvider?.toAuthenticationType() = when (this?.brand) {
SsoIdentityProvider.BRAND_GOOGLE -> AuthenticationType.Google
SsoIdentityProvider.BRAND_GITHUB -> AuthenticationType.GitHub
SsoIdentityProvider.BRAND_APPLE -> AuthenticationType.Apple
SsoIdentityProvider.BRAND_GOOGLE -> AuthenticationType.Google
SsoIdentityProvider.BRAND_GITHUB -> AuthenticationType.GitHub
SsoIdentityProvider.BRAND_APPLE -> AuthenticationType.Apple
SsoIdentityProvider.BRAND_FACEBOOK -> AuthenticationType.Facebook
SsoIdentityProvider.BRAND_GITLAB -> AuthenticationType.GitLab
SsoIdentityProvider.BRAND_TWITTER -> AuthenticationType.SSO
null -> AuthenticationType.SSO
else -> AuthenticationType.SSO
SsoIdentityProvider.BRAND_GITLAB -> AuthenticationType.GitLab
SsoIdentityProvider.BRAND_TWITTER -> AuthenticationType.SSO
null -> AuthenticationType.SSO
else -> AuthenticationType.SSO
}

View file

@ -563,7 +563,7 @@ class OnboardingViewModel @AssistedInject constructor(
setState { copy(isLoading = false, resetState = ResetState()) }
val nextEvent = when {
vectorFeatures.isOnboardingCombinedLoginEnabled() -> OnboardingViewEvents.OnResetPasswordComplete
else -> OnboardingViewEvents.OpenResetPasswordComplete
else -> OnboardingViewEvents.OpenResetPasswordComplete
}
_viewEvents.post(nextEvent)
},

View file

@ -31,6 +31,6 @@ fun SignMode.toAuthenticateAction(login: String, password: String, initialDevice
}
fun ThemeProvider.ftueBreakerBackground() = when (isLightTheme()) {
true -> R.drawable.bg_gradient_ftue_breaker
true -> R.drawable.bg_gradient_ftue_breaker
false -> R.drawable.bg_color_background
}

View file

@ -33,6 +33,6 @@ class BiometricAuthError(val code: Int, message: String) : Throwable(message) {
val isAuthPermanentlyDisabledError: Boolean get() = code == BiometricPrompt.ERROR_LOCKOUT_PERMANENT
companion object {
private val LOCKOUT_ERROR_CODES = arrayOf(BiometricPrompt.ERROR_LOCKOUT, BiometricPrompt.ERROR_LOCKOUT_PERMANENT)
private val LOCKOUT_ERROR_CODES = arrayOf(BiometricPrompt.ERROR_LOCKOUT, BiometricPrompt.ERROR_LOCKOUT_PERMANENT)
}
}

View file

@ -73,26 +73,30 @@ class BiometricHelper @Inject constructor(
/**
* Returns true if a weak biometric method (i.e.: some face or iris unlock implementations) can be used.
*/
val canUseWeakBiometricAuth: Boolean get() =
configuration.isWeakBiometricsEnabled && biometricManager.canAuthenticate(BIOMETRIC_WEAK) == BIOMETRIC_SUCCESS
val canUseWeakBiometricAuth: Boolean
get() =
configuration.isWeakBiometricsEnabled && biometricManager.canAuthenticate(BIOMETRIC_WEAK) == BIOMETRIC_SUCCESS
/**
* Returns true if a strong biometric method (i.e.: fingerprint, some face or iris unlock implementations) can be used.
*/
val canUseStrongBiometricAuth: Boolean get() =
configuration.isStrongBiometricsEnabled && biometricManager.canAuthenticate(BIOMETRIC_STRONG) == BIOMETRIC_SUCCESS
val canUseStrongBiometricAuth: Boolean
get() =
configuration.isStrongBiometricsEnabled && biometricManager.canAuthenticate(BIOMETRIC_STRONG) == BIOMETRIC_SUCCESS
/**
* Returns true if the device credentials can be used to unlock (system pin code, password, pattern, etc.).
*/
val canUseDeviceCredentialsAuth: Boolean get() =
configuration.isDeviceCredentialUnlockEnabled && biometricManager.canAuthenticate(DEVICE_CREDENTIAL) == BIOMETRIC_SUCCESS
val canUseDeviceCredentialsAuth: Boolean
get() =
configuration.isDeviceCredentialUnlockEnabled && biometricManager.canAuthenticate(DEVICE_CREDENTIAL) == BIOMETRIC_SUCCESS
/**
* Returns true if any system authentication method (biometric weak/strong or device credentials) can be used.
*/
@VisibleForTesting(otherwise = PRIVATE)
internal val canUseAnySystemAuth: Boolean get() = canUseWeakBiometricAuth || canUseStrongBiometricAuth || canUseDeviceCredentialsAuth
internal val canUseAnySystemAuth: Boolean
get() = canUseWeakBiometricAuth || canUseStrongBiometricAuth || canUseDeviceCredentialsAuth
/**
* Returns true if any system authentication method and there is a valid associated key.
@ -153,9 +157,9 @@ class BiometricHelper @Inject constructor(
@SuppressLint("NewApi")
@OptIn(ExperimentalCoroutinesApi::class)
private fun authenticateInternal(
activity: FragmentActivity,
checkSystemKeyExists: Boolean,
cryptoObject: BiometricPrompt.CryptoObject? = null,
activity: FragmentActivity,
checkSystemKeyExists: Boolean,
cryptoObject: BiometricPrompt.CryptoObject? = null,
): Flow<Boolean> {
if (checkSystemKeyExists && !isSystemAuthEnabledAndValid) return flowOf(false)
@ -189,9 +193,9 @@ class BiometricHelper @Inject constructor(
@VisibleForTesting(otherwise = PRIVATE)
internal fun authenticateWithPromptInternal(
activity: FragmentActivity,
cryptoObject: BiometricPrompt.CryptoObject? = null,
channel: Channel<Boolean>,
activity: FragmentActivity,
cryptoObject: BiometricPrompt.CryptoObject? = null,
channel: Channel<Boolean>,
): BiometricPrompt {
val executor = ContextCompat.getMainExecutor(context)
val callback = createSuspendingAuthCallback(channel, executor.asCoroutineDispatcher())

View file

@ -36,7 +36,7 @@ class LockScreenKeyRepository(
private val systemKeyAlias = "$baseName.system"
private val pinCodeCrypto: KeyStoreCrypto by lazy {
keyStoreCryptoFactory.provide(pinCodeKeyAlias, keyNeedsUserAuthentication = false)
keyStoreCryptoFactory.provide(pinCodeKeyAlias, keyNeedsUserAuthentication = false)
}
private val systemKeyCrypto: KeyStoreCrypto by lazy {
keyStoreCryptoFactory.provide(systemKeyAlias, keyNeedsUserAuthentication = true)

View file

@ -114,15 +114,15 @@ class LockScreenFragment : VectorBaseFragment<FragmentLockScreenBinding>() {
private fun handleEvent(viewEvent: LockScreenViewEvent) {
when (viewEvent) {
is LockScreenViewEvent.CodeCreationComplete -> lockScreenListener?.onPinCodeCreated()
is LockScreenViewEvent.ClearPinCode -> {
is LockScreenViewEvent.ClearPinCode -> {
if (viewEvent.confirmationFailed) {
lockScreenListener?.onNewCodeValidationFailed()
}
views.codeView.clearCode()
}
is LockScreenViewEvent.AuthSuccessful -> lockScreenListener?.onAuthenticationSuccess(viewEvent.method)
is LockScreenViewEvent.AuthFailure -> onAuthFailure(viewEvent.method)
is LockScreenViewEvent.AuthError -> onAuthError(viewEvent.method, viewEvent.throwable)
is LockScreenViewEvent.AuthSuccessful -> lockScreenListener?.onAuthenticationSuccess(viewEvent.method)
is LockScreenViewEvent.AuthFailure -> onAuthFailure(viewEvent.method)
is LockScreenViewEvent.AuthError -> onAuthError(viewEvent.method, viewEvent.throwable)
}
}

View file

@ -94,7 +94,7 @@ class LockScreenViewModel @AssistedInject constructor(
override fun handle(action: LockScreenAction) {
when (action) {
is LockScreenAction.PinCodeEntered -> onPinCodeEntered(action.value)
is LockScreenAction.PinCodeEntered -> onPinCodeEntered(action.value)
is LockScreenAction.ShowBiometricPrompt -> showBiometricPrompt(action.callingActivity)
}
}

View file

@ -48,15 +48,15 @@ object DevicePromptCheck {
* See [this OP forum thread](https://forums.oneplus.com/threads/oneplus-7-pro-fingerprint-biometricprompt-does-not-show.1035821/).
*/
private val isOnePlusDeviceWithNoBiometricUI: Boolean =
Build.BRAND.equals("OnePlus", ignoreCase = true) &&
!onePlusModelsWithWorkingBiometricUI.contains(Build.MODEL) &&
Build.VERSION.SDK_INT < Build.VERSION_CODES.R
Build.BRAND.equals("OnePlus", ignoreCase = true) &&
!onePlusModelsWithWorkingBiometricUI.contains(Build.MODEL) &&
Build.VERSION.SDK_INT < Build.VERSION_CODES.R
/**
* Some LG models don't seem to have a system biometric prompt at all.
*/
private val isLGDeviceWithNoBiometricUI: Boolean =
Build.BRAND.equals("LG", ignoreCase = true) && lgModelsWithoutBiometricUI.contains(Build.MODEL)
Build.BRAND.equals("LG", ignoreCase = true) && lgModelsWithoutBiometricUI.contains(Build.MODEL)
/**
* Check if this device is included in the list of devices with known Biometric Prompt issues.

View file

@ -31,7 +31,7 @@ import javax.inject.Inject
class FontScaleSettingFragment @Inject constructor(
private val fontListController: FontScaleSettingController
) : VectorBaseFragment<FragmentSettingsFontScalingBinding>(), FontScaleSettingController.Callback {
) : VectorBaseFragment<FragmentSettingsFontScalingBinding>(), FontScaleSettingController.Callback {
private val viewModel: FontScaleSettingViewModel by fragmentViewModel()

View file

@ -94,10 +94,10 @@ class SoftLogoutController @Inject constructor(
}
private fun buildForm(state: SoftLogoutViewState) = when (state.asyncHomeServerLoginFlowRequest) {
is Fail -> buildLoginErrorWithRetryItem(state.asyncHomeServerLoginFlowRequest.error)
is Success -> buildLoginSuccessItem(state)
is Fail -> buildLoginErrorWithRetryItem(state.asyncHomeServerLoginFlowRequest.error)
is Success -> buildLoginSuccessItem(state)
is Loading, Uninitialized -> buildLoadingItem()
is Incomplete -> Unit
is Incomplete -> Unit
}
private fun buildLoadingItem() {
@ -116,11 +116,11 @@ class SoftLogoutController @Inject constructor(
}
private fun buildLoginSuccessItem(state: SoftLogoutViewState) = when (state.asyncHomeServerLoginFlowRequest.invoke()) {
LoginMode.Password -> buildLoginPasswordForm(state)
is LoginMode.Sso -> buildLoginSSOForm()
LoginMode.Password -> buildLoginPasswordForm(state)
is LoginMode.Sso -> buildLoginSSOForm()
is LoginMode.SsoAndPassword -> disambiguateLoginSSOAndPasswordForm(state)
LoginMode.Unsupported -> buildLoginUnsupportedForm()
LoginMode.Unknown, null -> Unit // Should not happen
LoginMode.Unsupported -> buildLoginUnsupportedForm()
LoginMode.Unknown, null -> Unit // Should not happen
}
private fun buildLoginPasswordForm(state: SoftLogoutViewState) {
@ -148,12 +148,12 @@ class SoftLogoutController @Inject constructor(
private fun disambiguateLoginSSOAndPasswordForm(state: SoftLogoutViewState) {
when (state.loginType) {
LoginType.PASSWORD -> buildLoginPasswordForm(state)
LoginType.SSO -> buildLoginSSOForm()
LoginType.PASSWORD -> buildLoginPasswordForm(state)
LoginType.SSO -> buildLoginSSOForm()
LoginType.DIRECT,
LoginType.CUSTOM,
LoginType.UNSUPPORTED -> buildLoginUnsupportedForm()
LoginType.UNKNOWN -> Unit
LoginType.UNKNOWN -> Unit
}
}

View file

@ -110,6 +110,7 @@ class SpaceDirectoryController @Inject constructor(
?.filter {
it.parentRoomId == (data.hierarchyStack.lastOrNull() ?: data.spaceId)
}
?.filterNot { it.isUpgradedRoom(data) }
?: emptyList()
if (flattenChildInfo.isEmpty()) {
@ -209,4 +210,7 @@ class SpaceDirectoryController @Inject constructor(
}
}
}
private fun SpaceChildInfo.isUpgradedRoom(data: SpaceDirectoryState) =
data.knownRoomSummaries.any { it.roomId == childRoomId && it.versioningState.isUpgraded() }
}

View file

@ -97,14 +97,14 @@
<string name="notice_room_server_acl_updated_was_banned">• الخوادِم المُطابقة لـ %s أُزيلت مِن قائمة الحظر.</string>
<string name="notice_room_server_acl_updated_banned">• الخوادِم المُطابقة لـ %s محظورة الآن.</string>
<string name="notice_room_server_acl_updated_ip_literals_allowed">• خوادِم مُطابقة IP الحرفية مسموحة الآن.</string>
<string name="notice_room_server_acl_updated_title_by_you">يَّرتَ خادِم الـACLs لهذه الغُرفة.</string>
<string name="notice_room_server_acl_updated_title">غيَّرَ %s خادِم الـACLs لهذه الغُرفة.</string>
<string name="notice_room_server_acl_set_ip_literals_not_allowed">• الخوادِم المطابقة للقيم الحرفية للـIP محظورة.</string>
<string name="notice_room_server_acl_set_allowed">• الخوادِم المُطابقة لـ %s مسموحة.</string>
<string name="notice_room_server_acl_updated_title_by_you">لقد قمت بتغيير قائمة الوصول لهذه الغُرفة.</string>
<string name="notice_room_server_acl_updated_title">قام %s بتغيير قائمة الوصول (ACL) لهذه الغُرفة.</string>
<string name="notice_room_server_acl_set_ip_literals_not_allowed">• الخوادِم المتطابقة من حيث بروتوكول الإنترنت (IP) المستخدم محظورة.</string>
<string name="notice_room_server_acl_set_allowed">• الخوادِم المُطابقة لـِ %s مسموحة.</string>
<string name="notice_room_server_acl_set_banned">• الخوادِم المُطابقة لـ %s محظورة.</string>
<string name="notice_room_server_acl_set_ip_literals_allowed">• الخوادِم المطابقة للقيم الحرفية للـIP مسموحة.</string>
<string name="notice_room_server_acl_set_title_by_you">عيَّنتَ خادِم الـACLs لهذه الغُرفة.</string>
<string name="notice_room_server_acl_set_title">عيَّنَ %s خادِم الـACLs لهذه الغُرفة.</string>
<string name="notice_room_server_acl_set_ip_literals_allowed">الخوادِم المتطابقة من حيث بروتوكول الإنترنت (IP) المستخدم مسموحة.</string>
<string name="notice_room_server_acl_set_title_by_you">لقد قمت بتعيين قائمة التحكم بالوصول لهذه الغُرفة.</string>
<string name="notice_room_server_acl_set_title">%s قام بتعيين قائمة التحكم بالوصول لهذه الغرفة.</string>
<string name="notice_direct_room_update_by_you">رقيتَ هُنا.</string>
<string name="notice_direct_room_update">رقّى %s هُنا.</string>
<string name="notice_made_future_direct_room_visibility_by_you">جعلتَ الرسائل المُستقبلية مرئية لـ %1$s</string>

View file

@ -21,7 +21,7 @@
<string name="notice_room_ban">%1$s ha vetat %2$s</string>
<string name="notice_room_withdraw">%1$s ha retirat la invitació de %2$s</string>
<string name="notice_avatar_url_changed">%1$s ha canviat la seva foto</string>
<string name="notice_made_future_room_visibility">%1$s ha establert la visibilitat de l\'històric futur de la sala a %2$s</string>
<string name="notice_made_future_room_visibility">%1$s ha activat la visualització de l\'històric de la sala (a partir d\'ara) a %2$s</string>
<string name="notice_room_visibility_joined">tots els participants de la sala, des de que s\'hi uneixen.</string>
<string name="notice_room_visibility_world_readable">qualsevol.</string>
<string name="notice_avatar_changed_too">(també ha canviat la foto)</string>
@ -153,7 +153,7 @@
<string name="notice_room_update">%s ha actualitzat aquesta sala.</string>
<string name="notice_made_future_direct_room_visibility_by_you">Has establert la visibilitat dels missatges futurs a %1$s</string>
<string name="notice_made_future_direct_room_visibility">%1$s ha establert la visibilitat dels missatges futurs a %2$s</string>
<string name="notice_made_future_room_visibility_by_you">Has establert la visibilitat de l\'històric futur de la sala a %1$s</string>
<string name="notice_made_future_room_visibility_by_you">Has establert la visibilitat de l\'històric de la sala (a partir d\'ara) a %1$s</string>
<string name="notice_ended_call_by_you">Has finalitzat la trucada.</string>
<string name="notice_answered_call_by_you">Has respost a la trucada.</string>
<string name="notice_call_candidates_by_you">Has enviat dades per configurar la trucada.</string>
@ -1055,7 +1055,7 @@
<string name="login_splash_text2">Utilitza el xifrat per mantenir els teus xats privats</string>
<string name="login_splash_title">Aquest xat és teu. Apropia-te\'n.</string>
<string name="room_filtering_filter_hint">Filtra xats…</string>
<string name="this_is_the_beginning_of_dm">Inici de l\'històric del xat personal amb %s.</string>
<string name="this_is_the_beginning_of_dm">Inici de l\'històric del xat directe amb %s.</string>
<string name="settings_hs_admin_e2e_disabled">L\'administrador del servidor ha desactivat el xifrat d\'extrem a extrem per defecte en sales privades i en xats directes.</string>
<string name="room_member_open_or_create_dm">Xat personal</string>
<string name="direct_room_profile_encrypted_subtitle">Els missatges d\'aquí estan xifrats d\'extrem a extrem.
@ -1064,7 +1064,7 @@
<string name="a11y_create_direct_message">Crea un nou xat personal</string>
<string name="room_filtering_footer_create_new_direct_message">Envia un nou missatge</string>
<string name="bottom_action_people_x">Xats directes</string>
<string name="direct_room_encryption_enabled_tile_description">Els missatges d\'aquesta sala estan xifrats d\'extrem a extrem.</string>
<string name="direct_room_encryption_enabled_tile_description">Els missatges d\'aquest xat estan xifrats d\'extrem a extrem.</string>
<string name="settings_labs_show_hidden_events_in_timeline">Mostra els esdeveniments amagats a la cronologia</string>
<string name="send_suggestion_failed">No s\'ha pogut enviat el suggeriment (%s)</string>
<string name="send_suggestion_sent">Gràcies, el suggeriment s\'ha enviat correctament</string>
@ -2482,7 +2482,7 @@
<string name="tooltip_attachment_photo">Obre càmera</string>
<string name="message_bubbles">Mostra els contorns dels missatges</string>
<string name="live_location_bottom_sheet_last_updated_at">Actualitzada fa %1$s</string>
<string name="labs_enable_live_location_summary">Implementació temporal: les ubicacions persisteixen a l\'historial de la sala</string>
<string name="labs_enable_live_location_summary">Implementació temporal: les ubicacions persisteixen a l\'històric de la sala</string>
<string name="space_leave_radio_buttons_title">Coses en aquest espai</string>
<string name="settings_autoplay_animated_images_summary">Reprodueix immediatament les imatges animades a la cronologia</string>
<string name="live_location_bottom_sheet_stop_sharing">Deixa de compartir</string>
@ -2529,4 +2529,10 @@
<string name="settings_troubleshoot_test_endpoint_registration_success">\'Endpoint\' registrat correctament al servidor.</string>
<string name="settings_troubleshoot_test_endpoint_registration_title">Registre d\'endpoint</string>
<string name="action_next">Següent</string>
</resources>
<string name="labs_enable_msc3061_share_history_desc">Quan convidis algú a una sala xifrada que comparteix l\'històric de missatges, aquest serà visible.</string>
<string name="poll_undisclosed_not_ended">Els resultats es mostraran quan acabi l\'enquesta</string>
<string name="labs_enable_msc3061_share_history">MSC3061: Compartició de claus de sala per missatges antics</string>
<string name="send_your_first_msg_to_invite">Envia un primer missatge per convidar %s a parlar</string>
<string name="direct_room_encryption_enabled_tile_description_future">Els missatges d\'aquest xat seran xifrats d\'extrem a extrem.</string>
<string name="create_room_action_go">Crea</string>
</resources>

View file

@ -2577,4 +2577,10 @@
<string name="settings_troubleshoot_test_endpoint_registration_success">Koncový bod byl úspěšně zaregistrován na domovském serveru.</string>
<string name="settings_troubleshoot_test_endpoint_registration_title">Registrace koncového bodu</string>
<string name="action_next">Další</string>
</resources>
<string name="poll_undisclosed_not_ended">Výsledky se zobrazí po ukončení hlasování</string>
<string name="labs_enable_msc3061_share_history_desc">Při pozvání do šifrované místnosti, která sdílí historii, bude zašifrovaná historie viditelná.</string>
<string name="labs_enable_msc3061_share_history">MSC3061: Sdílení klíčů místnosti pro minulé zprávy</string>
<string name="send_your_first_msg_to_invite">Odesláním první zprávy pozvete %s do místnosti</string>
<string name="direct_room_encryption_enabled_tile_description_future">Zprávy v této místnosti budou koncově šifrovány.</string>
<string name="create_room_action_go">Přejít</string>
</resources>

View file

@ -2528,4 +2528,5 @@
<string name="ftue_account_created_personalize">Profil personalisieren</string>
<string name="ftue_auth_carousel_workplace_body">${app_name} ist auch für den Arbeitsplatz geeignet. Die sichersten Organisationen der Welt vertrauen darauf.</string>
<string name="send_feedback_threads_info">Threads sind noch in Arbeit, und es stehen neue, aufregende Funktionen an, wie z. B. verbesserte Benachrichtigungen. Wir würden uns sehr über Dein Feedback freuen!</string>
</resources>
<string name="direct_room_encryption_enabled_tile_description_future">Nachrichten in diesem Chat werden End-zu-End-Verschlüsselt</string>
</resources>

View file

@ -1705,7 +1705,7 @@
<string name="bad_passphrase_key_reset_all_action">Kas sa unustasid või kaotasid kõik võimalused taastada ligipääsu oma kontole\? Lähtesta kõik seadistused</string>
<string name="direct_room_created_summary_item_by_you">Sina liitusid.</string>
<string name="direct_room_created_summary_item">%s liitus.</string>
<string name="direct_room_encryption_enabled_tile_description">See jututuba on läbivalt krüptitud.</string>
<string name="direct_room_encryption_enabled_tile_description">See vestlus on läbivalt krüptitud.</string>
<string name="direct_room_profile_section_more_leave">Lahku</string>
<string name="direct_room_profile_section_more_settings">Seadistused</string>
<string name="direct_room_profile_encrypted_subtitle">Sõnumid siin jututoas kasutavad läbivat krüptimist.
@ -2520,4 +2520,10 @@
<string name="unifiedpush_distributor_background_sync">Sünkroniseerimine taustal</string>
<string name="unifiedpush_distributor_fcm_fallback">Google\'i teenused</string>
<string name="unifiedpush_getdistributors_dialog_title">Vali teavituste laadimise viis</string>
</resources>
<string name="poll_undisclosed_not_ended">Tulemused on näha siis, kui küsitlus on lõppenud</string>
<string name="labs_enable_msc3061_share_history_desc">Kutsudes osalejaid krüptitud jututuppa, kus ajaloo jagamine on lubatud, on vanad sõnumid loetavad.</string>
<string name="labs_enable_msc3061_share_history">MSC3061: Minevikus saadetud sõnumite lugemiseks vajalike krüptovõtmete jagamine jututoas</string>
<string name="send_your_first_msg_to_invite">Saada oma esimene sõnum kutsudes %s vestlusesse</string>
<string name="direct_room_encryption_enabled_tile_description_future">See vestlus saab olema läbivalt krüptitud.</string>
<string name="create_room_action_go">Mine</string>
</resources>

View file

@ -1095,7 +1095,7 @@
<string name="direct_room_created_summary_item">%s پیوست.</string>
<string name="room_created_summary_item_by_you">اتاق را ساخته و پیکربندی کردید.</string>
<string name="encryption_not_enabled">رمزنگاری به کار نیفتاده</string>
<string name="direct_room_encryption_enabled_tile_description">پیام‌های این اتاق، رمزنگاری سرتاسری دارند.</string>
<string name="direct_room_encryption_enabled_tile_description">پیام‌های این گپ، رمزنگاری سرتاسری دارند.</string>
<string name="encryption_enabled_tile_description">پیام‌های این اتاق رمزنگاری سرتاسری دارند. در نمایهٔ کاربران تأییدشان کرده و بیش‌تر بیاموزید.</string>
<string name="encryption_enabled">رمزنگاری به کار افتاد</string>
<string name="settings_when_rooms_are_upgraded">هنگام ارتقای اتاق‌ها</string>
@ -1213,7 +1213,7 @@
<string name="settings_troubleshoot_test_token_registration_failed">شکست در ثبت ژتون FCM در کارساز خانگی:
\n%1$s</string>
<string name="settings_troubleshoot_test_token_registration_success">ژتون FCM با موفقیت در کارساز خانگی ثبت شد.</string>
<string name="settings_troubleshoot_test_token_registration_title">ثبت توکن</string>
<string name="settings_troubleshoot_test_token_registration_title">ثبت ژتون</string>
<string name="settings_troubleshoot_test_fcm_failed_account_missing_quick_fix">افزودن حساب کاربری</string>
<string name="settings_troubleshoot_test_fcm_failed_account_missing">[%1$s]
\nاین خطا خارج از مهار ${app_name} است. هیچ حساب گوگلی روی تلفن نیست. لطفاً مدیر حساب را گشوده و حساب گوگلی بیفزایید.</string>
@ -1221,11 +1221,11 @@
\nاین خطا خارج از مهار ${app_name} است و ممکن است به دلایل مختلفی رخ داده باشد. ممکن است اگر بعداً دوباره تلاش کنید، کار کند. می‌توانید بررسی کنید که مصرف دادهٔ خدمات پلی گوگل در تنظیمات سامانه محدود نشده باشد یا ساعت افزاره‌تان درست باشد. همچنین ممکن است روی رام‌های سفارشی اتفاق بیفتد.</string>
<string name="settings_troubleshoot_test_fcm_failed_too_many_registration">[%1$s]
\nاین خطا، خارج از مهار ${app_name} است و طبق گفتهٔ گوگل، نشانگر ثبت بیش‌از حد کاره‌ها در FCM است. خطا فقط در مواردی که تعداد خیلی زیادی کاره وجود داشته باشد رخ می‌دهد، پس کاربران معمولی نباید تحت تأثیر قرار گیرند.</string>
<string name="settings_troubleshoot_test_fcm_failed">بازیابی توکن FCM با مشکل مواجه شد:
<string name="settings_troubleshoot_test_fcm_failed">شکست در بازیابی ژتون FCM:
\n%1$s</string>
<string name="settings_troubleshoot_test_fcm_success">توکن FCM با موفقیت بازیابی شد:
<string name="settings_troubleshoot_test_fcm_success">ژتون FCM با موفقیت بازیابی شد:
\n%1$s</string>
<string name="settings_troubleshoot_test_fcm_title">توکن Firebase</string>
<string name="settings_troubleshoot_test_fcm_title">ژتون فایربیس</string>
<string name="settings_troubleshoot_test_play_services_quickfix">مشکل Google Play Services را برطرف کنید</string>
<string name="settings_troubleshoot_test_play_services_failed">المنت برای ارسال آگاهی‌ها از خدمات پلی گوگل استفاده می‌کند اما به نظر می‌رسد به درستی پیکربندی نشده است:
\n%1$s</string>
@ -1494,7 +1494,7 @@
<string name="settings_discovery_disconnect_identity_server_info">قطع ارتباط با سرور هویت‌سنجی به این معنی است که توسط کاربران دیگر قابل شناسایی نخواهید بود و نمی توانید دیگران را از طریق ایمیل یا تلفن دعوت کنید.</string>
<string name="settings_discovery_identity_server_info_none">در حال استفاده از کارساز هویتی نیستید. برای کشق و قابل کشف بودن به دست آشنایان موجودی که می‌شناسید، یک کارساز هویت در زیر پیکربندی کنید.</string>
<string name="settings_discovery_identity_server_info">دارید برای کشف و قابل کشف بودن به دست آشنایان موجودی که می‌شناسید از %1$s استفاده می‌کنید.</string>
<string name="settings_troubleshoot_test_token_registration_quick_fix">ثبت توکن</string>
<string name="settings_troubleshoot_test_token_registration_quick_fix">ثبت ژتون</string>
<string name="push_gateway_item_format">فرمت:</string>
<string name="push_gateway_item_url">آدرس:</string>
<string name="push_gateway_item_device_name">نام نشست:</string>
@ -2521,4 +2521,18 @@
<string name="settings_troubleshoot_test_endpoint_registration_quick_fix">بازنشانی روش آگاهی</string>
<string name="push_gateway_item_profile_tag">برچسب نمایه:</string>
<string name="action_next">بعدی</string>
</resources>
<string name="live_location_labs_promotion_description">لطفاً به خاطر داشته باشید: این یک ویژگی آزمایشگاهی با پیاده‌سازی موقّتی است. یعنی نخواهید توانست تاریخجهٔ مکانتان را حذف کرده و کاربران پیش‌رفته خواهند توانست حتا پس از پایان هم‌رسانی مکان زنده‌تان با این اتاق، تاریخچهٔ مکانتان را ببینند.</string>
<string name="settings_troubleshoot_test_current_endpoint_failed">نتوانست نقطهٔ پایانی را بیابد.</string>
<string name="settings_troubleshoot_test_current_endpoint_success">نقطهٔ پایانی کنونی: %s</string>
<string name="settings_troubleshoot_test_current_endpoint_title">نقطهٔ پایانی</string>
<string name="poll_undisclosed_not_ended">هنگام پایان نظرسنجی، نتایج نمایان خواهند شد</string>
<string name="labs_enable_msc3061_share_history_desc">هنگام دعوت به اتاقی رمزشده که تاریخچه‌ای هم‌رسانده دارد، تاریخچهٔ رمز شده نمایان خواهد بود.</string>
<string name="labs_enable_msc3061_share_history">MSC3061: هم‌رسانی کلیدهای اتاق برای پیام‌های گذشته</string>
<string name="send_your_first_msg_to_invite">نخستین پیامتان را برای دعوت %s به گپ بفرستید</string>
<string name="direct_room_encryption_enabled_tile_description_future">پیام‌های این گپ رمزنگاری سرتاسری خواهند شد.</string>
<string name="create_room_action_go">رفتن</string>
<string name="settings_troubleshoot_test_endpoint_registration_failed">شکست در ثبت ژتون نقطهٔ پایانی روی کارساز خانگی:
\n%1$s</string>
<string name="settings_troubleshoot_test_endpoint_registration_success">نقطهٔ پایانی با موفّقیت روی کارساز خانگی ثبت شد.</string>
<string name="settings_troubleshoot_test_endpoint_registration_title">ثبت نقطهٔ پایانی</string>
</resources>

View file

@ -2529,4 +2529,10 @@
<string name="settings_troubleshoot_test_endpoint_registration_success">Le point de connexion a été correctement enregistré sur le serveur daccueil.</string>
<string name="settings_troubleshoot_test_endpoint_registration_title">Enregistrement du point de connexion</string>
<string name="action_next">Suivant</string>
</resources>
<string name="poll_undisclosed_not_ended">Les résultats seront visibles lorsque le sondage sera terminé</string>
<string name="labs_enable_msc3061_share_history_desc">Lors de linvitation dans un salon chiffré qui partage son historique, son historique chiffré sera visible.</string>
<string name="labs_enable_msc3061_share_history">MSC3061 : Partage des clés du salon pour les messages passés</string>
<string name="send_your_first_msg_to_invite">Envoyez votre premier message pour inviter %s à discuter</string>
<string name="direct_room_encryption_enabled_tile_description_future">Les messages de ce salon seront chiffrés de bout en bout.</string>
<string name="create_room_action_go">Cest parti</string>
</resources>

View file

@ -1607,7 +1607,7 @@ A Visszaállítási Kulcsot tartsd biztonságos helyen, mint pl. egy jelszókeze
<string name="settings_emails_empty">Még nem adtál hozzá a fiókodhoz email címet</string>
<string name="settings_emails">Email címek</string>
<string name="settings_phone_number_empty">Még nem adtál hozzá telefonszámot a fiókodhoz</string>
<string name="direct_room_encryption_enabled_tile_description">Az üzenetek ebben a szobában végpontok közötti titkosítással védettek.</string>
<string name="direct_room_encryption_enabled_tile_description">Az üzenetek ebben a beszélgetésben végpontok közötti titkosítással védettek.</string>
<string name="attachment_type_dialog_title">Kép hozzáadása</string>
<string name="add_a_topic_link_text">Adj meg egy témát</string>
<string name="room_created_summary_no_topic_creation_text">%s, hogy a többiek tudják, miről van szó ebben a szobában!</string>
@ -2318,7 +2318,7 @@ A Visszaállítási Kulcsot tartsd biztonságos helyen, mint pl. egy jelszókeze
<string name="restart_the_application_to_apply_changes">A változások életbelépéséhez indítsd újra az alkalmazást.</string>
<string name="labs_enable_latex_maths">LaTeX matematikai szintaxis engedélyezése</string>
<string name="room_error_access_unauthorized">Nem léphetsz be ebbe a szobába</string>
<string name="ftue_auth_carousel_secure_title">Az ön beszélgetései csak az öné.</string>
<string name="ftue_auth_carousel_secure_title">Birtokold a beszélgetéseid.</string>
<string name="labs_auto_report_uisi_desc">Titkosítás visszafejtési hiba esemény alkalmával a rendszer automatikusan elküldi a logokat</string>
<string name="labs_auto_report_uisi">Titkosítás visszafejtési hibák automatikus jelentése.</string>
<string name="tooltip_attachment_poll">Szavazás létrehozása</string>
@ -2436,7 +2436,7 @@ A Visszaállítási Kulcsot tartsd biztonságos helyen, mint pl. egy jelszókeze
<string name="ftue_display_name_title">Válassz egy megjelenítési nevet</string>
<string name="ftue_account_created_subtitle">A fiókod elkészült: %s.</string>
<string name="ftue_account_created_congratulations_title">Gratulálunk!</string>
<string name="ftue_account_created_take_me_home">Vigyél haza</string>
<string name="ftue_account_created_take_me_home">A kezdőlapra</string>
<string name="ftue_account_created_personalize">Profil személyre szabása</string>
<string name="action_disable">Tiltás</string>
<string name="location_share_live_started">Élő földrajzi helyzet meghatározás betöltése…</string>
@ -2499,4 +2499,40 @@ A Visszaállítási Kulcsot tartsd biztonságos helyen, mint pl. egy jelszókeze
<string name="time_unit_second_short">mperc</string>
<string name="time_unit_minute_short">perc</string>
<string name="time_unit_hour_short">ó</string>
</resources>
<string name="live_location_labs_promotion_switch_title">Földrajzi hely megosztás engedélyezése</string>
<string name="live_location_labs_promotion_description">Figyelem: ez a labor lehetőség egy átmeneti megvalósítás. Ez azt jelenti, hogy a szobába már elküldött helyadatok az élő hely megosztás leállítása után is hozzáférhetők maradnak a szobában.</string>
<string name="live_location_labs_promotion_title">Élő földrajzi hely megosztása</string>
<string name="settings_troubleshoot_test_current_gateway">Jelenlegi átjáró: %s</string>
<string name="settings_troubleshoot_test_current_gateway_title">Átjáró (gateway)</string>
<string name="settings_troubleshoot_test_current_endpoint_failed">Nem található végpont.</string>
<string name="settings_troubleshoot_test_current_endpoint_success">Jelenlegi végpont: %s</string>
<string name="settings_troubleshoot_test_current_endpoint_title">Végpont</string>
<string name="settings_troubleshoot_test_current_distributor">Jelenleg használatban: %s.</string>
<string name="settings_troubleshoot_test_current_distributor_title">Metódus</string>
<plurals name="settings_troubleshoot_test_distributors_many">
<item quantity="one">%d beállítás található.</item>
<item quantity="other">%d beállítás található.</item>
</plurals>
<string name="settings_troubleshoot_test_distributors_fdroid">A háttér szinkronizációs szolgáltatástól eltérő beállítási lehetőség nem érhető el.</string>
<string name="settings_troubleshoot_test_distributors_gplay">A Google Play szolgáltatástól eltérő beállítási lehetőség nem érhető el.</string>
<string name="settings_troubleshoot_test_distributors_title">Elérhető beállítások</string>
<string name="settings_notification_method">Értesítési beállítások</string>
<string name="unifiedpush_distributor_background_sync">Szinkronizálás a háttérben</string>
<string name="unifiedpush_distributor_fcm_fallback">Google szolgáltatások</string>
<string name="unifiedpush_getdistributors_dialog_title">Válaszd ki, hogyan szeretnél értesítéseket kapni</string>
<string name="poll_undisclosed_not_ended">Az eredmény a szavazás végeztével válik láthatóvá</string>
<string name="labs_enable_msc3061_share_history_desc">Ha olyan titkosított szobába hívsz meg valakit ahol a régi üzenetek megosztása engedélyezett a régi titkosított üzenetek is láthatóak lesznek a meghívott számára.</string>
<string name="labs_enable_msc3061_share_history">MSC3061: Szoba kulcsok megosztása a régi üzenetekhez</string>
<string name="settings_security_pin_code_use_biometrics_error">A biometrikus azonosítást nem lehet engedélyezni.</string>
<string name="auth_biometric_key_invalidated_message">A biometrikus azonosítás kikapcsolásra került mivel egy új biometrikus azonosítási metódus került hozzáadásra. Újra engedélyezheted a Beállításokban.</string>
<string name="send_your_first_msg_to_invite">Az első üzeneteddel hívd meg ide őt: %s</string>
<string name="direct_room_encryption_enabled_tile_description_future">Az üzenetek ebben a beszélgetésben végpontok közötti titkosítással lesznek védve.</string>
<string name="settings_troubleshoot_test_endpoint_registration_quick_fix">Értesítési metódus visszaállítása</string>
<string name="push_gateway_item_profile_tag">Profil címke:</string>
<string name="create_room_action_go">Menj</string>
<string name="settings_troubleshoot_test_endpoint_registration_failed">Végpont token regisztrációja sikertelen a Matrix-kiszolgálón:
\n%1$s</string>
<string name="settings_troubleshoot_test_endpoint_registration_success">Végpont sikeresen regisztrálva lett a matrix szerveren.</string>
<string name="settings_troubleshoot_test_endpoint_registration_title">Végpont regisztráció</string>
<string name="action_next">Következő</string>
</resources>

View file

@ -2032,7 +2032,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan.</string>
<string name="room_created_summary_item_by_you">Anda membuat dan mengatur ruangan ini.</string>
<string name="room_created_summary_item">%s membuat dan mengatur ruangan ini.</string>
<string name="encryption_not_enabled">Enkripsi tidak diaktifkan</string>
<string name="direct_room_encryption_enabled_tile_description">Pesan di ruangan ini dienkripsi secara ujung-ke-ujung.</string>
<string name="direct_room_encryption_enabled_tile_description">Pesan di obrolan ini dienkripsi secara ujung-ke-ujung.</string>
<string name="encryption_enabled_tile_description">Pesan di ruangan ini dienkripsi secara ujung-ke-ujung. Pelajari lebih lanjut &amp; verifikasi pengguna di profil mereka.</string>
<string name="encryption_enabled">Enkripsi diaktifkan</string>
<string name="bootstrap_cancel_text">Jika Anda batalkan, Anda mungkin kehilangan pesan terenkripsi dan data Anda jika Anda kehilangan akses ke login Anda.
@ -2483,4 +2483,10 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan.</string>
<string name="settings_troubleshoot_test_endpoint_registration_success">Endpoint berhasil terdaftar ke homeserver.</string>
<string name="settings_troubleshoot_test_endpoint_registration_title">Pendaftaran Endpoint</string>
<string name="action_next">Lanjut</string>
</resources>
<string name="poll_undisclosed_not_ended">Hasil akan ditampilkan ketika pemungutan suara berakhir</string>
<string name="labs_enable_msc3061_share_history_desc">Ketika mengundang ke ruangan terenkripsi yang juga membagikan riwayat, riwayat terenkripsi akan dapat dilihat.</string>
<string name="labs_enable_msc3061_share_history">MSC3061: Pembagian kunci ruangan untuk pesan lama</string>
<string name="send_your_first_msg_to_invite">Kirim pesan pertama Anda untuk mengundang %s ke obrolan</string>
<string name="direct_room_encryption_enabled_tile_description_future">Pesan di obrolan ini akan dienkripsi secara ujung-ke-ujung.</string>
<string name="create_room_action_go">Mulai</string>
</resources>

View file

@ -764,7 +764,7 @@
<string name="upgrade_security">Uppfærsla dulritunar tiltæk</string>
<string name="command_description_plain">Sendir skilaboð sem óbreyttur texti án þess að túlka það sem markdown</string>
<string name="encryption_not_enabled">Dulritun ekki virk</string>
<string name="direct_room_encryption_enabled_tile_description">Skilaboð í þessari spjallrás eru enda-í-enda dulrituð.</string>
<string name="direct_room_encryption_enabled_tile_description">Skilaboð í þessu spjalli eru enda-í-enda dulrituð.</string>
<string name="settings_hs_admin_e2e_disabled">Kerfisstjóri netþjónsins þíns hefur lokað á sjálfvirka dulritun í einkaspjallrásum og beinum skilaboðum.</string>
<string name="room_profile_section_more_settings">Stillingar spjallrásar</string>
<string name="room_profile_not_encrypted_subtitle">Skilaboð í þessari spjallrás eru ekki enda-í-enda dulrituð.</string>
@ -1292,7 +1292,7 @@
<string name="keys_backup_setup_step3_button_title">Lokið</string>
<string name="keys_backup_setup_step3_success_title">Tókst !</string>
<string name="keys_backup_setup_step1_advanced">(Ítarlegt)</string>
<string name="x_plus">%d+</string>
<string name="x_plus">+%d</string>
<string name="generic_label_and_value">%1$s: %2$s</string>
<string name="merged_events_collapse">fella saman</string>
<string name="merged_events_expand">fletta út</string>
@ -2017,4 +2017,4 @@
<string name="action_try_it_out">Prófaðu það</string>
<string name="action_disable">Gera óvirkt</string>
<string name="initial_sync_request_title">Upphafleg samstillingarbeiðni</string>
</resources>
</resources>

View file

@ -1692,7 +1692,7 @@
<string name="secure_backup_reset_all">Reimposta tutto</string>
<string name="bad_passphrase_key_reset_all_action">Hai dimenticato o perso tutte le opzioni di ripristino\? Reimposta tutto</string>
<string name="direct_room_created_summary_item_by_you">Sei entrato.</string>
<string name="direct_room_encryption_enabled_tile_description">I messaggi in questa stanza sono crittografati E2E.</string>
<string name="direct_room_encryption_enabled_tile_description">I messaggi in questa conversazione sono cifrati end-to-end.</string>
<string name="direct_room_profile_section_more_leave">Esci</string>
<string name="direct_room_profile_section_more_settings">Impostazioni</string>
<string name="direct_room_profile_encrypted_subtitle">I messaggi qui sono cifrati E2E.
@ -2520,4 +2520,10 @@
<string name="settings_troubleshoot_test_endpoint_registration_success">Endpoint registrato con successo sull\'homeserver.</string>
<string name="settings_troubleshoot_test_endpoint_registration_title">Registrazione endpoint</string>
<string name="action_next">Avanti</string>
</resources>
<string name="poll_undisclosed_not_ended">I risultati saranno visibili quando il sondaggio sarà terminato</string>
<string name="labs_enable_msc3061_share_history_desc">Quando si invita in una stanza crittografata che condivide la cronologia, la cronologia cifrata sarà visibile.</string>
<string name="labs_enable_msc3061_share_history">MSC3061: Condivisione chiavi stanza per messaggi passati</string>
<string name="send_your_first_msg_to_invite">Invia il primo messaggio per invitare %s a parlare</string>
<string name="direct_room_encryption_enabled_tile_description_future">I messaggi in questa conversazione saranno cifrati end-to-end.</string>
<string name="create_room_action_go">Vai</string>
</resources>

View file

@ -1927,7 +1927,7 @@
<string name="room_created_summary_item">%s heeft de kamer gemaakt en geconfigureerd.</string>
<string name="encryption_unknown_algorithm_tile_description">De versleuteling die door deze kamer wordt gebruikt, wordt niet ondersteund</string>
<string name="encryption_not_enabled">Versleuteling niet ingeschakeld</string>
<string name="direct_room_encryption_enabled_tile_description">Berichten in deze kamer zijn end-to-end-versleuteld.</string>
<string name="direct_room_encryption_enabled_tile_description">Berichten in deze chat zijn end-to-end-versleuteld.</string>
<string name="encryption_enabled_tile_description">Berichten in deze kamer zijn eind-tot-eind-versleuteld. Lees meer en verifieer persoon in hun profiel.</string>
<string name="bootstrap_cancel_text">Als u nu annuleert, kunt u versleutelde berichten en gegevens kwijtraken als u de toegang tot uw aanmeldingen verliest.
\n
@ -2529,4 +2529,10 @@
<string name="settings_troubleshoot_test_endpoint_registration_success">Eindpunt succesvol geregistreerd bij server.</string>
<string name="settings_troubleshoot_test_endpoint_registration_title">Registratie van eindpunt</string>
<string name="action_next">Volgende</string>
</resources>
<string name="poll_undisclosed_not_ended">Resultaten zijn zichtbaar wanneer de poll is afgelopen</string>
<string name="labs_enable_msc3061_share_history_desc">Bij het uitnodigen in een versleutelde ruimte die geschiedenis deelt, is de versleutelde geschiedenis zichtbaar.</string>
<string name="labs_enable_msc3061_share_history">MSC3061: Kamersleutels delen voor eerdere berichten</string>
<string name="send_your_first_msg_to_invite">Stuur uw eerste bericht om %s uit te nodigen om te chatten</string>
<string name="direct_room_encryption_enabled_tile_description_future">Berichten in deze chat worden eind-tot-eind versleuteld.</string>
<string name="create_room_action_go">Ga</string>
</resources>

View file

@ -1163,9 +1163,9 @@
<item quantity="other">Wyślij obrazów w oryginalnym rozmiarze</item>
</plurals>
<string name="delete_event_dialog_title">Potwierdź Usunięcie</string>
<string name="delete_event_dialog_content">Jesteś pewny(-na), że chcesz usunąć to wydarzenie\? Jeżeli usuniesz nazwę pokoju lub zmienisz temat, wciąż będzie możliwe cofnięcie zmiany.</string>
<string name="delete_event_dialog_content">Czy na pewno chcesz usunąć to wydarzenie\? Pamiętaj, że skasowanie nazwy pokoju lub zmiana jego tematu może czasem je przywrócić.</string>
<string name="delete_event_dialog_reason_checkbox">Podaj przyczynę</string>
<string name="delete_event_dialog_reason_hint">Przyczyna reakcji</string>
<string name="delete_event_dialog_reason_hint">Powód usunięcia</string>
<string name="event_redacted_by_user_reason_with_reason">Wydarzenie usunięte przez użytkownika, przyczyna: %1$s</string>
<string name="event_redacted_by_admin_reason_with_reason">Wydarzenie moderowane przez administratora pokoju, przyczyna: %1$s</string>
<string name="keys_backup_restore_success_title_already_up_to_date">Klucze są już aktualne!</string>
@ -2605,4 +2605,4 @@
<string name="settings_troubleshoot_test_distributors_title">Dostępni dostawcy</string>
<string name="settings_notification_method">Dostawca powiadomień</string>
<string name="unifiedpush_getdistributors_dialog_title">Wybierz, którego dostawcy powiadomień push chcesz używać</string>
</resources>
</resources>

View file

@ -1810,7 +1810,7 @@
<string name="invite_friends_text">Ahoj, ozvi sa mi na ${app_name}: %s</string>
<string name="create_room_dm_failure">Nemohli sme vytvoriť vašu priamu správu. Skontrolujte používateľov, ktorých chcete pozvať, a skúste to znova.</string>
<string name="notice_crypto_unable_to_decrypt_friendly_desc">Kvôli end-to-end šifrovaniu sa môže stať, že budete musieť chvíľu počkať, kým vám od niekoho príde správa, pretože vám neboli správne odoslané šifrovacie kľúče.</string>
<string name="direct_room_encryption_enabled_tile_description">Správy v tejto miestnosti sú šifrované od vás až k príjemcovi.</string>
<string name="direct_room_encryption_enabled_tile_description">Správy v tejto konverzácii sú šifrované od vás až k príjemcovi.</string>
<string name="encryption_enabled_tile_description">Správy v tejto miestnosti sú end-to-end šifrované. Zistite viac a overte používateľov v ich profile.</string>
<string name="settings_hs_admin_e2e_disabled">Správca vášho servera predvolene vypol end-to-end šifrovanie v súkromných miestnostiach a v priamych správach.</string>
<string name="verification_conclusion_ok_notice">Správy s týmto používateľom sú end-to-end šifrované a tretie strany ich nemôžu čítať.</string>
@ -2577,4 +2577,10 @@
<string name="settings_troubleshoot_test_endpoint_registration_success">Koncové zariadenie sa úspešne zaregistrovalo na domovský server.</string>
<string name="settings_troubleshoot_test_endpoint_registration_title">Registrácia koncového bodu</string>
<string name="action_next">Ďalej</string>
</resources>
<string name="poll_undisclosed_not_ended">Výsledky budú viditeľné po ukončení ankety</string>
<string name="labs_enable_msc3061_share_history_desc">Pri pozvaní do zašifrovanej miestnosti, ktorá zdieľa históriu, bude zašifrovaná história viditeľná.</string>
<string name="labs_enable_msc3061_share_history">MSC3061: Zdieľanie kľúčov od miestnosti pre staršie správy</string>
<string name="send_your_first_msg_to_invite">Odošlite svoju prvú správu a pozvite %s do konverzácie</string>
<string name="direct_room_encryption_enabled_tile_description_future">Správy v tejto miestnosti sú šifrované od vás až k príjemcovi.</string>
<string name="create_room_action_go">Spustiť</string>
</resources>

View file

@ -1706,7 +1706,7 @@
<string name="direct_room_profile_section_more_leave">Lämna</string>
<string name="secure_backup_reset_all">Återställ allt</string>
<string name="direct_room_created_summary_item_by_you">Du gick med.</string>
<string name="direct_room_encryption_enabled_tile_description">Meddelanden i det här rummet är totalsträckskrypterade.</string>
<string name="direct_room_encryption_enabled_tile_description">Meddelanden i den här chatten är totalsträckskrypterade.</string>
<string name="direct_room_profile_section_more_settings">Inställningar</string>
<string name="direct_room_profile_encrypted_subtitle">Meddelanden här är totalsträckskrypterade.
\n
@ -2529,4 +2529,10 @@
\n%1$s</string>
<string name="settings_troubleshoot_test_endpoint_registration_success">Lyckades registrera ändpunkten hos hemservern.</string>
<string name="settings_troubleshoot_test_endpoint_registration_title">Ändpunktsregistrering</string>
</resources>
<string name="poll_undisclosed_not_ended">Resultat kommer att synas när omröstningen avslutas</string>
<string name="labs_enable_msc3061_share_history_desc">När du bjuder in i ett krypterat rum som delar historik, så kommer krypterad historik att vara synlig.</string>
<string name="labs_enable_msc3061_share_history">MSC3061: Delar rumsnycklar för tidigare meddelanden</string>
<string name="send_your_first_msg_to_invite">Skicka ditt första meddelande för att bjuda in %s att chatta</string>
<string name="direct_room_encryption_enabled_tile_description_future">Meddelanden i den här chatten kommer att vara totalsträckskrypterade.</string>
<string name="create_room_action_go"></string>
</resources>

View file

@ -22,7 +22,7 @@
<string name="notice_placed_video_call">%s починає відеовиклик.</string>
<string name="notice_placed_voice_call">%s розпочинає голосовий виклик.</string>
<string name="notice_answered_call">%s відповідає на виклик.</string>
<string name="notice_ended_call">%s завершує дзвінок.</string>
<string name="notice_ended_call">%s завершує виклик.</string>
<string name="notice_made_future_room_visibility">%1$s робить майбутню історію кімнати видимою для %2$s</string>
<string name="notice_room_visibility_invited">всіх учасників кімнати, з моменту їх запрошення.</string>
<string name="notice_room_visibility_joined">всіх учасників кімнати, з моменту їх приєднання.</string>
@ -135,7 +135,7 @@
<string name="notice_made_future_room_visibility_by_you">Ви зробили майбутню історію кімнати видимою для %1$s</string>
<string name="notice_made_future_direct_room_visibility_by_you">Ви зробили майбутні повідомлення видимими для %1$s</string>
<string name="notice_made_future_direct_room_visibility">%1$s робить майбутні повідомлення видимими для %2$s</string>
<string name="notice_ended_call_by_you">Ви завершили дзвінок.</string>
<string name="notice_ended_call_by_you">Ви завершили виклик.</string>
<string name="notice_answered_call_by_you">Ви відповіли на виклик.</string>
<string name="notice_call_candidates_by_you">Ви надіслали дані для налаштування виклику.</string>
<string name="notice_call_candidates">%s надсилає дані для налаштування виклику.</string>
@ -230,8 +230,10 @@
<string name="call_in_progress">Виконується виклик…</string>
<string name="call_error_user_not_responding">Абонент не відповідає.</string>
<string name="permissions_rationale_popup_title">Інформація</string>
<string name="permissions_rationale_msg_record_audio">Для здійснення аудіодзвінків потрібен доступ до мікрофону.</string>
<string name="permissions_rationale_msg_camera_and_audio">Для здійснення відеодзвінків потрібен доступ до камери та мікрофону.\n\nБудь ласка, надайте його у наступних виринаючих вікнах, щоб мати змогу їх здійснити.</string>
<string name="permissions_rationale_msg_record_audio">Для здійснення аудіовикликів потрібен доступ до мікрофона.</string>
<string name="permissions_rationale_msg_camera_and_audio">Для здійснення відеовикликів потрібен доступ до камери та мікрофону.
\n
\nНадайте його у наступних спливних вікнах, щоб мати змогу їх здійснити.</string>
<string name="yes">ТАК</string>
<string name="no">НІ</string>
<string name="_continue">Продовжити</string>
@ -406,7 +408,7 @@
<string name="notification_noisy">Гучно</string>
<string name="encrypted_message">Зашифроване повідомлення</string>
<string name="settings_labs_native_camera">Використовувати рідну камеру</string>
<string name="you_added_a_new_device">Щойно доданий вами пристрій \'%s\' править ключі шифрування.</string>
<string name="you_added_a_new_device">Щойно доданий вами сеанс «%s», який запитує ключі шифрування.</string>
<string name="your_unverified_device_requesting">Ваш незвірений пристрій «%s» вимагає ключі шифрування.</string>
<string name="start_verification">Почати перевірку</string>
<string name="command_error">Помилка виконання команди</string>
@ -600,13 +602,13 @@
<string name="action_skip">Пропустити</string>
<string name="failed_to_remove_widget">Не вдалося видалити віджет</string>
<string name="failed_to_add_widget">Не вдалося додати віджет</string>
<string name="cannot_call_yourself">Ви не можете здійснити дзвінок із самим собою</string>
<string name="cannot_call_yourself">Ви не можете викликати самих себе</string>
<string name="audio_meeting">Почати аудіо-зустріч</string>
<string name="video_meeting">Почати відеозустріч</string>
<string name="no_permissions_to_start_webrtc_call_in_direct_room">У вас немає повноважень розпочати дзвінок</string>
<string name="no_permissions_to_start_webrtc_call">У вас немає повноважень на дзвінок у цій кімнаті</string>
<string name="no_permissions_to_start_conf_call_in_direct_room">У вас немає повноважень розпочати груповий виклик</string>
<string name="no_permissions_to_start_conf_call">У вас немає повноважень розпочати груповий виклик у цій кімнаті</string>
<string name="no_permissions_to_start_webrtc_call_in_direct_room">У вас немає дозволу розпочати виклик</string>
<string name="no_permissions_to_start_webrtc_call">У вас немає дозволу розпочати виклик у цій кімнаті</string>
<string name="no_permissions_to_start_conf_call_in_direct_room">У вас немає дозволу розпочати груповий виклик</string>
<string name="no_permissions_to_start_conf_call">У вас немає дозволу розпочати груповий виклик у цій кімнаті</string>
<string name="action_reset">Скинути</string>
<string name="action_dismiss">Відхилити</string>
<string name="action_play">Грати</string>
@ -628,7 +630,7 @@
<string name="sign_out_bottom_sheet_dont_want_secure_messages">Мені не потрібні мої зашифровані повідомлення</string>
<string name="warning_unsaved_change_discard">Скасувати зміни</string>
<string name="login_error_ssl_other">Помилка SSL.</string>
<string name="cannot_call_yourself_with_invite">Ви не можете здійснити дзвінок із самим собою, дочекайтесь, доки інші учасники приймуть ваше запрошення</string>
<string name="cannot_call_yourself_with_invite">Ви не можете викликати себе самих, дочекайтесь, доки інші учасники погодяться на ваше запрошення</string>
<string name="uploads_files_title">ФАЙЛИ</string>
<string name="uploads_media_no_result">У цій кімнаті немає медіа</string>
<string name="uploads_media_title">МЕДІА</string>
@ -1005,9 +1007,9 @@
\n
\nВи можете будь-коли змінити цю дію в загальних налаштуваннях.</string>
<string name="room_participants_action_ignore_title">Нехтувати користувача</string>
<string name="room_participants_power_level_demote">Понизити</string>
<string name="room_participants_power_level_demote_warning_prompt">Ви не зможете скасувати цю зміну, оскільки понижуєте свої права, якщо ви останній привілейований користувач у кімнаті, неможливо буде повернути собі привілеї.</string>
<string name="room_participants_power_level_demote_warning_title">Понизитися\?</string>
<string name="room_participants_power_level_demote">Зменшити</string>
<string name="room_participants_power_level_demote_warning_prompt">Ви не зможете скасувати цю зміну, оскільки зменшуєте свої повноваження, якщо ви останній привілейований користувач у кімнаті, неможливо буде повернути собі повноваження.</string>
<string name="room_participants_power_level_demote_warning_title">Зменшити свої повноваження\?</string>
<string name="permissions_denied_add_contact">Дозволити доступ до ваших контактів.</string>
<string name="permissions_denied_qr_code">Щоб сканувати QR-код необхідно дозволити доступ до камери.</string>
<string name="video_call_in_progress">Триває відеовиклик…</string>
@ -1074,7 +1076,7 @@
<string name="room_profile_not_encrypted_subtitle">Повідомлення в цій кімнаті не захищено наскрізним шифруванням.</string>
<string name="direct_room_profile_not_encrypted_subtitle">Повідомлення тут не захищено наскрізним шифруванням.</string>
<string name="room_settings_enable_encryption">Увімкнути наскрізне шифрування…</string>
<string name="direct_room_encryption_enabled_tile_description">Повідомлення в цій кімнаті захищені наскрізним шифруванням.</string>
<string name="direct_room_encryption_enabled_tile_description">Повідомлення в цій бесіді захищені наскрізним шифруванням.</string>
<string name="verification_verify_device">Звірити цей сеанс</string>
<string name="settings_active_sessions_unverified_device_desc">Звірте цей сеанс, щоб позначити його надійним та надати йому доступ до зашифрованих повідомлень. Якщо ви не входили в цей сеанс, ваш обліковий запис може бути зламано:</string>
<string name="room_directory_search_hint">Назва або ID (#example:matrix.org)</string>
@ -1152,8 +1154,8 @@
<string name="send_a_sticker">Наліпка</string>
<string name="terms_description_for_integration_manager">Використовувати ботів, мости, віджети та пакунки наліпок</string>
<string name="no_connectivity_to_the_server_indicator">Зв\'язок із сервером втрачено</string>
<string name="no_message_edits_found">Не знайдено жодної правки</string>
<string name="message_edits">Історія правок</string>
<string name="no_message_edits_found">Виправлень не знайдено</string>
<string name="message_edits">Історія виправлень</string>
<string name="a11y_trust_level_trusted">Рівень довіри</string>
<string name="not_trusted">Не довірений</string>
<string name="trusted">Довірений</string>
@ -2461,7 +2463,7 @@
<string name="ftue_auth_use_case_title">З ким ви спілкуватиметеся найчастіше\?</string>
<string name="navigate_to_thread_when_already_in_the_thread">Ви вже переглядаєте цю гілку!</string>
<string name="view_in_room">Переглянути у кімнаті</string>
<string name="reply_in_thread">Відповісти у гілку</string>
<string name="reply_in_thread">Відповісти в гілці</string>
<string name="command_not_supported_in_threads">Команду «%s» розпізнано, але вона не підтримується в гілках.</string>
<string name="search_thread_from_a_thread">З гілки</string>
<string name="thread_list_empty_notice">Порада: Торкніться й утримуйте повідомлення і виберіть «%s».</string>
@ -2623,4 +2625,10 @@
<string name="settings_troubleshoot_test_endpoint_registration_success">Кінцеву точку успішно зареєстровано на домашньому сервері.</string>
<string name="settings_troubleshoot_test_endpoint_registration_title">Реєстрація кінцевої точки</string>
<string name="action_next">Далі</string>
</resources>
<string name="poll_undisclosed_not_ended">Результати будуть видимі після завершення опитування</string>
<string name="labs_enable_msc3061_share_history_desc">Коли запросити когось у зашифровану кімнату, яка поширює історію, зашифрована історія буде видимою.</string>
<string name="labs_enable_msc3061_share_history">MSC3061: Поширення ключів кімнати для минулих повідомлень</string>
<string name="send_your_first_msg_to_invite">Надішліть своє перше повідомлення, щоб запросити %s до бесіди</string>
<string name="direct_room_encryption_enabled_tile_description_future">Повідомлення в цій бесіді будуть захищені наскрізним шифруванням.</string>
<string name="create_room_action_go">Уперед</string>
</resources>

Some files were not shown because too many files have changed in this diff Show more