Skip to content
Snippets Groups Projects
Commit 25b95f7d authored by Benoit Marty's avatar Benoit Marty
Browse files

Merge branch 'release/1.3.8' into main

parents 90a62470 1f0ab824
No related branches found
No related tags found
No related merge requests found
Showing
with 345 additions and 34 deletions
Please also refer to the Changelog of Element Android: https://github.com/vector-im/element-android/blob/main/CHANGES.md
Changes in Matrix-SDK 1.3.8 (2021-11-17)
===================================================
Imported from Element 1.3.8. (https://github.com/vector-im/element-android/releases/tag/v1.3.8)
SDK API changes ⚠️
------------------
- Add content scanner API from MSC1453
API documentation : https://github.com/matrix-org/matrix-content-scanner#api ([#4392](https://github.com/vector-im/element-android/issues/4392))
- Breaking SDK API change to PushRuleListener, the separated callbacks have been merged into one with a data class which includes all the previously separated push information ([#4401](https://github.com/vector-im/element-android/issues/4401))
Changes in Matrix-SDK 1.3.7 (2021-11-05)
===================================================
......
ext.versions = [
'minSdk' : 21,
'compileSdk' : 30,
'targetSdk' : 30,
'compileSdk' : 31,
'targetSdk' : 31,
'sourceCompat' : JavaVersion.VERSION_11,
'targetCompat' : JavaVersion.VERSION_11,
]
......@@ -11,13 +11,13 @@ def gradle = "7.0.3"
// Ref: https://kotlinlang.org/releases.html
def kotlin = "1.5.31"
def kotlinCoroutines = "1.5.2"
def dagger = "2.40"
def dagger = "2.40.1"
def retrofit = "2.9.0"
def arrow = "0.8.2"
def markwon = "4.6.2"
def moshi = "1.12.0"
def lifecycle = "2.2.0"
def rxBinding = "3.1.0"
def lifecycle = "2.4.0"
def flowBinding = "1.2.0"
def epoxy = "4.6.2"
def mavericks = "2.4.0"
def glide = "4.12.0"
......@@ -26,7 +26,7 @@ def jjwt = "0.11.2"
def vanniktechEmoji = "0.8.0"
// Testing
def mockk = "1.12.0"
def mockk = "1.12.1"
def espresso = "3.4.0"
def androidxTest = "1.4.0"
......@@ -41,22 +41,23 @@ ext.libs = [
jetbrains : [
'coroutinesCore' : "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutines",
'coroutinesAndroid' : "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinCoroutines",
'coroutinesRx2' : "org.jetbrains.kotlinx:kotlinx-coroutines-rx2:$kotlinCoroutines"
'coroutinesRx2' : "org.jetbrains.kotlinx:kotlinx-coroutines-rx2:$kotlinCoroutines",
'coroutinesTest' : "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinCoroutines"
],
androidx : [
'appCompat' : "androidx.appcompat:appcompat:1.3.1",
'core' : "androidx.core:core-ktx:1.6.0",
'core' : "androidx.core:core-ktx:1.7.0",
'recyclerview' : "androidx.recyclerview:recyclerview:1.2.1",
'exifinterface' : "androidx.exifinterface:exifinterface:1.3.3",
'fragmentKtx' : "androidx.fragment:fragment-ktx:1.3.6",
'constraintLayout' : "androidx.constraintlayout:constraintlayout:2.1.1",
'work' : "androidx.work:work-runtime-ktx:2.6.0",
'work' : "androidx.work:work-runtime-ktx:2.7.0",
'autoFill' : "androidx.autofill:autofill:1.1.0",
'preferenceKtx' : "androidx.preference:preference-ktx:1.1.1",
'junit' : "androidx.test.ext:junit:1.1.3",
'lifecycleExtensions' : "androidx.lifecycle:lifecycle-extensions:$lifecycle",
'lifecycleJava8' : "androidx.lifecycle:lifecycle-common-java8:$lifecycle",
'lifecycleLivedata' : "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1",
'lifecycleCommon' : "androidx.lifecycle:lifecycle-common:$lifecycle",
'lifecycleLivedata' : "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle",
'lifecycleProcess' : "androidx.lifecycle:lifecycle-process:$lifecycle",
'datastore' : "androidx.datastore:datastore:1.0.0",
'datastorepreferences' : "androidx.datastore:datastore-preferences:1.0.0",
'pagingRuntimeKtx' : "androidx.paging:paging-runtime-ktx:2.1.2",
......@@ -102,7 +103,6 @@ ext.libs = [
'epoxyProcessor' : "com.airbnb.android:epoxy-processor:$epoxy",
'epoxyPaging' : "com.airbnb.android:epoxy-paging:$epoxy",
'mavericks' : "com.airbnb.android:mavericks:$mavericks",
'mavericksRx' : "com.airbnb.android:mavericks-rxjava2:$mavericks",
'mavericksTesting' : "com.airbnb.android:mavericks-testing:$mavericks"
],
mockk : [
......@@ -115,13 +115,13 @@ ext.libs = [
'bigImageViewer' : "com.github.piasy:BigImageViewer:$bigImageViewer",
'glideImageLoader' : "com.github.piasy:GlideImageLoader:$bigImageViewer",
'progressPieIndicator' : "com.github.piasy:ProgressPieIndicator:$bigImageViewer",
'glideImageViewFactory' : "com.github.piasy:GlideImageViewFactory:$bigImageViewer"
'glideImageViewFactory' : "com.github.piasy:GlideImageViewFactory:$bigImageViewer",
'flowBinding' : "io.github.reactivecircus.flowbinding:flowbinding-android:$flowBinding",
'flowBindingAppcompat' : "io.github.reactivecircus.flowbinding:flowbinding-appcompat:$flowBinding",
'flowBindingMaterial' : "io.github.reactivecircus.flowbinding:flowbinding-material:$flowBinding"
],
jakewharton : [
'timber' : "com.jakewharton.timber:timber:5.0.1",
'rxbinding' : "com.jakewharton.rxbinding3:rxbinding:$rxBinding",
'rxbindingAppcompat' : "com.jakewharton.rxbinding3:rxbinding-appcompat:$rxBinding",
'rxbindingMaterial' : "com.jakewharton.rxbinding3:rxbinding-material:$rxBinding"
'timber' : "com.jakewharton.timber:timber:5.0.1"
],
jsonwebtoken: [
'jjwtApi' : "io.jsonwebtoken:jjwt-api:$jjwt",
......
......@@ -26,7 +26,7 @@ vector.httpLogLevel=NONE
# Ref: https://github.com/vanniktech/gradle-maven-publish-plugin
GROUP=org.matrix.android
POM_ARTIFACT_ID=matrix-android-sdk2
VERSION_NAME=1.3.7
VERSION_NAME=1.3.8
POM_PACKAGING=aar
......
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=a8da5b02437a60819cad23e10fc7e9cf32bcb57029d9cb277e26eeff76ce014b
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip
distributionSha256Sum=00b273629df4ce46e68df232161d5a7c4e495b9a029ce6e0420f071e21316867
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
......@@ -11,7 +11,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath "io.realm:realm-gradle-plugin:10.8.0"
classpath "io.realm:realm-gradle-plugin:10.8.1"
}
}
......@@ -47,6 +47,7 @@ android {
}
testOptions {
// Comment to run on Android 12
execution 'ANDROIDX_TEST_ORCHESTRATOR'
}
......@@ -109,8 +110,9 @@ dependencies {
implementation libs.androidx.appCompat
implementation libs.androidx.core
implementation libs.androidx.lifecycleExtensions
implementation libs.androidx.lifecycleJava8
// Lifecycle
implementation libs.androidx.lifecycleCommon
implementation libs.androidx.lifecycleProcess
// Network
implementation libs.squareup.retrofit
......@@ -159,10 +161,10 @@ dependencies {
implementation libs.apache.commonsImaging
// Phone number https://github.com/google/libphonenumber
implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.36'
implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.37'
testImplementation libs.tests.junit
testImplementation 'org.robolectric:robolectric:4.6.1'
testImplementation 'org.robolectric:robolectric:4.7'
//testImplementation 'org.robolectric:shadows-support-v4:3.0'
// Note: version sticks to 1.9.2 due to https://github.com/mockk/mockk/issues/281
testImplementation libs.mockk.mockk
......
......@@ -20,7 +20,18 @@ package org.matrix.android.sdk.api
* This class contains pattern to match Matrix Url, aka mxc urls
*/
object MatrixUrls {
/**
* "mxc" scheme, including "://". So "mxc://"
*/
const val MATRIX_CONTENT_URI_SCHEME = "mxc://"
/**
* Return true if the String starts with "mxc://"
*/
fun String.isMxcUrl() = startsWith(MATRIX_CONTENT_URI_SCHEME)
/**
* Remove the "mxc://" prefix. No op if the String is not a Mxc URL
*/
fun String.removeMxcPrefix() = removePrefix(MATRIX_CONTENT_URI_SCHEME)
}
......@@ -18,6 +18,8 @@ package org.matrix.android.sdk.api.failure
import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.contentscanner.ContentScannerError
import org.matrix.android.sdk.api.session.contentscanner.ScanFailure
import org.matrix.android.sdk.internal.di.MoshiProvider
import java.io.IOException
import javax.net.ssl.HttpsURLConnection
......@@ -100,3 +102,19 @@ fun Throwable.isRegistrationAvailabilityError(): Boolean {
error.code == MatrixError.M_INVALID_USERNAME ||
error.code == MatrixError.M_EXCLUSIVE)
}
/**
* Try to convert to a ScanFailure. Return null in the cases it's not possible
*/
fun Throwable.toScanFailure(): ScanFailure? {
return if (this is Failure.OtherServerError) {
tryOrNull {
MoshiProvider.providesMoshi()
.adapter(ContentScannerError::class.java)
.fromJson(errorBody)
}
?.let { ScanFailure(it, httpCode, this) }
} else {
null
}
}
/*
* Copyright 2021 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.matrix.android.sdk.api.pushrules
import org.matrix.android.sdk.api.pushrules.rest.PushRule
import org.matrix.android.sdk.api.session.events.model.Event
data class PushEvents(
val matchedEvents: List<Pair<Event, PushRule>>,
val roomsJoined: Collection<String>,
val roomsLeft: Collection<String>,
val redactedEventIds: List<String>
)
......@@ -51,11 +51,7 @@ interface PushRuleService {
// fun fulfilledBingRule(event: Event, rules: List<PushRule>): PushRule?
interface PushRuleListener {
fun onMatchRule(event: Event, actions: List<Action>)
fun onRoomJoined(roomId: String)
fun onRoomLeft(roomId: String)
fun onEventRedacted(redactedEventId: String)
fun batchFinish()
fun onEvents(pushEvents: PushEvents)
}
fun getKeywords(): LiveData<Set<String>>
......
......@@ -31,6 +31,7 @@ import org.matrix.android.sdk.api.session.cache.CacheService
import org.matrix.android.sdk.api.session.call.CallSignalingService
import org.matrix.android.sdk.api.session.content.ContentUploadStateTracker
import org.matrix.android.sdk.api.session.content.ContentUrlResolver
import org.matrix.android.sdk.api.session.contentscanner.ContentScannerService
import org.matrix.android.sdk.api.session.crypto.CryptoService
import org.matrix.android.sdk.api.session.events.EventService
import org.matrix.android.sdk.api.session.file.ContentDownloadStateTracker
......@@ -192,6 +193,11 @@ interface Session :
*/
fun cryptoService(): CryptoService
/**
* Returns the ContentScannerService associated with the session
*/
fun contentScannerService(): ContentScannerService
/**
* Returns the identity service associated with the session
*/
......
......@@ -16,6 +16,8 @@
package org.matrix.android.sdk.api.session.content
import org.matrix.android.sdk.internal.crypto.attachments.ElementToDecrypt
/**
* This interface defines methods for accessing content from the current session.
*/
......@@ -39,6 +41,15 @@ interface ContentUrlResolver {
*/
fun resolveFullSize(contentUrl: String?): String?
/**
* Get the ResolvedMethod to download a URL
*
* @param contentUrl the Matrix media content URI (in the form of "mxc://...").
* @param elementToDecrypt Encryption data may be required if you use a content scanner
* @return the Method to access resource, or null if invalid
*/
fun resolveForDownload(contentUrl: String?, elementToDecrypt: ElementToDecrypt? = null): ResolvedMethod?
/**
* Get the actual URL for accessing the thumbnail image of a given Matrix media content URI.
*
......@@ -49,4 +60,9 @@ interface ContentUrlResolver {
* @return the URL to access the described resource, or null if the url is invalid.
*/
fun resolveThumbnail(contentUrl: String?, width: Int, height: Int, method: ThumbnailMethod): String?
sealed class ResolvedMethod {
data class GET(val url: String) : ResolvedMethod()
data class POST(val url: String, val jsonBody: String) : ResolvedMethod()
}
}
/*
* Copyright 2021 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.matrix.android.sdk.api.session.contentscanner
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class ContentScannerError(
@Json(name = "info") val info: String? = null,
@Json(name = "reason") val reason: String? = null
) {
companion object {
// 502 The server failed to request media from the media repo.
const val REASON_MCS_MEDIA_REQUEST_FAILED = "MCS_MEDIA_REQUEST_FAILED"
/* 400 The server failed to decrypt the encrypted media downloaded from the media repo.*/
const val REASON_MCS_MEDIA_FAILED_TO_DECRYPT = "MCS_MEDIA_FAILED_TO_DECRYPT"
/* 403 The server scanned the downloaded media but the antivirus script returned a non-zero exit code.*/
const val REASON_MCS_MEDIA_NOT_CLEAN = "MCS_MEDIA_NOT_CLEAN"
/* 403 The provided encrypted_body could not be decrypted. The client should request the public key of the server and then retry (once).*/
const val REASON_MCS_BAD_DECRYPTION = "MCS_BAD_DECRYPTION"
/* 400 The request body contains malformed JSON.*/
const val REASON_MCS_MALFORMED_JSON = "MCS_MALFORMED_JSON"
}
}
class ScanFailure(val error: ContentScannerError, val httpCode: Int, cause: Throwable? = null) : Throwable(cause = cause)
// For Glide, which deals with Exception and not with Throwable
fun ScanFailure.toException() = Exception(this)
fun Throwable.toScanFailure() = this.cause as? ScanFailure
/*
* Copyright 2021 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.matrix.android.sdk.api.session.contentscanner
import androidx.lifecycle.LiveData
import org.matrix.android.sdk.api.util.Optional
import org.matrix.android.sdk.internal.crypto.attachments.ElementToDecrypt
interface ContentScannerService {
val serverPublicKey: String?
fun getContentScannerServer(): String?
fun setScannerUrl(url: String?)
fun enableScanner(enabled: Boolean)
fun isScannerEnabled(): Boolean
fun getLiveStatusForFile(mxcUrl: String, fetchIfNeeded: Boolean = true, fileInfo: ElementToDecrypt? = null): LiveData<Optional<ScanStatusInfo>>
fun getCachedScanResultForFile(mxcUrl: String): ScanStatusInfo?
/**
* Get the current public curve25519 key that the AV server is advertising.
* @param callback on success callback containing the server public key
*/
suspend fun getServerPublicKey(forceDownload: Boolean = false): String?
suspend fun getScanResultForAttachment(mxcUrl: String, fileInfo: ElementToDecrypt? = null): ScanStatusInfo
}
/*
* Copyright 2021 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.matrix.android.sdk.api.session.contentscanner
enum class ScanState {
TRUSTED,
INFECTED,
UNKNOWN,
IN_PROGRESS
}
data class ScanStatusInfo(
val state: ScanState,
val scanDateTimestamp: Long?,
val humanReadableMessage: String?
)
......@@ -102,6 +102,9 @@ object EventType {
// Relation Events
const val REACTION = "m.reaction"
// Poll
const val POLL_START = "org.matrix.msc3381.poll.start"
// Unwedging
internal const val DUMMY = "m.dummy"
......
/*
* Copyright 2021 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.matrix.android.sdk.api.session.room.model.message
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class MessagePollContent(
@Json(name = "org.matrix.msc3381.poll.start") val pollCreationInfo: PollCreationInfo? = null
)
/*
* Copyright 2021 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.matrix.android.sdk.api.session.room.model.message
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class PollAnswer(
@Json(name = "id") val id: String? = null,
@Json(name = "org.matrix.msc1767.text") val answer: String? = null
)
/*
* Copyright 2021 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.matrix.android.sdk.api.session.room.model.message
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class PollCreationInfo(
@Json(name = "question") val question: PollQuestion? = null,
@Json(name = "kind") val kind: String? = "org.matrix.msc3381.poll.disclosed",
@Json(name = "max_selections") val maxSelections: Int = 1,
@Json(name = "answers") val answers: List<PollAnswer>? = null
)
/*
* Copyright 2021 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.matrix.android.sdk.api.session.room.model.message
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class PollQuestion(
@Json(name = "org.matrix.msc1767.text") val question: String? = null
)
......@@ -20,7 +20,6 @@ import org.matrix.android.sdk.api.session.content.ContentAttachmentData
import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.room.model.message.MessageType
import org.matrix.android.sdk.api.session.room.model.message.OptionItem
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
import org.matrix.android.sdk.api.util.Cancelable
......@@ -84,10 +83,10 @@ interface SendService {
/**
* Send a poll to the room.
* @param question the question
* @param options list of (label, value)
* @param options list of options
* @return a [Cancelable]
*/
fun sendPoll(question: String, options: List<OptionItem>): Cancelable
fun sendPoll(question: String, options: List<String>): Cancelable
/**
* Method to send a poll response.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment