Do not auto-download videos for thumbnails if traffic undesired
Too much network traffic is likely undesired in - public rooms - metered network connections Change-Id: I7aba03098b15fc8a6f20bbc50d53dec842b4d7c9
This commit is contained in:
parent
82b072a081
commit
d713a782b0
|
@ -0,0 +1,27 @@
|
|||
package de.spiritcroc.util
|
||||
|
||||
import im.vector.app.features.home.room.detail.timeline.item.MessageInformationData
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import javax.inject.Inject
|
||||
|
||||
class ThumbnailGenerationVideoDownloadDecider @Inject constructor() /*val context: Context, val vectorPreference: VectorPreference)*/ {
|
||||
|
||||
fun enableVideoDownloadForThumbnailGeneration(informationData: MessageInformationData? = null): Boolean {
|
||||
// Disable automatic download for public rooms
|
||||
if (informationData?.isPublic.orFalse()) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Disable automatic download for metered connections
|
||||
/* Since this may change later, better check in VectorGlideModelLoader directly
|
||||
context.getSystemService<ConnectivityManager>()!!.apply {
|
||||
if (isActiveNetworkMetered) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Else, enable automatic download
|
||||
return true
|
||||
}
|
||||
}
|
|
@ -17,6 +17,8 @@
|
|||
package im.vector.app.core.glide
|
||||
|
||||
import android.content.Context
|
||||
import android.net.ConnectivityManager
|
||||
import androidx.core.content.getSystemService
|
||||
import com.bumptech.glide.Priority
|
||||
import com.bumptech.glide.load.DataSource
|
||||
import com.bumptech.glide.load.Options
|
||||
|
@ -62,7 +64,7 @@ class VectorGlideModelLoader(private val context: Context) :
|
|||
}
|
||||
|
||||
class VectorGlideDataFetcher(
|
||||
context: Context,
|
||||
private val context: Context,
|
||||
private val data: ImageContentRenderer.Data,
|
||||
private val width: Int,
|
||||
private val height: Int
|
||||
|
@ -130,15 +132,27 @@ class VectorGlideDataFetcher(
|
|||
)
|
||||
}
|
||||
if (result.isFailure && (data.fallbackUrl != null || data.fallbackElementToDecrypt != null)) {
|
||||
// Extract thumbnail from video
|
||||
val isInCache = fileService.isFileInCache(
|
||||
fileName = data.filename,
|
||||
mimeType = data.mimeType,
|
||||
mxcUrl = data.fallbackUrl,
|
||||
elementToDecrypt = data.fallbackElementToDecrypt)
|
||||
if (data.downloadFallbackIfThumbnailMissing || isInCache) {
|
||||
// Disable automatic download for metered connections
|
||||
if (isInCache || !context.getSystemService<ConnectivityManager>()!!.isActiveNetworkMetered) {
|
||||
result = runCatching {
|
||||
fileService.downloadFile(
|
||||
fileName = data.filename,
|
||||
mimeType = data.mimeType,
|
||||
url = data.fallbackUrl,
|
||||
elementToDecrypt = data.fallbackElementToDecrypt)
|
||||
elementToDecrypt = data.fallbackElementToDecrypt
|
||||
)
|
||||
}
|
||||
result = result.getOrNull()?.let { thumbnailExtractor.extractThumbnail(it) } ?: result
|
||||
}
|
||||
}
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
result.fold(
|
||||
{ callback.onDataReady(it.inputStream()) },
|
||||
|
|
|
@ -77,6 +77,7 @@ import de.spiritcroc.menu.toggleExec
|
|||
import de.spiritcroc.recyclerview.StickyHeaderItemDecoration
|
||||
import de.spiritcroc.recyclerview.widget.BetterLinearLayoutManager
|
||||
import de.spiritcroc.recyclerview.widget.LinearLayoutManager
|
||||
import de.spiritcroc.util.ThumbnailGenerationVideoDownloadDecider
|
||||
import im.vector.app.BuildConfig
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.animations.play
|
||||
|
@ -283,6 +284,7 @@ class TimelineFragment @Inject constructor(
|
|||
private val notificationDrawerManager: NotificationDrawerManager,
|
||||
private val eventHtmlRenderer: EventHtmlRenderer,
|
||||
private val vectorPreferences: VectorPreferences,
|
||||
private val generationVideoDownloadDecider: ThumbnailGenerationVideoDownloadDecider,
|
||||
private val bubbleThemeUtils: BubbleThemeUtils,
|
||||
private val threadsManager: ThreadsManager,
|
||||
private val colorProvider: ColorProvider,
|
||||
|
@ -1454,7 +1456,7 @@ class TimelineFragment @Inject constructor(
|
|||
views.composerLayout.views.composerRelatedMessageContent.text = (formattedBody ?: nonFormattedBody)
|
||||
|
||||
// Image Event
|
||||
val data = event.buildImageContentRendererData(dimensionConverter.dpToPx(66))
|
||||
val data = event.buildImageContentRendererData(dimensionConverter.dpToPx(66), generationVideoDownloadDecider.enableVideoDownloadForThumbnailGeneration())
|
||||
val isImageVisible = if (data != null) {
|
||||
imageContentRenderer.render(data, ImageContentRenderer.Mode.THUMBNAIL, views.composerLayout.views.composerRelatedMessageImage)
|
||||
true
|
||||
|
|
|
@ -17,6 +17,7 @@ package im.vector.app.features.home.room.detail.timeline.action
|
|||
|
||||
import com.airbnb.epoxy.TypedEpoxyController
|
||||
import com.airbnb.mvrx.Success
|
||||
import de.spiritcroc.util.ThumbnailGenerationVideoDownloadDecider
|
||||
import im.vector.app.EmojiCompatFontProvider
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.date.DateFormatKind
|
||||
|
@ -66,6 +67,7 @@ class MessageActionsEpoxyController @Inject constructor(
|
|||
private val spanUtils: SpanUtils,
|
||||
private val eventDetailsFormatter: EventDetailsFormatter,
|
||||
private val vectorPreferences: VectorPreferences,
|
||||
private val thumbnailGenerationVideoDownloadDecider: ThumbnailGenerationVideoDownloadDecider,
|
||||
private val dateFormatter: VectorDateFormatter,
|
||||
private val urlMapProvider: UrlMapProvider,
|
||||
private val locationPinProvider: LocationPinProvider
|
||||
|
@ -88,7 +90,7 @@ class MessageActionsEpoxyController @Inject constructor(
|
|||
matrixItem(state.informationData.matrixItem)
|
||||
movementMethod(createLinkMovementMethod(host.listener))
|
||||
imageContentRenderer(host.imageContentRenderer)
|
||||
data(state.timelineEvent()?.buildImageContentRendererData(host.dimensionConverter.dpToPx(66)))
|
||||
data(state.timelineEvent()?.buildImageContentRendererData(host.dimensionConverter.dpToPx(66), host.thumbnailGenerationVideoDownloadDecider.enableVideoDownloadForThumbnailGeneration()))
|
||||
userClicked { host.listener?.didSelectMenuAction(EventSharedAction.OpenUserProfile(state.informationData.senderId)) }
|
||||
bindingOptions(bindingOptions)
|
||||
body(body.toEpoxyCharSequence())
|
||||
|
|
|
@ -500,6 +500,7 @@ class MessageItemFactory @Inject constructor(
|
|||
maxWidth = maxWidth,
|
||||
allowNonMxcUrls = informationData.sendState.isSending(),
|
||||
// Video fallback for generating thumbnails
|
||||
downloadFallbackIfThumbnailMissing = attributes.generateMissingVideoThumbnails,
|
||||
fallbackUrl = messageContent.getFileUrl(),
|
||||
fallbackElementToDecrypt = messageContent.encryptedFileInfo?.toElementToDecrypt()
|
||||
)
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package im.vector.app.features.home.room.detail.timeline.helper
|
||||
|
||||
import de.spiritcroc.util.ThumbnailGenerationVideoDownloadDecider
|
||||
import im.vector.app.EmojiCompatFontProvider
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
|
@ -36,6 +37,7 @@ class MessageItemAttributesFactory @Inject constructor(
|
|||
private val stringProvider: StringProvider,
|
||||
private val displayableEventFormatter: DisplayableEventFormatter,
|
||||
private val preferencesProvider: UserPreferencesProvider,
|
||||
private val thumbnailGenerationVideoDownloadDecider: ThumbnailGenerationVideoDownloadDecider,
|
||||
private val emojiCompatFontProvider: EmojiCompatFontProvider
|
||||
) {
|
||||
|
||||
|
@ -71,7 +73,8 @@ class MessageItemAttributesFactory @Inject constructor(
|
|||
threadDetails = threadDetails,
|
||||
reactionsSummaryEvents = reactionsSummaryEvents,
|
||||
areThreadMessagesEnabled = preferencesProvider.areThreadMessagesEnabled(),
|
||||
autoplayAnimatedImages = preferencesProvider.autoplayAnimatedImages()
|
||||
autoplayAnimatedImages = preferencesProvider.autoplayAnimatedImages(),
|
||||
generateMissingVideoThumbnails = thumbnailGenerationVideoDownloadDecider.enableVideoDownloadForThumbnailGeneration(informationData)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ import org.matrix.android.sdk.api.session.room.model.message.getFileUrl
|
|||
import org.matrix.android.sdk.api.session.room.model.message.getThumbnailUrl
|
||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||
|
||||
fun TimelineEvent.buildImageContentRendererData(maxHeight: Int): ImageContentRenderer.Data? {
|
||||
fun TimelineEvent.buildImageContentRendererData(maxHeight: Int, generateMissingVideoThumbnails: Boolean): ImageContentRenderer.Data? {
|
||||
return when {
|
||||
root.isImageMessage() -> root.getClearContent().toModel<MessageImageContent>()
|
||||
?.let { messageImageContent ->
|
||||
|
@ -59,6 +59,7 @@ fun TimelineEvent.buildImageContentRendererData(maxHeight: Int): ImageContentRen
|
|||
maxWidth = maxHeight * 2,
|
||||
allowNonMxcUrls = false,
|
||||
// Video fallback for generating thumbnails
|
||||
downloadFallbackIfThumbnailMissing = generateMissingVideoThumbnails,
|
||||
fallbackUrl = messageVideoContent.getFileUrl(),
|
||||
fallbackElementToDecrypt = messageVideoContent.encryptedFileInfo?.toElementToDecrypt()
|
||||
)
|
||||
|
|
|
@ -207,6 +207,7 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder>(
|
|||
val threadDetails: ThreadDetails? = null,
|
||||
val areThreadMessagesEnabled: Boolean = false,
|
||||
val autoplayAnimatedImages: Boolean = false,
|
||||
val generateMissingVideoThumbnails: Boolean = false,
|
||||
override val reactionsSummaryEvents: ReactionsSummaryEvents? = null,
|
||||
) : AbsBaseMessageItem.Attributes {
|
||||
|
||||
|
|
|
@ -85,6 +85,7 @@ class ImageContentRenderer @Inject constructor(
|
|||
// If true will load non mxc url, be careful to set it only for images sent by you
|
||||
override val allowNonMxcUrls: Boolean = false,
|
||||
// Fallback for videos: generate preview from video
|
||||
val downloadFallbackIfThumbnailMissing: Boolean = false,
|
||||
val fallbackUrl: String? = null,
|
||||
val fallbackElementToDecrypt: ElementToDecrypt? = null,
|
||||
) : AttachmentData
|
||||
|
|
Loading…
Reference in New Issue