mirror of
https://github.com/element-hq/element-android
synced 2024-11-28 13:38:49 +03:00
Merge branch 'develop' into feature/fix_#498
This commit is contained in:
commit
d47cf7e932
56 changed files with 217 additions and 405 deletions
|
@ -3,13 +3,35 @@
|
||||||
# https://github.com/buildkite-plugins/docker-buildkite-plugin/releases
|
# https://github.com/buildkite-plugins/docker-buildkite-plugin/releases
|
||||||
# We propagate the environment to the container (sse https://github.com/buildkite-plugins/docker-buildkite-plugin#propagate-environment-optional-boolean)
|
# We propagate the environment to the container (sse https://github.com/buildkite-plugins/docker-buildkite-plugin#propagate-environment-optional-boolean)
|
||||||
|
|
||||||
# Build debug version of the RiotX application, from the develop branch and the features branches
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- label: "Assemble GPlay Debug version"
|
- label: "Compile and run Unit tests"
|
||||||
agents:
|
agents:
|
||||||
# We use a medium sized instance instead of the normal small ones because
|
# We use a medium sized instance instead of the normal small ones because
|
||||||
# gradle build is long
|
# gradle build can be memory hungry
|
||||||
|
queue: "medium"
|
||||||
|
commands:
|
||||||
|
- "./gradlew clean test --stacktrace"
|
||||||
|
plugins:
|
||||||
|
- docker#v3.1.0:
|
||||||
|
image: "runmymind/docker-android-sdk"
|
||||||
|
propagate-environment: true
|
||||||
|
|
||||||
|
- label: "Compile Android tests"
|
||||||
|
agents:
|
||||||
|
# We use a medium sized instance instead of the normal small ones because
|
||||||
|
# gradle build can be memory hungry
|
||||||
|
queue: "medium"
|
||||||
|
commands:
|
||||||
|
- "./gradlew clean assembleAndroidTest --stacktrace"
|
||||||
|
plugins:
|
||||||
|
- docker#v3.1.0:
|
||||||
|
image: "runmymind/docker-android-sdk"
|
||||||
|
propagate-environment: true
|
||||||
|
|
||||||
|
- label: "Assemble GPlay Debug version"
|
||||||
|
agents:
|
||||||
|
# We use a xlarge sized instance instead of the normal small ones because
|
||||||
|
# gradle build can be memory hungry
|
||||||
queue: "xlarge"
|
queue: "xlarge"
|
||||||
commands:
|
commands:
|
||||||
- "./gradlew clean lintGplayRelease assembleGplayDebug --stacktrace"
|
- "./gradlew clean lintGplayRelease assembleGplayDebug --stacktrace"
|
||||||
|
@ -23,8 +45,8 @@ steps:
|
||||||
|
|
||||||
- label: "Assemble FDroid Debug version"
|
- label: "Assemble FDroid Debug version"
|
||||||
agents:
|
agents:
|
||||||
# We use a medium sized instance instead of the normal small ones because
|
# We use a xlarge sized instance instead of the normal small ones because
|
||||||
# gradle build is long
|
# gradle build can be memory hungry
|
||||||
queue: "xlarge"
|
queue: "xlarge"
|
||||||
commands:
|
commands:
|
||||||
- "./gradlew clean lintFdroidRelease assembleFdroidDebug --stacktrace"
|
- "./gradlew clean lintFdroidRelease assembleFdroidDebug --stacktrace"
|
||||||
|
@ -38,8 +60,8 @@ steps:
|
||||||
|
|
||||||
- label: "Build Google Play unsigned APK"
|
- label: "Build Google Play unsigned APK"
|
||||||
agents:
|
agents:
|
||||||
# We use a medium sized instance instead of the normal small ones because
|
# We use a xlarge sized instance instead of the normal small ones because
|
||||||
# gradle build is long
|
# gradle build can be memory hungry
|
||||||
queue: "xlarge"
|
queue: "xlarge"
|
||||||
commands:
|
commands:
|
||||||
- "./gradlew clean assembleGplayRelease --stacktrace"
|
- "./gradlew clean assembleGplayRelease --stacktrace"
|
||||||
|
|
|
@ -12,6 +12,7 @@ Other changes:
|
||||||
|
|
||||||
Bugfix 🐛:
|
Bugfix 🐛:
|
||||||
- Fix issues with some member events rendering (#498)
|
- Fix issues with some member events rendering (#498)
|
||||||
|
- Passphrase does not match (Export room keys) (#644)
|
||||||
|
|
||||||
Translations 🗣:
|
Translations 🗣:
|
||||||
-
|
-
|
||||||
|
|
|
@ -11,6 +11,8 @@ android {
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "1.0"
|
versionName "1.0"
|
||||||
|
|
||||||
|
// Multidex is useful for tests
|
||||||
|
multiDexEnabled true
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.matrix.rx;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import androidx.test.InstrumentationRegistry;
|
|
||||||
import androidx.test.runner.AndroidJUnit4;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instrumented test, which will execute on an Android device.
|
|
||||||
*
|
|
||||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
|
||||||
*/
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
|
||||||
public class ExampleInstrumentedTest {
|
|
||||||
@Test
|
|
||||||
public void useAppContext() {
|
|
||||||
// Context of the app under test.
|
|
||||||
Context appContext = InstrumentationRegistry.getTargetContext();
|
|
||||||
|
|
||||||
assertEquals("im.vector.matrix.rx.test", appContext.getPackageName());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.matrix.rx;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Example local unit test, which will execute on the development machine (host).
|
|
||||||
*
|
|
||||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
|
||||||
*/
|
|
||||||
public class ExampleUnitTest {
|
|
||||||
@Test
|
|
||||||
public void addition_isCorrect() {
|
|
||||||
assertEquals(4, 2 + 2);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -155,7 +155,8 @@ dependencies {
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
testImplementation 'org.robolectric:robolectric:4.3'
|
testImplementation 'org.robolectric:robolectric:4.3'
|
||||||
//testImplementation 'org.robolectric:shadows-support-v4:3.0'
|
//testImplementation 'org.robolectric:shadows-support-v4:3.0'
|
||||||
testImplementation 'io.mockk:mockk:1.9.3.kotlin12'
|
// Note: version sticks to 1.9.2 due to https://github.com/mockk/mockk/issues/281
|
||||||
|
testImplementation 'io.mockk:mockk:1.9.2.kotlin12'
|
||||||
testImplementation 'org.amshove.kluent:kluent-android:1.44'
|
testImplementation 'org.amshove.kluent:kluent-android:1.44'
|
||||||
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
||||||
|
|
||||||
|
@ -165,7 +166,8 @@ dependencies {
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||||
androidTestImplementation 'org.amshove.kluent:kluent-android:1.44'
|
androidTestImplementation 'org.amshove.kluent:kluent-android:1.44'
|
||||||
androidTestImplementation 'io.mockk:mockk-android:1.9.3.kotlin12'
|
// Note: version sticks to 1.9.2 due to https://github.com/mockk/mockk/issues/281
|
||||||
|
androidTestImplementation 'io.mockk:mockk-android:1.9.2.kotlin12'
|
||||||
androidTestImplementation "androidx.arch.core:core-testing:$lifecycle_version"
|
androidTestImplementation "androidx.arch.core:core-testing:$lifecycle_version"
|
||||||
androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
||||||
|
|
||||||
|
|
|
@ -17,12 +17,12 @@
|
||||||
package im.vector.matrix.android
|
package im.vector.matrix.android
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.test.InstrumentationRegistry
|
import androidx.test.core.app.ApplicationProvider
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
interface InstrumentedTest {
|
interface InstrumentedTest {
|
||||||
fun context(): Context {
|
fun context(): Context {
|
||||||
return InstrumentationRegistry.getTargetContext()
|
return ApplicationProvider.getApplicationContext()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun cacheDir(): File {
|
fun cacheDir(): File {
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
package im.vector.matrix.android.auth
|
package im.vector.matrix.android.auth
|
||||||
|
|
||||||
import androidx.test.annotation.UiThreadTest
|
import androidx.test.annotation.UiThreadTest
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.rule.GrantPermissionRule
|
import androidx.test.rule.GrantPermissionRule
|
||||||
import androidx.test.runner.AndroidJUnit4
|
|
||||||
import im.vector.matrix.android.InstrumentedTest
|
import im.vector.matrix.android.InstrumentedTest
|
||||||
import im.vector.matrix.android.OkReplayRuleChainNoActivity
|
import im.vector.matrix.android.OkReplayRuleChainNoActivity
|
||||||
import im.vector.matrix.android.api.auth.Authenticator
|
import im.vector.matrix.android.api.auth.Authenticator
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
package im.vector.matrix.android.api.session.events.model
|
package im.vector.matrix.android.api.session.events.model
|
||||||
|
|
||||||
import java.util.*
|
import java.util.UUID
|
||||||
|
|
||||||
object LocalEcho {
|
object LocalEcho {
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ internal class DeviceListManager @Inject constructor(private val cryptoStore: IM
|
||||||
if (':' in userId) {
|
if (':' in userId) {
|
||||||
try {
|
try {
|
||||||
synchronized(notReadyToRetryHS) {
|
synchronized(notReadyToRetryHS) {
|
||||||
res = !notReadyToRetryHS.contains(userId.substring(userId.lastIndexOf(":") + 1))
|
res = !notReadyToRetryHS.contains(userId.substringAfterLast(':'))
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Timber.e(e, "## canRetryKeysDownload() failed")
|
Timber.e(e, "## canRetryKeysDownload() failed")
|
||||||
|
|
|
@ -216,7 +216,7 @@ internal class OutgoingRoomKeyRequestManager @Inject constructor(
|
||||||
sendMessageToDevices(requestMessage, request.recipients, request.requestId, object : MatrixCallback<Unit> {
|
sendMessageToDevices(requestMessage, request.recipients, request.requestId, object : MatrixCallback<Unit> {
|
||||||
private fun onDone(state: OutgoingRoomKeyRequest.RequestState) {
|
private fun onDone(state: OutgoingRoomKeyRequest.RequestState) {
|
||||||
if (request.state !== OutgoingRoomKeyRequest.RequestState.UNSENT) {
|
if (request.state !== OutgoingRoomKeyRequest.RequestState.UNSENT) {
|
||||||
Timber.v("## sendOutgoingRoomKeyRequest() : Cannot update room key request from UNSENT as it was already updated to " + request.state)
|
Timber.v("## sendOutgoingRoomKeyRequest() : Cannot update room key request from UNSENT as it was already updated to ${request.state}")
|
||||||
} else {
|
} else {
|
||||||
request.state = state
|
request.state = state
|
||||||
cryptoStore.updateOutgoingRoomKeyRequest(request)
|
cryptoStore.updateOutgoingRoomKeyRequest(request)
|
||||||
|
|
|
@ -43,6 +43,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.lang.Exception
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.collections.HashMap
|
import kotlin.collections.HashMap
|
||||||
|
@ -166,72 +167,59 @@ internal class DefaultSasVerificationService @Inject constructor(private val cre
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Download device keys prior to everything
|
// Download device keys prior to everything
|
||||||
checkKeysAreDownloaded(
|
if (checkKeysAreDownloaded(otherUserId!!, startReq) != null) {
|
||||||
otherUserId!!,
|
Timber.v("## SAS onStartRequestReceived ${startReq.transactionID!!}")
|
||||||
startReq,
|
val tid = startReq.transactionID!!
|
||||||
success = {
|
val existing = getExistingTransaction(otherUserId, tid)
|
||||||
Timber.v("## SAS onStartRequestReceived ${startReq.transactionID!!}")
|
val existingTxs = getExistingTransactionsForUser(otherUserId)
|
||||||
val tid = startReq.transactionID!!
|
if (existing != null) {
|
||||||
val existing = getExistingTransaction(otherUserId, tid)
|
// should cancel both!
|
||||||
val existingTxs = getExistingTransactionsForUser(otherUserId)
|
Timber.v("## SAS onStartRequestReceived - Request exist with same if ${startReq.transactionID!!}")
|
||||||
if (existing != null) {
|
existing.cancel(CancelCode.UnexpectedMessage)
|
||||||
// should cancel both!
|
cancelTransaction(tid, otherUserId, startReq.fromDevice!!, CancelCode.UnexpectedMessage)
|
||||||
Timber.v("## SAS onStartRequestReceived - Request exist with same if ${startReq.transactionID!!}")
|
} else if (existingTxs?.isEmpty() == false) {
|
||||||
existing.cancel(CancelCode.UnexpectedMessage)
|
Timber.v("## SAS onStartRequestReceived - There is already a transaction with this user ${startReq.transactionID!!}")
|
||||||
cancelTransaction(tid, otherUserId, startReq.fromDevice!!, CancelCode.UnexpectedMessage)
|
// Multiple keyshares between two devices: any two devices may only have at most one key verification in flight at a time.
|
||||||
} else if (existingTxs?.isEmpty() == false) {
|
existingTxs.forEach {
|
||||||
Timber.v("## SAS onStartRequestReceived - There is already a transaction with this user ${startReq.transactionID!!}")
|
it.cancel(CancelCode.UnexpectedMessage)
|
||||||
// Multiple keyshares between two devices: any two devices may only have at most one key verification in flight at a time.
|
}
|
||||||
existingTxs.forEach {
|
cancelTransaction(tid, otherUserId, startReq.fromDevice!!, CancelCode.UnexpectedMessage)
|
||||||
it.cancel(CancelCode.UnexpectedMessage)
|
} else {
|
||||||
}
|
// Ok we can create
|
||||||
cancelTransaction(tid, otherUserId, startReq.fromDevice!!, CancelCode.UnexpectedMessage)
|
if (KeyVerificationStart.VERIF_METHOD_SAS == startReq.method) {
|
||||||
} else {
|
Timber.v("## SAS onStartRequestReceived - request accepted ${startReq.transactionID!!}")
|
||||||
// Ok we can create
|
val tx = IncomingSASVerificationTransaction(
|
||||||
if (KeyVerificationStart.VERIF_METHOD_SAS == startReq.method) {
|
this,
|
||||||
Timber.v("## SAS onStartRequestReceived - request accepted ${startReq.transactionID!!}")
|
setDeviceVerificationAction,
|
||||||
val tx = IncomingSASVerificationTransaction(
|
credentials,
|
||||||
this,
|
cryptoStore,
|
||||||
setDeviceVerificationAction,
|
sendToDeviceTask,
|
||||||
credentials,
|
taskExecutor,
|
||||||
cryptoStore,
|
myDeviceInfoHolder.get().myDevice.fingerprint()!!,
|
||||||
sendToDeviceTask,
|
startReq.transactionID!!,
|
||||||
taskExecutor,
|
otherUserId)
|
||||||
myDeviceInfoHolder.get().myDevice.fingerprint()!!,
|
addTransaction(tx)
|
||||||
startReq.transactionID!!,
|
tx.acceptToDeviceEvent(otherUserId, startReq)
|
||||||
otherUserId)
|
} else {
|
||||||
addTransaction(tx)
|
Timber.e("## SAS onStartRequestReceived - unknown method ${startReq.method}")
|
||||||
tx.acceptToDeviceEvent(otherUserId, startReq)
|
cancelTransaction(tid, otherUserId, startReq.fromDevice
|
||||||
} else {
|
?: event.getSenderKey()!!, CancelCode.UnknownMethod)
|
||||||
Timber.e("## SAS onStartRequestReceived - unknown method ${startReq.method}")
|
}
|
||||||
cancelTransaction(tid, otherUserId, startReq.fromDevice
|
}
|
||||||
?: event.getSenderKey()!!, CancelCode.UnknownMethod)
|
} else {
|
||||||
}
|
cancelTransaction(startReq.transactionID!!, otherUserId, startReq.fromDevice!!, CancelCode.UnexpectedMessage)
|
||||||
}
|
}
|
||||||
},
|
|
||||||
error = {
|
|
||||||
cancelTransaction(startReq.transactionID!!, otherUserId, startReq.fromDevice!!, CancelCode.UnexpectedMessage)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun checkKeysAreDownloaded(otherUserId: String,
|
private suspend fun checkKeysAreDownloaded(otherUserId: String,
|
||||||
startReq: KeyVerificationStart,
|
startReq: KeyVerificationStart): MXUsersDevicesMap<MXDeviceInfo>? {
|
||||||
success: (MXUsersDevicesMap<MXDeviceInfo>) -> Unit,
|
return try {
|
||||||
error: () -> Unit) {
|
val keys = deviceListManager.downloadKeys(listOf(otherUserId), true)
|
||||||
runCatching {
|
val deviceIds = keys.getUserDeviceIds(otherUserId) ?: return null
|
||||||
deviceListManager.downloadKeys(listOf(otherUserId), true)
|
keys.takeIf { deviceIds.contains(startReq.fromDevice) }
|
||||||
}.fold(
|
} catch (e: Exception) {
|
||||||
{
|
null
|
||||||
if (it.getUserDeviceIds(otherUserId)?.contains(startReq.fromDevice) == true) {
|
}
|
||||||
success(it)
|
|
||||||
} else {
|
|
||||||
error()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
error()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun onCancelReceived(event: Event) {
|
private suspend fun onCancelReceived(event: Event) {
|
||||||
|
@ -342,10 +330,8 @@ internal class DefaultSasVerificationService @Inject constructor(private val cre
|
||||||
private fun addTransaction(tx: VerificationTransaction) {
|
private fun addTransaction(tx: VerificationTransaction) {
|
||||||
tx.otherUserId.let { otherUserId ->
|
tx.otherUserId.let { otherUserId ->
|
||||||
synchronized(txMap) {
|
synchronized(txMap) {
|
||||||
if (txMap[otherUserId] == null) {
|
val txInnerMap = txMap.getOrPut(otherUserId) { HashMap() }
|
||||||
txMap[otherUserId] = HashMap()
|
txInnerMap[tx.transactionId] = tx
|
||||||
}
|
|
||||||
txMap[otherUserId]?.set(tx.transactionId, tx)
|
|
||||||
dispatchTxAdded(tx)
|
dispatchTxAdded(tx)
|
||||||
tx.addListener(this)
|
tx.addListener(this)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -22,7 +22,7 @@ import com.novoda.merlin.MerlinsBeard
|
||||||
import im.vector.matrix.android.internal.di.MatrixScope
|
import im.vector.matrix.android.internal.di.MatrixScope
|
||||||
import im.vector.matrix.android.internal.util.BackgroundDetectionObserver
|
import im.vector.matrix.android.internal.util.BackgroundDetectionObserver
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.*
|
import java.util.Collections
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
import kotlin.coroutines.suspendCoroutine
|
import kotlin.coroutines.suspendCoroutine
|
||||||
|
|
|
@ -23,7 +23,7 @@ import im.vector.matrix.android.internal.database.query.getOrCreate
|
||||||
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 im.vector.matrix.android.internal.util.awaitTransaction
|
import im.vector.matrix.android.internal.util.awaitTransaction
|
||||||
import java.util.*
|
import java.util.Date
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal interface GetHomeServerCapabilitiesTask : Task<Unit, Unit>
|
internal interface GetHomeServerCapabilitiesTask : Task<Unit, Unit>
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,6 @@ 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 javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -52,7 +52,8 @@ import io.realm.RealmQuery
|
||||||
import io.realm.RealmResults
|
import io.realm.RealmResults
|
||||||
import io.realm.Sort
|
import io.realm.Sort
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.*
|
import java.util.Collections
|
||||||
|
import java.util.UUID
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
import java.util.concurrent.atomic.AtomicReference
|
import java.util.concurrent.atomic.AtomicReference
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
|
|
@ -31,7 +31,7 @@ import java.security.KeyPairGenerator
|
||||||
import java.security.KeyStore
|
import java.security.KeyStore
|
||||||
import java.security.KeyStoreException
|
import java.security.KeyStoreException
|
||||||
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
|
||||||
|
|
|
@ -36,7 +36,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
|
||||||
|
|
|
@ -18,7 +18,7 @@ package im.vector.matrix.android.internal.util
|
||||||
|
|
||||||
import im.vector.matrix.android.api.MatrixPatterns
|
import im.vector.matrix.android.api.MatrixPatterns
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.*
|
import java.util.Locale
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a string to an UTF8 String
|
* Convert a string to an UTF8 String
|
||||||
|
|
|
@ -18,7 +18,7 @@ package im.vector.matrix.android.api.pushrules
|
||||||
|
|
||||||
import im.vector.matrix.android.api.pushrules.rest.PushRule
|
import im.vector.matrix.android.api.pushrules.rest.PushRule
|
||||||
import im.vector.matrix.android.internal.di.MoshiProvider
|
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||||
import org.junit.Assert
|
import org.junit.Assert.*
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
class PushRuleActionsTest {
|
class PushRuleActionsTest {
|
||||||
|
@ -63,22 +63,17 @@ class PushRuleActionsTest {
|
||||||
|
|
||||||
val pushRule = MoshiProvider.providesMoshi().adapter<PushRule>(PushRule::class.java).fromJson(rawPushRule)
|
val pushRule = MoshiProvider.providesMoshi().adapter<PushRule>(PushRule::class.java).fromJson(rawPushRule)
|
||||||
|
|
||||||
Assert.assertNotNull("Should have parsed the rule", pushRule)
|
assertNotNull("Should have parsed the rule", pushRule)
|
||||||
Assert.assertNotNull("Failed to parse actions", Action.mapFrom(pushRule!!))
|
|
||||||
|
|
||||||
val actions = Action.mapFrom(pushRule)
|
val actions = pushRule!!.getActions()
|
||||||
Assert.assertEquals(3, actions!!.size)
|
assertEquals(3, actions.size)
|
||||||
|
|
||||||
Assert.assertEquals("First action should be notify", Action.Type.NOTIFY, actions[0].type)
|
assertTrue("First action should be notify", actions[0] is Action.Notify)
|
||||||
|
|
||||||
Assert.assertEquals("Second action should be tweak", Action.Type.SET_TWEAK, actions[1].type)
|
assertTrue("Second action should be sound", actions[1] is Action.Sound)
|
||||||
Assert.assertEquals("Second action tweak key should be sound", "sound", actions[1].tweak_action)
|
assertEquals("Second action should have default sound", "default", (actions[1] as Action.Sound).sound)
|
||||||
Assert.assertEquals("Second action should have default as stringValue", "default", actions[1].stringValue)
|
|
||||||
Assert.assertNull("Second action boolValue should be null", actions[1].boolValue)
|
|
||||||
|
|
||||||
Assert.assertEquals("Third action should be tweak", Action.Type.SET_TWEAK, actions[2].type)
|
assertTrue("Third action should be highlight", actions[2] is Action.Highlight)
|
||||||
Assert.assertEquals("Third action tweak key should be highlight", "highlight", actions[2].tweak_action)
|
assertEquals("Third action tweak param should be false", false, (actions[2] as Action.Highlight).highlight)
|
||||||
Assert.assertEquals("Third action tweak param should be false", false, actions[2].boolValue)
|
|
||||||
Assert.assertNull("Third action stringValue should be null", actions[2].stringValue)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,6 +199,10 @@ class PushrulesConditionTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
class MockRoom(override val roomId: String, val _numberOfJoinedMembers: Int) : Room {
|
class MockRoom(override val roomId: String, val _numberOfJoinedMembers: Int) : Room {
|
||||||
|
override fun reportContent(eventId: String, score: Int, reason: String, callback: MatrixCallback<Unit>): Cancelable {
|
||||||
|
TODO("not implemented") // To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
override fun getReadMarkerLive(): LiveData<Optional<String>> {
|
override fun getReadMarkerLive(): LiveData<Optional<String>> {
|
||||||
TODO("not implemented") // To change body of created functions use File | Settings | File Templates.
|
TODO("not implemented") // To change body of created functions use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 androidx.test.InstrumentationRegistry
|
|
||||||
import androidx.test.runner.AndroidJUnit4
|
|
||||||
|
|
||||||
import org.junit.Test
|
|
||||||
import org.junit.runner.RunWith
|
|
||||||
|
|
||||||
import org.junit.Assert.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instrumented test, which will execute on an Android device.
|
|
||||||
*
|
|
||||||
* See [testing documentation](http://d.android.com/tools/testing).
|
|
||||||
*/
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
|
||||||
class ExampleInstrumentedTest {
|
|
||||||
@Test
|
|
||||||
fun useAppContext() {
|
|
||||||
// Context of the app under test.
|
|
||||||
val appContext = InstrumentationRegistry.getTargetContext()
|
|
||||||
assertEquals("im.vector.riotx", appContext.packageName)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -55,7 +55,8 @@ import im.vector.riotx.features.version.VersionProvider
|
||||||
import im.vector.riotx.push.fcm.FcmHelper
|
import im.vector.riotx.push.fcm.FcmHelper
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.Date
|
||||||
|
import java.util.Locale
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class VectorApplication : Application(), HasVectorInjector, MatrixConfiguration.Provider, androidx.work.Configuration.Provider {
|
class VectorApplication : Application(), HasVectorInjector, MatrixConfiguration.Provider, androidx.work.Configuration.Provider {
|
||||||
|
|
|
@ -44,15 +44,15 @@ class ExportKeysDialog {
|
||||||
val textWatcher = object : SimpleTextWatcher() {
|
val textWatcher = object : SimpleTextWatcher() {
|
||||||
override fun afterTextChanged(s: Editable) {
|
override fun afterTextChanged(s: Editable) {
|
||||||
when {
|
when {
|
||||||
passPhrase1EditText.text.isNullOrEmpty() -> {
|
passPhrase1EditText.text.isNullOrEmpty() -> {
|
||||||
exportButton.isEnabled = false
|
exportButton.isEnabled = false
|
||||||
passPhrase2Til.error = null
|
passPhrase2Til.error = null
|
||||||
}
|
}
|
||||||
passPhrase1EditText.text == passPhrase2EditText.text -> {
|
passPhrase1EditText.text.toString() == passPhrase2EditText.text.toString() -> {
|
||||||
exportButton.isEnabled = true
|
exportButton.isEnabled = true
|
||||||
passPhrase2Til.error = null
|
passPhrase2Til.error = null
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
exportButton.isEnabled = false
|
exportButton.isEnabled = false
|
||||||
passPhrase2Til.error = activity.getString(R.string.passphrase_passphrase_does_not_match)
|
passPhrase2Til.error = activity.getString(R.string.passphrase_passphrase_does_not_match)
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,15 +30,10 @@ import java.io.File
|
||||||
*/
|
*/
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
fun writeToFile(str: String, file: File): Try<Unit> {
|
fun writeToFile(str: String, file: File): Try<Unit> {
|
||||||
return Try {
|
return Try<Unit> {
|
||||||
val sink = file.sink()
|
file.sink().buffer().use {
|
||||||
|
it.writeString(str, Charsets.UTF_8)
|
||||||
val bufferedSink = sink.buffer()
|
}
|
||||||
|
|
||||||
bufferedSink.writeString(str, Charsets.UTF_8)
|
|
||||||
|
|
||||||
bufferedSink.close()
|
|
||||||
sink.close()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,15 +42,10 @@ fun writeToFile(str: String, file: File): Try<Unit> {
|
||||||
*/
|
*/
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
fun writeToFile(data: ByteArray, file: File): Try<Unit> {
|
fun writeToFile(data: ByteArray, file: File): Try<Unit> {
|
||||||
return Try {
|
return Try<Unit> {
|
||||||
val sink = file.sink()
|
file.sink().buffer().use {
|
||||||
|
it.write(data)
|
||||||
val bufferedSink = sink.buffer()
|
}
|
||||||
|
|
||||||
bufferedSink.write(data)
|
|
||||||
|
|
||||||
bufferedSink.close()
|
|
||||||
sink.close()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
package im.vector.riotx.core.images
|
package im.vector.riotx.core.images
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.database.Cursor
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.provider.MediaStore
|
import android.provider.MediaStore
|
||||||
import androidx.exifinterface.media.ExifInterface
|
import androidx.exifinterface.media.ExifInterface
|
||||||
|
@ -37,26 +36,24 @@ class ImageTools @Inject constructor(private val context: Context) {
|
||||||
|
|
||||||
if (uri.scheme == "content") {
|
if (uri.scheme == "content") {
|
||||||
val proj = arrayOf(MediaStore.Images.Media.DATA)
|
val proj = arrayOf(MediaStore.Images.Media.DATA)
|
||||||
var cursor: Cursor? = null
|
|
||||||
try {
|
try {
|
||||||
cursor = context.contentResolver.query(uri, proj, null, null, null)
|
val cursor = context.contentResolver.query(uri, proj, null, null, null)
|
||||||
if (cursor != null && cursor.count > 0) {
|
cursor?.use {
|
||||||
cursor.moveToFirst()
|
if (it.moveToFirst()) {
|
||||||
val idxData = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
|
val idxData = it.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
|
||||||
val path = cursor.getString(idxData)
|
val path = it.getString(idxData)
|
||||||
if (path.isNullOrBlank()) {
|
if (path.isNullOrBlank()) {
|
||||||
Timber.w("Cannot find path in media db for uri $uri")
|
Timber.w("Cannot find path in media db for uri $uri")
|
||||||
return orientation
|
return orientation
|
||||||
|
}
|
||||||
|
val exif = ExifInterface(path)
|
||||||
|
orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED)
|
||||||
}
|
}
|
||||||
val exif = ExifInterface(path)
|
|
||||||
orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED)
|
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
// eg SecurityException from com.google.android.apps.photos.content.GooglePhotosImageProvider URIs
|
// eg SecurityException from com.google.android.apps.photos.content.GooglePhotosImageProvider URIs
|
||||||
// eg IOException from trying to parse the returned path as a file when it is an http uri.
|
// eg IOException from trying to parse the returned path as a file when it is an http uri.
|
||||||
Timber.e(e, "Cannot get orientation for bitmap")
|
Timber.e(e, "Cannot get orientation for bitmap")
|
||||||
} finally {
|
|
||||||
cursor?.close()
|
|
||||||
}
|
}
|
||||||
} else if (uri.scheme == "file") {
|
} else if (uri.scheme == "file") {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -17,28 +17,17 @@
|
||||||
package im.vector.riotx.core.intent
|
package im.vector.riotx.core.intent
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.database.Cursor
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.provider.OpenableColumns
|
import android.provider.OpenableColumns
|
||||||
|
|
||||||
fun getFilenameFromUri(context: Context?, uri: Uri): String? {
|
fun getFilenameFromUri(context: Context?, uri: Uri): String? {
|
||||||
var result: String? = null
|
|
||||||
if (context != null && uri.scheme == "content") {
|
if (context != null && uri.scheme == "content") {
|
||||||
val cursor: Cursor? = context.contentResolver.query(uri, null, null, null, null)
|
val cursor = context.contentResolver.query(uri, null, null, null, null)
|
||||||
try {
|
cursor?.use {
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
if (it.moveToFirst()) {
|
||||||
result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME))
|
return it.getString(it.getColumnIndex(OpenableColumns.DISPLAY_NAME))
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
cursor?.close()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (result == null) {
|
return uri.path?.substringAfterLast('/')
|
||||||
result = uri.path
|
|
||||||
val cut = result?.lastIndexOf('/') ?: -1
|
|
||||||
if (cut != -1) {
|
|
||||||
result = result?.substring(cut + 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package im.vector.riotx.core.linkify
|
package im.vector.riotx.core.linkify
|
||||||
|
|
||||||
import java.util.regex.Pattern
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Better support for geo URi
|
* Better support for geo URi
|
||||||
*/
|
*/
|
||||||
|
@ -26,7 +24,7 @@ object VectorAutoLinkPatterns {
|
||||||
private const val LAT_OR_LONG_OR_ALT_NUMBER = "-?\\d+(?:\\.\\d+)?"
|
private const val LAT_OR_LONG_OR_ALT_NUMBER = "-?\\d+(?:\\.\\d+)?"
|
||||||
private const val COORDINATE_SYSTEM = ";crs=[\\w-]+"
|
private const val COORDINATE_SYSTEM = ";crs=[\\w-]+"
|
||||||
|
|
||||||
val GEO_URI: Pattern = Pattern.compile("(?:geo:)?" +
|
val GEO_URI: Regex = Regex("(?:geo:)?" +
|
||||||
"(" + LAT_OR_LONG_OR_ALT_NUMBER + ")" +
|
"(" + LAT_OR_LONG_OR_ALT_NUMBER + ")" +
|
||||||
"," +
|
"," +
|
||||||
"(" + LAT_OR_LONG_OR_ALT_NUMBER + ")" +
|
"(" + LAT_OR_LONG_OR_ALT_NUMBER + ")" +
|
||||||
|
@ -35,5 +33,5 @@ object VectorAutoLinkPatterns {
|
||||||
"(?:" + ";u=\\d+(?:\\.\\d+)?" + ")?" + // uncertainty in meters
|
"(?:" + ";u=\\d+(?:\\.\\d+)?" + ")?" + // uncertainty in meters
|
||||||
"(?:" +
|
"(?:" +
|
||||||
";[\\w-]+=(?:[\\w-_.!~*'()]|%[\\da-f][\\da-f])+" + // dafuk
|
";[\\w-]+=(?:[\\w-_.!~*'()]|%[\\da-f][\\da-f])+" + // dafuk
|
||||||
")*", Pattern.CASE_INSENSITIVE)
|
")*", RegexOption.IGNORE_CASE)
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@ import android.text.Spannable
|
||||||
import android.text.style.URLSpan
|
import android.text.style.URLSpan
|
||||||
import android.text.util.Linkify
|
import android.text.util.Linkify
|
||||||
import androidx.core.text.util.LinkifyCompat
|
import androidx.core.text.util.LinkifyCompat
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
object VectorLinkify {
|
object VectorLinkify {
|
||||||
/**
|
/**
|
||||||
|
@ -95,7 +94,7 @@ object VectorLinkify {
|
||||||
createdSpans.add(LinkSpec(URLSpan(urlSpan.url), start, end))
|
createdSpans.add(LinkSpec(URLSpan(urlSpan.url), start, end))
|
||||||
}
|
}
|
||||||
|
|
||||||
LinkifyCompat.addLinks(spannable, VectorAutoLinkPatterns.GEO_URI, "geo:", arrayOf("geo:"), geoMatchFilter, null)
|
LinkifyCompat.addLinks(spannable, VectorAutoLinkPatterns.GEO_URI.toPattern(), "geo:", arrayOf("geo:"), geoMatchFilter, null)
|
||||||
spannable.forEachSpanIndexed { _, urlSpan, start, end ->
|
spannable.forEachSpanIndexed { _, urlSpan, start, end ->
|
||||||
spannable.removeSpan(urlSpan)
|
spannable.removeSpan(urlSpan)
|
||||||
createdSpans.add(LinkSpec(URLSpan(urlSpan.url), start, end))
|
createdSpans.add(LinkSpec(URLSpan(urlSpan.url), start, end))
|
||||||
|
@ -108,7 +107,7 @@ object VectorLinkify {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun pruneOverlaps(links: ArrayList<LinkSpec>) {
|
private fun pruneOverlaps(links: ArrayList<LinkSpec>) {
|
||||||
Collections.sort(links, COMPARATOR)
|
links.sortWith(COMPARATOR)
|
||||||
var len = links.size
|
var len = links.size
|
||||||
var i = 0
|
var i = 0
|
||||||
while (i < len - 1) {
|
while (i < len - 1) {
|
||||||
|
|
|
@ -30,7 +30,7 @@ import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
import im.vector.riotx.core.di.DaggerScreenComponent
|
import im.vector.riotx.core.di.DaggerScreenComponent
|
||||||
import im.vector.riotx.core.di.ScreenComponent
|
import im.vector.riotx.core.di.ScreenComponent
|
||||||
import im.vector.riotx.core.utils.DimensionConverter
|
import im.vector.riotx.core.utils.DimensionConverter
|
||||||
import java.util.*
|
import java.util.UUID
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add MvRx capabilities to bottomsheetdialog (like BaseMvRxFragment)
|
* Add MvRx capabilities to bottomsheetdialog (like BaseMvRxFragment)
|
||||||
|
|
|
@ -22,8 +22,9 @@ import im.vector.riotx.core.di.ActiveSessionHolder
|
||||||
import im.vector.riotx.core.resources.AppNameProvider
|
import im.vector.riotx.core.resources.AppNameProvider
|
||||||
import im.vector.riotx.core.resources.LocaleProvider
|
import im.vector.riotx.core.resources.LocaleProvider
|
||||||
import im.vector.riotx.core.resources.StringProvider
|
import im.vector.riotx.core.resources.StringProvider
|
||||||
import java.util.*
|
import java.util.UUID
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
private const val DEFAULT_PUSHER_FILE_TAG = "mobile"
|
private const val DEFAULT_PUSHER_FILE_TAG = "mobile"
|
||||||
|
|
||||||
|
@ -36,7 +37,7 @@ class PushersManager @Inject constructor(
|
||||||
|
|
||||||
fun registerPusherWithFcmKey(pushKey: String): UUID {
|
fun registerPusherWithFcmKey(pushKey: String): UUID {
|
||||||
val currentSession = activeSessionHolder.getActiveSession()
|
val currentSession = activeSessionHolder.getActiveSession()
|
||||||
var profileTag = DEFAULT_PUSHER_FILE_TAG + "_" + Math.abs(currentSession.myUserId.hashCode())
|
val profileTag = DEFAULT_PUSHER_FILE_TAG + "_" + abs(currentSession.myUserId.hashCode())
|
||||||
|
|
||||||
return currentSession.addHttpPusher(
|
return currentSession.addHttpPusher(
|
||||||
pushKey,
|
pushKey,
|
||||||
|
|
|
@ -18,7 +18,7 @@ package im.vector.riotx.core.resources
|
||||||
|
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import androidx.core.os.ConfigurationCompat
|
import androidx.core.os.ConfigurationCompat
|
||||||
import java.util.*
|
import java.util.Locale
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class LocaleProvider @Inject constructor(private val resources: Resources) {
|
class LocaleProvider @Inject constructor(private val resources: Resources) {
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
package im.vector.riotx.core.utils
|
package im.vector.riotx.core.utils
|
||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import java.util.*
|
import java.util.WeakHashMap
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple Debounced OnClickListener
|
* Simple Debounced OnClickListener
|
||||||
|
|
|
@ -59,9 +59,10 @@ fun initKnownEmojiHashSet(context: Context, done: (() -> Unit)? = null) {
|
||||||
val jsonAdapter = moshi.adapter(EmojiDataSource.EmojiData::class.java)
|
val jsonAdapter = moshi.adapter(EmojiDataSource.EmojiData::class.java)
|
||||||
val inputAsString = input.bufferedReader().use { it.readText() }
|
val inputAsString = input.bufferedReader().use { it.readText() }
|
||||||
val source = jsonAdapter.fromJson(inputAsString)
|
val source = jsonAdapter.fromJson(inputAsString)
|
||||||
knownEmojiSet = HashSet<String>()
|
knownEmojiSet = HashSet<String>().also {
|
||||||
source?.emojis?.values?.forEach {
|
source?.emojis?.mapTo(it) { (_, value) ->
|
||||||
knownEmojiSet?.add(it.emojiString())
|
value.emojiString()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
done?.invoke()
|
done?.invoke()
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,8 @@ import im.vector.riotx.R
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.Date
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open a url in the internet browser of the system
|
* Open a url in the internet browser of the system
|
||||||
|
|
|
@ -31,7 +31,7 @@ import im.vector.riotx.R
|
||||||
import im.vector.riotx.features.notifications.NotificationUtils
|
import im.vector.riotx.features.notifications.NotificationUtils
|
||||||
import im.vector.riotx.features.settings.VectorLocale
|
import im.vector.riotx.features.settings.VectorLocale
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.*
|
import java.util.Locale
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells if the application ignores battery optimizations.
|
* Tells if the application ignores battery optimizations.
|
||||||
|
|
|
@ -19,7 +19,7 @@ package im.vector.riotx.core.utils
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.text.format.Formatter
|
import android.text.format.Formatter
|
||||||
import java.util.*
|
import java.util.TreeMap
|
||||||
|
|
||||||
object TextUtils {
|
object TextUtils {
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ import im.vector.riotx.features.settings.FontScale
|
||||||
import im.vector.riotx.features.settings.VectorLocale
|
import im.vector.riotx.features.settings.VectorLocale
|
||||||
import im.vector.riotx.features.themes.ThemeUtils
|
import im.vector.riotx.features.themes.ThemeUtils
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.*
|
import java.util.Locale
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -18,10 +18,10 @@ package im.vector.riotx.features.crypto.keys
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import arrow.core.Try
|
|
||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.matrix.android.api.session.Session
|
||||||
import im.vector.matrix.android.internal.extensions.foldToCallback
|
import im.vector.matrix.android.internal.extensions.foldToCallback
|
||||||
|
import im.vector.matrix.android.internal.util.awaitCallback
|
||||||
import im.vector.riotx.core.files.addEntryToDownloadManager
|
import im.vector.riotx.core.files.addEntryToDownloadManager
|
||||||
import im.vector.riotx.core.files.writeToFile
|
import im.vector.riotx.core.files.writeToFile
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
@ -36,28 +36,20 @@ class KeysExporter(private val session: Session) {
|
||||||
* Export keys and return the file path with the callback
|
* Export keys and return the file path with the callback
|
||||||
*/
|
*/
|
||||||
fun export(context: Context, password: String, callback: MatrixCallback<String>) {
|
fun export(context: Context, password: String, callback: MatrixCallback<String>) {
|
||||||
session.exportRoomKeys(password, object : MatrixCallback<ByteArray> {
|
GlobalScope.launch(Dispatchers.Main) {
|
||||||
override fun onSuccess(data: ByteArray) {
|
runCatching {
|
||||||
GlobalScope.launch(Dispatchers.Main) {
|
val data = awaitCallback<ByteArray> { session.exportRoomKeys(password, it) }
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
Try {
|
val parentDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
|
||||||
val parentDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
|
val file = File(parentDir, "riotx-keys-" + System.currentTimeMillis() + ".txt")
|
||||||
val file = File(parentDir, "riotx-keys-" + System.currentTimeMillis() + ".txt")
|
|
||||||
|
|
||||||
writeToFile(data, file)
|
writeToFile(data, file)
|
||||||
|
|
||||||
addEntryToDownloadManager(context, file, "text/plain")
|
addEntryToDownloadManager(context, file, "text/plain")
|
||||||
|
|
||||||
file.absolutePath
|
file.absolutePath
|
||||||
}
|
|
||||||
}
|
|
||||||
.foldToCallback(callback)
|
|
||||||
}
|
}
|
||||||
}
|
}.foldToCallback(callback)
|
||||||
|
}
|
||||||
override fun onFailure(failure: Throwable) {
|
|
||||||
callback.onFailure(failure)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,10 +18,11 @@ package im.vector.riotx.features.crypto.keys
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import arrow.core.Try
|
|
||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.matrix.android.api.session.Session
|
||||||
import im.vector.matrix.android.internal.crypto.model.ImportRoomKeysResult
|
import im.vector.matrix.android.internal.crypto.model.ImportRoomKeysResult
|
||||||
|
import im.vector.matrix.android.internal.extensions.foldToCallback
|
||||||
|
import im.vector.matrix.android.internal.util.awaitCallback
|
||||||
import im.vector.riotx.core.intent.getMimeTypeFromUri
|
import im.vector.riotx.core.intent.getMimeTypeFromUri
|
||||||
import im.vector.riotx.core.resources.openResource
|
import im.vector.riotx.core.resources.openResource
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
@ -41,8 +42,8 @@ class KeysImporter(private val session: Session) {
|
||||||
password: String,
|
password: String,
|
||||||
callback: MatrixCallback<ImportRoomKeysResult>) {
|
callback: MatrixCallback<ImportRoomKeysResult>) {
|
||||||
GlobalScope.launch(Dispatchers.Main) {
|
GlobalScope.launch(Dispatchers.Main) {
|
||||||
withContext(Dispatchers.IO) {
|
runCatching {
|
||||||
Try {
|
withContext(Dispatchers.IO) {
|
||||||
val resource = openResource(context, uri, mimetype ?: getMimeTypeFromUri(context, uri))
|
val resource = openResource(context, uri, mimetype ?: getMimeTypeFromUri(context, uri))
|
||||||
|
|
||||||
if (resource?.mContentStream == null) {
|
if (resource?.mContentStream == null) {
|
||||||
|
@ -51,33 +52,17 @@ class KeysImporter(private val session: Session) {
|
||||||
|
|
||||||
val data: ByteArray
|
val data: ByteArray
|
||||||
try {
|
try {
|
||||||
data = ByteArray(resource.mContentStream!!.available())
|
data = resource.mContentStream!!.use { it.readBytes() }
|
||||||
resource.mContentStream!!.read(data)
|
|
||||||
resource.mContentStream!!.close()
|
|
||||||
|
|
||||||
data
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
try {
|
Timber.e(e, "## importKeys()")
|
||||||
resource.mContentStream!!.close()
|
|
||||||
} catch (e2: Exception) {
|
|
||||||
Timber.e(e2, "## importKeys()")
|
|
||||||
}
|
|
||||||
|
|
||||||
throw e
|
throw e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
awaitCallback<ImportRoomKeysResult> {
|
||||||
|
session.importRoomKeys(data, password, null, it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}.foldToCallback(callback)
|
||||||
.fold(
|
|
||||||
{
|
|
||||||
callback.onFailure(it)
|
|
||||||
},
|
|
||||||
{ byteArray ->
|
|
||||||
session.importRoomKeys(byteArray,
|
|
||||||
password,
|
|
||||||
null,
|
|
||||||
callback)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ import im.vector.riotx.core.epoxy.loadingItem
|
||||||
import im.vector.riotx.core.resources.StringProvider
|
import im.vector.riotx.core.resources.StringProvider
|
||||||
import im.vector.riotx.core.ui.list.GenericItem
|
import im.vector.riotx.core.ui.list.GenericItem
|
||||||
import im.vector.riotx.core.ui.list.genericItem
|
import im.vector.riotx.core.ui.list.genericItem
|
||||||
import java.util.*
|
import java.util.UUID
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class KeysBackupSettingsRecyclerViewController @Inject constructor(private val stringProvider: StringProvider,
|
class KeysBackupSettingsRecyclerViewController @Inject constructor(private val stringProvider: StringProvider,
|
||||||
|
|
|
@ -170,8 +170,8 @@ class KeysBackupSetupStep3Fragment : VectorBaseFragment() {
|
||||||
|
|
||||||
private fun exportRecoveryKeyToFile(data: String) {
|
private fun exportRecoveryKeyToFile(data: String) {
|
||||||
GlobalScope.launch(Dispatchers.Main) {
|
GlobalScope.launch(Dispatchers.Main) {
|
||||||
withContext(Dispatchers.IO) {
|
Try {
|
||||||
Try {
|
withContext(Dispatchers.IO) {
|
||||||
val parentDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
|
val parentDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
|
||||||
val file = File(parentDir, "recovery-key-" + System.currentTimeMillis() + ".txt")
|
val file = File(parentDir, "recovery-key-" + System.currentTimeMillis() + ".txt")
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,8 @@ import im.vector.riotx.features.home.room.detail.timeline.format.NoticeEventForm
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.MessageInformationData
|
import im.vector.riotx.features.home.room.detail.timeline.item.MessageInformationData
|
||||||
import im.vector.riotx.features.html.EventHtmlRenderer
|
import im.vector.riotx.features.html.EventHtmlRenderer
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.Date
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Quick reactions state
|
* Quick reactions state
|
||||||
|
|
|
@ -38,7 +38,7 @@ import im.vector.riotx.features.html.EventHtmlRenderer
|
||||||
import me.gujun.android.span.span
|
import me.gujun.android.span.span
|
||||||
import name.fraser.neil.plaintext.diff_match_patch
|
import name.fraser.neil.plaintext.diff_match_patch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.*
|
import java.util.Calendar
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Epoxy controller for edit history list
|
* Epoxy controller for edit history list
|
||||||
|
@ -94,7 +94,7 @@ class ViewEditHistoryEpoxyController(private val context: Context,
|
||||||
val body = cContent.second?.let { eventHtmlRenderer.render(it) }
|
val body = cContent.second?.let { eventHtmlRenderer.render(it) }
|
||||||
?: cContent.first
|
?: cContent.first
|
||||||
|
|
||||||
val nextEvent = if (index + 1 <= sourceEvents.lastIndex) sourceEvents[index + 1] else null
|
val nextEvent = sourceEvents.getOrNull(index + 1)
|
||||||
|
|
||||||
var spannedDiff: Spannable? = null
|
var spannedDiff: Spannable? = null
|
||||||
if (nextEvent != null && cContent.second == null /*No diff for html*/) {
|
if (nextEvent != null && cContent.second == null /*No diff for html*/) {
|
||||||
|
|
|
@ -30,7 +30,7 @@ import im.vector.riotx.core.platform.VectorViewModel
|
||||||
import im.vector.riotx.core.date.VectorDateFormatter
|
import im.vector.riotx.core.date.VectorDateFormatter
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.action.TimelineEventFragmentArgs
|
import im.vector.riotx.features.home.room.detail.timeline.action.TimelineEventFragmentArgs
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.*
|
import java.util.UUID
|
||||||
|
|
||||||
data class ViewEditHistoryViewState(
|
data class ViewEditHistoryViewState(
|
||||||
val eventId: String,
|
val eventId: String,
|
||||||
|
|
|
@ -33,7 +33,7 @@ import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.resources.StringProvider
|
import im.vector.riotx.core.resources.StringProvider
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.format.NoticeEventFormatter
|
import im.vector.riotx.features.home.room.detail.timeline.format.NoticeEventFormatter
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.*
|
import java.util.UUID
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -27,7 +27,7 @@ import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.di.ActiveSessionHolder
|
import im.vector.riotx.core.di.ActiveSessionHolder
|
||||||
import im.vector.riotx.core.extensions.vectorComponent
|
import im.vector.riotx.core.extensions.vectorComponent
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.*
|
import java.util.UUID
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -45,9 +45,9 @@ import im.vector.riotx.features.home.room.detail.RoomDetailActivity
|
||||||
import im.vector.riotx.features.home.room.detail.RoomDetailArgs
|
import im.vector.riotx.features.home.room.detail.RoomDetailArgs
|
||||||
import im.vector.riotx.features.settings.VectorPreferences
|
import im.vector.riotx.features.settings.VectorPreferences
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.*
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Util class for creating notifications.
|
* Util class for creating notifications.
|
||||||
|
@ -299,7 +299,7 @@ class NotificationUtils @Inject constructor(private val context: Context,
|
||||||
// use a generator for the private requestCode.
|
// use a generator for the private requestCode.
|
||||||
// When using 0, the intent is not created/launched when the user taps on the notification.
|
// When using 0, the intent is not created/launched when the user taps on the notification.
|
||||||
//
|
//
|
||||||
val pendingIntent = stackBuilder.getPendingIntent(Random().nextInt(1000), PendingIntent.FLAG_UPDATE_CURRENT)
|
val pendingIntent = stackBuilder.getPendingIntent(Random.nextInt(1000), PendingIntent.FLAG_UPDATE_CURRENT)
|
||||||
|
|
||||||
builder.setContentIntent(pendingIntent)
|
builder.setContentIntent(pendingIntent)
|
||||||
|
|
||||||
|
@ -599,7 +599,7 @@ class NotificationUtils @Inject constructor(private val context: Context,
|
||||||
val intent = HomeActivity.newIntent(context, clearNotification = true)
|
val intent = HomeActivity.newIntent(context, clearNotification = true)
|
||||||
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
|
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
|
||||||
intent.data = Uri.parse("foobar://tapSummary")
|
intent.data = Uri.parse("foobar://tapSummary")
|
||||||
return PendingIntent.getActivity(context, Random().nextInt(1000), intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
return PendingIntent.getActivity(context, Random.nextInt(1000), intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -46,7 +46,7 @@ import org.json.JSONObject
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.*
|
import java.io.*
|
||||||
import java.net.HttpURLConnection
|
import java.net.HttpURLConnection
|
||||||
import java.util.*
|
import java.util.Locale
|
||||||
import java.util.zip.GZIPOutputStream
|
import java.util.zip.GZIPOutputStream
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
|
@ -24,7 +24,9 @@ import java.io.File
|
||||||
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.Date
|
||||||
|
import java.util.Locale
|
||||||
|
import java.util.TimeZone
|
||||||
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.Inject
|
||||||
|
|
|
@ -51,7 +51,6 @@ import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class VectorSettingsGeneralFragment : VectorSettingsBaseFragment() {
|
class VectorSettingsGeneralFragment : VectorSettingsBaseFragment() {
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,8 @@ import im.vector.riotx.features.crypto.keysbackup.settings.KeysBackupManageActiv
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.text.DateFormat
|
import java.text.DateFormat
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.Date
|
||||||
|
import java.util.Locale
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class VectorSettingsSecurityPrivacyFragment : VectorSettingsBaseFragment() {
|
class VectorSettingsSecurityPrivacyFragment : VectorSettingsBaseFragment() {
|
||||||
|
|
|
@ -28,7 +28,6 @@ import androidx.core.graphics.drawable.DrawableCompat
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Util class for managing themes.
|
* Util class for managing themes.
|
||||||
|
@ -131,24 +130,16 @@ object ThemeUtils {
|
||||||
*/
|
*/
|
||||||
@ColorInt
|
@ColorInt
|
||||||
fun getColor(c: Context, @AttrRes colorAttribute: Int): Int {
|
fun getColor(c: Context, @AttrRes colorAttribute: Int): Int {
|
||||||
if (mColorByAttr.containsKey(colorAttribute)) {
|
return mColorByAttr.getOrPut(colorAttribute) {
|
||||||
return mColorByAttr[colorAttribute] as Int
|
try {
|
||||||
|
val color = TypedValue()
|
||||||
|
c.theme.resolveAttribute(colorAttribute, color, true)
|
||||||
|
color.data
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Timber.e(e, "Unable to get color")
|
||||||
|
ContextCompat.getColor(c, android.R.color.holo_red_dark)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var matchedColor: Int
|
|
||||||
|
|
||||||
try {
|
|
||||||
val color = TypedValue()
|
|
||||||
c.theme.resolveAttribute(colorAttribute, color, true)
|
|
||||||
matchedColor = color.data
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Timber.e(e, "Unable to get color")
|
|
||||||
matchedColor = ContextCompat.getColor(c, android.R.color.holo_red_dark)
|
|
||||||
}
|
|
||||||
|
|
||||||
mColorByAttr[colorAttribute] = matchedColor
|
|
||||||
|
|
||||||
return matchedColor
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAttribute(c: Context, @AttrRes attribute: Int): TypedValue? {
|
fun getAttribute(c: Context, @AttrRes attribute: Int): TypedValue? {
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 org.junit.Test
|
|
||||||
|
|
||||||
import org.junit.Assert.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Example local unit test, which will execute on the development machine (host).
|
|
||||||
*
|
|
||||||
* See [testing documentation](http://d.android.com/tools/testing).
|
|
||||||
*/
|
|
||||||
class ExampleUnitTest {
|
|
||||||
@Test
|
|
||||||
fun addition_isCorrect() {
|
|
||||||
assertEquals(4, 2 + 2)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue