diff --git a/vector/src/main/java/im/vector/riotx/core/platform/VectorBaseFragment.kt b/vector/src/main/java/im/vector/riotx/core/platform/VectorBaseFragment.kt index 65b78a4eaa..7b9916b9ad 100644 --- a/vector/src/main/java/im/vector/riotx/core/platform/VectorBaseFragment.kt +++ b/vector/src/main/java/im/vector/riotx/core/platform/VectorBaseFragment.kt @@ -126,6 +126,14 @@ abstract class VectorBaseFragment : BaseMvRxFragment(), HasScreenInjector { mUnBinder = ButterKnife.bind(this, view) } + open fun showLoading(message: CharSequence?) { + showLoadingDialog(message) + } + + open fun showFailure(throwable: Throwable) { + displayErrorDialog(throwable) + } + @CallSuper override fun onDestroyView() { super.onDestroyView() @@ -188,10 +196,10 @@ abstract class VectorBaseFragment : BaseMvRxFragment(), HasScreenInjector { } } - protected fun showLoadingDialog(message: CharSequence, cancelable: Boolean = false) { + protected fun showLoadingDialog(message: CharSequence? = null, cancelable: Boolean = false) { progress = ProgressDialog(requireContext()).apply { setCancelable(cancelable) - setMessage(message) + setMessage(message ?: getString(R.string.please_wait)) setProgressStyle(ProgressDialog.STYLE_SPINNER) show() } diff --git a/vector/src/main/java/im/vector/riotx/core/platform/VectorViewEvents.kt b/vector/src/main/java/im/vector/riotx/core/platform/VectorViewEvents.kt new file mode 100644 index 0000000000..b5c191f81a --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/core/platform/VectorViewEvents.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2020 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.riotx.core.platform + +/** + * Interface for View Events + */ +interface VectorViewEvents + +/** + * To use when no view events is associated to the ViewModel + */ +object EmptyViewEvents : VectorViewEvents diff --git a/vector/src/main/java/im/vector/riotx/core/platform/VectorViewModel.kt b/vector/src/main/java/im/vector/riotx/core/platform/VectorViewModel.kt index 74b18be3c2..bda4426c45 100644 --- a/vector/src/main/java/im/vector/riotx/core/platform/VectorViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/core/platform/VectorViewModel.kt @@ -16,20 +16,23 @@ package im.vector.riotx.core.platform -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import com.airbnb.mvrx.* -import im.vector.riotx.core.utils.LiveEvent +import com.airbnb.mvrx.Async +import com.airbnb.mvrx.BaseMvRxViewModel +import com.airbnb.mvrx.Fail +import com.airbnb.mvrx.Loading +import com.airbnb.mvrx.MvRxState +import com.airbnb.mvrx.Success +import im.vector.riotx.core.utils.DataSource +import im.vector.riotx.core.utils.PublishDataSource import io.reactivex.Observable import io.reactivex.Single -abstract class VectorViewModel(initialState: S) +abstract class VectorViewModel(initialState: S) : BaseMvRxViewModel(initialState, false) { - // Generic handling of any request error - protected val _requestErrorLiveData = MutableLiveData>() - val requestErrorLiveData: LiveData> - get() = _requestErrorLiveData + // Used to post transient events to the View + protected val _viewEvents = PublishDataSource() + val viewEvents: DataSource = _viewEvents /** * This method does the same thing as the execute function, but it doesn't subscribe to the stream @@ -53,5 +56,5 @@ abstract class VectorViewModel(initial .doOnNext { setState { stateReducer(it) } } } - abstract fun handle(action: A) + abstract fun handle(action: VA) } diff --git a/vector/src/main/java/im/vector/riotx/features/createdirect/CreateDirectRoomDirectoryUsersFragment.kt b/vector/src/main/java/im/vector/riotx/features/createdirect/CreateDirectRoomDirectoryUsersFragment.kt index 77cee5fd6f..ecfe054767 100644 --- a/vector/src/main/java/im/vector/riotx/features/createdirect/CreateDirectRoomDirectoryUsersFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/createdirect/CreateDirectRoomDirectoryUsersFragment.kt @@ -23,7 +23,11 @@ import com.airbnb.mvrx.withState import com.jakewharton.rxbinding3.widget.textChanges import im.vector.matrix.android.api.session.user.model.User import im.vector.riotx.R -import im.vector.riotx.core.extensions.* +import im.vector.riotx.core.extensions.cleanup +import im.vector.riotx.core.extensions.configureWith +import im.vector.riotx.core.extensions.hideKeyboard +import im.vector.riotx.core.extensions.setupAsSearch +import im.vector.riotx.core.extensions.showKeyboard import im.vector.riotx.core.platform.VectorBaseFragment import kotlinx.android.synthetic.main.fragment_create_direct_room_directory_users.* import javax.inject.Inject diff --git a/vector/src/main/java/im/vector/riotx/features/createdirect/CreateDirectRoomViewModel.kt b/vector/src/main/java/im/vector/riotx/features/createdirect/CreateDirectRoomViewModel.kt index 9023312530..fd56aacee4 100644 --- a/vector/src/main/java/im/vector/riotx/features/createdirect/CreateDirectRoomViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/createdirect/CreateDirectRoomViewModel.kt @@ -33,6 +33,7 @@ import im.vector.matrix.android.api.session.user.model.User import im.vector.matrix.android.api.util.toMatrixItem import im.vector.matrix.rx.rx import im.vector.riotx.core.extensions.postLiveEvent +import im.vector.riotx.core.platform.EmptyViewEvents import im.vector.riotx.core.platform.VectorViewModel import im.vector.riotx.core.utils.LiveEvent import io.reactivex.Single @@ -51,7 +52,7 @@ data class SelectUserAction( class CreateDirectRoomViewModel @AssistedInject constructor(@Assisted initialState: CreateDirectRoomViewState, private val session: Session) - : VectorViewModel(initialState) { + : VectorViewModel(initialState) { @AssistedInject.Factory interface Factory { diff --git a/vector/src/main/java/im/vector/riotx/features/crypto/keysbackup/settings/KeysBackupSettingsViewModel.kt b/vector/src/main/java/im/vector/riotx/features/crypto/keysbackup/settings/KeysBackupSettingsViewModel.kt index 4acb318033..bed18ae99d 100644 --- a/vector/src/main/java/im/vector/riotx/features/crypto/keysbackup/settings/KeysBackupSettingsViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/crypto/keysbackup/settings/KeysBackupSettingsViewModel.kt @@ -24,11 +24,12 @@ import im.vector.matrix.android.api.session.crypto.keysbackup.KeysBackupService import im.vector.matrix.android.api.session.crypto.keysbackup.KeysBackupState import im.vector.matrix.android.api.session.crypto.keysbackup.KeysBackupStateListener import im.vector.matrix.android.internal.crypto.keysbackup.model.KeysBackupVersionTrust +import im.vector.riotx.core.platform.EmptyViewEvents import im.vector.riotx.core.platform.VectorViewModel class KeysBackupSettingsViewModel @AssistedInject constructor(@Assisted initialState: KeysBackupSettingViewState, session: Session -) : VectorViewModel(initialState), +) : VectorViewModel(initialState), KeysBackupStateListener { @AssistedInject.Factory diff --git a/vector/src/main/java/im/vector/riotx/features/grouplist/GroupListViewModel.kt b/vector/src/main/java/im/vector/riotx/features/grouplist/GroupListViewModel.kt index 816f721040..c31a30b432 100644 --- a/vector/src/main/java/im/vector/riotx/features/grouplist/GroupListViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/grouplist/GroupListViewModel.kt @@ -33,6 +33,7 @@ import im.vector.matrix.android.api.session.room.model.Membership import im.vector.matrix.rx.rx import im.vector.riotx.R import im.vector.riotx.core.extensions.postLiveEvent +import im.vector.riotx.core.platform.EmptyViewEvents import im.vector.riotx.core.platform.VectorViewModel import im.vector.riotx.core.resources.StringProvider import im.vector.riotx.core.utils.LiveEvent @@ -45,7 +46,7 @@ class GroupListViewModel @AssistedInject constructor(@Assisted initialState: Gro private val selectedGroupStore: SelectedGroupDataSource, private val session: Session, private val stringProvider: StringProvider -) : VectorViewModel(initialState) { +) : VectorViewModel(initialState) { @AssistedInject.Factory interface Factory { diff --git a/vector/src/main/java/im/vector/riotx/features/home/HomeDetailViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/HomeDetailViewModel.kt index d6d8f06e60..6b322a2b48 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/HomeDetailViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/HomeDetailViewModel.kt @@ -24,6 +24,7 @@ import com.squareup.inject.assisted.AssistedInject import im.vector.matrix.android.api.session.Session import im.vector.matrix.rx.rx import im.vector.riotx.core.di.HasScreenInjector +import im.vector.riotx.core.platform.EmptyViewEvents import im.vector.riotx.core.platform.VectorViewModel import im.vector.riotx.core.resources.StringProvider import im.vector.riotx.features.grouplist.SelectedGroupDataSource @@ -40,7 +41,7 @@ class HomeDetailViewModel @AssistedInject constructor(@Assisted initialState: Ho private val selectedGroupStore: SelectedGroupDataSource, private val homeRoomListStore: HomeRoomListDataSource, private val stringProvider: StringProvider) - : VectorViewModel(initialState) { + : VectorViewModel(initialState) { @AssistedInject.Factory interface Factory { diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/breadcrumbs/BreadcrumbsViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/breadcrumbs/BreadcrumbsViewModel.kt index 83e9e0fb3f..f8a1e302af 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/breadcrumbs/BreadcrumbsViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/breadcrumbs/BreadcrumbsViewModel.kt @@ -24,12 +24,13 @@ import com.squareup.inject.assisted.AssistedInject import im.vector.matrix.android.api.session.Session import im.vector.matrix.rx.rx import im.vector.riotx.core.platform.EmptyAction +import im.vector.riotx.core.platform.EmptyViewEvents import im.vector.riotx.core.platform.VectorViewModel import io.reactivex.schedulers.Schedulers class BreadcrumbsViewModel @AssistedInject constructor(@Assisted initialState: BreadcrumbsViewState, private val session: Session) - : VectorViewModel(initialState) { + : VectorViewModel(initialState) { @AssistedInject.Factory interface Factory { diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewEvents.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewEvents.kt index a1ad480584..ce312d0d7f 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewEvents.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewEvents.kt @@ -16,9 +16,11 @@ package im.vector.riotx.features.home.room.detail +import im.vector.riotx.core.platform.VectorViewEvents + /** * Transient events for RoomDetail */ -sealed class RoomDetailViewEvents { +sealed class RoomDetailViewEvents : VectorViewEvents { data class Failure(val throwable: Throwable) : RoomDetailViewEvents() } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt index db938c14e5..36cbdcaa75 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt @@ -20,7 +20,12 @@ import android.net.Uri import androidx.annotation.IdRes import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData -import com.airbnb.mvrx.* +import com.airbnb.mvrx.Async +import com.airbnb.mvrx.Fail +import com.airbnb.mvrx.FragmentViewModelContext +import com.airbnb.mvrx.MvRxViewModelFactory +import com.airbnb.mvrx.Success +import com.airbnb.mvrx.ViewModelContext import com.jakewharton.rxrelay2.BehaviorRelay import com.jakewharton.rxrelay2.PublishRelay import com.squareup.inject.assisted.Assisted @@ -55,9 +60,7 @@ import im.vector.riotx.core.extensions.postLiveEvent import im.vector.riotx.core.platform.VectorViewModel import im.vector.riotx.core.resources.StringProvider import im.vector.riotx.core.resources.UserPreferencesProvider -import im.vector.riotx.core.utils.DataSource import im.vector.riotx.core.utils.LiveEvent -import im.vector.riotx.core.utils.PublishDataSource import im.vector.riotx.core.utils.subscribeLogError import im.vector.riotx.features.command.CommandParser import im.vector.riotx.features.command.ParsedCommand @@ -81,7 +84,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro private val stringProvider: StringProvider, private val typingHelper: TypingHelper, private val session: Session -) : VectorViewModel(initialState), Timeline.Listener { +) : VectorViewModel(initialState), Timeline.Listener { private val room = session.getRoom(initialState.roomId)!! private val eventId = initialState.eventId @@ -104,9 +107,6 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro var timeline = room.createTimeline(eventId, timelineSettings) private set - private val _viewEvents = PublishDataSource() - val viewEvents: DataSource = _viewEvents - // Can be used for several actions, for a one shot result private val _requestLiveData = MutableLiveData>>() val requestLiveData: LiveData>> @@ -290,6 +290,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro } } + // TODO Cleanup this and use ViewEvents private val _nonBlockingPopAlert = MutableLiveData>>>() val nonBlockingPopAlert: LiveData>>> get() = _nonBlockingPopAlert diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsViewModel.kt index 3f0e8b041f..29068b07df 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsViewModel.kt @@ -35,6 +35,7 @@ import im.vector.matrix.rx.rx import im.vector.matrix.rx.unwrap import im.vector.riotx.R import im.vector.riotx.core.extensions.canReact +import im.vector.riotx.core.platform.EmptyViewEvents import im.vector.riotx.core.platform.VectorViewModel import im.vector.riotx.core.resources.StringProvider import im.vector.riotx.features.home.room.detail.timeline.format.NoticeEventFormatter @@ -89,7 +90,7 @@ class MessageActionsViewModel @AssistedInject constructor(@Assisted private val noticeEventFormatter: NoticeEventFormatter, private val stringProvider: StringProvider, private val vectorPreferences: VectorPreferences -) : VectorViewModel(initialState) { +) : VectorViewModel(initialState) { private val eventId = initialState.eventId private val informationData = initialState.informationData diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/edithistory/ViewEditHistoryViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/edithistory/ViewEditHistoryViewModel.kt index 64d8950420..3c98d24ccf 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/edithistory/ViewEditHistoryViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/edithistory/ViewEditHistoryViewModel.kt @@ -15,7 +15,15 @@ */ package im.vector.riotx.features.home.room.detail.timeline.edithistory -import com.airbnb.mvrx.* +import com.airbnb.mvrx.Async +import com.airbnb.mvrx.Fail +import com.airbnb.mvrx.FragmentViewModelContext +import com.airbnb.mvrx.Loading +import com.airbnb.mvrx.MvRxState +import com.airbnb.mvrx.MvRxViewModelFactory +import com.airbnb.mvrx.Success +import com.airbnb.mvrx.Uninitialized +import com.airbnb.mvrx.ViewModelContext import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.AssistedInject import im.vector.matrix.android.api.MatrixCallback @@ -28,10 +36,11 @@ import im.vector.matrix.android.api.session.room.model.message.isReply import im.vector.matrix.android.internal.crypto.algorithms.olm.OlmDecryptionResult import im.vector.riotx.core.date.VectorDateFormatter import im.vector.riotx.core.platform.EmptyAction +import im.vector.riotx.core.platform.EmptyViewEvents import im.vector.riotx.core.platform.VectorViewModel import im.vector.riotx.features.home.room.detail.timeline.action.TimelineEventFragmentArgs import timber.log.Timber -import java.util.* +import java.util.UUID data class ViewEditHistoryViewState( val eventId: String, @@ -47,7 +56,7 @@ class ViewEditHistoryViewModel @AssistedInject constructor(@Assisted initialState: ViewEditHistoryViewState, val session: Session, val dateFormatter: VectorDateFormatter -) : VectorViewModel(initialState) { +) : VectorViewModel(initialState) { private val roomId = initialState.roomId private val eventId = initialState.eventId diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/reactions/ViewReactionsViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/reactions/ViewReactionsViewModel.kt index 761e80dd59..05cdbc0fd8 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/reactions/ViewReactionsViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/reactions/ViewReactionsViewModel.kt @@ -16,7 +16,12 @@ package im.vector.riotx.features.home.room.detail.timeline.reactions -import com.airbnb.mvrx.* +import com.airbnb.mvrx.Async +import com.airbnb.mvrx.FragmentViewModelContext +import com.airbnb.mvrx.MvRxState +import com.airbnb.mvrx.MvRxViewModelFactory +import com.airbnb.mvrx.Uninitialized +import com.airbnb.mvrx.ViewModelContext import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.AssistedInject import im.vector.matrix.android.api.session.Session @@ -25,6 +30,7 @@ import im.vector.matrix.rx.RxRoom import im.vector.matrix.rx.unwrap import im.vector.riotx.core.date.VectorDateFormatter import im.vector.riotx.core.platform.EmptyAction +import im.vector.riotx.core.platform.EmptyViewEvents import im.vector.riotx.core.platform.VectorViewModel import im.vector.riotx.features.home.room.detail.timeline.action.TimelineEventFragmentArgs import io.reactivex.Observable @@ -54,7 +60,7 @@ class ViewReactionsViewModel @AssistedInject constructor(@Assisted initialState: DisplayReactionsViewState, private val session: Session, private val dateFormatter: VectorDateFormatter -) : VectorViewModel(initialState) { +) : VectorViewModel(initialState) { private val roomId = initialState.roomId private val eventId = initialState.eventId diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListFragment.kt index 4d9f5fb847..6dde2a2d28 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListFragment.kt @@ -27,7 +27,11 @@ import androidx.core.view.isVisible import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.airbnb.epoxy.OnModelBuildFinishedListener -import com.airbnb.mvrx.* +import com.airbnb.mvrx.Fail +import com.airbnb.mvrx.Incomplete +import com.airbnb.mvrx.Success +import com.airbnb.mvrx.args +import com.airbnb.mvrx.fragmentViewModel import im.vector.matrix.android.api.failure.Failure import im.vector.matrix.android.api.session.room.model.Membership import im.vector.matrix.android.api.session.room.model.RoomSummary @@ -102,9 +106,11 @@ class RoomListFragment @Inject constructor( .observe() .observeOn(AndroidSchedulers.mainThread()) .subscribe { + dismissLoadingDialog() when (it) { + is RoomListViewEvents.Loading -> showLoading(it.message) + is RoomListViewEvents.Failure -> showFailure(it.throwable) is RoomListViewEvents.SelectRoom -> openSelectedRoom(it) - is RoomListViewEvents.Failure -> showErrorInSnackbar(it.throwable) } } .disposeOnDestroyView() @@ -117,6 +123,10 @@ class RoomListFragment @Inject constructor( .disposeOnDestroyView() } + override fun showFailure(throwable: Throwable) { + showErrorInSnackbar(throwable) + } + override fun onDestroyView() { roomController.removeModelBuildListener(modelBuildListener) modelBuildListener = null diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewEvents.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewEvents.kt index 1181236da2..2e147293ec 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewEvents.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewEvents.kt @@ -17,10 +17,14 @@ package im.vector.riotx.features.home.room.list +import im.vector.riotx.core.platform.VectorViewEvents + /** * Transient events for RoomList */ -sealed class RoomListViewEvents { +sealed class RoomListViewEvents : VectorViewEvents { + data class Loading(val message: CharSequence? = null) : RoomListViewEvents() data class Failure(val throwable: Throwable) : RoomListViewEvents() + data class SelectRoom(val roomId: String) : RoomListViewEvents() } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewModel.kt index a9ea831723..f2f563cf26 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewModel.kt @@ -26,7 +26,6 @@ import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.session.room.model.tag.RoomTag import im.vector.riotx.core.platform.VectorViewModel import im.vector.riotx.core.utils.DataSource -import im.vector.riotx.core.utils.PublishDataSource import io.reactivex.schedulers.Schedulers import timber.log.Timber import javax.inject.Inject @@ -34,7 +33,7 @@ import javax.inject.Inject class RoomListViewModel @Inject constructor(initialState: RoomListViewState, private val session: Session, private val roomSummariesSource: DataSource>) - : VectorViewModel(initialState) { + : VectorViewModel(initialState) { interface Factory { fun create(initialState: RoomListViewState): RoomListViewModel @@ -52,9 +51,6 @@ class RoomListViewModel @Inject constructor(initialState: RoomListViewState, private val displayMode = initialState.displayMode private val roomListDisplayModeFilter = RoomListDisplayModeFilter(displayMode) - private val _viewEvents = PublishDataSource() - val viewEvents: DataSource = _viewEvents - init { observeRoomSummaries() } @@ -197,6 +193,7 @@ class RoomListViewModel @Inject constructor(initialState: RoomListViewState, } private fun handleLeaveRoom(action: RoomListAction.LeaveRoom) { + _viewEvents.post(RoomListViewEvents.Loading(null)) session.getRoom(action.roomId)?.leave(null, object : MatrixCallback { override fun onFailure(failure: Throwable) { _viewEvents.post(RoomListViewEvents.Failure(failure)) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsViewModel.kt index 1c4d414f18..40f773b253 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsViewModel.kt @@ -24,11 +24,12 @@ import im.vector.matrix.android.api.session.Session import im.vector.matrix.rx.rx import im.vector.matrix.rx.unwrap import im.vector.riotx.core.platform.EmptyAction +import im.vector.riotx.core.platform.EmptyViewEvents import im.vector.riotx.core.platform.VectorViewModel class RoomListQuickActionsViewModel @AssistedInject constructor(@Assisted initialState: RoomListQuickActionsState, session: Session -) : VectorViewModel(initialState) { +) : VectorViewModel(initialState) { @AssistedInject.Factory interface Factory { diff --git a/vector/src/main/java/im/vector/riotx/features/login/AbstractLoginFragment.kt b/vector/src/main/java/im/vector/riotx/features/login/AbstractLoginFragment.kt index d7e37f762b..b243ea771f 100644 --- a/vector/src/main/java/im/vector/riotx/features/login/AbstractLoginFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/login/AbstractLoginFragment.kt @@ -70,14 +70,14 @@ abstract class AbstractLoginFragment : VectorBaseFragment(), OnBackPressed { private fun handleLoginViewEvents(loginViewEvents: LoginViewEvents) { when (loginViewEvents) { - is LoginViewEvents.Error -> showError(loginViewEvents.throwable) - else -> + is LoginViewEvents.Failure -> showFailure(loginViewEvents.throwable) + else -> // This is handled by the Activity Unit } } - private fun showError(throwable: Throwable) { + override fun showFailure(throwable: Throwable) { when (throwable) { is Failure.ServerError -> { if (throwable.error.code == MatrixError.M_FORBIDDEN @@ -96,11 +96,7 @@ abstract class AbstractLoginFragment : VectorBaseFragment(), OnBackPressed { } open fun onError(throwable: Throwable) { - AlertDialog.Builder(requireActivity()) - .setTitle(R.string.dialog_title_error) - .setMessage(errorFormatter.toHumanReadable(throwable)) - .setPositiveButton(R.string.ok, null) - .show() + super.showFailure(throwable) } override fun onBackPressed(toolbarButton: Boolean): Boolean { diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginActivity.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginActivity.kt index d879212c3d..908a9c6370 100644 --- a/vector/src/main/java/im/vector/riotx/features/login/LoginActivity.kt +++ b/vector/src/main/java/im/vector/riotx/features/login/LoginActivity.kt @@ -209,7 +209,7 @@ open class LoginActivity : VectorBaseActivity(), ToolbarConfigurable { .setMessage(R.string.login_error_outdated_homeserver_content) .setPositiveButton(R.string.ok, null) .show() - is LoginViewEvents.Error -> + is LoginViewEvents.Failure -> // This is handled by the Fragments Unit } diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginViewEvents.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginViewEvents.kt index 4c089174f4..25747df3d4 100644 --- a/vector/src/main/java/im/vector/riotx/features/login/LoginViewEvents.kt +++ b/vector/src/main/java/im/vector/riotx/features/login/LoginViewEvents.kt @@ -18,12 +18,15 @@ package im.vector.riotx.features.login import im.vector.matrix.android.api.auth.registration.FlowResult +import im.vector.riotx.core.platform.VectorViewEvents /** * Transient events for Login */ -sealed class LoginViewEvents { +sealed class LoginViewEvents: VectorViewEvents { + data class Loading(val message: CharSequence? = null) : LoginViewEvents() + data class Failure(val throwable: Throwable) : LoginViewEvents() + data class RegistrationFlowResult(val flowResult: FlowResult, val isRegistrationStarted: Boolean) : LoginViewEvents() - data class Error(val throwable: Throwable) : LoginViewEvents() object OutdatedHomeserver : LoginViewEvents() } diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginViewModel.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginViewModel.kt index 8eb4652da5..b38b1d3ee2 100644 --- a/vector/src/main/java/im/vector/riotx/features/login/LoginViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/login/LoginViewModel.kt @@ -41,8 +41,6 @@ import im.vector.matrix.android.internal.auth.data.LoginFlowTypes import im.vector.riotx.core.di.ActiveSessionHolder import im.vector.riotx.core.extensions.configureAndStart import im.vector.riotx.core.platform.VectorViewModel -import im.vector.riotx.core.utils.DataSource -import im.vector.riotx.core.utils.PublishDataSource import im.vector.riotx.features.notifications.PushRuleTriggerListener import im.vector.riotx.features.session.SessionListener import im.vector.riotx.features.signout.soft.SoftLogoutActivity @@ -59,7 +57,7 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi private val pushRuleTriggerListener: PushRuleTriggerListener, private val homeServerConnectionConfigFactory: HomeServerConnectionConfigFactory, private val sessionListener: SessionListener) - : VectorViewModel(initialState) { + : VectorViewModel(initialState) { @AssistedInject.Factory interface Factory { @@ -95,9 +93,6 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi private var currentTask: Cancelable? = null - private val _viewEvents = PublishDataSource() - val viewEvents: DataSource = _viewEvents - override fun handle(action: LoginAction) { when (action) { is LoginAction.UpdateServerType -> handleUpdateServerType(action) @@ -179,7 +174,7 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi override fun onFailure(failure: Throwable) { if (failure !is CancellationException) { - _viewEvents.post(LoginViewEvents.Error(failure)) + _viewEvents.post(LoginViewEvents.Failure(failure)) } setState { copy( @@ -201,7 +196,7 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi } override fun onFailure(failure: Throwable) { - _viewEvents.post(LoginViewEvents.Error(failure)) + _viewEvents.post(LoginViewEvents.Failure(failure)) setState { copy( asyncRegistration = Uninitialized @@ -223,7 +218,7 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi } override fun onFailure(failure: Throwable) { - _viewEvents.post(LoginViewEvents.Error(failure)) + _viewEvents.post(LoginViewEvents.Failure(failure)) setState { copy( asyncRegistration = Uninitialized @@ -526,7 +521,7 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi if (homeServerConnectionConfig == null) { // This is invalid - _viewEvents.post(LoginViewEvents.Error(Throwable("Unable to create a HomeServerConnectionConfig"))) + _viewEvents.post(LoginViewEvents.Failure(Throwable("Unable to create a HomeServerConnectionConfig"))) } else { currentTask?.cancel() currentTask = null @@ -540,7 +535,7 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi currentTask = authenticationService.getLoginFlow(homeServerConnectionConfig, object : MatrixCallback { override fun onFailure(failure: Throwable) { - _viewEvents.post(LoginViewEvents.Error(failure)) + _viewEvents.post(LoginViewEvents.Failure(failure)) setState { copy( asyncHomeServerLoginFlowRequest = Uninitialized diff --git a/vector/src/main/java/im/vector/riotx/features/reactions/EmojiSearchResultViewModel.kt b/vector/src/main/java/im/vector/riotx/features/reactions/EmojiSearchResultViewModel.kt index 8aa03d9b22..9856693d22 100644 --- a/vector/src/main/java/im/vector/riotx/features/reactions/EmojiSearchResultViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/reactions/EmojiSearchResultViewModel.kt @@ -21,6 +21,7 @@ import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.AssistedInject +import im.vector.riotx.core.platform.EmptyViewEvents import im.vector.riotx.core.platform.VectorViewModel import im.vector.riotx.features.reactions.data.EmojiDataSource import im.vector.riotx.features.reactions.data.EmojiItem @@ -33,7 +34,7 @@ data class EmojiSearchResultViewState( class EmojiSearchResultViewModel @AssistedInject constructor( @Assisted initialState: EmojiSearchResultViewState, private val dataSource: EmojiDataSource) - : VectorViewModel(initialState) { + : VectorViewModel(initialState) { @AssistedInject.Factory interface Factory { diff --git a/vector/src/main/java/im/vector/riotx/features/roomdirectory/PublicRoomsFragment.kt b/vector/src/main/java/im/vector/riotx/features/roomdirectory/PublicRoomsFragment.kt index 1e625cff75..580844ddfa 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomdirectory/PublicRoomsFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomdirectory/PublicRoomsFragment.kt @@ -75,6 +75,7 @@ class PublicRoomsFragment @Inject constructor( sharedActionViewModel.post(RoomDirectorySharedAction.CreateRoom) } + // TODO remove this, replace by ViewEvents viewModel.joinRoomErrorLiveData.observeEvent(this) { throwable -> Snackbar.make(publicRoomsCoordinator, errorFormatter.toHumanReadable(throwable), Snackbar.LENGTH_SHORT) .show() diff --git a/vector/src/main/java/im/vector/riotx/features/roomdirectory/RoomDirectoryViewModel.kt b/vector/src/main/java/im/vector/riotx/features/roomdirectory/RoomDirectoryViewModel.kt index c4a91a520a..bab07795e9 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomdirectory/RoomDirectoryViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomdirectory/RoomDirectoryViewModel.kt @@ -33,6 +33,7 @@ import im.vector.matrix.android.api.session.room.roomSummaryQueryParams import im.vector.matrix.android.api.util.Cancelable import im.vector.matrix.rx.rx import im.vector.riotx.core.extensions.postLiveEvent +import im.vector.riotx.core.platform.EmptyViewEvents import im.vector.riotx.core.platform.VectorViewModel import im.vector.riotx.core.utils.LiveEvent import timber.log.Timber @@ -41,7 +42,7 @@ private const val PUBLIC_ROOMS_LIMIT = 20 class RoomDirectoryViewModel @AssistedInject constructor(@Assisted initialState: PublicRoomsViewState, private val session: Session) - : VectorViewModel(initialState) { + : VectorViewModel(initialState) { @AssistedInject.Factory interface Factory { diff --git a/vector/src/main/java/im/vector/riotx/features/roomdirectory/createroom/CreateRoomViewModel.kt b/vector/src/main/java/im/vector/riotx/features/roomdirectory/createroom/CreateRoomViewModel.kt index ff4aa332f4..457574e736 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomdirectory/createroom/CreateRoomViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomdirectory/createroom/CreateRoomViewModel.kt @@ -17,7 +17,12 @@ package im.vector.riotx.features.roomdirectory.createroom import androidx.fragment.app.FragmentActivity -import com.airbnb.mvrx.* +import com.airbnb.mvrx.ActivityViewModelContext +import com.airbnb.mvrx.Fail +import com.airbnb.mvrx.Loading +import com.airbnb.mvrx.MvRxViewModelFactory +import com.airbnb.mvrx.Success +import com.airbnb.mvrx.ViewModelContext import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.AssistedInject import im.vector.matrix.android.api.MatrixCallback @@ -25,12 +30,13 @@ import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.api.session.room.model.RoomDirectoryVisibility import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams import im.vector.matrix.android.api.session.room.model.create.CreateRoomPreset +import im.vector.riotx.core.platform.EmptyViewEvents import im.vector.riotx.core.platform.VectorViewModel import im.vector.riotx.features.roomdirectory.RoomDirectoryActivity class CreateRoomViewModel @AssistedInject constructor(@Assisted initialState: CreateRoomViewState, private val session: Session -) : VectorViewModel(initialState) { +) : VectorViewModel(initialState) { @AssistedInject.Factory interface Factory { diff --git a/vector/src/main/java/im/vector/riotx/features/roomdirectory/picker/RoomDirectoryPickerViewModel.kt b/vector/src/main/java/im/vector/riotx/features/roomdirectory/picker/RoomDirectoryPickerViewModel.kt index b7bdaea495..54f93b5404 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomdirectory/picker/RoomDirectoryPickerViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomdirectory/picker/RoomDirectoryPickerViewModel.kt @@ -16,17 +16,22 @@ package im.vector.riotx.features.roomdirectory.picker -import com.airbnb.mvrx.* +import com.airbnb.mvrx.Fail +import com.airbnb.mvrx.FragmentViewModelContext +import com.airbnb.mvrx.MvRxViewModelFactory +import com.airbnb.mvrx.Success +import com.airbnb.mvrx.ViewModelContext import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.AssistedInject import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.api.session.room.model.thirdparty.ThirdPartyProtocol +import im.vector.riotx.core.platform.EmptyViewEvents import im.vector.riotx.core.platform.VectorViewModel class RoomDirectoryPickerViewModel @AssistedInject constructor(@Assisted initialState: RoomDirectoryPickerViewState, private val session: Session) - : VectorViewModel(initialState) { + : VectorViewModel(initialState) { @AssistedInject.Factory interface Factory { diff --git a/vector/src/main/java/im/vector/riotx/features/roomdirectory/roompreview/RoomPreviewViewModel.kt b/vector/src/main/java/im/vector/riotx/features/roomdirectory/roompreview/RoomPreviewViewModel.kt index 3de5cb4334..b4aae0d116 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomdirectory/roompreview/RoomPreviewViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomdirectory/roompreview/RoomPreviewViewModel.kt @@ -26,13 +26,14 @@ import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.api.session.room.model.Membership import im.vector.matrix.android.api.session.room.roomSummaryQueryParams import im.vector.matrix.rx.rx +import im.vector.riotx.core.platform.EmptyViewEvents import im.vector.riotx.core.platform.VectorViewModel import im.vector.riotx.features.roomdirectory.JoinState import timber.log.Timber class RoomPreviewViewModel @AssistedInject constructor(@Assisted initialState: RoomPreviewViewState, private val session: Session) - : VectorViewModel(initialState) { + : VectorViewModel(initialState) { @AssistedInject.Factory interface Factory { diff --git a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileFragment.kt b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileFragment.kt index 23db6b53a8..f118aad8ed 100644 --- a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileFragment.kt @@ -20,7 +20,12 @@ package im.vector.riotx.features.roommemberprofile import android.os.Bundle import android.os.Parcelable import android.view.View -import com.airbnb.mvrx.* +import com.airbnb.mvrx.Fail +import com.airbnb.mvrx.Incomplete +import com.airbnb.mvrx.Success +import com.airbnb.mvrx.args +import com.airbnb.mvrx.fragmentViewModel +import com.airbnb.mvrx.withState import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.R import im.vector.riotx.core.animations.AppBarStateChangeListener @@ -31,6 +36,7 @@ import im.vector.riotx.core.extensions.setTextOrHide import im.vector.riotx.core.platform.StateView import im.vector.riotx.core.platform.VectorBaseFragment import im.vector.riotx.features.home.AvatarRenderer +import io.reactivex.android.schedulers.AndroidSchedulers import kotlinx.android.parcel.Parcelize import kotlinx.android.synthetic.main.fragment_matrix_profile.* import kotlinx.android.synthetic.main.view_stub_room_member_profile_header.* @@ -75,11 +81,13 @@ class RoomMemberProfileFragment @Inject constructor( matrixProfileAppBarLayout.addOnOffsetChangedListener(appBarStateChangeListener) viewModel.viewEvents .observe() + .observeOn(AndroidSchedulers.mainThread()) .subscribe { dismissLoadingDialog() when (it) { - is RoomMemberProfileViewEvents.Loading -> showLoadingDialog(it.message) - is RoomMemberProfileViewEvents.Failure -> showErrorInSnackbar(it.throwable) + is RoomMemberProfileViewEvents.Loading -> showLoading(it.message) + is RoomMemberProfileViewEvents.Failure -> showFailure(it.throwable) + is RoomMemberProfileViewEvents.OnIgnoreActionSuccess -> Unit } } .disposeOnDestroyView() diff --git a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewEvents.kt b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewEvents.kt index 093e54989b..4647c124a6 100644 --- a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewEvents.kt +++ b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewEvents.kt @@ -16,11 +16,14 @@ package im.vector.riotx.features.roommemberprofile +import im.vector.riotx.core.platform.VectorViewEvents + /** * Transient events for RoomMemberProfile */ -sealed class RoomMemberProfileViewEvents { - data class Loading(val message: CharSequence) : RoomMemberProfileViewEvents() - object OnIgnoreActionSuccess : RoomMemberProfileViewEvents() +sealed class RoomMemberProfileViewEvents : VectorViewEvents { + data class Loading(val message: CharSequence? = null) : RoomMemberProfileViewEvents() data class Failure(val throwable: Throwable) : RoomMemberProfileViewEvents() + + object OnIgnoreActionSuccess : RoomMemberProfileViewEvents() } diff --git a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewModel.kt b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewModel.kt index 88f394e865..a2488b1ed4 100644 --- a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewModel.kt @@ -44,8 +44,6 @@ import im.vector.matrix.rx.unwrap import im.vector.riotx.R import im.vector.riotx.core.platform.VectorViewModel import im.vector.riotx.core.resources.StringProvider -import im.vector.riotx.core.utils.DataSource -import im.vector.riotx.core.utils.PublishDataSource import io.reactivex.Observable import io.reactivex.functions.BiFunction import kotlinx.coroutines.Dispatchers @@ -55,7 +53,7 @@ import kotlinx.coroutines.withContext class RoomMemberProfileViewModel @AssistedInject constructor(@Assisted private val initialState: RoomMemberProfileViewState, private val stringProvider: StringProvider, private val session: Session) - : VectorViewModel(initialState) { + : VectorViewModel(initialState) { @AssistedInject.Factory interface Factory { @@ -71,9 +69,6 @@ class RoomMemberProfileViewModel @AssistedInject constructor(@Assisted private v } } - private val _viewEvents = PublishDataSource() - val viewEvents: DataSource = _viewEvents - private val room = if (initialState.roomId != null) { session.getRoom(initialState.roomId) } else { @@ -183,7 +178,7 @@ class RoomMemberProfileViewModel @AssistedInject constructor(@Assisted private v private fun handleIgnoreAction() = withState { state -> val isIgnored = state.isIgnored() ?: return@withState - _viewEvents.post(RoomMemberProfileViewEvents.Loading(stringProvider.getString(R.string.please_wait))) + _viewEvents.post(RoomMemberProfileViewEvents.Loading()) val ignoreActionCallback = object : MatrixCallback { override fun onSuccess(data: Unit) { _viewEvents.post(RoomMemberProfileViewEvents.OnIgnoreActionSuccess) diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileFragment.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileFragment.kt index da161efd6a..b6e597f232 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileFragment.kt @@ -38,6 +38,7 @@ import im.vector.riotx.features.home.room.list.actions.RoomListActionsArgs import im.vector.riotx.features.home.room.list.actions.RoomListQuickActionsBottomSheet import im.vector.riotx.features.home.room.list.actions.RoomListQuickActionsSharedAction import im.vector.riotx.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel +import io.reactivex.android.schedulers.AndroidSchedulers import kotlinx.android.parcel.Parcelize import kotlinx.android.synthetic.main.fragment_matrix_profile.* import kotlinx.android.synthetic.main.view_stub_room_profile_header.* @@ -79,12 +80,13 @@ class RoomProfileFragment @Inject constructor( matrixProfileAppBarLayout.addOnOffsetChangedListener(appBarStateChangeListener) roomProfileViewModel.viewEvents .observe() + .observeOn(AndroidSchedulers.mainThread()) .subscribe { dismissLoadingDialog() when (it) { - is RoomProfileViewEvents.Loading -> showLoadingDialog(it.message) - RoomProfileViewEvents.OnLeaveRoomSuccess -> onLeaveRoom() - is RoomProfileViewEvents.Failure -> showError(it.throwable) + is RoomProfileViewEvents.Loading -> showLoading(it.message) + is RoomProfileViewEvents.Failure -> showFailure(it.throwable) + is RoomProfileViewEvents.OnLeaveRoomSuccess -> onLeaveRoom() } } .disposeOnDestroyView() diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileViewEvents.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileViewEvents.kt index 3834247b52..50b3c136e5 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileViewEvents.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileViewEvents.kt @@ -15,11 +15,15 @@ */ package im.vector.riotx.features.roomprofile + +import im.vector.riotx.core.platform.VectorViewEvents + /** * Transient events for RoomProfile */ -sealed class RoomProfileViewEvents { - data class Loading(val message: CharSequence): RoomProfileViewEvents() - object OnLeaveRoomSuccess: RoomProfileViewEvents() +sealed class RoomProfileViewEvents : VectorViewEvents { + data class Loading(val message: CharSequence? = null) : RoomProfileViewEvents() data class Failure(val throwable: Throwable) : RoomProfileViewEvents() + + object OnLeaveRoomSuccess : RoomProfileViewEvents() } diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileViewModel.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileViewModel.kt index 8134c93b4f..6c66ac67b2 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileViewModel.kt @@ -29,13 +29,11 @@ import im.vector.matrix.rx.unwrap import im.vector.riotx.R import im.vector.riotx.core.platform.VectorViewModel import im.vector.riotx.core.resources.StringProvider -import im.vector.riotx.core.utils.DataSource -import im.vector.riotx.core.utils.PublishDataSource class RoomProfileViewModel @AssistedInject constructor(@Assisted initialState: RoomProfileViewState, private val stringProvider: StringProvider, private val session: Session) - : VectorViewModel(initialState) { + : VectorViewModel(initialState) { @AssistedInject.Factory interface Factory { @@ -51,9 +49,6 @@ class RoomProfileViewModel @AssistedInject constructor(@Assisted initialState: R } } - private val _viewEvents = PublishDataSource() - val viewEvents: DataSource = _viewEvents - private val room = session.getRoom(initialState.roomId)!! init { diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListViewModel.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListViewModel.kt index 42ef8f285d..8472d4a2a5 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListViewModel.kt @@ -34,13 +34,14 @@ import im.vector.matrix.android.api.session.room.powerlevels.PowerLevelsHelper import im.vector.matrix.rx.mapOptional import im.vector.matrix.rx.rx import im.vector.matrix.rx.unwrap +import im.vector.riotx.core.platform.EmptyViewEvents import im.vector.riotx.core.platform.VectorViewModel import io.reactivex.Observable import io.reactivex.functions.BiFunction class RoomMemberListViewModel @AssistedInject constructor(@Assisted initialState: RoomMemberListViewState, private val session: Session) - : VectorViewModel(initialState) { + : VectorViewModel(initialState) { @AssistedInject.Factory interface Factory { diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsFragment.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsFragment.kt index b707a7e6e4..3c316a498e 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsFragment.kt @@ -27,10 +27,10 @@ import im.vector.matrix.android.api.util.toMatrixItem import im.vector.riotx.R import im.vector.riotx.core.extensions.cleanup import im.vector.riotx.core.extensions.configureWith -import im.vector.riotx.core.extensions.observeEvent import im.vector.riotx.core.platform.VectorBaseFragment import im.vector.riotx.features.home.AvatarRenderer import im.vector.riotx.features.roomprofile.RoomProfileArgs +import io.reactivex.android.schedulers.AndroidSchedulers import kotlinx.android.synthetic.main.fragment_room_setting_generic.* import kotlinx.android.synthetic.main.merge_overlay_waiting_view.* import javax.inject.Inject @@ -54,9 +54,16 @@ class RoomSettingsFragment @Inject constructor( waiting_view_status_text.setText(R.string.please_wait) waiting_view_status_text.isVisible = true - viewModel.requestErrorLiveData.observeEvent(this) { - displayErrorDialog(it) - } + viewModel.viewEvents + .observe() + .observeOn(AndroidSchedulers.mainThread()) + .subscribe { + dismissLoadingDialog() + when (it) { + is RoomSettingsViewEvents.Failure -> showFailure(it.throwable) + } + } + .disposeOnDestroyView() } override fun onDestroyView() { diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsViewEvents.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsViewEvents.kt new file mode 100644 index 0000000000..999258398b --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsViewEvents.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2020 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.riotx.features.roomprofile.settings + +import im.vector.riotx.core.platform.VectorViewEvents + +/** + * Transient events for room settings screen + */ +sealed class RoomSettingsViewEvents : VectorViewEvents { + data class Loading(val message: CharSequence? = null) : RoomSettingsViewEvents() + data class Failure(val throwable: Throwable) : RoomSettingsViewEvents() +} diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsViewModel.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsViewModel.kt index 27386c141c..ee6413b6a4 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsViewModel.kt @@ -17,9 +17,7 @@ package im.vector.riotx.features.roomprofile.settings import com.airbnb.mvrx.FragmentViewModelContext -import com.airbnb.mvrx.Loading import com.airbnb.mvrx.MvRxViewModelFactory -import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.ViewModelContext import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.AssistedInject @@ -28,12 +26,11 @@ import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM import im.vector.matrix.rx.rx import im.vector.matrix.rx.unwrap -import im.vector.riotx.core.extensions.postLiveEvent import im.vector.riotx.core.platform.VectorViewModel class RoomSettingsViewModel @AssistedInject constructor(@Assisted initialState: RoomSettingsViewState, private val session: Session) - : VectorViewModel(initialState) { + : VectorViewModel(initialState) { @AssistedInject.Factory interface Factory { @@ -80,7 +77,7 @@ class RoomSettingsViewModel @AssistedInject constructor(@Assisted initialState: copy(isLoading = false) } - _requestErrorLiveData.postLiveEvent(failure) + _viewEvents.post(RoomSettingsViewEvents.Failure(failure)) } override fun onSuccess(data: Unit) { diff --git a/vector/src/main/java/im/vector/riotx/features/settings/devices/DevicesAction.kt b/vector/src/main/java/im/vector/riotx/features/settings/devices/DevicesAction.kt new file mode 100644 index 0000000000..550703039f --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/settings/devices/DevicesAction.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2020 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.riotx.features.settings.devices + +import im.vector.matrix.android.internal.crypto.model.rest.DeviceInfo +import im.vector.riotx.core.platform.VectorViewModelAction + +sealed class DevicesAction : VectorViewModelAction { + object Retry : DevicesAction() + data class Delete(val deviceInfo: DeviceInfo) : DevicesAction() + data class Password(val password: String) : DevicesAction() + data class Rename(val deviceInfo: DeviceInfo, val newName: String) : DevicesAction() + data class ToggleDevice(val deviceInfo: DeviceInfo) : DevicesAction() +} diff --git a/vector/src/main/java/im/vector/riotx/features/settings/devices/DevicesViewEvents.kt b/vector/src/main/java/im/vector/riotx/features/settings/devices/DevicesViewEvents.kt new file mode 100644 index 0000000000..b42738439a --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/settings/devices/DevicesViewEvents.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2020 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.riotx.features.settings.devices + +import im.vector.riotx.core.platform.VectorViewEvents + +/** + * Transient events for Ignored users screen + */ +sealed class DevicesViewEvents : VectorViewEvents { + data class Loading(val message: CharSequence? = null) : DevicesViewEvents() + data class Failure(val throwable: Throwable) : DevicesViewEvents() +} diff --git a/vector/src/main/java/im/vector/riotx/features/settings/devices/DevicesViewModel.kt b/vector/src/main/java/im/vector/riotx/features/settings/devices/DevicesViewModel.kt index b2b015a3f0..0324036347 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/devices/DevicesViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/devices/DevicesViewModel.kt @@ -18,7 +18,15 @@ package im.vector.riotx.features.settings.devices import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData -import com.airbnb.mvrx.* +import com.airbnb.mvrx.Async +import com.airbnb.mvrx.Fail +import com.airbnb.mvrx.FragmentViewModelContext +import com.airbnb.mvrx.Loading +import com.airbnb.mvrx.MvRxState +import com.airbnb.mvrx.MvRxViewModelFactory +import com.airbnb.mvrx.Success +import com.airbnb.mvrx.Uninitialized +import com.airbnb.mvrx.ViewModelContext import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.AssistedInject import im.vector.matrix.android.api.MatrixCallback @@ -29,7 +37,6 @@ import im.vector.matrix.android.internal.crypto.model.rest.DeviceInfo import im.vector.matrix.android.internal.crypto.model.rest.DevicesListResponse import im.vector.riotx.core.extensions.postLiveEvent import im.vector.riotx.core.platform.VectorViewModel -import im.vector.riotx.core.platform.VectorViewModelAction import im.vector.riotx.core.utils.LiveEvent import timber.log.Timber @@ -37,20 +44,13 @@ data class DevicesViewState( val myDeviceId: String = "", val devices: Async> = Uninitialized, val currentExpandedDeviceId: String? = null, + // TODO Replace by isLoading boolean val request: Async = Uninitialized ) : MvRxState -sealed class DevicesAction : VectorViewModelAction { - object Retry : DevicesAction() - data class Delete(val deviceInfo: DeviceInfo) : DevicesAction() - data class Password(val password: String) : DevicesAction() - data class Rename(val deviceInfo: DeviceInfo, val newName: String) : DevicesAction() - data class ToggleDevice(val deviceInfo: DeviceInfo) : DevicesAction() -} - class DevicesViewModel @AssistedInject constructor(@Assisted initialState: DevicesViewState, private val session: Session) - : VectorViewModel(initialState) { + : VectorViewModel(initialState) { @AssistedInject.Factory interface Factory { @@ -153,7 +153,7 @@ class DevicesViewModel @AssistedInject constructor(@Assisted initialState: Devic ) } - _requestErrorLiveData.postLiveEvent(failure) + _viewEvents.post(DevicesViewEvents.Failure(failure)) } }) } @@ -207,7 +207,7 @@ class DevicesViewModel @AssistedInject constructor(@Assisted initialState: Devic ) } - _requestErrorLiveData.postLiveEvent(failure) + _viewEvents.post(DevicesViewEvents.Failure(failure)) } } @@ -261,7 +261,7 @@ class DevicesViewModel @AssistedInject constructor(@Assisted initialState: Devic ) } - _requestErrorLiveData.postLiveEvent(failure) + _viewEvents.post(DevicesViewEvents.Failure(failure)) } }) } diff --git a/vector/src/main/java/im/vector/riotx/features/settings/devices/VectorSettingsDevicesFragment.kt b/vector/src/main/java/im/vector/riotx/features/settings/devices/VectorSettingsDevicesFragment.kt index 8de7c7a322..f4b8b54143 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/devices/VectorSettingsDevicesFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/devices/VectorSettingsDevicesFragment.kt @@ -35,6 +35,7 @@ import im.vector.riotx.core.extensions.observeEvent import im.vector.riotx.core.platform.VectorBaseActivity import im.vector.riotx.core.platform.VectorBaseFragment import im.vector.riotx.core.utils.toast +import io.reactivex.android.schedulers.AndroidSchedulers import kotlinx.android.synthetic.main.fragment_generic_recycler.* import kotlinx.android.synthetic.main.merge_overlay_waiting_view.* import javax.inject.Inject @@ -52,7 +53,7 @@ class VectorSettingsDevicesFragment @Inject constructor( override fun getLayoutResId() = R.layout.fragment_generic_recycler - private val devicesViewModel: DevicesViewModel by fragmentViewModel() + private val viewModel: DevicesViewModel by fragmentViewModel() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -61,16 +62,29 @@ class VectorSettingsDevicesFragment @Inject constructor( waiting_view_status_text.isVisible = true devicesController.callback = this recyclerView.configureWith(devicesController, showDivider = true) - devicesViewModel.requestErrorLiveData.observeEvent(this) { - displayErrorDialog(it) - // Password is maybe not good, for safety measure, reset it here - mAccountPassword = "" - } - devicesViewModel.requestPasswordLiveData.observeEvent(this) { + viewModel.viewEvents + .observe() + .observeOn(AndroidSchedulers.mainThread()) + .subscribe { + dismissLoadingDialog() + when (it) { + is DevicesViewEvents.Loading -> showLoading(it.message) + is DevicesViewEvents.Failure -> showFailure(it.throwable) + } + } + .disposeOnDestroyView() + viewModel.requestPasswordLiveData.observeEvent(this) { maybeShowDeleteDeviceWithPasswordDialog() } } + override fun showFailure(throwable: Throwable) { + super.showFailure(throwable) + + // Password is maybe not good, for safety measure, reset it here + mAccountPassword = "" + } + override fun onDestroyView() { devicesController.callback = null recyclerView.cleanup() @@ -84,11 +98,11 @@ class VectorSettingsDevicesFragment @Inject constructor( } override fun onDeviceClicked(deviceInfo: DeviceInfo) { - devicesViewModel.handle(DevicesAction.ToggleDevice(deviceInfo)) + viewModel.handle(DevicesAction.ToggleDevice(deviceInfo)) } override fun onDeleteDevice(deviceInfo: DeviceInfo) { - devicesViewModel.handle(DevicesAction.Delete(deviceInfo)) + viewModel.handle(DevicesAction.Delete(deviceInfo)) } override fun onRenameDevice(deviceInfo: DeviceInfo) { @@ -96,7 +110,7 @@ class VectorSettingsDevicesFragment @Inject constructor( } override fun retry() { - devicesViewModel.handle(DevicesAction.Retry) + viewModel.handle(DevicesAction.Retry) } /** @@ -117,7 +131,7 @@ class VectorSettingsDevicesFragment @Inject constructor( .setPositiveButton(R.string.ok) { _, _ -> val newName = input.text.toString() - devicesViewModel.handle(DevicesAction.Rename(deviceInfo, newName)) + viewModel.handle(DevicesAction.Rename(deviceInfo, newName)) } .setNegativeButton(R.string.cancel, null) .show() @@ -128,7 +142,7 @@ class VectorSettingsDevicesFragment @Inject constructor( */ private fun maybeShowDeleteDeviceWithPasswordDialog() { if (mAccountPassword.isNotEmpty()) { - devicesViewModel.handle(DevicesAction.Password(mAccountPassword)) + viewModel.handle(DevicesAction.Password(mAccountPassword)) } else { val inflater = requireActivity().layoutInflater val layout = inflater.inflate(R.layout.dialog_device_delete, null) @@ -144,7 +158,7 @@ class VectorSettingsDevicesFragment @Inject constructor( return@OnClickListener } mAccountPassword = passwordEditText.text.toString() - devicesViewModel.handle(DevicesAction.Password(mAccountPassword)) + viewModel.handle(DevicesAction.Password(mAccountPassword)) }) .setNegativeButton(R.string.cancel, null) .setOnKeyListener(DialogInterface.OnKeyListener { dialog, keyCode, event -> @@ -158,7 +172,7 @@ class VectorSettingsDevicesFragment @Inject constructor( } } - override fun invalidate() = withState(devicesViewModel) { state -> + override fun invalidate() = withState(viewModel) { state -> devicesController.update(state) handleRequestStatus(state.request) diff --git a/vector/src/main/java/im/vector/riotx/features/settings/ignored/IgnoredUsersViewEvents.kt b/vector/src/main/java/im/vector/riotx/features/settings/ignored/IgnoredUsersViewEvents.kt new file mode 100644 index 0000000000..3b98159d1a --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/settings/ignored/IgnoredUsersViewEvents.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2019 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package im.vector.riotx.features.settings.ignored + +import im.vector.riotx.core.platform.VectorViewEvents + +/** + * Transient events for Ignored users screen + */ +sealed class IgnoredUsersViewEvents : VectorViewEvents { + data class Loading(val message: CharSequence? = null) : IgnoredUsersViewEvents() + data class Failure(val throwable: Throwable) : IgnoredUsersViewEvents() +} diff --git a/vector/src/main/java/im/vector/riotx/features/settings/ignored/IgnoredUsersViewModel.kt b/vector/src/main/java/im/vector/riotx/features/settings/ignored/IgnoredUsersViewModel.kt index e77660746c..e9c02618b0 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/ignored/IgnoredUsersViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/ignored/IgnoredUsersViewModel.kt @@ -16,14 +16,21 @@ package im.vector.riotx.features.settings.ignored -import com.airbnb.mvrx.* +import com.airbnb.mvrx.Async +import com.airbnb.mvrx.Fail +import com.airbnb.mvrx.FragmentViewModelContext +import com.airbnb.mvrx.Loading +import com.airbnb.mvrx.MvRxState +import com.airbnb.mvrx.MvRxViewModelFactory +import com.airbnb.mvrx.Success +import com.airbnb.mvrx.Uninitialized +import com.airbnb.mvrx.ViewModelContext import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.AssistedInject import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.api.session.user.model.User import im.vector.matrix.rx.rx -import im.vector.riotx.core.extensions.postLiveEvent import im.vector.riotx.core.platform.VectorViewModel import im.vector.riotx.core.platform.VectorViewModelAction @@ -38,7 +45,7 @@ sealed class IgnoredUsersAction : VectorViewModelAction { class IgnoredUsersViewModel @AssistedInject constructor(@Assisted initialState: IgnoredUsersViewState, private val session: Session) - : VectorViewModel(initialState) { + : VectorViewModel(initialState) { @AssistedInject.Factory interface Factory { @@ -89,7 +96,7 @@ class IgnoredUsersViewModel @AssistedInject constructor(@Assisted initialState: ) } - _requestErrorLiveData.postLiveEvent(failure) + _viewEvents.post(IgnoredUsersViewEvents.Failure(failure)) } override fun onSuccess(data: Unit) { diff --git a/vector/src/main/java/im/vector/riotx/features/settings/ignored/VectorSettingsIgnoredUsersFragment.kt b/vector/src/main/java/im/vector/riotx/features/settings/ignored/VectorSettingsIgnoredUsersFragment.kt index d7069ce9f9..66cad6f247 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/ignored/VectorSettingsIgnoredUsersFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/ignored/VectorSettingsIgnoredUsersFragment.kt @@ -27,9 +27,9 @@ import com.airbnb.mvrx.withState import im.vector.riotx.R import im.vector.riotx.core.extensions.cleanup import im.vector.riotx.core.extensions.configureWith -import im.vector.riotx.core.extensions.observeEvent import im.vector.riotx.core.platform.VectorBaseActivity import im.vector.riotx.core.platform.VectorBaseFragment +import io.reactivex.android.schedulers.AndroidSchedulers import kotlinx.android.synthetic.main.fragment_generic_recycler.* import kotlinx.android.synthetic.main.merge_overlay_waiting_view.* import javax.inject.Inject @@ -41,7 +41,7 @@ class VectorSettingsIgnoredUsersFragment @Inject constructor( override fun getLayoutResId() = R.layout.fragment_generic_recycler - private val ignoredUsersViewModel: IgnoredUsersViewModel by fragmentViewModel() + private val viewModel: IgnoredUsersViewModel by fragmentViewModel() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -50,9 +50,17 @@ class VectorSettingsIgnoredUsersFragment @Inject constructor( waiting_view_status_text.isVisible = true ignoredUsersController.callback = this recyclerView.configureWith(ignoredUsersController) - ignoredUsersViewModel.requestErrorLiveData.observeEvent(this) { - displayErrorDialog(it) - } + viewModel.viewEvents + .observe() + .observeOn(AndroidSchedulers.mainThread()) + .subscribe { + dismissLoadingDialog() + when (it) { + is IgnoredUsersViewEvents.Loading -> showLoading(it.message) + is IgnoredUsersViewEvents.Failure -> showFailure(it.throwable) + } + } + .disposeOnDestroyView() } override fun onDestroyView() { @@ -71,7 +79,7 @@ class VectorSettingsIgnoredUsersFragment @Inject constructor( AlertDialog.Builder(requireActivity()) .setMessage(getString(R.string.settings_unignore_user, userId)) .setPositiveButton(R.string.yes) { _, _ -> - ignoredUsersViewModel.handle(IgnoredUsersAction.UnIgnore(userId)) + viewModel.handle(IgnoredUsersAction.UnIgnore(userId)) } .setNegativeButton(R.string.no, null) .show() @@ -81,7 +89,7 @@ class VectorSettingsIgnoredUsersFragment @Inject constructor( // ignored users list management // ============================================================================================================== - override fun invalidate() = withState(ignoredUsersViewModel) { state -> + override fun invalidate() = withState(viewModel) { state -> ignoredUsersController.update(state) handleUnIgnoreRequestStatus(state.unIgnoreRequest) diff --git a/vector/src/main/java/im/vector/riotx/features/settings/push/PushGatewaysViewModel.kt b/vector/src/main/java/im/vector/riotx/features/settings/push/PushGatewaysViewModel.kt index db4586dff5..672e8e7874 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/push/PushGatewaysViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/push/PushGatewaysViewModel.kt @@ -16,13 +16,19 @@ package im.vector.riotx.features.settings.push -import com.airbnb.mvrx.* +import com.airbnb.mvrx.Async +import com.airbnb.mvrx.FragmentViewModelContext +import com.airbnb.mvrx.MvRxState +import com.airbnb.mvrx.MvRxViewModelFactory +import com.airbnb.mvrx.Uninitialized +import com.airbnb.mvrx.ViewModelContext import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.AssistedInject import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.api.session.pushers.Pusher import im.vector.matrix.rx.RxSession import im.vector.riotx.core.platform.EmptyAction +import im.vector.riotx.core.platform.EmptyViewEvents import im.vector.riotx.core.platform.VectorViewModel data class PushGatewayViewState( @@ -31,7 +37,7 @@ data class PushGatewayViewState( class PushGatewaysViewModel @AssistedInject constructor(@Assisted initialState: PushGatewayViewState, private val session: Session) - : VectorViewModel(initialState) { + : VectorViewModel(initialState) { @AssistedInject.Factory interface Factory { diff --git a/vector/src/main/java/im/vector/riotx/features/settings/push/PushRulesViewModel.kt b/vector/src/main/java/im/vector/riotx/features/settings/push/PushRulesViewModel.kt index e376b7ed6f..3c71238b33 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/push/PushRulesViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/push/PushRulesViewModel.kt @@ -21,6 +21,7 @@ import com.airbnb.mvrx.ViewModelContext import im.vector.matrix.android.api.pushrules.rest.PushRule import im.vector.riotx.core.di.HasScreenInjector import im.vector.riotx.core.platform.EmptyAction +import im.vector.riotx.core.platform.EmptyViewEvents import im.vector.riotx.core.platform.VectorViewModel data class PushRulesViewState( @@ -28,7 +29,7 @@ data class PushRulesViewState( ) : MvRxState class PushRulesViewModel(initialState: PushRulesViewState) - : VectorViewModel(initialState) { + : VectorViewModel(initialState) { companion object : MvRxViewModelFactory { diff --git a/vector/src/main/java/im/vector/riotx/features/share/IncomingShareViewModel.kt b/vector/src/main/java/im/vector/riotx/features/share/IncomingShareViewModel.kt index bfe08a5c52..37b429d3d7 100644 --- a/vector/src/main/java/im/vector/riotx/features/share/IncomingShareViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/share/IncomingShareViewModel.kt @@ -26,6 +26,7 @@ import im.vector.matrix.android.api.session.room.roomSummaryQueryParams import im.vector.matrix.rx.rx import im.vector.riotx.ActiveSessionDataSource import im.vector.riotx.core.platform.EmptyAction +import im.vector.riotx.core.platform.EmptyViewEvents import im.vector.riotx.core.platform.VectorViewModel import io.reactivex.Observable import io.reactivex.android.schedulers.AndroidSchedulers @@ -39,7 +40,7 @@ data class IncomingShareState(private val dummy: Boolean = false) : MvRxState class IncomingShareViewModel @AssistedInject constructor(@Assisted initialState: IncomingShareState, private val sessionObservableStore: ActiveSessionDataSource, private val shareRoomListObservableStore: ShareRoomListDataSource) - : VectorViewModel(initialState) { + : VectorViewModel(initialState) { @AssistedInject.Factory interface Factory { diff --git a/vector/src/main/java/im/vector/riotx/features/signout/soft/SoftLogoutActivity.kt b/vector/src/main/java/im/vector/riotx/features/signout/soft/SoftLogoutActivity.kt index 8d61fb00b5..96dbbaf102 100644 --- a/vector/src/main/java/im/vector/riotx/features/signout/soft/SoftLogoutActivity.kt +++ b/vector/src/main/java/im/vector/riotx/features/signout/soft/SoftLogoutActivity.kt @@ -73,7 +73,7 @@ class SoftLogoutActivity : LoginActivity() { private fun handleSoftLogoutViewEvents(softLogoutViewEvents: SoftLogoutViewEvents) { when (softLogoutViewEvents) { - is SoftLogoutViewEvents.Error -> + is SoftLogoutViewEvents.Failure -> showError(errorFormatter.toHumanReadable(softLogoutViewEvents.throwable)) is SoftLogoutViewEvents.ErrorNotSameUser -> { // Pop the backstack diff --git a/vector/src/main/java/im/vector/riotx/features/signout/soft/SoftLogoutViewEvents.kt b/vector/src/main/java/im/vector/riotx/features/signout/soft/SoftLogoutViewEvents.kt index 1e48fb2a25..314d6b0747 100644 --- a/vector/src/main/java/im/vector/riotx/features/signout/soft/SoftLogoutViewEvents.kt +++ b/vector/src/main/java/im/vector/riotx/features/signout/soft/SoftLogoutViewEvents.kt @@ -17,11 +17,14 @@ package im.vector.riotx.features.signout.soft +import im.vector.riotx.core.platform.VectorViewEvents + /** * Transient events for SoftLogout */ -sealed class SoftLogoutViewEvents { +sealed class SoftLogoutViewEvents : VectorViewEvents { + data class Failure(val throwable: Throwable) : SoftLogoutViewEvents() + data class ErrorNotSameUser(val currentUserId: String, val newUserId: String) : SoftLogoutViewEvents() - data class Error(val throwable: Throwable) : SoftLogoutViewEvents() object ClearData : SoftLogoutViewEvents() } diff --git a/vector/src/main/java/im/vector/riotx/features/signout/soft/SoftLogoutViewModel.kt b/vector/src/main/java/im/vector/riotx/features/signout/soft/SoftLogoutViewModel.kt index baf208636b..5ee7b6e8a3 100644 --- a/vector/src/main/java/im/vector/riotx/features/signout/soft/SoftLogoutViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/signout/soft/SoftLogoutViewModel.kt @@ -16,7 +16,13 @@ package im.vector.riotx.features.signout.soft -import com.airbnb.mvrx.* +import com.airbnb.mvrx.ActivityViewModelContext +import com.airbnb.mvrx.Fail +import com.airbnb.mvrx.Loading +import com.airbnb.mvrx.MvRxViewModelFactory +import com.airbnb.mvrx.Success +import com.airbnb.mvrx.Uninitialized +import com.airbnb.mvrx.ViewModelContext import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.AssistedInject import im.vector.matrix.android.api.MatrixCallback @@ -28,8 +34,6 @@ import im.vector.matrix.android.internal.auth.data.LoginFlowTypes import im.vector.riotx.core.di.ActiveSessionHolder import im.vector.riotx.core.extensions.hasUnsavedKeys import im.vector.riotx.core.platform.VectorViewModel -import im.vector.riotx.core.utils.DataSource -import im.vector.riotx.core.utils.PublishDataSource import im.vector.riotx.features.login.LoginMode import timber.log.Timber @@ -41,7 +45,7 @@ class SoftLogoutViewModel @AssistedInject constructor( private val session: Session, private val activeSessionHolder: ActiveSessionHolder, private val authenticationService: AuthenticationService -) : VectorViewModel(initialState) { +) : VectorViewModel(initialState) { @AssistedInject.Factory interface Factory { @@ -71,9 +75,6 @@ class SoftLogoutViewModel @AssistedInject constructor( private var currentTask: Cancelable? = null - private val _viewEvents = PublishDataSource() - val viewEvents: DataSource = _viewEvents - init { // Get the supported login flow getSupportedLoginFlow() @@ -192,7 +193,7 @@ class SoftLogoutViewModel @AssistedInject constructor( currentTask = session.updateCredentials(action.credentials, object : MatrixCallback { override fun onFailure(failure: Throwable) { - _viewEvents.post(SoftLogoutViewEvents.Error(failure)) + _viewEvents.post(SoftLogoutViewEvents.Failure(failure)) setState { copy( asyncLoginAction = Uninitialized