From cb275aee37e92c7dff90fc3270f807b45d900b8c Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 24 Oct 2019 19:11:49 +0200 Subject: [PATCH] Room list actions: start showing items and refact a bit RxStore --- .../riotx/ActiveSessionObservableStore.kt | 4 +- .../vector/riotx/core/di/ViewModelModule.kt | 14 ----- .../bottomsheet}/BottomSheetItemAction.kt | 5 +- .../BottomSheetItemMessagePreview.kt | 12 ++-- .../BottomSheetItemQuickReactions.kt | 5 +- .../bottomsheet/BottomSheetItemRoomPreview.kt | 57 +++++++++++++++++++ .../bottomsheet}/BottomSheetItemSendState.kt | 5 +- .../bottomsheet}/BottomSheetItemSeparator.kt | 5 +- .../riotx/core/mvrx/NavigationViewModel.kt | 34 ----------- .../riotx/core/platform/VectorViewModel.kt | 1 + .../im/vector/riotx/core/utils/RxStore.kt | 34 ++++++++++- .../riotx/features/home/HomeActivity.kt | 20 ++++--- .../riotx/features/home/HomeDetailFragment.kt | 2 +- .../features/home/HomeNavigationViewModel.kt | 8 ++- .../home/HomeRoomListObservableStore.kt | 4 +- .../createdirect/CreateDirectRoomActivity.kt | 17 +++--- .../CreateDirectRoomDirectoryUsersFragment.kt | 4 +- .../CreateDirectRoomKnownUsersFragment.kt | 2 +- .../CreateDirectRoomNavigationViewModel.kt | 8 ++- .../features/home/group/GroupListFragment.kt | 2 +- .../features/home/group/SelectedGroupStore.kt | 4 +- .../home/room/detail/RoomDetailFragment.kt | 15 +++-- .../action/MessageActionsBottomSheet.kt | 6 +- .../action/MessageActionsEpoxyController.kt | 9 ++- ...tionsHandler.kt => MessageActionsStore.kt} | 17 ++---- .../home/room/list/RoomListActions.kt | 2 + .../home/room/list/RoomListFragment.kt | 21 +++++++ .../home/room/list/RoomListViewModel.kt | 25 ++++++-- .../room/list/actions/RoomListQuickActions.kt | 20 +++++++ .../RoomListQuickActionsBottomSheet.kt | 8 ++- .../RoomListQuickActionsEpoxyController.kt | 47 +++++++++++---- .../list/actions/RoomListQuickActionsState.kt | 3 +- .../list/actions/RoomListQuickActionsStore.kt | 28 +++++++++ .../actions/RoomListQuickActionsViewModel.kt | 23 ++++++-- .../features/navigation/DefaultNavigator.kt | 5 ++ .../riotx/features/navigation/Navigator.kt | 3 + .../roomdirectory/PublicRoomsFragment.kt | 4 +- .../roomdirectory/RoomDirectoryActivity.kt | 18 +++--- .../RoomDirectoryNavigationViewModel.kt | 8 ++- .../createroom/CreateRoomActivity.kt | 14 +++-- .../createroom/CreateRoomFragment.kt | 4 +- .../picker/RoomDirectoryPickerFragment.kt | 2 +- .../res/drawable/ic_room_actions_leave.xml | 47 +++++++++++++++ .../ic_room_actions_notifications_all.xml | 39 +++++++++++++ ...c_room_actions_notifications_all_noisy.xml | 39 +++++++++++++ ...ic_room_actions_notifications_mentions.xml | 47 +++++++++++++++ .../ic_room_actions_notifications_mutes.xml | 47 +++++++++++++++ .../res/drawable/ic_room_actions_settings.xml | 39 +++++++++++++ .../layout/item_bottom_sheet_room_preview.xml | 57 +++++++++++++++++++ vector/src/main/res/values/strings_riotX.xml | 7 ++- 50 files changed, 683 insertions(+), 168 deletions(-) rename vector/src/main/java/im/vector/riotx/{features/home/room/detail/timeline/action => core/epoxy/bottomsheet}/BottomSheetItemAction.kt (94%) rename vector/src/main/java/im/vector/riotx/{features/home/room/detail/timeline/action => core/epoxy/bottomsheet}/BottomSheetItemMessagePreview.kt (84%) rename vector/src/main/java/im/vector/riotx/{features/home/room/detail/timeline/action => core/epoxy/bottomsheet}/BottomSheetItemQuickReactions.kt (96%) create mode 100644 vector/src/main/java/im/vector/riotx/core/epoxy/bottomsheet/BottomSheetItemRoomPreview.kt rename vector/src/main/java/im/vector/riotx/{features/home/room/detail/timeline/action => core/epoxy/bottomsheet}/BottomSheetItemSendState.kt (93%) rename vector/src/main/java/im/vector/riotx/{features/home/room/detail/timeline/action => core/epoxy/bottomsheet}/BottomSheetItemSeparator.kt (88%) delete mode 100644 vector/src/main/java/im/vector/riotx/core/mvrx/NavigationViewModel.kt rename vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/{ActionsHandler.kt => MessageActionsStore.kt} (65%) create mode 100644 vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsStore.kt create mode 100644 vector/src/main/res/drawable/ic_room_actions_leave.xml create mode 100644 vector/src/main/res/drawable/ic_room_actions_notifications_all.xml create mode 100644 vector/src/main/res/drawable/ic_room_actions_notifications_all_noisy.xml create mode 100644 vector/src/main/res/drawable/ic_room_actions_notifications_mentions.xml create mode 100644 vector/src/main/res/drawable/ic_room_actions_notifications_mutes.xml create mode 100644 vector/src/main/res/drawable/ic_room_actions_settings.xml create mode 100644 vector/src/main/res/layout/item_bottom_sheet_room_preview.xml diff --git a/vector/src/main/java/im/vector/riotx/ActiveSessionObservableStore.kt b/vector/src/main/java/im/vector/riotx/ActiveSessionObservableStore.kt index fd6a92e820..cb89497577 100644 --- a/vector/src/main/java/im/vector/riotx/ActiveSessionObservableStore.kt +++ b/vector/src/main/java/im/vector/riotx/ActiveSessionObservableStore.kt @@ -19,9 +19,9 @@ package im.vector.riotx import arrow.core.Option import im.vector.matrix.android.api.session.Session -import im.vector.riotx.core.utils.RxStore +import im.vector.riotx.core.utils.BehaviorStore import javax.inject.Inject import javax.inject.Singleton @Singleton -class ActiveSessionObservableStore @Inject constructor() : RxStore>() +class ActiveSessionObservableStore @Inject constructor() : BehaviorStore>() diff --git a/vector/src/main/java/im/vector/riotx/core/di/ViewModelModule.kt b/vector/src/main/java/im/vector/riotx/core/di/ViewModelModule.kt index 98c89c421a..83aa7103d9 100644 --- a/vector/src/main/java/im/vector/riotx/core/di/ViewModelModule.kt +++ b/vector/src/main/java/im/vector/riotx/core/di/ViewModelModule.kt @@ -76,16 +76,6 @@ interface ViewModelModule { @ViewModelKey(KeysBackupRestoreFromPassphraseViewModel::class) fun bindKeysBackupRestoreFromPassphraseViewModel(viewModel: KeysBackupRestoreFromPassphraseViewModel): ViewModel - @Binds - @IntoMap - @ViewModelKey(RoomDirectoryNavigationViewModel::class) - fun bindRoomDirectoryNavigationViewModel(viewModel: RoomDirectoryNavigationViewModel): ViewModel - - @Binds - @IntoMap - @ViewModelKey(HomeNavigationViewModel::class) - fun bindHomeNavigationViewModel(viewModel: HomeNavigationViewModel): ViewModel - @Binds @IntoMap @ViewModelKey(KeysBackupSetupSharedViewModel::class) @@ -96,8 +86,4 @@ interface ViewModelModule { @ViewModelKey(ConfigurationViewModel::class) fun bindConfigurationViewModel(viewModel: ConfigurationViewModel): ViewModel - @Binds - @IntoMap - @ViewModelKey(CreateDirectRoomNavigationViewModel::class) - fun bindCreateDirectRoomNavigationViewModel(viewModel: CreateDirectRoomNavigationViewModel): ViewModel } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/BottomSheetItemAction.kt b/vector/src/main/java/im/vector/riotx/core/epoxy/bottomsheet/BottomSheetItemAction.kt similarity index 94% rename from vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/BottomSheetItemAction.kt rename to vector/src/main/java/im/vector/riotx/core/epoxy/bottomsheet/BottomSheetItemAction.kt index d0d5b1deea..1099243ace 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/BottomSheetItemAction.kt +++ b/vector/src/main/java/im/vector/riotx/core/epoxy/bottomsheet/BottomSheetItemAction.kt @@ -5,15 +5,16 @@ * 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 + * 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.home.room.detail.timeline.action +package im.vector.riotx.core.epoxy.bottomsheet import android.view.View import android.widget.ImageView diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/BottomSheetItemMessagePreview.kt b/vector/src/main/java/im/vector/riotx/core/epoxy/bottomsheet/BottomSheetItemMessagePreview.kt similarity index 84% rename from vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/BottomSheetItemMessagePreview.kt rename to vector/src/main/java/im/vector/riotx/core/epoxy/bottomsheet/BottomSheetItemMessagePreview.kt index d37aa43770..999068b289 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/BottomSheetItemMessagePreview.kt +++ b/vector/src/main/java/im/vector/riotx/core/epoxy/bottomsheet/BottomSheetItemMessagePreview.kt @@ -5,15 +5,16 @@ * 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 + * 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.home.room.detail.timeline.action +package im.vector.riotx.core.epoxy.bottomsheet import android.widget.ImageView import android.widget.TextView @@ -24,7 +25,6 @@ import im.vector.riotx.core.epoxy.VectorEpoxyHolder import im.vector.riotx.core.epoxy.VectorEpoxyModel import im.vector.riotx.core.extensions.setTextOrHide import im.vector.riotx.features.home.AvatarRenderer -import im.vector.riotx.features.home.room.detail.timeline.item.MessageInformationData /** * A message preview for bottom sheet. @@ -35,7 +35,9 @@ abstract class BottomSheetItemMessagePreview : VectorEpoxyModel() { + + @EpoxyAttribute + lateinit var avatarRenderer: AvatarRenderer + @EpoxyAttribute + lateinit var avatarUrl: String + @EpoxyAttribute + lateinit var roomId: String + @EpoxyAttribute + var roomName: String? = null + @EpoxyAttribute var settingsClickListener: View.OnClickListener? = null + + override fun bind(holder: Holder) { + avatarRenderer.render(avatarUrl, roomId, roomName, holder.avatar) + holder.roomName.setTextOrHide(roomName) + holder.roomSettings.setOnClickListener(settingsClickListener) + } + + class Holder : VectorEpoxyHolder() { + val avatar by bind(R.id.bottomSheetRoomPreviewAvatar) + val roomName by bind(R.id.bottomSheetRoomPreviewName) + val roomSettings by bind(R.id.bottomSheetRoomPreviewSettings) + } +} diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/BottomSheetItemSendState.kt b/vector/src/main/java/im/vector/riotx/core/epoxy/bottomsheet/BottomSheetItemSendState.kt similarity index 93% rename from vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/BottomSheetItemSendState.kt rename to vector/src/main/java/im/vector/riotx/core/epoxy/bottomsheet/BottomSheetItemSendState.kt index 86a5512349..08d727cfa9 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/BottomSheetItemSendState.kt +++ b/vector/src/main/java/im/vector/riotx/core/epoxy/bottomsheet/BottomSheetItemSendState.kt @@ -5,15 +5,16 @@ * 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 + * 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.home.room.detail.timeline.action +package im.vector.riotx.core.epoxy.bottomsheet import android.view.View import android.widget.TextView diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/BottomSheetItemSeparator.kt b/vector/src/main/java/im/vector/riotx/core/epoxy/bottomsheet/BottomSheetItemSeparator.kt similarity index 88% rename from vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/BottomSheetItemSeparator.kt rename to vector/src/main/java/im/vector/riotx/core/epoxy/bottomsheet/BottomSheetItemSeparator.kt index f09f68b714..fddf507bf9 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/BottomSheetItemSeparator.kt +++ b/vector/src/main/java/im/vector/riotx/core/epoxy/bottomsheet/BottomSheetItemSeparator.kt @@ -5,15 +5,16 @@ * 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 + * 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.home.room.detail.timeline.action +package im.vector.riotx.core.epoxy.bottomsheet import com.airbnb.epoxy.EpoxyModelClass import im.vector.riotx.R diff --git a/vector/src/main/java/im/vector/riotx/core/mvrx/NavigationViewModel.kt b/vector/src/main/java/im/vector/riotx/core/mvrx/NavigationViewModel.kt deleted file mode 100644 index 3491f8d340..0000000000 --- a/vector/src/main/java/im/vector/riotx/core/mvrx/NavigationViewModel.kt +++ /dev/null @@ -1,34 +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.riotx.core.mvrx - -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel -import im.vector.riotx.core.extensions.postLiveEvent -import im.vector.riotx.core.utils.LiveEvent - -abstract class NavigationViewModel : ViewModel() { - - private val _navigateTo = MutableLiveData>() - val navigateTo: LiveData> - get() = _navigateTo - - fun goTo(navigation: NavigationClass) { - _navigateTo.postLiveEvent(navigation) - } -} 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 9679c20efb..7f04f184a8 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 @@ -44,4 +44,5 @@ abstract class VectorViewModel(initialState: S) .onErrorReturn { Fail(it) } .doOnNext { setState { stateReducer(it) } } } + } diff --git a/vector/src/main/java/im/vector/riotx/core/utils/RxStore.kt b/vector/src/main/java/im/vector/riotx/core/utils/RxStore.kt index b539ade931..0bac82e58e 100644 --- a/vector/src/main/java/im/vector/riotx/core/utils/RxStore.kt +++ b/vector/src/main/java/im/vector/riotx/core/utils/RxStore.kt @@ -17,18 +17,30 @@ package im.vector.riotx.core.utils import com.jakewharton.rxrelay2.BehaviorRelay +import com.jakewharton.rxrelay2.PublishRelay import io.reactivex.Observable import io.reactivex.schedulers.Schedulers -open class RxStore(private val defaultValue: T? = null) { +/** + * An interface to handle InMemory Rx Store from which you can post or observe values. + */ +interface RxStore { + fun observe(): Observable + fun post(value: T) +} + +/** + * This store emits the most recent value it has observed and all subsequent observed values to each subscriber. + */ +open class BehaviorStore(private val defaultValue: T? = null) : RxStore { private val storeRelay = createRelay() - fun observe(): Observable { + override fun observe(): Observable { return storeRelay.hide().observeOn(Schedulers.computation()) } - fun post(value: T) { + override fun post(value: T) { storeRelay.accept(value) } @@ -40,3 +52,19 @@ open class RxStore(private val defaultValue: T? = null) { } } } + +/** + * This store only emits all subsequent observed values to each subscriber. + */ +open class PublishStore : RxStore { + + private val storeRelay = PublishRelay.create() + + override fun observe(): Observable { + return storeRelay.hide() + } + + override fun post(value: T) { + storeRelay.accept(value) + } +} diff --git a/vector/src/main/java/im/vector/riotx/features/home/HomeActivity.kt b/vector/src/main/java/im/vector/riotx/features/home/HomeActivity.kt index af367164fc..e552af0095 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/HomeActivity.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/HomeActivity.kt @@ -85,16 +85,18 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable { replaceFragment(homeDrawerFragment, R.id.homeDrawerFragmentContainer) } - navigationViewModel.navigateTo.observeEvent(this) { navigation -> - when (navigation) { - is Navigation.OpenDrawer -> drawerLayout.openDrawer(GravityCompat.START) - is Navigation.OpenGroup -> { - drawerLayout.closeDrawer(GravityCompat.START) - val homeDetailFragment = HomeDetailFragment.newInstance() - replaceFragment(homeDetailFragment, R.id.homeDetailFragmentContainer) + navigationViewModel.observe() + .subscribe { navigation -> + when (navigation) { + is Navigation.OpenDrawer -> drawerLayout.openDrawer(GravityCompat.START) + is Navigation.OpenGroup -> { + drawerLayout.closeDrawer(GravityCompat.START) + val homeDetailFragment = HomeDetailFragment.newInstance() + replaceFragment(homeDetailFragment, R.id.homeDetailFragmentContainer) + } + } } - } - } + .disposeOnDestroy() if (intent.getBooleanExtra(EXTRA_CLEAR_EXISTING_NOTIFICATION, false)) { notificationDrawerManager.clearAllEvents() diff --git a/vector/src/main/java/im/vector/riotx/features/home/HomeDetailFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/HomeDetailFragment.kt index 844fd4f5b2..5bb427188e 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/HomeDetailFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/HomeDetailFragment.kt @@ -133,7 +133,7 @@ class HomeDetailFragment : VectorBaseFragment(), KeysBackupBanner.Delegate { } groupToolbar.title = "" groupToolbarAvatarImageView.setOnClickListener { - navigationViewModel.goTo(HomeActivity.Navigation.OpenDrawer) + navigationViewModel.post(HomeActivity.Navigation.OpenDrawer) } } diff --git a/vector/src/main/java/im/vector/riotx/features/home/HomeNavigationViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/HomeNavigationViewModel.kt index e1ab437060..122eee1833 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/HomeNavigationViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/HomeNavigationViewModel.kt @@ -16,7 +16,9 @@ package im.vector.riotx.features.home -import im.vector.riotx.core.mvrx.NavigationViewModel -import javax.inject.Inject +import androidx.lifecycle.ViewModel +import im.vector.riotx.core.utils.PublishStore +import im.vector.riotx.core.utils.RxStore -class HomeNavigationViewModel @Inject constructor() : NavigationViewModel() +class HomeNavigationViewModel(private val store: RxStore = PublishStore()) + : ViewModel(), RxStore by store diff --git a/vector/src/main/java/im/vector/riotx/features/home/HomeRoomListObservableStore.kt b/vector/src/main/java/im/vector/riotx/features/home/HomeRoomListObservableStore.kt index df8cd411bb..6b43af4bfc 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/HomeRoomListObservableStore.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/HomeRoomListObservableStore.kt @@ -17,9 +17,9 @@ package im.vector.riotx.features.home import im.vector.matrix.android.api.session.room.model.RoomSummary -import im.vector.riotx.core.utils.RxStore +import im.vector.riotx.core.utils.BehaviorStore import javax.inject.Inject import javax.inject.Singleton @Singleton -class HomeRoomListObservableStore @Inject constructor() : RxStore>() +class HomeRoomListObservableStore @Inject constructor() : BehaviorStore>() diff --git a/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomActivity.kt b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomActivity.kt index a94b2b85da..2b4322a87c 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomActivity.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomActivity.kt @@ -59,13 +59,16 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() { super.onCreate(savedInstanceState) toolbar.visibility = View.GONE navigationViewModel = ViewModelProviders.of(this, viewModelFactory).get(CreateDirectRoomNavigationViewModel::class.java) - navigationViewModel.navigateTo.observeEvent(this) { navigation -> - when (navigation) { - is Navigation.UsersDirectory -> addFragmentToBackstack(CreateDirectRoomDirectoryUsersFragment(), R.id.container) - Navigation.Close -> finish() - Navigation.Previous -> onBackPressed() - } - } + navigationViewModel + .observe() + .subscribe { navigation -> + when (navigation) { + is Navigation.UsersDirectory -> addFragmentToBackstack(CreateDirectRoomDirectoryUsersFragment(), R.id.container) + Navigation.Close -> finish() + Navigation.Previous -> onBackPressed() + } + } + .disposeOnDestroy() if (isFirstCreation()) { addFragment(CreateDirectRoomKnownUsersFragment(), R.id.container) } diff --git a/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomDirectoryUsersFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomDirectoryUsersFragment.kt index 6125d1b6b9..ca4b26ced8 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomDirectoryUsersFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomDirectoryUsersFragment.kt @@ -74,7 +74,7 @@ class CreateDirectRoomDirectoryUsersFragment : VectorBaseFragment(), DirectoryUs private fun setupCloseView() { createDirectRoomClose.setOnClickListener { - navigationViewModel.goTo(CreateDirectRoomActivity.Navigation.Previous) + navigationViewModel.post(CreateDirectRoomActivity.Navigation.Previous) } } @@ -85,7 +85,7 @@ class CreateDirectRoomDirectoryUsersFragment : VectorBaseFragment(), DirectoryUs override fun onItemClick(user: User) { view?.hideKeyboard() viewModel.handle(CreateDirectRoomActions.SelectUser(user)) - navigationViewModel.goTo(CreateDirectRoomActivity.Navigation.Previous) + navigationViewModel.post(CreateDirectRoomActivity.Navigation.Previous) } override fun retryDirectoryUsersRequest() { diff --git a/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomKnownUsersFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomKnownUsersFragment.kt index 04e8d16fd7..124ca018d1 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomKnownUsersFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomKnownUsersFragment.kt @@ -96,7 +96,7 @@ class CreateDirectRoomKnownUsersFragment : VectorBaseFragment(), KnownUsersContr private fun setupAddByMatrixIdView() { addByMatrixId.setOnClickListener { - navigationViewModel.goTo(CreateDirectRoomActivity.Navigation.UsersDirectory) + navigationViewModel.post(CreateDirectRoomActivity.Navigation.UsersDirectory) } } diff --git a/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomNavigationViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomNavigationViewModel.kt index e57d58a137..d120c306fb 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomNavigationViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomNavigationViewModel.kt @@ -16,7 +16,9 @@ package im.vector.riotx.features.home.createdirect -import im.vector.riotx.core.mvrx.NavigationViewModel -import javax.inject.Inject +import androidx.lifecycle.ViewModel +import im.vector.riotx.core.utils.PublishStore +import im.vector.riotx.core.utils.RxStore -class CreateDirectRoomNavigationViewModel @Inject constructor(): NavigationViewModel() +class CreateDirectRoomNavigationViewModel(private val store: RxStore = PublishStore()) + : ViewModel(), RxStore by store diff --git a/vector/src/main/java/im/vector/riotx/features/home/group/GroupListFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/group/GroupListFragment.kt index 54c2044ae4..77f34d7854 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/group/GroupListFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/group/GroupListFragment.kt @@ -60,7 +60,7 @@ class GroupListFragment : VectorBaseFragment(), GroupSummaryController.Callback groupListEpoxyRecyclerView.setController(groupController) viewModel.subscribe { renderState(it) } viewModel.openGroupLiveData.observeEvent(this) { - navigationViewModel.goTo(HomeActivity.Navigation.OpenGroup) + navigationViewModel.post(HomeActivity.Navigation.OpenGroup) } } diff --git a/vector/src/main/java/im/vector/riotx/features/home/group/SelectedGroupStore.kt b/vector/src/main/java/im/vector/riotx/features/home/group/SelectedGroupStore.kt index a6291ecbb5..a74f24c1d5 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/group/SelectedGroupStore.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/group/SelectedGroupStore.kt @@ -18,9 +18,9 @@ package im.vector.riotx.features.home.group import arrow.core.Option import im.vector.matrix.android.api.session.group.model.GroupSummary -import im.vector.riotx.core.utils.RxStore +import im.vector.riotx.core.utils.BehaviorStore import javax.inject.Inject import javax.inject.Singleton @Singleton -class SelectedGroupStore @Inject constructor() : RxStore>(Option.empty()) +class SelectedGroupStore @Inject constructor() : BehaviorStore>(Option.empty()) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt index 7c4437d6f0..a525e7acc6 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt @@ -100,8 +100,8 @@ import im.vector.riotx.features.home.room.detail.composer.TextComposerViewModel import im.vector.riotx.features.home.room.detail.composer.TextComposerViewState import im.vector.riotx.features.home.room.detail.readreceipts.DisplayReadReceiptsBottomSheet import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController -import im.vector.riotx.features.home.room.detail.timeline.action.ActionsHandler import im.vector.riotx.features.home.room.detail.timeline.action.MessageActionsBottomSheet +import im.vector.riotx.features.home.room.detail.timeline.action.MessageActionsStore import im.vector.riotx.features.home.room.detail.timeline.action.SimpleAction import im.vector.riotx.features.home.room.detail.timeline.edithistory.ViewEditHistoryBottomSheet import im.vector.riotx.features.home.room.detail.timeline.item.* @@ -202,7 +202,7 @@ class RoomDetailFragment : override fun getMenuRes() = R.menu.menu_timeline - private lateinit var actionViewModel: ActionsHandler + private lateinit var messageActionsStore: MessageActionsStore private lateinit var layoutManager: LinearLayoutManager private lateinit var attachmentsHelper: AttachmentsHelper private lateinit var keyboardStateUtils: KeyboardStateUtils @@ -219,7 +219,7 @@ class RoomDetailFragment : override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) - actionViewModel = ViewModelProviders.of(requireActivity()).get(ActionsHandler::class.java) + messageActionsStore = ViewModelProviders.of(requireActivity()).get(MessageActionsStore::class.java) attachmentsHelper = AttachmentsHelper.create(this, this).register() keyboardStateUtils = KeyboardStateUtils(requireActivity()) setupToolbar(roomToolbar) @@ -238,9 +238,12 @@ class RoomDetailFragment : val message = requireContext().getString(pair.first, *pair.second.toTypedArray()) showSnackWithMessage(message, Snackbar.LENGTH_LONG) } - actionViewModel.actionCommandEvent.observeEvent(this) { - handleActions(it) - } + messageActionsStore + .observe() + .subscribe { + handleActions(it) + } + .disposeOnDestroy() roomDetailViewModel.navigateToEvent.observeEvent(this) { val scrollPosition = timelineEventController.searchPositionOfEvent(it) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsBottomSheet.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsBottomSheet.kt index 8aaa7643c2..2f0e3fab65 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsBottomSheet.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsBottomSheet.kt @@ -47,7 +47,7 @@ class MessageActionsBottomSheet : VectorBaseBottomSheetDialogFragment(), Message override val showExpanded = true - private lateinit var actionHandlerModel: ActionsHandler + private lateinit var messageActionsStore: MessageActionsStore override fun injectWith(screenComponent: ScreenComponent) { screenComponent.inject(this) @@ -61,7 +61,7 @@ class MessageActionsBottomSheet : VectorBaseBottomSheetDialogFragment(), Message override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) - actionHandlerModel = ViewModelProviders.of(requireActivity()).get(ActionsHandler::class.java) + messageActionsStore = ViewModelProviders.of(requireActivity()).get(MessageActionsStore::class.java) recyclerView.layoutManager = LinearLayoutManager(requireContext(), RecyclerView.VERTICAL, false) recyclerView.adapter = messageActionsEpoxyController.adapter // Disable item animation @@ -74,7 +74,7 @@ class MessageActionsBottomSheet : VectorBaseBottomSheetDialogFragment(), Message // Toggle report menu viewModel.toggleReportMenu() } else { - actionHandlerModel.fireAction(simpleAction) + messageActionsStore.post(simpleAction) dismiss() } } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt index d9119f08b3..7fdb286c26 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt @@ -20,6 +20,12 @@ import com.airbnb.epoxy.TypedEpoxyController import com.airbnb.mvrx.Success import im.vector.riotx.EmojiCompatFontProvider import im.vector.riotx.R +import im.vector.riotx.core.epoxy.bottomsheet.BottomSheetItemQuickReactions +import im.vector.riotx.core.epoxy.bottomsheet.bottomSheetItemAction +import im.vector.riotx.core.epoxy.bottomsheet.bottomSheetItemMessagePreview +import im.vector.riotx.core.epoxy.bottomsheet.bottomSheetItemQuickReactions +import im.vector.riotx.core.epoxy.bottomsheet.bottomSheetItemSendState +import im.vector.riotx.core.epoxy.bottomsheet.bottomSheetItemSeparator import im.vector.riotx.core.resources.StringProvider import im.vector.riotx.features.home.AvatarRenderer import javax.inject.Inject @@ -40,7 +46,8 @@ class MessageActionsEpoxyController @Inject constructor(private val stringProvid bottomSheetItemMessagePreview { id("preview") avatarRenderer(avatarRenderer) - informationData(state.informationData) + avatarUrl(state.informationData.avatarUrl ?: "") + senderId(state.informationData.senderId) senderName(state.senderName()) body(body) time(state.time()) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/ActionsHandler.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsStore.kt similarity index 65% rename from vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/ActionsHandler.kt rename to vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsStore.kt index c9284b6ece..5c4c6fed80 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/ActionsHandler.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsStore.kt @@ -15,20 +15,13 @@ */ package im.vector.riotx.features.home.room.detail.timeline.action -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import im.vector.riotx.core.extensions.postLiveEvent -import im.vector.riotx.core.utils.LiveEvent -import javax.inject.Inject +import im.vector.riotx.core.utils.PublishStore +import im.vector.riotx.core.utils.RxStore /** * Activity shared view model to handle message actions */ -class ActionsHandler @Inject constructor() : ViewModel() { - - val actionCommandEvent = MutableLiveData>() - - fun fireAction(action: SimpleAction) { - actionCommandEvent.postLiveEvent(action) - } -} +class MessageActionsStore constructor( + private val store: RxStore = PublishStore() +) : ViewModel(), RxStore by store diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListActions.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListActions.kt index 8271086421..81b26a99d4 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListActions.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListActions.kt @@ -24,5 +24,7 @@ sealed class RoomListActions { data class AcceptInvitation(val roomSummary: RoomSummary) : RoomListActions() data class RejectInvitation(val roomSummary: RoomSummary) : RoomListActions() data class FilterWith(val filter: String) : RoomListActions() + data class ChangeNotificationMode(val notificationMode: String) : RoomListActions() + data class LeaveRoom(val roomId: String) : RoomListActions() object MarkAllRoomsRead : RoomListActions() } 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 76e4ff9e3b..22415fd792 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 @@ -23,6 +23,7 @@ import android.view.MenuItem import androidx.annotation.StringRes import androidx.core.content.ContextCompat import androidx.core.view.isVisible +import androidx.lifecycle.ViewModelProviders import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.airbnb.mvrx.* @@ -39,7 +40,9 @@ import im.vector.riotx.core.extensions.observeEventFirstThrottle import im.vector.riotx.core.platform.OnBackPressed import im.vector.riotx.core.platform.StateView import im.vector.riotx.core.platform.VectorBaseFragment +import im.vector.riotx.features.home.room.list.actions.RoomListQuickActions import im.vector.riotx.features.home.room.list.actions.RoomListQuickActionsBottomSheet +import im.vector.riotx.features.home.room.list.actions.RoomListQuickActionsStore import im.vector.riotx.features.home.room.list.widget.FabMenuView import im.vector.riotx.features.notifications.NotificationDrawerManager import im.vector.riotx.features.share.SharedData @@ -71,6 +74,7 @@ class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Listener, O } } + private lateinit var quickActionsDispatcher: RoomListQuickActionsStore private val roomListParams: RoomListParams by args() @Inject lateinit var roomController: RoomSummaryController @Inject lateinit var roomListViewModelFactory: RoomListViewModel.Factory @@ -106,6 +110,7 @@ class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Listener, O override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) + quickActionsDispatcher = ViewModelProviders.of(requireActivity()).get(RoomListQuickActionsStore::class.java) setupCreateRoomButton() setupRecyclerView() roomListViewModel.subscribe { renderState(it) } @@ -126,6 +131,11 @@ class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Listener, O .show() } } + + quickActionsDispatcher + .observe() + .subscribe { handleQuickActions(it) } + .disposeOnDestroy() } private fun setupCreateRoomButton() { @@ -204,6 +214,17 @@ class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Listener, O } } + private fun handleQuickActions(quickActions: RoomListQuickActions) { + when (quickActions) { + is RoomListQuickActions.NotificationsAllNoisy -> roomListViewModel.accept(RoomListActions.ChangeNotificationMode("")) + is RoomListQuickActions.NotificationsAll -> roomListViewModel.accept(RoomListActions.ChangeNotificationMode("")) + is RoomListQuickActions.NotificationsMentionsOnly -> roomListViewModel.accept(RoomListActions.ChangeNotificationMode("")) + is RoomListQuickActions.NotificationsMute -> roomListViewModel.accept(RoomListActions.ChangeNotificationMode("")) + is RoomListQuickActions.Settings -> navigator.openRoomSettings(requireContext(), quickActions.roomId) + is RoomListQuickActions.Leave -> roomListViewModel.accept(RoomListActions.LeaveRoom(quickActions.roomId)) + } + } + private fun renderState(state: RoomListViewState) { when (state.asyncFilteredRooms) { is Incomplete -> renderLoading() 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 b7a10edd49..c6010f89f0 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 @@ -73,12 +73,14 @@ class RoomListViewModel @AssistedInject constructor(@Assisted initialState: Room fun accept(action: RoomListActions) { when (action) { - is RoomListActions.SelectRoom -> handleSelectRoom(action) - is RoomListActions.ToggleCategory -> handleToggleCategory(action) - is RoomListActions.AcceptInvitation -> handleAcceptInvitation(action) - is RoomListActions.RejectInvitation -> handleRejectInvitation(action) - is RoomListActions.FilterWith -> handleFilter(action) - is RoomListActions.MarkAllRoomsRead -> handleMarkAllRoomsRead() + is RoomListActions.SelectRoom -> handleSelectRoom(action) + is RoomListActions.ToggleCategory -> handleToggleCategory(action) + is RoomListActions.AcceptInvitation -> handleAcceptInvitation(action) + is RoomListActions.RejectInvitation -> handleRejectInvitation(action) + is RoomListActions.FilterWith -> handleFilter(action) + is RoomListActions.MarkAllRoomsRead -> handleMarkAllRoomsRead() + is RoomListActions.LeaveRoom -> handleLeaveRoom(action) + is RoomListActions.ChangeNotificationMode -> handleChangeNotificationMode(action) } } @@ -203,6 +205,17 @@ class RoomListViewModel @AssistedInject constructor(@Assisted initialState: Room ?.let { session.markAllAsRead(it, object : MatrixCallback {}) } } + private fun handleChangeNotificationMode(action: RoomListActions.ChangeNotificationMode) { + //TODO handle this + Timber.v("Not handled yet: $action") + } + + private fun handleLeaveRoom(action: RoomListActions.LeaveRoom) { + session.getRoom(action.roomId)?.also { + it.leave(object : MatrixCallback {}) + } + } + private fun buildRoomSummaries(rooms: List): RoomSummaries { val invites = ArrayList() val favourites = ArrayList() diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActions.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActions.kt index c07d88f85a..30d4abff36 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActions.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActions.kt @@ -18,7 +18,27 @@ package im.vector.riotx.features.home.room.list.actions import androidx.annotation.DrawableRes import androidx.annotation.StringRes +import im.vector.riotx.R sealed class RoomListQuickActions(@StringRes val titleRes: Int, @DrawableRes val iconResId: Int) { + data class NotificationsAllNoisy(val roomId: String) : RoomListQuickActions(R.string.room_settings_all_messages_noisy, R.drawable.ic_room_actions_notifications_all_noisy) + data class NotificationsAll(val roomId: String) : RoomListQuickActions(R.string.room_settings_all_messages, R.drawable.ic_room_actions_notifications_all) + data class NotificationsMentionsOnly(val roomId: String) : RoomListQuickActions(R.string.room_settings_mention_only, R.drawable.ic_room_actions_notifications_mentions) + data class NotificationsMute(val roomId: String) : RoomListQuickActions(R.string.room_settings_mute, R.drawable.ic_room_actions_notifications_mutes) + data class Settings(val roomId: String) : RoomListQuickActions(R.string.room_sliding_menu_settings, R.drawable.ic_room_actions_settings) + data class Leave(val roomId: String) : RoomListQuickActions(R.string.leave, R.drawable.ic_room_actions_leave) + + companion object { + fun all(roomId: String): List { + return listOf( + NotificationsAllNoisy(roomId), + NotificationsAll(roomId), + NotificationsMentionsOnly(roomId), + NotificationsMute(roomId), + Settings(roomId), + Leave(roomId) + ) + } + } } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsBottomSheet.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsBottomSheet.kt index 19fe10de39..03e661eb20 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsBottomSheet.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsBottomSheet.kt @@ -21,6 +21,7 @@ import android.os.Parcelable import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.lifecycle.ViewModelProviders import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import butterknife.BindView @@ -30,6 +31,7 @@ import com.airbnb.mvrx.withState import im.vector.riotx.R import im.vector.riotx.core.di.ScreenComponent import im.vector.riotx.core.platform.VectorBaseBottomSheetDialogFragment +import im.vector.riotx.features.navigation.Navigator import kotlinx.android.parcel.Parcelize import javax.inject.Inject @@ -43,8 +45,10 @@ data class RoomListActionsArgs( */ class RoomListQuickActionsBottomSheet : VectorBaseBottomSheetDialogFragment(), RoomListQuickActionsEpoxyController.Listener { + private lateinit var actionsDispatcher: RoomListQuickActionsStore @Inject lateinit var roomListActionsViewModelFactory: RoomListActionsViewModel.Factory @Inject lateinit var roomListActionsEpoxyController: RoomListQuickActionsEpoxyController + @Inject lateinit var navigator: Navigator private val viewModel: RoomListActionsViewModel by fragmentViewModel(RoomListActionsViewModel::class) @@ -65,6 +69,7 @@ class RoomListQuickActionsBottomSheet : VectorBaseBottomSheetDialogFragment(), R override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) + actionsDispatcher = ViewModelProviders.of(requireActivity()).get(RoomListQuickActionsStore::class.java) recyclerView.layoutManager = LinearLayoutManager(requireContext(), RecyclerView.VERTICAL, false) recyclerView.adapter = roomListActionsEpoxyController.adapter // Disable item animation @@ -79,7 +84,8 @@ class RoomListQuickActionsBottomSheet : VectorBaseBottomSheetDialogFragment(), R } override fun didSelectMenuAction(quickActions: RoomListQuickActions) { - vectorBaseActivity.notImplemented("RoomListQuickActions") + actionsDispatcher.post(quickActions) + dismiss() } companion object { diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsEpoxyController.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsEpoxyController.kt index f4cc774092..f2c71868df 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsEpoxyController.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsEpoxyController.kt @@ -18,10 +18,12 @@ package im.vector.riotx.features.home.room.list.actions import android.view.View import com.airbnb.epoxy.TypedEpoxyController import im.vector.riotx.EmojiCompatFontProvider +import im.vector.riotx.core.date.VectorDateFormatter +import im.vector.riotx.core.epoxy.bottomsheet.BottomSheetItemAction_ +import im.vector.riotx.core.epoxy.bottomsheet.bottomSheetItemRoomPreview +import im.vector.riotx.core.epoxy.bottomsheet.bottomSheetItemSeparator import im.vector.riotx.core.resources.StringProvider import im.vector.riotx.features.home.AvatarRenderer -import im.vector.riotx.features.home.room.detail.timeline.action.bottomSheetItemAction -import im.vector.riotx.features.home.room.detail.timeline.action.bottomSheetItemSeparator import javax.inject.Inject /** @@ -29,26 +31,47 @@ import javax.inject.Inject */ class RoomListQuickActionsEpoxyController @Inject constructor(private val stringProvider: StringProvider, private val avatarRenderer: AvatarRenderer, + private val dateFormatter: VectorDateFormatter, private val fontProvider: EmojiCompatFontProvider) : TypedEpoxyController() { var listener: Listener? = null override fun buildModels(state: RoomListQuickActionsState) { + val roomSummary = state.roomSummary() ?: return - // Separator + // Preview + bottomSheetItemRoomPreview { + id("preview") + avatarRenderer(avatarRenderer) + roomName(roomSummary.displayName) + avatarUrl(roomSummary.avatarUrl) + roomId(roomSummary.roomId) + settingsClickListener(View.OnClickListener { listener?.didSelectMenuAction(RoomListQuickActions.Settings(roomSummary.roomId)) }) + } + + // Notifications bottomSheetItemSeparator { - id("actions_separator") + id("notifications_separator") } + RoomListQuickActions.NotificationsAllNoisy(roomSummary.roomId).toBottomSheetItem(0) + RoomListQuickActions.NotificationsAll(roomSummary.roomId).toBottomSheetItem(1) + RoomListQuickActions.NotificationsMentionsOnly(roomSummary.roomId).toBottomSheetItem(2) + RoomListQuickActions.NotificationsMute(roomSummary.roomId).toBottomSheetItem(3) - // Actions - state.quickActions()?.forEachIndexed { index, action -> - bottomSheetItemAction { - id("action_$index") - iconRes(action.iconResId) - textRes(action.titleRes) - listener(View.OnClickListener { listener?.didSelectMenuAction(action) }) - } + // Leave + bottomSheetItemSeparator { + id("leave_separator") } + RoomListQuickActions.Leave(roomSummary.roomId).toBottomSheetItem(5) + } + + private fun RoomListQuickActions.toBottomSheetItem(index: Int) { + return BottomSheetItemAction_() + .id("action_$index") + .iconRes(iconResId) + .textRes(titleRes) + .listener(View.OnClickListener { listener?.didSelectMenuAction(this) }) + .addTo(this@RoomListQuickActionsEpoxyController) } interface Listener { diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsState.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsState.kt index adefe24341..b15b91e6c0 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsState.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsState.kt @@ -23,8 +23,7 @@ import im.vector.matrix.android.api.session.room.model.RoomSummary data class RoomListQuickActionsState( val roomId: String, - val quickActions: Async> = Uninitialized, - val timelineEvent: Async = Uninitialized + val roomSummary: Async = Uninitialized ) : MvRxState { constructor(args: RoomListActionsArgs) : this(roomId = args.roomId) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsStore.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsStore.kt new file mode 100644 index 0000000000..ce0479ac92 --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsStore.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.home.room.list.actions + +import androidx.lifecycle.ViewModel +import im.vector.riotx.core.utils.PublishStore +import im.vector.riotx.core.utils.RxStore + +/** + * Activity shared view model to handle room list quick actions + */ +class RoomListQuickActionsStore constructor( + private val store: RxStore = PublishStore() +) : ViewModel(), RxStore by store 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 079c43041f..9569f2c434 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 @@ -19,18 +19,19 @@ import com.airbnb.mvrx.* import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.AssistedInject import dagger.Lazy +import im.vector.matrix.android.api.MatrixCallback 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.VectorViewModel import im.vector.riotx.core.resources.StringProvider import im.vector.riotx.features.home.room.detail.timeline.format.NoticeEventFormatter import im.vector.riotx.features.html.EventHtmlRenderer +import timber.log.Timber class RoomListActionsViewModel @AssistedInject constructor(@Assisted initialState: RoomListQuickActionsState, - private val eventHtmlRenderer: Lazy, - private val session: Session, - private val noticeEventFormatter: NoticeEventFormatter, - private val stringProvider: StringProvider + session: Session ) : VectorViewModel(initialState) { @AssistedInject.Factory @@ -46,8 +47,20 @@ class RoomListActionsViewModel @AssistedInject constructor(@Assisted } } - init { + private val room = session.getRoom(initialState.roomId)!! + init { + observeRoomSummary() + } + + private fun observeRoomSummary() { + room + .rx() + .liveRoomSummary() + .unwrap() + .execute { + copy(roomSummary = it) + } } diff --git a/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt b/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt index a3f9c009ed..f0958b5b35 100644 --- a/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt +++ b/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt @@ -112,4 +112,9 @@ class DefaultNavigator @Inject constructor() : Navigator { override fun openUserDetail(userId: String, context: Context) { Timber.v("Open user detail $userId") } + + override fun openRoomSettings(context: Context, roomId: String) { + Timber.v("Open room settings$roomId") + + } } diff --git a/vector/src/main/java/im/vector/riotx/features/navigation/Navigator.kt b/vector/src/main/java/im/vector/riotx/features/navigation/Navigator.kt index 4112dbbfc8..8bd5f520c1 100644 --- a/vector/src/main/java/im/vector/riotx/features/navigation/Navigator.kt +++ b/vector/src/main/java/im/vector/riotx/features/navigation/Navigator.kt @@ -50,4 +50,7 @@ interface Navigator { fun openGroupDetail(groupId: String, context: Context) fun openUserDetail(userId: String, context: Context) + + fun openRoomSettings(context: Context, roomId: String) + } 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 955713c0f8..3545b1cb71 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 @@ -76,7 +76,7 @@ class PublicRoomsFragment : VectorBaseFragment(), PublicRoomsController.Callback .disposeOnDestroy() publicRoomsCreateNewRoom.setOnClickListener { - navigationViewModel.goTo(RoomDirectoryActivity.Navigation.CreateRoom) + navigationViewModel.post(RoomDirectoryActivity.Navigation.CreateRoom) } viewModel.joinRoomErrorLiveData.observeEvent(this) { throwable -> @@ -88,7 +88,7 @@ class PublicRoomsFragment : VectorBaseFragment(), PublicRoomsController.Callback override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.itemId) { R.id.menu_room_directory_change_protocol -> { - navigationViewModel.goTo(RoomDirectoryActivity.Navigation.ChangeProtocol) + navigationViewModel.post(RoomDirectoryActivity.Navigation.ChangeProtocol) true } else -> diff --git a/vector/src/main/java/im/vector/riotx/features/roomdirectory/RoomDirectoryActivity.kt b/vector/src/main/java/im/vector/riotx/features/roomdirectory/RoomDirectoryActivity.kt index b2dd13e59a..e8914970ff 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomdirectory/RoomDirectoryActivity.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomdirectory/RoomDirectoryActivity.kt @@ -62,14 +62,16 @@ class RoomDirectoryActivity : VectorBaseActivity() { roomDirectoryViewModel.filterWith(intent?.getStringExtra(INITIAL_FILTER) ?: "") } - navigationViewModel.navigateTo.observeEvent(this) { navigation -> - when (navigation) { - is Navigation.Back -> onBackPressed() - is Navigation.CreateRoom -> addFragmentToBackstack(CreateRoomFragment(), R.id.simpleFragmentContainer) - is Navigation.ChangeProtocol -> addFragmentToBackstack(RoomDirectoryPickerFragment(), R.id.simpleFragmentContainer) - is Navigation.Close -> finish() - } - } + navigationViewModel.observe() + .subscribe { navigation -> + when (navigation) { + is Navigation.Back -> onBackPressed() + is Navigation.CreateRoom -> addFragmentToBackstack(CreateRoomFragment(), R.id.simpleFragmentContainer) + is Navigation.ChangeProtocol -> addFragmentToBackstack(RoomDirectoryPickerFragment(), R.id.simpleFragmentContainer) + is Navigation.Close -> finish() + } + } + .disposeOnDestroy() roomDirectoryViewModel.selectSubscribe(this, PublicRoomsViewState::currentFilter) { currentFilter -> // Transmit the filter to the createRoomViewModel diff --git a/vector/src/main/java/im/vector/riotx/features/roomdirectory/RoomDirectoryNavigationViewModel.kt b/vector/src/main/java/im/vector/riotx/features/roomdirectory/RoomDirectoryNavigationViewModel.kt index c87da6bd50..cb26ff0c54 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomdirectory/RoomDirectoryNavigationViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomdirectory/RoomDirectoryNavigationViewModel.kt @@ -16,7 +16,9 @@ package im.vector.riotx.features.roomdirectory -import im.vector.riotx.core.mvrx.NavigationViewModel -import javax.inject.Inject +import androidx.lifecycle.ViewModel +import im.vector.riotx.core.utils.PublishStore +import im.vector.riotx.core.utils.RxStore -class RoomDirectoryNavigationViewModel @Inject constructor(): NavigationViewModel() +class RoomDirectoryNavigationViewModel(private val store: RxStore = PublishStore()) + : ViewModel(), RxStore by store diff --git a/vector/src/main/java/im/vector/riotx/features/roomdirectory/createroom/CreateRoomActivity.kt b/vector/src/main/java/im/vector/riotx/features/roomdirectory/createroom/CreateRoomActivity.kt index 9a3e903954..00bd42901a 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomdirectory/createroom/CreateRoomActivity.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomdirectory/createroom/CreateRoomActivity.kt @@ -63,12 +63,14 @@ class CreateRoomActivity : VectorBaseActivity(), ToolbarConfigurable { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) navigationViewModel = ViewModelProviders.of(this, viewModelFactory).get(RoomDirectoryNavigationViewModel::class.java) - navigationViewModel.navigateTo.observeEvent(this) { navigation -> - when (navigation) { - is RoomDirectoryActivity.Navigation.Back, - is RoomDirectoryActivity.Navigation.Close -> finish() - } - } + navigationViewModel.observe() + .subscribe { navigation -> + when (navigation) { + is RoomDirectoryActivity.Navigation.Back, + is RoomDirectoryActivity.Navigation.Close -> finish() + } + } + .disposeOnDestroy() } companion object { diff --git a/vector/src/main/java/im/vector/riotx/features/roomdirectory/createroom/CreateRoomFragment.kt b/vector/src/main/java/im/vector/riotx/features/roomdirectory/createroom/CreateRoomFragment.kt index acea19b49a..8abf52328f 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomdirectory/createroom/CreateRoomFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomdirectory/createroom/CreateRoomFragment.kt @@ -52,7 +52,7 @@ class CreateRoomFragment : VectorBaseFragment(), CreateRoomController.Listener { navigationViewModel = ViewModelProviders.of(requireActivity()).get(RoomDirectoryNavigationViewModel::class.java) setupRecyclerView() createRoomClose.setOnClickListener { - navigationViewModel.goTo(RoomDirectoryActivity.Navigation.Back) + navigationViewModel.post(RoomDirectoryActivity.Navigation.Back) } } @@ -99,7 +99,7 @@ class CreateRoomFragment : VectorBaseFragment(), CreateRoomController.Listener { // Navigate to freshly created room navigator.openRoom(requireActivity(), async()) - navigationViewModel.goTo(RoomDirectoryActivity.Navigation.Close) + navigationViewModel.post(RoomDirectoryActivity.Navigation.Close) } else { // Populate list with Epoxy createRoomController.setData(state) diff --git a/vector/src/main/java/im/vector/riotx/features/roomdirectory/picker/RoomDirectoryPickerFragment.kt b/vector/src/main/java/im/vector/riotx/features/roomdirectory/picker/RoomDirectoryPickerFragment.kt index f338c71bbf..2367bc8d21 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomdirectory/picker/RoomDirectoryPickerFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomdirectory/picker/RoomDirectoryPickerFragment.kt @@ -94,7 +94,7 @@ class RoomDirectoryPickerFragment : VectorBaseFragment(), RoomDirectoryPickerCon Timber.v("onRoomDirectoryClicked: $roomDirectoryData") viewModel.setRoomDirectoryData(roomDirectoryData) - navigationViewModel.goTo(RoomDirectoryActivity.Navigation.Back) + navigationViewModel.post(RoomDirectoryActivity.Navigation.Back) } override fun retry() { diff --git a/vector/src/main/res/drawable/ic_room_actions_leave.xml b/vector/src/main/res/drawable/ic_room_actions_leave.xml new file mode 100644 index 0000000000..346defac7c --- /dev/null +++ b/vector/src/main/res/drawable/ic_room_actions_leave.xml @@ -0,0 +1,47 @@ + + + + + + + diff --git a/vector/src/main/res/drawable/ic_room_actions_notifications_all.xml b/vector/src/main/res/drawable/ic_room_actions_notifications_all.xml new file mode 100644 index 0000000000..5bf7226c59 --- /dev/null +++ b/vector/src/main/res/drawable/ic_room_actions_notifications_all.xml @@ -0,0 +1,39 @@ + + + + + + diff --git a/vector/src/main/res/drawable/ic_room_actions_notifications_all_noisy.xml b/vector/src/main/res/drawable/ic_room_actions_notifications_all_noisy.xml new file mode 100644 index 0000000000..0eec24a115 --- /dev/null +++ b/vector/src/main/res/drawable/ic_room_actions_notifications_all_noisy.xml @@ -0,0 +1,39 @@ + + + + + + diff --git a/vector/src/main/res/drawable/ic_room_actions_notifications_mentions.xml b/vector/src/main/res/drawable/ic_room_actions_notifications_mentions.xml new file mode 100644 index 0000000000..6bdf317097 --- /dev/null +++ b/vector/src/main/res/drawable/ic_room_actions_notifications_mentions.xml @@ -0,0 +1,47 @@ + + + + + + + diff --git a/vector/src/main/res/drawable/ic_room_actions_notifications_mutes.xml b/vector/src/main/res/drawable/ic_room_actions_notifications_mutes.xml new file mode 100644 index 0000000000..89bbc832cb --- /dev/null +++ b/vector/src/main/res/drawable/ic_room_actions_notifications_mutes.xml @@ -0,0 +1,47 @@ + + + + + + + diff --git a/vector/src/main/res/drawable/ic_room_actions_settings.xml b/vector/src/main/res/drawable/ic_room_actions_settings.xml new file mode 100644 index 0000000000..c80dfe0409 --- /dev/null +++ b/vector/src/main/res/drawable/ic_room_actions_settings.xml @@ -0,0 +1,39 @@ + + + + + + diff --git a/vector/src/main/res/layout/item_bottom_sheet_room_preview.xml b/vector/src/main/res/layout/item_bottom_sheet_room_preview.xml new file mode 100644 index 0000000000..410e6ea1ab --- /dev/null +++ b/vector/src/main/res/layout/item_bottom_sheet_room_preview.xml @@ -0,0 +1,57 @@ + + + + + + + + + + diff --git a/vector/src/main/res/values/strings_riotX.xml b/vector/src/main/res/values/strings_riotX.xml index 71fbc22acf..9b12db5e7f 100644 --- a/vector/src/main/res/values/strings_riotX.xml +++ b/vector/src/main/res/values/strings_riotX.xml @@ -2,6 +2,11 @@ - + "All messages (noisy)" + "All messages" + "Mentions only" + "Mute" + "Settings" + "Leave"