From 9762d5be40d9d88ad8e0f42d7acb6ee5b98b4dc1 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 23 Oct 2019 19:05:59 +0200 Subject: [PATCH 01/10] Room list actions: start creating all the components --- .../vector/riotx/core/di/ScreenComponent.kt | 3 + .../home/room/list/RoomListFragment.kt | 10 +- .../home/room/list/RoomSummaryController.kt | 3 +- .../home/room/list/RoomSummaryItem.kt | 6 +- .../home/room/list/RoomSummaryItemFactory.kt | 13 ++- .../room/list/actions/RoomListQuickActions.kt | 24 +++++ .../RoomListQuickActionsBottomSheet.kt | 92 +++++++++++++++++++ .../RoomListQuickActionsEpoxyController.kt | 57 ++++++++++++ .../list/actions/RoomListQuickActionsState.kt | 32 +++++++ .../actions/RoomListQuickActionsViewModel.kt | 54 +++++++++++ 10 files changed, 288 insertions(+), 6 deletions(-) create mode 100644 vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActions.kt create mode 100644 vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsBottomSheet.kt create mode 100644 vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsEpoxyController.kt create mode 100644 vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsState.kt create mode 100644 vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsViewModel.kt diff --git a/vector/src/main/java/im/vector/riotx/core/di/ScreenComponent.kt b/vector/src/main/java/im/vector/riotx/core/di/ScreenComponent.kt index da9daac68d..cb9dcf375e 100644 --- a/vector/src/main/java/im/vector/riotx/core/di/ScreenComponent.kt +++ b/vector/src/main/java/im/vector/riotx/core/di/ScreenComponent.kt @@ -45,6 +45,7 @@ import im.vector.riotx.features.home.room.detail.timeline.action.* import im.vector.riotx.features.home.room.detail.timeline.edithistory.ViewEditHistoryBottomSheet import im.vector.riotx.features.home.room.detail.timeline.reactions.ViewReactionsBottomSheet import im.vector.riotx.features.home.room.filtered.FilteredRoomsActivity +import im.vector.riotx.features.home.room.list.actions.RoomListQuickActionsBottomSheet import im.vector.riotx.features.home.room.list.RoomListFragment import im.vector.riotx.features.invite.VectorInviteView import im.vector.riotx.features.link.LinkHandlerActivity @@ -186,6 +187,8 @@ interface ScreenComponent { fun inject(incomingShareActivity: IncomingShareActivity) + fun inject(roomListActionsBottomSheet: RoomListQuickActionsBottomSheet) + @Component.Factory interface Factory { fun create(vectorComponent: VectorComponent, 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 a705c91a9e..76e4ff9e3b 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 @@ -39,6 +39,7 @@ 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.RoomListQuickActionsBottomSheet import im.vector.riotx.features.home.room.list.widget.FabMenuView import im.vector.riotx.features.notifications.NotificationDrawerManager import im.vector.riotx.features.share.SharedData @@ -298,10 +299,17 @@ class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Listener, O // RoomSummaryController.Callback ************************************************************** - override fun onRoomSelected(room: RoomSummary) { + override fun onRoomClicked(room: RoomSummary) { roomListViewModel.accept(RoomListActions.SelectRoom(room)) } + override fun onRoomLongClicked(room: RoomSummary): Boolean { + RoomListQuickActionsBottomSheet + .newInstance(room.roomId) + .show(requireActivity().supportFragmentManager, "ROOM_LIST_QUICK_ACTIONS") + return true + } + override fun onAcceptRoomInvitation(room: RoomSummary) { notificationDrawerManager.clearMemberShipNotificationForRoom(room.roomId) roomListViewModel.accept(RoomListActions.AcceptInvitation(room)) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryController.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryController.kt index 6d786cde5e..9f73d24c6d 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryController.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryController.kt @@ -138,7 +138,8 @@ class RoomSummaryController @Inject constructor(private val stringProvider: Stri interface Listener : FilteredRoomFooterItem.FilteredRoomFooterItemListener { fun onToggleRoomCategory(roomCategory: RoomCategory) - fun onRoomSelected(room: RoomSummary) + fun onRoomClicked(room: RoomSummary) + fun onRoomLongClicked(room: RoomSummary): Boolean fun onRejectRoomInvitation(room: RoomSummary) fun onAcceptRoomInvitation(room: RoomSummary) } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryItem.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryItem.kt index 812ad463f5..fe208a3085 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryItem.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryItem.kt @@ -41,11 +41,13 @@ abstract class RoomSummaryItem : VectorEpoxyModel() { @EpoxyAttribute var hasUnreadMessage: Boolean = false @EpoxyAttribute var hasDraft: Boolean = false @EpoxyAttribute var showHighlighted: Boolean = false - @EpoxyAttribute var listener: (() -> Unit)? = null + @EpoxyAttribute var itemLongClickListener: View.OnLongClickListener? = null + @EpoxyAttribute var itemClickListener: View.OnClickListener? = null override fun bind(holder: Holder) { super.bind(holder) - holder.rootView.setOnClickListener { listener?.invoke() } + holder.rootView.setOnClickListener(itemClickListener) + holder.rootView.setOnLongClickListener(itemLongClickListener) holder.titleView.text = roomName holder.lastEventTimeView.text = lastEventTime holder.lastEventView.text = lastFormattedEvent diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryItemFactory.kt index 0ad3b10159..c38c5cfd37 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryItemFactory.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryItemFactory.kt @@ -16,6 +16,7 @@ package im.vector.riotx.features.home.room.list +import android.view.View import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.events.model.toModel import im.vector.matrix.android.api.session.room.model.Membership @@ -28,6 +29,7 @@ import im.vector.riotx.core.extensions.localDateTime import im.vector.riotx.core.resources.ColorProvider import im.vector.riotx.core.resources.DateProvider import im.vector.riotx.core.resources.StringProvider +import im.vector.riotx.core.utils.DebouncedClickListener import im.vector.riotx.features.home.AvatarRenderer import im.vector.riotx.features.home.room.detail.timeline.format.NoticeEventFormatter import im.vector.riotx.features.home.room.detail.timeline.helper.senderName @@ -79,7 +81,7 @@ class RoomSummaryItemFactory @Inject constructor(private val noticeEventFormatte .rejectListener { listener?.onRejectRoomInvitation(roomSummary) } .roomName(roomSummary.displayName) .avatarUrl(roomSummary.avatarUrl) - .listener { listener?.onRoomSelected(roomSummary) } + .listener { listener?.onRoomClicked(roomSummary) } } private fun createRoomItem(roomSummary: RoomSummary, listener: RoomSummaryController.Listener?): VectorEpoxyModel<*> { @@ -134,6 +136,13 @@ class RoomSummaryItemFactory @Inject constructor(private val noticeEventFormatte .unreadNotificationCount(unreadCount) .hasUnreadMessage(roomSummary.hasUnreadMessages) .hasDraft(roomSummary.userDrafts.isNotEmpty()) - .listener { listener?.onRoomSelected(roomSummary) } + .itemLongClickListener { _ -> + listener?.onRoomLongClicked(roomSummary) ?: false + } + .itemClickListener( + DebouncedClickListener(View.OnClickListener { _ -> + listener?.onRoomClicked(roomSummary) + }) + ) } } 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 new file mode 100644 index 0000000000..c07d88f85a --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActions.kt @@ -0,0 +1,24 @@ +/* + * 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.annotation.DrawableRes +import androidx.annotation.StringRes + +sealed class RoomListQuickActions(@StringRes val titleRes: Int, @DrawableRes val iconResId: Int) { + +} 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 new file mode 100644 index 0000000000..19fe10de39 --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsBottomSheet.kt @@ -0,0 +1,92 @@ +/* + * 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 android.os.Bundle +import android.os.Parcelable +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import butterknife.BindView +import butterknife.ButterKnife +import com.airbnb.mvrx.fragmentViewModel +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 kotlinx.android.parcel.Parcelize +import javax.inject.Inject + +@Parcelize +data class RoomListActionsArgs( + val roomId: String +) : Parcelable + +/** + * Bottom sheet fragment that shows room information with list of contextual actions + */ +class RoomListQuickActionsBottomSheet : VectorBaseBottomSheetDialogFragment(), RoomListQuickActionsEpoxyController.Listener { + + @Inject lateinit var roomListActionsViewModelFactory: RoomListActionsViewModel.Factory + @Inject lateinit var roomListActionsEpoxyController: RoomListQuickActionsEpoxyController + + private val viewModel: RoomListActionsViewModel by fragmentViewModel(RoomListActionsViewModel::class) + + @BindView(R.id.bottomSheetRecyclerView) + lateinit var recyclerView: RecyclerView + + override val showExpanded = true + + override fun injectWith(screenComponent: ScreenComponent) { + screenComponent.inject(this) + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + val view = inflater.inflate(R.layout.bottom_sheet_generic_list, container, false) + ButterKnife.bind(this, view) + return view + } + + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + recyclerView.layoutManager = LinearLayoutManager(requireContext(), RecyclerView.VERTICAL, false) + recyclerView.adapter = roomListActionsEpoxyController.adapter + // Disable item animation + recyclerView.itemAnimator = null + roomListActionsEpoxyController.listener = this + } + + + override fun invalidate() = withState(viewModel) { + roomListActionsEpoxyController.setData(it) + super.invalidate() + } + + override fun didSelectMenuAction(quickActions: RoomListQuickActions) { + vectorBaseActivity.notImplemented("RoomListQuickActions") + } + + companion object { + fun newInstance(roomId: String): RoomListQuickActionsBottomSheet { + return RoomListQuickActionsBottomSheet().apply { + setArguments(RoomListActionsArgs(roomId)) + } + } + } +} 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 new file mode 100644 index 0000000000..f4cc774092 --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsEpoxyController.kt @@ -0,0 +1,57 @@ +/* + * 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 android.view.View +import com.airbnb.epoxy.TypedEpoxyController +import im.vector.riotx.EmojiCompatFontProvider +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 + +/** + * Epoxy controller for room list actions + */ +class RoomListQuickActionsEpoxyController @Inject constructor(private val stringProvider: StringProvider, + private val avatarRenderer: AvatarRenderer, + private val fontProvider: EmojiCompatFontProvider) : TypedEpoxyController() { + + var listener: Listener? = null + + override fun buildModels(state: RoomListQuickActionsState) { + + // Separator + bottomSheetItemSeparator { + id("actions_separator") + } + + // Actions + state.quickActions()?.forEachIndexed { index, action -> + bottomSheetItemAction { + id("action_$index") + iconRes(action.iconResId) + textRes(action.titleRes) + listener(View.OnClickListener { listener?.didSelectMenuAction(action) }) + } + } + } + + interface Listener { + fun didSelectMenuAction(quickActions: RoomListQuickActions) + } +} 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 new file mode 100644 index 0000000000..adefe24341 --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsState.kt @@ -0,0 +1,32 @@ +/* + * 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 com.airbnb.mvrx.Async +import com.airbnb.mvrx.MvRxState +import com.airbnb.mvrx.Uninitialized +import im.vector.matrix.android.api.session.room.model.RoomSummary + +data class RoomListQuickActionsState( + val roomId: String, + val quickActions: Async> = Uninitialized, + val timelineEvent: 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/RoomListQuickActionsViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsViewModel.kt new file mode 100644 index 0000000000..079c43041f --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsViewModel.kt @@ -0,0 +1,54 @@ +/* + * 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 com.airbnb.mvrx.* +import com.squareup.inject.assisted.Assisted +import com.squareup.inject.assisted.AssistedInject +import dagger.Lazy +import im.vector.matrix.android.api.session.Session +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 + +class RoomListActionsViewModel @AssistedInject constructor(@Assisted + initialState: RoomListQuickActionsState, + private val eventHtmlRenderer: Lazy, + private val session: Session, + private val noticeEventFormatter: NoticeEventFormatter, + private val stringProvider: StringProvider +) : VectorViewModel(initialState) { + + @AssistedInject.Factory + interface Factory { + fun create(initialState: RoomListQuickActionsState): RoomListActionsViewModel + } + + companion object : MvRxViewModelFactory { + + override fun create(viewModelContext: ViewModelContext, state: RoomListQuickActionsState): RoomListActionsViewModel? { + val fragment: RoomListQuickActionsBottomSheet = (viewModelContext as FragmentViewModelContext).fragment() + return fragment.roomListActionsViewModelFactory.create(state) + } + } + + init { + + } + + +} From cb275aee37e92c7dff90fc3270f807b45d900b8c Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 24 Oct 2019 19:11:49 +0200 Subject: [PATCH 02/10] 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" From 00ca5dc70af2ef8c559b4c0f4ea4ea3b37e551ce Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 25 Oct 2019 18:23:47 +0200 Subject: [PATCH 03/10] RoomListActions: handle room notification state. Still need to branch UI --- .../main/java/im/vector/matrix/rx/RxRoom.kt | 5 + .../matrix/android/api/pushrules/Action.kt | 26 ++++- .../android/api/pushrules/PushRuleService.kt | 4 + .../matrix/android/api/session/room/Room.kt | 4 +- .../notification/RoomNotificationState.kt | 42 ++++++++ .../room/notification/RoomPushRuleService.kt | 29 +++++ .../internal/database/model/PushRuleEntity.kt | 5 + .../internal/database/query/PushersQueries.kt | 13 ++- .../notification/DefaultPushRuleService.kt | 20 ++++ .../session/pushers/AddPushRuleTask.kt | 39 +++++++ .../internal/session/pushers/PushersModule.kt | 11 ++ .../session/pushers/RemovePushRuleTask.kt | 39 +++++++ .../internal/session/room/DefaultRoom.kt | 7 +- .../internal/session/room/RoomFactory.kt | 8 +- .../DefaultRoomPushRuleService.kt | 73 +++++++++++++ .../session/room/notification/RoomPushRule.kt | 25 +++++ .../room/notification/RoomPushRuleMapper.kt | 102 ++++++++++++++++++ .../SetRoomNotificationStateTask.kt | 54 ++++++++++ .../home/room/list/RoomListActions.kt | 3 +- .../home/room/list/RoomListFragment.kt | 25 +++-- .../home/room/list/RoomListViewModel.kt | 23 ++-- .../list/actions/RoomListQuickActionsState.kt | 4 +- .../actions/RoomListQuickActionsViewModel.kt | 10 ++ 23 files changed, 544 insertions(+), 27 deletions(-) create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/notification/RoomNotificationState.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/notification/RoomPushRuleService.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/AddPushRuleTask.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/RemovePushRuleTask.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/notification/DefaultRoomPushRuleService.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/notification/RoomPushRule.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/notification/RoomPushRuleMapper.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/notification/SetRoomNotificationStateTask.kt diff --git a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt index e058b2716c..6793d6249d 100644 --- a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt +++ b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt @@ -20,6 +20,7 @@ import im.vector.matrix.android.api.session.room.Room import im.vector.matrix.android.api.session.room.model.EventAnnotationsSummary import im.vector.matrix.android.api.session.room.model.ReadReceipt import im.vector.matrix.android.api.session.room.model.RoomSummary +import im.vector.matrix.android.api.session.room.notification.RoomNotificationState import im.vector.matrix.android.api.session.room.send.UserDraft import im.vector.matrix.android.api.session.room.timeline.TimelineEvent import im.vector.matrix.android.api.util.Optional @@ -67,6 +68,10 @@ class RxRoom(private val room: Room) { fun liveDrafts(): Observable> { return room.getDraftsLive().asObservable() } + + fun liveNotificationState(): Observable { + return room.getLiveRoomNotificationState().asObservable() + } } fun Room.rx(): RxRoom { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/Action.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/Action.kt index d135504055..d1e5b3c868 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/Action.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/Action.kt @@ -21,7 +21,7 @@ import timber.log.Timber sealed class Action { object Notify : Action() object DoNotNotify : Action() - data class Sound(val sound: String) : Action() + data class Sound(val sound: String = ACTION_OBJECT_VALUE_VALUE_DEFAULT) : Action() data class Highlight(val highlight: Boolean) : Action() } @@ -63,6 +63,30 @@ private const val ACTION_OBJECT_VALUE_VALUE_DEFAULT = "default" * * */ + +@Suppress("IMPLICIT_CAST_TO_ANY") +fun List.toJson(): List { + return map { action -> + when (action) { + is Action.Notify -> ACTION_NOTIFY + is Action.DoNotNotify -> ACTION_DONT_NOTIFY + is Action.Sound -> { + mapOf( + ACTION_OBJECT_SET_TWEAK_KEY to ACTION_OBJECT_SET_TWEAK_VALUE_SOUND, + ACTION_OBJECT_VALUE_KEY to action.sound + ) + } + is Action.Highlight -> { + mapOf( + ACTION_OBJECT_SET_TWEAK_KEY to ACTION_OBJECT_SET_TWEAK_VALUE_HIGHLIGHT, + ACTION_OBJECT_VALUE_KEY to action.highlight + ) + } + } + } +} + + fun PushRule.getActions(): List { val result = ArrayList() diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/PushRuleService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/PushRuleService.kt index aa277ea8bd..0ef70eb99b 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/PushRuleService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/PushRuleService.kt @@ -34,6 +34,10 @@ interface PushRuleService { fun updatePushRuleEnableStatus(kind: RuleKind, pushRule: PushRule, enabled: Boolean, callback: MatrixCallback): Cancelable + fun addPushRule(kind: RuleKind, pushRule: PushRule, callback: MatrixCallback): Cancelable + + fun removePushRule(kind: RuleKind, pushRule: PushRule, callback: MatrixCallback): Cancelable + fun addPushRuleListener(listener: PushRuleListener) fun removePushRuleListener(listener: PushRuleListener) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/Room.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/Room.kt index 70c9c6e36c..90790a6ab0 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/Room.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/Room.kt @@ -21,6 +21,7 @@ import im.vector.matrix.android.api.session.room.crypto.RoomCryptoService import im.vector.matrix.android.api.session.room.members.MembershipService import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.session.room.model.relation.RelationService +import im.vector.matrix.android.api.session.room.notification.RoomPushRuleService import im.vector.matrix.android.api.session.room.reporting.ReportingService import im.vector.matrix.android.api.session.room.read.ReadService import im.vector.matrix.android.api.session.room.send.DraftService @@ -41,7 +42,8 @@ interface Room : StateService, ReportingService, RelationService, - RoomCryptoService { + RoomCryptoService, + RoomPushRuleService { /** * The roomId of this room diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/notification/RoomNotificationState.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/notification/RoomNotificationState.kt new file mode 100644 index 0000000000..a638b2710c --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/notification/RoomNotificationState.kt @@ -0,0 +1,42 @@ +/* + * 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.matrix.android.api.session.room.notification + +/** + * Defines the room notification state + */ +enum class RoomNotificationState { + /** + * All the messages will trigger a noisy notification + */ + ALL_MESSAGES_NOISY, + + /** + * All the messages will trigger a notification + */ + ALL_MESSAGES, + + /** + * Only the messages with user display name / user name will trigger notifications + */ + MENTIONS_ONLY, + + /** + * No notifications + */ + MUTE +} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/notification/RoomPushRuleService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/notification/RoomPushRuleService.kt new file mode 100644 index 0000000000..7b3e88240b --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/notification/RoomPushRuleService.kt @@ -0,0 +1,29 @@ +/* + * 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.matrix.android.api.session.room.notification + +import androidx.lifecycle.LiveData +import im.vector.matrix.android.api.MatrixCallback +import im.vector.matrix.android.api.util.Cancelable + +interface RoomPushRuleService { + + fun getLiveRoomNotificationState(): LiveData + + fun setRoomNotificationState(roomNotificationState: RoomNotificationState, matrixCallback: MatrixCallback): Cancelable + +} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/PushRuleEntity.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/PushRuleEntity.kt index 4744c8d053..1ef65d9dea 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/PushRuleEntity.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/PushRuleEntity.kt @@ -17,6 +17,8 @@ package im.vector.matrix.android.internal.database.model import io.realm.RealmList import io.realm.RealmObject +import io.realm.RealmResults +import io.realm.annotations.LinkingObjects internal open class PushRuleEntity( // Required. The actions to perform when this rule is matched. @@ -33,5 +35,8 @@ internal open class PushRuleEntity( var pattern: String? = null ) : RealmObject() { + @LinkingObjects("pushRules") + val parent: RealmResults? = null + companion object } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/PushersQueries.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/PushersQueries.kt index 4ecb40a7e1..a97ed8d415 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/PushersQueries.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/PushersQueries.kt @@ -16,10 +16,10 @@ package im.vector.matrix.android.internal.database.query import im.vector.matrix.android.api.pushrules.RuleKind +import im.vector.matrix.android.internal.database.model.* +import im.vector.matrix.android.internal.database.model.PushRuleEntity import im.vector.matrix.android.internal.database.model.PushRulesEntity -import im.vector.matrix.android.internal.database.model.PushRulesEntityFields import im.vector.matrix.android.internal.database.model.PusherEntity -import im.vector.matrix.android.internal.database.model.PusherEntityFields import io.realm.Realm import io.realm.RealmQuery import io.realm.kotlin.where @@ -41,3 +41,12 @@ internal fun PushRulesEntity.Companion.where(realm: Realm, .equalTo(PushRulesEntityFields.SCOPE, scope) .equalTo(PushRulesEntityFields.KIND_STR, kind.name) } + +internal fun PushRuleEntity.Companion.where(realm: Realm, + scope: String, + ruleId: String): RealmQuery { + return realm.where() + .equalTo("${PushRuleEntityFields.PARENT}.${PushRulesEntityFields.SCOPE}", scope) + .equalTo(PushRuleEntityFields.RULE_ID, ruleId) +} + diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/DefaultPushRuleService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/DefaultPushRuleService.kt index 82b928fc54..9121202649 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/DefaultPushRuleService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/DefaultPushRuleService.kt @@ -28,7 +28,9 @@ import im.vector.matrix.android.internal.database.mapper.PushRulesMapper import im.vector.matrix.android.internal.database.model.PushRulesEntity import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.session.SessionScope +import im.vector.matrix.android.internal.session.pushers.AddPushRuleTask import im.vector.matrix.android.internal.session.pushers.GetPushRulesTask +import im.vector.matrix.android.internal.session.pushers.RemovePushRuleTask import im.vector.matrix.android.internal.session.pushers.UpdatePushRuleEnableStatusTask import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.configureWith @@ -38,6 +40,8 @@ import javax.inject.Inject @SessionScope internal class DefaultPushRuleService @Inject constructor(private val getPushRulesTask: GetPushRulesTask, private val updatePushRuleEnableStatusTask: UpdatePushRuleEnableStatusTask, + private val addPushRuleTask: AddPushRuleTask, + private val removePushRuleTask: RemovePushRuleTask, private val taskExecutor: TaskExecutor, private val monarchy: Monarchy ) : PushRuleService { @@ -98,6 +102,22 @@ internal class DefaultPushRuleService @Inject constructor(private val getPushRul .executeBy(taskExecutor) } + override fun addPushRule(kind: RuleKind, pushRule: PushRule, callback: MatrixCallback): Cancelable { + return addPushRuleTask + .configureWith(AddPushRuleTask.Params(kind, pushRule)) { + this.callback = callback + } + .executeBy(taskExecutor) + } + + override fun removePushRule(kind: RuleKind, pushRule: PushRule, callback: MatrixCallback): Cancelable { + return removePushRuleTask + .configureWith(RemovePushRuleTask.Params(kind, pushRule)) { + this.callback = callback + } + .executeBy(taskExecutor) + } + override fun removePushRuleListener(listener: PushRuleService.PushRuleListener) { synchronized(listeners) { listeners.remove(listener) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/AddPushRuleTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/AddPushRuleTask.kt new file mode 100644 index 0000000000..99992ef4dc --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/AddPushRuleTask.kt @@ -0,0 +1,39 @@ +/* + * 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.matrix.android.internal.session.pushers + +import im.vector.matrix.android.api.pushrules.RuleKind +import im.vector.matrix.android.api.pushrules.rest.PushRule +import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.task.Task +import javax.inject.Inject + +internal interface AddPushRuleTask : Task { + data class Params( + val kind: RuleKind, + val pushRule: PushRule + ) +} + +internal class DefaultAddPushRuleTask @Inject constructor(private val pushRulesApi: PushRulesApi) + : AddPushRuleTask { + + override suspend fun execute(params: AddPushRuleTask.Params) { + return executeRequest { + apiCall = pushRulesApi.addRule(params.kind.value, params.pushRule.ruleId, params.pushRule) + } + } +} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/PushersModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/PushersModule.kt index 7aa06c0275..1564363e1b 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/PushersModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/PushersModule.kt @@ -25,6 +25,8 @@ import im.vector.matrix.android.api.session.pushers.PushersService import im.vector.matrix.android.internal.session.notification.DefaultProcessEventForPushTask import im.vector.matrix.android.internal.session.notification.DefaultPushRuleService import im.vector.matrix.android.internal.session.notification.ProcessEventForPushTask +import im.vector.matrix.android.internal.session.room.notification.DefaultSetRoomNotificationStateTask +import im.vector.matrix.android.internal.session.room.notification.SetRoomNotificationStateTask import retrofit2.Retrofit @Module @@ -67,6 +69,15 @@ internal abstract class PushersModule { @Binds abstract fun bindUpdatePushRuleEnableStatusTask(updatePushRuleEnableStatusTask: DefaultUpdatePushRuleEnableStatusTask): UpdatePushRuleEnableStatusTask + @Binds + abstract fun bindAddPushRuleTask(addPushRuleTask: DefaultAddPushRuleTask): AddPushRuleTask + + @Binds + abstract fun bindRemovePushRuleTask(removePushRuleTask: DefaultRemovePushRuleTask): RemovePushRuleTask + + @Binds + abstract fun bindSetRoomNotificationStateTask(setRoomNotificationStateTask: DefaultSetRoomNotificationStateTask): SetRoomNotificationStateTask + @Binds abstract fun bindPushRuleService(pushRuleService: DefaultPushRuleService): PushRuleService diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/RemovePushRuleTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/RemovePushRuleTask.kt new file mode 100644 index 0000000000..c4938fa0cc --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/RemovePushRuleTask.kt @@ -0,0 +1,39 @@ +/* + * 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.matrix.android.internal.session.pushers + +import im.vector.matrix.android.api.pushrules.RuleKind +import im.vector.matrix.android.api.pushrules.rest.PushRule +import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.task.Task +import javax.inject.Inject + +internal interface RemovePushRuleTask : Task { + data class Params( + val kind: RuleKind, + val pushRule: PushRule + ) +} + +internal class DefaultRemovePushRuleTask @Inject constructor(private val pushRulesApi: PushRulesApi) + : RemovePushRuleTask { + + override suspend fun execute(params: RemovePushRuleTask.Params) { + return executeRequest { + apiCall = pushRulesApi.deleteRule(params.kind.value, params.pushRule.ruleId) + } + } +} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt index fea827fd25..cca20fc5fc 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt @@ -24,6 +24,7 @@ import im.vector.matrix.android.api.session.room.Room import im.vector.matrix.android.api.session.room.members.MembershipService import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.session.room.model.relation.RelationService +import im.vector.matrix.android.api.session.room.notification.RoomPushRuleService import im.vector.matrix.android.api.session.room.reporting.ReportingService import im.vector.matrix.android.api.session.room.read.ReadService import im.vector.matrix.android.api.session.room.send.DraftService @@ -49,7 +50,8 @@ internal class DefaultRoom @Inject constructor(override val roomId: String, private val readService: ReadService, private val cryptoService: CryptoService, private val relationService: RelationService, - private val roomMembersService: MembershipService) : + private val roomMembersService: MembershipService, + private val roomPushRuleService: RoomPushRuleService) : Room, TimelineService by timelineService, SendService by sendService, @@ -58,7 +60,8 @@ internal class DefaultRoom @Inject constructor(override val roomId: String, ReportingService by reportingService, ReadService by readService, RelationService by relationService, - MembershipService by roomMembersService { + MembershipService by roomMembersService, + RoomPushRuleService by roomPushRuleService { override fun getRoomSummaryLive(): LiveData> { val liveData = monarchy.findAllMappedWithChanges( diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomFactory.kt index e2199782f4..2c441762dd 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomFactory.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomFactory.kt @@ -19,9 +19,11 @@ package im.vector.matrix.android.internal.session.room import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.api.session.crypto.CryptoService import im.vector.matrix.android.api.session.room.Room +import im.vector.matrix.android.api.session.room.notification.RoomPushRuleService import im.vector.matrix.android.internal.database.mapper.RoomSummaryMapper import im.vector.matrix.android.internal.session.room.draft.DefaultDraftService import im.vector.matrix.android.internal.session.room.membership.DefaultMembershipService +import im.vector.matrix.android.internal.session.room.notification.DefaultRoomPushRuleService import im.vector.matrix.android.internal.session.room.read.DefaultReadService import im.vector.matrix.android.internal.session.room.relation.DefaultRelationService import im.vector.matrix.android.internal.session.room.reporting.DefaultReportingService @@ -44,7 +46,8 @@ internal class DefaultRoomFactory @Inject constructor(private val monarchy: Mona private val reportingServiceFactory: DefaultReportingService.Factory, private val readServiceFactory: DefaultReadService.Factory, private val relationServiceFactory: DefaultRelationService.Factory, - private val membershipServiceFactory: DefaultMembershipService.Factory) : + private val membershipServiceFactory: DefaultMembershipService.Factory, + private val roomPushRuleServiceFactory: DefaultRoomPushRuleService.Factory) : RoomFactory { override fun create(roomId: String): Room { @@ -60,7 +63,8 @@ internal class DefaultRoomFactory @Inject constructor(private val monarchy: Mona readServiceFactory.create(roomId), cryptoService, relationServiceFactory.create(roomId), - membershipServiceFactory.create(roomId) + membershipServiceFactory.create(roomId), + roomPushRuleServiceFactory.create(roomId) ) } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/notification/DefaultRoomPushRuleService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/notification/DefaultRoomPushRuleService.kt new file mode 100644 index 0000000000..a27cdb1007 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/notification/DefaultRoomPushRuleService.kt @@ -0,0 +1,73 @@ +/* + * 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.matrix.android.internal.session.room.notification + +import androidx.lifecycle.LiveData +import androidx.lifecycle.Transformations +import com.squareup.inject.assisted.Assisted +import com.squareup.inject.assisted.AssistedInject +import com.zhuinden.monarchy.Monarchy +import im.vector.matrix.android.api.MatrixCallback +import im.vector.matrix.android.api.pushrules.RuleScope +import im.vector.matrix.android.api.session.room.notification.RoomNotificationState +import im.vector.matrix.android.api.session.room.notification.RoomPushRuleService +import im.vector.matrix.android.api.util.Cancelable +import im.vector.matrix.android.internal.database.model.PushRuleEntity +import im.vector.matrix.android.internal.database.query.where +import im.vector.matrix.android.internal.task.TaskExecutor +import im.vector.matrix.android.internal.task.configureWith + +internal class DefaultRoomPushRuleService @AssistedInject constructor(@Assisted private val roomId: String, + private val setRoomNotificationStateTask: SetRoomNotificationStateTask, + private val monarchy: Monarchy, + private val taskExecutor: TaskExecutor) + : RoomPushRuleService { + + @AssistedInject.Factory + interface Factory { + fun create(roomId: String): RoomPushRuleService + } + + override fun getLiveRoomNotificationState(): LiveData { + return Transformations.map(getPushRuleForRoom()) { + it?.toRoomNotificationState() ?: RoomNotificationState.ALL_MESSAGES + } + } + + override fun setRoomNotificationState(roomNotificationState: RoomNotificationState, matrixCallback: MatrixCallback): Cancelable { + return setRoomNotificationStateTask + .configureWith(SetRoomNotificationStateTask.Params(roomId, roomNotificationState)) { + this.callback = callback + } + .executeBy(taskExecutor) + } + + private fun getPushRuleForRoom(): LiveData { + val liveData = monarchy.findAllMappedWithChanges( + { realm -> + PushRuleEntity.where(realm, scope = RuleScope.GLOBAL, ruleId = roomId) + }, + { result -> + result.toRoomPushRule() + } + ) + return Transformations.map(liveData) { results -> + results.firstOrNull() + } + } + +} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/notification/RoomPushRule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/notification/RoomPushRule.kt new file mode 100644 index 0000000000..b07f94f0f3 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/notification/RoomPushRule.kt @@ -0,0 +1,25 @@ +/* + * 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.matrix.android.internal.session.room.notification + +import im.vector.matrix.android.api.pushrules.RuleKind +import im.vector.matrix.android.api.pushrules.rest.PushRule + +internal data class RoomPushRule( + val kind: RuleKind, + val rule: PushRule +) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/notification/RoomPushRuleMapper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/notification/RoomPushRuleMapper.kt new file mode 100644 index 0000000000..159eb511ee --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/notification/RoomPushRuleMapper.kt @@ -0,0 +1,102 @@ +/* + * 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.matrix.android.internal.session.room.notification + +import im.vector.matrix.android.api.pushrules.* +import im.vector.matrix.android.api.pushrules.rest.PushCondition +import im.vector.matrix.android.api.pushrules.rest.PushRule +import im.vector.matrix.android.api.session.room.notification.RoomNotificationState +import im.vector.matrix.android.internal.database.mapper.PushRulesMapper +import im.vector.matrix.android.internal.database.model.PushRuleEntity + +internal fun PushRuleEntity.toRoomPushRule(): RoomPushRule? { + val kind = parent?.firstOrNull()?.kind + val pushRule = when (kind) { + RuleSetKey.OVERRIDE -> { + PushRulesMapper.map(this) + } + RuleSetKey.ROOM -> { + PushRulesMapper.mapRoomRule(this) + } + else -> null + } + return if (pushRule == null || kind == null) { + null + } else { + RoomPushRule(kind, pushRule) + } +} + +internal fun RoomNotificationState.toRoomPushRule(roomId: String): RoomPushRule? { + return when { + this == RoomNotificationState.ALL_MESSAGES -> null + this == RoomNotificationState.ALL_MESSAGES_NOISY -> { + val rule = PushRule( + actions = listOf(Action.Notify, Action.Sound()).toJson(), + enabled = true, + ruleId = roomId + ) + return RoomPushRule(RuleSetKey.ROOM, rule) + } + else -> { + val condition = PushCondition( + kind = Condition.Kind.event_match.value, + key = "room_id", + pattern = roomId + ) + val rule = PushRule( + actions = listOf(Action.DoNotNotify).toJson(), + enabled = true, + ruleId = roomId, + conditions = listOf(condition) + ) + val kind = if (this == RoomNotificationState.MUTE) { + RuleSetKey.OVERRIDE + } else { + RuleSetKey.ROOM + } + return RoomPushRule(kind, rule) + } + } +} + +internal fun RoomPushRule.toRoomNotificationState(): RoomNotificationState { + return if (rule.enabled) { + val actions = rule.getActions() + if (actions.contains(Action.DoNotNotify)) { + if (kind == RuleSetKey.OVERRIDE) { + RoomNotificationState.MUTE + } else { + RoomNotificationState.MENTIONS_ONLY + } + } else if (actions.contains(Action.Notify)) { + val hasSoundAction = actions.find { + it is Action.Sound + } != null + if (hasSoundAction) { + RoomNotificationState.ALL_MESSAGES_NOISY + } else { + RoomNotificationState.ALL_MESSAGES + } + } else { + RoomNotificationState.ALL_MESSAGES + } + } else { + RoomNotificationState.ALL_MESSAGES + } +} + diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/notification/SetRoomNotificationStateTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/notification/SetRoomNotificationStateTask.kt new file mode 100644 index 0000000000..0362a6607f --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/notification/SetRoomNotificationStateTask.kt @@ -0,0 +1,54 @@ +/* + * 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.matrix.android.internal.session.room.notification + +import com.zhuinden.monarchy.Monarchy +import im.vector.matrix.android.api.pushrules.RuleScope +import im.vector.matrix.android.api.session.room.notification.RoomNotificationState +import im.vector.matrix.android.internal.database.model.PushRuleEntity +import im.vector.matrix.android.internal.database.query.where +import im.vector.matrix.android.internal.session.pushers.AddPushRuleTask +import im.vector.matrix.android.internal.session.pushers.RemovePushRuleTask +import im.vector.matrix.android.internal.task.Task +import io.realm.Realm +import javax.inject.Inject + +internal interface SetRoomNotificationStateTask : Task { + data class Params( + val roomId: String, + val roomNotificationState: RoomNotificationState + ) +} + +internal class DefaultSetRoomNotificationStateTask @Inject constructor(private val monarchy: Monarchy, + private val removePushRuleTask: RemovePushRuleTask, + private val addPushRuleTask: AddPushRuleTask) + : SetRoomNotificationStateTask { + + override suspend fun execute(params: SetRoomNotificationStateTask.Params) { + val currentRoomPushRule = Realm.getInstance(monarchy.realmConfiguration).use { + PushRuleEntity.where(it, scope = RuleScope.GLOBAL, ruleId = params.roomId).findFirst()?.toRoomPushRule() + } + if (currentRoomPushRule != null) { + removePushRuleTask.execute(RemovePushRuleTask.Params(currentRoomPushRule.kind, currentRoomPushRule.rule)) + } + val newRoomPushRule = params.roomNotificationState.toRoomPushRule(params.roomId) + if (newRoomPushRule != null) { + addPushRuleTask.execute(AddPushRuleTask.Params(newRoomPushRule.kind, newRoomPushRule.rule)) + } + } +} 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 81b26a99d4..7fce5bf99f 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 @@ -17,6 +17,7 @@ package im.vector.riotx.features.home.room.list import im.vector.matrix.android.api.session.room.model.RoomSummary +import im.vector.matrix.android.api.session.room.notification.RoomNotificationState sealed class RoomListActions { data class SelectRoom(val roomSummary: RoomSummary) : RoomListActions() @@ -24,7 +25,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 ChangeRoomNotificationState(val roomId: String, val notificationState: RoomNotificationState) : 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 22415fd792..3eb9f99f75 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 @@ -31,6 +31,7 @@ import com.google.android.material.snackbar.Snackbar 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 +import im.vector.matrix.android.api.session.room.notification.RoomNotificationState import im.vector.riotx.R import im.vector.riotx.core.di.ScreenComponent import im.vector.riotx.core.epoxy.LayoutManagerStateRestorer @@ -216,12 +217,24 @@ 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)) + is RoomListQuickActions.NotificationsAllNoisy -> { + roomListViewModel.accept(RoomListActions.ChangeRoomNotificationState(quickActions.roomId, RoomNotificationState.ALL_MESSAGES_NOISY)) + } + is RoomListQuickActions.NotificationsAll -> { + roomListViewModel.accept(RoomListActions.ChangeRoomNotificationState(quickActions.roomId, RoomNotificationState.ALL_MESSAGES)) + } + is RoomListQuickActions.NotificationsMentionsOnly -> { + roomListViewModel.accept(RoomListActions.ChangeRoomNotificationState(quickActions.roomId, RoomNotificationState.MENTIONS_ONLY)) + } + is RoomListQuickActions.NotificationsMute -> { + roomListViewModel.accept(RoomListActions.ChangeRoomNotificationState(quickActions.roomId, RoomNotificationState.MUTE)) + } + is RoomListQuickActions.Settings -> { + navigator.openRoomSettings(requireContext(), quickActions.roomId) + } + is RoomListQuickActions.Leave -> { + roomListViewModel.accept(RoomListActions.LeaveRoom(quickActions.roomId)) + } } } 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 c6010f89f0..32061b9cbf 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,14 +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.LeaveRoom -> handleLeaveRoom(action) - is RoomListActions.ChangeNotificationMode -> handleChangeNotificationMode(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.LeaveRoom -> handleLeaveRoom(action) + is RoomListActions.ChangeRoomNotificationState -> handleChangeNotificationMode(action) } } @@ -205,9 +205,10 @@ 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 handleChangeNotificationMode(action: RoomListActions.ChangeRoomNotificationState) { + session.getRoom(action.roomId)?.also { + it.setRoomNotificationState(action.notificationState, object : MatrixCallback {}) + } } private fun handleLeaveRoom(action: RoomListActions.LeaveRoom) { 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 b15b91e6c0..e8e40c30e2 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 @@ -20,10 +20,12 @@ import com.airbnb.mvrx.Async import com.airbnb.mvrx.MvRxState import com.airbnb.mvrx.Uninitialized import im.vector.matrix.android.api.session.room.model.RoomSummary +import im.vector.matrix.android.api.session.room.notification.RoomNotificationState data class RoomListQuickActionsState( val roomId: String, - val roomSummary: Async = Uninitialized + val roomSummary: Async = Uninitialized, + val roomNotificationState: 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/RoomListQuickActionsViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsViewModel.kt index 9569f2c434..422a1097f2 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 @@ -51,6 +51,16 @@ class RoomListActionsViewModel @AssistedInject constructor(@Assisted init { observeRoomSummary() + observeNotificationState() + } + + private fun observeNotificationState() { + room + .rx() + .liveNotificationState() + .execute { + copy(roomNotificationState = it) + } } private fun observeRoomSummary() { From 8030c44f4441774a25fcfaa52e12c7141d2d6d65 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 4 Nov 2019 14:31:03 +0100 Subject: [PATCH 04/10] Room list actions: fix some UI issues and render selected notification state --- .../bottomsheet/BottomSheetItemAction.kt | 31 +++++++--- .../home/room/list/RoomListFragment.kt | 2 +- .../RoomListQuickActionsEpoxyController.kt | 22 ++++++-- .../main/res/drawable/ic_check_white_24dp.xml | 4 ++ .../res/layout/item_bottom_sheet_action.xml | 56 +++++++++++++------ 5 files changed, 84 insertions(+), 31 deletions(-) create mode 100644 vector/src/main/res/drawable/ic_check_white_24dp.xml diff --git a/vector/src/main/java/im/vector/riotx/core/epoxy/bottomsheet/BottomSheetItemAction.kt b/vector/src/main/java/im/vector/riotx/core/epoxy/bottomsheet/BottomSheetItemAction.kt index 1099243ace..3dd760a520 100644 --- a/vector/src/main/java/im/vector/riotx/core/epoxy/bottomsheet/BottomSheetItemAction.kt +++ b/vector/src/main/java/im/vector/riotx/core/epoxy/bottomsheet/BottomSheetItemAction.kt @@ -20,12 +20,17 @@ import android.view.View import android.widget.ImageView import android.widget.TextView import androidx.annotation.DrawableRes +import androidx.core.content.ContextCompat +import androidx.core.graphics.drawable.DrawableCompat +import androidx.core.view.isInvisible import androidx.core.view.isVisible import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import im.vector.riotx.R import im.vector.riotx.core.epoxy.VectorEpoxyHolder import im.vector.riotx.core.epoxy.VectorEpoxyModel +import im.vector.riotx.core.resources.ColorProvider +import im.vector.riotx.features.themes.ThemeUtils /** * A action for bottom sheet. @@ -43,6 +48,8 @@ abstract class BottomSheetItemAction : VectorEpoxyModel(R.id.action_start_space) - val icon by bind(R.id.action_icon) - val text by bind(R.id.action_title) - val expand by bind(R.id.action_expand) + val startSpace by bind(R.id.actionStartSpace) + val icon by bind(R.id.actionIcon) + val text by bind(R.id.actionTitle) + val selected by bind(R.id.actionSelected) } } 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 3eb9f99f75..bcd640589c 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 @@ -230,7 +230,7 @@ class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Listener, O roomListViewModel.accept(RoomListActions.ChangeRoomNotificationState(quickActions.roomId, RoomNotificationState.MUTE)) } is RoomListQuickActions.Settings -> { - navigator.openRoomSettings(requireContext(), quickActions.roomId) + vectorBaseActivity.notImplemented("Opening room settings") } is RoomListQuickActions.Leave -> { roomListViewModel.accept(RoomListActions.LeaveRoom(quickActions.roomId)) 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 f2c71868df..63b68b4c17 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 @@ -17,6 +17,7 @@ package im.vector.riotx.features.home.room.list.actions import android.view.View import com.airbnb.epoxy.TypedEpoxyController +import im.vector.matrix.android.api.session.room.notification.RoomNotificationState import im.vector.riotx.EmojiCompatFontProvider import im.vector.riotx.core.date.VectorDateFormatter import im.vector.riotx.core.epoxy.bottomsheet.BottomSheetItemAction_ @@ -53,10 +54,12 @@ class RoomListQuickActionsEpoxyController @Inject constructor(private val string bottomSheetItemSeparator { 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) + + val selectedRoomState = state.roomNotificationState() + RoomListQuickActions.NotificationsAllNoisy(roomSummary.roomId).toBottomSheetItem(0, selectedRoomState) + RoomListQuickActions.NotificationsAll(roomSummary.roomId).toBottomSheetItem(1, selectedRoomState) + RoomListQuickActions.NotificationsMentionsOnly(roomSummary.roomId).toBottomSheetItem(2, selectedRoomState) + RoomListQuickActions.NotificationsMute(roomSummary.roomId).toBottomSheetItem(3, selectedRoomState) // Leave bottomSheetItemSeparator { @@ -65,9 +68,18 @@ class RoomListQuickActionsEpoxyController @Inject constructor(private val string RoomListQuickActions.Leave(roomSummary.roomId).toBottomSheetItem(5) } - private fun RoomListQuickActions.toBottomSheetItem(index: Int) { + private fun RoomListQuickActions.toBottomSheetItem(index: Int, roomNotificationState: RoomNotificationState? = null) { + val selected = when (this) { + is RoomListQuickActions.NotificationsAllNoisy -> roomNotificationState == RoomNotificationState.ALL_MESSAGES_NOISY + is RoomListQuickActions.NotificationsAll -> roomNotificationState == RoomNotificationState.ALL_MESSAGES + is RoomListQuickActions.NotificationsMentionsOnly -> roomNotificationState == RoomNotificationState.MENTIONS_ONLY + is RoomListQuickActions.NotificationsMute -> roomNotificationState == RoomNotificationState.MUTE + is RoomListQuickActions.Settings, + is RoomListQuickActions.Leave -> false + } return BottomSheetItemAction_() .id("action_$index") + .selected(selected) .iconRes(iconResId) .textRes(titleRes) .listener(View.OnClickListener { listener?.didSelectMenuAction(this) }) diff --git a/vector/src/main/res/drawable/ic_check_white_24dp.xml b/vector/src/main/res/drawable/ic_check_white_24dp.xml new file mode 100644 index 0000000000..0aedb18ddd --- /dev/null +++ b/vector/src/main/res/drawable/ic_check_white_24dp.xml @@ -0,0 +1,4 @@ + + + + diff --git a/vector/src/main/res/layout/item_bottom_sheet_action.xml b/vector/src/main/res/layout/item_bottom_sheet_action.xml index 131ee0e63c..0ad7a211da 100644 --- a/vector/src/main/res/layout/item_bottom_sheet_action.xml +++ b/vector/src/main/res/layout/item_bottom_sheet_action.xml @@ -1,52 +1,72 @@ - + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toEndOf="@+id/actionStartSpace" + app:layout_constraintTop_toTopOf="parent" + tools:src="@drawable/ic_room_actions_notifications_all" /> + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toStartOf="@+id/actionSelected" + app:layout_constraintHorizontal_bias="0.0" + app:layout_constraintStart_toEndOf="@id/actionStartSpace" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintWidth_default="wrap" + tools:text="zbla azjazjaz s sdkqdskdsqk kqsdkdqsk kdqsksqdk" /> + - + + From 6ebe5532c5e20ef6016fd955be23a9d9c22a58a3 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 4 Nov 2019 14:59:12 +0100 Subject: [PATCH 05/10] Room list actions: use new strings --- .../home/room/list/actions/RoomListQuickActions.kt | 12 ++++++------ .../res/layout/item_bottom_sheet_room_preview.xml | 2 ++ vector/src/main/res/values/strings_riotX.xml | 4 ++-- 3 files changed, 10 insertions(+), 8 deletions(-) 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 30d4abff36..c0c77e0319 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 @@ -21,12 +21,12 @@ 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) + data class NotificationsAllNoisy(val roomId: String) : RoomListQuickActions(R.string.room_list_quick_actions_notifications_all_noisy, R.drawable.ic_room_actions_notifications_all_noisy) + data class NotificationsAll(val roomId: String) : RoomListQuickActions(R.string.room_list_quick_actions_notifications_all, R.drawable.ic_room_actions_notifications_all) + data class NotificationsMentionsOnly(val roomId: String) : RoomListQuickActions(R.string.room_list_quick_actions_notifications_mentions, R.drawable.ic_room_actions_notifications_mentions) + data class NotificationsMute(val roomId: String) : RoomListQuickActions(R.string.room_list_quick_actions_notifications_mute, R.drawable.ic_room_actions_notifications_mutes) + data class Settings(val roomId: String) : RoomListQuickActions(R.string.room_list_quick_actions_settings, R.drawable.ic_room_actions_settings) + data class Leave(val roomId: String) : RoomListQuickActions(R.string.room_list_quick_actions_leave, R.drawable.ic_room_actions_leave) companion object { fun all(roomId: String): List { 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 index 410e6ea1ab..1a38feface 100644 --- a/vector/src/main/res/layout/item_bottom_sheet_room_preview.xml +++ b/vector/src/main/res/layout/item_bottom_sheet_room_preview.xml @@ -16,6 +16,7 @@ android:layout_marginBottom="8dp" android:adjustViewBounds="true" android:background="@drawable/circle" + android:importantForAccessibility="no" android:contentDescription="@string/avatar" android:scaleType="centerCrop" app:layout_constraintBottom_toBottomOf="parent" @@ -50,6 +51,7 @@ android:background="?attr/selectableItemBackground" android:scaleType="centerInside" android:src="@drawable/ic_room_actions_settings" + android:contentDescription="@string/room_list_quick_actions_settings" app:layout_constraintBottom_toBottomOf="@+id/bottomSheetRoomPreviewAvatar" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="@id/bottomSheetRoomPreviewAvatar" /> diff --git a/vector/src/main/res/values/strings_riotX.xml b/vector/src/main/res/values/strings_riotX.xml index 9b12db5e7f..c627d40eb0 100644 --- a/vector/src/main/res/values/strings_riotX.xml +++ b/vector/src/main/res/values/strings_riotX.xml @@ -6,7 +6,7 @@ "All messages" "Mentions only" "Mute" - "Settings" - "Leave" + "Settings" + "Leave the room" From 5c71cabb5fef560e329ae47166694750ecd2b33a Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 4 Nov 2019 15:08:08 +0100 Subject: [PATCH 06/10] Clean code --- CHANGES.md | 1 + .../matrix/android/api/pushrules/Action.kt | 1 - .../room/notification/RoomPushRuleService.kt | 1 - .../internal/database/query/PushersQueries.kt | 1 - .../internal/session/room/RoomFactory.kt | 1 - .../DefaultRoomPushRuleService.kt | 1 - .../room/notification/RoomPushRuleMapper.kt | 1 - .../vector/riotx/core/di/ViewModelModule.kt | 4 -- .../bottomsheet/BottomSheetItemAction.kt | 1 - .../riotx/core/platform/VectorViewModel.kt | 1 - .../riotx/features/home/HomeActivity.kt | 1 - .../createdirect/CreateDirectRoomActivity.kt | 1 - .../room/list/actions/RoomListQuickActions.kt | 37 +++++++++++++++---- .../RoomListQuickActionsBottomSheet.kt | 5 +-- .../RoomListQuickActionsEpoxyController.kt | 3 +- .../list/actions/RoomListQuickActionsState.kt | 1 - .../actions/RoomListQuickActionsViewModel.kt | 19 +++------- .../features/navigation/DefaultNavigator.kt | 1 - .../riotx/features/navigation/Navigator.kt | 1 - .../roomdirectory/RoomDirectoryActivity.kt | 1 - .../createroom/CreateRoomActivity.kt | 1 - 21 files changed, 40 insertions(+), 44 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 8d536dbd97..c52ad4af0d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -13,6 +13,7 @@ Improvements: - Mark all messages as read (#396) - Add ability to report content (#515) + Other changes: - Accessibility improvements to read receipts in the room timeline and reactions emoji chooser diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/Action.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/Action.kt index d1e5b3c868..a81af2cf21 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/Action.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/Action.kt @@ -86,7 +86,6 @@ fun List.toJson(): List { } } - fun PushRule.getActions(): List { val result = ArrayList() diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/notification/RoomPushRuleService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/notification/RoomPushRuleService.kt index 7b3e88240b..41cd484ef9 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/notification/RoomPushRuleService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/notification/RoomPushRuleService.kt @@ -25,5 +25,4 @@ interface RoomPushRuleService { fun getLiveRoomNotificationState(): LiveData fun setRoomNotificationState(roomNotificationState: RoomNotificationState, matrixCallback: MatrixCallback): Cancelable - } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/PushersQueries.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/PushersQueries.kt index a97ed8d415..42e7770114 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/PushersQueries.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/PushersQueries.kt @@ -49,4 +49,3 @@ internal fun PushRuleEntity.Companion.where(realm: Realm, .equalTo("${PushRuleEntityFields.PARENT}.${PushRulesEntityFields.SCOPE}", scope) .equalTo(PushRuleEntityFields.RULE_ID, ruleId) } - diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomFactory.kt index 2c441762dd..30a2948f68 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomFactory.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomFactory.kt @@ -19,7 +19,6 @@ package im.vector.matrix.android.internal.session.room import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.api.session.crypto.CryptoService import im.vector.matrix.android.api.session.room.Room -import im.vector.matrix.android.api.session.room.notification.RoomPushRuleService import im.vector.matrix.android.internal.database.mapper.RoomSummaryMapper import im.vector.matrix.android.internal.session.room.draft.DefaultDraftService import im.vector.matrix.android.internal.session.room.membership.DefaultMembershipService diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/notification/DefaultRoomPushRuleService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/notification/DefaultRoomPushRuleService.kt index a27cdb1007..7cb7452244 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/notification/DefaultRoomPushRuleService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/notification/DefaultRoomPushRuleService.kt @@ -69,5 +69,4 @@ internal class DefaultRoomPushRuleService @AssistedInject constructor(@Assisted results.firstOrNull() } } - } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/notification/RoomPushRuleMapper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/notification/RoomPushRuleMapper.kt index 159eb511ee..d08d346a1f 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/notification/RoomPushRuleMapper.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/notification/RoomPushRuleMapper.kt @@ -99,4 +99,3 @@ internal fun RoomPushRule.toRoomNotificationState(): RoomNotificationState { RoomNotificationState.ALL_MESSAGES } } - 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 83aa7103d9..d2b8abb9c4 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 @@ -27,10 +27,7 @@ import im.vector.riotx.features.crypto.keysbackup.restore.KeysBackupRestoreFromP import im.vector.riotx.features.crypto.keysbackup.restore.KeysBackupRestoreSharedViewModel import im.vector.riotx.features.crypto.keysbackup.setup.KeysBackupSetupSharedViewModel import im.vector.riotx.features.crypto.verification.SasVerificationViewModel -import im.vector.riotx.features.home.HomeNavigationViewModel -import im.vector.riotx.features.home.createdirect.CreateDirectRoomNavigationViewModel import im.vector.riotx.features.reactions.EmojiChooserViewModel -import im.vector.riotx.features.roomdirectory.RoomDirectoryNavigationViewModel import im.vector.riotx.features.workers.signout.SignOutViewModel @Module @@ -85,5 +82,4 @@ interface ViewModelModule { @IntoMap @ViewModelKey(ConfigurationViewModel::class) fun bindConfigurationViewModel(viewModel: ConfigurationViewModel): ViewModel - } diff --git a/vector/src/main/java/im/vector/riotx/core/epoxy/bottomsheet/BottomSheetItemAction.kt b/vector/src/main/java/im/vector/riotx/core/epoxy/bottomsheet/BottomSheetItemAction.kt index 3dd760a520..e0299f4e65 100644 --- a/vector/src/main/java/im/vector/riotx/core/epoxy/bottomsheet/BottomSheetItemAction.kt +++ b/vector/src/main/java/im/vector/riotx/core/epoxy/bottomsheet/BottomSheetItemAction.kt @@ -29,7 +29,6 @@ import com.airbnb.epoxy.EpoxyModelClass import im.vector.riotx.R import im.vector.riotx.core.epoxy.VectorEpoxyHolder import im.vector.riotx.core.epoxy.VectorEpoxyModel -import im.vector.riotx.core.resources.ColorProvider import im.vector.riotx.features.themes.ThemeUtils /** 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 7f04f184a8..9679c20efb 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,5 +44,4 @@ abstract class VectorViewModel(initialState: S) .onErrorReturn { Fail(it) } .doOnNext { setState { stateReducer(it) } } } - } 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 e552af0095..01f869c82a 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 @@ -31,7 +31,6 @@ import im.vector.riotx.R import im.vector.riotx.core.di.ActiveSessionHolder import im.vector.riotx.core.di.ScreenComponent import im.vector.riotx.core.extensions.hideKeyboard -import im.vector.riotx.core.extensions.observeEvent import im.vector.riotx.core.extensions.replaceFragment import im.vector.riotx.core.platform.ToolbarConfigurable import im.vector.riotx.core.platform.VectorBaseActivity 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 2b4322a87c..c4e7855c14 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 @@ -31,7 +31,6 @@ import im.vector.riotx.core.di.ScreenComponent import im.vector.riotx.core.error.ErrorFormatter import im.vector.riotx.core.extensions.addFragment import im.vector.riotx.core.extensions.addFragmentToBackstack -import im.vector.riotx.core.extensions.observeEvent import im.vector.riotx.core.platform.SimpleFragmentActivity import im.vector.riotx.core.platform.WaitingViewData import kotlinx.android.synthetic.main.activity.* 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 c0c77e0319..e89b4ebcd0 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 @@ -21,12 +21,36 @@ 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_list_quick_actions_notifications_all_noisy, R.drawable.ic_room_actions_notifications_all_noisy) - data class NotificationsAll(val roomId: String) : RoomListQuickActions(R.string.room_list_quick_actions_notifications_all, R.drawable.ic_room_actions_notifications_all) - data class NotificationsMentionsOnly(val roomId: String) : RoomListQuickActions(R.string.room_list_quick_actions_notifications_mentions, R.drawable.ic_room_actions_notifications_mentions) - data class NotificationsMute(val roomId: String) : RoomListQuickActions(R.string.room_list_quick_actions_notifications_mute, R.drawable.ic_room_actions_notifications_mutes) - data class Settings(val roomId: String) : RoomListQuickActions(R.string.room_list_quick_actions_settings, R.drawable.ic_room_actions_settings) - data class Leave(val roomId: String) : RoomListQuickActions(R.string.room_list_quick_actions_leave, R.drawable.ic_room_actions_leave) + + data class NotificationsAllNoisy(val roomId: String) : RoomListQuickActions( + R.string.room_list_quick_actions_notifications_all_noisy, + R.drawable.ic_room_actions_notifications_all_noisy + ) + + data class NotificationsAll(val roomId: String) : RoomListQuickActions( + R.string.room_list_quick_actions_notifications_all, + R.drawable.ic_room_actions_notifications_all + ) + + data class NotificationsMentionsOnly(val roomId: String) : RoomListQuickActions( + R.string.room_list_quick_actions_notifications_mentions, + R.drawable.ic_room_actions_notifications_mentions + ) + + data class NotificationsMute(val roomId: String) : RoomListQuickActions( + R.string.room_list_quick_actions_notifications_mute, + R.drawable.ic_room_actions_notifications_mutes + ) + + data class Settings(val roomId: String) : RoomListQuickActions( + R.string.room_list_quick_actions_settings, + R.drawable.ic_room_actions_settings + ) + + data class Leave(val roomId: String) : RoomListQuickActions( + R.string.room_list_quick_actions_leave, + R.drawable.ic_room_actions_leave + ) companion object { fun all(roomId: String): List { @@ -40,5 +64,4 @@ sealed class RoomListQuickActions(@StringRes val titleRes: Int, @DrawableRes val ) } } - } 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 03e661eb20..560c05771c 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 @@ -46,11 +46,11 @@ data class RoomListActionsArgs( class RoomListQuickActionsBottomSheet : VectorBaseBottomSheetDialogFragment(), RoomListQuickActionsEpoxyController.Listener { private lateinit var actionsDispatcher: RoomListQuickActionsStore - @Inject lateinit var roomListActionsViewModelFactory: RoomListActionsViewModel.Factory + @Inject lateinit var roomListActionsViewModelFactory: RoomListQuickActionsViewModel.Factory @Inject lateinit var roomListActionsEpoxyController: RoomListQuickActionsEpoxyController @Inject lateinit var navigator: Navigator - private val viewModel: RoomListActionsViewModel by fragmentViewModel(RoomListActionsViewModel::class) + private val viewModel: RoomListQuickActionsViewModel by fragmentViewModel(RoomListQuickActionsViewModel::class) @BindView(R.id.bottomSheetRecyclerView) lateinit var recyclerView: RecyclerView @@ -77,7 +77,6 @@ class RoomListQuickActionsBottomSheet : VectorBaseBottomSheetDialogFragment(), R roomListActionsEpoxyController.listener = this } - override fun invalidate() = withState(viewModel) { roomListActionsEpoxyController.setData(it) super.invalidate() 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 63b68b4c17..cc6abc42b1 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 @@ -33,7 +33,8 @@ 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() { + private val fontProvider: EmojiCompatFontProvider) + : TypedEpoxyController() { var listener: Listener? = null 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 e8e40c30e2..a943db1804 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 @@ -29,5 +29,4 @@ data class RoomListQuickActionsState( ) : MvRxState { constructor(args: RoomListActionsArgs) : this(roomId = args.roomId) - } 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 422a1097f2..0eeef64a78 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 @@ -18,30 +18,23 @@ package im.vector.riotx.features.home.room.list.actions 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, - session: Session +class RoomListQuickActionsViewModel @AssistedInject constructor(@Assisted initialState: RoomListQuickActionsState, + session: Session ) : VectorViewModel(initialState) { @AssistedInject.Factory interface Factory { - fun create(initialState: RoomListQuickActionsState): RoomListActionsViewModel + fun create(initialState: RoomListQuickActionsState): RoomListQuickActionsViewModel } - companion object : MvRxViewModelFactory { + companion object : MvRxViewModelFactory { - override fun create(viewModelContext: ViewModelContext, state: RoomListQuickActionsState): RoomListActionsViewModel? { + override fun create(viewModelContext: ViewModelContext, state: RoomListQuickActionsState): RoomListQuickActionsViewModel? { val fragment: RoomListQuickActionsBottomSheet = (viewModelContext as FragmentViewModelContext).fragment() return fragment.roomListActionsViewModelFactory.create(state) } @@ -72,6 +65,4 @@ class RoomListActionsViewModel @AssistedInject constructor(@Assisted 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 f0958b5b35..685fa04fef 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 @@ -115,6 +115,5 @@ class DefaultNavigator @Inject constructor() : Navigator { 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 8bd5f520c1..83c4f7ce20 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 @@ -52,5 +52,4 @@ interface Navigator { fun openUserDetail(userId: String, context: Context) fun openRoomSettings(context: Context, roomId: String) - } 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 e8914970ff..43894aa244 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 @@ -25,7 +25,6 @@ import im.vector.riotx.R import im.vector.riotx.core.di.ScreenComponent import im.vector.riotx.core.extensions.addFragment import im.vector.riotx.core.extensions.addFragmentToBackstack -import im.vector.riotx.core.extensions.observeEvent import im.vector.riotx.core.platform.VectorBaseActivity import im.vector.riotx.features.roomdirectory.createroom.CreateRoomFragment import im.vector.riotx.features.roomdirectory.createroom.CreateRoomViewModel 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 00bd42901a..20843f86cb 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 @@ -25,7 +25,6 @@ import com.airbnb.mvrx.viewModel import im.vector.riotx.R import im.vector.riotx.core.di.ScreenComponent import im.vector.riotx.core.extensions.addFragment -import im.vector.riotx.core.extensions.observeEvent import im.vector.riotx.core.platform.ToolbarConfigurable import im.vector.riotx.core.platform.VectorBaseActivity import im.vector.riotx.features.roomdirectory.RoomDirectoryActivity From e66766f41ceb8ed4f3125f35b5c5dfd829162fa9 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 4 Nov 2019 15:12:30 +0100 Subject: [PATCH 07/10] Update CHANGES --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 1a29b77427..c53dc349d2 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,7 +2,7 @@ Changes in RiotX 0.8.0 (2019-XX-XX) =================================================== Features ✨: - - + - Handle long click on room in the room list (#395) Improvements 🙌: - Handle code tags (#567) From 93df8c56a877cca47398efb1b59e3576840ac2f5 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 4 Nov 2019 17:07:23 +0100 Subject: [PATCH 08/10] Fix compilation error and use mockk instead of manual mocking (prone to error) --- .../api/pushrules/PushrulesConditionTest.kt | 271 +++--------------- .../share/ShareRoomListObservableStore.kt | 3 +- 2 files changed, 40 insertions(+), 234 deletions(-) diff --git a/matrix-sdk-android/src/test/java/im/vector/matrix/android/api/pushrules/PushrulesConditionTest.kt b/matrix-sdk-android/src/test/java/im/vector/matrix/android/api/pushrules/PushrulesConditionTest.kt index 7651b32d20..7cb3917195 100644 --- a/matrix-sdk-android/src/test/java/im/vector/matrix/android/api/pushrules/PushrulesConditionTest.kt +++ b/matrix-sdk-android/src/test/java/im/vector/matrix/android/api/pushrules/PushrulesConditionTest.kt @@ -16,23 +16,21 @@ package im.vector.matrix.android.api.pushrules -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import im.vector.matrix.android.api.MatrixCallback -import im.vector.matrix.android.api.session.content.ContentAttachmentData import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.events.model.toContent import im.vector.matrix.android.api.session.room.Room import im.vector.matrix.android.api.session.room.RoomService -import im.vector.matrix.android.api.session.room.model.* -import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams +import im.vector.matrix.android.api.session.room.model.Membership +import im.vector.matrix.android.api.session.room.model.RoomMember import im.vector.matrix.android.api.session.room.model.message.MessageTextContent -import im.vector.matrix.android.api.session.room.send.UserDraft -import im.vector.matrix.android.api.session.room.timeline.Timeline -import im.vector.matrix.android.api.session.room.timeline.TimelineEvent -import im.vector.matrix.android.api.session.room.timeline.TimelineSettings -import im.vector.matrix.android.api.util.Cancelable -import im.vector.matrix.android.api.util.Optional +import io.mockk.every +import io.mockk.mockk +import org.amshove.kluent.When +import org.amshove.kluent.any +import org.amshove.kluent.calling +import org.amshove.kluent.itAnswers +import org.amshove.kluent.itReturns +import org.amshove.kluent.mock import org.junit.Assert import org.junit.Test @@ -133,17 +131,20 @@ class PushrulesConditionTest { val conditionEqual3Bis = RoomMemberCountCondition("==3") val conditionLessThan3 = RoomMemberCountCondition("<3") - val session = MockRoomService() + val room2JoinedId = "2joined" + val room3JoinedId = "3joined" - Event( - type = "m.room.message", - eventId = "mx0", - content = MessageTextContent("m.text", "A").toContent(), - originServerTs = 0, - roomId = "2joined").also { - Assert.assertFalse("This room does not have 3 members", conditionEqual3.isSatisfied(it, session)) - Assert.assertFalse("This room does not have 3 members", conditionEqual3Bis.isSatisfied(it, session)) - Assert.assertTrue("This room has less than 3 members", conditionLessThan3.isSatisfied(it, session)) + val roomStub2Joined = mockk { + every { getNumberOfJoinedMembers() } returns 2 + } + + val roomStub3Joined = mockk { + every { getNumberOfJoinedMembers() } returns 3 + } + + val sessionStub = mockk { + every { getRoom(room2JoinedId) } returns roomStub2Joined + every { getRoom(room3JoinedId) } returns roomStub3Joined } Event( @@ -151,10 +152,21 @@ class PushrulesConditionTest { eventId = "mx0", content = MessageTextContent("m.text", "A").toContent(), originServerTs = 0, - roomId = "3joined").also { - Assert.assertTrue("This room has 3 members", conditionEqual3.isSatisfied(it, session)) - Assert.assertTrue("This room has 3 members", conditionEqual3Bis.isSatisfied(it, session)) - Assert.assertFalse("This room has more than 3 members", conditionLessThan3.isSatisfied(it, session)) + roomId = room2JoinedId).also { + Assert.assertFalse("This room does not have 3 members", conditionEqual3.isSatisfied(it, sessionStub)) + Assert.assertFalse("This room does not have 3 members", conditionEqual3Bis.isSatisfied(it, sessionStub)) + Assert.assertTrue("This room has less than 3 members", conditionLessThan3.isSatisfied(it, sessionStub)) + } + + Event( + type = "m.room.message", + eventId = "mx0", + content = MessageTextContent("m.text", "A").toContent(), + originServerTs = 0, + roomId = room3JoinedId).also { + Assert.assertTrue("This room has 3 members", conditionEqual3.isSatisfied(it, sessionStub)) + Assert.assertTrue("This room has 3 members", conditionEqual3Bis.isSatisfied(it, sessionStub)) + Assert.assertFalse("This room has more than 3 members", conditionLessThan3.isSatisfied(it, sessionStub)) } } @@ -172,211 +184,4 @@ class PushrulesConditionTest { } } - class MockRoomService() : RoomService { - override fun createRoom(createRoomParams: CreateRoomParams, callback: MatrixCallback): Cancelable { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun joinRoom(roomId: String, viaServers: List, callback: MatrixCallback): Cancelable { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun getRoom(roomId: String): Room? { - return when (roomId) { - "2joined" -> MockRoom(roomId, 2) - "3joined" -> MockRoom(roomId, 3) - else -> null - } - } - - override fun liveRoomSummaries(): LiveData> { - return MutableLiveData() - } - - override fun markAllAsRead(roomIds: List, callback: MatrixCallback): Cancelable { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - } - - class MockRoom(override val roomId: String, val _numberOfJoinedMembers: Int) : Room { - override fun reportContent(eventId: String, score: Int, reason: String, callback: MatrixCallback): Cancelable { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun getReadMarkerLive(): LiveData> { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun getMyReadReceiptLive(): LiveData> { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun resendTextMessage(localEcho: TimelineEvent): Cancelable? { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun resendMediaMessage(localEcho: TimelineEvent): Cancelable? { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun deleteFailedEcho(localEcho: TimelineEvent) { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun clearSendingQueue() { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun resendAllFailedMessages() { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun saveDraft(draft: UserDraft) { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun deleteDraft() { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun getDraftsLive(): LiveData> { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun getEventReadReceiptsLive(eventId: String): LiveData> { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun getStateEvent(eventType: String): Event? { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun editReply(replyToEdit: TimelineEvent, originalTimelineEvent: TimelineEvent, newBodyText: String, compatibilityBodyText: String): Cancelable { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun fetchEditHistory(eventId: String, callback: MatrixCallback>) { - } - - override fun getTimeLineEventLive(eventId: String): LiveData> { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun getNumberOfJoinedMembers(): Int { - return _numberOfJoinedMembers - } - - override fun getRoomSummaryLive(): LiveData> { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun roomSummary(): RoomSummary? { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun createTimeline(eventId: String?, settings: TimelineSettings): Timeline { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun getTimeLineEvent(eventId: String): TimelineEvent? { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun sendTextMessage(text: String, msgType: String, autoMarkdown: Boolean): Cancelable { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun sendFormattedTextMessage(text: String, formattedText: String): Cancelable { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun sendMedia(attachment: ContentAttachmentData): Cancelable { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun sendMedias(attachments: List): Cancelable { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun redactEvent(event: Event, reason: String?): Cancelable { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun markAllAsRead(callback: MatrixCallback) { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun setReadReceipt(eventId: String, callback: MatrixCallback) { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun setReadMarker(fullyReadEventId: String, callback: MatrixCallback) { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun isEventRead(eventId: String): Boolean { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun loadRoomMembersIfNeeded(matrixCallback: MatrixCallback): Cancelable { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun getRoomMember(userId: String): RoomMember? { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun getRoomMemberIdsLive(): LiveData> { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun invite(userId: String, callback: MatrixCallback): Cancelable { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun join(viaServers: List, callback: MatrixCallback): Cancelable { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun leave(callback: MatrixCallback): Cancelable { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun updateTopic(topic: String, callback: MatrixCallback) { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun sendReaction(targetEventId: String, reaction: String): Cancelable { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun undoReaction(targetEventId: String, reaction: String): Cancelable { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun editTextMessage(targetEventId: String, msgType: String, newBodyText: String, - newBodyAutoMarkdown: Boolean, compatibilityBodyText: String): Cancelable { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun replyToMessage(eventReplied: TimelineEvent, replyText: String, autoMarkdown: Boolean): Cancelable? { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun getEventSummaryLive(eventId: String): LiveData> { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun isEncrypted(): Boolean { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun encryptionAlgorithm(): String? { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - - override fun shouldEncryptForInvitedMembers(): Boolean { - TODO("not implemented") // To change body of created functions use File | Settings | File Templates. - } - } } diff --git a/vector/src/main/java/im/vector/riotx/features/share/ShareRoomListObservableStore.kt b/vector/src/main/java/im/vector/riotx/features/share/ShareRoomListObservableStore.kt index c46ec42d64..bf7dde65ab 100644 --- a/vector/src/main/java/im/vector/riotx/features/share/ShareRoomListObservableStore.kt +++ b/vector/src/main/java/im/vector/riotx/features/share/ShareRoomListObservableStore.kt @@ -17,9 +17,10 @@ package im.vector.riotx.features.share import im.vector.matrix.android.api.session.room.model.RoomSummary +import im.vector.riotx.core.utils.BehaviorStore import im.vector.riotx.core.utils.RxStore import javax.inject.Inject import javax.inject.Singleton @Singleton -class ShareRoomListObservableStore @Inject constructor() : RxStore>() +class ShareRoomListObservableStore @Inject constructor() : BehaviorStore>() From ad9a48d5fa7cb3260fa2d81aa9165eefea8b92c0 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 5 Nov 2019 18:36:30 +0100 Subject: [PATCH 09/10] Clean code --- .../matrix/android/api/pushrules/PushrulesConditionTest.kt | 7 ------- .../java/im/vector/riotx/features/command/CommandParser.kt | 1 - .../riotx/features/share/ShareRoomListObservableStore.kt | 1 - 3 files changed, 9 deletions(-) diff --git a/matrix-sdk-android/src/test/java/im/vector/matrix/android/api/pushrules/PushrulesConditionTest.kt b/matrix-sdk-android/src/test/java/im/vector/matrix/android/api/pushrules/PushrulesConditionTest.kt index 7cb3917195..a29f5d5542 100644 --- a/matrix-sdk-android/src/test/java/im/vector/matrix/android/api/pushrules/PushrulesConditionTest.kt +++ b/matrix-sdk-android/src/test/java/im/vector/matrix/android/api/pushrules/PushrulesConditionTest.kt @@ -25,12 +25,6 @@ import im.vector.matrix.android.api.session.room.model.RoomMember import im.vector.matrix.android.api.session.room.model.message.MessageTextContent import io.mockk.every import io.mockk.mockk -import org.amshove.kluent.When -import org.amshove.kluent.any -import org.amshove.kluent.calling -import org.amshove.kluent.itAnswers -import org.amshove.kluent.itReturns -import org.amshove.kluent.mock import org.junit.Assert import org.junit.Test @@ -183,5 +177,4 @@ class PushrulesConditionTest { Assert.assertTrue("Notice", conditionEqual.isSatisfied(it)) } } - } diff --git a/vector/src/main/java/im/vector/riotx/features/command/CommandParser.kt b/vector/src/main/java/im/vector/riotx/features/command/CommandParser.kt index a9c20a9ec5..3f5808949b 100644 --- a/vector/src/main/java/im/vector/riotx/features/command/CommandParser.kt +++ b/vector/src/main/java/im/vector/riotx/features/command/CommandParser.kt @@ -56,7 +56,6 @@ object CommandParser { return ParsedCommand.ErrorEmptySlashCommand } - return when (val slashCommand = messageParts.first()) { Command.CHANGE_DISPLAY_NAME.command -> { val newDisplayName = textMessage.substring(Command.CHANGE_DISPLAY_NAME.command.length).trim() diff --git a/vector/src/main/java/im/vector/riotx/features/share/ShareRoomListObservableStore.kt b/vector/src/main/java/im/vector/riotx/features/share/ShareRoomListObservableStore.kt index bf7dde65ab..32b0093b8f 100644 --- a/vector/src/main/java/im/vector/riotx/features/share/ShareRoomListObservableStore.kt +++ b/vector/src/main/java/im/vector/riotx/features/share/ShareRoomListObservableStore.kt @@ -18,7 +18,6 @@ package im.vector.riotx.features.share import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.riotx.core.utils.BehaviorStore -import im.vector.riotx.core.utils.RxStore import javax.inject.Inject import javax.inject.Singleton From 04f72dfcb82586e7c516a540b83b4306ede6fd46 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 7 Nov 2019 15:19:12 +0100 Subject: [PATCH 10/10] Clean code after Benoit's review --- ...bleStore.kt => ActiveSessionDataSource.kt} | 4 +- .../java/im/vector/riotx/AppStateHandler.kt | 16 +++--- .../riotx/core/di/ActiveSessionHolder.kt | 4 +- .../vector/riotx/core/di/VectorComponent.kt | 16 +++--- .../bottomsheet/BottomSheetItemAction.kt | 12 +++- .../core/utils/{RxStore.kt => DataSource.kt} | 16 +++--- .../features/home/HomeDetailViewModel.kt | 6 +- .../features/home/HomeNavigationViewModel.kt | 8 +-- ...ableStore.kt => HomeRoomListDataSource.kt} | 4 +- .../CreateDirectRoomNavigationViewModel.kt | 8 +-- .../features/home/group/GroupListViewModel.kt | 2 +- ...oupStore.kt => SelectedGroupDataSource.kt} | 4 +- .../home/room/detail/RoomDetailFragment.kt | 8 +-- .../action/MessageActionsBottomSheet.kt | 4 +- ...nsStore.kt => MessageActionsDispatcher.kt} | 10 ++-- .../home/room/list/RoomListFragment.kt | 55 +++++++++++++------ .../home/room/list/RoomListViewEvents.kt | 26 +++++++++ .../home/room/list/RoomListViewModel.kt | 46 +++++++--------- .../room/list/RoomListViewModelFactory.kt | 10 ++-- .../room/list/actions/RoomListQuickActions.kt | 18 +----- .../RoomListQuickActionsEpoxyController.kt | 25 ++++----- .../list/actions/RoomListQuickActionsStore.kt | 8 +-- .../RoomDirectoryNavigationViewModel.kt | 8 +-- .../features/share/IncomingShareViewModel.kt | 6 +- ...bleStore.kt => ShareRoomListDataSource.kt} | 4 +- 25 files changed, 180 insertions(+), 148 deletions(-) rename vector/src/main/java/im/vector/riotx/{ActiveSessionObservableStore.kt => ActiveSessionDataSource.kt} (84%) rename vector/src/main/java/im/vector/riotx/core/utils/{RxStore.kt => DataSource.kt} (78%) rename vector/src/main/java/im/vector/riotx/features/home/{HomeRoomListObservableStore.kt => HomeRoomListDataSource.kt} (84%) rename vector/src/main/java/im/vector/riotx/features/home/group/{SelectedGroupStore.kt => SelectedGroupDataSource.kt} (83%) rename vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/{MessageActionsStore.kt => MessageActionsDispatcher.kt} (71%) create mode 100644 vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewEvents.kt rename vector/src/main/java/im/vector/riotx/features/share/{ShareRoomListObservableStore.kt => ShareRoomListDataSource.kt} (83%) diff --git a/vector/src/main/java/im/vector/riotx/ActiveSessionObservableStore.kt b/vector/src/main/java/im/vector/riotx/ActiveSessionDataSource.kt similarity index 84% rename from vector/src/main/java/im/vector/riotx/ActiveSessionObservableStore.kt rename to vector/src/main/java/im/vector/riotx/ActiveSessionDataSource.kt index cb89497577..4cafdb8d11 100644 --- a/vector/src/main/java/im/vector/riotx/ActiveSessionObservableStore.kt +++ b/vector/src/main/java/im/vector/riotx/ActiveSessionDataSource.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.BehaviorStore +import im.vector.riotx.core.utils.BehaviorDataSource import javax.inject.Inject import javax.inject.Singleton @Singleton -class ActiveSessionObservableStore @Inject constructor() : BehaviorStore>() +class ActiveSessionDataSource @Inject constructor() : BehaviorDataSource>() diff --git a/vector/src/main/java/im/vector/riotx/AppStateHandler.kt b/vector/src/main/java/im/vector/riotx/AppStateHandler.kt index 76cbb9ef94..7cb51b6373 100644 --- a/vector/src/main/java/im/vector/riotx/AppStateHandler.kt +++ b/vector/src/main/java/im/vector/riotx/AppStateHandler.kt @@ -23,9 +23,9 @@ import arrow.core.Option import im.vector.matrix.android.api.session.group.model.GroupSummary import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.rx.rx -import im.vector.riotx.features.home.HomeRoomListObservableStore +import im.vector.riotx.features.home.HomeRoomListDataSource import im.vector.riotx.features.home.group.ALL_COMMUNITIES_GROUP_ID -import im.vector.riotx.features.home.group.SelectedGroupStore +import im.vector.riotx.features.home.group.SelectedGroupDataSource import io.reactivex.Observable import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.CompositeDisposable @@ -41,9 +41,9 @@ import javax.inject.Singleton */ @Singleton class AppStateHandler @Inject constructor( - private val sessionObservableStore: ActiveSessionObservableStore, - private val homeRoomListObservableStore: HomeRoomListObservableStore, - private val selectedGroupStore: SelectedGroupStore) : LifecycleObserver { + private val sessionDataSource: ActiveSessionDataSource, + private val homeRoomListDataSource: HomeRoomListDataSource, + private val selectedGroupDataSource: SelectedGroupDataSource) : LifecycleObserver { private val compositeDisposable = CompositeDisposable() @@ -60,14 +60,14 @@ class AppStateHandler @Inject constructor( private fun observeRoomsAndGroup() { Observable .combineLatest, Option, List>( - sessionObservableStore.observe() + sessionDataSource.observe() .observeOn(AndroidSchedulers.mainThread()) .switchMap { it.orNull()?.rx()?.liveRoomSummaries() ?: Observable.just(emptyList()) } .throttleLast(300, TimeUnit.MILLISECONDS), - selectedGroupStore.observe(), + selectedGroupDataSource.observe(), BiFunction { rooms, selectedGroupOption -> val selectedGroup = selectedGroupOption.orNull() val filteredDirectRooms = rooms @@ -92,7 +92,7 @@ class AppStateHandler @Inject constructor( } ) .subscribe { - homeRoomListObservableStore.post(it) + homeRoomListDataSource.post(it) } .addTo(compositeDisposable) } diff --git a/vector/src/main/java/im/vector/riotx/core/di/ActiveSessionHolder.kt b/vector/src/main/java/im/vector/riotx/core/di/ActiveSessionHolder.kt index da3c041a1c..3eccb668ea 100644 --- a/vector/src/main/java/im/vector/riotx/core/di/ActiveSessionHolder.kt +++ b/vector/src/main/java/im/vector/riotx/core/di/ActiveSessionHolder.kt @@ -19,7 +19,7 @@ package im.vector.riotx.core.di import arrow.core.Option import im.vector.matrix.android.api.auth.Authenticator import im.vector.matrix.android.api.session.Session -import im.vector.riotx.ActiveSessionObservableStore +import im.vector.riotx.ActiveSessionDataSource import im.vector.riotx.features.crypto.keysrequest.KeyRequestHandler import im.vector.riotx.features.crypto.verification.IncomingVerificationRequestHandler import java.util.concurrent.atomic.AtomicReference @@ -28,7 +28,7 @@ import javax.inject.Singleton @Singleton class ActiveSessionHolder @Inject constructor(private val authenticator: Authenticator, - private val sessionObservableStore: ActiveSessionObservableStore, + private val sessionObservableStore: ActiveSessionDataSource, private val keyRequestHandler: KeyRequestHandler, private val incomingVerificationRequestHandler: IncomingVerificationRequestHandler ) { diff --git a/vector/src/main/java/im/vector/riotx/core/di/VectorComponent.kt b/vector/src/main/java/im/vector/riotx/core/di/VectorComponent.kt index 2dfbb5f799..d31955ce8e 100644 --- a/vector/src/main/java/im/vector/riotx/core/di/VectorComponent.kt +++ b/vector/src/main/java/im/vector/riotx/core/di/VectorComponent.kt @@ -23,7 +23,7 @@ import dagger.Component import im.vector.matrix.android.api.Matrix import im.vector.matrix.android.api.auth.Authenticator import im.vector.matrix.android.api.session.Session -import im.vector.riotx.ActiveSessionObservableStore +import im.vector.riotx.ActiveSessionDataSource import im.vector.riotx.EmojiCompatFontProvider import im.vector.riotx.EmojiCompatWrapper import im.vector.riotx.VectorApplication @@ -33,8 +33,8 @@ import im.vector.riotx.features.configuration.VectorConfiguration import im.vector.riotx.features.crypto.keysrequest.KeyRequestHandler import im.vector.riotx.features.crypto.verification.IncomingVerificationRequestHandler import im.vector.riotx.features.home.AvatarRenderer -import im.vector.riotx.features.home.HomeRoomListObservableStore -import im.vector.riotx.features.home.group.SelectedGroupStore +import im.vector.riotx.features.home.HomeRoomListDataSource +import im.vector.riotx.features.home.group.SelectedGroupDataSource import im.vector.riotx.features.html.EventHtmlRenderer import im.vector.riotx.features.navigation.Navigator import im.vector.riotx.features.notifications.* @@ -43,7 +43,7 @@ import im.vector.riotx.features.rageshake.VectorFileLogger import im.vector.riotx.features.rageshake.VectorUncaughtExceptionHandler import im.vector.riotx.features.session.SessionListener import im.vector.riotx.features.settings.VectorPreferences -import im.vector.riotx.features.share.ShareRoomListObservableStore +import im.vector.riotx.features.share.ShareRoomListDataSource import im.vector.riotx.features.ui.UiStateRepository import javax.inject.Singleton @@ -85,13 +85,13 @@ interface VectorComponent { fun navigator(): Navigator - fun homeRoomListObservableStore(): HomeRoomListObservableStore + fun homeRoomListObservableStore(): HomeRoomListDataSource - fun shareRoomListObservableStore(): ShareRoomListObservableStore + fun shareRoomListObservableStore(): ShareRoomListDataSource - fun selectedGroupStore(): SelectedGroupStore + fun selectedGroupStore(): SelectedGroupDataSource - fun activeSessionObservableStore(): ActiveSessionObservableStore + fun activeSessionObservableStore(): ActiveSessionDataSource fun incomingVerificationRequestHandler(): IncomingVerificationRequestHandler diff --git a/vector/src/main/java/im/vector/riotx/core/epoxy/bottomsheet/BottomSheetItemAction.kt b/vector/src/main/java/im/vector/riotx/core/epoxy/bottomsheet/BottomSheetItemAction.kt index e0299f4e65..483650a434 100644 --- a/vector/src/main/java/im/vector/riotx/core/epoxy/bottomsheet/BottomSheetItemAction.kt +++ b/vector/src/main/java/im/vector/riotx/core/epoxy/bottomsheet/BottomSheetItemAction.kt @@ -16,6 +16,7 @@ */ package im.vector.riotx.core.epoxy.bottomsheet +import android.content.res.ColorStateList import android.view.View import android.widget.ImageView import android.widget.TextView @@ -24,6 +25,7 @@ import androidx.core.content.ContextCompat import androidx.core.graphics.drawable.DrawableCompat import androidx.core.view.isInvisible import androidx.core.view.isVisible +import androidx.core.widget.ImageViewCompat import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import im.vector.riotx.R @@ -51,6 +53,8 @@ abstract class BottomSheetItemAction : VectorEpoxyModel { +interface DataSource { fun observe(): Observable +} + +interface MutableDataSource : DataSource { fun post(value: T) } /** - * This store emits the most recent value it has observed and all subsequent observed values to each subscriber. + * This datasource 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 { +open class BehaviorDataSource(private val defaultValue: T? = null) : MutableDataSource { private val storeRelay = createRelay() @@ -54,9 +54,9 @@ open class BehaviorStore(private val defaultValue: T? = null) : RxStore { } /** - * This store only emits all subsequent observed values to each subscriber. + * This datasource only emits all subsequent observed values to each subscriber. */ -open class PublishStore : RxStore { +open class PublishDataSource : MutableDataSource { private val storeRelay = PublishRelay.create() 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 c4dcd79ea0..585ecf126e 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 @@ -26,7 +26,7 @@ import im.vector.matrix.rx.rx import im.vector.riotx.core.di.HasScreenInjector import im.vector.riotx.core.platform.VectorViewModel import im.vector.riotx.core.resources.StringProvider -import im.vector.riotx.features.home.group.SelectedGroupStore +import im.vector.riotx.features.home.group.SelectedGroupDataSource import im.vector.riotx.features.home.room.list.RoomListFragment import im.vector.riotx.features.ui.UiStateRepository import io.reactivex.schedulers.Schedulers @@ -38,8 +38,8 @@ import io.reactivex.schedulers.Schedulers class HomeDetailViewModel @AssistedInject constructor(@Assisted initialState: HomeDetailViewState, private val session: Session, private val uiStateRepository: UiStateRepository, - private val selectedGroupStore: SelectedGroupStore, - private val homeRoomListStore: HomeRoomListObservableStore, + private val selectedGroupStore: SelectedGroupDataSource, + private val homeRoomListStore: HomeRoomListDataSource, private val stringProvider: StringProvider) : VectorViewModel(initialState) { 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 122eee1833..81c340e400 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 @@ -17,8 +17,8 @@ package im.vector.riotx.features.home import androidx.lifecycle.ViewModel -import im.vector.riotx.core.utils.PublishStore -import im.vector.riotx.core.utils.RxStore +import im.vector.riotx.core.utils.PublishDataSource +import im.vector.riotx.core.utils.MutableDataSource -class HomeNavigationViewModel(private val store: RxStore = PublishStore()) - : ViewModel(), RxStore by store +class HomeNavigationViewModel(private val source: MutableDataSource = PublishDataSource()) + : ViewModel(), MutableDataSource by source diff --git a/vector/src/main/java/im/vector/riotx/features/home/HomeRoomListObservableStore.kt b/vector/src/main/java/im/vector/riotx/features/home/HomeRoomListDataSource.kt similarity index 84% rename from vector/src/main/java/im/vector/riotx/features/home/HomeRoomListObservableStore.kt rename to vector/src/main/java/im/vector/riotx/features/home/HomeRoomListDataSource.kt index 6b43af4bfc..c27a58d177 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/HomeRoomListObservableStore.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/HomeRoomListDataSource.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.BehaviorStore +import im.vector.riotx.core.utils.BehaviorDataSource import javax.inject.Inject import javax.inject.Singleton @Singleton -class HomeRoomListObservableStore @Inject constructor() : BehaviorStore>() +class HomeRoomListDataSource @Inject constructor() : BehaviorDataSource>() 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 d120c306fb..5a84cf4258 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 @@ -17,8 +17,8 @@ package im.vector.riotx.features.home.createdirect import androidx.lifecycle.ViewModel -import im.vector.riotx.core.utils.PublishStore -import im.vector.riotx.core.utils.RxStore +import im.vector.riotx.core.utils.PublishDataSource +import im.vector.riotx.core.utils.MutableDataSource -class CreateDirectRoomNavigationViewModel(private val store: RxStore = PublishStore()) - : ViewModel(), RxStore by store +class CreateDirectRoomNavigationViewModel(private val dataSource: MutableDataSource = PublishDataSource()) + : ViewModel(), MutableDataSource by dataSource diff --git a/vector/src/main/java/im/vector/riotx/features/home/group/GroupListViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/group/GroupListViewModel.kt index ed547026ee..ac12113d66 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/group/GroupListViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/group/GroupListViewModel.kt @@ -39,7 +39,7 @@ import io.reactivex.functions.BiFunction const val ALL_COMMUNITIES_GROUP_ID = "ALL_COMMUNITIES_GROUP_ID" class GroupListViewModel @AssistedInject constructor(@Assisted initialState: GroupListViewState, - private val selectedGroupStore: SelectedGroupStore, + private val selectedGroupStore: SelectedGroupDataSource, private val session: Session, private val stringProvider: StringProvider ) : VectorViewModel(initialState) { 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/SelectedGroupDataSource.kt similarity index 83% rename from vector/src/main/java/im/vector/riotx/features/home/group/SelectedGroupStore.kt rename to vector/src/main/java/im/vector/riotx/features/home/group/SelectedGroupDataSource.kt index a74f24c1d5..c7b36e1e7f 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/SelectedGroupDataSource.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.BehaviorStore +import im.vector.riotx.core.utils.BehaviorDataSource import javax.inject.Inject import javax.inject.Singleton @Singleton -class SelectedGroupStore @Inject constructor() : BehaviorStore>(Option.empty()) +class SelectedGroupDataSource @Inject constructor() : BehaviorDataSource>(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 4875c87ec0..f2f65e5cf0 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 @@ -99,7 +99,7 @@ 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.MessageActionsBottomSheet -import im.vector.riotx.features.home.room.detail.timeline.action.MessageActionsStore +import im.vector.riotx.features.home.room.detail.timeline.action.MessageActionsDispatcher 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.* @@ -200,7 +200,7 @@ class RoomDetailFragment : override fun getMenuRes() = R.menu.menu_timeline - private lateinit var messageActionsStore: MessageActionsStore + private lateinit var messageActionsDispatcher: MessageActionsDispatcher private lateinit var layoutManager: LinearLayoutManager private lateinit var attachmentsHelper: AttachmentsHelper private lateinit var keyboardStateUtils: KeyboardStateUtils @@ -217,7 +217,7 @@ class RoomDetailFragment : override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) - messageActionsStore = ViewModelProviders.of(requireActivity()).get(MessageActionsStore::class.java) + messageActionsDispatcher = ViewModelProviders.of(requireActivity()).get(MessageActionsDispatcher::class.java) attachmentsHelper = AttachmentsHelper.create(this, this).register() keyboardStateUtils = KeyboardStateUtils(requireActivity()) setupToolbar(roomToolbar) @@ -236,7 +236,7 @@ class RoomDetailFragment : val message = requireContext().getString(pair.first, *pair.second.toTypedArray()) showSnackWithMessage(message, Snackbar.LENGTH_LONG) } - messageActionsStore + messageActionsDispatcher .observe() .subscribe { handleActions(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 2f0e3fab65..d0dc3de8f3 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 messageActionsStore: MessageActionsStore + private lateinit var messageActionsStore: MessageActionsDispatcher override fun injectWith(screenComponent: ScreenComponent) { screenComponent.inject(this) @@ -61,7 +61,7 @@ class MessageActionsBottomSheet : VectorBaseBottomSheetDialogFragment(), Message override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) - messageActionsStore = ViewModelProviders.of(requireActivity()).get(MessageActionsStore::class.java) + messageActionsStore = ViewModelProviders.of(requireActivity()).get(MessageActionsDispatcher::class.java) recyclerView.layoutManager = LinearLayoutManager(requireContext(), RecyclerView.VERTICAL, false) recyclerView.adapter = messageActionsEpoxyController.adapter // Disable item animation diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsStore.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsDispatcher.kt similarity index 71% rename from vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsStore.kt rename to vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsDispatcher.kt index 5c4c6fed80..a11e0c3689 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsStore.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsDispatcher.kt @@ -16,12 +16,12 @@ package im.vector.riotx.features.home.room.detail.timeline.action import androidx.lifecycle.ViewModel -import im.vector.riotx.core.utils.PublishStore -import im.vector.riotx.core.utils.RxStore +import im.vector.riotx.core.utils.PublishDataSource +import im.vector.riotx.core.utils.MutableDataSource /** * Activity shared view model to handle message actions */ -class MessageActionsStore constructor( - private val store: RxStore = PublishStore() -) : ViewModel(), RxStore by store +class MessageActionsDispatcher constructor( + private val dataSource: MutableDataSource = PublishDataSource() +) : ViewModel(), MutableDataSource by dataSource 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 bcd640589c..0ee34f0679 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 @@ -21,6 +21,7 @@ import android.os.Parcelable import android.view.Menu import android.view.MenuItem import androidx.annotation.StringRes +import androidx.appcompat.app.AlertDialog import androidx.core.content.ContextCompat import androidx.core.view.isVisible import androidx.lifecycle.ViewModelProviders @@ -36,8 +37,6 @@ import im.vector.riotx.R import im.vector.riotx.core.di.ScreenComponent import im.vector.riotx.core.epoxy.LayoutManagerStateRestorer import im.vector.riotx.core.error.ErrorFormatter -import im.vector.riotx.core.extensions.observeEvent -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 @@ -47,6 +46,7 @@ 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 +import io.reactivex.android.schedulers.AndroidSchedulers import kotlinx.android.parcel.Parcelize import kotlinx.android.synthetic.main.fragment_room_list.* import javax.inject.Inject @@ -115,30 +115,42 @@ class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Listener, O setupCreateRoomButton() setupRecyclerView() roomListViewModel.subscribe { renderState(it) } - roomListViewModel.openRoomLiveData.observeEventFirstThrottle(this, 800L) { - if (roomListParams.displayMode == DisplayMode.SHARE) { - val sharedData = roomListParams.sharedData ?: return@observeEventFirstThrottle - navigator.openRoomForSharing(requireActivity(), it, sharedData) - } else { - navigator.openRoom(requireActivity(), it) - } - } + + roomListViewModel.viewEvents + .observe() + .observeOn(AndroidSchedulers.mainThread()) + .subscribe { + when (it) { + is RoomListViewEvents.SelectRoom -> openSelectedRoom(it) + is RoomListViewEvents.Failure -> showError(it) + } + } + .disposeOnDestroy() createChatFabMenu.listener = this - roomListViewModel.invitationAnswerErrorLiveData.observeEvent(this) { throwable -> - vectorBaseActivity.coordinatorLayout?.let { - Snackbar.make(it, errorFormatter.toHumanReadable(throwable), Snackbar.LENGTH_SHORT) - .show() - } - } - quickActionsDispatcher .observe() .subscribe { handleQuickActions(it) } .disposeOnDestroy() } + private fun openSelectedRoom(event: RoomListViewEvents.SelectRoom) { + if (roomListParams.displayMode == DisplayMode.SHARE) { + val sharedData = roomListParams.sharedData ?: return + navigator.openRoomForSharing(requireActivity(), event.roomId, sharedData) + } else { + navigator.openRoom(requireActivity(), event.roomId) + } + } + + private fun showError(event: RoomListViewEvents.Failure) { + vectorBaseActivity.coordinatorLayout?.let { + Snackbar.make(it, errorFormatter.toHumanReadable(event.throwable), Snackbar.LENGTH_SHORT) + .show() + } + } + private fun setupCreateRoomButton() { when (roomListParams.displayMode) { DisplayMode.HOME -> createChatFabMenu.isVisible = true @@ -233,7 +245,14 @@ class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Listener, O vectorBaseActivity.notImplemented("Opening room settings") } is RoomListQuickActions.Leave -> { - roomListViewModel.accept(RoomListActions.LeaveRoom(quickActions.roomId)) + AlertDialog.Builder(requireContext()) + .setTitle(R.string.room_participants_leave_prompt_title) + .setMessage(R.string.room_participants_leave_prompt_msg) + .setPositiveButton(R.string.leave) { _, _ -> + roomListViewModel.accept(RoomListActions.LeaveRoom(quickActions.roomId)) + } + .setNegativeButton(R.string.cancel, null) + .show() } } } 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 new file mode 100644 index 0000000000..1181236da2 --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewEvents.kt @@ -0,0 +1,26 @@ +/* + * 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 + +/** + * Transient events for RoomList + */ +sealed class 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 31fa9d0309..ae8654d561 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 @@ -16,8 +16,6 @@ package im.vector.riotx.features.home.room.list -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext @@ -26,17 +24,16 @@ 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.model.RoomSummary import im.vector.matrix.android.api.session.room.model.tag.RoomTag -import im.vector.riotx.core.extensions.postLiveEvent import im.vector.riotx.core.platform.VectorViewModel -import im.vector.riotx.core.utils.LiveEvent -import im.vector.riotx.core.utils.RxStore +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 class RoomListViewModel @Inject constructor(initialState: RoomListViewState, private val session: Session, - private val roomSummariesStore: RxStore>, + private val roomSummariesSource: DataSource>, private val alphabeticalRoomComparator: AlphabeticalRoomComparator, private val chronologicalRoomComparator: ChronologicalRoomComparator) : VectorViewModel(initialState) { @@ -57,13 +54,8 @@ class RoomListViewModel @Inject constructor(initialState: RoomListViewState, private val displayMode = initialState.displayMode private val roomListDisplayModeFilter = RoomListDisplayModeFilter(displayMode) - private val _openRoomLiveData = MutableLiveData>() - val openRoomLiveData: LiveData> - get() = _openRoomLiveData - - private val _invitationAnswerErrorLiveData = MutableLiveData>() - val invitationAnswerErrorLiveData: LiveData> - get() = _invitationAnswerErrorLiveData + private val _viewEvents = PublishDataSource() + val viewEvents: DataSource = _viewEvents init { observeRoomSummaries() @@ -85,7 +77,7 @@ class RoomListViewModel @Inject constructor(initialState: RoomListViewState, // PRIVATE METHODS ***************************************************************************** private fun handleSelectRoom(action: RoomListActions.SelectRoom) { - _openRoomLiveData.postLiveEvent(action.roomSummary.roomId) + _viewEvents.post(RoomListViewEvents.SelectRoom(action.roomSummary.roomId)) } private fun handleToggleCategory(action: RoomListActions.ToggleCategory) = setState { @@ -101,7 +93,7 @@ class RoomListViewModel @Inject constructor(initialState: RoomListViewState, } private fun observeRoomSummaries() { - roomSummariesStore + roomSummariesSource .observe() .observeOn(Schedulers.computation()) .map { @@ -111,7 +103,7 @@ class RoomListViewModel @Inject constructor(initialState: RoomListViewState, copy(asyncRooms = asyncRooms) } - roomSummariesStore + roomSummariesSource .observe() .observeOn(Schedulers.computation()) .map { buildRoomSummaries(it) } @@ -144,8 +136,7 @@ class RoomListViewModel @Inject constructor(initialState: RoomListViewState, override fun onFailure(failure: Throwable) { // Notify the user - _invitationAnswerErrorLiveData.postLiveEvent(failure) - + _viewEvents.post(RoomListViewEvents.Failure(failure)) setState { copy( joiningRoomsIds = joiningRoomsIds - roomId, @@ -182,8 +173,7 @@ class RoomListViewModel @Inject constructor(initialState: RoomListViewState, override fun onFailure(failure: Throwable) { // Notify the user - _invitationAnswerErrorLiveData.postLiveEvent(failure) - + _viewEvents.post(RoomListViewEvents.Failure(failure)) setState { copy( rejectingRoomsIds = rejectingRoomsIds - roomId, @@ -204,15 +194,19 @@ class RoomListViewModel @Inject constructor(initialState: RoomListViewState, } private fun handleChangeNotificationMode(action: RoomListActions.ChangeRoomNotificationState) { - session.getRoom(action.roomId)?.also { - it.setRoomNotificationState(action.notificationState, object : MatrixCallback {}) - } + session.getRoom(action.roomId)?.setRoomNotificationState(action.notificationState, object : MatrixCallback { + override fun onFailure(failure: Throwable) { + _viewEvents.post(RoomListViewEvents.Failure(failure)) + } + }) } private fun handleLeaveRoom(action: RoomListActions.LeaveRoom) { - session.getRoom(action.roomId)?.also { - it.leave(object : MatrixCallback {}) - } + session.getRoom(action.roomId)?.leave(object : MatrixCallback { + override fun onFailure(failure: Throwable) { + _viewEvents.post(RoomListViewEvents.Failure(failure)) + } + }) } private fun buildRoomSummaries(rooms: List): RoomSummaries { diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewModelFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewModelFactory.kt index 5895aa4e52..897e72d811 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewModelFactory.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewModelFactory.kt @@ -17,14 +17,14 @@ package im.vector.riotx.features.home.room.list import im.vector.matrix.android.api.session.Session -import im.vector.riotx.features.home.HomeRoomListObservableStore -import im.vector.riotx.features.share.ShareRoomListObservableStore +import im.vector.riotx.features.home.HomeRoomListDataSource +import im.vector.riotx.features.share.ShareRoomListDataSource import javax.inject.Inject import javax.inject.Provider class RoomListViewModelFactory @Inject constructor(private val session: Provider, - private val homeRoomListObservableStore: Provider, - private val shareRoomListObservableStore: Provider, + private val homeRoomListDataSource: Provider, + private val shareRoomListDataSource: Provider, private val alphabeticalRoomComparator: Provider, private val chronologicalRoomComparator: Provider) : RoomListViewModel.Factory { @@ -32,7 +32,7 @@ class RoomListViewModelFactory @Inject constructor(private val session: Provider return RoomListViewModel( initialState, session.get(), - if (initialState.displayMode == RoomListFragment.DisplayMode.SHARE) shareRoomListObservableStore.get() else homeRoomListObservableStore.get(), + if (initialState.displayMode == RoomListFragment.DisplayMode.SHARE) shareRoomListDataSource.get() else homeRoomListDataSource.get(), alphabeticalRoomComparator.get(), chronologicalRoomComparator.get()) } 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 e89b4ebcd0..86cd9043f3 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 @@ -20,7 +20,7 @@ import androidx.annotation.DrawableRes import androidx.annotation.StringRes import im.vector.riotx.R -sealed class RoomListQuickActions(@StringRes val titleRes: Int, @DrawableRes val iconResId: Int) { +sealed class RoomListQuickActions(@StringRes val titleRes: Int, @DrawableRes val iconResId: Int, val destructive: Boolean = false) { data class NotificationsAllNoisy(val roomId: String) : RoomListQuickActions( R.string.room_list_quick_actions_notifications_all_noisy, @@ -49,19 +49,7 @@ sealed class RoomListQuickActions(@StringRes val titleRes: Int, @DrawableRes val data class Leave(val roomId: String) : RoomListQuickActions( R.string.room_list_quick_actions_leave, - R.drawable.ic_room_actions_leave + R.drawable.ic_room_actions_leave, + true ) - - 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/RoomListQuickActionsEpoxyController.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsEpoxyController.kt index cc6abc42b1..70d0fc5f76 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,22 +18,16 @@ package im.vector.riotx.features.home.room.list.actions import android.view.View import com.airbnb.epoxy.TypedEpoxyController import im.vector.matrix.android.api.session.room.notification.RoomNotificationState -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.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 javax.inject.Inject /** * Epoxy controller for room list actions */ -class RoomListQuickActionsEpoxyController @Inject constructor(private val stringProvider: StringProvider, - private val avatarRenderer: AvatarRenderer, - private val dateFormatter: VectorDateFormatter, - private val fontProvider: EmojiCompatFontProvider) +class RoomListQuickActionsEpoxyController @Inject constructor(private val avatarRenderer: AvatarRenderer) : TypedEpoxyController() { var listener: Listener? = null @@ -78,13 +72,14 @@ class RoomListQuickActionsEpoxyController @Inject constructor(private val string is RoomListQuickActions.Settings, is RoomListQuickActions.Leave -> false } - return BottomSheetItemAction_() - .id("action_$index") - .selected(selected) - .iconRes(iconResId) - .textRes(titleRes) - .listener(View.OnClickListener { listener?.didSelectMenuAction(this) }) - .addTo(this@RoomListQuickActionsEpoxyController) + return bottomSheetItemAction { + id("action_$index") + selected(selected) + iconRes(iconResId) + textRes(titleRes) + destructive(this@toBottomSheetItem.destructive) + listener(View.OnClickListener { listener?.didSelectMenuAction(this@toBottomSheetItem) }) + } } interface Listener { 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 index ce0479ac92..35fe09dff8 100644 --- 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 @@ -17,12 +17,12 @@ 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 +import im.vector.riotx.core.utils.PublishDataSource +import im.vector.riotx.core.utils.MutableDataSource /** * Activity shared view model to handle room list quick actions */ class RoomListQuickActionsStore constructor( - private val store: RxStore = PublishStore() -) : ViewModel(), RxStore by store + private val store: MutableDataSource = PublishDataSource() +) : ViewModel(), MutableDataSource by store 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 cb26ff0c54..4e4230e07b 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 @@ -17,8 +17,8 @@ package im.vector.riotx.features.roomdirectory import androidx.lifecycle.ViewModel -import im.vector.riotx.core.utils.PublishStore -import im.vector.riotx.core.utils.RxStore +import im.vector.riotx.core.utils.PublishDataSource +import im.vector.riotx.core.utils.MutableDataSource -class RoomDirectoryNavigationViewModel(private val store: RxStore = PublishStore()) - : ViewModel(), RxStore by store +class RoomDirectoryNavigationViewModel(private val source: MutableDataSource = PublishDataSource()) + : ViewModel(), MutableDataSource by source 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 51485ecbf9..9fba8541e3 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 @@ -23,7 +23,7 @@ import com.airbnb.mvrx.ViewModelContext import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.AssistedInject import im.vector.matrix.rx.rx -import im.vector.riotx.ActiveSessionObservableStore +import im.vector.riotx.ActiveSessionDataSource import im.vector.riotx.core.platform.VectorViewModel import io.reactivex.Observable import io.reactivex.android.schedulers.AndroidSchedulers @@ -35,8 +35,8 @@ data class IncomingShareState(private val dummy: Boolean = false) : MvRxState * View model used to observe the room list and post update to the ShareRoomListObservableStore */ class IncomingShareViewModel @AssistedInject constructor(@Assisted initialState: IncomingShareState, - private val sessionObservableStore: ActiveSessionObservableStore, - private val shareRoomListObservableStore: ShareRoomListObservableStore) + private val sessionObservableStore: ActiveSessionDataSource, + private val shareRoomListObservableStore: ShareRoomListDataSource) : VectorViewModel(initialState) { @AssistedInject.Factory diff --git a/vector/src/main/java/im/vector/riotx/features/share/ShareRoomListObservableStore.kt b/vector/src/main/java/im/vector/riotx/features/share/ShareRoomListDataSource.kt similarity index 83% rename from vector/src/main/java/im/vector/riotx/features/share/ShareRoomListObservableStore.kt rename to vector/src/main/java/im/vector/riotx/features/share/ShareRoomListDataSource.kt index 32b0093b8f..b1b4d7b46e 100644 --- a/vector/src/main/java/im/vector/riotx/features/share/ShareRoomListObservableStore.kt +++ b/vector/src/main/java/im/vector/riotx/features/share/ShareRoomListDataSource.kt @@ -17,9 +17,9 @@ package im.vector.riotx.features.share import im.vector.matrix.android.api.session.room.model.RoomSummary -import im.vector.riotx.core.utils.BehaviorStore +import im.vector.riotx.core.utils.BehaviorDataSource import javax.inject.Inject import javax.inject.Singleton @Singleton -class ShareRoomListObservableStore @Inject constructor() : BehaviorStore>() +class ShareRoomListDataSource @Inject constructor() : BehaviorDataSource>()