mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-21 17:05:39 +03:00
Flow migration: remove Rx completely (rxbinding)
This commit is contained in:
parent
a9d192fa39
commit
34cb99e8ae
57 changed files with 392 additions and 435 deletions
|
@ -17,7 +17,7 @@ def arrow = "0.8.2"
|
|||
def markwon = "4.6.2"
|
||||
def moshi = "1.12.0"
|
||||
def lifecycle = "2.2.0"
|
||||
def rxBinding = "3.1.0"
|
||||
def flowBinding = "1.2.0"
|
||||
def epoxy = "4.6.2"
|
||||
def mavericks = "2.4.0"
|
||||
def glide = "4.12.0"
|
||||
|
@ -115,13 +115,13 @@ ext.libs = [
|
|||
'bigImageViewer' : "com.github.piasy:BigImageViewer:$bigImageViewer",
|
||||
'glideImageLoader' : "com.github.piasy:GlideImageLoader:$bigImageViewer",
|
||||
'progressPieIndicator' : "com.github.piasy:ProgressPieIndicator:$bigImageViewer",
|
||||
'glideImageViewFactory' : "com.github.piasy:GlideImageViewFactory:$bigImageViewer"
|
||||
'glideImageViewFactory' : "com.github.piasy:GlideImageViewFactory:$bigImageViewer",
|
||||
'flowBinding' : "io.github.reactivecircus.flowbinding:flowbinding-android:$flowBinding",
|
||||
'flowBindingAppcompat' : "io.github.reactivecircus.flowbinding:flowbinding-appcompat:$flowBinding",
|
||||
'flowBindingMaterial' : "io.github.reactivecircus.flowbinding:flowbinding-material:$flowBinding"
|
||||
],
|
||||
jakewharton : [
|
||||
'timber' : "com.jakewharton.timber:timber:5.0.1",
|
||||
'rxbinding' : "com.jakewharton.rxbinding3:rxbinding:$rxBinding",
|
||||
'rxbindingAppcompat' : "com.jakewharton.rxbinding3:rxbinding-appcompat:$rxBinding",
|
||||
'rxbindingMaterial' : "com.jakewharton.rxbinding3:rxbinding-material:$rxBinding"
|
||||
'timber' : "com.jakewharton.timber:timber:5.0.1"
|
||||
],
|
||||
jsonwebtoken: [
|
||||
'jjwtApi' : "io.jsonwebtoken:jjwt-api:$jjwt",
|
||||
|
|
|
@ -373,14 +373,10 @@ dependencies {
|
|||
// Phone number https://github.com/google/libphonenumber
|
||||
implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.35'
|
||||
|
||||
// rx
|
||||
implementation libs.rx.rxKotlin
|
||||
implementation libs.rx.rxAndroid
|
||||
implementation 'com.jakewharton.rxrelay2:rxrelay:2.1.1'
|
||||
// RXBinding
|
||||
implementation libs.jakewharton.rxbinding
|
||||
implementation libs.jakewharton.rxbindingAppcompat
|
||||
implementation libs.jakewharton.rxbindingMaterial
|
||||
// FlowBinding
|
||||
implementation libs.github.flowBinding
|
||||
implementation libs.github.flowBindingAppcompat
|
||||
implementation libs.github.flowBindingMaterial
|
||||
|
||||
implementation libs.airbnb.epoxy
|
||||
implementation libs.airbnb.epoxyGlide
|
||||
|
|
|
@ -24,7 +24,6 @@ import im.vector.app.core.di.ActiveSessionHolder
|
|||
import im.vector.app.core.utils.BehaviorDataSource
|
||||
import im.vector.app.features.session.coroutineScope
|
||||
import im.vector.app.features.ui.UiStateRepository
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
|
@ -37,7 +36,6 @@ import org.matrix.android.sdk.api.extensions.tryOrNull
|
|||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.api.session.group.model.GroupSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import org.matrix.android.sdk.api.util.CancelableBag
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ import im.vector.app.features.roomprofile.members.RoomMemberListFragment
|
|||
import im.vector.app.features.roomprofile.notifications.RoomNotificationSettingsFragment
|
||||
import im.vector.app.features.roomprofile.permissions.RoomPermissionsFragment
|
||||
import im.vector.app.features.roomprofile.settings.RoomSettingsFragment
|
||||
import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleChooseRestrictedFragment
|
||||
import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedFragment
|
||||
import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleFragment
|
||||
import im.vector.app.features.roomprofile.uploads.RoomUploadsFragment
|
||||
import im.vector.app.features.roomprofile.uploads.files.RoomUploadsFilesFragment
|
||||
|
|
|
@ -26,6 +26,7 @@ import kotlinx.coroutines.coroutineScope
|
|||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.consumeAsFlow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.selects.select
|
||||
|
@ -66,6 +67,10 @@ fun <T> Flow<T>.chunk(durationInMillis: Long): Flow<List<T>> {
|
|||
}
|
||||
}
|
||||
|
||||
fun tickerFlow(scope: CoroutineScope, delayMillis: Long, initialDelayMillis: Long = delayMillis): Flow<Unit> {
|
||||
return scope.fixedPeriodTicker(delayMillis, initialDelayMillis).consumeAsFlow()
|
||||
}
|
||||
|
||||
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" }
|
|
@ -45,7 +45,6 @@ import com.airbnb.mvrx.MavericksView
|
|||
import com.bumptech.glide.util.Util
|
||||
import com.google.android.material.appbar.MaterialToolbar
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.jakewharton.rxbinding3.view.clicks
|
||||
import dagger.hilt.android.EntryPointAccessors
|
||||
import im.vector.app.BuildConfig
|
||||
import im.vector.app.R
|
||||
|
@ -78,17 +77,13 @@ import im.vector.app.features.settings.VectorPreferences
|
|||
import im.vector.app.features.themes.ActivityOtherThemes
|
||||
import im.vector.app.features.themes.ThemeUtils
|
||||
import im.vector.app.receivers.DebugReceiver
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import io.reactivex.disposables.Disposable
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.sample
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.failure.GlobalError
|
||||
import reactivecircus.flowbinding.android.view.clicks
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
abstract class VectorBaseActivity<VB : ViewBinding> : AppCompatActivity(), MavericksView {
|
||||
|
@ -123,10 +118,9 @@ abstract class VectorBaseActivity<VB : ViewBinding> : AppCompatActivity(), Maver
|
|||
|
||||
protected fun View.debouncedClicks(onClicked: () -> Unit) {
|
||||
clicks()
|
||||
.throttleFirst(300, TimeUnit.MILLISECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe { onClicked() }
|
||||
.disposeOnDestroy()
|
||||
.sample(300)
|
||||
.onEach { onClicked() }
|
||||
.launchIn(lifecycleScope)
|
||||
}
|
||||
|
||||
/* ==========================================================================================
|
||||
|
@ -137,6 +131,7 @@ abstract class VectorBaseActivity<VB : ViewBinding> : AppCompatActivity(), Maver
|
|||
private lateinit var sessionListener: SessionListener
|
||||
protected lateinit var bugReporter: BugReporter
|
||||
private lateinit var pinLocker: PinLocker
|
||||
|
||||
@Inject
|
||||
lateinit var rageShake: RageShake
|
||||
lateinit var navigator: Navigator
|
||||
|
@ -154,7 +149,6 @@ abstract class VectorBaseActivity<VB : ViewBinding> : AppCompatActivity(), Maver
|
|||
// For debug only
|
||||
private var debugReceiver: DebugReceiver? = null
|
||||
|
||||
private val uiDisposables = CompositeDisposable()
|
||||
private val restorables = ArrayList<Restorable>()
|
||||
|
||||
override fun attachBaseContext(base: Context) {
|
||||
|
@ -179,10 +173,6 @@ abstract class VectorBaseActivity<VB : ViewBinding> : AppCompatActivity(), Maver
|
|||
return this
|
||||
}
|
||||
|
||||
protected fun Disposable.disposeOnDestroy() {
|
||||
uiDisposables.add(this)
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
Timber.i("onCreate Activity ${javaClass.simpleName}")
|
||||
|
@ -306,8 +296,6 @@ abstract class VectorBaseActivity<VB : ViewBinding> : AppCompatActivity(), Maver
|
|||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
Timber.i("onDestroy Activity ${javaClass.simpleName}")
|
||||
|
||||
uiDisposables.dispose()
|
||||
}
|
||||
|
||||
private val pinStartForActivityResult = registerStartForActivityResult { activityResult ->
|
||||
|
|
|
@ -33,19 +33,14 @@ import com.airbnb.mvrx.MavericksView
|
|||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
import com.jakewharton.rxbinding3.view.clicks
|
||||
import dagger.hilt.android.EntryPointAccessors
|
||||
import im.vector.app.core.di.ActivityEntryPoint
|
||||
import im.vector.app.core.utils.DimensionConverter
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import io.reactivex.disposables.Disposable
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.sample
|
||||
import reactivecircus.flowbinding.android.view.clicks
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* Add Mavericks capabilities, handle DI and bindings.
|
||||
|
@ -113,14 +108,12 @@ abstract class VectorBaseBottomSheetDialogFragment<VB : ViewBinding> : BottomShe
|
|||
|
||||
@CallSuper
|
||||
override fun onDestroyView() {
|
||||
uiDisposables.clear()
|
||||
_binding = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
override fun onDestroy() {
|
||||
uiDisposables.dispose()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
|
@ -169,27 +162,15 @@ abstract class VectorBaseBottomSheetDialogFragment<VB : ViewBinding> : BottomShe
|
|||
arguments = args?.let { Bundle().apply { putParcelable(Mavericks.KEY_ARG, it) } }
|
||||
}
|
||||
|
||||
/* ==========================================================================================
|
||||
* Disposable
|
||||
* ========================================================================================== */
|
||||
|
||||
private val uiDisposables = CompositeDisposable()
|
||||
|
||||
protected fun Disposable.disposeOnDestroyView(): Disposable {
|
||||
uiDisposables.add(this)
|
||||
return this
|
||||
}
|
||||
|
||||
/* ==========================================================================================
|
||||
* Views
|
||||
* ========================================================================================== */
|
||||
|
||||
protected fun View.debouncedClicks(onClicked: () -> Unit) {
|
||||
clicks()
|
||||
.throttleFirst(300, TimeUnit.MILLISECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe { onClicked() }
|
||||
.disposeOnDestroyView()
|
||||
.sample(300)
|
||||
.onEach { onClicked() }
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
}
|
||||
|
||||
/* ==========================================================================================
|
||||
|
|
|
@ -35,7 +35,6 @@ import com.airbnb.mvrx.MavericksView
|
|||
import com.bumptech.glide.util.Util.assertMainThread
|
||||
import com.google.android.material.appbar.MaterialToolbar
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.jakewharton.rxbinding3.view.clicks
|
||||
import dagger.hilt.android.EntryPointAccessors
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.di.ActivityEntryPoint
|
||||
|
@ -46,14 +45,10 @@ import im.vector.app.core.extensions.toMvRxBundle
|
|||
import im.vector.app.features.navigation.Navigator
|
||||
import im.vector.lib.ui.styles.dialogs.MaterialProgressDialog
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import io.reactivex.disposables.Disposable
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.sample
|
||||
import reactivecircus.flowbinding.android.view.clicks
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
|
@ -155,7 +150,6 @@ abstract class VectorBaseFragment<VB : ViewBinding> : Fragment(), MavericksView
|
|||
@CallSuper
|
||||
override fun onDestroyView() {
|
||||
Timber.i("onDestroyView Fragment ${javaClass.simpleName}")
|
||||
uiDisposables.clear()
|
||||
_binding = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
@ -163,7 +157,6 @@ abstract class VectorBaseFragment<VB : ViewBinding> : Fragment(), MavericksView
|
|||
@CallSuper
|
||||
override fun onDestroy() {
|
||||
Timber.i("onDestroy Fragment ${javaClass.simpleName}")
|
||||
uiDisposables.dispose()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
|
@ -228,16 +221,6 @@ abstract class VectorBaseFragment<VB : ViewBinding> : Fragment(), MavericksView
|
|||
}
|
||||
}
|
||||
|
||||
/* ==========================================================================================
|
||||
* Disposable
|
||||
* ========================================================================================== */
|
||||
|
||||
private val uiDisposables = CompositeDisposable()
|
||||
|
||||
protected fun Disposable.disposeOnDestroyView() {
|
||||
uiDisposables.add(this)
|
||||
}
|
||||
|
||||
/* ==========================================================================================
|
||||
* ViewEvents
|
||||
* ========================================================================================== */
|
||||
|
@ -258,10 +241,9 @@ abstract class VectorBaseFragment<VB : ViewBinding> : Fragment(), MavericksView
|
|||
|
||||
protected fun View.debouncedClicks(onClicked: () -> Unit) {
|
||||
clicks()
|
||||
.throttleFirst(300, TimeUnit.MILLISECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe { onClicked() }
|
||||
.disposeOnDestroyView()
|
||||
.sample(300)
|
||||
.onEach { onClicked() }
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
}
|
||||
|
||||
/* ==========================================================================================
|
||||
|
|
|
@ -16,28 +16,14 @@
|
|||
|
||||
package im.vector.app.core.rx
|
||||
|
||||
import im.vector.app.features.settings.VectorPreferences
|
||||
import io.reactivex.plugins.RxJavaPlugins
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
class RxConfig @Inject constructor(
|
||||
private val vectorPreferences: VectorPreferences
|
||||
) {
|
||||
class RxConfig @Inject constructor() {
|
||||
|
||||
/**
|
||||
* Make sure unhandled Rx error does not crash the app in production
|
||||
*/
|
||||
fun setupRxPlugin() {
|
||||
RxJavaPlugins.setErrorHandler { throwable ->
|
||||
Timber.e(throwable, "RxError")
|
||||
// is InterruptedException -> fine, some blocking code was interrupted by a dispose call
|
||||
if (throwable !is InterruptedException) {
|
||||
// Avoid crash in production, except if user wants it
|
||||
if (vectorPreferences.failFast()) {
|
||||
throw throwable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,22 +16,35 @@
|
|||
|
||||
package im.vector.app.core.utils
|
||||
|
||||
import io.reactivex.Observable
|
||||
import java.util.concurrent.TimeUnit
|
||||
import im.vector.app.core.flow.tickerFlow
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import java.util.concurrent.atomic.AtomicLong
|
||||
|
||||
class CountUpTimer(private val intervalInMs: Long = 1_000) {
|
||||
|
||||
private val coroutineScope = CoroutineScope(Dispatchers.Main)
|
||||
private val elapsedTime: AtomicLong = AtomicLong()
|
||||
private val resumed: AtomicBoolean = AtomicBoolean(false)
|
||||
|
||||
private val disposable = Observable.interval(intervalInMs / 10, TimeUnit.MILLISECONDS)
|
||||
init {
|
||||
startCounter()
|
||||
}
|
||||
|
||||
private fun startCounter() {
|
||||
tickerFlow(coroutineScope, intervalInMs / 10)
|
||||
.filter { resumed.get() }
|
||||
.map { elapsedTime.addAndGet(intervalInMs / 10) }
|
||||
.filter { it % intervalInMs == 0L }
|
||||
.subscribe {
|
||||
.onEach {
|
||||
tickListener?.onTick(it)
|
||||
}.launchIn(coroutineScope)
|
||||
}
|
||||
|
||||
var tickListener: TickListener? = null
|
||||
|
@ -49,7 +62,7 @@ class CountUpTimer(private val intervalInMs: Long = 1_000) {
|
|||
}
|
||||
|
||||
fun stop() {
|
||||
disposable.dispose()
|
||||
coroutineScope.cancel()
|
||||
}
|
||||
|
||||
interface TickListener {
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package im.vector.app.core.utils
|
||||
|
||||
import com.jakewharton.rxrelay2.BehaviorRelay
|
||||
import kotlinx.coroutines.channels.BufferOverflow
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
|
@ -46,14 +45,6 @@ open class BehaviorDataSource<T>(private val defaultValue: T? = null) : MutableD
|
|||
override fun post(value: T) {
|
||||
mutableFlow.tryEmit(value)
|
||||
}
|
||||
|
||||
private fun createRelay(): BehaviorRelay<T> {
|
||||
return if (defaultValue == null) {
|
||||
BehaviorRelay.create()
|
||||
} else {
|
||||
BehaviorRelay.createDefault(defaultValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* Copyright 2019 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.core.utils
|
||||
|
||||
import io.reactivex.Completable
|
||||
import io.reactivex.Single
|
||||
import io.reactivex.disposables.Disposable
|
||||
import io.reactivex.internal.functions.Functions
|
||||
import timber.log.Timber
|
||||
|
||||
fun <T> Single<T>.subscribeLogError(): Disposable {
|
||||
return subscribe(Functions.emptyConsumer(), { Timber.e(it) })
|
||||
}
|
||||
|
||||
fun Completable.subscribeLogError(): Disposable {
|
||||
return subscribe({}, { Timber.e(it) })
|
||||
}
|
|
@ -19,8 +19,10 @@ 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
|
||||
import im.vector.app.features.call.CameraProxy
|
||||
|
@ -35,14 +37,16 @@ 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 io.reactivex.disposables.Disposable
|
||||
import io.reactivex.subjects.PublishSubject
|
||||
import io.reactivex.subjects.ReplaySubject
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Deferred
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
|
@ -85,7 +89,6 @@ import org.webrtc.VideoTrack
|
|||
import timber.log.Timber
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.concurrent.CopyOnWriteArrayList
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Provider
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
|
@ -157,7 +160,7 @@ class WebRtcCall(
|
|||
private var currentCaptureFormat: CaptureFormat = CaptureFormat.HD
|
||||
private var cameraAvailabilityCallback: CameraManager.AvailabilityCallback? = null
|
||||
|
||||
private val timer = CountUpTimer(Duration.ofSeconds(1).toMillis()).apply {
|
||||
private val timer = CountUpTimer(1000L).apply {
|
||||
tickListener = object : CountUpTimer.TickListener {
|
||||
override fun onTick(milliseconds: Long) {
|
||||
val formattedDuration = formatDuration(Duration.ofMillis(milliseconds))
|
||||
|
@ -197,26 +200,33 @@ class WebRtcCall(
|
|||
private var localSurfaceRenderers: MutableList<WeakReference<SurfaceViewRenderer>> = ArrayList()
|
||||
private var remoteSurfaceRenderers: MutableList<WeakReference<SurfaceViewRenderer>> = ArrayList()
|
||||
|
||||
private val iceCandidateSource: PublishSubject<IceCandidate> = PublishSubject.create()
|
||||
private val iceCandidateDisposable = iceCandidateSource
|
||||
.buffer(300, TimeUnit.MILLISECONDS)
|
||||
.subscribe {
|
||||
private val localIceCandidateSource = PublishDataSource<IceCandidate>()
|
||||
private var localIceCandidateJob: Job? = null
|
||||
|
||||
private val remoteCandidateSource: MutableSharedFlow<IceCandidate> = MutableSharedFlow(replay = Int.MAX_VALUE)
|
||||
private var remoteIceCandidateJob: Job? = null
|
||||
|
||||
init {
|
||||
setupLocalIceCanditate()
|
||||
mxCall.addListener(this)
|
||||
}
|
||||
|
||||
private fun setupLocalIceCanditate() {
|
||||
sessionScope?.let {
|
||||
localIceCandidateJob = localIceCandidateSource.stream()
|
||||
.chunk(300)
|
||||
.onEach {
|
||||
// omit empty :/
|
||||
if (it.isNotEmpty()) {
|
||||
Timber.tag(loggerTag.value).v("Sending local ice candidates to call")
|
||||
// it.forEach { peerConnection?.addIceCandidate(it) }
|
||||
mxCall.sendLocalCallCandidates(it.mapToCallCandidate())
|
||||
}
|
||||
}.launchIn(it)
|
||||
}
|
||||
}
|
||||
|
||||
private val remoteCandidateSource: ReplaySubject<IceCandidate> = ReplaySubject.create()
|
||||
private var remoteIceCandidateDisposable: Disposable? = null
|
||||
|
||||
init {
|
||||
mxCall.addListener(this)
|
||||
}
|
||||
|
||||
fun onIceCandidate(iceCandidate: IceCandidate) = iceCandidateSource.onNext(iceCandidate)
|
||||
fun onIceCandidate(iceCandidate: IceCandidate) = localIceCandidateSource.post(iceCandidate)
|
||||
|
||||
fun onRenegotiationNeeded(restartIce: Boolean) {
|
||||
sessionScope?.launch(dispatcher) {
|
||||
|
@ -438,12 +448,15 @@ class WebRtcCall(
|
|||
createLocalStream()
|
||||
attachViewRenderersInternal()
|
||||
Timber.tag(loggerTag.value).v("remoteCandidateSource $remoteCandidateSource")
|
||||
remoteIceCandidateDisposable = remoteCandidateSource.subscribe({
|
||||
remoteIceCandidateJob = remoteCandidateSource
|
||||
.onEach {
|
||||
Timber.tag(loggerTag.value).v("adding remote ice candidate $it")
|
||||
peerConnection?.addIceCandidate(it)
|
||||
}, {
|
||||
}
|
||||
.catch {
|
||||
Timber.tag(loggerTag.value).v("failed to add remote ice candidate $it")
|
||||
})
|
||||
}
|
||||
.launchIn(this)
|
||||
// Now we wait for negotiation callback
|
||||
}
|
||||
|
||||
|
@ -488,12 +501,13 @@ class WebRtcCall(
|
|||
mxCall.accept(it.description)
|
||||
}
|
||||
Timber.tag(loggerTag.value).v("remoteCandidateSource $remoteCandidateSource")
|
||||
remoteIceCandidateDisposable = remoteCandidateSource.subscribe({
|
||||
remoteIceCandidateJob = remoteCandidateSource
|
||||
.onEach {
|
||||
Timber.tag(loggerTag.value).v("adding remote ice candidate $it")
|
||||
peerConnection?.addIceCandidate(it)
|
||||
}, {
|
||||
}.catch {
|
||||
Timber.tag(loggerTag.value).v("failed to add remote ice candidate $it")
|
||||
})
|
||||
}.launchIn(this)
|
||||
}
|
||||
|
||||
private suspend fun getTurnServer(): TurnServerResponse? {
|
||||
|
@ -761,8 +775,8 @@ class WebRtcCall(
|
|||
videoCapturer?.stopCapture()
|
||||
videoCapturer?.dispose()
|
||||
videoCapturer = null
|
||||
remoteIceCandidateDisposable?.dispose()
|
||||
iceCandidateDisposable?.dispose()
|
||||
remoteIceCandidateJob?.cancel()
|
||||
localIceCandidateJob?.cancel()
|
||||
peerConnection?.close()
|
||||
peerConnection?.dispose()
|
||||
localAudioSource?.dispose()
|
||||
|
@ -852,7 +866,7 @@ class WebRtcCall(
|
|||
}
|
||||
Timber.tag(loggerTag.value).v("onCallIceCandidateReceived for call ${mxCall.callId} sdp: ${it.candidate}")
|
||||
val iceCandidate = IceCandidate(it.sdpMid, it.sdpMLineIndex, it.candidate)
|
||||
remoteCandidateSource.onNext(iceCandidate)
|
||||
remoteCandidateSource.emit(iceCandidate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,10 +21,9 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.airbnb.mvrx.activityViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import com.jakewharton.rxbinding3.widget.checkedChanges
|
||||
import com.jakewharton.rxbinding3.widget.textChanges
|
||||
import im.vector.app.core.extensions.cleanup
|
||||
import im.vector.app.core.extensions.configureWith
|
||||
import im.vector.app.core.extensions.hideKeyboard
|
||||
|
@ -37,8 +36,13 @@ import im.vector.app.features.userdirectory.UserListAction
|
|||
import im.vector.app.features.userdirectory.UserListSharedAction
|
||||
import im.vector.app.features.userdirectory.UserListSharedActionViewModel
|
||||
import im.vector.app.features.userdirectory.UserListViewModel
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import org.matrix.android.sdk.api.session.identity.ThreePid
|
||||
import org.matrix.android.sdk.api.session.user.model.User
|
||||
import reactivecircus.flowbinding.android.widget.checkedChanges
|
||||
import reactivecircus.flowbinding.android.widget.textChanges
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -83,21 +87,21 @@ class ContactsBookFragment @Inject constructor(
|
|||
|
||||
private fun setupOnlyBoundContactsView() {
|
||||
views.phoneBookOnlyBoundContacts.checkedChanges()
|
||||
.subscribe {
|
||||
.onEach {
|
||||
contactsBookViewModel.handle(ContactsBookAction.OnlyBoundContacts(it))
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
}
|
||||
|
||||
private fun setupFilterView() {
|
||||
views.phoneBookFilter
|
||||
.textChanges()
|
||||
.skipInitialValue()
|
||||
.debounce(300, TimeUnit.MILLISECONDS)
|
||||
.subscribe {
|
||||
.debounce(300)
|
||||
.onEach {
|
||||
contactsBookViewModel.handle(ContactsBookAction.FilterWith(it.toString()))
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
|
|
|
@ -22,16 +22,20 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.airbnb.mvrx.activityViewModel
|
||||
import com.jakewharton.rxbinding3.widget.editorActionEvents
|
||||
import com.jakewharton.rxbinding3.widget.textChanges
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.registerStartForActivityResult
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.core.utils.startImportTextFromFileIntent
|
||||
import im.vector.app.databinding.FragmentSsssAccessFromKeyBinding
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.sample
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import reactivecircus.flowbinding.android.widget.editorActionEvents
|
||||
import reactivecircus.flowbinding.android.widget.textChanges
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -48,22 +52,21 @@ class SharedSecuredStorageKeyFragment @Inject constructor() : VectorBaseFragment
|
|||
views.ssssRestoreWithKeyText.text = getString(R.string.enter_secret_storage_input_key)
|
||||
|
||||
views.ssssKeyEnterEdittext.editorActionEvents()
|
||||
.throttleFirst(300, TimeUnit.MILLISECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe {
|
||||
.sample(300)
|
||||
.onEach {
|
||||
if (it.actionId == EditorInfo.IME_ACTION_DONE) {
|
||||
submit()
|
||||
}
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
|
||||
views.ssssKeyEnterEdittext.textChanges()
|
||||
.skipInitialValue()
|
||||
.subscribe {
|
||||
.onEach {
|
||||
views.ssssKeyEnterTil.error = null
|
||||
views.ssssKeySubmit.isEnabled = it.isNotBlank()
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
|
||||
views.ssssKeyUseFile.debouncedClicks { startImportTextFromFileIntent(requireContext(), importFileStartForActivityResult) }
|
||||
|
||||
|
|
|
@ -22,14 +22,18 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import androidx.core.text.toSpannable
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.airbnb.mvrx.activityViewModel
|
||||
import com.jakewharton.rxbinding3.widget.editorActionEvents
|
||||
import com.jakewharton.rxbinding3.widget.textChanges
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.core.resources.ColorProvider
|
||||
import im.vector.app.databinding.FragmentSsssAccessFromPassphraseBinding
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.sample
|
||||
import reactivecircus.flowbinding.android.widget.editorActionEvents
|
||||
import reactivecircus.flowbinding.android.widget.textChanges
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -60,21 +64,20 @@ class SharedSecuredStoragePassphraseFragment @Inject constructor(
|
|||
// .colorizeMatchingText(key, colorProvider.getColorFromAttribute(android.R.attr.textColorLink))
|
||||
|
||||
views.ssssPassphraseEnterEdittext.editorActionEvents()
|
||||
.throttleFirst(300, TimeUnit.MILLISECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe {
|
||||
.sample(300)
|
||||
.onEach {
|
||||
if (it.actionId == EditorInfo.IME_ACTION_DONE) {
|
||||
submit()
|
||||
}
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
|
||||
views.ssssPassphraseEnterEdittext.textChanges()
|
||||
.subscribe {
|
||||
.onEach {
|
||||
views.ssssPassphraseEnterTil.error = null
|
||||
views.ssssPassphraseSubmit.isEnabled = it.isNotBlank()
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
|
||||
views.ssssPassphraseReset.views.bottomSheetActionClickableZone.debouncedClicks {
|
||||
sharedViewModel.handle(SharedSecureStorageAction.ForgotResetAll)
|
||||
|
|
|
@ -22,15 +22,19 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import androidx.core.view.isGone
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.airbnb.mvrx.parentFragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import com.jakewharton.rxbinding3.widget.editorActionEvents
|
||||
import com.jakewharton.rxbinding3.widget.textChanges
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.hideKeyboard
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.databinding.FragmentBootstrapEnterPassphraseBinding
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.sample
|
||||
import reactivecircus.flowbinding.android.widget.editorActionEvents
|
||||
import reactivecircus.flowbinding.android.widget.textChanges
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -58,21 +62,20 @@ class BootstrapConfirmPassphraseFragment @Inject constructor() :
|
|||
}
|
||||
|
||||
views.ssssPassphraseEnterEdittext.editorActionEvents()
|
||||
.throttleFirst(300, TimeUnit.MILLISECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe {
|
||||
.sample(300)
|
||||
.onEach {
|
||||
if (it.actionId == EditorInfo.IME_ACTION_DONE) {
|
||||
submit()
|
||||
}
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
|
||||
views.ssssPassphraseEnterEdittext.textChanges()
|
||||
.subscribe {
|
||||
.onEach {
|
||||
views.ssssPassphraseEnterTil.error = null
|
||||
sharedViewModel.handle(BootstrapActions.UpdateConfirmCandidatePassphrase(it?.toString() ?: ""))
|
||||
sharedViewModel.handle(BootstrapActions.UpdateConfirmCandidatePassphrase(it.toString()))
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
|
||||
sharedViewModel.observeViewEvents {
|
||||
// when (it) {
|
||||
|
|
|
@ -21,15 +21,19 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.airbnb.mvrx.parentFragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import com.jakewharton.rxbinding3.widget.editorActionEvents
|
||||
import com.jakewharton.rxbinding3.widget.textChanges
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.databinding.FragmentBootstrapEnterPassphraseBinding
|
||||
import im.vector.app.features.settings.VectorLocale
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.sample
|
||||
import reactivecircus.flowbinding.android.widget.editorActionEvents
|
||||
import reactivecircus.flowbinding.android.widget.textChanges
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -53,22 +57,21 @@ class BootstrapEnterPassphraseFragment @Inject constructor() :
|
|||
views.ssssPassphraseEnterEdittext.setText(it.passphrase ?: "")
|
||||
}
|
||||
views.ssssPassphraseEnterEdittext.editorActionEvents()
|
||||
.throttleFirst(300, TimeUnit.MILLISECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe {
|
||||
.sample(300)
|
||||
.onEach {
|
||||
if (it.actionId == EditorInfo.IME_ACTION_DONE) {
|
||||
submit()
|
||||
}
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
|
||||
views.ssssPassphraseEnterEdittext.textChanges()
|
||||
.subscribe {
|
||||
.onEach {
|
||||
// ssss_passphrase_enter_til.error = null
|
||||
sharedViewModel.handle(BootstrapActions.UpdateCandidatePassphrase(it?.toString() ?: ""))
|
||||
sharedViewModel.handle(BootstrapActions.UpdateCandidatePassphrase(it.toString()))
|
||||
// ssss_passphrase_submit.isEnabled = it.isNotBlank()
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
|
||||
sharedViewModel.observeViewEvents {
|
||||
// when (it) {
|
||||
|
|
|
@ -27,10 +27,9 @@ import android.view.ViewGroup
|
|||
import android.view.inputmethod.EditorInfo
|
||||
import androidx.core.text.toSpannable
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.airbnb.mvrx.parentFragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import com.jakewharton.rxbinding3.widget.editorActionEvents
|
||||
import com.jakewharton.rxbinding3.widget.textChanges
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.hideKeyboard
|
||||
import im.vector.app.core.extensions.registerStartForActivityResult
|
||||
|
@ -40,8 +39,13 @@ import im.vector.app.core.utils.colorizeMatchingText
|
|||
import im.vector.app.core.utils.startImportTextFromFileIntent
|
||||
import im.vector.app.databinding.FragmentBootstrapMigrateBackupBinding
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.sample
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.util.isValidRecoveryKey
|
||||
import reactivecircus.flowbinding.android.widget.editorActionEvents
|
||||
import reactivecircus.flowbinding.android.widget.textChanges
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -63,22 +67,21 @@ class BootstrapMigrateBackupFragment @Inject constructor(
|
|||
views.bootstrapMigrateEditText.setText(it.passphrase ?: "")
|
||||
}
|
||||
views.bootstrapMigrateEditText.editorActionEvents()
|
||||
.throttleFirst(300, TimeUnit.MILLISECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe {
|
||||
.sample(300)
|
||||
.onEach {
|
||||
if (it.actionId == EditorInfo.IME_ACTION_DONE) {
|
||||
submit()
|
||||
}
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
|
||||
views.bootstrapMigrateEditText.textChanges()
|
||||
.skipInitialValue()
|
||||
.subscribe {
|
||||
.onEach {
|
||||
views.bootstrapRecoveryKeyEnterTil.error = null
|
||||
// sharedViewModel.handle(BootstrapActions.UpdateCandidatePassphrase(it?.toString() ?: ""))
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
|
||||
// sharedViewModel.observeViewEvents {}
|
||||
views.bootstrapMigrateContinueButton.debouncedClicks { submit() }
|
||||
|
|
|
@ -20,12 +20,15 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.airbnb.mvrx.activityViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import com.jakewharton.rxbinding3.widget.textChanges
|
||||
import im.vector.app.core.extensions.hideKeyboard
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.databinding.FragmentDevtoolsEditorBinding
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import reactivecircus.flowbinding.android.widget.textChanges
|
||||
import javax.inject.Inject
|
||||
|
||||
class RoomDevToolEditFragment @Inject constructor() :
|
||||
|
@ -44,10 +47,10 @@ class RoomDevToolEditFragment @Inject constructor() :
|
|||
}
|
||||
views.editText.textChanges()
|
||||
.skipInitialValue()
|
||||
.subscribe {
|
||||
.onEach {
|
||||
sharedViewModel.handle(RoomDevToolAction.UpdateContentText(it.toString()))
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
|
|
|
@ -24,10 +24,10 @@ import android.view.inputmethod.EditorInfo
|
|||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.text.toSpannable
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.airbnb.mvrx.fragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.jakewharton.rxbinding3.widget.textChanges
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.extensions.registerStartForActivityResult
|
||||
|
@ -37,7 +37,10 @@ import im.vector.app.core.resources.ColorProvider
|
|||
import im.vector.app.core.utils.colorizeMatchingText
|
||||
import im.vector.app.databinding.FragmentSetIdentityServerBinding
|
||||
import im.vector.app.features.discovery.DiscoverySharedViewModel
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import org.matrix.android.sdk.api.session.terms.TermsService
|
||||
import reactivecircus.flowbinding.android.widget.textChanges
|
||||
import javax.inject.Inject
|
||||
|
||||
class SetIdentityServerFragment @Inject constructor(
|
||||
|
@ -90,11 +93,11 @@ class SetIdentityServerFragment @Inject constructor(
|
|||
|
||||
views.identityServerSetDefaultAlternativeTextInput
|
||||
.textChanges()
|
||||
.subscribe {
|
||||
.onEach {
|
||||
views.identityServerSetDefaultAlternativeTil.error = null
|
||||
views.identityServerSetDefaultAlternativeSubmit.isEnabled = it.isNotEmpty()
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
|
||||
views.identityServerSetDefaultSubmit.debouncedClicks {
|
||||
viewModel.handle(SetIdentityServerAction.UseDefaultIdentityServer)
|
||||
|
|
|
@ -36,7 +36,6 @@ 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 io.reactivex.schedulers.Schedulers
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
|
|
|
@ -66,8 +66,6 @@ import com.airbnb.mvrx.args
|
|||
import com.airbnb.mvrx.fragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.jakewharton.rxbinding3.view.focusChanges
|
||||
import com.jakewharton.rxbinding3.widget.textChanges
|
||||
import com.vanniktech.emoji.EmojiPopup
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.dialogs.ConfirmationDialogBuilder
|
||||
|
@ -185,7 +183,9 @@ import im.vector.app.features.widgets.WidgetArgs
|
|||
import im.vector.app.features.widgets.WidgetKind
|
||||
import im.vector.app.features.widgets.permissions.RoomWidgetPermissionBottomSheet
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.sample
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import nl.dionsegijn.konfetti.models.Shape
|
||||
|
@ -217,6 +217,8 @@ import org.matrix.android.sdk.api.util.MimeTypes
|
|||
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||
import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent
|
||||
import org.matrix.android.sdk.internal.crypto.model.event.WithHeldCode
|
||||
import reactivecircus.flowbinding.android.view.focusChanges
|
||||
import reactivecircus.flowbinding.android.widget.textChanges
|
||||
import timber.log.Timber
|
||||
import java.net.URL
|
||||
import java.util.UUID
|
||||
|
@ -1349,19 +1351,19 @@ class RoomDetailFragment @Inject constructor(
|
|||
private fun observerUserTyping() {
|
||||
views.composerLayout.views.composerEditText.textChanges()
|
||||
.skipInitialValue()
|
||||
.debounce(300, TimeUnit.MILLISECONDS)
|
||||
.sample(300)
|
||||
.map { it.isNotEmpty() }
|
||||
.subscribe {
|
||||
.onEach {
|
||||
Timber.d("Typing: User is typing: $it")
|
||||
textComposerViewModel.handle(TextComposerAction.UserIsTyping(it))
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
|
||||
views.composerLayout.views.composerEditText.focusChanges()
|
||||
.subscribe {
|
||||
.onEach {
|
||||
roomDetailViewModel.handle(RoomDetailAction.ComposerFocusChange(it))
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
}
|
||||
|
||||
private fun sendUri(uri: Uri): Boolean {
|
||||
|
|
|
@ -31,10 +31,8 @@ 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.home.room.detail.timeline.action.TimelineEventFragmentArgs
|
||||
import io.reactivex.Observable
|
||||
import kotlinx.coroutines.flow.map
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.flow.FlowRoom
|
||||
import org.matrix.android.sdk.flow.flow
|
||||
import org.matrix.android.sdk.flow.unwrap
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
package im.vector.app.features.home.room.list
|
||||
|
||||
import im.vector.app.features.home.RoomListDisplayMode
|
||||
import io.reactivex.functions.Predicate
|
||||
import androidx.core.util.Predicate
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
package im.vector.app.features.home.room.list
|
||||
|
||||
import io.reactivex.functions.Predicate
|
||||
import androidx.core.util.Predicate
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import javax.inject.Inject
|
||||
|
||||
|
|
|
@ -30,12 +30,8 @@ import im.vector.app.features.home.RoomListDisplayMode
|
|||
import im.vector.app.features.invite.AutoAcceptInvites
|
||||
import im.vector.app.features.invite.showInvites
|
||||
import im.vector.app.space
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
|
|
|
@ -18,7 +18,6 @@ package im.vector.app.features.invite
|
|||
|
||||
import im.vector.app.ActiveSessionDataSource
|
||||
import im.vector.app.features.session.coroutineScope
|
||||
import io.reactivex.disposables.Disposable
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
|
|
|
@ -25,21 +25,24 @@ import android.view.inputmethod.EditorInfo
|
|||
import androidx.autofill.HintConstants
|
||||
import androidx.core.text.isDigitsOnly
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.Success
|
||||
import com.jakewharton.rxbinding3.widget.textChanges
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.extensions.hideKeyboard
|
||||
import im.vector.app.core.extensions.hidePassword
|
||||
import im.vector.app.core.extensions.toReducedUrl
|
||||
import im.vector.app.databinding.FragmentLoginBinding
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.rxkotlin.subscribeBy
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import org.matrix.android.sdk.api.failure.Failure
|
||||
import org.matrix.android.sdk.api.failure.MatrixError
|
||||
import org.matrix.android.sdk.api.failure.isInvalidPassword
|
||||
import reactivecircus.flowbinding.android.widget.textChanges
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
|
@ -224,20 +227,18 @@ class LoginFragment @Inject constructor() : AbstractSSOLoginFragment<FragmentLog
|
|||
|
||||
private fun setupSubmitButton() {
|
||||
views.loginSubmit.setOnClickListener { submit() }
|
||||
Observable
|
||||
.combineLatest(
|
||||
combine(
|
||||
views.loginField.textChanges().map { it.trim().isNotEmpty() },
|
||||
views.passwordField.textChanges().map { it.isNotEmpty() },
|
||||
{ isLoginNotEmpty, isPasswordNotEmpty ->
|
||||
views.passwordField.textChanges().map { it.isNotEmpty() }
|
||||
) { isLoginNotEmpty, isPasswordNotEmpty ->
|
||||
isLoginNotEmpty && isPasswordNotEmpty
|
||||
}
|
||||
)
|
||||
.subscribeBy {
|
||||
.onEach {
|
||||
views.loginFieldTil.error = null
|
||||
views.passwordFieldTil.error = null
|
||||
views.loginSubmit.isEnabled = it
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
}
|
||||
|
||||
private fun forgetPasswordClicked() {
|
||||
|
|
|
@ -25,19 +25,22 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import androidx.autofill.HintConstants
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.airbnb.mvrx.args
|
||||
import com.google.i18n.phonenumbers.NumberParseException
|
||||
import com.google.i18n.phonenumbers.PhoneNumberUtil
|
||||
import com.jakewharton.rxbinding3.widget.textChanges
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.hideKeyboard
|
||||
import im.vector.app.core.extensions.isEmail
|
||||
import im.vector.app.core.extensions.setTextOrHide
|
||||
import im.vector.app.databinding.FragmentLoginGenericTextInputFormBinding
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import org.matrix.android.sdk.api.auth.registration.RegisterThreePid
|
||||
import org.matrix.android.sdk.api.failure.Failure
|
||||
import org.matrix.android.sdk.api.failure.is401
|
||||
import reactivecircus.flowbinding.android.widget.textChanges
|
||||
import javax.inject.Inject
|
||||
|
||||
enum class TextInputFormFragmentMode {
|
||||
|
@ -93,10 +96,10 @@ class LoginGenericTextInputFormFragment @Inject constructor() : AbstractLoginFra
|
|||
|
||||
private fun setupTil() {
|
||||
views.loginGenericTextInputFormTextInput.textChanges()
|
||||
.subscribe {
|
||||
.onEach {
|
||||
views.loginGenericTextInputFormTil.error = null
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
}
|
||||
|
||||
private fun setupUi() {
|
||||
|
@ -195,10 +198,10 @@ class LoginGenericTextInputFormFragment @Inject constructor() : AbstractLoginFra
|
|||
private fun setupSubmitButton() {
|
||||
views.loginGenericTextInputFormSubmit.isEnabled = false
|
||||
views.loginGenericTextInputFormTextInput.textChanges()
|
||||
.subscribe {
|
||||
.onEach {
|
||||
views.loginGenericTextInputFormSubmit.isEnabled = isInputValid(it)
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
}
|
||||
|
||||
private fun isInputValid(input: CharSequence): Boolean {
|
||||
|
|
|
@ -20,19 +20,22 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.Success
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.jakewharton.rxbinding3.widget.textChanges
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.hideKeyboard
|
||||
import im.vector.app.core.extensions.hidePassword
|
||||
import im.vector.app.core.extensions.isEmail
|
||||
import im.vector.app.core.extensions.toReducedUrl
|
||||
import im.vector.app.databinding.FragmentLoginResetPasswordBinding
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.rxkotlin.subscribeBy
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import reactivecircus.flowbinding.android.widget.textChanges
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
|
@ -59,21 +62,18 @@ class LoginResetPasswordFragment @Inject constructor() : AbstractLoginFragment<F
|
|||
|
||||
private fun setupSubmitButton() {
|
||||
views.resetPasswordSubmit.setOnClickListener { submit() }
|
||||
|
||||
Observable
|
||||
.combineLatest(
|
||||
combine(
|
||||
views.resetPasswordEmail.textChanges().map { it.isEmail() },
|
||||
views.passwordField.textChanges().map { it.isNotEmpty() },
|
||||
{ isEmail, isPasswordNotEmpty ->
|
||||
views.passwordField.textChanges().map { it.isNotEmpty() }
|
||||
) { isEmail, isPasswordNotEmpty ->
|
||||
isEmail && isPasswordNotEmpty
|
||||
}
|
||||
)
|
||||
.subscribeBy {
|
||||
.onEach {
|
||||
views.resetPasswordEmailTil.error = null
|
||||
views.passwordFieldTil.error = null
|
||||
views.resetPasswordSubmit.isEnabled = it
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
}
|
||||
|
||||
private fun submit() {
|
||||
|
|
|
@ -25,15 +25,18 @@ import android.view.inputmethod.EditorInfo
|
|||
import android.widget.ArrayAdapter
|
||||
import androidx.core.view.isInvisible
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import com.jakewharton.rxbinding3.widget.textChanges
|
||||
import im.vector.app.BuildConfig
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.hideKeyboard
|
||||
import im.vector.app.core.utils.ensureProtocol
|
||||
import im.vector.app.core.utils.openUrlInChromeCustomTab
|
||||
import im.vector.app.databinding.FragmentLoginServerUrlFormBinding
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import org.matrix.android.sdk.api.failure.Failure
|
||||
import reactivecircus.flowbinding.android.widget.textChanges
|
||||
import java.net.UnknownHostException
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -61,11 +64,11 @@ class LoginServerUrlFormFragment @Inject constructor() : AbstractLoginFragment<F
|
|||
|
||||
private fun setupHomeServerField() {
|
||||
views.loginServerUrlFormHomeServerUrl.textChanges()
|
||||
.subscribe {
|
||||
.onEach {
|
||||
views.loginServerUrlFormHomeServerUrlTil.error = null
|
||||
views.loginServerUrlFormSubmit.isEnabled = it.isNotBlank()
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
|
||||
views.loginServerUrlFormHomeServerUrl.setOnEditorActionListener { _, actionId, _ ->
|
||||
if (actionId == EditorInfo.IME_ACTION_DONE) {
|
||||
|
|
|
@ -24,17 +24,20 @@ import android.view.ViewGroup
|
|||
import android.view.inputmethod.EditorInfo
|
||||
import androidx.autofill.HintConstants
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.airbnb.mvrx.Fail
|
||||
import com.jakewharton.rxbinding3.widget.textChanges
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.hideKeyboard
|
||||
import im.vector.app.core.extensions.hidePassword
|
||||
import im.vector.app.databinding.FragmentLoginSigninPassword2Binding
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
import io.reactivex.rxkotlin.subscribeBy
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import org.matrix.android.sdk.api.auth.login.LoginProfileInfo
|
||||
import org.matrix.android.sdk.api.failure.Failure
|
||||
import org.matrix.android.sdk.api.failure.isInvalidPassword
|
||||
import reactivecircus.flowbinding.android.widget.textChanges
|
||||
import javax.inject.Inject
|
||||
import javax.net.ssl.HttpsURLConnection
|
||||
|
||||
|
@ -121,11 +124,11 @@ class LoginFragmentSigninPassword2 @Inject constructor(
|
|||
views.passwordField
|
||||
.textChanges()
|
||||
.map { it.isNotEmpty() }
|
||||
.subscribeBy {
|
||||
.onEach {
|
||||
views.passwordFieldTil.error = null
|
||||
views.loginSubmit.isEnabled = it
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
}
|
||||
|
||||
private fun forgetPasswordClicked() {
|
||||
|
|
|
@ -22,13 +22,16 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.autofill.HintConstants
|
||||
import com.jakewharton.rxbinding3.widget.textChanges
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.hideKeyboard
|
||||
import im.vector.app.databinding.FragmentLoginSigninUsername2Binding
|
||||
import io.reactivex.rxkotlin.subscribeBy
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import org.matrix.android.sdk.api.failure.Failure
|
||||
import org.matrix.android.sdk.api.failure.MatrixError
|
||||
import reactivecircus.flowbinding.android.widget.textChanges
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
|
@ -83,11 +86,11 @@ class LoginFragmentSigninUsername2 @Inject constructor() : AbstractLoginFragment
|
|||
views.loginSubmit.setOnClickListener { submit() }
|
||||
views.loginField.textChanges()
|
||||
.map { it.trim().isNotEmpty() }
|
||||
.subscribeBy {
|
||||
.onEach {
|
||||
views.loginFieldTil.error = null
|
||||
views.loginSubmit.isEnabled = it
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
}
|
||||
|
||||
override fun resetViewModel() {
|
||||
|
|
|
@ -23,12 +23,14 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import androidx.autofill.HintConstants
|
||||
import com.jakewharton.rxbinding3.widget.textChanges
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.hideKeyboard
|
||||
import im.vector.app.core.extensions.hidePassword
|
||||
import im.vector.app.databinding.FragmentLoginSignupPassword2Binding
|
||||
import io.reactivex.rxkotlin.subscribeBy
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import reactivecircus.flowbinding.android.widget.textChanges
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
|
@ -87,11 +89,11 @@ class LoginFragmentSignupPassword2 @Inject constructor() : AbstractLoginFragment
|
|||
private fun setupSubmitButton() {
|
||||
views.loginSubmit.setOnClickListener { submit() }
|
||||
views.passwordField.textChanges()
|
||||
.subscribeBy { password ->
|
||||
.onEach { password ->
|
||||
views.passwordFieldTil.error = null
|
||||
views.loginSubmit.isEnabled = password.isNotEmpty()
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
}
|
||||
|
||||
override fun resetViewModel() {
|
||||
|
|
|
@ -24,14 +24,17 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import androidx.autofill.HintConstants
|
||||
import androidx.core.view.isVisible
|
||||
import com.jakewharton.rxbinding3.widget.textChanges
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.hideKeyboard
|
||||
import im.vector.app.core.extensions.toReducedUrl
|
||||
import im.vector.app.databinding.FragmentLoginSignupUsername2Binding
|
||||
import im.vector.app.features.login.LoginMode
|
||||
import im.vector.app.features.login.SocialLoginButtonsView
|
||||
import io.reactivex.rxkotlin.subscribeBy
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import reactivecircus.flowbinding.android.widget.textChanges
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
|
@ -111,12 +114,12 @@ class LoginFragmentSignupUsername2 @Inject constructor() : AbstractSSOLoginFragm
|
|||
views.loginSubmit.setOnClickListener { submit() }
|
||||
views.loginField.textChanges()
|
||||
.map { it.trim() }
|
||||
.subscribeBy { text ->
|
||||
.onEach { text ->
|
||||
val isNotEmpty = text.isNotEmpty()
|
||||
views.loginFieldTil.error = null
|
||||
views.loginSubmit.isEnabled = isNotEmpty
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
}
|
||||
|
||||
override fun resetViewModel() {
|
||||
|
|
|
@ -24,7 +24,7 @@ import android.view.ViewGroup
|
|||
import android.view.inputmethod.EditorInfo
|
||||
import androidx.autofill.HintConstants
|
||||
import androidx.core.view.isVisible
|
||||
import com.jakewharton.rxbinding3.widget.textChanges
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.hideKeyboard
|
||||
import im.vector.app.core.extensions.hidePassword
|
||||
|
@ -32,11 +32,14 @@ import im.vector.app.core.extensions.toReducedUrl
|
|||
import im.vector.app.databinding.FragmentLoginSigninToAny2Binding
|
||||
import im.vector.app.features.login.LoginMode
|
||||
import im.vector.app.features.login.SocialLoginButtonsView
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.rxkotlin.subscribeBy
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import org.matrix.android.sdk.api.failure.Failure
|
||||
import org.matrix.android.sdk.api.failure.MatrixError
|
||||
import org.matrix.android.sdk.api.failure.isInvalidPassword
|
||||
import reactivecircus.flowbinding.android.widget.textChanges
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
|
@ -136,20 +139,18 @@ class LoginFragmentToAny2 @Inject constructor() : AbstractSSOLoginFragment2<Frag
|
|||
|
||||
private fun setupSubmitButton() {
|
||||
views.loginSubmit.setOnClickListener { submit() }
|
||||
Observable
|
||||
.combineLatest(
|
||||
combine(
|
||||
views.loginField.textChanges().map { it.trim().isNotEmpty() },
|
||||
views.passwordField.textChanges().map { it.isNotEmpty() },
|
||||
{ isLoginNotEmpty, isPasswordNotEmpty ->
|
||||
views.passwordField.textChanges().map { it.isNotEmpty() }
|
||||
) { isLoginNotEmpty, isPasswordNotEmpty ->
|
||||
isLoginNotEmpty && isPasswordNotEmpty
|
||||
}
|
||||
)
|
||||
.subscribeBy {
|
||||
.onEach {
|
||||
views.loginFieldTil.error = null
|
||||
views.passwordFieldTil.error = null
|
||||
views.loginSubmit.isEnabled = it
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
}
|
||||
|
||||
private fun forgetPasswordClicked() {
|
||||
|
|
|
@ -24,10 +24,10 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import androidx.autofill.HintConstants
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.airbnb.mvrx.args
|
||||
import com.google.i18n.phonenumbers.NumberParseException
|
||||
import com.google.i18n.phonenumbers.PhoneNumberUtil
|
||||
import com.jakewharton.rxbinding3.widget.textChanges
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.hideKeyboard
|
||||
import im.vector.app.core.extensions.isEmail
|
||||
|
@ -36,9 +36,12 @@ import im.vector.app.core.extensions.toReducedUrl
|
|||
import im.vector.app.databinding.FragmentLoginGenericTextInputForm2Binding
|
||||
import im.vector.app.features.login.LoginGenericTextInputFormFragmentArgument
|
||||
import im.vector.app.features.login.TextInputFormFragmentMode
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import org.matrix.android.sdk.api.auth.registration.RegisterThreePid
|
||||
import org.matrix.android.sdk.api.failure.Failure
|
||||
import org.matrix.android.sdk.api.failure.is401
|
||||
import reactivecircus.flowbinding.android.widget.textChanges
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
|
@ -82,10 +85,10 @@ class LoginGenericTextInputFormFragment2 @Inject constructor() : AbstractLoginFr
|
|||
|
||||
private fun setupTil() {
|
||||
views.loginGenericTextInputFormTextInput.textChanges()
|
||||
.subscribe {
|
||||
.onEach {
|
||||
views.loginGenericTextInputFormTil.error = null
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
}
|
||||
|
||||
private fun setupUi() {
|
||||
|
@ -189,11 +192,11 @@ class LoginGenericTextInputFormFragment2 @Inject constructor() : AbstractLoginFr
|
|||
private fun setupSubmitButton() {
|
||||
views.loginGenericTextInputFormSubmit.isEnabled = false
|
||||
views.loginGenericTextInputFormTextInput.textChanges()
|
||||
.subscribe { text ->
|
||||
.onEach { text ->
|
||||
views.loginGenericTextInputFormSubmit.isEnabled = isInputValid(text)
|
||||
text?.let { updateSubmitButtons(it) }
|
||||
updateSubmitButtons(text)
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
}
|
||||
|
||||
private fun updateSubmitButtons(text: CharSequence) {
|
||||
|
|
|
@ -23,8 +23,8 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import androidx.autofill.HintConstants
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.jakewharton.rxbinding3.widget.textChanges
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.hideKeyboard
|
||||
import im.vector.app.core.extensions.hidePassword
|
||||
|
@ -32,8 +32,11 @@ import im.vector.app.core.extensions.isEmail
|
|||
import im.vector.app.core.extensions.toReducedUrl
|
||||
import im.vector.app.core.utils.autoResetTextInputLayoutErrors
|
||||
import im.vector.app.databinding.FragmentLoginResetPassword2Binding
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.rxkotlin.subscribeBy
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import reactivecircus.flowbinding.android.widget.textChanges
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
|
@ -78,19 +81,16 @@ class LoginResetPasswordFragment2 @Inject constructor() : AbstractLoginFragment2
|
|||
|
||||
private fun setupSubmitButton() {
|
||||
views.resetPasswordSubmit.setOnClickListener { submit() }
|
||||
|
||||
Observable
|
||||
.combineLatest(
|
||||
combine(
|
||||
views.resetPasswordEmail.textChanges().map { it.isEmail() },
|
||||
views.passwordField.textChanges().map { it.isNotEmpty() },
|
||||
{ isEmail, isPasswordNotEmpty ->
|
||||
views.passwordField.textChanges().map { it.isNotEmpty() }
|
||||
) { isEmail, isPasswordNotEmpty ->
|
||||
isEmail && isPasswordNotEmpty
|
||||
}
|
||||
)
|
||||
.subscribeBy {
|
||||
.onEach {
|
||||
views.resetPasswordSubmit.isEnabled = it
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
}
|
||||
|
||||
private fun submit() {
|
||||
|
|
|
@ -24,15 +24,18 @@ import android.view.ViewGroup
|
|||
import android.view.inputmethod.EditorInfo
|
||||
import android.widget.ArrayAdapter
|
||||
import androidx.core.view.isInvisible
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import com.jakewharton.rxbinding3.widget.textChanges
|
||||
import im.vector.app.BuildConfig
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.hideKeyboard
|
||||
import im.vector.app.core.utils.ensureProtocol
|
||||
import im.vector.app.databinding.FragmentLoginServerUrlForm2Binding
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import org.matrix.android.sdk.api.failure.Failure
|
||||
import org.matrix.android.sdk.api.failure.MatrixError
|
||||
import reactivecircus.flowbinding.android.widget.textChanges
|
||||
import java.net.UnknownHostException
|
||||
import javax.inject.Inject
|
||||
import javax.net.ssl.HttpsURLConnection
|
||||
|
@ -60,11 +63,11 @@ class LoginServerUrlFormFragment2 @Inject constructor() : AbstractLoginFragment2
|
|||
|
||||
private fun setupHomeServerField() {
|
||||
views.loginServerUrlFormHomeServerUrl.textChanges()
|
||||
.subscribe {
|
||||
.onEach {
|
||||
views.loginServerUrlFormHomeServerUrlTil.error = null
|
||||
views.loginServerUrlFormSubmit.isEnabled = it.isNotBlank()
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
|
||||
views.loginServerUrlFormHomeServerUrl.setOnEditorActionListener { _, actionId, _ ->
|
||||
if (actionId == EditorInfo.IME_ACTION_DONE) {
|
||||
|
|
|
@ -28,7 +28,6 @@ import androidx.core.view.isVisible
|
|||
import androidx.lifecycle.lifecycleScope
|
||||
import com.airbnb.mvrx.viewModel
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.jakewharton.rxbinding3.widget.queryTextChanges
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import im.vector.app.EmojiCompatFontProvider
|
||||
import im.vector.app.R
|
||||
|
@ -37,7 +36,11 @@ import im.vector.app.core.platform.VectorBaseActivity
|
|||
import im.vector.app.databinding.ActivityEmojiReactionPickerBinding
|
||||
import im.vector.app.features.reactions.data.EmojiDataSource
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.sample
|
||||
import kotlinx.coroutines.launch
|
||||
import reactivecircus.flowbinding.android.widget.queryTextChanges
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
@ -167,13 +170,11 @@ class EmojiReactionPickerActivity : VectorBaseActivity<ActivityEmojiReactionPick
|
|||
}
|
||||
|
||||
searchView.queryTextChanges()
|
||||
.throttleWithTimeout(600, TimeUnit.MILLISECONDS)
|
||||
.doOnError { err -> Timber.e(err) }
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe { query ->
|
||||
.sample(600)
|
||||
.onEach { query ->
|
||||
onQueryText(query.toString())
|
||||
}
|
||||
.disposeOnDestroy()
|
||||
.launchIn(lifecycleScope)
|
||||
}
|
||||
searchItem.expandActionView()
|
||||
return true
|
||||
|
|
|
@ -25,7 +25,6 @@ import android.view.ViewGroup
|
|||
import androidx.lifecycle.lifecycleScope
|
||||
import com.airbnb.mvrx.activityViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import com.jakewharton.rxbinding3.appcompat.queryTextChanges
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.cleanup
|
||||
import im.vector.app.core.extensions.configureWith
|
||||
|
@ -37,10 +36,13 @@ import im.vector.app.core.utils.toast
|
|||
import im.vector.app.databinding.FragmentPublicRoomsBinding
|
||||
import im.vector.app.features.permalink.NavigationInterceptor
|
||||
import im.vector.app.features.permalink.PermalinkHandler
|
||||
import io.reactivex.rxkotlin.subscribeBy
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoom
|
||||
import reactivecircus.flowbinding.appcompat.queryTextChanges
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
@ -79,11 +81,11 @@ class PublicRoomsFragment @Inject constructor(
|
|||
setupRecyclerView()
|
||||
|
||||
views.publicRoomsFilter.queryTextChanges()
|
||||
.debounce(500, TimeUnit.MILLISECONDS)
|
||||
.subscribeBy {
|
||||
.debounce(500)
|
||||
.onEach {
|
||||
viewModel.handle(RoomDirectoryAction.FilterWith(it.toString()))
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
|
||||
views.publicRoomsCreateNewRoom.debouncedClicks {
|
||||
sharedActionViewModel.post(RoomDirectorySharedAction.CreateRoom)
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
package im.vector.app.features.roomprofile.members
|
||||
|
||||
import io.reactivex.functions.Predicate
|
||||
import androidx.core.util.Predicate
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||
import javax.inject.Inject
|
||||
|
|
|
@ -40,6 +40,7 @@ import im.vector.app.features.home.room.detail.upgrade.MigrateRoomBottomSheet
|
|||
import im.vector.app.features.roomprofile.RoomProfileArgs
|
||||
import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedActions
|
||||
import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedEvents
|
||||
import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedFragment
|
||||
import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedState
|
||||
import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedViewModel
|
||||
import javax.inject.Inject
|
||||
|
|
|
@ -14,26 +14,26 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.roomprofile.settings.joinrule
|
||||
package im.vector.app.features.roomprofile.settings.joinrule.advanced
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.airbnb.mvrx.activityViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import com.jakewharton.rxbinding3.appcompat.queryTextChanges
|
||||
import im.vector.app.core.extensions.cleanup
|
||||
import im.vector.app.core.extensions.configureWith
|
||||
import im.vector.app.core.platform.OnBackPressed
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.databinding.FragmentSpaceRestrictedSelectBinding
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
import im.vector.app.features.roomprofile.settings.joinrule.advanced.ChooseRestrictedController
|
||||
import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedActions
|
||||
import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedViewModel
|
||||
import io.reactivex.rxkotlin.subscribeBy
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import org.matrix.android.sdk.api.util.MatrixItem
|
||||
import reactivecircus.flowbinding.appcompat.queryTextChanges
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -54,11 +54,11 @@ class RoomJoinRuleChooseRestrictedFragment @Inject constructor(
|
|||
controller.listener = this
|
||||
views.recyclerView.configureWith(controller)
|
||||
views.roomsFilter.queryTextChanges()
|
||||
.debounce(500, TimeUnit.MILLISECONDS)
|
||||
.subscribeBy {
|
||||
.debounce(500)
|
||||
.onEach {
|
||||
viewModel.handle(RoomJoinRuleChooseRestrictedActions.FilterWith(it.toString()))
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
|
||||
views.okButton.debouncedClicks {
|
||||
parentFragmentManager.popBackStack()
|
||||
|
|
|
@ -27,8 +27,6 @@ import im.vector.app.core.error.ErrorFormatter
|
|||
import im.vector.app.core.extensions.singletonEntryPoint
|
||||
import im.vector.app.core.platform.VectorBaseActivity
|
||||
import im.vector.app.core.utils.toast
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import io.reactivex.disposables.Disposable
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import timber.log.Timber
|
||||
|
||||
|
@ -67,31 +65,10 @@ abstract class VectorSettingsBaseFragment : PreferenceFragmentCompat() {
|
|||
mLoadingView = vectorActivity.findViewById(R.id.vector_settings_spinner_views)
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
override fun onDestroyView() {
|
||||
uiDisposables.clear()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
uiDisposables.dispose()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
abstract fun bindPref()
|
||||
|
||||
abstract var titleRes: Int
|
||||
|
||||
/* ==========================================================================================
|
||||
* Disposable
|
||||
* ========================================================================================== */
|
||||
|
||||
private val uiDisposables = CompositeDisposable()
|
||||
|
||||
protected fun Disposable.disposeOnDestroyView() {
|
||||
uiDisposables.add(this)
|
||||
}
|
||||
|
||||
/* ==========================================================================================
|
||||
* Protected
|
||||
* ========================================================================================== */
|
||||
|
|
|
@ -58,7 +58,6 @@ import im.vector.app.features.pin.PinMode
|
|||
import im.vector.app.features.raw.wellknown.getElementWellknown
|
||||
import im.vector.app.features.raw.wellknown.isE2EByDefault
|
||||
import im.vector.app.features.themes.ThemeUtils
|
||||
import io.reactivex.disposables.Disposable
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
|
@ -85,7 +84,6 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor(
|
|||
|
||||
override var titleRes = R.string.settings_security_and_privacy
|
||||
override val preferenceXmlRes = R.xml.vector_settings_security_privacy
|
||||
private var disposables = mutableListOf<Disposable>()
|
||||
|
||||
// cryptography
|
||||
private val mCryptographyCategory by lazy {
|
||||
|
@ -172,14 +170,6 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor(
|
|||
// findPreference<VectorPreference>(VectorPreferences.SETTINGS_SECURE_BACKUP_RESET_PREFERENCE_KEY)
|
||||
// }
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
disposables.forEach {
|
||||
it.dispose()
|
||||
}
|
||||
disposables.clear()
|
||||
}
|
||||
|
||||
private fun refresh4SSection(info: SecretsSynchronisationInfo) {
|
||||
// it's a lot of if / else if / else
|
||||
// But it's not yet clear how to manage all cases
|
||||
|
|
|
@ -34,7 +34,6 @@ 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 io.reactivex.subjects.PublishSubject
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
|
|
|
@ -26,12 +26,12 @@ import android.view.ViewGroup
|
|||
import androidx.core.text.toSpannable
|
||||
import androidx.core.view.isInvisible
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.args
|
||||
import com.airbnb.mvrx.parentFragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import com.jakewharton.rxbinding3.widget.checkedChanges
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.error.ErrorFormatter
|
||||
|
@ -44,9 +44,12 @@ import im.vector.app.databinding.BottomSheetLeaveSpaceBinding
|
|||
import im.vector.app.features.displayname.getBestName
|
||||
import im.vector.app.features.spaces.leave.SpaceLeaveAdvancedActivity
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import me.gujun.android.span.span
|
||||
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||
import reactivecircus.flowbinding.android.widget.checkedChanges
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
|
@ -82,8 +85,7 @@ class LeaveSpaceBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetLea
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
views.autoLeaveRadioGroup.checkedChanges()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe {
|
||||
.onEach {
|
||||
when (it) {
|
||||
views.leaveAll.id -> {
|
||||
settingsViewModel.handle(SpaceLeaveViewAction.SetAutoLeaveAll)
|
||||
|
@ -100,7 +102,7 @@ class LeaveSpaceBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetLea
|
|||
}
|
||||
}
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
|
||||
views.leaveButton.debouncedClicks {
|
||||
settingsViewModel.handle(SpaceLeaveViewAction.LeaveSpace)
|
||||
|
|
|
@ -27,7 +27,7 @@ import im.vector.app.core.epoxy.noResultItem
|
|||
import im.vector.app.core.resources.StringProvider
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
import im.vector.app.features.spaces.manage.roomSelectionItem
|
||||
import io.reactivex.functions.Predicate
|
||||
import androidx.core.util.Predicate
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||
|
|
|
@ -20,15 +20,18 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.airbnb.mvrx.activityViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import com.jakewharton.rxbinding3.appcompat.queryTextChanges
|
||||
import im.vector.app.core.extensions.cleanup
|
||||
import im.vector.app.core.extensions.configureWith
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.databinding.FragmentSpaceLeaveAdvancedBinding
|
||||
import io.reactivex.rxkotlin.subscribeBy
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import reactivecircus.flowbinding.appcompat.queryTextChanges
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -54,11 +57,11 @@ class SpaceLeaveAdvancedFragment @Inject constructor(
|
|||
}
|
||||
|
||||
views.publicRoomsFilter.queryTextChanges()
|
||||
.debounce(100, TimeUnit.MILLISECONDS)
|
||||
.subscribeBy {
|
||||
.debounce(100)
|
||||
.onEach {
|
||||
viewModel.handle(SpaceLeaveAdvanceViewAction.UpdateFilter(it.toString()))
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
|
|
|
@ -22,6 +22,7 @@ import android.view.Menu
|
|||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.ConcatAdapter
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.airbnb.mvrx.Loading
|
||||
|
@ -29,14 +30,16 @@ import com.airbnb.mvrx.activityViewModel
|
|||
import com.airbnb.mvrx.fragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.jakewharton.rxbinding3.appcompat.queryTextChanges
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.cleanup
|
||||
import im.vector.app.core.platform.OnBackPressed
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.databinding.FragmentSpaceAddRoomsBinding
|
||||
import io.reactivex.rxkotlin.subscribeBy
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import reactivecircus.flowbinding.appcompat.queryTextChanges
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -72,11 +75,11 @@ class SpaceAddRoomFragment @Inject constructor(
|
|||
setupRecyclerView()
|
||||
|
||||
views.publicRoomsFilter.queryTextChanges()
|
||||
.debounce(100, TimeUnit.MILLISECONDS)
|
||||
.subscribeBy {
|
||||
.debounce(100)
|
||||
.onEach {
|
||||
viewModel.handle(SpaceAddRoomActions.UpdateFilter(it.toString()))
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
|
||||
spaceEpoxyController.subHeaderText = getString(R.string.spaces_feeling_experimental_subspace)
|
||||
viewModel.selectionListLiveData.observe(viewLifecycleOwner) {
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
package im.vector.app.features.spaces.manage
|
||||
|
||||
import io.reactivex.functions.Predicate
|
||||
import androidx.core.util.Predicate
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo
|
||||
|
||||
|
|
|
@ -25,13 +25,13 @@ import android.view.ViewGroup
|
|||
import androidx.appcompat.view.ActionMode
|
||||
import androidx.appcompat.view.ActionMode.Callback
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.transition.TransitionManager
|
||||
import com.airbnb.epoxy.EpoxyVisibilityTracker
|
||||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.activityViewModel
|
||||
import com.airbnb.mvrx.fragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import com.jakewharton.rxbinding3.appcompat.queryTextChanges
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.cleanup
|
||||
import im.vector.app.core.extensions.configureWith
|
||||
|
@ -39,8 +39,11 @@ import im.vector.app.core.platform.OnBackPressed
|
|||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.core.utils.toast
|
||||
import im.vector.app.databinding.FragmentSpaceAddRoomsBinding
|
||||
import io.reactivex.rxkotlin.subscribeBy
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo
|
||||
import reactivecircus.flowbinding.appcompat.queryTextChanges
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -72,11 +75,11 @@ class SpaceManageRoomsFragment @Inject constructor(
|
|||
epoxyVisibilityTracker.attach(views.roomList)
|
||||
|
||||
views.publicRoomsFilter.queryTextChanges()
|
||||
.debounce(200, TimeUnit.MILLISECONDS)
|
||||
.subscribeBy {
|
||||
.debounce(200)
|
||||
.onEach {
|
||||
viewModel.handle(SpaceManageRoomViewAction.UpdateFilter(it.toString()))
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
|
||||
viewModel.onEach(SpaceManageRoomViewState::actionState) { actionState ->
|
||||
when (actionState) {
|
||||
|
|
|
@ -20,13 +20,13 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.Success
|
||||
import com.airbnb.mvrx.Uninitialized
|
||||
import com.airbnb.mvrx.fragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import com.jakewharton.rxbinding3.appcompat.queryTextChanges
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.cleanup
|
||||
import im.vector.app.core.extensions.configureWith
|
||||
|
@ -37,8 +37,11 @@ import im.vector.app.core.resources.DrawableProvider
|
|||
import im.vector.app.databinding.FragmentRecyclerviewWithSearchBinding
|
||||
import im.vector.app.features.roomprofile.members.RoomMemberListAction
|
||||
import im.vector.app.features.roomprofile.members.RoomMemberListViewModel
|
||||
import io.reactivex.rxkotlin.subscribeBy
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||
import reactivecircus.flowbinding.appcompat.queryTextChanges
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -117,11 +120,11 @@ class SpacePeopleFragment @Inject constructor(
|
|||
private fun setupSearchView() {
|
||||
views.memberNameFilter.queryHint = getString(R.string.search_members_hint)
|
||||
views.memberNameFilter.queryTextChanges()
|
||||
.debounce(100, TimeUnit.MILLISECONDS)
|
||||
.subscribeBy {
|
||||
.debounce(100)
|
||||
.onEach {
|
||||
membersViewModel.handle(RoomMemberListAction.FilterMemberList(it.toString()))
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
}
|
||||
|
||||
private fun handleViewEvents(events: SpacePeopleViewEvents) {
|
||||
|
|
|
@ -22,13 +22,13 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.Success
|
||||
import com.airbnb.mvrx.Uninitialized
|
||||
import com.airbnb.mvrx.fragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import com.jakewharton.rxbinding3.appcompat.navigationClicks
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.cleanup
|
||||
import im.vector.app.core.extensions.configureWith
|
||||
|
@ -37,10 +37,12 @@ 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 io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.sample
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import org.matrix.android.sdk.api.util.MatrixItem
|
||||
import java.util.concurrent.TimeUnit
|
||||
import reactivecircus.flowbinding.appcompat.navigationClicks
|
||||
import javax.inject.Inject
|
||||
|
||||
@Parcelize
|
||||
|
@ -72,11 +74,11 @@ class SpacePreviewFragment @Inject constructor(
|
|||
handleViewEvents(it)
|
||||
}
|
||||
|
||||
views.roomPreviewNoPreviewToolbar.navigationClicks()
|
||||
.throttleFirst(300, TimeUnit.MILLISECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe { sharedActionViewModel.post(SpacePreviewSharedAction.DismissAction) }
|
||||
.disposeOnDestroyView()
|
||||
views.roomPreviewNoPreviewToolbar
|
||||
.navigationClicks()
|
||||
.sample(300)
|
||||
.onEach { sharedActionViewModel.post(SpacePreviewSharedAction.DismissAction) }
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
|
||||
views.spacePreviewRecyclerView.configureWith(epoxyController)
|
||||
|
||||
|
|
|
@ -31,7 +31,6 @@ import com.airbnb.mvrx.args
|
|||
import com.airbnb.mvrx.fragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import com.google.android.material.chip.Chip
|
||||
import com.jakewharton.rxbinding3.widget.textChanges
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.cleanup
|
||||
import im.vector.app.core.extensions.configureWith
|
||||
|
@ -45,8 +44,13 @@ import im.vector.app.databinding.FragmentUserListBinding
|
|||
import im.vector.app.features.homeserver.HomeServerCapabilitiesViewModel
|
||||
import im.vector.app.features.navigation.SettingsActivityPayload
|
||||
import im.vector.app.features.settings.VectorSettingsActivity
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
import kotlinx.coroutines.flow.startWith
|
||||
import org.matrix.android.sdk.api.session.identity.ThreePid
|
||||
import org.matrix.android.sdk.api.session.user.model.User
|
||||
import reactivecircus.flowbinding.android.widget.textChanges
|
||||
import javax.inject.Inject
|
||||
|
||||
class UserListFragment @Inject constructor(
|
||||
|
@ -133,8 +137,8 @@ class UserListFragment @Inject constructor(
|
|||
private fun setupSearchView() {
|
||||
views.userListSearch
|
||||
.textChanges()
|
||||
.startWith(views.userListSearch.text)
|
||||
.subscribe { text ->
|
||||
.onStart { emit(views.userListSearch.text)}
|
||||
.onEach { text ->
|
||||
val searchValue = text.trim()
|
||||
val action = if (searchValue.isBlank()) {
|
||||
UserListAction.ClearSearchUsers
|
||||
|
@ -143,7 +147,7 @@ class UserListFragment @Inject constructor(
|
|||
}
|
||||
viewModel.handle(action)
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
|
||||
views.userListSearch.setupAsSearch()
|
||||
views.userListSearch.requestFocus()
|
||||
|
|
Loading…
Reference in a new issue