From 8b4b264992a096540c22c118c12b08df3e1b2ddd Mon Sep 17 00:00:00 2001 From: jubb Date: Tue, 29 Jun 2021 14:20:52 +1000 Subject: [PATCH 1/4] fix: 421 errors not being handled properly by sendOnionRequest and prevent retrying with stale swarm data, no longer crash with large NotifyPNServerJob.kt payload in Kryo deserialization --- .../libsession/messaging/jobs/NotifyPNServerJob.kt | 3 ++- .../java/org/session/libsession/snode/OnionRequestAPI.kt | 9 +++++---- .../main/java/org/session/libsession/snode/SnodeAPI.kt | 4 +--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libsession/src/main/java/org/session/libsession/messaging/jobs/NotifyPNServerJob.kt b/libsession/src/main/java/org/session/libsession/messaging/jobs/NotifyPNServerJob.kt index 5b3225b117..90262fc358 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/jobs/NotifyPNServerJob.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/jobs/NotifyPNServerJob.kt @@ -7,6 +7,7 @@ import nl.komponents.kovenant.functional.map import okhttp3.MediaType import okhttp3.Request import okhttp3.RequestBody +import org.session.libsession.messaging.jobs.Job.Companion.MAX_BUFFER_SIZE import org.session.libsession.messaging.sending_receiving.notifications.PushNotificationAPI import org.session.libsession.messaging.utilities.Data @@ -64,7 +65,7 @@ class NotifyPNServerJob(val message: SnodeMessage) : Job { val kryo = Kryo() kryo.isRegistrationRequired = false val serializedMessage = ByteArray(4096) - val output = Output(serializedMessage) + val output = Output(serializedMessage, MAX_BUFFER_SIZE) kryo.writeObject(output, message) output.close() return Data.Builder() diff --git a/libsession/src/main/java/org/session/libsession/snode/OnionRequestAPI.kt b/libsession/src/main/java/org/session/libsession/snode/OnionRequestAPI.kt index a188b4a5a8..775b4ff24c 100644 --- a/libsession/src/main/java/org/session/libsession/snode/OnionRequestAPI.kt +++ b/libsession/src/main/java/org/session/libsession/snode/OnionRequestAPI.kt @@ -433,11 +433,12 @@ object OnionRequestAPI { internal fun sendOnionRequest(method: Snode.Method, parameters: Map<*, *>, snode: Snode, publicKey: String? = null): Promise, Exception> { val payload = mapOf( "method" to method.rawValue, "params" to parameters ) return sendOnionRequest(Destination.Snode(snode), payload).recover { exception -> - val httpRequestFailedException = exception as? HTTP.HTTPRequestFailedException - if (httpRequestFailedException != null) { - val error = SnodeAPI.handleSnodeError(httpRequestFailedException.statusCode, httpRequestFailedException.json, snode, publicKey) - if (error != null) { throw error } + val error = when (exception) { + is HTTP.HTTPRequestFailedException -> SnodeAPI.handleSnodeError(exception.statusCode, exception.json, snode, publicKey) + is HTTPRequestFailedAtDestinationException -> SnodeAPI.handleSnodeError(exception.statusCode, exception.json, snode, publicKey) + else -> null } + if (error != null) { throw error } throw exception } } diff --git a/libsession/src/main/java/org/session/libsession/snode/SnodeAPI.kt b/libsession/src/main/java/org/session/libsession/snode/SnodeAPI.kt index 281bd906e7..bec77506eb 100644 --- a/libsession/src/main/java/org/session/libsession/snode/SnodeAPI.kt +++ b/libsession/src/main/java/org/session/libsession/snode/SnodeAPI.kt @@ -290,9 +290,7 @@ object SnodeAPI { getTargetSnodes(destination).map { swarm -> swarm.map { snode -> val parameters = message.toJSON() - retryIfNeeded(maxRetryCount) { - invoke(Snode.Method.SendMessage, snode, destination, parameters) - } + invoke(Snode.Method.SendMessage, snode, destination, parameters) }.toSet() } } From c5c8ebba041e1594da404a644f2cc1ac72cd511e Mon Sep 17 00:00:00 2001 From: jubb Date: Tue, 29 Jun 2021 16:05:40 +1000 Subject: [PATCH 2/4] fix: enable body texts to open modal URL dialog --- .../conversation/v2/ConversationActivityV2.kt | 3 ++ .../v2/messages/LinkPreviewView.kt | 21 +++++++---- .../v2/messages/VisibleMessageContentView.kt | 35 ++++++++++++++----- .../v2/utilities/KThumbnailView.kt | 1 + .../conversation/v2/utilities/ModalURLSpan.kt | 10 ++++++ app/src/main/res/layout/view_link_preview.xml | 3 +- 6 files changed, 56 insertions(+), 17 deletions(-) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ModalURLSpan.kt diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt index 8ba6e3b388..77153fc2ea 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt @@ -586,6 +586,9 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe // region Interaction override fun onOptionsItemSelected(item: MenuItem): Boolean { + if (item.itemId == android.R.id.home) { + return false + } return ConversationMenuHelper.onOptionItemSelected(this, item, thread) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/LinkPreviewView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/LinkPreviewView.kt index da9f1117ab..1f0e9860fd 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/LinkPreviewView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/LinkPreviewView.kt @@ -1,23 +1,20 @@ package org.thoughtcrime.securesms.conversation.v2.messages import android.content.Context -import android.content.Intent import android.graphics.Canvas -import android.graphics.drawable.Drawable -import android.net.Uri +import android.graphics.Rect +import android.text.method.LinkMovementMethod import android.util.AttributeSet import android.view.LayoutInflater -import android.view.ViewOutlineProvider import android.widget.LinearLayout -import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.core.content.res.ResourcesCompat +import androidx.core.view.isVisible import kotlinx.android.synthetic.main.view_link_preview.view.* import network.loki.messenger.R import org.thoughtcrime.securesms.components.CornerMask import org.thoughtcrime.securesms.conversation.v2.dialogs.OpenURLDialog import org.thoughtcrime.securesms.conversation.v2.utilities.MessageBubbleUtilities -import org.thoughtcrime.securesms.database.model.MessageRecord import org.thoughtcrime.securesms.database.model.MmsMessageRecord import org.thoughtcrime.securesms.loki.utilities.UiModeUtilities import org.thoughtcrime.securesms.mms.GlideRequests @@ -44,7 +41,8 @@ class LinkPreviewView : LinearLayout { // Thumbnail if (linkPreview.getThumbnail().isPresent) { // This internally fetches the thumbnail - thumbnailImageView.setImageResource(glide, ImageSlide(context, linkPreview.getThumbnail().get()), false, false) + thumbnailImageView.setImageResource(glide, ImageSlide(context, linkPreview.getThumbnail().get()), isPreview = false) + thumbnailImageView.loadIndicator.isVisible = false } // Title titleTextView.text = linkPreview.title @@ -56,6 +54,7 @@ class LinkPreviewView : LinearLayout { titleTextView.setTextColor(ResourcesCompat.getColor(resources, textColorID, context.theme)) // Body val bodyTextView = VisibleMessageContentView.getBodyTextView(context, message) + bodyTextView.movementMethod = LinkMovementMethod.getInstance() mainLinkPreviewContainer.addView(bodyTextView) // Corner radii val cornerRadii = MessageBubbleUtilities.calculateRadii(context, isStartOfMessageCluster, isEndOfMessageCluster, message.isOutgoing) @@ -72,6 +71,14 @@ class LinkPreviewView : LinearLayout { // endregion // region Interaction + fun calculateHit(hitRect: Rect) { + val previewRect = Rect() + mainLinkPreviewParent.getGlobalVisibleRect(previewRect) + if (previewRect.contains(hitRect)) { + openURL() + } + } + fun openURL() { val url = this.url ?: return val activity = context as AppCompatActivity diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageContentView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageContentView.kt index f609a51115..94e80fb32d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageContentView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageContentView.kt @@ -3,8 +3,11 @@ package org.thoughtcrime.securesms.conversation.v2.messages import android.content.Context import android.graphics.Rect import android.graphics.drawable.Drawable +import android.text.style.ReplacementSpan +import android.text.style.URLSpan 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 @@ -12,10 +15,13 @@ import android.widget.TextView import android.widget.Toast import androidx.annotation.ColorInt import androidx.annotation.DrawableRes +import androidx.appcompat.app.AppCompatActivity import androidx.core.content.res.ResourcesCompat import androidx.core.graphics.BlendModeColorFilterCompat import androidx.core.graphics.BlendModeCompat +import androidx.core.text.getSpans import androidx.core.text.toSpannable +import androidx.core.text.util.LinkifyCompat import kotlinx.android.synthetic.main.view_visible_message_content.view.* import network.loki.messenger.R import org.session.libsession.utilities.ThemeUtil @@ -23,6 +29,8 @@ import org.session.libsession.utilities.ViewUtil import org.session.libsession.utilities.recipients.Recipient import org.thoughtcrime.securesms.conversation.v2.components.AlbumThumbnailView import org.thoughtcrime.securesms.components.emoji.EmojiTextView +import org.thoughtcrime.securesms.conversation.v2.dialogs.OpenURLDialog +import org.thoughtcrime.securesms.conversation.v2.utilities.ModalURLSpan import org.thoughtcrime.securesms.database.model.MessageRecord import org.thoughtcrime.securesms.database.model.MmsMessageRecord import org.thoughtcrime.securesms.loki.utilities.* @@ -61,7 +69,9 @@ class VisibleMessageContentView : LinearLayout { val linkPreviewView = LinkPreviewView(context) linkPreviewView.bind(message, glide, isStartOfMessageCluster, isEndOfMessageCluster) mainContainer.addView(linkPreviewView) - onContentClick = { linkPreviewView.openURL() } + onContentClick = { rect -> + linkPreviewView.calculateHit(rect) + } // Body text view is inside the link preview for layout convenience } else if (message is MmsMessageRecord && message.quote != null) { val quote = message.quote!! @@ -106,9 +116,8 @@ class VisibleMessageContentView : LinearLayout { mainContainer.addView(openGroupInvitationView) onContentClick = { openGroupInvitationView.joinOpenGroup() } } else { - val bodyTextView = VisibleMessageContentView.getBodyTextView(context, message) + val bodyTextView = getBodyTextView(context, message) mainContainer.addView(bodyTextView) - onContentClick = { openURLIfNeeded(message) } } } @@ -132,12 +141,6 @@ class VisibleMessageContentView : LinearLayout { } // endregion - // region Interaction - private fun openURLIfNeeded(message: MessageRecord) { - Toast.makeText(context, "Not yet implemented", Toast.LENGTH_LONG).show() - } - // endregion - // region Convenience companion object { @@ -152,6 +155,20 @@ class VisibleMessageContentView : LinearLayout { result.setLinkTextColor(color) var body = message.body.toSpannable() Linkify.addLinks(body, Linkify.WEB_URLS) + + // replace URLSpans with ModalURLSpans + body.getSpans(0, body.length).toList().forEach { urlSpan -> + val replacementSpan = ModalURLSpan(urlSpan.url) { url -> + val activity = context as AppCompatActivity + OpenURLDialog(url).show(activity.supportFragmentManager, "Open URL Dialog") + } + val start = body.getSpanStart(urlSpan) + val end = body.getSpanEnd(urlSpan) + val flags = body.getSpanFlags(urlSpan) + body.removeSpan(urlSpan) + body.setSpan(replacementSpan, start, end, flags) + } + body = MentionUtilities.highlightMentions(body, message.isOutgoing, message.threadId, context); result.text = body return result diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/KThumbnailView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/KThumbnailView.kt index b070264944..01b768dc45 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/KThumbnailView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/KThumbnailView.kt @@ -23,6 +23,7 @@ import org.thoughtcrime.securesms.components.GlideBitmapListeningTarget import org.thoughtcrime.securesms.components.GlideDrawableListeningTarget import org.thoughtcrime.securesms.mms.* import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri +import org.thoughtcrime.securesms.util.MediaUtil open class KThumbnailView: FrameLayout { diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ModalURLSpan.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ModalURLSpan.kt new file mode 100644 index 0000000000..358dd56357 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ModalURLSpan.kt @@ -0,0 +1,10 @@ +package org.thoughtcrime.securesms.conversation.v2.utilities + +import android.text.style.URLSpan +import android.view.View + +class ModalURLSpan(url: String, private val openModalCallback: (String)->Unit): URLSpan(url) { + override fun onClick(widget: View) { + openModalCallback(url) + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/view_link_preview.xml b/app/src/main/res/layout/view_link_preview.xml index 41997eaf64..78262d817f 100644 --- a/app/src/main/res/layout/view_link_preview.xml +++ b/app/src/main/res/layout/view_link_preview.xml @@ -8,6 +8,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto"> - Date: Tue, 29 Jun 2021 16:06:22 +1000 Subject: [PATCH 3/4] refactor: remove captionIcon --- .../securesms/conversation/v2/utilities/KThumbnailView.kt | 2 -- app/src/main/res/layout/thumbnail_view.xml | 8 -------- 2 files changed, 10 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/KThumbnailView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/KThumbnailView.kt index 01b768dc45..89045be665 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/KThumbnailView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/KThumbnailView.kt @@ -39,7 +39,6 @@ open class KThumbnailView: FrameLayout { private val image by lazy { thumbnail_image } private val playOverlay by lazy { play_overlay } - private val captionIcon by lazy { thumbnail_caption_icon } val loadIndicator: View by lazy { thumbnail_load_indicator } private val dimensDelegate = ThumbnailDimensDelegate() @@ -111,7 +110,6 @@ open class KThumbnailView: FrameLayout { this.slide = slide - captionIcon.isVisible = slide.caption.isPresent loadIndicator.isVisible = slide.isInProgress dimensDelegate.setDimens(naturalWidth, naturalHeight) diff --git a/app/src/main/res/layout/thumbnail_view.xml b/app/src/main/res/layout/thumbnail_view.xml index b20b58356d..8922112823 100644 --- a/app/src/main/res/layout/thumbnail_view.xml +++ b/app/src/main/res/layout/thumbnail_view.xml @@ -14,14 +14,6 @@ android:scaleType="fitCenter" android:contentDescription="@string/conversation_item__mms_image_description" /> - - Date: Tue, 29 Jun 2021 16:09:01 +1000 Subject: [PATCH 4/4] fix: movement method for all body text moved into the helper function, removed caption from legacy ThumbnailView --- .../securesms/conversation/v2/messages/LinkPreviewView.kt | 1 - .../conversation/v2/messages/VisibleMessageContentView.kt | 2 ++ .../securesms/conversation/v2/utilities/ThumbnailView.java | 4 ---- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/LinkPreviewView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/LinkPreviewView.kt index 1f0e9860fd..f0193c6882 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/LinkPreviewView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/LinkPreviewView.kt @@ -54,7 +54,6 @@ class LinkPreviewView : LinearLayout { titleTextView.setTextColor(ResourcesCompat.getColor(resources, textColorID, context.theme)) // Body val bodyTextView = VisibleMessageContentView.getBodyTextView(context, message) - bodyTextView.movementMethod = LinkMovementMethod.getInstance() mainLinkPreviewContainer.addView(bodyTextView) // Corner radii val cornerRadii = MessageBubbleUtilities.calculateRadii(context, isStartOfMessageCluster, isEndOfMessageCluster, message.isOutgoing) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageContentView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageContentView.kt index 94e80fb32d..1fef31fa22 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageContentView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageContentView.kt @@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.conversation.v2.messages import android.content.Context import android.graphics.Rect import android.graphics.drawable.Drawable +import android.text.method.LinkMovementMethod import android.text.style.ReplacementSpan import android.text.style.URLSpan import android.text.util.Linkify @@ -171,6 +172,7 @@ class VisibleMessageContentView : LinearLayout { body = MentionUtilities.highlightMentions(body, message.isOutgoing, message.threadId, context); result.text = body + result.movementMethod = LinkMovementMethod.getInstance() return result } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ThumbnailView.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ThumbnailView.java index 79d0099998..f40a57924a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ThumbnailView.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ThumbnailView.java @@ -57,7 +57,6 @@ public class ThumbnailView extends FrameLayout { private ImageView image; private View playOverlay; - private View captionIcon; private View loadIndicator; private OnClickListener parentClickListener; @@ -87,7 +86,6 @@ public class ThumbnailView extends FrameLayout { this.image = findViewById(R.id.thumbnail_image); this.playOverlay = findViewById(R.id.play_overlay); - this.captionIcon = findViewById(R.id.thumbnail_caption_icon); this.loadIndicator = findViewById(R.id.thumbnail_load_indicator); super.setOnClickListener(new ThumbnailClickDispatcher()); @@ -278,8 +276,6 @@ public class ThumbnailView extends FrameLayout { this.slide = slide; - this.captionIcon.setVisibility(GONE); - dimens[WIDTH] = naturalWidth; dimens[HEIGHT] = naturalHeight; invalidate();