mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2025-01-07 16:57:39 +03:00
Merge branch 'release/0.7.0'
This commit is contained in:
commit
01452efd8d
1132 changed files with 12341 additions and 8569 deletions
|
@ -54,4 +54,13 @@ steps:
|
|||
# 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
32
.editorconfig
Normal 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
14
.gitignore
vendored
|
@ -1,14 +1,18 @@
|
|||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
.idea/*
|
||||
/.idea/*
|
||||
/.idea/libraries
|
||||
/.idea/modules.xml
|
||||
/.idea/workspace.xml
|
||||
# idea files: exclude everything except dictionnaries
|
||||
.idea/caches
|
||||
.idea/codeStyles
|
||||
.idea/libraries
|
||||
.idea/*.xml
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
|
||||
/tmp
|
||||
|
||||
ktlint
|
||||
.idea/copyright/New_vector.xml
|
||||
.idea/copyright/profiles_settings.xml
|
||||
|
|
19
.idea/dictionaries/bmarty.xml
Normal file
19
.idea/dictionaries/bmarty.xml
Normal 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>
|
36
CHANGES.md
36
CHANGES.md
|
@ -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)
|
||||
===================================================
|
||||
|
||||
|
@ -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)
|
||||
===================================================
|
||||
|
||||
Features:
|
||||
Features ✨:
|
||||
-
|
||||
|
||||
Improvements:
|
||||
Improvements 🙌:
|
||||
-
|
||||
|
||||
Other changes:
|
||||
-
|
||||
|
||||
Bugfix:
|
||||
Bugfix 🐛:
|
||||
-
|
||||
|
||||
Translations:
|
||||
Translations 🗣:
|
||||
-
|
||||
|
||||
Build:
|
||||
Build 🧱:
|
||||
-
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
||||
> ./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
|
||||
|
||||
Make sure the following commands execute without any error:
|
||||
|
||||
> ./gradlew testGplayReleaseUnitTest
|
||||
<pre>
|
||||
./gradlew testGplayReleaseUnitTest
|
||||
</pre>
|
||||
|
||||
### 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.
|
||||
|
||||
### Internationalisation
|
||||
|
|
17
build.gradle
17
build.gradle
|
@ -1,9 +1,7 @@
|
|||
import javax.tools.JavaCompiler
|
||||
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.3.21'
|
||||
ext.kotlin_version = '1.3.50'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
|
@ -12,11 +10,11 @@ buildscript {
|
|||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.4.1'
|
||||
classpath 'com.google.gms:google-services:4.2.0'
|
||||
classpath "com.airbnb.okreplay:gradle-plugin:1.4.0"
|
||||
classpath 'com.android.tools.build:gradle:3.5.1'
|
||||
classpath 'com.google.gms:google-services:4.3.2'
|
||||
classpath "com.airbnb.okreplay:gradle-plugin:1.5.0"
|
||||
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'
|
||||
|
||||
// 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 {
|
||||
extensions.findByName("kapt")?.arguments {
|
||||
arg("dagger.gradle.incremental", "enabled")
|
||||
|
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,6 +1,6 @@
|
|||
#Tue Mar 19 09:53:05 CET 2019
|
||||
#Fri Sep 27 10:10:35 CEST 2019
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
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
|
||||
|
|
|
@ -5,8 +5,6 @@ apply plugin: 'kotlin-kapt'
|
|||
android {
|
||||
compileSdkVersion 28
|
||||
|
||||
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 28
|
||||
|
@ -14,7 +12,6 @@ android {
|
|||
versionName "1.0"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
|
@ -29,12 +26,14 @@ android {
|
|||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
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:rxandroid:2.1.1'
|
||||
// Paging
|
||||
|
|
|
@ -20,7 +20,6 @@ import androidx.lifecycle.LiveData
|
|||
import androidx.lifecycle.Observer
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.android.MainThreadDisposable
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
||||
private class LiveDataObservable<T>(
|
||||
|
|
|
@ -19,7 +19,6 @@ package im.vector.matrix.rx
|
|||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
import io.reactivex.CompletableEmitter
|
||||
import io.reactivex.SingleEmitter
|
||||
|
||||
internal class MatrixCallbackCompletable<T>(private val completableEmitter: CompletableEmitter) : MatrixCallback<T> {
|
||||
|
||||
|
|
|
@ -14,13 +14,11 @@
|
|||
* 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) {
|
||||
|
||||
init {
|
||||
addAll(items)
|
||||
}
|
||||
fun <T : Any> Observable<Optional<T>>.unwrap(): Observable<T> {
|
||||
return filter { it.hasValue() }.map { it.get() }
|
||||
}
|
|
@ -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.send.UserDraft
|
||||
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.Single
|
||||
|
||||
class RxRoom(private val room: Room) {
|
||||
|
||||
fun liveRoomSummary(): Observable<RoomSummary> {
|
||||
return room.liveRoomSummary().asObservable()
|
||||
fun liveRoomSummary(): Observable<Optional<RoomSummary>> {
|
||||
return room.getRoomSummaryLive().asObservable()
|
||||
}
|
||||
|
||||
fun liveRoomMemberIds(): Observable<List<String>> {
|
||||
return room.getRoomMemberIdsLive().asObservable()
|
||||
}
|
||||
|
||||
fun liveAnnotationSummary(eventId: String): Observable<EventAnnotationsSummary> {
|
||||
fun liveAnnotationSummary(eventId: String): Observable<Optional<EventAnnotationsSummary>> {
|
||||
return room.getEventSummaryLive(eventId).asObservable()
|
||||
}
|
||||
|
||||
fun liveTimelineEvent(eventId: String): Observable<TimelineEvent> {
|
||||
return room.liveTimeLineEvent(eventId).asObservable()
|
||||
fun liveTimelineEvent(eventId: String): Observable<Optional<TimelineEvent>> {
|
||||
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 {
|
||||
|
@ -58,7 +67,6 @@ class RxRoom(private val room: Room) {
|
|||
fun liveDrafts(): Observable<List<UserDraft>> {
|
||||
return room.getDraftsLive().asObservable()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun Room.rx(): RxRoom {
|
||||
|
|
|
@ -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.sync.SyncState
|
||||
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.Single
|
||||
|
||||
|
@ -45,6 +46,10 @@ class RxSession(private val session: Session) {
|
|||
return session.livePushers().asObservable()
|
||||
}
|
||||
|
||||
fun liveUser(userId: String): Observable<Optional<User>> {
|
||||
return session.liveUser(userId).asObservable().distinctUntilChanged()
|
||||
}
|
||||
|
||||
fun liveUsers(): Observable<List<User>> {
|
||||
return session.liveUsers().asObservable()
|
||||
}
|
||||
|
@ -66,7 +71,6 @@ class RxSession(private val session: Session) {
|
|||
fun joinRoom(roomId: String, viaServers: List<String> = emptyList()): Single<Unit> = Single.create {
|
||||
session.joinRoom(roomId, viaServers, MatrixCallbackSingle(it)).toSingle(it)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun Session.rx(): RxSession {
|
||||
|
|
|
@ -67,6 +67,10 @@ android {
|
|||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
}
|
||||
|
||||
static def gitRevision() {
|
||||
|
@ -86,41 +90,43 @@ static def gitRevisionDate() {
|
|||
|
||||
dependencies {
|
||||
|
||||
def arrow_version = "0.8.0"
|
||||
def support_version = '1.1.0-beta01'
|
||||
def arrow_version = "0.8.2"
|
||||
def moshi_version = '1.8.0'
|
||||
def lifecycle_version = '2.0.0'
|
||||
def coroutines_version = "1.0.1"
|
||||
def markwon_version = '3.0.0'
|
||||
def daggerVersion = '2.23.1'
|
||||
def lifecycle_version = '2.1.0'
|
||||
def coroutines_version = "1.3.2"
|
||||
def markwon_version = '3.1.0'
|
||||
def daggerVersion = '2.24'
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
||||
|
||||
implementation "androidx.appcompat:appcompat:1.1.0-rc01"
|
||||
implementation "androidx.recyclerview:recyclerview:1.1.0-beta01"
|
||||
implementation "androidx.appcompat:appcompat:1.1.0"
|
||||
implementation "androidx.recyclerview:recyclerview:1.1.0-beta05"
|
||||
|
||||
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
|
||||
kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
|
||||
|
||||
// Network
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.6.0'
|
||||
implementation 'com.squareup.retrofit2:converter-moshi:2.4.0'
|
||||
implementation 'com.squareup.okhttp3:okhttp:3.14.1'
|
||||
implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.6.2'
|
||||
implementation 'com.squareup.retrofit2:converter-moshi:2.6.2'
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.2.2'
|
||||
implementation 'com.squareup.okhttp3:logging-interceptor:4.2.2'
|
||||
implementation 'com.novoda:merlin:1.2.0'
|
||||
implementation "com.squareup.moshi:moshi-adapters:$moshi_version"
|
||||
kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version"
|
||||
|
||||
implementation "ru.noties.markwon:core:$markwon_version"
|
||||
|
||||
// Image
|
||||
implementation 'androidx.exifinterface:exifinterface:1.0.0'
|
||||
|
||||
// Database
|
||||
implementation 'com.github.Zhuinden:realm-monarchy:0.5.1'
|
||||
kapt 'dk.ilios:realmfieldnameshelper:1.1.1'
|
||||
|
||||
// Work
|
||||
implementation "androidx.work:work-runtime-ktx:2.1.0-rc01"
|
||||
implementation "androidx.work:work-runtime-ktx:2.3.0-alpha01"
|
||||
|
||||
// FP
|
||||
implementation "io.arrow-kt:arrow-core:$arrow_version"
|
||||
|
@ -132,24 +138,24 @@ dependencies {
|
|||
// DI
|
||||
implementation "com.google.dagger:dagger:$daggerVersion"
|
||||
kapt "com.google.dagger:dagger-compiler:$daggerVersion"
|
||||
compileOnly 'com.squareup.inject:assisted-inject-annotations-dagger2:0.4.0'
|
||||
kapt 'com.squareup.inject:assisted-inject-processor-dagger2:0.4.0'
|
||||
compileOnly 'com.squareup.inject:assisted-inject-annotations-dagger2:0.5.0'
|
||||
kapt 'com.squareup.inject:assisted-inject-processor-dagger2:0.5.0'
|
||||
|
||||
// Logging
|
||||
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
|
||||
implementation 'org.greenrobot:eventbus:3.1.1'
|
||||
|
||||
debugImplementation 'com.airbnb.okreplay:okreplay:1.4.0'
|
||||
releaseImplementation 'com.airbnb.okreplay:noop:1.4.0'
|
||||
androidTestImplementation 'com.airbnb.okreplay:espresso:1.4.0'
|
||||
debugImplementation 'com.airbnb.okreplay:okreplay:1.5.0'
|
||||
releaseImplementation 'com.airbnb.okreplay:noop:1.5.0'
|
||||
androidTestImplementation 'com.airbnb.okreplay:espresso:1.5.0'
|
||||
|
||||
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 "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.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
||||
|
||||
|
@ -159,7 +165,7 @@ dependencies {
|
|||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||
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 "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@ import org.junit.Rule
|
|||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
internal class AuthenticatorTest : InstrumentedTest {
|
||||
|
||||
|
@ -50,7 +49,6 @@ internal class AuthenticatorTest : InstrumentedTest {
|
|||
@UiThreadTest
|
||||
@OkReplay(tape = "auth", mode = TapeMode.READ_WRITE)
|
||||
fun auth() {
|
||||
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -59,6 +57,4 @@ internal class AuthenticatorTest : InstrumentedTest {
|
|||
val grantExternalStoragePermissionRule: GrantPermissionRule =
|
||||
GrantPermissionRule.grant(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -62,8 +62,6 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
|
|||
JsonCanonicalizer.canonicalize("{\"a\":\"\\\"\"}"))
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ==========================================================================================
|
||||
* Test from https://matrix.org/docs/spec/appendices.html#examples
|
||||
* ========================================================================================== */
|
||||
|
@ -74,7 +72,6 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
|
|||
JsonCanonicalizer.canonicalize("""{}"""))
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun matrixOrg002Test() {
|
||||
assertEquals("""{"one":1,"two":"Two"}""",
|
||||
|
@ -84,7 +81,6 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
|
|||
}"""))
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun matrixOrg003Test() {
|
||||
assertEquals("""{"a":"1","b":"2"}""",
|
||||
|
@ -94,14 +90,12 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
|
|||
}"""))
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun matrixOrg004Test() {
|
||||
assertEquals("""{"a":"1","b":"2"}""",
|
||||
JsonCanonicalizer.canonicalize("""{"b":"2","a":"1"}"""))
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
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}}""",
|
||||
|
@ -126,7 +120,6 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
|
|||
}"""))
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun matrixOrg006Test() {
|
||||
assertEquals("""{"a":"日本語"}""",
|
||||
|
@ -135,7 +128,6 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
|
|||
}"""))
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun matrixOrg007Test() {
|
||||
assertEquals("""{"日":1,"本":2}""",
|
||||
|
@ -145,7 +137,6 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
|
|||
}"""))
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun matrixOrg008Test() {
|
||||
assertEquals("""{"a":"日"}""",
|
||||
|
|
|
@ -35,7 +35,6 @@ import org.junit.Before
|
|||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
internal class ChunkEntityTest : InstrumentedTest {
|
||||
|
||||
|
@ -48,7 +47,6 @@ internal class ChunkEntityTest : InstrumentedTest {
|
|||
monarchy = Monarchy.Builder().setRealmConfiguration(testConfig).build()
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun add_shouldAdd_whenNotAlreadyIncluded() {
|
||||
monarchy.runTransactionSync { realm ->
|
||||
|
@ -194,5 +192,4 @@ internal class ChunkEntityTest : InstrumentedTest {
|
|||
chunk1.nextToken shouldEqual nextToken
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -32,6 +32,4 @@ internal class FakeGetContextOfEventTask constructor(private val tokenChunkEvent
|
|||
)
|
||||
return tokenChunkEventPersistor.insertInDb(tokenChunkEvent, params.roomId, PaginationDirection.BACKWARDS)
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -28,6 +28,4 @@ internal class FakePaginationTask @Inject constructor(private val tokenChunkEven
|
|||
val tokenChunkEvent = FakeTokenChunkEvent(params.from, Random.nextLong(System.currentTimeMillis()).toString(), fakeEvents)
|
||||
return tokenChunkEventPersistor.insertInDb(tokenChunkEvent, params.roomId, params.direction)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -88,6 +88,4 @@ object RoomDataHelper {
|
|||
roomEntity.addOrUpdate(chunkEntity)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -81,6 +81,4 @@ internal class TimelineTest : InstrumentedTest {
|
|||
// timelineEvents.size shouldEqual initialLoad + paginationCount
|
||||
// timeline.dispose()
|
||||
// }
|
||||
|
||||
|
||||
}
|
|
@ -22,6 +22,7 @@ import okhttp3.Interceptor
|
|||
import okhttp3.Response
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import okio.Buffer
|
||||
import timber.log.Timber
|
||||
import java.io.IOException
|
||||
import java.nio.charset.Charset
|
||||
import javax.inject.Inject
|
||||
|
@ -51,13 +52,18 @@ internal class CurlLoggingInterceptor @Inject constructor(private val logger: Ht
|
|||
var compressed = false
|
||||
|
||||
var curlCmd = "curl"
|
||||
if (curlOptions != null) {
|
||||
curlCmd += " " + curlOptions!!
|
||||
curlOptions?.let {
|
||||
curlCmd += " $it"
|
||||
}
|
||||
curlCmd += " -X " + request.method()
|
||||
curlCmd += " -X " + request.method
|
||||
|
||||
val requestBody = request.body()
|
||||
val requestBody = request.body
|
||||
if (requestBody != null) {
|
||||
if (requestBody.contentLength() > 100_000) {
|
||||
Timber.w("Unable to log curl command data, size is too big (${requestBody.contentLength()})")
|
||||
// Ensure the curl command will failed
|
||||
curlCmd += "DATA IS TOO BIG"
|
||||
} else {
|
||||
val buffer = Buffer()
|
||||
requestBody.writeTo(buffer)
|
||||
var charset: Charset? = UTF8
|
||||
|
@ -68,10 +74,11 @@ internal class CurlLoggingInterceptor @Inject constructor(private val logger: Ht
|
|||
// 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
|
||||
val count = headers.size()
|
||||
val count = headers.size
|
||||
while (i < count) {
|
||||
val name = headers.name(i)
|
||||
val value = headers.value(i)
|
||||
|
@ -82,7 +89,7 @@ internal class CurlLoggingInterceptor @Inject constructor(private val logger: Ht
|
|||
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("://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
|
||||
curlCmd += " | python -m json.tool"
|
||||
|
||||
logger.log("--- cURL (" + request.url() + ")")
|
||||
logger.log("--- cURL (" + request.url + ")")
|
||||
logger.log(curlCmd)
|
||||
|
||||
return chain.proceed(request)
|
||||
|
|
|
@ -51,7 +51,6 @@ class FormattedJsonHttpLogger : HttpLoggingInterceptor.Logger {
|
|||
// Finally this is not a JSON string...
|
||||
Timber.e(e)
|
||||
}
|
||||
|
||||
} else if (message.startsWith("[")) {
|
||||
// JSON Array detected
|
||||
try {
|
||||
|
@ -61,7 +60,6 @@ class FormattedJsonHttpLogger : HttpLoggingInterceptor.Logger {
|
|||
// Finally not JSON...
|
||||
Timber.e(e)
|
||||
}
|
||||
|
||||
}
|
||||
// Else not a json string to log
|
||||
}
|
||||
|
|
|
@ -38,7 +38,6 @@ data class MatrixConfiguration(
|
|||
interface Provider {
|
||||
fun providesMatrixConfiguration(): MatrixConfiguration
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -98,5 +97,4 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo
|
|||
return BuildConfig.VERSION_NAME + " (" + BuildConfig.GIT_SDK_REVISION + ")"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -37,5 +37,4 @@ interface MatrixCallback<in T> {
|
|||
fun onFailure(failure: Throwable) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
}
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package im.vector.matrix.android.api
|
||||
|
||||
|
||||
/**
|
||||
* This class contains pattern to match the different Matrix ids
|
||||
*/
|
||||
|
@ -154,6 +153,5 @@ object MatrixPatterns {
|
|||
return if (index == -1) {
|
||||
null
|
||||
} else matrixId.substring(index + 1)
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -253,13 +253,5 @@ data class HomeServerConnectionConfig(
|
|||
forceUsageTlsVersions
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ package im.vector.matrix.android.api.extensions
|
|||
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.rest.DeviceInfo
|
||||
import java.util.Collections
|
||||
|
||||
/* ==========================================================================================
|
||||
* MXDeviceInfo
|
||||
|
@ -29,7 +28,6 @@ fun MXDeviceInfo.getFingerprintHumanReadable() = fingerprint()
|
|||
?.chunked(4)
|
||||
?.joinToString(separator = " ")
|
||||
|
||||
|
||||
fun List<DeviceInfo>.sortByLastSeen() {
|
||||
Collections.sort(this, DatedObjectComparators.descComparator)
|
||||
fun MutableList<DeviceInfo>.sortByLastSeen() {
|
||||
sortWith(DatedObjectComparators.descComparator)
|
||||
}
|
|
@ -42,5 +42,4 @@ sealed class Failure(cause: Throwable? = null) : Throwable(cause = cause) {
|
|||
data class CryptoError(val error: MXCryptoError) : Failure(error)
|
||||
|
||||
abstract class FeatureFailure : Failure()
|
||||
|
||||
}
|
|
@ -33,7 +33,6 @@ data class MatrixError(
|
|||
@Json(name = "limit_type") val limitType: String? = null,
|
||||
@Json(name = "admin_contact") val adminUri: String? = null) {
|
||||
|
||||
|
||||
companion object {
|
||||
const val FORBIDDEN = "M_FORBIDDEN"
|
||||
const val UNKNOWN = "M_UNKNOWN"
|
||||
|
|
|
@ -30,9 +30,9 @@ object MatrixLinkify {
|
|||
*
|
||||
* @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
|
||||
if (spannable.isNullOrEmpty()) {
|
||||
if (spannable.isEmpty()) {
|
||||
return false
|
||||
}
|
||||
val text = spannable.toString()
|
||||
|
@ -51,5 +51,4 @@ object MatrixLinkify {
|
|||
}
|
||||
return hasMatch
|
||||
}
|
||||
|
||||
}
|
|
@ -35,6 +35,4 @@ class MatrixPermalinkSpan(private val url: String,
|
|||
override fun onClick(widget: View) {
|
||||
callback?.onUrlClicked(url)
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -33,5 +33,4 @@ sealed class PermalinkData {
|
|||
data class GroupLink(val groupId: String) : PermalinkData()
|
||||
|
||||
data class FallbackLink(val uri: Uri) : PermalinkData()
|
||||
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package im.vector.matrix.android.api.permalinks
|
||||
|
||||
import android.text.TextUtils
|
||||
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
|
||||
*/
|
||||
fun createPermalink(id: String): String? {
|
||||
return if (TextUtils.isEmpty(id)) {
|
||||
return if (id.isEmpty()) {
|
||||
null
|
||||
} 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"
|
||||
* @return the id from the url, ex: "@benoit:matrix.org", or null if the url is not a permalink
|
||||
*/
|
||||
fun getLinkedId(url: String?): String? {
|
||||
val isSupported = url != null && url.startsWith(MATRIX_TO_URL_BASE)
|
||||
fun getLinkedId(url: String): String? {
|
||||
val isSupported = url.startsWith(MATRIX_TO_URL_BASE)
|
||||
|
||||
return if (isSupported) {
|
||||
url!!.substring(MATRIX_TO_URL_BASE.length)
|
||||
url.substring(MATRIX_TO_URL_BASE.length)
|
||||
} else null
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Escape '/' in id, because it is used as a separator
|
||||
*
|
||||
|
@ -89,6 +85,6 @@ object PermalinkFactory {
|
|||
* @return the escaped id
|
||||
*/
|
||||
private fun escape(id: String): String {
|
||||
return id.replace("/".toRegex(), "%2F")
|
||||
return id.replace("/", "%2F")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,5 +72,4 @@ object PermalinkParser {
|
|||
else -> PermalinkData.FallbackLink(uri)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -18,7 +18,6 @@ package im.vector.matrix.android.api.pushrules
|
|||
import im.vector.matrix.android.api.pushrules.rest.PushRule
|
||||
import timber.log.Timber
|
||||
|
||||
|
||||
sealed class Action {
|
||||
object Notify : Action()
|
||||
object DoNotNotify : Action()
|
||||
|
@ -26,7 +25,6 @@ sealed class Action {
|
|||
data class Highlight(val highlight: Boolean) : Action()
|
||||
}
|
||||
|
||||
|
||||
private const val ACTION_NOTIFY = "notify"
|
||||
private const val ACTION_DONT_NOTIFY = "dont_notify"
|
||||
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)
|
||||
?: Action.Sound(ACTION_OBJECT_VALUE_VALUE_DEFAULT)
|
||||
|
||||
}
|
||||
ACTION_OBJECT_SET_TWEAK_VALUE_HIGHLIGHT -> {
|
||||
(actionStrOrObj[ACTION_OBJECT_VALUE_KEY] as? Boolean)?.let { boolValue ->
|
||||
|
@ -104,7 +101,5 @@ fun PushRule.getActions(): List<Action> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
|
|
|
@ -35,9 +35,7 @@ abstract class Condition(val kind: Kind) {
|
|||
else -> UNRECOGNIZE
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
abstract fun isSatisfied(conditionResolver: ConditionResolver): Boolean
|
||||
|
|
|
@ -15,13 +15,11 @@
|
|||
*/
|
||||
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.EventType
|
||||
import im.vector.matrix.android.api.session.events.model.toModel
|
||||
import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
||||
import timber.log.Timber
|
||||
import java.util.regex.Pattern
|
||||
|
||||
class ContainsDisplayNameCondition : Condition(Kind.contains_display_name) {
|
||||
|
||||
|
@ -34,7 +32,7 @@ class ContainsDisplayNameCondition : Condition(Kind.contains_display_name) {
|
|||
}
|
||||
|
||||
fun isSatisfied(event: Event, displayName: String): Boolean {
|
||||
var message = when (event.type) {
|
||||
val message = when (event.type) {
|
||||
EventType.MESSAGE -> {
|
||||
event.content.toModel<MessageContent>()
|
||||
}
|
||||
|
@ -49,7 +47,6 @@ class ContainsDisplayNameCondition : Condition(Kind.contains_display_name) {
|
|||
return caseInsensitiveFind(displayName, message.body)
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* 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 {
|
||||
// add sanity checks
|
||||
if (TextUtils.isEmpty(subString) || TextUtils.isEmpty(longString)) {
|
||||
if (subString.isEmpty() || longString.isEmpty()) {
|
||||
return false
|
||||
}
|
||||
|
||||
var res = false
|
||||
|
||||
try {
|
||||
val pattern = Pattern.compile("(\\W|^)" + Pattern.quote(subString) + "(\\W|$)", Pattern.CASE_INSENSITIVE)
|
||||
res = pattern.matcher(longString).find()
|
||||
val regex = Regex("(\\W|^)" + Regex.escape(subString) + "(\\W|$)", RegexOption.IGNORE_CASE)
|
||||
return regex.containsMatchIn(longString)
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "## caseInsensitiveFind() : failed")
|
||||
}
|
||||
|
||||
return res
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
|
@ -29,7 +29,6 @@ class EventMatchCondition(val key: String, val pattern: String) : Condition(Kind
|
|||
return "'$key' Matches '$pattern'"
|
||||
}
|
||||
|
||||
|
||||
fun isSatisfied(event: Event): Boolean {
|
||||
// TODO encrypted events?
|
||||
val rawJson = MoshiProvider.providesMoshi().adapter(Event::class.java).toJsonValue(event) as? Map<*, *>
|
||||
|
@ -47,10 +46,8 @@ class EventMatchCondition(val key: String, val pattern: String) : Condition(Kind
|
|||
Timber.e(e, "Failed to evaluate push condition")
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private fun extractField(jsonObject: Map<*, *>, fieldPath: String): String? {
|
||||
val fieldParts = fieldPath.split(".")
|
||||
if (fieldParts.isEmpty()) return null
|
||||
|
|
|
@ -42,6 +42,7 @@ interface PushRuleService {
|
|||
|
||||
interface PushRuleListener {
|
||||
fun onMatchRule(event: Event, actions: List<Action>)
|
||||
fun onRoomJoined(roomId: String)
|
||||
fun onRoomLeft(roomId: String)
|
||||
fun onEventRedacted(redactedEventId: String)
|
||||
fun batchFinish()
|
||||
|
|
|
@ -62,6 +62,5 @@ class RoomMemberCountCondition(val iz: String) : Condition(Kind.room_member_coun
|
|||
Timber.d(t)
|
||||
}
|
||||
return null
|
||||
|
||||
}
|
||||
}
|
|
@ -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.room.model.PowerLevels
|
||||
|
||||
|
||||
class SenderNotificationPermissionCondition(val key: String) : Condition(Kind.sender_notification_permission) {
|
||||
|
||||
override fun isSatisfied(conditionResolver: ConditionResolver): Boolean {
|
||||
|
@ -29,7 +28,6 @@ class SenderNotificationPermissionCondition(val key: String) : Condition(Kind.se
|
|||
return "User power level <$key>"
|
||||
}
|
||||
|
||||
|
||||
fun isSatisfied(event: Event, powerLevels: PowerLevels): Boolean {
|
||||
return event.senderId != null && powerLevels.getUserPowerLevel(event.senderId) >= powerLevels.notificationLevel(key)
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ package im.vector.matrix.android.api.pushrules.rest
|
|||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class PushRule(
|
||||
/**
|
||||
|
@ -47,4 +46,3 @@ data class PushRule(
|
|||
*/
|
||||
val pattern: String? = null
|
||||
)
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ package im.vector.matrix.android.api.session
|
|||
import androidx.annotation.MainThread
|
||||
import androidx.lifecycle.LiveData
|
||||
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.session.cache.CacheService
|
||||
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.file.FileService
|
||||
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.room.RoomDirectoryService
|
||||
import im.vector.matrix.android.api.session.room.RoomService
|
||||
|
@ -52,6 +54,7 @@ interface Session :
|
|||
PushRuleService,
|
||||
PushersService,
|
||||
InitialSyncProgressService,
|
||||
HomeServerCapabilitiesService,
|
||||
SecureStorageService {
|
||||
|
||||
/**
|
||||
|
@ -65,7 +68,6 @@ interface Session :
|
|||
val myUserId: String
|
||||
get() = sessionParams.credentials.userId
|
||||
|
||||
|
||||
/**
|
||||
* This method allow to open a session. It does start some service on the background.
|
||||
*/
|
||||
|
@ -138,6 +140,9 @@ interface Session :
|
|||
*/
|
||||
fun onInvalidToken()
|
||||
|
||||
/**
|
||||
* A M_CONSENT_NOT_GIVEN error has been received from the homeserver
|
||||
*/
|
||||
fun onConsentNotGivenError(consentNotGivenError: ConsentNotGivenError)
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
*/
|
||||
fun clearCache(callback: MatrixCallback<Unit>)
|
||||
|
||||
}
|
|
@ -17,6 +17,7 @@
|
|||
package im.vector.matrix.android.api.session.content
|
||||
|
||||
import android.os.Parcelable
|
||||
import androidx.exifinterface.media.ExifInterface
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
|
||||
@Parcelize
|
||||
|
@ -26,6 +27,7 @@ data class ContentAttachmentData(
|
|||
val date: Long = 0,
|
||||
val height: Long? = 0,
|
||||
val width: Long? = 0,
|
||||
val exifOrientation: Int = ExifInterface.ORIENTATION_UNDEFINED,
|
||||
val name: String? = null,
|
||||
val path: String,
|
||||
val mimeType: String,
|
||||
|
@ -38,5 +40,4 @@ data class ContentAttachmentData(
|
|||
AUDIO,
|
||||
VIDEO
|
||||
}
|
||||
|
||||
}
|
|
@ -112,5 +112,4 @@ interface CryptoService {
|
|||
fun addNewSessionListener(newSessionListener: NewSessionListener)
|
||||
|
||||
fun removeSessionListener(listener: NewSessionListener)
|
||||
|
||||
}
|
|
@ -210,5 +210,4 @@ interface KeysBackupService {
|
|||
val isEnabled: Boolean
|
||||
val isStucked: Boolean
|
||||
val state: KeysBackupState
|
||||
|
||||
}
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package im.vector.matrix.android.api.session.events.model
|
||||
|
||||
import android.text.TextUtils
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import im.vector.matrix.android.api.session.crypto.MXCryptoError
|
||||
|
@ -35,11 +34,10 @@ typealias Content = JsonDict
|
|||
* This methods is a facility method to map a json content to a model.
|
||||
*/
|
||||
inline fun <reified T> Content?.toModel(catchError: Boolean = true): T? {
|
||||
return this?.let {
|
||||
val moshi = MoshiProvider.providesMoshi()
|
||||
val moshiAdapter = moshi.adapter(T::class.java)
|
||||
return try {
|
||||
moshiAdapter.fromJsonValue(it)
|
||||
moshiAdapter.fromJsonValue(this)
|
||||
} catch (e: Exception) {
|
||||
if (catchError) {
|
||||
Timber.e(e, "To model failed : $e")
|
||||
|
@ -49,18 +47,15 @@ inline fun <reified T> Content?.toModel(catchError: Boolean = true): T? {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This methods is a facility method to map a model to a json Content
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
inline fun <reified T> T?.toContent(): Content? {
|
||||
return this?.let {
|
||||
inline fun <reified T> T.toContent(): Content {
|
||||
val moshi = MoshiProvider.providesMoshi()
|
||||
val moshiAdapter = moshi.adapter(T::class.java)
|
||||
return moshiAdapter.toJsonValue(it) as Content
|
||||
}
|
||||
return moshiAdapter.toJsonValue(this) as Content
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -81,7 +76,6 @@ data class Event(
|
|||
@Json(name = "redacts") val redacts: String? = null
|
||||
) {
|
||||
|
||||
|
||||
@Transient
|
||||
var mxDecryptionResult: OlmDecryptionResult? = null
|
||||
|
||||
|
@ -91,7 +85,6 @@ data class Event(
|
|||
@Transient
|
||||
var sendState: SendState = SendState.UNKNOWN
|
||||
|
||||
|
||||
/**
|
||||
* Check if event is a state event.
|
||||
* @return true if event is state event.
|
||||
|
@ -108,7 +101,7 @@ data class Event(
|
|||
* @return true if this event is encrypted.
|
||||
*/
|
||||
fun isEncrypted(): Boolean {
|
||||
return TextUtils.equals(type, EventType.ENCRYPTED)
|
||||
return type == EventType.ENCRYPTED
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -136,11 +129,12 @@ data class Event(
|
|||
* @return the event content
|
||||
*/
|
||||
fun getClearContent(): Content? {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return mxDecryptionResult?.payload?.get("content") as? Content ?: content
|
||||
}
|
||||
|
||||
fun toContentStringWithIndent(): String {
|
||||
val contentMap = toContent()?.toMutableMap() ?: HashMap()
|
||||
val contentMap = toContent().toMutableMap()
|
||||
return JSONObject(contentMap).toString(4)
|
||||
}
|
||||
|
||||
|
@ -194,10 +188,8 @@ data class Event(
|
|||
result = 31 * result + sendState.hashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
fun Event.isTextMessage(): Boolean {
|
||||
return getClearType() == EventType.MESSAGE
|
||||
&& when (getClearContent()?.toModel<MessageContent>()?.type) {
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package im.vector.matrix.android.api.session.events.model
|
||||
|
||||
|
||||
/**
|
||||
* Constants defining known event types from Matrix specifications.
|
||||
*/
|
||||
|
@ -93,7 +92,6 @@ object EventType {
|
|||
STATE_PINNED_EVENT
|
||||
)
|
||||
|
||||
|
||||
fun isStateEvent(type: String): Boolean {
|
||||
return STATE_EVENTS.contains(type)
|
||||
}
|
||||
|
|
|
@ -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()}"
|
||||
}
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
package im.vector.matrix.android.api.session.events.model
|
||||
|
||||
|
||||
/**
|
||||
* Constants defining known event relation types from Matrix specifications
|
||||
*/
|
||||
|
@ -27,5 +26,4 @@ object RelationType {
|
|||
const val REPLACE = "m.replace"
|
||||
/** Lets you define an event which references an existing event.*/
|
||||
const val REFERENCE = "m.reference"
|
||||
|
||||
}
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
package im.vector.matrix.android.api.session.events.model
|
||||
|
||||
|
||||
interface UnsignedRelationInfo {
|
||||
val limited : Boolean?
|
||||
val count: Int?
|
||||
|
|
|
@ -20,7 +20,6 @@ import im.vector.matrix.android.api.MatrixCallback
|
|||
import im.vector.matrix.android.internal.crypto.attachments.ElementToDecrypt
|
||||
import java.io.File
|
||||
|
||||
|
||||
/**
|
||||
* This interface defines methods to get files.
|
||||
*/
|
||||
|
|
|
@ -19,7 +19,6 @@ package im.vector.matrix.android.api.session.group
|
|||
import androidx.lifecycle.LiveData
|
||||
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
||||
|
||||
|
||||
/**
|
||||
* This interface defines methods to get groups. It's implemented at the session level.
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -19,7 +19,6 @@ import androidx.lifecycle.LiveData
|
|||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import java.util.UUID
|
||||
|
||||
|
||||
interface PushersService {
|
||||
|
||||
/**
|
||||
|
@ -53,7 +52,6 @@ interface PushersService {
|
|||
append: Boolean,
|
||||
withEventIdOnly: Boolean): UUID
|
||||
|
||||
|
||||
fun removeHttpPusher(pushkey: String, appId: String, callback: MatrixCallback<Unit>)
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -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.model.RoomSummary
|
||||
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.send.DraftService
|
||||
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.timeline.TimelineService
|
||||
import im.vector.matrix.android.api.util.Optional
|
||||
|
||||
/**
|
||||
* This interface defines methods to interact within a room.
|
||||
|
@ -37,6 +39,7 @@ interface Room :
|
|||
ReadService,
|
||||
MembershipService,
|
||||
StateService,
|
||||
ReportingService,
|
||||
RelationService,
|
||||
RoomCryptoService {
|
||||
|
||||
|
@ -49,8 +52,7 @@ interface Room :
|
|||
* A live [RoomSummary] associated with the 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?
|
||||
|
||||
}
|
|
@ -42,5 +42,4 @@ interface RoomDirectoryService {
|
|||
* Includes both the available protocols and all fields required for queries against each protocol.
|
||||
*/
|
||||
fun getThirdPartyProtocol(callback: MatrixCallback<Map<String, ThirdPartyProtocol>>): Cancelable
|
||||
|
||||
}
|
|
@ -54,4 +54,8 @@ interface RoomService {
|
|||
*/
|
||||
fun liveRoomSummaries(): LiveData<List<RoomSummary>>
|
||||
|
||||
/**
|
||||
* Mark all rooms as read
|
||||
*/
|
||||
fun markAllAsRead(roomIds: List<String>, callback: MatrixCallback<Unit>): Cancelable
|
||||
}
|
|
@ -21,5 +21,4 @@ import im.vector.matrix.android.api.failure.Failure
|
|||
sealed class CreateRoomFailure : Failure.FeatureFailure() {
|
||||
|
||||
object CreatedWithTimeout: CreateRoomFailure()
|
||||
|
||||
}
|
|
@ -21,5 +21,4 @@ import im.vector.matrix.android.api.failure.Failure
|
|||
sealed class JoinRoomFailure : Failure.FeatureFailure() {
|
||||
|
||||
object JoinedWithTimeout : JoinRoomFailure()
|
||||
|
||||
}
|
|
@ -64,5 +64,4 @@ interface MembershipService {
|
|||
* Leave the room, or reject an invitation.
|
||||
*/
|
||||
fun leave(callback: MatrixCallback<Unit>): Cancelable
|
||||
|
||||
}
|
|
@ -43,5 +43,4 @@ enum class Membership(val value: String) {
|
|||
fun isLeft(): Boolean {
|
||||
return this == KNOCK || this == LEAVE || this == BAN
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,11 +16,9 @@
|
|||
|
||||
package im.vector.matrix.android.api.session.room.model
|
||||
|
||||
import android.text.TextUtils
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import im.vector.matrix.android.api.session.events.model.EventType
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Class representing the EventType.EVENT_TYPE_STATE_ROOM_POWER_LEVELS state event content.
|
||||
|
@ -46,13 +44,7 @@ data class PowerLevels(
|
|||
* @return the power level
|
||||
*/
|
||||
fun getUserPowerLevel(userId: String): Int {
|
||||
// sanity check
|
||||
if (!TextUtils.isEmpty(userId)) {
|
||||
val powerLevel = users[userId]
|
||||
return powerLevel ?: usersDefault
|
||||
}
|
||||
|
||||
return usersDefault
|
||||
return users.getOrElse(userId) { usersDefault }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -61,10 +53,8 @@ data class PowerLevels(
|
|||
* @param userId the user
|
||||
* @param powerLevel the new power level
|
||||
*/
|
||||
fun setUserPowerLevel(userId: String?, powerLevel: Int) {
|
||||
if (null != userId) {
|
||||
users[userId] = Integer.valueOf(powerLevel)
|
||||
}
|
||||
fun setUserPowerLevel(userId: String, powerLevel: Int) {
|
||||
users[userId] = powerLevel
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -75,10 +65,9 @@ data class PowerLevels(
|
|||
* @return true if the user can send the event
|
||||
*/
|
||||
fun maySendEventOfType(eventTypeString: String, userId: String): Boolean {
|
||||
return if (!TextUtils.isEmpty(eventTypeString) && !TextUtils.isEmpty(userId)) {
|
||||
return if (eventTypeString.isNotEmpty() && userId.isNotEmpty()) {
|
||||
getUserPowerLevel(userId) >= minimumPowerLevelForSendingEventAsMessage(eventTypeString)
|
||||
} else false
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -113,25 +102,20 @@ data class PowerLevels(
|
|||
return events[eventTypeString] ?: stateDefault
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the notification level for a dedicated key.
|
||||
*
|
||||
* @param key the notification key
|
||||
* @return the level
|
||||
*/
|
||||
fun notificationLevel(key: String?): Int {
|
||||
if (null != key && notifications.containsKey(key)) {
|
||||
val valAsVoid = notifications[key]
|
||||
fun notificationLevel(key: String): Int {
|
||||
val valAsVoid = notifications[key] ?: return 50
|
||||
|
||||
// the first implementation was a string value
|
||||
return if (valAsVoid is String) {
|
||||
Integer.parseInt(valAsVoid)
|
||||
valAsVoid.toInt()
|
||||
} else {
|
||||
valAsVoid as Int
|
||||
}
|
||||
}
|
||||
|
||||
return 50
|
||||
}
|
||||
}
|
|
@ -38,9 +38,13 @@ data class RoomSummary(
|
|||
val tags: List<RoomTag> = emptyList(),
|
||||
val membership: Membership = Membership.NONE,
|
||||
val versioningState: VersioningState = VersioningState.NONE,
|
||||
val readMarkerId: String? = null,
|
||||
val userDrafts: List<UserDraft> = emptyList()
|
||||
) {
|
||||
|
||||
val isVersioned: Boolean
|
||||
get() = versioningState != VersioningState.NONE
|
||||
|
||||
val hasNewMessages: Boolean
|
||||
get() = notificationCount != 0
|
||||
}
|
|
@ -31,5 +31,4 @@ data class CallAnswerContent(
|
|||
@Json(name = "type") val type: String,
|
||||
@Json(name = "sdp") val sdp: String
|
||||
)
|
||||
|
||||
}
|
|
@ -32,5 +32,4 @@ data class CallCandidatesContent(
|
|||
@Json(name = "sdpMLineIndex") val sdpMLineIndex: String,
|
||||
@Json(name = "candidate") val candidate: String
|
||||
)
|
||||
|
||||
}
|
|
@ -37,6 +37,5 @@ data class CallInviteContent(
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
fun isVideo(): Boolean = offer.sdp.contains(Offer.SDP_VIDEO)
|
||||
}
|
|
@ -145,15 +145,7 @@ class CreateRoomParams {
|
|||
*/
|
||||
fun setHistoryVisibility(historyVisibility: RoomHistoryVisibility?) {
|
||||
// Remove the existing value if any.
|
||||
if (initialStates != null && !initialStates!!.isEmpty()) {
|
||||
val newInitialStates = ArrayList<Event>()
|
||||
for (event in initialStates!!) {
|
||||
if (event.getClearType() != EventType.STATE_HISTORY_VISIBILITY) {
|
||||
newInitialStates.add(event)
|
||||
}
|
||||
}
|
||||
initialStates = newInitialStates
|
||||
}
|
||||
initialStates?.removeAll { it.getClearType() == EventType.STATE_HISTORY_VISIBILITY }
|
||||
|
||||
if (historyVisibility != null) {
|
||||
val contentMap = HashMap<String, RoomHistoryVisibility>()
|
||||
|
|
|
@ -28,5 +28,3 @@ data class RoomCreateContent(
|
|||
@Json(name = "room_version") val roomVersion: String? = null,
|
||||
@Json(name = "predecessor") val predecessor: Predecessor? = null
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -42,16 +42,6 @@ data class ImageInfo(
|
|||
*/
|
||||
@Json(name = "size") val size: Int = 0,
|
||||
|
||||
/**
|
||||
* Not documented
|
||||
*/
|
||||
@Json(name = "rotation") val rotation: Int = 0,
|
||||
|
||||
/**
|
||||
* Not documented
|
||||
*/
|
||||
@Json(name = "orientation") val orientation: Int = 0,
|
||||
|
||||
/**
|
||||
* Metadata about the image referred to in thumbnail_url.
|
||||
*/
|
||||
|
|
|
@ -19,7 +19,6 @@ package im.vector.matrix.android.api.session.room.model.message
|
|||
import im.vector.matrix.android.api.session.events.model.Content
|
||||
import im.vector.matrix.android.api.session.room.model.relation.RelationDefaultContent
|
||||
|
||||
|
||||
interface MessageContent {
|
||||
val type: String
|
||||
val body: String
|
||||
|
@ -27,7 +26,6 @@ interface MessageContent {
|
|||
val newContent: Content?
|
||||
}
|
||||
|
||||
|
||||
fun MessageContent?.isReply(): Boolean {
|
||||
return this?.relatesTo?.inReplyTo?.eventId != null
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ package im.vector.matrix.android.api.session.room.model.message
|
|||
|
||||
import im.vector.matrix.android.internal.crypto.model.rest.EncryptedFileInfo
|
||||
|
||||
|
||||
/**
|
||||
* Interface for message which can contains an encrypted file
|
||||
*/
|
||||
|
|
|
@ -21,6 +21,7 @@ import im.vector.matrix.android.api.session.events.model.Event
|
|||
import im.vector.matrix.android.api.session.room.model.EventAnnotationsSummary
|
||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
import im.vector.matrix.android.api.util.Optional
|
||||
|
||||
/**
|
||||
* In some cases, events may wish to reference other events.
|
||||
|
@ -47,26 +48,21 @@ import im.vector.matrix.android.api.util.Cancelable
|
|||
*/
|
||||
interface RelationService {
|
||||
|
||||
|
||||
/**
|
||||
* Sends a reaction (emoji) to the targetedEvent.
|
||||
* @param reaction the reaction (preferably emoji)
|
||||
* @param targetEventId the id of the event being reacted
|
||||
* @param reaction the reaction (preferably emoji)
|
||||
*/
|
||||
fun sendReaction(reaction: String,
|
||||
targetEventId: String): Cancelable
|
||||
|
||||
fun sendReaction(targetEventId: String,
|
||||
reaction: String): Cancelable
|
||||
|
||||
/**
|
||||
* Undo a reaction (emoji) to the targetedEvent.
|
||||
* @param reaction the reaction (preferably emoji)
|
||||
* @param targetEventId the id of the event being reacted
|
||||
* @param myUserId used to know if a reaction event was made by the user
|
||||
* @param reaction the reaction (preferably emoji)
|
||||
*/
|
||||
fun undoReaction(reaction: String,
|
||||
targetEventId: String,
|
||||
myUserId: String)//: Cancelable
|
||||
|
||||
fun undoReaction(targetEventId: String,
|
||||
reaction: String): Cancelable
|
||||
|
||||
/**
|
||||
* Edit a text message body. Limited to "m.text" contentType
|
||||
|
@ -80,7 +76,6 @@ interface RelationService {
|
|||
newBodyAutoMarkdown: Boolean,
|
||||
compatibilityBodyText: String = "* $newBodyText"): Cancelable
|
||||
|
||||
|
||||
/**
|
||||
* Edit a reply. This is a special case because replies contains fallback text as a prefix.
|
||||
* This method will take the new body (stripped from fallbacks) and re-add them before sending.
|
||||
|
@ -95,11 +90,10 @@ interface RelationService {
|
|||
compatibilityBodyText: String = "* $newBodyText"): Cancelable
|
||||
|
||||
/**
|
||||
* Get's the edit history of the given event
|
||||
* Get the edit history of the given event
|
||||
*/
|
||||
fun fetchEditHistory(eventId: String, callback: MatrixCallback<List<Event>>)
|
||||
|
||||
|
||||
/**
|
||||
* Reply to an event in the timeline (must be in same room)
|
||||
* https://matrix.org/docs/spec/client_server/r0.4.0.html#id350
|
||||
|
@ -111,7 +105,5 @@ interface RelationService {
|
|||
replyText: String,
|
||||
autoMarkdown: Boolean = false): Cancelable?
|
||||
|
||||
fun getEventSummaryLive(eventId: String): LiveData<EventAnnotationsSummary>
|
||||
|
||||
|
||||
fun getEventSummaryLive(eventId: String): LiveData<Optional<EventAnnotationsSummary>>
|
||||
}
|
|
@ -27,5 +27,4 @@ data class RoomTag(
|
|||
val ROOM_TAG_NO_TAG = "m.recent"
|
||||
val ROOM_TAG_SERVER_NOTICE = "m.server_notice"
|
||||
}
|
||||
|
||||
}
|
|
@ -51,5 +51,4 @@ data class RoomDirectoryData(
|
|||
companion object {
|
||||
const val DEFAULT_HOME_SERVER_NAME = "Matrix"
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -51,7 +51,6 @@ data class ThirdPartyProtocolInstance(
|
|||
@Json(name = "instance_id")
|
||||
var instanceId: String? = null,
|
||||
|
||||
|
||||
/**
|
||||
* FIXDOC Not documented on matrix.org doc
|
||||
*/
|
||||
|
|
|
@ -19,6 +19,7 @@ package im.vector.matrix.android.api.session.room.read
|
|||
import androidx.lifecycle.LiveData
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.session.room.model.ReadReceipt
|
||||
import im.vector.matrix.android.api.util.Optional
|
||||
|
||||
/**
|
||||
* This interface defines methods to handle read receipts and read marker in a room. It's implemented at the room level.
|
||||
|
@ -40,7 +41,24 @@ interface ReadService {
|
|||
*/
|
||||
fun setReadMarker(fullyReadEventId: String, callback: MatrixCallback<Unit>)
|
||||
|
||||
/**
|
||||
* Check if an event is already read, ie. your read receipt is set on a more recent event.
|
||||
*/
|
||||
fun isEventRead(eventId: String): Boolean
|
||||
|
||||
/**
|
||||
* Returns a live read marker id for the room.
|
||||
*/
|
||||
fun getReadMarkerLive(): LiveData<Optional<String>>
|
||||
|
||||
/**
|
||||
* Returns a live read receipt id for the room.
|
||||
*/
|
||||
fun getMyReadReceiptLive(): LiveData<Optional<String>>
|
||||
|
||||
/**
|
||||
* Returns a live list of read receipts for a given event
|
||||
* @param eventId: the event
|
||||
*/
|
||||
fun getEventReadReceiptsLive(eventId: String): LiveData<List<ReadReceipt>>
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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.room.reporting
|
||||
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
|
||||
/**
|
||||
* This interface defines methods to report content of an event.
|
||||
*/
|
||||
interface ReportingService {
|
||||
|
||||
/**
|
||||
* Report content
|
||||
* Ref: https://matrix.org/docs/spec/client_server/latest#post-matrix-client-r0-rooms-roomid-report-eventid
|
||||
*/
|
||||
fun reportContent(eventId: String, score: Int, reason: String, callback: MatrixCallback<Unit>): Cancelable
|
||||
}
|
|
@ -35,5 +35,4 @@ interface DraftService {
|
|||
* The draft list can contain one draft for {regular, reply, quote} and an arbitrary number of {edit} drafts
|
||||
*/
|
||||
fun getDraftsLive(): LiveData<List<UserDraft>>
|
||||
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ import im.vector.matrix.android.api.session.room.model.message.MessageType
|
|||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
|
||||
|
||||
/**
|
||||
* This interface defines methods to send events in a room. It's implemented at the room level.
|
||||
*/
|
||||
|
@ -66,7 +65,6 @@ interface SendService {
|
|||
*/
|
||||
fun redactEvent(event: Event, reason: String?): Cancelable
|
||||
|
||||
|
||||
/**
|
||||
* Schedule this message to be resent
|
||||
* @param localEcho the unsent local echo
|
||||
|
@ -79,7 +77,6 @@ interface SendService {
|
|||
*/
|
||||
fun resendMediaMessage(localEcho: TimelineEvent): Cancelable?
|
||||
|
||||
|
||||
/**
|
||||
* Remove this failed message from the timeline
|
||||
* @param localEcho the unsent local echo
|
||||
|
@ -92,5 +89,4 @@ interface SendService {
|
|||
* Resend all failed messages one by one (and keep order)
|
||||
*/
|
||||
fun resendAllFailedMessages()
|
||||
|
||||
}
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package im.vector.matrix.android.api.session.room.send
|
||||
|
||||
|
||||
enum class SendState {
|
||||
UNKNOWN,
|
||||
// the event has not been sent
|
||||
|
@ -46,7 +45,4 @@ enum class SendState {
|
|||
fun hasFailed() = HAS_FAILED_STATES.contains(this)
|
||||
|
||||
fun isSending() = IS_SENDING_STATES.contains(this)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -27,5 +27,4 @@ interface StateService {
|
|||
fun updateTopic(topic: String, callback: MatrixCallback<Unit>)
|
||||
|
||||
fun getStateEvent(eventType: String): Event?
|
||||
|
||||
}
|
|
@ -32,6 +32,8 @@ interface Timeline {
|
|||
|
||||
var listener: Listener?
|
||||
|
||||
val isLive: Boolean
|
||||
|
||||
/**
|
||||
* This should be called before any other method after creating the timeline. It ensures the underlying database is open
|
||||
*/
|
||||
|
@ -42,6 +44,12 @@ interface Timeline {
|
|||
*/
|
||||
fun dispose()
|
||||
|
||||
/**
|
||||
* This method restarts the timeline, erases all built events and pagination states.
|
||||
* It then loads events around the eventId. If eventId is null, it does restart the live timeline.
|
||||
*/
|
||||
fun restartWithEventId(eventId: String?)
|
||||
|
||||
/**
|
||||
* Check if the timeline can be enriched by paginating.
|
||||
* @param the direction to check in
|
||||
|
@ -56,10 +64,37 @@ interface Timeline {
|
|||
*/
|
||||
fun paginate(direction: Direction, count: Int)
|
||||
|
||||
/**
|
||||
* Returns the number of sending events
|
||||
*/
|
||||
fun pendingEventCount(): Int
|
||||
|
||||
/**
|
||||
* Returns the number of failed sending events.
|
||||
*/
|
||||
fun failedToDeliverEventCount(): Int
|
||||
|
||||
/**
|
||||
* Returns the index of a built event or null.
|
||||
*/
|
||||
fun getIndexOfEvent(eventId: String?): Int?
|
||||
|
||||
/**
|
||||
* Returns the built [TimelineEvent] at index or null
|
||||
*/
|
||||
fun getTimelineEventAtIndex(index: Int): TimelineEvent?
|
||||
|
||||
/**
|
||||
* Returns the built [TimelineEvent] with eventId or null
|
||||
*/
|
||||
fun getTimelineEventWithId(eventId: String?): TimelineEvent?
|
||||
|
||||
/**
|
||||
* Returns the first displayable events starting from eventId.
|
||||
* It does depend on the provided [TimelineSettings].
|
||||
*/
|
||||
fun getFirstDisplayableEventId(eventId: String): String?
|
||||
|
||||
interface Listener {
|
||||
/**
|
||||
* Call when the timeline has been updated through pagination or sync.
|
||||
|
@ -81,5 +116,4 @@ interface Timeline {
|
|||
*/
|
||||
BACKWARDS
|
||||
}
|
||||
|
||||
}
|
|
@ -40,7 +40,8 @@ data class TimelineEvent(
|
|||
val isUniqueDisplayName: Boolean,
|
||||
val senderAvatar: String?,
|
||||
val annotations: EventAnnotationsSummary? = null,
|
||||
val readReceipts: List<ReadReceipt> = emptyList()
|
||||
val readReceipts: List<ReadReceipt> = emptyList(),
|
||||
val hasReadMarker: Boolean = false
|
||||
) {
|
||||
|
||||
val metadata = HashMap<String, Any>()
|
||||
|
@ -87,7 +88,6 @@ data class TimelineEvent(
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tells if the event has been edited
|
||||
*/
|
||||
|
@ -106,7 +106,6 @@ fun TimelineEvent.getEditedEventId(): String? {
|
|||
fun TimelineEvent.getLastMessageContent(): MessageContent? = annotations?.editSummary?.aggregatedContent?.toModel()
|
||||
?: root.getClearContent().toModel()
|
||||
|
||||
|
||||
/**
|
||||
* Get last Message body, after a possible edition
|
||||
*/
|
||||
|
@ -120,7 +119,6 @@ fun TimelineEvent.getLastMessageBody(): String? {
|
|||
return null
|
||||
}
|
||||
|
||||
|
||||
fun TimelineEvent.getTextEditableContent(): String? {
|
||||
val originalContent = root.getClearContent().toModel<MessageContent>() ?: return null
|
||||
val isReply = originalContent.isReply() || root.content.toModel<EncryptedEventContent>()?.relatesTo?.inReplyTo?.eventId != null
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package im.vector.matrix.android.api.session.room.timeline
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import im.vector.matrix.android.api.util.Optional
|
||||
|
||||
/**
|
||||
* This interface defines methods to interact with the timeline. It's implemented at the room level.
|
||||
|
@ -32,9 +33,7 @@ interface TimelineService {
|
|||
*/
|
||||
fun createTimeline(eventId: String?, settings: TimelineSettings): Timeline
|
||||
|
||||
|
||||
fun getTimeLineEvent(eventId: String): TimelineEvent?
|
||||
|
||||
|
||||
fun liveTimeLineEvent(eventId: String): LiveData<TimelineEvent>
|
||||
fun getTimeLineEventLive(eventId: String): LiveData<Optional<TimelineEvent>>
|
||||
}
|
|
@ -24,5 +24,4 @@ interface SecureStorageService {
|
|||
fun securelyStoreObject(any: Any, keyAlias: String, outputStream: OutputStream)
|
||||
|
||||
fun <T> loadSecureSecret(inputStream: InputStream, keyAlias: String): T?
|
||||
|
||||
}
|
||||
|
|
|
@ -27,5 +27,4 @@ interface SignOutService {
|
|||
* Sign out
|
||||
*/
|
||||
fun signOut(callback: MatrixCallback<Unit>)
|
||||
|
||||
}
|
|
@ -21,6 +21,7 @@ import androidx.paging.PagedList
|
|||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.session.user.model.User
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
import im.vector.matrix.android.api.util.Optional
|
||||
|
||||
/**
|
||||
* This interface defines methods to get users. It's implemented at the session level.
|
||||
|
@ -47,9 +48,9 @@ interface UserService {
|
|||
/**
|
||||
* Observe a live user from a userId
|
||||
* @param userId the userId to look for.
|
||||
* @return a Livedata of user with userId
|
||||
* @return a LiveData of user with userId
|
||||
*/
|
||||
fun liveUser(userId: String): LiveData<User?>
|
||||
fun liveUser(userId: String): LiveData<Optional<User>>
|
||||
|
||||
/**
|
||||
* Observe a live list of users sorted alphabetically
|
||||
|
@ -63,5 +64,4 @@ interface UserService {
|
|||
* @return a Livedata of users
|
||||
*/
|
||||
fun livePagedUsers(filter: String? = null): LiveData<PagedList<User>>
|
||||
|
||||
}
|
|
@ -29,4 +29,3 @@ interface Cancelable {
|
|||
// no-op
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
package im.vector.matrix.android.api.util
|
||||
|
||||
|
||||
object ContentUtils {
|
||||
fun extractUsefulTextFromReply(repliedBody: String): String {
|
||||
val lines = repliedBody.lines()
|
||||
|
@ -39,9 +38,10 @@ object ContentUtils {
|
|||
fun extractUsefulTextFromHtmlReply(repliedBody: String): String {
|
||||
if (repliedBody.startsWith("<mx-reply>")) {
|
||||
val closingTagIndex = repliedBody.lastIndexOf("</mx-reply>")
|
||||
if (closingTagIndex != -1)
|
||||
if (closingTagIndex != -1) {
|
||||
return repliedBody.substring(closingTagIndex + "</mx-reply>".length).trim()
|
||||
}
|
||||
}
|
||||
return repliedBody
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
|
||||
* 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.util
|
||||
|
||||
data class Optional<T : Any> constructor(private val value: T?) {
|
||||
|
||||
fun get(): T {
|
||||
return value!!
|
||||
}
|
||||
|
||||
fun getOrNull(): T? {
|
||||
return value
|
||||
}
|
||||
|
||||
fun getOrElse(fn: () -> T): T {
|
||||
return value ?: fn()
|
||||
}
|
||||
|
||||
fun hasValue(): Boolean {
|
||||
return value != null
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun <T : Any> from(value: T?): Optional<T> {
|
||||
return Optional(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : Any> T?.toOptional() = Optional(this)
|
|
@ -47,5 +47,4 @@ internal interface AuthAPI {
|
|||
@Headers("CONNECT_TIMEOUT:60000", "READ_TIMEOUT:60000", "WRITE_TIMEOUT:60000")
|
||||
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "login")
|
||||
fun login(@Body loginParams: PasswordLoginParams): Call<Credentials>
|
||||
|
||||
}
|
||||
|
|
|
@ -55,11 +55,9 @@ internal abstract class AuthModule {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Binds
|
||||
abstract fun bindSessionParamsStore(sessionParamsStore: RealmSessionParamsStore): SessionParamsStore
|
||||
|
||||
@Binds
|
||||
abstract fun bindAuthenticator(authenticator: DefaultAuthenticator): Authenticator
|
||||
|
||||
}
|
||||
|
|
|
@ -39,9 +39,10 @@ import kotlinx.coroutines.launch
|
|||
import kotlinx.coroutines.withContext
|
||||
import okhttp3.OkHttpClient
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Provider
|
||||
|
||||
internal class DefaultAuthenticator @Inject constructor(@Unauthenticated
|
||||
private val okHttpClient: OkHttpClient,
|
||||
private val okHttpClient: Provider<OkHttpClient>,
|
||||
private val retrofitFactory: RetrofitFactory,
|
||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||
private val sessionParamsStore: SessionParamsStore,
|
||||
|
@ -97,7 +98,6 @@ internal class DefaultAuthenticator @Inject constructor(@Unauthenticated
|
|||
private suspend fun authenticate(homeServerConnectionConfig: HomeServerConnectionConfig,
|
||||
login: String,
|
||||
password: String) = withContext(coroutineDispatchers.io) {
|
||||
|
||||
val authAPI = buildAuthAPI(homeServerConnectionConfig)
|
||||
val loginParams = if (Patterns.EMAIL_ADDRESS.matcher(login).matches()) {
|
||||
PasswordLoginParams.thirdPartyIdentifier(ThreePidMedium.EMAIL, login, password, "Mobile")
|
||||
|
@ -119,9 +119,7 @@ internal class DefaultAuthenticator @Inject constructor(@Unauthenticated
|
|||
}
|
||||
|
||||
private fun buildAuthAPI(homeServerConnectionConfig: HomeServerConnectionConfig): AuthAPI {
|
||||
val retrofit = retrofitFactory.create(okHttpClient, homeServerConnectionConfig.homeServerUri.toString())
|
||||
val retrofit = retrofitFactory.create(okHttpClient.get(), homeServerConnectionConfig.homeServerUri.toString())
|
||||
return retrofit.create(AuthAPI::class.java)
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -26,7 +26,6 @@ internal data class PasswordLoginParams(@Json(name = "identifier") val identifie
|
|||
@Json(name = "initial_device_display_name") val deviceDisplayName: String?,
|
||||
@Json(name = "device_id") val deviceId: String?) : LoginParams {
|
||||
|
||||
|
||||
companion object {
|
||||
|
||||
val IDENTIFIER_KEY_TYPE_USER = "m.id.user"
|
||||
|
@ -40,7 +39,6 @@ internal data class PasswordLoginParams(@Json(name = "identifier") val identifie
|
|||
val IDENTIFIER_KEY_COUNTRY = "country"
|
||||
val IDENTIFIER_KEY_NUMBER = "number"
|
||||
|
||||
|
||||
fun userIdentifier(user: String,
|
||||
password: String,
|
||||
deviceDisplayName: String? = null,
|
||||
|
@ -49,7 +47,6 @@ internal data class PasswordLoginParams(@Json(name = "identifier") val identifie
|
|||
identifier[IDENTIFIER_KEY_TYPE] = IDENTIFIER_KEY_TYPE_USER
|
||||
identifier[IDENTIFIER_KEY_USER] = user
|
||||
return PasswordLoginParams(identifier, password, LoginFlowTypes.PASSWORD, deviceDisplayName, deviceId)
|
||||
|
||||
}
|
||||
|
||||
fun thirdPartyIdentifier(medium: String,
|
||||
|
@ -62,7 +59,6 @@ internal data class PasswordLoginParams(@Json(name = "identifier") val identifie
|
|||
identifier[IDENTIFIER_KEY_MEDIUM] = medium
|
||||
identifier[IDENTIFIER_KEY_ADDRESS] = address
|
||||
return PasswordLoginParams(identifier, password, LoginFlowTypes.PASSWORD, deviceDisplayName, deviceId)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue