Skip to content

Commit

Permalink
Merge pull request #3032 from vector-im/feature/bca/spaces_context_menu
Browse files Browse the repository at this point in the history
Feature/bca/spaces context menu
  • Loading branch information
BillCarsonFr authored Mar 22, 2021
2 parents 389bf2b + ea5cc37 commit e6c7325
Show file tree
Hide file tree
Showing 16 changed files with 317 additions and 19 deletions.
3 changes: 3 additions & 0 deletions vector/src/main/java/im/vector/app/AppStateHandler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ class AppStateHandler @Inject constructor(
GlobalScope.launch {
sessionDataSource.currentValue?.orNull()?.let { session ->
val currentSpace = currentSpaceOptional.orNull()
.takeIf { it?.roomId != im.vector.app.features.spaces.ALL_COMMUNITIES_GROUP_ID }
if (currentSpace != null) {
val childInfo = withContext(Dispatchers.IO) {
tryOrNull {
Expand All @@ -115,6 +116,8 @@ class AppStateHandler @Inject constructor(
childInfo?.second?.let { currentSpaceSuggestedDataSource.post(it) } ?: kotlin.run {
currentSpaceSuggestedDataSource.post(emptyList())
}
} else {
currentSpaceSuggestedDataSource.post(emptyList())
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions vector/src/main/java/im/vector/app/core/di/ScreenComponent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ import im.vector.app.features.signout.soft.SoftLogoutActivity
import im.vector.app.features.spaces.ShareSpaceBottomSheet
import im.vector.app.features.spaces.SpaceCreationActivity
import im.vector.app.features.spaces.SpaceExploreActivity
import im.vector.app.features.spaces.SpaceSettingsMenuBottomSheet
import im.vector.app.features.terms.ReviewTermsActivity
import im.vector.app.features.ui.UiStateRepository
import im.vector.app.features.usercode.UserCodeActivity
Expand Down Expand Up @@ -179,6 +180,7 @@ interface ScreenComponent {
fun inject(bottomSheet: SignOutBottomSheetDialogFragment)
fun inject(bottomSheet: MatrixToBottomSheet)
fun inject(bottomSheet: ShareSpaceBottomSheet)
fun inject(bottomSheet: SpaceSettingsMenuBottomSheet)

/* ==========================================================================================
* Others
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ import im.vector.app.features.settings.VectorPreferences
import im.vector.app.features.settings.VectorSettingsActivity
import im.vector.app.features.spaces.SpaceCreationActivity
import im.vector.app.features.spaces.SpacePreviewActivity
import im.vector.app.features.spaces.SpaceSettingsMenuBottomSheet
import im.vector.app.features.themes.ThemeUtils
import im.vector.app.features.workers.signout.ServerBackupStatusViewModel
import im.vector.app.features.workers.signout.ServerBackupStatusViewState
Expand Down Expand Up @@ -164,6 +165,12 @@ class HomeActivity :
is HomeActivitySharedAction.AddSpace -> {
createSpaceResultLauncher.launch(SpaceCreationActivity.newIntent(this))
}
is HomeActivitySharedAction.ShowSpaceSettings -> {
// open bottom sheet
SpaceSettingsMenuBottomSheet
.newInstance(sharedAction.spaceId)
.show(supportFragmentManager, "SPACE_SETTINGS")
}
}.exhaustive
}
.disposeOnDestroy()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ sealed class HomeActivitySharedAction : VectorSharedAction {
object OpenGroup : HomeActivitySharedAction()
object AddSpace : HomeActivitySharedAction()
data class OpenSpacePreview(val spaceId: String) : HomeActivitySharedAction()
data class ShowSpaceSettings(val spaceId: String) : HomeActivitySharedAction()
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ import im.vector.app.core.platform.ToolbarConfigurable
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.ui.views.CurrentCallsView
import im.vector.app.core.ui.views.KnownCallsViewHolder
import im.vector.app.core.ui.views.KeysBackupBanner
import im.vector.app.core.ui.views.KnownCallsViewHolder
import im.vector.app.databinding.FragmentHomeDetailBinding
import im.vector.app.features.call.SharedKnownCallsViewModel
import im.vector.app.features.call.VectorCallActivity
Expand All @@ -52,7 +52,6 @@ import im.vector.app.features.themes.ThemeUtils
import im.vector.app.features.workers.signout.BannerState
import im.vector.app.features.workers.signout.ServerBackupStatusViewModel
import im.vector.app.features.workers.signout.ServerBackupStatusViewState

import org.matrix.android.sdk.api.session.group.model.GroupSummary
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.api.util.toMatrixItem
Expand Down Expand Up @@ -246,10 +245,10 @@ class HomeDetailFragment @Inject constructor(
serverBackupStatusViewModel
.subscribe(this) {
when (val banState = it.bannerState.invoke()) {
is BannerState.Setup -> views.homeKeysBackupBanner.render(KeysBackupBanner.State.Setup(banState.numberOfKeys), false)
is BannerState.Setup -> views.homeKeysBackupBanner.render(KeysBackupBanner.State.Setup(banState.numberOfKeys), false)
BannerState.BackingUp -> views.homeKeysBackupBanner.render(KeysBackupBanner.State.BackingUp, false)
null,
BannerState.Hidden -> views.homeKeysBackupBanner.render(KeysBackupBanner.State.Hidden, false)
BannerState.Hidden -> views.homeKeysBackupBanner.render(KeysBackupBanner.State.Hidden, false)
}
}
views.homeKeysBackupBanner.delegate = this
Expand All @@ -273,14 +272,24 @@ class HomeDetailFragment @Inject constructor(
views.groupToolbarAvatarImageView.debouncedClicks {
sharedActionViewModel.post(HomeActivitySharedAction.OpenDrawer)
}

views.homeToolbarContent.debouncedClicks {
withState(viewModel) {
val currentSpace = it.spaceSummary.orNull()
?.takeIf { it.roomId != ALL_COMMUNITIES_GROUP_ID }
if (vectorPreferences.labSpaces() && currentSpace != null) {
sharedActionViewModel.post(HomeActivitySharedAction.ShowSpaceSettings(currentSpace.roomId))
}
}
}
}

private fun setupBottomNavigationView() {
views.bottomNavigationView.menu.findItem(R.id.bottom_action_notification).isVisible = vectorPreferences.labAddNotificationTab()
views.bottomNavigationView.setOnNavigationItemSelectedListener {
val displayMode = when (it.itemId) {
R.id.bottom_action_people -> RoomListDisplayMode.PEOPLE
R.id.bottom_action_rooms -> RoomListDisplayMode.ROOMS
R.id.bottom_action_rooms -> RoomListDisplayMode.ROOMS
else -> RoomListDisplayMode.NOTIFICATIONS
}
viewModel.handle(HomeDetailAction.SwitchDisplayMode(displayMode))
Expand Down Expand Up @@ -356,7 +365,7 @@ class HomeDetailFragment @Inject constructor(

private fun RoomListDisplayMode.toMenuId() = when (this) {
RoomListDisplayMode.PEOPLE -> R.id.bottom_action_people
RoomListDisplayMode.ROOMS -> R.id.bottom_action_rooms
RoomListDisplayMode.ROOMS -> R.id.bottom_action_rooms
else -> R.id.bottom_action_notification
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ import javax.inject.Inject
class RoomListViewModel @Inject constructor(initialState: RoomListViewState,
private val session: Session,
private val roomSummariesSource: DataSource<List<RoomSummary>>,
private val suggestedRoomListDataSource: DataSource<List<SpaceChildInfo>>)
suggestedRoomListDataSource: DataSource<List<SpaceChildInfo>>)
: VectorViewModel<RoomListViewState, RoomListAction, RoomListViewEvents>(initialState) {

interface Factory {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class RoomProfileActivity :

const val EXTRA_DIRECT_ACCESS_ROOM_ROOT = 0
const val EXTRA_DIRECT_ACCESS_ROOM_SETTINGS = 1
const val EXTRA_DIRECT_ACCESS_ROOM_MEMBERS = 2

fun newIntent(context: Context, roomId: String, directAccess: Int?): Intent {
val roomProfileArgs = RoomProfileArgs(roomId)
Expand Down Expand Up @@ -97,6 +98,9 @@ class RoomProfileActivity :
addFragment(R.id.simpleFragmentContainer, RoomProfileFragment::class.java, roomProfileArgs)
addFragmentToBackstack(R.id.simpleFragmentContainer, RoomSettingsFragment::class.java, roomProfileArgs)
}
EXTRA_DIRECT_ACCESS_ROOM_MEMBERS -> {
addFragment(R.id.simpleFragmentContainer, RoomMemberListFragment::class.java, roomProfileArgs)
}
else -> addFragment(R.id.simpleFragmentContainer, RoomProfileFragment::class.java, roomProfileArgs)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ class SpaceListFragment @Inject constructor(
viewModel.handle(SpaceListAction.SelectSpace(spaceSummary))
}

override fun onLeaveSpace(spaceSummary: RoomSummary) {
viewModel.handle(SpaceListAction.LeaveSpace(spaceSummary))
override fun onSpaceSettings(spaceSummary: RoomSummary) {
sharedActionViewModel.post(HomeActivitySharedAction.ShowSpaceSettings(spaceSummary.roomId))
}

override fun onAddSpaceSelected() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/*
* 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.os.Bundle
import android.os.Parcelable
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import androidx.core.view.isVisible
import com.airbnb.mvrx.args
import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
import im.vector.app.databinding.BottomSheetSpaceSettingsBinding
import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.navigation.Navigator
import im.vector.app.features.powerlevel.PowerLevelsObservableFactory
import im.vector.app.features.roomprofile.RoomProfileActivity
import im.vector.app.features.settings.VectorPreferences
import io.reactivex.android.schedulers.AndroidSchedulers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.parcelize.Parcelize
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
import org.matrix.android.sdk.api.util.toMatrixItem
import org.matrix.android.sdk.internal.util.awaitCallback
import timber.log.Timber
import javax.inject.Inject

@Parcelize
data class SpaceBottomSheetSettingsArgs(
val spaceId: String
) : Parcelable

class SpaceSettingsMenuBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetSpaceSettingsBinding>() {

@Inject lateinit var navigator: Navigator
@Inject lateinit var activeSessionHolder: ActiveSessionHolder
@Inject lateinit var avatarRenderer: AvatarRenderer
@Inject lateinit var vectorPreferences: VectorPreferences

private val spaceArgs: SpaceBottomSheetSettingsArgs by args()

override fun injectWith(injector: ScreenComponent) {
injector.inject(this)
}

override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetSpaceSettingsBinding {
return BottomSheetSpaceSettingsBinding.inflate(inflater, container, false)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

val session = activeSessionHolder.getSafeActiveSession() ?: return
val roomSummary = session.getRoomSummary(spaceArgs.spaceId)
roomSummary?.toMatrixItem()?.let {
avatarRenderer.renderSpace(it, views.roomAvatarImageView)
}
views.roomNameView.text = roomSummary?.displayName
views.roomDescription.text = roomSummary?.topic

val room = session.getRoom(spaceArgs.spaceId) ?: return

PowerLevelsObservableFactory(room)
.createObservable()
.observeOn(AndroidSchedulers.mainThread())
.subscribe { powerLevelContent ->
val powerLevelsHelper = PowerLevelsHelper(powerLevelContent)
val canInvite = powerLevelsHelper.isUserAbleToInvite(session.myUserId)
views.invitePeople.isVisible = canInvite
}.disposeOnDestroyView()

views.invitePeople.views.bottomSheetActionClickableZone.debouncedClicks {
navigator.openInviteUsersToRoom(requireContext(), spaceArgs.spaceId)
}

views.showMemberList.views.bottomSheetActionClickableZone.debouncedClicks {
navigator.openRoomProfile(requireContext(), spaceArgs.spaceId, RoomProfileActivity.EXTRA_DIRECT_ACCESS_ROOM_MEMBERS)
}

views.spaceSettings.isVisible = vectorPreferences.developerMode()
views.spaceSettings.views.bottomSheetActionClickableZone.debouncedClicks {
navigator.openRoomProfile(requireContext(), spaceArgs.spaceId)
}

views.exploreRooms.views.bottomSheetActionClickableZone.debouncedClicks {
startActivity(SpaceExploreActivity.newIntent(requireContext(), spaceArgs.spaceId))
}

views.leaveSpace.views.bottomSheetActionClickableZone.debouncedClicks {
AlertDialog.Builder(requireContext())
.setMessage(getString(R.string.space_leave_prompt_msg))
.setPositiveButton(R.string.leave) { _, _ ->
GlobalScope.launch {
try {
awaitCallback {
session.getRoom(spaceArgs.spaceId)?.leave(null, it)
}
} catch (failure: Throwable) {
Timber.e(failure, "Failed to leave space")
}
}
dismiss()
}
.setNegativeButton(R.string.cancel, null)
.show()
}
}

companion object {
fun newInstance(spaceId: String): SpaceSettingsMenuBottomSheet {
return SpaceSettingsMenuBottomSheet().apply {
setArguments(SpaceBottomSheetSettingsArgs(spaceId))
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ class SpaceSummaryController @Inject constructor(
id(groupSummary.roomId)
matrixItem(groupSummary.toMatrixItem())
selected(isSelected)
onLeave { callback?.onLeaveSpace(groupSummary) }
onMore { callback?.onSpaceSettings(groupSummary) }
listener { callback?.onSpaceSelected(groupSummary) }
}
}
Expand All @@ -120,7 +120,7 @@ class SpaceSummaryController @Inject constructor(

interface Callback {
fun onSpaceSelected(spaceSummary: RoomSummary)
fun onLeaveSpace(spaceSummary: RoomSummary)
fun onSpaceSettings(spaceSummary: RoomSummary)
fun onAddSpaceSelected()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ abstract class SpaceSummaryItem : VectorEpoxyModel<SpaceSummaryItem.Holder>() {
@EpoxyAttribute lateinit var matrixItem: MatrixItem
@EpoxyAttribute var selected: Boolean = false
@EpoxyAttribute var listener: (() -> Unit)? = null
@EpoxyAttribute var onLeave: (() -> Unit)? = null
@EpoxyAttribute var onMore: (() -> Unit)? = null
@EpoxyAttribute var toggleExpand: (() -> Unit)? = null
@EpoxyAttribute var expanded: Boolean? = null

Expand All @@ -47,14 +47,14 @@ abstract class SpaceSummaryItem : VectorEpoxyModel<SpaceSummaryItem.Holder>() {
holder.rootView.setOnClickListener { listener?.invoke() }
holder.groupNameView.text = matrixItem.displayName
holder.rootView.isChecked = selected
if (onLeave != null) {
holder.leaveView.setOnClickListener(
if (onMore != null) {
holder.moreView.setOnClickListener(
DebouncedClickListener({ _ ->
onLeave?.invoke()
onMore?.invoke()
})
)
} else {
holder.leaveView.isVisible = false
holder.moreView.isVisible = false
}

when (expanded) {
Expand Down Expand Up @@ -88,7 +88,7 @@ abstract class SpaceSummaryItem : VectorEpoxyModel<SpaceSummaryItem.Holder>() {
val avatarImageView by bind<ImageView>(R.id.groupAvatarImageView)
val groupNameView by bind<TextView>(R.id.groupNameView)
val rootView by bind<CheckableConstraintLayout>(R.id.itemGroupLayout)
val leaveView by bind<ImageView>(R.id.groupTmpLeave)
val moreView by bind<ImageView>(R.id.groupTmpLeave)
val collapseIndicator by bind<ImageView>(R.id.groupChildrenCollapse)
}
}
13 changes: 13 additions & 0 deletions vector/src/main/res/drawable/ic_explore.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M22.6667,12C22.6667,17.8911 17.8911,22.6667 12,22.6667C6.109,22.6667 1.3333,17.8911 1.3333,12C1.3333,6.109 6.109,1.3334 12,1.3334C17.8911,1.3334 22.6667,6.109 22.6667,12ZM17.8333,7.1022C18.0778,6.5711 17.4288,5.9221 16.8977,6.1666L10.2263,9.238C9.7853,9.4411 9.4402,9.7861 9.2372,10.2271L6.1657,16.8986C5.9212,17.4297 6.5702,18.0787 7.1013,17.8341L13.7727,14.7627C14.2137,14.5597 14.5588,14.2146 14.7618,13.7736L17.8333,7.1022Z"
android:fillColor="#737D8C"
android:fillType="evenOdd"/>
<path
android:pathData="M13.178,13.1789C12.5271,13.8298 11.4719,13.8298 10.821,13.1789C10.1701,12.528 10.1701,11.4727 10.821,10.8219C11.4719,10.171 12.5271,10.171 13.178,10.8219C13.8289,11.4727 13.8289,12.528 13.178,13.1789Z"
android:fillColor="#737D8C"/>
</vector>
Loading

0 comments on commit e6c7325

Please sign in to comment.