From 962bd9eb2dd386aef0a43932263903f3666f43fd Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Fri, 13 Jan 2023 10:20:54 -0500 Subject: [PATCH] Dropdown menu to copy information from the note. --- .../com/vitorpamplona/amethyst/model/Hex.kt | 3 ++ .../vitorpamplona/amethyst/ui/note/Note.kt | 49 ++++++++++++++++++- .../ui/screen/loggedIn/AccountViewModel.kt | 7 +++ 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/Hex.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/Hex.kt index 49eed2d80..846446875 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/Hex.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/Hex.kt @@ -3,6 +3,7 @@ package com.vitorpamplona.amethyst.model import com.vitorpamplona.amethyst.ui.note.toDisplayHex import fr.acinq.secp256k1.Hex import java.util.regex.Pattern +import nostr.postr.Bech32 import nostr.postr.Persona import nostr.postr.bechToBytes import nostr.postr.toHex @@ -10,6 +11,8 @@ import nostr.postr.toHex /** Makes the distinction between String and Hex **/ typealias HexKey = String +fun ByteArray.toNote() = Bech32.encodeBytes(hrp = "note", this, Bech32.Encoding.Bech32) + fun ByteArray.toHexKey(): HexKey { return toHex() } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/Note.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/Note.kt index 6c56d12f4..63cc90d9d 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/Note.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/Note.kt @@ -1,10 +1,11 @@ package com.vitorpamplona.amethyst.ui.note -import android.text.format.DateUtils import android.text.format.DateUtils.getRelativeTimeSpanString +import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.clickable +import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -12,38 +13,56 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.Divider +import androidx.compose.material.DropdownMenu +import androidx.compose.material.DropdownMenuItem import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.platform.LocalClipboardManager +import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.dp import androidx.navigation.NavController import androidx.navigation.compose.rememberNavController import coil.compose.AsyncImage import com.vitorpamplona.amethyst.model.Note +import com.vitorpamplona.amethyst.model.toNote import com.vitorpamplona.amethyst.service.model.ReactionEvent import com.vitorpamplona.amethyst.service.model.RepostEvent import com.vitorpamplona.amethyst.ui.components.RichTextViewer import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import nostr.postr.events.TextNoteEvent +import nostr.postr.toNpub +@OptIn(ExperimentalFoundationApi::class) @Composable fun NoteCompose(baseNote: Note, modifier: Modifier = Modifier, isInnerNote: Boolean = false, accountViewModel: AccountViewModel, navController: NavController) { val noteState by baseNote.live.observeAsState() val note = noteState?.note + var popupExpanded by remember { mutableStateOf(false) } + if (note?.event == null) { BlankNote(modifier, isInnerNote) } else { val authorState by note.author!!.live.observeAsState() val author = authorState?.user - Column(modifier = modifier.clickable ( onClick = { navController.navigate("Note/${note.idHex}") } )) { + Column(modifier = + modifier.combinedClickable( + onClick = { navController.navigate("Note/${note.idHex}") }, + onLongClick = { popupExpanded = true }, + ) + ) { Row( modifier = Modifier .padding( @@ -135,8 +154,34 @@ fun NoteCompose(baseNote: Note, modifier: Modifier = Modifier, isInnerNote: Bool thickness = 0.25.dp ) } + + NoteDropDownMenu(note, popupExpanded, { popupExpanded = false }, accountViewModel) } } } } +} + +@Composable +fun NoteDropDownMenu(note: Note, popupExpanded: Boolean, onDismiss: () -> Unit, accountViewModel: AccountViewModel) { + val clipboardManager = LocalClipboardManager.current + + DropdownMenu( + expanded = popupExpanded, + onDismissRequest = onDismiss + ) { + DropdownMenuItem(onClick = { clipboardManager.setText(AnnotatedString(note.event?.content ?: "")); onDismiss() }) { + Text("Copy Text") + } + DropdownMenuItem(onClick = { clipboardManager.setText(AnnotatedString(note.author?.pubkey?.toNpub() ?: "")); onDismiss() }) { + Text("Copy User ID") + } + DropdownMenuItem(onClick = { clipboardManager.setText(AnnotatedString(note.id.toNote())); onDismiss() }) { + Text("Copy Note ID") + } + Divider() + DropdownMenuItem(onClick = { accountViewModel.broadcast(note); onDismiss() }) { + Text("Broadcast") + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt index 7fa0aa1e9..9cac8e538 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt @@ -7,6 +7,7 @@ import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.model.AccountState import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.UserState +import com.vitorpamplona.amethyst.service.relays.Client class AccountViewModel(private val account: Account): ViewModel() { val accountLiveData: LiveData = Transformations.map(account.live) { it } @@ -19,4 +20,10 @@ class AccountViewModel(private val account: Account): ViewModel() { fun boost(note: Note) { account.boost(note) } + + fun broadcast(note: Note) { + note.event?.let { + Client.send(it) + } + } } \ No newline at end of file