refactor: use activity dispatcher

This commit is contained in:
jubb 2021-06-25 16:30:23 +10:00
parent bb00754237
commit 9cccbd7aae
6 changed files with 72 additions and 35 deletions

View File

@ -1,6 +1,7 @@
package org.thoughtcrime.securesms.conversation.v2 package org.thoughtcrime.securesms.conversation.v2
import android.content.Context import android.content.Context
import android.content.Intent
import android.graphics.Canvas import android.graphics.Canvas
import android.graphics.Rect import android.graphics.Rect
import android.util.AttributeSet import android.util.AttributeSet
@ -11,9 +12,12 @@ import androidx.core.view.children
import androidx.core.view.isVisible import androidx.core.view.isVisible
import kotlinx.android.synthetic.main.album_thumbnail_view.view.* import kotlinx.android.synthetic.main.album_thumbnail_view.view.*
import network.loki.messenger.R import network.loki.messenger.R
import org.thoughtcrime.securesms.MediaPreviewActivity
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.database.model.MmsMessageRecord import org.thoughtcrime.securesms.database.model.MmsMessageRecord
import org.thoughtcrime.securesms.loki.utilities.ActivityDispatcher
import org.thoughtcrime.securesms.longmessage.LongMessageActivity
import org.thoughtcrime.securesms.mms.GlideRequests import org.thoughtcrime.securesms.mms.GlideRequests
import org.thoughtcrime.securesms.mms.Slide import org.thoughtcrime.securesms.mms.Slide
@ -35,12 +39,6 @@ class AlbumThumbnailView : FrameLayout {
private val cornerMask by lazy { CornerMask(this) } private val cornerMask by lazy { CornerMask(this) }
private var slides: List<Slide> = listOf() private var slides: List<Slide> = listOf()
sealed class Hit {
object ReadMoreHit : Hit()
data class SlideHit(val slide: Slide) : Hit()
data class DownloadHit(val slide: Slide) : Hit()
}
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)
} }
@ -54,25 +52,42 @@ class AlbumThumbnailView : FrameLayout {
// region Interaction // region Interaction
fun calculateHitObject(hitRect: Rect): Hit? { fun calculateHitObject(rawRect: Rect, mms: MmsMessageRecord) {
// Z-check in specific order // Z-check in specific order
val testRect = Rect() val testRect = Rect()
// test "Read More" // test "Read More"
albumCellBodyTextReadMore.getHitRect(testRect) albumCellBodyTextReadMore.getGlobalVisibleRect(testRect)
if (Rect.intersects(hitRect, testRect)) { if (Rect.intersects(rawRect, testRect)) {
return Hit.ReadMoreHit // dispatch to activity view
ActivityDispatcher.get(context)?.dispatchIntent { context ->
LongMessageActivity.getIntent(context, mms.recipient.address, mms.getId(), true)
}
return
} }
// test each album child // test each album child
albumCellContainer.findViewById<ViewGroup>(R.id.album_thumbnail_root)?.children?.forEachIndexed { index, child -> albumCellContainer.findViewById<ViewGroup>(R.id.album_thumbnail_root)?.children?.forEachIndexed { index, child ->
child.getHitRect(testRect) child.getGlobalVisibleRect(testRect)
if (Rect.intersects(hitRect, testRect)) { if (Rect.intersects(rawRect, testRect)) {
// hit intersects with this particular child // hit intersects with this particular child
slides.getOrNull(index)?.let { slide -> slides.getOrNull(index)?.let { slide ->
return Hit.SlideHit(slide) // dispatch to view image
if (MediaPreviewActivity.isContentTypeSupported(slide.contentType) && slide.uri != null) {
ActivityDispatcher.get(context)?.dispatchIntent { context ->
Intent(context, MediaPreviewActivity::class.java).apply {
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
setDataAndType(slide.uri, slide.contentType)
putExtra(MediaPreviewActivity.ADDRESS_EXTRA, mms.recipient.address)
putExtra(MediaPreviewActivity.OUTGOING_EXTRA, mms.isOutgoing)
putExtra(MediaPreviewActivity.DATE_EXTRA, mms.timestamp)
putExtra(MediaPreviewActivity.SIZE_EXTRA, slide.asAttachment().size)
putExtra(MediaPreviewActivity.CAPTION_EXTRA, slide.caption.orNull())
putExtra(MediaPreviewActivity.LEFT_IS_RECENT_EXTRA, false)
}
}
}
} }
} }
} }
return null
} }
fun bind(glideRequests: GlideRequests, message: MmsMessageRecord, fun bind(glideRequests: GlideRequests, message: MmsMessageRecord,

View File

@ -2,6 +2,9 @@ package org.thoughtcrime.securesms.conversation.v2
import android.animation.FloatEvaluator import android.animation.FloatEvaluator
import android.animation.ValueAnimator import android.animation.ValueAnimator
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.res.Resources import android.content.res.Resources
import android.database.Cursor import android.database.Cursor
import android.graphics.Rect import android.graphics.Rect
@ -46,6 +49,9 @@ import org.thoughtcrime.securesms.database.model.MessageRecord
import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository
import org.thoughtcrime.securesms.linkpreview.LinkPreviewViewModel import org.thoughtcrime.securesms.linkpreview.LinkPreviewViewModel
import org.thoughtcrime.securesms.linkpreview.LinkPreviewViewModel.LinkPreviewState import org.thoughtcrime.securesms.linkpreview.LinkPreviewViewModel.LinkPreviewState
import org.thoughtcrime.securesms.loki.utilities.ActivityDispatcher
import org.thoughtcrime.securesms.loki.utilities.push
import org.thoughtcrime.securesms.loki.utilities.show
import org.thoughtcrime.securesms.loki.utilities.toPx import org.thoughtcrime.securesms.loki.utilities.toPx
import org.thoughtcrime.securesms.mms.GlideApp import org.thoughtcrime.securesms.mms.GlideApp
import org.thoughtcrime.securesms.util.DateUtils import org.thoughtcrime.securesms.util.DateUtils
@ -57,7 +63,7 @@ import kotlin.math.*
// price we pay is a bit of back and forth between the input bar and the conversation activity. // price we pay is a bit of back and forth between the input bar and the conversation activity.
class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDelegate, class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDelegate,
InputBarRecordingViewDelegate, ConversationRecyclerViewDelegate { InputBarRecordingViewDelegate, ConversationRecyclerViewDelegate, ActivityDispatcher {
private val scrollButtonFullVisibilityThreshold by lazy { toPx(120.0f, resources) } private val scrollButtonFullVisibilityThreshold by lazy { toPx(120.0f, resources) }
private val scrollButtonNoVisibilityThreshold by lazy { toPx(20.0f, resources) } private val scrollButtonNoVisibilityThreshold by lazy { toPx(20.0f, resources) }
private val screenWidth = Resources.getSystem().displayMetrics.widthPixels private val screenWidth = Resources.getSystem().displayMetrics.widthPixels
@ -76,8 +82,8 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
val adapter = ConversationAdapter( val adapter = ConversationAdapter(
this, this,
cursor, cursor,
onItemPress = { message, position, view, rect -> onItemPress = { message, position, view, rawRect ->
handlePress(message, position, view, rect) handlePress(message, position, view, rawRect)
}, },
onItemSwipeToReply = { message, position -> onItemSwipeToReply = { message, position ->
handleSwipeToReply(message, position) handleSwipeToReply(message, position)
@ -138,6 +144,18 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
ApplicationContext.getInstance(this).messageNotifier.setVisibleThread(-1) ApplicationContext.getInstance(this).messageNotifier.setVisibleThread(-1)
} }
override fun getSystemService(name: String): Any? {
if (name == ActivityDispatcher.SERVICE) {
return this
}
return super.getSystemService(name)
}
override fun dispatchIntent(body: (Context) -> Intent) {
val intent = body(this)
push(intent, false)
}
private fun setUpRecyclerView() { private fun setUpRecyclerView() {
conversationRecyclerView.adapter = adapter conversationRecyclerView.adapter = adapter
val layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, true) val layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, true)
@ -452,7 +470,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
} }
// `position` is the adapter position; not the visual position // `position` is the adapter position; not the visual position
private fun handlePress(message: MessageRecord, position: Int, view: VisibleMessageView, hitRect: Rect) { private fun handlePress(message: MessageRecord, position: Int, view: VisibleMessageView, rawRect: Rect) {
val actionMode = this.actionMode val actionMode = this.actionMode
if (actionMode != null) { if (actionMode != null) {
adapter.toggleSelection(message, position) adapter.toggleSelection(message, position)
@ -467,7 +485,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
// We have to use onContentClick (rather than a click listener directly on // We have to use onContentClick (rather than a click listener directly on
// the view) so as to not interfere with all the other gestures. Do not add // the view) so as to not interfere with all the other gestures. Do not add
// onClickListeners directly to message content views. // onClickListeners directly to message content views.
view.onContentClick(hitRect) view.onContentClick(rawRect)
} }
} }

View File

@ -69,7 +69,7 @@ class ConversationAdapter(context: Context, cursor: Cursor, private val onItemPr
view.messageTimestampTextView.isVisible = isSelected view.messageTimestampTextView.isVisible = isSelected
val position = viewHolder.adapterPosition val position = viewHolder.adapterPosition
view.bind(message, getMessageBefore(position, cursor), getMessageAfter(position, cursor), glide) view.bind(message, getMessageBefore(position, cursor), getMessageAfter(position, cursor), glide)
view.onPress = { x, y -> onItemPress(message, viewHolder.adapterPosition, view, Rect(x,y,x,y)) } view.onPress = { rawX, rawY -> onItemPress(message, viewHolder.adapterPosition, view, Rect(rawX, rawY, rawX, rawY)) }
view.onSwipeToReply = { onItemSwipeToReply(message, viewHolder.adapterPosition) } view.onSwipeToReply = { onItemSwipeToReply(message, viewHolder.adapterPosition) }
view.onLongPress = { onItemLongPress(message, viewHolder.adapterPosition) } view.onLongPress = { onItemLongPress(message, viewHolder.adapterPosition) }
} }

View File

@ -31,7 +31,7 @@ import org.thoughtcrime.securesms.mms.GlideRequests
import kotlin.math.roundToInt import kotlin.math.roundToInt
class VisibleMessageContentView : LinearLayout { class VisibleMessageContentView : LinearLayout {
var onContentClick: ((Rect) -> Unit)? = null var onContentClick: ((rawRect: Rect) -> Unit)? = null
// region Lifecycle // region Lifecycle
constructor(context: Context) : super(context) { initialize() } constructor(context: Context) : super(context) { initialize() }
@ -96,16 +96,7 @@ class VisibleMessageContentView : LinearLayout {
isStart = isStartOfMessageCluster, isStart = isStartOfMessageCluster,
isEnd = isEndOfMessageCluster isEnd = isEndOfMessageCluster
) )
onContentClick = { onContentClick = { albumThumbnailView.calculateHitObject(it, message) }
when (val hitObject = albumThumbnailView.calculateHitObject(it)) {
is AlbumThumbnailView.Hit.SlideHit -> Log.d("Loki-UI", "clicked display slide ${hitObject.slide}")// open the slide preview
is AlbumThumbnailView.Hit.DownloadHit -> Log.d("Loki-UI", "clicked display download")
AlbumThumbnailView.Hit.ReadMoreHit -> Log.d("Loki-UI", "clicked the read more display")
else -> {
Log.d("Loki-UI", "DIDN'T click anything important")
}
}
}
} 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

@ -50,7 +50,7 @@ class VisibleMessageView : LinearLayout {
private var onDownTimestamp = 0L private var onDownTimestamp = 0L
var snIsSelected = false var snIsSelected = false
set(value) { field = value; handleIsSelectedChanged()} set(value) { field = value; handleIsSelectedChanged()}
var onPress: ((x: Int, y: Int) -> Unit)? = null var onPress: ((rawX: Int, rawY: Int) -> Unit)? = null
var onSwipeToReply: (() -> Unit)? = null var onSwipeToReply: (() -> Unit)? = null
var onLongPress: (() -> Unit)? = null var onLongPress: (() -> Unit)? = null
@ -272,7 +272,7 @@ class VisibleMessageView : LinearLayout {
onSwipeToReply?.invoke() onSwipeToReply?.invoke()
} else if ((Date().time - onDownTimestamp) < VisibleMessageView.longPressDurationThreshold) { } else if ((Date().time - onDownTimestamp) < VisibleMessageView.longPressDurationThreshold) {
longPressCallback?.let { gestureHandler.removeCallbacks(it) } longPressCallback?.let { gestureHandler.removeCallbacks(it) }
onPress?.invoke(event.x.toInt(), event.y.toInt()) onPress?.invoke(event.rawX.toInt(), event.rawY.toInt())
} }
resetPosition() resetPosition()
} }
@ -297,8 +297,8 @@ class VisibleMessageView : LinearLayout {
onLongPress?.invoke() onLongPress?.invoke()
} }
fun onContentClick(hitRect: Rect) { fun onContentClick(rawRect: Rect) {
messageContentView.onContentClick?.invoke(hitRect) messageContentView.onContentClick?.invoke(rawRect)
} }
// endregion // endregion
} }

View File

@ -1,6 +1,10 @@
package org.thoughtcrime.securesms.loki.utilities package org.thoughtcrime.securesms.loki.utilities
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle
import android.view.View import android.view.View
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
@ -53,3 +57,12 @@ fun AppCompatActivity.show(intent: Intent, isForResult: Boolean = false) {
} }
overridePendingTransition(R.anim.slide_from_bottom, R.anim.fade_scale_out) overridePendingTransition(R.anim.slide_from_bottom, R.anim.fade_scale_out)
} }
interface ActivityDispatcher {
companion object {
const val SERVICE = "ActivityDispatcher_SERVICE"
@SuppressLint("WrongConstant")
fun get(context: Context) = context.getSystemService(SERVICE) as? ActivityDispatcher
}
fun dispatchIntent(body: (Context)->Intent)
}