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