WIP compose openURL dialog

This commit is contained in:
alansley 2024-08-28 08:27:03 +10:00
parent 5df981bc7a
commit 2aa58f4dd6
2 changed files with 126 additions and 12 deletions

View File

@ -11,8 +11,12 @@ 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
@ -40,7 +44,14 @@ 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.Glide
import com.bumptech.glide.RequestManager 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
@ -60,6 +71,7 @@ class VisibleMessageContentView : ConstraintLayout {
// endregion // endregion
// region Updating // region Updating
@Composable
fun bind( fun bind(
message: MessageRecord, message: MessageRecord,
isStartOfMessageCluster: Boolean = true, isStartOfMessageCluster: Boolean = true,
@ -273,6 +285,7 @@ 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()
@ -293,8 +306,14 @@ 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 AppCompatActivity
activity.showOpenUrlDialog(url) // @Thomas - PREVIOUS CODE WAS:
//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)
@ -305,6 +324,35 @@ 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

View File

@ -12,7 +12,6 @@ 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.layout.width
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
@ -29,6 +28,7 @@ import androidx.compose.ui.graphics.takeOrElse
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.style.TextAlign 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.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import network.loki.messenger.R import network.loki.messenger.R
@ -57,7 +57,8 @@ fun AlertDialog(
text: String? = null, text: String? = null,
buttons: List<DialogButtonModel>? = null, buttons: List<DialogButtonModel>? = null,
showCloseButton: Boolean = false, showCloseButton: Boolean = false,
content: @Composable () -> Unit = {} content: @Composable () -> Unit = {},
optionalURL: String = ""
) { ) {
BasicAlertDialog( BasicAlertDialog(
modifier = modifier, modifier = modifier,
@ -88,19 +89,32 @@ fun AlertDialog(
) { ) {
title?.let { title?.let {
Text( Text(
it, text = it,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
style = LocalType.current.h7, style = LocalType.current.h7,
modifier = Modifier.padding(bottom = LocalDimensions.current.xxsSpacing) modifier = Modifier.padding(bottom = LocalDimensions.current.xxsSpacing)
) )
} }
text?.let { text?.let {
Text( if (optionalURL.isNotEmpty()) {
it, // If this is an open URL dialog it should have a maximum height of 5 lines and truncate long URLs with an ellipsis
textAlign = TextAlign.Center, Text(
style = LocalType.current.large, text = it,
modifier = Modifier.padding(bottom = LocalDimensions.current.xxsSpacing) textAlign = TextAlign.Center,
) style = LocalType.current.large,
modifier = Modifier.padding(bottom = LocalDimensions.current.xxsSpacing),
maxLines = 5,
overflow = TextOverflow.Ellipsis
)
} else {
// Otherwise it should be a regular, non-open-URL dialog
Text(
text = it,
textAlign = TextAlign.Center,
style = LocalType.current.large,
modifier = Modifier.padding(bottom = LocalDimensions.current.xxsSpacing)
)
}
} }
content() content()
} }
@ -127,6 +141,30 @@ fun AlertDialog(
) )
} }
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun OpenURLAlertDialog(
onDismissRequest: () -> Unit,
modifier: Modifier = Modifier,
title: String? = null,
text: String? = null,
buttons: List<DialogButtonModel>? = null,
showCloseButton: Boolean = false,
content: @Composable () -> Unit = {},
url: String = ""
) {
AlertDialog(
onDismissRequest = onDismissRequest,
modifier = modifier,
title = title,
text = text,
buttons = buttons,
showCloseButton = showCloseButton,
content = content,
optionalURL = url
)
}
@Composable @Composable
fun DialogButton( fun DialogButton(
text: String, text: String,
@ -224,7 +262,8 @@ fun PreviewSimpleDialog() {
DialogButtonModel( DialogButtonModel(
GetString(stringResource(R.string.cancel)) GetString(stringResource(R.string.cancel))
) )
) ),
optionalURL = "https://slashdot.org"
) )
} }
} }
@ -254,6 +293,33 @@ fun PreviewXCloseDialog() {
} }
} }
@Preview
@Composable
fun PreviewOpenURLDialog() {
PreviewTheme {
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 = {}
),
DialogButtonModel(
text = GetString(android.R.string.copyUrl),
contentDescription = GetString(R.string.AccessibilityId_copy),
onClick = {}
)
),
url = "http://slashdot.org",
onDismissRequest = {}
)
}
}
@Preview @Preview
@Composable @Composable
fun PreviewLoadingDialog() { fun PreviewLoadingDialog() {