kopia lustrzana https://github.com/ryukoposting/Signal-Android
276 wiersze
8.8 KiB
Kotlin
276 wiersze
8.8 KiB
Kotlin
package org.thoughtcrime.securesms.components
|
|
|
|
import android.content.Context
|
|
import android.graphics.Canvas
|
|
import android.os.Bundle
|
|
import android.os.Parcelable
|
|
import android.util.AttributeSet
|
|
import android.widget.FrameLayout
|
|
import android.widget.ImageView
|
|
import androidx.annotation.ColorInt
|
|
import androidx.annotation.Px
|
|
import androidx.annotation.UiThread
|
|
import androidx.core.os.bundleOf
|
|
import org.signal.core.util.dp
|
|
import org.signal.core.util.getParcelableCompat
|
|
import org.thoughtcrime.securesms.R
|
|
import org.thoughtcrime.securesms.mms.GlideRequests
|
|
import org.thoughtcrime.securesms.mms.Slide
|
|
import org.thoughtcrime.securesms.mms.SlideClickListener
|
|
import org.thoughtcrime.securesms.mms.SlidesClickedListener
|
|
import org.thoughtcrime.securesms.util.Projection.Corners
|
|
import org.thoughtcrime.securesms.util.views.Stub
|
|
|
|
class ConversationItemThumbnail @JvmOverloads constructor(
|
|
context: Context,
|
|
attrs: AttributeSet? = null
|
|
) : FrameLayout(context, attrs) {
|
|
|
|
private var state: ConversationItemThumbnailState
|
|
private var thumbnail: Stub<ThumbnailView>
|
|
private var album: Stub<AlbumThumbnailView>
|
|
private var shade: ImageView
|
|
var footer: Stub<ConversationItemFooter>
|
|
private set
|
|
private var cornerMask: CornerMask
|
|
private var borderless = false
|
|
private var normalBounds: IntArray
|
|
private var gifBounds: IntArray
|
|
private var minimumThumbnailWidth = 0
|
|
private var maximumThumbnailHeight = 0
|
|
|
|
init {
|
|
inflate(context, R.layout.conversation_item_thumbnail, this)
|
|
|
|
thumbnail = Stub(findViewById(R.id.thumbnail_view_stub))
|
|
album = Stub(findViewById(R.id.album_view_stub))
|
|
shade = findViewById(R.id.conversation_thumbnail_shade)
|
|
footer = Stub(findViewById(R.id.footer_view_stub))
|
|
cornerMask = CornerMask(this)
|
|
|
|
var gifWidth = 260.dp
|
|
|
|
if (attrs != null) {
|
|
val typedArray = context.theme.obtainStyledAttributes(attrs, R.styleable.ConversationItemThumbnail, 0, 0)
|
|
normalBounds = intArrayOf(
|
|
typedArray.getDimensionPixelSize(R.styleable.ConversationItemThumbnail_conversationThumbnail_minWidth, 0),
|
|
typedArray.getDimensionPixelSize(R.styleable.ConversationItemThumbnail_conversationThumbnail_maxWidth, 0),
|
|
typedArray.getDimensionPixelSize(R.styleable.ConversationItemThumbnail_conversationThumbnail_minHeight, 0),
|
|
typedArray.getDimensionPixelSize(R.styleable.ConversationItemThumbnail_conversationThumbnail_maxHeight, 0)
|
|
)
|
|
|
|
gifWidth = typedArray.getDimensionPixelSize(R.styleable.ConversationItemThumbnail_conversationThumbnail_gifWidth, gifWidth)
|
|
|
|
typedArray.recycle()
|
|
} else {
|
|
normalBounds = intArrayOf(0, 0, 0, 0)
|
|
}
|
|
|
|
gifBounds = intArrayOf(
|
|
gifWidth,
|
|
gifWidth,
|
|
1,
|
|
Int.MAX_VALUE
|
|
)
|
|
|
|
minimumThumbnailWidth = -1
|
|
maximumThumbnailHeight = -1
|
|
|
|
state = ConversationItemThumbnailState()
|
|
}
|
|
|
|
override fun dispatchDraw(canvas: Canvas) {
|
|
super.dispatchDraw(canvas)
|
|
if (!borderless) {
|
|
cornerMask.mask(canvas)
|
|
}
|
|
}
|
|
|
|
override fun onSaveInstanceState(): Parcelable? {
|
|
val root = super.onSaveInstanceState()
|
|
return bundleOf(
|
|
STATE_ROOT to root,
|
|
STATE_STATE to state
|
|
)
|
|
}
|
|
|
|
override fun onRestoreInstanceState(state: Parcelable) {
|
|
if (state is Bundle && state.containsKey(STATE_STATE)) {
|
|
val root: Parcelable? = state.getParcelableCompat(STATE_ROOT, Parcelable::class.java)
|
|
this.state = state.getParcelableCompat(STATE_STATE, ConversationItemThumbnailState::class.java)!!
|
|
super.onRestoreInstanceState(root)
|
|
} else {
|
|
super.onRestoreInstanceState(state)
|
|
}
|
|
}
|
|
|
|
override fun setFocusable(focusable: Boolean) {
|
|
state = state.copy(
|
|
thumbnailViewState = state.thumbnailViewState.copy(focusable = focusable),
|
|
albumViewState = state.albumViewState.copy(focusable = focusable)
|
|
)
|
|
|
|
state.applyState(thumbnail, album)
|
|
}
|
|
|
|
override fun setClickable(clickable: Boolean) {
|
|
state = state.copy(
|
|
thumbnailViewState = state.thumbnailViewState.copy(clickable = clickable),
|
|
albumViewState = state.albumViewState.copy(clickable = clickable)
|
|
)
|
|
|
|
state.applyState(thumbnail, album)
|
|
}
|
|
|
|
override fun setOnLongClickListener(l: OnLongClickListener?) {
|
|
state = state.copy(
|
|
thumbnailViewState = state.thumbnailViewState.copy(longClickListener = l),
|
|
albumViewState = state.albumViewState.copy(longClickListener = l)
|
|
)
|
|
|
|
state.applyState(thumbnail, album)
|
|
}
|
|
|
|
fun hideThumbnailView() {
|
|
state = state.copy(thumbnailViewState = state.thumbnailViewState.copy(alpha = 0f))
|
|
state.thumbnailViewState.applyState(thumbnail)
|
|
}
|
|
|
|
fun showThumbnailView() {
|
|
state = state.copy(thumbnailViewState = state.thumbnailViewState.copy(alpha = 1f))
|
|
state.thumbnailViewState.applyState(thumbnail)
|
|
}
|
|
|
|
val corners: Corners
|
|
get() = Corners(cornerMask.radii)
|
|
|
|
fun showShade(show: Boolean) {
|
|
shade.visibility = if (show) VISIBLE else GONE
|
|
forceLayout()
|
|
}
|
|
|
|
fun setCorners(topLeft: Int, topRight: Int, bottomRight: Int, bottomLeft: Int) {
|
|
cornerMask.setRadii(topLeft, topRight, bottomRight, bottomLeft)
|
|
state = state.copy(
|
|
thumbnailViewState = state.thumbnailViewState.copy(
|
|
cornerTopLeft = topLeft,
|
|
cornerTopRight = topRight,
|
|
cornerBottomRight = bottomRight,
|
|
cornerBottomLeft = bottomLeft
|
|
),
|
|
albumViewState = state.albumViewState.copy(
|
|
cornerTopLeft = topLeft,
|
|
cornerTopRight = topRight,
|
|
cornerBottomRight = bottomRight,
|
|
cornerBottomLeft = bottomLeft
|
|
)
|
|
)
|
|
|
|
state.applyState(thumbnail, album)
|
|
}
|
|
|
|
fun setMinimumThumbnailWidth(@Px width: Int) {
|
|
minimumThumbnailWidth = width
|
|
state = state.copy(thumbnailViewState = state.thumbnailViewState.copy(minWidth = width))
|
|
state.thumbnailViewState.applyState(thumbnail)
|
|
}
|
|
|
|
fun setMaximumThumbnailHeight(@Px height: Int) {
|
|
maximumThumbnailHeight = height
|
|
state = state.copy(thumbnailViewState = state.thumbnailViewState.copy(maxHeight = height))
|
|
state.thumbnailViewState.applyState(thumbnail)
|
|
}
|
|
|
|
fun setBorderless(borderless: Boolean) {
|
|
this.borderless = borderless
|
|
}
|
|
|
|
@UiThread
|
|
fun setImageResource(
|
|
glideRequests: GlideRequests,
|
|
slides: List<Slide>,
|
|
showControls: Boolean,
|
|
isPreview: Boolean
|
|
) {
|
|
if (slides.size == 1) {
|
|
val slide = slides[0]
|
|
|
|
if (slide.isVideoGif) {
|
|
setThumbnailBounds(gifBounds)
|
|
} else {
|
|
setThumbnailBounds(normalBounds)
|
|
|
|
if (minimumThumbnailWidth != -1) {
|
|
state = state.copy(thumbnailViewState = state.thumbnailViewState.copy(minWidth = minimumThumbnailWidth))
|
|
}
|
|
|
|
if (maximumThumbnailHeight != -1) {
|
|
state = state.copy(thumbnailViewState = state.thumbnailViewState.copy(maxHeight = maximumThumbnailHeight))
|
|
}
|
|
}
|
|
|
|
state = state.copy(
|
|
thumbnailViewState = state.thumbnailViewState.copy(visibility = VISIBLE),
|
|
albumViewState = state.albumViewState.copy(visibility = GONE)
|
|
)
|
|
|
|
state.applyState(thumbnail, album)
|
|
|
|
val attachment = slides[0].asAttachment()
|
|
|
|
thumbnail.get().setImageResource(glideRequests, slides[0], showControls, isPreview, attachment.width, attachment.height)
|
|
touchDelegate = thumbnail.get().touchDelegate
|
|
} else {
|
|
state = state.copy(
|
|
thumbnailViewState = state.thumbnailViewState.copy(visibility = GONE),
|
|
albumViewState = state.albumViewState.copy(visibility = VISIBLE)
|
|
)
|
|
|
|
state.applyState(thumbnail, album)
|
|
album.get().setSlides(glideRequests, slides, showControls)
|
|
touchDelegate = album.get().touchDelegate
|
|
}
|
|
}
|
|
|
|
fun setConversationColor(@ColorInt color: Int) {
|
|
state = state.copy(albumViewState = state.albumViewState.copy(cellBackgroundColor = color))
|
|
state.albumViewState.applyState(album)
|
|
}
|
|
|
|
fun setThumbnailClickListener(listener: SlideClickListener?) {
|
|
state = state.copy(
|
|
thumbnailViewState = state.thumbnailViewState.copy(clickListener = listener),
|
|
albumViewState = state.albumViewState.copy(clickListener = listener)
|
|
)
|
|
|
|
state.applyState(thumbnail, album)
|
|
}
|
|
|
|
fun setDownloadClickListener(listener: SlidesClickedListener?) {
|
|
state = state.copy(
|
|
thumbnailViewState = state.thumbnailViewState.copy(downloadClickListener = listener),
|
|
albumViewState = state.albumViewState.copy(downloadClickListener = listener)
|
|
)
|
|
|
|
state.applyState(thumbnail, album)
|
|
}
|
|
|
|
private fun setThumbnailBounds(bounds: IntArray) {
|
|
val (minWidth, maxWidth, minHeight, maxHeight) = bounds
|
|
state = state.copy(
|
|
thumbnailViewState = state.thumbnailViewState.copy(
|
|
minWidth = minWidth,
|
|
maxWidth = maxWidth,
|
|
minHeight = minHeight,
|
|
maxHeight = maxHeight
|
|
)
|
|
)
|
|
state.thumbnailViewState.applyState(thumbnail)
|
|
}
|
|
|
|
companion object {
|
|
private const val STATE_ROOT = "state.root"
|
|
private const val STATE_STATE = "state.state"
|
|
}
|
|
}
|