mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-24 10:35:19 +00:00
Merge branch 'compose-open-url-dialog' into strings-squashed
This commit is contained in:
commit
2a8f010369
@ -4,25 +4,16 @@ import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Typeface
|
||||
import android.net.Uri
|
||||
import android.text.Spannable
|
||||
import android.text.SpannableString
|
||||
import android.text.style.StyleSpan
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
||||
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
import android.widget.Button
|
||||
import android.widget.ImageButton
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.LinearLayout.VERTICAL
|
||||
import android.widget.RelativeLayout
|
||||
import android.widget.ScrollView
|
||||
import android.widget.Space
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.AttrRes
|
||||
import androidx.annotation.LayoutRes
|
||||
import androidx.annotation.StringRes
|
||||
@ -31,9 +22,7 @@ import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.text.HtmlCompat
|
||||
import androidx.core.view.updateMargins
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.squareup.phrase.Phrase
|
||||
import network.loki.messenger.R
|
||||
import org.session.libsession.utilities.StringSubstitutionConstants.URL_KEY
|
||||
import org.thoughtcrime.securesms.util.toPx
|
||||
|
||||
@DslMarker
|
||||
@ -199,127 +188,6 @@ public fun Context.copyURLToClipboard(url: String) {
|
||||
clipboard.setPrimaryClip(clip)
|
||||
}
|
||||
|
||||
// Method to show a dialog used to open or copy a URL
|
||||
fun Context.showOpenUrlDialog(url: String, showCloseButton: Boolean = true): AlertDialog {
|
||||
|
||||
return SessionDialogBuilder(this).apply {
|
||||
// If we're not showing a close button we can just use a simple title..
|
||||
if (!showCloseButton) {
|
||||
title(R.string.urlOpen)
|
||||
} else {
|
||||
// ..otherwise we have to jump through some hoops to add a close button.
|
||||
|
||||
// Create a RelativeLayout as the container for the custom title
|
||||
val titleLayout = RelativeLayout(context).apply {
|
||||
layoutParams = RelativeLayout.LayoutParams(
|
||||
RelativeLayout.LayoutParams.MATCH_PARENT,
|
||||
RelativeLayout.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
}
|
||||
|
||||
// Create a TextView for the title
|
||||
val titleTextView = TextView(context).apply {
|
||||
// Set the text and display it in the correct 'title' style
|
||||
text = context.getString(R.string.urlOpen)
|
||||
setTextAppearance(R.style.TextAppearance_AppCompat_Title)
|
||||
|
||||
layoutParams = RelativeLayout.LayoutParams(
|
||||
RelativeLayout.LayoutParams.WRAP_CONTENT,
|
||||
RelativeLayout.LayoutParams.WRAP_CONTENT
|
||||
).apply {
|
||||
addRule(RelativeLayout.CENTER_HORIZONTAL)
|
||||
addRule(RelativeLayout.CENTER_VERTICAL)
|
||||
}
|
||||
}
|
||||
|
||||
// Create an ImageButton for the close button
|
||||
val closeButton = ImageButton(context).apply {
|
||||
setImageResource(android.R.drawable.ic_menu_close_clear_cancel) // Use a standard Android close icon
|
||||
background = null // Remove the background to make it look like an icon
|
||||
layoutParams = RelativeLayout.LayoutParams(
|
||||
RelativeLayout.LayoutParams.WRAP_CONTENT,
|
||||
RelativeLayout.LayoutParams.WRAP_CONTENT
|
||||
).apply {
|
||||
addRule(RelativeLayout.ALIGN_PARENT_END) // Place the close button on the "right" side
|
||||
addRule(RelativeLayout.CENTER_VERTICAL)
|
||||
}
|
||||
contentDescription = context.getString(R.string.close)
|
||||
}
|
||||
|
||||
// // Close the dialog when the button is clicked
|
||||
closeButton.setOnClickListener { dismiss() }
|
||||
|
||||
// Add the TextView and ImageButton to the RelativeLayout..
|
||||
titleLayout.addView(titleTextView)
|
||||
titleLayout.addView(closeButton)
|
||||
|
||||
// ..and then add that layout to the contentView.
|
||||
contentView.addView(titleLayout)
|
||||
}
|
||||
|
||||
// Create a TextView for the "Are you sure you want to open this URL?"
|
||||
val txtView = TextView(context).apply {
|
||||
layoutParams = LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT)
|
||||
.apply { updateMargins(dp40, 0, dp40, 0) }
|
||||
|
||||
// Substitute the URL into the string then make it bold
|
||||
val txt = Phrase.from(context, R.string.urlOpenDescription).put(URL_KEY, url).format().toString()
|
||||
val txtWithBoldedURL = SpannableString(txt)
|
||||
val urlStart = txt.indexOf(url)
|
||||
if (urlStart >= 0) {
|
||||
txtWithBoldedURL.setSpan(
|
||||
StyleSpan(Typeface.BOLD),
|
||||
urlStart,
|
||||
urlStart + url.length,
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||
)
|
||||
}
|
||||
text = txtWithBoldedURL
|
||||
|
||||
gravity = Gravity.CENTER // Center the text
|
||||
}
|
||||
|
||||
// Create a ScrollView and add the TextView to it
|
||||
val scrollView = ScrollView(context).apply {
|
||||
addView(txtView)
|
||||
|
||||
// Apply padding to the ScrollView so that the scroll bar isn't right up against the edge.
|
||||
// We'll apply the same padding to both sides to keep the text centered.
|
||||
setPadding(dp20, 0, dp20, 0)
|
||||
|
||||
// Place the scroll bar inside the container.
|
||||
// See the following for how different options look: https://stackoverflow.com/questions/3103132/android-listview-scrollbarstyle
|
||||
scrollBarStyle = ScrollView.SCROLLBARS_INSIDE_INSET
|
||||
}
|
||||
|
||||
// If the textView takes up 5 lines or more then show the scroll bar, force it to remain visible,
|
||||
// and set the ScrollView height accordingly.
|
||||
txtView.viewTreeObserver.addOnGlobalLayoutListener {
|
||||
// Only display the vertical scroll bar if the text takes up 5 lines or more
|
||||
val maxLines = 5
|
||||
if (txtView.lineCount >= maxLines) {
|
||||
scrollView.isVerticalScrollBarEnabled = true
|
||||
// Note: `scrollView.isScrollbarFadingEnabled = false` does NOT
|
||||
// work to prevent the scroll bar from fading away - so a hacky
|
||||
// way to fix this is to allow it to fade out... after an hour, lol.
|
||||
scrollView.scrollBarFadeDuration = 1000 * 60 * 60 // Value is in milliseconds
|
||||
scrollView.isVerticalFadingEdgeEnabled = false
|
||||
val lineHeight = txtView.lineHeight
|
||||
scrollView.layoutParams.height = lineHeight * maxLines
|
||||
}
|
||||
}
|
||||
|
||||
// Add the ScrollView to the contentView and then add the 'Open' and 'Copy URL' buttons.
|
||||
// Note: The text and contentDescription are set on the `copyUrlButton` by the function.
|
||||
contentView.addView(scrollView)
|
||||
dangerButton(R.string.open, R.string.AccessibilityId_urlOpenBrowser) { openUrl(url) }
|
||||
copyUrlButton {
|
||||
context.copyURLToClipboard(url)
|
||||
Toast.makeText(context, R.string.copied, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}.show()
|
||||
}
|
||||
|
||||
// Method to actually open a given URL via an Intent that will use the default browser
|
||||
fun Context.openUrl(url: String) = Intent(Intent.ACTION_VIEW, Uri.parse(url)).let(::startActivity)
|
||||
|
||||
|
@ -19,10 +19,7 @@ import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.provider.MediaStore
|
||||
import android.text.SpannableString
|
||||
import android.text.Spanned
|
||||
import android.text.TextUtils
|
||||
import android.text.style.StyleSpan
|
||||
import android.util.Pair
|
||||
import android.util.TypedValue
|
||||
import android.view.ActionMode
|
||||
@ -36,6 +33,10 @@ import android.widget.Toast
|
||||
import androidx.activity.result.ActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.activity.viewModels
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.platform.ViewCompositionStrategy
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.drawToBitmap
|
||||
import androidx.core.view.isGone
|
||||
@ -171,6 +172,8 @@ import org.thoughtcrime.securesms.permissions.Permissions
|
||||
import org.thoughtcrime.securesms.reactions.ReactionsDialogFragment
|
||||
import org.thoughtcrime.securesms.reactions.any.ReactWithAnyEmojiDialogFragment
|
||||
import org.thoughtcrime.securesms.showSessionDialog
|
||||
import org.thoughtcrime.securesms.ui.OpenURLAlertDialog
|
||||
import org.thoughtcrime.securesms.ui.theme.SessionMaterialTheme
|
||||
import org.thoughtcrime.securesms.util.ActivityDispatcher
|
||||
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
||||
import org.thoughtcrime.securesms.util.DateUtils
|
||||
@ -196,6 +199,7 @@ import kotlin.math.roundToInt
|
||||
import kotlin.math.sqrt
|
||||
import kotlin.time.Duration.Companion.minutes
|
||||
|
||||
|
||||
private const val TAG = "ConversationActivityV2"
|
||||
|
||||
// Some things that seemingly belong to the input bar (e.g. the voice message recording UI) are actually
|
||||
@ -238,6 +242,8 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
||||
.get(LinkPreviewViewModel::class.java)
|
||||
}
|
||||
|
||||
private var openLinkDialogUrl: String? by mutableStateOf(null)
|
||||
|
||||
private val threadId: Long by lazy {
|
||||
var threadId = intent.getLongExtra(THREAD_ID, -1L)
|
||||
if (threadId == -1L) {
|
||||
@ -401,12 +407,33 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
||||
}
|
||||
// endregion
|
||||
|
||||
fun showOpenUrlDialog(url: String){
|
||||
openLinkDialogUrl = url
|
||||
}
|
||||
|
||||
// region Lifecycle
|
||||
override fun onCreate(savedInstanceState: Bundle?, isReady: Boolean) {
|
||||
super.onCreate(savedInstanceState, isReady)
|
||||
binding = ActivityConversationV2Binding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
// set the compose dialog content
|
||||
binding.dialogOpenUrl.apply {
|
||||
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
|
||||
setContent {
|
||||
SessionMaterialTheme {
|
||||
if(!openLinkDialogUrl.isNullOrEmpty()){
|
||||
OpenURLAlertDialog(
|
||||
url = openLinkDialogUrl!!,
|
||||
onDismissRequest = {
|
||||
openLinkDialogUrl = null
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// messageIdToScroll
|
||||
messageToScrollTimestamp.set(intent.getLongExtra(SCROLL_MESSAGE_ID, -1))
|
||||
messageToScrollAuthor.set(intent.getParcelableExtra(SCROLL_MESSAGE_AUTHOR))
|
||||
|
@ -6,7 +6,6 @@ import android.graphics.Rect
|
||||
import android.util.AttributeSet
|
||||
import android.view.MotionEvent
|
||||
import android.widget.LinearLayout
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.isVisible
|
||||
import com.bumptech.glide.RequestManager
|
||||
import network.loki.messenger.R
|
||||
@ -14,10 +13,10 @@ import network.loki.messenger.databinding.ViewLinkPreviewBinding
|
||||
import org.session.libsession.utilities.getColorFromAttr
|
||||
import org.session.libsignal.utilities.Log
|
||||
import org.thoughtcrime.securesms.components.CornerMask
|
||||
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
|
||||
import org.thoughtcrime.securesms.conversation.v2.utilities.MessageBubbleUtilities
|
||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
||||
import org.thoughtcrime.securesms.mms.ImageSlide
|
||||
import org.thoughtcrime.securesms.showOpenUrlDialog
|
||||
|
||||
class LinkPreviewView : LinearLayout {
|
||||
private val binding: ViewLinkPreviewBinding by lazy { ViewLinkPreviewBinding.bind(this) }
|
||||
@ -88,8 +87,8 @@ class LinkPreviewView : LinearLayout {
|
||||
// Method to show the open or copy URL dialog
|
||||
private fun openURL() {
|
||||
val url = this.url ?: return Log.w("LinkPreviewView", "Cannot open a null URL")
|
||||
val activity = context as AppCompatActivity
|
||||
activity.showOpenUrlDialog(url)
|
||||
val activity = context as? ConversationActivityV2
|
||||
activity?.showOpenUrlDialog(url)
|
||||
}
|
||||
// endregion
|
||||
}
|
@ -12,35 +12,29 @@ import android.util.AttributeSet
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.core.text.getSpans
|
||||
import androidx.core.text.toSpannable
|
||||
import androidx.core.view.children
|
||||
import androidx.core.view.isVisible
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.RequestManager
|
||||
import network.loki.messenger.R
|
||||
import network.loki.messenger.databinding.ViewVisibleMessageContentBinding
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
|
||||
import org.session.libsession.utilities.ThemeUtil
|
||||
import org.session.libsession.utilities.getColorFromAttr
|
||||
import org.session.libsession.utilities.modifyLayoutParams
|
||||
import org.session.libsession.utilities.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
|
||||
import org.thoughtcrime.securesms.conversation.v2.ModalUrlBottomSheet
|
||||
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
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
||||
import org.thoughtcrime.securesms.database.model.SmsMessageRecord
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.RequestManager
|
||||
import org.thoughtcrime.securesms.showOpenUrlDialog
|
||||
import org.thoughtcrime.securesms.util.GlowViewUtilities
|
||||
import org.thoughtcrime.securesms.util.SearchUtil
|
||||
import org.thoughtcrime.securesms.util.getAccentColor
|
||||
@ -293,8 +287,8 @@ class VisibleMessageContentView : ConstraintLayout {
|
||||
body.getSpans<URLSpan>(0, body.length).toList().forEach { urlSpan ->
|
||||
val updatedUrl = urlSpan.url.let { it.toHttpUrlOrNull().toString() }
|
||||
val replacementSpan = ModalURLSpan(updatedUrl) { url ->
|
||||
val activity = context as AppCompatActivity
|
||||
activity.showOpenUrlDialog(url)
|
||||
val activity = context as? ConversationActivityV2
|
||||
activity?.showOpenUrlDialog(url)
|
||||
}
|
||||
val start = body.getSpanStart(urlSpan)
|
||||
val end = body.getSpanEnd(urlSpan)
|
||||
|
@ -1,5 +1,6 @@
|
||||
package org.thoughtcrime.securesms.ui
|
||||
|
||||
import android.widget.Toast
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.Box
|
||||
@ -12,7 +13,8 @@ import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.BasicAlertDialog
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
@ -26,13 +28,24 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.RectangleShape
|
||||
import androidx.compose.ui.graphics.takeOrElse
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.max
|
||||
import androidx.compose.ui.unit.times
|
||||
import com.squareup.phrase.Phrase
|
||||
import network.loki.messenger.R
|
||||
import org.session.libsession.utilities.StringSubstitutionConstants.URL_KEY
|
||||
import org.thoughtcrime.securesms.copyURLToClipboard
|
||||
import org.thoughtcrime.securesms.openUrl
|
||||
import org.thoughtcrime.securesms.ui.components.CircularProgressIndicator
|
||||
import org.thoughtcrime.securesms.ui.components.annotatedStringResource
|
||||
import org.thoughtcrime.securesms.ui.theme.LocalColors
|
||||
import org.thoughtcrime.securesms.ui.theme.LocalDimensions
|
||||
import org.thoughtcrime.securesms.ui.theme.LocalType
|
||||
@ -48,13 +61,37 @@ class DialogButtonModel(
|
||||
val onClick: () -> Unit = {},
|
||||
)
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun AlertDialog(
|
||||
onDismissRequest: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
title: String? = null,
|
||||
text: String? = null,
|
||||
maxLines: Int? = null,
|
||||
buttons: List<DialogButtonModel>? = null,
|
||||
showCloseButton: Boolean = false,
|
||||
content: @Composable () -> Unit = {}
|
||||
) {
|
||||
AlertDialog(
|
||||
onDismissRequest = onDismissRequest,
|
||||
modifier = modifier,
|
||||
title = if(title != null) AnnotatedString(title) else null,
|
||||
text = if(text != null) AnnotatedString(text) else null,
|
||||
maxLines = maxLines,
|
||||
buttons = buttons,
|
||||
showCloseButton = showCloseButton,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun AlertDialog(
|
||||
onDismissRequest: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
title: AnnotatedString? = null,
|
||||
text: AnnotatedString? = null,
|
||||
maxLines: Int? = null,
|
||||
buttons: List<DialogButtonModel>? = null,
|
||||
showCloseButton: Boolean = false,
|
||||
content: @Composable () -> Unit = {}
|
||||
@ -88,18 +125,32 @@ fun AlertDialog(
|
||||
) {
|
||||
title?.let {
|
||||
Text(
|
||||
it,
|
||||
text = it,
|
||||
textAlign = TextAlign.Center,
|
||||
style = LocalType.current.h7,
|
||||
modifier = Modifier.padding(bottom = LocalDimensions.current.xxsSpacing)
|
||||
)
|
||||
}
|
||||
text?.let {
|
||||
val textStyle = LocalType.current.large
|
||||
var textModifier = Modifier.padding(bottom = LocalDimensions.current.xxsSpacing)
|
||||
|
||||
// if we have a maxLines, make the text scrollable
|
||||
if(maxLines != null) {
|
||||
val textHeight = with(LocalDensity.current) {
|
||||
textStyle.lineHeight.toDp()
|
||||
} * maxLines
|
||||
|
||||
textModifier = textModifier
|
||||
.height(textHeight)
|
||||
.verticalScroll(rememberScrollState())
|
||||
}
|
||||
|
||||
Text(
|
||||
it,
|
||||
text = it,
|
||||
textAlign = TextAlign.Center,
|
||||
style = LocalType.current.large,
|
||||
modifier = Modifier.padding(bottom = LocalDimensions.current.xxsSpacing)
|
||||
style = textStyle,
|
||||
modifier = textModifier
|
||||
)
|
||||
}
|
||||
content()
|
||||
@ -127,6 +178,45 @@ fun AlertDialog(
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun OpenURLAlertDialog(
|
||||
onDismissRequest: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
url: String,
|
||||
content: @Composable () -> Unit = {}
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val unformattedText = Phrase.from(context.getText(R.string.urlOpenDescription))
|
||||
.put(URL_KEY, url).format()
|
||||
|
||||
|
||||
AlertDialog(
|
||||
modifier = modifier,
|
||||
title = AnnotatedString(stringResource(R.string.urlOpen)),
|
||||
text = annotatedStringResource(text = unformattedText),
|
||||
maxLines = 5,
|
||||
showCloseButton = true, // display the 'x' button
|
||||
buttons = listOf(
|
||||
DialogButtonModel(
|
||||
text = GetString(R.string.open),
|
||||
contentDescription = GetString(R.string.AccessibilityId_urlOpenBrowser),
|
||||
color = LocalColors.current.danger,
|
||||
onClick = { context.openUrl(url) }
|
||||
),
|
||||
DialogButtonModel(
|
||||
text = GetString(android.R.string.copyUrl),
|
||||
contentDescription = GetString(R.string.AccessibilityId_copy),
|
||||
onClick = {
|
||||
context.copyURLToClipboard(url)
|
||||
Toast.makeText(context, R.string.copied, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
)
|
||||
),
|
||||
onDismissRequest = onDismissRequest,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DialogButton(
|
||||
text: String,
|
||||
@ -217,12 +307,12 @@ fun PreviewSimpleDialog() {
|
||||
text = stringResource(R.string.onboardingBackAccountCreation),
|
||||
buttons = listOf(
|
||||
DialogButtonModel(
|
||||
GetString(stringResource(R.string.quit)),
|
||||
GetString(stringResource(R.string.cancel)),
|
||||
color = LocalColors.current.danger,
|
||||
onClick = { }
|
||||
),
|
||||
DialogButtonModel(
|
||||
GetString(stringResource(R.string.cancel))
|
||||
GetString(stringResource(R.string.ok))
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -254,6 +344,17 @@ fun PreviewXCloseDialog() {
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun PreviewOpenURLDialog() {
|
||||
PreviewTheme {
|
||||
OpenURLAlertDialog(
|
||||
url = "https://getsession.org/",
|
||||
onDismissRequest = {}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun PreviewLoadingDialog() {
|
||||
|
@ -14,6 +14,7 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
@ -26,6 +27,9 @@ import androidx.compose.ui.unit.Density
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.em
|
||||
import androidx.core.text.HtmlCompat
|
||||
import com.squareup.phrase.Phrase
|
||||
import network.loki.messenger.R
|
||||
import org.session.libsession.utilities.StringSubstitutionConstants.URL_KEY
|
||||
|
||||
// TODO Remove this file once we update to composeVersion=1.7.0-alpha06 fixes https://issuetracker.google.com/issues/139320238?pli=1
|
||||
// which allows Stylized string in string resources
|
||||
@ -71,6 +75,14 @@ fun annotatedStringResource(@StringRes id: Int): AnnotatedString {
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun annotatedStringResource(text: CharSequence): AnnotatedString {
|
||||
val density = LocalDensity.current
|
||||
return remember(text.hashCode()) {
|
||||
spannableStringToAnnotatedString(text, density)
|
||||
}
|
||||
}
|
||||
|
||||
private fun spannableStringToAnnotatedString(
|
||||
text: CharSequence,
|
||||
density: Density
|
||||
|
@ -346,4 +346,9 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.compose.ui.platform.ComposeView
|
||||
android:id="@+id/dialog_open_url"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
@ -792,7 +792,7 @@ NOTE: Strings with blank lines have manually been replaced with '\n\n' - this wi
|
||||
<string name="urlCopy">Copy URL</string>
|
||||
<string name="urlOpen">Open URL</string>
|
||||
<string name="urlOpenBrowser">This will open in your browser.</string>
|
||||
<string name="urlOpenDescription">Are you sure you want to open this URL in your browser?\n\n{url}</string>
|
||||
<string name="urlOpenDescription">Are you sure you want to open this URL in your browser?\n\n<b>{url}</b></string>
|
||||
<string name="useFastMode">Use Fast Mode</string>
|
||||
<string name="video">Video</string>
|
||||
<string name="videoErrorPlay">Unable to play video.</string>
|
||||
|
Loading…
Reference in New Issue
Block a user