Merge branch 'release/0.7.0'

This commit is contained in:
Benoit Marty 2019-10-24 14:37:52 +02:00
commit 01452efd8d
1132 changed files with 12341 additions and 8569 deletions

View File

@ -54,4 +54,13 @@ steps:
# Code quality # Code quality
- label: "Code quality" - label: "Code quality"
command: "./tools/check/check_code_quality.sh" command:
- "./tools/check/check_code_quality.sh"
- label: "ktlint"
command:
- "curl -sSLO https://github.com/pinterest/ktlint/releases/download/0.34.2/ktlint && chmod a+x ktlint"
- "./ktlint --android --experimental -v"
plugins:
- docker#v3.1.0:
image: "openjdk"

32
.editorconfig Normal file
View File

@ -0,0 +1,32 @@
# For ktlint configuration. Ref: https://ktlint.github.io/
[*.{kt,kts}]
# possible values: number (e.g. 2), "unset" (makes ktlint ignore indentation completely)
indent_size=unset
# true (recommended) / false
insert_final_newline=true
# possible values: number (e.g. 120) (package name, imports & comments are ignored), "off"
# it's automatically set to 100 on `ktlint --android ...` (per Android Kotlin Style Guide)
max_line_length=off
# Comma-separated list of rules to disable (Since 0.34.0)
# Note that rules in any ruleset other than the standard ruleset will need to be prefixed
# by the ruleset identifier.
disabled_rules=no-wildcard-imports,no-multi-spaces,colon-spacing,chain-wrapping,import-ordering,experimental:annotation
# The following (so far identified) rules are kept:
# no-blank-line-before-rbrace
# final-newline
# no-consecutive-blank-lines
# comment-spacing
# filename
# comma-spacing
# paren-spacing
# op-spacing
# string-template
# no-unused-imports
# curly-spacing
# no-semi
# no-empty-class-body
# experimental:multiline-if-else
# experimental:no-empty-first-line-in-method-block

14
.gitignore vendored
View File

@ -1,14 +1,18 @@
*.iml *.iml
.gradle .gradle
/local.properties /local.properties
.idea/* # idea files: exclude everything except dictionnaries
/.idea/* .idea/caches
/.idea/libraries .idea/codeStyles
/.idea/modules.xml .idea/libraries
/.idea/workspace.xml .idea/*.xml
.DS_Store .DS_Store
/build /build
/captures /captures
.externalNativeBuild .externalNativeBuild
/tmp /tmp
ktlint
.idea/copyright/New_vector.xml
.idea/copyright/profiles_settings.xml

View File

@ -0,0 +1,19 @@
<component name="ProjectDictionaryState">
<dictionary name="bmarty">
<words>
<w>backstack</w>
<w>bytearray</w>
<w>ciphertext</w>
<w>decryptor</w>
<w>emoji</w>
<w>emojis</w>
<w>hmac</w>
<w>ktlint</w>
<w>linkified</w>
<w>linkify</w>
<w>megolm</w>
<w>pbkdf</w>
<w>pkcs</w>
</words>
</dictionary>
</component>

View File

@ -1,3 +1,29 @@
Changes in RiotX 0.7.0 (2019-10-24)
===================================================
Features:
- Share elements from other app to RiotX (#58)
- Read marker (#84)
- Add ability to report content (#515)
Improvements:
- Persist active tab between sessions (#503)
- Do not upload file too big for the homeserver (#587)
- Attachments: start using system pickers (#52)
- Mark all messages as read (#396)
Other changes:
- Accessibility improvements to read receipts in the room timeline and reactions emoji chooser
Bugfix:
- Fix issue on upload error in loop (#587)
- Fix opening a permalink: the targeted event is displayed twice (#556)
- Fix opening a permalink paginates all the history up to the last event (#282)
- after login, the icon in the top left is a green 'A' for (all communities) rather than my avatar (#267)
- Picture uploads are unreliable, pictures are shown in wrong aspect ratio on desktop client (#517)
- Invitation notifications are not dismissed automatically if room is joined from another client (#347)
- Opening links from RiotX reuses browser tab (#599)
Changes in RiotX 0.6.1 (2019-09-24) Changes in RiotX 0.6.1 (2019-09-24)
=================================================== ===================================================
@ -141,21 +167,21 @@ Mode details here: https://medium.com/@RiotChat/introducing-the-riotx-beta-for-a
Changes in RiotX 0.0.0 (2019-XX-XX) Changes in RiotX 0.0.0 (2019-XX-XX)
=================================================== ===================================================
Features: Features:
- -
Improvements: Improvements 🙌:
- -
Other changes: Other changes:
- -
Bugfix: Bugfix 🐛:
- -
Translations: Translations 🗣:
- -
Build: Build 🧱:
- -

View File

@ -40,19 +40,45 @@ Please add a line to the top of the file `CHANGES.md` describing your change.
Make sure the following commands execute without any error: Make sure the following commands execute without any error:
> ./tools/check/check_code_quality.sh #### Internal tool
> ./gradlew lintGplayRelease <pre>
./tools/check/check_code_quality.sh
</pre>
#### ktlint
<pre>
curl -sSLO https://github.com/pinterest/ktlint/releases/download/0.34.2/ktlint && chmod a+x ktlint
./ktlint --android --experimental -v
</pre>
Note that you can run
<pre>
./ktlint --android --experimental -v -F
</pre>
For ktlint to fix some detected errors for you (you still have to check and commit the fix of course)
#### lint
<pre>
./gradlew lintGplayRelease
./gradlew lintFdroidRelease
</pre>
### Unit tests ### Unit tests
Make sure the following commands execute without any error: Make sure the following commands execute without any error:
> ./gradlew testGplayReleaseUnitTest <pre>
./gradlew testGplayReleaseUnitTest
</pre>
### Tests ### Tests
RiotX is currently supported on Android Jelly Bean (API 16+): please test your change on an Android device (or Android emulator) running with API 16. Many issues can happen (including crashes) on older devices. RiotX is currently supported on Android KitKat (API 19+): please test your change on an Android device (or Android emulator) running with API 19. Many issues can happen (including crashes) on older devices.
Also, if possible, please test your change on a real device. Testing on Android emulator may not be sufficient. Also, if possible, please test your change on a real device. Testing on Android emulator may not be sufficient.
### Internationalisation ### Internationalisation

View File

@ -1,9 +1,7 @@
import javax.tools.JavaCompiler
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
ext.kotlin_version = '1.3.21' ext.kotlin_version = '1.3.50'
repositories { repositories {
google() google()
jcenter() jcenter()
@ -12,11 +10,11 @@ buildscript {
} }
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.4.1' classpath 'com.android.tools.build:gradle:3.5.1'
classpath 'com.google.gms:google-services:4.2.0' classpath 'com.google.gms:google-services:4.3.2'
classpath "com.airbnb.okreplay:gradle-plugin:1.4.0" classpath "com.airbnb.okreplay:gradle-plugin:1.5.0"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.6.2' classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.7.1'
classpath 'com.google.android.gms:oss-licenses-plugin:0.9.5' classpath 'com.google.android.gms:oss-licenses-plugin:0.9.5'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
@ -61,6 +59,11 @@ allprojects {
] ]
} }
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
// Warnings are potential errors, so stop ignoring them
kotlinOptions.allWarningsAsErrors = true
}
afterEvaluate { afterEvaluate {
extensions.findByName("kapt")?.arguments { extensions.findByName("kapt")?.arguments {
arg("dagger.gradle.incremental", "enabled") arg("dagger.gradle.incremental", "enabled")

View File

@ -1,6 +1,6 @@
#Tue Mar 19 09:53:05 CET 2019 #Fri Sep 27 10:10:35 CEST 2019
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip

View File

@ -5,8 +5,6 @@ apply plugin: 'kotlin-kapt'
android { android {
compileSdkVersion 28 compileSdkVersion 28
defaultConfig { defaultConfig {
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 28 targetSdkVersion 28
@ -14,7 +12,6 @@ android {
versionName "1.0" versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
buildTypes { buildTypes {
@ -29,12 +26,14 @@ android {
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8
} }
kotlinOptions {
jvmTarget = "1.8"
}
} }
dependencies { dependencies {
implementation project(":matrix-sdk-android") implementation project(":matrix-sdk-android")
implementation 'androidx.appcompat:appcompat:1.1.0-beta01' implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'io.reactivex.rxjava2:rxkotlin:2.3.0' implementation 'io.reactivex.rxjava2:rxkotlin:2.3.0'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
// Paging // Paging

View File

@ -20,7 +20,6 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import io.reactivex.Observable import io.reactivex.Observable
import io.reactivex.android.MainThreadDisposable import io.reactivex.android.MainThreadDisposable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers import io.reactivex.schedulers.Schedulers
private class LiveDataObservable<T>( private class LiveDataObservable<T>(
@ -60,4 +59,4 @@ private class LiveDataObservable<T>(
fun <T> LiveData<T>.asObservable(): Observable<T> { fun <T> LiveData<T>.asObservable(): Observable<T> {
return LiveDataObservable(this).observeOn(Schedulers.computation()) return LiveDataObservable(this).observeOn(Schedulers.computation())
} }

View File

@ -19,7 +19,6 @@ package im.vector.matrix.rx
import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.util.Cancelable import im.vector.matrix.android.api.util.Cancelable
import io.reactivex.CompletableEmitter import io.reactivex.CompletableEmitter
import io.reactivex.SingleEmitter
internal class MatrixCallbackCompletable<T>(private val completableEmitter: CompletableEmitter) : MatrixCallback<T> { internal class MatrixCallbackCompletable<T>(private val completableEmitter: CompletableEmitter) : MatrixCallback<T> {
@ -36,4 +35,4 @@ fun Cancelable.toCompletable(completableEmitter: CompletableEmitter) {
completableEmitter.setCancellable { completableEmitter.setCancellable {
this.cancel() this.cancel()
} }
} }

View File

@ -35,4 +35,4 @@ fun <T> Cancelable.toSingle(singleEmitter: SingleEmitter<T>) {
singleEmitter.setCancellable { singleEmitter.setCancellable {
this.cancel() this.cancel()
} }
} }

View File

@ -14,13 +14,11 @@
* limitations under the License. * limitations under the License.
*/ */
package im.vector.riotx.core.dialogs package im.vector.matrix.rx
import android.content.Context import im.vector.matrix.android.api.util.Optional
import io.reactivex.Observable
internal class DialogSendItemAdapter(context: Context, items: MutableList<DialogListItem>) : DialogAdapter(context) { fun <T : Any> Observable<Optional<T>>.unwrap(): Observable<T> {
return filter { it.hasValue() }.map { it.get() }
init {
addAll(items)
}
} }

View File

@ -22,25 +22,34 @@ import im.vector.matrix.android.api.session.room.model.ReadReceipt
import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.session.room.model.RoomSummary
import im.vector.matrix.android.api.session.room.send.UserDraft import im.vector.matrix.android.api.session.room.send.UserDraft
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.util.Optional
import io.reactivex.Observable import io.reactivex.Observable
import io.reactivex.Single import io.reactivex.Single
class RxRoom(private val room: Room) { class RxRoom(private val room: Room) {
fun liveRoomSummary(): Observable<RoomSummary> { fun liveRoomSummary(): Observable<Optional<RoomSummary>> {
return room.liveRoomSummary().asObservable() return room.getRoomSummaryLive().asObservable()
} }
fun liveRoomMemberIds(): Observable<List<String>> { fun liveRoomMemberIds(): Observable<List<String>> {
return room.getRoomMemberIdsLive().asObservable() return room.getRoomMemberIdsLive().asObservable()
} }
fun liveAnnotationSummary(eventId: String): Observable<EventAnnotationsSummary> { fun liveAnnotationSummary(eventId: String): Observable<Optional<EventAnnotationsSummary>> {
return room.getEventSummaryLive(eventId).asObservable() return room.getEventSummaryLive(eventId).asObservable()
} }
fun liveTimelineEvent(eventId: String): Observable<TimelineEvent> { fun liveTimelineEvent(eventId: String): Observable<Optional<TimelineEvent>> {
return room.liveTimeLineEvent(eventId).asObservable() return room.getTimeLineEventLive(eventId).asObservable()
}
fun liveReadMarker(): Observable<Optional<String>> {
return room.getReadMarkerLive().asObservable()
}
fun liveReadReceipt(): Observable<Optional<String>> {
return room.getMyReadReceiptLive().asObservable()
} }
fun loadRoomMembersIfNeeded(): Single<Unit> = Single.create { fun loadRoomMembersIfNeeded(): Single<Unit> = Single.create {
@ -58,9 +67,8 @@ class RxRoom(private val room: Room) {
fun liveDrafts(): Observable<List<UserDraft>> { fun liveDrafts(): Observable<List<UserDraft>> {
return room.getDraftsLive().asObservable() return room.getDraftsLive().asObservable()
} }
} }
fun Room.rx(): RxRoom { fun Room.rx(): RxRoom {
return RxRoom(this) return RxRoom(this)
} }

View File

@ -24,6 +24,7 @@ import im.vector.matrix.android.api.session.room.model.RoomSummary
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
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.model.User import im.vector.matrix.android.api.session.user.model.User
import im.vector.matrix.android.api.util.Optional
import io.reactivex.Observable import io.reactivex.Observable
import io.reactivex.Single import io.reactivex.Single
@ -45,6 +46,10 @@ class RxSession(private val session: Session) {
return session.livePushers().asObservable() return session.livePushers().asObservable()
} }
fun liveUser(userId: String): Observable<Optional<User>> {
return session.liveUser(userId).asObservable().distinctUntilChanged()
}
fun liveUsers(): Observable<List<User>> { fun liveUsers(): Observable<List<User>> {
return session.liveUsers().asObservable() return session.liveUsers().asObservable()
} }
@ -66,9 +71,8 @@ class RxSession(private val session: Session) {
fun joinRoom(roomId: String, viaServers: List<String> = emptyList()): Single<Unit> = Single.create { fun joinRoom(roomId: String, viaServers: List<String> = emptyList()): Single<Unit> = Single.create {
session.joinRoom(roomId, viaServers, MatrixCallbackSingle(it)).toSingle(it) session.joinRoom(roomId, viaServers, MatrixCallbackSingle(it)).toSingle(it)
} }
} }
fun Session.rx(): RxSession { fun Session.rx(): RxSession {
return RxSession(this) return RxSession(this)
} }

View File

@ -67,6 +67,10 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8
} }
kotlinOptions {
jvmTarget = "1.8"
}
} }
static def gitRevision() { static def gitRevision() {
@ -86,41 +90,43 @@ static def gitRevisionDate() {
dependencies { dependencies {
def arrow_version = "0.8.0" def arrow_version = "0.8.2"
def support_version = '1.1.0-beta01'
def moshi_version = '1.8.0' def moshi_version = '1.8.0'
def lifecycle_version = '2.0.0' def lifecycle_version = '2.1.0'
def coroutines_version = "1.0.1" def coroutines_version = "1.3.2"
def markwon_version = '3.0.0' def markwon_version = '3.1.0'
def daggerVersion = '2.23.1' def daggerVersion = '2.24'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
implementation "androidx.appcompat:appcompat:1.1.0-rc01" implementation "androidx.appcompat:appcompat:1.1.0"
implementation "androidx.recyclerview:recyclerview:1.1.0-beta01" implementation "androidx.recyclerview:recyclerview:1.1.0-beta05"
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version" implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version" kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
// Network // Network
implementation 'com.squareup.retrofit2:retrofit:2.6.0' implementation 'com.squareup.retrofit2:retrofit:2.6.2'
implementation 'com.squareup.retrofit2:converter-moshi:2.4.0' implementation 'com.squareup.retrofit2:converter-moshi:2.6.2'
implementation 'com.squareup.okhttp3:okhttp:3.14.1' implementation 'com.squareup.okhttp3:okhttp:4.2.2'
implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0' implementation 'com.squareup.okhttp3:logging-interceptor:4.2.2'
implementation 'com.novoda:merlin:1.2.0' implementation 'com.novoda:merlin:1.2.0'
implementation "com.squareup.moshi:moshi-adapters:$moshi_version" implementation "com.squareup.moshi:moshi-adapters:$moshi_version"
kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version" kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version"
implementation "ru.noties.markwon:core:$markwon_version" implementation "ru.noties.markwon:core:$markwon_version"
// Image
implementation 'androidx.exifinterface:exifinterface:1.0.0'
// Database // Database
implementation 'com.github.Zhuinden:realm-monarchy:0.5.1' implementation 'com.github.Zhuinden:realm-monarchy:0.5.1'
kapt 'dk.ilios:realmfieldnameshelper:1.1.1' kapt 'dk.ilios:realmfieldnameshelper:1.1.1'
// Work // Work
implementation "androidx.work:work-runtime-ktx:2.1.0-rc01" implementation "androidx.work:work-runtime-ktx:2.3.0-alpha01"
// FP // FP
implementation "io.arrow-kt:arrow-core:$arrow_version" implementation "io.arrow-kt:arrow-core:$arrow_version"
@ -132,24 +138,24 @@ dependencies {
// DI // DI
implementation "com.google.dagger:dagger:$daggerVersion" implementation "com.google.dagger:dagger:$daggerVersion"
kapt "com.google.dagger:dagger-compiler:$daggerVersion" kapt "com.google.dagger:dagger-compiler:$daggerVersion"
compileOnly 'com.squareup.inject:assisted-inject-annotations-dagger2:0.4.0' compileOnly 'com.squareup.inject:assisted-inject-annotations-dagger2:0.5.0'
kapt 'com.squareup.inject:assisted-inject-processor-dagger2:0.4.0' kapt 'com.squareup.inject:assisted-inject-processor-dagger2:0.5.0'
// Logging // Logging
implementation 'com.jakewharton.timber:timber:4.7.1' implementation 'com.jakewharton.timber:timber:4.7.1'
implementation 'com.facebook.stetho:stetho-okhttp3:1.5.0' implementation 'com.facebook.stetho:stetho-okhttp3:1.5.1'
// Bus // Bus
implementation 'org.greenrobot:eventbus:3.1.1' implementation 'org.greenrobot:eventbus:3.1.1'
debugImplementation 'com.airbnb.okreplay:okreplay:1.4.0' debugImplementation 'com.airbnb.okreplay:okreplay:1.5.0'
releaseImplementation 'com.airbnb.okreplay:noop:1.4.0' releaseImplementation 'com.airbnb.okreplay:noop:1.5.0'
androidTestImplementation 'com.airbnb.okreplay:espresso:1.4.0' androidTestImplementation 'com.airbnb.okreplay:espresso:1.5.0'
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
testImplementation 'org.robolectric:robolectric:4.0.2' 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.8.13.kotlin13" testImplementation 'io.mockk:mockk:1.9.3.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"
@ -159,7 +165,7 @@ 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.8.13.kotlin13" androidTestImplementation 'io.mockk:mockk-android:1.9.3.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"

View File

@ -28,4 +28,4 @@ interface InstrumentedTest {
fun cacheDir(): File { fun cacheDir(): File {
return context().cacheDir return context().cacheDir
} }
} }

View File

@ -29,4 +29,4 @@ class OkReplayRuleChainNoActivity(
return RuleChain.outerRule(PermissionRule(configuration)) return RuleChain.outerRule(PermissionRule(configuration))
.around(RecorderRule(configuration)) .around(RecorderRule(configuration))
} }
} }

View File

@ -19,4 +19,4 @@ package im.vector.matrix.android
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Dispatchers.Main
internal val testCoroutineDispatchers = MatrixCoroutineDispatchers(Main, Main, Main, Main, Main) internal val testCoroutineDispatchers = MatrixCoroutineDispatchers(Main, Main, Main, Main, Main)

View File

@ -28,7 +28,6 @@ import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
internal class AuthenticatorTest : InstrumentedTest { internal class AuthenticatorTest : InstrumentedTest {
@ -50,7 +49,6 @@ internal class AuthenticatorTest : InstrumentedTest {
@UiThreadTest @UiThreadTest
@OkReplay(tape = "auth", mode = TapeMode.READ_WRITE) @OkReplay(tape = "auth", mode = TapeMode.READ_WRITE)
fun auth() { fun auth() {
} }
companion object { companion object {
@ -59,6 +57,4 @@ internal class AuthenticatorTest : InstrumentedTest {
val grantExternalStoragePermissionRule: GrantPermissionRule = val grantExternalStoragePermissionRule: GrantPermissionRule =
GrantPermissionRule.grant(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) GrantPermissionRule.grant(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
} }
}
}

View File

@ -41,4 +41,4 @@ internal class CryptoStoreHelper {
refreshToken = null, refreshToken = null,
deviceId = "deviceId_sample" deviceId = "deviceId_sample"
) )
} }

View File

@ -114,4 +114,4 @@ class CryptoStoreTest {
olmAccount1.releaseAccount() olmAccount1.releaseAccount()
olmAccount2.releaseAccount() olmAccount2.releaseAccount()
} }
} }

View File

@ -62,8 +62,6 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
JsonCanonicalizer.canonicalize("{\"a\":\"\\\"\"}")) JsonCanonicalizer.canonicalize("{\"a\":\"\\\"\"}"))
} }
/* ========================================================================================== /* ==========================================================================================
* Test from https://matrix.org/docs/spec/appendices.html#examples * Test from https://matrix.org/docs/spec/appendices.html#examples
* ========================================================================================== */ * ========================================================================================== */
@ -74,7 +72,6 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
JsonCanonicalizer.canonicalize("""{}""")) JsonCanonicalizer.canonicalize("""{}"""))
} }
@Test @Test
fun matrixOrg002Test() { fun matrixOrg002Test() {
assertEquals("""{"one":1,"two":"Two"}""", assertEquals("""{"one":1,"two":"Two"}""",
@ -84,7 +81,6 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
}""")) }"""))
} }
@Test @Test
fun matrixOrg003Test() { fun matrixOrg003Test() {
assertEquals("""{"a":"1","b":"2"}""", assertEquals("""{"a":"1","b":"2"}""",
@ -94,14 +90,12 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
}""")) }"""))
} }
@Test @Test
fun matrixOrg004Test() { fun matrixOrg004Test() {
assertEquals("""{"a":"1","b":"2"}""", assertEquals("""{"a":"1","b":"2"}""",
JsonCanonicalizer.canonicalize("""{"b":"2","a":"1"}""")) JsonCanonicalizer.canonicalize("""{"b":"2","a":"1"}"""))
} }
@Test @Test
fun matrixOrg005Test() { fun matrixOrg005Test() {
assertEquals("""{"auth":{"mxid":"@john.doe:example.com","profile":{"display_name":"John Doe","three_pids":[{"address":"john.doe@example.org","medium":"email"},{"address":"123456789","medium":"msisdn"}]},"success":true}}""", assertEquals("""{"auth":{"mxid":"@john.doe:example.com","profile":{"display_name":"John Doe","three_pids":[{"address":"john.doe@example.org","medium":"email"},{"address":"123456789","medium":"msisdn"}]},"success":true}}""",
@ -126,7 +120,6 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
}""")) }"""))
} }
@Test @Test
fun matrixOrg006Test() { fun matrixOrg006Test() {
assertEquals("""{"a":"日本語"}""", assertEquals("""{"a":"日本語"}""",
@ -135,7 +128,6 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
}""")) }"""))
} }
@Test @Test
fun matrixOrg007Test() { fun matrixOrg007Test() {
assertEquals("""{"日":1,"本":2}""", assertEquals("""{"日":1,"本":2}""",
@ -145,7 +137,6 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
}""")) }"""))
} }
@Test @Test
fun matrixOrg008Test() { fun matrixOrg008Test() {
assertEquals("""{"a":"日"}""", assertEquals("""{"a":"日"}""",
@ -159,4 +150,4 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
"a": null "a": null
}""")) }"""))
} }
} }

View File

@ -35,7 +35,6 @@ import org.junit.Before
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
internal class ChunkEntityTest : InstrumentedTest { internal class ChunkEntityTest : InstrumentedTest {
@ -48,7 +47,6 @@ internal class ChunkEntityTest : InstrumentedTest {
monarchy = Monarchy.Builder().setRealmConfiguration(testConfig).build() monarchy = Monarchy.Builder().setRealmConfiguration(testConfig).build()
} }
@Test @Test
fun add_shouldAdd_whenNotAlreadyIncluded() { fun add_shouldAdd_whenNotAlreadyIncluded() {
monarchy.runTransactionSync { realm -> monarchy.runTransactionSync { realm ->
@ -194,5 +192,4 @@ internal class ChunkEntityTest : InstrumentedTest {
chunk1.nextToken shouldEqual nextToken chunk1.nextToken shouldEqual nextToken
} }
} }
}
}

View File

@ -32,6 +32,4 @@ internal class FakeGetContextOfEventTask constructor(private val tokenChunkEvent
) )
return tokenChunkEventPersistor.insertInDb(tokenChunkEvent, params.roomId, PaginationDirection.BACKWARDS) return tokenChunkEventPersistor.insertInDb(tokenChunkEvent, params.roomId, PaginationDirection.BACKWARDS)
} }
}
}

View File

@ -28,6 +28,4 @@ internal class FakePaginationTask @Inject constructor(private val tokenChunkEven
val tokenChunkEvent = FakeTokenChunkEvent(params.from, Random.nextLong(System.currentTimeMillis()).toString(), fakeEvents) val tokenChunkEvent = FakeTokenChunkEvent(params.from, Random.nextLong(System.currentTimeMillis()).toString(), fakeEvents)
return tokenChunkEventPersistor.insertInDb(tokenChunkEvent, params.roomId, params.direction) return tokenChunkEventPersistor.insertInDb(tokenChunkEvent, params.roomId, params.direction)
} }
} }

View File

@ -23,4 +23,4 @@ internal data class FakeTokenChunkEvent(override val start: String?,
override val end: String?, override val end: String?,
override val events: List<Event> = emptyList(), override val events: List<Event> = emptyList(),
override val stateEvents: List<Event> = emptyList() override val stateEvents: List<Event> = emptyList()
) : TokenChunkEvent ) : TokenChunkEvent

View File

@ -88,6 +88,4 @@ object RoomDataHelper {
roomEntity.addOrUpdate(chunkEntity) roomEntity.addOrUpdate(chunkEntity)
} }
} }
}
}

View File

@ -81,6 +81,4 @@ internal class TimelineTest : InstrumentedTest {
// timelineEvents.size shouldEqual initialLoad + paginationCount // timelineEvents.size shouldEqual initialLoad + paginationCount
// timeline.dispose() // timeline.dispose()
// } // }
}
}

View File

@ -22,6 +22,7 @@ import okhttp3.Interceptor
import okhttp3.Response import okhttp3.Response
import okhttp3.logging.HttpLoggingInterceptor import okhttp3.logging.HttpLoggingInterceptor
import okio.Buffer import okio.Buffer
import timber.log.Timber
import java.io.IOException import java.io.IOException
import java.nio.charset.Charset import java.nio.charset.Charset
import javax.inject.Inject import javax.inject.Inject
@ -51,27 +52,33 @@ internal class CurlLoggingInterceptor @Inject constructor(private val logger: Ht
var compressed = false var compressed = false
var curlCmd = "curl" var curlCmd = "curl"
if (curlOptions != null) { curlOptions?.let {
curlCmd += " " + curlOptions!! curlCmd += " $it"
} }
curlCmd += " -X " + request.method() curlCmd += " -X " + request.method
val requestBody = request.body() val requestBody = request.body
if (requestBody != null) { if (requestBody != null) {
val buffer = Buffer() if (requestBody.contentLength() > 100_000) {
requestBody.writeTo(buffer) Timber.w("Unable to log curl command data, size is too big (${requestBody.contentLength()})")
var charset: Charset? = UTF8 // Ensure the curl command will failed
val contentType = requestBody.contentType() curlCmd += "DATA IS TOO BIG"
if (contentType != null) { } else {
charset = contentType.charset(UTF8) val buffer = Buffer()
requestBody.writeTo(buffer)
var charset: Charset? = UTF8
val contentType = requestBody.contentType()
if (contentType != null) {
charset = contentType.charset(UTF8)
}
// try to keep to a single line and use a subshell to preserve any line breaks
curlCmd += " --data $'" + buffer.readString(charset!!).replace("\n", "\\n") + "'"
} }
// try to keep to a single line and use a subshell to preserve any line breaks
curlCmd += " --data $'" + buffer.readString(charset!!).replace("\n", "\\n") + "'"
} }
val headers = request.headers() val headers = request.headers
var i = 0 var i = 0
val count = headers.size() val count = headers.size
while (i < count) { while (i < count) {
val name = headers.name(i) val name = headers.name(i)
val value = headers.value(i) val value = headers.value(i)
@ -82,7 +89,7 @@ internal class CurlLoggingInterceptor @Inject constructor(private val logger: Ht
i++ i++
} }
curlCmd += ((if (compressed) " --compressed " else " ") + "'" + request.url().toString() curlCmd += ((if (compressed) " --compressed " else " ") + "'" + request.url.toString()
// Replace localhost for emulator by localhost for shell // Replace localhost for emulator by localhost for shell
.replace("://10.0.2.2:8080/".toRegex(), "://127.0.0.1:8080/") .replace("://10.0.2.2:8080/".toRegex(), "://127.0.0.1:8080/")
+ "'") + "'")
@ -90,7 +97,7 @@ internal class CurlLoggingInterceptor @Inject constructor(private val logger: Ht
// Add Json formatting // Add Json formatting
curlCmd += " | python -m json.tool" curlCmd += " | python -m json.tool"
logger.log("--- cURL (" + request.url() + ")") logger.log("--- cURL (" + request.url + ")")
logger.log(curlCmd) logger.log(curlCmd)
return chain.proceed(request) return chain.proceed(request)

View File

@ -51,7 +51,6 @@ class FormattedJsonHttpLogger : HttpLoggingInterceptor.Logger {
// Finally this is not a JSON string... // Finally this is not a JSON string...
Timber.e(e) Timber.e(e)
} }
} else if (message.startsWith("[")) { } else if (message.startsWith("[")) {
// JSON Array detected // JSON Array detected
try { try {
@ -61,7 +60,6 @@ class FormattedJsonHttpLogger : HttpLoggingInterceptor.Logger {
// Finally not JSON... // Finally not JSON...
Timber.e(e) Timber.e(e)
} }
} }
// Else not a json string to log // Else not a json string to log
} }
@ -73,4 +71,4 @@ class FormattedJsonHttpLogger : HttpLoggingInterceptor.Logger {
Timber.v(s) Timber.v(s)
} }
} }
} }

View File

@ -38,7 +38,6 @@ data class MatrixConfiguration(
interface Provider { interface Provider {
fun providesMatrixConfiguration(): MatrixConfiguration fun providesMatrixConfiguration(): MatrixConfiguration
} }
} }
/** /**
@ -98,5 +97,4 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo
return BuildConfig.VERSION_NAME + " (" + BuildConfig.GIT_SDK_REVISION + ")" return BuildConfig.VERSION_NAME + " (" + BuildConfig.GIT_SDK_REVISION + ")"
} }
} }
} }

View File

@ -27,7 +27,7 @@ interface MatrixCallback<in T> {
* @param data the data successfully returned from the async function * @param data the data successfully returned from the async function
*/ */
fun onSuccess(data: T) { fun onSuccess(data: T) {
//no-op // no-op
} }
/** /**
@ -35,7 +35,6 @@ interface MatrixCallback<in T> {
* @param failure the failure data returned from the async function * @param failure the failure data returned from the async function
*/ */
fun onFailure(failure: Throwable) { fun onFailure(failure: Throwable) {
//no-op // no-op
} }
}
}

View File

@ -16,7 +16,6 @@
package im.vector.matrix.android.api package im.vector.matrix.android.api
/** /**
* This class contains pattern to match the different Matrix ids * This class contains pattern to match the different Matrix ids
*/ */
@ -154,6 +153,5 @@ object MatrixPatterns {
return if (index == -1) { return if (index == -1) {
null null
} else matrixId.substring(index + 1) } else matrixId.substring(index + 1)
} }
} }

View File

@ -68,4 +68,4 @@ interface Authenticator {
* Create a session after a SSO successful login * Create a session after a SSO successful login
*/ */
fun createSessionFromSso(credentials: Credentials, homeServerConnectionConfig: HomeServerConnectionConfig): Session fun createSessionFromSso(credentials: Credentials, homeServerConnectionConfig: HomeServerConnectionConfig): Session
} }

View File

@ -253,13 +253,5 @@ data class HomeServerConnectionConfig(
forceUsageTlsVersions forceUsageTlsVersions
) )
} }
} }
} }

View File

@ -37,4 +37,4 @@ object DatedObjectComparators {
(datedObject2.date - datedObject1.date).toInt() (datedObject2.date - datedObject1.date).toInt()
} }
} }
} }

View File

@ -19,7 +19,6 @@ 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.Collections
/* ========================================================================================== /* ==========================================================================================
* MXDeviceInfo * MXDeviceInfo
@ -29,7 +28,6 @@ fun MXDeviceInfo.getFingerprintHumanReadable() = fingerprint()
?.chunked(4) ?.chunked(4)
?.joinToString(separator = " ") ?.joinToString(separator = " ")
fun MutableList<DeviceInfo>.sortByLastSeen() {
fun List<DeviceInfo>.sortByLastSeen() { sortWith(DatedObjectComparators.descComparator)
Collections.sort(this, DatedObjectComparators.descComparator) }
}

View File

@ -19,4 +19,4 @@ package im.vector.matrix.android.api.failure
// This data class will be sent to the bus // This data class will be sent to the bus
data class ConsentNotGivenError( data class ConsentNotGivenError(
val consentUri: String val consentUri: String
) )

View File

@ -42,5 +42,4 @@ sealed class Failure(cause: Throwable? = null) : Throwable(cause = cause) {
data class CryptoError(val error: MXCryptoError) : Failure(error) data class CryptoError(val error: MXCryptoError) : Failure(error)
abstract class FeatureFailure : Failure() abstract class FeatureFailure : Failure()
}
}

View File

@ -33,7 +33,6 @@ data class MatrixError(
@Json(name = "limit_type") val limitType: String? = null, @Json(name = "limit_type") val limitType: String? = null,
@Json(name = "admin_contact") val adminUri: String? = null) { @Json(name = "admin_contact") val adminUri: String? = null) {
companion object { companion object {
const val FORBIDDEN = "M_FORBIDDEN" const val FORBIDDEN = "M_FORBIDDEN"
const val UNKNOWN = "M_UNKNOWN" const val UNKNOWN = "M_UNKNOWN"
@ -64,4 +63,4 @@ data class MatrixError(
// Possible value for "limit_type" // Possible value for "limit_type"
const val LIMIT_TYPE_MAU = "monthly_active_user" const val LIMIT_TYPE_MAU = "monthly_active_user"
} }
} }

View File

@ -25,4 +25,4 @@ interface ProgressListener {
* @param total * @param total
*/ */
fun onProgress(progress: Int, total: Int) fun onProgress(progress: Int, total: Int)
} }

View File

@ -31,4 +31,4 @@ interface StepProgressListener {
* @param step The current step, containing progress data if available. Else you should consider progress as indeterminate * @param step The current step, containing progress data if available. Else you should consider progress as indeterminate
*/ */
fun onStepProgress(step: Step) fun onStepProgress(step: Step)
} }

View File

@ -30,9 +30,9 @@ object MatrixLinkify {
* *
* @param spannable the text in which the matrix items has to be clickable. * @param spannable the text in which the matrix items has to be clickable.
*/ */
fun addLinks(spannable: Spannable?, callback: MatrixPermalinkSpan.Callback?): Boolean { fun addLinks(spannable: Spannable, callback: MatrixPermalinkSpan.Callback?): Boolean {
// sanity checks // sanity checks
if (spannable.isNullOrEmpty()) { if (spannable.isEmpty()) {
return false return false
} }
val text = spannable.toString() val text = spannable.toString()
@ -51,5 +51,4 @@ object MatrixLinkify {
} }
return hasMatch return hasMatch
} }
}
}

View File

@ -35,6 +35,4 @@ class MatrixPermalinkSpan(private val url: String,
override fun onClick(widget: View) { override fun onClick(widget: View) {
callback?.onUrlClicked(url) callback?.onUrlClicked(url)
} }
}
}

View File

@ -33,5 +33,4 @@ sealed class PermalinkData {
data class GroupLink(val groupId: String) : PermalinkData() data class GroupLink(val groupId: String) : PermalinkData()
data class FallbackLink(val uri: Uri) : PermalinkData() data class FallbackLink(val uri: Uri) : PermalinkData()
} }

View File

@ -16,7 +16,6 @@
package im.vector.matrix.android.api.permalinks package im.vector.matrix.android.api.permalinks
import android.text.TextUtils
import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.events.model.Event
/** /**
@ -48,10 +47,9 @@ object PermalinkFactory {
* @return the permalink, or null in case of error * @return the permalink, or null in case of error
*/ */
fun createPermalink(id: String): String? { fun createPermalink(id: String): String? {
return if (TextUtils.isEmpty(id)) { return if (id.isEmpty()) {
null null
} else MATRIX_TO_URL_BASE + escape(id) } else MATRIX_TO_URL_BASE + escape(id)
} }
/** /**
@ -72,16 +70,14 @@ object PermalinkFactory {
* @param url the universal link, Ex: "https://matrix.to/#/@benoit:matrix.org" * @param url the universal link, Ex: "https://matrix.to/#/@benoit:matrix.org"
* @return the id from the url, ex: "@benoit:matrix.org", or null if the url is not a permalink * @return the id from the url, ex: "@benoit:matrix.org", or null if the url is not a permalink
*/ */
fun getLinkedId(url: String?): String? { fun getLinkedId(url: String): String? {
val isSupported = url != null && url.startsWith(MATRIX_TO_URL_BASE) val isSupported = url.startsWith(MATRIX_TO_URL_BASE)
return if (isSupported) { return if (isSupported) {
url!!.substring(MATRIX_TO_URL_BASE.length) url.substring(MATRIX_TO_URL_BASE.length)
} else null } else null
} }
/** /**
* Escape '/' in id, because it is used as a separator * Escape '/' in id, because it is used as a separator
* *
@ -89,6 +85,6 @@ object PermalinkFactory {
* @return the escaped id * @return the escaped id
*/ */
private fun escape(id: String): String { private fun escape(id: String): String {
return id.replace("/".toRegex(), "%2F") return id.replace("/", "%2F")
} }
} }

View File

@ -72,5 +72,4 @@ object PermalinkParser {
else -> PermalinkData.FallbackLink(uri) else -> PermalinkData.FallbackLink(uri)
} }
} }
}
}

View File

@ -18,7 +18,6 @@ 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 timber.log.Timber import timber.log.Timber
sealed class Action { sealed class Action {
object Notify : Action() object Notify : Action()
object DoNotNotify : Action() object DoNotNotify : Action()
@ -26,7 +25,6 @@ sealed class Action {
data class Highlight(val highlight: Boolean) : Action() data class Highlight(val highlight: Boolean) : Action()
} }
private const val ACTION_NOTIFY = "notify" private const val ACTION_NOTIFY = "notify"
private const val ACTION_DONT_NOTIFY = "dont_notify" private const val ACTION_DONT_NOTIFY = "dont_notify"
private const val ACTION_COALESCE = "coalesce" private const val ACTION_COALESCE = "coalesce"
@ -80,7 +78,6 @@ fun PushRule.getActions(): List<Action> {
} }
// When the value is not there, default sound (not specified by the spec) // When the value is not there, default sound (not specified by the spec)
?: Action.Sound(ACTION_OBJECT_VALUE_VALUE_DEFAULT) ?: Action.Sound(ACTION_OBJECT_VALUE_VALUE_DEFAULT)
} }
ACTION_OBJECT_SET_TWEAK_VALUE_HIGHLIGHT -> { ACTION_OBJECT_SET_TWEAK_VALUE_HIGHLIGHT -> {
(actionStrOrObj[ACTION_OBJECT_VALUE_KEY] as? Boolean)?.let { boolValue -> (actionStrOrObj[ACTION_OBJECT_VALUE_KEY] as? Boolean)?.let { boolValue ->
@ -104,7 +101,5 @@ fun PushRule.getActions(): List<Action> {
} }
} }
return result return result
} }

View File

@ -35,9 +35,7 @@ abstract class Condition(val kind: Kind) {
else -> UNRECOGNIZE else -> UNRECOGNIZE
} }
} }
} }
} }
abstract fun isSatisfied(conditionResolver: ConditionResolver): Boolean abstract fun isSatisfied(conditionResolver: ConditionResolver): Boolean
@ -45,4 +43,4 @@ abstract class Condition(val kind: Kind) {
open fun technicalDescription(): String { open fun technicalDescription(): String {
return "Kind: $kind" return "Kind: $kind"
} }
} }

View File

@ -25,4 +25,4 @@ interface ConditionResolver {
fun resolveRoomMemberCountCondition(roomMemberCountCondition: RoomMemberCountCondition): Boolean fun resolveRoomMemberCountCondition(roomMemberCountCondition: RoomMemberCountCondition): Boolean
fun resolveSenderNotificationPermissionCondition(senderNotificationPermissionCondition: SenderNotificationPermissionCondition): Boolean fun resolveSenderNotificationPermissionCondition(senderNotificationPermissionCondition: SenderNotificationPermissionCondition): Boolean
fun resolveContainsDisplayNameCondition(containsDisplayNameCondition: ContainsDisplayNameCondition) : Boolean fun resolveContainsDisplayNameCondition(containsDisplayNameCondition: ContainsDisplayNameCondition) : Boolean
} }

View File

@ -15,13 +15,11 @@
*/ */
package im.vector.matrix.android.api.pushrules package im.vector.matrix.android.api.pushrules
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
import im.vector.matrix.android.api.session.room.model.message.MessageContent import im.vector.matrix.android.api.session.room.model.message.MessageContent
import timber.log.Timber import timber.log.Timber
import java.util.regex.Pattern
class ContainsDisplayNameCondition : Condition(Kind.contains_display_name) { class ContainsDisplayNameCondition : Condition(Kind.contains_display_name) {
@ -34,11 +32,11 @@ class ContainsDisplayNameCondition : Condition(Kind.contains_display_name) {
} }
fun isSatisfied(event: Event, displayName: String): Boolean { fun isSatisfied(event: Event, displayName: String): Boolean {
var message = when (event.type) { val message = when (event.type) {
EventType.MESSAGE -> { EventType.MESSAGE -> {
event.content.toModel<MessageContent>() event.content.toModel<MessageContent>()
} }
//TODO the spec says: // TODO the spec says:
// Matches any message whose content is unencrypted and contains the user's current display name // Matches any message whose content is unencrypted and contains the user's current display name
// EventType.ENCRYPTED -> { // EventType.ENCRYPTED -> {
// event.root.getClearContent()?.toModel<MessageContent>() // event.root.getClearContent()?.toModel<MessageContent>()
@ -49,7 +47,6 @@ class ContainsDisplayNameCondition : Condition(Kind.contains_display_name) {
return caseInsensitiveFind(displayName, message.body) return caseInsensitiveFind(displayName, message.body)
} }
companion object { companion object {
/** /**
* Returns whether a string contains an occurrence of another, as a standalone word, regardless of case. * Returns whether a string contains an occurrence of another, as a standalone word, regardless of case.
@ -60,20 +57,18 @@ class ContainsDisplayNameCondition : Condition(Kind.contains_display_name) {
*/ */
fun caseInsensitiveFind(subString: String, longString: String): Boolean { fun caseInsensitiveFind(subString: String, longString: String): Boolean {
// add sanity checks // add sanity checks
if (TextUtils.isEmpty(subString) || TextUtils.isEmpty(longString)) { if (subString.isEmpty() || longString.isEmpty()) {
return false return false
} }
var res = false
try { try {
val pattern = Pattern.compile("(\\W|^)" + Pattern.quote(subString) + "(\\W|$)", Pattern.CASE_INSENSITIVE) val regex = Regex("(\\W|^)" + Regex.escape(subString) + "(\\W|$)", RegexOption.IGNORE_CASE)
res = pattern.matcher(longString).find() return regex.containsMatchIn(longString)
} catch (e: Exception) { } catch (e: Exception) {
Timber.e(e, "## caseInsensitiveFind() : failed") Timber.e(e, "## caseInsensitiveFind() : failed")
} }
return res return false
} }
} }
} }

View File

@ -29,28 +29,25 @@ class EventMatchCondition(val key: String, val pattern: String) : Condition(Kind
return "'$key' Matches '$pattern'" return "'$key' Matches '$pattern'"
} }
fun isSatisfied(event: Event): Boolean { fun isSatisfied(event: Event): Boolean {
//TODO encrypted events? // TODO encrypted events?
val rawJson = MoshiProvider.providesMoshi().adapter(Event::class.java).toJsonValue(event) as? Map<*, *> val rawJson = MoshiProvider.providesMoshi().adapter(Event::class.java).toJsonValue(event) as? Map<*, *>
?: return false ?: return false
val value = extractField(rawJson, key) ?: return false val value = extractField(rawJson, key) ?: return false
//Patterns with no special glob characters should be treated as having asterisks prepended // Patterns with no special glob characters should be treated as having asterisks prepended
// and appended when testing the condition. // and appended when testing the condition.
try { try {
val modPattern = if (hasSpecialGlobChar(pattern)) simpleGlobToRegExp(pattern) else simpleGlobToRegExp("*$pattern*") val modPattern = if (hasSpecialGlobChar(pattern)) simpleGlobToRegExp(pattern) else simpleGlobToRegExp("*$pattern*")
val regex = Regex(modPattern, RegexOption.DOT_MATCHES_ALL) val regex = Regex(modPattern, RegexOption.DOT_MATCHES_ALL)
return regex.containsMatchIn(value) return regex.containsMatchIn(value)
} catch (e: Throwable) { } catch (e: Throwable) {
//e.g PatternSyntaxException // e.g PatternSyntaxException
Timber.e(e, "Failed to evaluate push condition") Timber.e(e, "Failed to evaluate push condition")
return false return false
} }
} }
private fun extractField(jsonObject: Map<*, *>, fieldPath: String): String? { private fun extractField(jsonObject: Map<*, *>, fieldPath: String): String? {
val fieldParts = fieldPath.split(".") val fieldParts = fieldPath.split(".")
if (fieldParts.isEmpty()) return null if (fieldParts.isEmpty()) return null
@ -77,9 +74,9 @@ class EventMatchCondition(val key: String, val pattern: String) : Condition(Kind
return glob.contains("*") || glob.contains("?") return glob.contains("*") || glob.contains("?")
} }
//Very simple glob to regexp converter // Very simple glob to regexp converter
private fun simpleGlobToRegExp(glob: String): String { private fun simpleGlobToRegExp(glob: String): String {
var out = ""//"^" var out = "" // "^"
for (i in 0 until glob.length) { for (i in 0 until glob.length) {
val c = glob[i] val c = glob[i]
when (c) { when (c) {
@ -90,8 +87,8 @@ class EventMatchCondition(val key: String, val pattern: String) : Condition(Kind
else -> out += c else -> out += c
} }
} }
out += ""//'$'.toString() out += "" // '$'.toString()
return out return out
} }
} }
} }

View File

@ -27,10 +27,10 @@ interface PushRuleService {
*/ */
fun fetchPushRules(scope: String = RuleScope.GLOBAL) fun fetchPushRules(scope: String = RuleScope.GLOBAL)
//TODO get push rule set // TODO get push rule set
fun getPushRules(scope: String = RuleScope.GLOBAL): List<PushRule> fun getPushRules(scope: String = RuleScope.GLOBAL): List<PushRule>
//TODO update rule // TODO update rule
fun updatePushRuleEnableStatus(kind: RuleKind, pushRule: PushRule, enabled: Boolean, callback: MatrixCallback<Unit>): Cancelable fun updatePushRuleEnableStatus(kind: RuleKind, pushRule: PushRule, enabled: Boolean, callback: MatrixCallback<Unit>): Cancelable
@ -42,8 +42,9 @@ interface PushRuleService {
interface PushRuleListener { interface PushRuleListener {
fun onMatchRule(event: Event, actions: List<Action>) fun onMatchRule(event: Event, actions: List<Action>)
fun onRoomJoined(roomId: String)
fun onRoomLeft(roomId: String) fun onRoomLeft(roomId: String)
fun onEventRedacted(redactedEventId: String) fun onEventRedacted(redactedEventId: String)
fun batchFinish() fun batchFinish()
} }
} }

View File

@ -62,6 +62,5 @@ class RoomMemberCountCondition(val iz: String) : Condition(Kind.room_member_coun
Timber.d(t) Timber.d(t)
} }
return null return null
} }
} }

View File

@ -18,7 +18,6 @@ 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.model.PowerLevels import im.vector.matrix.android.api.session.room.model.PowerLevels
class SenderNotificationPermissionCondition(val key: String) : Condition(Kind.sender_notification_permission) { class SenderNotificationPermissionCondition(val key: String) : Condition(Kind.sender_notification_permission) {
override fun isSatisfied(conditionResolver: ConditionResolver): Boolean { override fun isSatisfied(conditionResolver: ConditionResolver): Boolean {
@ -29,8 +28,7 @@ class SenderNotificationPermissionCondition(val key: String) : Condition(Kind.se
return "User power level <$key>" return "User power level <$key>"
} }
fun isSatisfied(event: Event, powerLevels: PowerLevels): Boolean { fun isSatisfied(event: Event, powerLevels: PowerLevels): Boolean {
return event.senderId != null && powerLevels.getUserPowerLevel(event.senderId) >= powerLevels.notificationLevel(key) return event.senderId != null && powerLevels.getUserPowerLevel(event.senderId) >= powerLevels.notificationLevel(key)
} }
} }

View File

@ -76,4 +76,4 @@ data class PushCondition(
} }
} }
} }
} }

View File

@ -19,7 +19,6 @@ package im.vector.matrix.android.api.pushrules.rest
import com.squareup.moshi.Json import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
data class PushRule( data class PushRule(
/** /**
@ -47,4 +46,3 @@ data class PushRule(
*/ */
val pattern: String? = null val pattern: String? = null
) )

View File

@ -24,4 +24,4 @@ data class Ruleset(
val room: List<PushRule>? = null, val room: List<PushRule>? = null,
val sender: List<PushRule>? = null, val sender: List<PushRule>? = null,
val underride: List<PushRule>? = null val underride: List<PushRule>? = null
) )

View File

@ -26,4 +26,4 @@ interface InitialSyncProgressService {
@StringRes val statusText: Int, @StringRes val statusText: Int,
val percentProgress: Int = 0 val percentProgress: Int = 0
) )
} }

View File

@ -19,6 +19,7 @@ package im.vector.matrix.android.api.session
import androidx.annotation.MainThread import androidx.annotation.MainThread
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import im.vector.matrix.android.api.auth.data.SessionParams import im.vector.matrix.android.api.auth.data.SessionParams
import im.vector.matrix.android.api.failure.ConsentNotGivenError
import im.vector.matrix.android.api.pushrules.PushRuleService import im.vector.matrix.android.api.pushrules.PushRuleService
import im.vector.matrix.android.api.session.cache.CacheService import im.vector.matrix.android.api.session.cache.CacheService
import im.vector.matrix.android.api.session.content.ContentUploadStateTracker import im.vector.matrix.android.api.session.content.ContentUploadStateTracker
@ -26,6 +27,7 @@ import im.vector.matrix.android.api.session.content.ContentUrlResolver
import im.vector.matrix.android.api.session.crypto.CryptoService import im.vector.matrix.android.api.session.crypto.CryptoService
import im.vector.matrix.android.api.session.file.FileService import im.vector.matrix.android.api.session.file.FileService
import im.vector.matrix.android.api.session.group.GroupService import im.vector.matrix.android.api.session.group.GroupService
import im.vector.matrix.android.api.session.homeserver.HomeServerCapabilitiesService
import im.vector.matrix.android.api.session.pushers.PushersService import im.vector.matrix.android.api.session.pushers.PushersService
import im.vector.matrix.android.api.session.room.RoomDirectoryService import im.vector.matrix.android.api.session.room.RoomDirectoryService
import im.vector.matrix.android.api.session.room.RoomService import im.vector.matrix.android.api.session.room.RoomService
@ -52,6 +54,7 @@ interface Session :
PushRuleService, PushRuleService,
PushersService, PushersService,
InitialSyncProgressService, InitialSyncProgressService,
HomeServerCapabilitiesService,
SecureStorageService { SecureStorageService {
/** /**
@ -65,7 +68,6 @@ interface Session :
val myUserId: String val myUserId: String
get() = sessionParams.credentials.userId get() = sessionParams.credentials.userId
/** /**
* This method allow to open a session. It does start some service on the background. * This method allow to open a session. It does start some service on the background.
*/ */
@ -138,6 +140,9 @@ interface Session :
*/ */
fun onInvalidToken() fun onInvalidToken()
/**
* A M_CONSENT_NOT_GIVEN error has been received from the homeserver
*/
fun onConsentNotGivenError(consentNotGivenError: ConsentNotGivenError)
} }
}
}

View File

@ -27,5 +27,4 @@ interface CacheService {
* Clear the whole cached data, except credentials. Once done, the session is closed and has to be opened again * Clear the whole cached data, except credentials. Once done, the session is closed and has to be opened again
*/ */
fun clearCache(callback: MatrixCallback<Unit>) fun clearCache(callback: MatrixCallback<Unit>)
}
}

View File

@ -17,6 +17,7 @@
package im.vector.matrix.android.api.session.content package im.vector.matrix.android.api.session.content
import android.os.Parcelable import android.os.Parcelable
import androidx.exifinterface.media.ExifInterface
import kotlinx.android.parcel.Parcelize import kotlinx.android.parcel.Parcelize
@Parcelize @Parcelize
@ -26,6 +27,7 @@ data class ContentAttachmentData(
val date: Long = 0, val date: Long = 0,
val height: Long? = 0, val height: Long? = 0,
val width: Long? = 0, val width: Long? = 0,
val exifOrientation: Int = ExifInterface.ORIENTATION_UNDEFINED,
val name: String? = null, val name: String? = null,
val path: String, val path: String,
val mimeType: String, val mimeType: String,
@ -38,5 +40,4 @@ data class ContentAttachmentData(
AUDIO, AUDIO,
VIDEO VIDEO
} }
}
}

View File

@ -35,4 +35,4 @@ interface ContentUploadStateTracker {
object Success : State() object Success : State()
data class Failure(val throwable: Throwable) : State() data class Failure(val throwable: Throwable) : State()
} }
} }

View File

@ -44,4 +44,4 @@ interface ContentUrlResolver {
* @return the URL to access the described resource, or null if the url is invalid. * @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? fun resolveThumbnail(contentUrl: String?, width: Int, height: Int, method: ThumbnailMethod): String?
} }

View File

@ -112,5 +112,4 @@ interface CryptoService {
fun addNewSessionListener(newSessionListener: NewSessionListener) fun addNewSessionListener(newSessionListener: NewSessionListener)
fun removeSessionListener(listener: NewSessionListener) fun removeSessionListener(listener: NewSessionListener)
}
}

View File

@ -90,4 +90,4 @@ sealed class MXCryptoError : Throwable() {
const val NO_MORE_ALGORITHM_REASON = "Room was previously configured to use encryption, but is no longer." + const val NO_MORE_ALGORITHM_REASON = "Room was previously configured to use encryption, but is no longer." +
" Perhaps the homeserver is hiding the configuration event." " Perhaps the homeserver is hiding the configuration event."
} }
} }

View File

@ -210,5 +210,4 @@ interface KeysBackupService {
val isEnabled: Boolean val isEnabled: Boolean
val isStucked: Boolean val isStucked: Boolean
val state: KeysBackupState val state: KeysBackupState
}
}

View File

@ -72,4 +72,4 @@ enum class KeysBackupState {
WillBackUp, WillBackUp,
// e2e keys are being sent to the homeserver // e2e keys are being sent to the homeserver
BackingUp BackingUp
} }

View File

@ -23,4 +23,4 @@ interface KeysBackupStateListener {
* @param newState the new state * @param newState the new state
*/ */
fun onStateChange(newState: KeysBackupState) fun onStateChange(newState: KeysBackupState)
} }

View File

@ -30,4 +30,4 @@ enum class CancelCode(val value: String, val humanReadable: String) {
fun safeValueOf(code: String?): CancelCode { fun safeValueOf(code: String?): CancelCode {
return CancelCode.values().firstOrNull { code == it.value } ?: CancelCode.User return CancelCode.values().firstOrNull { code == it.value } ?: CancelCode.User
} }

View File

@ -19,4 +19,4 @@ package im.vector.matrix.android.api.session.crypto.sas
import androidx.annotation.StringRes import androidx.annotation.StringRes
data class EmojiRepresentation(val emoji: String, data class EmojiRepresentation(val emoji: String,
@StringRes val nameResId: Int) @StringRes val nameResId: Int)

View File

@ -31,4 +31,4 @@ interface IncomingSasVerificationTransaction {
CANCELLED_BY_ME, CANCELLED_BY_ME,
CANCELLED_BY_OTHER CANCELLED_BY_OTHER
} }
} }

View File

@ -29,4 +29,4 @@ interface OutgoingSasVerificationRequest {
CANCELLED_BY_ME, CANCELLED_BY_ME,
CANCELLED_BY_OTHER CANCELLED_BY_OTHER
} }
} }

View File

@ -19,4 +19,4 @@ package im.vector.matrix.android.api.session.crypto.sas
object SasMode { object SasMode {
const val DECIMAL = "decimal" const val DECIMAL = "decimal"
const val EMOJI = "emoji" const val EMOJI = "emoji"
} }

View File

@ -36,4 +36,4 @@ interface SasVerificationService {
fun transactionUpdated(tx: SasVerificationTransaction) fun transactionUpdated(tx: SasVerificationTransaction)
fun markedAsManuallyVerified(userId: String, deviceId: String) fun markedAsManuallyVerified(userId: String, deviceId: String)
} }
} }

View File

@ -47,4 +47,4 @@ interface SasVerificationTransaction {
* both short codes do match * both short codes do match
*/ */
fun userHasVerifiedShortCode() fun userHasVerifiedShortCode()
} }

View File

@ -43,7 +43,7 @@ enum class SasVerificationTxState {
Verifying, Verifying,
Verified, Verified,
//Global: The verification has been cancelled (by me or other), see cancelReason for details // Global: The verification has been cancelled (by me or other), see cancelReason for details
Cancelled, Cancelled,
OnCancelled OnCancelled
} }

View File

@ -34,9 +34,9 @@ import com.squareup.moshi.JsonClass
*/ */
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
data class AggregatedAnnotation ( data class AggregatedAnnotation(
override val limited: Boolean? = false, override val limited: Boolean? = false,
override val count: Int? = 0, override val count: Int? = 0,
val chunk: List<RelationChunkInfo>? = null val chunk: List<RelationChunkInfo>? = null
) : UnsignedRelationInfo ) : UnsignedRelationInfo

View File

@ -50,4 +50,4 @@ import com.squareup.moshi.JsonClass
data class AggregatedRelations( data class AggregatedRelations(
@Json(name = "m.annotation") val annotations: AggregatedAnnotation? = null, @Json(name = "m.annotation") val annotations: AggregatedAnnotation? = null,
@Json(name = "m.reference") val references: DefaultUnsignedRelationInfo? = null @Json(name = "m.reference") val references: DefaultUnsignedRelationInfo? = null
) )

View File

@ -23,4 +23,4 @@ data class DefaultUnsignedRelationInfo(
override val count: Int? = 0, override val count: Int? = 0,
val chunk: List<Map<String, Any>>? = null val chunk: List<Map<String, Any>>? = null
) : UnsignedRelationInfo ) : UnsignedRelationInfo

View File

@ -16,7 +16,6 @@
package im.vector.matrix.android.api.session.events.model package im.vector.matrix.android.api.session.events.model
import android.text.TextUtils
import com.squareup.moshi.Json import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass import com.squareup.moshi.JsonClass
import im.vector.matrix.android.api.session.crypto.MXCryptoError import im.vector.matrix.android.api.session.crypto.MXCryptoError
@ -35,18 +34,16 @@ typealias Content = JsonDict
* This methods is a facility method to map a json content to a model. * This methods is a facility method to map a json content to a model.
*/ */
inline fun <reified T> Content?.toModel(catchError: Boolean = true): T? { inline fun <reified T> Content?.toModel(catchError: Boolean = true): T? {
return this?.let { val moshi = MoshiProvider.providesMoshi()
val moshi = MoshiProvider.providesMoshi() val moshiAdapter = moshi.adapter(T::class.java)
val moshiAdapter = moshi.adapter(T::class.java) return try {
return try { moshiAdapter.fromJsonValue(this)
moshiAdapter.fromJsonValue(it) } catch (e: Exception) {
} catch (e: Exception) { if (catchError) {
if (catchError) { Timber.e(e, "To model failed : $e")
Timber.e(e, "To model failed : $e") null
null } else {
} else { throw e
throw e
}
} }
} }
} }
@ -55,12 +52,10 @@ inline fun <reified T> Content?.toModel(catchError: Boolean = true): T? {
* This methods is a facility method to map a model to a json Content * This methods is a facility method to map a model to a json Content
*/ */
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
inline fun <reified T> T?.toContent(): Content? { inline fun <reified T> T.toContent(): Content {
return this?.let { val moshi = MoshiProvider.providesMoshi()
val moshi = MoshiProvider.providesMoshi() val moshiAdapter = moshi.adapter(T::class.java)
val moshiAdapter = moshi.adapter(T::class.java) return moshiAdapter.toJsonValue(this) as Content
return moshiAdapter.toJsonValue(it) as Content
}
} }
/** /**
@ -81,7 +76,6 @@ data class Event(
@Json(name = "redacts") val redacts: String? = null @Json(name = "redacts") val redacts: String? = null
) { ) {
@Transient @Transient
var mxDecryptionResult: OlmDecryptionResult? = null var mxDecryptionResult: OlmDecryptionResult? = null
@ -91,7 +85,6 @@ data class Event(
@Transient @Transient
var sendState: SendState = SendState.UNKNOWN var sendState: SendState = SendState.UNKNOWN
/** /**
* Check if event is a state event. * Check if event is a state event.
* @return true if event is state event. * @return true if event is state event.
@ -100,15 +93,15 @@ data class Event(
return EventType.isStateEvent(getClearType()) return EventType.isStateEvent(getClearType())
} }
//============================================================================================================== // ==============================================================================================================
// Crypto // Crypto
//============================================================================================================== // ==============================================================================================================
/** /**
* @return true if this event is encrypted. * @return true if this event is encrypted.
*/ */
fun isEncrypted(): Boolean { fun isEncrypted(): Boolean {
return TextUtils.equals(type, EventType.ENCRYPTED) return type == EventType.ENCRYPTED
} }
/** /**
@ -136,11 +129,12 @@ data class Event(
* @return the event content * @return the event content
*/ */
fun getClearContent(): Content? { fun getClearContent(): Content? {
@Suppress("UNCHECKED_CAST")
return mxDecryptionResult?.payload?.get("content") as? Content ?: content return mxDecryptionResult?.payload?.get("content") as? Content ?: content
} }
fun toContentStringWithIndent(): String { fun toContentStringWithIndent(): String {
val contentMap = toContent()?.toMutableMap() ?: HashMap() val contentMap = toContent().toMutableMap()
return JSONObject(contentMap).toString(4) return JSONObject(contentMap).toString(4)
} }
@ -194,10 +188,8 @@ data class Event(
result = 31 * result + sendState.hashCode() result = 31 * result + sendState.hashCode()
return result return result
} }
} }
fun Event.isTextMessage(): Boolean { fun Event.isTextMessage(): Boolean {
return getClearType() == EventType.MESSAGE return getClearType() == EventType.MESSAGE
&& when (getClearContent()?.toModel<MessageContent>()?.type) { && when (getClearContent()?.toModel<MessageContent>()?.type) {
@ -214,4 +206,4 @@ fun Event.isImageMessage(): Boolean {
MessageType.MSGTYPE_IMAGE -> true MessageType.MSGTYPE_IMAGE -> true
else -> false else -> false
} }
} }

View File

@ -16,7 +16,6 @@
package im.vector.matrix.android.api.session.events.model package im.vector.matrix.android.api.session.events.model
/** /**
* Constants defining known event types from Matrix specifications. * Constants defining known event types from Matrix specifications.
*/ */
@ -93,7 +92,6 @@ object EventType {
STATE_PINNED_EVENT STATE_PINNED_EVENT
) )
fun isStateEvent(type: String): Boolean { fun isStateEvent(type: String): Boolean {
return STATE_EVENTS.contains(type) return STATE_EVENTS.contains(type)
} }

View File

@ -0,0 +1,28 @@
/*
* 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.android.api.session.events.model
import java.util.*
object LocalEcho {
private const val PREFIX = "local."
fun isLocalEchoId(eventId: String) = eventId.startsWith(PREFIX)
fun createLocalEchoId() = "${PREFIX}${UUID.randomUUID()}"
}

View File

@ -15,7 +15,6 @@
*/ */
package im.vector.matrix.android.api.session.events.model package im.vector.matrix.android.api.session.events.model
/** /**
* Constants defining known event relation types from Matrix specifications * Constants defining known event relation types from Matrix specifications
*/ */
@ -27,5 +26,4 @@ object RelationType {
const val REPLACE = "m.replace" const val REPLACE = "m.replace"
/** Lets you define an event which references an existing event.*/ /** Lets you define an event which references an existing event.*/
const val REFERENCE = "m.reference" const val REFERENCE = "m.reference"
}
}

View File

@ -26,4 +26,4 @@ data class UnsignedData(
@Json(name = "transaction_id") val transactionId: String? = null, @Json(name = "transaction_id") val transactionId: String? = null,
@Json(name = "prev_content") val prevContent: Map<String, Any>? = null, @Json(name = "prev_content") val prevContent: Map<String, Any>? = null,
@Json(name = "m.relations") val relations: AggregatedRelations? = null @Json(name = "m.relations") val relations: AggregatedRelations? = null
) )

View File

@ -15,8 +15,7 @@
*/ */
package im.vector.matrix.android.api.session.events.model package im.vector.matrix.android.api.session.events.model
interface UnsignedRelationInfo { interface UnsignedRelationInfo {
val limited : Boolean? val limited : Boolean?
val count: Int? val count: Int?
} }

View File

@ -20,7 +20,6 @@ import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.internal.crypto.attachments.ElementToDecrypt import im.vector.matrix.android.internal.crypto.attachments.ElementToDecrypt
import java.io.File import java.io.File
/** /**
* This interface defines methods to get files. * This interface defines methods to get files.
*/ */
@ -49,4 +48,4 @@ interface FileService {
url: String?, url: String?,
elementToDecrypt: ElementToDecrypt?, elementToDecrypt: ElementToDecrypt?,
callback: MatrixCallback<File>) callback: MatrixCallback<File>)
} }

View File

@ -21,4 +21,4 @@ package im.vector.matrix.android.api.session.group
*/ */
interface Group { interface Group {
val groupId: String val groupId: String
} }

View File

@ -19,7 +19,6 @@ package im.vector.matrix.android.api.session.group
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import im.vector.matrix.android.api.session.group.model.GroupSummary import im.vector.matrix.android.api.session.group.model.GroupSummary
/** /**
* This interface defines methods to get groups. It's implemented at the session level. * This interface defines methods to get groups. It's implemented at the session level.
*/ */
@ -37,4 +36,4 @@ interface GroupService {
* @return the [LiveData] of [GroupSummary] * @return the [LiveData] of [GroupSummary]
*/ */
fun liveGroupSummaries(): LiveData<List<GroupSummary>> fun liveGroupSummaries(): LiveData<List<GroupSummary>>
} }

View File

@ -30,4 +30,4 @@ data class GroupSummary(
val avatarUrl: String = "", val avatarUrl: String = "",
val roomIds: List<String> = emptyList(), val roomIds: List<String> = emptyList(),
val userIds: List<String> = emptyList() val userIds: List<String> = emptyList()
) )

View File

@ -0,0 +1,28 @@
/*
* 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.android.api.session.homeserver
data class HomeServerCapabilities(
/**
* Max size of file which can be uploaded to the homeserver in bytes. [MAX_UPLOAD_FILE_SIZE_UNKNOWN] if unknown or not retrieved yet
*/
val maxUploadFileSize: Long = MAX_UPLOAD_FILE_SIZE_UNKNOWN
) {
companion object {
const val MAX_UPLOAD_FILE_SIZE_UNKNOWN = -1L
}
}

View File

@ -0,0 +1,28 @@
/*
* 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.android.api.session.homeserver
/**
* This interface defines a method to retrieve the homeserver capabilities.
*/
interface HomeServerCapabilitiesService {
/**
* Get the HomeServer capabilities
*/
fun getHomeServerCapabilities(): HomeServerCapabilities
}

View File

@ -39,4 +39,4 @@ enum class PusherState {
data class PusherData( data class PusherData(
val url: String? = null, val url: String? = null,
val format: String? = null val format: String? = null
) )

View File

@ -19,7 +19,6 @@ import androidx.lifecycle.LiveData
import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.MatrixCallback
import java.util.UUID import java.util.UUID
interface PushersService { interface PushersService {
/** /**
@ -53,7 +52,6 @@ interface PushersService {
append: Boolean, append: Boolean,
withEventIdOnly: Boolean): UUID withEventIdOnly: Boolean): UUID
fun removeHttpPusher(pushkey: String, appId: String, callback: MatrixCallback<Unit>) fun removeHttpPusher(pushkey: String, appId: String, callback: MatrixCallback<Unit>)
companion object { companion object {
@ -63,4 +61,4 @@ interface PushersService {
fun livePushers(): LiveData<List<Pusher>> fun livePushers(): LiveData<List<Pusher>>
fun pushers() : List<Pusher> fun pushers() : List<Pusher>
} }

View File

@ -21,11 +21,13 @@ import im.vector.matrix.android.api.session.room.crypto.RoomCryptoService
import im.vector.matrix.android.api.session.room.members.MembershipService import im.vector.matrix.android.api.session.room.members.MembershipService
import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.session.room.model.RoomSummary
import im.vector.matrix.android.api.session.room.model.relation.RelationService import im.vector.matrix.android.api.session.room.model.relation.RelationService
import im.vector.matrix.android.api.session.room.reporting.ReportingService
import im.vector.matrix.android.api.session.room.read.ReadService import im.vector.matrix.android.api.session.room.read.ReadService
import im.vector.matrix.android.api.session.room.send.DraftService import im.vector.matrix.android.api.session.room.send.DraftService
import im.vector.matrix.android.api.session.room.send.SendService import im.vector.matrix.android.api.session.room.send.SendService
import im.vector.matrix.android.api.session.room.state.StateService import im.vector.matrix.android.api.session.room.state.StateService
import im.vector.matrix.android.api.session.room.timeline.TimelineService import im.vector.matrix.android.api.session.room.timeline.TimelineService
import im.vector.matrix.android.api.util.Optional
/** /**
* This interface defines methods to interact within a room. * This interface defines methods to interact within a room.
@ -37,6 +39,7 @@ interface Room :
ReadService, ReadService,
MembershipService, MembershipService,
StateService, StateService,
ReportingService,
RelationService, RelationService,
RoomCryptoService { RoomCryptoService {
@ -49,8 +52,7 @@ interface Room :
* A live [RoomSummary] associated with the room * A live [RoomSummary] associated with the room
* You can observe this summary to get dynamic data from this room. * You can observe this summary to get dynamic data from this room.
*/ */
fun liveRoomSummary(): LiveData<RoomSummary> fun getRoomSummaryLive(): LiveData<Optional<RoomSummary>>
fun roomSummary(): RoomSummary? fun roomSummary(): RoomSummary?
}
}

View File

@ -42,5 +42,4 @@ interface RoomDirectoryService {
* Includes both the available protocols and all fields required for queries against each protocol. * Includes both the available protocols and all fields required for queries against each protocol.
*/ */
fun getThirdPartyProtocol(callback: MatrixCallback<Map<String, ThirdPartyProtocol>>): Cancelable fun getThirdPartyProtocol(callback: MatrixCallback<Map<String, ThirdPartyProtocol>>): Cancelable
}
}

View File

@ -54,4 +54,8 @@ interface RoomService {
*/ */
fun liveRoomSummaries(): LiveData<List<RoomSummary>> fun liveRoomSummaries(): LiveData<List<RoomSummary>>
} /**
* Mark all rooms as read
*/
fun markAllAsRead(roomIds: List<String>, callback: MatrixCallback<Unit>): Cancelable
}

View File

@ -23,4 +23,4 @@ interface RoomCryptoService {
fun encryptionAlgorithm(): String? fun encryptionAlgorithm(): String?
fun shouldEncryptForInvitedMembers(): Boolean fun shouldEncryptForInvitedMembers(): Boolean
} }

View File

@ -21,5 +21,4 @@ import im.vector.matrix.android.api.failure.Failure
sealed class CreateRoomFailure : Failure.FeatureFailure() { sealed class CreateRoomFailure : Failure.FeatureFailure() {
object CreatedWithTimeout: CreateRoomFailure() object CreatedWithTimeout: CreateRoomFailure()
}
}

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