From d171552efd31df439756f453bb96f31d74deb473 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Wed, 18 Jan 2023 09:18:26 -0500 Subject: [PATCH] Clickable Phone and Emails --- .../amethyst/ui/components/ClickableEmail.kt | 38 +++++++++++++++++++ .../amethyst/ui/components/ClickablePhone.kt | 33 ++++++++++++++++ .../amethyst/ui/components/RichTextViewer.kt | 4 ++ 3 files changed, 75 insertions(+) create mode 100644 app/src/main/java/com/vitorpamplona/amethyst/ui/components/ClickableEmail.kt create mode 100644 app/src/main/java/com/vitorpamplona/amethyst/ui/components/ClickablePhone.kt diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/ClickableEmail.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/ClickableEmail.kt new file mode 100644 index 000000000..caea0d0b4 --- /dev/null +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/ClickableEmail.kt @@ -0,0 +1,38 @@ +package com.vitorpamplona.amethyst.ui.components + +import android.content.ActivityNotFoundException +import android.content.Context +import android.content.Intent +import androidx.compose.foundation.text.ClickableText +import androidx.compose.material.LocalTextStyle +import androidx.compose.material.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalUriHandler +import androidx.compose.ui.text.AnnotatedString + +@Composable +fun ClickableEmail(email: String) { + val context = LocalContext.current + + ClickableText( + text = AnnotatedString("$email "), + onClick = { runCatching { context.sendMail(email) } }, + style = LocalTextStyle.current.copy(color = MaterialTheme.colors.primary), + ) +} + +fun Context.sendMail(to: String, subject: String? = null) { + try { + val intent = Intent(Intent.ACTION_SEND) + intent.type = "vnd.android.cursor.item/email" // or "message/rfc822" + intent.putExtra(Intent.EXTRA_EMAIL, arrayOf(to)) + if (subject != null) + intent.putExtra(Intent.EXTRA_SUBJECT, subject) + startActivity(intent) + } catch (e: ActivityNotFoundException) { + // TODO: Handle case where no email app is available + } catch (t: Throwable) { + // TODO: Handle potential other type of exceptions + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/ClickablePhone.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/ClickablePhone.kt new file mode 100644 index 000000000..f71fdd975 --- /dev/null +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/ClickablePhone.kt @@ -0,0 +1,33 @@ +package com.vitorpamplona.amethyst.ui.components + +import android.content.ActivityNotFoundException +import android.content.Context +import android.content.Intent +import android.net.Uri +import androidx.compose.foundation.text.ClickableText +import androidx.compose.material.LocalTextStyle +import androidx.compose.material.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalUriHandler +import androidx.compose.ui.text.AnnotatedString + +@Composable +fun ClickablePhone(phone: String) { + val context = LocalContext.current + + ClickableText( + text = AnnotatedString("$phone "), + onClick = { runCatching { context.dial(phone) } }, + style = LocalTextStyle.current.copy(color = MaterialTheme.colors.primary), + ) +} + +fun Context.dial(phone: String) { + try { + val intent = Intent(Intent.ACTION_DIAL, Uri.fromParts("tel", phone, null)) + startActivity(intent) + } catch (t: Throwable) { + // TODO: Handle potential exceptions + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/RichTextViewer.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/RichTextViewer.kt index d2be737cc..b7c013ecf 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/RichTextViewer.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/RichTextViewer.kt @@ -60,6 +60,10 @@ fun RichTextViewer(content: String, tags: List>?, note: Note, accou } else { UrlPreview(word, word) } + } else if (Patterns.EMAIL_ADDRESS.matcher(word).matches()) { + ClickableEmail(word) + } else if (Patterns.PHONE.matcher(word).matches()) { + ClickablePhone(word) } else if (noProtocolUrlValidator.matcher(word).matches()) { UrlPreview("https://$word", word) } else if (tagIndex.matcher(word).matches() && tags != null) {