mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-21 15:05:19 +00:00
Proper set up for the Open URL dialog
This commit is contained in:
parent
2aa58f4dd6
commit
25132c6342
@ -19,10 +19,7 @@ import android.os.Bundle
|
|||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.provider.MediaStore
|
import android.provider.MediaStore
|
||||||
import android.text.SpannableString
|
|
||||||
import android.text.Spanned
|
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.text.style.StyleSpan
|
|
||||||
import android.util.Pair
|
import android.util.Pair
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.ActionMode
|
import android.view.ActionMode
|
||||||
@ -36,6 +33,10 @@ import android.widget.Toast
|
|||||||
import androidx.activity.result.ActivityResult
|
import androidx.activity.result.ActivityResult
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.activity.viewModels
|
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.content.ContextCompat
|
||||||
import androidx.core.view.drawToBitmap
|
import androidx.core.view.drawToBitmap
|
||||||
import androidx.core.view.isGone
|
import androidx.core.view.isGone
|
||||||
@ -170,6 +171,8 @@ import org.thoughtcrime.securesms.permissions.Permissions
|
|||||||
import org.thoughtcrime.securesms.reactions.ReactionsDialogFragment
|
import org.thoughtcrime.securesms.reactions.ReactionsDialogFragment
|
||||||
import org.thoughtcrime.securesms.reactions.any.ReactWithAnyEmojiDialogFragment
|
import org.thoughtcrime.securesms.reactions.any.ReactWithAnyEmojiDialogFragment
|
||||||
import org.thoughtcrime.securesms.showSessionDialog
|
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.ActivityDispatcher
|
||||||
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
||||||
import org.thoughtcrime.securesms.util.DateUtils
|
import org.thoughtcrime.securesms.util.DateUtils
|
||||||
@ -195,6 +198,7 @@ import kotlin.math.roundToInt
|
|||||||
import kotlin.math.sqrt
|
import kotlin.math.sqrt
|
||||||
import kotlin.time.Duration.Companion.minutes
|
import kotlin.time.Duration.Companion.minutes
|
||||||
|
|
||||||
|
|
||||||
private const val TAG = "ConversationActivityV2"
|
private const val TAG = "ConversationActivityV2"
|
||||||
|
|
||||||
// Some things that seemingly belong to the input bar (e.g. the voice message recording UI) are actually
|
// Some things that seemingly belong to the input bar (e.g. the voice message recording UI) are actually
|
||||||
@ -237,6 +241,8 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
.get(LinkPreviewViewModel::class.java)
|
.get(LinkPreviewViewModel::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var openLinkDialogUrl: String? by mutableStateOf(null)
|
||||||
|
|
||||||
private val threadId: Long by lazy {
|
private val threadId: Long by lazy {
|
||||||
var threadId = intent.getLongExtra(THREAD_ID, -1L)
|
var threadId = intent.getLongExtra(THREAD_ID, -1L)
|
||||||
if (threadId == -1L) {
|
if (threadId == -1L) {
|
||||||
@ -400,12 +406,33 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
}
|
}
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
|
fun showOpenUrlDialog(url: String){
|
||||||
|
openLinkDialogUrl = url
|
||||||
|
}
|
||||||
|
|
||||||
// region Lifecycle
|
// region Lifecycle
|
||||||
override fun onCreate(savedInstanceState: Bundle?, isReady: Boolean) {
|
override fun onCreate(savedInstanceState: Bundle?, isReady: Boolean) {
|
||||||
super.onCreate(savedInstanceState, isReady)
|
super.onCreate(savedInstanceState, isReady)
|
||||||
binding = ActivityConversationV2Binding.inflate(layoutInflater)
|
binding = ActivityConversationV2Binding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
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
|
// messageIdToScroll
|
||||||
messageToScrollTimestamp.set(intent.getLongExtra(SCROLL_MESSAGE_ID, -1))
|
messageToScrollTimestamp.set(intent.getLongExtra(SCROLL_MESSAGE_ID, -1))
|
||||||
messageToScrollAuthor.set(intent.getParcelableExtra(SCROLL_MESSAGE_AUTHOR))
|
messageToScrollAuthor.set(intent.getParcelableExtra(SCROLL_MESSAGE_AUTHOR))
|
||||||
|
@ -11,47 +11,32 @@ import android.text.util.Linkify
|
|||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.annotation.ColorInt
|
import androidx.annotation.ColorInt
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.res.stringResource
|
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
import androidx.core.graphics.ColorUtils
|
import androidx.core.graphics.ColorUtils
|
||||||
import androidx.core.text.getSpans
|
import androidx.core.text.getSpans
|
||||||
import androidx.core.text.toSpannable
|
import androidx.core.text.toSpannable
|
||||||
import androidx.core.view.children
|
import androidx.core.view.children
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.bumptech.glide.RequestManager
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import network.loki.messenger.databinding.ViewVisibleMessageContentBinding
|
import network.loki.messenger.databinding.ViewVisibleMessageContentBinding
|
||||||
import okhttp3.HttpUrl
|
|
||||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
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.messaging.sending_receiving.attachments.DatabaseAttachment
|
||||||
import org.session.libsession.utilities.ThemeUtil
|
import org.session.libsession.utilities.ThemeUtil
|
||||||
import org.session.libsession.utilities.getColorFromAttr
|
import org.session.libsession.utilities.getColorFromAttr
|
||||||
import org.session.libsession.utilities.modifyLayoutParams
|
import org.session.libsession.utilities.modifyLayoutParams
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
|
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.MentionUtilities
|
||||||
import org.thoughtcrime.securesms.conversation.v2.utilities.ModalURLSpan
|
import org.thoughtcrime.securesms.conversation.v2.utilities.ModalURLSpan
|
||||||
import org.thoughtcrime.securesms.conversation.v2.utilities.TextUtilities.getIntersectedModalSpans
|
import org.thoughtcrime.securesms.conversation.v2.utilities.TextUtilities.getIntersectedModalSpans
|
||||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
||||||
import org.thoughtcrime.securesms.database.model.SmsMessageRecord
|
import org.thoughtcrime.securesms.database.model.SmsMessageRecord
|
||||||
import com.bumptech.glide.Glide
|
|
||||||
import com.bumptech.glide.RequestManager
|
|
||||||
import org.thoughtcrime.securesms.copyURLToClipboard
|
|
||||||
import org.thoughtcrime.securesms.openUrl
|
|
||||||
import org.thoughtcrime.securesms.showOpenUrlDialog
|
import org.thoughtcrime.securesms.showOpenUrlDialog
|
||||||
import org.thoughtcrime.securesms.ui.AlertDialog
|
|
||||||
import org.thoughtcrime.securesms.ui.DialogButtonModel
|
|
||||||
import org.thoughtcrime.securesms.ui.GetString
|
|
||||||
import org.thoughtcrime.securesms.ui.OpenURLAlertDialog
|
|
||||||
import org.thoughtcrime.securesms.ui.theme.LocalColors
|
|
||||||
import org.thoughtcrime.securesms.util.GlowViewUtilities
|
import org.thoughtcrime.securesms.util.GlowViewUtilities
|
||||||
import org.thoughtcrime.securesms.util.SearchUtil
|
import org.thoughtcrime.securesms.util.SearchUtil
|
||||||
import org.thoughtcrime.securesms.util.getAccentColor
|
import org.thoughtcrime.securesms.util.getAccentColor
|
||||||
@ -71,7 +56,6 @@ class VisibleMessageContentView : ConstraintLayout {
|
|||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Updating
|
// region Updating
|
||||||
@Composable
|
|
||||||
fun bind(
|
fun bind(
|
||||||
message: MessageRecord,
|
message: MessageRecord,
|
||||||
isStartOfMessageCluster: Boolean = true,
|
isStartOfMessageCluster: Boolean = true,
|
||||||
@ -285,7 +269,6 @@ class VisibleMessageContentView : ConstraintLayout {
|
|||||||
// region Convenience
|
// region Convenience
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun getBodySpans(context: Context, message: MessageRecord, searchQuery: String?): Spannable {
|
fun getBodySpans(context: Context, message: MessageRecord, searchQuery: String?): Spannable {
|
||||||
var body = message.body.toSpannable()
|
var body = message.body.toSpannable()
|
||||||
|
|
||||||
@ -306,14 +289,8 @@ class VisibleMessageContentView : ConstraintLayout {
|
|||||||
body.getSpans<URLSpan>(0, body.length).toList().forEach { urlSpan ->
|
body.getSpans<URLSpan>(0, body.length).toList().forEach { urlSpan ->
|
||||||
val updatedUrl = urlSpan.url.let { it.toHttpUrlOrNull().toString() }
|
val updatedUrl = urlSpan.url.let { it.toHttpUrlOrNull().toString() }
|
||||||
val replacementSpan = ModalURLSpan(updatedUrl) { url ->
|
val replacementSpan = ModalURLSpan(updatedUrl) { url ->
|
||||||
|
val activity = context as ConversationActivityV2
|
||||||
// @Thomas - PREVIOUS CODE WAS:
|
activity.showOpenUrlDialog(url)
|
||||||
//val activity = context as AppCompatActivity
|
|
||||||
//activity.showOpenUrlDialog(url)
|
|
||||||
|
|
||||||
// Now attempting to use compose for the dialog - but it's not happy =/
|
|
||||||
OpenURLWarningDialog(url)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
val start = body.getSpanStart(urlSpan)
|
val start = body.getSpanStart(urlSpan)
|
||||||
val end = body.getSpanEnd(urlSpan)
|
val end = body.getSpanEnd(urlSpan)
|
||||||
@ -324,35 +301,6 @@ class VisibleMessageContentView : ConstraintLayout {
|
|||||||
return body
|
return body
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun OpenURLWarningDialog(url: String) {
|
|
||||||
val context = LocalContext.current
|
|
||||||
|
|
||||||
OpenURLAlertDialog(
|
|
||||||
title = stringResource(R.string.urlOpen),
|
|
||||||
text = stringResource(R.string.urlOpenDescription),
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
),
|
|
||||||
url = url,
|
|
||||||
onDismissRequest = {}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@ColorInt
|
@ColorInt
|
||||||
fun getTextColor(context: Context, message: MessageRecord): Int = context.getColorFromAttr(
|
fun getTextColor(context: Context, message: MessageRecord): Int = context.getColorFromAttr(
|
||||||
if (message.isOutgoing) R.attr.message_sent_text_color else R.attr.message_received_text_color
|
if (message.isOutgoing) R.attr.message_sent_text_color else R.attr.message_received_text_color
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package org.thoughtcrime.securesms.ui
|
package org.thoughtcrime.securesms.ui
|
||||||
|
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
@ -12,6 +13,8 @@ import androidx.compose.foundation.layout.fillMaxHeight
|
|||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material3.BasicAlertDialog
|
import androidx.compose.material3.BasicAlertDialog
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
@ -25,14 +28,24 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.RectangleShape
|
import androidx.compose.ui.graphics.RectangleShape
|
||||||
import androidx.compose.ui.graphics.takeOrElse
|
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.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
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.TextAlign
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
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 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.CircularProgressIndicator
|
||||||
|
import org.thoughtcrime.securesms.ui.components.annotatedStringResource
|
||||||
import org.thoughtcrime.securesms.ui.theme.LocalColors
|
import org.thoughtcrime.securesms.ui.theme.LocalColors
|
||||||
import org.thoughtcrime.securesms.ui.theme.LocalDimensions
|
import org.thoughtcrime.securesms.ui.theme.LocalDimensions
|
||||||
import org.thoughtcrime.securesms.ui.theme.LocalType
|
import org.thoughtcrime.securesms.ui.theme.LocalType
|
||||||
@ -48,17 +61,40 @@ class DialogButtonModel(
|
|||||||
val onClick: () -> Unit = {},
|
val onClick: () -> Unit = {},
|
||||||
)
|
)
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AlertDialog(
|
fun AlertDialog(
|
||||||
onDismissRequest: () -> Unit,
|
onDismissRequest: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
title: String? = null,
|
title: String? = null,
|
||||||
text: String? = null,
|
text: String? = null,
|
||||||
|
maxLines: Int? = null,
|
||||||
buttons: List<DialogButtonModel>? = null,
|
buttons: List<DialogButtonModel>? = null,
|
||||||
showCloseButton: Boolean = false,
|
showCloseButton: Boolean = false,
|
||||||
content: @Composable () -> Unit = {},
|
content: @Composable () -> Unit = {}
|
||||||
optionalURL: String = ""
|
) {
|
||||||
|
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 = {}
|
||||||
) {
|
) {
|
||||||
BasicAlertDialog(
|
BasicAlertDialog(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
@ -96,25 +132,26 @@ fun AlertDialog(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
text?.let {
|
text?.let {
|
||||||
if (optionalURL.isNotEmpty()) {
|
val textStyle = LocalType.current.large
|
||||||
// If this is an open URL dialog it should have a maximum height of 5 lines and truncate long URLs with an ellipsis
|
var textModifier = Modifier.padding(bottom = LocalDimensions.current.xxsSpacing)
|
||||||
Text(
|
|
||||||
text = it,
|
// if we have a maxLines, make the text scrollable
|
||||||
textAlign = TextAlign.Center,
|
if(maxLines != null) {
|
||||||
style = LocalType.current.large,
|
val textHeight = with(LocalDensity.current) {
|
||||||
modifier = Modifier.padding(bottom = LocalDimensions.current.xxsSpacing),
|
textStyle.lineHeight.toDp()
|
||||||
maxLines = 5,
|
} * maxLines
|
||||||
overflow = TextOverflow.Ellipsis
|
|
||||||
)
|
textModifier = textModifier
|
||||||
} else {
|
.height(textHeight)
|
||||||
// Otherwise it should be a regular, non-open-URL dialog
|
.verticalScroll(rememberScrollState())
|
||||||
Text(
|
|
||||||
text = it,
|
|
||||||
textAlign = TextAlign.Center,
|
|
||||||
style = LocalType.current.large,
|
|
||||||
modifier = Modifier.padding(bottom = LocalDimensions.current.xxsSpacing)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = it,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
style = textStyle,
|
||||||
|
modifier = textModifier
|
||||||
|
)
|
||||||
}
|
}
|
||||||
content()
|
content()
|
||||||
}
|
}
|
||||||
@ -141,27 +178,42 @@ fun AlertDialog(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
fun OpenURLAlertDialog(
|
fun OpenURLAlertDialog(
|
||||||
onDismissRequest: () -> Unit,
|
onDismissRequest: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
title: String? = null,
|
url: String,
|
||||||
text: String? = null,
|
content: @Composable () -> Unit = {}
|
||||||
buttons: List<DialogButtonModel>? = null,
|
|
||||||
showCloseButton: Boolean = false,
|
|
||||||
content: @Composable () -> Unit = {},
|
|
||||||
url: String = ""
|
|
||||||
) {
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val unformattedText = Phrase.from(context.getText(R.string.urlOpenDescription))
|
||||||
|
.put(URL_KEY, url).format()
|
||||||
|
|
||||||
|
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = onDismissRequest,
|
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
title = title,
|
title = AnnotatedString(stringResource(R.string.urlOpen)),
|
||||||
text = text,
|
text = annotatedStringResource(text = unformattedText),
|
||||||
buttons = buttons,
|
maxLines = 5,
|
||||||
showCloseButton = showCloseButton,
|
showCloseButton = true, // display the 'x' button
|
||||||
content = content,
|
buttons = listOf(
|
||||||
optionalURL = url
|
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
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,15 +307,14 @@ fun PreviewSimpleDialog() {
|
|||||||
text = stringResource(R.string.onboardingBackAccountCreation),
|
text = stringResource(R.string.onboardingBackAccountCreation),
|
||||||
buttons = listOf(
|
buttons = listOf(
|
||||||
DialogButtonModel(
|
DialogButtonModel(
|
||||||
GetString(stringResource(R.string.quit)),
|
GetString(stringResource(R.string.cancel)),
|
||||||
color = LocalColors.current.danger,
|
color = LocalColors.current.danger,
|
||||||
onClick = { }
|
onClick = { }
|
||||||
),
|
),
|
||||||
DialogButtonModel(
|
DialogButtonModel(
|
||||||
GetString(stringResource(R.string.cancel))
|
GetString(stringResource(R.string.ok))
|
||||||
)
|
)
|
||||||
),
|
)
|
||||||
optionalURL = "https://slashdot.org"
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -298,23 +349,7 @@ fun PreviewXCloseDialog() {
|
|||||||
fun PreviewOpenURLDialog() {
|
fun PreviewOpenURLDialog() {
|
||||||
PreviewTheme {
|
PreviewTheme {
|
||||||
OpenURLAlertDialog(
|
OpenURLAlertDialog(
|
||||||
title = stringResource(R.string.urlOpen),
|
url = "https://getsession.org/",
|
||||||
text = stringResource(R.string.urlOpenDescription),
|
|
||||||
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 = {}
|
|
||||||
),
|
|
||||||
DialogButtonModel(
|
|
||||||
text = GetString(android.R.string.copyUrl),
|
|
||||||
contentDescription = GetString(R.string.AccessibilityId_copy),
|
|
||||||
onClick = {}
|
|
||||||
)
|
|
||||||
),
|
|
||||||
url = "http://slashdot.org",
|
|
||||||
onDismissRequest = {}
|
onDismissRequest = {}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ import androidx.compose.ui.graphics.Color
|
|||||||
import androidx.compose.ui.platform.LocalConfiguration
|
import androidx.compose.ui.platform.LocalConfiguration
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.AnnotatedString
|
import androidx.compose.ui.text.AnnotatedString
|
||||||
import androidx.compose.ui.text.SpanStyle
|
import androidx.compose.ui.text.SpanStyle
|
||||||
import androidx.compose.ui.text.buildAnnotatedString
|
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.dp
|
||||||
import androidx.compose.ui.unit.em
|
import androidx.compose.ui.unit.em
|
||||||
import androidx.core.text.HtmlCompat
|
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
|
// 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
|
// 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(
|
private fun spannableStringToAnnotatedString(
|
||||||
text: CharSequence,
|
text: CharSequence,
|
||||||
density: Density
|
density: Density
|
||||||
|
@ -346,4 +346,9 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</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>
|
</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="urlCopy">Copy URL</string>
|
||||||
<string name="urlOpen">Open URL</string>
|
<string name="urlOpen">Open URL</string>
|
||||||
<string name="urlOpenBrowser">This will open in your browser.</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="useFastMode">Use Fast Mode</string>
|
||||||
<string name="video">Video</string>
|
<string name="video">Video</string>
|
||||||
<string name="videoErrorPlay">Unable to play video.</string>
|
<string name="videoErrorPlay">Unable to play video.</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user