mirror of
https://github.com/element-hq/element-android
synced 2024-11-24 02:15:35 +03:00
Merge pull request #3279 from vector-im/feature/bca/space_beta_people
Spaces | beta Browsing Member Directory In Space
This commit is contained in:
commit
096e95f9da
25 changed files with 926 additions and 36 deletions
|
@ -295,6 +295,7 @@
|
|||
<activity android:name=".features.spaces.SpaceExploreActivity" />
|
||||
<activity android:name=".features.spaces.SpaceCreationActivity" />
|
||||
<activity android:name=".features.spaces.manage.SpaceManageActivity" />
|
||||
<activity android:name=".features.spaces.people.SpacePeopleActivity" />
|
||||
<!-- Services -->
|
||||
|
||||
<service
|
||||
|
|
|
@ -125,6 +125,7 @@ import im.vector.app.features.spaces.create.CreateSpaceDefaultRoomsFragment
|
|||
import im.vector.app.features.spaces.create.CreateSpaceDetailsFragment
|
||||
import im.vector.app.features.spaces.explore.SpaceDirectoryFragment
|
||||
import im.vector.app.features.spaces.manage.SpaceAddRoomFragment
|
||||
import im.vector.app.features.spaces.people.SpacePeopleFragment
|
||||
import im.vector.app.features.spaces.preview.SpacePreviewFragment
|
||||
import im.vector.app.features.terms.ReviewTermsFragment
|
||||
import im.vector.app.features.usercode.ShowUserCodeFragment
|
||||
|
@ -678,4 +679,9 @@ interface FragmentModule {
|
|||
@IntoMap
|
||||
@FragmentKey(SpaceAddRoomFragment::class)
|
||||
fun bindSpaceAddRoomFragment(fragment: SpaceAddRoomFragment): Fragment
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FragmentKey(SpacePeopleFragment::class)
|
||||
fun bindSpacePeopleFragment(fragment: SpacePeopleFragment): Fragment
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ import im.vector.app.features.roomprofile.alias.detail.RoomAliasBottomSheetShare
|
|||
import im.vector.app.features.roomprofile.settings.historyvisibility.RoomHistoryVisibilitySharedActionViewModel
|
||||
import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleSharedActionViewModel
|
||||
import im.vector.app.features.spaces.SpacePreviewSharedActionViewModel
|
||||
import im.vector.app.features.spaces.people.SpacePeopleSharedActionViewModel
|
||||
import im.vector.app.features.userdirectory.UserListSharedActionViewModel
|
||||
|
||||
@Module
|
||||
|
@ -148,4 +149,9 @@ interface ViewModelModule {
|
|||
@IntoMap
|
||||
@ViewModelKey(SpacePreviewSharedActionViewModel::class)
|
||||
fun bindSpacePreviewSharedActionViewModel(viewModel: SpacePreviewSharedActionViewModel): ViewModel
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ViewModelKey(SpacePeopleSharedActionViewModel::class)
|
||||
fun bindSpacePeopleSharedActionViewModel(viewModel: SpacePeopleSharedActionViewModel): ViewModel
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package im.vector.app.core.epoxy.profiles
|
||||
|
||||
import android.view.View
|
||||
import androidx.annotation.CallSuper
|
||||
import androidx.core.view.isVisible
|
||||
import com.airbnb.epoxy.EpoxyAttribute
|
||||
import im.vector.app.core.epoxy.VectorEpoxyModel
|
||||
|
@ -34,6 +35,7 @@ abstract class BaseProfileMatrixItem<T : ProfileMatrixItem.Holder> : VectorEpoxy
|
|||
var userEncryptionTrustLevel: RoomEncryptionTrustLevel? = null
|
||||
@EpoxyAttribute var clickListener: View.OnClickListener? = null
|
||||
|
||||
@CallSuper
|
||||
override fun bind(holder: T) {
|
||||
super.bind(holder)
|
||||
val bestName = matrixItem.getBestName()
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright 2020 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.app.core.epoxy.profiles
|
||||
|
||||
import android.widget.TextView
|
||||
import androidx.core.view.isVisible
|
||||
import com.airbnb.epoxy.EpoxyAttribute
|
||||
import com.airbnb.epoxy.EpoxyModelClass
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.setTextOrHide
|
||||
|
||||
@EpoxyModelClass(layout = R.layout.item_profile_matrix_item)
|
||||
abstract class ProfileMatrixItemWithPowerLevel : BaseProfileMatrixItem<ProfileMatrixItemWithPowerLevel.Holder>() {
|
||||
|
||||
@EpoxyAttribute var powerLevelLabel: CharSequence? = null
|
||||
|
||||
override fun bind(holder: Holder) {
|
||||
super.bind(holder)
|
||||
holder.editableView.isVisible = false
|
||||
holder.powerLabel.setTextOrHide(powerLevelLabel)
|
||||
}
|
||||
|
||||
class Holder : ProfileMatrixItem.Holder() {
|
||||
val powerLabel by bind<TextView>(R.id.matrixItemPowerLevelLabel)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2021 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.app.core.platform
|
||||
|
||||
import android.os.Parcelable
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
/**
|
||||
* Generic argument with one String. Can be an id (ex: roomId, spaceId, callId, etc.), or anything else
|
||||
*/
|
||||
@Parcelize
|
||||
data class GenericIdArgs(
|
||||
val id: String
|
||||
) : Parcelable
|
|
@ -75,6 +75,7 @@ import im.vector.app.features.spaces.InviteRoomSpaceChooserBottomSheet
|
|||
import im.vector.app.features.spaces.SpaceExploreActivity
|
||||
import im.vector.app.features.spaces.SpacePreviewActivity
|
||||
import im.vector.app.features.spaces.manage.SpaceManageActivity
|
||||
import im.vector.app.features.spaces.people.SpacePeopleActivity
|
||||
import im.vector.app.features.terms.ReviewTermsActivity
|
||||
import im.vector.app.features.widgets.WidgetActivity
|
||||
import im.vector.app.features.widgets.WidgetArgsBuilder
|
||||
|
@ -283,7 +284,19 @@ class DefaultNavigator @Inject constructor(
|
|||
}
|
||||
|
||||
override fun openCreateDirectRoom(context: Context) {
|
||||
val intent = CreateDirectRoomActivity.getIntent(context)
|
||||
val intent = when (val currentGroupingMethod = appStateHandler.getCurrentRoomGroupingMethod()) {
|
||||
is RoomGroupingMethod.ByLegacyGroup -> {
|
||||
CreateDirectRoomActivity.getIntent(context)
|
||||
}
|
||||
is RoomGroupingMethod.BySpace -> {
|
||||
if (currentGroupingMethod.spaceSummary != null) {
|
||||
SpacePeopleActivity.newIntent(context, currentGroupingMethod.spaceSummary.roomId)
|
||||
} else {
|
||||
CreateDirectRoomActivity.getIntent(context)
|
||||
}
|
||||
}
|
||||
else -> null
|
||||
} ?: return
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
|
|
|
@ -47,11 +47,16 @@ class RoomMemberListFragment @Inject constructor(
|
|||
private val roomMemberListController: RoomMemberListController,
|
||||
private val avatarRenderer: AvatarRenderer
|
||||
) : VectorBaseFragment<FragmentRoomMemberListBinding>(),
|
||||
RoomMemberListController.Callback {
|
||||
RoomMemberListController.Callback,
|
||||
RoomMemberListViewModel.Factory {
|
||||
|
||||
private val viewModel: RoomMemberListViewModel by fragmentViewModel()
|
||||
private val roomProfileArgs: RoomProfileArgs by args()
|
||||
|
||||
override fun create(initialState: RoomMemberListViewState): RoomMemberListViewModel {
|
||||
return viewModelFactory.create(initialState)
|
||||
}
|
||||
|
||||
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentRoomMemberListBinding {
|
||||
return FragmentRoomMemberListBinding.inflate(inflater, container, false)
|
||||
}
|
||||
|
|
|
@ -17,12 +17,13 @@
|
|||
package im.vector.app.features.roomprofile.members
|
||||
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.airbnb.mvrx.ActivityViewModelContext
|
||||
import com.airbnb.mvrx.FragmentViewModelContext
|
||||
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||
import com.airbnb.mvrx.ViewModelContext
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedInject
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.platform.EmptyViewEvents
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
|
@ -62,8 +63,11 @@ class RoomMemberListViewModel @AssistedInject constructor(@Assisted initialState
|
|||
|
||||
@JvmStatic
|
||||
override fun create(viewModelContext: ViewModelContext, state: RoomMemberListViewState): RoomMemberListViewModel? {
|
||||
val fragment: RoomMemberListFragment = (viewModelContext as FragmentViewModelContext).fragment()
|
||||
return fragment.viewModelFactory.create(state)
|
||||
val factory = when (viewModelContext) {
|
||||
is FragmentViewModelContext -> viewModelContext.fragment as? Factory
|
||||
is ActivityViewModelContext -> viewModelContext.activity as? Factory
|
||||
}
|
||||
return factory?.create(state) ?: error("You should let your activity/fragment implements Factory interface")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import com.airbnb.mvrx.Async
|
|||
import com.airbnb.mvrx.MvRxState
|
||||
import com.airbnb.mvrx.Uninitialized
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.platform.GenericIdArgs
|
||||
import im.vector.app.features.roomprofile.RoomProfileArgs
|
||||
import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
|
@ -38,6 +39,8 @@ data class RoomMemberListViewState(
|
|||
) : MvRxState {
|
||||
|
||||
constructor(args: RoomProfileArgs) : this(roomId = args.roomId)
|
||||
|
||||
constructor(args: GenericIdArgs) : this(roomId = args.id)
|
||||
}
|
||||
|
||||
data class ActionPermissions(
|
||||
|
|
|
@ -29,9 +29,11 @@ class RoomMemberSummaryFilter @Inject constructor() : Predicate<RoomMemberSummar
|
|||
// No filter
|
||||
return true
|
||||
}
|
||||
|
||||
return roomMemberSummary.displayName?.contains(filter, ignoreCase = true).orFalse()
|
||||
// if filter is "Jo Do", it should match "John Doe"
|
||||
return filter.split(" ").all {
|
||||
roomMemberSummary.displayName?.contains(it, ignoreCase = true).orFalse()
|
||||
// We should maybe exclude the domain from the userId
|
||||
|| roomMemberSummary.userId.contains(filter, ignoreCase = true)
|
||||
|| roomMemberSummary.userId.contains(it, ignoreCase = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright (c) 2021 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.app.features.spaces.people
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.core.view.isGone
|
||||
import androidx.core.view.isVisible
|
||||
import com.airbnb.mvrx.MvRx
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.commitTransaction
|
||||
import im.vector.app.core.extensions.hideKeyboard
|
||||
import im.vector.app.core.platform.GenericIdArgs
|
||||
import im.vector.app.core.platform.VectorBaseActivity
|
||||
import im.vector.app.databinding.ActivitySimpleLoadingBinding
|
||||
import im.vector.app.features.spaces.ShareSpaceBottomSheet
|
||||
|
||||
class SpacePeopleActivity : VectorBaseActivity<ActivitySimpleLoadingBinding>() {
|
||||
|
||||
override fun getBinding() = ActivitySimpleLoadingBinding.inflate(layoutInflater)
|
||||
|
||||
private lateinit var sharedActionViewModel: SpacePeopleSharedActionViewModel
|
||||
|
||||
override fun initUiAndData() {
|
||||
super.initUiAndData()
|
||||
waitingView = views.waitingView.waitingView
|
||||
}
|
||||
|
||||
override fun showWaitingView(text: String?) {
|
||||
hideKeyboard()
|
||||
views.waitingView.waitingStatusText.isGone = views.waitingView.waitingStatusText.text.isNullOrBlank()
|
||||
super.showWaitingView(text)
|
||||
}
|
||||
|
||||
override fun hideWaitingView() {
|
||||
views.waitingView.waitingStatusText.text = null
|
||||
views.waitingView.waitingStatusText.isGone = true
|
||||
views.waitingView.waitingHorizontalProgress.progress = 0
|
||||
views.waitingView.waitingHorizontalProgress.isVisible = false
|
||||
super.hideWaitingView()
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val args = intent?.getParcelableExtra<GenericIdArgs>(MvRx.KEY_ARG)
|
||||
if (isFirstCreation()) {
|
||||
val simpleName = SpacePeopleFragment::class.java.simpleName
|
||||
if (supportFragmentManager.findFragmentByTag(simpleName) == null) {
|
||||
supportFragmentManager.commitTransaction {
|
||||
replace(R.id.simpleFragmentContainer,
|
||||
SpacePeopleFragment::class.java,
|
||||
Bundle().apply { this.putParcelable(MvRx.KEY_ARG, args) },
|
||||
simpleName
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sharedActionViewModel = viewModelProvider.get(SpacePeopleSharedActionViewModel::class.java)
|
||||
sharedActionViewModel
|
||||
.observe()
|
||||
.subscribe { sharedAction ->
|
||||
when (sharedAction) {
|
||||
SpacePeopleSharedAction.Dismiss -> finish()
|
||||
is SpacePeopleSharedAction.NavigateToRoom -> navigateToRooms(sharedAction)
|
||||
SpacePeopleSharedAction.HideModalLoading -> hideWaitingView()
|
||||
SpacePeopleSharedAction.ShowModalLoading -> {
|
||||
showWaitingView()
|
||||
}
|
||||
is SpacePeopleSharedAction.NavigateToInvite -> {
|
||||
ShareSpaceBottomSheet.show(supportFragmentManager, sharedAction.spaceId)
|
||||
}
|
||||
}
|
||||
}.disposeOnDestroy()
|
||||
}
|
||||
|
||||
private fun navigateToRooms(action: SpacePeopleSharedAction.NavigateToRoom) {
|
||||
navigator.openRoom(this, action.roomId)
|
||||
finish()
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun newIntent(context: Context, spaceId: String): Intent {
|
||||
return Intent(context, SpacePeopleActivity::class.java).apply {
|
||||
putExtra(MvRx.KEY_ARG, GenericIdArgs(spaceId))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* Copyright (c) 2021 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.app.features.spaces.people
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.Success
|
||||
import com.airbnb.mvrx.Uninitialized
|
||||
import com.airbnb.mvrx.fragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import com.jakewharton.rxbinding3.appcompat.queryTextChanges
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.cleanup
|
||||
import im.vector.app.core.extensions.configureWith
|
||||
import im.vector.app.core.platform.OnBackPressed
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.core.resources.ColorProvider
|
||||
import im.vector.app.core.resources.DrawableProvider
|
||||
import im.vector.app.databinding.FragmentRecyclerviewWithSearchBinding
|
||||
import im.vector.app.features.roomprofile.members.RoomMemberListAction
|
||||
import im.vector.app.features.roomprofile.members.RoomMemberListViewModel
|
||||
import im.vector.app.features.roomprofile.members.RoomMemberListViewState
|
||||
import io.reactivex.rxkotlin.subscribeBy
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
class SpacePeopleFragment @Inject constructor(
|
||||
private val viewModelFactory: SpacePeopleViewModel.Factory,
|
||||
private val roomMemberModelFactory: RoomMemberListViewModel.Factory,
|
||||
private val drawableProvider: DrawableProvider,
|
||||
private val colorProvider: ColorProvider,
|
||||
private val epoxyController: SpacePeopleListController
|
||||
) : VectorBaseFragment<FragmentRecyclerviewWithSearchBinding>(),
|
||||
SpacePeopleViewModel.Factory,
|
||||
RoomMemberListViewModel.Factory,
|
||||
OnBackPressed, SpacePeopleListController.InteractionListener {
|
||||
|
||||
private val viewModel by fragmentViewModel(SpacePeopleViewModel::class)
|
||||
private val membersViewModel by fragmentViewModel(RoomMemberListViewModel::class)
|
||||
private lateinit var sharedActionViewModel: SpacePeopleSharedActionViewModel
|
||||
|
||||
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?) =
|
||||
FragmentRecyclerviewWithSearchBinding.inflate(inflater, container, false)
|
||||
|
||||
override fun onBackPressed(toolbarButton: Boolean): Boolean {
|
||||
sharedActionViewModel.post(SpacePeopleSharedAction.Dismiss)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun create(initialState: SpacePeopleViewState): SpacePeopleViewModel {
|
||||
return viewModelFactory.create(initialState)
|
||||
}
|
||||
|
||||
override fun create(initialState: RoomMemberListViewState): RoomMemberListViewModel {
|
||||
return roomMemberModelFactory.create(initialState)
|
||||
}
|
||||
|
||||
override fun invalidate() = withState(membersViewModel) { memberListState ->
|
||||
views.appBarTitle.text = getString(R.string.bottom_action_people)
|
||||
val memberCount = (memberListState.roomSummary.invoke()?.otherMemberIds?.size ?: 0) + 1
|
||||
views.appBarSpaceInfo.text = resources.getQuantityString(R.plurals.room_title_members, memberCount, memberCount)
|
||||
// views.listBuildingProgress.isVisible = true
|
||||
epoxyController.setData(memberListState)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
sharedActionViewModel = activityViewModelProvider.get(SpacePeopleSharedActionViewModel::class.java)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setupRecyclerView()
|
||||
setupSearchView()
|
||||
|
||||
views.addRoomToSpaceToolbar.navigationIcon = drawableProvider.getDrawable(
|
||||
R.drawable.ic_close_24dp,
|
||||
colorProvider.getColorFromAttribute(R.attr.riot_primary_text_color)
|
||||
)
|
||||
views.addRoomToSpaceToolbar.setNavigationOnClickListener {
|
||||
sharedActionViewModel.post(SpacePeopleSharedAction.Dismiss)
|
||||
}
|
||||
|
||||
viewModel.observeViewEvents {
|
||||
handleViewEvents(it)
|
||||
}
|
||||
|
||||
viewModel.subscribe(this) {
|
||||
when (it.createAndInviteState) {
|
||||
is Loading -> sharedActionViewModel.post(SpacePeopleSharedAction.ShowModalLoading)
|
||||
Uninitialized,
|
||||
is Fail -> sharedActionViewModel.post(SpacePeopleSharedAction.HideModalLoading)
|
||||
is Success -> {
|
||||
// don't hide on success, it will navigate out. If not the loading goes out before navigation
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
epoxyController.listener = null
|
||||
views.roomList.cleanup()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
private fun setupRecyclerView() {
|
||||
views.roomList.configureWith(epoxyController, hasFixedSize = false, disableItemAnimation = false)
|
||||
epoxyController.listener = this
|
||||
}
|
||||
|
||||
private fun setupSearchView() {
|
||||
views.memberNameFilter.queryHint = getString(R.string.search_members_hint)
|
||||
views.memberNameFilter.queryTextChanges()
|
||||
.debounce(100, TimeUnit.MILLISECONDS)
|
||||
.subscribeBy {
|
||||
membersViewModel.handle(RoomMemberListAction.FilterMemberList(it.toString()))
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
}
|
||||
|
||||
private fun handleViewEvents(events: SpacePeopleViewEvents) {
|
||||
when (events) {
|
||||
is SpacePeopleViewEvents.OpenRoom -> {
|
||||
sharedActionViewModel.post(SpacePeopleSharedAction.NavigateToRoom(events.roomId))
|
||||
}
|
||||
is SpacePeopleViewEvents.InviteToSpace -> {
|
||||
sharedActionViewModel.post(SpacePeopleSharedAction.NavigateToInvite(events.spaceId))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSpaceMemberClicked(roomMemberSummary: RoomMemberSummary) {
|
||||
viewModel.handle(SpacePeopleViewAction.ChatWith(roomMemberSummary))
|
||||
}
|
||||
|
||||
override fun onInviteToSpaceSelected() {
|
||||
viewModel.handle(SpacePeopleViewAction.InviteToSpace)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* Copyright (c) 2021 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.app.features.spaces.people
|
||||
|
||||
import com.airbnb.epoxy.TypedEpoxyController
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.epoxy.dividerItem
|
||||
import im.vector.app.core.epoxy.loadingItem
|
||||
import im.vector.app.core.epoxy.profiles.profileMatrixItemWithPowerLevel
|
||||
import im.vector.app.core.extensions.join
|
||||
import im.vector.app.core.resources.ColorProvider
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import im.vector.app.core.ui.list.GenericItem
|
||||
import im.vector.app.core.ui.list.genericItem
|
||||
import im.vector.app.core.utils.DimensionConverter
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
import im.vector.app.features.roomprofile.members.RoomMemberListCategories
|
||||
import im.vector.app.features.roomprofile.members.RoomMemberListViewState
|
||||
import im.vector.app.features.roomprofile.members.RoomMemberSummaryFilter
|
||||
import me.gujun.android.span.span
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||
import javax.inject.Inject
|
||||
|
||||
class SpacePeopleListController @Inject constructor(
|
||||
private val avatarRenderer: AvatarRenderer,
|
||||
private val colorProvider: ColorProvider,
|
||||
private val stringProvider: StringProvider,
|
||||
private val dimensionConverter: DimensionConverter,
|
||||
private val roomMemberSummaryFilter: RoomMemberSummaryFilter
|
||||
) : TypedEpoxyController<RoomMemberListViewState>() {
|
||||
|
||||
private val dividerColor = colorProvider.getColorFromAttribute(R.attr.vctr_list_divider_color)
|
||||
|
||||
interface InteractionListener {
|
||||
fun onSpaceMemberClicked(roomMemberSummary: RoomMemberSummary)
|
||||
fun onInviteToSpaceSelected()
|
||||
}
|
||||
|
||||
var listener: InteractionListener? = null
|
||||
|
||||
init {
|
||||
setData(null)
|
||||
}
|
||||
|
||||
override fun buildModels(data: RoomMemberListViewState?) {
|
||||
val memberSummaries = data?.roomMemberSummaries?.invoke()
|
||||
if (memberSummaries == null) {
|
||||
loadingItem { id("loading") }
|
||||
return
|
||||
}
|
||||
roomMemberSummaryFilter.filter = data.filter
|
||||
var foundCount = 0
|
||||
memberSummaries.forEach { memberEntry ->
|
||||
|
||||
val filtered = memberEntry.second
|
||||
.filter { roomMemberSummaryFilter.test(it) }
|
||||
if (filtered.isNotEmpty()) {
|
||||
dividerItem {
|
||||
id("divider_type_${memberEntry.first.titleRes}")
|
||||
color(dividerColor)
|
||||
}
|
||||
}
|
||||
foundCount += filtered.size
|
||||
filtered
|
||||
.join(
|
||||
each = { _, roomMember ->
|
||||
profileMatrixItemWithPowerLevel {
|
||||
id(roomMember.userId)
|
||||
matrixItem(roomMember.toMatrixItem())
|
||||
avatarRenderer(avatarRenderer)
|
||||
userEncryptionTrustLevel(data.trustLevelMap.invoke()?.get(roomMember.userId))
|
||||
.apply {
|
||||
val pl = memberEntry.first.toPowerLevelLabel()
|
||||
if (memberEntry.first == RoomMemberListCategories.INVITE) {
|
||||
powerLevelLabel(
|
||||
span {
|
||||
span(stringProvider.getString(R.string.invited)) {
|
||||
textColor = colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
|
||||
textStyle = "bold"
|
||||
// fontFamily = "monospace"
|
||||
}
|
||||
}
|
||||
)
|
||||
} else if (pl != null) {
|
||||
powerLevelLabel(
|
||||
span {
|
||||
span(" $pl ") {
|
||||
backgroundColor = colorProvider.getColor(R.color.notification_accent_color)
|
||||
paddingTop = dimensionConverter.dpToPx(2)
|
||||
paddingBottom = dimensionConverter.dpToPx(2)
|
||||
textColor = colorProvider.getColor(R.color.white)
|
||||
textStyle = "bold"
|
||||
// fontFamily = "monospace"
|
||||
}
|
||||
}
|
||||
)
|
||||
} else {
|
||||
powerLevelLabel(null)
|
||||
}
|
||||
}
|
||||
|
||||
clickListener { _ ->
|
||||
listener?.onSpaceMemberClicked(roomMember)
|
||||
}
|
||||
}
|
||||
},
|
||||
between = { _, roomMemberBefore ->
|
||||
dividerItem {
|
||||
id("divider_${roomMemberBefore.userId}")
|
||||
color(dividerColor)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (foundCount == 0 && data.filter.isNotEmpty()) {
|
||||
// add the footer thing
|
||||
genericItem {
|
||||
id("not_found")
|
||||
title(
|
||||
span {
|
||||
+"\n"
|
||||
+stringProvider.getString(R.string.no_result_placeholder)
|
||||
}
|
||||
)
|
||||
description(
|
||||
span {
|
||||
+stringProvider.getString(R.string.looking_for_someone_not_in_space, data.roomSummary.invoke()?.displayName ?: "")
|
||||
+"\n"
|
||||
span("Invite them") {
|
||||
textColor = colorProvider.getColorFromAttribute(R.attr.colorAccent)
|
||||
textStyle = "bold"
|
||||
}
|
||||
}
|
||||
)
|
||||
itemClickAction(GenericItem.Action("invite").apply {
|
||||
perform = Runnable {
|
||||
listener?.onInviteToSpaceSelected()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun RoomMemberListCategories.toPowerLevelLabel(): String? {
|
||||
return when (this) {
|
||||
RoomMemberListCategories.ADMIN -> stringProvider.getString(R.string.power_level_admin)
|
||||
RoomMemberListCategories.MODERATOR -> stringProvider.getString(R.string.power_level_moderator)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2021 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.app.features.spaces.people
|
||||
|
||||
import im.vector.app.core.platform.VectorSharedAction
|
||||
|
||||
sealed class SpacePeopleSharedAction : VectorSharedAction {
|
||||
object Dismiss : SpacePeopleSharedAction()
|
||||
object ShowModalLoading : SpacePeopleSharedAction()
|
||||
object HideModalLoading : SpacePeopleSharedAction()
|
||||
data class NavigateToRoom(val roomId: String) : SpacePeopleSharedAction()
|
||||
data class NavigateToInvite(val spaceId: String) : SpacePeopleSharedAction()
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright (c) 2021 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.app.features.spaces.people
|
||||
|
||||
import im.vector.app.core.platform.VectorSharedActionViewModel
|
||||
import javax.inject.Inject
|
||||
|
||||
class SpacePeopleSharedActionViewModel @Inject constructor() : VectorSharedActionViewModel<SpacePeopleSharedAction>()
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) 2021 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.app.features.spaces.people
|
||||
|
||||
import im.vector.app.core.platform.VectorViewModelAction
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||
|
||||
sealed class SpacePeopleViewAction : VectorViewModelAction {
|
||||
data class ChatWith(val member: RoomMemberSummary) : SpacePeopleViewAction()
|
||||
object InviteToSpace : SpacePeopleViewAction()
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (c) 2021 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.app.features.spaces.people
|
||||
|
||||
import im.vector.app.core.platform.VectorViewEvents
|
||||
|
||||
sealed class SpacePeopleViewEvents : VectorViewEvents {
|
||||
data class OpenRoom(val roomId: String) : SpacePeopleViewEvents()
|
||||
data class InviteToSpace(val spaceId: String) : SpacePeopleViewEvents()
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright (c) 2021 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.app.features.spaces.people
|
||||
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.airbnb.mvrx.ActivityViewModelContext
|
||||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.FragmentViewModelContext
|
||||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||
import com.airbnb.mvrx.Success
|
||||
import com.airbnb.mvrx.ViewModelContext
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.features.raw.wellknown.getElementWellknown
|
||||
import im.vector.app.features.raw.wellknown.isE2EByDefault
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.android.sdk.api.raw.RawService
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||
|
||||
class SpacePeopleViewModel @AssistedInject constructor(
|
||||
@Assisted val initialState: SpacePeopleViewState,
|
||||
private val rawService: RawService,
|
||||
private val session: Session
|
||||
) : VectorViewModel<SpacePeopleViewState, SpacePeopleViewAction, SpacePeopleViewEvents>(initialState) {
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(initialState: SpacePeopleViewState): SpacePeopleViewModel
|
||||
}
|
||||
|
||||
companion object : MvRxViewModelFactory<SpacePeopleViewModel, SpacePeopleViewState> {
|
||||
override fun create(viewModelContext: ViewModelContext, state: SpacePeopleViewState): SpacePeopleViewModel? {
|
||||
val factory = when (viewModelContext) {
|
||||
is FragmentViewModelContext -> viewModelContext.fragment as? Factory
|
||||
is ActivityViewModelContext -> viewModelContext.activity as? Factory
|
||||
}
|
||||
return factory?.create(state) ?: error("You should let your activity/fragment implements Factory interface")
|
||||
}
|
||||
}
|
||||
|
||||
override fun handle(action: SpacePeopleViewAction) {
|
||||
when (action) {
|
||||
is SpacePeopleViewAction.ChatWith -> handleChatWith(action)
|
||||
SpacePeopleViewAction.InviteToSpace -> handleInviteToSpace()
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
private fun handleInviteToSpace() {
|
||||
_viewEvents.post(SpacePeopleViewEvents.InviteToSpace(initialState.spaceId))
|
||||
}
|
||||
|
||||
private fun handleChatWith(action: SpacePeopleViewAction.ChatWith) {
|
||||
val otherUserId = action.member.userId
|
||||
if (otherUserId == session.myUserId) return
|
||||
val existingRoomId = session.getExistingDirectRoomWithUser(otherUserId)
|
||||
if (existingRoomId != null) {
|
||||
// just open it
|
||||
_viewEvents.post(SpacePeopleViewEvents.OpenRoom(existingRoomId))
|
||||
return
|
||||
}
|
||||
setState { copy(createAndInviteState = Loading()) }
|
||||
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val adminE2EByDefault = rawService.getElementWellknown(session.myUserId)
|
||||
?.isE2EByDefault()
|
||||
?: true
|
||||
|
||||
val roomParams = CreateRoomParams()
|
||||
.apply {
|
||||
invitedUserIds.add(otherUserId)
|
||||
setDirectMessage()
|
||||
enableEncryptionIfInvitedUsersSupportIt = adminE2EByDefault
|
||||
}
|
||||
|
||||
try {
|
||||
val roomId = session.createRoom(roomParams)
|
||||
_viewEvents.post(SpacePeopleViewEvents.OpenRoom(roomId))
|
||||
setState { copy(createAndInviteState = Success(roomId)) }
|
||||
} catch (failure: Throwable) {
|
||||
setState { copy(createAndInviteState = Fail(failure)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2021 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.app.features.spaces.people
|
||||
|
||||
import com.airbnb.mvrx.Async
|
||||
import com.airbnb.mvrx.MvRxState
|
||||
import com.airbnb.mvrx.Uninitialized
|
||||
import im.vector.app.core.platform.GenericIdArgs
|
||||
|
||||
data class SpacePeopleViewState(
|
||||
val spaceId: String,
|
||||
val createAndInviteState: Async<String> = Uninitialized
|
||||
) : MvRxState {
|
||||
constructor(args: GenericIdArgs) : this(
|
||||
spaceId = args.id
|
||||
)
|
||||
}
|
17
vector/src/main/res/layout/activity_simple_loading.xml
Normal file
17
vector/src/main/res/layout/activity_simple_loading.xml
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/coordinatorLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/simpleFragmentContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<include
|
||||
android:id="@+id/waiting_view"
|
||||
layout="@layout/merge_overlay_waiting_view" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -0,0 +1,96 @@
|
|||
<?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"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/coordinatorLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?riotx_background">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/roomList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?riotx_background"
|
||||
android:overScrollMode="always"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
tools:listitem="@layout/item_profile_matrix_item" />
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
style="@style/VectorAppBarLayoutStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:elevation="4dp">
|
||||
|
||||
<!-- minHeight="0dp" is important to collapse on scroll -->
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/addRoomToSpaceToolbar"
|
||||
style="@style/VectorToolbarStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:elevation="4dp"
|
||||
android:minHeight="0dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap|enterAlways">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical|start"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/appBarTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:ellipsize="end"
|
||||
android:gravity="start|center"
|
||||
android:maxLines="1"
|
||||
android:textColor="?riotx_text_primary"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
tools:text="@tools:sample/lorem/random" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/appBarSpaceInfo"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:ellipsize="end"
|
||||
android:gravity="start|center"
|
||||
android:maxLines="1"
|
||||
android:textColor="?riotx_text_secondary"
|
||||
android:textSize="16sp"
|
||||
tools:text="@tools:sample/lorem/random" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
|
||||
|
||||
<androidx.appcompat.widget.SearchView
|
||||
android:id="@+id/memberNameFilter"
|
||||
style="@style/VectorSearchView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/addRoomToSpaceToolbar"
|
||||
app:queryHint="@string/search_hint_room_name" />
|
||||
|
||||
<!-- <ProgressBar-->
|
||||
<!-- android:id="@+id/listBuildingProgress"-->
|
||||
<!-- android:indeterminate="true"-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:layout_height="8dp"-->
|
||||
<!-- style="@style/Widget.AppCompat.ProgressBar.Horizontal"-->
|
||||
<!-- />-->
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -37,44 +37,53 @@
|
|||
|
||||
<TextView
|
||||
android:id="@+id/matrixItemTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:drawablePadding="16dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?riotx_text_primary"
|
||||
android:textSize="16sp"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintBottom_toTopOf="@+id/matrixItemSubtitle"
|
||||
app:layout_constraintEnd_toStartOf="@+id/matrixItemEditable"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintEnd_toStartOf="@+id/matrixItemPowerLevelLabel"
|
||||
app:layout_constraintStart_toEndOf="@id/matrixItemAvatar"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_goneMarginStart="0dp"
|
||||
app:layout_goneMarginEnd="80dp"
|
||||
tools:text="@sample/matrix.json/data/displayName" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/matrixItemSubtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:drawablePadding="16dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?riotx_text_secondary"
|
||||
android:textSize="12sp"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/matrixItemEditable"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintEnd_toStartOf="@+id/matrixItemPowerLevelLabel"
|
||||
app:layout_constraintStart_toEndOf="@id/matrixItemAvatar"
|
||||
app:layout_constraintTop_toBottomOf="@id/matrixItemTitle"
|
||||
app:layout_goneMarginStart="0dp"
|
||||
app:layout_goneMarginEnd="8dp"
|
||||
tools:text="@sample/matrix.json/data/mxid" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/matrixItemPowerLevelLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:textSize="12sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/matrixItemEditable"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Admin"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/matrixItemEditable"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -87,5 +96,4 @@
|
|||
app:tint="?riotx_text_secondary"
|
||||
tools:ignore="MissingPrefix" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
|
@ -37,11 +37,10 @@
|
|||
|
||||
<TextView
|
||||
android:id="@+id/matrixItemTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:drawablePadding="16dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?riotx_text_primary"
|
||||
|
@ -49,19 +48,17 @@
|
|||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintBottom_toTopOf="@+id/matrixItemSubtitle"
|
||||
app:layout_constraintEnd_toStartOf="@+id/matrixItemProgress"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toEndOf="@id/matrixItemAvatar"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_goneMarginStart="0dp"
|
||||
app:layout_goneMarginEnd="80dp"
|
||||
tools:text="@sample/matrix.json/data/displayName" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/matrixItemSubtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:drawablePadding="16dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?riotx_text_secondary"
|
||||
|
@ -69,10 +66,9 @@
|
|||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/matrixItemProgress"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toEndOf="@id/matrixItemAvatar"
|
||||
app:layout_constraintTop_toBottomOf="@id/matrixItemTitle"
|
||||
app:layout_goneMarginStart="0dp"
|
||||
app:layout_goneMarginEnd="8dp"
|
||||
tools:text="@sample/matrix.json/data/mxid" />
|
||||
|
||||
<ProgressBar
|
||||
|
@ -93,12 +89,10 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/ic_arrow_right"
|
||||
android:visibility="visible"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:tint="?riotx_text_secondary"
|
||||
tools:ignore="MissingPrefix"
|
||||
tools:visibility="visible" />
|
||||
tools:ignore="MissingPrefix" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
|
@ -3353,4 +3353,6 @@
|
|||
<string name="labs_use_restricted_join_rule">Experimental Space - Restricted Room.</string>
|
||||
<string name="labs_use_restricted_join_rule_desc">Warning requires server support and experimental room version</string>
|
||||
<string name="user_invites_you">%s invites you</string>
|
||||
|
||||
<string name="looking_for_someone_not_in_space">Looking for someone not in %s?</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in a new issue