feat: AlbumThumbnailView.kt view visible and binding to thumbnail slides

This commit is contained in:
jubb 2021-06-24 16:15:13 +10:00
parent 19f2546d81
commit 277c741851
12 changed files with 409 additions and 28 deletions

View File

@ -11,6 +11,8 @@ import android.widget.FrameLayout;
import android.widget.TextView;
import network.loki.messenger.R;
import org.thoughtcrime.securesms.components.v2.ThumbnailView;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.mms.Slide;
@ -149,7 +151,6 @@ public class AlbumThumbnailView extends FrameLayout {
private void setSlide(@NonNull GlideRequests glideRequests, @NonNull Slide slide, @IdRes int id) {
ThumbnailView cell = findViewById(id);
cell.setImageResource(glideRequests, slide, false, false);
cell.setLoadIndicatorVisibile(slide.isInProgress());
cell.setThumbnailClickListener(defaultThumbnailClickListener);
cell.setOnLongClickListener(defaultLongClickListener);
}

View File

@ -72,7 +72,6 @@ public class ConversationItemThumbnail extends FrameLayout {
}
}
@SuppressWarnings("SuspiciousNameCombination")
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);

View File

@ -0,0 +1,99 @@
package org.thoughtcrime.securesms.components.v2
import android.content.Context
import android.graphics.Canvas
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.FrameLayout
import kotlinx.android.synthetic.main.album_thumbnail_view.view.*
import network.loki.messenger.R
import org.thoughtcrime.securesms.components.CornerMask
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
import org.thoughtcrime.securesms.mms.GlideRequests
class AlbumThumbnailView: FrameLayout {
// region Lifecycle
constructor(context: Context) : super(context) { initialize() }
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { initialize() }
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { initialize() }
private val albumCellContainer by lazy { album_cell_container }
private lateinit var cornerMask: CornerMask
private fun initialize() {
LayoutInflater.from(context).inflate(R.layout.album_thumbnail_view, this)
cornerMask = CornerMask(this)
cornerMask.setRadius(80)
}
override fun dispatchDraw(canvas: Canvas?) {
super.dispatchDraw(canvas)
cornerMask.mask(canvas)
}
// endregion
// region Interaction
fun bind(glideRequests: GlideRequests, message: MmsMessageRecord, isStart: Boolean, isEnd: Boolean) {
// TODO: optimize for same size
val slides = message.slideDeck.thumbnailSlides
if (slides.isEmpty()) {
// this should never be encountered because it's checked by parent
return
}
calculateRadius(isStart, isEnd, message.isOutgoing)
albumCellContainer.removeAllViews()
LayoutInflater.from(context).inflate(layoutRes(slides.size), albumCellContainer)
// iterate
slides.take(5).forEachIndexed { position, slide ->
getThumbnailView(position).setImageResource(glideRequests, slide, showControls = false, isPreview = false)
}
}
// endregion
fun layoutRes(slideCount: Int) = when (slideCount) {
1 -> R.layout.album_thumbnail_1 // single
2 -> R.layout.album_thumbnail_2// two sidebyside
3 -> R.layout.album_thumbnail_3// three stacked
4 -> R.layout.album_thumbnail_4// four square
5 -> R.layout.album_thumbnail_5//
else -> R.layout.album_thumbnail_many// five or more
}
fun getThumbnailView(position: Int): ThumbnailView = when (position) {
0 -> albumCellContainer.findViewById<ViewGroup>(R.id.album_cell_container).findViewById(R.id.album_cell_1)
1 -> albumCellContainer.findViewById<ViewGroup>(R.id.album_cell_container).findViewById(R.id.album_cell_2)
2 -> albumCellContainer.findViewById<ViewGroup>(R.id.album_cell_container).findViewById(R.id.album_cell_3)
3 -> albumCellContainer.findViewById<ViewGroup>(R.id.album_cell_container).findViewById(R.id.album_cell_4)
4 -> albumCellContainer.findViewById<ViewGroup>(R.id.album_cell_container).findViewById(R.id.album_cell_5)
else -> throw Exception("Can't get thumbnail view for non-existent thumbnail at position: $position")
}
fun calculateRadius(isStart: Boolean, isEnd: Boolean, outgoing: Boolean) {
val roundedDimen = context.resources.getDimension(R.dimen.message_corner_radius).toInt()
val collapsedDimen = context.resources.getDimension(R.dimen.message_corner_collapse_radius).toInt()
val (startTop, endTop, startBottom, endBottom) = when {
// single message, consistent dimen
isStart && isEnd -> intArrayOf(roundedDimen, roundedDimen, roundedDimen, roundedDimen)
// start of message cluster, collapsed BL
isStart -> intArrayOf(roundedDimen, roundedDimen, collapsedDimen, roundedDimen)
// end of message cluster, collapsed TL
isEnd -> intArrayOf(collapsedDimen, roundedDimen, roundedDimen, roundedDimen)
// else in the middle, no rounding left side
else -> intArrayOf(collapsedDimen, roundedDimen, collapsedDimen, roundedDimen)
}
// TL, TR, BR, BL (CW direction)
cornerMask.setRadii(
if (!outgoing) startTop else endTop, // TL
if (!outgoing) endTop else startTop, // TR
if (!outgoing) endBottom else startBottom, // BR
if (!outgoing) startBottom else endBottom // BL
)
}
}

View File

@ -0,0 +1,91 @@
package org.thoughtcrime.securesms.components.v2
class ThumbnailDimensDelegate {
companion object {
// dimens array constants
private const val WIDTH = 0
private const val HEIGHT = 1
private const val DIMENS_ARRAY_SIZE = 2
// bounds array constants
private const val MIN_WIDTH = 0
private const val MIN_HEIGHT = 1
private const val MAX_WIDTH = 2
private const val MAX_HEIGHT = 3
private const val BOUNDS_ARRAY_SIZE = 4
// const zero int array
private val EMPTY_DIMENS = intArrayOf(0,0)
}
private val measured: IntArray = IntArray(DIMENS_ARRAY_SIZE)
private val dimens: IntArray = IntArray(DIMENS_ARRAY_SIZE)
private val bounds: IntArray = IntArray(BOUNDS_ARRAY_SIZE)
fun resourceSize(): IntArray {
if (dimens.all { it == 0 }) {
// dimens are (0, 0), don't go any further
return EMPTY_DIMENS
}
val naturalWidth = dimens[WIDTH].toDouble()
val naturalHeight = dimens[HEIGHT].toDouble()
val minWidth = dimens[MIN_WIDTH]
val maxWidth = dimens[MAX_WIDTH]
val minHeight = dimens[MIN_HEIGHT]
val maxHeight = dimens[MAX_HEIGHT]
// calculate actual measured
var measuredWidth: Double = naturalWidth
var measuredHeight: Double = naturalHeight
val widthInBounds = measuredWidth >= minWidth && measuredWidth <= maxWidth
val heightInBounds = measuredHeight >= minHeight && measuredHeight <= maxHeight
if (!widthInBounds || !heightInBounds) {
val minWidthRatio: Double = naturalWidth / minWidth
val maxWidthRatio: Double = naturalWidth / maxWidth
val minHeightRatio: Double = naturalHeight / minHeight
val maxHeightRatio: Double = naturalHeight / maxHeight
if (maxWidthRatio > 1 || maxHeightRatio > 1) {
if (maxWidthRatio >= maxHeightRatio) {
measuredWidth /= maxWidthRatio
measuredHeight /= maxWidthRatio
} else {
measuredWidth /= maxHeightRatio
measuredHeight /= maxHeightRatio
}
measuredWidth = Math.max(measuredWidth, minWidth.toDouble())
measuredHeight = Math.max(measuredHeight, minHeight.toDouble())
} else if (minWidthRatio < 1 || minHeightRatio < 1) {
if (minWidthRatio <= minHeightRatio) {
measuredWidth /= minWidthRatio
measuredHeight /= minWidthRatio
} else {
measuredWidth /= minHeightRatio
measuredHeight /= minHeightRatio
}
measuredWidth = Math.min(measuredWidth, maxWidth.toDouble())
measuredHeight = Math.min(measuredHeight, maxHeight.toDouble())
}
}
measured[WIDTH] = measuredWidth.toInt()
measured[HEIGHT] = measuredHeight.toInt()
return measured
}
fun setBounds(minWidth: Int, minHeight: Int, maxWidth: Int, maxHeight: Int) {
bounds[MIN_WIDTH] = minWidth
bounds[MIN_HEIGHT] = minHeight
bounds[MAX_WIDTH] = maxWidth
bounds[MAX_HEIGHT] = maxHeight
}
fun setDimens(width: Int, height: Int) {
dimens[WIDTH] = width
dimens[HEIGHT] = height
}
}

View File

@ -0,0 +1,174 @@
package org.thoughtcrime.securesms.components.v2
import android.content.Context
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.widget.FrameLayout
import android.widget.ProgressBar
import androidx.core.view.isVisible
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
import com.bumptech.glide.request.RequestOptions
import kotlinx.android.synthetic.main.thumbnail_view.view.*
import network.loki.messenger.R
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress
import org.session.libsession.utilities.Util.equals
import org.session.libsession.utilities.ViewUtil
import org.thoughtcrime.securesms.components.TransferControlView
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri
import org.thoughtcrime.securesms.mms.GlideRequest
import org.thoughtcrime.securesms.mms.GlideRequests
import org.thoughtcrime.securesms.mms.Slide
import org.thoughtcrime.securesms.mms.SlideClickListener
class ThumbnailView: FrameLayout {
companion object {
private const val WIDTH = 0
private const val HEIGHT = 1
}
// 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) }
private val image by lazy { thumbnail_image }
private val playOverlay by lazy { play_overlay }
private val captionIcon by lazy { thumbnail_caption_icon }
val loadIndicator: ProgressBar by lazy { thumbnail_load_indicator }
private val transferControls by lazy { ViewUtil.inflateStub<TransferControlView>(this, R.id.transfer_controls_stub) }
private val dimensDelegate = ThumbnailDimensDelegate()
var thumbnailClickListener: SlideClickListener? = null
private var slide: Slide? = null
private fun initialize(attrs: AttributeSet?) {
inflate(context, R.layout.thumbnail_view, this)
if (attrs != null) {
val typedArray = context.theme.obtainStyledAttributes(attrs, R.styleable.ThumbnailView, 0, 0)
dimensDelegate.setBounds(typedArray.getDimensionPixelSize(R.styleable.ConversationItemThumbnail_conversationThumbnail_minWidth, 0),
typedArray.getDimensionPixelSize(R.styleable.ConversationItemThumbnail_conversationThumbnail_minHeight, 0),
typedArray.getDimensionPixelSize(R.styleable.ConversationItemThumbnail_conversationThumbnail_maxWidth, 0),
typedArray.getDimensionPixelSize(R.styleable.ConversationItemThumbnail_conversationThumbnail_maxHeight, 0))
typedArray.recycle()
}
}
// region Lifecycle
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
val adjustedDimens = dimensDelegate.resourceSize()
if (adjustedDimens[WIDTH] == 0 && adjustedDimens[HEIGHT] == 0) {
return super.onMeasure(widthMeasureSpec, heightMeasureSpec)
}
val finalWidth: Int = adjustedDimens[WIDTH] + paddingLeft + paddingRight
val finalHeight: Int = adjustedDimens[HEIGHT] + paddingTop + paddingBottom
super.onMeasure(
MeasureSpec.makeMeasureSpec(finalWidth, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(finalHeight, MeasureSpec.EXACTLY)
)
}
private fun getDefaultWidth() = maxOf(layoutParams?.width ?: 0, 0)
private fun getDefaultHeight() = maxOf(layoutParams?.height ?: 0, 0)
// endregion
// region Interaction
fun setImageResource(glide: GlideRequests, slide: Slide, showControls: Boolean, isPreview: Boolean) {
return setImageResource(glide, slide, showControls, isPreview, 0, 0)
}
fun setImageResource(glide: GlideRequests, slide: Slide,
showControls: Boolean, isPreview: Boolean,
naturalWidth: Int, naturalHeight: Int) {
val currentSlide = this.slide
if (showControls) {
transferControls.setSlide(slide)
// transferControls.setDownloadClickListener() TODO: re-add this
} else {
transferControls.isVisible = false
}
playOverlay.isVisible = (slide.thumbnailUri != null && slide.hasPlayOverlay() &&
(slide.transferState == AttachmentTransferProgress.TRANSFER_PROGRESS_DONE || isPreview))
if (equals(currentSlide, slide)) {
// don't re-load slide
return
}
if (currentSlide != null && currentSlide.fastPreflightId != null && currentSlide.fastPreflightId == slide.fastPreflightId) {
// not reloading slide for fast preflight
this.slide = slide
}
this.slide = slide
captionIcon.isVisible = slide.caption.isPresent
loadIndicator.isVisible = slide.isInProgress
dimensDelegate.setDimens(naturalWidth, naturalHeight)
invalidate()
when {
slide.thumbnailUri != null -> {
buildThumbnailGlideRequest(glide, slide).into(image)
}
slide.hasPlaceholder() -> {
buildPlaceholderGlideRequest(glide, slide).into(image)
}
else -> {
glide.clear(image)
}
}
}
fun buildThumbnailGlideRequest(glide: GlideRequests, slide: Slide): GlideRequest<Drawable> {
val dimens = dimensDelegate.resourceSize()
val request = glide.load(DecryptableUri(slide.thumbnailUri!!))
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
.let { request ->
if (dimens[WIDTH] == 0 || dimens[HEIGHT] == 0) {
request.override(getDefaultWidth(), getDefaultHeight())
} else {
request.override(dimens[WIDTH], dimens[HEIGHT])
}
}
.transition(DrawableTransitionOptions.withCrossFade())
.centerCrop()
return if (slide.isInProgress) request else request.apply(RequestOptions.errorOf(R.drawable.ic_missing_thumbnail_picture))
}
fun buildPlaceholderGlideRequest(glide: GlideRequests, slide: Slide): GlideRequest<Bitmap> {
val dimens = dimensDelegate.resourceSize()
return glide.asBitmap()
.load(slide.getPlaceholderRes(context.theme))
.diskCacheStrategy(DiskCacheStrategy.NONE)
.let { request ->
if (dimens[WIDTH] == 0 || dimens[HEIGHT] == 0) {
request.override(getDefaultWidth(), getDefaultHeight())
} else {
request.override(dimens[WIDTH], dimens[HEIGHT])
}
}
.fitCenter()
}
// endregion
}

View File

@ -1,11 +1,9 @@
package org.thoughtcrime.securesms.conversation.v2.messages
import android.content.Context
import android.content.res.ColorStateList
import android.graphics.drawable.Drawable
import android.text.util.Linkify
import android.util.AttributeSet
import android.util.Log
import android.util.TypedValue
import android.view.LayoutInflater
import android.widget.LinearLayout
@ -17,11 +15,10 @@ import androidx.core.graphics.BlendModeColorFilterCompat
import androidx.core.graphics.BlendModeCompat
import kotlinx.android.synthetic.main.view_visible_message_content.view.*
import network.loki.messenger.R
import org.session.libsession.messaging.utilities.UpdateMessageData
import org.session.libsession.messaging.utilities.UpdateMessageData.Companion.fromJSON
import org.session.libsession.utilities.ThemeUtil
import org.session.libsession.utilities.ViewUtil
import org.session.libsession.utilities.recipients.Recipient
import org.thoughtcrime.securesms.components.v2.AlbumThumbnailView
import org.thoughtcrime.securesms.database.model.MessageRecord
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
import org.thoughtcrime.securesms.loki.utilities.UiMode
@ -89,9 +86,10 @@ class VisibleMessageContentView : LinearLayout {
documentView.bind(message, VisibleMessageContentView.getTextColor(context, message))
mainContainer.addView(documentView)
} else if (message is MmsMessageRecord && message.slideDeck.asAttachments().isNotEmpty()) {
val dummyTextView = TextView(context)
dummyTextView.text = "asifuygaihsfo"
mainContainer.addView(dummyTextView)
val albumThumbnailView = AlbumThumbnailView(context)
mainContainer.addView(albumThumbnailView)
// isStart and isEnd of cluster needed for calculating the mask for full bubble image groups
albumThumbnailView.bind(glide, message, isStartOfMessageCluster, isEndOfMessageCluster)
} else if (message.isOpenGroupInvitation) {
val openGroupInvitationView = OpenGroupInvitationView(context)
openGroupInvitationView.bind(message, VisibleMessageContentView.getTextColor(context, message))

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/album_thumbnail_root"
android:layout_width="@dimen/media_bubble_default_dimens"
android:layout_height="@dimen/media_bubble_default_dimens">
<org.thoughtcrime.securesms.components.v2.ThumbnailView
android:id="@+id/album_cell_1"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:conversationThumbnail_minWidth="@dimen/media_bubble_min_width"
app:conversationThumbnail_maxWidth="@dimen/media_bubble_max_width"
app:conversationThumbnail_minHeight="@dimen/media_bubble_min_height"
app:conversationThumbnail_maxHeight="@dimen/media_bubble_max_height"
app:thumbnail_radius="1dp"/>
</FrameLayout>

View File

@ -7,13 +7,13 @@
android:layout_width="@dimen/album_total_width"
android:layout_height="@dimen/album_2_total_height">
<org.thoughtcrime.securesms.components.ThumbnailView
<org.thoughtcrime.securesms.components.v2.ThumbnailView
android:id="@+id/album_cell_1"
android:layout_width="@dimen/album_2_cell_width"
android:layout_height="@dimen/album_2_total_height"
app:thumbnail_radius="0dp"/>
<org.thoughtcrime.securesms.components.ThumbnailView
<org.thoughtcrime.securesms.components.v2.ThumbnailView
android:id="@+id/album_cell_2"
android:layout_width="@dimen/album_2_cell_width"
android:layout_height="@dimen/album_2_total_height"

View File

@ -6,20 +6,20 @@
android:layout_width="@dimen/album_total_width"
android:layout_height="@dimen/album_3_total_height">
<org.thoughtcrime.securesms.components.ThumbnailView
<org.thoughtcrime.securesms.components.v2.ThumbnailView
android:id="@+id/album_cell_1"
android:layout_width="@dimen/album_3_cell_width_big"
android:layout_height="@dimen/album_3_total_height"
app:thumbnail_radius="0dp"/>
<org.thoughtcrime.securesms.components.ThumbnailView
<org.thoughtcrime.securesms.components.v2.ThumbnailView
android:id="@+id/album_cell_2"
android:layout_width="@dimen/album_3_cell_size_small"
android:layout_height="@dimen/album_3_cell_size_small"
android:layout_gravity="right|end|top"
app:thumbnail_radius="0dp"/>
<org.thoughtcrime.securesms.components.ThumbnailView
<org.thoughtcrime.securesms.components.v2.ThumbnailView
android:id="@+id/album_cell_3"
android:layout_width="@dimen/album_3_cell_size_small"
android:layout_height="@dimen/album_3_cell_size_small"

View File

@ -6,27 +6,27 @@
android:layout_width="@dimen/album_total_width"
android:layout_height="@dimen/album_4_total_height">
<org.thoughtcrime.securesms.components.ThumbnailView
<org.thoughtcrime.securesms.components.v2.ThumbnailView
android:id="@+id/album_cell_1"
android:layout_width="@dimen/album_4_cell_size"
android:layout_height="@dimen/album_4_cell_size"
app:thumbnail_radius="0dp"/>
<org.thoughtcrime.securesms.components.ThumbnailView
<org.thoughtcrime.securesms.components.v2.ThumbnailView
android:id="@+id/album_cell_2"
android:layout_width="@dimen/album_4_cell_size"
android:layout_height="@dimen/album_4_cell_size"
android:layout_gravity="right|end|top"
app:thumbnail_radius="0dp"/>
<org.thoughtcrime.securesms.components.ThumbnailView
<org.thoughtcrime.securesms.components.v2.ThumbnailView
android:id="@+id/album_cell_3"
android:layout_width="@dimen/album_4_cell_size"
android:layout_height="@dimen/album_4_cell_size"
android:layout_gravity="left|start|bottom"
app:thumbnail_radius="0dp"/>
<org.thoughtcrime.securesms.components.ThumbnailView
<org.thoughtcrime.securesms.components.v2.ThumbnailView
android:id="@+id/album_cell_4"
android:layout_width="@dimen/album_4_cell_size"
android:layout_height="@dimen/album_4_cell_size"

View File

@ -6,34 +6,34 @@
android:layout_width="@dimen/album_total_width"
android:layout_height="@dimen/album_5_total_height">
<org.thoughtcrime.securesms.components.ThumbnailView
<org.thoughtcrime.securesms.components.v2.ThumbnailView
android:id="@+id/album_cell_1"
android:layout_width="@dimen/album_5_cell_size_big"
android:layout_height="@dimen/album_5_cell_size_big"
app:thumbnail_radius="0dp"/>
<org.thoughtcrime.securesms.components.ThumbnailView
<org.thoughtcrime.securesms.components.v2.ThumbnailView
android:id="@+id/album_cell_2"
android:layout_width="@dimen/album_5_cell_size_big"
android:layout_height="@dimen/album_5_cell_size_big"
android:layout_gravity="right|end|top"
app:thumbnail_radius="0dp"/>
<org.thoughtcrime.securesms.components.ThumbnailView
<org.thoughtcrime.securesms.components.v2.ThumbnailView
android:id="@+id/album_cell_3"
android:layout_width="@dimen/album_5_cell_size_small"
android:layout_height="@dimen/album_5_cell_size_small"
android:layout_gravity="left|start|bottom"
app:thumbnail_radius="0dp"/>
<org.thoughtcrime.securesms.components.ThumbnailView
<org.thoughtcrime.securesms.components.v2.ThumbnailView
android:id="@+id/album_cell_4"
android:layout_width="@dimen/album_5_cell_size_small"
android:layout_height="@dimen/album_5_cell_size_small"
android:layout_gravity="center_horizontal|bottom"
app:thumbnail_radius="0dp"/>
<org.thoughtcrime.securesms.components.ThumbnailView
<org.thoughtcrime.securesms.components.v2.ThumbnailView
android:id="@+id/album_cell_5"
android:layout_width="@dimen/album_5_cell_size_small"
android:layout_height="@dimen/album_5_cell_size_small"

View File

@ -7,27 +7,27 @@
android:layout_width="@dimen/album_total_width"
android:layout_height="@dimen/album_5_total_height">
<org.thoughtcrime.securesms.components.ThumbnailView
<org.thoughtcrime.securesms.components.v2.ThumbnailView
android:id="@+id/album_cell_1"
android:layout_width="@dimen/album_5_cell_size_big"
android:layout_height="@dimen/album_5_cell_size_big"
app:thumbnail_radius="0dp"/>
<org.thoughtcrime.securesms.components.ThumbnailView
<org.thoughtcrime.securesms.components.v2.ThumbnailView
android:id="@+id/album_cell_2"
android:layout_width="@dimen/album_5_cell_size_big"
android:layout_height="@dimen/album_5_cell_size_big"
android:layout_gravity="right|end|top"
app:thumbnail_radius="0dp"/>
<org.thoughtcrime.securesms.components.ThumbnailView
<org.thoughtcrime.securesms.components.v2.ThumbnailView
android:id="@+id/album_cell_3"
android:layout_width="@dimen/album_5_cell_size_small"
android:layout_height="@dimen/album_5_cell_size_small"
android:layout_gravity="left|start|bottom"
app:thumbnail_radius="0dp"/>
<org.thoughtcrime.securesms.components.ThumbnailView
<org.thoughtcrime.securesms.components.v2.ThumbnailView
android:id="@+id/album_cell_4"
android:layout_width="@dimen/album_5_cell_size_small"
android:layout_height="@dimen/album_5_cell_size_small"
@ -39,7 +39,7 @@
android:layout_height="@dimen/album_5_cell_size_small"
android:layout_gravity="right|end|bottom">
<org.thoughtcrime.securesms.components.ThumbnailView
<org.thoughtcrime.securesms.components.v2.ThumbnailView
android:id="@+id/album_cell_5"
android:layout_height="match_parent"
android:layout_width="match_parent"