Timeline media : compute max size from recyclerview size

This commit is contained in:
ganfra 2019-01-24 18:04:55 +01:00
parent 946ae32cd8
commit 3cbdba2fe9
5 changed files with 59 additions and 11 deletions

View File

@ -49,6 +49,8 @@ dependencies {


implementation 'androidx.appcompat:appcompat:1.1.0-alpha01' implementation 'androidx.appcompat:appcompat:1.1.0-alpha01'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.core:core-ktx:1.0.1'

// Paging // Paging
implementation 'androidx.paging:paging-runtime:2.0.0' implementation 'androidx.paging:paging-runtime:2.0.0'



View File

@ -10,6 +10,7 @@ import im.vector.riotredesign.features.home.room.detail.timeline.RoomTopicItemFa
import im.vector.riotredesign.features.home.room.detail.timeline.TimelineDateFormatter import im.vector.riotredesign.features.home.room.detail.timeline.TimelineDateFormatter
import im.vector.riotredesign.features.home.room.detail.timeline.TimelineEventController import im.vector.riotredesign.features.home.room.detail.timeline.TimelineEventController
import im.vector.riotredesign.features.home.room.detail.timeline.TimelineItemFactory import im.vector.riotredesign.features.home.room.detail.timeline.TimelineItemFactory
import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider
import org.koin.dsl.module.module import org.koin.dsl.module.module


class HomeModule { class HomeModule {
@ -21,7 +22,7 @@ class HomeModule {
} }


single { single {
MessageItemFactory(get()) MessageItemFactory(get(), get())
} }


single { single {
@ -49,7 +50,11 @@ class HomeModule {
} }


factory { (roomId: String) -> factory { (roomId: String) ->
TimelineEventController(roomId, get(), get()) TimelineEventController(roomId, get(), get(), get())
}

single {
TimelineMediaSizeProvider()
} }


single { single {

View File

@ -11,9 +11,11 @@ import im.vector.matrix.android.api.session.room.model.message.MessageContent
import im.vector.matrix.android.api.session.room.model.message.MessageImageContent import im.vector.matrix.android.api.session.room.model.message.MessageImageContent
import im.vector.matrix.android.api.session.room.model.message.MessageTextContent import im.vector.matrix.android.api.session.room.model.message.MessageTextContent
import im.vector.riotredesign.core.extensions.localDateTime import im.vector.riotredesign.core.extensions.localDateTime
import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider
import im.vector.riotredesign.features.media.MediaContentRenderer import im.vector.riotredesign.features.media.MediaContentRenderer


class MessageItemFactory(private val timelineDateFormatter: TimelineDateFormatter) { class MessageItemFactory(private val timelineMediaSizeProvider: TimelineMediaSizeProvider,
private val timelineDateFormatter: TimelineDateFormatter) {


private val messagesDisplayedWithInformation = HashSet<String?>() private val messagesDisplayedWithInformation = HashSet<String?>()


@ -29,12 +31,12 @@ class MessageItemFactory(private val timelineDateFormatter: TimelineDateFormatte
val nextDate = nextEvent?.root?.localDateTime() val nextDate = nextEvent?.root?.localDateTime()
val addDaySeparator = date.toLocalDate() != nextDate?.toLocalDate() val addDaySeparator = date.toLocalDate() != nextDate?.toLocalDate()
val isNextMessageReceivedMoreThanOneHourAgo = nextDate?.isBefore(date.minusMinutes(60)) val isNextMessageReceivedMoreThanOneHourAgo = nextDate?.isBefore(date.minusMinutes(60))
?: false ?: false


if (addDaySeparator if (addDaySeparator
|| nextRoomMember != roomMember || nextRoomMember != roomMember
|| nextEvent?.root?.type != EventType.MESSAGE || nextEvent?.root?.type != EventType.MESSAGE
|| isNextMessageReceivedMoreThanOneHourAgo) { || isNextMessageReceivedMoreThanOneHourAgo) {
messagesDisplayedWithInformation.add(event.root.eventId) messagesDisplayedWithInformation.add(event.root.eventId)
} }


@ -54,13 +56,14 @@ class MessageItemFactory(private val timelineDateFormatter: TimelineDateFormatte


private fun buildImageMessageItem(messageContent: MessageImageContent, private fun buildImageMessageItem(messageContent: MessageImageContent,
informationData: MessageInformationData): MessageImageItem? { informationData: MessageInformationData): MessageImageItem? {
// TODO : manage maxHeight/maxWidth
val (maxWidth, maxHeight) = timelineMediaSizeProvider.getMaxSize()
val data = MediaContentRenderer.Data( val data = MediaContentRenderer.Data(
url = messageContent.url, url = messageContent.url,
height = messageContent.info.height, height = messageContent.info.height,
maxHeight = 800, maxHeight = maxHeight,
width = messageContent.info.width, width = messageContent.info.width,
maxWidth = 800, maxWidth = maxWidth,
rotation = messageContent.info.rotation, rotation = messageContent.info.rotation,
orientation = messageContent.info.orientation orientation = messageContent.info.orientation
) )

View File

@ -1,5 +1,6 @@
package im.vector.riotredesign.features.home.room.detail.timeline package im.vector.riotredesign.features.home.room.detail.timeline


import androidx.recyclerview.widget.RecyclerView
import com.airbnb.epoxy.EpoxyAsyncUtil import com.airbnb.epoxy.EpoxyAsyncUtil
import com.airbnb.epoxy.EpoxyModel import com.airbnb.epoxy.EpoxyModel
import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.events.model.EventType
@ -7,11 +8,13 @@ import im.vector.matrix.android.api.session.events.model.TimelineEvent
import im.vector.matrix.android.api.session.room.timeline.TimelineData import im.vector.matrix.android.api.session.room.timeline.TimelineData
import im.vector.riotredesign.core.extensions.localDateTime import im.vector.riotredesign.core.extensions.localDateTime
import im.vector.riotredesign.features.home.LoadingItemModel_ import im.vector.riotredesign.features.home.LoadingItemModel_
import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider
import im.vector.riotredesign.features.home.room.detail.timeline.paging.PagedListEpoxyController import im.vector.riotredesign.features.home.room.detail.timeline.paging.PagedListEpoxyController


class TimelineEventController(private val roomId: String, class TimelineEventController(private val roomId: String,
private val dateFormatter: TimelineDateFormatter, private val dateFormatter: TimelineDateFormatter,
private val timelineItemFactory: TimelineItemFactory private val timelineItemFactory: TimelineItemFactory,
private val timelineMediaSizeProvider: TimelineMediaSizeProvider
) : PagedListEpoxyController<TimelineEvent>( ) : PagedListEpoxyController<TimelineEvent>(
EpoxyAsyncUtil.getAsyncBackgroundHandler(), EpoxyAsyncUtil.getAsyncBackgroundHandler(),
EpoxyAsyncUtil.getAsyncBackgroundHandler() EpoxyAsyncUtil.getAsyncBackgroundHandler()
@ -36,6 +39,10 @@ class TimelineEventController(private val roomId: String,
} }
} }


override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
super.onAttachedToRecyclerView(recyclerView)
timelineMediaSizeProvider.recyclerView = recyclerView
}


override fun buildItemModels(currentPosition: Int, items: List<TimelineEvent?>): List<EpoxyModel<*>> { override fun buildItemModels(currentPosition: Int, items: List<TimelineEvent?>): List<EpoxyModel<*>> {
if (items.isNullOrEmpty()) { if (items.isNullOrEmpty()) {

View File

@ -0,0 +1,31 @@
package im.vector.riotredesign.features.home.room.detail.timeline.helper

import androidx.recyclerview.widget.RecyclerView

class TimelineMediaSizeProvider {

lateinit var recyclerView: RecyclerView
private var cachedSize: Pair<Int, Int>? = null

fun getMaxSize(): Pair<Int, Int> {
return cachedSize ?: computeMaxSize().also { cachedSize = it }
}

private fun computeMaxSize(): Pair<Int, Int> {
val width = recyclerView.width
val height = recyclerView.height
val maxImageWidth: Int
val maxImageHeight: Int
// landscape / portrait
if (width < height) {
maxImageWidth = Math.round(width * 0.7f)
maxImageHeight = Math.round(height * 0.5f)
} else {
maxImageWidth = Math.round(width * 0.5f)
maxImageHeight = Math.round(height * 0.7f)
}
return Pair(maxImageWidth, maxImageHeight)
}


}