kopia lustrzana https://github.com/vitorpamplona/amethyst
Dropdown menu to copy information from the note.
rodzic
9d4f4c67f1
commit
962bd9eb2d
|
@ -3,6 +3,7 @@ package com.vitorpamplona.amethyst.model
|
||||||
import com.vitorpamplona.amethyst.ui.note.toDisplayHex
|
import com.vitorpamplona.amethyst.ui.note.toDisplayHex
|
||||||
import fr.acinq.secp256k1.Hex
|
import fr.acinq.secp256k1.Hex
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
|
import nostr.postr.Bech32
|
||||||
import nostr.postr.Persona
|
import nostr.postr.Persona
|
||||||
import nostr.postr.bechToBytes
|
import nostr.postr.bechToBytes
|
||||||
import nostr.postr.toHex
|
import nostr.postr.toHex
|
||||||
|
@ -10,6 +11,8 @@ import nostr.postr.toHex
|
||||||
/** Makes the distinction between String and Hex **/
|
/** Makes the distinction between String and Hex **/
|
||||||
typealias HexKey = String
|
typealias HexKey = String
|
||||||
|
|
||||||
|
fun ByteArray.toNote() = Bech32.encodeBytes(hrp = "note", this, Bech32.Encoding.Bech32)
|
||||||
|
|
||||||
fun ByteArray.toHexKey(): HexKey {
|
fun ByteArray.toHexKey(): HexKey {
|
||||||
return toHex()
|
return toHex()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
package com.vitorpamplona.amethyst.ui.note
|
package com.vitorpamplona.amethyst.ui.note
|
||||||
|
|
||||||
import android.text.format.DateUtils
|
|
||||||
import android.text.format.DateUtils.getRelativeTimeSpanString
|
import android.text.format.DateUtils.getRelativeTimeSpanString
|
||||||
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.combinedClickable
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
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.layout.width
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.material.Divider
|
import androidx.compose.material.Divider
|
||||||
|
import androidx.compose.material.DropdownMenu
|
||||||
|
import androidx.compose.material.DropdownMenuItem
|
||||||
import androidx.compose.material.MaterialTheme
|
import androidx.compose.material.MaterialTheme
|
||||||
import androidx.compose.material.Text
|
import androidx.compose.material.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.livedata.observeAsState
|
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.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
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.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.unit.DpOffset
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
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.ReactionEvent
|
||||||
import com.vitorpamplona.amethyst.service.model.RepostEvent
|
import com.vitorpamplona.amethyst.service.model.RepostEvent
|
||||||
import com.vitorpamplona.amethyst.ui.components.RichTextViewer
|
import com.vitorpamplona.amethyst.ui.components.RichTextViewer
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import nostr.postr.events.TextNoteEvent
|
import nostr.postr.events.TextNoteEvent
|
||||||
|
import nostr.postr.toNpub
|
||||||
|
|
||||||
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun NoteCompose(baseNote: Note, modifier: Modifier = Modifier, isInnerNote: Boolean = false, accountViewModel: AccountViewModel, navController: NavController) {
|
fun NoteCompose(baseNote: Note, modifier: Modifier = Modifier, isInnerNote: Boolean = false, accountViewModel: AccountViewModel, navController: NavController) {
|
||||||
val noteState by baseNote.live.observeAsState()
|
val noteState by baseNote.live.observeAsState()
|
||||||
val note = noteState?.note
|
val note = noteState?.note
|
||||||
|
|
||||||
|
var popupExpanded by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
if (note?.event == null) {
|
if (note?.event == null) {
|
||||||
BlankNote(modifier, isInnerNote)
|
BlankNote(modifier, isInnerNote)
|
||||||
} else {
|
} else {
|
||||||
val authorState by note.author!!.live.observeAsState()
|
val authorState by note.author!!.live.observeAsState()
|
||||||
val author = authorState?.user
|
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(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(
|
.padding(
|
||||||
|
@ -135,8 +154,34 @@ fun NoteCompose(baseNote: Note, modifier: Modifier = Modifier, isInnerNote: Bool
|
||||||
thickness = 0.25.dp
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -7,6 +7,7 @@ import com.vitorpamplona.amethyst.model.Account
|
||||||
import com.vitorpamplona.amethyst.model.AccountState
|
import com.vitorpamplona.amethyst.model.AccountState
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
import com.vitorpamplona.amethyst.model.UserState
|
import com.vitorpamplona.amethyst.model.UserState
|
||||||
|
import com.vitorpamplona.amethyst.service.relays.Client
|
||||||
|
|
||||||
class AccountViewModel(private val account: Account): ViewModel() {
|
class AccountViewModel(private val account: Account): ViewModel() {
|
||||||
val accountLiveData: LiveData<AccountState> = Transformations.map(account.live) { it }
|
val accountLiveData: LiveData<AccountState> = Transformations.map(account.live) { it }
|
||||||
|
@ -19,4 +20,10 @@ class AccountViewModel(private val account: Account): ViewModel() {
|
||||||
fun boost(note: Note) {
|
fun boost(note: Note) {
|
||||||
account.boost(note)
|
account.boost(note)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun broadcast(note: Note) {
|
||||||
|
note.event?.let {
|
||||||
|
Client.send(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
Ładowanie…
Reference in New Issue