From ab4eda18bfc1c489f82613ada40666870bf85be3 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Tue, 2 Aug 2022 17:44:27 +0200 Subject: [PATCH 01/17] Adds SpacesBottomSheet --- .../room/list/home/HomeRoomListFragment.kt | 2 + .../app/features/spaces/SpacesBottomSheet.kt | 46 +++++++++++++++++++ .../layout/fragment_spaces_bottom_sheet.xml | 11 +++++ 3 files changed, 59 insertions(+) create mode 100644 vector/src/main/java/im/vector/app/features/spaces/SpacesBottomSheet.kt create mode 100644 vector/src/main/res/layout/fragment_spaces_bottom_sheet.xml diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListFragment.kt index e7882ff36f..68143ddc7d 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListFragment.kt @@ -44,6 +44,7 @@ import im.vector.app.features.home.room.list.RoomSummaryPagedController import im.vector.app.features.home.room.list.actions.RoomListQuickActionsBottomSheet import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedAction import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel +import im.vector.app.features.spaces.SpacesBottomSheet import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.matrix.android.sdk.api.session.room.model.RoomSummary @@ -119,6 +120,7 @@ class HomeRoomListFragment @Inject constructor( views.newLayoutOpenSpacesButton.setOnClickListener { // Click action for open spaces modal goes here + SpacesBottomSheet().show(requireActivity().supportFragmentManager, SpacesBottomSheet.TAG) } // Hide FABs when list is scrolling diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpacesBottomSheet.kt b/vector/src/main/java/im/vector/app/features/spaces/SpacesBottomSheet.kt new file mode 100644 index 0000000000..c50e4b6387 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/spaces/SpacesBottomSheet.kt @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.spaces + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.google.android.material.bottomsheet.BottomSheetDialogFragment +import im.vector.app.R +import im.vector.app.core.extensions.replaceChildFragment +import im.vector.app.databinding.FragmentSpacesBottomSheetBinding + +class SpacesBottomSheet : BottomSheetDialogFragment() { + + private lateinit var binding: FragmentSpacesBottomSheetBinding + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + binding = FragmentSpacesBottomSheetBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + if (savedInstanceState == null) { + replaceChildFragment(R.id.space_list, SpaceListFragment::class.java) + } + } + + companion object { + const val TAG = "SpacesBottomSheet" + } +} diff --git a/vector/src/main/res/layout/fragment_spaces_bottom_sheet.xml b/vector/src/main/res/layout/fragment_spaces_bottom_sheet.xml new file mode 100644 index 0000000000..27324c852f --- /dev/null +++ b/vector/src/main/res/layout/fragment_spaces_bottom_sheet.xml @@ -0,0 +1,11 @@ + + + + + + From aa24debd870be2e2bc78c49876dc84a8a1531bea Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Tue, 2 Aug 2022 22:49:58 +0200 Subject: [PATCH 02/17] Adds new space list controller --- .../grouplist/HomeSpaceSummaryItem.kt | 1 + .../features/home/NewHomeDetailFragment.kt | 17 +-- .../app/features/spaces/NewSpaceAddItem.kt | 38 ++++++ .../features/spaces/NewSpaceListHeaderItem.kt | 27 +++++ .../spaces/NewSpaceSummaryController.kt | 111 ++++++++++++++++++ .../features/spaces/NewSpaceSummaryItem.kt | 71 +++++++++++ .../app/features/spaces/SpaceListFragment.kt | 48 ++++++-- vector/src/main/res/drawable/ic_plus.xml | 11 ++ vector/src/main/res/layout/item_new_space.xml | 77 ++++++++++++ .../main/res/layout/item_new_space_add.xml | 54 +++++++++ .../res/layout/item_new_space_list_header.xml | 13 ++ 11 files changed, 447 insertions(+), 21 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/spaces/NewSpaceAddItem.kt create mode 100644 vector/src/main/java/im/vector/app/features/spaces/NewSpaceListHeaderItem.kt create mode 100644 vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryController.kt create mode 100644 vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryItem.kt create mode 100644 vector/src/main/res/drawable/ic_plus.xml create mode 100644 vector/src/main/res/layout/item_new_space.xml create mode 100644 vector/src/main/res/layout/item_new_space_add.xml create mode 100644 vector/src/main/res/layout/item_new_space_list_header.xml diff --git a/vector/src/main/java/im/vector/app/features/grouplist/HomeSpaceSummaryItem.kt b/vector/src/main/java/im/vector/app/features/grouplist/HomeSpaceSummaryItem.kt index 816b9acb24..8ca217636a 100644 --- a/vector/src/main/java/im/vector/app/features/grouplist/HomeSpaceSummaryItem.kt +++ b/vector/src/main/java/im/vector/app/features/grouplist/HomeSpaceSummaryItem.kt @@ -37,6 +37,7 @@ import im.vector.app.features.themes.ThemeUtils @EpoxyModelClass abstract class HomeSpaceSummaryItem : VectorEpoxyModel(R.layout.item_space) { + @EpoxyAttribute var text: String = "" @EpoxyAttribute var selected: Boolean = false @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var listener: ClickListener? = null @EpoxyAttribute var countState: UnreadCounterBadgeView.State = UnreadCounterBadgeView.State(0, false) diff --git a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt index 36372fc73a..55fb3daafa 100644 --- a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt @@ -28,8 +28,8 @@ import com.airbnb.mvrx.activityViewModel import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import com.google.android.material.badge.BadgeDrawable -import im.vector.app.AppStateHandler import im.vector.app.R +import im.vector.app.SpaceStateHandler import im.vector.app.core.extensions.commitTransaction import im.vector.app.core.extensions.toMvRxBundle import im.vector.app.core.platform.OnBackPressed @@ -47,6 +47,7 @@ import im.vector.app.features.call.dialpad.DialPadFragment import im.vector.app.features.call.webrtc.WebRtcCallManager import im.vector.app.features.home.room.list.RoomListFragment import im.vector.app.features.home.room.list.RoomListParams +import im.vector.app.features.home.room.list.home.HomeRoomListFragment import im.vector.app.features.popup.PopupAlertManager import im.vector.app.features.popup.VerificationVectorAlert import im.vector.app.features.settings.VectorLocale @@ -69,7 +70,7 @@ class NewHomeDetailFragment @Inject constructor( private val alertManager: PopupAlertManager, private val callManager: WebRtcCallManager, private val vectorPreferences: VectorPreferences, - private val appStateHandler: AppStateHandler, + private val spaceStateHandler: SpaceStateHandler, private val session: Session, ) : VectorBaseFragment(), KeysBackupBanner.Delegate, @@ -178,13 +179,13 @@ class NewHomeDetailFragment @Inject constructor( } private fun navigateBack() { - val previousSpaceId = appStateHandler.getSpaceBackstack().removeLastOrNull() - val parentSpaceId = appStateHandler.getCurrentSpace()?.flattenParentIds?.lastOrNull() + val previousSpaceId = spaceStateHandler.getSpaceBackstack().removeLastOrNull() + val parentSpaceId = spaceStateHandler.getCurrentSpace()?.flattenParentIds?.lastOrNull() setCurrentSpace(previousSpaceId ?: parentSpaceId) } private fun setCurrentSpace(spaceId: String?) { - appStateHandler.setCurrentSpace(spaceId, isForwardNavigation = false) + spaceStateHandler.setCurrentSpace(spaceId, isForwardNavigation = false) sharedActionViewModel.post(HomeActivitySharedAction.OnCloseSpace) } @@ -207,7 +208,7 @@ class NewHomeDetailFragment @Inject constructor( } private fun refreshSpaceState() { - appStateHandler.getCurrentSpace()?.let { + spaceStateHandler.getCurrentSpace()?.let { onSpaceChange(it) } } @@ -340,7 +341,7 @@ class NewHomeDetailFragment @Inject constructor( when (tab) { is HomeTab.RoomList -> { val params = RoomListParams(tab.displayMode) - add(R.id.roomListContainer, RoomListFragment::class.java, params.toMvRxBundle(), fragmentTag) + add(R.id.roomListContainer, HomeRoomListFragment::class.java, params.toMvRxBundle(), fragmentTag) } is HomeTab.DialPad -> { add(R.id.roomListContainer, createDialPadFragment(), fragmentTag) @@ -453,7 +454,7 @@ class NewHomeDetailFragment @Inject constructor( return this } - override fun onBackPressed(toolbarButton: Boolean) = if (appStateHandler.getCurrentSpace() != null) { + override fun onBackPressed(toolbarButton: Boolean) = if (spaceStateHandler.getCurrentSpace() != null) { navigateBack() true } else { diff --git a/vector/src/main/java/im/vector/app/features/spaces/NewSpaceAddItem.kt b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceAddItem.kt new file mode 100644 index 0000000000..d90cb5bc67 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceAddItem.kt @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.spaces + +import com.airbnb.epoxy.EpoxyAttribute +import com.airbnb.epoxy.EpoxyModelClass +import im.vector.app.R +import im.vector.app.core.epoxy.ClickListener +import im.vector.app.core.epoxy.VectorEpoxyHolder +import im.vector.app.core.epoxy.VectorEpoxyModel +import im.vector.app.core.epoxy.onClick + +@EpoxyModelClass +abstract class NewSpaceAddItem : VectorEpoxyModel(R.layout.item_new_space_add) { + + @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var listener: ClickListener? = null + + override fun bind(holder: Holder) { + super.bind(holder) + holder.view.onClick(listener) + } + + class Holder : VectorEpoxyHolder() +} diff --git a/vector/src/main/java/im/vector/app/features/spaces/NewSpaceListHeaderItem.kt b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceListHeaderItem.kt new file mode 100644 index 0000000000..8fc53f07d4 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceListHeaderItem.kt @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.spaces + +import com.airbnb.epoxy.EpoxyModelClass +import im.vector.app.R +import im.vector.app.core.epoxy.VectorEpoxyHolder +import im.vector.app.core.epoxy.VectorEpoxyModel + +@EpoxyModelClass +abstract class NewSpaceListHeaderItem : VectorEpoxyModel(R.layout.item_new_space_list_header) { + class Holder : VectorEpoxyHolder() +} diff --git a/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryController.kt b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryController.kt new file mode 100644 index 0000000000..80a8acb1bb --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryController.kt @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.spaces + +import com.airbnb.epoxy.EpoxyController +import im.vector.app.R +import im.vector.app.core.resources.StringProvider +import im.vector.app.features.grouplist.homeSpaceSummaryItem +import im.vector.app.features.home.AvatarRenderer +import im.vector.app.features.home.room.list.UnreadCounterBadgeView +import org.matrix.android.sdk.api.extensions.orFalse +import org.matrix.android.sdk.api.session.room.model.Membership +import org.matrix.android.sdk.api.session.room.model.RoomSummary +import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo +import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotificationCount +import org.matrix.android.sdk.api.util.toMatrixItem +import javax.inject.Inject + +class NewSpaceSummaryController @Inject constructor( + private val avatarRenderer: AvatarRenderer, + private val stringProvider: StringProvider, +) : EpoxyController() { + + var callback: Callback? = null + private var viewState: SpaceListViewState? = null + + private val subSpaceComparator: Comparator = compareBy { it.order }.thenBy { it.childRoomId } + + fun update(viewState: SpaceListViewState) { + this.viewState = viewState + requestModelBuild() + } + + override fun buildModels() { + val nonNullViewState = viewState ?: return + buildGroupModels( + nonNullViewState.selectedSpace, + nonNullViewState.rootSpacesOrdered, + nonNullViewState.homeAggregateCount + ) + } + + private fun buildGroupModels( + selectedSpace: RoomSummary?, + rootSpaces: List?, + homeCount: RoomAggregateNotificationCount + ) { + val host = this + + newSpaceListHeaderItem { + id("space_list_header") + } + + homeSpaceSummaryItem { + id("space_home") + text(this@NewSpaceSummaryController.stringProvider.getString(R.string.all_chats)) + selected(selectedSpace == null) + countState(UnreadCounterBadgeView.State(homeCount.totalCount, homeCount.isHighlight)) + listener { host.callback?.onSpaceSelected(null) } + } + + rootSpaces + ?.filter { it.membership != Membership.INVITE } + ?.forEach { roomSummary -> + val isSelected = roomSummary.roomId == selectedSpace?.roomId + + newSpaceSummaryItem { + avatarRenderer(host.avatarRenderer) + id(roomSummary.roomId) + matrixItem(roomSummary.toMatrixItem()) + selected(isSelected) + canDrag(true) + onMore { host.callback?.onSpaceSettings(roomSummary) } + listener { host.callback?.onSpaceSelected(roomSummary) } + countState( + UnreadCounterBadgeView.State( + roomSummary.notificationCount, + roomSummary.highlightCount > 0 + ) + ) + } + } + + newSpaceAddItem { + id("create") + listener { host.callback?.onAddSpaceSelected() } + } + } + + interface Callback { + fun onSpaceSelected(spaceSummary: RoomSummary?) + fun onSpaceInviteSelected(spaceSummary: RoomSummary) + fun onSpaceSettings(spaceSummary: RoomSummary) + fun onAddSpaceSelected() + fun sendFeedBack() + } +} diff --git a/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryItem.kt b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryItem.kt new file mode 100644 index 0000000000..eecb02b320 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryItem.kt @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.spaces + +import android.widget.ImageView +import android.widget.TextView +import com.airbnb.epoxy.EpoxyAttribute +import com.airbnb.epoxy.EpoxyModelClass +import im.vector.app.R +import im.vector.app.core.epoxy.ClickListener +import im.vector.app.core.epoxy.VectorEpoxyHolder +import im.vector.app.core.epoxy.VectorEpoxyModel +import im.vector.app.core.epoxy.onClick +import im.vector.app.core.platform.CheckableConstraintLayout +import im.vector.app.features.home.AvatarRenderer +import im.vector.app.features.home.room.list.UnreadCounterBadgeView +import org.matrix.android.sdk.api.util.MatrixItem + +@EpoxyModelClass +abstract class NewSpaceSummaryItem : VectorEpoxyModel(R.layout.item_new_space) { + + @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) lateinit var avatarRenderer: AvatarRenderer + @EpoxyAttribute lateinit var matrixItem: MatrixItem + @EpoxyAttribute var selected: Boolean = false + @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var listener: ClickListener? = null + @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var onMore: ClickListener? = null + @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var toggleExpand: ClickListener? = null + @EpoxyAttribute var expanded: Boolean = false + @EpoxyAttribute var hasChildren: Boolean = false + @EpoxyAttribute var indent: Int = 0 + @EpoxyAttribute var countState: UnreadCounterBadgeView.State = UnreadCounterBadgeView.State(0, false) + @EpoxyAttribute var description: String? = null + @EpoxyAttribute var showSeparator: Boolean = false + @EpoxyAttribute var canDrag: Boolean = true + + override fun bind(holder: Holder) { + super.bind(holder) + holder.rootView.onClick(listener) + holder.groupNameView.text = matrixItem.displayName + holder.rootView.isChecked = selected + + avatarRenderer.render(matrixItem, holder.avatarImageView) + holder.counterBadgeView.render(countState) + } + + override fun unbind(holder: Holder) { + avatarRenderer.clear(holder.avatarImageView) + super.unbind(holder) + } + + class Holder : VectorEpoxyHolder() { + val rootView by bind(R.id.root) + val avatarImageView by bind(R.id.avatar) + val groupNameView by bind(R.id.name) + val counterBadgeView by bind(R.id.unread_counter) + } +} diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt index b358a8c1a6..bf76c2eecd 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt @@ -32,6 +32,7 @@ import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.StateView import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentSpaceListBinding +import im.vector.app.features.VectorFeatures import im.vector.app.features.home.HomeActivitySharedAction import im.vector.app.features.home.HomeSharedActionViewModel import org.matrix.android.sdk.api.session.room.model.RoomSummary @@ -42,8 +43,10 @@ import javax.inject.Inject * is displaying the space hierarchy, with some actions on Spaces. */ class SpaceListFragment @Inject constructor( - private val spaceController: SpaceSummaryController -) : VectorBaseFragment(), SpaceSummaryController.Callback { + private val spaceController: SpaceSummaryController, + private val newSpaceController: NewSpaceSummaryController, + private val vectorFeatures: VectorFeatures, +) : VectorBaseFragment(), SpaceSummaryController.Callback, NewSpaceSummaryController.Callback { private lateinit var sharedActionViewModel: HomeSharedActionViewModel private val viewModel: SpaceListViewModel by fragmentViewModel() @@ -54,10 +57,24 @@ class SpaceListFragment @Inject constructor( override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - sharedActionViewModel = activityViewModelProvider.get(HomeSharedActionViewModel::class.java) - spaceController.callback = this + sharedActionViewModel = activityViewModelProvider[HomeSharedActionViewModel::class.java] views.stateView.contentView = views.groupListView - views.groupListView.configureWith(spaceController) + setupSpaceController() + enableDragAndDrop() + observeViewEvents() + } + + private fun setupSpaceController() { + if (vectorFeatures.isNewAppLayoutEnabled()) { + newSpaceController.callback = this + views.groupListView.configureWith(newSpaceController) + } else { + spaceController.callback = this + views.groupListView.configureWith(spaceController) + } + } + + private fun enableDragAndDrop() { EpoxyTouchHelper.initDragging(spaceController) .withRecyclerView(views.groupListView) .forVerticalList() @@ -100,14 +117,14 @@ class SpaceListFragment @Inject constructor( return model?.canDrag == true } }) + } - viewModel.observeViewEvents { - when (it) { - is SpaceListViewEvents.OpenSpaceSummary -> sharedActionViewModel.post(HomeActivitySharedAction.OpenSpacePreview(it.id)) - is SpaceListViewEvents.AddSpace -> sharedActionViewModel.post(HomeActivitySharedAction.AddSpace) - is SpaceListViewEvents.OpenSpaceInvite -> sharedActionViewModel.post(HomeActivitySharedAction.OpenSpaceInvite(it.id)) - SpaceListViewEvents.CloseDrawer -> sharedActionViewModel.post(HomeActivitySharedAction.CloseDrawer) - } + private fun observeViewEvents() = viewModel.observeViewEvents { + when (it) { + is SpaceListViewEvents.OpenSpaceSummary -> sharedActionViewModel.post(HomeActivitySharedAction.OpenSpacePreview(it.id)) + is SpaceListViewEvents.AddSpace -> sharedActionViewModel.post(HomeActivitySharedAction.AddSpace) + is SpaceListViewEvents.OpenSpaceInvite -> sharedActionViewModel.post(HomeActivitySharedAction.OpenSpaceInvite(it.id)) + SpaceListViewEvents.CloseDrawer -> sharedActionViewModel.post(HomeActivitySharedAction.CloseDrawer) } } @@ -124,7 +141,12 @@ class SpaceListFragment @Inject constructor( is Success -> views.stateView.state = StateView.State.Content else -> Unit } - spaceController.update(state) + + if (vectorFeatures.isNewAppLayoutEnabled()) { + newSpaceController.update(state) + } else { + spaceController.update(state) + } } override fun onSpaceSelected(spaceSummary: RoomSummary?) { diff --git a/vector/src/main/res/drawable/ic_plus.xml b/vector/src/main/res/drawable/ic_plus.xml new file mode 100644 index 0000000000..25a611472b --- /dev/null +++ b/vector/src/main/res/drawable/ic_plus.xml @@ -0,0 +1,11 @@ + + + + diff --git a/vector/src/main/res/layout/item_new_space.xml b/vector/src/main/res/layout/item_new_space.xml new file mode 100644 index 0000000000..367d69ce69 --- /dev/null +++ b/vector/src/main/res/layout/item_new_space.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + diff --git a/vector/src/main/res/layout/item_new_space_add.xml b/vector/src/main/res/layout/item_new_space_add.xml new file mode 100644 index 0000000000..1033d3c6a0 --- /dev/null +++ b/vector/src/main/res/layout/item_new_space_add.xml @@ -0,0 +1,54 @@ + + + + + + + + + + diff --git a/vector/src/main/res/layout/item_new_space_list_header.xml b/vector/src/main/res/layout/item_new_space_list_header.xml new file mode 100644 index 0000000000..51edd8de59 --- /dev/null +++ b/vector/src/main/res/layout/item_new_space_list_header.xml @@ -0,0 +1,13 @@ + + From 5d183654b1992f6ab53a9f76bf3d94e8c686a4f6 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Wed, 3 Aug 2022 21:54:05 +0200 Subject: [PATCH 03/17] Fixes bug where bottom sheet sometimes renders with the wrong height --- .../room/list/home/HomeRoomListFragment.kt | 4 +- .../app/features/spaces/SpaceListFragment.kt | 2 +- .../app/features/spaces/SpacesBottomSheet.kt | 5 +- .../main/res/layout/fragment_room_list.xml | 166 +++++++++--------- 4 files changed, 91 insertions(+), 86 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListFragment.kt index 68143ddc7d..fae6ddb0c8 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListFragment.kt @@ -64,6 +64,8 @@ class HomeRoomListFragment @Inject constructor( private var concatAdapter = ConcatAdapter() private var modelBuildListener: OnModelBuildFinishedListener? = null + private val spacesBottomSheet = SpacesBottomSheet() + private lateinit var stateRestorer: LayoutManagerStateRestorer override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentRoomListBinding { @@ -120,7 +122,7 @@ class HomeRoomListFragment @Inject constructor( views.newLayoutOpenSpacesButton.setOnClickListener { // Click action for open spaces modal goes here - SpacesBottomSheet().show(requireActivity().supportFragmentManager, SpacesBottomSheet.TAG) + spacesBottomSheet.show(requireActivity().supportFragmentManager, SpacesBottomSheet.TAG) } // Hide FABs when list is scrolling diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt index bf76c2eecd..51fbaad757 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt @@ -143,7 +143,7 @@ class SpaceListFragment @Inject constructor( } if (vectorFeatures.isNewAppLayoutEnabled()) { - newSpaceController.update(state) + newSpaceController.update(state).also { onUpdate?.invoke() } } else { spaceController.update(state) } diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpacesBottomSheet.kt b/vector/src/main/java/im/vector/app/features/spaces/SpacesBottomSheet.kt index c50e4b6387..757e39b85a 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpacesBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpacesBottomSheet.kt @@ -31,13 +31,10 @@ class SpacesBottomSheet : BottomSheetDialogFragment() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { binding = FragmentSpacesBottomSheetBinding.inflate(inflater, container, false) - return binding.root - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { if (savedInstanceState == null) { replaceChildFragment(R.id.space_list, SpaceListFragment::class.java) } + return binding.root } companion object { diff --git a/vector/src/main/res/layout/fragment_room_list.xml b/vector/src/main/res/layout/fragment_room_list.xml index 631602bb14..6107482f72 100644 --- a/vector/src/main/res/layout/fragment_room_list.xml +++ b/vector/src/main/res/layout/fragment_room_list.xml @@ -1,101 +1,107 @@ - + android:layout_height="match_parent"> - + android:background="?android:colorBackground"> - + - - - - - - - - + app:layoutDescription="@xml/motion_scene_notifs_fab_menu" + tools:showPaths="true" + tools:visibility="visible" /> + + + app:maxImageSize="32dp" + tools:layout_marginEnd="144dp" + tools:visibility="visible" /> - + - + + + + + + + + + + From b4ed380caf73d448f98ca3a7b55f0f4287bcd014 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Wed, 3 Aug 2022 22:49:21 +0200 Subject: [PATCH 04/17] Finalises home and add bottom sheet buttons --- .../grouplist/NewHomeSpaceSummaryItem.kt | 69 +++++++++++++++++++ .../app/features/spaces/NewSpaceAddItem.kt | 9 ++- .../spaces/NewSpaceSummaryController.kt | 3 +- .../app/features/spaces/SpaceListFragment.kt | 2 +- .../drawable/new_space_home_background.xml | 11 +++ .../res/drawable/space_home_background.xml | 2 +- .../main/res/layout/item_new_space_add.xml | 4 +- .../res/layout/item_new_space_list_header.xml | 1 + 8 files changed, 95 insertions(+), 6 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/grouplist/NewHomeSpaceSummaryItem.kt create mode 100644 vector/src/main/res/drawable/new_space_home_background.xml diff --git a/vector/src/main/java/im/vector/app/features/grouplist/NewHomeSpaceSummaryItem.kt b/vector/src/main/java/im/vector/app/features/grouplist/NewHomeSpaceSummaryItem.kt new file mode 100644 index 0000000000..1f967db7ad --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/grouplist/NewHomeSpaceSummaryItem.kt @@ -0,0 +1,69 @@ +/* + * Copyright 2019 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package im.vector.app.features.grouplist + +import android.content.res.ColorStateList +import android.widget.ImageView +import android.widget.TextView +import androidx.core.content.ContextCompat +import androidx.core.graphics.ColorUtils +import com.airbnb.epoxy.EpoxyAttribute +import com.airbnb.epoxy.EpoxyModelClass +import im.vector.app.R +import im.vector.app.core.epoxy.ClickListener +import im.vector.app.core.epoxy.VectorEpoxyHolder +import im.vector.app.core.epoxy.VectorEpoxyModel +import im.vector.app.core.epoxy.onClick +import im.vector.app.core.platform.CheckableConstraintLayout +import im.vector.app.features.home.room.list.UnreadCounterBadgeView +import im.vector.app.features.themes.ThemeUtils + +@EpoxyModelClass +abstract class NewHomeSpaceSummaryItem : VectorEpoxyModel(R.layout.item_new_space) { + + @EpoxyAttribute var text: String = "" + @EpoxyAttribute var selected: Boolean = false + @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var listener: ClickListener? = null + @EpoxyAttribute var countState: UnreadCounterBadgeView.State = UnreadCounterBadgeView.State(0, false) + @EpoxyAttribute var showSeparator: Boolean = false + + override fun getViewType() = R.id.space_item_home + + override fun bind(holder: Holder) { + super.bind(holder) + holder.root.onClick(listener) + holder.name.text = holder.view.context.getString(R.string.all_chats) + holder.root.isChecked = selected + holder.root.context.resources + holder.avatar.background = ContextCompat.getDrawable(holder.view.context, R.drawable.new_space_home_background) + holder.avatar.backgroundTintList = ColorStateList.valueOf( + ColorUtils.setAlphaComponent(ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_tertiary), (255 * 0.3).toInt())) + holder.avatar.setImageResource(R.drawable.ic_space_home) + holder.avatar.imageTintList = ColorStateList.valueOf(ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_primary)) + holder.avatar.scaleType = ImageView.ScaleType.CENTER_INSIDE + + holder.unreadCounter.render(countState) + } + + class Holder : VectorEpoxyHolder() { + val root by bind(R.id.root) + val avatar by bind(R.id.avatar) + val name by bind(R.id.name) + val unreadCounter by bind(R.id.unread_counter) + } +} diff --git a/vector/src/main/java/im/vector/app/features/spaces/NewSpaceAddItem.kt b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceAddItem.kt index d90cb5bc67..60816df9c0 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/NewSpaceAddItem.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceAddItem.kt @@ -16,6 +16,8 @@ package im.vector.app.features.spaces +import android.content.res.ColorStateList +import android.widget.ImageView import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import im.vector.app.R @@ -23,6 +25,7 @@ import im.vector.app.core.epoxy.ClickListener import im.vector.app.core.epoxy.VectorEpoxyHolder import im.vector.app.core.epoxy.VectorEpoxyModel import im.vector.app.core.epoxy.onClick +import im.vector.app.features.themes.ThemeUtils @EpoxyModelClass abstract class NewSpaceAddItem : VectorEpoxyModel(R.layout.item_new_space_add) { @@ -32,7 +35,11 @@ abstract class NewSpaceAddItem : VectorEpoxyModel(R.layo override fun bind(holder: Holder) { super.bind(holder) holder.view.onClick(listener) + + holder.plus.imageTintList = ColorStateList.valueOf(ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_primary)) } - class Holder : VectorEpoxyHolder() + class Holder : VectorEpoxyHolder() { + val plus by bind(R.id.plus) + } } diff --git a/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryController.kt b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryController.kt index 80a8acb1bb..6690e92b50 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryController.kt @@ -20,6 +20,7 @@ import com.airbnb.epoxy.EpoxyController import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.features.grouplist.homeSpaceSummaryItem +import im.vector.app.features.grouplist.newHomeSpaceSummaryItem import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.list.UnreadCounterBadgeView import org.matrix.android.sdk.api.extensions.orFalse @@ -65,7 +66,7 @@ class NewSpaceSummaryController @Inject constructor( id("space_list_header") } - homeSpaceSummaryItem { + newHomeSpaceSummaryItem { id("space_home") text(this@NewSpaceSummaryController.stringProvider.getString(R.string.all_chats)) selected(selectedSpace == null) diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt index 51fbaad757..bf76c2eecd 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt @@ -143,7 +143,7 @@ class SpaceListFragment @Inject constructor( } if (vectorFeatures.isNewAppLayoutEnabled()) { - newSpaceController.update(state).also { onUpdate?.invoke() } + newSpaceController.update(state) } else { spaceController.update(state) } diff --git a/vector/src/main/res/drawable/new_space_home_background.xml b/vector/src/main/res/drawable/new_space_home_background.xml new file mode 100644 index 0000000000..47fdeb0226 --- /dev/null +++ b/vector/src/main/res/drawable/new_space_home_background.xml @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/vector/src/main/res/drawable/space_home_background.xml b/vector/src/main/res/drawable/space_home_background.xml index 2efd6d407c..c7fc727267 100644 --- a/vector/src/main/res/drawable/space_home_background.xml +++ b/vector/src/main/res/drawable/space_home_background.xml @@ -10,4 +10,4 @@ - \ No newline at end of file + diff --git a/vector/src/main/res/layout/item_new_space_add.xml b/vector/src/main/res/layout/item_new_space_add.xml index 1033d3c6a0..5a62abd740 100644 --- a/vector/src/main/res/layout/item_new_space_add.xml +++ b/vector/src/main/res/layout/item_new_space_add.xml @@ -20,7 +20,7 @@ app:layout_constraintTop_toTopOf="parent" /> diff --git a/vector/src/main/res/layout/item_new_space_list_header.xml b/vector/src/main/res/layout/item_new_space_list_header.xml index 51edd8de59..103d1a1b83 100644 --- a/vector/src/main/res/layout/item_new_space_list_header.xml +++ b/vector/src/main/res/layout/item_new_space_list_header.xml @@ -4,6 +4,7 @@ style="@style/TextAppearance.Vector.Body.Medium" android:layout_width="match_parent" android:layout_height="wrap_content" + android:background="@drawable/bg_space_item" android:orientation="vertical" android:padding="16dp" android:text="@string/all_chats" From 79e6dd074ace3eaadb24aecc3f768330dc5dbcea Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Thu, 4 Aug 2022 11:41:00 +0200 Subject: [PATCH 05/17] Makes bottom sheet dismiss on space change --- .../im/vector/app/core/di/ViewModelModule.kt | 6 ++ .../RoomListQuickActionsSharedAction.kt | 3 +- .../room/list/actions/RoomListSharedAction.kt | 24 +++++ .../actions/RoomListSharedActionViewModel.kt | 22 +++++ .../room/list/home/HomeRoomListFragment.kt | 95 +++++++++++-------- .../app/features/spaces/SpaceListFragment.kt | 21 ++-- 6 files changed, 122 insertions(+), 49 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListSharedAction.kt create mode 100644 vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListSharedActionViewModel.kt diff --git a/vector/src/main/java/im/vector/app/core/di/ViewModelModule.kt b/vector/src/main/java/im/vector/app/core/di/ViewModelModule.kt index d90e934d0a..c08f939524 100644 --- a/vector/src/main/java/im/vector/app/core/di/ViewModelModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/ViewModelModule.kt @@ -34,6 +34,7 @@ import im.vector.app.features.home.HomeSharedActionViewModel import im.vector.app.features.home.room.detail.RoomDetailSharedActionViewModel import im.vector.app.features.home.room.detail.timeline.action.MessageSharedActionViewModel import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel +import im.vector.app.features.home.room.list.actions.RoomListSharedActionViewModel import im.vector.app.features.reactions.EmojiChooserViewModel import im.vector.app.features.roomdirectory.RoomDirectorySharedActionViewModel import im.vector.app.features.roomprofile.RoomProfileSharedActionViewModel @@ -157,4 +158,9 @@ interface ViewModelModule { @IntoMap @ViewModelKey(SpacePeopleSharedActionViewModel::class) fun bindSpacePeopleSharedActionViewModel(viewModel: SpacePeopleSharedActionViewModel): ViewModel + + @Binds + @IntoMap + @ViewModelKey(RoomListSharedActionViewModel::class) + fun bindRoomListSharedActionViewModel(viewModel: RoomListSharedActionViewModel): ViewModel } diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsSharedAction.kt b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsSharedAction.kt index 0423a8fffc..8c84aa55e1 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsSharedAction.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsSharedAction.kt @@ -25,8 +25,7 @@ sealed class RoomListQuickActionsSharedAction( @StringRes val titleRes: Int, @DrawableRes val iconResId: Int?, val destructive: Boolean = false -) : - VectorSharedAction { +) : VectorSharedAction { data class NotificationsAllNoisy(val roomId: String) : RoomListQuickActionsSharedAction( R.string.room_list_quick_actions_notifications_all_noisy, diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListSharedAction.kt b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListSharedAction.kt new file mode 100644 index 0000000000..766bc6eea1 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListSharedAction.kt @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.home.room.list.actions + +import im.vector.app.core.platform.VectorSharedAction + +sealed class RoomListSharedAction : VectorSharedAction { + + object CloseBottomSheet : RoomListSharedAction() +} diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListSharedActionViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListSharedActionViewModel.kt new file mode 100644 index 0000000000..e2545accc8 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListSharedActionViewModel.kt @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.home.room.list.actions + +import im.vector.app.core.platform.VectorSharedActionViewModel +import javax.inject.Inject + +class RoomListSharedActionViewModel @Inject constructor() : VectorSharedActionViewModel() diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListFragment.kt index fae6ddb0c8..a329d52ad6 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListFragment.kt @@ -44,6 +44,8 @@ import im.vector.app.features.home.room.list.RoomSummaryPagedController import im.vector.app.features.home.room.list.actions.RoomListQuickActionsBottomSheet import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedAction import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel +import im.vector.app.features.home.room.list.actions.RoomListSharedAction +import im.vector.app.features.home.room.list.actions.RoomListSharedActionViewModel import im.vector.app.features.spaces.SpacesBottomSheet import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -60,7 +62,8 @@ class HomeRoomListFragment @Inject constructor( RoomListListener { private val roomListViewModel: HomeRoomListViewModel by fragmentViewModel() - private lateinit var sharedActionViewModel: RoomListQuickActionsSharedActionViewModel + private lateinit var sharedQuickActionsViewModel: RoomListQuickActionsSharedActionViewModel + private lateinit var sharedActionViewModel: RoomListSharedActionViewModel private var concatAdapter = ConcatAdapter() private var modelBuildListener: OnModelBuildFinishedListener? = null @@ -74,15 +77,25 @@ class HomeRoomListFragment @Inject constructor( override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - - sharedActionViewModel = activityViewModelProvider[RoomListQuickActionsSharedActionViewModel::class.java] - sharedActionViewModel - .stream() - .onEach { handleQuickActions(it) } - .launchIn(viewLifecycleOwner.lifecycleScope) - views.stateView.contentView = views.roomListView views.stateView.state = StateView.State.Loading + setupObservers() + setupRecyclerView() + setupFabs() + } + + private fun setupObservers() { + sharedQuickActionsViewModel = activityViewModelProvider[RoomListQuickActionsSharedActionViewModel::class.java] + sharedActionViewModel = activityViewModelProvider[RoomListSharedActionViewModel::class.java] + + sharedActionViewModel + .stream() + .onEach(::handleSharedAction) + .launchIn(viewLifecycleOwner.lifecycleScope) + sharedQuickActionsViewModel + .stream() + .onEach(::handleQuickActions) + .launchIn(viewLifecycleOwner.lifecycleScope) roomListViewModel.observeViewEvents { when (it) { @@ -92,9 +105,42 @@ class HomeRoomListFragment @Inject constructor( is HomeRoomListViewEvents.Done -> Unit } } + } - setupRecyclerView() - setupFabs() + private fun handleSharedAction(action: RoomListSharedAction) { + when (action) { + RoomListSharedAction.CloseBottomSheet -> spacesBottomSheet.dismiss() + } + } + + private fun handleQuickActions(quickAction: RoomListQuickActionsSharedAction) { + when (quickAction) { + is RoomListQuickActionsSharedAction.NotificationsAllNoisy -> { + roomListViewModel.handle(HomeRoomListAction.ChangeRoomNotificationState(quickAction.roomId, RoomNotificationState.ALL_MESSAGES_NOISY)) + } + is RoomListQuickActionsSharedAction.NotificationsAll -> { + roomListViewModel.handle(HomeRoomListAction.ChangeRoomNotificationState(quickAction.roomId, RoomNotificationState.ALL_MESSAGES)) + } + is RoomListQuickActionsSharedAction.NotificationsMentionsOnly -> { + roomListViewModel.handle(HomeRoomListAction.ChangeRoomNotificationState(quickAction.roomId, RoomNotificationState.MENTIONS_ONLY)) + } + is RoomListQuickActionsSharedAction.NotificationsMute -> { + roomListViewModel.handle(HomeRoomListAction.ChangeRoomNotificationState(quickAction.roomId, RoomNotificationState.MUTE)) + } + is RoomListQuickActionsSharedAction.Settings -> { + navigator.openRoomProfile(requireActivity(), quickAction.roomId) + } + is RoomListQuickActionsSharedAction.Favorite -> { + roomListViewModel.handle(HomeRoomListAction.ToggleTag(quickAction.roomId, RoomTag.ROOM_TAG_FAVOURITE)) + } + is RoomListQuickActionsSharedAction.LowPriority -> { + roomListViewModel.handle(HomeRoomListAction.ToggleTag(quickAction.roomId, RoomTag.ROOM_TAG_LOW_PRIORITY)) + } + is RoomListQuickActionsSharedAction.Leave -> { + roomListViewModel.handle(HomeRoomListAction.LeaveRoom(quickAction.roomId)) + promptLeaveRoom(quickAction.roomId) + } + } } private fun setupRecyclerView() { @@ -159,35 +205,6 @@ class HomeRoomListFragment @Inject constructor( } } - private fun handleQuickActions(quickAction: RoomListQuickActionsSharedAction) { - when (quickAction) { - is RoomListQuickActionsSharedAction.NotificationsAllNoisy -> { - roomListViewModel.handle(HomeRoomListAction.ChangeRoomNotificationState(quickAction.roomId, RoomNotificationState.ALL_MESSAGES_NOISY)) - } - is RoomListQuickActionsSharedAction.NotificationsAll -> { - roomListViewModel.handle(HomeRoomListAction.ChangeRoomNotificationState(quickAction.roomId, RoomNotificationState.ALL_MESSAGES)) - } - is RoomListQuickActionsSharedAction.NotificationsMentionsOnly -> { - roomListViewModel.handle(HomeRoomListAction.ChangeRoomNotificationState(quickAction.roomId, RoomNotificationState.MENTIONS_ONLY)) - } - is RoomListQuickActionsSharedAction.NotificationsMute -> { - roomListViewModel.handle(HomeRoomListAction.ChangeRoomNotificationState(quickAction.roomId, RoomNotificationState.MUTE)) - } - is RoomListQuickActionsSharedAction.Settings -> { - navigator.openRoomProfile(requireActivity(), quickAction.roomId) - } - is RoomListQuickActionsSharedAction.Favorite -> { - roomListViewModel.handle(HomeRoomListAction.ToggleTag(quickAction.roomId, RoomTag.ROOM_TAG_FAVOURITE)) - } - is RoomListQuickActionsSharedAction.LowPriority -> { - roomListViewModel.handle(HomeRoomListAction.ToggleTag(quickAction.roomId, RoomTag.ROOM_TAG_LOW_PRIORITY)) - } - is RoomListQuickActionsSharedAction.Leave -> { - roomListViewModel.handle(HomeRoomListAction.LeaveRoom(quickAction.roomId)) - promptLeaveRoom(quickAction.roomId) - } - } - } private fun promptLeaveRoom(roomId: String) { val isPublicRoom = roomListViewModel.isPublicRoom(roomId) diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt index bf76c2eecd..770fe1ec52 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt @@ -35,6 +35,8 @@ import im.vector.app.databinding.FragmentSpaceListBinding import im.vector.app.features.VectorFeatures import im.vector.app.features.home.HomeActivitySharedAction import im.vector.app.features.home.HomeSharedActionViewModel +import im.vector.app.features.home.room.list.actions.RoomListSharedAction +import im.vector.app.features.home.room.list.actions.RoomListSharedActionViewModel import org.matrix.android.sdk.api.session.room.model.RoomSummary import javax.inject.Inject @@ -48,7 +50,8 @@ class SpaceListFragment @Inject constructor( private val vectorFeatures: VectorFeatures, ) : VectorBaseFragment(), SpaceSummaryController.Callback, NewSpaceSummaryController.Callback { - private lateinit var sharedActionViewModel: HomeSharedActionViewModel + private lateinit var homeActivitySharedActionViewModel: HomeSharedActionViewModel + private lateinit var roomListSharedActionViewModel: RoomListSharedActionViewModel private val viewModel: SpaceListViewModel by fragmentViewModel() override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentSpaceListBinding { @@ -57,7 +60,8 @@ class SpaceListFragment @Inject constructor( override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - sharedActionViewModel = activityViewModelProvider[HomeSharedActionViewModel::class.java] + homeActivitySharedActionViewModel = activityViewModelProvider[HomeSharedActionViewModel::class.java] + roomListSharedActionViewModel = activityViewModelProvider[RoomListSharedActionViewModel::class.java] views.stateView.contentView = views.groupListView setupSpaceController() enableDragAndDrop() @@ -121,10 +125,10 @@ class SpaceListFragment @Inject constructor( private fun observeViewEvents() = viewModel.observeViewEvents { when (it) { - is SpaceListViewEvents.OpenSpaceSummary -> sharedActionViewModel.post(HomeActivitySharedAction.OpenSpacePreview(it.id)) - is SpaceListViewEvents.AddSpace -> sharedActionViewModel.post(HomeActivitySharedAction.AddSpace) - is SpaceListViewEvents.OpenSpaceInvite -> sharedActionViewModel.post(HomeActivitySharedAction.OpenSpaceInvite(it.id)) - SpaceListViewEvents.CloseDrawer -> sharedActionViewModel.post(HomeActivitySharedAction.CloseDrawer) + is SpaceListViewEvents.OpenSpaceSummary -> homeActivitySharedActionViewModel.post(HomeActivitySharedAction.OpenSpacePreview(it.id)) + is SpaceListViewEvents.AddSpace -> homeActivitySharedActionViewModel.post(HomeActivitySharedAction.AddSpace) + is SpaceListViewEvents.OpenSpaceInvite -> homeActivitySharedActionViewModel.post(HomeActivitySharedAction.OpenSpaceInvite(it.id)) + SpaceListViewEvents.CloseDrawer -> homeActivitySharedActionViewModel.post(HomeActivitySharedAction.CloseDrawer) } } @@ -151,6 +155,7 @@ class SpaceListFragment @Inject constructor( override fun onSpaceSelected(spaceSummary: RoomSummary?) { viewModel.handle(SpaceListAction.SelectSpace(spaceSummary)) + roomListSharedActionViewModel.post(RoomListSharedAction.CloseBottomSheet) } override fun onSpaceInviteSelected(spaceSummary: RoomSummary) { @@ -158,7 +163,7 @@ class SpaceListFragment @Inject constructor( } override fun onSpaceSettings(spaceSummary: RoomSummary) { - sharedActionViewModel.post(HomeActivitySharedAction.ShowSpaceSettings(spaceSummary.roomId)) + homeActivitySharedActionViewModel.post(HomeActivitySharedAction.ShowSpaceSettings(spaceSummary.roomId)) } override fun onToggleExpand(spaceSummary: RoomSummary) { @@ -170,6 +175,6 @@ class SpaceListFragment @Inject constructor( } override fun sendFeedBack() { - sharedActionViewModel.post(HomeActivitySharedAction.SendSpaceFeedBack) + homeActivitySharedActionViewModel.post(HomeActivitySharedAction.SendSpaceFeedBack) } } From ff71e69b0ee9ffdfe574775fd3e3ddad3d559dde Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Fri, 5 Aug 2022 11:48:11 +0200 Subject: [PATCH 06/17] Makes space list work inside spaces --- .../spaces/NewSpaceSummaryController.kt | 103 ++++++++++++------ 1 file changed, 72 insertions(+), 31 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryController.kt b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryController.kt index 6690e92b50..5c346be0de 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryController.kt @@ -19,11 +19,9 @@ package im.vector.app.features.spaces import com.airbnb.epoxy.EpoxyController import im.vector.app.R import im.vector.app.core.resources.StringProvider -import im.vector.app.features.grouplist.homeSpaceSummaryItem import im.vector.app.features.grouplist.newHomeSpaceSummaryItem import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.list.UnreadCounterBadgeView -import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo @@ -49,6 +47,7 @@ class NewSpaceSummaryController @Inject constructor( override fun buildModels() { val nonNullViewState = viewState ?: return buildGroupModels( + nonNullViewState.asyncSpaces(), nonNullViewState.selectedSpace, nonNullViewState.rootSpacesOrdered, nonNullViewState.homeAggregateCount @@ -56,52 +55,94 @@ class NewSpaceSummaryController @Inject constructor( } private fun buildGroupModels( + spaceSummaries: List?, selectedSpace: RoomSummary?, rootSpaces: List?, homeCount: RoomAggregateNotificationCount ) { val host = this - newSpaceListHeaderItem { id("space_list_header") } - newHomeSpaceSummaryItem { - id("space_home") - text(this@NewSpaceSummaryController.stringProvider.getString(R.string.all_chats)) - selected(selectedSpace == null) - countState(UnreadCounterBadgeView.State(homeCount.totalCount, homeCount.isHighlight)) - listener { host.callback?.onSpaceSelected(null) } + if (selectedSpace != null) { + addSubSpaces(selectedSpace, spaceSummaries, homeCount) + } else { + addHomeItem(true, homeCount) + addRootSpaces(rootSpaces) } - rootSpaces - ?.filter { it.membership != Membership.INVITE } - ?.forEach { roomSummary -> - val isSelected = roomSummary.roomId == selectedSpace?.roomId - - newSpaceSummaryItem { - avatarRenderer(host.avatarRenderer) - id(roomSummary.roomId) - matrixItem(roomSummary.toMatrixItem()) - selected(isSelected) - canDrag(true) - onMore { host.callback?.onSpaceSettings(roomSummary) } - listener { host.callback?.onSpaceSelected(roomSummary) } - countState( - UnreadCounterBadgeView.State( - roomSummary.notificationCount, - roomSummary.highlightCount > 0 - ) - ) - } - } - newSpaceAddItem { id("create") listener { host.callback?.onAddSpaceSelected() } } } + private fun addHomeItem(selected: Boolean, homeCount: RoomAggregateNotificationCount) { + val host = this + newHomeSpaceSummaryItem { + id("space_home") + text(host.stringProvider.getString(R.string.all_chats)) + selected(selected) + countState(UnreadCounterBadgeView.State(homeCount.totalCount, homeCount.isHighlight)) + listener { host.callback?.onSpaceSelected(null) } + } + } + + private fun addSubSpaces( + selectedSpace: RoomSummary, + spaceSummaries: List?, + homeCount: RoomAggregateNotificationCount, + ) { + val host = this + val spaceChildren = selectedSpace.spaceChildren + var subSpacesAdded = false + + spaceChildren?.sortedWith(subSpaceComparator)?.forEach { spaceChild -> + val subSpaceSummary = spaceSummaries?.firstOrNull { it.roomId == spaceChild.childRoomId } ?: return@forEach + + if (subSpaceSummary.membership != Membership.INVITE) { + subSpacesAdded = true + newSpaceSummaryItem { + avatarRenderer(host.avatarRenderer) + id(subSpaceSummary.roomId) + matrixItem(subSpaceSummary.toMatrixItem()) + selected(false) + canDrag(true) + onMore { host.callback?.onSpaceSettings(subSpaceSummary) } + listener { host.callback?.onSpaceSelected(subSpaceSummary) } + countState( + UnreadCounterBadgeView.State( + subSpaceSummary.notificationCount, + subSpaceSummary.highlightCount > 0 + ) + ) + } + } + } + + if (!subSpacesAdded) { + addHomeItem(false, homeCount) + } + } + + private fun addRootSpaces(rootSpaces: List?) { + val host = this + rootSpaces + ?.filter { it.membership != Membership.INVITE } + ?.forEach { roomSummary -> + newSpaceSummaryItem { + avatarRenderer(host.avatarRenderer) + id(roomSummary.roomId) + matrixItem(roomSummary.toMatrixItem()) + canDrag(true) + onMore { host.callback?.onSpaceSettings(roomSummary) } + listener { host.callback?.onSpaceSelected(roomSummary) } + countState(UnreadCounterBadgeView.State(roomSummary.notificationCount, roomSummary.highlightCount > 0)) + } + } + } + interface Callback { fun onSpaceSelected(spaceSummary: RoomSummary?) fun onSpaceInviteSelected(spaceSummary: RoomSummary) From 0506c9abfdc9b4f90f15b1169ad899b67e9cea01 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Fri, 5 Aug 2022 11:59:22 +0200 Subject: [PATCH 07/17] Fixes bottom sheet intermittently not having the correct height --- .../spaces/NewSpaceSummaryController.kt | 2 +- .../app/features/spaces/SpaceListViewModel.kt | 34 +++++++++---------- .../app/features/spaces/SpaceListViewState.kt | 1 + 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryController.kt b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryController.kt index 5c346be0de..781d6942bc 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryController.kt @@ -47,7 +47,7 @@ class NewSpaceSummaryController @Inject constructor( override fun buildModels() { val nonNullViewState = viewState ?: return buildGroupModels( - nonNullViewState.asyncSpaces(), + nonNullViewState.spaces, nonNullViewState.selectedSpace, nonNullViewState.rootSpacesOrdered, nonNullViewState.homeAggregateCount diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt index eea11f9b1b..6aab2521f2 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt @@ -257,29 +257,29 @@ class SpaceListViewModel @AssistedInject constructor( } combine( - session.flow() - .liveSpaceSummaries(params), + session.flow().liveSpaceSummaries(params), session.accountDataService() .getLiveRoomAccountDataEvents(setOf(RoomAccountDataTypes.EVENT_TYPE_SPACE_ORDER)) .asFlow() ) { spaces, _ -> spaces + }.execute { asyncSpaces -> + val spaces = asyncSpaces.invoke().orEmpty() + val rootSpaces = asyncSpaces.invoke().orEmpty().filter { it.flattenParentIds.isEmpty() } + val orders = rootSpaces.associate { + it.roomId to session.getRoom(it.roomId) + ?.roomAccountDataService() + ?.getAccountDataEvent(RoomAccountDataTypes.EVENT_TYPE_SPACE_ORDER) + ?.content.toModel() + ?.safeOrder() + } + copy( + asyncSpaces = asyncSpaces, + spaces = spaces, + rootSpacesOrdered = rootSpaces.sortedWith(TopLevelSpaceComparator(orders)), + spaceOrderInfo = orders + ) } - .execute { async -> - val rootSpaces = async.invoke().orEmpty().filter { it.flattenParentIds.isEmpty() } - val orders = rootSpaces.associate { - it.roomId to session.getRoom(it.roomId) - ?.roomAccountDataService() - ?.getAccountDataEvent(RoomAccountDataTypes.EVENT_TYPE_SPACE_ORDER) - ?.content.toModel() - ?.safeOrder() - } - copy( - asyncSpaces = async, - rootSpacesOrdered = rootSpaces.sortedWith(TopLevelSpaceComparator(orders)), - spaceOrderInfo = orders - ) - } // clear local echos on update session.accountDataService() diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewState.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewState.kt index 794f1dbd69..f75c336b5d 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewState.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewState.kt @@ -26,6 +26,7 @@ import org.matrix.android.sdk.api.util.MatrixItem data class SpaceListViewState( val myMxItem: Async = Uninitialized, val asyncSpaces: Async> = Uninitialized, + val spaces: List = emptyList(), val selectedSpace: RoomSummary? = null, val rootSpacesOrdered: List? = null, val spaceOrderInfo: Map? = null, From a821f34fc0f80d1c7d159c8bfe35123f97c7cfbc Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Fri, 5 Aug 2022 12:37:02 +0200 Subject: [PATCH 08/17] Adds drag and drop to space list --- .../app/features/spaces/SpaceListFragment.kt | 52 ++++++++++++++++++- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt index 770fe1ec52..c408884bc0 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt @@ -64,21 +64,69 @@ class SpaceListFragment @Inject constructor( roomListSharedActionViewModel = activityViewModelProvider[RoomListSharedActionViewModel::class.java] views.stateView.contentView = views.groupListView setupSpaceController() - enableDragAndDrop() observeViewEvents() } private fun setupSpaceController() { if (vectorFeatures.isNewAppLayoutEnabled()) { + enableDragAndDropForNewSpaceController() newSpaceController.callback = this views.groupListView.configureWith(newSpaceController) } else { + enableDragAndDropForSpaceController() spaceController.callback = this views.groupListView.configureWith(spaceController) } } - private fun enableDragAndDrop() { + private fun enableDragAndDropForNewSpaceController() { + EpoxyTouchHelper.initDragging(newSpaceController) + .withRecyclerView(views.groupListView) + .forVerticalList() + .withTarget(NewSpaceSummaryItem::class.java) + .andCallbacks(object : EpoxyTouchHelper.DragCallbacks() { + var toPositionM: Int? = null + var fromPositionM: Int? = null + var initialElevation: Float? = null + + override fun onDragStarted(model: NewSpaceSummaryItem?, itemView: View?, adapterPosition: Int) { + toPositionM = null + fromPositionM = null + model?.matrixItem?.id?.let { + viewModel.handle(SpaceListAction.OnStartDragging(it, model.expanded)) + } + itemView?.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) + initialElevation = itemView?.elevation + itemView?.elevation = 6f + } + + override fun onDragReleased(model: NewSpaceSummaryItem?, itemView: View?) { + if (toPositionM == null || fromPositionM == null) return + val movedSpaceId = model?.matrixItem?.id ?: return + viewModel.handle(SpaceListAction.MoveSpace(movedSpaceId, toPositionM!! - fromPositionM!!)) + } + + override fun clearView(model: NewSpaceSummaryItem?, itemView: View?) { + itemView?.elevation = initialElevation ?: 0f + } + + override fun onModelMoved(fromPosition: Int, toPosition: Int, modelBeingMoved: NewSpaceSummaryItem?, itemView: View?) { + if (fromPositionM == null) { + fromPositionM = fromPosition + } + if (toPositionM != toPosition) { + toPositionM = toPosition + itemView?.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) + } + } + + override fun isDragEnabledForModel(model: NewSpaceSummaryItem?): Boolean { + return model?.canDrag == true + } + }) + } + + private fun enableDragAndDropForSpaceController() { EpoxyTouchHelper.initDragging(spaceController) .withRecyclerView(views.groupListView) .forVerticalList() From 90f2b93763801391da2e32bd8b0c45dbd998723c Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Fri, 5 Aug 2022 12:39:52 +0200 Subject: [PATCH 09/17] Appends to comment in SpaceListFragment and refactors SpaceListBottomSheet class name --- .../features/home/room/list/home/HomeRoomListFragment.kt | 8 ++++---- .../{SpacesBottomSheet.kt => SpaceListBottomSheet.kt} | 2 +- .../im/vector/app/features/spaces/SpaceListFragment.kt | 3 +++ 3 files changed, 8 insertions(+), 5 deletions(-) rename vector/src/main/java/im/vector/app/features/spaces/{SpacesBottomSheet.kt => SpaceListBottomSheet.kt} (96%) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListFragment.kt index a329d52ad6..da228572e9 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListFragment.kt @@ -46,7 +46,7 @@ import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedA import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel import im.vector.app.features.home.room.list.actions.RoomListSharedAction import im.vector.app.features.home.room.list.actions.RoomListSharedActionViewModel -import im.vector.app.features.spaces.SpacesBottomSheet +import im.vector.app.features.spaces.SpaceListBottomSheet import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.matrix.android.sdk.api.session.room.model.RoomSummary @@ -67,7 +67,7 @@ class HomeRoomListFragment @Inject constructor( private var concatAdapter = ConcatAdapter() private var modelBuildListener: OnModelBuildFinishedListener? = null - private val spacesBottomSheet = SpacesBottomSheet() + private val spaceListBottomSheet = SpaceListBottomSheet() private lateinit var stateRestorer: LayoutManagerStateRestorer @@ -109,7 +109,7 @@ class HomeRoomListFragment @Inject constructor( private fun handleSharedAction(action: RoomListSharedAction) { when (action) { - RoomListSharedAction.CloseBottomSheet -> spacesBottomSheet.dismiss() + RoomListSharedAction.CloseBottomSheet -> spaceListBottomSheet.dismiss() } } @@ -168,7 +168,7 @@ class HomeRoomListFragment @Inject constructor( views.newLayoutOpenSpacesButton.setOnClickListener { // Click action for open spaces modal goes here - spacesBottomSheet.show(requireActivity().supportFragmentManager, SpacesBottomSheet.TAG) + spaceListBottomSheet.show(requireActivity().supportFragmentManager, SpaceListBottomSheet.TAG) } // Hide FABs when list is scrolling diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpacesBottomSheet.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceListBottomSheet.kt similarity index 96% rename from vector/src/main/java/im/vector/app/features/spaces/SpacesBottomSheet.kt rename to vector/src/main/java/im/vector/app/features/spaces/SpaceListBottomSheet.kt index 757e39b85a..910f8c5379 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpacesBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceListBottomSheet.kt @@ -25,7 +25,7 @@ import im.vector.app.R import im.vector.app.core.extensions.replaceChildFragment import im.vector.app.databinding.FragmentSpacesBottomSheetBinding -class SpacesBottomSheet : BottomSheetDialogFragment() { +class SpaceListBottomSheet : BottomSheetDialogFragment() { private lateinit var binding: FragmentSpacesBottomSheetBinding diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt index c408884bc0..70bf7c3839 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt @@ -43,6 +43,9 @@ import javax.inject.Inject /** * This Fragment is displayed in the navigation drawer [im.vector.app.features.home.HomeDrawerFragment] and * is displaying the space hierarchy, with some actions on Spaces. + * + * In the New App Layout this fragment will instead be displayed in a Bottom Sheet [SpaceListBottomSheet] + * and will only display spaces that are direct children of the currently selected space (or root spaces if none) */ class SpaceListFragment @Inject constructor( private val spaceController: SpaceSummaryController, From 0567fa3e53b222e3d24cefcaf7e75af7fd2c3db0 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Fri, 5 Aug 2022 15:45:53 +0200 Subject: [PATCH 10/17] Changes header text of bottom sheet to Change Space --- .../java/im/vector/app/features/spaces/SpaceListViewModel.kt | 2 +- vector/src/main/res/layout/item_new_space_list_header.xml | 2 +- vector/src/main/res/values/strings.xml | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt index 6aab2521f2..9048026771 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt @@ -194,7 +194,7 @@ class SpaceListViewModel @AssistedInject constructor( val moved = removeAt(index) add(index + action.delta, moved) }, - spaceOrderLocalEchos = updatedLocalEchos + spaceOrderLocalEchos = updatedLocalEchos, ) } session.coroutineScope.launch { diff --git a/vector/src/main/res/layout/item_new_space_list_header.xml b/vector/src/main/res/layout/item_new_space_list_header.xml index 103d1a1b83..15dceb9b7f 100644 --- a/vector/src/main/res/layout/item_new_space_list_header.xml +++ b/vector/src/main/res/layout/item_new_space_list_header.xml @@ -7,7 +7,7 @@ android:background="@drawable/bg_space_item" android:orientation="vertical" android:padding="16dp" - android:text="@string/all_chats" + android:text="@string/change_space" android:textAllCaps="true" android:textColor="?vctr_content_tertiary" android:textSize="14sp" diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index e3f250151b..859e4daffc 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -137,6 +137,7 @@ All Chats + Change Space From e6508e8a5a7fca71d9f1d10c52a158cacd407657 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Fri, 5 Aug 2022 16:08:05 +0200 Subject: [PATCH 11/17] Cleans up epoxy class for NewSpaceSummaryItem and adds ellipsize to header --- .../spaces/NewSpaceSummaryController.kt | 4 ---- .../features/spaces/NewSpaceSummaryItem.kt | 22 ++++++------------- .../app/features/spaces/SpaceListFragment.kt | 6 +---- .../res/layout/item_new_space_list_header.xml | 2 ++ 4 files changed, 10 insertions(+), 24 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryController.kt b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryController.kt index 781d6942bc..7c4435bf59 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryController.kt @@ -108,8 +108,6 @@ class NewSpaceSummaryController @Inject constructor( id(subSpaceSummary.roomId) matrixItem(subSpaceSummary.toMatrixItem()) selected(false) - canDrag(true) - onMore { host.callback?.onSpaceSettings(subSpaceSummary) } listener { host.callback?.onSpaceSelected(subSpaceSummary) } countState( UnreadCounterBadgeView.State( @@ -135,8 +133,6 @@ class NewSpaceSummaryController @Inject constructor( avatarRenderer(host.avatarRenderer) id(roomSummary.roomId) matrixItem(roomSummary.toMatrixItem()) - canDrag(true) - onMore { host.callback?.onSpaceSettings(roomSummary) } listener { host.callback?.onSpaceSelected(roomSummary) } countState(UnreadCounterBadgeView.State(roomSummary.notificationCount, roomSummary.highlightCount > 0)) } diff --git a/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryItem.kt b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryItem.kt index eecb02b320..778b9c933e 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryItem.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryItem.kt @@ -37,35 +37,27 @@ abstract class NewSpaceSummaryItem : VectorEpoxyModel(R.id.root) - val avatarImageView by bind(R.id.avatar) - val groupNameView by bind(R.id.name) - val counterBadgeView by bind(R.id.unread_counter) + val avatar by bind(R.id.avatar) + val name by bind(R.id.name) + val unreadCounter by bind(R.id.unread_counter) } } diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt index 70bf7c3839..7b034356b4 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt @@ -96,7 +96,7 @@ class SpaceListFragment @Inject constructor( toPositionM = null fromPositionM = null model?.matrixItem?.id?.let { - viewModel.handle(SpaceListAction.OnStartDragging(it, model.expanded)) + viewModel.handle(SpaceListAction.OnStartDragging(it, false)) } itemView?.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) initialElevation = itemView?.elevation @@ -122,10 +122,6 @@ class SpaceListFragment @Inject constructor( itemView?.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) } } - - override fun isDragEnabledForModel(model: NewSpaceSummaryItem?): Boolean { - return model?.canDrag == true - } }) } diff --git a/vector/src/main/res/layout/item_new_space_list_header.xml b/vector/src/main/res/layout/item_new_space_list_header.xml index 15dceb9b7f..2c52304249 100644 --- a/vector/src/main/res/layout/item_new_space_list_header.xml +++ b/vector/src/main/res/layout/item_new_space_list_header.xml @@ -5,8 +5,10 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/bg_space_item" + android:ellipsize="middle" android:orientation="vertical" android:padding="16dp" + android:singleLine="true" android:text="@string/change_space" android:textAllCaps="true" android:textColor="?vctr_content_tertiary" From 756570793f0c6d32da42bba9a58fd47d0f4c51e2 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Fri, 5 Aug 2022 17:12:47 +0200 Subject: [PATCH 12/17] Adds changelog file --- changelog.d/6749.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/6749.feature diff --git a/changelog.d/6749.feature b/changelog.d/6749.feature new file mode 100644 index 0000000000..d7fac1efc1 --- /dev/null +++ b/changelog.d/6749.feature @@ -0,0 +1 @@ +Adds space list bottom sheet for new app layout From 9892c66d2753e81f6ed4d8c90c9fd69881a89980 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Tue, 9 Aug 2022 10:54:28 +0200 Subject: [PATCH 13/17] Fixes lint errors --- .../java/im/vector/app/features/home/NewHomeDetailFragment.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt index c0f6c673f4..cfd4b1f0bf 100644 --- a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt @@ -44,7 +44,6 @@ import im.vector.app.features.call.SharedKnownCallsViewModel import im.vector.app.features.call.VectorCallActivity import im.vector.app.features.call.dialpad.DialPadFragment import im.vector.app.features.call.webrtc.WebRtcCallManager -import im.vector.app.features.home.room.list.RoomListFragment import im.vector.app.features.home.room.list.RoomListParams import im.vector.app.features.home.room.list.home.HomeRoomListFragment import im.vector.app.features.popup.PopupAlertManager From 65b7a317286e73f0c035dfefa5c54ce378752a64 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Tue, 9 Aug 2022 14:23:56 +0200 Subject: [PATCH 14/17] Fixes toMvRxBundle import --- .../java/im/vector/app/features/home/NewHomeDetailFragment.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt index cfd4b1f0bf..bfdf385356 100644 --- a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt @@ -31,6 +31,7 @@ import com.google.android.material.badge.BadgeDrawable import im.vector.app.R import im.vector.app.SpaceStateHandler import im.vector.app.core.extensions.commitTransaction +import im.vector.app.core.extensions.toMvRxBundle import im.vector.app.core.platform.OnBackPressed import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.platform.VectorBaseFragment From ddaf5397b1f2dc77be401290dd709739b1f72a35 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Wed, 10 Aug 2022 08:24:03 +0200 Subject: [PATCH 15/17] Removes params passed into HomeRoomListFragment and fixes lint error --- .../im/vector/app/features/home/NewHomeDetailFragment.kt | 5 +---- .../app/features/home/room/list/home/HomeRoomListFragment.kt | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt index bfdf385356..c2b61d694a 100644 --- a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt @@ -31,7 +31,6 @@ import com.google.android.material.badge.BadgeDrawable import im.vector.app.R import im.vector.app.SpaceStateHandler import im.vector.app.core.extensions.commitTransaction -import im.vector.app.core.extensions.toMvRxBundle import im.vector.app.core.platform.OnBackPressed import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.platform.VectorBaseFragment @@ -45,7 +44,6 @@ import im.vector.app.features.call.SharedKnownCallsViewModel import im.vector.app.features.call.VectorCallActivity import im.vector.app.features.call.dialpad.DialPadFragment import im.vector.app.features.call.webrtc.WebRtcCallManager -import im.vector.app.features.home.room.list.RoomListParams import im.vector.app.features.home.room.list.home.HomeRoomListFragment import im.vector.app.features.popup.PopupAlertManager import im.vector.app.features.popup.VerificationVectorAlert @@ -339,8 +337,7 @@ class NewHomeDetailFragment @Inject constructor( if (fragmentToShow == null) { when (tab) { is HomeTab.RoomList -> { - val params = RoomListParams(tab.displayMode) - add(R.id.roomListContainer, HomeRoomListFragment::class.java, params.toMvRxBundle(), fragmentTag) + add(R.id.roomListContainer, HomeRoomListFragment::class.java, null, fragmentTag) } is HomeTab.DialPad -> { add(R.id.roomListContainer, createDialPadFragment(), fragmentTag) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListFragment.kt index bb8fee632c..d0ef6fc0c2 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListFragment.kt @@ -205,7 +205,6 @@ class HomeRoomListFragment @Inject constructor( } } - private fun promptLeaveRoom(roomId: String) { val isPublicRoom = roomListViewModel.isPublicRoom(roomId) val message = buildString { From 358ec5a722e5fe0b6889a65e9f9d6d9bf918301e Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Wed, 10 Aug 2022 08:25:51 +0200 Subject: [PATCH 16/17] Fixes post merge errors --- .../app/features/home/room/list/home/HomeRoomListFragment.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListFragment.kt index b29e151350..3c0c8f6b7e 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListFragment.kt @@ -47,8 +47,8 @@ import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedA import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel import im.vector.app.features.home.room.list.actions.RoomListSharedAction import im.vector.app.features.home.room.list.actions.RoomListSharedActionViewModel -import im.vector.app.features.spaces.SpaceListBottomSheet import im.vector.app.features.home.room.list.home.recent.RecentRoomCarouselController +import im.vector.app.features.spaces.SpaceListBottomSheet import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.matrix.android.sdk.api.session.room.model.RoomSummary From fd37b31c4482868ee7d23f8f25c622258b79f03c Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Wed, 10 Aug 2022 11:28:14 +0200 Subject: [PATCH 17/17] Changes changelog file extension --- changelog.d/{6749.feature => 6749.wip} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename changelog.d/{6749.feature => 6749.wip} (100%) diff --git a/changelog.d/6749.feature b/changelog.d/6749.wip similarity index 100% rename from changelog.d/6749.feature rename to changelog.d/6749.wip