mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-23 09:56:00 +03:00
Filter rooms
This commit is contained in:
parent
fc1c0caea3
commit
3c25088243
21 changed files with 390 additions and 43 deletions
|
@ -60,6 +60,7 @@
|
|||
android:label="@string/title_activity_emoji_reaction_picker" />
|
||||
<activity android:name=".features.roomdirectory.RoomDirectoryActivity" />
|
||||
<activity android:name=".features.roomdirectory.roompreview.RoomPreviewActivity" />
|
||||
<activity android:name=".features.home.room.filtered.FilteredRoomsActivity" />
|
||||
<activity android:name=".features.home.room.detail.RoomDetailActivity" />
|
||||
<activity android:name=".features.debug.DebugMenuActivity" />
|
||||
|
||||
|
|
|
@ -32,10 +32,14 @@ import im.vector.riotx.features.crypto.keysbackup.setup.KeysBackupSetupStep1Frag
|
|||
import im.vector.riotx.features.crypto.keysbackup.setup.KeysBackupSetupStep2Fragment
|
||||
import im.vector.riotx.features.crypto.keysbackup.setup.KeysBackupSetupStep3Fragment
|
||||
import im.vector.riotx.features.crypto.verification.SASVerificationIncomingFragment
|
||||
import im.vector.riotx.features.home.*
|
||||
import im.vector.riotx.features.home.HomeActivity
|
||||
import im.vector.riotx.features.home.HomeDetailFragment
|
||||
import im.vector.riotx.features.home.HomeDrawerFragment
|
||||
import im.vector.riotx.features.home.HomeModule
|
||||
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.timeline.action.*
|
||||
import im.vector.riotx.features.home.room.filtered.FilteredRoomsActivity
|
||||
import im.vector.riotx.features.home.room.list.RoomListFragment
|
||||
import im.vector.riotx.features.invite.VectorInviteView
|
||||
import im.vector.riotx.features.login.LoginActivity
|
||||
|
@ -130,6 +134,8 @@ interface ScreenComponent {
|
|||
|
||||
fun inject(imageMediaViewerActivity: ImageMediaViewerActivity)
|
||||
|
||||
fun inject(filteredRoomsActivity: FilteredRoomsActivity)
|
||||
|
||||
fun inject(vectorInviteView: VectorInviteView)
|
||||
|
||||
fun inject(videoMediaViewerActivity: VideoMediaViewerActivity)
|
||||
|
|
|
@ -23,8 +23,8 @@ fun AppCompatActivity.addFragment(fragment: Fragment, frameId: Int) {
|
|||
supportFragmentManager.inTransaction { add(frameId, fragment) }
|
||||
}
|
||||
|
||||
fun AppCompatActivity.replaceFragment(fragment: Fragment, frameId: Int) {
|
||||
supportFragmentManager.inTransaction { replace(frameId, fragment) }
|
||||
fun AppCompatActivity.replaceFragment(fragment: Fragment, frameId: Int, tag: String? = null) {
|
||||
supportFragmentManager.inTransaction { replace(frameId, fragment, tag) }
|
||||
}
|
||||
|
||||
fun AppCompatActivity.addFragmentToBackstack(fragment: Fragment, frameId: Int, tag: String? = null) {
|
||||
|
|
|
@ -41,6 +41,7 @@ import im.vector.riotx.core.platform.ToolbarConfigurable
|
|||
import im.vector.riotx.core.platform.VectorBaseActivity
|
||||
import im.vector.riotx.core.pushers.PushersManager
|
||||
import im.vector.riotx.features.disclaimer.showDisclaimerDialog
|
||||
import im.vector.riotx.features.navigation.Navigator
|
||||
import im.vector.riotx.features.notifications.NotificationDrawerManager
|
||||
import im.vector.riotx.features.rageshake.VectorUncaughtExceptionHandler
|
||||
import im.vector.riotx.features.workers.signout.SignOutViewModel
|
||||
|
@ -64,6 +65,7 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable {
|
|||
@Inject lateinit var activeSessionHolder: ActiveSessionHolder
|
||||
@Inject lateinit var homeActivityViewModelFactory: HomeActivityViewModel.Factory
|
||||
@Inject lateinit var homeNavigator: HomeNavigator
|
||||
@Inject lateinit var navigator: Navigator
|
||||
@Inject lateinit var vectorUncaughtExceptionHandler: VectorUncaughtExceptionHandler
|
||||
@Inject lateinit var pushManager: PushersManager
|
||||
@Inject lateinit var notificationDrawerManager: NotificationDrawerManager
|
||||
|
@ -192,6 +194,10 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable {
|
|||
bugReporter.openBugReportScreen(this, false)
|
||||
return true
|
||||
}
|
||||
R.id.menu_home_filter -> {
|
||||
navigator.openRoomsFiltering(this)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
|
|
|
@ -35,7 +35,7 @@ class RoomDetailActivity : VectorBaseActivity(), ToolbarConfigurable {
|
|||
super.onCreate(savedInstanceState)
|
||||
if (isFirstCreation()) {
|
||||
val roomDetailArgs: RoomDetailArgs = intent?.extras?.getParcelable(EXTRA_ROOM_DETAIL_ARGS)
|
||||
?: return
|
||||
?: return
|
||||
val roomDetailFragment = RoomDetailFragment.newInstance(roomDetailArgs)
|
||||
replaceFragment(roomDetailFragment, R.id.roomDetailContainer)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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.filtered
|
||||
|
||||
import android.widget.Button
|
||||
import com.airbnb.epoxy.EpoxyAttribute
|
||||
import com.airbnb.epoxy.EpoxyModelClass
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.epoxy.VectorEpoxyHolder
|
||||
import im.vector.riotx.core.epoxy.VectorEpoxyModel
|
||||
import im.vector.riotx.features.home.room.list.widget.FabMenuView
|
||||
|
||||
@EpoxyModelClass(layout = R.layout.item_room_filter_footer)
|
||||
abstract class FilteredRoomFooterItem : VectorEpoxyModel<FilteredRoomFooterItem.Holder>() {
|
||||
|
||||
@EpoxyAttribute
|
||||
var listener: FilteredRoomFooterItemListener? = null
|
||||
|
||||
override fun bind(holder: Holder) {
|
||||
holder.createRoomButton.setOnClickListener { listener?.createRoom() }
|
||||
holder.createDirectChat.setOnClickListener { listener?.createDirectChat() }
|
||||
holder.openRoomDirectory.setOnClickListener { listener?.openRoomDirectory() }
|
||||
}
|
||||
|
||||
class Holder : VectorEpoxyHolder() {
|
||||
val createRoomButton by bind<Button>(R.id.roomFilterFooterCreateRoom)
|
||||
val createDirectChat by bind<Button>(R.id.roomFilterFooterCreateDirect)
|
||||
val openRoomDirectory by bind<Button>(R.id.roomFilterFooterOpenRoomDirectory)
|
||||
}
|
||||
|
||||
interface FilteredRoomFooterItemListener : FabMenuView.Listener {
|
||||
fun createRoom()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* 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.filtered
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.di.ScreenComponent
|
||||
import im.vector.riotx.core.extensions.replaceFragment
|
||||
import im.vector.riotx.core.platform.ToolbarConfigurable
|
||||
import im.vector.riotx.core.platform.VectorBaseActivity
|
||||
import im.vector.riotx.features.home.room.list.RoomListFragment
|
||||
import im.vector.riotx.features.home.room.list.RoomListParams
|
||||
import kotlinx.android.synthetic.main.activity_filtered_rooms.*
|
||||
|
||||
class FilteredRoomsActivity : VectorBaseActivity(), ToolbarConfigurable {
|
||||
|
||||
private lateinit var roomListFragment: RoomListFragment
|
||||
|
||||
override fun getLayoutRes(): Int {
|
||||
return R.layout.activity_filtered_rooms
|
||||
}
|
||||
|
||||
override fun injectWith(injector: ScreenComponent) {
|
||||
injector.inject(this)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
if (isFirstCreation()) {
|
||||
roomListFragment = RoomListFragment.newInstance(RoomListParams(RoomListFragment.DisplayMode.FILTERED))
|
||||
replaceFragment(roomListFragment, R.id.filteredRoomsFragmentContainer, FRAGMENT_TAG)
|
||||
} else {
|
||||
roomListFragment = supportFragmentManager.findFragmentByTag(FRAGMENT_TAG) as RoomListFragment
|
||||
}
|
||||
|
||||
filteredRoomsSearchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
||||
override fun onQueryTextSubmit(query: String): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onQueryTextChange(newText: String): Boolean {
|
||||
// TODO Create a viewModel and remove this public fun
|
||||
roomListFragment.filterRoomsWith(newText)
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
// Open the keyboard immediately
|
||||
filteredRoomsSearchView.requestFocus()
|
||||
}
|
||||
|
||||
override fun configure(toolbar: Toolbar) {
|
||||
configureToolbar(toolbar)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val FRAGMENT_TAG = "RoomListFragment"
|
||||
|
||||
fun newIntent(context: Context): Intent {
|
||||
return Intent(context, FilteredRoomsActivity::class.java)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,4 +28,6 @@ sealed class RoomListActions {
|
|||
|
||||
data class RejectInvitation(val roomSummary: RoomSummary) : RoomListActions()
|
||||
|
||||
data class FilterWith(val filter: String) : RoomListActions()
|
||||
|
||||
}
|
|
@ -27,9 +27,10 @@ class RoomListDisplayModeFilter(private val displayMode: RoomListFragment.Displa
|
|||
return false
|
||||
}
|
||||
return when (displayMode) {
|
||||
RoomListFragment.DisplayMode.HOME -> roomSummary.notificationCount > 0 || roomSummary.membership == Membership.INVITE
|
||||
RoomListFragment.DisplayMode.PEOPLE -> roomSummary.isDirect && roomSummary.membership == Membership.JOIN
|
||||
RoomListFragment.DisplayMode.ROOMS -> !roomSummary.isDirect && roomSummary.membership == Membership.JOIN
|
||||
RoomListFragment.DisplayMode.HOME -> roomSummary.notificationCount > 0 || roomSummary.membership == Membership.INVITE
|
||||
RoomListFragment.DisplayMode.PEOPLE -> roomSummary.isDirect && roomSummary.membership == Membership.JOIN
|
||||
RoomListFragment.DisplayMode.ROOMS -> !roomSummary.isDirect && roomSummary.membership == Membership.JOIN
|
||||
RoomListFragment.DisplayMode.FILTERED -> roomSummary.membership == Membership.JOIN
|
||||
}
|
||||
}
|
||||
}
|
|
@ -53,7 +53,8 @@ class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Listener, O
|
|||
enum class DisplayMode(@StringRes val titleRes: Int) {
|
||||
HOME(R.string.bottom_action_home),
|
||||
PEOPLE(R.string.bottom_action_people_x),
|
||||
ROOMS(R.string.bottom_action_rooms)
|
||||
ROOMS(R.string.bottom_action_rooms),
|
||||
FILTERED(/* Not used */ R.string.bottom_action_rooms)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -97,9 +98,10 @@ class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Listener, O
|
|||
|
||||
private fun setupCreateRoomButton() {
|
||||
when (roomListParams.displayMode) {
|
||||
DisplayMode.HOME -> createChatFabMenu.isVisible = true
|
||||
DisplayMode.PEOPLE -> createChatRoomButton.isVisible = true
|
||||
else -> createGroupRoomButton.isVisible = true
|
||||
DisplayMode.HOME -> createChatFabMenu.isVisible = true
|
||||
DisplayMode.PEOPLE -> createChatRoomButton.isVisible = true
|
||||
DisplayMode.ROOMS -> createGroupRoomButton.isVisible = true
|
||||
DisplayMode.FILTERED -> Unit // No button in this mode
|
||||
}
|
||||
|
||||
createChatRoomButton.setOnClickListener {
|
||||
|
@ -122,9 +124,10 @@ class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Listener, O
|
|||
RecyclerView.SCROLL_STATE_DRAGGING,
|
||||
RecyclerView.SCROLL_STATE_SETTLING -> {
|
||||
when (roomListParams.displayMode) {
|
||||
DisplayMode.HOME -> createChatFabMenu.hide()
|
||||
DisplayMode.PEOPLE -> createChatRoomButton.hide()
|
||||
else -> createGroupRoomButton.hide()
|
||||
DisplayMode.HOME -> createChatFabMenu.hide()
|
||||
DisplayMode.PEOPLE -> createChatRoomButton.hide()
|
||||
DisplayMode.ROOMS -> createGroupRoomButton.hide()
|
||||
DisplayMode.FILTERED -> Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -132,6 +135,9 @@ class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Listener, O
|
|||
})
|
||||
}
|
||||
|
||||
fun filterRoomsWith(filter: String) {
|
||||
roomListViewModel.accept(RoomListActions.FilterWith(filter))
|
||||
}
|
||||
|
||||
override fun openRoomDirectory() {
|
||||
navigator.openRoomDirectory(requireActivity())
|
||||
|
@ -155,9 +161,10 @@ class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Listener, O
|
|||
private val showFabRunnable = Runnable {
|
||||
if (isAdded) {
|
||||
when (roomListParams.displayMode) {
|
||||
DisplayMode.HOME -> createChatFabMenu.show()
|
||||
DisplayMode.PEOPLE -> createChatRoomButton.show()
|
||||
else -> createGroupRoomButton.show()
|
||||
DisplayMode.HOME -> createChatFabMenu.show()
|
||||
DisplayMode.PEOPLE -> createChatRoomButton.show()
|
||||
DisplayMode.ROOMS -> createGroupRoomButton.show()
|
||||
DisplayMode.FILTERED -> Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -188,7 +195,7 @@ class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Listener, O
|
|||
}
|
||||
.isNullOrEmpty()
|
||||
val emptyState = when (roomListParams.displayMode) {
|
||||
DisplayMode.HOME -> {
|
||||
DisplayMode.HOME -> {
|
||||
if (hasNoRoom) {
|
||||
StateView.State.Empty(
|
||||
getString(R.string.room_list_catchup_welcome_title),
|
||||
|
@ -202,18 +209,21 @@ class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Listener, O
|
|||
getString(R.string.room_list_catchup_empty_body))
|
||||
}
|
||||
}
|
||||
DisplayMode.PEOPLE ->
|
||||
DisplayMode.PEOPLE ->
|
||||
StateView.State.Empty(
|
||||
getString(R.string.room_list_people_empty_title),
|
||||
ContextCompat.getDrawable(requireContext(), R.drawable.ic_home_bottom_chat),
|
||||
getString(R.string.room_list_people_empty_body)
|
||||
)
|
||||
DisplayMode.ROOMS ->
|
||||
DisplayMode.ROOMS ->
|
||||
StateView.State.Empty(
|
||||
getString(R.string.room_list_rooms_empty_title),
|
||||
ContextCompat.getDrawable(requireContext(), R.drawable.ic_home_bottom_group),
|
||||
getString(R.string.room_list_rooms_empty_body)
|
||||
)
|
||||
DisplayMode.FILTERED ->
|
||||
// Always display the content in this mode, because if the footer
|
||||
StateView.State.Content
|
||||
}
|
||||
stateView.state = emptyState
|
||||
}
|
||||
|
@ -255,4 +265,10 @@ class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Listener, O
|
|||
override fun onToggleRoomCategory(roomCategory: RoomCategory) {
|
||||
roomListViewModel.accept(RoomListActions.ToggleCategory(roomCategory))
|
||||
}
|
||||
|
||||
override fun createRoom() {
|
||||
// TODO Create an Activity to host CreateRoomFragment
|
||||
navigator.openRoomDirectory(requireActivity())
|
||||
}
|
||||
|
||||
}
|
|
@ -14,8 +14,21 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.features.home.room
|
||||
package im.vector.riotx.features.home.room.list
|
||||
|
||||
import im.vector.riotx.core.utils.RxStore
|
||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||
import io.reactivex.functions.Predicate
|
||||
|
||||
class VisibleRoomStore : RxStore<String>()
|
||||
class RoomListNameFilter : Predicate<RoomSummary> {
|
||||
|
||||
var filter: String = ""
|
||||
|
||||
override fun test(roomSummary: RoomSummary): Boolean {
|
||||
if (filter.isBlank()) {
|
||||
// No filter
|
||||
return true
|
||||
}
|
||||
|
||||
return roomSummary.displayName.contains(filter, ignoreCase = true)
|
||||
}
|
||||
}
|
|
@ -76,6 +76,7 @@ class RoomListViewModel @AssistedInject constructor(@Assisted initialState: Room
|
|||
is RoomListActions.ToggleCategory -> handleToggleCategory(action)
|
||||
is RoomListActions.AcceptInvitation -> handleAcceptInvitation(action)
|
||||
is RoomListActions.RejectInvitation -> handleRejectInvitation(action)
|
||||
is RoomListActions.FilterWith -> handleFilter(action)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,10 +90,21 @@ class RoomListViewModel @AssistedInject constructor(@Assisted initialState: Room
|
|||
this.toggle(action.category)
|
||||
}
|
||||
|
||||
private fun handleFilter(action: RoomListActions.FilterWith) {
|
||||
setState {
|
||||
copy(
|
||||
roomFilter = action.filter
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun observeRoomSummaries() {
|
||||
homeRoomListObservableSource
|
||||
.observe()
|
||||
.observeOn(Schedulers.computation())
|
||||
.map {
|
||||
it.sortedWith(chronologicalRoomComparator)
|
||||
}
|
||||
.execute { asyncRooms ->
|
||||
copy(asyncRooms = asyncRooms)
|
||||
}
|
||||
|
@ -201,9 +213,10 @@ class RoomListViewModel @AssistedInject constructor(@Assisted initialState: Room
|
|||
}
|
||||
|
||||
val roomComparator = when (displayMode) {
|
||||
RoomListFragment.DisplayMode.HOME -> chronologicalRoomComparator
|
||||
RoomListFragment.DisplayMode.PEOPLE -> chronologicalRoomComparator
|
||||
RoomListFragment.DisplayMode.ROOMS -> chronologicalRoomComparator
|
||||
RoomListFragment.DisplayMode.HOME -> chronologicalRoomComparator
|
||||
RoomListFragment.DisplayMode.PEOPLE -> chronologicalRoomComparator
|
||||
RoomListFragment.DisplayMode.ROOMS -> chronologicalRoomComparator
|
||||
RoomListFragment.DisplayMode.FILTERED -> chronologicalRoomComparator
|
||||
}
|
||||
|
||||
return RoomSummaries().apply {
|
||||
|
|
|
@ -26,6 +26,7 @@ import im.vector.riotx.R
|
|||
data class RoomListViewState(
|
||||
val displayMode: RoomListFragment.DisplayMode,
|
||||
val asyncRooms: Async<List<RoomSummary>> = Uninitialized,
|
||||
val roomFilter: String = "",
|
||||
val asyncFilteredRooms: Async<RoomSummaries> = Uninitialized,
|
||||
// List of roomIds that the user wants to join
|
||||
val joiningRoomsIds: Set<String> = emptySet(),
|
||||
|
|
|
@ -20,6 +20,8 @@ import androidx.annotation.StringRes
|
|||
import com.airbnb.epoxy.TypedEpoxyController
|
||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||
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
|
||||
import javax.inject.Inject
|
||||
|
||||
class RoomSummaryController @Inject constructor(private val stringProvider: StringProvider,
|
||||
|
@ -28,27 +30,56 @@ class RoomSummaryController @Inject constructor(private val stringProvider: Stri
|
|||
|
||||
var listener: Listener? = null
|
||||
|
||||
private val roomListNameFilter = RoomListNameFilter()
|
||||
|
||||
override fun buildModels(viewState: RoomListViewState) {
|
||||
val roomSummaries = viewState.asyncFilteredRooms()
|
||||
roomSummaries?.forEach { (category, summaries) ->
|
||||
if (summaries.isEmpty()) {
|
||||
return@forEach
|
||||
} else {
|
||||
val isExpanded = viewState.isCategoryExpanded(category)
|
||||
buildRoomCategory(viewState, summaries, category.titleRes, viewState.isCategoryExpanded(category)) {
|
||||
listener?.onToggleRoomCategory(category)
|
||||
}
|
||||
if (isExpanded) {
|
||||
buildRoomModels(summaries,
|
||||
viewState.joiningRoomsIds,
|
||||
viewState.joiningErrorRoomsIds,
|
||||
viewState.rejectingRoomsIds,
|
||||
viewState.rejectingErrorRoomsIds)
|
||||
if (viewState.displayMode == RoomListFragment.DisplayMode.FILTERED) {
|
||||
buildFilteredRooms(viewState)
|
||||
} else {
|
||||
val roomSummaries = viewState.asyncFilteredRooms()
|
||||
roomSummaries?.forEach { (category, summaries) ->
|
||||
if (summaries.isEmpty()) {
|
||||
return@forEach
|
||||
} else {
|
||||
val isExpanded = viewState.isCategoryExpanded(category)
|
||||
buildRoomCategory(viewState, summaries, category.titleRes, viewState.isCategoryExpanded(category)) {
|
||||
listener?.onToggleRoomCategory(category)
|
||||
}
|
||||
if (isExpanded) {
|
||||
buildRoomModels(summaries,
|
||||
viewState.joiningRoomsIds,
|
||||
viewState.joiningErrorRoomsIds,
|
||||
viewState.rejectingRoomsIds,
|
||||
viewState.rejectingErrorRoomsIds)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildFilteredRooms(viewState: RoomListViewState) {
|
||||
val summaries = viewState.asyncRooms() ?: return
|
||||
|
||||
roomListNameFilter.filter = viewState.roomFilter
|
||||
|
||||
val filteredSummaries = summaries.filter { roomListNameFilter.test(it) }
|
||||
|
||||
buildRoomModels(filteredSummaries,
|
||||
viewState.joiningRoomsIds,
|
||||
viewState.joiningErrorRoomsIds,
|
||||
viewState.rejectingRoomsIds,
|
||||
viewState.rejectingErrorRoomsIds)
|
||||
|
||||
addFilterFooter()
|
||||
}
|
||||
|
||||
private fun addFilterFooter() {
|
||||
filteredRoomFooterItem {
|
||||
id("filter_footer")
|
||||
listener(listener)
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildRoomCategory(viewState: RoomListViewState,
|
||||
summaries: List<RoomSummary>,
|
||||
@StringRes titleRes: Int,
|
||||
|
@ -89,7 +120,7 @@ class RoomSummaryController @Inject constructor(private val stringProvider: Stri
|
|||
}
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
interface Listener : FilteredRoomFooterItem.FilteredRoomFooterItemListener {
|
||||
fun onToggleRoomCategory(roomCategory: RoomCategory)
|
||||
fun onRoomSelected(room: RoomSummary)
|
||||
fun onRejectRoomInvitation(room: RoomSummary)
|
||||
|
|
|
@ -27,6 +27,7 @@ import im.vector.riotx.features.crypto.keysbackup.setup.KeysBackupSetupActivity
|
|||
import im.vector.riotx.features.debug.DebugMenuActivity
|
||||
import im.vector.riotx.features.home.room.detail.RoomDetailActivity
|
||||
import im.vector.riotx.features.home.room.detail.RoomDetailArgs
|
||||
import im.vector.riotx.features.home.room.filtered.FilteredRoomsActivity
|
||||
import im.vector.riotx.features.roomdirectory.RoomDirectoryActivity
|
||||
import im.vector.riotx.features.roomdirectory.roompreview.RoomPreviewActivity
|
||||
import im.vector.riotx.features.settings.VectorSettingsActivity
|
||||
|
@ -61,6 +62,11 @@ class DefaultNavigator @Inject constructor() : Navigator {
|
|||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
override fun openRoomsFiltering(context: Context) {
|
||||
val intent = FilteredRoomsActivity.newIntent(context)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
override fun openSettings(context: Context) {
|
||||
val intent = VectorSettingsActivity.getIntent(context, "TODO")
|
||||
context.startActivity(intent)
|
||||
|
|
|
@ -29,6 +29,8 @@ interface Navigator {
|
|||
|
||||
fun openRoomDirectory(context: Context)
|
||||
|
||||
fun openRoomsFiltering(context: Context)
|
||||
|
||||
fun openSettings(context: Context)
|
||||
|
||||
fun openDebug(context: Context)
|
||||
|
|
20
vector/src/main/res/drawable/ic_filter.xml
Normal file
20
vector/src/main/res/drawable/ic_filter.xml
Normal file
|
@ -0,0 +1,20 @@
|
|||
<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="M4,6.5h16"
|
||||
android:strokeWidth="1.8"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#03B381"
|
||||
android:fillType="evenOdd"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M6,12.5h12M9,18.5h6"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#03B381"
|
||||
android:fillType="evenOdd"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
42
vector/src/main/res/layout/activity_filtered_rooms.xml
Normal file
42
vector/src/main/res/layout/activity_filtered_rooms.xml
Normal file
|
@ -0,0 +1,42 @@
|
|||
<?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"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/filteredRoomsToolbar"
|
||||
style="@style/VectorToolbarStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:elevation="4dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.appcompat.widget.SearchView
|
||||
android:id="@+id/filteredRoomsSearchView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:iconifiedByDefault="false"
|
||||
app:queryHint="@string/home_filter_placeholder_home"
|
||||
app:searchIcon="@drawable/ic_filter" />
|
||||
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/filteredRoomsFragmentContainer"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/filteredRoomsToolbar" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
43
vector/src/main/res/layout/item_room_filter_footer.xml
Normal file
43
vector/src/main/res/layout/item_room_filter_footer.xml
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?riotx_background"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="56dp"
|
||||
android:text="@string/room_filtering_footer_title"
|
||||
android:textColor="?riotx_text_secondary"
|
||||
android:textSize="15sp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/roomFilterFooterCreateRoom"
|
||||
style="@style/VectorButtonStyleFlat"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="@dimen/layout_vertical_margin"
|
||||
android:text="@string/room_filtering_footer_create_new_room" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/roomFilterFooterCreateDirect"
|
||||
style="@style/VectorButtonStyleFlat"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:text="@string/room_filtering_footer_create_new_direct_message" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/roomFilterFooterOpenRoomDirectory"
|
||||
style="@style/VectorButtonStyleFlat"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginBottom="@dimen/layout_vertical_margin"
|
||||
android:text="@string/room_filtering_footer_open_room_directory" />
|
||||
|
||||
</LinearLayout>
|
|
@ -1,5 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_home_suggestion"
|
||||
|
@ -11,4 +12,10 @@
|
|||
android:icon="@drawable/ic_material_bug_report"
|
||||
android:title="@string/send_bug_report" />
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_home_filter"
|
||||
android:icon="@drawable/ic_filter"
|
||||
android:title="@string/home_filter_placeholder_home"
|
||||
app:showAsAction="always" />
|
||||
|
||||
</menu>
|
|
@ -25,4 +25,11 @@
|
|||
<string name="message_edits">Message Edits</string>
|
||||
<string name="no_message_edits_found">No edits found</string>
|
||||
|
||||
<!-- Room filtering -->
|
||||
<string name="room_filtering_footer_title">Can’t find what you’re looking for?</string>
|
||||
<string name="room_filtering_footer_create_new_room">Create a new room</string>
|
||||
<string name="room_filtering_footer_create_new_direct_message">Send a new direct message</string>
|
||||
<string name="room_filtering_footer_open_room_directory">View the room directory</string>
|
||||
|
||||
|
||||
</resources>
|
Loading…
Reference in a new issue