forked from GitHub-Mirror/riotX-android
Compare commits
45 Commits
feature/no
...
develop
Author | SHA1 | Date | |
---|---|---|---|
|
f2c8d4ad02 | ||
|
be524472ec | ||
|
1b82a1a24d | ||
|
cf0b331c3b | ||
|
2a92a3dc80 | ||
|
012840abba | ||
|
a5975a099e | ||
|
38da4b9ee5 | ||
|
242e60fcaa | ||
|
a23be05cbf | ||
|
ed39b02924 | ||
|
fe931b5361 | ||
|
90d9cd0587 | ||
|
9cedb18921 | ||
|
e89ba7b87b | ||
|
902657c22a | ||
|
eec2abf164 | ||
|
6879cc8ca8 | ||
|
fd6bbbd3b5 | ||
|
0ff0b014a9 | ||
|
fdc9e84dd5 | ||
|
58f878fca9 | ||
|
88095e4bd9 | ||
|
47d22a3d5e | ||
|
28e82cb8ea | ||
|
35817245cb | ||
|
75266f42bb | ||
|
95c4c9ce56 | ||
|
ce5570105d | ||
|
188a9aebfa | ||
|
c95223f5d2 | ||
|
ef0362ba9c | ||
|
ea242f6737 | ||
|
cbc08d834b | ||
|
0ab6b33fb6 | ||
|
1b394527b6 | ||
|
a8f1388721 | ||
|
166be4e289 | ||
|
b49ccefe63 | ||
|
825760d17e | ||
|
b5af62c3ea | ||
|
a51d96bf00 | ||
|
456908c851 | ||
|
215324a03e | ||
|
02e342849f |
36
CHANGES.md
36
CHANGES.md
@ -1,3 +1,26 @@
|
|||||||
|
Changes in RiotX 0.5.0 (2019-XX-XX)
|
||||||
|
===================================================
|
||||||
|
|
||||||
|
Features:
|
||||||
|
-
|
||||||
|
|
||||||
|
Improvements:
|
||||||
|
- Reduce default release build log level, and lab option to enable more logs.
|
||||||
|
|
||||||
|
Other changes:
|
||||||
|
-
|
||||||
|
|
||||||
|
Bugfix:
|
||||||
|
- Fix crash due to missing informationData (#535)
|
||||||
|
- Progress in initial sync dialog is decreasing for a step and should not (#532)
|
||||||
|
|
||||||
|
Translations:
|
||||||
|
-
|
||||||
|
|
||||||
|
Build:
|
||||||
|
- Fix issue with version name (#533)
|
||||||
|
- Fix rendering issue of accepted third party invitation event
|
||||||
|
|
||||||
Changes in RiotX 0.4.0 (2019-XX-XX)
|
Changes in RiotX 0.4.0 (2019-XX-XX)
|
||||||
===================================================
|
===================================================
|
||||||
|
|
||||||
@ -7,19 +30,14 @@ Features:
|
|||||||
Improvements:
|
Improvements:
|
||||||
- Reactions: Reinstate the ability to react with non-unicode keys (#307)
|
- Reactions: Reinstate the ability to react with non-unicode keys (#307)
|
||||||
|
|
||||||
Other changes:
|
|
||||||
-
|
|
||||||
|
|
||||||
Bugfix:
|
Bugfix:
|
||||||
- Fix text diff linebreak display (#441)
|
- Fix text diff linebreak display (#441)
|
||||||
- Date change message repeats for each redaction until a normal message (#358)
|
- Date change message repeats for each redaction until a normal message (#358)
|
||||||
- Slide-in reply icon is distorted (#423)
|
- Slide-in reply icon is distorted (#423)
|
||||||
|
- Regression / e2e replies not encrypted
|
||||||
Translations:
|
- Some video won't play
|
||||||
-
|
- Privacy: remove log of notifiable event (#519)
|
||||||
|
- Fix crash with EmojiCompat (#530)
|
||||||
Build:
|
|
||||||
-
|
|
||||||
|
|
||||||
Changes in RiotX 0.3.0 (2019-08-08)
|
Changes in RiotX 0.3.0 (2019-08-08)
|
||||||
===================================================
|
===================================================
|
||||||
|
@ -21,7 +21,7 @@ import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
|
|||||||
import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStore
|
import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStore
|
||||||
import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStoreModule
|
import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStoreModule
|
||||||
import io.realm.RealmConfiguration
|
import io.realm.RealmConfiguration
|
||||||
import java.util.*
|
import kotlin.random.Random
|
||||||
|
|
||||||
internal class CryptoStoreHelper {
|
internal class CryptoStoreHelper {
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ internal class CryptoStoreHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun createCredential() = Credentials(
|
fun createCredential() = Credentials(
|
||||||
userId = "userId_" + Random().nextInt(),
|
userId = "userId_" + Random.nextInt(),
|
||||||
homeServer = "http://matrix.org",
|
homeServer = "http://matrix.org",
|
||||||
accessToken = "access_token",
|
accessToken = "access_token",
|
||||||
refreshToken = null,
|
refreshToken = null,
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
package im.vector.matrix.android.api.comparators
|
package im.vector.matrix.android.api.comparators
|
||||||
|
|
||||||
import im.vector.matrix.android.api.interfaces.DatedObject
|
import im.vector.matrix.android.api.interfaces.DatedObject
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
object DatedObjectComparators {
|
object DatedObjectComparators {
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ package im.vector.matrix.android.api.extensions
|
|||||||
import im.vector.matrix.android.api.comparators.DatedObjectComparators
|
import im.vector.matrix.android.api.comparators.DatedObjectComparators
|
||||||
import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo
|
import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.DeviceInfo
|
import im.vector.matrix.android.internal.crypto.model.rest.DeviceInfo
|
||||||
import java.util.*
|
import java.util.Collections
|
||||||
|
|
||||||
/* ==========================================================================================
|
/* ==========================================================================================
|
||||||
* MXDeviceInfo
|
* MXDeviceInfo
|
||||||
|
@ -18,18 +18,17 @@ package im.vector.matrix.android.api.pushrules
|
|||||||
import im.vector.matrix.android.api.session.events.model.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.api.session.room.RoomService
|
import im.vector.matrix.android.api.session.room.RoomService
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.regex.Pattern
|
|
||||||
|
|
||||||
private val regex = Pattern.compile("^(==|<=|>=|<|>)?(\\d*)$")
|
private val regex = Regex("^(==|<=|>=|<|>)?(\\d*)$")
|
||||||
|
|
||||||
class RoomMemberCountCondition(val `is`: String) : Condition(Kind.room_member_count) {
|
class RoomMemberCountCondition(val iz: String) : Condition(Kind.room_member_count) {
|
||||||
|
|
||||||
override fun isSatisfied(conditionResolver: ConditionResolver): Boolean {
|
override fun isSatisfied(conditionResolver: ConditionResolver): Boolean {
|
||||||
return conditionResolver.resolveRoomMemberCountCondition(this)
|
return conditionResolver.resolveRoomMemberCountCondition(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun technicalDescription(): String {
|
override fun technicalDescription(): String {
|
||||||
return "Room member count is $`is`"
|
return "Room member count is $iz"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isSatisfied(event: Event, session: RoomService?): Boolean {
|
fun isSatisfied(event: Event, session: RoomService?): Boolean {
|
||||||
@ -56,12 +55,9 @@ class RoomMemberCountCondition(val `is`: String) : Condition(Kind.room_member_co
|
|||||||
*/
|
*/
|
||||||
private fun parseIsField(): Pair<String?, Int>? {
|
private fun parseIsField(): Pair<String?, Int>? {
|
||||||
try {
|
try {
|
||||||
val match = regex.matcher(`is`)
|
val match = regex.find(iz) ?: return null
|
||||||
if (match.find()) {
|
val (prefix, count) = match.destructured
|
||||||
val prefix = match.group(1)
|
return prefix to count.toInt()
|
||||||
val count = match.group(2).toInt()
|
|
||||||
return prefix to count
|
|
||||||
}
|
|
||||||
} catch (t: Throwable) {
|
} catch (t: Throwable) {
|
||||||
Timber.d(t)
|
Timber.d(t)
|
||||||
}
|
}
|
||||||
|
@ -20,10 +20,10 @@ import androidx.lifecycle.LiveData
|
|||||||
|
|
||||||
interface InitialSyncProgressService {
|
interface InitialSyncProgressService {
|
||||||
|
|
||||||
fun getLiveStatus() : LiveData<Status?>
|
fun getInitialSyncProgressStatus() : LiveData<Status?>
|
||||||
|
|
||||||
data class Status(
|
data class Status(
|
||||||
@StringRes val statusText: Int?,
|
@StringRes val statusText: Int,
|
||||||
val percentProgress: Int = 0
|
val percentProgress: Int = 0
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -17,7 +17,7 @@ package im.vector.matrix.android.api.session.pushers
|
|||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
import java.util.*
|
import java.util.UUID
|
||||||
|
|
||||||
|
|
||||||
interface PushersService {
|
interface PushersService {
|
||||||
|
@ -29,7 +29,6 @@ import im.vector.matrix.android.api.session.room.model.PowerLevels
|
|||||||
import im.vector.matrix.android.api.session.room.model.RoomDirectoryVisibility
|
import im.vector.matrix.android.api.session.room.model.RoomDirectoryVisibility
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomHistoryVisibility
|
import im.vector.matrix.android.api.session.room.model.RoomHistoryVisibility
|
||||||
import im.vector.matrix.android.internal.auth.data.ThreePidMedium
|
import im.vector.matrix.android.internal.auth.data.ThreePidMedium
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parameter to create a room, with facilities functions to configure it
|
* Parameter to create a room, with facilities functions to configure it
|
||||||
@ -133,7 +132,7 @@ class CreateRoomParams {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (null == initialStates) {
|
if (null == initialStates) {
|
||||||
initialStates = Arrays.asList<Event>(algoEvent)
|
initialStates = mutableListOf(algoEvent)
|
||||||
} else {
|
} else {
|
||||||
initialStates!!.add(algoEvent)
|
initialStates!!.add(algoEvent)
|
||||||
}
|
}
|
||||||
@ -166,7 +165,7 @@ class CreateRoomParams {
|
|||||||
content = contentMap.toContent())
|
content = contentMap.toContent())
|
||||||
|
|
||||||
if (null == initialStates) {
|
if (null == initialStates) {
|
||||||
initialStates = Arrays.asList<Event>(historyVisibilityEvent)
|
initialStates = mutableListOf(historyVisibilityEvent)
|
||||||
} else {
|
} else {
|
||||||
initialStates!!.add(historyVisibilityEvent)
|
initialStates!!.add(historyVisibilityEvent)
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ import java.math.BigInteger
|
|||||||
import java.security.KeyPairGenerator
|
import java.security.KeyPairGenerator
|
||||||
import java.security.KeyStore
|
import java.security.KeyStore
|
||||||
import java.security.SecureRandom
|
import java.security.SecureRandom
|
||||||
import java.util.*
|
import java.util.Calendar
|
||||||
import javax.crypto.*
|
import javax.crypto.*
|
||||||
import javax.crypto.spec.GCMParameterSpec
|
import javax.crypto.spec.GCMParameterSpec
|
||||||
import javax.crypto.spec.IvParameterSpec
|
import javax.crypto.spec.IvParameterSpec
|
||||||
@ -479,12 +479,7 @@ object SecretStoringUtils {
|
|||||||
val output = Cipher.getInstance(RSA_MODE)
|
val output = Cipher.getInstance(RSA_MODE)
|
||||||
output.init(Cipher.DECRYPT_MODE, privateKeyEntry.privateKey)
|
output.init(Cipher.DECRYPT_MODE, privateKeyEntry.privateKey)
|
||||||
|
|
||||||
val bos = ByteArrayOutputStream()
|
return CipherInputStream(encrypted, output).use { it.readBytes() }
|
||||||
CipherInputStream(encrypted, output).use {
|
|
||||||
it.copyTo(bos)
|
|
||||||
}
|
|
||||||
|
|
||||||
return bos.toByteArray()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun formatMExtract(bis: InputStream): Pair<ByteArray, ByteArray> {
|
private fun formatMExtract(bis: InputStream): Pair<ByteArray, ByteArray> {
|
||||||
@ -495,14 +490,7 @@ object SecretStoringUtils {
|
|||||||
val iv = ByteArray(ivSize)
|
val iv = ByteArray(ivSize)
|
||||||
bis.read(iv, 0, ivSize)
|
bis.read(iv, 0, ivSize)
|
||||||
|
|
||||||
|
val encrypted = bis.readBytes()
|
||||||
val bos = ByteArrayOutputStream()
|
|
||||||
var next = bis.read()
|
|
||||||
while (next != -1) {
|
|
||||||
bos.write(next)
|
|
||||||
next = bis.read()
|
|
||||||
}
|
|
||||||
val encrypted = bos.toByteArray()
|
|
||||||
return Pair(iv, encrypted)
|
return Pair(iv, encrypted)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -530,14 +518,7 @@ object SecretStoringUtils {
|
|||||||
val iv = ByteArray(ivSize)
|
val iv = ByteArray(ivSize)
|
||||||
bis.read(iv)
|
bis.read(iv)
|
||||||
|
|
||||||
val bos = ByteArrayOutputStream()
|
val encrypted = bis.readBytes()
|
||||||
|
|
||||||
var next = bis.read()
|
|
||||||
while (next != -1) {
|
|
||||||
bos.write(next)
|
|
||||||
next = bis.read()
|
|
||||||
}
|
|
||||||
val encrypted = bos.toByteArray()
|
|
||||||
return Triple(encryptedKey, iv, encrypted)
|
return Triple(encryptedKey, iv, encrypted)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -579,14 +560,7 @@ object SecretStoringUtils {
|
|||||||
val iv = ByteArray(ivSize)
|
val iv = ByteArray(ivSize)
|
||||||
bis.read(iv)
|
bis.read(iv)
|
||||||
|
|
||||||
val bos = ByteArrayOutputStream()
|
val encrypted = bis.readBytes()
|
||||||
|
|
||||||
var next = bis.read()
|
|
||||||
while (next != -1) {
|
|
||||||
bos.write(next)
|
|
||||||
next = bis.read()
|
|
||||||
}
|
|
||||||
val encrypted = bos.toByteArray()
|
|
||||||
return Triple(salt, iv, encrypted)
|
return Triple(salt, iv, encrypted)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -105,7 +105,7 @@ internal abstract class CryptoModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun bindCryptoService(cryptoManager: CryptoManager): CryptoService
|
abstract fun bindCryptoService(cryptoService: DefaultCryptoService): CryptoService
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun bindDeleteDeviceTask(deleteDeviceTask: DefaultDeleteDeviceTask): DeleteDeviceTask
|
abstract fun bindDeleteDeviceTask(deleteDeviceTask: DefaultDeleteDeviceTask): DeleteDeviceTask
|
||||||
|
@ -93,7 +93,7 @@ import kotlin.math.max
|
|||||||
* Specially, it tracks all room membership changes events in order to do keys updates.
|
* Specially, it tracks all room membership changes events in order to do keys updates.
|
||||||
*/
|
*/
|
||||||
@SessionScope
|
@SessionScope
|
||||||
internal class CryptoManager @Inject constructor(
|
internal class DefaultCryptoService @Inject constructor(
|
||||||
// Olm Manager
|
// Olm Manager
|
||||||
private val olmManager: OlmManager,
|
private val olmManager: OlmManager,
|
||||||
// The credentials,
|
// The credentials,
|
||||||
@ -1067,6 +1067,6 @@ internal class CryptoManager @Inject constructor(
|
|||||||
* ========================================================================================== */
|
* ========================================================================================== */
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "CryptoManager of " + credentials.userId + " (" + credentials.deviceId + ")"
|
return "DefaultCryptoService of " + credentials.userId + " (" + credentials.deviceId + ")"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -17,7 +17,6 @@
|
|||||||
package im.vector.matrix.android.internal.crypto
|
package im.vector.matrix.android.internal.crypto
|
||||||
|
|
||||||
import im.vector.matrix.android.api.auth.data.Credentials
|
import im.vector.matrix.android.api.auth.data.Credentials
|
||||||
import java.util.*
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class ObjectSigner @Inject constructor(private val credentials: Credentials,
|
internal class ObjectSigner @Inject constructor(private val credentials: Credentials,
|
||||||
|
@ -31,7 +31,6 @@ import im.vector.matrix.android.internal.crypto.model.event.OlmPayloadContent
|
|||||||
import im.vector.matrix.android.internal.di.MoshiProvider
|
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||||
import im.vector.matrix.android.internal.util.convertFromUTF8
|
import im.vector.matrix.android.internal.util.convertFromUTF8
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
internal class MXOlmDecryption(
|
internal class MXOlmDecryption(
|
||||||
// The olm device interface
|
// The olm device interface
|
||||||
@ -158,33 +157,14 @@ internal class MXOlmDecryption(
|
|||||||
* @return payload, if decrypted successfully.
|
* @return payload, if decrypted successfully.
|
||||||
*/
|
*/
|
||||||
private fun decryptMessage(message: JsonDict, theirDeviceIdentityKey: String): String? {
|
private fun decryptMessage(message: JsonDict, theirDeviceIdentityKey: String): String? {
|
||||||
val sessionIdsSet = olmDevice.getSessionIds(theirDeviceIdentityKey)
|
val sessionIds = olmDevice.getSessionIds(theirDeviceIdentityKey) ?: emptySet()
|
||||||
|
|
||||||
val sessionIds: List<String>
|
val messageBody = message["body"] as? String ?: return null
|
||||||
|
val messageType = when (val typeAsVoid = message["type"]) {
|
||||||
if (null == sessionIdsSet) {
|
is Double -> typeAsVoid.toInt()
|
||||||
sessionIds = ArrayList()
|
is Int -> typeAsVoid
|
||||||
} else {
|
is Long -> typeAsVoid.toInt()
|
||||||
sessionIds = ArrayList(sessionIdsSet)
|
else -> return null
|
||||||
}
|
|
||||||
|
|
||||||
val messageBody = message["body"] as? String
|
|
||||||
var messageType: Int? = null
|
|
||||||
|
|
||||||
val typeAsVoid = message["type"]
|
|
||||||
|
|
||||||
if (null != typeAsVoid) {
|
|
||||||
if (typeAsVoid is Double) {
|
|
||||||
messageType = typeAsVoid.toInt()
|
|
||||||
} else if (typeAsVoid is Int) {
|
|
||||||
messageType = typeAsVoid
|
|
||||||
} else if (typeAsVoid is Long) {
|
|
||||||
messageType = typeAsVoid.toInt()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null == messageBody || null == messageType) {
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try each session in turn
|
// Try each session in turn
|
||||||
|
@ -26,7 +26,6 @@ import java.io.ByteArrayOutputStream
|
|||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
import java.security.SecureRandom
|
import java.security.SecureRandom
|
||||||
import java.util.*
|
|
||||||
import javax.crypto.Cipher
|
import javax.crypto.Cipher
|
||||||
import javax.crypto.spec.IvParameterSpec
|
import javax.crypto.spec.IvParameterSpec
|
||||||
import javax.crypto.spec.SecretKeySpec
|
import javax.crypto.spec.SecretKeySpec
|
||||||
@ -59,8 +58,7 @@ object MXEncryptedAttachments {
|
|||||||
// Half of the IV is random, the lower order bits are zeroed
|
// Half of the IV is random, the lower order bits are zeroed
|
||||||
// such that the counter never wraps.
|
// such that the counter never wraps.
|
||||||
// See https://github.com/matrix-org/matrix-ios-kit/blob/3dc0d8e46b4deb6669ed44f72ad79be56471354c/MatrixKit/Models/Room/MXEncryptedAttachments.m#L75
|
// See https://github.com/matrix-org/matrix-ios-kit/blob/3dc0d8e46b4deb6669ed44f72ad79be56471354c/MatrixKit/Models/Room/MXEncryptedAttachments.m#L75
|
||||||
val initVectorBytes = ByteArray(16)
|
val initVectorBytes = ByteArray(16) { 0.toByte() }
|
||||||
Arrays.fill(initVectorBytes, 0.toByte())
|
|
||||||
|
|
||||||
val ivRandomPart = ByteArray(8)
|
val ivRandomPart = ByteArray(8)
|
||||||
secureRandom.nextBytes(ivRandomPart)
|
secureRandom.nextBytes(ivRandomPart)
|
||||||
@ -115,7 +113,7 @@ object MXEncryptedAttachments {
|
|||||||
encryptedByteArray = outStream.toByteArray()
|
encryptedByteArray = outStream.toByteArray()
|
||||||
)
|
)
|
||||||
|
|
||||||
Timber.v("Encrypt in " + (System.currentTimeMillis() - t0) + " ms")
|
Timber.v("Encrypt in ${System.currentTimeMillis() - t0} ms")
|
||||||
return Try.just(result)
|
return Try.just(result)
|
||||||
} catch (oom: OutOfMemoryError) {
|
} catch (oom: OutOfMemoryError) {
|
||||||
Timber.e(oom, "## encryptAttachment failed")
|
Timber.e(oom, "## encryptAttachment failed")
|
||||||
@ -206,13 +204,13 @@ object MXEncryptedAttachments {
|
|||||||
val decryptedStream = ByteArrayInputStream(outStream.toByteArray())
|
val decryptedStream = ByteArrayInputStream(outStream.toByteArray())
|
||||||
outStream.close()
|
outStream.close()
|
||||||
|
|
||||||
Timber.v("Decrypt in " + (System.currentTimeMillis() - t0) + " ms")
|
Timber.v("Decrypt in ${System.currentTimeMillis() - t0} ms")
|
||||||
|
|
||||||
return decryptedStream
|
return decryptedStream
|
||||||
} catch (oom: OutOfMemoryError) {
|
} catch (oom: OutOfMemoryError) {
|
||||||
Timber.e(oom, "## decryptAttachment() : failed " + oom.message)
|
Timber.e(oom, "## decryptAttachment() : failed ${oom.message}")
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Timber.e(e, "## decryptAttachment() : failed " + e.message)
|
Timber.e(e, "## decryptAttachment() : failed ${e.message}")
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -228,34 +226,20 @@ object MXEncryptedAttachments {
|
|||||||
* Base64 URL conversion methods
|
* Base64 URL conversion methods
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private fun base64UrlToBase64(base64Url: String?): String? {
|
private fun base64UrlToBase64(base64Url: String): String {
|
||||||
var result = base64Url
|
return base64Url.replace('-', '+')
|
||||||
if (null != result) {
|
.replace('_', '/')
|
||||||
result = result.replace("-".toRegex(), "+")
|
|
||||||
result = result.replace("_".toRegex(), "/")
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun base64ToBase64Url(base64: String?): String? {
|
private fun base64ToBase64Url(base64: String): String {
|
||||||
var result = base64
|
return base64.replace("\n".toRegex(), "")
|
||||||
if (null != result) {
|
.replace("\\+".toRegex(), "-")
|
||||||
result = result.replace("\n".toRegex(), "")
|
.replace('/', '_')
|
||||||
result = result.replace("\\+".toRegex(), "-")
|
.replace("=", "")
|
||||||
result = result.replace("/".toRegex(), "_")
|
|
||||||
result = result.replace("=".toRegex(), "")
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun base64ToUnpaddedBase64(base64: String?): String? {
|
private fun base64ToUnpaddedBase64(base64: String): String {
|
||||||
var result = base64
|
return base64.replace("\n".toRegex(), "")
|
||||||
if (null != result) {
|
.replace("=", "")
|
||||||
result = result.replace("\n".toRegex(), "")
|
|
||||||
result = result.replace("=".toRegex(), "")
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,9 +66,8 @@ import org.matrix.olm.OlmPkEncryption
|
|||||||
import org.matrix.olm.OlmPkMessage
|
import org.matrix.olm.OlmPkMessage
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.security.InvalidParameterException
|
import java.security.InvalidParameterException
|
||||||
import java.util.*
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.collections.HashMap
|
import kotlin.random.Random
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A KeysBackup class instance manage incremental backup of e2e keys (megolm keys)
|
* A KeysBackup class instance manage incremental backup of e2e keys (megolm keys)
|
||||||
@ -114,8 +113,6 @@ internal class KeysBackup @Inject constructor(
|
|||||||
// The backup key being used.
|
// The backup key being used.
|
||||||
private var backupOlmPkEncryption: OlmPkEncryption? = null
|
private var backupOlmPkEncryption: OlmPkEncryption? = null
|
||||||
|
|
||||||
private val random = Random()
|
|
||||||
|
|
||||||
private var backupAllGroupSessionsCallback: MatrixCallback<Unit>? = null
|
private var backupAllGroupSessionsCallback: MatrixCallback<Unit>? = null
|
||||||
|
|
||||||
private var keysBackupStateListener: KeysBackupStateListener? = null
|
private var keysBackupStateListener: KeysBackupStateListener? = null
|
||||||
@ -848,7 +845,7 @@ internal class KeysBackup @Inject constructor(
|
|||||||
// Wait between 0 and 10 seconds, to avoid backup requests from
|
// Wait between 0 and 10 seconds, to avoid backup requests from
|
||||||
// different clients hitting the server all at the same time when a
|
// different clients hitting the server all at the same time when a
|
||||||
// new key is sent
|
// new key is sent
|
||||||
val delayInMs = random.nextInt(KEY_BACKUP_WAITING_TIME_TO_SEND_KEY_BACKUP_MILLIS).toLong()
|
val delayInMs = Random.nextLong(KEY_BACKUP_WAITING_TIME_TO_SEND_KEY_BACKUP_MILLIS)
|
||||||
|
|
||||||
uiHandler.postDelayed({ backupKeys() }, delayInMs)
|
uiHandler.postDelayed({ backupKeys() }, delayInMs)
|
||||||
}
|
}
|
||||||
@ -1307,7 +1304,7 @@ internal class KeysBackup @Inject constructor(
|
|||||||
|
|
||||||
// Make the request
|
// Make the request
|
||||||
storeSessionDataTask
|
storeSessionDataTask
|
||||||
.configureWith(StoreSessionsDataTask.Params(keysBackupVersion!!.version!!, keysBackupData)){
|
.configureWith(StoreSessionsDataTask.Params(keysBackupVersion!!.version!!, keysBackupData)) {
|
||||||
this.callback = sendingRequestCallback
|
this.callback = sendingRequestCallback
|
||||||
}
|
}
|
||||||
.executeBy(taskExecutor)
|
.executeBy(taskExecutor)
|
||||||
@ -1405,7 +1402,7 @@ internal class KeysBackup @Inject constructor(
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
// Maximum delay in ms in {@link maybeBackupKeys}
|
// Maximum delay in ms in {@link maybeBackupKeys}
|
||||||
private const val KEY_BACKUP_WAITING_TIME_TO_SEND_KEY_BACKUP_MILLIS = 10000
|
private const val KEY_BACKUP_WAITING_TIME_TO_SEND_KEY_BACKUP_MILLIS = 10_000L
|
||||||
|
|
||||||
// Maximum number of keys to send at a time to the homeserver.
|
// Maximum number of keys to send at a time to the homeserver.
|
||||||
private const val KEY_BACKUP_SEND_KEYS_MAX_COUNT = 100
|
private const val KEY_BACKUP_SEND_KEYS_MAX_COUNT = 100
|
||||||
|
@ -22,7 +22,7 @@ package im.vector.matrix.android.internal.crypto.keysbackup
|
|||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
import im.vector.matrix.android.api.listeners.ProgressListener
|
import im.vector.matrix.android.api.listeners.ProgressListener
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.*
|
import java.util.UUID
|
||||||
import javax.crypto.Mac
|
import javax.crypto.Mac
|
||||||
import javax.crypto.spec.SecretKeySpec
|
import javax.crypto.spec.SecretKeySpec
|
||||||
import kotlin.experimental.xor
|
import kotlin.experimental.xor
|
||||||
|
@ -20,7 +20,6 @@ import android.os.Handler
|
|||||||
import im.vector.matrix.android.api.session.crypto.keysbackup.KeysBackupState
|
import im.vector.matrix.android.api.session.crypto.keysbackup.KeysBackupState
|
||||||
import im.vector.matrix.android.api.session.crypto.keysbackup.KeysBackupStateListener
|
import im.vector.matrix.android.api.session.crypto.keysbackup.KeysBackupStateListener
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
internal class KeysBackupStateManager(private val uiHandler: Handler) {
|
internal class KeysBackupStateManager(private val uiHandler: Handler) {
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@ import com.squareup.moshi.JsonClass
|
|||||||
import im.vector.matrix.android.api.util.JsonDict
|
import im.vector.matrix.android.api.util.JsonDict
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.DeviceKeys
|
import im.vector.matrix.android.internal.crypto.model.rest.DeviceKeys
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
data class MXDeviceInfo(
|
data class MXDeviceInfo(
|
||||||
|
@ -18,7 +18,6 @@ package im.vector.matrix.android.internal.crypto.model
|
|||||||
|
|
||||||
import im.vector.matrix.android.api.util.JsonDict
|
import im.vector.matrix.android.api.util.JsonDict
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
data class MXKey(
|
data class MXKey(
|
||||||
/**
|
/**
|
||||||
@ -46,11 +45,7 @@ data class MXKey(
|
|||||||
* @return the signed data map
|
* @return the signed data map
|
||||||
*/
|
*/
|
||||||
fun signalableJSONDictionary(): Map<String, Any> {
|
fun signalableJSONDictionary(): Map<String, Any> {
|
||||||
val map = HashMap<String, Any>()
|
return mapOf("key" to value)
|
||||||
|
|
||||||
map["key"] = value
|
|
||||||
|
|
||||||
return map
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package im.vector.matrix.android.internal.crypto.model
|
package im.vector.matrix.android.internal.crypto.model
|
||||||
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class MXUsersDevicesMap<E> {
|
class MXUsersDevicesMap<E> {
|
||||||
|
|
||||||
@ -27,7 +26,7 @@ class MXUsersDevicesMap<E> {
|
|||||||
* @return the user Ids
|
* @return the user Ids
|
||||||
*/
|
*/
|
||||||
val userIds: List<String>
|
val userIds: List<String>
|
||||||
get() = ArrayList(map.keys)
|
get() = map.keys.toList()
|
||||||
|
|
||||||
val isEmpty: Boolean
|
val isEmpty: Boolean
|
||||||
get() = map.isEmpty()
|
get() = map.isEmpty()
|
||||||
@ -40,7 +39,7 @@ class MXUsersDevicesMap<E> {
|
|||||||
* @return the device ids list
|
* @return the device ids list
|
||||||
*/
|
*/
|
||||||
fun getUserDeviceIds(userId: String?): List<String>? {
|
fun getUserDeviceIds(userId: String?): List<String>? {
|
||||||
return if (userId?.isNotBlank() == true && map.containsKey(userId)) {
|
return if (!userId.isNullOrBlank() && map.containsKey(userId)) {
|
||||||
map[userId]!!.keys.toList()
|
map[userId]!!.keys.toList()
|
||||||
} else null
|
} else null
|
||||||
}
|
}
|
||||||
@ -53,7 +52,7 @@ class MXUsersDevicesMap<E> {
|
|||||||
* @return the object
|
* @return the object
|
||||||
*/
|
*/
|
||||||
fun getObject(userId: String?, deviceId: String?): E? {
|
fun getObject(userId: String?, deviceId: String?): E? {
|
||||||
return if (userId?.isNotBlank() == true && deviceId?.isNotBlank() == true && map.containsKey(userId)) {
|
return if (!userId.isNullOrBlank() && !deviceId.isNullOrBlank()) {
|
||||||
map[userId]?.get(deviceId)
|
map[userId]?.get(deviceId)
|
||||||
} else null
|
} else null
|
||||||
}
|
}
|
||||||
@ -67,11 +66,8 @@ class MXUsersDevicesMap<E> {
|
|||||||
*/
|
*/
|
||||||
fun setObject(userId: String?, deviceId: String?, o: E?) {
|
fun setObject(userId: String?, deviceId: String?, o: E?) {
|
||||||
if (null != o && userId?.isNotBlank() == true && deviceId?.isNotBlank() == true) {
|
if (null != o && userId?.isNotBlank() == true && deviceId?.isNotBlank() == true) {
|
||||||
if (map[userId] == null) {
|
val devices = map.getOrPut(userId) { HashMap() }
|
||||||
map[userId] = HashMap()
|
devices[deviceId] = o
|
||||||
}
|
|
||||||
|
|
||||||
map[userId]?.put(deviceId, o)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +78,7 @@ class MXUsersDevicesMap<E> {
|
|||||||
* @param userId the user id
|
* @param userId the user id
|
||||||
*/
|
*/
|
||||||
fun setObjects(userId: String?, objectsPerDevices: Map<String, E>?) {
|
fun setObjects(userId: String?, objectsPerDevices: Map<String, E>?) {
|
||||||
if (userId?.isNotBlank() == true) {
|
if (!userId.isNullOrBlank()) {
|
||||||
if (null == objectsPerDevices) {
|
if (null == objectsPerDevices) {
|
||||||
map.remove(userId)
|
map.remove(userId)
|
||||||
} else {
|
} else {
|
||||||
@ -97,7 +93,7 @@ class MXUsersDevicesMap<E> {
|
|||||||
* @param userId the user id.
|
* @param userId the user id.
|
||||||
*/
|
*/
|
||||||
fun removeUserObjects(userId: String?) {
|
fun removeUserObjects(userId: String?) {
|
||||||
if (userId?.isNotBlank() == true) {
|
if (!userId.isNullOrBlank()) {
|
||||||
map.remove(userId)
|
map.remove(userId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,8 @@ import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap
|
|||||||
import im.vector.matrix.android.internal.crypto.model.rest.SendToDeviceBody
|
import im.vector.matrix.android.internal.crypto.model.rest.SendToDeviceBody
|
||||||
import im.vector.matrix.android.internal.network.executeRequest
|
import im.vector.matrix.android.internal.network.executeRequest
|
||||||
import im.vector.matrix.android.internal.task.Task
|
import im.vector.matrix.android.internal.task.Task
|
||||||
import java.util.*
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
internal interface SendToDeviceTask : Task<SendToDeviceTask.Params, Unit> {
|
internal interface SendToDeviceTask : Task<SendToDeviceTask.Params, Unit> {
|
||||||
data class Params(
|
data class Params(
|
||||||
@ -45,7 +45,7 @@ internal class DefaultSendToDeviceTask @Inject constructor(private val cryptoApi
|
|||||||
return executeRequest {
|
return executeRequest {
|
||||||
apiCall = cryptoApi.sendToDevice(
|
apiCall = cryptoApi.sendToDevice(
|
||||||
params.eventType,
|
params.eventType,
|
||||||
params.transactionId ?: Random().nextInt(Integer.MAX_VALUE).toString(),
|
params.transactionId ?: Random.nextInt(Integer.MAX_VALUE).toString(),
|
||||||
sendToDeviceBody
|
sendToDeviceBody
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
|||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.*
|
import java.util.UUID
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.collections.HashMap
|
import kotlin.collections.HashMap
|
||||||
|
|
||||||
@ -161,7 +161,7 @@ internal class DefaultSasVerificationService @Inject constructor(private val cre
|
|||||||
cancelTransaction(
|
cancelTransaction(
|
||||||
startReq.transactionID!!,
|
startReq.transactionID!!,
|
||||||
otherUserId!!,
|
otherUserId!!,
|
||||||
startReq?.fromDevice ?: event.getSenderKey()!!,
|
startReq.fromDevice ?: event.getSenderKey()!!,
|
||||||
CancelCode.UnknownMethod
|
CancelCode.UnknownMethod
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -388,14 +388,13 @@ internal class DefaultSasVerificationService @Inject constructor(private val cre
|
|||||||
* This string must be unique for the pair of users performing verification for the duration that the transaction is valid
|
* This string must be unique for the pair of users performing verification for the duration that the transaction is valid
|
||||||
*/
|
*/
|
||||||
private fun createUniqueIDForTransaction(userId: String, deviceID: String): String {
|
private fun createUniqueIDForTransaction(userId: String, deviceID: String): String {
|
||||||
val buff = StringBuffer()
|
return buildString {
|
||||||
buff
|
append(credentials.userId).append("|")
|
||||||
.append(credentials.userId).append("|")
|
append(credentials.deviceId).append("|")
|
||||||
.append(credentials.deviceId).append("|")
|
append(userId).append("|")
|
||||||
.append(userId).append("|")
|
append(deviceID).append("|")
|
||||||
.append(deviceID).append("|")
|
append(UUID.randomUUID().toString())
|
||||||
.append(UUID.randomUUID().toString())
|
}
|
||||||
return buff.toString()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ import im.vector.matrix.android.api.session.room.model.RoomSummary
|
|||||||
import im.vector.matrix.android.api.session.room.model.tag.RoomTag
|
import im.vector.matrix.android.api.session.room.model.tag.RoomTag
|
||||||
import im.vector.matrix.android.internal.crypto.algorithms.olm.OlmDecryptionResult
|
import im.vector.matrix.android.internal.crypto.algorithms.olm.OlmDecryptionResult
|
||||||
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
||||||
import java.util.*
|
import java.util.UUID
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class RoomSummaryMapper @Inject constructor(
|
internal class RoomSummaryMapper @Inject constructor(
|
||||||
|
@ -24,7 +24,6 @@ import java.security.KeyStore
|
|||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
import java.security.cert.CertificateException
|
import java.security.cert.CertificateException
|
||||||
import java.security.cert.X509Certificate
|
import java.security.cert.X509Certificate
|
||||||
import java.util.*
|
|
||||||
import javax.net.ssl.*
|
import javax.net.ssl.*
|
||||||
import kotlin.experimental.and
|
import kotlin.experimental.and
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@ import java.net.UnknownHostException
|
|||||||
import java.security.KeyManagementException
|
import java.security.KeyManagementException
|
||||||
import java.security.NoSuchAlgorithmException
|
import java.security.NoSuchAlgorithmException
|
||||||
import java.security.SecureRandom
|
import java.security.SecureRandom
|
||||||
import java.util.*
|
|
||||||
import javax.net.ssl.SSLContext
|
import javax.net.ssl.SSLContext
|
||||||
import javax.net.ssl.SSLSocket
|
import javax.net.ssl.SSLSocket
|
||||||
import javax.net.ssl.SSLSocketFactory
|
import javax.net.ssl.SSLSocketFactory
|
||||||
@ -101,25 +100,16 @@ constructor(trustPinned: Array<TrustManager>, acceptedTlsVersions: List<TlsVersi
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun enableTLSOnSocket(socket: Socket?): Socket? {
|
private fun enableTLSOnSocket(socket: Socket?): Socket? {
|
||||||
if (socket != null && socket is SSLSocket) {
|
if (socket is SSLSocket) {
|
||||||
val sslSocket = socket as SSLSocket?
|
val supportedProtocols = socket.supportedProtocols.toSet()
|
||||||
|
val filteredEnabledProtocols = enabledProtocols.filter { it in supportedProtocols }
|
||||||
|
|
||||||
val supportedProtocols = Arrays.asList(*sslSocket!!.supportedProtocols)
|
if (filteredEnabledProtocols.isNotEmpty()) {
|
||||||
val filteredEnabledProtocols = ArrayList<String>()
|
|
||||||
|
|
||||||
for (protocol in enabledProtocols) {
|
|
||||||
if (supportedProtocols.contains(protocol)) {
|
|
||||||
filteredEnabledProtocols.add(protocol)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!filteredEnabledProtocols.isEmpty()) {
|
|
||||||
try {
|
try {
|
||||||
sslSocket.enabledProtocols = filteredEnabledProtocols.toTypedArray()
|
socket.enabledProtocols = filteredEnabledProtocols.toTypedArray()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Timber.e(e)
|
Timber.e(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return socket
|
return socket
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package im.vector.matrix.android.internal.session
|
package im.vector.matrix.android.internal.session
|
||||||
|
|
||||||
|
import androidx.annotation.StringRes
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import im.vector.matrix.android.api.session.InitialSyncProgressService
|
import im.vector.matrix.android.api.session.InitialSyncProgressService
|
||||||
@ -25,31 +26,33 @@ import javax.inject.Inject
|
|||||||
@SessionScope
|
@SessionScope
|
||||||
class DefaultInitialSyncProgressService @Inject constructor() : InitialSyncProgressService {
|
class DefaultInitialSyncProgressService @Inject constructor() : InitialSyncProgressService {
|
||||||
|
|
||||||
var status = MutableLiveData<InitialSyncProgressService.Status>()
|
private var status = MutableLiveData<InitialSyncProgressService.Status>()
|
||||||
|
|
||||||
var rootTask: TaskInfo? = null
|
private var rootTask: TaskInfo? = null
|
||||||
|
|
||||||
override fun getLiveStatus(): LiveData<InitialSyncProgressService.Status?> {
|
override fun getInitialSyncProgressStatus(): LiveData<InitialSyncProgressService.Status?> {
|
||||||
return status
|
return status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun startTask(@StringRes nameRes: Int, totalProgress: Int, parentWeight: Float = 1f) {
|
||||||
fun startTask(nameRes: Int, totalProgress: Int, parentWeight: Float = 1f) {
|
// Create a rootTask, or add a child to the leaf
|
||||||
if (rootTask == null) {
|
if (rootTask == null) {
|
||||||
rootTask = TaskInfo(nameRes, totalProgress)
|
rootTask = TaskInfo(nameRes, totalProgress)
|
||||||
} else {
|
} else {
|
||||||
val currentLeaf = rootTask!!.leaf()
|
val currentLeaf = rootTask!!.leaf()
|
||||||
val newTask = TaskInfo(nameRes, totalProgress)
|
|
||||||
newTask.parent = currentLeaf
|
val newTask = TaskInfo(nameRes,
|
||||||
newTask.offset = currentLeaf.currentProgress
|
totalProgress,
|
||||||
|
currentLeaf,
|
||||||
|
parentWeight)
|
||||||
|
|
||||||
currentLeaf.child = newTask
|
currentLeaf.child = newTask
|
||||||
newTask.parentWeight = parentWeight
|
|
||||||
}
|
}
|
||||||
reportProgress(0)
|
reportProgress(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reportProgress(progress: Int) {
|
fun reportProgress(progress: Int) {
|
||||||
rootTask?.leaf()?.incrementProgress(progress)
|
rootTask?.leaf()?.setProgress(progress)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun endTask(nameRes: Int) {
|
fun endTask(nameRes: Int) {
|
||||||
@ -58,7 +61,7 @@ class DefaultInitialSyncProgressService @Inject constructor() : InitialSyncProgr
|
|||||||
//close it
|
//close it
|
||||||
val parent = endedTask.parent
|
val parent = endedTask.parent
|
||||||
parent?.child = null
|
parent?.child = null
|
||||||
parent?.incrementProgress(endedTask.offset + (endedTask.totalProgress * endedTask.parentWeight).toInt())
|
parent?.setProgress(endedTask.offset + (endedTask.totalProgress * endedTask.parentWeight).toInt())
|
||||||
}
|
}
|
||||||
if (endedTask?.parent == null) {
|
if (endedTask?.parent == null) {
|
||||||
status.postValue(null)
|
status.postValue(null)
|
||||||
@ -71,14 +74,17 @@ class DefaultInitialSyncProgressService @Inject constructor() : InitialSyncProgr
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inner class TaskInfo(var nameRes: Int,
|
private inner class TaskInfo(@StringRes var nameRes: Int,
|
||||||
var totalProgress: Int) {
|
var totalProgress: Int,
|
||||||
var parent: TaskInfo? = null
|
var parent: TaskInfo? = null,
|
||||||
|
var parentWeight: Float = 1f,
|
||||||
|
var offset: Int = parent?.currentProgress ?: 0) {
|
||||||
var child: TaskInfo? = null
|
var child: TaskInfo? = null
|
||||||
var parentWeight: Float = 1f
|
|
||||||
var currentProgress: Int = 0
|
var currentProgress: Int = 0
|
||||||
var offset: Int = 0
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the further child
|
||||||
|
*/
|
||||||
fun leaf(): TaskInfo {
|
fun leaf(): TaskInfo {
|
||||||
var last = this
|
var last = this
|
||||||
while (last.child != null) {
|
while (last.child != null) {
|
||||||
@ -87,26 +93,27 @@ class DefaultInitialSyncProgressService @Inject constructor() : InitialSyncProgr
|
|||||||
return last
|
return last
|
||||||
}
|
}
|
||||||
|
|
||||||
fun incrementProgress(progress: Int) {
|
/**
|
||||||
|
* Set progress of the parent if any (which will post value), or post the value
|
||||||
|
*/
|
||||||
|
fun setProgress(progress: Int) {
|
||||||
currentProgress = progress
|
currentProgress = progress
|
||||||
// val newProgress = Math.min(currentProgress + progress, totalProgress)
|
// val newProgress = Math.min(currentProgress + progress, totalProgress)
|
||||||
parent?.let {
|
parent?.let {
|
||||||
val parentProgress = (currentProgress * parentWeight).toInt()
|
val parentProgress = (currentProgress * parentWeight).toInt()
|
||||||
it.incrementProgress(offset + parentProgress)
|
it.setProgress(offset + parentProgress)
|
||||||
}
|
} ?: run {
|
||||||
if (parent == null) {
|
Timber.e("--- ${leaf().nameRes}: $currentProgress")
|
||||||
Timber.e("--- ${leaf().nameRes}: ${currentProgress}")
|
|
||||||
status.postValue(
|
status.postValue(
|
||||||
InitialSyncProgressService.Status(leaf().nameRes, currentProgress)
|
InitialSyncProgressService.Status(leaf().nameRes, currentProgress)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <T> reportSubtask(reporter: DefaultInitialSyncProgressService?,
|
inline fun <T> reportSubtask(reporter: DefaultInitialSyncProgressService?,
|
||||||
nameRes: Int,
|
@StringRes nameRes: Int,
|
||||||
totalProgress: Int,
|
totalProgress: Int,
|
||||||
parentWeight: Float = 1f,
|
parentWeight: Float = 1f,
|
||||||
block: () -> T): T {
|
block: () -> T): T {
|
||||||
@ -121,11 +128,11 @@ inline fun <K, V, R> Map<out K, V>.mapWithProgress(reporter: DefaultInitialSyncP
|
|||||||
taskId: Int,
|
taskId: Int,
|
||||||
weight: Float,
|
weight: Float,
|
||||||
transform: (Map.Entry<K, V>) -> R): List<R> {
|
transform: (Map.Entry<K, V>) -> R): List<R> {
|
||||||
val total = count()
|
val total = count().toFloat()
|
||||||
var current = 0
|
var current = 0
|
||||||
reporter?.startTask(taskId, 100, weight)
|
reporter?.startTask(taskId, 100, weight)
|
||||||
return this.map {
|
return map {
|
||||||
reporter?.reportProgress((current / total.toFloat() * 100).toInt())
|
reporter?.reportProgress((current / total * 100).toInt())
|
||||||
current++
|
current++
|
||||||
transform.invoke(it)
|
transform.invoke(it)
|
||||||
}.also {
|
}.also {
|
||||||
|
@ -40,7 +40,7 @@ import im.vector.matrix.android.api.session.sync.FilterService
|
|||||||
import im.vector.matrix.android.api.session.sync.SyncState
|
import im.vector.matrix.android.api.session.sync.SyncState
|
||||||
import im.vector.matrix.android.api.session.user.UserService
|
import im.vector.matrix.android.api.session.user.UserService
|
||||||
import im.vector.matrix.android.api.util.MatrixCallbackDelegate
|
import im.vector.matrix.android.api.util.MatrixCallbackDelegate
|
||||||
import im.vector.matrix.android.internal.crypto.CryptoManager
|
import im.vector.matrix.android.internal.crypto.DefaultCryptoService
|
||||||
import im.vector.matrix.android.internal.database.LiveEntityObserver
|
import im.vector.matrix.android.internal.database.LiveEntityObserver
|
||||||
import im.vector.matrix.android.internal.session.sync.job.SyncThread
|
import im.vector.matrix.android.internal.session.sync.job.SyncThread
|
||||||
import im.vector.matrix.android.internal.session.sync.job.SyncWorker
|
import im.vector.matrix.android.internal.session.sync.job.SyncWorker
|
||||||
@ -63,7 +63,7 @@ internal class DefaultSession @Inject constructor(override val sessionParams: Se
|
|||||||
private val signOutService: Lazy<SignOutService>,
|
private val signOutService: Lazy<SignOutService>,
|
||||||
private val pushRuleService: Lazy<PushRuleService>,
|
private val pushRuleService: Lazy<PushRuleService>,
|
||||||
private val pushersService: Lazy<PushersService>,
|
private val pushersService: Lazy<PushersService>,
|
||||||
private val cryptoService: Lazy<CryptoManager>,
|
private val cryptoService: Lazy<DefaultCryptoService>,
|
||||||
private val fileService: Lazy<FileService>,
|
private val fileService: Lazy<FileService>,
|
||||||
private val syncThreadProvider: Provider<SyncThread>,
|
private val syncThreadProvider: Provider<SyncThread>,
|
||||||
private val contentUrlResolver: ContentUrlResolver,
|
private val contentUrlResolver: ContentUrlResolver,
|
||||||
|
@ -30,9 +30,8 @@ internal class DefaultContentUploadStateTracker @Inject constructor() : ContentU
|
|||||||
private val listeners = mutableMapOf<String, MutableList<ContentUploadStateTracker.UpdateListener>>()
|
private val listeners = mutableMapOf<String, MutableList<ContentUploadStateTracker.UpdateListener>>()
|
||||||
|
|
||||||
override fun track(key: String, updateListener: ContentUploadStateTracker.UpdateListener) {
|
override fun track(key: String, updateListener: ContentUploadStateTracker.UpdateListener) {
|
||||||
val listeners = listeners[key] ?: ArrayList()
|
val listeners = listeners.getOrPut(key) { ArrayList() }
|
||||||
listeners.add(updateListener)
|
listeners.add(updateListener)
|
||||||
this.listeners[key] = listeners
|
|
||||||
val currentState = states[key] ?: ContentUploadStateTracker.State.Idle
|
val currentState = states[key] ?: ContentUploadStateTracker.State.Idle
|
||||||
mainHandler.post { updateListener.onUpdate(currentState) }
|
mainHandler.post { updateListener.onUpdate(currentState) }
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ import im.vector.matrix.android.internal.task.configureWith
|
|||||||
import im.vector.matrix.android.internal.worker.WorkManagerUtil
|
import im.vector.matrix.android.internal.worker.WorkManagerUtil
|
||||||
import im.vector.matrix.android.internal.worker.WorkManagerUtil.matrixOneTimeWorkRequestBuilder
|
import im.vector.matrix.android.internal.worker.WorkManagerUtil.matrixOneTimeWorkRequestBuilder
|
||||||
import im.vector.matrix.android.internal.worker.WorkerParamsFactory
|
import im.vector.matrix.android.internal.worker.WorkerParamsFactory
|
||||||
import java.util.*
|
import java.util.UUID
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -69,15 +69,11 @@ internal class DefaultRelationService @AssistedInject constructor(@Assisted priv
|
|||||||
.also {
|
.also {
|
||||||
saveLocalEcho(it)
|
saveLocalEcho(it)
|
||||||
}
|
}
|
||||||
val sendRelationWork = createSendRelationWork(event)
|
val sendRelationWork = createSendEventWork(event, true)
|
||||||
TimelineSendEventWorkCommon.postWork(context, roomId, sendRelationWork)
|
TimelineSendEventWorkCommon.postWork(context, roomId, sendRelationWork)
|
||||||
return CancelableWork(context, sendRelationWork.id)
|
return CancelableWork(context, sendRelationWork.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createSendRelationWork(event: Event): OneTimeWorkRequest {
|
|
||||||
return createSendEventWork(event)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun undoReaction(reaction: String, targetEventId: String, myUserId: String)/*: Cancelable*/ {
|
override fun undoReaction(reaction: String, targetEventId: String, myUserId: String)/*: Cancelable*/ {
|
||||||
|
|
||||||
val params = FindReactionEventForUndoTask.Params(
|
val params = FindReactionEventForUndoTask.Params(
|
||||||
@ -134,42 +130,42 @@ internal class DefaultRelationService @AssistedInject constructor(@Assisted priv
|
|||||||
.also {
|
.also {
|
||||||
saveLocalEcho(it)
|
saveLocalEcho(it)
|
||||||
}
|
}
|
||||||
if (cryptoService.isRoomEncrypted(roomId)) {
|
return if (cryptoService.isRoomEncrypted(roomId)) {
|
||||||
val encryptWork = createEncryptEventWork(event, listOf("m.relates_to"))
|
val encryptWork = createEncryptEventWork(event, listOf("m.relates_to"))
|
||||||
val workRequest = createSendEventWork(event)
|
val workRequest = createSendEventWork(event, false)
|
||||||
TimelineSendEventWorkCommon.postSequentialWorks(context, roomId, encryptWork, workRequest)
|
TimelineSendEventWorkCommon.postSequentialWorks(context, roomId, encryptWork, workRequest)
|
||||||
return CancelableWork(context, encryptWork.id)
|
CancelableWork(context, encryptWork.id)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
val workRequest = createSendEventWork(event)
|
val workRequest = createSendEventWork(event, true)
|
||||||
TimelineSendEventWorkCommon.postWork(context, roomId, workRequest)
|
TimelineSendEventWorkCommon.postWork(context, roomId, workRequest)
|
||||||
return CancelableWork(context, workRequest.id)
|
CancelableWork(context, workRequest.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun editReply(replyToEdit: TimelineEvent,
|
override fun editReply(replyToEdit: TimelineEvent,
|
||||||
originalEvent: TimelineEvent,
|
originalTimelineEvent: TimelineEvent,
|
||||||
newBodyText: String,
|
newBodyText: String,
|
||||||
compatibilityBodyText: String): Cancelable {
|
compatibilityBodyText: String): Cancelable {
|
||||||
val event = eventFactory
|
val event = eventFactory
|
||||||
.createReplaceTextOfReply(roomId,
|
.createReplaceTextOfReply(roomId,
|
||||||
replyToEdit,
|
replyToEdit,
|
||||||
originalEvent,
|
originalTimelineEvent,
|
||||||
newBodyText, true, MessageType.MSGTYPE_TEXT, compatibilityBodyText)
|
newBodyText, true, MessageType.MSGTYPE_TEXT, compatibilityBodyText)
|
||||||
.also {
|
.also {
|
||||||
saveLocalEcho(it)
|
saveLocalEcho(it)
|
||||||
}
|
}
|
||||||
if (cryptoService.isRoomEncrypted(roomId)) {
|
return if (cryptoService.isRoomEncrypted(roomId)) {
|
||||||
val encryptWork = createEncryptEventWork(event, listOf("m.relates_to"))
|
val encryptWork = createEncryptEventWork(event, listOf("m.relates_to"))
|
||||||
val workRequest = createSendEventWork(event)
|
val workRequest = createSendEventWork(event, false)
|
||||||
TimelineSendEventWorkCommon.postSequentialWorks(context, roomId, encryptWork, workRequest)
|
TimelineSendEventWorkCommon.postSequentialWorks(context, roomId, encryptWork, workRequest)
|
||||||
return CancelableWork(context, encryptWork.id)
|
CancelableWork(context, encryptWork.id)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
val workRequest = createSendEventWork(event)
|
val workRequest = createSendEventWork(event, true)
|
||||||
TimelineSendEventWorkCommon.postWork(context, roomId, workRequest)
|
TimelineSendEventWorkCommon.postWork(context, roomId, workRequest)
|
||||||
return CancelableWork(context, workRequest.id)
|
CancelableWork(context, workRequest.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,16 +183,16 @@ internal class DefaultRelationService @AssistedInject constructor(@Assisted priv
|
|||||||
saveLocalEcho(it)
|
saveLocalEcho(it)
|
||||||
} ?: return null
|
} ?: return null
|
||||||
|
|
||||||
if (cryptoService.isRoomEncrypted(roomId)) {
|
return if (cryptoService.isRoomEncrypted(roomId)) {
|
||||||
val encryptWork = createEncryptEventWork(event, listOf("m.relates_to"))
|
val encryptWork = createEncryptEventWork(event, listOf("m.relates_to"))
|
||||||
val workRequest = createSendEventWork(event)
|
val workRequest = createSendEventWork(event, false)
|
||||||
TimelineSendEventWorkCommon.postSequentialWorks(context, roomId, encryptWork, workRequest)
|
TimelineSendEventWorkCommon.postSequentialWorks(context, roomId, encryptWork, workRequest)
|
||||||
return CancelableWork(context, encryptWork.id)
|
CancelableWork(context, encryptWork.id)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
val workRequest = createSendEventWork(event)
|
val workRequest = createSendEventWork(event, true)
|
||||||
TimelineSendEventWorkCommon.postWork(context, roomId, workRequest)
|
TimelineSendEventWorkCommon.postWork(context, roomId, workRequest)
|
||||||
return CancelableWork(context, workRequest.id)
|
CancelableWork(context, workRequest.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -208,10 +204,10 @@ internal class DefaultRelationService @AssistedInject constructor(@Assisted priv
|
|||||||
return TimelineSendEventWorkCommon.createWork<EncryptEventWorker>(sendWorkData, true)
|
return TimelineSendEventWorkCommon.createWork<EncryptEventWorker>(sendWorkData, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createSendEventWork(event: Event): OneTimeWorkRequest {
|
private fun createSendEventWork(event: Event, startChain: Boolean): OneTimeWorkRequest {
|
||||||
val sendContentWorkerParams = SendEventWorker.Params(credentials.userId, roomId, event)
|
val sendContentWorkerParams = SendEventWorker.Params(credentials.userId, roomId, event)
|
||||||
val sendWorkData = WorkerParamsFactory.toData(sendContentWorkerParams)
|
val sendWorkData = WorkerParamsFactory.toData(sendContentWorkerParams)
|
||||||
return TimelineSendEventWorkCommon.createWork<SendEventWorker>(sendWorkData, true)
|
return TimelineSendEventWorkCommon.createWork<SendEventWorker>(sendWorkData, startChain)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getEventSummaryLive(eventId: String): LiveData<EventAnnotationsSummary> {
|
override fun getEventSummaryLive(eventId: String): LiveData<EventAnnotationsSummary> {
|
||||||
@ -220,7 +216,7 @@ internal class DefaultRelationService @AssistedInject constructor(@Assisted priv
|
|||||||
}
|
}
|
||||||
return Transformations.map(liveEntity) { realmResults ->
|
return Transformations.map(liveEntity) { realmResults ->
|
||||||
realmResults.firstOrNull()?.asDomain()
|
realmResults.firstOrNull()?.asDomain()
|
||||||
?: EventAnnotationsSummary(eventId, emptyList(), null)
|
?: EventAnnotationsSummary(eventId, emptyList(), null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,7 +229,7 @@ internal class DefaultRelationService @AssistedInject constructor(@Assisted priv
|
|||||||
private fun saveLocalEcho(event: Event) {
|
private fun saveLocalEcho(event: Event) {
|
||||||
monarchy.writeAsync { realm ->
|
monarchy.writeAsync { realm ->
|
||||||
val roomEntity = RoomEntity.where(realm, roomId = roomId).findFirst()
|
val roomEntity = RoomEntity.where(realm, roomId = roomId).findFirst()
|
||||||
?: return@writeAsync
|
?: return@writeAsync
|
||||||
roomEntity.addSendingEvent(event)
|
roomEntity.addSendingEvent(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater
|
|||||||
import im.vector.matrix.android.internal.util.StringProvider
|
import im.vector.matrix.android.internal.util.StringProvider
|
||||||
import org.commonmark.parser.Parser
|
import org.commonmark.parser.Parser
|
||||||
import org.commonmark.renderer.html.HtmlRenderer
|
import org.commonmark.renderer.html.HtmlRenderer
|
||||||
import java.util.*
|
import java.util.UUID
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -304,17 +304,22 @@ internal class LocalEchoEventFactory @Inject constructor(private val credentials
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun buildReplyFallback(body: TextContent, originalSenderId: String?, newBodyText: String): String {
|
private fun buildReplyFallback(body: TextContent, originalSenderId: String?, newBodyText: String): String {
|
||||||
val lines = body.text.split("\n")
|
return buildString {
|
||||||
val replyFallback = StringBuffer("> <$originalSenderId>")
|
append("> <")
|
||||||
lines.forEachIndexed { index, s ->
|
append(originalSenderId)
|
||||||
if (index == 0) {
|
append(">")
|
||||||
replyFallback.append(" $s")
|
|
||||||
} else {
|
val lines = body.text.split("\n")
|
||||||
replyFallback.append("\n> $s")
|
lines.forEachIndexed { index, s ->
|
||||||
|
if (index == 0) {
|
||||||
|
append(" $s")
|
||||||
|
} else {
|
||||||
|
append("\n> $s")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
append("\n\n")
|
||||||
|
append(newBodyText)
|
||||||
}
|
}
|
||||||
replyFallback.append("\n\n").append(newBodyText)
|
|
||||||
return replyFallback.toString()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,7 +22,7 @@ import im.vector.matrix.android.api.session.events.model.Event
|
|||||||
import im.vector.matrix.android.api.session.events.model.EventType
|
import im.vector.matrix.android.api.session.events.model.EventType
|
||||||
import im.vector.matrix.android.api.session.events.model.toModel
|
import im.vector.matrix.android.api.session.events.model.toModel
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
||||||
import im.vector.matrix.android.internal.crypto.CryptoManager
|
import im.vector.matrix.android.internal.crypto.DefaultCryptoService
|
||||||
import im.vector.matrix.android.internal.crypto.MXEventDecryptionResult
|
import im.vector.matrix.android.internal.crypto.MXEventDecryptionResult
|
||||||
import im.vector.matrix.android.internal.crypto.algorithms.olm.OlmDecryptionResult
|
import im.vector.matrix.android.internal.crypto.algorithms.olm.OlmDecryptionResult
|
||||||
import im.vector.matrix.android.internal.crypto.verification.DefaultSasVerificationService
|
import im.vector.matrix.android.internal.crypto.verification.DefaultSasVerificationService
|
||||||
@ -33,7 +33,7 @@ import timber.log.Timber
|
|||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
||||||
internal class CryptoSyncHandler @Inject constructor(private val cryptoManager: CryptoManager,
|
internal class CryptoSyncHandler @Inject constructor(private val cryptoService: DefaultCryptoService,
|
||||||
private val sasVerificationService: DefaultSasVerificationService) {
|
private val sasVerificationService: DefaultSasVerificationService) {
|
||||||
|
|
||||||
fun handleToDevice(toDevice: ToDeviceSyncResponse, initialSyncProgressService: DefaultInitialSyncProgressService? = null) {
|
fun handleToDevice(toDevice: ToDeviceSyncResponse, initialSyncProgressService: DefaultInitialSyncProgressService? = null) {
|
||||||
@ -47,13 +47,13 @@ internal class CryptoSyncHandler @Inject constructor(private val cryptoManager:
|
|||||||
Timber.e("## handleToDeviceEvent() : Warning: Unable to decrypt to-device event : " + event.content)
|
Timber.e("## handleToDeviceEvent() : Warning: Unable to decrypt to-device event : " + event.content)
|
||||||
} else {
|
} else {
|
||||||
sasVerificationService.onToDeviceEvent(event)
|
sasVerificationService.onToDeviceEvent(event)
|
||||||
cryptoManager.onToDeviceEvent(event)
|
cryptoService.onToDeviceEvent(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onSyncCompleted(syncResponse: SyncResponse) {
|
fun onSyncCompleted(syncResponse: SyncResponse) {
|
||||||
cryptoManager.onSyncCompleted(syncResponse)
|
cryptoService.onSyncCompleted(syncResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ internal class CryptoSyncHandler @Inject constructor(private val cryptoManager:
|
|||||||
if (event.getClearType() == EventType.ENCRYPTED) {
|
if (event.getClearType() == EventType.ENCRYPTED) {
|
||||||
var result: MXEventDecryptionResult? = null
|
var result: MXEventDecryptionResult? = null
|
||||||
try {
|
try {
|
||||||
result = cryptoManager.decryptEvent(event, timelineId ?: "")
|
result = cryptoService.decryptEvent(event, timelineId ?: "")
|
||||||
} catch (exception: MXCryptoError) {
|
} catch (exception: MXCryptoError) {
|
||||||
event.mCryptoError = (exception as? MXCryptoError.Base)?.errorType //setCryptoError(exception.cryptoError)
|
event.mCryptoError = (exception as? MXCryptoError.Base)?.errorType //setCryptoError(exception.cryptoError)
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ import im.vector.matrix.android.api.session.events.model.EventType
|
|||||||
import im.vector.matrix.android.api.session.events.model.toModel
|
import im.vector.matrix.android.api.session.events.model.toModel
|
||||||
import im.vector.matrix.android.api.session.room.model.Membership
|
import im.vector.matrix.android.api.session.room.model.Membership
|
||||||
import im.vector.matrix.android.api.session.room.model.tag.RoomTagContent
|
import im.vector.matrix.android.api.session.room.model.tag.RoomTagContent
|
||||||
import im.vector.matrix.android.internal.crypto.CryptoManager
|
import im.vector.matrix.android.internal.crypto.DefaultCryptoService
|
||||||
import im.vector.matrix.android.internal.database.helper.*
|
import im.vector.matrix.android.internal.database.helper.*
|
||||||
import im.vector.matrix.android.internal.database.model.ChunkEntity
|
import im.vector.matrix.android.internal.database.model.ChunkEntity
|
||||||
import im.vector.matrix.android.internal.database.model.EventEntityFields
|
import im.vector.matrix.android.internal.database.model.EventEntityFields
|
||||||
@ -50,7 +50,7 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch
|
|||||||
private val readReceiptHandler: ReadReceiptHandler,
|
private val readReceiptHandler: ReadReceiptHandler,
|
||||||
private val roomSummaryUpdater: RoomSummaryUpdater,
|
private val roomSummaryUpdater: RoomSummaryUpdater,
|
||||||
private val roomTagHandler: RoomTagHandler,
|
private val roomTagHandler: RoomTagHandler,
|
||||||
private val cryptoManager: CryptoManager,
|
private val cryptoService: DefaultCryptoService,
|
||||||
private val tokenStore: SyncTokenStore,
|
private val tokenStore: SyncTokenStore,
|
||||||
private val pushRuleService: DefaultPushRuleService,
|
private val pushRuleService: DefaultPushRuleService,
|
||||||
private val processForPushTask: ProcessEventForPushTask,
|
private val processForPushTask: ProcessEventForPushTask,
|
||||||
@ -97,12 +97,12 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch
|
|||||||
handleJoinedRoom(realm, it.key, it.value, isInitialSync)
|
handleJoinedRoom(realm, it.key, it.value, isInitialSync)
|
||||||
}
|
}
|
||||||
is HandlingStrategy.INVITED ->
|
is HandlingStrategy.INVITED ->
|
||||||
handlingStrategy.data.mapWithProgress(reporter, R.string.initial_sync_start_importing_account_invited_rooms, 0.4f) {
|
handlingStrategy.data.mapWithProgress(reporter, R.string.initial_sync_start_importing_account_invited_rooms, 0.1f) {
|
||||||
handleInvitedRoom(realm, it.key, it.value)
|
handleInvitedRoom(realm, it.key, it.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
is HandlingStrategy.LEFT -> {
|
is HandlingStrategy.LEFT -> {
|
||||||
handlingStrategy.data.mapWithProgress(reporter, R.string.initial_sync_start_importing_account_left_rooms, 0.2f) {
|
handlingStrategy.data.mapWithProgress(reporter, R.string.initial_sync_start_importing_account_left_rooms, 0.3f) {
|
||||||
handleLeftRoom(realm, it.key, it.value)
|
handleLeftRoom(realm, it.key, it.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -125,8 +125,7 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch
|
|||||||
handleRoomAccountDataEvents(realm, roomId, roomSync.accountData)
|
handleRoomAccountDataEvents(realm, roomId, roomSync.accountData)
|
||||||
}
|
}
|
||||||
|
|
||||||
val roomEntity = RoomEntity.where(realm, roomId).findFirst()
|
val roomEntity = RoomEntity.where(realm, roomId).findFirst() ?: realm.createObject(roomId)
|
||||||
?: realm.createObject(roomId)
|
|
||||||
|
|
||||||
if (roomEntity.membership == Membership.INVITE) {
|
if (roomEntity.membership == Membership.INVITE) {
|
||||||
roomEntity.chunks.deleteAllFromRealm()
|
roomEntity.chunks.deleteAllFromRealm()
|
||||||
@ -135,13 +134,12 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch
|
|||||||
|
|
||||||
// State event
|
// State event
|
||||||
if (roomSync.state != null && roomSync.state.events.isNotEmpty()) {
|
if (roomSync.state != null && roomSync.state.events.isNotEmpty()) {
|
||||||
val minStateIndex = roomEntity.untimelinedStateEvents.where().min(EventEntityFields.STATE_INDEX)?.toInt()
|
val minStateIndex = roomEntity.untimelinedStateEvents.where().min(EventEntityFields.STATE_INDEX)?.toInt() ?: Int.MIN_VALUE
|
||||||
?: Int.MIN_VALUE
|
|
||||||
val untimelinedStateIndex = minStateIndex + 1
|
val untimelinedStateIndex = minStateIndex + 1
|
||||||
roomSync.state.events.forEach { event ->
|
roomSync.state.events.forEach { event ->
|
||||||
roomEntity.addStateEvent(event, filterDuplicates = true, stateIndex = untimelinedStateIndex)
|
roomEntity.addStateEvent(event, filterDuplicates = true, stateIndex = untimelinedStateIndex)
|
||||||
// Give info to crypto module
|
// Give info to crypto module
|
||||||
cryptoManager.onStateEvent(roomId, event)
|
cryptoService.onStateEvent(roomId, event)
|
||||||
UserEntityFactory.createOrNull(event)?.also {
|
UserEntityFactory.createOrNull(event)?.also {
|
||||||
realm.insertOrUpdate(it)
|
realm.insertOrUpdate(it)
|
||||||
}
|
}
|
||||||
@ -167,8 +165,7 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch
|
|||||||
roomSync:
|
roomSync:
|
||||||
InvitedRoomSync): RoomEntity {
|
InvitedRoomSync): RoomEntity {
|
||||||
Timber.v("Handle invited sync for room $roomId")
|
Timber.v("Handle invited sync for room $roomId")
|
||||||
val roomEntity = RoomEntity.where(realm, roomId).findFirst()
|
val roomEntity = RoomEntity.where(realm, roomId).findFirst() ?: realm.createObject(roomId)
|
||||||
?: realm.createObject(roomId)
|
|
||||||
roomEntity.membership = Membership.INVITE
|
roomEntity.membership = Membership.INVITE
|
||||||
if (roomSync.inviteState != null && roomSync.inviteState.events.isNotEmpty()) {
|
if (roomSync.inviteState != null && roomSync.inviteState.events.isNotEmpty()) {
|
||||||
val chunkEntity = handleTimelineEvents(realm, roomEntity, roomSync.inviteState.events)
|
val chunkEntity = handleTimelineEvents(realm, roomEntity, roomSync.inviteState.events)
|
||||||
@ -181,8 +178,7 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch
|
|||||||
private fun handleLeftRoom(realm: Realm,
|
private fun handleLeftRoom(realm: Realm,
|
||||||
roomId: String,
|
roomId: String,
|
||||||
roomSync: RoomSync): RoomEntity {
|
roomSync: RoomSync): RoomEntity {
|
||||||
val roomEntity = RoomEntity.where(realm, roomId).findFirst()
|
val roomEntity = RoomEntity.where(realm, roomId).findFirst() ?: realm.createObject(roomId)
|
||||||
?: realm.createObject(roomId)
|
|
||||||
|
|
||||||
roomEntity.membership = Membership.LEAVE
|
roomEntity.membership = Membership.LEAVE
|
||||||
roomEntity.chunks.deleteAllFromRealm()
|
roomEntity.chunks.deleteAllFromRealm()
|
||||||
@ -214,7 +210,7 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch
|
|||||||
event.eventId?.also { eventIds.add(it) }
|
event.eventId?.also { eventIds.add(it) }
|
||||||
chunkEntity.add(roomEntity.roomId, event, PaginationDirection.FORWARDS, stateIndexOffset)
|
chunkEntity.add(roomEntity.roomId, event, PaginationDirection.FORWARDS, stateIndexOffset)
|
||||||
// Give info to crypto module
|
// Give info to crypto module
|
||||||
cryptoManager.onLiveEvent(roomEntity.roomId, event)
|
cryptoService.onLiveEvent(roomEntity.roomId, event)
|
||||||
// Try to remove local echo
|
// Try to remove local echo
|
||||||
event.unsignedData?.transactionId?.also {
|
event.unsignedData?.transactionId?.also {
|
||||||
val sendingEventEntity = roomEntity.sendingTimelineEvents.find(it)
|
val sendingEventEntity = roomEntity.sendingTimelineEvents.find(it)
|
||||||
|
@ -21,7 +21,6 @@ import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
|||||||
import im.vector.matrix.android.internal.database.model.RoomTagEntity
|
import im.vector.matrix.android.internal.database.model.RoomTagEntity
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
import java.util.*
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class RoomTagHandler @Inject constructor() {
|
internal class RoomTagHandler @Inject constructor() {
|
||||||
@ -30,16 +29,8 @@ internal class RoomTagHandler @Inject constructor() {
|
|||||||
if (content == null) {
|
if (content == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val tags = ArrayList<RoomTagEntity>()
|
val tags = content.tags.entries.map { (tagName, params) ->
|
||||||
for (tagName in content.tags.keys) {
|
RoomTagEntity(tagName, params["order"] as? Double)
|
||||||
val params = content.tags[tagName]
|
|
||||||
val order = params?.get("order")
|
|
||||||
val tag = if (order is Double) {
|
|
||||||
RoomTagEntity(tagName, order)
|
|
||||||
} else {
|
|
||||||
RoomTagEntity(tagName, null)
|
|
||||||
}
|
|
||||||
tags.add(tag)
|
|
||||||
}
|
}
|
||||||
val roomSummaryEntity = RoomSummaryEntity.where(realm, roomId).findFirst()
|
val roomSummaryEntity = RoomSummaryEntity.where(realm, roomId).findFirst()
|
||||||
?: RoomSummaryEntity(roomId)
|
?: RoomSummaryEntity(roomId)
|
||||||
|
@ -18,7 +18,7 @@ package im.vector.matrix.android.internal.session.sync
|
|||||||
|
|
||||||
import arrow.core.Try
|
import arrow.core.Try
|
||||||
import im.vector.matrix.android.R
|
import im.vector.matrix.android.R
|
||||||
import im.vector.matrix.android.internal.crypto.CryptoManager
|
import im.vector.matrix.android.internal.crypto.DefaultCryptoService
|
||||||
import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService
|
import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService
|
||||||
import im.vector.matrix.android.internal.session.reportSubtask
|
import im.vector.matrix.android.internal.session.reportSubtask
|
||||||
import im.vector.matrix.android.internal.session.sync.model.SyncResponse
|
import im.vector.matrix.android.internal.session.sync.model.SyncResponse
|
||||||
@ -30,7 +30,7 @@ internal class SyncResponseHandler @Inject constructor(private val roomSyncHandl
|
|||||||
private val userAccountDataSyncHandler: UserAccountDataSyncHandler,
|
private val userAccountDataSyncHandler: UserAccountDataSyncHandler,
|
||||||
private val groupSyncHandler: GroupSyncHandler,
|
private val groupSyncHandler: GroupSyncHandler,
|
||||||
private val cryptoSyncHandler: CryptoSyncHandler,
|
private val cryptoSyncHandler: CryptoSyncHandler,
|
||||||
private val cryptoManager: CryptoManager,
|
private val cryptoService: DefaultCryptoService,
|
||||||
private val initialSyncProgressService: DefaultInitialSyncProgressService) {
|
private val initialSyncProgressService: DefaultInitialSyncProgressService) {
|
||||||
|
|
||||||
fun handleResponse(syncResponse: SyncResponse, fromToken: String?, isCatchingUp: Boolean): Try<SyncResponse> {
|
fun handleResponse(syncResponse: SyncResponse, fromToken: String?, isCatchingUp: Boolean): Try<SyncResponse> {
|
||||||
@ -40,12 +40,12 @@ internal class SyncResponseHandler @Inject constructor(private val roomSyncHandl
|
|||||||
val reporter = initialSyncProgressService.takeIf { isInitialSync }
|
val reporter = initialSyncProgressService.takeIf { isInitialSync }
|
||||||
|
|
||||||
measureTimeMillis {
|
measureTimeMillis {
|
||||||
if (!cryptoManager.isStarted()) {
|
if (!cryptoService.isStarted()) {
|
||||||
Timber.v("Should start cryptoManager")
|
Timber.v("Should start cryptoService")
|
||||||
cryptoManager.start(isInitialSync)
|
cryptoService.start(isInitialSync)
|
||||||
}
|
}
|
||||||
}.also {
|
}.also {
|
||||||
Timber.v("Finish handling start cryptoManager in $it ms")
|
Timber.v("Finish handling start cryptoService in $it ms")
|
||||||
}
|
}
|
||||||
val measure = measureTimeMillis {
|
val measure = measureTimeMillis {
|
||||||
// Handle the to device events before the room ones
|
// Handle the to device events before the room ones
|
||||||
|
@ -19,7 +19,7 @@ package im.vector.matrix.android.internal.util
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import im.vector.matrix.android.api.util.Cancelable
|
import im.vector.matrix.android.api.util.Cancelable
|
||||||
import java.util.*
|
import java.util.UUID
|
||||||
|
|
||||||
internal class CancelableWork(private val context: Context,
|
internal class CancelableWork(private val context: Context,
|
||||||
private val workId: UUID) : Cancelable {
|
private val workId: UUID) : Cancelable {
|
||||||
|
@ -34,7 +34,7 @@ import java.security.*
|
|||||||
import java.security.cert.CertificateException
|
import java.security.cert.CertificateException
|
||||||
import java.security.spec.AlgorithmParameterSpec
|
import java.security.spec.AlgorithmParameterSpec
|
||||||
import java.security.spec.RSAKeyGenParameterSpec
|
import java.security.spec.RSAKeyGenParameterSpec
|
||||||
import java.util.*
|
import java.util.Calendar
|
||||||
import java.util.zip.GZIPOutputStream
|
import java.util.zip.GZIPOutputStream
|
||||||
import javax.crypto.*
|
import javax.crypto.*
|
||||||
import javax.crypto.spec.GCMParameterSpec
|
import javax.crypto.spec.GCMParameterSpec
|
||||||
|
@ -22,7 +22,7 @@ import org.json.JSONArray
|
|||||||
import org.json.JSONException
|
import org.json.JSONException
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.*
|
import java.util.TreeSet
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build canonical Json
|
* Build canonical Json
|
||||||
@ -60,43 +60,33 @@ object JsonCanonicalizer {
|
|||||||
when (any) {
|
when (any) {
|
||||||
is JSONArray -> {
|
is JSONArray -> {
|
||||||
// Canonicalize each element of the array
|
// Canonicalize each element of the array
|
||||||
val result = StringBuilder("[")
|
return (0 until any.length()).joinToString(separator = ",", prefix = "[", postfix = "]") {
|
||||||
|
canonicalizeRecursive(any.get(it))
|
||||||
for (i in 0 until any.length()) {
|
|
||||||
result.append(canonicalizeRecursive(any.get(i)))
|
|
||||||
if (i < any.length() - 1) {
|
|
||||||
result.append(",")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result.append("]")
|
|
||||||
|
|
||||||
return result.toString()
|
|
||||||
}
|
}
|
||||||
is JSONObject -> {
|
is JSONObject -> {
|
||||||
// Sort the attributes by name, and the canonicalize each element of the JSONObject
|
// Sort the attributes by name, and the canonicalize each element of the JSONObject
|
||||||
val result = StringBuilder("{")
|
|
||||||
|
|
||||||
val attributes = TreeSet<String>()
|
val attributes = TreeSet<String>()
|
||||||
for (entry in any.keys()) {
|
for (entry in any.keys()) {
|
||||||
attributes.add(entry)
|
attributes.add(entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (attribute in attributes.withIndex()) {
|
return buildString {
|
||||||
result.append("\"")
|
append("{")
|
||||||
.append(attribute.value)
|
for ((index, value) in attributes.withIndex()) {
|
||||||
.append("\"")
|
append("\"")
|
||||||
.append(":")
|
append(value)
|
||||||
.append(canonicalizeRecursive(any[attribute.value]))
|
append("\"")
|
||||||
|
append(":")
|
||||||
|
append(canonicalizeRecursive(any[value]))
|
||||||
|
|
||||||
if (attribute.index < attributes.size - 1) {
|
if (index < attributes.size - 1) {
|
||||||
result.append(",")
|
append(",")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
append("}")
|
||||||
}
|
}
|
||||||
|
|
||||||
result.append("}")
|
|
||||||
|
|
||||||
return result.toString()
|
|
||||||
}
|
}
|
||||||
is String -> return JSONObject.quote(any)
|
is String -> return JSONObject.quote(any)
|
||||||
else -> return any.toString()
|
else -> return any.toString()
|
||||||
|
@ -167,4 +167,9 @@
|
|||||||
<string name="initial_sync_start_importing_account_data">Начална синхронизация:
|
<string name="initial_sync_start_importing_account_data">Начална синхронизация:
|
||||||
\nИмпортиране на данни за профила</string>
|
\nИмпортиране на данни за профила</string>
|
||||||
|
|
||||||
|
<string name="notice_room_update">%s обнови тази стая.</string>
|
||||||
|
|
||||||
|
<string name="event_status_sending_message">Изпращане на съобщение…</string>
|
||||||
|
<string name="clear_timeline_send_queue">Изчисти опашката за изпращане</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -105,4 +105,65 @@
|
|||||||
<string name="verification_emoji_pig">Schwein</string>
|
<string name="verification_emoji_pig">Schwein</string>
|
||||||
<string name="verification_emoji_elephant">Elefant</string>
|
<string name="verification_emoji_elephant">Elefant</string>
|
||||||
<string name="verification_emoji_rabbit">Hase</string>
|
<string name="verification_emoji_rabbit">Hase</string>
|
||||||
|
<string name="notice_room_update">%s hat diesen Raum aufgewertet.</string>
|
||||||
|
|
||||||
|
<string name="verification_emoji_panda">Panda</string>
|
||||||
|
<string name="verification_emoji_rooster">Hahn</string>
|
||||||
|
<string name="verification_emoji_penguin">Pinguin</string>
|
||||||
|
<string name="verification_emoji_turtle">Schildkröte</string>
|
||||||
|
<string name="verification_emoji_fish">Fisch</string>
|
||||||
|
<string name="verification_emoji_octopus">Tintenfisch</string>
|
||||||
|
<string name="verification_emoji_butterfly">Schmetterling</string>
|
||||||
|
<string name="verification_emoji_flower">Blume</string>
|
||||||
|
<string name="verification_emoji_tree">Baum</string>
|
||||||
|
<string name="verification_emoji_cactus">Kaktus</string>
|
||||||
|
<string name="verification_emoji_mushroom">Pilz</string>
|
||||||
|
<string name="verification_emoji_globe">Globus</string>
|
||||||
|
<string name="verification_emoji_moon">Mond</string>
|
||||||
|
<string name="verification_emoji_cloud">Wolke</string>
|
||||||
|
<string name="verification_emoji_fire">Feuer</string>
|
||||||
|
<string name="verification_emoji_banana">Banane</string>
|
||||||
|
<string name="verification_emoji_apple">Apfel</string>
|
||||||
|
<string name="verification_emoji_strawberry">Erdbeere</string>
|
||||||
|
<string name="verification_emoji_corn">Mais</string>
|
||||||
|
<string name="verification_emoji_cake">Kuchen</string>
|
||||||
|
<string name="verification_emoji_heart">Herz</string>
|
||||||
|
<string name="verification_emoji_smiley">Lächeln</string>
|
||||||
|
<string name="verification_emoji_robot">Roboter</string>
|
||||||
|
<string name="verification_emoji_hat">Hut</string>
|
||||||
|
<string name="verification_emoji_glasses">Brille</string>
|
||||||
|
<string name="verification_emoji_wrench">Schraubenschlüssel</string>
|
||||||
|
<string name="verification_emoji_santa">Nikolaus</string>
|
||||||
|
<string name="verification_emoji_thumbsup">Daumen hoch</string>
|
||||||
|
<string name="verification_emoji_umbrella">Regenschirm</string>
|
||||||
|
<string name="verification_emoji_hourglass">Sanduhr</string>
|
||||||
|
<string name="verification_emoji_clock">Uhr</string>
|
||||||
|
<string name="verification_emoji_gift">Geschenk</string>
|
||||||
|
<string name="verification_emoji_lightbulb">Glühbirne</string>
|
||||||
|
<string name="verification_emoji_book">Buch</string>
|
||||||
|
<string name="verification_emoji_pencil">Stift</string>
|
||||||
|
<string name="verification_emoji_paperclip">Büroklammer</string>
|
||||||
|
<string name="verification_emoji_scissors">Scheren</string>
|
||||||
|
<string name="verification_emoji_lock">sperren</string>
|
||||||
|
<string name="verification_emoji_key">Schlüssel</string>
|
||||||
|
<string name="verification_emoji_hammer">Hammer</string>
|
||||||
|
<string name="verification_emoji_telephone">Telefon</string>
|
||||||
|
<string name="verification_emoji_flag">Flagge</string>
|
||||||
|
<string name="verification_emoji_train">Zug</string>
|
||||||
|
<string name="verification_emoji_bicycle">Fahrrad</string>
|
||||||
|
<string name="verification_emoji_airplane">Flugzeug</string>
|
||||||
|
<string name="verification_emoji_rocket">Rakete</string>
|
||||||
|
<string name="verification_emoji_trophy">Pokal</string>
|
||||||
|
<string name="verification_emoji_ball">Ball</string>
|
||||||
|
<string name="verification_emoji_guitar">Gitarre</string>
|
||||||
|
<string name="verification_emoji_trumpet">Trompete</string>
|
||||||
|
<string name="verification_emoji_bell">Glocke</string>
|
||||||
|
<string name="verification_emoji_anchor">Anker</string>
|
||||||
|
<string name="verification_emoji_headphone">Kopfhörer</string>
|
||||||
|
<string name="verification_emoji_folder">Ordner</string>
|
||||||
|
<string name="verification_emoji_pin">Stecknadel</string>
|
||||||
|
|
||||||
|
<string name="event_status_sending_message">Sende eine Nachricht…</string>
|
||||||
|
<string name="clear_timeline_send_queue">Sendewarteschlange leeren</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -167,4 +167,9 @@
|
|||||||
<string name="initial_sync_start_importing_account_data">Hasierako sinkronizazioa:
|
<string name="initial_sync_start_importing_account_data">Hasierako sinkronizazioa:
|
||||||
\nKontuaren datuak inportatzen</string>
|
\nKontuaren datuak inportatzen</string>
|
||||||
|
|
||||||
|
<string name="notice_room_update">%s erabiltzaileak gela hau eguneratu du.</string>
|
||||||
|
|
||||||
|
<string name="event_status_sending_message">Mezua bidaltzen…</string>
|
||||||
|
<string name="clear_timeline_send_queue">Garbitu bidalketa-ilara</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -168,4 +168,9 @@
|
|||||||
<string name="initial_sync_start_importing_account_data">Alkusynkronointi:
|
<string name="initial_sync_start_importing_account_data">Alkusynkronointi:
|
||||||
\nTuodaan tilin tietoja</string>
|
\nTuodaan tilin tietoja</string>
|
||||||
|
|
||||||
|
<string name="notice_room_update">%s päivitti tämän huoneen.</string>
|
||||||
|
|
||||||
|
<string name="event_status_sending_message">Lähetetään viestiä…</string>
|
||||||
|
<string name="clear_timeline_send_queue">Tyhjennä lähetysjono</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -167,4 +167,9 @@
|
|||||||
<string name="initial_sync_start_importing_account_data">Synchronisation initiale :
|
<string name="initial_sync_start_importing_account_data">Synchronisation initiale :
|
||||||
\nImportation des données du compte</string>
|
\nImportation des données du compte</string>
|
||||||
|
|
||||||
|
<string name="notice_room_update">%s a mis à niveau ce salon.</string>
|
||||||
|
|
||||||
|
<string name="event_status_sending_message">Envoi du message…</string>
|
||||||
|
<string name="clear_timeline_send_queue">Vider la file d’envoi</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -166,4 +166,9 @@
|
|||||||
<string name="initial_sync_start_importing_account_data">Induló szinkronizáció:
|
<string name="initial_sync_start_importing_account_data">Induló szinkronizáció:
|
||||||
\nFiók adatok betöltése</string>
|
\nFiók adatok betöltése</string>
|
||||||
|
|
||||||
|
<string name="notice_room_update">%s frissítette ezt a szobát.</string>
|
||||||
|
|
||||||
|
<string name="event_status_sending_message">Üzenet küldése…</string>
|
||||||
|
<string name="clear_timeline_send_queue">Küldő sor ürítése</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -167,4 +167,9 @@
|
|||||||
<string name="initial_sync_start_importing_account_data">Sync iniziale:
|
<string name="initial_sync_start_importing_account_data">Sync iniziale:
|
||||||
\nImportazione dati account</string>
|
\nImportazione dati account</string>
|
||||||
|
|
||||||
|
<string name="notice_room_update">%s ha aggiornato questa stanza.</string>
|
||||||
|
|
||||||
|
<string name="event_status_sending_message">Invio messaggio in corso …</string>
|
||||||
|
<string name="clear_timeline_send_queue">Cancella la coda di invio</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -1,6 +1,173 @@
|
|||||||
<?xml version='1.0' encoding='UTF-8'?>
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="summary_message">%1$s: %2$s</string>
|
<string name="summary_message">%1$s: %2$s</string>
|
||||||
<string name="notice_room_invite_no_invitee">%s\'의 초대</string>
|
<string name="notice_room_invite_no_invitee">%s님의 초대</string>
|
||||||
<string name="verification_emoji_headphone">헤드폰</string>
|
<string name="verification_emoji_headphone">헤드폰</string>
|
||||||
|
<string name="summary_user_sent_image">%1$s님이 사진을 보냈습니다.</string>
|
||||||
|
<string name="summary_user_sent_sticker">%1$s님이 스티커를 보냈습니다.</string>
|
||||||
|
|
||||||
|
<string name="notice_room_invite">%1$s님이 %2$s님을 초대했습니다</string>
|
||||||
|
<string name="notice_room_invite_you">%1$s님이 당신을 초대했습니다</string>
|
||||||
|
<string name="notice_room_join">%1$s님이 참가했습니다</string>
|
||||||
|
<string name="notice_room_leave">%1$s님이 떠났습니다</string>
|
||||||
|
<string name="notice_room_reject">%1$s님이 초대를 거부했습니다</string>
|
||||||
|
<string name="notice_room_kick">%1$s님이 %2$s님을 추방했습니다</string>
|
||||||
|
<string name="notice_room_unban">%1$s님이 %2$s님의 차단을 풀었습니다</string>
|
||||||
|
<string name="notice_room_ban">%1$s님이 %2$s님을 차단했습니다</string>
|
||||||
|
<string name="notice_room_withdraw">%1$s님이 %2$s님의 초대를 취소했습니다</string>
|
||||||
|
<string name="notice_avatar_url_changed">%1$s님이 아바타를 변경했습니다</string>
|
||||||
|
<string name="notice_display_name_set">%1$s님이 표시 이름을 %2$s(으)로 설정했습니다</string>
|
||||||
|
<string name="notice_display_name_changed_from">%1$s님이 표시 이름을 %2$s에서 %3$s(으)로 변경했습니다</string>
|
||||||
|
<string name="notice_display_name_removed">%1$s님이 표시 이름을 삭제했습니다 (%2$s)</string>
|
||||||
|
<string name="notice_room_topic_changed">%1$s님이 주제를 다음으로 변경했습니다: %2$s</string>
|
||||||
|
<string name="notice_room_name_changed">%1$s님이 방 이름을 다음으로 변경했습니다: %2$s</string>
|
||||||
|
<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_made_future_room_visibility">%1$s님이 이후 %2$s에게 방 기록을 공개했습니다</string>
|
||||||
|
<string name="notice_room_visibility_invited">초대된 시점부터 모든 방 구성원.</string>
|
||||||
|
<string name="notice_room_visibility_joined">들어온 시점부터 모든 방 구성원.</string>
|
||||||
|
<string name="notice_room_visibility_shared">모든 방 구성원.</string>
|
||||||
|
<string name="notice_room_visibility_world_readable">누구나.</string>
|
||||||
|
<string name="notice_room_visibility_unknown">알 수 없음 (%s).</string>
|
||||||
|
<string name="notice_end_to_end">%1$s님이 종단 간 암호화를 켰습니다 (%2$s)</string>
|
||||||
|
<string name="notice_room_update">%s님이 방을 업그레이드했습니다.</string>
|
||||||
|
|
||||||
|
<string name="notice_requested_voip_conference">%1$s님이 VoIP 회의를 요청했습니다</string>
|
||||||
|
<string name="notice_voip_started">VoIP 회의가 시작했습니다</string>
|
||||||
|
<string name="notice_voip_finished">VoIP 회의가 끝났습니다</string>
|
||||||
|
|
||||||
|
<string name="notice_avatar_changed_too">(아바타도 변경됨)</string>
|
||||||
|
<string name="notice_room_name_removed">%1$s님이 방 이름을 삭제했습니다</string>
|
||||||
|
<string name="notice_room_topic_removed">%1$s님이 방 주제를 삭제했습니다</string>
|
||||||
|
<string name="notice_event_redacted">메시지가 삭제되었습니다</string>
|
||||||
|
<string name="notice_event_redacted_by">메시지가 %1$s님에 의해 삭제되었습니다</string>
|
||||||
|
<string name="notice_event_redacted_with_reason">메시지가 삭제되었습니다 [이유: %1$s]</string>
|
||||||
|
<string name="notice_event_redacted_by_with_reason">메시지가 %1$s님에 의해 삭제되었습니다 [이유: %2$s]</string>
|
||||||
|
<string name="notice_profile_change_redacted">%1$s님이 프로필 %2$s을(를) 업데이트했습니다</string>
|
||||||
|
<string name="notice_room_third_party_invite">%1$s님이 %2$s님에게 방 초대를 보냈습니다</string>
|
||||||
|
<string name="notice_room_third_party_registered_invite">%1$s님이 %2$s의 초대를 수락했습니다</string>
|
||||||
|
|
||||||
|
<string name="notice_crypto_unable_to_decrypt">** 암호를 해독할 수 없음: %s **</string>
|
||||||
|
<string name="notice_crypto_error_unkwown_inbound_session_id">발신인의 기기에서 이 메시지의 키를 보내지 않았습니다.</string>
|
||||||
|
|
||||||
|
<string name="message_reply_to_prefix">이 답장의 질문</string>
|
||||||
|
|
||||||
|
<string name="could_not_redact">검열할 수 없습니다</string>
|
||||||
|
<string name="unable_to_send_message">메시지를 보낼 수 없습니다</string>
|
||||||
|
|
||||||
|
<string name="message_failed_to_upload">사진 업로드에 실패했습니다</string>
|
||||||
|
|
||||||
|
<string name="network_error">네트워크 오류</string>
|
||||||
|
<string name="matrix_error">Matrix 오류</string>
|
||||||
|
|
||||||
|
<string name="room_error_join_failed_empty_room">현재 빈 방에 다시 들어갈 수 없습니다.</string>
|
||||||
|
|
||||||
|
<string name="encrypted_message">암호화된 메시지</string>
|
||||||
|
|
||||||
|
<string name="medium_email">이메일 주소</string>
|
||||||
|
<string name="medium_phone_number">전화번호</string>
|
||||||
|
|
||||||
|
<string name="reply_to_an_image">사진을 보냈습니다.</string>
|
||||||
|
<string name="reply_to_a_video">동영상을 보냈습니다.</string>
|
||||||
|
<string name="reply_to_an_audio_file">오디오 파일을 보냈습니다.</string>
|
||||||
|
<string name="reply_to_a_file">파일을 보냈습니다.</string>
|
||||||
|
|
||||||
|
<string name="room_displayname_invite_from">%s에서 초대함</string>
|
||||||
|
<string name="room_displayname_room_invite">방 초대</string>
|
||||||
|
|
||||||
|
<string name="room_displayname_two_members">%1$s님과 %2$s님</string>
|
||||||
|
|
||||||
|
<plurals name="room_displayname_three_and_more_members">
|
||||||
|
<item quantity="other">%1$s님 외 %2$d명</item>
|
||||||
|
</plurals>
|
||||||
|
|
||||||
|
<string name="room_displayname_empty_room">빈 방</string>
|
||||||
|
|
||||||
|
|
||||||
|
<string name="verification_emoji_dog">개</string>
|
||||||
|
<string name="verification_emoji_cat">고양이</string>
|
||||||
|
<string name="verification_emoji_lion">사자</string>
|
||||||
|
<string name="verification_emoji_horse">말</string>
|
||||||
|
<string name="verification_emoji_unicorn">유니콘</string>
|
||||||
|
<string name="verification_emoji_pig">돼지</string>
|
||||||
|
<string name="verification_emoji_elephant">코끼리</string>
|
||||||
|
<string name="verification_emoji_rabbit">토끼</string>
|
||||||
|
<string name="verification_emoji_panda">판다</string>
|
||||||
|
<string name="verification_emoji_rooster">수탉</string>
|
||||||
|
<string name="verification_emoji_penguin">펭귄</string>
|
||||||
|
<string name="verification_emoji_turtle">거북</string>
|
||||||
|
<string name="verification_emoji_fish">물고기</string>
|
||||||
|
<string name="verification_emoji_octopus">문어</string>
|
||||||
|
<string name="verification_emoji_butterfly">나비</string>
|
||||||
|
<string name="verification_emoji_flower">꽃</string>
|
||||||
|
<string name="verification_emoji_tree">나무</string>
|
||||||
|
<string name="verification_emoji_cactus">선인장</string>
|
||||||
|
<string name="verification_emoji_mushroom">버섯</string>
|
||||||
|
<string name="verification_emoji_globe">지구본</string>
|
||||||
|
<string name="verification_emoji_moon">달</string>
|
||||||
|
<string name="verification_emoji_cloud">구름</string>
|
||||||
|
<string name="verification_emoji_fire">불</string>
|
||||||
|
<string name="verification_emoji_banana">바나나</string>
|
||||||
|
<string name="verification_emoji_apple">사과</string>
|
||||||
|
<string name="verification_emoji_strawberry">딸기</string>
|
||||||
|
<string name="verification_emoji_corn">옥수수</string>
|
||||||
|
<string name="verification_emoji_pizza">피자</string>
|
||||||
|
<string name="verification_emoji_cake">케이크</string>
|
||||||
|
<string name="verification_emoji_heart">하트</string>
|
||||||
|
<string name="verification_emoji_smiley">웃음</string>
|
||||||
|
<string name="verification_emoji_robot">로봇</string>
|
||||||
|
<string name="verification_emoji_hat">모자</string>
|
||||||
|
<string name="verification_emoji_glasses">안경</string>
|
||||||
|
<string name="verification_emoji_wrench">스패너</string>
|
||||||
|
<string name="verification_emoji_santa">산타클로스</string>
|
||||||
|
<string name="verification_emoji_thumbsup">좋아요</string>
|
||||||
|
<string name="verification_emoji_umbrella">우산</string>
|
||||||
|
<string name="verification_emoji_hourglass">모래시계</string>
|
||||||
|
<string name="verification_emoji_clock">시계</string>
|
||||||
|
<string name="verification_emoji_gift">선물</string>
|
||||||
|
<string name="verification_emoji_lightbulb">전구</string>
|
||||||
|
<string name="verification_emoji_book">책</string>
|
||||||
|
<string name="verification_emoji_pencil">연필</string>
|
||||||
|
<string name="verification_emoji_paperclip">클립</string>
|
||||||
|
<string name="verification_emoji_scissors">가위</string>
|
||||||
|
<string name="verification_emoji_lock">자물쇠</string>
|
||||||
|
<string name="verification_emoji_key">열쇠</string>
|
||||||
|
<string name="verification_emoji_hammer">망치</string>
|
||||||
|
<string name="verification_emoji_telephone">전화기</string>
|
||||||
|
<string name="verification_emoji_flag">깃발</string>
|
||||||
|
<string name="verification_emoji_train">기차</string>
|
||||||
|
<string name="verification_emoji_bicycle">자전거</string>
|
||||||
|
<string name="verification_emoji_airplane">비행기</string>
|
||||||
|
<string name="verification_emoji_rocket">로켓</string>
|
||||||
|
<string name="verification_emoji_trophy">트로피</string>
|
||||||
|
<string name="verification_emoji_ball">공</string>
|
||||||
|
<string name="verification_emoji_guitar">기타</string>
|
||||||
|
<string name="verification_emoji_trumpet">트럼펫</string>
|
||||||
|
<string name="verification_emoji_bell">종</string>
|
||||||
|
<string name="verification_emoji_anchor">닻</string>
|
||||||
|
<string name="verification_emoji_folder">폴더</string>
|
||||||
|
<string name="verification_emoji_pin">핀</string>
|
||||||
|
|
||||||
|
<string name="initial_sync_start_importing_account">초기 동기화:
|
||||||
|
\n계정 가져오는 중…</string>
|
||||||
|
<string name="initial_sync_start_importing_account_crypto">초기 동기화:
|
||||||
|
\n암호 가져오는 중</string>
|
||||||
|
<string name="initial_sync_start_importing_account_rooms">초기 동기화:
|
||||||
|
\n방 가져오는 중</string>
|
||||||
|
<string name="initial_sync_start_importing_account_joined_rooms">초기 동기화:
|
||||||
|
\n들어간 방 가져오는 중</string>
|
||||||
|
<string name="initial_sync_start_importing_account_invited_rooms">초기 동기화:
|
||||||
|
\n초대받은 방 가져오는 중</string>
|
||||||
|
<string name="initial_sync_start_importing_account_left_rooms">초기 동기화:
|
||||||
|
\n떠난 방 가져오는 중</string>
|
||||||
|
<string name="initial_sync_start_importing_account_groups">초기 동기화:
|
||||||
|
\n커뮤니티 가져오는 중</string>
|
||||||
|
<string name="initial_sync_start_importing_account_data">초기 동기화:
|
||||||
|
\n계정 데이터 가져오는 중</string>
|
||||||
|
|
||||||
|
<string name="event_status_sending_message">메시지 보내는 중…</string>
|
||||||
|
<string name="clear_timeline_send_queue">전송 대기 열 지우기</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -176,4 +176,9 @@
|
|||||||
<string name="initial_sync_start_importing_account_data">Initiële synchronisatie:
|
<string name="initial_sync_start_importing_account_data">Initiële synchronisatie:
|
||||||
\nAccountgegevens worden geïmporteerd</string>
|
\nAccountgegevens worden geïmporteerd</string>
|
||||||
|
|
||||||
|
<string name="notice_room_update">%s heeft dit gesprek opgewaardeerd.</string>
|
||||||
|
|
||||||
|
<string name="event_status_sending_message">Bericht wordt verstuurd…</string>
|
||||||
|
<string name="clear_timeline_send_queue">Uitgaande wachtrij legen</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<string name="notice_room_invite">%1$s zaprosił(a) %2$s</string>
|
<string name="notice_room_invite">%1$s zaprosił(a) %2$s</string>
|
||||||
<string name="notice_room_invite_you">%1$s zaprosił(a) Cię</string>
|
<string name="notice_room_invite_you">%1$s zaprosił(a) Cię</string>
|
||||||
<string name="notice_room_join">%1$s dołączył(a)</string>
|
<string name="notice_room_join">%1$s dołączył(a)</string>
|
||||||
<string name="notice_room_leave">%1$s wyszedł(-ła)</string>
|
<string name="notice_room_leave">%1$s opuścił(a)</string>
|
||||||
<string name="notice_room_reject">%1$s odrzucił(a) zaproszenie</string>
|
<string name="notice_room_reject">%1$s odrzucił(a) zaproszenie</string>
|
||||||
<string name="notice_room_kick">%1$s wyrzucił(a) %2$s</string>
|
<string name="notice_room_kick">%1$s wyrzucił(a) %2$s</string>
|
||||||
<string name="notice_room_unban">%1$s odblokował(a) %2$s</string>
|
<string name="notice_room_unban">%1$s odblokował(a) %2$s</string>
|
||||||
@ -17,11 +17,11 @@
|
|||||||
<string name="notice_display_name_changed_from">%1$s zmienił(a) wyświetlaną nazwę z %2$s na %3$s</string>
|
<string name="notice_display_name_changed_from">%1$s zmienił(a) wyświetlaną nazwę z %2$s na %3$s</string>
|
||||||
<string name="notice_display_name_removed">%1$s usunął(-ęła) swoją wyświetlaną nazwę (%2$s)</string>
|
<string name="notice_display_name_removed">%1$s usunął(-ęła) swoją wyświetlaną nazwę (%2$s)</string>
|
||||||
<string name="notice_room_topic_changed">%1$s zmienił(a) temat na: %2$s</string>
|
<string name="notice_room_topic_changed">%1$s zmienił(a) temat na: %2$s</string>
|
||||||
<string name="unable_to_send_message">Nie udało się wysłać wiadomości</string>
|
<string name="unable_to_send_message">Nie można wysłać wiadomości</string>
|
||||||
|
|
||||||
<string name="message_failed_to_upload">Nie udało się wysłać zdjęcia</string>
|
<string name="message_failed_to_upload">Przesyłanie zdjęcia nie powiodło się</string>
|
||||||
|
|
||||||
<string name="network_error">ogólne błędy</string>
|
<string name="network_error">Błąd sieci</string>
|
||||||
<string name="matrix_error">Błąd Matrixa</string>
|
<string name="matrix_error">Błąd Matrixa</string>
|
||||||
|
|
||||||
<string name="encrypted_message">Wiadomość zaszyfrowana</string>
|
<string name="encrypted_message">Wiadomość zaszyfrowana</string>
|
||||||
@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
<string name="notice_room_visibility_shared">wszyscy członkowie pokoju.</string>
|
<string name="notice_room_visibility_shared">wszyscy członkowie pokoju.</string>
|
||||||
<string name="notice_room_visibility_world_readable">wszyscy.</string>
|
<string name="notice_room_visibility_world_readable">wszyscy.</string>
|
||||||
<string name="notice_room_name_changed">%1$s zmienił(a) znawę pokoju na: %2$s</string>
|
<string name="notice_room_name_changed">%1$s zmienił(a) nazwę pokoju na: %2$s</string>
|
||||||
<string name="notice_ended_call">%s zakończył(a) rozmowę.</string>
|
<string name="notice_ended_call">%s zakończył(a) rozmowę.</string>
|
||||||
<string name="notice_room_name_removed">%1$s usunął(-ęła) nazwę pokoju</string>
|
<string name="notice_room_name_removed">%1$s usunął(-ęła) nazwę pokoju</string>
|
||||||
<string name="notice_room_topic_removed">%1$s usunął(-ęła) temat pokoju</string>
|
<string name="notice_room_topic_removed">%1$s usunął(-ęła) temat pokoju</string>
|
||||||
@ -57,9 +57,9 @@
|
|||||||
</plurals>
|
</plurals>
|
||||||
|
|
||||||
<string name="notice_crypto_unable_to_decrypt">** Nie można odszyfrować: %s **</string>
|
<string name="notice_crypto_unable_to_decrypt">** Nie można odszyfrować: %s **</string>
|
||||||
<string name="notice_placed_video_call">%s umieścił wideo rozmowe.</string>
|
<string name="notice_placed_video_call">%s wykonał(a) rozmowę wideo.</string>
|
||||||
<string name="notice_placed_voice_call">%s umieścił połączenie głosowe.</string>
|
<string name="notice_placed_voice_call">%s wykonał(a) połączenie głosowe.</string>
|
||||||
<string name="notice_made_future_room_visibility">%1$s uczynił historię pokoju widoczną do %2$s</string>
|
<string name="notice_made_future_room_visibility">%1$s uczynił(a) przyszłą historię pokoju widoczną dla %2$s</string>
|
||||||
<string name="notice_room_visibility_invited">wszyscy członkowie pokoju, od momentu w którym zostali zaproszeni.</string>
|
<string name="notice_room_visibility_invited">wszyscy członkowie pokoju, od momentu w którym zostali zaproszeni.</string>
|
||||||
<string name="notice_room_visibility_joined">wszyscy członkowie pokoju, od momentu w którym dołączyli.</string>
|
<string name="notice_room_visibility_joined">wszyscy członkowie pokoju, od momentu w którym dołączyli.</string>
|
||||||
<string name="notice_room_visibility_unknown">nieznane (%s).</string>
|
<string name="notice_room_visibility_unknown">nieznane (%s).</string>
|
||||||
@ -147,4 +147,29 @@
|
|||||||
<string name="verification_emoji_santa">Mikołaj</string>
|
<string name="verification_emoji_santa">Mikołaj</string>
|
||||||
<string name="verification_emoji_gift">Prezent</string>
|
<string name="verification_emoji_gift">Prezent</string>
|
||||||
<string name="verification_emoji_hammer">Młotek</string>
|
<string name="verification_emoji_hammer">Młotek</string>
|
||||||
|
<string name="notice_room_update">%s zakutalizował(a) ten pokój.</string>
|
||||||
|
|
||||||
|
<string name="verification_emoji_thumbsup">Kciuk w górę</string>
|
||||||
|
<string name="verification_emoji_lock">Zamek</string>
|
||||||
|
<string name="verification_emoji_ball">Piłka</string>
|
||||||
|
<string name="initial_sync_start_importing_account">Synchronizacja początkowa:
|
||||||
|
\nImportowanie konta…</string>
|
||||||
|
<string name="initial_sync_start_importing_account_crypto">Synchronizacja początkowa:
|
||||||
|
\nImportowanie kryptografii</string>
|
||||||
|
<string name="initial_sync_start_importing_account_rooms">Synchronizacja początkowa:
|
||||||
|
\nImportowanie Pokoi</string>
|
||||||
|
<string name="initial_sync_start_importing_account_joined_rooms">Synchronizacja początkowa:
|
||||||
|
\nImportowanie dołączonych Pokoi</string>
|
||||||
|
<string name="initial_sync_start_importing_account_invited_rooms">Synchronizacja początkowa:
|
||||||
|
\nImportowanie zaproszonych Pokoi</string>
|
||||||
|
<string name="initial_sync_start_importing_account_left_rooms">Synchronizacja początkowa:
|
||||||
|
\nImportowanie opuszczonych Pokoi</string>
|
||||||
|
<string name="initial_sync_start_importing_account_groups">Synchronizacja początkowa:
|
||||||
|
\nImportowanie Społeczności</string>
|
||||||
|
<string name="initial_sync_start_importing_account_data">Synchronizacja początkowa:
|
||||||
|
\nImportowanie danych Konta</string>
|
||||||
|
|
||||||
|
<string name="event_status_sending_message">Wysyłanie wiadomości…</string>
|
||||||
|
<string name="clear_timeline_send_queue">Wyczyść kolejkę wysyłania</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -78,4 +78,10 @@
|
|||||||
<string name="room_displayname_empty_room">Sala vazia</string>
|
<string name="room_displayname_empty_room">Sala vazia</string>
|
||||||
|
|
||||||
|
|
||||||
|
<string name="summary_user_sent_sticker">%1$s enviou um sticker.</string>
|
||||||
|
|
||||||
|
<string name="notice_room_update">%s fez o upgrade da sala.</string>
|
||||||
|
|
||||||
|
<string name="notice_event_redacted">Mensagem removida</string>
|
||||||
|
<string name="notice_event_redacted_by">Mensagem removida por %1$s</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -169,9 +169,9 @@
|
|||||||
\nИмпорт криптографии</string>
|
\nИмпорт криптографии</string>
|
||||||
<string name="initial_sync_start_importing_account_rooms">Начальная синхронизация:
|
<string name="initial_sync_start_importing_account_rooms">Начальная синхронизация:
|
||||||
\nИмпорт комнат</string>
|
\nИмпорт комнат</string>
|
||||||
<string name="initial_sync_start_importing_account_joined_rooms">Начальная синхронизация:
|
<string name="initial_sync_start_importing_account_joined_rooms">Синхронизация начата:
|
||||||
\nИмпорт присоединенных комнат</string>
|
\nИмпорт присоединенных комнат</string>
|
||||||
<string name="initial_sync_start_importing_account_invited_rooms">Начальная синхронизация:
|
<string name="initial_sync_start_importing_account_invited_rooms">Синхронизация начата:
|
||||||
\nИмпорт приглашенных комнат</string>
|
\nИмпорт приглашенных комнат</string>
|
||||||
<string name="initial_sync_start_importing_account_left_rooms">Начальная синхронизация:
|
<string name="initial_sync_start_importing_account_left_rooms">Начальная синхронизация:
|
||||||
\nИмпорт покинутых комнат</string>
|
\nИмпорт покинутых комнат</string>
|
||||||
@ -180,4 +180,9 @@
|
|||||||
<string name="initial_sync_start_importing_account_data">Начальная синхронизация:
|
<string name="initial_sync_start_importing_account_data">Начальная синхронизация:
|
||||||
\nИмпорт данных учетной записи</string>
|
\nИмпорт данных учетной записи</string>
|
||||||
|
|
||||||
|
<string name="notice_room_update">%s обновил эту комнату.</string>
|
||||||
|
|
||||||
|
<string name="event_status_sending_message">Отправка сообщения…</string>
|
||||||
|
<string name="clear_timeline_send_queue">Очистить очередь отправки</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -82,4 +82,95 @@
|
|||||||
</plurals>
|
</plurals>
|
||||||
|
|
||||||
|
|
||||||
|
<string name="notice_room_update">%s aktualizoval túto miestnosť.</string>
|
||||||
|
|
||||||
|
<string name="notice_event_redacted">Správa odstránená</string>
|
||||||
|
<string name="notice_event_redacted_by">Správa odstránená používateľom %1$s</string>
|
||||||
|
<string name="notice_event_redacted_with_reason">Správa odstránená [dôvod: %1$s]</string>
|
||||||
|
<string name="notice_event_redacted_by_with_reason">Správa odstránená používateľom %1$s [dôvod: %2$s]</string>
|
||||||
|
<string name="verification_emoji_dog">Pes</string>
|
||||||
|
<string name="verification_emoji_cat">Mačka</string>
|
||||||
|
<string name="verification_emoji_lion">Lev</string>
|
||||||
|
<string name="verification_emoji_horse">Kôň</string>
|
||||||
|
<string name="verification_emoji_unicorn">Jednorožec</string>
|
||||||
|
<string name="verification_emoji_pig">Prasa</string>
|
||||||
|
<string name="verification_emoji_elephant">Slon</string>
|
||||||
|
<string name="verification_emoji_rabbit">Zajac</string>
|
||||||
|
<string name="verification_emoji_panda">Panda</string>
|
||||||
|
<string name="verification_emoji_rooster">Kohút</string>
|
||||||
|
<string name="verification_emoji_penguin">Tučniak</string>
|
||||||
|
<string name="verification_emoji_turtle">Korytnačka</string>
|
||||||
|
<string name="verification_emoji_fish">Ryba</string>
|
||||||
|
<string name="verification_emoji_octopus">Chobotnica</string>
|
||||||
|
<string name="verification_emoji_butterfly">Motýľ</string>
|
||||||
|
<string name="verification_emoji_flower">Kvetina</string>
|
||||||
|
<string name="verification_emoji_tree">Strom</string>
|
||||||
|
<string name="verification_emoji_cactus">Kaktus</string>
|
||||||
|
<string name="verification_emoji_mushroom">Hríb</string>
|
||||||
|
<string name="verification_emoji_globe">Zemeguľa</string>
|
||||||
|
<string name="verification_emoji_moon">Mesiac</string>
|
||||||
|
<string name="verification_emoji_cloud">Oblak</string>
|
||||||
|
<string name="verification_emoji_fire">Oheň</string>
|
||||||
|
<string name="verification_emoji_banana">Banán</string>
|
||||||
|
<string name="verification_emoji_apple">Jablko</string>
|
||||||
|
<string name="verification_emoji_strawberry">Jahoda</string>
|
||||||
|
<string name="verification_emoji_corn">Kukurica</string>
|
||||||
|
<string name="verification_emoji_pizza">Pizza</string>
|
||||||
|
<string name="verification_emoji_cake">Koláč</string>
|
||||||
|
<string name="verification_emoji_heart">Srdce</string>
|
||||||
|
<string name="verification_emoji_smiley">Úsmev</string>
|
||||||
|
<string name="verification_emoji_robot">Robot</string>
|
||||||
|
<string name="verification_emoji_hat">Klobúk</string>
|
||||||
|
<string name="verification_emoji_glasses">Okuliare</string>
|
||||||
|
<string name="verification_emoji_wrench">Skrutkovač</string>
|
||||||
|
<string name="verification_emoji_santa">Mikuláš</string>
|
||||||
|
<string name="verification_emoji_thumbsup">Palec nahor</string>
|
||||||
|
<string name="verification_emoji_umbrella">Dáždnik</string>
|
||||||
|
<string name="verification_emoji_hourglass">Presýpacie hodiny</string>
|
||||||
|
<string name="verification_emoji_clock">Hodiny</string>
|
||||||
|
<string name="verification_emoji_gift">Darček</string>
|
||||||
|
<string name="verification_emoji_lightbulb">Žiarovka</string>
|
||||||
|
<string name="verification_emoji_book">Kniha</string>
|
||||||
|
<string name="verification_emoji_pencil">Ceruzka</string>
|
||||||
|
<string name="verification_emoji_paperclip">Kancelárska sponka</string>
|
||||||
|
<string name="verification_emoji_scissors">Nožnice</string>
|
||||||
|
<string name="verification_emoji_lock">Zámok</string>
|
||||||
|
<string name="verification_emoji_key">Kľúč</string>
|
||||||
|
<string name="verification_emoji_hammer">Kladivo</string>
|
||||||
|
<string name="verification_emoji_telephone">Telefón</string>
|
||||||
|
<string name="verification_emoji_flag">Vlajka</string>
|
||||||
|
<string name="verification_emoji_train">Vlak</string>
|
||||||
|
<string name="verification_emoji_bicycle">Bicykel</string>
|
||||||
|
<string name="verification_emoji_airplane">Lietadlo</string>
|
||||||
|
<string name="verification_emoji_rocket">Raketa</string>
|
||||||
|
<string name="verification_emoji_trophy">Trofej</string>
|
||||||
|
<string name="verification_emoji_ball">Lopta</string>
|
||||||
|
<string name="verification_emoji_guitar">Gitara</string>
|
||||||
|
<string name="verification_emoji_trumpet">Trúbka</string>
|
||||||
|
<string name="verification_emoji_bell">Zvonček</string>
|
||||||
|
<string name="verification_emoji_anchor">Kotva</string>
|
||||||
|
<string name="verification_emoji_headphone">Schlúchadlá</string>
|
||||||
|
<string name="verification_emoji_folder">Priečinok</string>
|
||||||
|
<string name="verification_emoji_pin">Pin</string>
|
||||||
|
|
||||||
|
<string name="initial_sync_start_importing_account">Úvodná synchronizácia:
|
||||||
|
\nPrebieha import účtu…</string>
|
||||||
|
<string name="initial_sync_start_importing_account_crypto">Úvodná synchronizácia:
|
||||||
|
\nPrebieha import šifrovacích kľúčov</string>
|
||||||
|
<string name="initial_sync_start_importing_account_rooms">Úvodná synchronizácia:
|
||||||
|
\nPrebieha import miestností</string>
|
||||||
|
<string name="initial_sync_start_importing_account_joined_rooms">Úvodná synchronizácia:
|
||||||
|
\nPrebieha import miestností, do ktorých ste vstúpili</string>
|
||||||
|
<string name="initial_sync_start_importing_account_invited_rooms">Úvodná synchronizácia:
|
||||||
|
\nPrebieha import pozvánok</string>
|
||||||
|
<string name="initial_sync_start_importing_account_left_rooms">Úvodná synchronizácia:
|
||||||
|
\nPrebieha import opustených miestností</string>
|
||||||
|
<string name="initial_sync_start_importing_account_groups">Úvodná synchronizácia:
|
||||||
|
\nPrebieha import komunít</string>
|
||||||
|
<string name="initial_sync_start_importing_account_data">Úvodná synchronizácia:
|
||||||
|
\nPrebieha import údajov účtu</string>
|
||||||
|
|
||||||
|
<string name="event_status_sending_message">Odosielanie správy…</string>
|
||||||
|
<string name="clear_timeline_send_queue">Vymazať správy na odoslanie</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -146,4 +146,26 @@
|
|||||||
<string name="verification_emoji_anchor">Spirancë</string>
|
<string name="verification_emoji_anchor">Spirancë</string>
|
||||||
<string name="verification_emoji_headphone">Kufje</string>
|
<string name="verification_emoji_headphone">Kufje</string>
|
||||||
<string name="verification_emoji_folder">Dosje</string>
|
<string name="verification_emoji_folder">Dosje</string>
|
||||||
|
<string name="notice_room_update">%s e përmirësoi këtë dhomë.</string>
|
||||||
|
|
||||||
|
<string name="initial_sync_start_importing_account">Njëkohësimi Fillestar:
|
||||||
|
\nPo importohet llogaria…</string>
|
||||||
|
<string name="initial_sync_start_importing_account_crypto">Njëkohësimi Fillestar:
|
||||||
|
\nPo importohet kriptografi</string>
|
||||||
|
<string name="initial_sync_start_importing_account_rooms">Njëkohësimi Fillestar:
|
||||||
|
\nPo importohen Dhoma</string>
|
||||||
|
<string name="initial_sync_start_importing_account_joined_rooms">Njëkohësimi Fillestar:
|
||||||
|
\nPo importohen Dhoma Ku Është Bërë Hyrje</string>
|
||||||
|
<string name="initial_sync_start_importing_account_invited_rooms">Njëkohësimi Fillestar:
|
||||||
|
\nPo importohen Dhoma Me Ftesë</string>
|
||||||
|
<string name="initial_sync_start_importing_account_left_rooms">Njëkohësimi Fillestar:
|
||||||
|
\nPo importohen Dhoma të Braktisura</string>
|
||||||
|
<string name="initial_sync_start_importing_account_groups">Njëkohësimi Fillestar:
|
||||||
|
\nPo importohen Bashkësi</string>
|
||||||
|
<string name="initial_sync_start_importing_account_data">Njëkohësimi Fillestar:
|
||||||
|
\nPo importohet të Dhëna Llogarie</string>
|
||||||
|
|
||||||
|
<string name="event_status_sending_message">Po dërgohet mesazh…</string>
|
||||||
|
<string name="clear_timeline_send_queue">Spastro radhë pritjeje</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
<string name="notice_room_third_party_registered_invite">%1$s èt d’uutnodigienge vo %2$s anveird</string>
|
<string name="notice_room_third_party_registered_invite">%1$s èt d’uutnodigienge vo %2$s anveird</string>
|
||||||
|
|
||||||
<string name="notice_crypto_unable_to_decrypt">** Kun nie ountsleuteln: %s **</string>
|
<string name="notice_crypto_unable_to_decrypt">** Kun nie ountsleuteln: %s **</string>
|
||||||
<string name="notice_crypto_error_unkwown_inbound_session_id">’t Toestel van den afzender èt geen sleutels vo dit bericht gesteurd.</string>
|
<string name="notice_crypto_error_unkwown_inbound_session_id">’t Toestel van den afzender èt geen sleutels vo da bericht hier gesteurd.</string>
|
||||||
|
|
||||||
<string name="message_reply_to_prefix">Als antwoord ip</string>
|
<string name="message_reply_to_prefix">Als antwoord ip</string>
|
||||||
|
|
||||||
@ -150,21 +150,26 @@
|
|||||||
<string name="verification_emoji_folder">Mappe</string>
|
<string name="verification_emoji_folder">Mappe</string>
|
||||||
<string name="verification_emoji_pin">Pinne</string>
|
<string name="verification_emoji_pin">Pinne</string>
|
||||||
|
|
||||||
<string name="initial_sync_start_importing_account">Initiële synchronisoatie:
|
<string name="initial_sync_start_importing_account">Initiële synchronisoasje:
|
||||||
\nAccount wor geïmporteerd…</string>
|
\nAccount wor geïmporteerd…</string>
|
||||||
<string name="initial_sync_start_importing_account_crypto">Initiële synchronisoatie:
|
<string name="initial_sync_start_importing_account_crypto">Initiële synchronisoasje:
|
||||||
\nCrypto wor geïmporteerd</string>
|
\nCrypto wor geïmporteerd</string>
|
||||||
<string name="initial_sync_start_importing_account_rooms">Initiële synchronisoatie:
|
<string name="initial_sync_start_importing_account_rooms">Initiële synchronisoasje:
|
||||||
\nGesprekkn wordn geïmporteerd</string>
|
\nGesprekkn wordn geïmporteerd</string>
|
||||||
<string name="initial_sync_start_importing_account_joined_rooms">Initiële synchronisoatie:
|
<string name="initial_sync_start_importing_account_joined_rooms">Initiële synchronisoasje:
|
||||||
\nDeelgenoomn gesprekken wordn geïmporteerd</string>
|
\nDeelgenoomn gesprekken wordn geïmporteerd</string>
|
||||||
<string name="initial_sync_start_importing_account_invited_rooms">Initiële synchronisoatie:
|
<string name="initial_sync_start_importing_account_invited_rooms">Initiële synchronisoasje:
|
||||||
\nUutgenodigde gesprekkn wordn geïmporteerd</string>
|
\nUutgenodigde gesprekkn wordn geïmporteerd</string>
|
||||||
<string name="initial_sync_start_importing_account_left_rooms">Initiële synchronisoatie:
|
<string name="initial_sync_start_importing_account_left_rooms">Initiële synchronisoasje:
|
||||||
\nVerloatn gesprekkn wordn geïmporteerd</string>
|
\nVerloatn gesprekkn wordn geïmporteerd</string>
|
||||||
<string name="initial_sync_start_importing_account_groups">Initiële synchronisoatie:
|
<string name="initial_sync_start_importing_account_groups">Initiële synchronisoasje:
|
||||||
\nGemeenschappn wordn geïmporteerd</string>
|
\nGemeenschappn wordn geïmporteerd</string>
|
||||||
<string name="initial_sync_start_importing_account_data">Initiële synchronisoatie:
|
<string name="initial_sync_start_importing_account_data">Initiële synchronisoasje:
|
||||||
\nAccountgegeevns wordn geïmporteerd</string>
|
\nAccountgegeevns wordn geïmporteerd</string>
|
||||||
|
|
||||||
|
<string name="notice_room_update">%s èt da gesprek hier ipgewoardeerd.</string>
|
||||||
|
|
||||||
|
<string name="event_status_sending_message">Bericht wor verstuurd…</string>
|
||||||
|
<string name="clear_timeline_send_queue">Uutgoande wachtreeke leegn</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -162,4 +162,9 @@
|
|||||||
<string name="initial_sync_start_importing_account_data">初始化同步:
|
<string name="initial_sync_start_importing_account_data">初始化同步:
|
||||||
\n正在导入账号数据</string>
|
\n正在导入账号数据</string>
|
||||||
|
|
||||||
|
<string name="notice_room_update">%s 升级了聊天室。</string>
|
||||||
|
|
||||||
|
<string name="event_status_sending_message">正在发送消息…</string>
|
||||||
|
<string name="clear_timeline_send_queue">清除正在发送队列</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -165,4 +165,9 @@
|
|||||||
<string name="initial_sync_start_importing_account_data">初始化同步:
|
<string name="initial_sync_start_importing_account_data">初始化同步:
|
||||||
\n正在匯入帳號資料</string>
|
\n正在匯入帳號資料</string>
|
||||||
|
|
||||||
|
<string name="notice_room_update">%s 已升級此聊天室。</string>
|
||||||
|
|
||||||
|
<string name="event_status_sending_message">正在傳送訊息……</string>
|
||||||
|
<string name="clear_timeline_send_queue">清除傳送佇列</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -15,7 +15,7 @@ androidExtensions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ext.versionMajor = 0
|
ext.versionMajor = 0
|
||||||
ext.versionMinor = 3
|
ext.versionMinor = 5
|
||||||
ext.versionPatch = 0
|
ext.versionPatch = 0
|
||||||
|
|
||||||
static def getGitTimestamp() {
|
static def getGitTimestamp() {
|
||||||
@ -51,7 +51,7 @@ static def gitRevisionDate() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static def gitBranchName() {
|
static def gitBranchName() {
|
||||||
def cmd = "git name-rev --name-only HEAD"
|
def cmd = "git rev-parse --abbrev-ref HEAD"
|
||||||
return cmd.execute().text.trim()
|
return cmd.execute().text.trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
67
vector/src/main/java/im/vector/riotx/EmojiCompatWrapper.kt
Normal file
67
vector/src/main/java/im/vector/riotx/EmojiCompatWrapper.kt
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package im.vector.riotx
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.provider.FontRequest
|
||||||
|
import androidx.emoji.text.EmojiCompat
|
||||||
|
import androidx.emoji.text.FontRequestEmojiCompatConfig
|
||||||
|
import timber.log.Timber
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class EmojiCompatWrapper @Inject constructor(private val context: Context) {
|
||||||
|
|
||||||
|
private var initialized = false
|
||||||
|
|
||||||
|
fun init(fontRequest: FontRequest) {
|
||||||
|
|
||||||
|
//Use emoji compat for the benefit of emoji spans
|
||||||
|
val config = FontRequestEmojiCompatConfig(context, fontRequest)
|
||||||
|
// we want to replace all emojis with selected font
|
||||||
|
.setReplaceAll(true)
|
||||||
|
//Debug options
|
||||||
|
// .setEmojiSpanIndicatorEnabled(true)
|
||||||
|
// .setEmojiSpanIndicatorColor(Color.GREEN)
|
||||||
|
EmojiCompat.init(config)
|
||||||
|
.registerInitCallback(object : EmojiCompat.InitCallback() {
|
||||||
|
override fun onInitialized() {
|
||||||
|
Timber.v("Emoji compat onInitialized success ")
|
||||||
|
initialized = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailed(throwable: Throwable?) {
|
||||||
|
Timber.e(throwable, "Failed to init EmojiCompat")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun safeEmojiSpanify(sequence: CharSequence): CharSequence {
|
||||||
|
if (initialized) {
|
||||||
|
try {
|
||||||
|
return EmojiCompat.get().process(sequence)
|
||||||
|
} catch (throwable: Throwable) {
|
||||||
|
//Defensive coding against error (should not happend as it is initialized)
|
||||||
|
Timber.e(throwable, "Failed to init EmojiCompat")
|
||||||
|
return sequence
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return sequence
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -19,13 +19,10 @@ package im.vector.riotx
|
|||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.graphics.Color
|
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.HandlerThread
|
import android.os.HandlerThread
|
||||||
import androidx.core.provider.FontRequest
|
import androidx.core.provider.FontRequest
|
||||||
import androidx.core.provider.FontsContractCompat
|
import androidx.core.provider.FontsContractCompat
|
||||||
import androidx.emoji.text.EmojiCompat
|
|
||||||
import androidx.emoji.text.FontRequestEmojiCompatConfig
|
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.LifecycleObserver
|
import androidx.lifecycle.LifecycleObserver
|
||||||
import androidx.lifecycle.OnLifecycleEvent
|
import androidx.lifecycle.OnLifecycleEvent
|
||||||
@ -69,6 +66,7 @@ class VectorApplication : Application(), HasVectorInjector, MatrixConfiguration.
|
|||||||
@Inject lateinit var authenticator: Authenticator
|
@Inject lateinit var authenticator: Authenticator
|
||||||
@Inject lateinit var vectorConfiguration: VectorConfiguration
|
@Inject lateinit var vectorConfiguration: VectorConfiguration
|
||||||
@Inject lateinit var emojiCompatFontProvider: EmojiCompatFontProvider
|
@Inject lateinit var emojiCompatFontProvider: EmojiCompatFontProvider
|
||||||
|
@Inject lateinit var emojiCompatWrapper: EmojiCompatWrapper
|
||||||
@Inject lateinit var vectorUncaughtExceptionHandler: VectorUncaughtExceptionHandler
|
@Inject lateinit var vectorUncaughtExceptionHandler: VectorUncaughtExceptionHandler
|
||||||
@Inject lateinit var activeSessionHolder: ActiveSessionHolder
|
@Inject lateinit var activeSessionHolder: ActiveSessionHolder
|
||||||
@Inject lateinit var notificationDrawerManager: NotificationDrawerManager
|
@Inject lateinit var notificationDrawerManager: NotificationDrawerManager
|
||||||
@ -88,9 +86,12 @@ class VectorApplication : Application(), HasVectorInjector, MatrixConfiguration.
|
|||||||
vectorComponent = DaggerVectorComponent.factory().create(this)
|
vectorComponent = DaggerVectorComponent.factory().create(this)
|
||||||
vectorComponent.inject(this)
|
vectorComponent.inject(this)
|
||||||
vectorUncaughtExceptionHandler.activate(this)
|
vectorUncaughtExceptionHandler.activate(this)
|
||||||
// Log
|
|
||||||
VectorFileLogger.init(this)
|
if (BuildConfig.DEBUG) {
|
||||||
Timber.plant(Timber.DebugTree(), VectorFileLogger)
|
Timber.plant(Timber.DebugTree())
|
||||||
|
}
|
||||||
|
Timber.plant(vectorComponent.vectorFileLogger())
|
||||||
|
|
||||||
if (BuildConfig.DEBUG) {
|
if (BuildConfig.DEBUG) {
|
||||||
Stetho.initializeWithDefaults(this)
|
Stetho.initializeWithDefaults(this)
|
||||||
}
|
}
|
||||||
@ -109,21 +110,7 @@ class VectorApplication : Application(), HasVectorInjector, MatrixConfiguration.
|
|||||||
FontsContractCompat.requestFont(this, fontRequest, emojiCompatFontProvider, getFontThreadHandler())
|
FontsContractCompat.requestFont(this, fontRequest, emojiCompatFontProvider, getFontThreadHandler())
|
||||||
vectorConfiguration.initConfiguration()
|
vectorConfiguration.initConfiguration()
|
||||||
|
|
||||||
//Use emoji compat for the benefit of emoji spans
|
emojiCompatWrapper.init(fontRequest)
|
||||||
val config = FontRequestEmojiCompatConfig(this, fontRequest)
|
|
||||||
.setReplaceAll(true) // we want to replace all emojis with selected font
|
|
||||||
// .setEmojiSpanIndicatorEnabled(true)
|
|
||||||
// .setEmojiSpanIndicatorColor(Color.GREEN)
|
|
||||||
EmojiCompat.init(config)
|
|
||||||
.registerInitCallback(object : EmojiCompat.InitCallback() {
|
|
||||||
override fun onInitialized() {
|
|
||||||
Timber.v("Emoji compat onInitialized success ")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailed(throwable: Throwable?) {
|
|
||||||
Timber.e(throwable,"Failed to init EmojiCompat")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
NotificationUtils.createNotificationChannels(applicationContext)
|
NotificationUtils.createNotificationChannels(applicationContext)
|
||||||
if (authenticator.hasAuthenticatedSessions() && !activeSessionHolder.hasActiveSession()) {
|
if (authenticator.hasAuthenticatedSessions() && !activeSessionHolder.hasActiveSession()) {
|
||||||
|
@ -58,6 +58,7 @@ import im.vector.riotx.features.rageshake.BugReportActivity
|
|||||||
import im.vector.riotx.features.rageshake.BugReporter
|
import im.vector.riotx.features.rageshake.BugReporter
|
||||||
import im.vector.riotx.features.rageshake.RageShake
|
import im.vector.riotx.features.rageshake.RageShake
|
||||||
import im.vector.riotx.features.reactions.EmojiReactionPickerActivity
|
import im.vector.riotx.features.reactions.EmojiReactionPickerActivity
|
||||||
|
import im.vector.riotx.features.reactions.widget.ReactionButton
|
||||||
import im.vector.riotx.features.roomdirectory.PublicRoomsFragment
|
import im.vector.riotx.features.roomdirectory.PublicRoomsFragment
|
||||||
import im.vector.riotx.features.roomdirectory.RoomDirectoryActivity
|
import im.vector.riotx.features.roomdirectory.RoomDirectoryActivity
|
||||||
import im.vector.riotx.features.roomdirectory.createroom.CreateRoomActivity
|
import im.vector.riotx.features.roomdirectory.createroom.CreateRoomActivity
|
||||||
@ -181,6 +182,8 @@ interface ScreenComponent {
|
|||||||
|
|
||||||
fun inject(displayReadReceiptsBottomSheet: DisplayReadReceiptsBottomSheet)
|
fun inject(displayReadReceiptsBottomSheet: DisplayReadReceiptsBottomSheet)
|
||||||
|
|
||||||
|
fun inject(reactionButton: ReactionButton)
|
||||||
|
|
||||||
@Component.Factory
|
@Component.Factory
|
||||||
interface Factory {
|
interface Factory {
|
||||||
fun create(vectorComponent: VectorComponent,
|
fun create(vectorComponent: VectorComponent,
|
||||||
|
@ -24,6 +24,7 @@ import im.vector.matrix.android.api.Matrix
|
|||||||
import im.vector.matrix.android.api.auth.Authenticator
|
import im.vector.matrix.android.api.auth.Authenticator
|
||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.matrix.android.api.session.Session
|
||||||
import im.vector.riotx.EmojiCompatFontProvider
|
import im.vector.riotx.EmojiCompatFontProvider
|
||||||
|
import im.vector.riotx.EmojiCompatWrapper
|
||||||
import im.vector.riotx.VectorApplication
|
import im.vector.riotx.VectorApplication
|
||||||
import im.vector.riotx.core.pushers.PushersManager
|
import im.vector.riotx.core.pushers.PushersManager
|
||||||
import im.vector.riotx.features.configuration.VectorConfiguration
|
import im.vector.riotx.features.configuration.VectorConfiguration
|
||||||
@ -40,6 +41,7 @@ import im.vector.riotx.features.notifications.NotificationBroadcastReceiver
|
|||||||
import im.vector.riotx.features.notifications.NotificationDrawerManager
|
import im.vector.riotx.features.notifications.NotificationDrawerManager
|
||||||
import im.vector.riotx.features.notifications.PushRuleTriggerListener
|
import im.vector.riotx.features.notifications.PushRuleTriggerListener
|
||||||
import im.vector.riotx.features.rageshake.BugReporter
|
import im.vector.riotx.features.rageshake.BugReporter
|
||||||
|
import im.vector.riotx.features.rageshake.VectorFileLogger
|
||||||
import im.vector.riotx.features.rageshake.VectorUncaughtExceptionHandler
|
import im.vector.riotx.features.rageshake.VectorUncaughtExceptionHandler
|
||||||
import im.vector.riotx.features.settings.VectorPreferences
|
import im.vector.riotx.features.settings.VectorPreferences
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
@ -70,6 +72,8 @@ interface VectorComponent {
|
|||||||
|
|
||||||
fun emojiCompatFontProvider(): EmojiCompatFontProvider
|
fun emojiCompatFontProvider(): EmojiCompatFontProvider
|
||||||
|
|
||||||
|
fun emojiCompatWrapper() : EmojiCompatWrapper
|
||||||
|
|
||||||
fun eventHtmlRenderer(): EventHtmlRenderer
|
fun eventHtmlRenderer(): EventHtmlRenderer
|
||||||
|
|
||||||
fun navigator(): Navigator
|
fun navigator(): Navigator
|
||||||
@ -98,6 +102,8 @@ interface VectorComponent {
|
|||||||
|
|
||||||
fun vectorPreferences(): VectorPreferences
|
fun vectorPreferences(): VectorPreferences
|
||||||
|
|
||||||
|
fun vectorFileLogger(): VectorFileLogger
|
||||||
|
|
||||||
@Component.Factory
|
@Component.Factory
|
||||||
interface Factory {
|
interface Factory {
|
||||||
fun create(@BindsInstance context: Context): VectorComponent
|
fun create(@BindsInstance context: Context): VectorComponent
|
||||||
|
@ -21,11 +21,8 @@ import android.util.AttributeSet
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import androidx.core.view.isInvisible
|
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import butterknife.ButterKnife
|
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.utils.DebouncedClickListener
|
|
||||||
import im.vector.riotx.features.home.AvatarRenderer
|
import im.vector.riotx.features.home.AvatarRenderer
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.ReadReceiptData
|
import im.vector.riotx.features.home.room.detail.timeline.item.ReadReceiptData
|
||||||
import kotlinx.android.synthetic.main.view_read_receipts.view.*
|
import kotlinx.android.synthetic.main.view_read_receipts.view.*
|
||||||
@ -48,7 +45,6 @@ class ReadReceiptsView @JvmOverloads constructor(
|
|||||||
|
|
||||||
private fun setupView() {
|
private fun setupView() {
|
||||||
inflate(context, R.layout.view_read_receipts, this)
|
inflate(context, R.layout.view_read_receipts, this)
|
||||||
ButterKnife.bind(this)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun render(readReceipts: List<ReadReceiptData>, avatarRenderer: AvatarRenderer, clickListener: OnClickListener) {
|
fun render(readReceipts: List<ReadReceiptData>, avatarRenderer: AvatarRenderer, clickListener: OnClickListener) {
|
||||||
|
@ -26,7 +26,6 @@ import androidx.appcompat.widget.Toolbar
|
|||||||
import androidx.core.view.GravityCompat
|
import androidx.core.view.GravityCompat
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.drawerlayout.widget.DrawerLayout
|
import androidx.drawerlayout.widget.DrawerLayout
|
||||||
import androidx.fragment.app.FragmentManager
|
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import androidx.lifecycle.ViewModelProviders
|
import androidx.lifecycle.ViewModelProviders
|
||||||
import com.airbnb.mvrx.viewModel
|
import com.airbnb.mvrx.viewModel
|
||||||
@ -36,12 +35,10 @@ import im.vector.riotx.core.di.ScreenComponent
|
|||||||
import im.vector.riotx.core.extensions.hideKeyboard
|
import im.vector.riotx.core.extensions.hideKeyboard
|
||||||
import im.vector.riotx.core.extensions.observeEvent
|
import im.vector.riotx.core.extensions.observeEvent
|
||||||
import im.vector.riotx.core.extensions.replaceFragment
|
import im.vector.riotx.core.extensions.replaceFragment
|
||||||
import im.vector.riotx.core.platform.OnBackPressed
|
|
||||||
import im.vector.riotx.core.platform.ToolbarConfigurable
|
import im.vector.riotx.core.platform.ToolbarConfigurable
|
||||||
import im.vector.riotx.core.platform.VectorBaseActivity
|
import im.vector.riotx.core.platform.VectorBaseActivity
|
||||||
import im.vector.riotx.core.pushers.PushersManager
|
import im.vector.riotx.core.pushers.PushersManager
|
||||||
import im.vector.riotx.features.disclaimer.showDisclaimerDialog
|
import im.vector.riotx.features.disclaimer.showDisclaimerDialog
|
||||||
import im.vector.riotx.features.navigation.Navigator
|
|
||||||
import im.vector.riotx.features.notifications.NotificationDrawerManager
|
import im.vector.riotx.features.notifications.NotificationDrawerManager
|
||||||
import im.vector.riotx.features.rageshake.VectorUncaughtExceptionHandler
|
import im.vector.riotx.features.rageshake.VectorUncaughtExceptionHandler
|
||||||
import im.vector.riotx.features.workers.signout.SignOutViewModel
|
import im.vector.riotx.features.workers.signout.SignOutViewModel
|
||||||
@ -119,22 +116,22 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable {
|
|||||||
intent.removeExtra(EXTRA_CLEAR_EXISTING_NOTIFICATION)
|
intent.removeExtra(EXTRA_CLEAR_EXISTING_NOTIFICATION)
|
||||||
}
|
}
|
||||||
|
|
||||||
activeSessionHolder.getSafeActiveSession()?.getLiveStatus()?.observe(this, Observer { sprogress ->
|
activeSessionHolder.getSafeActiveSession()?.getInitialSyncProgressStatus()?.observe(this, Observer { status ->
|
||||||
Timber.e("${sprogress?.statusText?.let { getString(it) }} ${sprogress?.percentProgress}")
|
if (status == null) {
|
||||||
if (sprogress == null) {
|
|
||||||
waiting_view.isVisible = false
|
waiting_view.isVisible = false
|
||||||
} else {
|
} else {
|
||||||
|
Timber.e("${getString(status.statusText)} ${status.percentProgress}")
|
||||||
waiting_view.setOnClickListener {
|
waiting_view.setOnClickListener {
|
||||||
//block interactions
|
//block interactions
|
||||||
}
|
}
|
||||||
waiting_view_status_horizontal_progress.apply {
|
waiting_view_status_horizontal_progress.apply {
|
||||||
isIndeterminate = false
|
isIndeterminate = false
|
||||||
max = 100
|
max = 100
|
||||||
progress = sprogress.percentProgress
|
progress = status.percentProgress
|
||||||
isVisible = true
|
isVisible = true
|
||||||
}
|
}
|
||||||
waiting_view_status_text.apply {
|
waiting_view_status_text.apply {
|
||||||
text = sprogress.statusText?.let { getString(it) }
|
text = getString(status.statusText)
|
||||||
isVisible = true
|
isVisible = true
|
||||||
}
|
}
|
||||||
waiting_view.isVisible = true
|
waiting_view.isVisible = true
|
||||||
@ -213,8 +210,6 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val EXTRA_CLEAR_EXISTING_NOTIFICATION = "EXTRA_CLEAR_EXISTING_NOTIFICATION"
|
private const val EXTRA_CLEAR_EXISTING_NOTIFICATION = "EXTRA_CLEAR_EXISTING_NOTIFICATION"
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ class DisplayReadReceiptsBottomSheet : VectorBaseBottomSheetDialogFragment() {
|
|||||||
val dividerItemDecoration = DividerItemDecoration(epoxyRecyclerView.context,
|
val dividerItemDecoration = DividerItemDecoration(epoxyRecyclerView.context,
|
||||||
LinearLayout.VERTICAL)
|
LinearLayout.VERTICAL)
|
||||||
epoxyRecyclerView.addItemDecoration(dividerItemDecoration)
|
epoxyRecyclerView.addItemDecoration(dividerItemDecoration)
|
||||||
bottomSheetTitle.text = getString(R.string.read_receipts_list)
|
bottomSheetTitle.text = getString(R.string.read_at)
|
||||||
epoxyController.setData(displayReadReceiptArgs.readReceipts)
|
epoxyController.setData(displayReadReceiptArgs.readReceipts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,9 +46,7 @@ class ViewReactionBottomSheet : VectorBaseBottomSheetDialogFragment() {
|
|||||||
@BindView(R.id.bottom_sheet_display_reactions_list)
|
@BindView(R.id.bottom_sheet_display_reactions_list)
|
||||||
lateinit var epoxyRecyclerView: EpoxyRecyclerView
|
lateinit var epoxyRecyclerView: EpoxyRecyclerView
|
||||||
|
|
||||||
private val epoxyController by lazy {
|
@Inject lateinit var epoxyController: ViewReactionsEpoxyController
|
||||||
ViewReactionsEpoxyController(requireContext())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun injectWith(screenComponent: ScreenComponent) {
|
override fun injectWith(screenComponent: ScreenComponent) {
|
||||||
screenComponent.inject(this)
|
screenComponent.inject(this)
|
||||||
|
@ -17,21 +17,23 @@
|
|||||||
package im.vector.riotx.features.home.room.detail.timeline.action
|
package im.vector.riotx.features.home.room.detail.timeline.action
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Typeface
|
|
||||||
import android.text.format.DateUtils
|
|
||||||
import androidx.emoji.text.EmojiCompat
|
|
||||||
import com.airbnb.epoxy.TypedEpoxyController
|
import com.airbnb.epoxy.TypedEpoxyController
|
||||||
import com.airbnb.mvrx.Fail
|
import com.airbnb.mvrx.Fail
|
||||||
import com.airbnb.mvrx.Incomplete
|
import com.airbnb.mvrx.Incomplete
|
||||||
import com.airbnb.mvrx.Success
|
import com.airbnb.mvrx.Success
|
||||||
|
import im.vector.riotx.EmojiCompatWrapper
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
|
import im.vector.riotx.core.resources.StringProvider
|
||||||
import im.vector.riotx.core.ui.list.genericFooterItem
|
import im.vector.riotx.core.ui.list.genericFooterItem
|
||||||
import im.vector.riotx.core.ui.list.genericLoaderItem
|
import im.vector.riotx.core.ui.list.genericLoaderItem
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Epoxy controller for reaction event list
|
* Epoxy controller for reaction event list
|
||||||
*/
|
*/
|
||||||
class ViewReactionsEpoxyController(private val context: Context)
|
class ViewReactionsEpoxyController @Inject constructor(
|
||||||
|
private val stringProvider: StringProvider,
|
||||||
|
private val emojiCompatWrapper: EmojiCompatWrapper )
|
||||||
: TypedEpoxyController<DisplayReactionsViewState>() {
|
: TypedEpoxyController<DisplayReactionsViewState>() {
|
||||||
|
|
||||||
override fun buildModels(state: DisplayReactionsViewState) {
|
override fun buildModels(state: DisplayReactionsViewState) {
|
||||||
@ -44,7 +46,7 @@ class ViewReactionsEpoxyController(private val context: Context)
|
|||||||
is Fail -> {
|
is Fail -> {
|
||||||
genericFooterItem {
|
genericFooterItem {
|
||||||
id("failure")
|
id("failure")
|
||||||
text(context.getString(R.string.unknown_error))
|
text(stringProvider.getString(R.string.unknown_error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is Success -> {
|
is Success -> {
|
||||||
@ -52,7 +54,7 @@ class ViewReactionsEpoxyController(private val context: Context)
|
|||||||
reactionInfoSimpleItem {
|
reactionInfoSimpleItem {
|
||||||
id(it.eventId)
|
id(it.eventId)
|
||||||
timeStamp(it.timestamp)
|
timeStamp(it.timestamp)
|
||||||
reactionKey(EmojiCompat.get().process(it.reactionKey))
|
reactionKey(emojiCompatWrapper.safeEmojiSpanify(it.reactionKey))
|
||||||
authorDisplayName(it.authorName ?: it.authorId)
|
authorDisplayName(it.authorName ?: it.authorId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,21 +17,35 @@
|
|||||||
package im.vector.riotx.features.home.room.detail.timeline.factory
|
package im.vector.riotx.features.home.room.detail.timeline.factory
|
||||||
|
|
||||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||||
|
import im.vector.riotx.features.home.AvatarRenderer
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.DefaultItem
|
import im.vector.riotx.features.home.room.detail.timeline.item.DefaultItem
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.DefaultItem_
|
import im.vector.riotx.features.home.room.detail.timeline.item.DefaultItem_
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.util.MessageInformationDataFactory
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class DefaultItemFactory @Inject constructor(){
|
class DefaultItemFactory @Inject constructor(private val avatarRenderer: AvatarRenderer,
|
||||||
|
private val informationDataFactory: MessageInformationDataFactory) {
|
||||||
|
|
||||||
fun create(event: TimelineEvent, highlight: Boolean, exception: Exception? = null): DefaultItem? {
|
fun create(event: TimelineEvent,
|
||||||
|
highlight: Boolean,
|
||||||
|
callback: TimelineEventController.Callback?,
|
||||||
|
exception: Exception? = null): DefaultItem? {
|
||||||
val text = if (exception == null) {
|
val text = if (exception == null) {
|
||||||
"${event.root.getClearType()} events are not yet handled"
|
"${event.root.getClearType()} events are not yet handled"
|
||||||
} else {
|
} else {
|
||||||
"an exception occurred when rendering the event ${event.root.eventId}"
|
"an exception occurred when rendering the event ${event.root.eventId}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val informationData = informationDataFactory.create(event, null)
|
||||||
|
|
||||||
return DefaultItem_()
|
return DefaultItem_()
|
||||||
.text(text)
|
.text(text)
|
||||||
|
.avatarRenderer(avatarRenderer)
|
||||||
.highlighted(highlight)
|
.highlighted(highlight)
|
||||||
|
.informationData(informationData)
|
||||||
|
.baseCallback(callback)
|
||||||
|
.readReceiptsCallback(callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -28,15 +28,7 @@ import im.vector.matrix.android.api.permalinks.MatrixLinkify
|
|||||||
import im.vector.matrix.android.api.permalinks.MatrixPermalinkSpan
|
import im.vector.matrix.android.api.permalinks.MatrixPermalinkSpan
|
||||||
import im.vector.matrix.android.api.session.events.model.RelationType
|
import im.vector.matrix.android.api.session.events.model.RelationType
|
||||||
import im.vector.matrix.android.api.session.events.model.toModel
|
import im.vector.matrix.android.api.session.events.model.toModel
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageAudioContent
|
import im.vector.matrix.android.api.session.room.model.message.*
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageEmoteContent
|
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageFileContent
|
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageImageContent
|
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageNoticeContent
|
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageTextContent
|
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageVideoContent
|
|
||||||
import im.vector.matrix.android.api.session.room.model.message.getFileUrl
|
|
||||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||||
import im.vector.matrix.android.api.session.room.timeline.getLastMessageContent
|
import im.vector.matrix.android.api.session.room.timeline.getLastMessageContent
|
||||||
import im.vector.matrix.android.internal.crypto.attachments.toElementToDecrypt
|
import im.vector.matrix.android.internal.crypto.attachments.toElementToDecrypt
|
||||||
@ -47,26 +39,12 @@ import im.vector.riotx.core.epoxy.VectorEpoxyModel
|
|||||||
import im.vector.riotx.core.linkify.VectorLinkify
|
import im.vector.riotx.core.linkify.VectorLinkify
|
||||||
import im.vector.riotx.core.resources.ColorProvider
|
import im.vector.riotx.core.resources.ColorProvider
|
||||||
import im.vector.riotx.core.resources.StringProvider
|
import im.vector.riotx.core.resources.StringProvider
|
||||||
import im.vector.riotx.core.resources.UserPreferencesProvider
|
|
||||||
import im.vector.riotx.core.utils.DebouncedClickListener
|
import im.vector.riotx.core.utils.DebouncedClickListener
|
||||||
import im.vector.riotx.features.home.AvatarRenderer
|
import im.vector.riotx.features.home.AvatarRenderer
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController
|
import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.helper.ContentUploadStateTrackerBinder
|
import im.vector.riotx.features.home.room.detail.timeline.helper.ContentUploadStateTrackerBinder
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider
|
import im.vector.riotx.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.helper.senderAvatar
|
import im.vector.riotx.features.home.room.detail.timeline.item.*
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.BlankItem_
|
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.DefaultItem
|
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.DefaultItem_
|
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.MessageFileItem
|
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.MessageFileItem_
|
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.MessageImageVideoItem
|
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.MessageImageVideoItem_
|
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.MessageInformationData
|
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.MessageTextItem
|
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.MessageTextItem_
|
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.NoticeItem_
|
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.RedactedMessageItem
|
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.RedactedMessageItem_
|
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.util.MessageInformationDataFactory
|
import im.vector.riotx.features.home.room.detail.timeline.util.MessageInformationDataFactory
|
||||||
import im.vector.riotx.features.html.EventHtmlRenderer
|
import im.vector.riotx.features.html.EventHtmlRenderer
|
||||||
import im.vector.riotx.features.media.ImageContentRenderer
|
import im.vector.riotx.features.media.ImageContentRenderer
|
||||||
@ -103,32 +81,28 @@ class MessageItemFactory @Inject constructor(
|
|||||||
|
|
||||||
val messageContent: MessageContent =
|
val messageContent: MessageContent =
|
||||||
event.getLastMessageContent()
|
event.getLastMessageContent()
|
||||||
?: //Malformed content, we should echo something on screen
|
?: //Malformed content, we should echo something on screen
|
||||||
return DefaultItem_().text(stringProvider.getString(R.string.malformed_message))
|
return buildNotHandledMessageItem(stringProvider.getString(R.string.malformed_message),
|
||||||
|
informationData, highlight, callback)
|
||||||
|
|
||||||
if (messageContent.relatesTo?.type == RelationType.REPLACE
|
if (messageContent.relatesTo?.type == RelationType.REPLACE
|
||||||
|| event.isEncrypted() && event.root.content.toModel<EncryptedEventContent>()?.relatesTo?.type == RelationType.REPLACE
|
|| event.isEncrypted() && event.root.content.toModel<EncryptedEventContent>()?.relatesTo?.type == RelationType.REPLACE
|
||||||
) {
|
) {
|
||||||
// This is an edit event, we should it when debugging as a notice event
|
// This is an edit event, we should display it when debugging as a notice event
|
||||||
return noticeItemFactory.create(event, highlight, callback)
|
return noticeItemFactory.create(event, highlight, callback)
|
||||||
}
|
}
|
||||||
// val all = event.root.toContent()
|
// val all = event.root.toContent()
|
||||||
// val ev = all.toModel<Event>()
|
// val ev = all.toModel<Event>()
|
||||||
return when (messageContent) {
|
return when (messageContent) {
|
||||||
is MessageEmoteContent -> buildEmoteMessageItem(messageContent,
|
is MessageEmoteContent -> buildEmoteMessageItem(messageContent, informationData, highlight, callback)
|
||||||
informationData,
|
is MessageTextContent -> buildTextMessageItem(messageContent, informationData, highlight, callback)
|
||||||
highlight,
|
|
||||||
callback)
|
|
||||||
is MessageTextContent -> buildTextMessageItem(messageContent,
|
|
||||||
informationData,
|
|
||||||
highlight,
|
|
||||||
callback)
|
|
||||||
is MessageImageContent -> buildImageMessageItem(messageContent, informationData, highlight, callback)
|
is MessageImageContent -> buildImageMessageItem(messageContent, informationData, highlight, callback)
|
||||||
is MessageNoticeContent -> buildNoticeMessageItem(messageContent, informationData, highlight, callback)
|
is MessageNoticeContent -> buildNoticeMessageItem(messageContent, informationData, highlight, callback)
|
||||||
is MessageVideoContent -> buildVideoMessageItem(messageContent, informationData, highlight, callback)
|
is MessageVideoContent -> buildVideoMessageItem(messageContent, informationData, highlight, callback)
|
||||||
is MessageFileContent -> buildFileMessageItem(messageContent, informationData, highlight, callback)
|
is MessageFileContent -> buildFileMessageItem(messageContent, informationData, highlight, callback)
|
||||||
is MessageAudioContent -> buildAudioMessageItem(messageContent, informationData, highlight, callback)
|
is MessageAudioContent -> buildAudioMessageItem(messageContent, informationData, highlight, callback)
|
||||||
else -> buildNotHandledMessageItem(messageContent, highlight)
|
else -> buildNotHandledMessageItem("${messageContent.type} message events are not yet handled",
|
||||||
|
informationData, highlight, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +131,7 @@ class MessageItemFactory @Inject constructor(
|
|||||||
}))
|
}))
|
||||||
.longClickListener { view ->
|
.longClickListener { view ->
|
||||||
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
|
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
|
||||||
?: false
|
?: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,7 +156,7 @@ class MessageItemFactory @Inject constructor(
|
|||||||
}))
|
}))
|
||||||
.longClickListener { view ->
|
.longClickListener { view ->
|
||||||
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
|
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
|
||||||
?: false
|
?: false
|
||||||
}
|
}
|
||||||
.clickListener(
|
.clickListener(
|
||||||
DebouncedClickListener(View.OnClickListener { _ ->
|
DebouncedClickListener(View.OnClickListener { _ ->
|
||||||
@ -190,11 +164,17 @@ class MessageItemFactory @Inject constructor(
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildNotHandledMessageItem(messageContent: MessageContent, highlight: Boolean): DefaultItem? {
|
private fun buildNotHandledMessageItem(text: String,
|
||||||
val text = "${messageContent.type} message events are not yet handled"
|
informationData: MessageInformationData,
|
||||||
|
highlight: Boolean,
|
||||||
|
callback: TimelineEventController.Callback?): DefaultItem? {
|
||||||
return DefaultItem_()
|
return DefaultItem_()
|
||||||
.text(text)
|
.text(text)
|
||||||
|
.avatarRenderer(avatarRenderer)
|
||||||
.highlighted(highlight)
|
.highlighted(highlight)
|
||||||
|
.informationData(informationData)
|
||||||
|
.baseCallback(callback)
|
||||||
|
.readReceiptsCallback(callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildImageMessageItem(messageContent: MessageImageContent,
|
private fun buildImageMessageItem(messageContent: MessageImageContent,
|
||||||
@ -237,7 +217,7 @@ class MessageItemFactory @Inject constructor(
|
|||||||
}))
|
}))
|
||||||
.longClickListener { view ->
|
.longClickListener { view ->
|
||||||
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
|
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
|
||||||
?: false
|
?: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,7 +230,7 @@ class MessageItemFactory @Inject constructor(
|
|||||||
val thumbnailData = ImageContentRenderer.Data(
|
val thumbnailData = ImageContentRenderer.Data(
|
||||||
filename = messageContent.body,
|
filename = messageContent.body,
|
||||||
url = messageContent.videoInfo?.thumbnailFile?.url
|
url = messageContent.videoInfo?.thumbnailFile?.url
|
||||||
?: messageContent.videoInfo?.thumbnailUrl,
|
?: messageContent.videoInfo?.thumbnailUrl,
|
||||||
elementToDecrypt = messageContent.videoInfo?.thumbnailFile?.toElementToDecrypt(),
|
elementToDecrypt = messageContent.videoInfo?.thumbnailFile?.toElementToDecrypt(),
|
||||||
height = messageContent.videoInfo?.height,
|
height = messageContent.videoInfo?.height,
|
||||||
maxHeight = maxHeight,
|
maxHeight = maxHeight,
|
||||||
@ -286,7 +266,7 @@ class MessageItemFactory @Inject constructor(
|
|||||||
.clickListener { view -> callback?.onVideoMessageClicked(messageContent, videoData, view) }
|
.clickListener { view -> callback?.onVideoMessageClicked(messageContent, videoData, view) }
|
||||||
.longClickListener { view ->
|
.longClickListener { view ->
|
||||||
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
|
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
|
||||||
?: false
|
?: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,7 +306,7 @@ class MessageItemFactory @Inject constructor(
|
|||||||
}))
|
}))
|
||||||
.longClickListener { view ->
|
.longClickListener { view ->
|
||||||
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
|
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
|
||||||
?: false
|
?: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,9 +336,9 @@ class MessageItemFactory @Inject constructor(
|
|||||||
//nop
|
//nop
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
editStart,
|
editStart,
|
||||||
editEnd,
|
editEnd,
|
||||||
Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
|
Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
|
||||||
return spannable
|
return spannable
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -396,7 +376,7 @@ class MessageItemFactory @Inject constructor(
|
|||||||
}))
|
}))
|
||||||
.longClickListener { view ->
|
.longClickListener { view ->
|
||||||
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
|
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
|
||||||
?: false
|
?: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -433,7 +413,7 @@ class MessageItemFactory @Inject constructor(
|
|||||||
}))
|
}))
|
||||||
.longClickListener { view ->
|
.longClickListener { view ->
|
||||||
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
|
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
|
||||||
?: false
|
?: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -453,7 +433,7 @@ class MessageItemFactory @Inject constructor(
|
|||||||
}))
|
}))
|
||||||
.longClickListener { view ->
|
.longClickListener { view ->
|
||||||
return@longClickListener callback?.onEventLongClicked(informationData, null, view)
|
return@longClickListener callback?.onEventLongClicked(informationData, null, view)
|
||||||
?: false
|
?: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,12 +20,7 @@ import im.vector.matrix.android.api.session.events.model.EventType
|
|||||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||||
import im.vector.riotx.core.epoxy.EmptyItem_
|
import im.vector.riotx.core.epoxy.EmptyItem_
|
||||||
import im.vector.riotx.core.epoxy.VectorEpoxyModel
|
import im.vector.riotx.core.epoxy.VectorEpoxyModel
|
||||||
import im.vector.riotx.features.home.AvatarRenderer
|
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController
|
import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.helper.senderAvatar
|
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.MessageInformationData
|
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.NoticeItem_
|
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.util.MessageInformationDataFactory
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -71,7 +66,7 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me
|
|||||||
|
|
||||||
// Unhandled event types (yet)
|
// Unhandled event types (yet)
|
||||||
EventType.STATE_ROOM_THIRD_PARTY_INVITE,
|
EventType.STATE_ROOM_THIRD_PARTY_INVITE,
|
||||||
EventType.STICKER -> defaultItemFactory.create(event, highlight)
|
EventType.STICKER -> defaultItemFactory.create(event, highlight, callback)
|
||||||
else -> {
|
else -> {
|
||||||
Timber.v("Type ${event.root.getClearType()} not handled")
|
Timber.v("Type ${event.root.getClearType()} not handled")
|
||||||
null
|
null
|
||||||
@ -79,7 +74,7 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me
|
|||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Timber.e(e, "failed to create message item")
|
Timber.e(e, "failed to create message item")
|
||||||
defaultItemFactory.create(event, highlight, e)
|
defaultItemFactory.create(event, highlight, callback, e)
|
||||||
}
|
}
|
||||||
return (computedModel ?: EmptyItem_())
|
return (computedModel ?: EmptyItem_())
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package im.vector.riotx.features.home.room.detail.timeline.format
|
package im.vector.riotx.features.home.room.detail.timeline.format
|
||||||
|
|
||||||
import android.text.TextUtils
|
|
||||||
import im.vector.matrix.android.api.session.events.model.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.api.session.events.model.EventType
|
import im.vector.matrix.android.api.session.events.model.EventType
|
||||||
import im.vector.matrix.android.api.session.events.model.toModel
|
import im.vector.matrix.android.api.session.events.model.toModel
|
||||||
@ -24,12 +23,14 @@ import im.vector.matrix.android.api.session.room.model.*
|
|||||||
import im.vector.matrix.android.api.session.room.model.call.CallInviteContent
|
import im.vector.matrix.android.api.session.room.model.call.CallInviteContent
|
||||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
|
import im.vector.riotx.core.di.ActiveSessionHolder
|
||||||
import im.vector.riotx.core.resources.StringProvider
|
import im.vector.riotx.core.resources.StringProvider
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.helper.senderName
|
import im.vector.riotx.features.home.room.detail.timeline.helper.senderName
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class NoticeEventFormatter @Inject constructor(private val stringProvider: StringProvider) {
|
class NoticeEventFormatter @Inject constructor(private val sessionHolder: ActiveSessionHolder,
|
||||||
|
private val stringProvider: StringProvider) {
|
||||||
|
|
||||||
fun format(timelineEvent: TimelineEvent): CharSequence? {
|
fun format(timelineEvent: TimelineEvent): CharSequence? {
|
||||||
return when (val type = timelineEvent.root.getClearType()) {
|
return when (val type = timelineEvent.root.getClearType()) {
|
||||||
@ -74,10 +75,10 @@ class NoticeEventFormatter @Inject constructor(private val stringProvider: Strin
|
|||||||
|
|
||||||
private fun formatRoomNameEvent(event: Event, senderName: String?): CharSequence? {
|
private fun formatRoomNameEvent(event: Event, senderName: String?): CharSequence? {
|
||||||
val content = event.getClearContent().toModel<RoomNameContent>() ?: return null
|
val content = event.getClearContent().toModel<RoomNameContent>() ?: return null
|
||||||
return if (!TextUtils.isEmpty(content.name)) {
|
return if (content.name.isNullOrBlank()) {
|
||||||
stringProvider.getString(R.string.notice_room_name_changed, senderName, content.name)
|
|
||||||
} else {
|
|
||||||
stringProvider.getString(R.string.notice_room_name_removed, senderName)
|
stringProvider.getString(R.string.notice_room_name_removed, senderName)
|
||||||
|
} else {
|
||||||
|
stringProvider.getString(R.string.notice_room_name_changed, senderName, content.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,8 +96,7 @@ class NoticeEventFormatter @Inject constructor(private val stringProvider: Strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun formatRoomHistoryVisibilityEvent(event: Event, senderName: String?): CharSequence? {
|
private fun formatRoomHistoryVisibilityEvent(event: Event, senderName: String?): CharSequence? {
|
||||||
val historyVisibility = event.getClearContent().toModel<RoomHistoryVisibilityContent>()?.historyVisibility
|
val historyVisibility = event.getClearContent().toModel<RoomHistoryVisibilityContent>()?.historyVisibility ?: return null
|
||||||
?: return null
|
|
||||||
|
|
||||||
val formattedVisibility = when (historyVisibility) {
|
val formattedVisibility = when (historyVisibility) {
|
||||||
RoomHistoryVisibility.SHARED -> stringProvider.getString(R.string.notice_room_visibility_shared)
|
RoomHistoryVisibility.SHARED -> stringProvider.getString(R.string.notice_room_visibility_shared)
|
||||||
@ -138,7 +138,7 @@ class NoticeEventFormatter @Inject constructor(private val stringProvider: Strin
|
|||||||
private fun buildProfileNotice(event: Event, senderName: String?, eventContent: RoomMember?, prevEventContent: RoomMember?): String? {
|
private fun buildProfileNotice(event: Event, senderName: String?, eventContent: RoomMember?, prevEventContent: RoomMember?): String? {
|
||||||
val displayText = StringBuilder()
|
val displayText = StringBuilder()
|
||||||
// Check display name has been changed
|
// Check display name has been changed
|
||||||
if (!TextUtils.equals(eventContent?.displayName, prevEventContent?.displayName)) {
|
if (eventContent?.displayName != prevEventContent?.displayName) {
|
||||||
val displayNameText = when {
|
val displayNameText = when {
|
||||||
prevEventContent?.displayName.isNullOrEmpty() ->
|
prevEventContent?.displayName.isNullOrEmpty() ->
|
||||||
stringProvider.getString(R.string.notice_display_name_set, event.senderId, eventContent?.displayName)
|
stringProvider.getString(R.string.notice_display_name_set, event.senderId, eventContent?.displayName)
|
||||||
@ -146,12 +146,12 @@ class NoticeEventFormatter @Inject constructor(private val stringProvider: Strin
|
|||||||
stringProvider.getString(R.string.notice_display_name_removed, event.senderId, prevEventContent?.displayName)
|
stringProvider.getString(R.string.notice_display_name_removed, event.senderId, prevEventContent?.displayName)
|
||||||
else ->
|
else ->
|
||||||
stringProvider.getString(R.string.notice_display_name_changed_from,
|
stringProvider.getString(R.string.notice_display_name_changed_from,
|
||||||
event.senderId, prevEventContent?.displayName, eventContent?.displayName)
|
event.senderId, prevEventContent?.displayName, eventContent?.displayName)
|
||||||
}
|
}
|
||||||
displayText.append(displayNameText)
|
displayText.append(displayNameText)
|
||||||
}
|
}
|
||||||
// Check whether the avatar has been changed
|
// Check whether the avatar has been changed
|
||||||
if (!TextUtils.equals(eventContent?.avatarUrl, prevEventContent?.avatarUrl)) {
|
if (eventContent?.avatarUrl != prevEventContent?.avatarUrl) {
|
||||||
val displayAvatarText = if (displayText.isNotEmpty()) {
|
val displayAvatarText = if (displayText.isNotEmpty()) {
|
||||||
displayText.append(" ")
|
displayText.append(" ")
|
||||||
stringProvider.getString(R.string.notice_avatar_changed_too)
|
stringProvider.getString(R.string.notice_avatar_changed_too)
|
||||||
@ -168,17 +168,18 @@ class NoticeEventFormatter @Inject constructor(private val stringProvider: Strin
|
|||||||
val targetDisplayName = eventContent?.displayName ?: prevEventContent?.displayName ?: ""
|
val targetDisplayName = eventContent?.displayName ?: prevEventContent?.displayName ?: ""
|
||||||
return when {
|
return when {
|
||||||
Membership.INVITE == eventContent?.membership -> {
|
Membership.INVITE == eventContent?.membership -> {
|
||||||
// TODO get userId
|
val selfUserId = sessionHolder.getSafeActiveSession()?.myUserId
|
||||||
val selfUserId = ""
|
|
||||||
when {
|
when {
|
||||||
eventContent.thirdPartyInvite != null ->
|
eventContent.thirdPartyInvite != null -> {
|
||||||
|
val userWhoHasAccepted = eventContent.thirdPartyInvite?.signed?.mxid ?: event.stateKey
|
||||||
stringProvider.getString(R.string.notice_room_third_party_registered_invite,
|
stringProvider.getString(R.string.notice_room_third_party_registered_invite,
|
||||||
targetDisplayName, eventContent.thirdPartyInvite?.displayName)
|
userWhoHasAccepted, eventContent.thirdPartyInvite?.displayName)
|
||||||
TextUtils.equals(event.stateKey, selfUserId) ->
|
}
|
||||||
|
event.stateKey == selfUserId ->
|
||||||
stringProvider.getString(R.string.notice_room_invite_you, senderDisplayName)
|
stringProvider.getString(R.string.notice_room_invite_you, senderDisplayName)
|
||||||
event.stateKey.isNullOrEmpty() ->
|
event.stateKey.isNullOrEmpty() ->
|
||||||
stringProvider.getString(R.string.notice_room_invite_no_invitee, senderDisplayName)
|
stringProvider.getString(R.string.notice_room_invite_no_invitee, senderDisplayName)
|
||||||
else ->
|
else ->
|
||||||
stringProvider.getString(R.string.notice_room_invite, senderDisplayName, targetDisplayName)
|
stringProvider.getString(R.string.notice_room_invite, senderDisplayName, targetDisplayName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -186,7 +187,7 @@ class NoticeEventFormatter @Inject constructor(private val stringProvider: Strin
|
|||||||
stringProvider.getString(R.string.notice_room_join, senderDisplayName)
|
stringProvider.getString(R.string.notice_room_join, senderDisplayName)
|
||||||
Membership.LEAVE == eventContent?.membership ->
|
Membership.LEAVE == eventContent?.membership ->
|
||||||
// 2 cases here: this member may have left voluntarily or they may have been "left" by someone else ie. kicked
|
// 2 cases here: this member may have left voluntarily or they may have been "left" by someone else ie. kicked
|
||||||
return if (TextUtils.equals(event.senderId, event.stateKey)) {
|
return if (event.senderId == event.stateKey) {
|
||||||
if (prevEventContent?.membership == Membership.INVITE) {
|
if (prevEventContent?.membership == Membership.INVITE) {
|
||||||
stringProvider.getString(R.string.notice_room_reject, senderDisplayName)
|
stringProvider.getString(R.string.notice_room_reject, senderDisplayName)
|
||||||
} else {
|
} else {
|
||||||
|
@ -32,7 +32,6 @@ import com.airbnb.epoxy.EpoxyAttribute
|
|||||||
import im.vector.matrix.android.api.session.room.send.SendState
|
import im.vector.matrix.android.api.session.room.send.SendState
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.resources.ColorProvider
|
import im.vector.riotx.core.resources.ColorProvider
|
||||||
import im.vector.riotx.core.ui.views.ReadReceiptsView
|
|
||||||
import im.vector.riotx.core.utils.DebouncedClickListener
|
import im.vector.riotx.core.utils.DebouncedClickListener
|
||||||
import im.vector.riotx.core.utils.DimensionUtils.dpToPx
|
import im.vector.riotx.core.utils.DimensionUtils.dpToPx
|
||||||
import im.vector.riotx.features.home.AvatarRenderer
|
import im.vector.riotx.features.home.AvatarRenderer
|
||||||
@ -181,7 +180,6 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder> : BaseEventItem<H>() {
|
|||||||
val avatarImageView by bind<ImageView>(R.id.messageAvatarImageView)
|
val avatarImageView by bind<ImageView>(R.id.messageAvatarImageView)
|
||||||
val memberNameView by bind<TextView>(R.id.messageMemberNameView)
|
val memberNameView by bind<TextView>(R.id.messageMemberNameView)
|
||||||
val timeView by bind<TextView>(R.id.messageTimeView)
|
val timeView by bind<TextView>(R.id.messageTimeView)
|
||||||
val readReceiptsView by bind<ReadReceiptsView>(R.id.readReceiptsView)
|
|
||||||
var reactionWrapper: ViewGroup? = null
|
var reactionWrapper: ViewGroup? = null
|
||||||
var reactionFlowHelper: Flow? = null
|
var reactionFlowHelper: Flow? = null
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import im.vector.riotx.R
|
|||||||
import im.vector.riotx.core.epoxy.VectorEpoxyHolder
|
import im.vector.riotx.core.epoxy.VectorEpoxyHolder
|
||||||
import im.vector.riotx.core.epoxy.VectorEpoxyModel
|
import im.vector.riotx.core.epoxy.VectorEpoxyModel
|
||||||
import im.vector.riotx.core.platform.CheckableView
|
import im.vector.riotx.core.platform.CheckableView
|
||||||
|
import im.vector.riotx.core.ui.views.ReadReceiptsView
|
||||||
import im.vector.riotx.core.utils.DimensionUtils.dpToPx
|
import im.vector.riotx.core.utils.DimensionUtils.dpToPx
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,6 +50,7 @@ abstract class BaseEventItem<H : BaseEventItem.BaseHolder> : VectorEpoxyModel<H>
|
|||||||
abstract class BaseHolder(@IdRes val stubId: Int) : VectorEpoxyHolder() {
|
abstract class BaseHolder(@IdRes val stubId: Int) : VectorEpoxyHolder() {
|
||||||
val leftGuideline by bind<Guideline>(R.id.messageStartGuideline)
|
val leftGuideline by bind<Guideline>(R.id.messageStartGuideline)
|
||||||
val checkableBackground by bind<CheckableView>(R.id.messageSelectedBackground)
|
val checkableBackground by bind<CheckableView>(R.id.messageSelectedBackground)
|
||||||
|
val readReceiptsView by bind<ReadReceiptsView>(R.id.readReceiptsView)
|
||||||
|
|
||||||
override fun bindView(itemView: View) {
|
override fun bindView(itemView: View) {
|
||||||
super.bindView(itemView)
|
super.bindView(itemView)
|
||||||
|
@ -16,19 +16,46 @@
|
|||||||
|
|
||||||
package im.vector.riotx.features.home.room.detail.timeline.item
|
package im.vector.riotx.features.home.room.detail.timeline.item
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import com.airbnb.epoxy.EpoxyAttribute
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
import com.airbnb.epoxy.EpoxyModelClass
|
import com.airbnb.epoxy.EpoxyModelClass
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
|
import im.vector.riotx.core.utils.DebouncedClickListener
|
||||||
|
import im.vector.riotx.features.home.AvatarRenderer
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController
|
||||||
|
|
||||||
@EpoxyModelClass(layout = R.layout.item_timeline_event_base_noinfo)
|
@EpoxyModelClass(layout = R.layout.item_timeline_event_base_noinfo)
|
||||||
abstract class DefaultItem : BaseEventItem<DefaultItem.Holder>() {
|
abstract class DefaultItem : BaseEventItem<DefaultItem.Holder>() {
|
||||||
|
|
||||||
|
@EpoxyAttribute
|
||||||
|
lateinit var informationData: MessageInformationData
|
||||||
|
|
||||||
|
@EpoxyAttribute
|
||||||
|
lateinit var avatarRenderer: AvatarRenderer
|
||||||
|
|
||||||
|
@EpoxyAttribute
|
||||||
|
var baseCallback: TimelineEventController.BaseCallback? = null
|
||||||
|
|
||||||
|
private var longClickListener = View.OnLongClickListener {
|
||||||
|
return@OnLongClickListener baseCallback?.onEventLongClicked(informationData, null, it) == true
|
||||||
|
}
|
||||||
|
|
||||||
|
@EpoxyAttribute
|
||||||
|
var readReceiptsCallback: TimelineEventController.ReadReceiptsCallback? = null
|
||||||
|
|
||||||
|
private val _readReceiptsClickListener = DebouncedClickListener(View.OnClickListener {
|
||||||
|
readReceiptsCallback?.onReadReceiptsClicked(informationData.readReceipts)
|
||||||
|
})
|
||||||
|
|
||||||
@EpoxyAttribute
|
@EpoxyAttribute
|
||||||
var text: CharSequence? = null
|
var text: CharSequence? = null
|
||||||
|
|
||||||
override fun bind(holder: Holder) {
|
override fun bind(holder: Holder) {
|
||||||
holder.messageView.text = text
|
holder.messageView.text = text
|
||||||
|
|
||||||
|
holder.view.setOnLongClickListener(longClickListener)
|
||||||
|
holder.readReceiptsView.render(informationData.readReceipts, avatarRenderer, _readReceiptsClickListener)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getViewType() = STUB_ID
|
override fun getViewType() = STUB_ID
|
||||||
|
@ -21,6 +21,7 @@ import android.view.ViewGroup
|
|||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.core.view.children
|
import androidx.core.view.children
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.features.home.AvatarRenderer
|
import im.vector.riotx.features.home.AvatarRenderer
|
||||||
|
|
||||||
@ -75,6 +76,9 @@ data class MergedHeaderItem(private val isCollapsed: Boolean,
|
|||||||
holder.separatorView.visibility = View.VISIBLE
|
holder.separatorView.visibility = View.VISIBLE
|
||||||
holder.expandView.setText(R.string.merged_events_collapse)
|
holder.expandView.setText(R.string.merged_events_collapse)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No read receipt for this item
|
||||||
|
holder.readReceiptsView.isVisible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
data class Data(
|
data class Data(
|
||||||
|
@ -22,7 +22,6 @@ import android.widget.TextView
|
|||||||
import com.airbnb.epoxy.EpoxyAttribute
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
import com.airbnb.epoxy.EpoxyModelClass
|
import com.airbnb.epoxy.EpoxyModelClass
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.ui.views.ReadReceiptsView
|
|
||||||
import im.vector.riotx.core.utils.DebouncedClickListener
|
import im.vector.riotx.core.utils.DebouncedClickListener
|
||||||
import im.vector.riotx.features.home.AvatarRenderer
|
import im.vector.riotx.features.home.AvatarRenderer
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController
|
import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController
|
||||||
@ -72,7 +71,6 @@ abstract class NoticeItem : BaseEventItem<NoticeItem.Holder>() {
|
|||||||
class Holder : BaseHolder(STUB_ID) {
|
class Holder : BaseHolder(STUB_ID) {
|
||||||
val avatarImageView by bind<ImageView>(R.id.itemNoticeAvatarView)
|
val avatarImageView by bind<ImageView>(R.id.itemNoticeAvatarView)
|
||||||
val noticeTextView by bind<TextView>(R.id.itemNoticeTextView)
|
val noticeTextView by bind<TextView>(R.id.itemNoticeTextView)
|
||||||
val readReceiptsView by bind<ReadReceiptsView>(R.id.readReceiptsView)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -89,18 +89,44 @@ class VideoContentRenderer @Inject constructor(private val activeSessionHolder:
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
thumbnailView.isVisible = false
|
|
||||||
loadingView.isVisible = false
|
|
||||||
|
|
||||||
val resolvedUrl = contentUrlResolver.resolveFullSize(data.url)
|
val resolvedUrl = contentUrlResolver.resolveFullSize(data.url)
|
||||||
|
|
||||||
if (resolvedUrl == null) {
|
if (resolvedUrl == null) {
|
||||||
|
thumbnailView.isVisible = false
|
||||||
|
loadingView.isVisible = false
|
||||||
errorView.isVisible = true
|
errorView.isVisible = true
|
||||||
errorView.setText(R.string.unknown_error)
|
errorView.setText(R.string.unknown_error)
|
||||||
} else {
|
} else {
|
||||||
videoView.isVisible = true
|
|
||||||
videoView.setVideoPath(resolvedUrl)
|
//Temporary code, some remote videos are not played by videoview setVideoUri
|
||||||
videoView.start()
|
//So for now we download them then play
|
||||||
|
thumbnailView.isVisible = true
|
||||||
|
loadingView.isVisible = true
|
||||||
|
|
||||||
|
activeSessionHolder.getActiveSession()
|
||||||
|
.downloadFile(
|
||||||
|
FileService.DownloadMode.FOR_INTERNAL_USE,
|
||||||
|
data.eventId,
|
||||||
|
data.filename,
|
||||||
|
data.url,
|
||||||
|
null,
|
||||||
|
object : MatrixCallback<File> {
|
||||||
|
override fun onSuccess(data: File) {
|
||||||
|
thumbnailView.isVisible = false
|
||||||
|
loadingView.isVisible = false
|
||||||
|
videoView.isVisible = true
|
||||||
|
|
||||||
|
videoView.setVideoPath(data.path)
|
||||||
|
videoView.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(failure: Throwable) {
|
||||||
|
loadingView.isVisible = false
|
||||||
|
errorView.isVisible = true
|
||||||
|
errorView.text = errorFormatter.toHumanReadable(failure)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ class PushRuleTriggerListener @Inject constructor(
|
|||||||
//TODO
|
//TODO
|
||||||
} else {
|
} else {
|
||||||
notifiableEvent.noisy = !notificationAction.soundName.isNullOrBlank()
|
notifiableEvent.noisy = !notificationAction.soundName.isNullOrBlank()
|
||||||
Timber.v("New event to notify $notifiableEvent tweaks:$notificationAction")
|
Timber.v("New event to notify")
|
||||||
notificationDrawerManager.onNotifiableEventReceived(notifiableEvent)
|
notificationDrawerManager.onNotifiableEventReceived(notifiableEvent)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -52,7 +52,8 @@ import javax.inject.Singleton
|
|||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
class BugReporter @Inject constructor(private val activeSessionHolder: ActiveSessionHolder,
|
class BugReporter @Inject constructor(private val activeSessionHolder: ActiveSessionHolder,
|
||||||
private val versionProvider: VersionProvider) {
|
private val versionProvider: VersionProvider,
|
||||||
|
private val vectorFileLogger : VectorFileLogger) {
|
||||||
var inMultiWindowMode = false
|
var inMultiWindowMode = false
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@ -162,7 +163,7 @@ class BugReporter @Inject constructor(private val activeSessionHolder: ActiveSes
|
|||||||
val gzippedFiles = ArrayList<File>()
|
val gzippedFiles = ArrayList<File>()
|
||||||
|
|
||||||
if (withDevicesLogs) {
|
if (withDevicesLogs) {
|
||||||
val files = VectorFileLogger.getLogFiles()
|
val files = vectorFileLogger.getLogFiles()
|
||||||
|
|
||||||
for (f in files) {
|
for (f in files) {
|
||||||
if (!mIsCancelled) {
|
if (!mIsCancelled) {
|
||||||
@ -348,20 +349,20 @@ class BugReporter @Inject constructor(private val activeSessionHolder: ActiveSes
|
|||||||
} else if (null == response || null == response.body()) {
|
} else if (null == response || null == response.body()) {
|
||||||
serverError = "Failed with error $responseCode"
|
serverError = "Failed with error $responseCode"
|
||||||
} else {
|
} else {
|
||||||
var `is`: InputStream? = null
|
var inputStream: InputStream? = null
|
||||||
|
|
||||||
try {
|
try {
|
||||||
`is` = response.body()!!.byteStream()
|
inputStream = response.body()!!.byteStream()
|
||||||
|
|
||||||
if (null != `is`) {
|
if (null != inputStream) {
|
||||||
var ch = `is`.read()
|
var ch = inputStream.read()
|
||||||
val b = StringBuilder()
|
val b = StringBuilder()
|
||||||
while (ch != -1) {
|
while (ch != -1) {
|
||||||
b.append(ch.toChar())
|
b.append(ch.toChar())
|
||||||
ch = `is`.read()
|
ch = inputStream.read()
|
||||||
}
|
}
|
||||||
serverError = b.toString()
|
serverError = b.toString()
|
||||||
`is`.close()
|
inputStream.close()
|
||||||
|
|
||||||
// check if the error message
|
// check if the error message
|
||||||
try {
|
try {
|
||||||
@ -380,7 +381,7 @@ class BugReporter @Inject constructor(private val activeSessionHolder: ActiveSes
|
|||||||
Timber.e(e, "## sendBugReport() : failed to parse error " + e.message)
|
Timber.e(e, "## sendBugReport() : failed to parse error " + e.message)
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
`is`?.close()
|
inputStream?.close()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Timber.e(e, "## sendBugReport() : failed to close the error stream " + e.message)
|
Timber.e(e, "## sendBugReport() : failed to close the error stream " + e.message)
|
||||||
}
|
}
|
||||||
|
@ -17,43 +17,74 @@
|
|||||||
package im.vector.riotx.features.rageshake
|
package im.vector.riotx.features.rageshake
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.text.TextUtils
|
import android.util.Log
|
||||||
|
import im.vector.riotx.features.settings.VectorPreferences
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
|
||||||
import java.io.PrintWriter
|
import java.io.PrintWriter
|
||||||
import java.io.StringWriter
|
import java.io.StringWriter
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.logging.*
|
import java.util.logging.*
|
||||||
import java.util.logging.Formatter
|
import java.util.logging.Formatter
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
object VectorFileLogger : Timber.DebugTree() {
|
private const val LOG_SIZE_BYTES = 20 * 1024 * 1024 // 20MB
|
||||||
|
|
||||||
private const val LOG_SIZE_BYTES = 50 * 1024 * 1024 // 50MB
|
private const val LOG_ROTATION_COUNT = 3
|
||||||
|
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class VectorFileLogger @Inject constructor(val context: Context, private val vectorPreferences: VectorPreferences) : Timber.DebugTree() {
|
||||||
|
|
||||||
// relatively large rotation count because closing > opening the app rotates the log (!)
|
|
||||||
private const val LOG_ROTATION_COUNT = 15
|
|
||||||
|
|
||||||
private val sLogger = Logger.getLogger("im.vector.riotx")
|
private val sLogger = Logger.getLogger("im.vector.riotx")
|
||||||
private lateinit var sFileHandler: FileHandler
|
private var sFileHandler: FileHandler? = null
|
||||||
private lateinit var sCacheDirectory: File
|
private var sCacheDirectory: File? = null
|
||||||
private var sFileName = "riotx"
|
private var sFileName = "riotxlogs"
|
||||||
|
|
||||||
fun init(context: Context) {
|
private val prioPrefixes = mapOf(
|
||||||
|
Log.VERBOSE to "V/ ",
|
||||||
|
Log.DEBUG to "D/ ",
|
||||||
|
Log.INFO to "I/ ",
|
||||||
|
Log.WARN to "W/ ",
|
||||||
|
Log.ERROR to "E/ ",
|
||||||
|
Log.ASSERT to "WTF/ "
|
||||||
|
)
|
||||||
|
|
||||||
|
init {
|
||||||
val logsDirectoryFile = context.cacheDir.absolutePath + "/logs"
|
val logsDirectoryFile = context.cacheDir.absolutePath + "/logs"
|
||||||
|
|
||||||
setLogDirectory(File(logsDirectoryFile))
|
setLogDirectory(File(logsDirectoryFile))
|
||||||
init("RiotXLog")
|
try {
|
||||||
|
if (sCacheDirectory != null) {
|
||||||
|
sFileHandler = FileHandler(sCacheDirectory!!.absolutePath + "/" + sFileName + ".%g.txt", LOG_SIZE_BYTES, LOG_ROTATION_COUNT)
|
||||||
|
sFileHandler?.formatter = LogFormatter()
|
||||||
|
sLogger.useParentHandlers = false
|
||||||
|
sLogger.level = Level.ALL
|
||||||
|
sLogger.addHandler(sFileHandler)
|
||||||
|
}
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
Timber.e(e, "Failed to initialize FileLogger")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
|
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
|
||||||
|
if (sFileHandler == null) return
|
||||||
|
if (skipLog(priority)) return
|
||||||
if (t != null) {
|
if (t != null) {
|
||||||
logToFile(t)
|
logToFile(t)
|
||||||
}
|
}
|
||||||
|
logToFile(prioPrefixes[priority] ?: "$priority ", tag ?: "Tag", message)
|
||||||
|
}
|
||||||
|
|
||||||
logToFile("$priority ", tag ?: "Tag", message)
|
private fun skipLog(priority: Int): Boolean {
|
||||||
|
return if (vectorPreferences.labAllowedExtendedLogging()) {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
priority < Log.ERROR
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -68,24 +99,6 @@ object VectorFileLogger : Timber.DebugTree() {
|
|||||||
sCacheDirectory = cacheDir
|
sCacheDirectory = cacheDir
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialises the logger. Should be called AFTER [Log.setLogDirectory].
|
|
||||||
*
|
|
||||||
* @param fileName the base file name
|
|
||||||
*/
|
|
||||||
private fun init(fileName: String) {
|
|
||||||
try {
|
|
||||||
if (!TextUtils.isEmpty(fileName)) {
|
|
||||||
sFileName = fileName
|
|
||||||
}
|
|
||||||
sFileHandler = FileHandler(sCacheDirectory.absolutePath + "/" + sFileName + ".%g.txt", LOG_SIZE_BYTES, LOG_ROTATION_COUNT)
|
|
||||||
sFileHandler.formatter = LogFormatter()
|
|
||||||
sLogger.useParentHandlers = false
|
|
||||||
sLogger.level = Level.ALL
|
|
||||||
sLogger.addHandler(sFileHandler)
|
|
||||||
} catch (e: IOException) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds our own log files to the provided list of files.
|
* Adds our own log files to the provided list of files.
|
||||||
@ -99,8 +112,8 @@ object VectorFileLogger : Timber.DebugTree() {
|
|||||||
try {
|
try {
|
||||||
// reported by GA
|
// reported by GA
|
||||||
if (null != sFileHandler) {
|
if (null != sFileHandler) {
|
||||||
sFileHandler.flush()
|
sFileHandler!!.flush()
|
||||||
val absPath = sCacheDirectory.absolutePath
|
val absPath = sCacheDirectory?.absolutePath ?: return emptyList()
|
||||||
|
|
||||||
for (i in 0..LOG_ROTATION_COUNT) {
|
for (i in 0..LOG_ROTATION_COUNT) {
|
||||||
val filepath = "$absPath/$sFileName.$i.txt"
|
val filepath = "$absPath/$sFileName.$i.txt"
|
||||||
@ -111,7 +124,7 @@ object VectorFileLogger : Timber.DebugTree() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Timber.e(e, "## addLogFiles() failed : " + e.message)
|
Timber.e(e, "## addLogFiles() failed : %s", e.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
return files
|
return files
|
||||||
|
@ -21,7 +21,6 @@ import android.animation.AnimatorSet
|
|||||||
import android.animation.ObjectAnimator
|
import android.animation.ObjectAnimator
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.TypedArray
|
import android.content.res.TypedArray
|
||||||
import android.graphics.Typeface
|
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
@ -35,9 +34,11 @@ import android.widget.TextView
|
|||||||
import androidx.annotation.ColorInt
|
import androidx.annotation.ColorInt
|
||||||
import androidx.annotation.ColorRes
|
import androidx.annotation.ColorRes
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.emoji.text.EmojiCompat
|
import im.vector.riotx.EmojiCompatWrapper
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
|
import im.vector.riotx.core.di.HasScreenInjector
|
||||||
import im.vector.riotx.core.utils.TextUtils
|
import im.vector.riotx.core.utils.TextUtils
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An animated reaction button.
|
* An animated reaction button.
|
||||||
@ -47,6 +48,12 @@ class ReactionButton @JvmOverloads constructor(context: Context, attrs: Attribut
|
|||||||
defStyleAttr: Int = 0)
|
defStyleAttr: Int = 0)
|
||||||
: FrameLayout(context, attrs, defStyleAttr), View.OnClickListener, View.OnLongClickListener {
|
: FrameLayout(context, attrs, defStyleAttr), View.OnClickListener, View.OnLongClickListener {
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (context is HasScreenInjector) {
|
||||||
|
context.injector().inject(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val DECCELERATE_INTERPOLATOR = DecelerateInterpolator()
|
private val DECCELERATE_INTERPOLATOR = DecelerateInterpolator()
|
||||||
private val ACCELERATE_DECELERATE_INTERPOLATOR = AccelerateDecelerateInterpolator()
|
private val ACCELERATE_DECELERATE_INTERPOLATOR = AccelerateDecelerateInterpolator()
|
||||||
@ -54,6 +61,8 @@ class ReactionButton @JvmOverloads constructor(context: Context, attrs: Attribut
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Inject lateinit var emojiCompatWrapper: EmojiCompatWrapper
|
||||||
|
|
||||||
private var emojiView: TextView? = null
|
private var emojiView: TextView? = null
|
||||||
private var countTextView: TextView? = null
|
private var countTextView: TextView? = null
|
||||||
|
|
||||||
@ -78,7 +87,7 @@ class ReactionButton @JvmOverloads constructor(context: Context, attrs: Attribut
|
|||||||
set(value) {
|
set(value) {
|
||||||
field = value
|
field = value
|
||||||
//maybe cache this for performances?
|
//maybe cache this for performances?
|
||||||
val emojiSpanned = EmojiCompat.get().process(value)
|
val emojiSpanned = emojiCompatWrapper.safeEmojiSpanify(value)
|
||||||
emojiView?.text = emojiSpanned
|
emojiView?.text = emojiSpanned
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,6 +149,8 @@ class VectorPreferences @Inject constructor(private val context: Context) {
|
|||||||
private const val SETTINGS_USE_NATIVE_CAMERA_PREFERENCE_KEY = "SETTINGS_USE_NATIVE_CAMERA_PREFERENCE_KEY"
|
private const val SETTINGS_USE_NATIVE_CAMERA_PREFERENCE_KEY = "SETTINGS_USE_NATIVE_CAMERA_PREFERENCE_KEY"
|
||||||
private const val SETTINGS_ENABLE_SEND_VOICE_FEATURE_PREFERENCE_KEY = "SETTINGS_ENABLE_SEND_VOICE_FEATURE_PREFERENCE_KEY"
|
private const val SETTINGS_ENABLE_SEND_VOICE_FEATURE_PREFERENCE_KEY = "SETTINGS_ENABLE_SEND_VOICE_FEATURE_PREFERENCE_KEY"
|
||||||
|
|
||||||
|
const val SETTINGS_LABS_ALLOW_EXTENDED_LOGS = "SETTINGS_LABS_ALLOW_EXTENDED_LOGS"
|
||||||
|
|
||||||
private const val SETTINGS_LABS_SHOW_HIDDEN_EVENTS_PREFERENCE_KEY = "SETTINGS_LABS_SHOW_HIDDEN_EVENTS_PREFERENCE_KEY"
|
private const val SETTINGS_LABS_SHOW_HIDDEN_EVENTS_PREFERENCE_KEY = "SETTINGS_LABS_SHOW_HIDDEN_EVENTS_PREFERENCE_KEY"
|
||||||
private const val SETTINGS_LABS_ENABLE_SWIPE_TO_REPLY = "SETTINGS_LABS_ENABLE_SWIPE_TO_REPLY"
|
private const val SETTINGS_LABS_ENABLE_SWIPE_TO_REPLY = "SETTINGS_LABS_ENABLE_SWIPE_TO_REPLY"
|
||||||
|
|
||||||
@ -257,6 +259,10 @@ class VectorPreferences @Inject constructor(private val context: Context) {
|
|||||||
return defaultPrefs.getBoolean(SETTINGS_LABS_ENABLE_SWIPE_TO_REPLY, true)
|
return defaultPrefs.getBoolean(SETTINGS_LABS_ENABLE_SWIPE_TO_REPLY, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun labAllowedExtendedLogging(): Boolean {
|
||||||
|
return defaultPrefs.getBoolean(SETTINGS_LABS_ALLOW_EXTENDED_LOGS, false)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells if we have already asked the user to disable battery optimisations on android >= M devices.
|
* Tells if we have already asked the user to disable battery optimisations on android >= M devices.
|
||||||
*
|
*
|
||||||
|
6
vector/src/main/res/drawable/pill_receipt_black.xml
Normal file
6
vector/src/main/res/drawable/pill_receipt_black.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<corners android:radius="10dp" />
|
||||||
|
<solid android:color="@color/riotx_header_panel_border_mobile_black" />
|
||||||
|
</shape>
|
6
vector/src/main/res/drawable/pill_receipt_dark.xml
Normal file
6
vector/src/main/res/drawable/pill_receipt_dark.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<corners android:radius="10dp" />
|
||||||
|
<solid android:color="@color/riotx_header_panel_border_mobile_dark" />
|
||||||
|
</shape>
|
6
vector/src/main/res/drawable/pill_receipt_light.xml
Normal file
6
vector/src/main/res/drawable/pill_receipt_light.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<corners android:radius="10dp" />
|
||||||
|
<solid android:color="@color/riotx_header_panel_border_mobile_light" />
|
||||||
|
</shape>
|
@ -34,7 +34,9 @@
|
|||||||
android:id="@+id/videoMediaViewerThumbnailView"
|
android:id="@+id/videoMediaViewerThumbnailView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
|
android:scaleType="centerInside"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
@ -49,6 +51,7 @@
|
|||||||
android:id="@+id/videoMediaViewerVideoView"
|
android:id="@+id/videoMediaViewerVideoView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
@ -5,38 +5,26 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
|
android:minHeight="40dp"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:paddingStart="8dp"
|
android:paddingStart="8dp"
|
||||||
android:paddingEnd="8dp">
|
android:paddingEnd="8dp">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/readReceiptAvatar"
|
android:id="@+id/readReceiptAvatar"
|
||||||
android:layout_width="24dp"
|
android:layout_width="32dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="32dp"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
tools:src="@tools:sample/avatars" />
|
tools:src="@tools:sample/avatars" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/readReceiptName"
|
android:id="@+id/readReceiptName"
|
||||||
android:layout_width="0dp"
|
style="@style/BottomSheetItemTextMain"
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="4dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:lines="1"
|
|
||||||
android:paddingTop="8dp"
|
|
||||||
android:paddingBottom="8dp"
|
|
||||||
android:textColor="?riotx_text_primary"
|
|
||||||
android:textSize="16sp"
|
|
||||||
tools:text="@sample/matrix.json/data/displayName" />
|
tools:text="@sample/matrix.json/data/displayName" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/readReceiptDate"
|
android:id="@+id/readReceiptDate"
|
||||||
android:layout_width="wrap_content"
|
style="@style/BottomSheetItemTime"
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:lines="1"
|
|
||||||
android:textColor="?riotx_text_secondary"
|
|
||||||
android:textSize="12sp"
|
|
||||||
tools:text="10:44" />
|
tools:text="10:44" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
@ -6,6 +6,7 @@
|
|||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:paddingStart="8dp"
|
android:paddingStart="8dp"
|
||||||
|
android:minHeight="40dp"
|
||||||
android:paddingEnd="8dp">
|
android:paddingEnd="8dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@ -22,25 +23,12 @@
|
|||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/itemSimpleReactionInfoMemberName"
|
android:id="@+id/itemSimpleReactionInfoMemberName"
|
||||||
android:layout_width="0dp"
|
style="@style/BottomSheetItemTextMain"
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="4dp"
|
|
||||||
android:paddingTop="8dp"
|
|
||||||
android:paddingBottom="8dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:lines="1"
|
|
||||||
android:textColor="?android:textColorPrimary"
|
|
||||||
android:textSize="16sp"
|
|
||||||
tools:text="@sample/matrix.json/data/displayName" />
|
tools:text="@sample/matrix.json/data/displayName" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/itemSimpleReactionInfoTime"
|
android:id="@+id/itemSimpleReactionInfoTime"
|
||||||
android:layout_width="wrap_content"
|
style="@style/BottomSheetItemTime"
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:lines="1"
|
|
||||||
android:textColor="?android:textColorSecondary"
|
|
||||||
android:textSize="12sp"
|
|
||||||
tools:text="10:44" />
|
tools:text="10:44" />
|
||||||
|
|
||||||
|
|
||||||
|
@ -129,8 +129,10 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:layout_marginBottom="4dp"
|
android:layout_marginBottom="4dp"
|
||||||
|
android:visibility="gone"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent" />
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -58,8 +58,10 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:layout_marginBottom="4dp"
|
android:layout_marginBottom="4dp"
|
||||||
|
android:visibility="gone"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent" />
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -9,48 +9,55 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/receiptMore"
|
android:id="@+id/receiptMore"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="18dp"
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:textSize="12sp"
|
android:textSize="12sp"
|
||||||
|
android:background="?vctr_pill_receipt"
|
||||||
|
android:paddingStart="4dp"
|
||||||
|
android:paddingEnd="4dp"
|
||||||
tools:text="999+" />
|
tools:text="999+" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/receiptAvatar5"
|
android:id="@+id/receiptAvatar5"
|
||||||
android:layout_width="16dp"
|
android:layout_width="18dp"
|
||||||
android:layout_height="16dp"
|
android:layout_height="18dp"
|
||||||
|
android:layout_marginStart="2dp"
|
||||||
android:adjustViewBounds="true"
|
android:adjustViewBounds="true"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
tools:src="@tools:sample/avatars" />
|
tools:src="@tools:sample/avatars" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/receiptAvatar4"
|
android:id="@+id/receiptAvatar4"
|
||||||
android:layout_width="16dp"
|
android:layout_width="18dp"
|
||||||
android:layout_height="16dp"
|
android:layout_height="18dp"
|
||||||
|
android:layout_marginStart="2dp"
|
||||||
android:adjustViewBounds="true"
|
android:adjustViewBounds="true"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
tools:src="@tools:sample/avatars" />
|
tools:src="@tools:sample/avatars" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/receiptAvatar3"
|
android:id="@+id/receiptAvatar3"
|
||||||
android:layout_width="16dp"
|
android:layout_width="18dp"
|
||||||
android:layout_height="16dp"
|
android:layout_height="18dp"
|
||||||
|
android:layout_marginStart="2dp"
|
||||||
android:adjustViewBounds="true"
|
android:adjustViewBounds="true"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
tools:src="@tools:sample/avatars" />
|
tools:src="@tools:sample/avatars" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/receiptAvatar2"
|
android:id="@+id/receiptAvatar2"
|
||||||
android:layout_width="16dp"
|
android:layout_width="18dp"
|
||||||
android:layout_height="16dp"
|
android:layout_height="18dp"
|
||||||
|
android:layout_marginStart="2dp"
|
||||||
android:adjustViewBounds="true"
|
android:adjustViewBounds="true"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
tools:src="@tools:sample/avatars" />
|
tools:src="@tools:sample/avatars" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/receiptAvatar1"
|
android:id="@+id/receiptAvatar1"
|
||||||
android:layout_width="16dp"
|
android:layout_width="18dp"
|
||||||
android:layout_height="16dp"
|
android:layout_height="18dp"
|
||||||
|
android:layout_marginStart="2dp"
|
||||||
android:adjustViewBounds="true"
|
android:adjustViewBounds="true"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
tools:src="@tools:sample/avatars" />
|
tools:src="@tools:sample/avatars" />
|
||||||
|
@ -326,7 +326,7 @@
|
|||||||
<string name="room_unsent_messages_notification">Съобщенията не са изпратени. %1$s или %2$s?</string>
|
<string name="room_unsent_messages_notification">Съобщенията не са изпратени. %1$s или %2$s?</string>
|
||||||
<string name="room_unknown_devices_messages_notification">Съобщението не е изпратено поради наличието на непознати устройства. %1$s или %2$s?</string>
|
<string name="room_unknown_devices_messages_notification">Съобщението не е изпратено поради наличието на непознати устройства. %1$s или %2$s?</string>
|
||||||
<string name="room_prompt_resend">Изпрати всички отново</string>
|
<string name="room_prompt_resend">Изпрати всички отново</string>
|
||||||
<string name="room_prompt_cancel">откажи всички</string>
|
<string name="room_prompt_cancel">Откажи всички</string>
|
||||||
<string name="room_resend_unsent_messages">Изпрати отново неизпратените съобщения</string>
|
<string name="room_resend_unsent_messages">Изпрати отново неизпратените съобщения</string>
|
||||||
<string name="room_delete_unsent_messages">Изтрий неизпратените съобщения</string>
|
<string name="room_delete_unsent_messages">Изтрий неизпратените съобщения</string>
|
||||||
<string name="room_message_file_not_found">Файлът не е намерен</string>
|
<string name="room_message_file_not_found">Файлът не е намерен</string>
|
||||||
@ -1600,4 +1600,17 @@
|
|||||||
|
|
||||||
<string name="link_copied_to_clipboard">Връзката беше копирана</string>
|
<string name="link_copied_to_clipboard">Връзката беше копирана</string>
|
||||||
|
|
||||||
|
<string name="settings_integration_manager">Мениджър на интеграции</string>
|
||||||
|
|
||||||
|
<string name="integration_manager_not_configured">Не е конфигуриран мениджър на интеграции.</string>
|
||||||
|
<string name="add_by_matrix_id">Добави по Matrix идентификатор</string>
|
||||||
|
<string name="creating_direct_room">Създаване на стая…</string>
|
||||||
|
<string name="direct_room_no_known_users">Не са намерени резултати, използва \"Добави по Matrix идентификатор\" за търсене на сървъра.</string>
|
||||||
|
<string name="direct_room_start_search">Започнете да пишете, за да получите резултати</string>
|
||||||
|
<string name="direct_room_filter_hint">Филтрирай по потребител или ID…</string>
|
||||||
|
|
||||||
|
<string name="joining_room">Присъединяване в стая…</string>
|
||||||
|
|
||||||
|
<string name="message_view_edit_history">Виж историята на редакциите</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<string name="black_them">Tema negre</string>
|
<string name="black_them">Tema negre</string>
|
||||||
|
|
||||||
<!-- permanent notification subtitle -->
|
<!-- permanent notification subtitle -->
|
||||||
<string name="notification_sync_in_progress">Sincronitzant</string>
|
<string name="notification_sync_in_progress">S\'està sincronitzant…</string>
|
||||||
<string name="notification_listening_for_events">Escolta esdeveniments</string>
|
<string name="notification_listening_for_events">Escolta esdeveniments</string>
|
||||||
<string name="notification_noisy_notifications">Notificacions sorolloses</string>
|
<string name="notification_noisy_notifications">Notificacions sorolloses</string>
|
||||||
<string name="notification_silent_notifications">Notificacions silencioses</string>
|
<string name="notification_silent_notifications">Notificacions silencioses</string>
|
||||||
@ -46,9 +46,10 @@
|
|||||||
<string name="rename">Reanomena</string>
|
<string name="rename">Reanomena</string>
|
||||||
<string name="report_content">Informa del contingut</string>
|
<string name="report_content">Informa del contingut</string>
|
||||||
<string name="active_call">Trucada activa</string>
|
<string name="active_call">Trucada activa</string>
|
||||||
<string name="ongoing_conference_call">" Conferència en curs.\nUniu-vos hi per %1$s o %2$s."</string>
|
<string name="ongoing_conference_call">Conferència en curs.
|
||||||
<string name="ongoing_conference_call_voice">veu</string>
|
\nUniu-vos hi per %1$s o %2$s.</string>
|
||||||
<string name="ongoing_conference_call_video">vídeo</string>
|
<string name="ongoing_conference_call_voice">Veu</string>
|
||||||
|
<string name="ongoing_conference_call_video">Vídeo</string>
|
||||||
<string name="cannot_start_call">La trucada no es pot iniciar, prova-ho més tard</string>
|
<string name="cannot_start_call">La trucada no es pot iniciar, prova-ho més tard</string>
|
||||||
<string name="missing_permissions_warning">Pot ser que algunes funcions no apareguin per manca de permisos…</string>
|
<string name="missing_permissions_warning">Pot ser que algunes funcions no apareguin per manca de permisos…</string>
|
||||||
<string name="missing_permissions_to_start_conf_call">Es necessiten permisos per convidar a iniciar una conferència en aquesta sala</string>
|
<string name="missing_permissions_to_start_conf_call">Es necessiten permisos per convidar a iniciar una conferència en aquesta sala</string>
|
||||||
@ -84,11 +85,11 @@
|
|||||||
<string name="bottom_action_rooms">Sales</string>
|
<string name="bottom_action_rooms">Sales</string>
|
||||||
|
|
||||||
<!-- Home screen -->
|
<!-- Home screen -->
|
||||||
<string name="home_filter_placeholder_home">Cerca sales</string>
|
<string name="home_filter_placeholder_home">Filtrar noms de sales</string>
|
||||||
<string name="home_filter_placeholder_favorites">Cerca preferits</string>
|
<string name="home_filter_placeholder_favorites">Filtrar preferits</string>
|
||||||
<string name="home_filter_placeholder_people">Cerca persones</string>
|
<string name="home_filter_placeholder_people">Filtrar persones</string>
|
||||||
<string name="home_filter_placeholder_rooms">Cerca sales</string>
|
<string name="home_filter_placeholder_rooms">Filtrar per noms de sala</string>
|
||||||
<string name="home_filter_placeholder_groups">Cerca comunitats</string>
|
<string name="home_filter_placeholder_groups">Filtrar per nom de comunitats</string>
|
||||||
|
|
||||||
<!-- Home fragment -->
|
<!-- Home fragment -->
|
||||||
<string name="invitations_header">Convida</string>
|
<string name="invitations_header">Convida</string>
|
||||||
@ -137,7 +138,7 @@
|
|||||||
|
|
||||||
<string name="join_room">Uneix-te a la sala</string>
|
<string name="join_room">Uneix-te a la sala</string>
|
||||||
<string name="username">Nom d\'usuari</string>
|
<string name="username">Nom d\'usuari</string>
|
||||||
<string name="create_account">Registra\'m</string>
|
<string name="create_account">Crear un compte</string>
|
||||||
<string name="login">Entra</string>
|
<string name="login">Entra</string>
|
||||||
<string name="logout">Desconnecta</string>
|
<string name="logout">Desconnecta</string>
|
||||||
<string name="hs_url">URL del servidor</string>
|
<string name="hs_url">URL del servidor</string>
|
||||||
@ -235,7 +236,7 @@
|
|||||||
<!-- accounts list Screen -->
|
<!-- accounts list Screen -->
|
||||||
|
|
||||||
<!-- image size selection -->
|
<!-- image size selection -->
|
||||||
<string name="compression_options">"Envia com "</string>
|
<string name="compression_options">Envia com</string>
|
||||||
<string name="compression_opt_list_original">Original</string>
|
<string name="compression_opt_list_original">Original</string>
|
||||||
<string name="compression_opt_list_large">Gran</string>
|
<string name="compression_opt_list_large">Gran</string>
|
||||||
<string name="compression_opt_list_medium">Mitjana</string>
|
<string name="compression_opt_list_medium">Mitjana</string>
|
||||||
@ -283,7 +284,9 @@
|
|||||||
<string name="permissions_rationale_msg_record_audio">Per tal de fer trucades de veu, el Riot necessita permís d\'accés al microfon.</string>
|
<string name="permissions_rationale_msg_record_audio">Per tal de fer trucades de veu, el Riot necessita permís d\'accés al microfon.</string>
|
||||||
<string name="permissions_rationale_msg_record_audio_explanation">\n\nA la següent finestra emergent, doneu permís d\'accés per tal de poder fer la trucada.</string>
|
<string name="permissions_rationale_msg_record_audio_explanation">\n\nA la següent finestra emergent, doneu permís d\'accés per tal de poder fer la trucada.</string>
|
||||||
<string name="permissions_rationale_msg_camera_and_audio">Per tal de fer vídeotrucades, el Riot necessita permís d\'accés a la càmera i al microfon.\n\nA la següent finestra emergent, doneu permís d\'accés per tal de poder fer la trucada.</string>
|
<string name="permissions_rationale_msg_camera_and_audio">Per tal de fer vídeotrucades, el Riot necessita permís d\'accés a la càmera i al microfon.\n\nA la següent finestra emergent, doneu permís d\'accés per tal de poder fer la trucada.</string>
|
||||||
<string name="permissions_rationale_msg_contacts">Per tal de trobar altres usuaris de Matrix a partir dels seus correus electrònics o dels seus números de telefon, el Riot necessita permís d\'accés a l\'agenda de contactes.\n\nA la següent finestra emergent, doneu permís d\'accés per trobar amb quins contactes de la teva agenda pots contactar a partir de Riot.</string>
|
<string name="permissions_rationale_msg_contacts">Riot pot comprovar la vostra agenda de contactes per tal de trobar altres usuaris de Matrix basant-se en les seves adreces de correu i números de telèfon.
|
||||||
|
\n
|
||||||
|
\nSi accepteu compartir la vostra agenda de contactes amb aquesta finalitat, si us plau permeteu l\'accés de la següent finestra emergent.</string>
|
||||||
<string name="permissions_msg_contacts_warning_other_androids">Per tal de trobar altres usuaris de Matrix a partir dels seus correus electrònics o dels seus números de telefon, el Riot necessita permís d\'accés a l\'agenda de contactes.\n\nPermeteu que Riot accedeixi als vostres contactes?</string>
|
<string name="permissions_msg_contacts_warning_other_androids">Per tal de trobar altres usuaris de Matrix a partir dels seus correus electrònics o dels seus números de telefon, el Riot necessita permís d\'accés a l\'agenda de contactes.\n\nPermeteu que Riot accedeixi als vostres contactes?</string>
|
||||||
|
|
||||||
<string name="permissions_action_not_performed_missing_permissions">No s\'ha realitzat l\'acció per falta de permisos</string>
|
<string name="permissions_action_not_performed_missing_permissions">No s\'ha realitzat l\'acció per falta de permisos</string>
|
||||||
@ -370,7 +373,7 @@
|
|||||||
<string name="room_unsent_messages_notification">Els missatges no s\'han enviat. %1$s o %2$s ara?</string>
|
<string name="room_unsent_messages_notification">Els missatges no s\'han enviat. %1$s o %2$s ara?</string>
|
||||||
<string name="room_unknown_devices_messages_notification">Els missatges no s\'han enviat perquè hi ha disposistius desconeguts. %1$s o %2$s ara?</string>
|
<string name="room_unknown_devices_messages_notification">Els missatges no s\'han enviat perquè hi ha disposistius desconeguts. %1$s o %2$s ara?</string>
|
||||||
<string name="room_prompt_resend">Reenvia-ho tot</string>
|
<string name="room_prompt_resend">Reenvia-ho tot</string>
|
||||||
<string name="room_prompt_cancel">cancel·la-ho tot</string>
|
<string name="room_prompt_cancel">Cancel·la-ho tot</string>
|
||||||
<string name="room_resend_unsent_messages">Reenvia els missatges no enviats</string>
|
<string name="room_resend_unsent_messages">Reenvia els missatges no enviats</string>
|
||||||
<string name="room_delete_unsent_messages">Elimina els missatges no enviats</string>
|
<string name="room_delete_unsent_messages">Elimina els missatges no enviats</string>
|
||||||
<string name="room_message_file_not_found">No s\'ha trobat el fitxer</string>
|
<string name="room_message_file_not_found">No s\'ha trobat el fitxer</string>
|
||||||
@ -542,9 +545,9 @@ Tingueu en compte que aquesta acció reiniciarà l\'aplicació i que pot trigar
|
|||||||
<string name="account_phone_number_already_used_error">Aquest número de telèfon ja està en ús.</string>
|
<string name="account_phone_number_already_used_error">Aquest número de telèfon ja està en ús.</string>
|
||||||
|
|
||||||
<string name="settings_change_password">Canvia la contrasenya</string>
|
<string name="settings_change_password">Canvia la contrasenya</string>
|
||||||
<string name="settings_old_password">Contrasenya antiga</string>
|
<string name="settings_old_password">Contrasenya actual</string>
|
||||||
<string name="settings_new_password">Contrasenya nova</string>
|
<string name="settings_new_password">Contrasenya nova</string>
|
||||||
<string name="settings_confirm_password">Confirmeu la contrasenya</string>
|
<string name="settings_confirm_password">Confirmeu la nova contrasenya</string>
|
||||||
<string name="settings_fail_to_update_password">No s\'ha pogut actualitzar la contrasenya</string>
|
<string name="settings_fail_to_update_password">No s\'ha pogut actualitzar la contrasenya</string>
|
||||||
<string name="settings_password_updated">La contrasenya s\'ha actualitzat</string>
|
<string name="settings_password_updated">La contrasenya s\'ha actualitzat</string>
|
||||||
<string name="settings_unignore_user">Mostra tots els missatges des de %s?
|
<string name="settings_unignore_user">Mostra tots els missatges des de %s?
|
||||||
@ -889,7 +892,7 @@ Atenció: es podria eliminar aquest fitxer si es desinstal·la l\'aplicació.</s
|
|||||||
<string name="e2e_re_request_encryption_key_dialog_content">Si us plau, engega Riot a un altre dispositiu que pugui desencriptar el missatge de manera que pugui enviar la clau a aquest dispositiu.</string>
|
<string name="e2e_re_request_encryption_key_dialog_content">Si us plau, engega Riot a un altre dispositiu que pugui desencriptar el missatge de manera que pugui enviar la clau a aquest dispositiu.</string>
|
||||||
|
|
||||||
<string name="settings_notification_privacy_normal">Normal</string>
|
<string name="settings_notification_privacy_normal">Normal</string>
|
||||||
<string name="status_theme">Motiu Status.im</string>
|
<string name="status_theme">Tema Status.im</string>
|
||||||
|
|
||||||
<string name="missing_permissions_error">Manquen permisos per a dur a terme aquesta acció.</string>
|
<string name="missing_permissions_error">Manquen permisos per a dur a terme aquesta acció.</string>
|
||||||
<string name="dialog_title_error">Error</string>
|
<string name="dialog_title_error">Error</string>
|
||||||
@ -924,7 +927,7 @@ En voleu afegir algun?</string>
|
|||||||
<string name="room_participants_action_unignore_prompt">Mostrar tots els missatges d\'aquest usuari?
|
<string name="room_participants_action_unignore_prompt">Mostrar tots els missatges d\'aquest usuari?
|
||||||
|
|
||||||
Tingueu en compte que aquesta acció reiniciarà l\'aplicació i pot trigar una estona.</string>
|
Tingueu en compte que aquesta acció reiniciarà l\'aplicació i pot trigar una estona.</string>
|
||||||
<string name="room_participants_invite_join_names">"%1$s, "</string>
|
<string name="room_participants_invite_join_names">"%1$s,· "</string>
|
||||||
<string name="room_participants_invite_join_names_and">%1$s i %2$s</string>
|
<string name="room_participants_invite_join_names_and">%1$s i %2$s</string>
|
||||||
<string name="room_participants_invite_join_names_combined">%1$s %2$s</string>
|
<string name="room_participants_invite_join_names_combined">%1$s %2$s</string>
|
||||||
|
|
||||||
@ -938,7 +941,7 @@ Tingueu en compte que aquesta acció reiniciarà l\'aplicació i pot trigar una
|
|||||||
<string name="settings_notification_privacy">Notificació de privacitat</string>
|
<string name="settings_notification_privacy">Notificació de privacitat</string>
|
||||||
<string name="settings_notification_privacy_reduced">Privacitat reduïda</string>
|
<string name="settings_notification_privacy_reduced">Privacitat reduïda</string>
|
||||||
<string name="settings_notification_privacy_need_permission">L\'aplicació necessita permisos per funcionar en segon pla</string>
|
<string name="settings_notification_privacy_need_permission">L\'aplicació necessita permisos per funcionar en segon pla</string>
|
||||||
<string name="settings_notification_privacy_fcm">• Les notificacions s\'envien via Google Cloud Messaging</string>
|
<string name="settings_notification_privacy_fcm">• Les notificacions s\'envien via Firebase Cloud Messaging</string>
|
||||||
<string name="settings_notification_privacy_metadata">• Les notificacions contenen només meta dades</string>
|
<string name="settings_notification_privacy_metadata">• Les notificacions contenen només meta dades</string>
|
||||||
<string name="settings_notification_privacy_secure_message_content">• El contingut dels missatges de les notificacions s\'obté <b>de forma segura des del servidor de Matrix</b></string>
|
<string name="settings_notification_privacy_secure_message_content">• El contingut dels missatges de les notificacions s\'obté <b>de forma segura des del servidor de Matrix</b></string>
|
||||||
<string name="settings_notification_privacy_nosecure_message_content">• Les notificacions contenen <b>meta dades i dades de missatges</b></string>
|
<string name="settings_notification_privacy_nosecure_message_content">• Les notificacions contenen <b>meta dades i dades de missatges</b></string>
|
||||||
@ -1246,7 +1249,7 @@ Aquest error és fora del control del Riot. No hi ha cap compte de Google al tel
|
|||||||
<string name="settings_troubleshoot_test_bg_restricted_failed">Les restriccions de rerefons són habilitades per al Riot.
|
<string name="settings_troubleshoot_test_bg_restricted_failed">Les restriccions de rerefons són habilitades per al Riot.
|
||||||
Les tasques que l\'aplicació intenta fer estaran restringides agressivament mentre estigui al rerefons, i això pot afectar les notificacions.
|
Les tasques que l\'aplicació intenta fer estaran restringides agressivament mentre estigui al rerefons, i això pot afectar les notificacions.
|
||||||
%1$s</string>
|
%1$s</string>
|
||||||
<string name="settings_troubleshoot_test_battery_failed">"Si un usuari deixa un dispositiu sense endollar i immòbil durant un període de temps, amb la pantalla apagada, el dispositiu entra en el mode Doze. Això impedeix les aplicacions d\'accedir a la xarxa i ajorna les seves tasques, sincronitzacions i alarmes estàndard. "</string>
|
<string name="settings_troubleshoot_test_battery_failed">Si un usuari deixa un dispositiu sense endollar i immòbil durant un període de temps, amb la pantalla apagada, el dispositiu entra en el mode d\'estalvi d\'energia. Això impedeix les aplicacions d\'accedir a la xarxa i ajorna les seves tasques, sincronitzacions i alarmes estàndard.</string>
|
||||||
<string name="store_full_description">"Una aplicació de xat, sota el vostre control i totalment flexible. El Riot us permet comunicar-vos de la manera que preferiu. Fet per al [matrix] - l’estàndard per a la comunicació oberta i descentralitzada.
|
<string name="store_full_description">"Una aplicació de xat, sota el vostre control i totalment flexible. El Riot us permet comunicar-vos de la manera que preferiu. Fet per al [matrix] - l’estàndard per a la comunicació oberta i descentralitzada.
|
||||||
|
|
||||||
Obteniu un compte gratuït de matrix.org, executeu el vostre servidor propi a https://modular.im, o empreu un altre servidor de Matrix.
|
Obteniu un compte gratuït de matrix.org, executeu el vostre servidor propi a https://modular.im, o empreu un altre servidor de Matrix.
|
||||||
@ -1385,7 +1388,7 @@ Per què triar Riot.im?
|
|||||||
<string name="notification_sync_init">Inicialitzar servei</string>
|
<string name="notification_sync_init">Inicialitzar servei</string>
|
||||||
<string name="ignore">Ignorar</string>
|
<string name="ignore">Ignorar</string>
|
||||||
|
|
||||||
<string name="auth_login_sso">Registrar-se amb Single Sign-on</string>
|
<string name="auth_login_sso">Iniciar sessió amb Single Sign-on</string>
|
||||||
<string name="login_error_unknown_host">Aquesta URL no està disponible , si us plau verifiqueu-la</string>
|
<string name="login_error_unknown_host">Aquesta URL no està disponible , si us plau verifiqueu-la</string>
|
||||||
<string name="login_error_ssl_handshake">El vostre dispositiu està usant una versió obsoleta del protocol de seguretat TLS, vulnerable a atacs. Per a la vostra seguretat no us podreu connectar</string>
|
<string name="login_error_ssl_handshake">El vostre dispositiu està usant una versió obsoleta del protocol de seguretat TLS, vulnerable a atacs. Per a la vostra seguretat no us podreu connectar</string>
|
||||||
<string name="settings_send_message_with_enter">Envieu un missatge amb Enter</string>
|
<string name="settings_send_message_with_enter">Envieu un missatge amb Enter</string>
|
||||||
@ -1403,4 +1406,174 @@ Per què triar Riot.im?
|
|||||||
<string name="autodiscover_invalid_response">Resposta no vàlida en descobrir homeservers</string>
|
<string name="autodiscover_invalid_response">Resposta no vàlida en descobrir homeservers</string>
|
||||||
<string name="autodiscover_well_known_autofill_confirm">Usar Config</string>
|
<string name="autodiscover_well_known_autofill_confirm">Usar Config</string>
|
||||||
|
|
||||||
|
<string name="title_activity_verify_device">Verificar dispositiu</string>
|
||||||
|
|
||||||
|
<string name="action_mark_room_read">Marcar com a llegit</string>
|
||||||
|
<string name="settings_notification_privacy_no_background_sync">Les app <b>no</b> necessita connectar-se al HomeServer en segon pla, hauria de reduir el consum de bateria</string>
|
||||||
|
<string name="settings_integration_manager">Administrador d\'integracions</string>
|
||||||
|
|
||||||
|
<string name="settings_play_shutter_sound">Reproduir el so de disparador</string>
|
||||||
|
|
||||||
|
<string name="encryption_information_unknown_ip">IP desconeguda</string>
|
||||||
|
<plurals name="notification_compat_summary_line_for_room">
|
||||||
|
<item quantity="one">%1$s: 1 missatge</item>
|
||||||
|
<item quantity="other">%1$s: %2$d missatges</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="notification_compat_summary_title">
|
||||||
|
<item quantity="one">%d notificacion</item>
|
||||||
|
<item quantity="other">%d notificacions</item>
|
||||||
|
</plurals>
|
||||||
|
|
||||||
|
<string name="notification_unknown_new_event">Nou esdeveniment</string>
|
||||||
|
<string name="notification_unknown_room_name">Sala</string>
|
||||||
|
<string name="notification_new_messages">Missatges nous</string>
|
||||||
|
<string name="notification_new_invitation">Nova invitació</string>
|
||||||
|
<string name="notification_sender_me">Jo</string>
|
||||||
|
<string name="notification_inline_reply_failed">** Error en enviar - Si us plau obriu la sala</string>
|
||||||
|
|
||||||
|
<string name="error_jitsi_not_supported_on_old_device">Ho sentim, els dispositius amb SO Android inferior a 5.0 no suporten trucades multi-usuari amb Jitsi</string>
|
||||||
|
|
||||||
|
<string name="integration_manager_not_configured">No heu configurat cap administrador d\'integracions.</string>
|
||||||
|
<string name="you_added_a_new_device_with_info">Un nou dispositiu està sol·licitant claus d\'encriptació.
|
||||||
|
\nNom del dispositiu: %1$s
|
||||||
|
\nVist per última vegada: %s$s
|
||||||
|
\nSi no heu iniciat sessió en un altre dispositiu, ignoreu la sol·licitud.</string>
|
||||||
|
<string name="your_unverified_device_requesting_with_info">Un dispositiu no verificat està sol·licitant claus d\'encriptació.
|
||||||
|
\nNom del dispositiu: %1$s
|
||||||
|
\nVist per última vegada: %s$s
|
||||||
|
\nSi no heu iniciat sessió en un altre dispositiu, ignoreu la sol·licitud.</string>
|
||||||
|
|
||||||
|
<string name="start_verification_short_label">Verificar</string>
|
||||||
|
<string name="share_without_verifying_short_label">Compartir</string>
|
||||||
|
<string name="key_share_request">Sol·licitud de compartició de clau</string>
|
||||||
|
<string name="ignore_request_short_label">Ignorar</string>
|
||||||
|
|
||||||
|
<string name="keys_backup_setup_override_backup_prompt_tile">Ja existeix una còpia de seguretat al vostre HomeServer</string>
|
||||||
|
<string name="keys_backup_setup_override_backup_prompt_description">Sembla que ja heu configurat una còpia de seguretat de claus des d\'un altre dispositiu. Voleu reemplaçar-la amb la que esteu creant\?</string>
|
||||||
|
<string name="keys_backup_setup_override_replace">Reemplaçar</string>
|
||||||
|
<string name="keys_backup_setup_override_stop">Aturar</string>
|
||||||
|
|
||||||
|
<string name="keys_backup_settings_checking_backup_state">Comprovant l\'estat de la còpia de seguretat</string>
|
||||||
|
<string name="autodiscover_well_known_autofill_dialog_title">Opcions d\'autocompleció del servidor</string>
|
||||||
|
<string name="autodiscover_well_known_autofill_dialog_message">Riot ha detectat una configuració de servidor personalitzat pel domini del seu identificador d\'usuari \"%1$s\":
|
||||||
|
\n%2$s</string>
|
||||||
|
<string name="invalid_or_expired_credentials">Us heu desconnectat a causa de credencials incorrectes o caducades.</string>
|
||||||
|
|
||||||
|
<string name="sas_verify_title">Verificar comparant una cadena de text curta.</string>
|
||||||
|
<string name="sas_security_advise">Per la màxima seguretat us recomanem fer això en persona o usar un altre medi de comunicació confiable.</string>
|
||||||
|
<string name="sas_verify_start_button_title">Començar la verificació</string>
|
||||||
|
<string name="sas_incoming_request_title">Sol·licitud de verificació entrant</string>
|
||||||
|
<string name="sas_incoming_request_description">Verificar aquest dispositiu per marcar-lo com a confiable. Confiar en dispositius d\'amistats us dona un alleujament addicional quan useu missatges encriptats end-to-end.</string>
|
||||||
|
<string name="sas_incoming_request_description_2">Verificant aquest dispositiu el marcareu com a confiable, i també marcareu el vostre dispositiu com a confiable pel vostre company.</string>
|
||||||
|
|
||||||
|
<string name="sas_emoji_description">Verificar aquest dispositiu confirmant els següents emojis que apareguin a la pantalla del vostre company</string>
|
||||||
|
<string name="sas_decimal_description">Verificar aquest dispositiu confirmant els següents números que sortiran a la pantalla del vostre company</string>
|
||||||
|
|
||||||
|
<string name="sas_incoming_verification_request_dialog">Heu rebut una sol·licitud de verificació entrant.</string>
|
||||||
|
<string name="sas_view_request_action">Veure sol·licitud</string>
|
||||||
|
<string name="sas_waiting_for_partner">Esperant que el vostre company confirmi…</string>
|
||||||
|
|
||||||
|
<string name="sas_verified">Verificat!</string>
|
||||||
|
<string name="sas_verified_successful">Heu verificat aquest dispositiu amb èxit.</string>
|
||||||
|
<string name="sas_verified_successful_description">Els missatges segurs amb aquest usuari estan encriptats end-to-end i no serà possible llegir-los per tercers.</string>
|
||||||
|
<string name="sas_got_it">Entesos</string>
|
||||||
|
|
||||||
|
<string name="sas_verifying_keys">No surt res\? Encara no tots els clients suporten la verificació interactiva. Useu el mètode de verificació antic.</string>
|
||||||
|
<string name="sas_legacy_verification_button_title">Useu el mètode antic de verificació.</string>
|
||||||
|
|
||||||
|
<string name="sas_verification_request_notification_channel_title">Verificació de clau</string>
|
||||||
|
<string name="sas_cancelled_dialog_title">Sol·licitud cancel·lada</string>
|
||||||
|
<string name="sas_cancelled_by_other">L\'altre part ha cancel·lat la verificació.
|
||||||
|
\n%s</string>
|
||||||
|
<string name="sas_cancelled_by_me">S\'ha cancel·lat la verificació.
|
||||||
|
\nMotiu: %s</string>
|
||||||
|
|
||||||
|
<string name="sas_verification_request_notification_channel">Verificació de dispositiu interactiva</string>
|
||||||
|
<string name="sas_incoming_request_notif_title">Sol·licitud de verificació</string>
|
||||||
|
<string name="sas_incoming_request_notif_content">%s vol verificar el vostre dispositiu</string>
|
||||||
|
|
||||||
|
<string name="sas_error_m_user">L\'usuari ha cancel·lat la verificació</string>
|
||||||
|
<string name="sas_error_m_timeout">El marge de temps pel procés de verificació ha expirat</string>
|
||||||
|
<string name="sas_error_m_unknown_transaction">El dispositiu no coneix la transacció</string>
|
||||||
|
<string name="sas_error_m_unknown_method">El dispositiu no pot acceptar un acord de claus amb mètodes hash, MAC o SAS</string>
|
||||||
|
<string name="sas_error_m_mismatched_commitment">El compromís del hash no ha coincidit</string>
|
||||||
|
<string name="sas_error_m_mismatched_sas">El SAS no ha coincidit</string>
|
||||||
|
<string name="sas_error_m_unexpected_message">El dispositiu ha rebut un missatge inesperat</string>
|
||||||
|
<string name="sas_error_m_invalid_message">S\'ha rebut un missatge invàlid</string>
|
||||||
|
<string name="sas_error_m_key_mismatch">La clau no coincideix</string>
|
||||||
|
<string name="sas_error_m_user_error">L\'usuari no coincideix</string>
|
||||||
|
<string name="sas_error_unknown">Error desconegut</string>
|
||||||
|
|
||||||
|
|
||||||
|
<string name="edit">Editar</string>
|
||||||
|
<string name="reply">Respondre</string>
|
||||||
|
|
||||||
|
<string name="global_retry">Tornar-ho a provar</string>
|
||||||
|
<string name="room_list_empty">Unir-se a una sala per començar usant l\'app.</string>
|
||||||
|
<string name="send_you_invite">Se t\'ha enviat una invitació</string>
|
||||||
|
<string name="invited_by">Convidat per %s</string>
|
||||||
|
|
||||||
|
<string name="room_list_catchup_empty_title">Esteu al dia!</string>
|
||||||
|
<string name="room_list_catchup_empty_body">No teniu més missatges sense llegir</string>
|
||||||
|
<string name="room_list_catchup_welcome_title">Benvingut a casa!</string>
|
||||||
|
<string name="room_list_catchup_welcome_body">Posar-se al dia dels missatges sense llegir</string>
|
||||||
|
<string name="room_list_people_empty_title">Converses</string>
|
||||||
|
<string name="room_list_people_empty_body">Els vostres missatges directes es mostraran aquí</string>
|
||||||
|
<string name="room_list_rooms_empty_title">Sales</string>
|
||||||
|
<string name="room_list_rooms_empty_body">Les vostres sales es mostraran aquí</string>
|
||||||
|
|
||||||
|
<string name="title_activity_emoji_reaction_picker">Reaccions</string>
|
||||||
|
<string name="reactions_agree">Confirmar</string>
|
||||||
|
<string name="reactions_like">M\'agrada</string>
|
||||||
|
<string name="message_add_reaction">Afegir reacció</string>
|
||||||
|
<string name="message_view_reaction">Veure reaccions</string>
|
||||||
|
<string name="reactions">Reaccions</string>
|
||||||
|
|
||||||
|
<string name="event_redacted_by_user_reason">Esdeveniment eliminat per l\'usuari</string>
|
||||||
|
<string name="event_redacted_by_admin_reason">Esdeveniment moderat per l\'administrador de la sala</string>
|
||||||
|
<string name="last_edited_info_message">Última edició per %s el %s</string>
|
||||||
|
|
||||||
|
|
||||||
|
<string name="malformed_message">Esdeveniment mal format, no es pot mostrar</string>
|
||||||
|
<string name="create_new_room">Crear sala nova</string>
|
||||||
|
<string name="error_no_network">No hi ha xarxa. Si us plau comproveu la vostra connexió a internet.</string>
|
||||||
|
<string name="action_change">Canviar</string>
|
||||||
|
<string name="change_room_directory_network">Canviar de xarxa</string>
|
||||||
|
<string name="please_wait">Espereu, si us plau…</string>
|
||||||
|
<string name="group_all_communities">Totes les comunitats</string>
|
||||||
|
|
||||||
|
<string name="room_preview_no_preview">Aquesta sala no es pot pre-visualitzar</string>
|
||||||
|
<string name="room_preview_world_readable_room_not_supported_yet">RiotX encara no suporta la pre-visualització de sales llegibles per tothom</string>
|
||||||
|
|
||||||
|
<string name="fab_menu_create_room">Sales</string>
|
||||||
|
<string name="fab_menu_create_chat">Missatges directes</string>
|
||||||
|
|
||||||
|
<string name="create_room_title">Sala nova</string>
|
||||||
|
<string name="create_room_action_create">CREAR</string>
|
||||||
|
<string name="create_room_name_hint">Nom de la sala</string>
|
||||||
|
<string name="create_room_public_title">Públic</string>
|
||||||
|
<string name="create_room_public_description">Qualsevol podrà unir-se a aquesta sala</string>
|
||||||
|
<string name="create_room_directory_title">Directori de sales</string>
|
||||||
|
<string name="create_room_directory_description">Publicar aquesta sala al directori de sales</string>
|
||||||
|
|
||||||
|
<string name="keys_backup_unable_to_get_trust_info">Hi ha hagut un error rebent informació de confança</string>
|
||||||
|
<string name="keys_backup_unable_to_get_keys_backup_data">Hi ha hagut un error rebent dades de la còpia de seguretat de les claus</string>
|
||||||
|
|
||||||
|
<string name="alpha_disclaimer_title">Benvinguts a la beta!</string>
|
||||||
|
<string name="alpha_disclaimer_content_line_1">Mentre RiotX estigui en les primeres etapes de desenvolupament, faltaran algunes funcions i podríeu experimentar alguns errors.</string>
|
||||||
|
<string name="alpha_disclaimer_content_line_2_gplay">L\'última llista de característiques està sempre a %1$s, i si trobeu errors si us plau reporteu informe des de la part superior esquerra del menú d\'Inici, i el resoldrem tan aviat com puguem.</string>
|
||||||
|
<string name="alpha_disclaimer_content_line_2_gplay_colored_part">Descripció de la Play Store</string>
|
||||||
|
<string name="alpha_disclaimer_content_line_2_fdroid">Si trobeu errors si us plau envieu un informe d\'errors des de la part superior esquerra del menú d\'Inici, i el resoldrem tan aviat com puguem.</string>
|
||||||
|
|
||||||
|
<string name="import_e2e_keys_from_file">Importar claus e2e des del fitxer \"%1$s\".</string>
|
||||||
|
|
||||||
|
<string name="settings_sdk_version">Versió de l\'SDK de Matrix</string>
|
||||||
|
<string name="navigate_to_room_when_already_in_the_room">Ja esteu veient aquesta sala!</string>
|
||||||
|
|
||||||
|
<string name="quick_reactions">Reaccions ràpides</string>
|
||||||
|
|
||||||
|
<string name="settings_general_title">General</string>
|
||||||
|
<string name="settings_preferences">Preferències</string>
|
||||||
|
<string name="settings_security_and_privacy">Seguretat i privadesa</string>
|
||||||
|
<string name="settings_expert">Expert</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -210,7 +210,7 @@ Du wurdest auf allen Geräten abgemeldet und wirst keine Push-Benachrichtigungen
|
|||||||
<!-- accounts list Screen -->
|
<!-- accounts list Screen -->
|
||||||
|
|
||||||
<!-- image size selection -->
|
<!-- image size selection -->
|
||||||
<string name="compression_options">"Sende als "</string>
|
<string name="compression_options">Sende als</string>
|
||||||
<string name="compression_opt_list_original">Original</string>
|
<string name="compression_opt_list_original">Original</string>
|
||||||
<string name="compression_opt_list_large">Groß</string>
|
<string name="compression_opt_list_large">Groß</string>
|
||||||
<string name="compression_opt_list_medium">Mittel</string>
|
<string name="compression_opt_list_medium">Mittel</string>
|
||||||
@ -1551,4 +1551,113 @@ Wenn du diese neue Wiederherstellungsmethode nicht eingerichtet hast, kann ein A
|
|||||||
<string name="create_room_directory_title">Raumverzeichnis</string>
|
<string name="create_room_directory_title">Raumverzeichnis</string>
|
||||||
<string name="create_room_directory_description">Veröffentliche diesen Raum ins Raumverzeichnis</string>
|
<string name="create_room_directory_description">Veröffentliche diesen Raum ins Raumverzeichnis</string>
|
||||||
|
|
||||||
|
<string name="settings_integration_manager">Integrationsmanager</string>
|
||||||
|
|
||||||
|
<string name="integration_manager_not_configured">Kein Integrationsmanager konfiguriert.</string>
|
||||||
|
<string name="key_share_request">Schlüsselfreigabe Anfordern</string>
|
||||||
|
<string name="keys_backup_setup_override_backup_prompt_description">Es sieht so aus, als hätten Sie bereits ein Setup-Schlüssel-Backup von einem anderen Gerät. Möchten Sie es durch das ersetzen, das Sie gerade erstellen\?</string>
|
||||||
|
<string name="sas_security_advise">Für maximale Sicherheit empfehlen wir, dies persönlich zu tun oder ein anderes vertrauenswürdiges Kommunikationsmittel zu verwenden.</string>
|
||||||
|
<string name="sas_incoming_request_description">Überprüfen Sie dieses Gerät, um es als vertrauenswürdig zu markieren. Das Vertrauen auf Geräte von Partnern gibt Ihnen zusätzliche Sicherheit, wenn Sie verschlüsselte End-to-End-Nachrichten verwenden.</string>
|
||||||
|
<string name="sas_incoming_request_description_2">Das Verifizieren dieses Benutzers wird seine Geräte als \"vertraut\" markieren und dein Gerät bei ihnen als \"vertraut\" markieren.</string>
|
||||||
|
|
||||||
|
<string name="sas_emoji_description">Verifizieren Sie diesen Benutzer, indem Sie bestätigen, dass folgendes Emoji auf dessen Bildschirm erscheint.</string>
|
||||||
|
<string name="sas_decimal_description">Verifizieren Sie diesen Benutzer, indem Sie bestätigen, dass die folgende Nummer auf dessen Bildschirm erscheint.</string>
|
||||||
|
|
||||||
|
<string name="sas_verifying_keys">Es ist nichts aufgetaucht\? Noch nicht alle Clients unterstützen die interaktive Verifikation. <button>Nutze alte Verifikation</button>.</string>
|
||||||
|
<string name="sas_legacy_verification_button_title">Verwenden Sie die Alte-Überprüfung</string>
|
||||||
|
|
||||||
|
<string name="sas_error_m_unknown_transaction">Das Gerät kennt diese Transaktion nicht</string>
|
||||||
|
<string name="sas_error_m_mismatched_commitment">Die Hash-Verpflichtung stimmte nicht überein</string>
|
||||||
|
<string name="sas_error_m_mismatched_sas">Die SAS stimmte nicht überein</string>
|
||||||
|
<string name="sas_error_m_key_mismatch">Wiederherstellungsschlüssel passt nicht</string>
|
||||||
|
<string name="sas_error_m_user_error">Der Benutzer Wiederherstellungsschlüssel passt nicht</string>
|
||||||
|
<string name="room_list_catchup_welcome_body">Informieren Sie sich hier über ungelesene Nachrichten</string>
|
||||||
|
<string name="room_list_people_empty_body">Ihre direkte Konversation wird hier angezeigt</string>
|
||||||
|
<string name="malformed_message">Fehlerhaftes Ereignis, kann nicht angezeigt werden</string>
|
||||||
|
<string name="keys_backup_unable_to_get_trust_info">Beim Abrufen der Vertrauensinformationen ist ein Fehler aufgetreten</string>
|
||||||
|
<string name="keys_backup_unable_to_get_keys_backup_data">Beim Abrufen der Schlüsselsicherungsdaten ist ein Fehler aufgetreten</string>
|
||||||
|
|
||||||
|
<string name="alpha_disclaimer_title">Willkommen in der Beta!</string>
|
||||||
|
<string name="alpha_disclaimer_content_line_1">Während sich RiotX in der frühen Entwicklung befindet, fehlen möglicherweise einige Funktionen und es können Fehler auftreten.</string>
|
||||||
|
<string name="alpha_disclaimer_content_line_2_gplay_colored_part">Play Store Beschreibung</string>
|
||||||
|
<string name="settings_sdk_version">Matrix SDK Version</string>
|
||||||
|
<string name="settings_other_third_party_notices">Sonstige Hinweise Dritter</string>
|
||||||
|
<string name="navigate_to_room_when_already_in_the_room">Sie sehen diesen Raum bereits!</string>
|
||||||
|
|
||||||
|
<string name="quick_reactions">Schnelle Reaktionen</string>
|
||||||
|
|
||||||
|
<string name="settings_general_title">Allgemein</string>
|
||||||
|
<string name="settings_preferences">Einstellungen</string>
|
||||||
|
<string name="settings_security_and_privacy">Sicherheit & Privatsphäre</string>
|
||||||
|
<string name="settings_expert">Experte</string>
|
||||||
|
<string name="settings_push_rules">Push-Regeln</string>
|
||||||
|
<string name="settings_push_rules_no_rules">Keine Push-Regeln definiert</string>
|
||||||
|
<string name="settings_push_gateway_no_pushers">Keine registrierten Push-Gateways</string>
|
||||||
|
|
||||||
|
<string name="preference_voice_and_video">Sprache & Video</string>
|
||||||
|
<string name="preference_root_help_about">Hilfe & Über</string>
|
||||||
|
|
||||||
|
|
||||||
|
<string name="settings_troubleshoot_test_token_registration_quick_fix">Token registrieren</string>
|
||||||
|
|
||||||
|
<string name="send_suggestion">Mache einen Vorschlag</string>
|
||||||
|
<string name="send_suggestion_content">Bitte schreiben Sie Ihren Vorschlag unten.</string>
|
||||||
|
<string name="send_suggestion_report_placeholder">Beschreiben Sie hier Ihren Vorschlag</string>
|
||||||
|
<string name="settings_labs_show_hidden_events_in_timeline">Versteckte Ereignisse in der Zeitleiste anzeigen</string>
|
||||||
|
|
||||||
|
<string name="bottom_action_people_x">Direkte Nachrichten</string>
|
||||||
|
|
||||||
|
<string name="send_file_step_idle">Warten…</string>
|
||||||
|
<string name="send_file_step_encrypting_thumbnail">Miniaturbild wird verschlüsselt…</string>
|
||||||
|
<string name="send_file_step_encrypting_file">Datei wird verschlüsselt…</string>
|
||||||
|
<string name="edited_suffix">(bearbeitet)</string>
|
||||||
|
|
||||||
|
<string name="message_edits">Nachrichtenbearbeitung</string>
|
||||||
|
<string name="no_message_edits_found">Keine Änderungen gefunden</string>
|
||||||
|
|
||||||
|
<string name="room_filtering_filter_hint">Gespräche filtern…</string>
|
||||||
|
<string name="room_filtering_footer_create_new_direct_message">Senden Sie eine neue Direktnachricht</string>
|
||||||
|
<string name="room_filtering_footer_open_room_directory">Das Raumverzeichnis anzeigen</string>
|
||||||
|
|
||||||
|
<string name="link_copied_to_clipboard">Link in die Zwischenablage kopiert</string>
|
||||||
|
|
||||||
|
<string name="add_by_matrix_id">Nach Matrix-ID hinzufügen</string>
|
||||||
|
<string name="creating_direct_room">Raum erstellen…</string>
|
||||||
|
<string name="message_view_edit_history">Bearbeitungsverlauf anzeigen</string>
|
||||||
|
|
||||||
|
<string name="sas_cancelled_by_other">Die andere Partei hat die Überprüfung abgebrochen.
|
||||||
|
\n%s</string>
|
||||||
|
<string name="sas_error_m_unknown_method">Das Gerät kann sich nicht auf eine Schlüsselvereinbarung, eine Hash-, eine MAC- oder eine SAS-Methode einigen</string>
|
||||||
|
<string name="alpha_disclaimer_content_line_2_gplay">Die neueste Featureliste befindet sich immer in %1$s. Wenn Sie Fehler finden, senden Sie uns bitte einen Bericht im Menü oben links von \"Startseite\". Wir werden den Fehler so schnell wie möglich beheben.</string>
|
||||||
|
<string name="alpha_disclaimer_content_line_2_fdroid">Wenn Sie Fehler finden, senden Sie uns bitte einen Bericht im Menü oben links von \"Startseite\". Wir werden diese so schnell wie möglich beheben.</string>
|
||||||
|
|
||||||
|
<string name="import_e2e_keys_from_file">Importieren Sie e2e-Schlüssel aus der Datei \"%1$s\".</string>
|
||||||
|
|
||||||
|
<string name="send_suggestion_sent">Vielen Dank, der Vorschlag wurde erfolgreich gesendet</string>
|
||||||
|
<string name="send_suggestion_failed">Der Vorschlag konnte nicht gesendet werden (%s)</string>
|
||||||
|
|
||||||
|
<string name="store_riotx_title">RiotX - Matrix Client der nächsten Generation</string>
|
||||||
|
<string name="store_riotx_short_description">Ein schnellerer und leichterer Client für Matrix mit den neuesten Android-Frameworks</string>
|
||||||
|
<string name="send_file_step_sending_thumbnail">Miniaturbild wird gesendet (%1$s / %2$s)</string>
|
||||||
|
<string name="send_file_step_sending_file">Datei wird gesendet (%1$s / %2$s)</string>
|
||||||
|
|
||||||
|
<string name="downloading_file">Datei %1$s wird heruntergeladen …</string>
|
||||||
|
<string name="downloaded_file">Die Datei %1$s wurde heruntergeladen!</string>
|
||||||
|
|
||||||
|
<string name="riotx_no_registration_notice">%1$s , um ein Konto zu erstellen.</string>
|
||||||
|
<string name="riotx_no_registration_notice_colored_part">Benutze die alte App</string>
|
||||||
|
|
||||||
|
|
||||||
|
<string name="room_filtering_footer_title">Können Sie nicht finden, wonach Sie suchen\?</string>
|
||||||
|
<string name="room_filtering_footer_create_new_room">Erstelle einen neuen Raum</string>
|
||||||
|
<string name="room_directory_search_hint">Name oder ID (#Beispiel: matrix.org)</string>
|
||||||
|
|
||||||
|
<string name="labs_swipe_to_reply_in_timeline">Aktivieren Sie das Streichen, um in der Zeitleiste zu antworten</string>
|
||||||
|
|
||||||
|
<string name="direct_room_no_known_users">Kein Ergebnis gefunden. Verwenden Sie Nach Matrix-ID hinzufügen, um auf dem Server zu suchen.</string>
|
||||||
|
<string name="direct_room_start_search">Beginnen Sie mit der Eingabe, um Ergebnisse zu erhalten</string>
|
||||||
|
<string name="direct_room_filter_hint">Filtern nach Benutzername oder ID…</string>
|
||||||
|
|
||||||
|
<string name="joining_room">Raum betreten…</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -331,7 +331,7 @@ Ziur zaude?</string>
|
|||||||
<string name="room_unsent_messages_notification">Bidali gabeko mezuak daude. %1$s edo %2$s orain?</string>
|
<string name="room_unsent_messages_notification">Bidali gabeko mezuak daude. %1$s edo %2$s orain?</string>
|
||||||
<string name="room_unknown_devices_messages_notification">Mezuak ez dira bidali gailu ezezagunak daudelako. %1$s edo %2$s orain?</string>
|
<string name="room_unknown_devices_messages_notification">Mezuak ez dira bidali gailu ezezagunak daudelako. %1$s edo %2$s orain?</string>
|
||||||
<string name="room_prompt_resend">Birbidali dena</string>
|
<string name="room_prompt_resend">Birbidali dena</string>
|
||||||
<string name="room_prompt_cancel">utzi dena</string>
|
<string name="room_prompt_cancel">Utzi dena</string>
|
||||||
<string name="room_resend_unsent_messages">Birbidali bidali gabeko mezuak</string>
|
<string name="room_resend_unsent_messages">Birbidali bidali gabeko mezuak</string>
|
||||||
<string name="room_delete_unsent_messages">Ezabatu bidali gabeko mezuak</string>
|
<string name="room_delete_unsent_messages">Ezabatu bidali gabeko mezuak</string>
|
||||||
<string name="room_message_file_not_found">Ez da fitxategia aurkitu</string>
|
<string name="room_message_file_not_found">Ez da fitxategia aurkitu</string>
|
||||||
@ -1607,4 +1607,17 @@ Abisua: Fitxategi hau ezabatu daiteke aplikazioa desinstalatzen bada.</string>
|
|||||||
|
|
||||||
<string name="link_copied_to_clipboard">Esteka arbelera kopiatu da</string>
|
<string name="link_copied_to_clipboard">Esteka arbelera kopiatu da</string>
|
||||||
|
|
||||||
|
<string name="settings_integration_manager">Integrazio kudeatzailea</string>
|
||||||
|
|
||||||
|
<string name="integration_manager_not_configured">Ez da integrazio kudeatzailerik konfiguratu.</string>
|
||||||
|
<string name="add_by_matrix_id">Gehitu matrix ID bidez</string>
|
||||||
|
<string name="creating_direct_room">Gela sortzen…</string>
|
||||||
|
<string name="direct_room_no_known_users">Ez da emaitzarik aurkitu, erabili gehitu matrix ID bidez zerbitzarian bilatzeko.</string>
|
||||||
|
<string name="direct_room_start_search">Hasi idazten emaitzak jasotzeko</string>
|
||||||
|
<string name="direct_room_filter_hint">Iragazi erabiltzaile-izena edo ID-a erabiliz…</string>
|
||||||
|
|
||||||
|
<string name="joining_room">Gelara elkartzen…</string>
|
||||||
|
|
||||||
|
<string name="message_view_edit_history">Ikusi edizioen historiala</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -111,7 +111,7 @@
|
|||||||
<string name="send_bug_report_sent">Virheraportti lähetettiin</string>
|
<string name="send_bug_report_sent">Virheraportti lähetettiin</string>
|
||||||
<string name="send_bug_report_failed">Virheraporttia ei voitu lähettää (%s)</string>
|
<string name="send_bug_report_failed">Virheraporttia ei voitu lähettää (%s)</string>
|
||||||
<string name="send_bug_report_progress">Lähetetään (%s%%)</string>
|
<string name="send_bug_report_progress">Lähetetään (%s%%)</string>
|
||||||
<string name="send_bug_report_app_crashed">Sovellus kaatui viime kerralla. Haluaisitko tehdä kaatumisesta virheilmoituksen\?</string>
|
<string name="send_bug_report_app_crashed">Sovellus kaatui viime kerralla. Haluatko tehdä kaatumisesta virheilmoituksen\?</string>
|
||||||
|
|
||||||
<string name="send_files_in">Lähetä</string>
|
<string name="send_files_in">Lähetä</string>
|
||||||
<string name="read_receipt">Luettu</string>
|
<string name="read_receipt">Luettu</string>
|
||||||
@ -1533,4 +1533,83 @@ Jotta et menetä mitään, automaattiset päivitykset kannattaa pitää käytös
|
|||||||
|
|
||||||
<string name="settings_preferences">Asetukset</string>
|
<string name="settings_preferences">Asetukset</string>
|
||||||
<string name="settings_security_and_privacy">Tietoturva ja yksityisyys</string>
|
<string name="settings_security_and_privacy">Tietoturva ja yksityisyys</string>
|
||||||
|
<string name="room_list_catchup_empty_title">Olet ajan tasalla!</string>
|
||||||
|
<string name="last_edited_info_message">Viimeksi muokannut %s %s</string>
|
||||||
|
|
||||||
|
|
||||||
|
<string name="change_room_directory_network">Vaihda verkkoa</string>
|
||||||
|
<string name="navigate_to_room_when_already_in_the_room">Katselet jo tätä huonetta!</string>
|
||||||
|
|
||||||
|
<string name="settings_general_title">Yleiset</string>
|
||||||
|
<string name="preference_voice_and_video">Ääni ja video</string>
|
||||||
|
<string name="preference_root_help_about">Ohje ja tietoa</string>
|
||||||
|
|
||||||
|
|
||||||
|
<string name="send_suggestion">Tee ehdotus</string>
|
||||||
|
<string name="send_suggestion_content">Kirjoita ehdotuksesi alle.</string>
|
||||||
|
<string name="send_suggestion_report_placeholder">Kuvaile ehdotuksesi tässä</string>
|
||||||
|
<string name="send_suggestion_sent">Kiitos, ehdotus on lähetetty</string>
|
||||||
|
<string name="send_suggestion_failed">Ehdotuksen lähettäminen epäonnistui (%s)</string>
|
||||||
|
|
||||||
|
<string name="settings_labs_show_hidden_events_in_timeline">Näytä piilotetut tapahtumat aikajanalla</string>
|
||||||
|
|
||||||
|
<string name="store_riotx_title">RiotX - seuraavan sukupolven Matrix-asiakasohjelma</string>
|
||||||
|
<string name="store_riotx_short_description">Nopeampi ja kevyempi Matrix-asiakasohjelma</string>
|
||||||
|
<string name="bottom_action_people_x">Yksityisviestit</string>
|
||||||
|
|
||||||
|
<string name="send_file_step_idle">Odotetaan…</string>
|
||||||
|
<string name="send_file_step_encrypting_file">Salataan tiedostoa…</string>
|
||||||
|
<string name="send_file_step_sending_file">Lähetetään tiedostoa (%1$s / %2$s)</string>
|
||||||
|
|
||||||
|
<string name="downloading_file">Ladataan tiedostoa %1$s…</string>
|
||||||
|
<string name="downloaded_file">Tiedosto %1$s ladattu!</string>
|
||||||
|
|
||||||
|
<string name="edited_suffix">(muokattu)</string>
|
||||||
|
|
||||||
|
<string name="riotx_no_registration_notice_colored_part">Käytä vanhaa sovellusta</string>
|
||||||
|
|
||||||
|
|
||||||
|
<string name="no_message_edits_found">Muokkauksia ei löytynyt</string>
|
||||||
|
|
||||||
|
<string name="room_filtering_filter_hint">Suodata keskusteluja…</string>
|
||||||
|
<string name="room_filtering_footer_title">Etkö löydä, mitä etsit\?</string>
|
||||||
|
<string name="room_filtering_footer_create_new_room">Luo uusi huone</string>
|
||||||
|
<string name="room_filtering_footer_create_new_direct_message">Lähetä uusi yksityisviesti</string>
|
||||||
|
<string name="room_filtering_footer_open_room_directory">Näytä huoneluettelo</string>
|
||||||
|
|
||||||
|
<string name="link_copied_to_clipboard">Linkki kopioitu leikepöydälle</string>
|
||||||
|
|
||||||
|
<string name="creating_direct_room">Luodaan huonetta…</string>
|
||||||
|
<string name="direct_room_start_search">Näet tuloksia kirjoittamalla jotain</string>
|
||||||
|
<string name="joining_room">Liitytään huoneeseen…</string>
|
||||||
|
|
||||||
|
<string name="message_view_edit_history">Näytä muokkaushistoria</string>
|
||||||
|
|
||||||
|
<string name="title_activity_verify_device">Vahvista laite</string>
|
||||||
|
|
||||||
|
<string name="start_verification_short_label">Vahvista</string>
|
||||||
|
<string name="key_share_request">Avaimen jakopyyntö</string>
|
||||||
|
<string name="sas_verify_start_button_title">Aloita vahvistaminen</string>
|
||||||
|
<string name="sas_incoming_request_title">Saapuva vahvistuspyyntö</string>
|
||||||
|
<string name="sas_incoming_verification_request_dialog">Vastaanotit saapuvan vahvistuspyynnön.</string>
|
||||||
|
<string name="sas_verified">Vahvistettu!</string>
|
||||||
|
<string name="sas_verified_successful">Vahvistit tämän laitteen onnistuneesti.</string>
|
||||||
|
<string name="sas_verification_request_notification_channel_title">Avaimen vahvistus</string>
|
||||||
|
<string name="sas_cancelled_by_other">Toinen osapuoli perui vahvistuksen.
|
||||||
|
\n%s</string>
|
||||||
|
<string name="sas_cancelled_by_me">Vahvistus on peruttu.
|
||||||
|
\nSyy: %s</string>
|
||||||
|
|
||||||
|
<string name="sas_verification_request_notification_channel">Vuorovaikutteinen laitteen vahvistus</string>
|
||||||
|
<string name="sas_incoming_request_notif_title">Vahvistuspyyntö</string>
|
||||||
|
<string name="sas_incoming_request_notif_content">%s haluaa vahvistaa laitteesi</string>
|
||||||
|
|
||||||
|
<string name="sas_error_m_user">Käyttäjä perui vahvistuksen</string>
|
||||||
|
<string name="sas_error_m_timeout">Vahvistustoimenpide aikakatkaistiin</string>
|
||||||
|
<string name="create_room_directory_title">Huoneluettelo</string>
|
||||||
|
<string name="create_room_directory_description">Julkaise tämä huone huoneluettelossa</string>
|
||||||
|
|
||||||
|
<string name="alpha_disclaimer_content_line_2_gplay_colored_part">Play Storen kuvaus</string>
|
||||||
|
<string name="settings_push_rules">Push-säännöt</string>
|
||||||
|
<string name="riotx_no_registration_notice">%1$s luodaksesi tilin.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -219,7 +219,7 @@
|
|||||||
<string name="room_message_placeholder_encrypted">Envoyer un message chiffré…</string>
|
<string name="room_message_placeholder_encrypted">Envoyer un message chiffré…</string>
|
||||||
<string name="room_message_placeholder_not_encrypted">Envoyer un message (non chiffré)…</string>
|
<string name="room_message_placeholder_not_encrypted">Envoyer un message (non chiffré)…</string>
|
||||||
<string name="room_prompt_resend">Tout renvoyer</string>
|
<string name="room_prompt_resend">Tout renvoyer</string>
|
||||||
<string name="room_prompt_cancel">tout annuler</string>
|
<string name="room_prompt_cancel">Tout annuler</string>
|
||||||
<string name="room_resend_unsent_messages">Renvoyer les messages non envoyés</string>
|
<string name="room_resend_unsent_messages">Renvoyer les messages non envoyés</string>
|
||||||
<string name="room_delete_unsent_messages">Supprimer les messages non envoyés</string>
|
<string name="room_delete_unsent_messages">Supprimer les messages non envoyés</string>
|
||||||
<string name="room_message_file_not_found">Fichier non trouvé</string>
|
<string name="room_message_file_not_found">Fichier non trouvé</string>
|
||||||
@ -1612,4 +1612,17 @@ Si vous n’avez pas configuré de nouvelle méthode de récupération, un attaq
|
|||||||
|
|
||||||
<string name="link_copied_to_clipboard">Lien copié dans le presse-papiers</string>
|
<string name="link_copied_to_clipboard">Lien copié dans le presse-papiers</string>
|
||||||
|
|
||||||
|
<string name="settings_integration_manager">Gestionnaire d’intégrations</string>
|
||||||
|
|
||||||
|
<string name="integration_manager_not_configured">Aucun gestionnaire d’intégrations n’est configuré.</string>
|
||||||
|
<string name="add_by_matrix_id">Ajouter par identifiant matrix</string>
|
||||||
|
<string name="creating_direct_room">Création du salon…</string>
|
||||||
|
<string name="direct_room_no_known_users">Aucun résultat trouvé, utilisez Ajouter par identifiant matrix pour chercher sur le serveur.</string>
|
||||||
|
<string name="direct_room_start_search">Entrez du texte pour avoir des résultats</string>
|
||||||
|
<string name="direct_room_filter_hint">Filtrer par nom d’utilisateur ou identifiant…</string>
|
||||||
|
|
||||||
|
<string name="joining_room">En train de rejoindre le salon…</string>
|
||||||
|
|
||||||
|
<string name="message_view_edit_history">Voir l’historique des éditions</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -329,7 +329,7 @@ Kérlek engedélyezd a hozzáférést a következő felugró ablakban, hogy tudj
|
|||||||
<string name="room_unsent_messages_notification">Üzenetek nem kerültek elküldésre. %1$s vagy %2$s most?</string>
|
<string name="room_unsent_messages_notification">Üzenetek nem kerültek elküldésre. %1$s vagy %2$s most?</string>
|
||||||
<string name="room_unknown_devices_messages_notification">Üzenetek nem kerültek elküldésre mert egy ismeretlen eszköz van jelen. %1$s vagy %2$s most?</string>
|
<string name="room_unknown_devices_messages_notification">Üzenetek nem kerültek elküldésre mert egy ismeretlen eszköz van jelen. %1$s vagy %2$s most?</string>
|
||||||
<string name="room_prompt_resend">Összes újraküldése</string>
|
<string name="room_prompt_resend">Összes újraküldése</string>
|
||||||
<string name="room_prompt_cancel">Összes megszüntetése</string>
|
<string name="room_prompt_cancel">Összes elvetése</string>
|
||||||
<string name="room_resend_unsent_messages">El nem küldött üzenetek újraküldése</string>
|
<string name="room_resend_unsent_messages">El nem küldött üzenetek újraküldése</string>
|
||||||
<string name="room_delete_unsent_messages">El nem küldött üzenetek törlése</string>
|
<string name="room_delete_unsent_messages">El nem küldött üzenetek törlése</string>
|
||||||
<string name="room_message_file_not_found">Fájl nem található</string>
|
<string name="room_message_file_not_found">Fájl nem található</string>
|
||||||
@ -1611,4 +1611,17 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró
|
|||||||
|
|
||||||
<string name="link_copied_to_clipboard">Hivatkozás a vágólapra másolva</string>
|
<string name="link_copied_to_clipboard">Hivatkozás a vágólapra másolva</string>
|
||||||
|
|
||||||
|
<string name="settings_integration_manager">Integrációs Menedzser</string>
|
||||||
|
|
||||||
|
<string name="integration_manager_not_configured">Integrációs Menedzser nincs beállítva.</string>
|
||||||
|
<string name="add_by_matrix_id">Hozzáadás matrix ID-vel</string>
|
||||||
|
<string name="creating_direct_room">Szoba létrehozása…</string>
|
||||||
|
<string name="direct_room_no_known_users">Nincs találat, használd a „Hozzáadás matrix ID-vel”-t a szerveren való kereséshez.</string>
|
||||||
|
<string name="direct_room_start_search">A találatokhoz kezdj gépelni</string>
|
||||||
|
<string name="direct_room_filter_hint">Szűrés felhasználói névre vagy azonosítóra…</string>
|
||||||
|
|
||||||
|
<string name="joining_room">Szobába belépés…</string>
|
||||||
|
|
||||||
|
<string name="message_view_edit_history">Szerkesztési napló megtekintése</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -362,7 +362,7 @@ Sicuro di procedere?</string>
|
|||||||
<string name="room_unsent_messages_notification">Messaggi non inviati. %1$s o %2$s ora?</string>
|
<string name="room_unsent_messages_notification">Messaggi non inviati. %1$s o %2$s ora?</string>
|
||||||
<string name="room_unknown_devices_messages_notification">Messaggi non inviati a causa di dispositivi sconosciuti qui presenti. %1$s o %2$s ora?</string>
|
<string name="room_unknown_devices_messages_notification">Messaggi non inviati a causa di dispositivi sconosciuti qui presenti. %1$s o %2$s ora?</string>
|
||||||
<string name="room_prompt_resend">Rispedisci tutto</string>
|
<string name="room_prompt_resend">Rispedisci tutto</string>
|
||||||
<string name="room_prompt_cancel">annulla tutto</string>
|
<string name="room_prompt_cancel">Annulla tutto</string>
|
||||||
<string name="room_resend_unsent_messages">Rinvia messaggi non spediti</string>
|
<string name="room_resend_unsent_messages">Rinvia messaggi non spediti</string>
|
||||||
<string name="room_delete_unsent_messages">Elimina messaggi non spediti</string>
|
<string name="room_delete_unsent_messages">Elimina messaggi non spediti</string>
|
||||||
<string name="room_message_file_not_found">File non trovato</string>
|
<string name="room_message_file_not_found">File non trovato</string>
|
||||||
@ -1656,4 +1656,17 @@ Per essere certo di non perdere nulla, mantieni gli aggiornamenti attivi."</stri
|
|||||||
|
|
||||||
<string name="link_copied_to_clipboard">Collegamento copiato negli appunti</string>
|
<string name="link_copied_to_clipboard">Collegamento copiato negli appunti</string>
|
||||||
|
|
||||||
|
<string name="settings_integration_manager">Gestore dell\'integrazione</string>
|
||||||
|
|
||||||
|
<string name="integration_manager_not_configured">Nessun gestore integrazione configurato.</string>
|
||||||
|
<string name="add_by_matrix_id">Aggiungi per ID matrix</string>
|
||||||
|
<string name="creating_direct_room">Creare una stanza …</string>
|
||||||
|
<string name="direct_room_no_known_users">Nessun risultato trovato, usa \"Aggiungi per ID matrix\" per cercare sul server.</string>
|
||||||
|
<string name="direct_room_start_search">Inizia a digitare per ottenere risultati</string>
|
||||||
|
<string name="direct_room_filter_hint">Filtra per nome utente o ID …</string>
|
||||||
|
|
||||||
|
<string name="joining_room">Sto entrando nella stanza …</string>
|
||||||
|
|
||||||
|
<string name="message_view_edit_history">Visualizza Modifica cronologia</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -155,7 +155,7 @@
|
|||||||
<string name="auth_repeat_password_placeholder">Wachtwoord herhalen</string>
|
<string name="auth_repeat_password_placeholder">Wachtwoord herhalen</string>
|
||||||
<string name="auth_repeat_new_password_placeholder">Nieuw wachtwoord bevestigen</string>
|
<string name="auth_repeat_new_password_placeholder">Nieuw wachtwoord bevestigen</string>
|
||||||
<string name="auth_invalid_login_param">Verkeerde gebruikersnaam en/of wachtwoord</string>
|
<string name="auth_invalid_login_param">Verkeerde gebruikersnaam en/of wachtwoord</string>
|
||||||
<string name="auth_invalid_user_name">Gebruikersnamen mogen alleen letters, cijfers, punten en afbreek- en lage streepjes bevatten</string>
|
<string name="auth_invalid_user_name">Gebruikersnamen mogen alleen letters, cijfers, punten, koppeltekens en underscores bevatten</string>
|
||||||
<string name="auth_invalid_password">Wachtwoord te kort (min 6)</string>
|
<string name="auth_invalid_password">Wachtwoord te kort (min 6)</string>
|
||||||
<string name="auth_missing_password">Wachtwoord ontbreekt</string>
|
<string name="auth_missing_password">Wachtwoord ontbreekt</string>
|
||||||
<string name="auth_invalid_email">Dit is geen geldig e-mailadres</string>
|
<string name="auth_invalid_email">Dit is geen geldig e-mailadres</string>
|
||||||
@ -292,7 +292,7 @@
|
|||||||
<string name="reject">Afwijzen</string>
|
<string name="reject">Afwijzen</string>
|
||||||
|
|
||||||
<!-- Room -->
|
<!-- Room -->
|
||||||
<string name="room_jump_to_first_unread">Spring naar het eerste ongelezen bericht.</string>
|
<string name="room_jump_to_first_unread">Ga naar het eerste ongelezen bericht.</string>
|
||||||
|
|
||||||
<!-- Room Preview -->
|
<!-- Room Preview -->
|
||||||
<string name="room_preview_invitation_format">%s heeft u uitgenodigd in dit gesprek</string>
|
<string name="room_preview_invitation_format">%s heeft u uitgenodigd in dit gesprek</string>
|
||||||
@ -484,7 +484,7 @@
|
|||||||
<string name="settings_cryptography">Cryptografie</string>
|
<string name="settings_cryptography">Cryptografie</string>
|
||||||
<string name="settings_notifications_targets">Meldingsdoelen</string>
|
<string name="settings_notifications_targets">Meldingsdoelen</string>
|
||||||
<string name="settings_contact">Lokale contacten</string>
|
<string name="settings_contact">Lokale contacten</string>
|
||||||
<string name="settings_contacts_app_permission">Contacten-toestemming</string>
|
<string name="settings_contacts_app_permission">Toegang geven tot lokale contacten</string>
|
||||||
<string name="settings_contacts_phonebook_country">Land voor telefoonboek</string>
|
<string name="settings_contacts_phonebook_country">Land voor telefoonboek</string>
|
||||||
<string name="settings_home_display">Startscherm</string>
|
<string name="settings_home_display">Startscherm</string>
|
||||||
<string name="settings_pin_missed_notifications">Gesprekken met gemiste meldingen vastprikken</string>
|
<string name="settings_pin_missed_notifications">Gesprekken met gemiste meldingen vastprikken</string>
|
||||||
@ -689,7 +689,7 @@
|
|||||||
<string name="directory_server_native_rooms">Alle lokale gesprekken op %s</string>
|
<string name="directory_server_native_rooms">Alle lokale gesprekken op %s</string>
|
||||||
|
|
||||||
<!-- historical -->
|
<!-- historical -->
|
||||||
<string name="historical_placeholder">Zoeken naar historische</string>
|
<string name="historical_placeholder">Zoeken in de historiek</string>
|
||||||
<string name="offline">Offline</string>
|
<string name="offline">Offline</string>
|
||||||
|
|
||||||
<string name="user_directory_header">Gebruikerscatalogus</string>
|
<string name="user_directory_header">Gebruikerscatalogus</string>
|
||||||
@ -903,8 +903,8 @@
|
|||||||
<string name="avatar">Avatar</string>
|
<string name="avatar">Avatar</string>
|
||||||
|
|
||||||
<plurals name="notification_unread_notified_messages">
|
<plurals name="notification_unread_notified_messages">
|
||||||
<item quantity="one">1 ongelezen bericht waarin u vermeld staat</item>
|
<item quantity="one">1 ongelezen bericht waarin u vermeld bent</item>
|
||||||
<item quantity="other">%d ongelezen berichten waarin u vermeld staat</item>
|
<item quantity="other">%d ongelezen berichten waarin u vermeld bent</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="notice_avatar">Vermeldingsavatar</string>
|
<string name="notice_avatar">Vermeldingsavatar</string>
|
||||||
<string name="title_activity_choose_sticker">Verstuur een sticker</string>
|
<string name="title_activity_choose_sticker">Verstuur een sticker</string>
|
||||||
@ -1208,7 +1208,7 @@
|
|||||||
<string name="settings_troubleshoot_test_battery_failed">Als een gebruiker een apparaat los van de oplader een tijd laat stilliggen, met het scherm uitgeschakeld, gaat het apparaat in slaapmodus. Dit verhindert apps de toegang tot het netwerk, en stelt hun taken, synchronisaties en standaardalarmen uit.</string>
|
<string name="settings_troubleshoot_test_battery_failed">Als een gebruiker een apparaat los van de oplader een tijd laat stilliggen, met het scherm uitgeschakeld, gaat het apparaat in slaapmodus. Dit verhindert apps de toegang tot het netwerk, en stelt hun taken, synchronisaties en standaardalarmen uit.</string>
|
||||||
<string name="settings_troubleshoot_test_battery_quickfix">Optimalisatie negeren</string>
|
<string name="settings_troubleshoot_test_battery_quickfix">Optimalisatie negeren</string>
|
||||||
|
|
||||||
<string name="settings_notification_privacy_no_background_sync">De app heeft <b>geen</b> verbinding met de homeserver nodig in de achtergrond, dit zou accuverbruik moeten verlagen</string>
|
<string name="settings_notification_privacy_no_background_sync">De app heeft <b>geen</b> verbinding met de homeserver nodig in de achtergrond, dit zou het gebruik van de batterij moeten verlagen</string>
|
||||||
<string name="settings_noisy_notifications_preferences">Lawaaiierige meldingen configureren</string>
|
<string name="settings_noisy_notifications_preferences">Lawaaiierige meldingen configureren</string>
|
||||||
<string name="settings_call_notifications_preferences">Oproepmeldingen configureren</string>
|
<string name="settings_call_notifications_preferences">Oproepmeldingen configureren</string>
|
||||||
<string name="settings_silent_notifications_preferences">Stille meldingen configureren</string>
|
<string name="settings_silent_notifications_preferences">Stille meldingen configureren</string>
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
<string name="ongoing_conference_call">Przychodzące połączenie grupowe.
|
<string name="ongoing_conference_call">Przychodzące połączenie grupowe.
|
||||||
\nDołącz z %1$s lub %2$s</string>
|
\nDołącz z %1$s lub %2$s</string>
|
||||||
<string name="ongoing_conference_call_voice">Głos</string>
|
<string name="ongoing_conference_call_voice">Głos</string>
|
||||||
<string name="ongoing_conference_call_video">kamerą</string>
|
<string name="ongoing_conference_call_video">Wideo</string>
|
||||||
<string name="cannot_start_call">Nie można rozpocząć połączenia, spróbuj ponownie później</string>
|
<string name="cannot_start_call">Nie można rozpocząć połączenia, spróbuj ponownie później</string>
|
||||||
<string name="missing_permissions_warning">Ze względu na brak pewnych uprawnień, niektóre funkcje mogą nie działać…</string>
|
<string name="missing_permissions_warning">Ze względu na brak pewnych uprawnień, niektóre funkcje mogą nie działać…</string>
|
||||||
<string name="missing_permissions_to_start_conf_call">Musisz być uprawniony, aby rozpocząć połączenie grupowe</string>
|
<string name="missing_permissions_to_start_conf_call">Musisz być uprawniony, aby rozpocząć połączenie grupowe</string>
|
||||||
@ -287,7 +287,7 @@ Przyznaj dostęp w następnym oknie.</string>
|
|||||||
<string name="room_message_placeholder_not_encrypted">Wyślij wiadomość (niezaszyfrowaną)…</string>
|
<string name="room_message_placeholder_not_encrypted">Wyślij wiadomość (niezaszyfrowaną)…</string>
|
||||||
<string name="room_offline_notification">Utracono połączenie z serwerem.</string>
|
<string name="room_offline_notification">Utracono połączenie z serwerem.</string>
|
||||||
<string name="room_prompt_resend">Wyślij ponownie wszystko</string>
|
<string name="room_prompt_resend">Wyślij ponownie wszystko</string>
|
||||||
<string name="room_prompt_cancel">anuluj wszystko</string>
|
<string name="room_prompt_cancel">Anuluj wszystko</string>
|
||||||
<string name="room_resend_unsent_messages">Wyślij niewysłane wiadomości ponownie</string>
|
<string name="room_resend_unsent_messages">Wyślij niewysłane wiadomości ponownie</string>
|
||||||
<string name="room_delete_unsent_messages">Usuń niewysłane wiadomości</string>
|
<string name="room_delete_unsent_messages">Usuń niewysłane wiadomości</string>
|
||||||
<string name="room_message_file_not_found">Nie znaleziono pliku</string>
|
<string name="room_message_file_not_found">Nie znaleziono pliku</string>
|
||||||
@ -430,7 +430,7 @@ Zauważ, że ta czynność spowoduje ponowne uruchomienie aplikacji i może to t
|
|||||||
<string name="settings_phone_number_country_label">Kraj</string>
|
<string name="settings_phone_number_country_label">Kraj</string>
|
||||||
<string name="settings_phone_number_country_error">Wybierz kraj</string>
|
<string name="settings_phone_number_country_error">Wybierz kraj</string>
|
||||||
<string name="settings_phone_number_label">Numer telefonu</string>
|
<string name="settings_phone_number_label">Numer telefonu</string>
|
||||||
<string name="settings_phone_number_verification">Weryfikacja numeru</string>
|
<string name="settings_phone_number_verification">Weryfikacja numeru telefonu</string>
|
||||||
<string name="settings_phone_number_verification_error_empty_code">Wprowadź kod aktywacyjny</string>
|
<string name="settings_phone_number_verification_error_empty_code">Wprowadź kod aktywacyjny</string>
|
||||||
<string name="settings_phone_number_verification_error">Wystąpił błąd podczas weryfikowania numeru telefonu</string>
|
<string name="settings_phone_number_verification_error">Wystąpił błąd podczas weryfikowania numeru telefonu</string>
|
||||||
<string name="settings_phone_number_code">Kod</string>
|
<string name="settings_phone_number_code">Kod</string>
|
||||||
@ -616,8 +616,8 @@ Zezwól na dostęp w następnym oknie aby móc wykonać połączenie.</string>
|
|||||||
Przyznaj dostęp w następnym oknie.</string>
|
Przyznaj dostęp w następnym oknie.</string>
|
||||||
<string name="permissions_rationale_msg_contacts">Riot może sprawdzić Twoją książkę adresową, aby znajdywać innych użytkowników Matrixa bazując na ich adresie e-mail i numerze telefonu. Jeśli zgadzasz się na udostępnienie Twojej książki adresowej w tym celu, zezwól na dostęp w następnym okienku.</string>
|
<string name="permissions_rationale_msg_contacts">Riot może sprawdzić Twoją książkę adresową, aby znajdywać innych użytkowników Matrixa bazując na ich adresie e-mail i numerze telefonu. Jeśli zgadzasz się na udostępnienie Twojej książki adresowej w tym celu, zezwól na dostęp w następnym okienku.</string>
|
||||||
<string name="permissions_msg_contacts_warning_other_androids">Riot wymaga dostępu do kontaktów, aby znajdywać innych użytkowników Matrixa bazując na adresie e-mail i numerze telefonu.
|
<string name="permissions_msg_contacts_warning_other_androids">Riot wymaga dostępu do kontaktów, aby znajdywać innych użytkowników Matrixa bazując na adresie e-mail i numerze telefonu.
|
||||||
|
\n
|
||||||
Zezwolić Riot na dostęp do kontaktów?</string>
|
\nZezwolić Riot na dostęp do kontaktów\?</string>
|
||||||
|
|
||||||
<string name="list_members">Lista uczestników</string>
|
<string name="list_members">Lista uczestników</string>
|
||||||
<string name="open_chat_header">Otwarty nagłówek</string>
|
<string name="open_chat_header">Otwarty nagłówek</string>
|
||||||
@ -1232,4 +1232,22 @@ Spróbuj uruchomić ponownie aplikację.</string>
|
|||||||
<string name="backup">Utwórz kopię zapasową</string>
|
<string name="backup">Utwórz kopię zapasową</string>
|
||||||
<string name="login_error_ssl_handshake">Twoje urządzenie używa przestarzałego protokołu bezpieczeństwa TSL, podatnego na ataki, dlatego dla Twojego bezpieczeństwa nie będziesz mógł się połączyć</string>
|
<string name="login_error_ssl_handshake">Twoje urządzenie używa przestarzałego protokołu bezpieczeństwa TSL, podatnego na ataki, dlatego dla Twojego bezpieczeństwa nie będziesz mógł się połączyć</string>
|
||||||
<string name="keys_backup_settings_status_ok">Kopia zapasowa klucza została prawidłowo skonfigurowana dla tego urządzenia.</string>
|
<string name="keys_backup_settings_status_ok">Kopia zapasowa klucza została prawidłowo skonfigurowana dla tego urządzenia.</string>
|
||||||
|
<string name="notification_sync_init">Inicjalizacja usługi</string>
|
||||||
|
<string name="auth_login_sso">Zaloguj się za pomocą logowania jednorazowego</string>
|
||||||
|
<string name="settings_notification_advanced_summary">Ustaw ważność powiadomienia za pomocą wydarzeń, skonfiguruj dźwięk, diodę LED, wibracje</string>
|
||||||
|
<string name="settings_notification_by_event">Ważność powiadomień ze względu na wydarzenie</string>
|
||||||
|
|
||||||
|
<string name="settings_notification_troubleshoot">Powiadomienia diagnostyczne</string>
|
||||||
|
<string name="settings_troubleshoot_diagnostic">Rozwiązywanie problemów</string>
|
||||||
|
<string name="settings_troubleshoot_diagnostic_success_status">Diagnostyka podstawowa nie wykazała problemów. Jeżeli wciąż nie otrzymujesz powiadomień, prosimy o przesłanie raportu o błędach, w celu ich rozwiązania.</string>
|
||||||
|
<string name="settings_notification_privacy_no_background_sync">Aplikacja <b>nie</b> potrzebuje łączyć się z serwerem domowym w tle, powinno to zredukować użycie baterii</string>
|
||||||
|
<string name="keys_backup_restore_with_passphrase_helper_with_link">Jeżeli nie pamiętasz swoich danych odzystkiwania, możesz %s.</string>
|
||||||
|
|
||||||
|
<string name="keys_backup_restore_with_key_helper">Zgubiłeś (-łaś) swój klucz odzyskiwania\? Możesz ustawić nowy w ustawieniach.</string>
|
||||||
|
<string name="keys_backup_settings_valid_signature_from_unverified_device">Kopia zapasowa posiada poprawną sygnaturę z niezweryfikowanego urządzenia %s</string>
|
||||||
|
<string name="new_recovery_method_popup_description">Wykryto nową, bezpieczną kopię kluczy wiadomości.
|
||||||
|
\n
|
||||||
|
\nJeżeli nie ustawiałeś nowej metody odzyskiwania, atakujący mogą uzyskać dostęp do Twojego konta. Zmień hasło konta i ustaw nową metodę odzyskiwania jak najszybciej w Ustawieniach.</string>
|
||||||
|
<string name="room_list_catchup_empty_title">Jesteś na bieżąco!</string>
|
||||||
|
<string name="login_error_unknown_host">Ten adres URL jest nieosiągalny, proszę sprawdź jego poprawność</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user