mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-28 04:25:18 +00:00
feat: AlbumThumbnailView.kt view visible and binding to thumbnail slides
This commit is contained in:
parent
19f2546d81
commit
277c741851
@ -11,6 +11,8 @@ import android.widget.FrameLayout;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import network.loki.messenger.R;
|
import network.loki.messenger.R;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.components.v2.ThumbnailView;
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.mms.Slide;
|
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) {
|
private void setSlide(@NonNull GlideRequests glideRequests, @NonNull Slide slide, @IdRes int id) {
|
||||||
ThumbnailView cell = findViewById(id);
|
ThumbnailView cell = findViewById(id);
|
||||||
cell.setImageResource(glideRequests, slide, false, false);
|
cell.setImageResource(glideRequests, slide, false, false);
|
||||||
cell.setLoadIndicatorVisibile(slide.isInProgress());
|
|
||||||
cell.setThumbnailClickListener(defaultThumbnailClickListener);
|
cell.setThumbnailClickListener(defaultThumbnailClickListener);
|
||||||
cell.setOnLongClickListener(defaultLongClickListener);
|
cell.setOnLongClickListener(defaultLongClickListener);
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,6 @@ public class ConversationItemThumbnail extends FrameLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("SuspiciousNameCombination")
|
|
||||||
@Override
|
@Override
|
||||||
protected void dispatchDraw(Canvas canvas) {
|
protected void dispatchDraw(Canvas canvas) {
|
||||||
super.dispatchDraw(canvas);
|
super.dispatchDraw(canvas);
|
||||||
|
@ -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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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
|
||||||
|
|
||||||
|
}
|
@ -1,11 +1,9 @@
|
|||||||
package org.thoughtcrime.securesms.conversation.v2.messages
|
package org.thoughtcrime.securesms.conversation.v2.messages
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.ColorStateList
|
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.text.util.Linkify
|
import android.text.util.Linkify
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.util.Log
|
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
@ -17,11 +15,10 @@ import androidx.core.graphics.BlendModeColorFilterCompat
|
|||||||
import androidx.core.graphics.BlendModeCompat
|
import androidx.core.graphics.BlendModeCompat
|
||||||
import kotlinx.android.synthetic.main.view_visible_message_content.view.*
|
import kotlinx.android.synthetic.main.view_visible_message_content.view.*
|
||||||
import network.loki.messenger.R
|
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.ThemeUtil
|
||||||
import org.session.libsession.utilities.ViewUtil
|
import org.session.libsession.utilities.ViewUtil
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
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.MessageRecord
|
||||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
||||||
import org.thoughtcrime.securesms.loki.utilities.UiMode
|
import org.thoughtcrime.securesms.loki.utilities.UiMode
|
||||||
@ -89,9 +86,10 @@ class VisibleMessageContentView : LinearLayout {
|
|||||||
documentView.bind(message, VisibleMessageContentView.getTextColor(context, message))
|
documentView.bind(message, VisibleMessageContentView.getTextColor(context, message))
|
||||||
mainContainer.addView(documentView)
|
mainContainer.addView(documentView)
|
||||||
} else if (message is MmsMessageRecord && message.slideDeck.asAttachments().isNotEmpty()) {
|
} else if (message is MmsMessageRecord && message.slideDeck.asAttachments().isNotEmpty()) {
|
||||||
val dummyTextView = TextView(context)
|
val albumThumbnailView = AlbumThumbnailView(context)
|
||||||
dummyTextView.text = "asifuygaihsfo"
|
mainContainer.addView(albumThumbnailView)
|
||||||
mainContainer.addView(dummyTextView)
|
// 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) {
|
} else if (message.isOpenGroupInvitation) {
|
||||||
val openGroupInvitationView = OpenGroupInvitationView(context)
|
val openGroupInvitationView = OpenGroupInvitationView(context)
|
||||||
openGroupInvitationView.bind(message, VisibleMessageContentView.getTextColor(context, message))
|
openGroupInvitationView.bind(message, VisibleMessageContentView.getTextColor(context, message))
|
||||||
|
19
app/src/main/res/layout/album_thumbnail_1.xml
Normal file
19
app/src/main/res/layout/album_thumbnail_1.xml
Normal 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>
|
@ -7,13 +7,13 @@
|
|||||||
android:layout_width="@dimen/album_total_width"
|
android:layout_width="@dimen/album_total_width"
|
||||||
android:layout_height="@dimen/album_2_total_height">
|
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:id="@+id/album_cell_1"
|
||||||
android:layout_width="@dimen/album_2_cell_width"
|
android:layout_width="@dimen/album_2_cell_width"
|
||||||
android:layout_height="@dimen/album_2_total_height"
|
android:layout_height="@dimen/album_2_total_height"
|
||||||
app:thumbnail_radius="0dp"/>
|
app:thumbnail_radius="0dp"/>
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.ThumbnailView
|
<org.thoughtcrime.securesms.components.v2.ThumbnailView
|
||||||
android:id="@+id/album_cell_2"
|
android:id="@+id/album_cell_2"
|
||||||
android:layout_width="@dimen/album_2_cell_width"
|
android:layout_width="@dimen/album_2_cell_width"
|
||||||
android:layout_height="@dimen/album_2_total_height"
|
android:layout_height="@dimen/album_2_total_height"
|
||||||
|
@ -6,20 +6,20 @@
|
|||||||
android:layout_width="@dimen/album_total_width"
|
android:layout_width="@dimen/album_total_width"
|
||||||
android:layout_height="@dimen/album_3_total_height">
|
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:id="@+id/album_cell_1"
|
||||||
android:layout_width="@dimen/album_3_cell_width_big"
|
android:layout_width="@dimen/album_3_cell_width_big"
|
||||||
android:layout_height="@dimen/album_3_total_height"
|
android:layout_height="@dimen/album_3_total_height"
|
||||||
app:thumbnail_radius="0dp"/>
|
app:thumbnail_radius="0dp"/>
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.ThumbnailView
|
<org.thoughtcrime.securesms.components.v2.ThumbnailView
|
||||||
android:id="@+id/album_cell_2"
|
android:id="@+id/album_cell_2"
|
||||||
android:layout_width="@dimen/album_3_cell_size_small"
|
android:layout_width="@dimen/album_3_cell_size_small"
|
||||||
android:layout_height="@dimen/album_3_cell_size_small"
|
android:layout_height="@dimen/album_3_cell_size_small"
|
||||||
android:layout_gravity="right|end|top"
|
android:layout_gravity="right|end|top"
|
||||||
app:thumbnail_radius="0dp"/>
|
app:thumbnail_radius="0dp"/>
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.ThumbnailView
|
<org.thoughtcrime.securesms.components.v2.ThumbnailView
|
||||||
android:id="@+id/album_cell_3"
|
android:id="@+id/album_cell_3"
|
||||||
android:layout_width="@dimen/album_3_cell_size_small"
|
android:layout_width="@dimen/album_3_cell_size_small"
|
||||||
android:layout_height="@dimen/album_3_cell_size_small"
|
android:layout_height="@dimen/album_3_cell_size_small"
|
||||||
|
@ -6,27 +6,27 @@
|
|||||||
android:layout_width="@dimen/album_total_width"
|
android:layout_width="@dimen/album_total_width"
|
||||||
android:layout_height="@dimen/album_4_total_height">
|
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:id="@+id/album_cell_1"
|
||||||
android:layout_width="@dimen/album_4_cell_size"
|
android:layout_width="@dimen/album_4_cell_size"
|
||||||
android:layout_height="@dimen/album_4_cell_size"
|
android:layout_height="@dimen/album_4_cell_size"
|
||||||
app:thumbnail_radius="0dp"/>
|
app:thumbnail_radius="0dp"/>
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.ThumbnailView
|
<org.thoughtcrime.securesms.components.v2.ThumbnailView
|
||||||
android:id="@+id/album_cell_2"
|
android:id="@+id/album_cell_2"
|
||||||
android:layout_width="@dimen/album_4_cell_size"
|
android:layout_width="@dimen/album_4_cell_size"
|
||||||
android:layout_height="@dimen/album_4_cell_size"
|
android:layout_height="@dimen/album_4_cell_size"
|
||||||
android:layout_gravity="right|end|top"
|
android:layout_gravity="right|end|top"
|
||||||
app:thumbnail_radius="0dp"/>
|
app:thumbnail_radius="0dp"/>
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.ThumbnailView
|
<org.thoughtcrime.securesms.components.v2.ThumbnailView
|
||||||
android:id="@+id/album_cell_3"
|
android:id="@+id/album_cell_3"
|
||||||
android:layout_width="@dimen/album_4_cell_size"
|
android:layout_width="@dimen/album_4_cell_size"
|
||||||
android:layout_height="@dimen/album_4_cell_size"
|
android:layout_height="@dimen/album_4_cell_size"
|
||||||
android:layout_gravity="left|start|bottom"
|
android:layout_gravity="left|start|bottom"
|
||||||
app:thumbnail_radius="0dp"/>
|
app:thumbnail_radius="0dp"/>
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.ThumbnailView
|
<org.thoughtcrime.securesms.components.v2.ThumbnailView
|
||||||
android:id="@+id/album_cell_4"
|
android:id="@+id/album_cell_4"
|
||||||
android:layout_width="@dimen/album_4_cell_size"
|
android:layout_width="@dimen/album_4_cell_size"
|
||||||
android:layout_height="@dimen/album_4_cell_size"
|
android:layout_height="@dimen/album_4_cell_size"
|
||||||
|
@ -6,34 +6,34 @@
|
|||||||
android:layout_width="@dimen/album_total_width"
|
android:layout_width="@dimen/album_total_width"
|
||||||
android:layout_height="@dimen/album_5_total_height">
|
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:id="@+id/album_cell_1"
|
||||||
android:layout_width="@dimen/album_5_cell_size_big"
|
android:layout_width="@dimen/album_5_cell_size_big"
|
||||||
android:layout_height="@dimen/album_5_cell_size_big"
|
android:layout_height="@dimen/album_5_cell_size_big"
|
||||||
app:thumbnail_radius="0dp"/>
|
app:thumbnail_radius="0dp"/>
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.ThumbnailView
|
<org.thoughtcrime.securesms.components.v2.ThumbnailView
|
||||||
android:id="@+id/album_cell_2"
|
android:id="@+id/album_cell_2"
|
||||||
android:layout_width="@dimen/album_5_cell_size_big"
|
android:layout_width="@dimen/album_5_cell_size_big"
|
||||||
android:layout_height="@dimen/album_5_cell_size_big"
|
android:layout_height="@dimen/album_5_cell_size_big"
|
||||||
android:layout_gravity="right|end|top"
|
android:layout_gravity="right|end|top"
|
||||||
app:thumbnail_radius="0dp"/>
|
app:thumbnail_radius="0dp"/>
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.ThumbnailView
|
<org.thoughtcrime.securesms.components.v2.ThumbnailView
|
||||||
android:id="@+id/album_cell_3"
|
android:id="@+id/album_cell_3"
|
||||||
android:layout_width="@dimen/album_5_cell_size_small"
|
android:layout_width="@dimen/album_5_cell_size_small"
|
||||||
android:layout_height="@dimen/album_5_cell_size_small"
|
android:layout_height="@dimen/album_5_cell_size_small"
|
||||||
android:layout_gravity="left|start|bottom"
|
android:layout_gravity="left|start|bottom"
|
||||||
app:thumbnail_radius="0dp"/>
|
app:thumbnail_radius="0dp"/>
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.ThumbnailView
|
<org.thoughtcrime.securesms.components.v2.ThumbnailView
|
||||||
android:id="@+id/album_cell_4"
|
android:id="@+id/album_cell_4"
|
||||||
android:layout_width="@dimen/album_5_cell_size_small"
|
android:layout_width="@dimen/album_5_cell_size_small"
|
||||||
android:layout_height="@dimen/album_5_cell_size_small"
|
android:layout_height="@dimen/album_5_cell_size_small"
|
||||||
android:layout_gravity="center_horizontal|bottom"
|
android:layout_gravity="center_horizontal|bottom"
|
||||||
app:thumbnail_radius="0dp"/>
|
app:thumbnail_radius="0dp"/>
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.ThumbnailView
|
<org.thoughtcrime.securesms.components.v2.ThumbnailView
|
||||||
android:id="@+id/album_cell_5"
|
android:id="@+id/album_cell_5"
|
||||||
android:layout_width="@dimen/album_5_cell_size_small"
|
android:layout_width="@dimen/album_5_cell_size_small"
|
||||||
android:layout_height="@dimen/album_5_cell_size_small"
|
android:layout_height="@dimen/album_5_cell_size_small"
|
||||||
|
@ -7,27 +7,27 @@
|
|||||||
android:layout_width="@dimen/album_total_width"
|
android:layout_width="@dimen/album_total_width"
|
||||||
android:layout_height="@dimen/album_5_total_height">
|
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:id="@+id/album_cell_1"
|
||||||
android:layout_width="@dimen/album_5_cell_size_big"
|
android:layout_width="@dimen/album_5_cell_size_big"
|
||||||
android:layout_height="@dimen/album_5_cell_size_big"
|
android:layout_height="@dimen/album_5_cell_size_big"
|
||||||
app:thumbnail_radius="0dp"/>
|
app:thumbnail_radius="0dp"/>
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.ThumbnailView
|
<org.thoughtcrime.securesms.components.v2.ThumbnailView
|
||||||
android:id="@+id/album_cell_2"
|
android:id="@+id/album_cell_2"
|
||||||
android:layout_width="@dimen/album_5_cell_size_big"
|
android:layout_width="@dimen/album_5_cell_size_big"
|
||||||
android:layout_height="@dimen/album_5_cell_size_big"
|
android:layout_height="@dimen/album_5_cell_size_big"
|
||||||
android:layout_gravity="right|end|top"
|
android:layout_gravity="right|end|top"
|
||||||
app:thumbnail_radius="0dp"/>
|
app:thumbnail_radius="0dp"/>
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.ThumbnailView
|
<org.thoughtcrime.securesms.components.v2.ThumbnailView
|
||||||
android:id="@+id/album_cell_3"
|
android:id="@+id/album_cell_3"
|
||||||
android:layout_width="@dimen/album_5_cell_size_small"
|
android:layout_width="@dimen/album_5_cell_size_small"
|
||||||
android:layout_height="@dimen/album_5_cell_size_small"
|
android:layout_height="@dimen/album_5_cell_size_small"
|
||||||
android:layout_gravity="left|start|bottom"
|
android:layout_gravity="left|start|bottom"
|
||||||
app:thumbnail_radius="0dp"/>
|
app:thumbnail_radius="0dp"/>
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.ThumbnailView
|
<org.thoughtcrime.securesms.components.v2.ThumbnailView
|
||||||
android:id="@+id/album_cell_4"
|
android:id="@+id/album_cell_4"
|
||||||
android:layout_width="@dimen/album_5_cell_size_small"
|
android:layout_width="@dimen/album_5_cell_size_small"
|
||||||
android:layout_height="@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_height="@dimen/album_5_cell_size_small"
|
||||||
android:layout_gravity="right|end|bottom">
|
android:layout_gravity="right|end|bottom">
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.ThumbnailView
|
<org.thoughtcrime.securesms.components.v2.ThumbnailView
|
||||||
android:id="@+id/album_cell_5"
|
android:id="@+id/album_cell_5"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
Loading…
Reference in New Issue
Block a user