forked from GitHub-Mirror/riotX-android
Direct chat : finalize flow
This commit is contained in:
parent
5af6bf3762
commit
76a9625f25
@ -31,7 +31,6 @@ import im.vector.matrix.android.internal.database.query.where
|
|||||||
import im.vector.matrix.android.internal.session.user.model.SearchUserTask
|
import im.vector.matrix.android.internal.session.user.model.SearchUserTask
|
||||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||||
import im.vector.matrix.android.internal.task.configureWith
|
import im.vector.matrix.android.internal.task.configureWith
|
||||||
import im.vector.matrix.android.internal.task.toConfigurableTask
|
|
||||||
import im.vector.matrix.android.internal.util.fetchCopied
|
import im.vector.matrix.android.internal.util.fetchCopied
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -23,13 +23,16 @@ import android.view.MotionEvent
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.inputmethod.EditorInfo
|
import android.view.inputmethod.EditorInfo
|
||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
|
import androidx.annotation.DrawableRes
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
|
|
||||||
fun EditText.setupAsSearch() {
|
fun EditText.setupAsSearch(@DrawableRes searchIconRes: Int = R.drawable.ic_filter,
|
||||||
|
@DrawableRes clearIconRes: Int = R.drawable.ic_x_green) {
|
||||||
|
|
||||||
addTextChangedListener(object : TextWatcher {
|
addTextChangedListener(object : TextWatcher {
|
||||||
override fun afterTextChanged(editable: Editable?) {
|
override fun afterTextChanged(editable: Editable?) {
|
||||||
val clearIcon = if (editable?.isNotEmpty() == true) R.drawable.ic_clear_white else 0
|
val clearIcon = if (editable?.isNotEmpty() == true) clearIconRes else 0
|
||||||
setCompoundDrawablesWithIntrinsicBounds(0, 0, clearIcon, 0)
|
setCompoundDrawablesWithIntrinsicBounds(searchIconRes, 0, clearIcon, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) = Unit
|
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) = Unit
|
||||||
|
@ -86,7 +86,7 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun renderCreationLoading() {
|
private fun renderCreationLoading() {
|
||||||
updateWaitingView(WaitingViewData(getString(R.string.room_recents_create_room)))
|
updateWaitingView(WaitingViewData(getString(R.string.creating_direct_room)))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun renderCreationFailure(error: Throwable) {
|
private fun renderCreationFailure(error: Throwable) {
|
||||||
|
@ -18,19 +18,25 @@
|
|||||||
|
|
||||||
package im.vector.riotx.features.home.createdirect
|
package im.vector.riotx.features.home.createdirect
|
||||||
|
|
||||||
|
import arrow.core.Option
|
||||||
import com.airbnb.epoxy.EpoxyController
|
import com.airbnb.epoxy.EpoxyController
|
||||||
import com.airbnb.mvrx.Fail
|
import com.airbnb.mvrx.*
|
||||||
import com.airbnb.mvrx.Incomplete
|
import im.vector.matrix.android.api.session.Session
|
||||||
import com.airbnb.mvrx.Success
|
|
||||||
import im.vector.matrix.android.api.session.user.model.User
|
import im.vector.matrix.android.api.session.user.model.User
|
||||||
import im.vector.matrix.android.internal.util.firstLetterOfDisplayName
|
import im.vector.matrix.android.internal.util.firstLetterOfDisplayName
|
||||||
|
import im.vector.riotx.R
|
||||||
|
import im.vector.riotx.core.epoxy.NoResultItem_
|
||||||
import im.vector.riotx.core.epoxy.errorWithRetryItem
|
import im.vector.riotx.core.epoxy.errorWithRetryItem
|
||||||
import im.vector.riotx.core.epoxy.loadingItem
|
import im.vector.riotx.core.epoxy.loadingItem
|
||||||
|
import im.vector.riotx.core.epoxy.noResultItem
|
||||||
import im.vector.riotx.core.error.ErrorFormatter
|
import im.vector.riotx.core.error.ErrorFormatter
|
||||||
|
import im.vector.riotx.core.resources.StringProvider
|
||||||
import im.vector.riotx.features.home.AvatarRenderer
|
import im.vector.riotx.features.home.AvatarRenderer
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class CreateDirectRoomController @Inject constructor(private val avatarRenderer: AvatarRenderer,
|
class CreateDirectRoomController @Inject constructor(private val session: Session,
|
||||||
|
private val avatarRenderer: AvatarRenderer,
|
||||||
|
private val stringProvider: StringProvider,
|
||||||
private val errorFormatter: ErrorFormatter) : EpoxyController() {
|
private val errorFormatter: ErrorFormatter) : EpoxyController() {
|
||||||
|
|
||||||
private var state: CreateDirectRoomViewState? = null
|
private var state: CreateDirectRoomViewState? = null
|
||||||
@ -49,14 +55,16 @@ class CreateDirectRoomController @Inject constructor(private val avatarRenderer:
|
|||||||
|
|
||||||
override fun buildModels() {
|
override fun buildModels() {
|
||||||
val currentState = state ?: return
|
val currentState = state ?: return
|
||||||
|
val hasSearch = currentState.searchTerm.isNotBlank()
|
||||||
val asyncUsers = if (displayMode == CreateDirectRoomViewState.DisplayMode.DIRECTORY_USERS) {
|
val asyncUsers = if (displayMode == CreateDirectRoomViewState.DisplayMode.DIRECTORY_USERS) {
|
||||||
currentState.directoryUsers
|
currentState.directoryUsers
|
||||||
} else {
|
} else {
|
||||||
currentState.knownUsers
|
currentState.knownUsers
|
||||||
}
|
}
|
||||||
when (asyncUsers) {
|
when (asyncUsers) {
|
||||||
is Incomplete -> renderLoading()
|
is Uninitialized -> renderEmptyState(false)
|
||||||
is Success -> renderUsers(asyncUsers(), currentState.selectedUsers.map { it.userId })
|
is Loading -> renderLoading()
|
||||||
|
is Success -> renderSuccess(asyncUsers(), currentState.selectedUsers.map { it.userId }, hasSearch)
|
||||||
is Fail -> renderFailure(asyncUsers.error)
|
is Fail -> renderFailure(asyncUsers.error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -75,9 +83,22 @@ class CreateDirectRoomController @Inject constructor(private val avatarRenderer:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun renderSuccess(users: List<User>,
|
||||||
|
selectedUsers: List<String>,
|
||||||
|
hasSearch: Boolean) {
|
||||||
|
if (users.isEmpty()) {
|
||||||
|
renderEmptyState(hasSearch)
|
||||||
|
} else {
|
||||||
|
renderUsers(users, selectedUsers)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun renderUsers(users: List<User>, selectedUsers: List<String>) {
|
private fun renderUsers(users: List<User>, selectedUsers: List<String>) {
|
||||||
var lastFirstLetter: String? = null
|
var lastFirstLetter: String? = null
|
||||||
users.forEach { user ->
|
for (user in users) {
|
||||||
|
if (user.userId == session.myUserId) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
val isSelected = selectedUsers.contains(user.userId)
|
val isSelected = selectedUsers.contains(user.userId)
|
||||||
val currentFirstLetter = user.displayName.firstLetterOfDisplayName()
|
val currentFirstLetter = user.displayName.firstLetterOfDisplayName()
|
||||||
val showLetter = currentFirstLetter.isNotEmpty() && lastFirstLetter != currentFirstLetter
|
val showLetter = currentFirstLetter.isNotEmpty() && lastFirstLetter != currentFirstLetter
|
||||||
@ -102,6 +123,22 @@ class CreateDirectRoomController @Inject constructor(private val avatarRenderer:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun renderEmptyState(hasSearch: Boolean) {
|
||||||
|
val noResultRes = if (displayMode == CreateDirectRoomViewState.DisplayMode.DIRECTORY_USERS) {
|
||||||
|
if (hasSearch) {
|
||||||
|
R.string.no_result_placeholder
|
||||||
|
} else {
|
||||||
|
R.string.direct_room_start_search
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
R.string.direct_room_no_known_users
|
||||||
|
}
|
||||||
|
noResultItem {
|
||||||
|
id("noResult")
|
||||||
|
text(stringProvider.getString(noResultRes))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
interface Callback {
|
interface Callback {
|
||||||
fun onItemClick(user: User)
|
fun onItemClick(user: User)
|
||||||
fun retryDirectoryUsersRequest() {
|
fun retryDirectoryUsersRequest() {
|
||||||
|
@ -21,6 +21,7 @@ import android.os.Bundle
|
|||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import androidx.lifecycle.ViewModelProviders
|
import androidx.lifecycle.ViewModelProviders
|
||||||
import com.airbnb.mvrx.activityViewModel
|
import com.airbnb.mvrx.activityViewModel
|
||||||
|
import com.airbnb.mvrx.withState
|
||||||
import com.jakewharton.rxbinding3.widget.textChanges
|
import com.jakewharton.rxbinding3.widget.textChanges
|
||||||
import im.vector.matrix.android.api.session.user.model.User
|
import im.vector.matrix.android.api.session.user.model.User
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
@ -50,7 +51,6 @@ class CreateDirectRoomDirectoryUsersFragment : VectorBaseFragment(), CreateDirec
|
|||||||
setupRecyclerView()
|
setupRecyclerView()
|
||||||
setupSearchByMatrixIdView()
|
setupSearchByMatrixIdView()
|
||||||
setupCloseView()
|
setupCloseView()
|
||||||
viewModel.subscribe(this) { renderState(it) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupRecyclerView() {
|
private fun setupRecyclerView() {
|
||||||
@ -61,7 +61,7 @@ class CreateDirectRoomDirectoryUsersFragment : VectorBaseFragment(), CreateDirec
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun setupSearchByMatrixIdView() {
|
private fun setupSearchByMatrixIdView() {
|
||||||
createDirectRoomSearchById.setupAsSearch()
|
createDirectRoomSearchById.setupAsSearch(searchIconRes = 0)
|
||||||
createDirectRoomSearchById
|
createDirectRoomSearchById
|
||||||
.textChanges()
|
.textChanges()
|
||||||
.subscribe {
|
.subscribe {
|
||||||
@ -80,8 +80,8 @@ class CreateDirectRoomDirectoryUsersFragment : VectorBaseFragment(), CreateDirec
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun renderState(state: CreateDirectRoomViewState) {
|
override fun invalidate() = withState(viewModel) {
|
||||||
directRoomController.setData(state)
|
directRoomController.setData(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemClick(user: User) {
|
override fun onItemClick(user: User) {
|
||||||
|
@ -71,7 +71,6 @@ class CreateDirectRoomFragment : VectorBaseFragment(), CreateDirectRoomControlle
|
|||||||
viewModel.selectSubscribe(this, CreateDirectRoomViewState::selectedUsers) {
|
viewModel.selectSubscribe(this, CreateDirectRoomViewState::selectedUsers) {
|
||||||
renderSelectedUsers(it)
|
renderSelectedUsers(it)
|
||||||
}
|
}
|
||||||
viewModel.subscribe(this) { renderState(it) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPrepareOptionsMenu(menu: Menu) {
|
override fun onPrepareOptionsMenu(menu: Menu) {
|
||||||
@ -133,8 +132,8 @@ class CreateDirectRoomFragment : VectorBaseFragment(), CreateDirectRoomControlle
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun renderState(state: CreateDirectRoomViewState) {
|
override fun invalidate() = withState(viewModel) {
|
||||||
directRoomController.setData(state)
|
directRoomController.setData(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateChipsView(data: SelectUserAction) {
|
private fun updateChipsView(data: SelectUserAction) {
|
||||||
@ -166,8 +165,8 @@ class CreateDirectRoomFragment : VectorBaseFragment(), CreateDirectRoomControlle
|
|||||||
chip.setOnCloseIconClickListener {
|
chip.setOnCloseIconClickListener {
|
||||||
viewModel.handle(CreateDirectRoomActions.RemoveSelectedUser(user))
|
viewModel.handle(CreateDirectRoomActions.RemoveSelectedUser(user))
|
||||||
}
|
}
|
||||||
chipGroupContainer.post {
|
chipGroupScrollView.post {
|
||||||
chipGroupContainer.fullScroll(ScrollView.FOCUS_DOWN)
|
chipGroupScrollView.fullScroll(ScrollView.FOCUS_DOWN)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,11 +28,14 @@ import com.squareup.inject.assisted.AssistedInject
|
|||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.matrix.android.api.session.Session
|
||||||
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
|
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
|
||||||
import im.vector.matrix.android.api.session.user.model.User
|
import im.vector.matrix.android.api.session.user.model.User
|
||||||
|
import im.vector.matrix.android.internal.util.firstLetterOfDisplayName
|
||||||
import im.vector.matrix.rx.rx
|
import im.vector.matrix.rx.rx
|
||||||
import im.vector.riotx.core.extensions.postLiveEvent
|
import im.vector.riotx.core.extensions.postLiveEvent
|
||||||
import im.vector.riotx.core.platform.VectorViewModel
|
import im.vector.riotx.core.platform.VectorViewModel
|
||||||
import im.vector.riotx.core.utils.LiveEvent
|
import im.vector.riotx.core.utils.LiveEvent
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
|
import io.reactivex.Single
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.functions.BiFunction
|
import io.reactivex.functions.BiFunction
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
@ -132,14 +135,20 @@ class CreateDirectRoomViewModel @AssistedInject constructor(@Assisted
|
|||||||
|
|
||||||
private fun observeDirectoryUsers() {
|
private fun observeDirectoryUsers() {
|
||||||
directoryUsersSearch
|
directoryUsersSearch
|
||||||
.throttleLast(500, TimeUnit.MILLISECONDS)
|
.debounce(300, TimeUnit.MILLISECONDS)
|
||||||
.switchMapSingle { search ->
|
.switchMapSingle { search ->
|
||||||
|
val stream = if (search.isBlank()) {
|
||||||
|
Single.just(emptyList())
|
||||||
|
} else {
|
||||||
session.rx()
|
session.rx()
|
||||||
.searchUsersDirectory(search, 50, emptySet())
|
.searchUsersDirectory(search, 50, emptySet())
|
||||||
.map { users ->
|
.map { users ->
|
||||||
users.sortedBy { it.displayName }
|
users.sortedBy { it.displayName.firstLetterOfDisplayName() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stream.toAsync {
|
||||||
|
copy(directoryUsers = it, searchTerm = search)
|
||||||
}
|
}
|
||||||
.toAsync { copy(directoryUsers = it) }
|
|
||||||
}
|
}
|
||||||
.subscribe()
|
.subscribe()
|
||||||
.disposeOnClear()
|
.disposeOnClear()
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
package im.vector.riotx.features.home.createdirect
|
package im.vector.riotx.features.home.createdirect
|
||||||
|
|
||||||
|
import arrow.core.Option
|
||||||
import com.airbnb.mvrx.Async
|
import com.airbnb.mvrx.Async
|
||||||
import com.airbnb.mvrx.MvRxState
|
import com.airbnb.mvrx.MvRxState
|
||||||
import com.airbnb.mvrx.Uninitialized
|
import com.airbnb.mvrx.Uninitialized
|
||||||
@ -27,7 +28,9 @@ data class CreateDirectRoomViewState(
|
|||||||
val knownUsers: Async<List<User>> = Uninitialized,
|
val knownUsers: Async<List<User>> = Uninitialized,
|
||||||
val directoryUsers: Async<List<User>> = Uninitialized,
|
val directoryUsers: Async<List<User>> = Uninitialized,
|
||||||
val selectedUsers: Set<User> = emptySet(),
|
val selectedUsers: Set<User> = emptySet(),
|
||||||
val createAndInviteState: Async<String> = Uninitialized
|
val createAndInviteState: Async<String> = Uninitialized,
|
||||||
|
val searchTerm: String = "",
|
||||||
|
val filterKnownUsersValue: Option<String> = Option.empty()
|
||||||
) : MvRxState {
|
) : MvRxState {
|
||||||
|
|
||||||
enum class DisplayMode {
|
enum class DisplayMode {
|
||||||
|
@ -44,7 +44,7 @@
|
|||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:text="@string/direct_chats_header"
|
android:text="@string/fab_menu_create_chat"
|
||||||
android:textColor="?riotx_text_primary"
|
android:textColor="?riotx_text_primary"
|
||||||
android:textSize="18sp"
|
android:textSize="18sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
@ -59,7 +59,7 @@
|
|||||||
</androidx.appcompat.widget.Toolbar>
|
</androidx.appcompat.widget.Toolbar>
|
||||||
|
|
||||||
<im.vector.riotx.core.platform.MaxHeightScrollView
|
<im.vector.riotx.core.platform.MaxHeightScrollView
|
||||||
android:id="@+id/chipGroupContainer"
|
android:id="@+id/chipGroupScrollView"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="@dimen/layout_horizontal_margin"
|
android:layout_marginStart="@dimen/layout_horizontal_margin"
|
||||||
@ -68,13 +68,13 @@
|
|||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/createDirectRoomToolbar"
|
app:layout_constraintTop_toBottomOf="@+id/createDirectRoomToolbar"
|
||||||
app:maxHeight="80dp">
|
app:maxHeight="64dp">
|
||||||
|
|
||||||
<com.google.android.material.chip.ChipGroup
|
<com.google.android.material.chip.ChipGroup
|
||||||
android:id="@+id/chipGroup"
|
android:id="@+id/chipGroup"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:lineSpacing="4dp" />
|
app:lineSpacing="2dp" />
|
||||||
|
|
||||||
</im.vector.riotx.core.platform.MaxHeightScrollView>
|
</im.vector.riotx.core.platform.MaxHeightScrollView>
|
||||||
|
|
||||||
@ -85,21 +85,23 @@
|
|||||||
android:layout_marginStart="@dimen/layout_horizontal_margin"
|
android:layout_marginStart="@dimen/layout_horizontal_margin"
|
||||||
android:layout_marginEnd="@dimen/layout_horizontal_margin"
|
android:layout_marginEnd="@dimen/layout_horizontal_margin"
|
||||||
android:background="@null"
|
android:background="@null"
|
||||||
android:hint="@string/room_directory_search_hint"
|
android:drawablePadding="8dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:hint="@string/direct_room_filter_hint"
|
||||||
android:importantForAutofill="no"
|
android:importantForAutofill="no"
|
||||||
android:maxHeight="80dp"
|
android:maxHeight="80dp"
|
||||||
android:padding="8dp"
|
android:paddingTop="16dp"
|
||||||
|
android:paddingBottom="16dp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/chipGroupContainer" />
|
app:layout_constraintTop_toBottomOf="@+id/chipGroupScrollView" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:id="@+id/createDirectRoomFilterDivider"
|
android:id="@+id/createDirectRoomFilterDivider"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="1dp"
|
android:layout_height="1dp"
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:background="?attr/vctr_list_divider_color"
|
android:background="?attr/vctr_list_divider_color"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
@ -65,7 +65,7 @@
|
|||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="@dimen/layout_horizontal_margin"
|
android:layout_marginStart="@dimen/layout_horizontal_margin"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="16dp"
|
||||||
android:layout_marginEnd="@dimen/layout_horizontal_margin"
|
android:layout_marginEnd="@dimen/layout_horizontal_margin"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
@ -74,24 +74,32 @@
|
|||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
android:id="@+id/createDirectRoomSearchById"
|
android:id="@+id/createDirectRoomSearchById"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:hint="@string/add_by_matrix_id" />
|
android:hint="@string/add_by_matrix_id" />
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/createDirectRoomFilterDivider"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:background="?attr/vctr_list_divider_color"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/createDirectRoomSearchByIdContainer" />
|
||||||
|
|
||||||
<com.airbnb.epoxy.EpoxyRecyclerView
|
<com.airbnb.epoxy.EpoxyRecyclerView
|
||||||
android:id="@+id/recyclerView"
|
android:id="@+id/recyclerView"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
android:fastScrollEnabled="true"
|
android:fastScrollEnabled="true"
|
||||||
android:scrollbars="vertical"
|
android:scrollbars="vertical"
|
||||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/createDirectRoomSearchByIdContainer"
|
app:layout_constraintTop_toBottomOf="@+id/createDirectRoomFilterDivider"
|
||||||
tools:listitem="@layout/item_create_direct_room_user" />
|
tools:listitem="@layout/item_create_direct_room_user" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
@ -3,5 +3,8 @@
|
|||||||
|
|
||||||
<!-- Strings not defined in Riot -->
|
<!-- Strings not defined in Riot -->
|
||||||
<string name="add_by_matrix_id">Add by matrix ID</string>
|
<string name="add_by_matrix_id">Add by matrix ID</string>
|
||||||
|
<string name="creating_direct_room">"Creating room…"</string>
|
||||||
|
<string name="direct_room_no_known_users">"No result found, use Add by matrix ID to search on server."</string>
|
||||||
|
<string name="direct_room_start_search">"Start typing to get results"</string>
|
||||||
|
<string name="direct_room_filter_hint">"Filter by username or ID…"</string>
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in New Issue
Block a user