room summary now has constant height (#7145)
This commit is contained in:
		
							parent
							
								
									0fea172154
								
							
						
					
					
						commit
						830e5ffa9f
					
				
							
								
								
									
										1
									
								
								changelog.d/7079.bugfix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								changelog.d/7079.bugfix
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| Fixed problem when room list's scroll did jump after rooms placeholders were replaced with rooms summary items | ||||
| @ -0,0 +1,47 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022 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.utils | ||||
| 
 | ||||
| import androidx.recyclerview.widget.LinearLayoutManager | ||||
| import androidx.recyclerview.widget.RecyclerView | ||||
| 
 | ||||
| /** | ||||
|  * This observer detects when item was added or moved to the first position of the adapter, while recyclerView is scrolled to the top. This is necessary | ||||
|  * to force recycler to scroll to the top to make such item visible, because by default it will keep items on screen, while adding new item to the top, | ||||
|  * outside of the viewport | ||||
|  * @param layoutManager - [LinearLayoutManager] of the recycler view, which displays items | ||||
|  * @property onItemUpdated - callback to be called, when observer detects event | ||||
|  */ | ||||
| class FirstItemUpdatedObserver( | ||||
|         layoutManager: LinearLayoutManager, | ||||
|         private val onItemUpdated: () -> Unit | ||||
| ) : RecyclerView.AdapterDataObserver() { | ||||
| 
 | ||||
|     val layoutManager: LinearLayoutManager? by weak(layoutManager) | ||||
| 
 | ||||
|     override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) { | ||||
|         if ((toPosition == 0 || fromPosition == 0) && layoutManager?.findFirstCompletelyVisibleItemPosition() == 0) { | ||||
|             onItemUpdated.invoke() | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun onItemRangeInserted(positionStart: Int, itemCount: Int) { | ||||
|         if (positionStart == 0 && layoutManager?.findFirstCompletelyVisibleItemPosition() == 0) { | ||||
|             onItemUpdated.invoke() | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -103,6 +103,9 @@ abstract class RoomSummaryItem : VectorEpoxyModel<RoomSummaryItem.Holder>(R.layo | ||||
|     @EpoxyAttribute | ||||
|     var showSelected: Boolean = false | ||||
| 
 | ||||
|     @EpoxyAttribute | ||||
|     var useSingleLineForLastEvent: Boolean = false | ||||
| 
 | ||||
|     override fun bind(holder: Holder) { | ||||
|         super.bind(holder) | ||||
| 
 | ||||
| @ -122,6 +125,10 @@ abstract class RoomSummaryItem : VectorEpoxyModel<RoomSummaryItem.Holder>(R.layo | ||||
|         holder.roomAvatarFailSendingImageView.isVisible = hasFailedSending | ||||
|         renderSelection(holder, showSelected) | ||||
|         holder.roomAvatarPresenceImageView.render(showPresence, userPresence) | ||||
| 
 | ||||
|         if (useSingleLineForLastEvent) { | ||||
|             holder.subtitleView.setLines(1) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private fun renderDisplayMode(holder: Holder) = when (displayMode) { | ||||
|  | ||||
| @ -51,7 +51,8 @@ class RoomSummaryItemFactory @Inject constructor( | ||||
|             roomChangeMembershipStates: Map<String, ChangeMembershipState>, | ||||
|             selectedRoomIds: Set<String>, | ||||
|             displayMode: RoomListDisplayMode, | ||||
|             listener: RoomListListener? | ||||
|             listener: RoomListListener?, | ||||
|             singleLineLastEvent: Boolean = false | ||||
|     ): VectorEpoxyModel<*> { | ||||
|         return when (roomSummary.membership) { | ||||
|             Membership.INVITE -> { | ||||
| @ -59,7 +60,7 @@ class RoomSummaryItemFactory @Inject constructor( | ||||
|                 createInvitationItem(roomSummary, changeMembershipState, listener) | ||||
|             } | ||||
|             else -> createRoomItem( | ||||
|                     roomSummary, selectedRoomIds, displayMode, listener?.let { it::onRoomClicked }, listener?.let { it::onRoomLongClicked } | ||||
|                     roomSummary, selectedRoomIds, displayMode, singleLineLastEvent, listener?.let { it::onRoomClicked }, listener?.let { it::onRoomLongClicked } | ||||
|             ) | ||||
|         } | ||||
|     } | ||||
| @ -118,8 +119,9 @@ class RoomSummaryItemFactory @Inject constructor( | ||||
|             roomSummary: RoomSummary, | ||||
|             selectedRoomIds: Set<String>, | ||||
|             displayMode: RoomListDisplayMode, | ||||
|             singleLineLastEvent: Boolean, | ||||
|             onClick: ((RoomSummary) -> Unit)?, | ||||
|             onLongClick: ((RoomSummary) -> Boolean)? | ||||
|             onLongClick: ((RoomSummary) -> Boolean)?, | ||||
|     ): VectorEpoxyModel<*> { | ||||
|         val subtitle = getSearchResultSubtitle(roomSummary) | ||||
|         val unreadCount = roomSummary.notificationCount | ||||
| @ -140,7 +142,7 @@ class RoomSummaryItemFactory @Inject constructor( | ||||
|         } else { | ||||
|             createRoomSummaryItem( | ||||
|                     roomSummary, displayMode, subtitle, latestEventTime, typingMessage, | ||||
|                     latestFormattedEvent, showHighlighted, showSelected, unreadCount, onClick, onLongClick | ||||
|                     latestFormattedEvent, showHighlighted, showSelected, unreadCount, singleLineLastEvent, onClick, onLongClick | ||||
|             ) | ||||
|         } | ||||
|     } | ||||
| @ -155,6 +157,7 @@ class RoomSummaryItemFactory @Inject constructor( | ||||
|             showHighlighted: Boolean, | ||||
|             showSelected: Boolean, | ||||
|             unreadCount: Int, | ||||
|             singleLineLastEvent: Boolean, | ||||
|             onClick: ((RoomSummary) -> Unit)?, | ||||
|             onLongClick: ((RoomSummary) -> Boolean)? | ||||
|     ) = RoomSummaryItem_() | ||||
| @ -177,6 +180,7 @@ class RoomSummaryItemFactory @Inject constructor( | ||||
|             .unreadNotificationCount(unreadCount) | ||||
|             .hasUnreadMessage(roomSummary.hasUnreadMessages) | ||||
|             .hasDraft(roomSummary.userDrafts.isNotEmpty()) | ||||
|             .useSingleLineForLastEvent(singleLineLastEvent) | ||||
|             .itemLongClickListener { _ -> onLongClick?.invoke(roomSummary) ?: false } | ||||
|             .itemClickListener { onClick?.invoke(roomSummary) } | ||||
| 
 | ||||
|  | ||||
| @ -16,6 +16,8 @@ | ||||
| 
 | ||||
| package im.vector.app.features.home.room.list | ||||
| 
 | ||||
| import android.widget.TextView | ||||
| import com.airbnb.epoxy.EpoxyAttribute | ||||
| import com.airbnb.epoxy.EpoxyModelClass | ||||
| import im.vector.app.R | ||||
| import im.vector.app.core.epoxy.VectorEpoxyHolder | ||||
| @ -23,5 +25,18 @@ import im.vector.app.core.epoxy.VectorEpoxyModel | ||||
| 
 | ||||
| @EpoxyModelClass | ||||
| abstract class RoomSummaryItemPlaceHolder : VectorEpoxyModel<RoomSummaryItemPlaceHolder.Holder>(R.layout.item_room_placeholder) { | ||||
|     class Holder : VectorEpoxyHolder() | ||||
| 
 | ||||
|     @EpoxyAttribute | ||||
|     var useSingleLineForLastEvent: Boolean = false | ||||
| 
 | ||||
|     override fun bind(holder: Holder) { | ||||
|         super.bind(holder) | ||||
|         if (useSingleLineForLastEvent) { | ||||
|             holder.subtitleView.setLines(1) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     class Holder : VectorEpoxyHolder() { | ||||
|         val subtitleView by bind<TextView>(R.id.subtitleView) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -17,18 +17,26 @@ | ||||
| package im.vector.app.features.home.room.list | ||||
| 
 | ||||
| import im.vector.app.features.home.RoomListDisplayMode | ||||
| import im.vector.app.features.settings.FontScalePreferences | ||||
| import org.matrix.android.sdk.api.session.room.model.RoomSummary | ||||
| 
 | ||||
| class RoomSummaryListController( | ||||
|         private val roomSummaryItemFactory: RoomSummaryItemFactory, | ||||
|         private val displayMode: RoomListDisplayMode | ||||
|         private val displayMode: RoomListDisplayMode, | ||||
|         fontScalePreferences: FontScalePreferences | ||||
| ) : CollapsableTypedEpoxyController<List<RoomSummary>>() { | ||||
| 
 | ||||
|     var listener: RoomListListener? = null | ||||
|     private val shouldUseSingleLine: Boolean | ||||
| 
 | ||||
|     init { | ||||
|         val fontScale = fontScalePreferences.getResolvedFontScaleValue() | ||||
|         shouldUseSingleLine = fontScale.scale > FontScalePreferences.SCALE_LARGE | ||||
|     } | ||||
| 
 | ||||
|     override fun buildModels(data: List<RoomSummary>?) { | ||||
|         data?.forEach { | ||||
|             add(roomSummaryItemFactory.create(it, emptyMap(), emptySet(), displayMode, listener)) | ||||
|             add(roomSummaryItemFactory.create(it, emptyMap(), emptySet(), displayMode, listener, shouldUseSingleLine)) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -20,18 +20,26 @@ import com.airbnb.epoxy.EpoxyModel | ||||
| import com.airbnb.epoxy.paging.PagedListEpoxyController | ||||
| import im.vector.app.core.utils.createUIHandler | ||||
| import im.vector.app.features.home.RoomListDisplayMode | ||||
| import im.vector.app.features.settings.FontScalePreferences | ||||
| import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState | ||||
| import org.matrix.android.sdk.api.session.room.model.RoomSummary | ||||
| 
 | ||||
| class RoomSummaryPagedController( | ||||
|         private val roomSummaryItemFactory: RoomSummaryItemFactory, | ||||
|         private val displayMode: RoomListDisplayMode | ||||
|         private val displayMode: RoomListDisplayMode, | ||||
|         fontScalePreferences: FontScalePreferences | ||||
| ) : PagedListEpoxyController<RoomSummary>( | ||||
|         // Important it must match the PageList builder notify Looper | ||||
|         modelBuildingHandler = createUIHandler() | ||||
| ), CollapsableControllerExtension { | ||||
| 
 | ||||
|     var listener: RoomListListener? = null | ||||
|     private val shouldUseSingleLine: Boolean | ||||
| 
 | ||||
|     init { | ||||
|         val fontScale = fontScalePreferences.getResolvedFontScaleValue() | ||||
|         shouldUseSingleLine = fontScale.scale > FontScalePreferences.SCALE_LARGE | ||||
|     } | ||||
| 
 | ||||
|     var roomChangeMembershipStates: Map<String, ChangeMembershipState>? = null | ||||
|         set(value) { | ||||
| @ -57,8 +65,14 @@ class RoomSummaryPagedController( | ||||
|     } | ||||
| 
 | ||||
|     override fun buildItemModel(currentPosition: Int, item: RoomSummary?): EpoxyModel<*> { | ||||
|         // for place holder if enabled | ||||
|         item ?: return RoomSummaryItemPlaceHolder_().apply { id(currentPosition) } | ||||
|         return roomSummaryItemFactory.create(item, roomChangeMembershipStates.orEmpty(), emptySet(), displayMode, listener) | ||||
|         return if (item == null) { | ||||
|             val host = this | ||||
|             RoomSummaryItemPlaceHolder_().apply { | ||||
|                 id(currentPosition) | ||||
|                 useSingleLineForLastEvent(host.shouldUseSingleLine) | ||||
|             } | ||||
|         } else { | ||||
|             roomSummaryItemFactory.create(item, roomChangeMembershipStates.orEmpty(), emptySet(), displayMode, listener, shouldUseSingleLine) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -17,18 +17,20 @@ | ||||
| package im.vector.app.features.home.room.list | ||||
| 
 | ||||
| import im.vector.app.features.home.RoomListDisplayMode | ||||
| import im.vector.app.features.settings.FontScalePreferences | ||||
| import javax.inject.Inject | ||||
| 
 | ||||
| class RoomSummaryPagedControllerFactory @Inject constructor( | ||||
|         private val roomSummaryItemFactory: RoomSummaryItemFactory | ||||
|         private val roomSummaryItemFactory: RoomSummaryItemFactory, | ||||
|         private val fontScalePreferences: FontScalePreferences | ||||
| ) { | ||||
| 
 | ||||
|     fun createRoomSummaryPagedController(displayMode: RoomListDisplayMode): RoomSummaryPagedController { | ||||
|         return RoomSummaryPagedController(roomSummaryItemFactory, displayMode) | ||||
|         return RoomSummaryPagedController(roomSummaryItemFactory, displayMode, fontScalePreferences) | ||||
|     } | ||||
| 
 | ||||
|     fun createRoomSummaryListController(displayMode: RoomListDisplayMode): RoomSummaryListController { | ||||
|         return RoomSummaryListController(roomSummaryItemFactory, displayMode) | ||||
|         return RoomSummaryListController(roomSummaryItemFactory, displayMode, fontScalePreferences) | ||||
|     } | ||||
| 
 | ||||
|     fun createSuggestedRoomListController(): SuggestedRoomListController { | ||||
|  | ||||
| @ -24,12 +24,14 @@ import im.vector.app.features.home.RoomListDisplayMode | ||||
| import im.vector.app.features.home.room.list.RoomListListener | ||||
| import im.vector.app.features.home.room.list.RoomSummaryItemFactory | ||||
| import im.vector.app.features.home.room.list.RoomSummaryItemPlaceHolder_ | ||||
| import im.vector.app.features.settings.FontScalePreferences | ||||
| import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState | ||||
| import org.matrix.android.sdk.api.session.room.model.RoomSummary | ||||
| import javax.inject.Inject | ||||
| 
 | ||||
| class HomeFilteredRoomsController @Inject constructor( | ||||
|         private val roomSummaryItemFactory: RoomSummaryItemFactory, | ||||
|         fontScalePreferences: FontScalePreferences | ||||
| ) : PagedListEpoxyController<RoomSummary>( | ||||
|         // Important it must match the PageList builder notify Looper | ||||
|         modelBuildingHandler = createUIHandler() | ||||
| @ -47,6 +49,13 @@ class HomeFilteredRoomsController @Inject constructor( | ||||
|     private var emptyStateData: StateView.State.Empty? = null | ||||
|     private var currentState: StateView.State = StateView.State.Content | ||||
| 
 | ||||
|     private val shouldUseSingleLine: Boolean | ||||
| 
 | ||||
|     init { | ||||
|         val fontScale = fontScalePreferences.getResolvedFontScaleValue() | ||||
|         shouldUseSingleLine = fontScale.scale > FontScalePreferences.SCALE_LARGE | ||||
|     } | ||||
| 
 | ||||
|     override fun addModels(models: List<EpoxyModel<*>>) { | ||||
|         if (models.isEmpty() && emptyStateData != null) { | ||||
|             emptyStateData?.let { emptyState -> | ||||
| @ -67,7 +76,14 @@ class HomeFilteredRoomsController @Inject constructor( | ||||
|     } | ||||
| 
 | ||||
|     override fun buildItemModel(currentPosition: Int, item: RoomSummary?): EpoxyModel<*> { | ||||
|         item ?: return RoomSummaryItemPlaceHolder_().apply { id(currentPosition) } | ||||
|         return roomSummaryItemFactory.create(item, roomChangeMembershipStates.orEmpty(), emptySet(), RoomListDisplayMode.ROOMS, listener) | ||||
|         return if (item == null) { | ||||
|             val host = this | ||||
|             RoomSummaryItemPlaceHolder_().apply { | ||||
|                 id(currentPosition) | ||||
|                 useSingleLineForLastEvent(host.shouldUseSingleLine) | ||||
|             } | ||||
|         } else { | ||||
|             roomSummaryItemFactory.create(item, roomChangeMembershipStates.orEmpty(), emptySet(), RoomListDisplayMode.ROOMS, listener, shouldUseSingleLine) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -24,7 +24,6 @@ import android.view.ViewGroup | ||||
| import androidx.lifecycle.lifecycleScope | ||||
| import androidx.recyclerview.widget.ConcatAdapter | ||||
| import androidx.recyclerview.widget.LinearLayoutManager | ||||
| import androidx.recyclerview.widget.RecyclerView | ||||
| import com.airbnb.epoxy.OnModelBuildFinishedListener | ||||
| import com.airbnb.mvrx.fragmentViewModel | ||||
| import com.airbnb.mvrx.withState | ||||
| @ -36,6 +35,7 @@ import im.vector.app.core.extensions.cleanup | ||||
| import im.vector.app.core.platform.StateView | ||||
| import im.vector.app.core.platform.VectorBaseFragment | ||||
| import im.vector.app.core.resources.UserPreferencesProvider | ||||
| import im.vector.app.core.utils.FirstItemUpdatedObserver | ||||
| import im.vector.app.databinding.FragmentRoomListBinding | ||||
| import im.vector.app.features.analytics.plan.ViewRoom | ||||
| import im.vector.app.features.home.room.list.RoomListAnimator | ||||
| @ -66,6 +66,7 @@ class HomeRoomListFragment : | ||||
|     private val roomListViewModel: HomeRoomListViewModel by fragmentViewModel() | ||||
|     private lateinit var sharedQuickActionsViewModel: RoomListQuickActionsSharedActionViewModel | ||||
|     private var concatAdapter = ConcatAdapter() | ||||
|     private lateinit var firstItemObserver: FirstItemUpdatedObserver | ||||
|     private var modelBuildListener: OnModelBuildFinishedListener? = null | ||||
| 
 | ||||
|     private lateinit var stateRestorer: LayoutManagerStateRestorer | ||||
| @ -130,6 +131,9 @@ class HomeRoomListFragment : | ||||
| 
 | ||||
|     private fun setupRecyclerView() { | ||||
|         val layoutManager = LinearLayoutManager(context) | ||||
|         firstItemObserver = FirstItemUpdatedObserver(layoutManager) { | ||||
|             layoutManager.scrollToPosition(0) | ||||
|         } | ||||
|         stateRestorer = LayoutManagerStateRestorer(layoutManager).register() | ||||
|         views.roomListView.layoutManager = layoutManager | ||||
|         views.roomListView.itemAnimator = RoomListAnimator() | ||||
| @ -158,14 +162,7 @@ class HomeRoomListFragment : | ||||
| 
 | ||||
|         views.roomListView.adapter = concatAdapter | ||||
| 
 | ||||
|         // we need to force scroll when recents/filter tabs are added to make them visible | ||||
|         concatAdapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() { | ||||
|             override fun onItemRangeInserted(positionStart: Int, itemCount: Int) { | ||||
|                 if (positionStart == 0) { | ||||
|                     layoutManager.scrollToPosition(0) | ||||
|                 } | ||||
|             } | ||||
|         }) | ||||
|         concatAdapter.registerAdapterDataObserver(firstItemObserver) | ||||
|     } | ||||
| 
 | ||||
|     override fun invalidate() = withState(roomListViewModel) { state -> | ||||
| @ -233,6 +230,8 @@ class HomeRoomListFragment : | ||||
| 
 | ||||
|         roomsController.listener = null | ||||
| 
 | ||||
|         concatAdapter.unregisterAdapterDataObserver(firstItemObserver) | ||||
| 
 | ||||
|         super.onDestroyView() | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -18,7 +18,7 @@ package im.vector.app.features.home.room.list.home.header | ||||
| 
 | ||||
| import android.content.res.Resources | ||||
| import android.util.TypedValue | ||||
| import androidx.recyclerview.widget.RecyclerView | ||||
| import androidx.recyclerview.widget.LinearLayoutManager | ||||
| import com.airbnb.epoxy.Carousel | ||||
| import com.airbnb.epoxy.CarouselModelBuilder | ||||
| import com.airbnb.epoxy.EpoxyController | ||||
| @ -27,6 +27,7 @@ import com.airbnb.epoxy.carousel | ||||
| import com.google.android.material.color.MaterialColors | ||||
| import im.vector.app.R | ||||
| import im.vector.app.core.resources.StringProvider | ||||
| import im.vector.app.core.utils.FirstItemUpdatedObserver | ||||
| import im.vector.app.features.home.AvatarRenderer | ||||
| import im.vector.app.features.home.room.list.RoomListListener | ||||
| import org.matrix.android.sdk.api.session.room.model.RoomSummary | ||||
| @ -47,22 +48,7 @@ class HomeRoomsHeadersController @Inject constructor( | ||||
| 
 | ||||
|     private var carousel: Carousel? = null | ||||
| 
 | ||||
|     private val carouselAdapterObserver = object : RecyclerView.AdapterDataObserver() { | ||||
|         override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) { | ||||
|             if (toPosition == 0 || fromPosition == 0) { | ||||
|                 carousel?.post { | ||||
|                     carousel?.layoutManager?.scrollToPosition(0) | ||||
|                 } | ||||
|             } | ||||
|             super.onItemRangeMoved(fromPosition, toPosition, itemCount) | ||||
|         } | ||||
| 
 | ||||
|         override fun onItemRangeInserted(positionStart: Int, itemCount: Int) { | ||||
|             if (positionStart == 0) { | ||||
|                 carousel?.layoutManager?.scrollToPosition(0) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     private var carouselAdapterObserver: FirstItemUpdatedObserver? = null | ||||
| 
 | ||||
|     private val recentsHPadding = TypedValue.applyDimension( | ||||
|             TypedValue.COMPLEX_UNIT_DIP, | ||||
| @ -113,25 +99,16 @@ class HomeRoomsHeadersController @Inject constructor( | ||||
|             ) | ||||
|             onBind { _, view, _ -> | ||||
|                 host.carousel = view | ||||
|                 host.unsubscribeAdapterObserver() | ||||
|                 host.subscribeAdapterObserver() | ||||
| 
 | ||||
|                 val colorSurface = MaterialColors.getColor(view, R.attr.vctr_toolbar_background) | ||||
|                 view.setBackgroundColor(colorSurface) | ||||
| 
 | ||||
|                 try { | ||||
|                     view.adapter?.registerAdapterDataObserver(host.carouselAdapterObserver) | ||||
|                 } catch (e: IllegalStateException) { | ||||
|                     // do nothing | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             onUnbind { _, view -> | ||||
|             onUnbind { _, _ -> | ||||
|                 host.carousel = null | ||||
| 
 | ||||
|                 try { | ||||
|                     view.adapter?.unregisterAdapterDataObserver(host.carouselAdapterObserver) | ||||
|                 } catch (e: IllegalStateException) { | ||||
|                     // do nothing | ||||
|                 } | ||||
|                 host.unsubscribeAdapterObserver() | ||||
|             } | ||||
| 
 | ||||
|             withModelsFrom(recents) { roomSummary -> | ||||
| @ -150,6 +127,33 @@ class HomeRoomsHeadersController @Inject constructor( | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private fun unsubscribeAdapterObserver() { | ||||
|         carouselAdapterObserver?.let { observer -> | ||||
|             try { | ||||
|                 carousel?.adapter?.unregisterAdapterDataObserver(observer) | ||||
|                 carouselAdapterObserver = null | ||||
|             } catch (e: IllegalStateException) { | ||||
|                 // do nothing | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private fun subscribeAdapterObserver() { | ||||
|         (carousel?.layoutManager as? LinearLayoutManager)?.let { layoutManager -> | ||||
|             carouselAdapterObserver = FirstItemUpdatedObserver(layoutManager) { | ||||
|                 carousel?.post { | ||||
|                     layoutManager.scrollToPosition(0) | ||||
|                 } | ||||
|             }.also { observer -> | ||||
|                 try { | ||||
|                     carousel?.adapter?.registerAdapterDataObserver(observer) | ||||
|                 } catch (e: IllegalStateException) { | ||||
|                     // do nothing | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private fun addRoomFilterHeaderItem( | ||||
|             filterChangedListener: ((HomeRoomFilter) -> Unit)?, | ||||
|             filtersList: List<HomeRoomFilter>, | ||||
|  | ||||
| @ -57,6 +57,16 @@ interface FontScalePreferences { | ||||
|      * @return list of values | ||||
|      */ | ||||
|     fun getAvailableScales(): List<FontScaleValue> | ||||
| 
 | ||||
|     companion object { | ||||
|         const val SCALE_TINY = 0.70f | ||||
|         const val SCALE_SMALL = 0.85f | ||||
|         const val SCALE_NORMAL = 1.00f | ||||
|         const val SCALE_LARGE = 1.15f | ||||
|         const val SCALE_LARGER = 1.30f | ||||
|         const val SCALE_LARGEST = 1.45f | ||||
|         const val SCALE_HUGE = 1.60f | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /** | ||||
| @ -73,13 +83,13 @@ class FontScalePreferencesImpl @Inject constructor( | ||||
|     } | ||||
| 
 | ||||
|     private val fontScaleValues = listOf( | ||||
|             FontScaleValue(0, "FONT_SCALE_TINY", 0.70f, R.string.tiny), | ||||
|             FontScaleValue(1, "FONT_SCALE_SMALL", 0.85f, R.string.small), | ||||
|             FontScaleValue(2, "FONT_SCALE_NORMAL", 1.00f, R.string.normal), | ||||
|             FontScaleValue(3, "FONT_SCALE_LARGE", 1.15f, R.string.large), | ||||
|             FontScaleValue(4, "FONT_SCALE_LARGER", 1.30f, R.string.larger), | ||||
|             FontScaleValue(5, "FONT_SCALE_LARGEST", 1.45f, R.string.largest), | ||||
|             FontScaleValue(6, "FONT_SCALE_HUGE", 1.60f, R.string.huge) | ||||
|             FontScaleValue(0, "FONT_SCALE_TINY", FontScalePreferences.SCALE_TINY, R.string.tiny), | ||||
|             FontScaleValue(1, "FONT_SCALE_SMALL", FontScalePreferences.SCALE_SMALL, R.string.small), | ||||
|             FontScaleValue(2, "FONT_SCALE_NORMAL", FontScalePreferences.SCALE_NORMAL, R.string.normal), | ||||
|             FontScaleValue(3, "FONT_SCALE_LARGE", FontScalePreferences.SCALE_LARGE, R.string.large), | ||||
|             FontScaleValue(4, "FONT_SCALE_LARGER", FontScalePreferences.SCALE_LARGER, R.string.larger), | ||||
|             FontScaleValue(5, "FONT_SCALE_LARGEST", FontScalePreferences.SCALE_LARGEST, R.string.largest), | ||||
|             FontScaleValue(6, "FONT_SCALE_HUGE", FontScalePreferences.SCALE_HUGE, R.string.huge) | ||||
|     ) | ||||
| 
 | ||||
|     private val normalFontScaleValue = fontScaleValues[2] | ||||
|  | ||||
| @ -60,6 +60,7 @@ class IncomingShareController @Inject constructor( | ||||
|                                 roomSummary, | ||||
|                                 data.selectedRoomIds, | ||||
|                                 RoomListDisplayMode.FILTERED, | ||||
|                                 singleLineLastEvent = false, | ||||
|                                 callback?.let { it::onRoomClicked }, | ||||
|                                 callback?.let { it::onRoomLongClicked } | ||||
|                         ) | ||||
|  | ||||
| @ -2,7 +2,6 @@ | ||||
| <shape xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:shape="rectangle"> | ||||
| 
 | ||||
|     <size android:width="40dp" android:height="40dp"/> | ||||
| 
 | ||||
|     <solid android:color="?vctr_reaction_background_off" /> | ||||
| 
 | ||||
|  | ||||
| @ -5,7 +5,6 @@ | ||||
|     android:id="@+id/recentRoot" | ||||
|     android:layout_width="84dp" | ||||
|     android:layout_height="wrap_content" | ||||
|     android:background="?vctr_toolbar_background" | ||||
|     android:clickable="true" | ||||
|     android:focusable="true" | ||||
|     android:foreground="?attr/selectableItemBackground" | ||||
|  | ||||
| @ -190,7 +190,7 @@ | ||||
|         android:layout_marginTop="3dp" | ||||
|         android:layout_marginEnd="8dp" | ||||
|         android:ellipsize="end" | ||||
|         android:maxLines="2" | ||||
|         android:lines="2" | ||||
|         android:textAlignment="viewStart" | ||||
|         android:textColor="?vctr_content_secondary" | ||||
|         app:layout_constraintEnd_toEndOf="parent" | ||||
|  | ||||
| @ -16,7 +16,7 @@ | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginStart="8dp" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
|         android:layout_marginTop="12dp" | ||||
|         app:layout_constraintStart_toStartOf="parent" | ||||
|         app:layout_constraintTop_toTopOf="parent"> | ||||
| 
 | ||||
| @ -29,23 +29,20 @@ | ||||
| 
 | ||||
|     </FrameLayout> | ||||
| 
 | ||||
|     <!-- Margin bottom does not work, so I use space --> | ||||
|     <Space | ||||
|         android:id="@+id/roomAvatarBottomSpace" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="12dp" | ||||
|         app:layout_constraintStart_toStartOf="parent" | ||||
|         app:layout_constraintTop_toBottomOf="@id/roomAvatarContainer" | ||||
|         tools:layout_marginStart="20dp" /> | ||||
| 
 | ||||
|     <View | ||||
|     <TextView | ||||
|         android:id="@+id/roomNameView" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="15dp" | ||||
|         style="@style/Widget.Vector.TextView.Subtitle" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginStart="@dimen/layout_horizontal_margin" | ||||
|         android:layout_marginTop="12dp" | ||||
|         android:layout_marginEnd="70dp" | ||||
|         android:background="@drawable/placeholder_shape_8" | ||||
|         android:duplicateParentState="true" | ||||
|         android:ellipsize="end" | ||||
|         android:maxLines="1" | ||||
|         android:textColor="?vctr_content_primary" | ||||
|         android:textStyle="bold" | ||||
|         app:layout_constrainedWidth="true" | ||||
|         app:layout_constraintEnd_toEndOf="parent" | ||||
|         app:layout_constraintHorizontal_bias="0.0" | ||||
| @ -53,23 +50,38 @@ | ||||
|         app:layout_constraintStart_toEndOf="@id/roomAvatarContainer" | ||||
|         app:layout_constraintTop_toTopOf="parent" /> | ||||
| 
 | ||||
|     <View | ||||
|         android:id="@+id/roomTypingView" | ||||
|     <TextView | ||||
|         android:id="@+id/subtitleView" | ||||
|         style="@style/Widget.Vector.TextView.Body" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="30dp" | ||||
|         android:layout_marginTop="8dp" | ||||
|         android:layout_marginEnd="20dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginTop="3dp" | ||||
|         android:layout_marginEnd="8dp" | ||||
|         android:background="@drawable/placeholder_shape_8" | ||||
|         android:ellipsize="end" | ||||
|         android:lines="2" | ||||
|         android:textAlignment="viewStart" | ||||
|         android:textColor="?vctr_content_secondary" | ||||
|         app:layout_constraintEnd_toEndOf="parent" | ||||
|         app:layout_constraintStart_toStartOf="@id/roomNameView" | ||||
|         app:layout_constraintTop_toBottomOf="@id/roomNameView" /> | ||||
| 
 | ||||
|     <!-- Margin bottom does not work, so I use space --> | ||||
|     <Space | ||||
|         android:id="@+id/roomAvatarBottomSpace" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="7dp" | ||||
|         app:layout_constraintStart_toStartOf="parent" | ||||
|         app:layout_constraintTop_toBottomOf="@id/subtitleView" | ||||
|         tools:layout_marginStart="120dp" /> | ||||
| 
 | ||||
|     <!-- We use vctr_list_separator_system here for a better rendering --> | ||||
|     <View | ||||
|         android:id="@+id/roomDividerView" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="1dp" | ||||
|         android:background="?vctr_list_separator_system" | ||||
|         app:layout_constraintTop_toBottomOf="@id/roomAvatarBottomSpace" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
|         app:layout_constraintEnd_toEndOf="parent" | ||||
|         app:layout_constraintStart_toStartOf="parent" /> | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user