feat: wiring up click listeners in AlbumThumbnailView.kt

This commit is contained in:
jubb 2021-06-25 12:18:52 +10:00
parent 4a8c5f5946
commit 21835800ff
5 changed files with 120 additions and 26 deletions

View File

@ -1,27 +1,27 @@
package org.thoughtcrime.securesms.components; package org.thoughtcrime.securesms.components;
import android.content.Context; import android.content.Context;
import androidx.annotation.ColorInt;
import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.TextView; import android.widget.TextView;
import network.loki.messenger.R; import androidx.annotation.ColorInt;
import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.thoughtcrime.securesms.conversation.v2.utilities.ThumbnailView; import org.session.libsession.utilities.Stub;
import org.thoughtcrime.securesms.conversation.v2.utilities.KThumbnailView;
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 org.thoughtcrime.securesms.mms.SlideClickListener; import org.thoughtcrime.securesms.mms.SlideClickListener;
import org.thoughtcrime.securesms.mms.SlidesClickedListener; import org.thoughtcrime.securesms.mms.SlidesClickedListener;
import org.session.libsession.utilities.Stub;
import java.util.List; import java.util.List;
import network.loki.messenger.R;
public class AlbumThumbnailView extends FrameLayout { public class AlbumThumbnailView extends FrameLayout {
private @Nullable SlideClickListener thumbnailClickListener; private @Nullable SlideClickListener thumbnailClickListener;
@ -149,7 +149,7 @@ 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); KThumbnailView cell = findViewById(id);
cell.setImageResource(glideRequests, slide, false, false); cell.setImageResource(glideRequests, slide, false, false);
cell.setThumbnailClickListener(defaultThumbnailClickListener); cell.setThumbnailClickListener(defaultThumbnailClickListener);
cell.setOnLongClickListener(defaultLongClickListener); cell.setOnLongClickListener(defaultLongClickListener);

View File

@ -4,6 +4,7 @@ import android.content.Context
import android.graphics.Canvas import android.graphics.Canvas
import android.util.AttributeSet import android.util.AttributeSet
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.core.view.isVisible import androidx.core.view.isVisible
@ -11,21 +12,27 @@ import kotlinx.android.synthetic.main.album_thumbnail_view.view.*
import network.loki.messenger.R import network.loki.messenger.R
import org.thoughtcrime.securesms.components.CornerMask import org.thoughtcrime.securesms.components.CornerMask
import org.thoughtcrime.securesms.conversation.v2.utilities.KThumbnailView import org.thoughtcrime.securesms.conversation.v2.utilities.KThumbnailView
import org.thoughtcrime.securesms.conversation.v2.utilities.ThumbnailView
import org.thoughtcrime.securesms.database.model.MmsMessageRecord import org.thoughtcrime.securesms.database.model.MmsMessageRecord
import org.thoughtcrime.securesms.mms.GlideRequests import org.thoughtcrime.securesms.mms.GlideRequests
import org.thoughtcrime.securesms.mms.Slide
import org.thoughtcrime.securesms.mms.SlideClickListener
import org.thoughtcrime.securesms.mms.SlidesClickedListener
class AlbumThumbnailView: FrameLayout { class AlbumThumbnailView: FrameLayout, SlideClickListener, SlidesClickedListener, View.OnClickListener {
// region Lifecycle // region Lifecycle
constructor(context: Context) : super(context) { initialize() } constructor(context: Context) : super(context) { initialize() }
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { initialize() } constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { initialize() }
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { initialize() } constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { initialize() }
private var slideClickListener: ((Slide) -> Unit)? = null
private var downloadClickListener: ((Slide) -> Unit)? = null
private var readMoreListener: (() -> Unit)? = null
private val cornerMask by lazy { CornerMask(this) } private val cornerMask by lazy { CornerMask(this) }
private fun initialize() { private fun initialize() {
LayoutInflater.from(context).inflate(R.layout.album_thumbnail_view, this) LayoutInflater.from(context).inflate(R.layout.album_thumbnail_view, this)
albumCellBodyTextReadMore.setOnClickListener(this)
} }
override fun dispatchDraw(canvas: Canvas?) { override fun dispatchDraw(canvas: Canvas?) {
@ -37,7 +44,34 @@ class AlbumThumbnailView: FrameLayout {
// region Interaction // region Interaction
fun bind(glideRequests: GlideRequests, message: MmsMessageRecord, isStart: Boolean, isEnd: Boolean) { override fun onClick(v: View?) {
// clicked the view or one of its children
if (v === albumCellBodyTextReadMore) {
readMoreListener?.invoke()
}
}
override fun onClick(v: View?, slide: Slide?) {
// slide thumbnail clicked
if (slide==null) return
slideClickListener?.invoke(slide)
}
override fun onClick(v: View?, slides: MutableList<Slide>?) {
// slide download clicked
if (slides.isNullOrEmpty()) return
slides.firstOrNull().let { slide ->
if (slide == null) return@let
downloadClickListener?.invoke(slide)
}
}
fun bind(glideRequests: GlideRequests, message: MmsMessageRecord,
clickListener: (Slide)->Unit, downloadClickListener: (Slide)->Unit, readMoreListener: ()->Unit,
isStart: Boolean, isEnd: Boolean) {
this.slideClickListener = clickListener
this.downloadClickListener = downloadClickListener
this.readMoreListener = readMoreListener
// TODO: optimize for same size // TODO: optimize for same size
val slides = message.slideDeck.thumbnailSlides val slides = message.slideDeck.thumbnailSlides
if (slides.isEmpty()) { if (slides.isEmpty()) {
@ -49,10 +83,21 @@ class AlbumThumbnailView: FrameLayout {
LayoutInflater.from(context).inflate(layoutRes(slides.size), albumCellContainer) LayoutInflater.from(context).inflate(layoutRes(slides.size), albumCellContainer)
// iterate // iterate
slides.take(5).forEachIndexed { position, slide -> slides.take(5).forEachIndexed { position, slide ->
val imageResource = getThumbnailView(position).setImageResource(glideRequests, slide, showControls = false, isPreview = false) val thumbnailView = getThumbnailView(position)
thumbnailView.thumbnailClickListener = this
thumbnailView.setImageResource(glideRequests, slide, showControls = false, isPreview = false)
thumbnailView.setDownloadClickListener(this)
} }
albumCellBodyParent.isVisible = message.body.isNotEmpty() albumCellBodyParent.isVisible = message.body.isNotEmpty()
albumCellBodyText.text = message.body albumCellBodyText.text = message.body
post {
// post to await layout of text
albumCellBodyText.layout?.let { layout ->
val maxEllipsis = (0 until layout.lineCount).maxByOrNull { lineNum -> layout.getEllipsisCount(lineNum) } ?: 0
// show read more text if at least one line is ellipsized
albumCellBodyTextReadMore.isVisible = maxEllipsis > 0
}
}
} }
// endregion // endregion

View File

@ -4,6 +4,7 @@ import android.content.Context
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
@ -88,7 +89,22 @@ class VisibleMessageContentView : LinearLayout {
mainContainer.addView(albumThumbnailView) mainContainer.addView(albumThumbnailView)
// isStart and isEnd of cluster needed for calculating the mask for full bubble image groups // isStart and isEnd of cluster needed for calculating the mask for full bubble image groups
// bind after add view because views are inflated and calculated during bind // bind after add view because views are inflated and calculated during bind
albumThumbnailView.bind(glide, message, isStartOfMessageCluster, isEndOfMessageCluster) albumThumbnailView.bind(
glideRequests = glide,
message = message,
isStart = isStartOfMessageCluster,
isEnd = isEndOfMessageCluster,
clickListener = { slide ->
Log.d("Loki-UI","clicked to display the slide $slide")
},
downloadClickListener = { slide ->
// trigger download of content?
Log.d("Loki-UI","clicked to download the slide $slide")
},
readMoreListener = {
Log.d("Loki-UI", "clicked to read more the message $message")
}
)
} 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))

View File

@ -5,6 +5,7 @@ import android.graphics.Bitmap
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.net.Uri import android.net.Uri
import android.util.AttributeSet import android.util.AttributeSet
import android.view.View
import android.widget.FrameLayout import android.widget.FrameLayout
import android.widget.ProgressBar import android.widget.ProgressBar
import androidx.core.view.isVisible import androidx.core.view.isVisible
@ -26,7 +27,7 @@ import org.thoughtcrime.securesms.components.TransferControlView
import org.thoughtcrime.securesms.mms.* import org.thoughtcrime.securesms.mms.*
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri
open class KThumbnailView: FrameLayout { open class KThumbnailView: FrameLayout, View.OnClickListener {
companion object { companion object {
private const val WIDTH = 0 private const val WIDTH = 0
@ -65,9 +66,9 @@ open class KThumbnailView: FrameLayout {
typedArray.recycle() typedArray.recycle()
} }
setOnClickListener(this)
} }
// region Lifecycle
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
val adjustedDimens = dimensDelegate.resourceSize() val adjustedDimens = dimensDelegate.resourceSize()
if (adjustedDimens[WIDTH] == 0 && adjustedDimens[HEIGHT] == 0) { if (adjustedDimens[WIDTH] == 0 && adjustedDimens[HEIGHT] == 0) {
@ -85,10 +86,16 @@ open class KThumbnailView: FrameLayout {
private fun getDefaultWidth() = maxOf(layoutParams?.width ?: 0, 0) private fun getDefaultWidth() = maxOf(layoutParams?.width ?: 0, 0)
private fun getDefaultHeight() = maxOf(layoutParams?.height ?: 0, 0) private fun getDefaultHeight() = maxOf(layoutParams?.height ?: 0, 0)
// endregion // endregion
// region Interaction // region Interaction
override fun onClick(v: View?) {
if (v === this) {
thumbnailClickListener?.onClick(v, slide)
}
}
fun setImageResource(glide: GlideRequests, slide: Slide, showControls: Boolean, isPreview: Boolean): ListenableFuture<Boolean> { fun setImageResource(glide: GlideRequests, slide: Slide, showControls: Boolean, isPreview: Boolean): ListenableFuture<Boolean> {
return setImageResource(glide, slide, showControls, isPreview, 0, 0) return setImageResource(glide, slide, showControls, isPreview, 0, 0)
} }
@ -216,7 +223,11 @@ open class KThumbnailView: FrameLayout {
} }
fun setDownloadClickListener(listener: SlidesClickedListener) { fun setDownloadClickListener(listener: SlidesClickedListener) {
transferControls.setDownloadClickListener {
slide?.let { slide ->
listener.onClick(it, listOf(slide))
}
}
} }
// endregion // endregion

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<merge <merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
@ -17,7 +18,8 @@
android:layout_gravity="center" android:layout_gravity="center"
android:layout="@layout/transfer_controls_stub" /> android:layout="@layout/transfer_controls_stub" />
<FrameLayout <androidx.constraintlayout.widget.ConstraintLayout
tools:visibility="visible"
android:visibility="gone" android:visibility="gone"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:id="@+id/albumCellBodyParent" android:id="@+id/albumCellBodyParent"
@ -27,23 +29,43 @@
android:id="@+id/albumCellShade" android:id="@+id/albumCellShade"
android:src="@drawable/image_shade" android:src="@drawable/image_shade"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"/> android:layout_height="0dp"
app:layout_constraintTop_toTopOf="@+id/albumCellBodyTextParent"
app:layout_constraintBottom_toBottomOf="parent"
/>
<LinearLayout <LinearLayout
android:id="@+id/albumCellBodyTextParent"
android:padding="@dimen/small_spacing"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/albumCellBodyTextReadMore"
android:orientation="horizontal"> android:orientation="horizontal">
<View <View
android:layout_margin="@dimen/small_spacing" android:layout_marginStart="@dimen/small_spacing"
android:layout_width="@dimen/small_spacing" android:layout_width="@dimen/accent_line_thickness"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/accent"/> android:background="@color/accent"/>
<TextView <TextView
android:maxLines="4"
android:ellipsize="end"
android:id="@+id/albumCellBodyText" android:id="@+id/albumCellBodyText"
android:textColor="@color/core_white" android:textColor="@color/core_white"
android:layout_margin="@dimen/small_spacing" android:layout_margin="@dimen/small_spacing"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
</LinearLayout> </LinearLayout>
</FrameLayout> <TextView
tools:visibility="visible"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:id="@+id/albumCellBodyTextReadMore"
android:textColor="@color/core_white"
android:padding="@dimen/small_spacing"
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/ConversationItem_read_more"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</merge> </merge>