Merge pull request #383 from vector-im/feature/filter_params

Pass filter to room directory screen or create room screen
This commit is contained in:
Benoit Marty 2019-07-17 14:20:29 +02:00 committed by GitHub
commit e3e86c0a41
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 125 additions and 68 deletions

View File

@ -57,9 +57,15 @@ import im.vector.riotx.features.workers.signout.SignOutViewModel
interface ViewModelModule {


/**
* ViewModels with @IntoMap will be injected by this factory
*/
@Binds
fun bindViewModelFactory(factory: VectorViewModelFactory): ViewModelProvider.Factory

/**
* Below are bindings for the androidx view models (which extend ViewModel). Will be converted to MvRx ViewModel in the future.
*/
@Binds
@IntoMap
@ViewModelKey(SignOutViewModel::class)
@ -110,6 +116,10 @@ interface ViewModelModule {
@ViewModelKey(ConfigurationViewModel::class)
fun bindConfigurationViewModel(viewModel: ConfigurationViewModel): ViewModel

/**
* Below are bindings for the MvRx view models (which extend VectorViewModel). Will be the only usage in the future.
*/

@Binds
fun bindHomeActivityViewModelFactory(factory: HomeActivityViewModel_AssistedFactory): HomeActivityViewModel.Factory


View File

@ -30,10 +30,13 @@ abstract class FilteredRoomFooterItem : VectorEpoxyModel<FilteredRoomFooterItem.
@EpoxyAttribute
var listener: FilteredRoomFooterItemListener? = null

@EpoxyAttribute
var currentFilter: String = ""

override fun bind(holder: Holder) {
holder.createRoomButton.setOnClickListener { listener?.createRoom() }
holder.createRoomButton.setOnClickListener { listener?.createRoom(currentFilter) }
holder.createDirectChat.setOnClickListener { listener?.createDirectChat() }
holder.openRoomDirectory.setOnClickListener { listener?.openRoomDirectory() }
holder.openRoomDirectory.setOnClickListener { listener?.openRoomDirectory(currentFilter) }
}

class Holder : VectorEpoxyHolder() {
@ -43,7 +46,7 @@ abstract class FilteredRoomFooterItem : VectorEpoxyModel<FilteredRoomFooterItem.
}

interface FilteredRoomFooterItemListener : FabMenuView.Listener {
fun createRoom()
fun createRoom(initialName: String)
}
}


View File

@ -20,17 +20,15 @@ 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 {
class FilteredRoomsActivity : VectorBaseActivity() {

private lateinit var roomListFragment: RoomListFragment

@ -44,6 +42,9 @@ class FilteredRoomsActivity : VectorBaseActivity(), ToolbarConfigurable {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

configureToolbar(filteredRoomsToolbar)

if (isFirstCreation()) {
roomListFragment = RoomListFragment.newInstance(RoomListParams(RoomListFragment.DisplayMode.FILTERED))
replaceFragment(roomListFragment, R.id.filteredRoomsFragmentContainer, FRAGMENT_TAG)
@ -67,10 +68,6 @@ class FilteredRoomsActivity : VectorBaseActivity(), ToolbarConfigurable {
filteredRoomsSearchView.requestFocus()
}

override fun configure(toolbar: Toolbar) {
configureToolbar(toolbar)
}

companion object {
private const val FRAGMENT_TAG = "RoomListFragment"


View File

@ -112,7 +112,7 @@ class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Listener, O
}

// Hide FAB when list is scrolling
epoxyRecyclerView.addOnScrollListener(
roomListEpoxyRecyclerView.addOnScrollListener(
object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
createChatFabMenu.removeCallbacks(showFabRunnable)
@ -136,11 +136,14 @@ class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Listener, O
}

fun filterRoomsWith(filter: String) {
// Scroll the list to top
roomListEpoxyRecyclerView.scrollToPosition(0)

roomListViewModel.accept(RoomListActions.FilterWith(filter))
}

override fun openRoomDirectory() {
navigator.openRoomDirectory(requireActivity())
override fun openRoomDirectory(initialFilter: String) {
navigator.openRoomDirectory(requireActivity(), initialFilter)
}

override fun createDirectChat() {
@ -150,12 +153,12 @@ class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Listener, O
private fun setupRecyclerView() {
val layoutManager = LinearLayoutManager(context)
val stateRestorer = LayoutManagerStateRestorer(layoutManager).register()
epoxyRecyclerView.layoutManager = layoutManager
epoxyRecyclerView.itemAnimator = RoomListAnimator()
roomListEpoxyRecyclerView.layoutManager = layoutManager
roomListEpoxyRecyclerView.itemAnimator = RoomListAnimator()
roomController.listener = this
roomController.addModelBuildListener { it.dispatchTo(stateRestorer) }
stateView.contentView = epoxyRecyclerView
epoxyRecyclerView.setController(roomController)
stateView.contentView = roomListEpoxyRecyclerView
roomListEpoxyRecyclerView.setController(roomController)
}

private val showFabRunnable = Runnable {
@ -266,9 +269,8 @@ class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Listener, O
roomListViewModel.accept(RoomListActions.ToggleCategory(roomCategory))
}

// TODO Pass title
override fun createRoom() {
navigator.openCreateRoom(requireActivity())
override fun createRoom(initialName: String) {
navigator.openCreateRoom(requireActivity(), initialName)
}

}

View File

@ -70,13 +70,14 @@ class RoomSummaryController @Inject constructor(private val stringProvider: Stri
viewState.rejectingRoomsIds,
viewState.rejectingErrorRoomsIds)

addFilterFooter()
addFilterFooter(viewState)
}

private fun addFilterFooter() {
private fun addFilterFooter(viewState: RoomListViewState) {
filteredRoomFooterItem {
id("filter_footer")
listener(listener)
currentFilter(viewState.roomFilter)
}
}


View File

@ -92,7 +92,7 @@ class FabMenuView @JvmOverloads constructor(context: Context, attrs: AttributeSe

interface Listener {
fun createDirectChat()
fun openRoomDirectory()
fun openRoomDirectory(initialFilter: String = "")
}

}

View File

@ -58,13 +58,13 @@ class DefaultNavigator @Inject constructor() : Navigator {
context.startActivity(intent)
}

override fun openRoomDirectory(context: Context) {
val intent = Intent(context, RoomDirectoryActivity::class.java)
override fun openRoomDirectory(context: Context, initialFilter: String) {
val intent = RoomDirectoryActivity.getIntent(context, initialFilter)
context.startActivity(intent)
}

override fun openCreateRoom(context: Context) {
val intent = CreateRoomActivity.getIntent(context)
override fun openCreateRoom(context: Context, initialName: String) {
val intent = CreateRoomActivity.getIntent(context, initialName)
context.startActivity(intent)
}


View File

@ -27,9 +27,9 @@ interface Navigator {

fun openRoomPreview(publicRoom: PublicRoom, context: Context)

fun openCreateRoom(context: Context)
fun openCreateRoom(context: Context, initialName: String = "")

fun openRoomDirectory(context: Context)
fun openRoomDirectory(context: Context, initialFilter: String = "")

fun openRoomsFiltering(context: Context)


View File

@ -144,6 +144,11 @@ class PublicRoomsFragment : VectorBaseFragment(), PublicRoomsController.Callback
}

override fun invalidate() = withState(viewModel) { state ->
if (publicRoomsFilter.text.toString() != state.currentFilter) {
// For initial filter
publicRoomsFilter.setText(state.currentFilter)
}

// Populate list with Epoxy
publicRoomsController.setData(state)
}

View File

@ -22,6 +22,8 @@ import com.airbnb.mvrx.Uninitialized
import im.vector.matrix.android.api.session.room.model.roomdirectory.PublicRoom

data class PublicRoomsViewState(
// The current filter
val currentFilter: String = "",
// Store cumul of pagination result
val publicRooms: List<PublicRoom> = emptyList(),
// Current pagination request

View File

@ -16,8 +16,11 @@

package im.vector.riotx.features.roomdirectory

import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.lifecycle.ViewModelProviders
import com.airbnb.mvrx.viewModel
import im.vector.riotx.R
import im.vector.riotx.core.di.ScreenComponent
import im.vector.riotx.core.extensions.addFragment
@ -25,6 +28,7 @@ import im.vector.riotx.core.extensions.addFragmentToBackstack
import im.vector.riotx.core.extensions.observeEvent
import im.vector.riotx.core.platform.VectorBaseActivity
import im.vector.riotx.features.roomdirectory.createroom.CreateRoomFragment
import im.vector.riotx.features.roomdirectory.createroom.CreateRoomViewModel
import im.vector.riotx.features.roomdirectory.picker.RoomDirectoryPickerFragment
import javax.inject.Inject

@ -39,7 +43,10 @@ class RoomDirectoryActivity : VectorBaseActivity() {
}


@Inject lateinit var createRoomViewModelFactory: CreateRoomViewModel.Factory
@Inject lateinit var roomDirectoryViewModelFactory: RoomDirectoryViewModel.Factory
private val roomDirectoryViewModel: RoomDirectoryViewModel by viewModel()
private val createRoomViewModel: CreateRoomViewModel by viewModel()
private lateinit var navigationViewModel: RoomDirectoryNavigationViewModel

override fun getLayoutRes() = R.layout.activity_simple
@ -51,6 +58,11 @@ class RoomDirectoryActivity : VectorBaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
navigationViewModel = ViewModelProviders.of(this, viewModelFactory).get(RoomDirectoryNavigationViewModel::class.java)

if (isFirstCreation()) {
roomDirectoryViewModel.filterWith(intent?.getStringExtra(INITIAL_FILTER) ?: "")
}

navigationViewModel.navigateTo.observeEvent(this) { navigation ->
when (navigation) {
is Navigation.Back -> onBackPressed()
@ -59,6 +71,11 @@ class RoomDirectoryActivity : VectorBaseActivity() {
is Navigation.Close -> finish()
}
}

roomDirectoryViewModel.selectSubscribe(this, PublicRoomsViewState::currentFilter) { currentFilter ->
// Transmit the filter to the createRoomViewModel
createRoomViewModel.setName(currentFilter)
}
}

override fun initUiAndData() {
@ -67,4 +84,13 @@ class RoomDirectoryActivity : VectorBaseActivity() {
}
}

companion object {
private const val INITIAL_FILTER = "INITIAL_FILTER"

fun getIntent(context: Context, initialFilter: String = ""): Intent {
val intent = Intent(context, RoomDirectoryActivity::class.java)
intent.putExtra(INITIAL_FILTER, initialFilter)
return intent
}
}
}

View File

@ -59,9 +59,6 @@ class RoomDirectoryViewModel @AssistedInject constructor(@Assisted initialState:
get() = _joinRoomErrorLiveData


// TODO Store in ViewState?
private var currentFilter: String = ""

private var since: String? = null

private var currentTask: Cancelable? = null
@ -70,9 +67,6 @@ class RoomDirectoryViewModel @AssistedInject constructor(@Assisted initialState:
private var roomDirectoryData = RoomDirectoryData()

init {
// Load with empty filter
load()

setState {
copy(
roomDirectoryDisplayName = roomDirectoryData.displayName
@ -115,24 +109,20 @@ class RoomDirectoryViewModel @AssistedInject constructor(@Assisted initialState:

this.roomDirectoryData = roomDirectoryData

reset()
load()
reset("")
load("")
}

fun filterWith(filter: String) {
if (currentFilter == filter) {
return
fun filterWith(filter: String) = withState { state ->
if (state.currentFilter != filter) {
currentTask?.cancel()

reset(filter)
load(filter)
}

currentTask?.cancel()

currentFilter = filter

reset()
load()
}

private fun reset() {
private fun reset(newFilter: String) {
// Reset since token
since = null

@ -141,12 +131,13 @@ class RoomDirectoryViewModel @AssistedInject constructor(@Assisted initialState:
publicRooms = emptyList(),
asyncPublicRoomsRequest = Loading(),
hasMore = false,
roomDirectoryDisplayName = roomDirectoryData.displayName
roomDirectoryDisplayName = roomDirectoryData.displayName,
currentFilter = newFilter
)
}
}

fun loadMore() {
fun loadMore() = withState { state ->
if (currentTask == null) {
setState {
copy(
@ -154,15 +145,15 @@ class RoomDirectoryViewModel @AssistedInject constructor(@Assisted initialState:
)
}

load()
load(state.currentFilter)
}
}

private fun load() {
private fun load(filter: String) {
currentTask = session.getPublicRooms(roomDirectoryData.homeServer,
PublicRoomsParams(
limit = PUBLIC_ROOMS_LIMIT,
filter = PublicRoomsFilter(searchTerm = currentFilter),
filter = PublicRoomsFilter(searchTerm = filter),
includeAllNetworks = roomDirectoryData.includeAllNetworks,
since = since,
thirdPartyInstanceId = roomDirectoryData.thirdPartyInstanceId

View File

@ -21,6 +21,7 @@ import android.content.Intent
import android.os.Bundle
import androidx.appcompat.widget.Toolbar
import androidx.lifecycle.ViewModelProviders
import com.airbnb.mvrx.viewModel
import im.vector.riotx.R
import im.vector.riotx.core.di.ScreenComponent
import im.vector.riotx.core.extensions.addFragment
@ -29,12 +30,16 @@ import im.vector.riotx.core.platform.ToolbarConfigurable
import im.vector.riotx.core.platform.VectorBaseActivity
import im.vector.riotx.features.roomdirectory.RoomDirectoryActivity
import im.vector.riotx.features.roomdirectory.RoomDirectoryNavigationViewModel
import javax.inject.Inject

/**
* Simple container for [CreateRoomFragment]
*/
class CreateRoomActivity : VectorBaseActivity(), ToolbarConfigurable {

@Inject lateinit var createRoomViewModelFactory: CreateRoomViewModel.Factory
private val createRoomViewModel: CreateRoomViewModel by viewModel()

private lateinit var navigationViewModel: RoomDirectoryNavigationViewModel

override fun getLayoutRes() = R.layout.activity_simple
@ -46,6 +51,8 @@ class CreateRoomActivity : VectorBaseActivity(), ToolbarConfigurable {
override fun initUiAndData() {
if (isFirstCreation()) {
addFragment(CreateRoomFragment(), R.id.simpleFragmentContainer)

createRoomViewModel.setName(intent?.getStringExtra(INITIAL_NAME) ?: "")
}
}

@ -58,14 +65,19 @@ class CreateRoomActivity : VectorBaseActivity(), ToolbarConfigurable {
navigationViewModel = ViewModelProviders.of(this, viewModelFactory).get(RoomDirectoryNavigationViewModel::class.java)
navigationViewModel.navigateTo.observeEvent(this) { navigation ->
when (navigation) {
is RoomDirectoryActivity.Navigation.Back -> finish()
is RoomDirectoryActivity.Navigation.Back,
is RoomDirectoryActivity.Navigation.Close -> finish()
}
}
}

companion object {
fun getIntent(context: Context): Intent {
return Intent(context, CreateRoomActivity::class.java)
private const val INITIAL_NAME = "INITIAL_NAME"

fun getIntent(context: Context, initialName: String = ""): Intent {
return Intent(context, CreateRoomActivity::class.java).apply {
putExtra(INITIAL_NAME, initialName)
}
}
}


View File

@ -21,7 +21,7 @@ import android.view.MenuItem
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.LinearLayoutManager
import com.airbnb.mvrx.Success
import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.activityViewModel
import com.airbnb.mvrx.withState
import im.vector.riotx.R
import im.vector.riotx.core.di.ScreenComponent
@ -35,9 +35,8 @@ import javax.inject.Inject
class CreateRoomFragment : VectorBaseFragment(), CreateRoomController.Listener {

private lateinit var navigationViewModel: RoomDirectoryNavigationViewModel
private val viewModel: CreateRoomViewModel by fragmentViewModel()
private val viewModel: CreateRoomViewModel by activityViewModel()
@Inject lateinit var createRoomController: CreateRoomController
@Inject lateinit var createRoomViewModelFactory: CreateRoomViewModel.Factory

override fun getLayoutResId() = R.layout.fragment_create_room


View File

@ -16,6 +16,7 @@

package im.vector.riotx.features.roomdirectory.createroom

import androidx.fragment.app.FragmentActivity
import com.airbnb.mvrx.*
import com.squareup.inject.assisted.Assisted
import com.squareup.inject.assisted.AssistedInject
@ -25,6 +26,7 @@ import im.vector.matrix.android.api.session.room.model.RoomDirectoryVisibility
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
import im.vector.matrix.android.api.session.room.model.create.CreateRoomPreset
import im.vector.riotx.core.platform.VectorViewModel
import im.vector.riotx.features.roomdirectory.RoomDirectoryActivity

class CreateRoomViewModel @AssistedInject constructor(@Assisted initialState: CreateRoomViewState,
private val session: Session
@ -39,8 +41,13 @@ class CreateRoomViewModel @AssistedInject constructor(@Assisted initialState: Cr

@JvmStatic
override fun create(viewModelContext: ViewModelContext, state: CreateRoomViewState): CreateRoomViewModel? {
val fragment: CreateRoomFragment = (viewModelContext as FragmentViewModelContext).fragment()
return fragment.createRoomViewModelFactory.create(state)
val activity: FragmentActivity = (viewModelContext as ActivityViewModelContext).activity()

return when (activity) {
is CreateRoomActivity -> activity.createRoomViewModelFactory.create(state)
is RoomDirectoryActivity -> activity.createRoomViewModelFactory.create(state)
else -> throw IllegalStateException("Wrong activity")
}
}
}


View File

@ -14,6 +14,7 @@
android:layout_width="0dp"
android:layout_height="?attr/actionBarSize"
android:elevation="4dp"
app:contentInsetStart="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">

View File

@ -11,10 +11,10 @@

<androidx.appcompat.widget.Toolbar
android:id="@+id/createRoomToolbar"
style="@style/VectorToolbarStyle"
android:layout_width="0dp"
android:layout_height="?actionBarSize"
android:elevation="4dp"
app:contentInsetStartWithNavigation="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">

View File

@ -8,10 +8,10 @@

<androidx.appcompat.widget.Toolbar
android:id="@+id/groupToolbar"
style="@style/VectorToolbarStyle"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:elevation="4dp"
app:contentInsetStartWithNavigation="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent">


View File

@ -23,11 +23,11 @@

<androidx.appcompat.widget.Toolbar
android:id="@+id/publicRoomsToolbar"
style="@style/VectorToolbarStyle"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:elevation="4dp"
android:minHeight="0dp"
app:contentInsetStartWithNavigation="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"

View File

@ -8,10 +8,10 @@

<androidx.appcompat.widget.Toolbar
android:id="@+id/roomToolbar"
style="@style/VectorToolbarStyle"
android:layout_width="0dp"
android:layout_height="?actionBarSize"
android:elevation="4dp"
app:contentInsetStartWithNavigation="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">

View File

@ -8,7 +8,7 @@
android:background="?riotx_header_panel_background">

<com.airbnb.epoxy.EpoxyRecyclerView
android:id="@+id/epoxyRecyclerView"
android:id="@+id/roomListEpoxyRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />


View File

@ -13,10 +13,10 @@

<androidx.appcompat.widget.Toolbar
android:id="@+id/roomPreviewNoPreviewToolbar"
style="@style/VectorToolbarStyle"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:elevation="4dp"
app:contentInsetStartWithNavigation="0dp">
android:elevation="4dp">

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"

View File

@ -9,6 +9,7 @@
<item name="titleTextAppearance">@style/Vector.Toolbar.Title</item>
<item name="subtitleTextAppearance">@style/Vector.Toolbar.SubTitle</item>
<item name="android:background">?riotx_background</item>
<item name="contentInsetStartWithNavigation">0dp</item>
</style>

<style name="VectorToolbarStyle.Group">