mirror of
https://github.com/oxen-io/session-android.git
synced 2023-12-14 02:53:01 +01:00
Merge 4a403d4c16
into 82cbf830ae
This commit is contained in:
commit
a98dfdfe4c
6 changed files with 95 additions and 105 deletions
|
@ -114,7 +114,7 @@ class MediaGalleryAdapter extends StickyHeaderGridAdapter {
|
||||||
Slide slide = MediaUtil.getSlideForAttachment(context, mediaRecord.getAttachment());
|
Slide slide = MediaUtil.getSlideForAttachment(context, mediaRecord.getAttachment());
|
||||||
|
|
||||||
if (slide != null) {
|
if (slide != null) {
|
||||||
thumbnailView.setImageResource(glideRequests, slide, false, null);
|
thumbnailView.setImageResource(glideRequests, slide, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
thumbnailView.setOnClickListener(view -> itemClickListener.onMediaClicked(mediaRecord));
|
thumbnailView.setOnClickListener(view -> itemClickListener.onMediaClicked(mediaRecord));
|
||||||
|
|
|
@ -104,7 +104,7 @@ class AlbumThumbnailView : RelativeLayout {
|
||||||
// iterate binding
|
// iterate binding
|
||||||
slides.take(MAX_ALBUM_DISPLAY_SIZE).forEachIndexed { position, slide ->
|
slides.take(MAX_ALBUM_DISPLAY_SIZE).forEachIndexed { position, slide ->
|
||||||
val thumbnailView = getThumbnailView(position)
|
val thumbnailView = getThumbnailView(position)
|
||||||
thumbnailView.setImageResource(glideRequests, slide, isPreview = false, mms = message)
|
thumbnailView.setImageResource(glideRequests, slide, isPreview = false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ class LinkPreviewDraftView : LinearLayout {
|
||||||
binding.thumbnailImageView.root.radius = toPx(4, resources)
|
binding.thumbnailImageView.root.radius = toPx(4, resources)
|
||||||
if (linkPreview.getThumbnail().isPresent) {
|
if (linkPreview.getThumbnail().isPresent) {
|
||||||
// This internally fetches the thumbnail
|
// This internally fetches the thumbnail
|
||||||
binding.thumbnailImageView.root.setImageResource(glide, ImageSlide(context, linkPreview.getThumbnail().get()), false, null)
|
binding.thumbnailImageView.root.setImageResource(glide, ImageSlide(context, linkPreview.getThumbnail().get()), false)
|
||||||
}
|
}
|
||||||
binding.linkPreviewDraftTitleTextView.text = linkPreview.title
|
binding.linkPreviewDraftTitleTextView.text = linkPreview.title
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ class LinkPreviewView : LinearLayout {
|
||||||
// Thumbnail
|
// Thumbnail
|
||||||
if (linkPreview.getThumbnail().isPresent) {
|
if (linkPreview.getThumbnail().isPresent) {
|
||||||
// This internally fetches the thumbnail
|
// This internally fetches the thumbnail
|
||||||
binding.thumbnailImageView.root.setImageResource(glide, ImageSlide(context, linkPreview.getThumbnail().get()), isPreview = false, message)
|
binding.thumbnailImageView.root.setImageResource(glide, ImageSlide(context, linkPreview.getThumbnail().get()), isPreview = false)
|
||||||
binding.thumbnailImageView.root.loadIndicator.isVisible = false
|
binding.thumbnailImageView.root.loadIndicator.isVisible = false
|
||||||
}
|
}
|
||||||
// Title
|
// Title
|
||||||
|
|
|
@ -109,7 +109,7 @@ class QuoteView @JvmOverloads constructor(context: Context, attrs: AttributeSet?
|
||||||
val slide = attachments.thumbnailSlide!!
|
val slide = attachments.thumbnailSlide!!
|
||||||
// This internally fetches the thumbnail
|
// This internally fetches the thumbnail
|
||||||
binding.quoteViewAttachmentThumbnailImageView.root.radius = toPx(4, resources)
|
binding.quoteViewAttachmentThumbnailImageView.root.radius = toPx(4, resources)
|
||||||
binding.quoteViewAttachmentThumbnailImageView.root.setImageResource(glide, slide, false, null)
|
binding.quoteViewAttachmentThumbnailImageView.root.setImageResource(glide, slide, false)
|
||||||
binding.quoteViewAttachmentThumbnailImageView.root.isVisible = true
|
binding.quoteViewAttachmentThumbnailImageView.root.isVisible = true
|
||||||
binding.quoteViewBodyTextView.text = if (MediaUtil.isVideo(slide.asAttachment())) resources.getString(R.string.Slide_video) else resources.getString(R.string.Slide_image)
|
binding.quoteViewBodyTextView.text = if (MediaUtil.isVideo(slide.asAttachment())) resources.getString(R.string.Slide_video) else resources.getString(R.string.Slide_image)
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,18 +21,17 @@ import org.session.libsignal.utilities.ListenableFuture
|
||||||
import org.session.libsignal.utilities.SettableFuture
|
import org.session.libsignal.utilities.SettableFuture
|
||||||
import org.thoughtcrime.securesms.components.GlideBitmapListeningTarget
|
import org.thoughtcrime.securesms.components.GlideBitmapListeningTarget
|
||||||
import org.thoughtcrime.securesms.components.GlideDrawableListeningTarget
|
import org.thoughtcrime.securesms.components.GlideDrawableListeningTarget
|
||||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
|
||||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri
|
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequest
|
import org.thoughtcrime.securesms.mms.GlideRequest
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||||
import org.thoughtcrime.securesms.mms.Slide
|
import org.thoughtcrime.securesms.mms.Slide
|
||||||
import kotlin.Boolean
|
|
||||||
import kotlin.Int
|
|
||||||
import kotlin.getValue
|
|
||||||
import kotlin.lazy
|
|
||||||
import kotlin.let
|
|
||||||
|
|
||||||
open class ThumbnailView: FrameLayout {
|
open class ThumbnailView @JvmOverloads constructor(
|
||||||
|
context: Context,
|
||||||
|
attrs: AttributeSet? = null,
|
||||||
|
defStyleAttr: Int = 0
|
||||||
|
) : FrameLayout(context, attrs, defStyleAttr) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val WIDTH = 0
|
private const val WIDTH = 0
|
||||||
private const val HEIGHT = 1
|
private const val HEIGHT = 1
|
||||||
|
@ -41,9 +40,6 @@ open class ThumbnailView: FrameLayout {
|
||||||
private val binding: ThumbnailViewBinding by lazy { ThumbnailViewBinding.bind(this) }
|
private val binding: ThumbnailViewBinding by lazy { ThumbnailViewBinding.bind(this) }
|
||||||
|
|
||||||
// region Lifecycle
|
// region Lifecycle
|
||||||
constructor(context: Context) : super(context) { initialize(null) }
|
|
||||||
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { initialize(attrs) }
|
|
||||||
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { initialize(attrs) }
|
|
||||||
|
|
||||||
val loadIndicator: View by lazy { binding.thumbnailLoadIndicator }
|
val loadIndicator: View by lazy { binding.thumbnailLoadIndicator }
|
||||||
|
|
||||||
|
@ -52,18 +48,19 @@ open class ThumbnailView: FrameLayout {
|
||||||
private var slide: Slide? = null
|
private var slide: Slide? = null
|
||||||
var radius: Int = 0
|
var radius: Int = 0
|
||||||
|
|
||||||
private fun initialize(attrs: AttributeSet?) {
|
init {
|
||||||
if (attrs != null) {
|
attrs?.let { context.theme.obtainStyledAttributes(it, R.styleable.ThumbnailView, 0, 0) }
|
||||||
val typedArray = context.theme.obtainStyledAttributes(attrs, R.styleable.ThumbnailView, 0, 0)
|
?.apply {
|
||||||
|
dimensDelegate.setBounds(
|
||||||
|
getDimensionPixelSize(R.styleable.ThumbnailView_minWidth, 0),
|
||||||
|
getDimensionPixelSize(R.styleable.ThumbnailView_minHeight, 0),
|
||||||
|
getDimensionPixelSize(R.styleable.ThumbnailView_maxWidth, 0),
|
||||||
|
getDimensionPixelSize(R.styleable.ThumbnailView_maxHeight, 0)
|
||||||
|
)
|
||||||
|
|
||||||
dimensDelegate.setBounds(typedArray.getDimensionPixelSize(R.styleable.ThumbnailView_minWidth, 0),
|
radius = getDimensionPixelSize(R.styleable.ThumbnailView_thumbnail_radius, 0)
|
||||||
typedArray.getDimensionPixelSize(R.styleable.ThumbnailView_minHeight, 0),
|
|
||||||
typedArray.getDimensionPixelSize(R.styleable.ThumbnailView_maxWidth, 0),
|
|
||||||
typedArray.getDimensionPixelSize(R.styleable.ThumbnailView_maxHeight, 0))
|
|
||||||
|
|
||||||
radius = typedArray.getDimensionPixelSize(R.styleable.ThumbnailView_thumbnail_radius, 0)
|
recycle()
|
||||||
|
|
||||||
typedArray.recycle()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,111 +84,104 @@ open class ThumbnailView: FrameLayout {
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Interaction
|
// region Interaction
|
||||||
fun setImageResource(glide: GlideRequests, slide: Slide, isPreview: Boolean, mms: MmsMessageRecord?): ListenableFuture<Boolean> {
|
fun setImageResource(
|
||||||
return setImageResource(glide, slide, isPreview, 0, 0, mms)
|
glide: GlideRequests,
|
||||||
}
|
slide: Slide,
|
||||||
|
isPreview: Boolean
|
||||||
|
): ListenableFuture<Boolean> = setImageResource(glide, slide, isPreview, 0, 0)
|
||||||
|
|
||||||
fun setImageResource(glide: GlideRequests, slide: Slide,
|
fun setImageResource(
|
||||||
|
glide: GlideRequests, slide: Slide,
|
||||||
isPreview: Boolean, naturalWidth: Int,
|
isPreview: Boolean, naturalWidth: Int,
|
||||||
naturalHeight: Int, mms: MmsMessageRecord?): ListenableFuture<Boolean> {
|
naturalHeight: Int
|
||||||
|
): ListenableFuture<Boolean> {
|
||||||
val currentSlide = this.slide
|
|
||||||
|
|
||||||
binding.playOverlay.isVisible = (slide.thumbnailUri != null && slide.hasPlayOverlay() &&
|
binding.playOverlay.isVisible = (slide.thumbnailUri != null && slide.hasPlayOverlay() &&
|
||||||
(slide.transferState == AttachmentTransferProgress.TRANSFER_PROGRESS_DONE || isPreview))
|
(slide.transferState == AttachmentTransferProgress.TRANSFER_PROGRESS_DONE || isPreview))
|
||||||
|
|
||||||
if (equals(currentSlide, slide)) {
|
if (equals(this.slide, slide)) {
|
||||||
// don't re-load slide
|
// don't re-load slide
|
||||||
return SettableFuture(false)
|
return SettableFuture(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (currentSlide != null && currentSlide.fastPreflightId != null && currentSlide.fastPreflightId == slide.fastPreflightId) {
|
|
||||||
// not reloading slide for fast preflight
|
|
||||||
this.slide = slide
|
|
||||||
}
|
|
||||||
|
|
||||||
this.slide = slide
|
this.slide = slide
|
||||||
|
|
||||||
binding.thumbnailLoadIndicator.isVisible = slide.isInProgress
|
binding.thumbnailLoadIndicator.isVisible = slide.isInProgress
|
||||||
binding.thumbnailDownloadIcon.isVisible = slide.transferState == AttachmentTransferProgress.TRANSFER_PROGRESS_FAILED
|
binding.thumbnailDownloadIcon.isVisible =
|
||||||
|
slide.transferState == AttachmentTransferProgress.TRANSFER_PROGRESS_FAILED
|
||||||
|
|
||||||
dimensDelegate.setDimens(naturalWidth, naturalHeight)
|
dimensDelegate.setDimens(naturalWidth, naturalHeight)
|
||||||
invalidate()
|
invalidate()
|
||||||
|
|
||||||
val result = SettableFuture<Boolean>()
|
return SettableFuture<Boolean>().also {
|
||||||
|
|
||||||
when {
|
when {
|
||||||
slide.thumbnailUri != null -> {
|
slide.thumbnailUri != null -> {
|
||||||
buildThumbnailGlideRequest(glide, slide).into(GlideDrawableListeningTarget(binding.thumbnailImage, binding.thumbnailLoadIndicator, result))
|
buildThumbnailGlideRequest(glide, slide).into(
|
||||||
|
GlideDrawableListeningTarget(binding.thumbnailImage, binding.thumbnailLoadIndicator, it)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
slide.hasPlaceholder() -> {
|
slide.hasPlaceholder() -> {
|
||||||
buildPlaceholderGlideRequest(glide, slide).into(GlideBitmapListeningTarget(binding.thumbnailImage, null, result))
|
buildPlaceholderGlideRequest(glide, slide).into(
|
||||||
|
GlideBitmapListeningTarget(binding.thumbnailImage, null, it)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
glide.clear(binding.thumbnailImage)
|
glide.clear(binding.thumbnailImage)
|
||||||
result.set(false)
|
it.set(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun buildThumbnailGlideRequest(glide: GlideRequests, slide: Slide): GlideRequest<Drawable> {
|
private fun buildThumbnailGlideRequest(
|
||||||
|
glide: GlideRequests,
|
||||||
val dimens = dimensDelegate.resourceSize()
|
slide: Slide
|
||||||
|
): GlideRequest<Drawable> = glide.load(DecryptableUri(slide.thumbnailUri!!))
|
||||||
val request = glide.load(DecryptableUri(slide.thumbnailUri!!))
|
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
.let { request ->
|
.overrideDimensions()
|
||||||
if (dimens[WIDTH] == 0 || dimens[HEIGHT] == 0) {
|
|
||||||
request.override(getDefaultWidth(), getDefaultHeight())
|
|
||||||
} else {
|
|
||||||
request.override(dimens[WIDTH], dimens[HEIGHT])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.transition(DrawableTransitionOptions.withCrossFade())
|
.transition(DrawableTransitionOptions.withCrossFade())
|
||||||
.centerCrop()
|
.crop(radius)
|
||||||
|
.missingThumbnailPicture(slide.isInProgress)
|
||||||
|
|
||||||
return if (slide.isInProgress) request else request.apply(RequestOptions.errorOf(R.drawable.ic_missing_thumbnail_picture))
|
private fun buildPlaceholderGlideRequest(
|
||||||
}
|
glide: GlideRequests,
|
||||||
|
slide: Slide
|
||||||
fun buildPlaceholderGlideRequest(glide: GlideRequests, slide: Slide): GlideRequest<Bitmap> {
|
): GlideRequest<Bitmap> = glide.asBitmap()
|
||||||
|
|
||||||
val dimens = dimensDelegate.resourceSize()
|
|
||||||
|
|
||||||
return glide.asBitmap()
|
|
||||||
.load(slide.getPlaceholderRes(context.theme))
|
.load(slide.getPlaceholderRes(context.theme))
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
.let { request ->
|
.overrideDimensions()
|
||||||
if (dimens[WIDTH] == 0 || dimens[HEIGHT] == 0) {
|
|
||||||
request.override(getDefaultWidth(), getDefaultHeight())
|
|
||||||
} else {
|
|
||||||
request.override(dimens[WIDTH], dimens[HEIGHT])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.fitCenter()
|
.fitCenter()
|
||||||
}
|
|
||||||
|
|
||||||
open fun clear(glideRequests: GlideRequests) {
|
open fun clear(glideRequests: GlideRequests) {
|
||||||
glideRequests.clear(binding.thumbnailImage)
|
glideRequests.clear(binding.thumbnailImage)
|
||||||
slide = null
|
slide = null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setImageResource(glideRequests: GlideRequests, uri: Uri): ListenableFuture<Boolean> {
|
fun setImageResource(
|
||||||
val future = SettableFuture<Boolean>()
|
glideRequests: GlideRequests,
|
||||||
|
uri: Uri
|
||||||
var request: GlideRequest<Drawable> = glideRequests.load(DecryptableUri(uri))
|
): ListenableFuture<Boolean> = glideRequests.load(DecryptableUri(uri))
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
.transition(DrawableTransitionOptions.withCrossFade())
|
.transition(DrawableTransitionOptions.withCrossFade())
|
||||||
|
.crop(radius)
|
||||||
|
.intoDrawableTargetAsFuture()
|
||||||
|
|
||||||
request = if (radius > 0) {
|
private fun GlideRequest<Drawable>.intoDrawableTargetAsFuture() =
|
||||||
request.transforms(CenterCrop(), RoundedCorners(radius))
|
SettableFuture<Boolean>().also {
|
||||||
} else {
|
binding.run {
|
||||||
request.transforms(CenterCrop())
|
GlideDrawableListeningTarget(thumbnailImage, thumbnailLoadIndicator, it)
|
||||||
|
}.let { into(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
request.into(GlideDrawableListeningTarget(binding.thumbnailImage, binding.thumbnailLoadIndicator, future))
|
private fun <T> GlideRequest<T>.overrideDimensions() =
|
||||||
|
dimensDelegate.resourceSize().takeIf { 0 !in it }
|
||||||
|
?.let { override(it[WIDTH], it[HEIGHT]) }
|
||||||
|
?: override(getDefaultWidth(), getDefaultHeight())
|
||||||
|
|
||||||
return future
|
private fun <T> GlideRequest<T>.crop(radius: Int) =
|
||||||
}
|
if (radius > 0) transforms(CenterCrop(), RoundedCorners(radius))
|
||||||
|
else transforms(CenterCrop())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun <T> GlideRequest<T>.missingThumbnailPicture(
|
||||||
|
inProgress: Boolean
|
||||||
|
) = takeIf { inProgress } ?: apply(RequestOptions.errorOf(R.drawable.ic_missing_thumbnail_picture))
|
||||||
|
|
Loading…
Reference in a new issue