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.
|
||||
- ``.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.
|
||||
- ``.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.
|
||||
|
||||
See https://github.com/twisted/towncrier#news-fragments if you need more details.
|
||||
|
|
|
@ -47,12 +47,10 @@ android {
|
|||
|
||||
dependencies {
|
||||
implementation project(":library:ui-styles")
|
||||
implementation project(":library:core-utils")
|
||||
|
||||
implementation 'com.github.chrisbanes:PhotoView:2.3.0'
|
||||
|
||||
implementation libs.rx.rxKotlin
|
||||
implementation libs.rx.rxAndroid
|
||||
|
||||
implementation libs.androidx.core
|
||||
implementation libs.androidx.appCompat
|
||||
implementation libs.androidx.recyclerview
|
||||
|
|
|
@ -20,12 +20,9 @@ import android.util.Log
|
|||
import android.view.View
|
||||
import androidx.core.view.isVisible
|
||||
import im.vector.lib.attachmentviewer.databinding.ItemVideoAttachmentBinding
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.Disposable
|
||||
import im.vector.lib.core.utils.timer.CountUpTimer
|
||||
import java.io.File
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
// TODO, it would be probably better to use a unique media player
|
||||
// for better customization and control
|
||||
|
@ -35,7 +32,7 @@ class VideoViewHolder constructor(itemView: View) :
|
|||
|
||||
private var isSelected = false
|
||||
private var mVideoPath: String? = null
|
||||
private var progressDisposable: Disposable? = null
|
||||
private var countUpTimer: CountUpTimer? = null
|
||||
private var progress: Int = 0
|
||||
private var wasPaused = false
|
||||
|
||||
|
@ -47,8 +44,7 @@ class VideoViewHolder constructor(itemView: View) :
|
|||
|
||||
override fun onRecycled() {
|
||||
super.onRecycled()
|
||||
progressDisposable?.dispose()
|
||||
progressDisposable = null
|
||||
stopTimer()
|
||||
mVideoPath = null
|
||||
}
|
||||
|
||||
|
@ -72,8 +68,7 @@ class VideoViewHolder constructor(itemView: View) :
|
|||
override fun entersBackground() {
|
||||
if (views.videoView.isPlaying) {
|
||||
progress = views.videoView.currentPosition
|
||||
progressDisposable?.dispose()
|
||||
progressDisposable = null
|
||||
stopTimer()
|
||||
views.videoView.stopPlayback()
|
||||
views.videoView.pause()
|
||||
}
|
||||
|
@ -91,8 +86,7 @@ class VideoViewHolder constructor(itemView: View) :
|
|||
} else {
|
||||
progress = 0
|
||||
}
|
||||
progressDisposable?.dispose()
|
||||
progressDisposable = null
|
||||
stopTimer()
|
||||
} else {
|
||||
if (mVideoPath != null) {
|
||||
startPlaying()
|
||||
|
@ -107,17 +101,19 @@ class VideoViewHolder constructor(itemView: View) :
|
|||
views.videoView.isVisible = true
|
||||
|
||||
views.videoView.setOnPreparedListener {
|
||||
progressDisposable?.dispose()
|
||||
progressDisposable = Observable.interval(100, TimeUnit.MILLISECONDS)
|
||||
.timeInterval()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe {
|
||||
stopTimer()
|
||||
countUpTimer = CountUpTimer(100).also {
|
||||
it.tickListener = object : CountUpTimer.TickListener {
|
||||
override fun onTick(milliseconds: Long) {
|
||||
val duration = views.videoView.duration
|
||||
val progress = views.videoView.currentPosition
|
||||
val isPlaying = views.videoView.isPlaying
|
||||
// Log.v("FOO", "isPlaying $isPlaying $progress/$duration")
|
||||
eventListener?.get()?.onEvent(AttachmentEvents.VideoEvent(isPlaying, progress, duration))
|
||||
}
|
||||
}
|
||||
it.resume()
|
||||
}
|
||||
}
|
||||
try {
|
||||
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) {
|
||||
if (!isSelected) return
|
||||
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 : [
|
||||
'coroutinesCore' : "org.jetbrains.kotlinx:kotlinx-coroutines-core:$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"
|
||||
],
|
||||
androidx : [
|
||||
|
@ -87,8 +86,7 @@ ext.libs = [
|
|||
'retrofitMoshi' : "com.squareup.retrofit2:converter-moshi:$retrofit"
|
||||
],
|
||||
rx : [
|
||||
'rxKotlin' : "io.reactivex.rxjava2:rxkotlin:2.4.0",
|
||||
'rxAndroid' : "io.reactivex.rxjava2:rxandroid:2.1.1"
|
||||
'rxKotlin' : "io.reactivex.rxjava2:rxkotlin:2.4.0"
|
||||
],
|
||||
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.
|
||||
*/
|
||||
|
||||
package im.vector.app.core.flow
|
||||
package im.vector.lib.core.utils.flow
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
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> {
|
||||
return scope.fixedPeriodTicker(delayMillis, initialDelayMillis).consumeAsFlow()
|
||||
}
|
||||
|
||||
@ExperimentalCoroutinesApi
|
||||
private fun CoroutineScope.fixedPeriodTicker(delayMillis: Long, initialDelayMillis: Long = delayMillis): ReceiveChannel<Unit> {
|
||||
require(delayMillis >= 0) { "Expected non-negative delay, but has $delayMillis ms" }
|
||||
require(initialDelayMillis >= 0) { "Expected non-negative initial delay, but has $initialDelayMillis ms" }
|
|
@ -14,9 +14,9 @@
|
|||
* 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.Dispatchers
|
||||
import kotlinx.coroutines.cancel
|
||||
|
@ -27,6 +27,7 @@ import kotlinx.coroutines.flow.onEach
|
|||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import java.util.concurrent.atomic.AtomicLong
|
||||
|
||||
@OptIn(kotlinx.coroutines.ExperimentalCoroutinesApi::class)
|
||||
class CountUpTimer(private val intervalInMs: Long = 1_000) {
|
||||
|
||||
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.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 'com.squareup.okhttp3:okhttp'
|
||||
implementation 'com.squareup.okhttp3:logging-interceptor'
|
||||
|
|
|
@ -22,6 +22,7 @@ import dagger.Module
|
|||
import dagger.Provides
|
||||
import okhttp3.ConnectionSpec
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Protocol
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import org.matrix.android.sdk.BuildConfig
|
||||
import org.matrix.android.sdk.api.MatrixConfiguration
|
||||
|
@ -71,6 +72,8 @@ internal object NetworkModule {
|
|||
val spec = ConnectionSpec.Builder(matrixConfiguration.connectionSpec).build()
|
||||
|
||||
return OkHttpClient.Builder()
|
||||
// workaround for #4669
|
||||
.protocols(listOf(Protocol.HTTP_1_1))
|
||||
.connectTimeout(30, TimeUnit.SECONDS)
|
||||
.readTimeout(60, TimeUnit.SECONDS)
|
||||
.writeTimeout(60, TimeUnit.SECONDS)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
include ':vector'
|
||||
include ':matrix-sdk-android'
|
||||
include ':matrix-sdk-android-rx'
|
||||
include ':diff-match-patch'
|
||||
include ':attachment-viewer'
|
||||
include ':multipicker'
|
||||
include ':library:core-utils'
|
||||
include ':library:ui-styles'
|
||||
include ':matrix-sdk-android-flow'
|
||||
|
|
|
@ -15,13 +15,18 @@
|
|||
name = "Bugfixes 🐛"
|
||||
showcontent = true
|
||||
|
||||
[[tool.towncrier.type]]
|
||||
directory = "wip"
|
||||
name = "In development 🚧"
|
||||
showcontent = true
|
||||
|
||||
[[tool.towncrier.type]]
|
||||
directory = "doc"
|
||||
name = "Improved Documentation 📚"
|
||||
showcontent = true
|
||||
|
||||
[[tool.towncrier.type]]
|
||||
directory = "removal"
|
||||
directory = "sdk"
|
||||
name = "SDK API changes ⚠️"
|
||||
showcontent = true
|
||||
|
||||
|
|
|
@ -333,6 +333,7 @@ dependencies {
|
|||
implementation project(":multipicker")
|
||||
implementation project(":attachment-viewer")
|
||||
implementation project(":library:ui-styles")
|
||||
implementation project(":library:core-utils")
|
||||
implementation 'androidx.multidex:multidex:2.0.1'
|
||||
|
||||
implementation libs.jetbrains.coroutinesCore
|
||||
|
|
|
@ -61,7 +61,7 @@ class AppStateHandler @Inject constructor(
|
|||
private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
|
||||
private val selectedSpaceDataSource = BehaviorDataSource<Option<RoomGroupingMethod>>(Option.empty())
|
||||
|
||||
val selectedRoomGroupingObservable = selectedSpaceDataSource.stream()
|
||||
val selectedRoomGroupingFlow = selectedSpaceDataSource.stream()
|
||||
|
||||
fun getCurrentRoomGroupingMethod(): RoomGroupingMethod? {
|
||||
// XXX we should somehow make it live :/ just a work around
|
||||
|
|
|
@ -31,7 +31,7 @@ import javax.inject.Inject
|
|||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class ActiveSessionHolder @Inject constructor(private val sessionObservableStore: ActiveSessionDataSource,
|
||||
class ActiveSessionHolder @Inject constructor(private val activeSessionDataSource: ActiveSessionDataSource,
|
||||
private val keyRequestHandler: KeyRequestHandler,
|
||||
private val incomingVerificationRequestHandler: IncomingVerificationRequestHandler,
|
||||
private val callManager: WebRtcCallManager,
|
||||
|
@ -46,7 +46,7 @@ class ActiveSessionHolder @Inject constructor(private val sessionObservableStore
|
|||
fun setActiveSession(session: Session) {
|
||||
Timber.w("setActiveSession of ${session.myUserId}")
|
||||
activeSession.set(session)
|
||||
sessionObservableStore.post(Option.just(session))
|
||||
activeSessionDataSource.post(Option.just(session))
|
||||
|
||||
keyRequestHandler.start(session)
|
||||
incomingVerificationRequestHandler.start(session)
|
||||
|
@ -66,7 +66,7 @@ class ActiveSessionHolder @Inject constructor(private val sessionObservableStore
|
|||
}
|
||||
|
||||
activeSession.set(null)
|
||||
sessionObservableStore.post(Option.empty())
|
||||
activeSessionDataSource.post(Option.empty())
|
||||
|
||||
keyRequestHandler.stop()
|
||||
incomingVerificationRequestHandler.stop()
|
||||
|
|
|
@ -16,9 +16,9 @@
|
|||
|
||||
package im.vector.app.features.analytics
|
||||
|
||||
import im.vector.app.core.flow.tickerFlow
|
||||
import im.vector.app.core.time.Clock
|
||||
import im.vector.app.features.analytics.plan.Error
|
||||
import im.vector.lib.core.utils.flow.tickerFlow
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
|
|
|
@ -19,9 +19,7 @@ package im.vector.app.features.call.webrtc
|
|||
import android.content.Context
|
||||
import android.hardware.camera2.CameraManager
|
||||
import androidx.core.content.getSystemService
|
||||
import im.vector.app.core.flow.chunk
|
||||
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.TextUtils.formatDuration
|
||||
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.mapToCallCandidate
|
||||
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.Deferred
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
|
|
@ -26,10 +26,10 @@ import androidx.lifecycle.lifecycleScope
|
|||
import com.airbnb.mvrx.activityViewModel
|
||||
import im.vector.app.R
|
||||
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.utils.startImportTextFromFileIntent
|
||||
import im.vector.app.databinding.FragmentSsssAccessFromKeyBinding
|
||||
import im.vector.lib.core.utils.flow.throttleFirst
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
|
|
|
@ -25,10 +25,10 @@ import androidx.core.text.toSpannable
|
|||
import androidx.lifecycle.lifecycleScope
|
||||
import com.airbnb.mvrx.activityViewModel
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.flow.throttleFirst
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.core.resources.ColorProvider
|
||||
import im.vector.app.databinding.FragmentSsssAccessFromPassphraseBinding
|
||||
import im.vector.lib.core.utils.flow.throttleFirst
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import reactivecircus.flowbinding.android.widget.editorActionEvents
|
||||
|
|
|
@ -27,9 +27,9 @@ import com.airbnb.mvrx.parentFragmentViewModel
|
|||
import com.airbnb.mvrx.withState
|
||||
import im.vector.app.R
|
||||
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.databinding.FragmentBootstrapEnterPassphraseBinding
|
||||
import im.vector.lib.core.utils.flow.throttleFirst
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import reactivecircus.flowbinding.android.widget.editorActionEvents
|
||||
|
|
|
@ -25,10 +25,10 @@ import androidx.lifecycle.lifecycleScope
|
|||
import com.airbnb.mvrx.parentFragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.flow.throttleFirst
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.databinding.FragmentBootstrapEnterPassphraseBinding
|
||||
import im.vector.app.features.settings.VectorLocale
|
||||
import im.vector.lib.core.utils.flow.throttleFirst
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import reactivecircus.flowbinding.android.widget.editorActionEvents
|
||||
|
|
|
@ -33,12 +33,12 @@ import com.airbnb.mvrx.withState
|
|||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.hideKeyboard
|
||||
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.resources.ColorProvider
|
||||
import im.vector.app.core.utils.colorizeMatchingText
|
||||
import im.vector.app.core.utils.startImportTextFromFileIntent
|
||||
import im.vector.app.databinding.FragmentBootstrapMigrateBackupBinding
|
||||
import im.vector.lib.core.utils.flow.throttleFirst
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
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.hiltMavericksViewModelFactory
|
||||
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.features.call.dialpad.DialPadLookup
|
||||
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.settings.VectorDataStore
|
||||
import im.vector.app.features.ui.UiStateRepository
|
||||
import im.vector.lib.core.utils.flow.throttleFirst
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.filterIsInstance
|
||||
|
@ -197,7 +197,7 @@ class HomeDetailViewModel @AssistedInject constructor(
|
|||
}
|
||||
|
||||
private fun observeRoomGroupingMethod() {
|
||||
appStateHandler.selectedRoomGroupingObservable
|
||||
appStateHandler.selectedRoomGroupingFlow
|
||||
.setOnEach {
|
||||
copy(
|
||||
roomGroupingMethod = it.orNull() ?: RoomGroupingMethod.BySpace(null)
|
||||
|
@ -206,7 +206,7 @@ class HomeDetailViewModel @AssistedInject constructor(
|
|||
}
|
||||
|
||||
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
|
||||
// the actual models
|
||||
session.getPagedRoomSummariesLive(
|
||||
|
|
|
@ -50,7 +50,7 @@ class PromoteRestrictedViewModel @AssistedInject constructor(
|
|||
) : VectorViewModel<ActiveSpaceViewState, EmptyAction, EmptyViewEvents>(initialState) {
|
||||
|
||||
init {
|
||||
appStateHandler.selectedRoomGroupingObservable.distinctUntilChanged().execute { state ->
|
||||
appStateHandler.selectedRoomGroupingFlow.distinctUntilChanged().execute { state ->
|
||||
val groupingMethod = state.invoke()?.orNull()
|
||||
val isSpaceMode = groupingMethod is RoomGroupingMethod.BySpace
|
||||
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.core.di.MavericksAssistedViewModelFactory
|
||||
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.EmptyViewEvents
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.features.invite.AutoAcceptInvites
|
||||
import im.vector.app.features.settings.VectorPreferences
|
||||
import im.vector.lib.core.utils.flow.throttleFirst
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
|
@ -107,8 +107,8 @@ class UnreadMessagesSharedViewModel @AssistedInject constructor(@Assisted initia
|
|||
}
|
||||
|
||||
combine(
|
||||
appStateHandler.selectedRoomGroupingObservable.distinctUntilChanged(),
|
||||
appStateHandler.selectedRoomGroupingObservable.flatMapLatest {
|
||||
appStateHandler.selectedRoomGroupingFlow.distinctUntilChanged(),
|
||||
appStateHandler.selectedRoomGroupingFlow.flatMapLatest {
|
||||
session.getPagedRoomSummariesLive(
|
||||
roomSummaryQueryParams {
|
||||
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.hiltMavericksViewModelFactory
|
||||
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.platform.VectorViewModel
|
||||
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.VectorPreferences
|
||||
import im.vector.app.space
|
||||
import im.vector.lib.core.utils.flow.chunk
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
|
|
|
@ -21,11 +21,11 @@ import android.media.AudioAttributes
|
|||
import android.media.MediaPlayer
|
||||
import androidx.core.content.FileProvider
|
||||
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.voice.VoiceFailure
|
||||
import im.vector.app.features.voice.VoiceRecorder
|
||||
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.utils.toMultiPickerAudioType
|
||||
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.hardware.vibrate
|
||||
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.databinding.ViewVoiceMessageRecorderBinding
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.VoiceMessagePlaybackTracker
|
||||
import im.vector.lib.core.utils.timer.CountUpTimer
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.floor
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ class RoomListSectionBuilderGroup(
|
|||
}
|
||||
}
|
||||
|
||||
appStateHandler.selectedRoomGroupingObservable
|
||||
appStateHandler.selectedRoomGroupingFlow
|
||||
.distinctUntilChanged()
|
||||
.onEach { groupingMethod ->
|
||||
val selectedGroupId = (groupingMethod.orNull() as? RoomGroupingMethod.ByLegacyGroup)?.groupSummary?.groupId
|
||||
|
|
|
@ -132,7 +132,7 @@ class RoomListSectionBuilderSpace(
|
|||
}
|
||||
}
|
||||
|
||||
appStateHandler.selectedRoomGroupingObservable
|
||||
appStateHandler.selectedRoomGroupingFlow
|
||||
.distinctUntilChanged()
|
||||
.onEach { groupingMethod ->
|
||||
val selectedSpace = groupingMethod.orNull()?.space()
|
||||
|
@ -222,7 +222,7 @@ class RoomListSectionBuilderSpace(
|
|||
|
||||
// add suggested rooms
|
||||
val suggestedRoomsFlow = // MutableLiveData<List<SpaceChildInfo>>()
|
||||
appStateHandler.selectedRoomGroupingObservable
|
||||
appStateHandler.selectedRoomGroupingFlow
|
||||
.distinctUntilChanged()
|
||||
.flatMapLatest { groupingMethod ->
|
||||
val selectedSpace = groupingMethod.orNull()?.space()
|
||||
|
|
|
@ -92,7 +92,7 @@ class RoomListViewModel @AssistedInject constructor(
|
|||
init {
|
||||
observeMembershipChanges()
|
||||
|
||||
appStateHandler.selectedRoomGroupingObservable
|
||||
appStateHandler.selectedRoomGroupingFlow
|
||||
.distinctUntilChanged()
|
||||
.execute {
|
||||
copy(
|
||||
|
|
|
@ -25,6 +25,7 @@ import com.tapadoo.alerter.Alerter
|
|||
import im.vector.app.R
|
||||
import im.vector.app.core.platform.VectorBaseActivity
|
||||
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.signout.hard.SignedOutActivity
|
||||
import im.vector.app.features.themes.ThemeUtils
|
||||
|
@ -300,6 +301,7 @@ class PopupAlertManager @Inject constructor() {
|
|||
return alert != null &&
|
||||
activity !is PinActivity &&
|
||||
activity !is SignedOutActivity &&
|
||||
activity !is AnalyticsOptInActivity &&
|
||||
activity is VectorBaseActivity<*> &&
|
||||
alert.shouldBeDisplayedIn.invoke(activity)
|
||||
}
|
||||
|
|
|
@ -32,10 +32,10 @@ import dagger.hilt.android.AndroidEntryPoint
|
|||
import im.vector.app.EmojiCompatFontProvider
|
||||
import im.vector.app.R
|
||||
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.databinding.ActivityEmojiReactionPickerBinding
|
||||
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.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
|
@ -29,12 +29,12 @@ import dagger.assisted.AssistedInject
|
|||
import im.vector.app.R
|
||||
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
||||
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.resources.StringProvider
|
||||
import im.vector.app.core.utils.PublishDataSource
|
||||
import im.vector.app.features.auth.ReAuthActivity
|
||||
import im.vector.app.features.login.ReAuthHelper
|
||||
import im.vector.lib.core.utils.flow.throttleFirst
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
|
|
|
@ -88,7 +88,7 @@ class SpaceListViewModel @AssistedInject constructor(@Assisted initialState: Spa
|
|||
|
||||
observeSpaceSummaries()
|
||||
// observeSelectionState()
|
||||
appStateHandler.selectedRoomGroupingObservable
|
||||
appStateHandler.selectedRoomGroupingFlow
|
||||
.distinctUntilChanged()
|
||||
.setOnEach {
|
||||
copy(
|
||||
|
|
|
@ -32,12 +32,12 @@ import com.airbnb.mvrx.withState
|
|||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.cleanup
|
||||
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.databinding.FragmentSpacePreviewBinding
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
import im.vector.app.features.spaces.SpacePreviewSharedAction
|
||||
import im.vector.app.features.spaces.SpacePreviewSharedActionViewModel
|
||||
import im.vector.lib.core.utils.flow.throttleFirst
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
|
Loading…
Reference in a new issue