diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/DefaultSpaceService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/DefaultSpaceService.kt index 8fdc563edb..540eed9b6a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/DefaultSpaceService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/DefaultSpaceService.kt @@ -127,24 +127,29 @@ internal class DefaultSpaceService @Inject constructor( ), second = response.rooms ?.filter { it.roomId != spaceId } - ?.map { childSummary -> - val childStateEv = response.events - ?.firstOrNull { it.stateKey == childSummary.roomId && it.type == EventType.STATE_SPACE_CHILD } - val childStateEvContent = childStateEv?.content.toModel() - SpaceChildInfo( - childRoomId = childSummary.roomId, - isKnown = true, - roomType = childSummary.roomType, - name = childSummary.name, - topic = childSummary.topic, - avatarUrl = childSummary.avatarUrl, - order = childStateEvContent?.order, - autoJoin = childStateEvContent?.autoJoin ?: false, - viaServers = childStateEvContent?.via ?: emptyList(), - activeMemberCount = childSummary.numJoinedMembers, - parentRoomId = childStateEv?.roomId - ) - }.orEmpty() + ?.flatMap { childSummary -> + response.events + ?.filter { it.stateKey == childSummary.roomId && it.type == EventType.STATE_SPACE_CHILD } + ?.map { childStateEv -> + // create a child entry for everytime this room is the child of a space + // beware that a room could appear then twice in this list + val childStateEvContent = childStateEv.content.toModel() + SpaceChildInfo( + childRoomId = childSummary.roomId, + isKnown = true, + roomType = childSummary.roomType, + name = childSummary.name, + topic = childSummary.topic, + avatarUrl = childSummary.avatarUrl, + order = childStateEvContent?.order, + autoJoin = childStateEvContent?.autoJoin ?: false, + viaServers = childStateEvContent?.via ?: emptyList(), + activeMemberCount = childSummary.numJoinedMembers, + parentRoomId = childStateEv.roomId + ) + }.orEmpty() + } + .orEmpty() ) } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/SpaceRoomListSectionBuilder.kt b/vector/src/main/java/im/vector/app/features/home/room/list/SpaceRoomListSectionBuilder.kt index f7e527a710..351c72ab48 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/SpaceRoomListSectionBuilder.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/SpaceRoomListSectionBuilder.kt @@ -194,7 +194,7 @@ class SpaceRoomListSectionBuilder( } else { liveData(context = viewModelScope.coroutineContext + Dispatchers.IO) { val spaceSum = tryOrNull { session.spaceService().querySpaceChildren(selectedSpace.roomId, suggestedOnly = true) } - val value = spaceSum?.second ?: emptyList() + val value = spaceSum?.second.orEmpty().distinctBy { it.childRoomId } // i need to check if it's already joined. val filtered = value.filter { session.getRoomSummary(it.childRoomId)?.membership?.isActive() != true diff --git a/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheet.kt b/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheet.kt index b9ef833850..13c0645d8d 100644 --- a/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheet.kt @@ -56,7 +56,7 @@ class MatrixToBottomSheet : injector.inject(this) } - private var interactionListener: InteractionListener? = null + var interactionListener: InteractionListener? = null override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetMatrixToCardBinding { return BottomSheetMatrixToCardBinding.inflate(inflater, container, false) diff --git a/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheetViewModel.kt b/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheetViewModel.kt index 0d633ac422..694f324025 100644 --- a/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheetViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheetViewModel.kt @@ -120,6 +120,7 @@ class MatrixToBottomSheetViewModel @AssistedInject constructor( ?.roomSummary() // don't take if not active, as it could be outdated ?.takeIf { it.membership.isActive() } + // XXX fix that val forceRefresh = true if (!forceRefresh && knownRoom != null) { setState { @@ -147,7 +148,7 @@ class MatrixToBottomSheetViewModel @AssistedInject constructor( topic = peekResult.topic ?: "", memberCount = peekResult.numJoinedMembers, alias = peekResult.alias, - membership = Membership.NONE, + membership = knownRoom?.membership ?: Membership.NONE, roomType = peekResult.roomType, viaServers = peekResult.viaServers.takeIf { it.isNotEmpty() } ?: permalinkData.viaParameters ).also { diff --git a/vector/src/main/java/im/vector/app/features/matrixto/MatrixToRoomSpaceFragment.kt b/vector/src/main/java/im/vector/app/features/matrixto/MatrixToRoomSpaceFragment.kt index 7a5a740b93..43fd819c4d 100644 --- a/vector/src/main/java/im/vector/app/features/matrixto/MatrixToRoomSpaceFragment.kt +++ b/vector/src/main/java/im/vector/app/features/matrixto/MatrixToRoomSpaceFragment.kt @@ -21,7 +21,6 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.core.view.isGone -import androidx.core.view.isInvisible import androidx.core.view.isVisible import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading @@ -31,6 +30,7 @@ import com.airbnb.mvrx.parentFragmentViewModel import com.airbnb.mvrx.withState import im.vector.app.R import im.vector.app.core.extensions.setTextOrHide +import im.vector.app.core.platform.ButtonStateView import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentMatrixToRoomSpaceCardBinding import im.vector.app.features.home.AvatarRenderer @@ -50,11 +50,18 @@ class MatrixToRoomSpaceFragment @Inject constructor( override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - views.matrixToCardMainButton.debouncedClicks { - mainButtonClicked() + views.matrixToCardMainButton.callback = object : ButtonStateView.Callback { + override fun onButtonClicked() { + mainButtonClicked() + } + + override fun onRetryClicked() = onButtonClicked() } - views.matrixToCardSecondaryButton.debouncedClicks { - secondaryButtonClicked() + views.matrixToCardSecondaryButton.callback = object : ButtonStateView.Callback { + override fun onButtonClicked() { + secondaryButtonClicked() + } + override fun onRetryClicked() = onButtonClicked() } } @@ -182,21 +189,17 @@ class MatrixToRoomSpaceFragment @Inject constructor( when (state.startChattingState) { Uninitialized -> { - views.matrixToCardButtonLoading.isVisible = false -// views.matrixToCardMainButton.isVisible = false + views.matrixToCardMainButton.render(ButtonStateView.State.Button) } is Success -> { - views.matrixToCardButtonLoading.isVisible = false - views.matrixToCardMainButton.isVisible = true + views.matrixToCardMainButton.render(ButtonStateView.State.Button) } is Fail -> { - views.matrixToCardButtonLoading.isVisible = false - views.matrixToCardMainButton.isVisible = true + views.matrixToCardMainButton.render(ButtonStateView.State.Error) // TODO display some error copy? } is Loading -> { - views.matrixToCardButtonLoading.isVisible = true - views.matrixToCardMainButton.isInvisible = true + views.matrixToCardMainButton.render(ButtonStateView.State.Loading) } } } diff --git a/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryController.kt b/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryController.kt index 44d98766d5..f8e45dcd5e 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryController.kt @@ -38,6 +38,7 @@ class SpaceDirectoryController @Inject constructor( interface InteractionListener { fun onButtonClick(spaceChildInfo: SpaceChildInfo) fun onSpaceChildClick(spaceChildInfo: SpaceChildInfo) + fun onRoomClick(spaceChildInfo: SpaceChildInfo) } var listener: InteractionListener? = null @@ -81,6 +82,8 @@ class SpaceDirectoryController @Inject constructor( apply { if (isSpace) { itemClickListener(View.OnClickListener { listener?.onSpaceChildClick(info) }) + } else { + itemClickListener(View.OnClickListener { listener?.onRoomClick(info) }) } } buttonClickListener(View.OnClickListener { listener?.onButtonClick(info) }) diff --git a/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryFragment.kt index 567012675e..0454112417 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryFragment.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryFragment.kt @@ -21,15 +21,17 @@ import android.os.Parcelable import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.fragment.app.FragmentOnAttachListener import com.airbnb.mvrx.activityViewModel import com.airbnb.mvrx.withState +import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.OnBackPressed import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentRoomDirectoryPickerBinding +import im.vector.app.features.matrixto.MatrixToBottomSheet import kotlinx.parcelize.Parcelize -import org.matrix.android.sdk.api.session.room.model.RoomType import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo import javax.inject.Inject @@ -42,13 +44,19 @@ class SpaceDirectoryFragment @Inject constructor( private val epoxyController: SpaceDirectoryController ) : VectorBaseFragment(), SpaceDirectoryController.InteractionListener, - OnBackPressed { + OnBackPressed, MatrixToBottomSheet.InteractionListener { override fun getBinding(inflater: LayoutInflater, container: ViewGroup?) = FragmentRoomDirectoryPickerBinding.inflate(layoutInflater, container, false) private val viewModel by activityViewModel(SpaceDirectoryViewModel::class) + private var fragmentOnAttachListener = FragmentOnAttachListener { _, fragment -> + if (fragment is MatrixToBottomSheet) { + fragment.interactionListener = this + } + } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -60,16 +68,24 @@ class SpaceDirectoryFragment @Inject constructor( } epoxyController.listener = this views.roomDirectoryPickerList.configureWith(epoxyController) + + childFragmentManager.addFragmentOnAttachListener(fragmentOnAttachListener) } override fun onDestroyView() { + childFragmentManager.removeFragmentOnAttachListener(fragmentOnAttachListener) epoxyController.listener = null views.roomDirectoryPickerList.cleanup() super.onDestroyView() } - override fun invalidate() = withState(viewModel) { - epoxyController.setData(it) + override fun invalidate() = withState(viewModel) { state -> + epoxyController.setData(state) + + val title = state.hierarchyStack.lastOrNull()?.let { currentParent -> + state.spaceSummaryApiResult.invoke()?.firstOrNull { it.childRoomId == currentParent } + }?.name ?: getString(R.string.space_explore_activity_title) + views.toolbar.title = title } override fun onButtonClick(spaceChildInfo: SpaceChildInfo) { @@ -77,8 +93,14 @@ class SpaceDirectoryFragment @Inject constructor( } override fun onSpaceChildClick(spaceChildInfo: SpaceChildInfo) { - if (spaceChildInfo.roomType == RoomType.SPACE) { - viewModel.handle(SpaceDirectoryViewAction.ExploreSubSpace(spaceChildInfo)) + viewModel.handle(SpaceDirectoryViewAction.ExploreSubSpace(spaceChildInfo)) + } + + override fun onRoomClick(spaceChildInfo: SpaceChildInfo) { + // This is temporary for now to at least display something for the space beta + // It's not ideal as it's doing some peeking that is not needed. + viewModel.session.permalinkService().createRoomPermalink(spaceChildInfo.childRoomId)?.let { + MatrixToBottomSheet.withLink(it, this).show(childFragmentManager, "ShowChild") } } @@ -86,4 +108,8 @@ class SpaceDirectoryFragment @Inject constructor( viewModel.handle(SpaceDirectoryViewAction.HandleBack) return true } + + override fun navigateToRoom(roomId: String) { + viewModel.handle(SpaceDirectoryViewAction.NavigateToRoom(roomId)) + } } diff --git a/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryViewAction.kt b/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryViewAction.kt index a74662759e..562d1c1124 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryViewAction.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryViewAction.kt @@ -22,5 +22,6 @@ import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo sealed class SpaceDirectoryViewAction : VectorViewModelAction { data class ExploreSubSpace(val spaceChildInfo: SpaceChildInfo) : SpaceDirectoryViewAction() data class JoinOrOpen(val spaceChildInfo: SpaceChildInfo) : SpaceDirectoryViewAction() + data class NavigateToRoom(val roomId: String) : SpaceDirectoryViewAction() object HandleBack : SpaceDirectoryViewAction() } diff --git a/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryViewModel.kt b/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryViewModel.kt index fbe405e641..9173e15dac 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryViewModel.kt @@ -40,7 +40,7 @@ import timber.log.Timber class SpaceDirectoryViewModel @AssistedInject constructor( @Assisted initialState: SpaceDirectoryState, - private val session: Session + val session: Session ) : VectorViewModel(initialState) { @AssistedFactory @@ -91,6 +91,7 @@ class SpaceDirectoryViewModel @AssistedInject constructor( private fun observeJoinedRooms() { val queryParams = roomSummaryQueryParams { memberships = listOf(Membership.JOIN) + excludeType = null } session .rx() @@ -135,6 +136,9 @@ class SpaceDirectoryViewModel @AssistedInject constructor( is SpaceDirectoryViewAction.JoinOrOpen -> { handleJoinOrOpen(action.spaceChildInfo) } + is SpaceDirectoryViewAction.NavigateToRoom -> { + _viewEvents.post(SpaceDirectoryViewEvents.NavigateToRoom(action.roomId)) + } } }