diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/SelectTextDialog.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/SelectTextDialog.kt
new file mode 100644
index 000000000..69bc90918
--- /dev/null
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/SelectTextDialog.kt
@@ -0,0 +1,57 @@
+package com.vitorpamplona.amethyst.ui.components
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.text.selection.SelectionContainer
+import androidx.compose.material.Card
+import androidx.compose.material.Divider
+import androidx.compose.material.Icon
+import androidx.compose.material.IconButton
+import androidx.compose.material.MaterialTheme
+import androidx.compose.material.Text
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.ArrowBack
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.window.Dialog
+import com.vitorpamplona.amethyst.R
+
+@Composable
+fun SelectTextDialog(text: String, onDismiss: () -> Unit) {
+ Dialog(
+ onDismissRequest = onDismiss,
+ ) {
+ Card {
+ Column {
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ horizontalArrangement = Arrangement.End
+ ) {
+ IconButton(
+ onClick = onDismiss,
+ modifier = Modifier.background(MaterialTheme.colors.background)
+ ) {
+ Icon(
+ imageVector = Icons.Default.ArrowBack,
+ contentDescription = null,
+ tint = MaterialTheme.colors.primary
+ )
+ }
+ Text(text = stringResource(R.string.select_text))
+ }
+ Divider()
+ Row(modifier = Modifier.padding(16.dp)) {
+ SelectionContainer {
+ Text(text)
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteQuickActionMenu.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteQuickActionMenu.kt
new file mode 100644
index 000000000..2973c45e8
--- /dev/null
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteQuickActionMenu.kt
@@ -0,0 +1,171 @@
+package com.vitorpamplona.amethyst.ui.note
+
+import android.content.Intent
+import android.widget.Toast
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.IntrinsicSize
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxHeight
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.Card
+import androidx.compose.material.Divider
+import androidx.compose.material.Icon
+import androidx.compose.material.MaterialTheme
+import androidx.compose.material.Text
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.AlternateEmail
+import androidx.compose.material.icons.filled.ContentCopy
+import androidx.compose.material.icons.filled.Share
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.shadow
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.toArgb
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.platform.LocalClipboardManager
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.res.vectorResource
+import androidx.compose.ui.text.AnnotatedString
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import androidx.compose.ui.window.Popup
+import androidx.core.content.ContextCompat
+import androidx.core.graphics.ColorUtils
+import com.vitorpamplona.amethyst.R
+import com.vitorpamplona.amethyst.model.Note
+import com.vitorpamplona.amethyst.ui.components.SelectTextDialog
+import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
+import kotlinx.coroutines.launch
+
+fun lightenColor(color: Color, amount: Float): Color {
+ var argb = color.toArgb()
+ val hslOut = floatArrayOf(0f, 0f, 0f)
+ ColorUtils.colorToHSL(argb, hslOut)
+ hslOut[2] += amount
+ argb = ColorUtils.HSLToColor(hslOut)
+ return Color(argb)
+}
+
+val externalLinkForNote = { note: Note -> "https://snort.social/e/${note.idNote()}" }
+
+@Composable
+fun VerticalDivider(color: Color) =
+ Divider(
+ color = color, modifier = Modifier
+ .fillMaxHeight()
+ .width(1.dp)
+ )
+
+@Composable
+fun NoteQuickActionMenu(note: Note, popupExpanded: Boolean, onDismiss: () -> Unit, accountViewModel: AccountViewModel) {
+ val context = LocalContext.current
+ val primaryLight = lightenColor(MaterialTheme.colors.primary, 0.2f)
+ val cardShape = RoundedCornerShape(5.dp)
+ val clipboardManager = LocalClipboardManager.current
+ val scope = rememberCoroutineScope()
+ var showSelectTextDialog by remember { mutableStateOf(false) }
+
+ val showToast = { stringResource: Int ->
+ scope.launch {
+ Toast.makeText(
+ context,
+ context.getString(stringResource),
+ Toast.LENGTH_SHORT
+ ).show()
+ }
+ }
+
+ if (popupExpanded) {
+ Popup(onDismissRequest = onDismiss) {
+ Card(
+ modifier = Modifier.shadow(elevation = 6.dp, shape = cardShape),
+ shape = cardShape,
+ backgroundColor = MaterialTheme.colors.primary,
+ ) {
+ Column(modifier = Modifier.width(IntrinsicSize.Min)) {
+ Row(modifier = Modifier.height(IntrinsicSize.Min)) {
+ NoteQuickActionItem(
+ icon = Icons.Default.ContentCopy,
+ label = stringResource(R.string.quick_action_copy_text)
+ ) {
+ clipboardManager.setText(
+ AnnotatedString(
+ accountViewModel.decrypt(note) ?: ""
+ )
+ )
+ showToast(R.string.copied_note_text_to_clipboard)
+ onDismiss()
+ }
+ VerticalDivider(primaryLight)
+ NoteQuickActionItem(Icons.Default.AlternateEmail, stringResource(R.string.quick_action_copy_note_id)) {
+ clipboardManager.setText(AnnotatedString("@${note.idNote()}"))
+ showToast(R.string.copied_note_id_to_clipboard)
+ onDismiss()
+ }
+ VerticalDivider(primaryLight)
+ NoteQuickActionItem(
+ icon = ImageVector.vectorResource(id = R.drawable.text_select_move_forward_character),
+ label = stringResource(R.string.quick_action_select)
+ ) {
+ showSelectTextDialog = true
+ onDismiss()
+ }
+ VerticalDivider(primaryLight)
+ NoteQuickActionItem(icon = Icons.Default.Share, label = stringResource(R.string.quick_action_share)) {
+ val sendIntent = Intent().apply {
+ action = Intent.ACTION_SEND
+ type = "text/plain"
+ putExtra(
+ Intent.EXTRA_TEXT,
+ externalLinkForNote(note)
+ )
+ putExtra(Intent.EXTRA_TITLE, context.getString(R.string.quick_action_share_browser_link))
+ }
+
+ val shareIntent = Intent.createChooser(sendIntent, context.getString(R.string.quick_action_share))
+ ContextCompat.startActivity(context, shareIntent, null)
+ onDismiss()
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (showSelectTextDialog) {
+ accountViewModel.decrypt(note)?.let {
+ SelectTextDialog(it) { showSelectTextDialog = false }
+ }
+ }
+}
+
+@Composable
+fun NoteQuickActionItem(icon: ImageVector, label: String, onClick: () -> Unit) {
+ Column(
+ modifier = Modifier
+ .size(64.dp)
+ .clickable { onClick() },
+ verticalArrangement = Arrangement.Center,
+ horizontalAlignment = Alignment.CenterHorizontally,
+ ) {
+ Icon(
+ imageVector = icon,
+ contentDescription = null,
+ modifier = Modifier.size(20.dp),
+ tint = MaterialTheme.colors.onPrimary,
+ )
+ Text(text = label, fontSize = 12.sp)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/text_select_move_forward_character.xml b/app/src/main/res/drawable/text_select_move_forward_character.xml
new file mode 100644
index 000000000..312d40dbc
--- /dev/null
+++ b/app/src/main/res/drawable/text_select_move_forward_character.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index eb90867a7..aa56b00a7 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,4 +1,4 @@
-
+
Amethyst
Amethyst Debug
Point to the QR Code
@@ -20,7 +20,7 @@
Relay Icon
Unknown Author
Copy Text
- Copy User PubKey
+ Copy Author @npub
Copy Note ID
Broadcast
@@ -177,7 +177,7 @@
Mark all Known as read
Mark all New as read
Mark all as read
-
+
## Key Backup and Safety Tips
\n\nYour account is secured by a secret key. The key is long random string starting with **nsec1**. Anyone who has access to your secret key can publish content using your identity.
\n\n- Do **not** put your secret key in any website or software you do not trust.
@@ -192,4 +192,12 @@
"Badge award image for %1$s"
You Received a new Badge Award
Badge award granted to
-
\ No newline at end of file
+ Copied note text to clipboard
+ Copied note ID (@note1) to clipboard
+ Select Text
+ Select
+ Share Browser Link
+ Share
+ Copy ID
+ Copy Text
+