mirror of
https://github.com/element-hq/element-android
synced 2024-11-24 02:15:35 +03:00
Merge branch 'develop' into feature/bca/fix_switch_space_on_tap_notif
This commit is contained in:
commit
e2e3f72564
54 changed files with 139 additions and 675 deletions
|
@ -61,8 +61,9 @@ Supported filename extensions are:
|
||||||
|
|
||||||
- ``.feature``: Signifying a new feature in Element Android or in the Matrix SDK.
|
- ``.feature``: Signifying a new feature in Element Android or in the Matrix SDK.
|
||||||
- ``.bugfix``: Signifying a bug fix.
|
- ``.bugfix``: Signifying a bug fix.
|
||||||
|
- ``.wip``: Signifying a work in progress change, typically a component of a larger feature which will be enabled once all tasks are complete.
|
||||||
- ``.doc``: Signifying a documentation improvement.
|
- ``.doc``: Signifying a documentation improvement.
|
||||||
- ``.removal``: Signifying a deprecation or removal of public API. Can be used to notifying about API change in the Matrix SDK
|
- ``.sdk``: Signifying a change to the Matrix SDK, this could be an addition, deprecation or removal of a public API.
|
||||||
- ``.misc``: Any other changes.
|
- ``.misc``: Any other changes.
|
||||||
|
|
||||||
See https://github.com/twisted/towncrier#news-fragments if you need more details.
|
See https://github.com/twisted/towncrier#news-fragments if you need more details.
|
||||||
|
|
|
@ -47,12 +47,10 @@ android {
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(":library:ui-styles")
|
implementation project(":library:ui-styles")
|
||||||
|
implementation project(":library:core-utils")
|
||||||
|
|
||||||
implementation 'com.github.chrisbanes:PhotoView:2.3.0'
|
implementation 'com.github.chrisbanes:PhotoView:2.3.0'
|
||||||
|
|
||||||
implementation libs.rx.rxKotlin
|
|
||||||
implementation libs.rx.rxAndroid
|
|
||||||
|
|
||||||
implementation libs.androidx.core
|
implementation libs.androidx.core
|
||||||
implementation libs.androidx.appCompat
|
implementation libs.androidx.appCompat
|
||||||
implementation libs.androidx.recyclerview
|
implementation libs.androidx.recyclerview
|
||||||
|
|
|
@ -20,12 +20,9 @@ import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import im.vector.lib.attachmentviewer.databinding.ItemVideoAttachmentBinding
|
import im.vector.lib.attachmentviewer.databinding.ItemVideoAttachmentBinding
|
||||||
import io.reactivex.Observable
|
import im.vector.lib.core.utils.timer.CountUpTimer
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
|
||||||
import io.reactivex.disposables.Disposable
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
|
|
||||||
// TODO, it would be probably better to use a unique media player
|
// TODO, it would be probably better to use a unique media player
|
||||||
// for better customization and control
|
// for better customization and control
|
||||||
|
@ -35,7 +32,7 @@ class VideoViewHolder constructor(itemView: View) :
|
||||||
|
|
||||||
private var isSelected = false
|
private var isSelected = false
|
||||||
private var mVideoPath: String? = null
|
private var mVideoPath: String? = null
|
||||||
private var progressDisposable: Disposable? = null
|
private var countUpTimer: CountUpTimer? = null
|
||||||
private var progress: Int = 0
|
private var progress: Int = 0
|
||||||
private var wasPaused = false
|
private var wasPaused = false
|
||||||
|
|
||||||
|
@ -47,8 +44,7 @@ class VideoViewHolder constructor(itemView: View) :
|
||||||
|
|
||||||
override fun onRecycled() {
|
override fun onRecycled() {
|
||||||
super.onRecycled()
|
super.onRecycled()
|
||||||
progressDisposable?.dispose()
|
stopTimer()
|
||||||
progressDisposable = null
|
|
||||||
mVideoPath = null
|
mVideoPath = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,8 +68,7 @@ class VideoViewHolder constructor(itemView: View) :
|
||||||
override fun entersBackground() {
|
override fun entersBackground() {
|
||||||
if (views.videoView.isPlaying) {
|
if (views.videoView.isPlaying) {
|
||||||
progress = views.videoView.currentPosition
|
progress = views.videoView.currentPosition
|
||||||
progressDisposable?.dispose()
|
stopTimer()
|
||||||
progressDisposable = null
|
|
||||||
views.videoView.stopPlayback()
|
views.videoView.stopPlayback()
|
||||||
views.videoView.pause()
|
views.videoView.pause()
|
||||||
}
|
}
|
||||||
|
@ -91,8 +86,7 @@ class VideoViewHolder constructor(itemView: View) :
|
||||||
} else {
|
} else {
|
||||||
progress = 0
|
progress = 0
|
||||||
}
|
}
|
||||||
progressDisposable?.dispose()
|
stopTimer()
|
||||||
progressDisposable = null
|
|
||||||
} else {
|
} else {
|
||||||
if (mVideoPath != null) {
|
if (mVideoPath != null) {
|
||||||
startPlaying()
|
startPlaying()
|
||||||
|
@ -107,17 +101,19 @@ class VideoViewHolder constructor(itemView: View) :
|
||||||
views.videoView.isVisible = true
|
views.videoView.isVisible = true
|
||||||
|
|
||||||
views.videoView.setOnPreparedListener {
|
views.videoView.setOnPreparedListener {
|
||||||
progressDisposable?.dispose()
|
stopTimer()
|
||||||
progressDisposable = Observable.interval(100, TimeUnit.MILLISECONDS)
|
countUpTimer = CountUpTimer(100).also {
|
||||||
.timeInterval()
|
it.tickListener = object : CountUpTimer.TickListener {
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
override fun onTick(milliseconds: Long) {
|
||||||
.subscribe {
|
|
||||||
val duration = views.videoView.duration
|
val duration = views.videoView.duration
|
||||||
val progress = views.videoView.currentPosition
|
val progress = views.videoView.currentPosition
|
||||||
val isPlaying = views.videoView.isPlaying
|
val isPlaying = views.videoView.isPlaying
|
||||||
// Log.v("FOO", "isPlaying $isPlaying $progress/$duration")
|
// Log.v("FOO", "isPlaying $isPlaying $progress/$duration")
|
||||||
eventListener?.get()?.onEvent(AttachmentEvents.VideoEvent(isPlaying, progress, duration))
|
eventListener?.get()?.onEvent(AttachmentEvents.VideoEvent(isPlaying, progress, duration))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
it.resume()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
views.videoView.setVideoPath(mVideoPath)
|
views.videoView.setVideoPath(mVideoPath)
|
||||||
|
@ -134,6 +130,11 @@ class VideoViewHolder constructor(itemView: View) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun stopTimer() {
|
||||||
|
countUpTimer?.stop()
|
||||||
|
countUpTimer = null
|
||||||
|
}
|
||||||
|
|
||||||
override fun handleCommand(commands: AttachmentCommands) {
|
override fun handleCommand(commands: AttachmentCommands) {
|
||||||
if (!isSelected) return
|
if (!isSelected) return
|
||||||
when (commands) {
|
when (commands) {
|
||||||
|
|
10
build.gradle
10
build.gradle
|
@ -153,13 +153,3 @@ project(":diff-match-patch") {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
//
|
|
||||||
//project(":matrix-sdk-android-rx") {
|
|
||||||
// sonarqube {
|
|
||||||
// properties {
|
|
||||||
// property "sonar.sources", project(":matrix-sdk-android-rx").android.sourceSets.main.java.srcDirs
|
|
||||||
// // exclude source code from analyses separated by a colon (:)
|
|
||||||
// // property "sonar.exclusions", "**/*.*"
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
1
changelog.d/4669.bugfix
Normal file
1
changelog.d/4669.bugfix
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Fix sync timeout after returning from background
|
1
changelog.d/4914.wip
Normal file
1
changelog.d/4914.wip
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Disabling onboarding automatic carousel transitions on user interaction
|
1
changelog.d/4918.wip
Normal file
1
changelog.d/4918.wip
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Locking phones to portrait during the FTUE onboarding
|
1
changelog.d/4927.wip
Normal file
1
changelog.d/4927.wip
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Adds a messaging use case screen to the FTUE onboarding
|
1
changelog.d/4942.misc
Normal file
1
changelog.d/4942.misc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Remove unused module matrix-sdk-android-rx and do some cleanup
|
1
changelog.d/4948.bugfix
Normal file
1
changelog.d/4948.bugfix
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Prevent Alerts to be displayed in the automatically displayed analytics opt-in screen
|
|
@ -42,7 +42,6 @@ ext.libs = [
|
||||||
jetbrains : [
|
jetbrains : [
|
||||||
'coroutinesCore' : "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutines",
|
'coroutinesCore' : "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutines",
|
||||||
'coroutinesAndroid' : "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinCoroutines",
|
'coroutinesAndroid' : "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinCoroutines",
|
||||||
'coroutinesRx2' : "org.jetbrains.kotlinx:kotlinx-coroutines-rx2:$kotlinCoroutines",
|
|
||||||
'coroutinesTest' : "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinCoroutines"
|
'coroutinesTest' : "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinCoroutines"
|
||||||
],
|
],
|
||||||
androidx : [
|
androidx : [
|
||||||
|
@ -87,8 +86,7 @@ ext.libs = [
|
||||||
'retrofitMoshi' : "com.squareup.retrofit2:converter-moshi:$retrofit"
|
'retrofitMoshi' : "com.squareup.retrofit2:converter-moshi:$retrofit"
|
||||||
],
|
],
|
||||||
rx : [
|
rx : [
|
||||||
'rxKotlin' : "io.reactivex.rxjava2:rxkotlin:2.4.0",
|
'rxKotlin' : "io.reactivex.rxjava2:rxkotlin:2.4.0"
|
||||||
'rxAndroid' : "io.reactivex.rxjava2:rxandroid:2.1.1"
|
|
||||||
],
|
],
|
||||||
arrow : [
|
arrow : [
|
||||||
'core' : "io.arrow-kt:arrow-core:$arrow",
|
'core' : "io.arrow-kt:arrow-core:$arrow",
|
||||||
|
|
1
library/core-utils/.gitignore
vendored
Normal file
1
library/core-utils/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/build
|
55
library/core-utils/build.gradle
Normal file
55
library/core-utils/build.gradle
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id 'com.android.library'
|
||||||
|
id 'kotlin-android'
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdk versions.compileSdk
|
||||||
|
defaultConfig {
|
||||||
|
minSdk versions.minSdk
|
||||||
|
targetSdk versions.targetSdk
|
||||||
|
|
||||||
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
consumerProguardFiles "consumer-rules.pro"
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility versions.sourceCompat
|
||||||
|
targetCompatibility versions.targetCompat
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = "11"
|
||||||
|
freeCompilerArgs += [
|
||||||
|
"-Xopt-in=kotlin.RequiresOptIn"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation libs.androidx.appCompat
|
||||||
|
implementation libs.jetbrains.coroutinesAndroid
|
||||||
|
}
|
2
library/core-utils/src/main/AndroidManifest.xml
Normal file
2
library/core-utils/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest package="im.vector.lib.core.utils" />
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package im.vector.app.core.flow
|
package im.vector.lib.core.utils.flow
|
||||||
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
@ -85,10 +85,12 @@ fun <T> Flow<T>.throttleFirst(windowDuration: Long): Flow<T> = flow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ExperimentalCoroutinesApi
|
||||||
fun tickerFlow(scope: CoroutineScope, delayMillis: Long, initialDelayMillis: Long = delayMillis): Flow<Unit> {
|
fun tickerFlow(scope: CoroutineScope, delayMillis: Long, initialDelayMillis: Long = delayMillis): Flow<Unit> {
|
||||||
return scope.fixedPeriodTicker(delayMillis, initialDelayMillis).consumeAsFlow()
|
return scope.fixedPeriodTicker(delayMillis, initialDelayMillis).consumeAsFlow()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ExperimentalCoroutinesApi
|
||||||
private fun CoroutineScope.fixedPeriodTicker(delayMillis: Long, initialDelayMillis: Long = delayMillis): ReceiveChannel<Unit> {
|
private fun CoroutineScope.fixedPeriodTicker(delayMillis: Long, initialDelayMillis: Long = delayMillis): ReceiveChannel<Unit> {
|
||||||
require(delayMillis >= 0) { "Expected non-negative delay, but has $delayMillis ms" }
|
require(delayMillis >= 0) { "Expected non-negative delay, but has $delayMillis ms" }
|
||||||
require(initialDelayMillis >= 0) { "Expected non-negative initial delay, but has $initialDelayMillis ms" }
|
require(initialDelayMillis >= 0) { "Expected non-negative initial delay, but has $initialDelayMillis ms" }
|
|
@ -14,9 +14,9 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package im.vector.app.core.utils
|
package im.vector.lib.core.utils.timer
|
||||||
|
|
||||||
import im.vector.app.core.flow.tickerFlow
|
import im.vector.lib.core.utils.flow.tickerFlow
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.cancel
|
import kotlinx.coroutines.cancel
|
||||||
|
@ -27,6 +27,7 @@ import kotlinx.coroutines.flow.onEach
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
import java.util.concurrent.atomic.AtomicLong
|
import java.util.concurrent.atomic.AtomicLong
|
||||||
|
|
||||||
|
@OptIn(kotlinx.coroutines.ExperimentalCoroutinesApi::class)
|
||||||
class CountUpTimer(private val intervalInMs: Long = 1_000) {
|
class CountUpTimer(private val intervalInMs: Long = 1_000) {
|
||||||
|
|
||||||
private val coroutineScope = CoroutineScope(Dispatchers.Main)
|
private val coroutineScope = CoroutineScope(Dispatchers.Main)
|
1
matrix-sdk-android-rx/.gitignore
vendored
1
matrix-sdk-android-rx/.gitignore
vendored
|
@ -1 +0,0 @@
|
||||||
/build
|
|
|
@ -1,47 +0,0 @@
|
||||||
apply plugin: 'com.android.library'
|
|
||||||
apply plugin: 'kotlin-android'
|
|
||||||
apply plugin: 'kotlin-kapt'
|
|
||||||
|
|
||||||
android {
|
|
||||||
compileSdk versions.compileSdk
|
|
||||||
|
|
||||||
defaultConfig {
|
|
||||||
minSdk versions.minSdk
|
|
||||||
targetSdk versions.targetSdk
|
|
||||||
|
|
||||||
// Multidex is useful for tests
|
|
||||||
multiDexEnabled true
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
||||||
}
|
|
||||||
|
|
||||||
buildTypes {
|
|
||||||
release {
|
|
||||||
minifyEnabled false
|
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
compileOptions {
|
|
||||||
sourceCompatibility versions.sourceCompat
|
|
||||||
targetCompatibility versions.targetCompat
|
|
||||||
}
|
|
||||||
|
|
||||||
kotlinOptions {
|
|
||||||
jvmTarget = "11"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
|
|
||||||
implementation project(":matrix-sdk-android")
|
|
||||||
implementation libs.androidx.appCompat
|
|
||||||
implementation libs.rx.rxKotlin
|
|
||||||
implementation libs.rx.rxAndroid
|
|
||||||
implementation libs.jetbrains.coroutinesRx2
|
|
||||||
|
|
||||||
// Paging
|
|
||||||
implementation libs.androidx.pagingRuntimeKtx
|
|
||||||
|
|
||||||
// Logging
|
|
||||||
implementation libs.jakewharton.timber
|
|
||||||
}
|
|
21
matrix-sdk-android-rx/proguard-rules.pro
vendored
21
matrix-sdk-android-rx/proguard-rules.pro
vendored
|
@ -1,21 +0,0 @@
|
||||||
# Add project specific ProGuard rules here.
|
|
||||||
# You can control the set of applied configuration files using the
|
|
||||||
# proguardFiles setting in build.gradle.
|
|
||||||
#
|
|
||||||
# For more details, see
|
|
||||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
|
||||||
|
|
||||||
# If your project uses WebView with JS, uncomment the following
|
|
||||||
# and specify the fully qualified class name to the JavaScript interface
|
|
||||||
# class:
|
|
||||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
|
||||||
# public *;
|
|
||||||
#}
|
|
||||||
|
|
||||||
# Uncomment this to preserve the line number information for
|
|
||||||
# debugging stack traces.
|
|
||||||
#-keepattributes SourceFile,LineNumberTable
|
|
||||||
|
|
||||||
# If you keep the line number information, uncomment this to
|
|
||||||
# hide the original source file name.
|
|
||||||
#-renamesourcefileattribute SourceFile
|
|
|
@ -1 +0,0 @@
|
||||||
<manifest package="org.matrix.android.sdk.rx" />
|
|
|
@ -1,71 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.matrix.android.sdk.rx
|
|
||||||
|
|
||||||
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>(
|
|
||||||
private val liveData: LiveData<T>,
|
|
||||||
private val valueIfNull: T? = null
|
|
||||||
) : Observable<T>() {
|
|
||||||
|
|
||||||
override fun subscribeActual(observer: io.reactivex.Observer<in T>) {
|
|
||||||
val relay = RemoveObserverInMainThread(observer)
|
|
||||||
observer.onSubscribe(relay)
|
|
||||||
liveData.observeForever(relay)
|
|
||||||
}
|
|
||||||
|
|
||||||
private inner class RemoveObserverInMainThread(private val observer: io.reactivex.Observer<in T>) :
|
|
||||||
MainThreadDisposable(), Observer<T> {
|
|
||||||
|
|
||||||
override fun onChanged(t: T?) {
|
|
||||||
if (!isDisposed) {
|
|
||||||
if (t == null) {
|
|
||||||
if (valueIfNull != null) {
|
|
||||||
observer.onNext(valueIfNull)
|
|
||||||
} else {
|
|
||||||
observer.onError(NullPointerException(
|
|
||||||
"convert liveData value t to RxJava onNext(t), t cannot be null"))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
observer.onNext(t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDispose() {
|
|
||||||
liveData.removeObserver(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> LiveData<T>.asObservable(): Observable<T> {
|
|
||||||
return LiveDataObservable(this).observeOn(Schedulers.computation())
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun <T> Observable<T>.startWithCallable(supplier: () -> T): Observable<T> {
|
|
||||||
val startObservable = Observable
|
|
||||||
.fromCallable(supplier)
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
return startWith(startObservable)
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.matrix.android.sdk.rx
|
|
||||||
|
|
||||||
import io.reactivex.Observable
|
|
||||||
import org.matrix.android.sdk.api.util.Optional
|
|
||||||
|
|
||||||
fun <T : Any> Observable<Optional<T>>.unwrap(): Observable<T> {
|
|
||||||
return filter { it.hasValue() }.map { it.get() }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T : Any, U : Any> Observable<Optional<T>>.mapOptional(fn: (T) -> U?): Observable<Optional<U>> {
|
|
||||||
return map {
|
|
||||||
it.map(fn)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,158 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.matrix.android.sdk.rx
|
|
||||||
|
|
||||||
import android.net.Uri
|
|
||||||
import io.reactivex.Completable
|
|
||||||
import io.reactivex.Observable
|
|
||||||
import io.reactivex.Single
|
|
||||||
import kotlinx.coroutines.rx2.rxCompletable
|
|
||||||
import kotlinx.coroutines.rx2.rxSingle
|
|
||||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
|
||||||
import org.matrix.android.sdk.api.session.content.ContentAttachmentData
|
|
||||||
import org.matrix.android.sdk.api.session.events.model.Event
|
|
||||||
import org.matrix.android.sdk.api.session.identity.ThreePid
|
|
||||||
import org.matrix.android.sdk.api.session.room.Room
|
|
||||||
import org.matrix.android.sdk.api.session.room.members.RoomMemberQueryParams
|
|
||||||
import org.matrix.android.sdk.api.session.room.model.EventAnnotationsSummary
|
|
||||||
import org.matrix.android.sdk.api.session.room.model.GuestAccess
|
|
||||||
import org.matrix.android.sdk.api.session.room.model.ReadReceipt
|
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
|
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomJoinRules
|
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
|
||||||
import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState
|
|
||||||
import org.matrix.android.sdk.api.session.room.send.UserDraft
|
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
|
||||||
import org.matrix.android.sdk.api.util.Optional
|
|
||||||
import org.matrix.android.sdk.api.util.toOptional
|
|
||||||
|
|
||||||
class RxRoom(private val room: Room) {
|
|
||||||
|
|
||||||
fun liveRoomSummary(): Observable<Optional<RoomSummary>> {
|
|
||||||
return room.getRoomSummaryLive()
|
|
||||||
.asObservable()
|
|
||||||
.startWithCallable { room.roomSummary().toOptional() }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun liveRoomMembers(queryParams: RoomMemberQueryParams): Observable<List<RoomMemberSummary>> {
|
|
||||||
return room.getRoomMembersLive(queryParams).asObservable()
|
|
||||||
.startWithCallable {
|
|
||||||
room.getRoomMembers(queryParams)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun liveAnnotationSummary(eventId: String): Observable<Optional<EventAnnotationsSummary>> {
|
|
||||||
return room.getEventAnnotationsSummaryLive(eventId).asObservable()
|
|
||||||
.startWithCallable {
|
|
||||||
room.getEventAnnotationsSummary(eventId).toOptional()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun liveTimelineEvent(eventId: String): Observable<Optional<TimelineEvent>> {
|
|
||||||
return room.getTimeLineEventLive(eventId).asObservable()
|
|
||||||
.startWithCallable {
|
|
||||||
room.getTimeLineEvent(eventId).toOptional()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun liveStateEvent(eventType: String, stateKey: QueryStringValue): Observable<Optional<Event>> {
|
|
||||||
return room.getStateEventLive(eventType, stateKey).asObservable()
|
|
||||||
.startWithCallable {
|
|
||||||
room.getStateEvent(eventType, stateKey).toOptional()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun liveStateEvents(eventTypes: Set<String>): Observable<List<Event>> {
|
|
||||||
return room.getStateEventsLive(eventTypes).asObservable()
|
|
||||||
.startWithCallable {
|
|
||||||
room.getStateEvents(eventTypes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun liveReadMarker(): Observable<Optional<String>> {
|
|
||||||
return room.getReadMarkerLive().asObservable()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun liveReadReceipt(): Observable<Optional<String>> {
|
|
||||||
return room.getMyReadReceiptLive().asObservable()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun loadRoomMembersIfNeeded(): Single<Unit> = rxSingle {
|
|
||||||
room.loadRoomMembersIfNeeded()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun joinRoom(reason: String? = null,
|
|
||||||
viaServers: List<String> = emptyList()): Single<Unit> = rxSingle {
|
|
||||||
room.join(reason, viaServers)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun liveEventReadReceipts(eventId: String): Observable<List<ReadReceipt>> {
|
|
||||||
return room.getEventReadReceiptsLive(eventId).asObservable()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun liveDraft(): Observable<Optional<UserDraft>> {
|
|
||||||
return room.getDraftLive().asObservable()
|
|
||||||
.startWithCallable {
|
|
||||||
room.getDraft().toOptional()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun liveNotificationState(): Observable<RoomNotificationState> {
|
|
||||||
return room.getLiveRoomNotificationState().asObservable()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun invite(userId: String, reason: String? = null): Completable = rxCompletable {
|
|
||||||
room.invite(userId, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun invite3pid(threePid: ThreePid): Completable = rxCompletable {
|
|
||||||
room.invite3pid(threePid)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateTopic(topic: String): Completable = rxCompletable {
|
|
||||||
room.updateTopic(topic)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateName(name: String): Completable = rxCompletable {
|
|
||||||
room.updateName(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateHistoryReadability(readability: RoomHistoryVisibility): Completable = rxCompletable {
|
|
||||||
room.updateHistoryReadability(readability)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateJoinRule(joinRules: RoomJoinRules?, guestAccess: GuestAccess?): Completable = rxCompletable {
|
|
||||||
room.updateJoinRule(joinRules, guestAccess)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateAvatar(avatarUri: Uri, fileName: String): Completable = rxCompletable {
|
|
||||||
room.updateAvatar(avatarUri, fileName)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteAvatar(): Completable = rxCompletable {
|
|
||||||
room.deleteAvatar()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun sendMedia(attachment: ContentAttachmentData, compressBeforeSending: Boolean, roomIds: Set<String>): Completable = rxCompletable {
|
|
||||||
room.sendMedia(attachment, compressBeforeSending, roomIds)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Room.rx(): RxRoom {
|
|
||||||
return RxRoom(this)
|
|
||||||
}
|
|
|
@ -1,251 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.matrix.android.sdk.rx
|
|
||||||
|
|
||||||
import androidx.paging.PagedList
|
|
||||||
import io.reactivex.Observable
|
|
||||||
import io.reactivex.Single
|
|
||||||
import io.reactivex.functions.Function3
|
|
||||||
import kotlinx.coroutines.rx2.rxSingle
|
|
||||||
import org.matrix.android.sdk.api.extensions.orFalse
|
|
||||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
|
||||||
import org.matrix.android.sdk.api.session.Session
|
|
||||||
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
|
|
||||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME
|
|
||||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME
|
|
||||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo
|
|
||||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME
|
|
||||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME
|
|
||||||
import org.matrix.android.sdk.api.session.group.GroupSummaryQueryParams
|
|
||||||
import org.matrix.android.sdk.api.session.group.model.GroupSummary
|
|
||||||
import org.matrix.android.sdk.api.session.identity.FoundThreePid
|
|
||||||
import org.matrix.android.sdk.api.session.identity.ThreePid
|
|
||||||
import org.matrix.android.sdk.api.session.pushers.Pusher
|
|
||||||
import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
|
|
||||||
import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataEvent
|
|
||||||
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
|
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
|
||||||
import org.matrix.android.sdk.api.session.space.SpaceSummaryQueryParams
|
|
||||||
import org.matrix.android.sdk.api.session.sync.SyncState
|
|
||||||
import org.matrix.android.sdk.api.session.user.model.User
|
|
||||||
import org.matrix.android.sdk.api.session.widgets.model.Widget
|
|
||||||
import org.matrix.android.sdk.api.util.JsonDict
|
|
||||||
import org.matrix.android.sdk.api.util.Optional
|
|
||||||
import org.matrix.android.sdk.api.util.toOptional
|
|
||||||
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
|
|
||||||
import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
|
|
||||||
import org.matrix.android.sdk.internal.crypto.store.PrivateKeysInfo
|
|
||||||
import org.matrix.android.sdk.internal.session.room.alias.RoomAliasDescription
|
|
||||||
|
|
||||||
class RxSession(private val session: Session) {
|
|
||||||
|
|
||||||
fun liveRoomSummaries(queryParams: RoomSummaryQueryParams): Observable<List<RoomSummary>> {
|
|
||||||
return session.getRoomSummariesLive(queryParams).asObservable()
|
|
||||||
.startWithCallable {
|
|
||||||
session.getRoomSummaries(queryParams)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun liveGroupSummaries(queryParams: GroupSummaryQueryParams): Observable<List<GroupSummary>> {
|
|
||||||
return session.getGroupSummariesLive(queryParams).asObservable()
|
|
||||||
.startWithCallable {
|
|
||||||
session.getGroupSummaries(queryParams)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun liveSpaceSummaries(queryParams: SpaceSummaryQueryParams): Observable<List<RoomSummary>> {
|
|
||||||
return session.spaceService().getSpaceSummariesLive(queryParams).asObservable()
|
|
||||||
.startWithCallable {
|
|
||||||
session.spaceService().getSpaceSummaries(queryParams)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun liveBreadcrumbs(queryParams: RoomSummaryQueryParams): Observable<List<RoomSummary>> {
|
|
||||||
return session.getBreadcrumbsLive(queryParams).asObservable()
|
|
||||||
.startWithCallable {
|
|
||||||
session.getBreadcrumbs(queryParams)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun liveMyDevicesInfo(): Observable<List<DeviceInfo>> {
|
|
||||||
return session.cryptoService().getLiveMyDevicesInfo().asObservable()
|
|
||||||
.startWithCallable {
|
|
||||||
session.cryptoService().getMyDevicesInfo()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun liveSyncState(): Observable<SyncState> {
|
|
||||||
return session.getSyncStateLive().asObservable()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun livePushers(): Observable<List<Pusher>> {
|
|
||||||
return session.getPushersLive().asObservable()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun liveUser(userId: String): Observable<Optional<User>> {
|
|
||||||
return session.getUserLive(userId).asObservable()
|
|
||||||
.startWithCallable {
|
|
||||||
session.getUser(userId).toOptional()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun liveRoomMember(userId: String, roomId: String): Observable<Optional<RoomMemberSummary>> {
|
|
||||||
return session.getRoomMemberLive(userId, roomId).asObservable()
|
|
||||||
.startWithCallable {
|
|
||||||
session.getRoomMember(userId, roomId).toOptional()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun liveUsers(): Observable<List<User>> {
|
|
||||||
return session.getUsersLive().asObservable()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun liveIgnoredUsers(): Observable<List<User>> {
|
|
||||||
return session.getIgnoredUsersLive().asObservable()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun livePagedUsers(filter: String? = null, excludedUserIds: Set<String>? = null): Observable<PagedList<User>> {
|
|
||||||
return session.getPagedUsersLive(filter, excludedUserIds).asObservable()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun liveThreePIds(refreshData: Boolean): Observable<List<ThreePid>> {
|
|
||||||
return session.getThreePidsLive(refreshData).asObservable()
|
|
||||||
.startWithCallable { session.getThreePids() }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun livePendingThreePIds(): Observable<List<ThreePid>> {
|
|
||||||
return session.getPendingThreePidsLive().asObservable()
|
|
||||||
.startWithCallable { session.getPendingThreePids() }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun createRoom(roomParams: CreateRoomParams): Single<String> = rxSingle {
|
|
||||||
session.createRoom(roomParams)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun searchUsersDirectory(search: String,
|
|
||||||
limit: Int,
|
|
||||||
excludedUserIds: Set<String>): Single<List<User>> = rxSingle {
|
|
||||||
session.searchUsersDirectory(search, limit, excludedUserIds)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun joinRoom(roomIdOrAlias: String,
|
|
||||||
reason: String? = null,
|
|
||||||
viaServers: List<String> = emptyList()): Single<Unit> = rxSingle {
|
|
||||||
session.joinRoom(roomIdOrAlias, reason, viaServers)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getRoomIdByAlias(roomAlias: String,
|
|
||||||
searchOnServer: Boolean): Single<Optional<RoomAliasDescription>> = rxSingle {
|
|
||||||
session.getRoomIdByAlias(roomAlias, searchOnServer)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getProfileInfo(userId: String): Single<JsonDict> = rxSingle {
|
|
||||||
session.getProfile(userId)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun liveUserCryptoDevices(userId: String): Observable<List<CryptoDeviceInfo>> {
|
|
||||||
return session.cryptoService().getLiveCryptoDeviceInfo(userId).asObservable().startWithCallable {
|
|
||||||
session.cryptoService().getCryptoDeviceInfo(userId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun liveCrossSigningInfo(userId: String): Observable<Optional<MXCrossSigningInfo>> {
|
|
||||||
return session.cryptoService().crossSigningService().getLiveCrossSigningKeys(userId).asObservable()
|
|
||||||
.startWithCallable {
|
|
||||||
session.cryptoService().crossSigningService().getUserCrossSigningKeys(userId).toOptional()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun liveCrossSigningPrivateKeys(): Observable<Optional<PrivateKeysInfo>> {
|
|
||||||
return session.cryptoService().crossSigningService().getLiveCrossSigningPrivateKeys().asObservable()
|
|
||||||
.startWithCallable {
|
|
||||||
session.cryptoService().crossSigningService().getCrossSigningPrivateKeys().toOptional()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun liveUserAccountData(types: Set<String>): Observable<List<UserAccountDataEvent>> {
|
|
||||||
return session.accountDataService().getLiveUserAccountDataEvents(types).asObservable()
|
|
||||||
.startWithCallable {
|
|
||||||
session.accountDataService().getUserAccountDataEvents(types)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun liveRoomAccountData(types: Set<String>): Observable<List<RoomAccountDataEvent>> {
|
|
||||||
return session.accountDataService().getLiveRoomAccountDataEvents(types).asObservable()
|
|
||||||
.startWithCallable {
|
|
||||||
session.accountDataService().getRoomAccountDataEvents(types)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun liveRoomWidgets(
|
|
||||||
roomId: String,
|
|
||||||
widgetId: QueryStringValue,
|
|
||||||
widgetTypes: Set<String>? = null,
|
|
||||||
excludedTypes: Set<String>? = null
|
|
||||||
): Observable<List<Widget>> {
|
|
||||||
return session.widgetService().getRoomWidgetsLive(roomId, widgetId, widgetTypes, excludedTypes).asObservable()
|
|
||||||
.startWithCallable {
|
|
||||||
session.widgetService().getRoomWidgets(roomId, widgetId, widgetTypes, excludedTypes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun liveRoomChangeMembershipState(): Observable<Map<String, ChangeMembershipState>> {
|
|
||||||
return session.getChangeMembershipsLive().asObservable()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun liveSecretSynchronisationInfo(): Observable<SecretsSynchronisationInfo> {
|
|
||||||
return Observable.combineLatest<List<UserAccountDataEvent>, Optional<MXCrossSigningInfo>, Optional<PrivateKeysInfo>, SecretsSynchronisationInfo>(
|
|
||||||
liveUserAccountData(setOf(MASTER_KEY_SSSS_NAME, USER_SIGNING_KEY_SSSS_NAME, SELF_SIGNING_KEY_SSSS_NAME, KEYBACKUP_SECRET_SSSS_NAME)),
|
|
||||||
liveCrossSigningInfo(session.myUserId),
|
|
||||||
liveCrossSigningPrivateKeys(),
|
|
||||||
Function3 { _, crossSigningInfo, pInfo ->
|
|
||||||
// first check if 4S is already setup
|
|
||||||
val is4SSetup = session.sharedSecretStorageService.isRecoverySetup()
|
|
||||||
val isCrossSigningEnabled = crossSigningInfo.getOrNull() != null
|
|
||||||
val isCrossSigningTrusted = crossSigningInfo.getOrNull()?.isTrusted() == true
|
|
||||||
val allPrivateKeysKnown = pInfo.getOrNull()?.allKnown().orFalse()
|
|
||||||
|
|
||||||
val keysBackupService = session.cryptoService().keysBackupService()
|
|
||||||
val currentBackupVersion = keysBackupService.currentBackupVersion
|
|
||||||
val megolmBackupAvailable = currentBackupVersion != null
|
|
||||||
val savedBackupKey = keysBackupService.getKeyBackupRecoveryKeyInfo()
|
|
||||||
|
|
||||||
val megolmKeyKnown = savedBackupKey?.version == currentBackupVersion
|
|
||||||
SecretsSynchronisationInfo(
|
|
||||||
isBackupSetup = is4SSetup,
|
|
||||||
isCrossSigningEnabled = isCrossSigningEnabled,
|
|
||||||
isCrossSigningTrusted = isCrossSigningTrusted,
|
|
||||||
allPrivateKeysKnown = allPrivateKeysKnown,
|
|
||||||
megolmBackupAvailable = megolmBackupAvailable,
|
|
||||||
megolmSecretKnown = megolmKeyKnown,
|
|
||||||
isMegolmKeyIn4S = session.sharedSecretStorageService.isMegolmKeyInBackup()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.distinctUntilChanged()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun lookupThreePid(threePid: ThreePid): Single<Optional<FoundThreePid>> = rxSingle {
|
|
||||||
session.identityService().lookUp(listOf(threePid)).firstOrNull().toOptional()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Session.rx(): RxSession {
|
|
||||||
return RxSession(this)
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.matrix.android.sdk.rx
|
|
||||||
|
|
||||||
data class SecretsSynchronisationInfo(
|
|
||||||
val isBackupSetup: Boolean,
|
|
||||||
val isCrossSigningEnabled: Boolean,
|
|
||||||
val isCrossSigningTrusted: Boolean,
|
|
||||||
val allPrivateKeysKnown: Boolean,
|
|
||||||
val megolmBackupAvailable: Boolean,
|
|
||||||
val megolmSecretKnown: Boolean,
|
|
||||||
val isMegolmKeyIn4S: Boolean
|
|
||||||
)
|
|
|
@ -116,6 +116,11 @@ dependencies {
|
||||||
implementation libs.squareup.retrofit
|
implementation libs.squareup.retrofit
|
||||||
implementation libs.squareup.retrofitMoshi
|
implementation libs.squareup.retrofitMoshi
|
||||||
|
|
||||||
|
// When version of okhttp is updated (current is 4.9.3), consider removing the workaround
|
||||||
|
// to force usage of Protocol.HTTP_1_1. Check the status of:
|
||||||
|
// - https://github.com/square/okhttp/issues/3278
|
||||||
|
// - https://github.com/square/okhttp/issues/4455
|
||||||
|
// - https://github.com/square/okhttp/issues/3146
|
||||||
implementation(platform("com.squareup.okhttp3:okhttp-bom:4.9.3"))
|
implementation(platform("com.squareup.okhttp3:okhttp-bom:4.9.3"))
|
||||||
implementation 'com.squareup.okhttp3:okhttp'
|
implementation 'com.squareup.okhttp3:okhttp'
|
||||||
implementation 'com.squareup.okhttp3:logging-interceptor'
|
implementation 'com.squareup.okhttp3:logging-interceptor'
|
||||||
|
|
|
@ -22,6 +22,7 @@ import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
import okhttp3.ConnectionSpec
|
import okhttp3.ConnectionSpec
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.Protocol
|
||||||
import okhttp3.logging.HttpLoggingInterceptor
|
import okhttp3.logging.HttpLoggingInterceptor
|
||||||
import org.matrix.android.sdk.BuildConfig
|
import org.matrix.android.sdk.BuildConfig
|
||||||
import org.matrix.android.sdk.api.MatrixConfiguration
|
import org.matrix.android.sdk.api.MatrixConfiguration
|
||||||
|
@ -71,6 +72,8 @@ internal object NetworkModule {
|
||||||
val spec = ConnectionSpec.Builder(matrixConfiguration.connectionSpec).build()
|
val spec = ConnectionSpec.Builder(matrixConfiguration.connectionSpec).build()
|
||||||
|
|
||||||
return OkHttpClient.Builder()
|
return OkHttpClient.Builder()
|
||||||
|
// workaround for #4669
|
||||||
|
.protocols(listOf(Protocol.HTTP_1_1))
|
||||||
.connectTimeout(30, TimeUnit.SECONDS)
|
.connectTimeout(30, TimeUnit.SECONDS)
|
||||||
.readTimeout(60, TimeUnit.SECONDS)
|
.readTimeout(60, TimeUnit.SECONDS)
|
||||||
.writeTimeout(60, TimeUnit.SECONDS)
|
.writeTimeout(60, TimeUnit.SECONDS)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
include ':vector'
|
include ':vector'
|
||||||
include ':matrix-sdk-android'
|
include ':matrix-sdk-android'
|
||||||
include ':matrix-sdk-android-rx'
|
|
||||||
include ':diff-match-patch'
|
include ':diff-match-patch'
|
||||||
include ':attachment-viewer'
|
include ':attachment-viewer'
|
||||||
include ':multipicker'
|
include ':multipicker'
|
||||||
|
include ':library:core-utils'
|
||||||
include ':library:ui-styles'
|
include ':library:ui-styles'
|
||||||
include ':matrix-sdk-android-flow'
|
include ':matrix-sdk-android-flow'
|
||||||
|
|
|
@ -15,13 +15,18 @@
|
||||||
name = "Bugfixes 🐛"
|
name = "Bugfixes 🐛"
|
||||||
showcontent = true
|
showcontent = true
|
||||||
|
|
||||||
|
[[tool.towncrier.type]]
|
||||||
|
directory = "wip"
|
||||||
|
name = "In development 🚧"
|
||||||
|
showcontent = true
|
||||||
|
|
||||||
[[tool.towncrier.type]]
|
[[tool.towncrier.type]]
|
||||||
directory = "doc"
|
directory = "doc"
|
||||||
name = "Improved Documentation 📚"
|
name = "Improved Documentation 📚"
|
||||||
showcontent = true
|
showcontent = true
|
||||||
|
|
||||||
[[tool.towncrier.type]]
|
[[tool.towncrier.type]]
|
||||||
directory = "removal"
|
directory = "sdk"
|
||||||
name = "SDK API changes ⚠️"
|
name = "SDK API changes ⚠️"
|
||||||
showcontent = true
|
showcontent = true
|
||||||
|
|
||||||
|
|
|
@ -333,6 +333,7 @@ dependencies {
|
||||||
implementation project(":multipicker")
|
implementation project(":multipicker")
|
||||||
implementation project(":attachment-viewer")
|
implementation project(":attachment-viewer")
|
||||||
implementation project(":library:ui-styles")
|
implementation project(":library:ui-styles")
|
||||||
|
implementation project(":library:core-utils")
|
||||||
implementation 'androidx.multidex:multidex:2.0.1'
|
implementation 'androidx.multidex:multidex:2.0.1'
|
||||||
|
|
||||||
implementation libs.jetbrains.coroutinesCore
|
implementation libs.jetbrains.coroutinesCore
|
||||||
|
|
|
@ -61,7 +61,7 @@ class AppStateHandler @Inject constructor(
|
||||||
private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
|
private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
|
||||||
private val selectedSpaceDataSource = BehaviorDataSource<Option<RoomGroupingMethod>>(Option.empty())
|
private val selectedSpaceDataSource = BehaviorDataSource<Option<RoomGroupingMethod>>(Option.empty())
|
||||||
|
|
||||||
val selectedRoomGroupingObservable = selectedSpaceDataSource.stream()
|
val selectedRoomGroupingFlow = selectedSpaceDataSource.stream()
|
||||||
|
|
||||||
fun getCurrentRoomGroupingMethod(): RoomGroupingMethod? {
|
fun getCurrentRoomGroupingMethod(): RoomGroupingMethod? {
|
||||||
// XXX we should somehow make it live :/ just a work around
|
// XXX we should somehow make it live :/ just a work around
|
||||||
|
|
|
@ -31,7 +31,7 @@ import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class ActiveSessionHolder @Inject constructor(private val sessionObservableStore: ActiveSessionDataSource,
|
class ActiveSessionHolder @Inject constructor(private val activeSessionDataSource: ActiveSessionDataSource,
|
||||||
private val keyRequestHandler: KeyRequestHandler,
|
private val keyRequestHandler: KeyRequestHandler,
|
||||||
private val incomingVerificationRequestHandler: IncomingVerificationRequestHandler,
|
private val incomingVerificationRequestHandler: IncomingVerificationRequestHandler,
|
||||||
private val callManager: WebRtcCallManager,
|
private val callManager: WebRtcCallManager,
|
||||||
|
@ -46,7 +46,7 @@ class ActiveSessionHolder @Inject constructor(private val sessionObservableStore
|
||||||
fun setActiveSession(session: Session) {
|
fun setActiveSession(session: Session) {
|
||||||
Timber.w("setActiveSession of ${session.myUserId}")
|
Timber.w("setActiveSession of ${session.myUserId}")
|
||||||
activeSession.set(session)
|
activeSession.set(session)
|
||||||
sessionObservableStore.post(Option.just(session))
|
activeSessionDataSource.post(Option.just(session))
|
||||||
|
|
||||||
keyRequestHandler.start(session)
|
keyRequestHandler.start(session)
|
||||||
incomingVerificationRequestHandler.start(session)
|
incomingVerificationRequestHandler.start(session)
|
||||||
|
@ -66,7 +66,7 @@ class ActiveSessionHolder @Inject constructor(private val sessionObservableStore
|
||||||
}
|
}
|
||||||
|
|
||||||
activeSession.set(null)
|
activeSession.set(null)
|
||||||
sessionObservableStore.post(Option.empty())
|
activeSessionDataSource.post(Option.empty())
|
||||||
|
|
||||||
keyRequestHandler.stop()
|
keyRequestHandler.stop()
|
||||||
incomingVerificationRequestHandler.stop()
|
incomingVerificationRequestHandler.stop()
|
||||||
|
|
|
@ -16,9 +16,9 @@
|
||||||
|
|
||||||
package im.vector.app.features.analytics
|
package im.vector.app.features.analytics
|
||||||
|
|
||||||
import im.vector.app.core.flow.tickerFlow
|
|
||||||
import im.vector.app.core.time.Clock
|
import im.vector.app.core.time.Clock
|
||||||
import im.vector.app.features.analytics.plan.Error
|
import im.vector.app.features.analytics.plan.Error
|
||||||
|
import im.vector.lib.core.utils.flow.tickerFlow
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
|
|
@ -19,9 +19,7 @@ package im.vector.app.features.call.webrtc
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.hardware.camera2.CameraManager
|
import android.hardware.camera2.CameraManager
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
import im.vector.app.core.flow.chunk
|
|
||||||
import im.vector.app.core.services.CallService
|
import im.vector.app.core.services.CallService
|
||||||
import im.vector.app.core.utils.CountUpTimer
|
|
||||||
import im.vector.app.core.utils.PublishDataSource
|
import im.vector.app.core.utils.PublishDataSource
|
||||||
import im.vector.app.core.utils.TextUtils.formatDuration
|
import im.vector.app.core.utils.TextUtils.formatDuration
|
||||||
import im.vector.app.features.call.CameraEventsHandlerAdapter
|
import im.vector.app.features.call.CameraEventsHandlerAdapter
|
||||||
|
@ -37,6 +35,8 @@ import im.vector.app.features.call.utils.awaitSetLocalDescription
|
||||||
import im.vector.app.features.call.utils.awaitSetRemoteDescription
|
import im.vector.app.features.call.utils.awaitSetRemoteDescription
|
||||||
import im.vector.app.features.call.utils.mapToCallCandidate
|
import im.vector.app.features.call.utils.mapToCallCandidate
|
||||||
import im.vector.app.features.session.coroutineScope
|
import im.vector.app.features.session.coroutineScope
|
||||||
|
import im.vector.lib.core.utils.flow.chunk
|
||||||
|
import im.vector.lib.core.utils.timer.CountUpTimer
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Deferred
|
import kotlinx.coroutines.Deferred
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
|
|
@ -26,10 +26,10 @@ import androidx.lifecycle.lifecycleScope
|
||||||
import com.airbnb.mvrx.activityViewModel
|
import com.airbnb.mvrx.activityViewModel
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.extensions.registerStartForActivityResult
|
import im.vector.app.core.extensions.registerStartForActivityResult
|
||||||
import im.vector.app.core.flow.throttleFirst
|
|
||||||
import im.vector.app.core.platform.VectorBaseFragment
|
import im.vector.app.core.platform.VectorBaseFragment
|
||||||
import im.vector.app.core.utils.startImportTextFromFileIntent
|
import im.vector.app.core.utils.startImportTextFromFileIntent
|
||||||
import im.vector.app.databinding.FragmentSsssAccessFromKeyBinding
|
import im.vector.app.databinding.FragmentSsssAccessFromKeyBinding
|
||||||
|
import im.vector.lib.core.utils.flow.throttleFirst
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||||
|
|
|
@ -25,10 +25,10 @@ import androidx.core.text.toSpannable
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.airbnb.mvrx.activityViewModel
|
import com.airbnb.mvrx.activityViewModel
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.flow.throttleFirst
|
|
||||||
import im.vector.app.core.platform.VectorBaseFragment
|
import im.vector.app.core.platform.VectorBaseFragment
|
||||||
import im.vector.app.core.resources.ColorProvider
|
import im.vector.app.core.resources.ColorProvider
|
||||||
import im.vector.app.databinding.FragmentSsssAccessFromPassphraseBinding
|
import im.vector.app.databinding.FragmentSsssAccessFromPassphraseBinding
|
||||||
|
import im.vector.lib.core.utils.flow.throttleFirst
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import reactivecircus.flowbinding.android.widget.editorActionEvents
|
import reactivecircus.flowbinding.android.widget.editorActionEvents
|
||||||
|
|
|
@ -27,9 +27,9 @@ import com.airbnb.mvrx.parentFragmentViewModel
|
||||||
import com.airbnb.mvrx.withState
|
import com.airbnb.mvrx.withState
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.extensions.hideKeyboard
|
import im.vector.app.core.extensions.hideKeyboard
|
||||||
import im.vector.app.core.flow.throttleFirst
|
|
||||||
import im.vector.app.core.platform.VectorBaseFragment
|
import im.vector.app.core.platform.VectorBaseFragment
|
||||||
import im.vector.app.databinding.FragmentBootstrapEnterPassphraseBinding
|
import im.vector.app.databinding.FragmentBootstrapEnterPassphraseBinding
|
||||||
|
import im.vector.lib.core.utils.flow.throttleFirst
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import reactivecircus.flowbinding.android.widget.editorActionEvents
|
import reactivecircus.flowbinding.android.widget.editorActionEvents
|
||||||
|
|
|
@ -25,10 +25,10 @@ import androidx.lifecycle.lifecycleScope
|
||||||
import com.airbnb.mvrx.parentFragmentViewModel
|
import com.airbnb.mvrx.parentFragmentViewModel
|
||||||
import com.airbnb.mvrx.withState
|
import com.airbnb.mvrx.withState
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.flow.throttleFirst
|
|
||||||
import im.vector.app.core.platform.VectorBaseFragment
|
import im.vector.app.core.platform.VectorBaseFragment
|
||||||
import im.vector.app.databinding.FragmentBootstrapEnterPassphraseBinding
|
import im.vector.app.databinding.FragmentBootstrapEnterPassphraseBinding
|
||||||
import im.vector.app.features.settings.VectorLocale
|
import im.vector.app.features.settings.VectorLocale
|
||||||
|
import im.vector.lib.core.utils.flow.throttleFirst
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import reactivecircus.flowbinding.android.widget.editorActionEvents
|
import reactivecircus.flowbinding.android.widget.editorActionEvents
|
||||||
|
|
|
@ -33,12 +33,12 @@ import com.airbnb.mvrx.withState
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.extensions.hideKeyboard
|
import im.vector.app.core.extensions.hideKeyboard
|
||||||
import im.vector.app.core.extensions.registerStartForActivityResult
|
import im.vector.app.core.extensions.registerStartForActivityResult
|
||||||
import im.vector.app.core.flow.throttleFirst
|
|
||||||
import im.vector.app.core.platform.VectorBaseFragment
|
import im.vector.app.core.platform.VectorBaseFragment
|
||||||
import im.vector.app.core.resources.ColorProvider
|
import im.vector.app.core.resources.ColorProvider
|
||||||
import im.vector.app.core.utils.colorizeMatchingText
|
import im.vector.app.core.utils.colorizeMatchingText
|
||||||
import im.vector.app.core.utils.startImportTextFromFileIntent
|
import im.vector.app.core.utils.startImportTextFromFileIntent
|
||||||
import im.vector.app.databinding.FragmentBootstrapMigrateBackupBinding
|
import im.vector.app.databinding.FragmentBootstrapMigrateBackupBinding
|
||||||
|
import im.vector.lib.core.utils.flow.throttleFirst
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||||
|
|
|
@ -27,7 +27,6 @@ import im.vector.app.RoomGroupingMethod
|
||||||
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
||||||
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||||
import im.vector.app.core.extensions.singletonEntryPoint
|
import im.vector.app.core.extensions.singletonEntryPoint
|
||||||
import im.vector.app.core.flow.throttleFirst
|
|
||||||
import im.vector.app.core.platform.VectorViewModel
|
import im.vector.app.core.platform.VectorViewModel
|
||||||
import im.vector.app.features.call.dialpad.DialPadLookup
|
import im.vector.app.features.call.dialpad.DialPadLookup
|
||||||
import im.vector.app.features.call.lookup.CallProtocolsChecker
|
import im.vector.app.features.call.lookup.CallProtocolsChecker
|
||||||
|
@ -37,6 +36,7 @@ import im.vector.app.features.invite.AutoAcceptInvites
|
||||||
import im.vector.app.features.invite.showInvites
|
import im.vector.app.features.invite.showInvites
|
||||||
import im.vector.app.features.settings.VectorDataStore
|
import im.vector.app.features.settings.VectorDataStore
|
||||||
import im.vector.app.features.ui.UiStateRepository
|
import im.vector.app.features.ui.UiStateRepository
|
||||||
|
import im.vector.lib.core.utils.flow.throttleFirst
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.flow.filterIsInstance
|
import kotlinx.coroutines.flow.filterIsInstance
|
||||||
|
@ -197,7 +197,7 @@ class HomeDetailViewModel @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun observeRoomGroupingMethod() {
|
private fun observeRoomGroupingMethod() {
|
||||||
appStateHandler.selectedRoomGroupingObservable
|
appStateHandler.selectedRoomGroupingFlow
|
||||||
.setOnEach {
|
.setOnEach {
|
||||||
copy(
|
copy(
|
||||||
roomGroupingMethod = it.orNull() ?: RoomGroupingMethod.BySpace(null)
|
roomGroupingMethod = it.orNull() ?: RoomGroupingMethod.BySpace(null)
|
||||||
|
@ -206,7 +206,7 @@ class HomeDetailViewModel @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun observeRoomSummaries() {
|
private fun observeRoomSummaries() {
|
||||||
appStateHandler.selectedRoomGroupingObservable.distinctUntilChanged().flatMapLatest {
|
appStateHandler.selectedRoomGroupingFlow.distinctUntilChanged().flatMapLatest {
|
||||||
// we use it as a trigger to all changes in room, but do not really load
|
// we use it as a trigger to all changes in room, but do not really load
|
||||||
// the actual models
|
// the actual models
|
||||||
session.getPagedRoomSummariesLive(
|
session.getPagedRoomSummariesLive(
|
||||||
|
|
|
@ -50,7 +50,7 @@ class PromoteRestrictedViewModel @AssistedInject constructor(
|
||||||
) : VectorViewModel<ActiveSpaceViewState, EmptyAction, EmptyViewEvents>(initialState) {
|
) : VectorViewModel<ActiveSpaceViewState, EmptyAction, EmptyViewEvents>(initialState) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
appStateHandler.selectedRoomGroupingObservable.distinctUntilChanged().execute { state ->
|
appStateHandler.selectedRoomGroupingFlow.distinctUntilChanged().execute { state ->
|
||||||
val groupingMethod = state.invoke()?.orNull()
|
val groupingMethod = state.invoke()?.orNull()
|
||||||
val isSpaceMode = groupingMethod is RoomGroupingMethod.BySpace
|
val isSpaceMode = groupingMethod is RoomGroupingMethod.BySpace
|
||||||
val currentSpace = (groupingMethod as? RoomGroupingMethod.BySpace)?.spaceSummary
|
val currentSpace = (groupingMethod as? RoomGroupingMethod.BySpace)?.spaceSummary
|
||||||
|
|
|
@ -26,12 +26,12 @@ import im.vector.app.AppStateHandler
|
||||||
import im.vector.app.RoomGroupingMethod
|
import im.vector.app.RoomGroupingMethod
|
||||||
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
||||||
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||||
import im.vector.app.core.flow.throttleFirst
|
|
||||||
import im.vector.app.core.platform.EmptyAction
|
import im.vector.app.core.platform.EmptyAction
|
||||||
import im.vector.app.core.platform.EmptyViewEvents
|
import im.vector.app.core.platform.EmptyViewEvents
|
||||||
import im.vector.app.core.platform.VectorViewModel
|
import im.vector.app.core.platform.VectorViewModel
|
||||||
import im.vector.app.features.invite.AutoAcceptInvites
|
import im.vector.app.features.invite.AutoAcceptInvites
|
||||||
import im.vector.app.features.settings.VectorPreferences
|
import im.vector.app.features.settings.VectorPreferences
|
||||||
|
import im.vector.lib.core.utils.flow.throttleFirst
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
|
@ -107,8 +107,8 @@ class UnreadMessagesSharedViewModel @AssistedInject constructor(@Assisted initia
|
||||||
}
|
}
|
||||||
|
|
||||||
combine(
|
combine(
|
||||||
appStateHandler.selectedRoomGroupingObservable.distinctUntilChanged(),
|
appStateHandler.selectedRoomGroupingFlow.distinctUntilChanged(),
|
||||||
appStateHandler.selectedRoomGroupingObservable.flatMapLatest {
|
appStateHandler.selectedRoomGroupingFlow.flatMapLatest {
|
||||||
session.getPagedRoomSummariesLive(
|
session.getPagedRoomSummariesLive(
|
||||||
roomSummaryQueryParams {
|
roomSummaryQueryParams {
|
||||||
this.memberships = Membership.activeMemberships()
|
this.memberships = Membership.activeMemberships()
|
||||||
|
|
|
@ -34,7 +34,6 @@ import im.vector.app.R
|
||||||
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
||||||
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||||
import im.vector.app.core.extensions.exhaustive
|
import im.vector.app.core.extensions.exhaustive
|
||||||
import im.vector.app.core.flow.chunk
|
|
||||||
import im.vector.app.core.mvrx.runCatchingToAsync
|
import im.vector.app.core.mvrx.runCatchingToAsync
|
||||||
import im.vector.app.core.platform.VectorViewModel
|
import im.vector.app.core.platform.VectorViewModel
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
|
@ -57,6 +56,7 @@ import im.vector.app.features.session.coroutineScope
|
||||||
import im.vector.app.features.settings.VectorDataStore
|
import im.vector.app.features.settings.VectorDataStore
|
||||||
import im.vector.app.features.settings.VectorPreferences
|
import im.vector.app.features.settings.VectorPreferences
|
||||||
import im.vector.app.space
|
import im.vector.app.space
|
||||||
|
import im.vector.lib.core.utils.flow.chunk
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
|
|
|
@ -21,11 +21,11 @@ import android.media.AudioAttributes
|
||||||
import android.media.MediaPlayer
|
import android.media.MediaPlayer
|
||||||
import androidx.core.content.FileProvider
|
import androidx.core.content.FileProvider
|
||||||
import im.vector.app.BuildConfig
|
import im.vector.app.BuildConfig
|
||||||
import im.vector.app.core.utils.CountUpTimer
|
|
||||||
import im.vector.app.features.home.room.detail.timeline.helper.VoiceMessagePlaybackTracker
|
import im.vector.app.features.home.room.detail.timeline.helper.VoiceMessagePlaybackTracker
|
||||||
import im.vector.app.features.voice.VoiceFailure
|
import im.vector.app.features.voice.VoiceFailure
|
||||||
import im.vector.app.features.voice.VoiceRecorder
|
import im.vector.app.features.voice.VoiceRecorder
|
||||||
import im.vector.app.features.voice.VoiceRecorderProvider
|
import im.vector.app.features.voice.VoiceRecorderProvider
|
||||||
|
import im.vector.lib.core.utils.timer.CountUpTimer
|
||||||
import im.vector.lib.multipicker.entity.MultiPickerAudioType
|
import im.vector.lib.multipicker.entity.MultiPickerAudioType
|
||||||
import im.vector.lib.multipicker.utils.toMultiPickerAudioType
|
import im.vector.lib.multipicker.utils.toMultiPickerAudioType
|
||||||
import org.matrix.android.sdk.api.extensions.orFalse
|
import org.matrix.android.sdk.api.extensions.orFalse
|
||||||
|
|
|
@ -26,10 +26,10 @@ import im.vector.app.R
|
||||||
import im.vector.app.core.extensions.exhaustive
|
import im.vector.app.core.extensions.exhaustive
|
||||||
import im.vector.app.core.hardware.vibrate
|
import im.vector.app.core.hardware.vibrate
|
||||||
import im.vector.app.core.time.Clock
|
import im.vector.app.core.time.Clock
|
||||||
import im.vector.app.core.utils.CountUpTimer
|
|
||||||
import im.vector.app.core.utils.DimensionConverter
|
import im.vector.app.core.utils.DimensionConverter
|
||||||
import im.vector.app.databinding.ViewVoiceMessageRecorderBinding
|
import im.vector.app.databinding.ViewVoiceMessageRecorderBinding
|
||||||
import im.vector.app.features.home.room.detail.timeline.helper.VoiceMessagePlaybackTracker
|
import im.vector.app.features.home.room.detail.timeline.helper.VoiceMessagePlaybackTracker
|
||||||
|
import im.vector.lib.core.utils.timer.CountUpTimer
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.math.floor
|
import kotlin.math.floor
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ class RoomListSectionBuilderGroup(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
appStateHandler.selectedRoomGroupingObservable
|
appStateHandler.selectedRoomGroupingFlow
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
.onEach { groupingMethod ->
|
.onEach { groupingMethod ->
|
||||||
val selectedGroupId = (groupingMethod.orNull() as? RoomGroupingMethod.ByLegacyGroup)?.groupSummary?.groupId
|
val selectedGroupId = (groupingMethod.orNull() as? RoomGroupingMethod.ByLegacyGroup)?.groupSummary?.groupId
|
||||||
|
|
|
@ -132,7 +132,7 @@ class RoomListSectionBuilderSpace(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
appStateHandler.selectedRoomGroupingObservable
|
appStateHandler.selectedRoomGroupingFlow
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
.onEach { groupingMethod ->
|
.onEach { groupingMethod ->
|
||||||
val selectedSpace = groupingMethod.orNull()?.space()
|
val selectedSpace = groupingMethod.orNull()?.space()
|
||||||
|
@ -222,7 +222,7 @@ class RoomListSectionBuilderSpace(
|
||||||
|
|
||||||
// add suggested rooms
|
// add suggested rooms
|
||||||
val suggestedRoomsFlow = // MutableLiveData<List<SpaceChildInfo>>()
|
val suggestedRoomsFlow = // MutableLiveData<List<SpaceChildInfo>>()
|
||||||
appStateHandler.selectedRoomGroupingObservable
|
appStateHandler.selectedRoomGroupingFlow
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
.flatMapLatest { groupingMethod ->
|
.flatMapLatest { groupingMethod ->
|
||||||
val selectedSpace = groupingMethod.orNull()?.space()
|
val selectedSpace = groupingMethod.orNull()?.space()
|
||||||
|
|
|
@ -92,7 +92,7 @@ class RoomListViewModel @AssistedInject constructor(
|
||||||
init {
|
init {
|
||||||
observeMembershipChanges()
|
observeMembershipChanges()
|
||||||
|
|
||||||
appStateHandler.selectedRoomGroupingObservable
|
appStateHandler.selectedRoomGroupingFlow
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
.execute {
|
.execute {
|
||||||
copy(
|
copy(
|
||||||
|
|
|
@ -25,6 +25,7 @@ import com.tapadoo.alerter.Alerter
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.platform.VectorBaseActivity
|
import im.vector.app.core.platform.VectorBaseActivity
|
||||||
import im.vector.app.core.utils.isAnimationDisabled
|
import im.vector.app.core.utils.isAnimationDisabled
|
||||||
|
import im.vector.app.features.analytics.ui.consent.AnalyticsOptInActivity
|
||||||
import im.vector.app.features.pin.PinActivity
|
import im.vector.app.features.pin.PinActivity
|
||||||
import im.vector.app.features.signout.hard.SignedOutActivity
|
import im.vector.app.features.signout.hard.SignedOutActivity
|
||||||
import im.vector.app.features.themes.ThemeUtils
|
import im.vector.app.features.themes.ThemeUtils
|
||||||
|
@ -300,6 +301,7 @@ class PopupAlertManager @Inject constructor() {
|
||||||
return alert != null &&
|
return alert != null &&
|
||||||
activity !is PinActivity &&
|
activity !is PinActivity &&
|
||||||
activity !is SignedOutActivity &&
|
activity !is SignedOutActivity &&
|
||||||
|
activity !is AnalyticsOptInActivity &&
|
||||||
activity is VectorBaseActivity<*> &&
|
activity is VectorBaseActivity<*> &&
|
||||||
alert.shouldBeDisplayedIn.invoke(activity)
|
alert.shouldBeDisplayedIn.invoke(activity)
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,10 +32,10 @@ import dagger.hilt.android.AndroidEntryPoint
|
||||||
import im.vector.app.EmojiCompatFontProvider
|
import im.vector.app.EmojiCompatFontProvider
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.extensions.observeEvent
|
import im.vector.app.core.extensions.observeEvent
|
||||||
import im.vector.app.core.flow.throttleFirst
|
|
||||||
import im.vector.app.core.platform.VectorBaseActivity
|
import im.vector.app.core.platform.VectorBaseActivity
|
||||||
import im.vector.app.databinding.ActivityEmojiReactionPickerBinding
|
import im.vector.app.databinding.ActivityEmojiReactionPickerBinding
|
||||||
import im.vector.app.features.reactions.data.EmojiDataSource
|
import im.vector.app.features.reactions.data.EmojiDataSource
|
||||||
|
import im.vector.lib.core.utils.flow.throttleFirst
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
|
@ -29,12 +29,12 @@ import dagger.assisted.AssistedInject
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
||||||
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||||
import im.vector.app.core.flow.throttleFirst
|
|
||||||
import im.vector.app.core.platform.VectorViewModel
|
import im.vector.app.core.platform.VectorViewModel
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
import im.vector.app.core.utils.PublishDataSource
|
import im.vector.app.core.utils.PublishDataSource
|
||||||
import im.vector.app.features.auth.ReAuthActivity
|
import im.vector.app.features.auth.ReAuthActivity
|
||||||
import im.vector.app.features.login.ReAuthHelper
|
import im.vector.app.features.login.ReAuthHelper
|
||||||
|
import im.vector.lib.core.utils.flow.throttleFirst
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
|
|
|
@ -88,7 +88,7 @@ class SpaceListViewModel @AssistedInject constructor(@Assisted initialState: Spa
|
||||||
|
|
||||||
observeSpaceSummaries()
|
observeSpaceSummaries()
|
||||||
// observeSelectionState()
|
// observeSelectionState()
|
||||||
appStateHandler.selectedRoomGroupingObservable
|
appStateHandler.selectedRoomGroupingFlow
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
.setOnEach {
|
.setOnEach {
|
||||||
copy(
|
copy(
|
||||||
|
|
|
@ -32,12 +32,12 @@ import com.airbnb.mvrx.withState
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.extensions.cleanup
|
import im.vector.app.core.extensions.cleanup
|
||||||
import im.vector.app.core.extensions.configureWith
|
import im.vector.app.core.extensions.configureWith
|
||||||
import im.vector.app.core.flow.throttleFirst
|
|
||||||
import im.vector.app.core.platform.VectorBaseFragment
|
import im.vector.app.core.platform.VectorBaseFragment
|
||||||
import im.vector.app.databinding.FragmentSpacePreviewBinding
|
import im.vector.app.databinding.FragmentSpacePreviewBinding
|
||||||
import im.vector.app.features.home.AvatarRenderer
|
import im.vector.app.features.home.AvatarRenderer
|
||||||
import im.vector.app.features.spaces.SpacePreviewSharedAction
|
import im.vector.app.features.spaces.SpacePreviewSharedAction
|
||||||
import im.vector.app.features.spaces.SpacePreviewSharedActionViewModel
|
import im.vector.app.features.spaces.SpacePreviewSharedActionViewModel
|
||||||
|
import im.vector.lib.core.utils.flow.throttleFirst
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
Loading…
Reference in a new issue