Merge pull request #638 from vector-im/feature/filter
Fix 2 issues with share Activity: filter and room lists
This commit is contained in:
commit
e52f0faaa7
@ -42,7 +42,7 @@ import javax.inject.Singleton
|
||||
@Singleton
|
||||
class AppStateHandler @Inject constructor(
|
||||
private val sessionObservableStore: ActiveSessionObservableStore,
|
||||
private val homeRoomListStore: HomeRoomListObservableStore,
|
||||
private val homeRoomListObservableStore: HomeRoomListObservableStore,
|
||||
private val selectedGroupStore: SelectedGroupStore) : LifecycleObserver {
|
||||
|
||||
private val compositeDisposable = CompositeDisposable()
|
||||
@ -92,7 +92,7 @@ class AppStateHandler @Inject constructor(
|
||||
}
|
||||
)
|
||||
.subscribe {
|
||||
homeRoomListStore.post(it)
|
||||
homeRoomListObservableStore.post(it)
|
||||
}
|
||||
.addTo(compositeDisposable)
|
||||
}
|
||||
|
@ -41,11 +41,12 @@ import im.vector.riotx.features.home.createdirect.CreateDirectRoomKnownUsersFrag
|
||||
import im.vector.riotx.features.home.group.GroupListFragment
|
||||
import im.vector.riotx.features.home.room.detail.RoomDetailFragment
|
||||
import im.vector.riotx.features.home.room.detail.readreceipts.DisplayReadReceiptsBottomSheet
|
||||
import im.vector.riotx.features.home.room.detail.timeline.action.*
|
||||
import im.vector.riotx.features.home.room.detail.timeline.action.MessageActionsBottomSheet
|
||||
import im.vector.riotx.features.home.room.detail.timeline.edithistory.ViewEditHistoryBottomSheet
|
||||
import im.vector.riotx.features.home.room.detail.timeline.reactions.ViewReactionsBottomSheet
|
||||
import im.vector.riotx.features.home.room.filtered.FilteredRoomsActivity
|
||||
import im.vector.riotx.features.home.room.list.RoomListFragment
|
||||
import im.vector.riotx.features.home.room.list.RoomListModule
|
||||
import im.vector.riotx.features.invite.VectorInviteView
|
||||
import im.vector.riotx.features.link.LinkHandlerActivity
|
||||
import im.vector.riotx.features.login.LoginActivity
|
||||
@ -70,7 +71,17 @@ import im.vector.riotx.features.settings.push.PushGatewaysFragment
|
||||
import im.vector.riotx.features.share.IncomingShareActivity
|
||||
import im.vector.riotx.features.ui.UiStateRepository
|
||||
|
||||
@Component(dependencies = [VectorComponent::class], modules = [AssistedInjectModule::class, ViewModelModule::class, HomeModule::class])
|
||||
@Component(
|
||||
dependencies = [
|
||||
VectorComponent::class
|
||||
],
|
||||
modules = [
|
||||
AssistedInjectModule::class,
|
||||
ViewModelModule::class,
|
||||
HomeModule::class,
|
||||
RoomListModule::class
|
||||
]
|
||||
)
|
||||
@ScreenScope
|
||||
interface ScreenComponent {
|
||||
|
||||
|
@ -23,6 +23,7 @@ import dagger.Component
|
||||
import im.vector.matrix.android.api.Matrix
|
||||
import im.vector.matrix.android.api.auth.Authenticator
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.riotx.ActiveSessionObservableStore
|
||||
import im.vector.riotx.EmojiCompatFontProvider
|
||||
import im.vector.riotx.EmojiCompatWrapper
|
||||
import im.vector.riotx.VectorApplication
|
||||
@ -42,6 +43,7 @@ import im.vector.riotx.features.rageshake.VectorFileLogger
|
||||
import im.vector.riotx.features.rageshake.VectorUncaughtExceptionHandler
|
||||
import im.vector.riotx.features.session.SessionListener
|
||||
import im.vector.riotx.features.settings.VectorPreferences
|
||||
import im.vector.riotx.features.share.ShareRoomListObservableStore
|
||||
import im.vector.riotx.features.ui.UiStateRepository
|
||||
import javax.inject.Singleton
|
||||
|
||||
@ -85,8 +87,12 @@ interface VectorComponent {
|
||||
|
||||
fun homeRoomListObservableStore(): HomeRoomListObservableStore
|
||||
|
||||
fun shareRoomListObservableStore(): ShareRoomListObservableStore
|
||||
|
||||
fun selectedGroupStore(): SelectedGroupStore
|
||||
|
||||
fun activeSessionObservableStore(): ActiveSessionObservableStore
|
||||
|
||||
fun incomingVerificationRequestHandler(): IncomingVerificationRequestHandler
|
||||
|
||||
fun incomingKeyRequestHandler(): KeyRequestHandler
|
||||
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2019 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.features.home.room.list
|
||||
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
|
||||
@Module
|
||||
abstract class RoomListModule {
|
||||
|
||||
@Binds
|
||||
abstract fun providesRoomListViewModelFactory(roomListViewModelFactory: RoomListViewModelFactory): RoomListViewModel.Factory
|
||||
}
|
@ -21,8 +21,6 @@ import androidx.lifecycle.MutableLiveData
|
||||
import com.airbnb.mvrx.FragmentViewModelContext
|
||||
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||
import com.airbnb.mvrx.ViewModelContext
|
||||
import com.squareup.inject.assisted.Assisted
|
||||
import com.squareup.inject.assisted.AssistedInject
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.api.session.room.model.Membership
|
||||
@ -31,18 +29,18 @@ import im.vector.matrix.android.api.session.room.model.tag.RoomTag
|
||||
import im.vector.riotx.core.extensions.postLiveEvent
|
||||
import im.vector.riotx.core.platform.VectorViewModel
|
||||
import im.vector.riotx.core.utils.LiveEvent
|
||||
import im.vector.riotx.features.home.HomeRoomListObservableStore
|
||||
import im.vector.riotx.core.utils.RxStore
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
class RoomListViewModel @AssistedInject constructor(@Assisted initialState: RoomListViewState,
|
||||
private val session: Session,
|
||||
private val homeRoomListObservableSource: HomeRoomListObservableStore,
|
||||
private val alphabeticalRoomComparator: AlphabeticalRoomComparator,
|
||||
private val chronologicalRoomComparator: ChronologicalRoomComparator)
|
||||
class RoomListViewModel @Inject constructor(initialState: RoomListViewState,
|
||||
private val session: Session,
|
||||
private val roomSummariesStore: RxStore<List<RoomSummary>>,
|
||||
private val alphabeticalRoomComparator: AlphabeticalRoomComparator,
|
||||
private val chronologicalRoomComparator: ChronologicalRoomComparator)
|
||||
: VectorViewModel<RoomListViewState>(initialState) {
|
||||
|
||||
@AssistedInject.Factory
|
||||
interface Factory {
|
||||
fun create(initialState: RoomListViewState): RoomListViewModel
|
||||
}
|
||||
@ -101,7 +99,7 @@ class RoomListViewModel @AssistedInject constructor(@Assisted initialState: Room
|
||||
}
|
||||
|
||||
private fun observeRoomSummaries() {
|
||||
homeRoomListObservableSource
|
||||
roomSummariesStore
|
||||
.observe()
|
||||
.observeOn(Schedulers.computation())
|
||||
.map {
|
||||
@ -111,7 +109,7 @@ class RoomListViewModel @AssistedInject constructor(@Assisted initialState: Room
|
||||
copy(asyncRooms = asyncRooms)
|
||||
}
|
||||
|
||||
homeRoomListObservableSource
|
||||
roomSummariesStore
|
||||
.observe()
|
||||
.observeOn(Schedulers.computation())
|
||||
.map { buildRoomSummaries(it) }
|
||||
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2019 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.features.home.room.list
|
||||
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.riotx.features.home.HomeRoomListObservableStore
|
||||
import im.vector.riotx.features.share.ShareRoomListObservableStore
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Provider
|
||||
|
||||
class RoomListViewModelFactory @Inject constructor(private val session: Provider<Session>,
|
||||
private val homeRoomListObservableStore: Provider<HomeRoomListObservableStore>,
|
||||
private val shareRoomListObservableStore: Provider<ShareRoomListObservableStore>,
|
||||
private val alphabeticalRoomComparator: Provider<AlphabeticalRoomComparator>,
|
||||
private val chronologicalRoomComparator: Provider<ChronologicalRoomComparator>) : RoomListViewModel.Factory {
|
||||
|
||||
override fun create(initialState: RoomListViewState): RoomListViewModel {
|
||||
return RoomListViewModel(
|
||||
initialState,
|
||||
session.get(),
|
||||
if (initialState.displayMode == RoomListFragment.DisplayMode.SHARE) shareRoomListObservableStore.get() else homeRoomListObservableStore.get(),
|
||||
alphabeticalRoomComparator.get(),
|
||||
chronologicalRoomComparator.get())
|
||||
}
|
||||
}
|
@ -20,6 +20,8 @@ import androidx.annotation.StringRes
|
||||
import com.airbnb.epoxy.EpoxyController
|
||||
import im.vector.matrix.android.api.session.room.model.Membership
|
||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.epoxy.noResultItem
|
||||
import im.vector.riotx.core.resources.StringProvider
|
||||
import im.vector.riotx.features.home.room.filtered.FilteredRoomFooterItem
|
||||
import im.vector.riotx.features.home.room.filtered.filteredRoomFooterItem
|
||||
@ -47,24 +49,28 @@ class RoomSummaryController @Inject constructor(private val stringProvider: Stri
|
||||
|
||||
override fun buildModels() {
|
||||
val nonNullViewState = viewState ?: return
|
||||
if (nonNullViewState.displayMode == RoomListFragment.DisplayMode.FILTERED) {
|
||||
buildFilteredRooms(nonNullViewState)
|
||||
} else {
|
||||
val roomSummaries = nonNullViewState.asyncFilteredRooms()
|
||||
roomSummaries?.forEach { (category, summaries) ->
|
||||
if (summaries.isEmpty()) {
|
||||
return@forEach
|
||||
} else {
|
||||
val isExpanded = nonNullViewState.isCategoryExpanded(category)
|
||||
buildRoomCategory(nonNullViewState, summaries, category.titleRes, nonNullViewState.isCategoryExpanded(category)) {
|
||||
listener?.onToggleRoomCategory(category)
|
||||
}
|
||||
if (isExpanded) {
|
||||
buildRoomModels(summaries,
|
||||
nonNullViewState.joiningRoomsIds,
|
||||
nonNullViewState.joiningErrorRoomsIds,
|
||||
nonNullViewState.rejectingRoomsIds,
|
||||
nonNullViewState.rejectingErrorRoomsIds)
|
||||
when (nonNullViewState.displayMode) {
|
||||
RoomListFragment.DisplayMode.FILTERED,
|
||||
RoomListFragment.DisplayMode.SHARE -> {
|
||||
buildFilteredRooms(nonNullViewState)
|
||||
}
|
||||
else -> {
|
||||
val roomSummaries = nonNullViewState.asyncFilteredRooms()
|
||||
roomSummaries?.forEach { (category, summaries) ->
|
||||
if (summaries.isEmpty()) {
|
||||
return@forEach
|
||||
} else {
|
||||
val isExpanded = nonNullViewState.isCategoryExpanded(category)
|
||||
buildRoomCategory(nonNullViewState, summaries, category.titleRes, nonNullViewState.isCategoryExpanded(category)) {
|
||||
listener?.onToggleRoomCategory(category)
|
||||
}
|
||||
if (isExpanded) {
|
||||
buildRoomModels(summaries,
|
||||
nonNullViewState.joiningRoomsIds,
|
||||
nonNullViewState.joiningErrorRoomsIds,
|
||||
nonNullViewState.rejectingRoomsIds,
|
||||
nonNullViewState.rejectingErrorRoomsIds)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -80,12 +86,15 @@ class RoomSummaryController @Inject constructor(private val stringProvider: Stri
|
||||
.filter { it.membership == Membership.JOIN && roomListNameFilter.test(it) }
|
||||
|
||||
buildRoomModels(filteredSummaries,
|
||||
viewState.joiningRoomsIds,
|
||||
viewState.joiningErrorRoomsIds,
|
||||
viewState.rejectingRoomsIds,
|
||||
viewState.rejectingErrorRoomsIds)
|
||||
viewState.joiningRoomsIds,
|
||||
viewState.joiningErrorRoomsIds,
|
||||
viewState.rejectingRoomsIds,
|
||||
viewState.rejectingErrorRoomsIds)
|
||||
|
||||
addFilterFooter(viewState)
|
||||
when {
|
||||
viewState.displayMode == RoomListFragment.DisplayMode.FILTERED -> addFilterFooter(viewState)
|
||||
filteredSummaries.isEmpty() -> addEmptyFooter()
|
||||
}
|
||||
}
|
||||
|
||||
private fun addFilterFooter(viewState: RoomListViewState) {
|
||||
@ -96,6 +105,13 @@ class RoomSummaryController @Inject constructor(private val stringProvider: Stri
|
||||
}
|
||||
}
|
||||
|
||||
private fun addEmptyFooter() {
|
||||
noResultItem {
|
||||
id("no_result")
|
||||
text(stringProvider.getString(R.string.no_result_placeholder))
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildRoomCategory(viewState: RoomListViewState,
|
||||
summaries: List<RoomSummary>,
|
||||
@StringRes titleRes: Int,
|
||||
|
@ -20,6 +20,8 @@ import android.content.ClipDescription
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import com.airbnb.mvrx.viewModel
|
||||
import com.kbeanie.multipicker.utils.IntentUtils
|
||||
import im.vector.matrix.android.api.session.content.ContentAttachmentData
|
||||
import im.vector.riotx.R
|
||||
@ -39,8 +41,10 @@ class IncomingShareActivity :
|
||||
VectorBaseActivity(), AttachmentsHelper.Callback {
|
||||
|
||||
@Inject lateinit var sessionHolder: ActiveSessionHolder
|
||||
private lateinit var roomListFragment: RoomListFragment
|
||||
@Inject lateinit var incomingShareViewModelFactory: IncomingShareViewModel.Factory
|
||||
private var roomListFragment: RoomListFragment? = null
|
||||
private lateinit var attachmentsHelper: AttachmentsHelper
|
||||
private val incomingShareViewModel: IncomingShareViewModel by viewModel()
|
||||
|
||||
override fun getLayoutRes(): Int {
|
||||
return R.layout.activity_incoming_share
|
||||
@ -77,12 +81,23 @@ class IncomingShareActivity :
|
||||
} else {
|
||||
cannotManageShare()
|
||||
}
|
||||
|
||||
incomingShareSearchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
||||
override fun onQueryTextSubmit(query: String): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onQueryTextChange(newText: String): Boolean {
|
||||
roomListFragment?.filterRoomsWith(newText)
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onContentAttachmentsReady(attachments: List<ContentAttachmentData>) {
|
||||
val roomListParams = RoomListParams(RoomListFragment.DisplayMode.SHARE, sharedData = SharedData.Attachments(attachments))
|
||||
roomListFragment = RoomListFragment.newInstance(roomListParams)
|
||||
replaceFragment(roomListFragment, R.id.shareRoomListFragmentContainer)
|
||||
.also { replaceFragment(it, R.id.shareRoomListFragmentContainer) }
|
||||
}
|
||||
|
||||
override fun onAttachmentsProcessFailed() {
|
||||
@ -102,7 +117,7 @@ class IncomingShareActivity :
|
||||
} else {
|
||||
val roomListParams = RoomListParams(RoomListFragment.DisplayMode.SHARE, sharedData = SharedData.Text(sharedText))
|
||||
roomListFragment = RoomListFragment.newInstance(roomListParams)
|
||||
replaceFragment(roomListFragment, R.id.shareRoomListFragmentContainer)
|
||||
.also { replaceFragment(it, R.id.shareRoomListFragmentContainer) }
|
||||
true
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2019 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.features.share
|
||||
|
||||
import com.airbnb.mvrx.ActivityViewModelContext
|
||||
import com.airbnb.mvrx.MvRxState
|
||||
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||
import com.airbnb.mvrx.ViewModelContext
|
||||
import com.squareup.inject.assisted.Assisted
|
||||
import com.squareup.inject.assisted.AssistedInject
|
||||
import im.vector.matrix.rx.rx
|
||||
import im.vector.riotx.ActiveSessionObservableStore
|
||||
import im.vector.riotx.core.platform.VectorViewModel
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
data class IncomingShareState(private val dummy: Boolean = false) : MvRxState
|
||||
|
||||
/**
|
||||
* View model used to observe the room list and post update to the ShareRoomListObservableStore
|
||||
*/
|
||||
class IncomingShareViewModel @AssistedInject constructor(@Assisted initialState: IncomingShareState,
|
||||
private val sessionObservableStore: ActiveSessionObservableStore,
|
||||
private val shareRoomListObservableStore: ShareRoomListObservableStore)
|
||||
: VectorViewModel<IncomingShareState>(initialState) {
|
||||
|
||||
@AssistedInject.Factory
|
||||
interface Factory {
|
||||
fun create(initialState: IncomingShareState): IncomingShareViewModel
|
||||
}
|
||||
|
||||
companion object : MvRxViewModelFactory<IncomingShareViewModel, IncomingShareState> {
|
||||
|
||||
@JvmStatic
|
||||
override fun create(viewModelContext: ViewModelContext, state: IncomingShareState): IncomingShareViewModel? {
|
||||
val activity: IncomingShareActivity = (viewModelContext as ActivityViewModelContext).activity()
|
||||
return activity.incomingShareViewModelFactory.create(state)
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
observeRoomSummaries()
|
||||
}
|
||||
|
||||
private fun observeRoomSummaries() {
|
||||
sessionObservableStore.observe()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.switchMap {
|
||||
it.orNull()?.rx()?.liveRoomSummaries()
|
||||
?: Observable.just(emptyList())
|
||||
}
|
||||
.throttleLast(300, TimeUnit.MILLISECONDS)
|
||||
.subscribe {
|
||||
shareRoomListObservableStore.post(it)
|
||||
}
|
||||
.disposeOnClear()
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2019 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.features.share
|
||||
|
||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||
import im.vector.riotx.core.utils.RxStore
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class ShareRoomListObservableStore @Inject constructor() : RxStore<List<RoomSummary>>()
|
Loading…
x
Reference in New Issue
Block a user