mirror of
https://github.com/element-hq/element-android
synced 2024-11-23 18:05:36 +03:00
Room list : quickly branch filter room name field
This commit is contained in:
parent
32b29c47e7
commit
85608b04d1
11 changed files with 109 additions and 10 deletions
|
@ -0,0 +1,44 @@
|
|||
package im.vector.riotredesign.core.extensions
|
||||
|
||||
import android.text.Editable
|
||||
import android.text.InputType
|
||||
import android.text.TextWatcher
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.widget.EditText
|
||||
import im.vector.riotredesign.R
|
||||
|
||||
fun EditText.setupAsSearch() {
|
||||
addTextChangedListener(object : TextWatcher {
|
||||
override fun afterTextChanged(editable: Editable?) {
|
||||
val clearIcon = if (editable?.isNotEmpty() == true) R.drawable.ic_clear_white else 0
|
||||
setCompoundDrawablesWithIntrinsicBounds(0, 0, clearIcon, 0)
|
||||
}
|
||||
|
||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) = Unit
|
||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) = Unit
|
||||
})
|
||||
|
||||
maxLines = 1
|
||||
inputType = InputType.TYPE_CLASS_TEXT
|
||||
imeOptions = EditorInfo.IME_ACTION_SEARCH
|
||||
setOnEditorActionListener { _, actionId, event ->
|
||||
var consumed = false
|
||||
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
|
||||
hideKeyboard()
|
||||
consumed = true
|
||||
}
|
||||
consumed
|
||||
}
|
||||
|
||||
setOnTouchListener(View.OnTouchListener { _, event ->
|
||||
if (event.action == MotionEvent.ACTION_UP) {
|
||||
if (event.rawX >= (this.right - this.compoundPaddingRight)) {
|
||||
text = null
|
||||
return@OnTouchListener true
|
||||
}
|
||||
}
|
||||
return@OnTouchListener false
|
||||
})
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package im.vector.riotredesign.core.extensions
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
|
||||
fun View.hideKeyboard() {
|
||||
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
imm.hideSoftInputFromWindow(windowToken, 0)
|
||||
}
|
|
@ -8,4 +8,6 @@ sealed class RoomListActions {
|
|||
|
||||
object RoomDisplayed : RoomListActions()
|
||||
|
||||
data class FilterRooms(val roomName: CharSequence? = null) : RoomListActions()
|
||||
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
package im.vector.riotredesign.features.home.room.list
|
||||
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.Incomplete
|
||||
import com.airbnb.mvrx.Success
|
||||
|
@ -11,6 +14,8 @@ import com.airbnb.mvrx.activityViewModel
|
|||
import im.vector.matrix.android.api.failure.Failure
|
||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||
import im.vector.riotredesign.R
|
||||
import im.vector.riotredesign.core.extensions.hideKeyboard
|
||||
import im.vector.riotredesign.core.extensions.setupAsSearch
|
||||
import im.vector.riotredesign.core.platform.RiotFragment
|
||||
import im.vector.riotredesign.core.platform.StateView
|
||||
import im.vector.riotredesign.features.home.HomeNavigator
|
||||
|
@ -38,6 +43,7 @@ class RoomListFragment : RiotFragment(), RoomSummaryController.Callback {
|
|||
roomController = RoomSummaryController(this)
|
||||
stateView.contentView = epoxyRecyclerView
|
||||
epoxyRecyclerView.setController(roomController)
|
||||
setupFilterView()
|
||||
homeViewModel.subscribe { renderState(it) }
|
||||
}
|
||||
|
||||
|
@ -70,6 +76,21 @@ class RoomListFragment : RiotFragment(), RoomSummaryController.Callback {
|
|||
stateView.state = StateView.State.Error(message)
|
||||
}
|
||||
|
||||
private fun setupFilterView() {
|
||||
filterRoomView.setupAsSearch()
|
||||
filterRoomView.addTextChangedListener(object : TextWatcher {
|
||||
override fun afterTextChanged(s: Editable?) = Unit
|
||||
|
||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) = Unit
|
||||
|
||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
|
||||
homeViewModel.accept(RoomListActions.FilterRooms(s))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// RoomSummaryController.Callback **************************************************************
|
||||
|
||||
override fun onRoomSelected(room: RoomSummary) {
|
||||
homeViewModel.accept(RoomListActions.SelectRoom(room))
|
||||
homeNavigator.openRoomDetail(room.roomId, null)
|
||||
|
|
|
@ -3,6 +3,7 @@ package im.vector.riotredesign.features.home.room.list
|
|||
import arrow.core.Option
|
||||
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||
import com.airbnb.mvrx.ViewModelContext
|
||||
import com.jakewharton.rxrelay2.BehaviorRelay
|
||||
import im.vector.matrix.android.api.Matrix
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
||||
|
@ -12,10 +13,12 @@ import im.vector.riotredesign.core.platform.RiotViewModel
|
|||
import im.vector.riotredesign.features.home.group.SelectedGroupHolder
|
||||
import im.vector.riotredesign.features.home.room.VisibleRoomHolder
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.functions.BiFunction
|
||||
import io.reactivex.functions.Function3
|
||||
import io.reactivex.rxkotlin.subscribeBy
|
||||
import org.koin.android.ext.android.get
|
||||
|
||||
typealias RoomListFilterName = CharSequence
|
||||
|
||||
class RoomListViewModel(initialState: RoomListViewState,
|
||||
private val session: Session,
|
||||
private val selectedGroupHolder: SelectedGroupHolder,
|
||||
|
@ -35,6 +38,9 @@ class RoomListViewModel(initialState: RoomListViewState,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private val roomListFilter = BehaviorRelay.createDefault<Option<RoomListFilterName>>(Option.empty())
|
||||
|
||||
init {
|
||||
observeRoomSummaries()
|
||||
observeVisibleRoom()
|
||||
|
@ -42,7 +48,8 @@ class RoomListViewModel(initialState: RoomListViewState,
|
|||
|
||||
fun accept(action: RoomListActions) {
|
||||
when (action) {
|
||||
is RoomListActions.SelectRoom -> handleSelectRoom(action)
|
||||
is RoomListActions.SelectRoom -> handleSelectRoom(action)
|
||||
is RoomListActions.FilterRooms -> handleFilterRooms(action)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,6 +61,11 @@ class RoomListViewModel(initialState: RoomListViewState,
|
|||
}
|
||||
}
|
||||
|
||||
private fun handleFilterRooms(action: RoomListActions.FilterRooms) {
|
||||
val optionalFilter = Option.fromNullable(action.roomName)
|
||||
roomListFilter.accept(optionalFilter)
|
||||
}
|
||||
|
||||
private fun observeVisibleRoom() {
|
||||
visibleRoomHolder.visibleRoom()
|
||||
.subscribeBy {
|
||||
|
@ -63,13 +75,22 @@ class RoomListViewModel(initialState: RoomListViewState,
|
|||
}
|
||||
|
||||
private fun observeRoomSummaries() {
|
||||
Observable.combineLatest<List<RoomSummary>, Option<GroupSummary>, RoomSummaries>(
|
||||
Observable.combineLatest<List<RoomSummary>, Option<GroupSummary>, Option<RoomListFilterName>, RoomSummaries>(
|
||||
session.rx().liveRoomSummaries(),
|
||||
selectedGroupHolder.selectedGroup(),
|
||||
BiFunction { rooms, selectedGroupOption ->
|
||||
val selectedGroup = selectedGroupOption.orNull()
|
||||
roomListFilter,
|
||||
Function3 { rooms, selectedGroupOption, filterRoomOption ->
|
||||
val filterRoom = filterRoomOption.orNull()
|
||||
val filteredRooms = rooms.filter {
|
||||
if (filterRoom.isNullOrBlank()) {
|
||||
true
|
||||
} else {
|
||||
it.displayName.contains(other = filterRoom, ignoreCase = true)
|
||||
}
|
||||
}
|
||||
|
||||
val filteredDirectRooms = rooms
|
||||
val selectedGroup = selectedGroupOption.orNull()
|
||||
val filteredDirectRooms = filteredRooms
|
||||
.filter { it.isDirect }
|
||||
.filter {
|
||||
if (selectedGroup == null) {
|
||||
|
@ -81,7 +102,7 @@ class RoomListViewModel(initialState: RoomListViewState,
|
|||
}
|
||||
}
|
||||
|
||||
val filteredGroupRooms = rooms
|
||||
val filteredGroupRooms = filteredRooms
|
||||
.filter { !it.isDirect }
|
||||
.filter {
|
||||
selectedGroup?.roomIds?.contains(it.roomId) ?: true
|
||||
|
|
BIN
app/src/main/res/drawable-hdpi/ic_clear_white.png
Normal file
BIN
app/src/main/res/drawable-hdpi/ic_clear_white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 276 B |
BIN
app/src/main/res/drawable-mdpi/ic_clear_white.png
Normal file
BIN
app/src/main/res/drawable-mdpi/ic_clear_white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 209 B |
BIN
app/src/main/res/drawable-xhdpi/ic_clear_white.png
Normal file
BIN
app/src/main/res/drawable-xhdpi/ic_clear_white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 329 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_clear_white.png
Normal file
BIN
app/src/main/res/drawable-xxhdpi/ic_clear_white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 462 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_clear_white.png
Normal file
BIN
app/src/main/res/drawable-xxxhdpi/ic_clear_white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 601 B |
|
@ -11,15 +11,16 @@
|
|||
android:id="@+id/filterRoomView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:background="@drawable/bg_search_edit_text"
|
||||
android:drawableLeft="@drawable/ic_search_white"
|
||||
android:drawablePadding="8dp"
|
||||
android:drawableTint="#9fa9ba"
|
||||
android:hint="Filter by name..."
|
||||
android:lines="1"
|
||||
android:paddingLeft="8dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/stateView"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
|
@ -30,8 +31,8 @@
|
|||
android:id="@+id/stateView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginBottom="0dp"
|
||||
android:layout_marginEnd="0dp"
|
||||
android:layout_marginBottom="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
|
|
Loading…
Reference in a new issue