Merge pull request #729 from hjubb/copy_url_link

Allow copying URL from conversation
This commit is contained in:
Harris
2021-09-21 00:13:59 +00:00
committed by GitHub
7 changed files with 147 additions and 52 deletions

View File

@@ -1338,12 +1338,21 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
override fun copyMessages(messages: Set<MessageRecord>) {
val sortedMessages = messages.sortedBy { it.dateSent }
val messageSize = sortedMessages.size
val builder = StringBuilder()
for (message in sortedMessages) {
val messageIterator = sortedMessages.iterator()
while (messageIterator.hasNext()) {
val message = messageIterator.next()
val body = MentionUtilities.highlightMentions(message.body, threadID, this)
if (TextUtils.isEmpty(body)) { continue }
val formattedTimestamp = DateUtils.getDisplayFormattedTimeSpanString(this, Locale.getDefault(), message.timestamp)
builder.append("$formattedTimestamp: $body").append('\n')
if (messageSize > 1) {
val formattedTimestamp = DateUtils.getDisplayFormattedTimeSpanString(this, Locale.getDefault(), message.timestamp)
builder.append("$formattedTimestamp: ")
}
builder.append(body)
if (messageIterator.hasNext()) {
builder.append('\n')
}
}
if (builder.isNotEmpty() && builder[builder.length - 1] == '\n') {
builder.deleteCharAt(builder.length - 1)

View File

@@ -0,0 +1,72 @@
package org.thoughtcrime.securesms.conversation.v2
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context.CLIPBOARD_SERVICE
import android.content.Intent
import android.graphics.Typeface
import android.net.Uri
import android.os.Bundle
import android.text.Spannable
import android.text.SpannableStringBuilder
import android.text.style.StyleSpan
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import kotlinx.android.synthetic.main.fragment_modal_url_bottom_sheet.*
import network.loki.messenger.R
import org.thoughtcrime.securesms.util.UiModeUtilities
class ModalUrlBottomSheet(private val url: String): BottomSheetDialogFragment(), View.OnClickListener {
override fun onCreateView(inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_modal_url_bottom_sheet, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val explanation = resources.getString(R.string.dialog_open_url_explanation, url)
val spannable = SpannableStringBuilder(explanation)
val startIndex = explanation.indexOf(url)
spannable.setSpan(StyleSpan(Typeface.BOLD), startIndex, startIndex + url.count(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
openURLExplanationTextView.text = spannable
cancelButton.setOnClickListener(this)
copyButton.setOnClickListener(this)
openURLButton.setOnClickListener(this)
}
private fun open() {
try {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
requireContext().startActivity(intent)
} catch (e: Exception) {
Toast.makeText(context, R.string.invalid_url, Toast.LENGTH_SHORT).show()
}
dismiss()
}
private fun copy() {
val clip = ClipData.newPlainText("URL", url)
val manager = requireContext().getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
manager.setPrimaryClip(clip)
Toast.makeText(requireContext(), R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show()
dismiss()
}
override fun onStart() {
super.onStart()
val window = dialog?.window ?: return
val isLightMode = UiModeUtilities.isDayUiMode(requireContext())
window.setDimAmount(if (isLightMode) 0.1f else 0.75f)
}
override fun onClick(v: View?) {
when (v) {
openURLButton -> open()
copyButton -> copy()
cancelButton -> dismiss()
}
}
}

View File

@@ -1,40 +0,0 @@
package org.thoughtcrime.securesms.conversation.v2.dialogs
import android.content.Intent
import android.graphics.Typeface
import android.net.Uri
import android.text.Spannable
import android.text.SpannableStringBuilder
import android.text.style.StyleSpan
import android.view.LayoutInflater
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import kotlinx.android.synthetic.main.dialog_open_url.view.*
import network.loki.messenger.R
import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog
/** Shown upon tapping a URL. */
class OpenURLDialog(private val url: String) : BaseDialog() {
override fun setContentView(builder: AlertDialog.Builder) {
val contentView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_open_url, null)
val explanation = resources.getString(R.string.dialog_open_url_explanation, url)
val spannable = SpannableStringBuilder(explanation)
val startIndex = explanation.indexOf(url)
spannable.setSpan(StyleSpan(Typeface.BOLD), startIndex, startIndex + url.count(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
contentView.openURLExplanationTextView.text = spannable
contentView.cancelButton.setOnClickListener { dismiss() }
contentView.openURLButton.setOnClickListener { open() }
builder.setView(contentView)
}
private fun open() {
try {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
requireContext().startActivity(intent)
} catch (e: Exception) {
Toast.makeText(context, R.string.invalid_url, Toast.LENGTH_SHORT).show()
}
dismiss()
}
}

View File

@@ -3,7 +3,6 @@ package org.thoughtcrime.securesms.conversation.v2.messages
import android.content.Context
import android.graphics.Canvas
import android.graphics.Rect
import android.text.method.LinkMovementMethod
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.MotionEvent
@@ -11,20 +10,17 @@ import android.widget.LinearLayout
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.res.ResourcesCompat
import androidx.core.text.getSpans
import androidx.core.text.toSpannable
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.ModalUrlBottomSheet
import org.thoughtcrime.securesms.conversation.v2.utilities.MessageBubbleUtilities
import org.thoughtcrime.securesms.conversation.v2.utilities.ModalURLSpan
import org.thoughtcrime.securesms.conversation.v2.utilities.TextUtilities.getIntersectedModalSpans
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
import org.thoughtcrime.securesms.util.UiModeUtilities
import org.thoughtcrime.securesms.mms.GlideRequests
import org.thoughtcrime.securesms.mms.ImageSlide
import org.thoughtcrime.securesms.util.UiModeUtilities
class LinkPreviewView : LinearLayout {
private val cornerMask by lazy { CornerMask(this) }
@@ -97,7 +93,7 @@ class LinkPreviewView : LinearLayout {
fun openURL() {
val url = this.url ?: return
val activity = context as AppCompatActivity
OpenURLDialog(url).show(activity.supportFragmentManager, "Open URL Dialog")
ModalUrlBottomSheet(url).show(activity.supportFragmentManager, "Open URL Dialog")
}
// endregion
}

View File

@@ -31,8 +31,8 @@ import org.session.libsession.utilities.ViewUtil
import org.session.libsession.utilities.recipients.Recipient
import org.thoughtcrime.securesms.components.emoji.EmojiTextView
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
import org.thoughtcrime.securesms.conversation.v2.ModalUrlBottomSheet
import org.thoughtcrime.securesms.conversation.v2.components.AlbumThumbnailView
import org.thoughtcrime.securesms.conversation.v2.dialogs.OpenURLDialog
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionUtilities
import org.thoughtcrime.securesms.conversation.v2.utilities.ModalURLSpan
import org.thoughtcrime.securesms.conversation.v2.utilities.TextUtilities.getIntersectedModalSpans
@@ -237,7 +237,7 @@ class VisibleMessageContentView : LinearLayout {
val updatedUrl = urlSpan.url.let { HttpUrl.parse(it).toString() }
val replacementSpan = ModalURLSpan(updatedUrl) { url ->
val activity = context as AppCompatActivity
OpenURLDialog(url).show(activity.supportFragmentManager, "Open URL Dialog")
ModalUrlBottomSheet(url).show(activity.supportFragmentManager, "Open URL Dialog")
}
val start = body.getSpanStart(urlSpan)
val end = body.getSpanEnd(urlSpan)