Cherry pick room on leave space
This commit is contained in:
parent
8fd784e275
commit
9a9a3d8cc6
|
@ -319,6 +319,7 @@
|
|||
<activity android:name=".features.spaces.SpaceCreationActivity" />
|
||||
<activity android:name=".features.spaces.manage.SpaceManageActivity" />
|
||||
<activity android:name=".features.spaces.people.SpacePeopleActivity" />
|
||||
<activity android:name=".features.spaces.leave.SpaceLeaveAdvancedActivity" />
|
||||
<!-- Services -->
|
||||
|
||||
<service
|
||||
|
|
|
@ -146,6 +146,7 @@ import im.vector.app.features.spaces.create.CreateSpaceAdd3pidInvitesFragment
|
|||
import im.vector.app.features.spaces.create.CreateSpaceDefaultRoomsFragment
|
||||
import im.vector.app.features.spaces.create.CreateSpaceDetailsFragment
|
||||
import im.vector.app.features.spaces.explore.SpaceDirectoryFragment
|
||||
import im.vector.app.features.spaces.leave.SpaceLeaveAdvancedFragment
|
||||
import im.vector.app.features.spaces.manage.SpaceAddRoomFragment
|
||||
import im.vector.app.features.spaces.manage.SpaceManageRoomsFragment
|
||||
import im.vector.app.features.spaces.manage.SpaceSettingsFragment
|
||||
|
@ -828,4 +829,9 @@ interface FragmentModule {
|
|||
@IntoMap
|
||||
@FragmentKey(RoomJoinRuleChooseRestrictedFragment::class)
|
||||
fun bindRoomJoinRuleChooseRestrictedFragment(fragment: RoomJoinRuleChooseRestrictedFragment): Fragment
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FragmentKey(SpaceLeaveAdvancedFragment::class)
|
||||
fun bindSpaceLeaveAdvancedFragment(fragment: SpaceLeaveAdvancedFragment): Fragment
|
||||
}
|
||||
|
|
|
@ -89,6 +89,7 @@ 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.spaces.invite.SpaceInviteBottomSheet
|
||||
import im.vector.app.features.spaces.leave.SpaceLeaveAdvancedActivity
|
||||
import im.vector.app.features.spaces.manage.SpaceManageActivity
|
||||
import im.vector.app.features.spaces.share.ShareSpaceBottomSheet
|
||||
import im.vector.app.features.terms.ReviewTermsActivity
|
||||
|
@ -172,6 +173,7 @@ interface ScreenComponent {
|
|||
fun inject(activity: SpaceExploreActivity)
|
||||
fun inject(activity: SpaceManageActivity)
|
||||
fun inject(activity: RoomJoinRuleActivity)
|
||||
fun inject(activity: SpaceLeaveAdvancedActivity)
|
||||
|
||||
/* ==========================================================================================
|
||||
* BottomSheets
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package im.vector.app.features.spaces
|
||||
|
||||
import android.app.Activity
|
||||
import android.graphics.Typeface
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
|
@ -32,11 +33,13 @@ import com.airbnb.mvrx.withState
|
|||
import com.jakewharton.rxbinding3.widget.checkedChanges
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.di.ScreenComponent
|
||||
import im.vector.app.core.extensions.registerStartForActivityResult
|
||||
import im.vector.app.core.extensions.setTextOrHide
|
||||
import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
|
||||
import im.vector.app.core.resources.ColorProvider
|
||||
import im.vector.app.core.utils.styleMatchingText
|
||||
import im.vector.app.databinding.BottomSheetLeaveSpaceBinding
|
||||
import im.vector.app.features.spaces.leave.SpaceLeaveAdvancedActivity
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import me.gujun.android.span.span
|
||||
|
@ -66,6 +69,15 @@ class LeaveSpaceBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetLea
|
|||
|
||||
private val spaceArgs: SpaceBottomSheetSettingsArgs by args()
|
||||
|
||||
private val cherryPickLeaveActivityResult = registerStartForActivityResult { activityResult ->
|
||||
if (activityResult.resultCode == Activity.RESULT_OK) {
|
||||
// nothing actually?
|
||||
} else {
|
||||
// move back to default
|
||||
settingsViewModel.handle(SpaceMenuViewAction.SetAutoLeaveAll)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
views.autoLeaveRadioGroup.checkedChanges()
|
||||
|
@ -80,6 +92,10 @@ class LeaveSpaceBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetLea
|
|||
}
|
||||
views.leaveSelected.id -> {
|
||||
settingsViewModel.handle(SpaceMenuViewAction.SetAutoLeaveSelected)
|
||||
// launch dedicated activity
|
||||
cherryPickLeaveActivityResult.launch(
|
||||
SpaceLeaveAdvancedActivity.newIntent(requireContext(), spaceArgs.spaceId)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -142,16 +158,22 @@ class LeaveSpaceBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetLea
|
|||
views.leaveProgress.isVisible = false
|
||||
}
|
||||
|
||||
when (state.leaveMode) {
|
||||
SpaceMenuState.LeaveMode.LEAVE_ALL -> {
|
||||
views.autoLeaveRadioGroup.check(views.leaveAll.id)
|
||||
}
|
||||
SpaceMenuState.LeaveMode.LEAVE_NONE -> {
|
||||
views.autoLeaveRadioGroup.check(views.leaveNone.id)
|
||||
}
|
||||
SpaceMenuState.LeaveMode.LEAVE_SELECTED -> {
|
||||
views.autoLeaveRadioGroup.check(views.leaveSelected.id)
|
||||
val hasChildren = (spaceSummary.spaceChildren?.size ?: 0) > 0
|
||||
if (hasChildren) {
|
||||
views.autoLeaveRadioGroup.isVisible = true
|
||||
when (state.leaveMode) {
|
||||
SpaceMenuState.LeaveMode.LEAVE_ALL -> {
|
||||
views.autoLeaveRadioGroup.check(views.leaveAll.id)
|
||||
}
|
||||
SpaceMenuState.LeaveMode.LEAVE_NONE -> {
|
||||
views.autoLeaveRadioGroup.check(views.leaveNone.id)
|
||||
}
|
||||
SpaceMenuState.LeaveMode.LEAVE_SELECTED -> {
|
||||
views.autoLeaveRadioGroup.check(views.leaveSelected.id)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
views.autoLeaveRadioGroup.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -78,8 +78,10 @@ class SpaceMenuViewModel @AssistedInject constructor(
|
|||
it.getOrNull()?.let {
|
||||
if (it.membership == Membership.LEAVE) {
|
||||
setState { copy(leavingState = Success(Unit)) }
|
||||
// switch to home?
|
||||
appStateHandler.setCurrentSpace(null, session)
|
||||
if (appStateHandler.safeActiveSpaceId() == initialState.spaceId) {
|
||||
// switch to home?
|
||||
appStateHandler.setCurrentSpace(null, session)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* 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.leave
|
||||
|
||||
import com.airbnb.epoxy.TypedEpoxyController
|
||||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.Success
|
||||
import com.airbnb.mvrx.Uninitialized
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.epoxy.loadingItem
|
||||
import im.vector.app.core.epoxy.noResultItem
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
import im.vector.app.features.spaces.manage.roomSelectionItem
|
||||
import io.reactivex.functions.Predicate
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||
import javax.inject.Inject
|
||||
|
||||
class SelectChildrenController @Inject constructor(
|
||||
val avatarRenderer: AvatarRenderer,
|
||||
val stringProvider: StringProvider
|
||||
) : TypedEpoxyController<SpaceLeaveAdvanceViewState>() {
|
||||
|
||||
interface Listener {
|
||||
fun onItemSelected(roomSummary: RoomSummary)
|
||||
}
|
||||
|
||||
var listener: Listener? = null
|
||||
private val matchFilter = RoomSearchMatchFilter()
|
||||
override fun buildModels(data: SpaceLeaveAdvanceViewState?) {
|
||||
val children = data?.allChildren ?: return
|
||||
val host = this
|
||||
when (children) {
|
||||
Uninitialized -> return
|
||||
is Loading -> {
|
||||
loadingItem {
|
||||
id("loading")
|
||||
}
|
||||
}
|
||||
is Success -> {
|
||||
matchFilter.filter = data.currentFilter
|
||||
val roomList = children.invoke().filter { matchFilter.test(it) }
|
||||
|
||||
if (roomList.isEmpty()) {
|
||||
noResultItem {
|
||||
id("empty")
|
||||
text(host.stringProvider.getString(R.string.no_result_placeholder))
|
||||
}
|
||||
} else {
|
||||
roomList.forEach { item ->
|
||||
roomSelectionItem {
|
||||
id(item.roomId)
|
||||
matrixItem(item.toMatrixItem())
|
||||
avatarRenderer(host.avatarRenderer)
|
||||
selected(data.selectedRooms.contains(item.roomId))
|
||||
itemClickListener {
|
||||
host.listener?.onItemSelected(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
is Fail -> {
|
||||
// errorWithRetryItem {
|
||||
// id("failed_to_load")
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RoomSearchMatchFilter : Predicate<RoomSummary> {
|
||||
var filter: String = ""
|
||||
|
||||
override fun test(roomSummary: RoomSummary): Boolean {
|
||||
if (filter.isEmpty()) {
|
||||
// No filter
|
||||
return true
|
||||
}
|
||||
// if filter is "Jo Do", it should match "John Doe"
|
||||
return filter.split(" ").all {
|
||||
roomSummary.name.contains(it, ignoreCase = true).orFalse()
|
||||
|| roomSummary.topic.contains(it, ignoreCase = true).orFalse()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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.leave
|
||||
|
||||
import im.vector.app.core.platform.VectorViewModelAction
|
||||
|
||||
sealed class SpaceLeaveAdvanceViewAction : VectorViewModelAction {
|
||||
data class ToggleSelection(val roomId: String) : SpaceLeaveAdvanceViewAction()
|
||||
data class UpdateFilter(val filter: String) : SpaceLeaveAdvanceViewAction()
|
||||
object DoLeave : SpaceLeaveAdvanceViewAction()
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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.leave
|
||||
|
||||
import com.airbnb.mvrx.Async
|
||||
import com.airbnb.mvrx.MvRxState
|
||||
import com.airbnb.mvrx.Uninitialized
|
||||
import im.vector.app.features.spaces.SpaceBottomSheetSettingsArgs
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
|
||||
data class SpaceLeaveAdvanceViewState(
|
||||
val spaceId: String,
|
||||
val spaceSummary: RoomSummary? = null,
|
||||
val allChildren: Async<List<RoomSummary>> = Uninitialized,
|
||||
val selectedRooms: List<String> = emptyList(),
|
||||
val currentFilter: String = "",
|
||||
val leaveState: Async<Unit> = Uninitialized
|
||||
) : MvRxState {
|
||||
constructor(args: SpaceBottomSheetSettingsArgs) : this(
|
||||
spaceId = args.spaceId
|
||||
)
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* 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.leave
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.core.view.isGone
|
||||
import androidx.core.view.isVisible
|
||||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.MvRx
|
||||
import com.airbnb.mvrx.Success
|
||||
import com.airbnb.mvrx.viewModel
|
||||
import com.google.android.material.appbar.MaterialToolbar
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.di.ScreenComponent
|
||||
import im.vector.app.core.error.ErrorFormatter
|
||||
import im.vector.app.core.extensions.commitTransaction
|
||||
import im.vector.app.core.extensions.hideKeyboard
|
||||
import im.vector.app.core.platform.ToolbarConfigurable
|
||||
import im.vector.app.core.platform.VectorBaseActivity
|
||||
import im.vector.app.databinding.ActivitySimpleLoadingBinding
|
||||
import im.vector.app.features.spaces.SpaceBottomSheetSettingsArgs
|
||||
import javax.inject.Inject
|
||||
|
||||
class SpaceLeaveAdvancedActivity : VectorBaseActivity<ActivitySimpleLoadingBinding>(),
|
||||
SpaceLeaveAdvancedViewModel.Factory,
|
||||
ToolbarConfigurable {
|
||||
|
||||
override fun getBinding(): ActivitySimpleLoadingBinding = ActivitySimpleLoadingBinding.inflate(layoutInflater)
|
||||
|
||||
val leaveViewModel: SpaceLeaveAdvancedViewModel by viewModel()
|
||||
|
||||
@Inject lateinit var viewModelFactory: SpaceLeaveAdvancedViewModel.Factory
|
||||
@Inject lateinit var errorFormatter: ErrorFormatter
|
||||
|
||||
override fun create(initialState: SpaceLeaveAdvanceViewState) = viewModelFactory.create(initialState)
|
||||
|
||||
override fun injectWith(injector: ScreenComponent) {
|
||||
super.injectWith(injector)
|
||||
injector.inject(this)
|
||||
}
|
||||
|
||||
override fun showWaitingView(text: String?) {
|
||||
hideKeyboard()
|
||||
views.waitingView.waitingStatusText.isGone = views.waitingView.waitingStatusText.text.isNullOrBlank()
|
||||
super.showWaitingView(text)
|
||||
}
|
||||
|
||||
override fun hideWaitingView() {
|
||||
views.waitingView.waitingStatusText.text = null
|
||||
views.waitingView.waitingStatusText.isGone = true
|
||||
views.waitingView.waitingHorizontalProgress.progress = 0
|
||||
views.waitingView.waitingHorizontalProgress.isVisible = false
|
||||
super.hideWaitingView()
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val args = intent?.getParcelableExtra<SpaceBottomSheetSettingsArgs>(MvRx.KEY_ARG)
|
||||
|
||||
if (isFirstCreation()) {
|
||||
val simpleName = SpaceLeaveAdvancedFragment::class.java.simpleName
|
||||
if (supportFragmentManager.findFragmentByTag(simpleName) == null) {
|
||||
supportFragmentManager.commitTransaction {
|
||||
replace(
|
||||
R.id.simpleFragmentContainer,
|
||||
SpaceLeaveAdvancedFragment::class.java,
|
||||
Bundle().apply { this.putParcelable(MvRx.KEY_ARG, args) },
|
||||
simpleName
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun initUiAndData() {
|
||||
super.initUiAndData()
|
||||
waitingView = views.waitingView.waitingView
|
||||
leaveViewModel.subscribe(this) { state ->
|
||||
when (state.leaveState) {
|
||||
is Loading -> {
|
||||
showWaitingView()
|
||||
}
|
||||
is Success -> {
|
||||
setResult(RESULT_OK)
|
||||
finish()
|
||||
}
|
||||
is Fail -> {
|
||||
hideWaitingView()
|
||||
showSnackbar(errorFormatter.toHumanReadable(state.leaveState.error))
|
||||
}
|
||||
else -> {
|
||||
hideWaitingView()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun newIntent(context: Context, spaceId: String): Intent {
|
||||
return Intent(context, SpaceLeaveAdvancedActivity::class.java).apply {
|
||||
putExtra(MvRx.KEY_ARG, SpaceBottomSheetSettingsArgs(spaceId))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun configure(toolbar: MaterialToolbar) {
|
||||
configureToolbar(toolbar)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* 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.leave
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.airbnb.mvrx.activityViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import com.jakewharton.rxbinding3.appcompat.queryTextChanges
|
||||
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.FragmentSpaceLeaveAdvancedBinding
|
||||
import io.reactivex.rxkotlin.subscribeBy
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
class SpaceLeaveAdvancedFragment @Inject constructor(
|
||||
val controller: SelectChildrenController
|
||||
) : VectorBaseFragment<FragmentSpaceLeaveAdvancedBinding>(),
|
||||
OnBackPressed,
|
||||
SelectChildrenController.Listener {
|
||||
|
||||
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?) =
|
||||
FragmentSpaceLeaveAdvancedBinding.inflate(layoutInflater, container, false)
|
||||
|
||||
val viewModel: SpaceLeaveAdvancedViewModel by activityViewModel()
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setupToolbar(views.toolbar)
|
||||
controller.listener = this
|
||||
views.roomList.configureWith(controller)
|
||||
views.spaceLeaveCancel.debouncedClicks { requireActivity().finish() }
|
||||
|
||||
views.spaceLeaveButton.debouncedClicks {
|
||||
viewModel.handle(SpaceLeaveAdvanceViewAction.DoLeave)
|
||||
}
|
||||
|
||||
views.publicRoomsFilter.queryTextChanges()
|
||||
.debounce(100, TimeUnit.MILLISECONDS)
|
||||
.subscribeBy {
|
||||
viewModel.handle(SpaceLeaveAdvanceViewAction.UpdateFilter(it.toString()))
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
controller.listener = null
|
||||
views.roomList.cleanup()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun invalidate() = withState(viewModel) { state ->
|
||||
super.invalidate()
|
||||
controller.setData(state)
|
||||
}
|
||||
|
||||
override fun onItemSelected(roomSummary: RoomSummary) {
|
||||
viewModel.handle(SpaceLeaveAdvanceViewAction.ToggleSelection(roomSummary.roomId))
|
||||
}
|
||||
|
||||
override fun onBackPressed(toolbarButton: Boolean): Boolean {
|
||||
requireActivity().finish()
|
||||
return true
|
||||
}
|
||||
}
|
|
@ -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.leave
|
||||
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.airbnb.mvrx.ActivityViewModelContext
|
||||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.FragmentViewModelContext
|
||||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||
import com.airbnb.mvrx.Success
|
||||
import com.airbnb.mvrx.ViewModelContext
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import im.vector.app.AppStateHandler
|
||||
import im.vector.app.core.platform.EmptyViewEvents
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.android.sdk.api.query.ActiveSpaceFilter
|
||||
import org.matrix.android.sdk.api.query.RoomCategoryFilter
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
||||
import org.matrix.android.sdk.rx.rx
|
||||
import timber.log.Timber
|
||||
|
||||
class SpaceLeaveAdvancedViewModel @AssistedInject constructor(
|
||||
@Assisted val initialState: SpaceLeaveAdvanceViewState,
|
||||
private val session: Session,
|
||||
private val appStateHandler: AppStateHandler
|
||||
) : VectorViewModel<SpaceLeaveAdvanceViewState, SpaceLeaveAdvanceViewAction, EmptyViewEvents>(initialState) {
|
||||
|
||||
override fun handle(action: SpaceLeaveAdvanceViewAction) = withState { state ->
|
||||
when (action) {
|
||||
is SpaceLeaveAdvanceViewAction.ToggleSelection -> {
|
||||
val existing = state.selectedRooms.toMutableList()
|
||||
if (existing.contains(action.roomId)) {
|
||||
existing.remove(action.roomId)
|
||||
} else {
|
||||
existing.add(action.roomId)
|
||||
}
|
||||
setState {
|
||||
copy(
|
||||
selectedRooms = existing.toList()
|
||||
)
|
||||
}
|
||||
}
|
||||
is SpaceLeaveAdvanceViewAction.UpdateFilter -> {
|
||||
setState { copy(currentFilter = action.filter) }
|
||||
}
|
||||
SpaceLeaveAdvanceViewAction.DoLeave -> {
|
||||
setState { copy(leaveState = Loading()) }
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
try {
|
||||
state.selectedRooms.forEach {
|
||||
session.getRoom(it)?.leave(null)
|
||||
}
|
||||
} catch (failure: Throwable) {
|
||||
// silently ignore?
|
||||
Timber.e(failure, "Fail to leave sub rooms/spaces")
|
||||
}
|
||||
session.getRoom(initialState.spaceId)?.leave(null)
|
||||
// We observe the membership and to dismiss when we have remote echo of leaving
|
||||
} catch (failure: Throwable) {
|
||||
setState { copy(leaveState = Fail(failure)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
val spaceSummary = session.getRoomSummary(initialState.spaceId)
|
||||
setState { copy(spaceSummary = spaceSummary) }
|
||||
session.getRoom(initialState.spaceId)?.let { room ->
|
||||
room.rx().liveRoomSummary().subscribe {
|
||||
it.getOrNull()?.let {
|
||||
if (it.membership == Membership.LEAVE) {
|
||||
setState { copy(leaveState = Success(Unit)) }
|
||||
if (appStateHandler.safeActiveSpaceId() == initialState.spaceId) {
|
||||
// switch to home?
|
||||
appStateHandler.setCurrentSpace(null, session)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
viewModelScope.launch {
|
||||
val children = session.getRoomSummaries(
|
||||
roomSummaryQueryParams {
|
||||
includeType = null
|
||||
memberships = listOf(Membership.JOIN)
|
||||
activeSpaceFilter = ActiveSpaceFilter.ActiveSpace(initialState.spaceId)
|
||||
roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS
|
||||
}
|
||||
)
|
||||
|
||||
setState {
|
||||
copy(allChildren = Success(children))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(initialState: SpaceLeaveAdvanceViewState): SpaceLeaveAdvancedViewModel
|
||||
}
|
||||
|
||||
companion object : MvRxViewModelFactory<SpaceLeaveAdvancedViewModel, SpaceLeaveAdvanceViewState> {
|
||||
override fun create(viewModelContext: ViewModelContext, state: SpaceLeaveAdvanceViewState): SpaceLeaveAdvancedViewModel? {
|
||||
val factory = when (viewModelContext) {
|
||||
is FragmentViewModelContext -> viewModelContext.fragment as? Factory
|
||||
is ActivityViewModelContext -> viewModelContext.activity as? Factory
|
||||
}
|
||||
return factory?.create(state) ?: error("You should let your activity/fragment implements Factory interface")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -30,21 +30,21 @@
|
|||
|
||||
<RadioButton
|
||||
android:id="@+id/leave_all"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/leave_all_rooms_and_spaces"
|
||||
tools:checked="true" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/leave_none"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minWidth="180dp"
|
||||
android:text="@string/dont_leave_any" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/leave_selected"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minWidth="180dp"
|
||||
android:text="@string/leave_specific_ones" />
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/coordinatorLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/roomList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?android:colorBackground"
|
||||
android:overScrollMode="always"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
tools:listitem="@layout/item_room_to_add_in_space" />
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<!-- minHeight="0dp" is important to collapse on scroll -->
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:minHeight="0dp"
|
||||
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap|enterAlways">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical|start"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/appBarTitle"
|
||||
style="@style/Widget.Vector.TextView.HeadlineMedium"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:ellipsize="end"
|
||||
android:gravity="start|center"
|
||||
android:maxLines="1"
|
||||
android:text="@string/pick_tings_to_leave"
|
||||
android:textColor="?vctr_content_primary"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.appbar.MaterialToolbar>
|
||||
|
||||
|
||||
<androidx.appcompat.widget.SearchView
|
||||
android:id="@+id/publicRoomsFilter"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/addRoomToSpaceToolbar"
|
||||
app:queryHint="@string/search_hint_room_name" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/spacePreviewButtonBar"
|
||||
app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="?vctr_system"
|
||||
android:elevation="2dp"
|
||||
android:orientation="horizontal"
|
||||
android:padding="8dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/spaceLeaveCancel"
|
||||
style="@style/Widget.Vector.Button.Text"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/cancel" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/spaceLeaveButton"
|
||||
style="@style/Widget.Vector.Button.Destructive"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/leave_space" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -3487,6 +3487,7 @@
|
|||
<string name="you_will_leave_all_in">You will leave all rooms and spaces in %s.</string>
|
||||
<string name="dont_leave_any">Don’t leave any rooms and spaces</string>
|
||||
<string name="leave_specific_ones">Leave specific rooms and spaces</string>
|
||||
<string name="pick_tings_to_leave">Pick things to leave</string>
|
||||
|
||||
<string name="space_add_existing_rooms">Add existing rooms and space</string>
|
||||
<string name="space_add_rooms">Add rooms</string>
|
||||
|
|
Loading…
Reference in New Issue