mirror of
https://github.com/vector-im/riotX-android
synced 2025-10-06 00:02:48 +02:00
Compare commits
4 Commits
v1.3.13
...
feature/_e
Author | SHA1 | Date | |
---|---|---|---|
|
071db7a4d8 | ||
|
2c747cc847 | ||
|
87322ce8b0 | ||
|
5286e6983c |
@@ -112,7 +112,7 @@ android {
|
||||
ndkVersion "21.3.6528147"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "im.vector.app"
|
||||
applicationId "im.vector.app.grid"
|
||||
// Set to API 21: see #405
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 29
|
||||
@@ -186,7 +186,7 @@ android {
|
||||
buildTypes {
|
||||
debug {
|
||||
applicationIdSuffix ".debug"
|
||||
resValue "string", "app_name", "Element dbg"
|
||||
resValue "string", "app_name", "Element Grid"
|
||||
|
||||
resValue "bool", "debug_mode", "true"
|
||||
buildConfigField "boolean", "LOW_PRIVACY_LOG_ENABLE", "false"
|
||||
@@ -195,7 +195,7 @@ android {
|
||||
}
|
||||
|
||||
release {
|
||||
resValue "string", "app_name", "Element (Riot.im)"
|
||||
resValue "string", "app_name", "Element Grid"
|
||||
|
||||
resValue "bool", "debug_mode", "false"
|
||||
buildConfigField "boolean", "LOW_PRIVACY_LOG_ENABLE", "false"
|
||||
|
@@ -10,7 +10,7 @@
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:912726360885:android:4ef8f3a0021e774d",
|
||||
"android_client_info": {
|
||||
"package_name": "im.vector.app.debug"
|
||||
"package_name": "im.vector.app.grid.debug"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
|
@@ -10,7 +10,7 @@
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:912726360885:android:4ef8f3a0021e774d",
|
||||
"android_client_info": {
|
||||
"package_name": "im.vector.app"
|
||||
"package_name": "im.vector.app.grid"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
|
@@ -17,9 +17,11 @@
|
||||
package im.vector.app.features.home.room.list
|
||||
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.drawable.DrawableCompat
|
||||
import androidx.core.view.isVisible
|
||||
import com.airbnb.epoxy.EpoxyAttribute
|
||||
import com.airbnb.epoxy.EpoxyModelClass
|
||||
import im.vector.app.R
|
||||
@@ -32,8 +34,11 @@ abstract class RoomCategoryItem : VectorEpoxyModel<RoomCategoryItem.Holder>() {
|
||||
|
||||
@EpoxyAttribute lateinit var title: CharSequence
|
||||
@EpoxyAttribute var expanded: Boolean = false
|
||||
@EpoxyAttribute var mode: RoomListViewState.CategoryMode = RoomListViewState.CategoryMode.List
|
||||
@EpoxyAttribute var unreadNotificationCount: Int = 0
|
||||
@EpoxyAttribute var showHighlighted: Boolean = false
|
||||
@EpoxyAttribute var showSwitchMode: Boolean = true
|
||||
@EpoxyAttribute var changeModeListener: ((RoomListViewState.CategoryMode) -> Unit)? = null
|
||||
@EpoxyAttribute var listener: (() -> Unit)? = null
|
||||
|
||||
override fun bind(holder: Holder) {
|
||||
@@ -47,11 +52,32 @@ abstract class RoomCategoryItem : VectorEpoxyModel<RoomCategoryItem.Holder>() {
|
||||
holder.titleView.setCompoundDrawablesWithIntrinsicBounds(null, null, expandedArrowDrawable, null)
|
||||
holder.titleView.text = title
|
||||
holder.rootView.setOnClickListener { listener?.invoke() }
|
||||
|
||||
if (showSwitchMode && expanded) {
|
||||
holder.modeSwitch.isVisible = true
|
||||
holder.modeSwitch.setImageResource(
|
||||
when (mode) {
|
||||
RoomListViewState.CategoryMode.Grid -> R.drawable.ic_mode_grid_24dp
|
||||
RoomListViewState.CategoryMode.List -> R.drawable.ic_mode_list_24dp
|
||||
}
|
||||
)
|
||||
holder.modeSwitch.setOnClickListener {
|
||||
changeModeListener?.invoke(
|
||||
when (mode) {
|
||||
RoomListViewState.CategoryMode.Grid -> RoomListViewState.CategoryMode.List
|
||||
RoomListViewState.CategoryMode.List -> RoomListViewState.CategoryMode.Grid
|
||||
}
|
||||
)
|
||||
}
|
||||
} else {
|
||||
holder.modeSwitch.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
class Holder : VectorEpoxyHolder() {
|
||||
val unreadCounterBadgeView by bind<UnreadCounterBadgeView>(R.id.roomCategoryUnreadCounterBadgeView)
|
||||
val titleView by bind<TextView>(R.id.roomCategoryTitleView)
|
||||
val modeSwitch by bind<ImageView>(R.id.roomCategoryMode)
|
||||
val rootView by bind<ViewGroup>(R.id.roomCategoryRootView)
|
||||
}
|
||||
}
|
||||
|
@@ -23,6 +23,7 @@ import org.matrix.android.sdk.api.session.room.notification.RoomNotificationStat
|
||||
sealed class RoomListAction : VectorViewModelAction {
|
||||
data class SelectRoom(val roomSummary: RoomSummary) : RoomListAction()
|
||||
data class ToggleCategory(val category: RoomCategory) : RoomListAction()
|
||||
data class ChangeCategoryMode(val category: RoomCategory, val newCategoryMode: RoomListViewState.CategoryMode) : RoomListAction()
|
||||
data class AcceptInvitation(val roomSummary: RoomSummary) : RoomListAction()
|
||||
data class RejectInvitation(val roomSummary: RoomSummary) : RoomListAction()
|
||||
data class FilterWith(val filter: String) : RoomListAction()
|
||||
|
@@ -18,13 +18,14 @@ package im.vector.app.features.home.room.list
|
||||
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import android.util.DisplayMetrics
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.airbnb.epoxy.OnModelBuildFinishedListener
|
||||
import com.airbnb.mvrx.Fail
|
||||
@@ -40,6 +41,7 @@ import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.platform.OnBackPressed
|
||||
import im.vector.app.core.platform.StateView
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.core.utils.DimensionConverter
|
||||
import im.vector.app.features.home.RoomListDisplayMode
|
||||
import im.vector.app.features.home.room.list.actions.RoomListActionsArgs
|
||||
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsBottomSheet
|
||||
@@ -47,12 +49,13 @@ import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedA
|
||||
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel
|
||||
import im.vector.app.features.home.room.list.widget.FabMenuView
|
||||
import im.vector.app.features.notifications.NotificationDrawerManager
|
||||
import im.vector.app.features.roomprofile.uploads.media.IMAGE_SIZE_DP
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import kotlinx.android.synthetic.main.fragment_room_list.*
|
||||
import org.matrix.android.sdk.api.failure.Failure
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import kotlinx.android.synthetic.main.fragment_room_list.*
|
||||
import javax.inject.Inject
|
||||
|
||||
@Parcelize
|
||||
@@ -64,8 +67,8 @@ class RoomListFragment @Inject constructor(
|
||||
private val roomController: RoomSummaryController,
|
||||
val roomListViewModelFactory: RoomListViewModel.Factory,
|
||||
private val notificationDrawerManager: NotificationDrawerManager,
|
||||
private val sharedViewPool: RecyclerView.RecycledViewPool
|
||||
|
||||
private val sharedViewPool: RecyclerView.RecycledViewPool,
|
||||
private val dimensionConverter: DimensionConverter
|
||||
) : VectorBaseFragment(), RoomSummaryController.Listener, OnBackPressed, FabMenuView.Listener {
|
||||
|
||||
private var modelBuildListener: OnModelBuildFinishedListener? = null
|
||||
@@ -103,10 +106,10 @@ class RoomListFragment @Inject constructor(
|
||||
sharedActionViewModel = activityViewModelProvider.get(RoomListQuickActionsSharedActionViewModel::class.java)
|
||||
roomListViewModel.observeViewEvents {
|
||||
when (it) {
|
||||
is RoomListViewEvents.Loading -> showLoading(it.message)
|
||||
is RoomListViewEvents.Failure -> showFailure(it.throwable)
|
||||
is RoomListViewEvents.Loading -> showLoading(it.message)
|
||||
is RoomListViewEvents.Failure -> showFailure(it.throwable)
|
||||
is RoomListViewEvents.SelectRoom -> handleSelectRoom(it)
|
||||
is RoomListViewEvents.Done -> Unit
|
||||
is RoomListViewEvents.Done -> Unit
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
@@ -139,9 +142,9 @@ class RoomListFragment @Inject constructor(
|
||||
private fun setupCreateRoomButton() {
|
||||
when (roomListParams.displayMode) {
|
||||
RoomListDisplayMode.NOTIFICATIONS -> createChatFabMenu.isVisible = true
|
||||
RoomListDisplayMode.PEOPLE -> createChatRoomButton.isVisible = true
|
||||
RoomListDisplayMode.ROOMS -> createGroupRoomButton.isVisible = true
|
||||
else -> Unit // No button in this mode
|
||||
RoomListDisplayMode.PEOPLE -> createChatRoomButton.isVisible = true
|
||||
RoomListDisplayMode.ROOMS -> createGroupRoomButton.isVisible = true
|
||||
else -> Unit // No button in this mode
|
||||
}
|
||||
|
||||
createChatRoomButton.debouncedClicks {
|
||||
@@ -166,8 +169,8 @@ class RoomListFragment @Inject constructor(
|
||||
when (roomListParams.displayMode) {
|
||||
RoomListDisplayMode.NOTIFICATIONS -> createChatFabMenu.hide()
|
||||
RoomListDisplayMode.PEOPLE -> createChatRoomButton.hide()
|
||||
RoomListDisplayMode.ROOMS -> createGroupRoomButton.hide()
|
||||
else -> Unit
|
||||
RoomListDisplayMode.ROOMS -> createGroupRoomButton.hide()
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -191,7 +194,8 @@ class RoomListFragment @Inject constructor(
|
||||
}
|
||||
|
||||
private fun setupRecyclerView() {
|
||||
val layoutManager = LinearLayoutManager(context)
|
||||
val numOfColumns = getNumberOfColumns()
|
||||
val layoutManager = GridLayoutManager(context, numOfColumns)
|
||||
stateRestorer = LayoutManagerStateRestorer(layoutManager).register()
|
||||
roomListView.layoutManager = layoutManager
|
||||
roomListView.itemAnimator = RoomListAnimator()
|
||||
@@ -202,40 +206,49 @@ class RoomListFragment @Inject constructor(
|
||||
roomController.addModelBuildListener(modelBuildListener)
|
||||
roomListView.adapter = roomController.adapter
|
||||
stateView.contentView = roomListView
|
||||
|
||||
roomController.spanCount = numOfColumns
|
||||
layoutManager.spanSizeLookup = roomController.spanSizeLookup
|
||||
}
|
||||
|
||||
private fun getNumberOfColumns(): Int {
|
||||
val displayMetrics = DisplayMetrics()
|
||||
requireActivity().windowManager.defaultDisplay.getMetrics(displayMetrics)
|
||||
return dimensionConverter.pxToDp(displayMetrics.widthPixels) / ITEM_SIZE_DP
|
||||
}
|
||||
|
||||
private val showFabRunnable = Runnable {
|
||||
if (isAdded) {
|
||||
when (roomListParams.displayMode) {
|
||||
RoomListDisplayMode.NOTIFICATIONS -> createChatFabMenu.show()
|
||||
RoomListDisplayMode.PEOPLE -> createChatRoomButton.show()
|
||||
RoomListDisplayMode.ROOMS -> createGroupRoomButton.show()
|
||||
else -> Unit
|
||||
RoomListDisplayMode.PEOPLE -> createChatRoomButton.show()
|
||||
RoomListDisplayMode.ROOMS -> createGroupRoomButton.show()
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleQuickActions(quickAction: RoomListQuickActionsSharedAction) {
|
||||
when (quickAction) {
|
||||
is RoomListQuickActionsSharedAction.NotificationsAllNoisy -> {
|
||||
is RoomListQuickActionsSharedAction.NotificationsAllNoisy -> {
|
||||
roomListViewModel.handle(RoomListAction.ChangeRoomNotificationState(quickAction.roomId, RoomNotificationState.ALL_MESSAGES_NOISY))
|
||||
}
|
||||
is RoomListQuickActionsSharedAction.NotificationsAll -> {
|
||||
is RoomListQuickActionsSharedAction.NotificationsAll -> {
|
||||
roomListViewModel.handle(RoomListAction.ChangeRoomNotificationState(quickAction.roomId, RoomNotificationState.ALL_MESSAGES))
|
||||
}
|
||||
is RoomListQuickActionsSharedAction.NotificationsMentionsOnly -> {
|
||||
roomListViewModel.handle(RoomListAction.ChangeRoomNotificationState(quickAction.roomId, RoomNotificationState.MENTIONS_ONLY))
|
||||
}
|
||||
is RoomListQuickActionsSharedAction.NotificationsMute -> {
|
||||
is RoomListQuickActionsSharedAction.NotificationsMute -> {
|
||||
roomListViewModel.handle(RoomListAction.ChangeRoomNotificationState(quickAction.roomId, RoomNotificationState.MUTE))
|
||||
}
|
||||
is RoomListQuickActionsSharedAction.Settings -> {
|
||||
is RoomListQuickActionsSharedAction.Settings -> {
|
||||
navigator.openRoomProfile(requireActivity(), quickAction.roomId)
|
||||
}
|
||||
is RoomListQuickActionsSharedAction.Favorite -> {
|
||||
is RoomListQuickActionsSharedAction.Favorite -> {
|
||||
roomListViewModel.handle(RoomListAction.ToggleFavorite(quickAction.roomId))
|
||||
}
|
||||
is RoomListQuickActionsSharedAction.Leave -> {
|
||||
is RoomListQuickActionsSharedAction.Leave -> {
|
||||
AlertDialog.Builder(requireContext())
|
||||
.setTitle(R.string.room_participants_leave_prompt_title)
|
||||
.setMessage(R.string.room_participants_leave_prompt_msg)
|
||||
@@ -252,8 +265,8 @@ class RoomListFragment @Inject constructor(
|
||||
override fun invalidate() = withState(roomListViewModel) { state ->
|
||||
when (state.asyncFilteredRooms) {
|
||||
is Incomplete -> renderLoading()
|
||||
is Success -> renderSuccess(state)
|
||||
is Fail -> renderFailure(state.asyncFilteredRooms.error)
|
||||
is Success -> renderSuccess(state)
|
||||
is Fail -> renderFailure(state.asyncFilteredRooms.error)
|
||||
}
|
||||
roomController.update(state)
|
||||
// Mark all as read menu
|
||||
@@ -308,13 +321,13 @@ class RoomListFragment @Inject constructor(
|
||||
ContextCompat.getDrawable(requireContext(), R.drawable.ic_home_bottom_chat),
|
||||
getString(R.string.room_list_people_empty_body)
|
||||
)
|
||||
RoomListDisplayMode.ROOMS ->
|
||||
RoomListDisplayMode.ROOMS ->
|
||||
StateView.State.Empty(
|
||||
getString(R.string.room_list_rooms_empty_title),
|
||||
ContextCompat.getDrawable(requireContext(), R.drawable.ic_home_bottom_group),
|
||||
getString(R.string.room_list_rooms_empty_body)
|
||||
)
|
||||
else ->
|
||||
else ->
|
||||
// Always display the content in this mode, because if the footer
|
||||
StateView.State.Content
|
||||
}
|
||||
@@ -368,7 +381,15 @@ class RoomListFragment @Inject constructor(
|
||||
roomListViewModel.handle(RoomListAction.ToggleCategory(roomCategory))
|
||||
}
|
||||
|
||||
override fun onChangeModeRoomCategory(roomCategory: RoomCategory, newMode: RoomListViewState.CategoryMode) {
|
||||
roomListViewModel.handle(RoomListAction.ChangeCategoryMode(roomCategory, newMode))
|
||||
}
|
||||
|
||||
override fun createRoom(initialName: String) {
|
||||
navigator.openCreateRoom(requireActivity(), initialName)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ITEM_SIZE_DP = 80
|
||||
}
|
||||
}
|
||||
|
@@ -64,6 +64,7 @@ class RoomListViewModel @Inject constructor(initialState: RoomListViewState,
|
||||
when (action) {
|
||||
is RoomListAction.SelectRoom -> handleSelectRoom(action)
|
||||
is RoomListAction.ToggleCategory -> handleToggleCategory(action)
|
||||
is RoomListAction.ChangeCategoryMode -> handleChangeCategoryMode(action)
|
||||
is RoomListAction.AcceptInvitation -> handleAcceptInvitation(action)
|
||||
is RoomListAction.RejectInvitation -> handleRejectInvitation(action)
|
||||
is RoomListAction.FilterWith -> handleFilter(action)
|
||||
@@ -84,6 +85,10 @@ class RoomListViewModel @Inject constructor(initialState: RoomListViewState,
|
||||
this.toggle(action.category)
|
||||
}
|
||||
|
||||
private fun handleChangeCategoryMode(action: RoomListAction.ChangeCategoryMode) = setState {
|
||||
this.setMode(action.category, action.newCategoryMode)
|
||||
}
|
||||
|
||||
private fun handleFilter(action: RoomListAction.FilterWith) {
|
||||
setState {
|
||||
copy(
|
||||
|
@@ -37,7 +37,12 @@ data class RoomListViewState(
|
||||
val isDirectRoomsExpanded: Boolean = true,
|
||||
val isGroupRoomsExpanded: Boolean = true,
|
||||
val isLowPriorityRoomsExpanded: Boolean = true,
|
||||
val isServerNoticeRoomsExpanded: Boolean = true
|
||||
val isServerNoticeRoomsExpanded: Boolean = true,
|
||||
val favouriteRoomsMode: CategoryMode = CategoryMode.List,
|
||||
val directRoomsMode: CategoryMode = CategoryMode.List,
|
||||
val groupRoomsMode: CategoryMode = CategoryMode.List,
|
||||
val lowPriorityRoomsMode: CategoryMode = CategoryMode.List,
|
||||
val serverNoticeRoomsMode: CategoryMode = CategoryMode.List
|
||||
) : MvRxState {
|
||||
|
||||
constructor(args: RoomListParams) : this(displayMode = args.displayMode)
|
||||
@@ -53,6 +58,22 @@ data class RoomListViewState(
|
||||
}
|
||||
}
|
||||
|
||||
enum class CategoryMode {
|
||||
List,
|
||||
Grid
|
||||
}
|
||||
|
||||
fun getCategoryMode(roomCategory: RoomCategory): CategoryMode {
|
||||
return when (roomCategory) {
|
||||
RoomCategory.INVITE -> CategoryMode.List
|
||||
RoomCategory.FAVOURITE -> favouriteRoomsMode
|
||||
RoomCategory.DIRECT -> directRoomsMode
|
||||
RoomCategory.GROUP -> groupRoomsMode
|
||||
RoomCategory.LOW_PRIORITY -> lowPriorityRoomsMode
|
||||
RoomCategory.SERVER_NOTICE -> serverNoticeRoomsMode
|
||||
}
|
||||
}
|
||||
|
||||
fun toggle(roomCategory: RoomCategory): RoomListViewState {
|
||||
return when (roomCategory) {
|
||||
RoomCategory.INVITE -> copy(isInviteExpanded = !isInviteExpanded)
|
||||
@@ -64,6 +85,17 @@ data class RoomListViewState(
|
||||
}
|
||||
}
|
||||
|
||||
fun setMode(roomCategory: RoomCategory, newCategoryMode: CategoryMode): RoomListViewState {
|
||||
return when (roomCategory) {
|
||||
RoomCategory.INVITE -> this
|
||||
RoomCategory.FAVOURITE -> copy(favouriteRoomsMode = newCategoryMode)
|
||||
RoomCategory.DIRECT -> copy(directRoomsMode = newCategoryMode)
|
||||
RoomCategory.GROUP -> copy(groupRoomsMode = newCategoryMode)
|
||||
RoomCategory.LOW_PRIORITY -> copy(lowPriorityRoomsMode = newCategoryMode)
|
||||
RoomCategory.SERVER_NOTICE -> copy(serverNoticeRoomsMode = newCategoryMode)
|
||||
}
|
||||
}
|
||||
|
||||
val hasUnread: Boolean
|
||||
get() = asyncFilteredRooms.invoke()
|
||||
?.flatMap { it.value }
|
||||
|
@@ -16,24 +16,30 @@
|
||||
|
||||
package im.vector.app.features.home.room.list
|
||||
|
||||
import android.view.View
|
||||
import androidx.annotation.StringRes
|
||||
import com.airbnb.epoxy.EpoxyController
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.epoxy.helpFooterItem
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import im.vector.app.core.resources.UserPreferencesProvider
|
||||
import im.vector.app.core.utils.DebouncedClickListener
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
import im.vector.app.features.home.RoomListDisplayMode
|
||||
import im.vector.app.features.home.room.filtered.FilteredRoomFooterItem
|
||||
import im.vector.app.features.home.room.filtered.filteredRoomFooterItem
|
||||
import im.vector.app.features.home.room.list.grid.roomGridItem
|
||||
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||
import javax.inject.Inject
|
||||
|
||||
class RoomSummaryController @Inject constructor(private val stringProvider: StringProvider,
|
||||
private val roomSummaryItemFactory: RoomSummaryItemFactory,
|
||||
private val roomListNameFilter: RoomListNameFilter,
|
||||
private val userPreferencesProvider: UserPreferencesProvider
|
||||
private val userPreferencesProvider: UserPreferencesProvider,
|
||||
private val avatarRenderer: AvatarRenderer
|
||||
) : EpoxyController() {
|
||||
|
||||
var listener: Listener? = null
|
||||
@@ -73,6 +79,7 @@ class RoomSummaryController @Inject constructor(private val stringProvider: Stri
|
||||
.filter { it.membership == Membership.JOIN && roomListNameFilter.test(it) }
|
||||
|
||||
buildRoomModels(filteredSummaries,
|
||||
RoomListViewState.CategoryMode.List,
|
||||
viewState.roomMembershipChanges,
|
||||
emptySet())
|
||||
|
||||
@@ -87,11 +94,23 @@ class RoomSummaryController @Inject constructor(private val stringProvider: Stri
|
||||
return@forEach
|
||||
} else {
|
||||
val isExpanded = viewState.isCategoryExpanded(category)
|
||||
buildRoomCategory(viewState, summaries, category.titleRes, viewState.isCategoryExpanded(category)) {
|
||||
listener?.onToggleRoomCategory(category)
|
||||
}
|
||||
val mode = viewState.getCategoryMode(category)
|
||||
buildRoomCategory(
|
||||
viewState,
|
||||
category,
|
||||
summaries,
|
||||
isExpanded,
|
||||
mode,
|
||||
{ newMode ->
|
||||
listener?.onChangeModeRoomCategory(category, newMode)
|
||||
},
|
||||
{
|
||||
listener?.onToggleRoomCategory(category)
|
||||
}
|
||||
)
|
||||
if (isExpanded) {
|
||||
buildRoomModels(summaries,
|
||||
mode,
|
||||
viewState.roomMembershipChanges,
|
||||
emptySet())
|
||||
// Never set showHelp to true for invitation
|
||||
@@ -111,6 +130,7 @@ class RoomSummaryController @Inject constructor(private val stringProvider: Stri
|
||||
helpFooterItem {
|
||||
id("long_click_help")
|
||||
text(stringProvider.getString(R.string.help_long_click_on_room_for_more_options))
|
||||
spanSizeOverride { _, _, _ -> spanCount }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,13 +139,16 @@ class RoomSummaryController @Inject constructor(private val stringProvider: Stri
|
||||
id("filter_footer")
|
||||
listener(listener)
|
||||
currentFilter(viewState.roomFilter)
|
||||
spanSizeOverride { _, _, _ -> spanCount }
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildRoomCategory(viewState: RoomListViewState,
|
||||
category: RoomCategory,
|
||||
summaries: List<RoomSummary>,
|
||||
@StringRes titleRes: Int,
|
||||
isExpanded: Boolean,
|
||||
mode: RoomListViewState.CategoryMode,
|
||||
changeModeListener: (RoomListViewState.CategoryMode) -> Unit,
|
||||
mutateExpandedState: () -> Unit) {
|
||||
// TODO should add some business logic later
|
||||
val unreadCount = if (summaries.isEmpty()) {
|
||||
@@ -135,33 +158,67 @@ class RoomSummaryController @Inject constructor(private val stringProvider: Stri
|
||||
}
|
||||
val showHighlighted = summaries.any { it.highlightCount > 0 }
|
||||
roomCategoryItem {
|
||||
id(titleRes)
|
||||
title(stringProvider.getString(titleRes))
|
||||
id(category.titleRes)
|
||||
title(stringProvider.getString(category.titleRes))
|
||||
expanded(isExpanded)
|
||||
unreadNotificationCount(unreadCount)
|
||||
showHighlighted(showHighlighted)
|
||||
showSwitchMode(category != RoomCategory.INVITE)
|
||||
mode(mode)
|
||||
listener {
|
||||
mutateExpandedState()
|
||||
update(viewState)
|
||||
}
|
||||
changeModeListener(changeModeListener)
|
||||
spanSizeOverride { _, _, _ -> spanCount }
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildRoomModels(summaries: List<RoomSummary>,
|
||||
mode: RoomListViewState.CategoryMode,
|
||||
roomChangedMembershipStates: Map<String, ChangeMembershipState>,
|
||||
selectedRoomIds: Set<String>) {
|
||||
summaries.forEach { roomSummary ->
|
||||
roomSummaryItemFactory
|
||||
.create(roomSummary,
|
||||
roomChangedMembershipStates,
|
||||
selectedRoomIds,
|
||||
listener)
|
||||
.addTo(this)
|
||||
when (mode) {
|
||||
RoomListViewState.CategoryMode.List ->
|
||||
summaries.forEach { roomSummary ->
|
||||
roomSummaryItemFactory
|
||||
.create(roomSummary,
|
||||
roomChangedMembershipStates,
|
||||
selectedRoomIds,
|
||||
spanCount,
|
||||
listener)
|
||||
.addTo(this)
|
||||
}
|
||||
RoomListViewState.CategoryMode.Grid -> {
|
||||
// Use breadcrumbs for the moment
|
||||
summaries.forEach { roomSummary ->
|
||||
roomGridItem {
|
||||
id(roomSummary.roomId)
|
||||
hasTypingUsers(roomSummary.typingUsers.isNotEmpty())
|
||||
avatarRenderer(avatarRenderer)
|
||||
matrixItem(roomSummary.toMatrixItem())
|
||||
unreadNotificationCount(roomSummary.notificationCount)
|
||||
showHighlighted(roomSummary.highlightCount > 0)
|
||||
hasUnreadMessage(roomSummary.hasUnreadMessages)
|
||||
hasDraft(roomSummary.userDrafts.isNotEmpty())
|
||||
itemLongClickListener { _ ->
|
||||
listener?.onRoomLongClicked(roomSummary) ?: false
|
||||
}
|
||||
itemClickListener(
|
||||
DebouncedClickListener(View.OnClickListener { _ ->
|
||||
listener?.onRoomClicked(roomSummary)
|
||||
})
|
||||
)
|
||||
spanCount
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface Listener : FilteredRoomFooterItem.FilteredRoomFooterItemListener {
|
||||
fun onToggleRoomCategory(roomCategory: RoomCategory)
|
||||
fun onChangeModeRoomCategory(roomCategory: RoomCategory, newMode: RoomListViewState.CategoryMode)
|
||||
fun onRoomClicked(room: RoomSummary)
|
||||
fun onRoomLongClicked(room: RoomSummary): Boolean
|
||||
fun onRejectRoomInvitation(room: RoomSummary)
|
||||
|
@@ -41,18 +41,20 @@ class RoomSummaryItemFactory @Inject constructor(private val displayableEventFor
|
||||
fun create(roomSummary: RoomSummary,
|
||||
roomChangeMembershipStates: Map<String, ChangeMembershipState>,
|
||||
selectedRoomIds: Set<String>,
|
||||
spanCount: Int,
|
||||
listener: RoomSummaryController.Listener?): VectorEpoxyModel<*> {
|
||||
return when (roomSummary.membership) {
|
||||
Membership.INVITE -> {
|
||||
val changeMembershipState = roomChangeMembershipStates[roomSummary.roomId] ?: ChangeMembershipState.Unknown
|
||||
createInvitationItem(roomSummary, changeMembershipState, listener)
|
||||
createInvitationItem(roomSummary, changeMembershipState, spanCount, listener)
|
||||
}
|
||||
else -> createRoomItem(roomSummary, selectedRoomIds, listener?.let { it::onRoomClicked }, listener?.let { it::onRoomLongClicked })
|
||||
else -> createRoomItem(roomSummary, selectedRoomIds, spanCount, listener?.let { it::onRoomClicked }, listener?.let { it::onRoomLongClicked })
|
||||
}
|
||||
}
|
||||
|
||||
private fun createInvitationItem(roomSummary: RoomSummary,
|
||||
changeMembershipState: ChangeMembershipState,
|
||||
spanCount: Int,
|
||||
listener: RoomSummaryController.Listener?): VectorEpoxyModel<*> {
|
||||
val secondLine = if (roomSummary.isDirect) {
|
||||
roomSummary.inviterId
|
||||
@@ -71,11 +73,13 @@ class RoomSummaryItemFactory @Inject constructor(private val displayableEventFor
|
||||
.acceptListener { listener?.onAcceptRoomInvitation(roomSummary) }
|
||||
.rejectListener { listener?.onRejectRoomInvitation(roomSummary) }
|
||||
.listener { listener?.onRoomClicked(roomSummary) }
|
||||
.spanSizeOverride { _, _, _ -> spanCount }
|
||||
}
|
||||
|
||||
fun createRoomItem(
|
||||
roomSummary: RoomSummary,
|
||||
selectedRoomIds: Set<String>,
|
||||
spanCount: Int,
|
||||
onClick: ((RoomSummary) -> Unit)?,
|
||||
onLongClick: ((RoomSummary) -> Boolean)?
|
||||
): VectorEpoxyModel<*> {
|
||||
@@ -113,5 +117,6 @@ class RoomSummaryItemFactory @Inject constructor(private val displayableEventFor
|
||||
onClick?.invoke(roomSummary)
|
||||
})
|
||||
)
|
||||
.spanSizeOverride { _, _, _ -> spanCount }
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2019 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.home.room.list.grid
|
||||
|
||||
import android.view.HapticFeedbackConstants
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
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.epoxy.VectorEpoxyHolder
|
||||
import im.vector.app.core.epoxy.VectorEpoxyModel
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
import im.vector.app.features.home.room.list.UnreadCounterBadgeView
|
||||
import org.matrix.android.sdk.api.util.MatrixItem
|
||||
|
||||
@EpoxyModelClass(layout = R.layout.item_room_grid)
|
||||
abstract class RoomGridItem : VectorEpoxyModel<RoomGridItem.Holder>() {
|
||||
|
||||
@EpoxyAttribute var hasTypingUsers: Boolean = false
|
||||
@EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer
|
||||
@EpoxyAttribute lateinit var matrixItem: MatrixItem
|
||||
@EpoxyAttribute var unreadNotificationCount: Int = 0
|
||||
@EpoxyAttribute var showHighlighted: Boolean = false
|
||||
@EpoxyAttribute var hasUnreadMessage: Boolean = false
|
||||
@EpoxyAttribute var hasDraft: Boolean = false
|
||||
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var itemClickListener: View.OnClickListener? = null
|
||||
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var itemLongClickListener: View.OnLongClickListener? = null
|
||||
|
||||
override fun bind(holder: Holder) {
|
||||
super.bind(holder)
|
||||
holder.rootView.setOnClickListener(itemClickListener)
|
||||
holder.rootView.setOnLongClickListener {
|
||||
it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
|
||||
itemLongClickListener?.onLongClick(it) ?: false
|
||||
}
|
||||
holder.unreadIndentIndicator.isVisible = hasUnreadMessage
|
||||
avatarRenderer.render(matrixItem, holder.avatarImageView)
|
||||
holder.unreadCounterBadgeView.render(UnreadCounterBadgeView.State(unreadNotificationCount, showHighlighted))
|
||||
holder.draftIndentIndicator.isVisible = hasDraft
|
||||
holder.typingIndicator.isVisible = hasTypingUsers
|
||||
holder.roomName.text = matrixItem.getBestName()
|
||||
}
|
||||
|
||||
override fun unbind(holder: Holder) {
|
||||
holder.rootView.setOnClickListener(null)
|
||||
super.unbind(holder)
|
||||
}
|
||||
|
||||
class Holder : VectorEpoxyHolder() {
|
||||
val unreadCounterBadgeView by bind<UnreadCounterBadgeView>(R.id.itemRoomGridUnreadCounterBadgeView)
|
||||
val unreadIndentIndicator by bind<View>(R.id.itemRoomGridUnreadIndicator)
|
||||
val draftIndentIndicator by bind<View>(R.id.itemRoomGridDraftBadge)
|
||||
val typingIndicator by bind<View>(R.id.itemRoomGridTypingView)
|
||||
val avatarImageView by bind<ImageView>(R.id.itemRoomGridImageView)
|
||||
val roomName by bind<TextView>(R.id.itemRoomGridRoomName)
|
||||
val rootView by bind<ViewGroup>(R.id.itemRoomGridRoot)
|
||||
}
|
||||
}
|
@@ -52,7 +52,13 @@ class IncomingShareController @Inject constructor(private val roomSummaryItemFac
|
||||
} else {
|
||||
roomSummaries.forEach { roomSummary ->
|
||||
roomSummaryItemFactory
|
||||
.createRoomItem(roomSummary, data.selectedRoomIds, callback?.let { it::onRoomClicked }, callback?.let { it::onRoomLongClicked })
|
||||
.createRoomItem(
|
||||
roomSummary,
|
||||
data.selectedRoomIds,
|
||||
1,
|
||||
callback?.let { it::onRoomClicked },
|
||||
callback?.let { it::onRoomLongClicked }
|
||||
)
|
||||
.addTo(this)
|
||||
}
|
||||
}
|
||||
|
9
vector/src/main/res/drawable/ic_mode_grid_24dp.xml
Normal file
9
vector/src/main/res/drawable/ic_mode_grid_24dp.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M18.4,4H5.6C4.72,4 4,4.72 4,5.6V18.4C4,19.28 4.72,20 5.6,20H18.4C19.28,20 20,19.28 20,18.4V5.6C20,4.72 19.28,4 18.4,4ZM8.8,18.4H5.6V15.2H8.8V18.4ZM8.8,13.6H5.6V10.4H8.8V13.6ZM8.8,8.8H5.6V5.6H8.8V8.8ZM13.6,18.4H10.4V15.2H13.6V18.4ZM13.6,13.6H10.4V10.4H13.6V13.6ZM13.6,8.8H10.4V5.6H13.6V8.8ZM18.4,18.4H15.2V15.2H18.4V18.4ZM18.4,13.6H15.2V10.4H18.4V13.6ZM18.4,8.8H15.2V5.6H18.4V8.8Z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
10
vector/src/main/res/drawable/ic_mode_list_24dp.xml
Normal file
10
vector/src/main/res/drawable/ic_mode_list_24dp.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M4,5C4,5.5523 4.4477,6 5,6C5.5523,6 6,5.5523 6,5C6,4.4477 5.5523,4 5,4C4.4477,4 4,4.4477 4,5ZM8,5C8,5.5523 8.4477,6 9,6H19C19.5523,6 20,5.5523 20,5C20,4.4477 19.5523,4 19,4H9C8.4477,4 8,4.4477 8,5ZM4,9.5C4,10.0523 4.4477,10.5 5,10.5C5.5523,10.5 6,10.0523 6,9.5C6,8.9477 5.5523,8.5 5,8.5C4.4477,8.5 4,8.9477 4,9.5ZM8,9.5C8,10.0523 8.4477,10.5 9,10.5H19C19.5523,10.5 20,10.0523 20,9.5C20,8.9477 19.5523,8.5 19,8.5H9C8.4477,8.5 8,8.9477 8,9.5ZM4,19C4,19.5523 4.4477,20 5,20C5.5523,20 6,19.5523 6,19C6,18.4477 5.5523,18 5,18C4.4477,18 4,18.4477 4,19ZM8,19C8,19.5523 8.4477,20 9,20H19C19.5523,20 20,19.5523 20,19C20,18.4477 19.5523,18 19,18H9C8.4477,18 8,18.4477 8,19ZM6,14.5C6,15.0523 5.5523,15.5 5,15.5C4.4477,15.5 4,15.0523 4,14.5C4,13.9477 4.4477,13.5 5,13.5C5.5523,13.5 6,13.9477 6,14.5ZM20,14.5C20,15.0523 19.5523,15.5 19,15.5H9C8.4477,15.5 8,15.0523 8,14.5C8,13.9477 8.4477,13.5 9,13.5H19C19.5523,13.5 20,13.9477 20,14.5Z"
|
||||
android:fillColor="#000000"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
@@ -5,7 +5,7 @@
|
||||
android:id="@+id/stateView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?riotx_header_panel_background">
|
||||
android:background="?riotx_background">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/roomListView"
|
||||
|
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout 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/roomCategoryRootView"
|
||||
android:layout_width="match_parent"
|
||||
@@ -8,19 +9,14 @@
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:foreground="?attr/selectableItemBackground"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingEnd="@dimen/layout_horizontal_margin"
|
||||
android:paddingBottom="4dp">
|
||||
android:paddingStart="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/roomCategoryTitleView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
tools:drawableEnd="@drawable/ic_expand_more_white"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:drawableTint="?riotx_text_secondary"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
@@ -28,12 +24,17 @@
|
||||
android:textColor="?riotx_text_secondary"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:drawableEnd="@drawable/ic_expand_more_white"
|
||||
tools:text="@string/room_participants_header_direct_chats" />
|
||||
|
||||
<im.vector.app.features.home.room.list.UnreadCounterBadgeView
|
||||
android:id="@+id/roomCategoryUnreadCounterBadgeView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:gravity="center"
|
||||
android:minWidth="16dp"
|
||||
android:minHeight="16dp"
|
||||
@@ -41,7 +42,21 @@
|
||||
android:paddingEnd="4dp"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="10sp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/roomCategoryTitleView"
|
||||
app:layout_constraintStart_toEndOf="@+id/roomCategoryTitleView"
|
||||
app:layout_constraintTop_toTopOf="@+id/roomCategoryTitleView"
|
||||
tools:background="@drawable/bg_unread_highlight"
|
||||
tools:text="24" />
|
||||
|
||||
</LinearLayout>
|
||||
<ImageView
|
||||
android:id="@+id/roomCategoryMode"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="0dp"
|
||||
android:scaleType="center"
|
||||
android:tint="?riotx_text_secondary"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@drawable/ic_mode_list_24dp" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
103
vector/src/main/res/layout/item_room_grid.xml
Normal file
103
vector/src/main/res/layout/item_room_grid.xml
Normal file
@@ -0,0 +1,103 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout 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/itemRoomGridRoot"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?riotx_background"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:foreground="?attr/selectableItemBackground">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/itemRoomGridUnreadIndicator"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:src="@drawable/circle"
|
||||
android:tint="?attr/colorAccent"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/itemRoomGridImageView"
|
||||
app:layout_constraintEnd_toEndOf="@+id/itemRoomGridImageView"
|
||||
app:layout_constraintStart_toStartOf="@+id/itemRoomGridImageView"
|
||||
app:layout_constraintTop_toTopOf="@+id/itemRoomGridImageView"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/itemRoomGridImageView"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@tools:sample/avatars" />
|
||||
|
||||
<im.vector.app.features.home.room.list.UnreadCounterBadgeView
|
||||
android:id="@+id/itemRoomGridUnreadCounterBadgeView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:minWidth="18dp"
|
||||
android:minHeight="18dp"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="11sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintCircle="@+id/itemRoomGridImageView"
|
||||
app:layout_constraintCircleAngle="45"
|
||||
app:layout_constraintCircleRadius="28dp"
|
||||
tools:background="@drawable/bg_unread_highlight"
|
||||
tools:ignore="MissingConstraints"
|
||||
tools:text="24"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/itemRoomGridTypingView"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:background="@drawable/bg_breadcrumbs_typing"
|
||||
android:gravity="center"
|
||||
android:text="@string/ellipsis"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="11sp"
|
||||
android:textStyle="bold"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintCircle="@+id/itemRoomGridImageView"
|
||||
app:layout_constraintCircleAngle="135"
|
||||
app:layout_constraintCircleRadius="28dp"
|
||||
tools:ignore="MissingConstraints"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/itemRoomGridDraftBadge"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:background="@drawable/circle"
|
||||
android:padding="3dp"
|
||||
android:src="@drawable/ic_edit"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintCircle="@+id/itemRoomGridImageView"
|
||||
app:layout_constraintCircleAngle="225"
|
||||
app:layout_constraintCircleRadius="28dp"
|
||||
tools:ignore="MissingConstraints"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/itemRoomGridRoomName"
|
||||
android:layout_width="76dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="2dp"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:lines="2"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/itemRoomGridImageView"
|
||||
tools:text="@sample/matrix.json/data/roomName" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
Reference in New Issue
Block a user