Delete Relay Selection dialog from all new post screens.
This commit is contained in:
@@ -92,6 +92,7 @@ import com.vitorpamplona.quartz.experimental.profileGallery.dimension
|
|||||||
import com.vitorpamplona.quartz.experimental.profileGallery.fromEvent
|
import com.vitorpamplona.quartz.experimental.profileGallery.fromEvent
|
||||||
import com.vitorpamplona.quartz.experimental.profileGallery.hash
|
import com.vitorpamplona.quartz.experimental.profileGallery.hash
|
||||||
import com.vitorpamplona.quartz.experimental.profileGallery.mimeType
|
import com.vitorpamplona.quartz.experimental.profileGallery.mimeType
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
|
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
|
||||||
@@ -1085,14 +1086,15 @@ class Account(
|
|||||||
fun consumeAndSendNip95(
|
fun consumeAndSendNip95(
|
||||||
data: FileStorageEvent,
|
data: FileStorageEvent,
|
||||||
signedEvent: FileStorageHeaderEvent,
|
signedEvent: FileStorageHeaderEvent,
|
||||||
relayList: List<NormalizedRelayUrl>,
|
|
||||||
): Note? {
|
): Note? {
|
||||||
if (!isWriteable()) return null
|
if (!isWriteable()) return null
|
||||||
|
|
||||||
client.send(data, relayList = relayList.toSet())
|
val relayList = computeRelayListToBroadcast(signedEvent)
|
||||||
|
|
||||||
|
client.send(data, relayList = relayList)
|
||||||
cache.justConsumeMyOwnEvent(data)
|
cache.justConsumeMyOwnEvent(data)
|
||||||
|
|
||||||
client.send(signedEvent, relayList = relayList.toSet())
|
client.send(signedEvent, relayList = relayList)
|
||||||
cache.justConsumeMyOwnEvent(signedEvent)
|
cache.justConsumeMyOwnEvent(signedEvent)
|
||||||
|
|
||||||
return cache.getNoteIfExists(signedEvent.id)
|
return cache.getNoteIfExists(signedEvent.id)
|
||||||
@@ -1161,7 +1163,6 @@ class Account(
|
|||||||
urlHeaderInfo: Map<String, FileHeader>,
|
urlHeaderInfo: Map<String, FileHeader>,
|
||||||
caption: String?,
|
caption: String?,
|
||||||
contentWarningReason: String?,
|
contentWarningReason: String?,
|
||||||
relayList: Set<NormalizedRelayUrl>,
|
|
||||||
onReady: (Note) -> Unit,
|
onReady: (Note) -> Unit,
|
||||||
) {
|
) {
|
||||||
val iMetas =
|
val iMetas =
|
||||||
@@ -1180,7 +1181,7 @@ class Account(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
signer.sign(
|
val template =
|
||||||
PictureEvent.build(iMetas, caption ?: "") {
|
PictureEvent.build(iMetas, caption ?: "") {
|
||||||
caption?.let {
|
caption?.let {
|
||||||
hashtags(findHashtags(it))
|
hashtags(findHashtags(it))
|
||||||
@@ -1192,9 +1193,10 @@ class Account(
|
|||||||
// add geohashes
|
// add geohashes
|
||||||
// add title
|
// add title
|
||||||
contentWarningReason?.let { contentWarning(contentWarningReason) }
|
contentWarningReason?.let { contentWarning(contentWarningReason) }
|
||||||
},
|
}
|
||||||
) {
|
|
||||||
sendHeader(it, relayList = relayList, onReady)
|
signAndComputeBroadcast(template) { event ->
|
||||||
|
cache.getNoteIfExists(event.id)?.let { onReady(it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1205,7 +1207,6 @@ class Account(
|
|||||||
alt: String?,
|
alt: String?,
|
||||||
contentWarningReason: String?,
|
contentWarningReason: String?,
|
||||||
originalHash: String? = null,
|
originalHash: String? = null,
|
||||||
relayList: Set<NormalizedRelayUrl>,
|
|
||||||
onReady: (Note) -> Unit,
|
onReady: (Note) -> Unit,
|
||||||
) {
|
) {
|
||||||
if (!isWriteable()) return
|
if (!isWriteable()) return
|
||||||
@@ -1273,8 +1274,8 @@ class Account(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
signer.sign(template) {
|
signAndComputeBroadcast(template) { event ->
|
||||||
sendHeader(it, relayList = relayList, onReady)
|
cache.getNoteIfExists(event.id)?.let { onReady(it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1305,6 +1306,30 @@ class Account(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <T : Event> signAndComputeBroadcast(
|
||||||
|
template: EventTemplate<T>,
|
||||||
|
broadcast: List<Event> = emptyList(),
|
||||||
|
onDone: (T) -> Unit = {},
|
||||||
|
) {
|
||||||
|
signer.sign(template) { event ->
|
||||||
|
cache.justConsumeMyOwnEvent(event)
|
||||||
|
val note =
|
||||||
|
if (event is AddressableEvent) {
|
||||||
|
cache.getOrCreateAddressableNote(event.address())
|
||||||
|
} else {
|
||||||
|
cache.getOrCreateNote(event.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
val relayList = computeRelayListToBroadcast(note)
|
||||||
|
|
||||||
|
client.send(event, relayList)
|
||||||
|
|
||||||
|
broadcast.forEach { client.send(it, relayList) }
|
||||||
|
|
||||||
|
onDone(event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun <T : Event> signAndSend(
|
fun <T : Event> signAndSend(
|
||||||
template: EventTemplate<T>,
|
template: EventTemplate<T>,
|
||||||
relayList: Set<NormalizedRelayUrl>,
|
relayList: Set<NormalizedRelayUrl>,
|
||||||
@@ -1581,7 +1606,7 @@ class Account(
|
|||||||
originalNote: Note,
|
originalNote: Note,
|
||||||
notify: HexKey?,
|
notify: HexKey?,
|
||||||
summary: String? = null,
|
summary: String? = null,
|
||||||
relayList: List<NormalizedRelayUrl>,
|
broadcast: List<Event>,
|
||||||
) {
|
) {
|
||||||
if (!isWriteable()) return
|
if (!isWriteable()) return
|
||||||
|
|
||||||
@@ -1593,9 +1618,14 @@ class Account(
|
|||||||
notify = notify,
|
notify = notify,
|
||||||
summary = summary,
|
summary = summary,
|
||||||
signer = signer,
|
signer = signer,
|
||||||
) {
|
) { event ->
|
||||||
cache.justConsumeMyOwnEvent(it)
|
cache.justConsumeMyOwnEvent(event)
|
||||||
client.send(it, relayList = relayList.toSet())
|
val note = cache.getOrCreateNote(event.id)
|
||||||
|
val relayList = computeRelayListToBroadcast(note)
|
||||||
|
|
||||||
|
client.send(event, relayList = relayList)
|
||||||
|
|
||||||
|
broadcast.forEach { client.send(it, relayList) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1715,7 +1745,7 @@ class Account(
|
|||||||
)?.relays()?.ifEmpty { null }?.toSet()
|
)?.relays()?.ifEmpty { null }?.toSet()
|
||||||
|
|
||||||
if (relayList != null) {
|
if (relayList != null) {
|
||||||
client.send(signedEvent = wrap, relayList = relayList)
|
client.send(event = wrap, relayList = relayList)
|
||||||
} else {
|
} else {
|
||||||
val taggedUserInboxRelays =
|
val taggedUserInboxRelays =
|
||||||
wrap.taggedUserIds().flatMapTo(mutableSetOf()) { pubkey ->
|
wrap.taggedUserIds().flatMapTo(mutableSetOf()) { pubkey ->
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ package com.vitorpamplona.amethyst.ui.actions
|
|||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
import androidx.compose.foundation.horizontalScroll
|
import androidx.compose.foundation.horizontalScroll
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
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
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
@@ -96,7 +95,6 @@ import com.vitorpamplona.amethyst.ui.note.creators.invoice.InvoiceRequest
|
|||||||
import com.vitorpamplona.amethyst.ui.note.creators.messagefield.MessageField
|
import com.vitorpamplona.amethyst.ui.note.creators.messagefield.MessageField
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.uploads.ImageVideoDescription
|
import com.vitorpamplona.amethyst.ui.note.creators.uploads.ImageVideoDescription
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.userSuggestions.ShowUserSuggestionList
|
import com.vitorpamplona.amethyst.ui.note.creators.userSuggestions.ShowUserSuggestionList
|
||||||
import com.vitorpamplona.amethyst.ui.painterRes
|
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
|
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
|
||||||
@@ -108,7 +106,6 @@ import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
|
|||||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||||
import com.vitorpamplona.amethyst.ui.theme.replyModifier
|
import com.vitorpamplona.amethyst.ui.theme.replyModifier
|
||||||
import com.vitorpamplona.amethyst.ui.theme.subtleBorder
|
import com.vitorpamplona.amethyst.ui.theme.subtleBorder
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@@ -128,12 +125,6 @@ fun EditPostView(
|
|||||||
|
|
||||||
val scrollState = rememberScrollState()
|
val scrollState = rememberScrollState()
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
var showRelaysDialog by remember { mutableStateOf(false) }
|
|
||||||
var relayList =
|
|
||||||
remember {
|
|
||||||
accountViewModel.account.outboxRelays.flow.value
|
|
||||||
.toImmutableList()
|
|
||||||
}
|
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
postViewModel.load(edit, versionLookingAt, accountViewModel)
|
postViewModel.load(edit, versionLookingAt, accountViewModel)
|
||||||
@@ -148,16 +139,6 @@ fun EditPostView(
|
|||||||
decorFitsSystemWindows = false,
|
decorFitsSystemWindows = false,
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
if (showRelaysDialog) {
|
|
||||||
RelaySelectionDialog(
|
|
||||||
preSelectedList = relayList,
|
|
||||||
onClose = { showRelaysDialog = false },
|
|
||||||
onPost = { relayList = it },
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
nav = nav,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
@@ -169,22 +150,9 @@ fun EditPostView(
|
|||||||
) {
|
) {
|
||||||
Spacer(modifier = StdHorzSpacer)
|
Spacer(modifier = StdHorzSpacer)
|
||||||
|
|
||||||
Box {
|
|
||||||
IconButton(
|
|
||||||
modifier = Modifier.align(Alignment.Center),
|
|
||||||
onClick = { showRelaysDialog = true },
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
painter = painterRes(R.drawable.relays, 2),
|
|
||||||
contentDescription = stringRes(id = R.string.relay_list_selector),
|
|
||||||
modifier = Modifier.height(25.dp),
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PostButton(
|
PostButton(
|
||||||
onPost = {
|
onPost = {
|
||||||
postViewModel.sendPost(relayList = relayList)
|
postViewModel.sendPost()
|
||||||
scope.launch {
|
scope.launch {
|
||||||
delay(100)
|
delay(100)
|
||||||
onClose()
|
onClose()
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.UserSuggestionAnchor
|
|||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
import com.vitorpamplona.quartz.experimental.nip95.data.FileStorageEvent
|
import com.vitorpamplona.quartz.experimental.nip95.data.FileStorageEvent
|
||||||
import com.vitorpamplona.quartz.experimental.nip95.header.FileStorageHeaderEvent
|
import com.vitorpamplona.quartz.experimental.nip95.header.FileStorageHeaderEvent
|
||||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||||
import com.vitorpamplona.quartz.nip92IMeta.IMetaTag
|
import com.vitorpamplona.quartz.nip92IMeta.IMetaTag
|
||||||
import com.vitorpamplona.quartz.nip92IMeta.IMetaTagBuilder
|
import com.vitorpamplona.quartz.nip92IMeta.IMetaTagBuilder
|
||||||
import com.vitorpamplona.quartz.nip94FileMetadata.alt
|
import com.vitorpamplona.quartz.nip94FileMetadata.alt
|
||||||
@@ -120,18 +120,21 @@ open class EditPostViewModel : ViewModel() {
|
|||||||
editedFromNote = edit
|
editedFromNote = edit
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendPost(relayList: List<NormalizedRelayUrl>) {
|
fun sendPost() {
|
||||||
viewModelScope.launch(Dispatchers.IO) { innerSendPost(relayList) }
|
viewModelScope.launch(Dispatchers.IO) { innerSendPost() }
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun innerSendPost(relayList: List<NormalizedRelayUrl>) {
|
suspend fun innerSendPost() {
|
||||||
if (accountViewModel == null) {
|
if (accountViewModel == null) {
|
||||||
cancel()
|
cancel()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val extraNotesToBroadcast = mutableListOf<Event>()
|
||||||
|
|
||||||
nip95attachments.forEach {
|
nip95attachments.forEach {
|
||||||
account?.sendNip95(it.first, it.second, relayList.toSet())
|
extraNotesToBroadcast.add(it.first)
|
||||||
|
extraNotesToBroadcast.add(it.second)
|
||||||
}
|
}
|
||||||
|
|
||||||
val notify =
|
val notify =
|
||||||
@@ -147,7 +150,7 @@ open class EditPostViewModel : ViewModel() {
|
|||||||
originalNote = editedFromNote!!,
|
originalNote = editedFromNote!!,
|
||||||
notify = notify,
|
notify = notify,
|
||||||
summary = subject.text.ifBlank { null },
|
summary = subject.text.ifBlank { null },
|
||||||
relayList = relayList,
|
extraNotesToBroadcast,
|
||||||
)
|
)
|
||||||
|
|
||||||
cancel()
|
cancel()
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerName
|
|||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMediaProcessing
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMediaProcessing
|
||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.joinAll
|
import kotlinx.coroutines.joinAll
|
||||||
@@ -82,13 +81,11 @@ open class NewMediaModel : ViewModel() {
|
|||||||
|
|
||||||
fun upload(
|
fun upload(
|
||||||
context: Context,
|
context: Context,
|
||||||
relayList: List<NormalizedRelayUrl>,
|
|
||||||
onSucess: () -> Unit,
|
onSucess: () -> Unit,
|
||||||
onError: (String, String) -> Unit,
|
onError: (String, String) -> Unit,
|
||||||
) {
|
) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
val myAccount = account ?: return@launch
|
val myAccount = account ?: return@launch
|
||||||
if (relayList.isEmpty()) return@launch
|
|
||||||
val serverToUse = selectedServer ?: return@launch
|
val serverToUse = selectedServer ?: return@launch
|
||||||
|
|
||||||
val myMultiOrchestrator = multiOrchestrator ?: return@launch
|
val myMultiOrchestrator = multiOrchestrator ?: return@launch
|
||||||
@@ -141,7 +138,7 @@ open class NewMediaModel : ViewModel() {
|
|||||||
withTimeoutOrNull(30000) {
|
withTimeoutOrNull(30000) {
|
||||||
suspendCancellableCoroutine { continuation ->
|
suspendCancellableCoroutine { continuation ->
|
||||||
account?.createNip95(it.bytes, headerInfo = it.fileHeader, caption, if (sensitiveContent) "" else null) { nip95 ->
|
account?.createNip95(it.bytes, headerInfo = it.fileHeader, caption, if (sensitiveContent) "" else null) { nip95 ->
|
||||||
account?.consumeAndSendNip95(nip95.first, nip95.second, relayList)
|
account?.consumeAndSendNip95(nip95.first, nip95.second)
|
||||||
continuation.resume(true)
|
continuation.resume(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,13 +153,12 @@ open class NewMediaModel : ViewModel() {
|
|||||||
withTimeoutOrNull(30000) {
|
withTimeoutOrNull(30000) {
|
||||||
suspendCancellableCoroutine { continuation ->
|
suspendCancellableCoroutine { continuation ->
|
||||||
account?.sendHeader(
|
account?.sendHeader(
|
||||||
it.url,
|
url = it.url,
|
||||||
it.magnet,
|
magnetUri = it.magnet,
|
||||||
it.fileHeader,
|
headerInfo = it.fileHeader,
|
||||||
caption,
|
alt = caption,
|
||||||
if (sensitiveContent) "" else null,
|
contentWarningReason = if (sensitiveContent) "" else null,
|
||||||
it.uploadedHash,
|
originalHash = it.uploadedHash,
|
||||||
relayList.toSet(),
|
|
||||||
) {
|
) {
|
||||||
continuation.resume(true)
|
continuation.resume(true)
|
||||||
}
|
}
|
||||||
@@ -178,10 +174,9 @@ open class NewMediaModel : ViewModel() {
|
|||||||
withTimeoutOrNull(30000) {
|
withTimeoutOrNull(30000) {
|
||||||
suspendCancellableCoroutine { continuation ->
|
suspendCancellableCoroutine { continuation ->
|
||||||
account?.sendAllAsOnePictureEvent(
|
account?.sendAllAsOnePictureEvent(
|
||||||
imageUrls,
|
urlHeaderInfo = imageUrls,
|
||||||
caption,
|
caption = caption,
|
||||||
if (sensitiveContent) "" else null,
|
contentWarningReason = if (sensitiveContent) "" else null,
|
||||||
relayList.toSet(),
|
|
||||||
) {
|
) {
|
||||||
continuation.resume(true)
|
continuation.resume(true)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,8 +35,6 @@ import androidx.compose.foundation.rememberScrollState
|
|||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
@@ -49,7 +47,6 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
@@ -70,7 +67,6 @@ import com.vitorpamplona.amethyst.ui.navigation.INav
|
|||||||
import com.vitorpamplona.amethyst.ui.note.buttons.CloseButton
|
import com.vitorpamplona.amethyst.ui.note.buttons.CloseButton
|
||||||
import com.vitorpamplona.amethyst.ui.note.buttons.PostButton
|
import com.vitorpamplona.amethyst.ui.note.buttons.PostButton
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.contentWarning.SettingSwitchItem
|
import com.vitorpamplona.amethyst.ui.note.creators.contentWarning.SettingSwitchItem
|
||||||
import com.vitorpamplona.amethyst.ui.painterRes
|
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.TextSpinner
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.TextSpinner
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.TitleExplainer
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.TitleExplainer
|
||||||
@@ -100,13 +96,6 @@ fun NewMediaView(
|
|||||||
postViewModel.load(account, uris)
|
postViewModel.load(account, uris)
|
||||||
}
|
}
|
||||||
|
|
||||||
var showRelaysDialog by remember { mutableStateOf(false) }
|
|
||||||
var relayList =
|
|
||||||
remember {
|
|
||||||
accountViewModel.account.outboxRelays.flow.value
|
|
||||||
.toImmutableList()
|
|
||||||
}
|
|
||||||
|
|
||||||
Dialog(
|
Dialog(
|
||||||
onDismissRequest = { onClose() },
|
onDismissRequest = { onClose() },
|
||||||
properties =
|
properties =
|
||||||
@@ -128,23 +117,9 @@ fun NewMediaView(
|
|||||||
) {
|
) {
|
||||||
Spacer(modifier = StdHorzSpacer)
|
Spacer(modifier = StdHorzSpacer)
|
||||||
|
|
||||||
Box {
|
|
||||||
IconButton(
|
|
||||||
modifier = Modifier.align(Alignment.Center),
|
|
||||||
onClick = { showRelaysDialog = true },
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
painter = painterRes(R.drawable.relays, 3),
|
|
||||||
contentDescription = stringRes(id = R.string.relay_list_selector),
|
|
||||||
modifier = Modifier.height(25.dp),
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PostButton(
|
PostButton(
|
||||||
onPost = {
|
onPost = {
|
||||||
postViewModel.upload(context, relayList, onClose, accountViewModel.toastManager::toast)
|
postViewModel.upload(context, onClose, accountViewModel.toastManager::toast)
|
||||||
postViewModel.selectedServer?.let {
|
postViewModel.selectedServer?.let {
|
||||||
if (it.type != ServerType.NIP95) {
|
if (it.type != ServerType.NIP95) {
|
||||||
account.settings.changeDefaultFileServer(it)
|
account.settings.changeDefaultFileServer(it)
|
||||||
@@ -173,16 +148,6 @@ fun NewMediaView(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
) { pad ->
|
) { pad ->
|
||||||
if (showRelaysDialog) {
|
|
||||||
RelaySelectionDialog(
|
|
||||||
preSelectedList = relayList,
|
|
||||||
onClose = { showRelaysDialog = false },
|
|
||||||
onPost = { relayList = it },
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
nav = nav,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
Surface(
|
Surface(
|
||||||
modifier =
|
modifier =
|
||||||
Modifier
|
Modifier
|
||||||
|
|||||||
+2
-2
@@ -66,7 +66,7 @@ fun NewPollVoteValueRange(pollViewModel: ShortNotePostViewModel) {
|
|||||||
onValueChange = { pollViewModel.updateMinZapAmountForPoll(it) },
|
onValueChange = { pollViewModel.updateMinZapAmountForPoll(it) },
|
||||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
colors = if (pollViewModel.isValidvalueMinimum.value) colorValid else colorInValid,
|
colors = if (pollViewModel.isValidValueMinimum.value) colorValid else colorInValid,
|
||||||
label = {
|
label = {
|
||||||
Text(
|
Text(
|
||||||
text = stringRes(R.string.poll_zap_value_min),
|
text = stringRes(R.string.poll_zap_value_min),
|
||||||
@@ -88,7 +88,7 @@ fun NewPollVoteValueRange(pollViewModel: ShortNotePostViewModel) {
|
|||||||
onValueChange = { pollViewModel.updateMaxZapAmountForPoll(it) },
|
onValueChange = { pollViewModel.updateMaxZapAmountForPoll(it) },
|
||||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
colors = if (pollViewModel.isValidvalueMaximum.value) colorValid else colorInValid,
|
colors = if (pollViewModel.isValidValueMaximum.value) colorValid else colorInValid,
|
||||||
label = {
|
label = {
|
||||||
Text(
|
Text(
|
||||||
text = stringRes(R.string.poll_zap_value_max),
|
text = stringRes(R.string.poll_zap_value_max),
|
||||||
|
|||||||
@@ -1,278 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Vitor Pamplona
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
||||||
* this software and associated documentation files (the "Software"), to deal in
|
|
||||||
* the Software without restriction, including without limitation the rights to use,
|
|
||||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
|
||||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
|
||||||
* subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
||||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
|
||||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
package com.vitorpamplona.amethyst.ui.actions
|
|
||||||
|
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
|
||||||
import androidx.compose.foundation.combinedClickable
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.Spacer
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
|
||||||
import androidx.compose.foundation.lazy.itemsIndexed
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
||||||
import androidx.compose.material3.Scaffold
|
|
||||||
import androidx.compose.material3.Switch
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TopAppBar
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.derivedStateOf
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
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.platform.LocalContext
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.compose.ui.window.Dialog
|
|
||||||
import androidx.compose.ui.window.DialogProperties
|
|
||||||
import com.vitorpamplona.amethyst.R
|
|
||||||
import com.vitorpamplona.amethyst.service.Nip11Retriever
|
|
||||||
import com.vitorpamplona.amethyst.ui.components.SetDialogToEdgeToEdge
|
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.INav
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.buttons.CloseButton
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.buttons.SaveButton
|
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.publicChannels.ephemChat.header.loadRelayInfo
|
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.relays.RelayInformationDialog
|
|
||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
|
||||||
import com.vitorpamplona.amethyst.ui.theme.FeedPadding
|
|
||||||
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
|
|
||||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
|
||||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.displayUrl
|
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
|
||||||
import kotlin.collections.map
|
|
||||||
|
|
||||||
data class RelayList(
|
|
||||||
val relay: NormalizedRelayUrl,
|
|
||||||
val isSelected: Boolean,
|
|
||||||
)
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
|
||||||
fun RelaySelectionDialog(
|
|
||||||
preSelectedList: ImmutableList<NormalizedRelayUrl>,
|
|
||||||
onClose: () -> Unit,
|
|
||||||
onPost: (list: ImmutableList<NormalizedRelayUrl>) -> Unit,
|
|
||||||
accountViewModel: AccountViewModel,
|
|
||||||
nav: INav,
|
|
||||||
) {
|
|
||||||
var relays by remember {
|
|
||||||
mutableStateOf(
|
|
||||||
accountViewModel.account.client.allAvailableRelays().map {
|
|
||||||
RelayList(
|
|
||||||
relay = it,
|
|
||||||
isSelected = preSelectedList.any { relayUrl -> it == relayUrl },
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val hasSelectedRelay by remember { derivedStateOf { relays.any { it.isSelected } } }
|
|
||||||
|
|
||||||
var selected by remember { mutableStateOf(true) }
|
|
||||||
|
|
||||||
Dialog(
|
|
||||||
onDismissRequest = { onClose() },
|
|
||||||
properties =
|
|
||||||
DialogProperties(
|
|
||||||
usePlatformDefaultWidth = false,
|
|
||||||
dismissOnClickOutside = false,
|
|
||||||
decorFitsSystemWindows = false,
|
|
||||||
),
|
|
||||||
) {
|
|
||||||
SetDialogToEdgeToEdge()
|
|
||||||
|
|
||||||
Scaffold(
|
|
||||||
modifier = Modifier.fillMaxSize(),
|
|
||||||
topBar = {
|
|
||||||
TopAppBar(
|
|
||||||
actions = {
|
|
||||||
SaveButton(
|
|
||||||
onPost = {
|
|
||||||
val selectedRelays = relays.filter { it.isSelected }.map { it.relay }.toImmutableList()
|
|
||||||
onPost(selectedRelays)
|
|
||||||
onClose()
|
|
||||||
},
|
|
||||||
isActive = hasSelectedRelay,
|
|
||||||
)
|
|
||||||
Spacer(modifier = StdHorzSpacer)
|
|
||||||
},
|
|
||||||
title = {},
|
|
||||||
navigationIcon = {
|
|
||||||
Row {
|
|
||||||
Spacer(modifier = StdHorzSpacer)
|
|
||||||
CloseButton(
|
|
||||||
onPress = { onClose() },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
},
|
|
||||||
) { pad ->
|
|
||||||
Column(
|
|
||||||
modifier =
|
|
||||||
Modifier.padding(pad).padding(start = 10.dp, end = 10.dp, top = 10.dp),
|
|
||||||
) {
|
|
||||||
RelaySwitch(
|
|
||||||
text = stringRes(R.string.select_deselect_all),
|
|
||||||
checked = selected,
|
|
||||||
onClick = {
|
|
||||||
selected = !selected
|
|
||||||
relays = relays.mapIndexed { _, item -> item.copy(isSelected = selected) }
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
LazyColumn(
|
|
||||||
contentPadding = FeedPadding,
|
|
||||||
) {
|
|
||||||
itemsIndexed(
|
|
||||||
relays,
|
|
||||||
key = { _, item -> item.relay.url },
|
|
||||||
) { index, item ->
|
|
||||||
RenderRelaySwitch(
|
|
||||||
item,
|
|
||||||
onClick = {
|
|
||||||
relays =
|
|
||||||
relays.mapIndexed { j, item ->
|
|
||||||
if (index == j) {
|
|
||||||
item.copy(isSelected = !item.isSelected)
|
|
||||||
} else {
|
|
||||||
item
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
accountViewModel,
|
|
||||||
nav,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun RenderRelaySwitch(
|
|
||||||
item: RelayList,
|
|
||||||
onClick: () -> Unit,
|
|
||||||
accountViewModel: AccountViewModel,
|
|
||||||
nav: INav,
|
|
||||||
) {
|
|
||||||
val context = LocalContext.current
|
|
||||||
|
|
||||||
val relayInfo by loadRelayInfo(item.relay, accountViewModel)
|
|
||||||
|
|
||||||
var openRelayDialog by remember { mutableStateOf(false) }
|
|
||||||
|
|
||||||
if (openRelayDialog) {
|
|
||||||
RelayInformationDialog(
|
|
||||||
onClose = { openRelayDialog = false },
|
|
||||||
relayInfo = relayInfo,
|
|
||||||
relay = item.relay,
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
nav = nav,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
RelaySwitch(
|
|
||||||
text = item.relay.displayUrl(),
|
|
||||||
checked = item.isSelected,
|
|
||||||
onClick = onClick,
|
|
||||||
onLongPress = {
|
|
||||||
openRelayDialog = true
|
|
||||||
accountViewModel.retrieveRelayDocument(
|
|
||||||
relay = item.relay,
|
|
||||||
onInfo = { },
|
|
||||||
onError = { relay, errorCode, exceptionMessage ->
|
|
||||||
val msg =
|
|
||||||
when (errorCode) {
|
|
||||||
Nip11Retriever.ErrorCode.FAIL_TO_ASSEMBLE_URL ->
|
|
||||||
stringRes(
|
|
||||||
context,
|
|
||||||
R.string.relay_information_document_error_assemble_url,
|
|
||||||
relay.url,
|
|
||||||
exceptionMessage,
|
|
||||||
)
|
|
||||||
Nip11Retriever.ErrorCode.FAIL_TO_REACH_SERVER ->
|
|
||||||
stringRes(
|
|
||||||
context,
|
|
||||||
R.string.relay_information_document_error_assemble_url,
|
|
||||||
relay.url,
|
|
||||||
exceptionMessage,
|
|
||||||
)
|
|
||||||
Nip11Retriever.ErrorCode.FAIL_TO_PARSE_RESULT ->
|
|
||||||
stringRes(
|
|
||||||
context,
|
|
||||||
R.string.relay_information_document_error_assemble_url,
|
|
||||||
relay.url,
|
|
||||||
exceptionMessage,
|
|
||||||
)
|
|
||||||
Nip11Retriever.ErrorCode.FAIL_WITH_HTTP_STATUS ->
|
|
||||||
stringRes(
|
|
||||||
context,
|
|
||||||
R.string.relay_information_document_error_assemble_url,
|
|
||||||
relay.url,
|
|
||||||
exceptionMessage,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
accountViewModel.toastManager.toast(
|
|
||||||
stringRes(context, R.string.unable_to_download_relay_document),
|
|
||||||
msg,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
|
||||||
@Composable
|
|
||||||
fun RelaySwitch(
|
|
||||||
text: String,
|
|
||||||
checked: Boolean,
|
|
||||||
onClick: () -> Unit,
|
|
||||||
onLongPress: () -> Unit = {},
|
|
||||||
) {
|
|
||||||
Row(
|
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
modifier =
|
|
||||||
Modifier.combinedClickable(
|
|
||||||
onClick = onClick,
|
|
||||||
onLongClick = onLongPress,
|
|
||||||
),
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
modifier = Modifier.weight(1f),
|
|
||||||
text = text,
|
|
||||||
)
|
|
||||||
Switch(
|
|
||||||
checked = checked,
|
|
||||||
onCheckedChange = { onClick() },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+39
-52
@@ -64,7 +64,6 @@ import com.vitorpamplona.quartz.experimental.nip95.data.FileStorageEvent
|
|||||||
import com.vitorpamplona.quartz.experimental.nip95.header.FileStorageHeaderEvent
|
import com.vitorpamplona.quartz.experimental.nip95.header.FileStorageHeaderEvent
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent
|
import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
|
||||||
import com.vitorpamplona.quartz.nip01Core.signers.EventTemplate
|
import com.vitorpamplona.quartz.nip01Core.signers.EventTemplate
|
||||||
import com.vitorpamplona.quartz.nip01Core.tags.geohash.geohash
|
import com.vitorpamplona.quartz.nip01Core.tags.geohash.geohash
|
||||||
import com.vitorpamplona.quartz.nip01Core.tags.geohash.hasGeohashes
|
import com.vitorpamplona.quartz.nip01Core.tags.geohash.hasGeohashes
|
||||||
@@ -99,13 +98,14 @@ import com.vitorpamplona.quartz.nip94FileMetadata.mimeType
|
|||||||
import com.vitorpamplona.quartz.nip94FileMetadata.originalHash
|
import com.vitorpamplona.quartz.nip94FileMetadata.originalHash
|
||||||
import com.vitorpamplona.quartz.nip94FileMetadata.sensitiveContent
|
import com.vitorpamplona.quartz.nip94FileMetadata.sensitiveContent
|
||||||
import com.vitorpamplona.quartz.nip94FileMetadata.size
|
import com.vitorpamplona.quartz.nip94FileMetadata.size
|
||||||
|
import com.vitorpamplona.quartz.utils.tryAndWait
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlin.collections.plus
|
import kotlin.collections.plus
|
||||||
|
import kotlin.coroutines.resume
|
||||||
|
|
||||||
@Stable
|
@Stable
|
||||||
open class CommentPostViewModel :
|
open class CommentPostViewModel :
|
||||||
@@ -131,7 +131,7 @@ open class CommentPostViewModel :
|
|||||||
var account: Account? = null
|
var account: Account? = null
|
||||||
|
|
||||||
var externalIdentity by mutableStateOf<ExternalId?>(null)
|
var externalIdentity by mutableStateOf<ExternalId?>(null)
|
||||||
var replyingTo: Note? by mutableStateOf<Note?>(null)
|
var replyingTo: Note? by mutableStateOf(null)
|
||||||
|
|
||||||
val iMetaAttachments = IMetaAttachments()
|
val iMetaAttachments = IMetaAttachments()
|
||||||
var nip95attachments by mutableStateOf<List<Pair<FileStorageEvent, FileStorageHeaderEvent>>>(
|
var nip95attachments by mutableStateOf<List<Pair<FileStorageEvent, FileStorageHeaderEvent>>>(
|
||||||
@@ -177,9 +177,6 @@ open class CommentPostViewModel :
|
|||||||
var wantsZapraiser by mutableStateOf(false)
|
var wantsZapraiser by mutableStateOf(false)
|
||||||
override val zapRaiserAmount = mutableStateOf<Long?>(null)
|
override val zapRaiserAmount = mutableStateOf<Long?>(null)
|
||||||
|
|
||||||
var showRelaysDialog by mutableStateOf(false)
|
|
||||||
var relayList by mutableStateOf<ImmutableList<NormalizedRelayUrl>?>(null)
|
|
||||||
|
|
||||||
fun lnAddress(): String? = account?.userProfile()?.info?.lnAddress()
|
fun lnAddress(): String? = account?.userProfile()?.info?.lnAddress()
|
||||||
|
|
||||||
fun hasLnAddress(): Boolean = account?.userProfile()?.info?.lnAddress() != null
|
fun hasLnAddress(): Boolean = account?.userProfile()?.info?.lnAddress() != null
|
||||||
@@ -270,15 +267,15 @@ open class CommentPostViewModel :
|
|||||||
canAddZapRaiser = accountViewModel?.userProfile()?.info?.lnAddress() != null
|
canAddZapRaiser = accountViewModel?.userProfile()?.info?.lnAddress() != null
|
||||||
multiOrchestrator = null
|
multiOrchestrator = null
|
||||||
|
|
||||||
val localfowardZapTo = draftEvent.tags.filter { it.size > 1 && it[0] == "zap" }
|
val localForwardZapTo = draftEvent.tags.filter { it.size > 1 && it[0] == "zap" }
|
||||||
forwardZapTo.value = SplitBuilder()
|
forwardZapTo.value = SplitBuilder()
|
||||||
localfowardZapTo.forEach {
|
localForwardZapTo.forEach {
|
||||||
val user = LocalCache.getOrCreateUser(it[1])
|
val user = LocalCache.getOrCreateUser(it[1])
|
||||||
val value = it.last().toFloatOrNull() ?: 0f
|
val value = it.last().toFloatOrNull() ?: 0f
|
||||||
forwardZapTo.value.addItem(user, value)
|
forwardZapTo.value.addItem(user, value)
|
||||||
}
|
}
|
||||||
forwardZapToEditting.value = TextFieldValue("")
|
forwardZapToEditting.value = TextFieldValue("")
|
||||||
wantsForwardZapTo = localfowardZapTo.isNotEmpty()
|
wantsForwardZapTo = localForwardZapTo.isNotEmpty()
|
||||||
|
|
||||||
wantsToMarkAsSensitive = draftEvent.isSensitive()
|
wantsToMarkAsSensitive = draftEvent.isSensitive()
|
||||||
|
|
||||||
@@ -311,21 +308,23 @@ open class CommentPostViewModel :
|
|||||||
|
|
||||||
suspend fun sendPostSync() {
|
suspend fun sendPostSync() {
|
||||||
val template = createTemplate() ?: return
|
val template = createTemplate() ?: return
|
||||||
val relayList = relayList
|
val extraNotesToBroadcast = mutableListOf<Event>()
|
||||||
|
|
||||||
if (nip95attachments.isNotEmpty() && relayList != null && relayList.isNotEmpty()) {
|
if (nip95attachments.isNotEmpty()) {
|
||||||
val usedImages = template.tags.taggedQuoteIds().toSet()
|
val usedImages = template.tags.taggedQuoteIds().toSet()
|
||||||
nip95attachments.forEach {
|
nip95attachments.forEach {
|
||||||
if (usedImages.contains(it.second.id)) {
|
if (usedImages.contains(it.second.id)) {
|
||||||
account?.sendNip95(it.first, it.second, relayList.toSet())
|
extraNotesToBroadcast.add(it.first)
|
||||||
|
extraNotesToBroadcast.add(it.second)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
accountViewModel?.account?.signAndSendPrivatelyOrBroadcast(
|
tryAndWait { continuation ->
|
||||||
template,
|
accountViewModel?.account?.signAndComputeBroadcast(template, extraNotesToBroadcast) {
|
||||||
relayList = { relayList },
|
continuation.resume(it)
|
||||||
)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
accountViewModel?.deleteDraft(draftTag.current)
|
accountViewModel?.deleteDraft(draftTag.current)
|
||||||
|
|
||||||
@@ -378,7 +377,7 @@ open class CommentPostViewModel :
|
|||||||
msg = tagger.message,
|
msg = tagger.message,
|
||||||
replyingTo = eventHint,
|
replyingTo = eventHint,
|
||||||
) {
|
) {
|
||||||
tagger.pTags?.let { notify(it.map { it.toPTag() }) }
|
tagger.pTags?.let { pTagList -> notify(pTagList.map { it.toPTag() }) }
|
||||||
|
|
||||||
hashtags(findHashtags(tagger.message))
|
hashtags(findHashtags(tagger.message))
|
||||||
references(findURLs(tagger.message))
|
references(findURLs(tagger.message))
|
||||||
@@ -398,7 +397,7 @@ open class CommentPostViewModel :
|
|||||||
msg = tagger.message,
|
msg = tagger.message,
|
||||||
extId = externalIdentity,
|
extId = externalIdentity,
|
||||||
) {
|
) {
|
||||||
tagger.pTags?.let { notify(it.map { it.toPTag() }) }
|
tagger.pTags?.let { pTagList -> notify(pTagList.map { it.toPTag() }) }
|
||||||
|
|
||||||
hashtags(findHashtags(tagger.message))
|
hashtags(findHashtags(tagger.message))
|
||||||
references(findURLs(tagger.message))
|
references(findURLs(tagger.message))
|
||||||
@@ -458,9 +457,9 @@ open class CommentPostViewModel :
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (results.allGood) {
|
if (results.allGood) {
|
||||||
results.successful.forEach {
|
results.successful.forEach { state ->
|
||||||
if (it.result is UploadOrchestrator.OrchestratorResult.NIP95Result) {
|
if (state.result is UploadOrchestrator.OrchestratorResult.NIP95Result) {
|
||||||
account?.createNip95(it.result.bytes, headerInfo = it.result.fileHeader, alt, contentWarningReason) { nip95 ->
|
account?.createNip95(state.result.bytes, headerInfo = state.result.fileHeader, alt, contentWarningReason) { nip95 ->
|
||||||
nip95attachments = nip95attachments + nip95
|
nip95attachments = nip95attachments + nip95
|
||||||
val note = nip95.let { it1 -> account?.consumeNip95(it1.first, it1.second) }
|
val note = nip95.let { it1 -> account?.consumeNip95(it1.first, it1.second) }
|
||||||
|
|
||||||
@@ -469,20 +468,20 @@ open class CommentPostViewModel :
|
|||||||
urlPreviews.update(message)
|
urlPreviews.update(message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (it.result is UploadOrchestrator.OrchestratorResult.ServerResult) {
|
} else if (state.result is UploadOrchestrator.OrchestratorResult.ServerResult) {
|
||||||
val iMeta =
|
val iMeta =
|
||||||
IMetaTagBuilder(it.result.url)
|
IMetaTagBuilder(state.result.url)
|
||||||
.apply {
|
.apply {
|
||||||
hash(it.result.fileHeader.hash)
|
hash(state.result.fileHeader.hash)
|
||||||
size(it.result.fileHeader.size)
|
size(state.result.fileHeader.size)
|
||||||
it.result.fileHeader.mimeType
|
state.result.fileHeader.mimeType
|
||||||
?.let { mimeType(it) }
|
?.let { mimeType(it) }
|
||||||
it.result.fileHeader.dim
|
state.result.fileHeader.dim
|
||||||
?.let { dims(it) }
|
?.let { dims(it) }
|
||||||
it.result.fileHeader.blurHash
|
state.result.fileHeader.blurHash
|
||||||
?.let { blurhash(it.blurhash) }
|
?.let { blurhash(it.blurhash) }
|
||||||
it.result.magnet?.let { magnet(it) }
|
state.result.magnet?.let { magnet(it) }
|
||||||
it.result.uploadedHash?.let { originalHash(it) }
|
state.result.uploadedHash?.let { originalHash(it) }
|
||||||
|
|
||||||
alt?.let { alt(it) }
|
alt?.let { alt(it) }
|
||||||
contentWarningReason?.let { sensitiveContent(contentWarningReason) }
|
contentWarningReason?.let { sensitiveContent(contentWarningReason) }
|
||||||
@@ -490,7 +489,7 @@ open class CommentPostViewModel :
|
|||||||
|
|
||||||
iMetaAttachments.replace(iMeta.url, iMeta)
|
iMetaAttachments.replace(iMeta.url, iMeta)
|
||||||
|
|
||||||
message = message.insertUrlAtCursor(it.result.url)
|
message = message.insertUrlAtCursor(state.result.url)
|
||||||
urlPreviews.update(message)
|
urlPreviews.update(message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -546,21 +545,9 @@ open class CommentPostViewModel :
|
|||||||
|
|
||||||
emojiSuggestions?.reset()
|
emojiSuggestions?.reset()
|
||||||
|
|
||||||
showRelaysDialog = false
|
|
||||||
|
|
||||||
reloadRelaySet()
|
|
||||||
|
|
||||||
draftTag.rotate()
|
draftTag.rotate()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reloadRelaySet() {
|
|
||||||
val account = accountViewModel?.account ?: return
|
|
||||||
|
|
||||||
relayList =
|
|
||||||
account.outboxRelays.flow.value
|
|
||||||
.toImmutableList()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteMediaToUpload(selected: SelectedMediaProcessing) {
|
fun deleteMediaToUpload(selected: SelectedMediaProcessing) {
|
||||||
this.multiOrchestrator?.remove(selected)
|
this.multiOrchestrator?.remove(selected)
|
||||||
}
|
}
|
||||||
@@ -569,8 +556,8 @@ open class CommentPostViewModel :
|
|||||||
notifying = notifying?.filter { it != userToRemove }
|
notifying = notifying?.filter { it != userToRemove }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateMessage(it: TextFieldValue) {
|
override fun updateMessage(newMessage: TextFieldValue) {
|
||||||
message = it
|
message = newMessage
|
||||||
urlPreviews.update(message)
|
urlPreviews.update(message)
|
||||||
|
|
||||||
if (message.selection.collapsed) {
|
if (message.selection.collapsed) {
|
||||||
@@ -627,13 +614,13 @@ open class CommentPostViewModel :
|
|||||||
val wordToInsert = item.link.url + " "
|
val wordToInsert = item.link.url + " "
|
||||||
|
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
iMetaAttachments.downloadAndPrepare(
|
iMetaAttachments.downloadAndPrepare(item.link.url) {
|
||||||
item.link.url,
|
Amethyst.Companion.instance.okHttpClients
|
||||||
{
|
.getHttpClient(
|
||||||
Amethyst.Companion.instance.okHttpClients
|
accountViewModel?.account?.shouldUseTorForImageDownload(item.link.url)
|
||||||
.getHttpClient(accountViewModel?.account?.shouldUseTorForImageDownload(item.link.url) ?: false)
|
?: false,
|
||||||
},
|
)
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
message = message.replaceCurrentWord(wordToInsert)
|
message = message.replaceCurrentWord(wordToInsert)
|
||||||
|
|||||||
-30
@@ -23,7 +23,6 @@ package com.vitorpamplona.amethyst.ui.note.nip22Comments
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.compose.foundation.horizontalScroll
|
import androidx.compose.foundation.horizontalScroll
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
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
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
@@ -37,8 +36,6 @@ import androidx.compose.foundation.layout.padding
|
|||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
@@ -46,7 +43,6 @@ import androidx.compose.material3.TopAppBar
|
|||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Alignment.Companion.CenterVertically
|
import androidx.compose.ui.Alignment.Companion.CenterVertically
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
@@ -56,7 +52,6 @@ import androidx.lifecycle.viewModelScope
|
|||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
import com.vitorpamplona.amethyst.ui.actions.RelaySelectionDialog
|
|
||||||
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType
|
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectFromGallery
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectFromGallery
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
||||||
@@ -85,7 +80,6 @@ import com.vitorpamplona.amethyst.ui.note.creators.zapraiser.AddZapraiserButton
|
|||||||
import com.vitorpamplona.amethyst.ui.note.creators.zapraiser.ZapRaiserRequest
|
import com.vitorpamplona.amethyst.ui.note.creators.zapraiser.ZapRaiserRequest
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.zapsplits.ForwardZapTo
|
import com.vitorpamplona.amethyst.ui.note.creators.zapsplits.ForwardZapTo
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.zapsplits.ForwardZapToButton
|
import com.vitorpamplona.amethyst.ui.note.creators.zapsplits.ForwardZapToButton
|
||||||
import com.vitorpamplona.amethyst.ui.painterRes
|
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
import com.vitorpamplona.amethyst.ui.theme.Size10dp
|
import com.vitorpamplona.amethyst.ui.theme.Size10dp
|
||||||
@@ -116,7 +110,6 @@ fun ReplyCommentPostScreen(
|
|||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
postViewModel.reloadRelaySet()
|
|
||||||
reply?.let {
|
reply?.let {
|
||||||
postViewModel.reply(it)
|
postViewModel.reply(it)
|
||||||
}
|
}
|
||||||
@@ -159,20 +152,6 @@ fun GenericCommentPostScreen(
|
|||||||
verticalAlignment = CenterVertically,
|
verticalAlignment = CenterVertically,
|
||||||
) {
|
) {
|
||||||
Spacer(modifier = StdHorzSpacer)
|
Spacer(modifier = StdHorzSpacer)
|
||||||
|
|
||||||
Box {
|
|
||||||
IconButton(
|
|
||||||
modifier = Modifier.align(Alignment.Center),
|
|
||||||
onClick = { postViewModel.showRelaysDialog = true },
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
painter = painterRes(R.drawable.relays, 5),
|
|
||||||
contentDescription = stringRes(id = R.string.relay_list_selector),
|
|
||||||
modifier = Modifier.height(25.dp),
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PostButton(
|
PostButton(
|
||||||
onPost = {
|
onPost = {
|
||||||
// uses the accountViewModel scope to avoid cancelling this
|
// uses the accountViewModel scope to avoid cancelling this
|
||||||
@@ -209,15 +188,6 @@ fun GenericCommentPostScreen(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
) { pad ->
|
) { pad ->
|
||||||
if (postViewModel.showRelaysDialog) {
|
|
||||||
RelaySelectionDialog(
|
|
||||||
preSelectedList = postViewModel.relayList ?: persistentListOf(),
|
|
||||||
onClose = { postViewModel.showRelaysDialog = false },
|
|
||||||
onPost = { postViewModel.relayList = it },
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
nav = nav,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Surface(
|
Surface(
|
||||||
modifier =
|
modifier =
|
||||||
Modifier
|
Modifier
|
||||||
|
|||||||
-32
@@ -23,7 +23,6 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip99Classifieds
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.compose.foundation.horizontalScroll
|
import androidx.compose.foundation.horizontalScroll
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
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
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
@@ -37,8 +36,6 @@ import androidx.compose.foundation.layout.padding
|
|||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
@@ -47,10 +44,7 @@ import androidx.compose.material3.TopAppBarDefaults
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Alignment.Companion.CenterVertically
|
import androidx.compose.ui.Alignment.Companion.CenterVertically
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
@@ -60,7 +54,6 @@ import androidx.lifecycle.viewModelScope
|
|||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
import com.vitorpamplona.amethyst.ui.actions.RelaySelectionDialog
|
|
||||||
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType
|
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectFromGallery
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectFromGallery
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
||||||
@@ -88,7 +81,6 @@ import com.vitorpamplona.amethyst.ui.note.creators.zapraiser.AddZapraiserButton
|
|||||||
import com.vitorpamplona.amethyst.ui.note.creators.zapraiser.ZapRaiserRequest
|
import com.vitorpamplona.amethyst.ui.note.creators.zapraiser.ZapRaiserRequest
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.zapsplits.ForwardZapTo
|
import com.vitorpamplona.amethyst.ui.note.creators.zapsplits.ForwardZapTo
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.zapsplits.ForwardZapToButton
|
import com.vitorpamplona.amethyst.ui.note.creators.zapsplits.ForwardZapToButton
|
||||||
import com.vitorpamplona.amethyst.ui.painterRes
|
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
import com.vitorpamplona.amethyst.ui.theme.Size10dp
|
import com.vitorpamplona.amethyst.ui.theme.Size10dp
|
||||||
@@ -151,8 +143,6 @@ fun NewProductScreen(
|
|||||||
) {
|
) {
|
||||||
WatchAndLoadMyEmojiList(accountViewModel)
|
WatchAndLoadMyEmojiList(accountViewModel)
|
||||||
|
|
||||||
var showRelaysDialog by remember { mutableStateOf(false) }
|
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
@@ -164,19 +154,6 @@ fun NewProductScreen(
|
|||||||
) {
|
) {
|
||||||
Spacer(modifier = StdHorzSpacer)
|
Spacer(modifier = StdHorzSpacer)
|
||||||
|
|
||||||
Box {
|
|
||||||
IconButton(
|
|
||||||
modifier = Modifier.align(Alignment.Center),
|
|
||||||
onClick = { showRelaysDialog = true },
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
painter = painterRes(R.drawable.relays, 1),
|
|
||||||
contentDescription = stringRes(id = R.string.relay_list_selector),
|
|
||||||
modifier = Modifier.height(25.dp),
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PostButton(
|
PostButton(
|
||||||
onPost = {
|
onPost = {
|
||||||
accountViewModel.viewModelScope.launch(Dispatchers.IO) {
|
accountViewModel.viewModelScope.launch(Dispatchers.IO) {
|
||||||
@@ -210,15 +187,6 @@ fun NewProductScreen(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
) { pad ->
|
) { pad ->
|
||||||
if (showRelaysDialog) {
|
|
||||||
RelaySelectionDialog(
|
|
||||||
preSelectedList = postViewModel.relayList ?: persistentListOf(),
|
|
||||||
onClose = { showRelaysDialog = false },
|
|
||||||
onPost = { postViewModel.relayList = it },
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
nav = nav,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Surface(
|
Surface(
|
||||||
modifier =
|
modifier =
|
||||||
Modifier
|
Modifier
|
||||||
|
|||||||
-1
@@ -54,7 +54,6 @@ fun GeoHashPostScreen(
|
|||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
postViewModel.reloadRelaySet()
|
|
||||||
geohash?.let {
|
geohash?.let {
|
||||||
postViewModel.newPostFor(GeohashId(it))
|
postViewModel.newPostFor(GeohashId(it))
|
||||||
}
|
}
|
||||||
|
|||||||
-1
@@ -54,7 +54,6 @@ fun HashtagPostScreen(
|
|||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
postViewModel.reloadRelaySet()
|
|
||||||
hashtag?.let {
|
hashtag?.let {
|
||||||
postViewModel.newPostFor(HashtagId(it))
|
postViewModel.newPostFor(HashtagId(it))
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-31
@@ -25,7 +25,6 @@ import android.net.Uri
|
|||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import androidx.compose.foundation.horizontalScroll
|
import androidx.compose.foundation.horizontalScroll
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
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
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
@@ -50,8 +49,6 @@ import androidx.compose.material3.TopAppBarDefaults
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.DisposableEffect
|
import androidx.compose.runtime.DisposableEffect
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Alignment.Companion.CenterVertically
|
import androidx.compose.ui.Alignment.Companion.CenterVertically
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
@@ -62,7 +59,6 @@ import androidx.lifecycle.viewModelScope
|
|||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
import com.vitorpamplona.amethyst.ui.actions.RelaySelectionDialog
|
|
||||||
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType
|
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectFromGallery
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectFromGallery
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
||||||
@@ -173,8 +169,6 @@ private fun NewPostScreenInner(
|
|||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
nav: Nav,
|
nav: Nav,
|
||||||
) {
|
) {
|
||||||
val scope = rememberCoroutineScope()
|
|
||||||
|
|
||||||
WatchAndLoadMyEmojiList(accountViewModel)
|
WatchAndLoadMyEmojiList(accountViewModel)
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
@@ -188,19 +182,6 @@ private fun NewPostScreenInner(
|
|||||||
) {
|
) {
|
||||||
Spacer(modifier = StdHorzSpacer)
|
Spacer(modifier = StdHorzSpacer)
|
||||||
|
|
||||||
Box {
|
|
||||||
IconButton(
|
|
||||||
modifier = Modifier.align(Alignment.Center),
|
|
||||||
onClick = { postViewModel.showRelaysDialog = true },
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
painter = painterRes(R.drawable.relays, 6),
|
|
||||||
contentDescription = stringRes(id = R.string.relay_list_selector),
|
|
||||||
modifier = Modifier.height(25.dp),
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PostButton(
|
PostButton(
|
||||||
onPost = {
|
onPost = {
|
||||||
// uses the accountViewModel scope to avoid cancelling this
|
// uses the accountViewModel scope to avoid cancelling this
|
||||||
@@ -238,15 +219,6 @@ private fun NewPostScreenInner(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
) { pad ->
|
) { pad ->
|
||||||
if (postViewModel.showRelaysDialog) {
|
|
||||||
RelaySelectionDialog(
|
|
||||||
preSelectedList = postViewModel.relayList ?: persistentListOf(),
|
|
||||||
onClose = { postViewModel.showRelaysDialog = false },
|
|
||||||
onPost = { postViewModel.relayList = it },
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
nav = nav,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Surface(
|
Surface(
|
||||||
modifier =
|
modifier =
|
||||||
Modifier
|
Modifier
|
||||||
@@ -419,7 +391,7 @@ private fun NewPostScreenBody(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (postViewModel.wantsZapraiser && postViewModel.hasLnAddress()) {
|
if (postViewModel.wantsZapRaiser && postViewModel.hasLnAddress()) {
|
||||||
Row(
|
Row(
|
||||||
verticalAlignment = CenterVertically,
|
verticalAlignment = CenterVertically,
|
||||||
modifier = Modifier.padding(vertical = Size5dp, horizontal = Size10dp),
|
modifier = Modifier.padding(vertical = Size5dp, horizontal = Size10dp),
|
||||||
@@ -495,8 +467,8 @@ private fun BottomRowActions(postViewModel: ShortNotePostViewModel) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (postViewModel.canAddZapRaiser) {
|
if (postViewModel.canAddZapRaiser) {
|
||||||
AddZapraiserButton(postViewModel.wantsZapraiser) {
|
AddZapraiserButton(postViewModel.wantsZapRaiser) {
|
||||||
postViewModel.wantsZapraiser = !postViewModel.wantsZapraiser
|
postViewModel.wantsZapRaiser = !postViewModel.wantsZapRaiser
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+69
-79
@@ -74,7 +74,6 @@ import com.vitorpamplona.quartz.experimental.zapPolls.tags.PollOptionTag
|
|||||||
import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent
|
import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
|
||||||
import com.vitorpamplona.quartz.nip01Core.signers.EventTemplate
|
import com.vitorpamplona.quartz.nip01Core.signers.EventTemplate
|
||||||
import com.vitorpamplona.quartz.nip01Core.tags.geohash.geohash
|
import com.vitorpamplona.quartz.nip01Core.tags.geohash.geohash
|
||||||
import com.vitorpamplona.quartz.nip01Core.tags.geohash.getGeoHash
|
import com.vitorpamplona.quartz.nip01Core.tags.geohash.getGeoHash
|
||||||
@@ -115,12 +114,13 @@ import com.vitorpamplona.quartz.nip94FileMetadata.mimeType
|
|||||||
import com.vitorpamplona.quartz.nip94FileMetadata.originalHash
|
import com.vitorpamplona.quartz.nip94FileMetadata.originalHash
|
||||||
import com.vitorpamplona.quartz.nip94FileMetadata.sensitiveContent
|
import com.vitorpamplona.quartz.nip94FileMetadata.sensitiveContent
|
||||||
import com.vitorpamplona.quartz.nip94FileMetadata.size
|
import com.vitorpamplona.quartz.nip94FileMetadata.size
|
||||||
|
import com.vitorpamplona.quartz.utils.tryAndWait
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlin.coroutines.resume
|
||||||
|
|
||||||
enum class UserSuggestionAnchor {
|
enum class UserSuggestionAnchor {
|
||||||
MAIN_MESSAGE,
|
MAIN_MESSAGE,
|
||||||
@@ -151,8 +151,8 @@ open class ShortNotePostViewModel :
|
|||||||
var accountViewModel: AccountViewModel? = null
|
var accountViewModel: AccountViewModel? = null
|
||||||
var account: Account? = null
|
var account: Account? = null
|
||||||
|
|
||||||
var originalNote: Note? by mutableStateOf<Note?>(null)
|
var originalNote: Note? by mutableStateOf(null)
|
||||||
var forkedFromNote: Note? by mutableStateOf<Note?>(null)
|
var forkedFromNote: Note? by mutableStateOf(null)
|
||||||
|
|
||||||
var pTags by mutableStateOf<List<User>?>(null)
|
var pTags by mutableStateOf<List<User>?>(null)
|
||||||
var eTags by mutableStateOf<List<Note>?>(null)
|
var eTags by mutableStateOf<List<Note>?>(null)
|
||||||
@@ -185,9 +185,8 @@ open class ShortNotePostViewModel :
|
|||||||
var consensusThreshold: Int? = null
|
var consensusThreshold: Int? = null
|
||||||
var closedAt: Long? = null
|
var closedAt: Long? = null
|
||||||
|
|
||||||
var isValidRecipients = mutableStateOf(true)
|
var isValidValueMaximum = mutableStateOf(true)
|
||||||
var isValidvalueMaximum = mutableStateOf(true)
|
var isValidValueMinimum = mutableStateOf(true)
|
||||||
var isValidvalueMinimum = mutableStateOf(true)
|
|
||||||
var isValidConsensusThreshold = mutableStateOf(true)
|
var isValidConsensusThreshold = mutableStateOf(true)
|
||||||
var isValidClosedAt = mutableStateOf(true)
|
var isValidClosedAt = mutableStateOf(true)
|
||||||
|
|
||||||
@@ -212,12 +211,9 @@ open class ShortNotePostViewModel :
|
|||||||
|
|
||||||
// ZapRaiser
|
// ZapRaiser
|
||||||
var canAddZapRaiser by mutableStateOf(false)
|
var canAddZapRaiser by mutableStateOf(false)
|
||||||
var wantsZapraiser by mutableStateOf(false)
|
var wantsZapRaiser by mutableStateOf(false)
|
||||||
override val zapRaiserAmount = mutableStateOf<Long?>(null)
|
override val zapRaiserAmount = mutableStateOf<Long?>(null)
|
||||||
|
|
||||||
var showRelaysDialog by mutableStateOf(false)
|
|
||||||
var relayList by mutableStateOf<ImmutableList<NormalizedRelayUrl>?>(null)
|
|
||||||
|
|
||||||
fun lnAddress(): String? = account?.userProfile()?.info?.lnAddress()
|
fun lnAddress(): String? = account?.userProfile()?.info?.lnAddress()
|
||||||
|
|
||||||
fun hasLnAddress(): Boolean = account?.userProfile()?.info?.lnAddress() != null
|
fun hasLnAddress(): Boolean = account?.userProfile()?.info?.lnAddress() != null
|
||||||
@@ -295,10 +291,10 @@ open class ShortNotePostViewModel :
|
|||||||
canUsePoll = originalNote == null
|
canUsePoll = originalNote == null
|
||||||
multiOrchestrator = null
|
multiOrchestrator = null
|
||||||
|
|
||||||
quote?.let {
|
quote?.let { quotedNote ->
|
||||||
message = TextFieldValue(message.text + "\nnostr:${it.toNEvent()}")
|
message = TextFieldValue(message.text + "\nnostr:${quotedNote.toNEvent()}")
|
||||||
|
|
||||||
it.author?.let { quotedUser ->
|
quotedNote.author?.let { quotedUser ->
|
||||||
if (quotedUser.pubkeyHex != accountViewModel.userProfile().pubkeyHex) {
|
if (quotedUser.pubkeyHex != accountViewModel.userProfile().pubkeyHex) {
|
||||||
if (forwardZapTo.value.items.none { it.key.pubkeyHex == quotedUser.pubkeyHex }) {
|
if (forwardZapTo.value.items.none { it.key.pubkeyHex == quotedUser.pubkeyHex }) {
|
||||||
forwardZapTo.value.addItem(quotedUser)
|
forwardZapTo.value.addItem(quotedUser)
|
||||||
@@ -313,21 +309,21 @@ open class ShortNotePostViewModel :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fork?.let {
|
fork?.let { forkedNoted ->
|
||||||
message = TextFieldValue(version?.event?.content ?: it.event?.content ?: "")
|
message = TextFieldValue(version?.event?.content ?: forkedNoted.event?.content ?: "")
|
||||||
|
|
||||||
it.event?.isSensitiveOrNSFW()?.let {
|
forkedNoted.event?.isSensitiveOrNSFW()?.let {
|
||||||
if (it) wantsToMarkAsSensitive = true
|
if (it) wantsToMarkAsSensitive = true
|
||||||
}
|
}
|
||||||
|
|
||||||
it.event?.zapraiserAmount()?.let {
|
forkedNoted.event?.zapraiserAmount()?.let {
|
||||||
zapRaiserAmount.value = it
|
zapRaiserAmount.value = it
|
||||||
}
|
}
|
||||||
|
|
||||||
it.event?.zapSplitSetup()?.let {
|
forkedNoted.event?.zapSplitSetup()?.let { setup ->
|
||||||
val totalWeight = it.sumOf { if (it is ZapSplitSetupLnAddress) 0.0 else it.weight }
|
val totalWeight = setup.sumOf { if (it is ZapSplitSetupLnAddress) 0.0 else it.weight }
|
||||||
|
|
||||||
it.forEach {
|
setup.forEach {
|
||||||
if (it is ZapSplitSetup) {
|
if (it is ZapSplitSetup) {
|
||||||
forwardZapTo.value.addItem(LocalCache.getOrCreateUser(it.pubKeyHex), (it.weight / totalWeight).toFloat())
|
forwardZapTo.value.addItem(LocalCache.getOrCreateUser(it.pubKeyHex), (it.weight / totalWeight).toFloat())
|
||||||
}
|
}
|
||||||
@@ -336,7 +332,7 @@ open class ShortNotePostViewModel :
|
|||||||
|
|
||||||
// Only adds if it is not already set up.
|
// Only adds if it is not already set up.
|
||||||
if (forwardZapTo.value.items.isEmpty()) {
|
if (forwardZapTo.value.items.isEmpty()) {
|
||||||
it.author?.let { forkedAuthor ->
|
forkedNoted.author?.let { forkedAuthor ->
|
||||||
if (forkedAuthor.pubkeyHex != accountViewModel.userProfile().pubkeyHex) {
|
if (forkedAuthor.pubkeyHex != accountViewModel.userProfile().pubkeyHex) {
|
||||||
if (forwardZapTo.value.items.none { it.key.pubkeyHex == forkedAuthor.pubkeyHex }) forwardZapTo.value.addItem(forkedAuthor)
|
if (forwardZapTo.value.items.none { it.key.pubkeyHex == forkedAuthor.pubkeyHex }) forwardZapTo.value.addItem(forkedAuthor)
|
||||||
if (forwardZapTo.value.items.none { it.key.pubkeyHex == accountViewModel.userProfile().pubkeyHex }) forwardZapTo.value.addItem(accountViewModel.userProfile())
|
if (forwardZapTo.value.items.none { it.key.pubkeyHex == accountViewModel.userProfile().pubkeyHex }) forwardZapTo.value.addItem(accountViewModel.userProfile())
|
||||||
@@ -347,7 +343,7 @@ open class ShortNotePostViewModel :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
it.author?.let {
|
forkedNoted.author?.let {
|
||||||
if (this.pTags == null) {
|
if (this.pTags == null) {
|
||||||
this.pTags = listOf(it)
|
this.pTags = listOf(it)
|
||||||
} else if (this.pTags?.contains(it) != true) {
|
} else if (this.pTags?.contains(it) != true) {
|
||||||
@@ -355,7 +351,7 @@ open class ShortNotePostViewModel :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
forkedFromNote = it
|
forkedFromNote = forkedNoted
|
||||||
} ?: run {
|
} ?: run {
|
||||||
forkedFromNote = null
|
forkedFromNote = null
|
||||||
}
|
}
|
||||||
@@ -380,15 +376,15 @@ open class ShortNotePostViewModel :
|
|||||||
canAddZapRaiser = accountViewModel?.userProfile()?.info?.lnAddress() != null
|
canAddZapRaiser = accountViewModel?.userProfile()?.info?.lnAddress() != null
|
||||||
multiOrchestrator = null
|
multiOrchestrator = null
|
||||||
|
|
||||||
val localfowardZapTo = draftEvent.tags.filter { it.size > 1 && it[0] == "zap" }
|
val localForwardZapTo = draftEvent.tags.filter { it.size > 1 && it[0] == "zap" }
|
||||||
forwardZapTo.value = SplitBuilder()
|
forwardZapTo.value = SplitBuilder()
|
||||||
localfowardZapTo.forEach {
|
localForwardZapTo.forEach {
|
||||||
val user = LocalCache.getOrCreateUser(it[1])
|
val user = LocalCache.getOrCreateUser(it[1])
|
||||||
val value = it.last().toFloatOrNull() ?: 0f
|
val value = it.last().toFloatOrNull() ?: 0f
|
||||||
forwardZapTo.value.addItem(user, value)
|
forwardZapTo.value.addItem(user, value)
|
||||||
}
|
}
|
||||||
forwardZapToEditting.value = TextFieldValue("")
|
forwardZapToEditting.value = TextFieldValue("")
|
||||||
wantsForwardZapTo = localfowardZapTo.isNotEmpty()
|
wantsForwardZapTo = localForwardZapTo.isNotEmpty()
|
||||||
|
|
||||||
wantsToMarkAsSensitive = draftEvent.isSensitive()
|
wantsToMarkAsSensitive = draftEvent.isSensitive()
|
||||||
|
|
||||||
@@ -398,11 +394,11 @@ open class ShortNotePostViewModel :
|
|||||||
wantsExclusiveGeoPost = draftEvent.kind == CommentEvent.KIND
|
wantsExclusiveGeoPost = draftEvent.kind == CommentEvent.KIND
|
||||||
}
|
}
|
||||||
|
|
||||||
val zapraiser = draftEvent.zapraiserAmount()
|
val zapRaiser = draftEvent.zapraiserAmount()
|
||||||
wantsZapraiser = zapraiser != null
|
wantsZapRaiser = zapRaiser != null
|
||||||
zapRaiserAmount.value = null
|
zapRaiserAmount.value = null
|
||||||
if (zapraiser != null) {
|
if (zapRaiser != null) {
|
||||||
zapRaiserAmount.value = zapraiser
|
zapRaiserAmount.value = zapRaiser
|
||||||
}
|
}
|
||||||
|
|
||||||
eTags =
|
eTags =
|
||||||
@@ -416,7 +412,7 @@ open class ShortNotePostViewModel :
|
|||||||
LocalCache.getOrCreateUser(it[1])
|
LocalCache.getOrCreateUser(it[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
draftEvent.tags.filter { it.size > 3 && (it[0] == "e" || it[0] == "a") && it.get(3) == "fork" }.forEach {
|
draftEvent.tags.filter { it.size > 3 && (it[0] == "e" || it[0] == "a") && it[3] == "fork" }.forEach {
|
||||||
val note = LocalCache.checkGetOrCreateNote(it[1])
|
val note = LocalCache.checkGetOrCreateNote(it[1])
|
||||||
forkedFromNote = note
|
forkedFromNote = note
|
||||||
}
|
}
|
||||||
@@ -470,21 +466,23 @@ open class ShortNotePostViewModel :
|
|||||||
|
|
||||||
suspend fun sendPostSync() {
|
suspend fun sendPostSync() {
|
||||||
val template = createTemplate() ?: return
|
val template = createTemplate() ?: return
|
||||||
val relayList = relayList
|
val extraNotesToBroadcast = mutableListOf<Event>()
|
||||||
|
|
||||||
if (nip95attachments.isNotEmpty() && relayList != null && relayList.isNotEmpty()) {
|
if (nip95attachments.isNotEmpty()) {
|
||||||
val usedImages = template.tags.taggedQuoteIds().toSet()
|
val usedImages = template.tags.taggedQuoteIds().toSet()
|
||||||
nip95attachments.forEach {
|
nip95attachments.forEach {
|
||||||
if (usedImages.contains(it.second.id)) {
|
if (usedImages.contains(it.second.id)) {
|
||||||
account?.sendNip95(it.first, it.second, relayList.toSet())
|
extraNotesToBroadcast.add(it.first)
|
||||||
|
extraNotesToBroadcast.add(it.second)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
accountViewModel?.account?.signAndSendPrivatelyOrBroadcast(
|
tryAndWait { continuation ->
|
||||||
template,
|
accountViewModel?.account?.signAndComputeBroadcast(template, extraNotesToBroadcast) {
|
||||||
relayList = { relayList },
|
continuation.resume(it)
|
||||||
)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
accountViewModel?.deleteDraft(draftTag.current)
|
accountViewModel?.deleteDraft(draftTag.current)
|
||||||
|
|
||||||
@@ -526,7 +524,7 @@ open class ShortNotePostViewModel :
|
|||||||
val zapReceiver = if (wantsForwardZapTo) forwardZapTo.value.toZapSplitSetup() else null
|
val zapReceiver = if (wantsForwardZapTo) forwardZapTo.value.toZapSplitSetup() else null
|
||||||
|
|
||||||
val geoHash = (location?.value as? LocationState.LocationResult.Success)?.geoHash?.toString()
|
val geoHash = (location?.value as? LocationState.LocationResult.Success)?.geoHash?.toString()
|
||||||
val localZapRaiserAmount = if (wantsZapraiser) zapRaiserAmount.value else null
|
val localZapRaiserAmount = if (wantsZapRaiser) zapRaiserAmount.value else null
|
||||||
|
|
||||||
val emojis = findEmoji(tagger.message, account?.emoji?.myEmojis?.value)
|
val emojis = findEmoji(tagger.message, account?.emoji?.myEmojis?.value)
|
||||||
val urls = findURLs(tagger.message)
|
val urls = findURLs(tagger.message)
|
||||||
@@ -565,7 +563,7 @@ open class ShortNotePostViewModel :
|
|||||||
replyingTo = originalNote?.toEventHint<TextNoteEvent>(),
|
replyingTo = originalNote?.toEventHint<TextNoteEvent>(),
|
||||||
forkingFrom = forkedFromNote?.toEventHint<TextNoteEvent>(),
|
forkingFrom = forkedFromNote?.toEventHint<TextNoteEvent>(),
|
||||||
) {
|
) {
|
||||||
tagger.pTags?.let { notify(it.map { it.toPTag() }) }
|
tagger.pTags?.let { pTagList -> notify(pTagList.map { it.toPTag() }) }
|
||||||
|
|
||||||
hashtags(findHashtags(tagger.message))
|
hashtags(findHashtags(tagger.message))
|
||||||
references(findURLs(tagger.message))
|
references(findURLs(tagger.message))
|
||||||
@@ -619,9 +617,9 @@ open class ShortNotePostViewModel :
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (results.allGood) {
|
if (results.allGood) {
|
||||||
results.successful.forEach {
|
results.successful.forEach { state ->
|
||||||
if (it.result is UploadOrchestrator.OrchestratorResult.NIP95Result) {
|
if (state.result is UploadOrchestrator.OrchestratorResult.NIP95Result) {
|
||||||
account?.createNip95(it.result.bytes, headerInfo = it.result.fileHeader, alt, contentWarningReason) { nip95 ->
|
account?.createNip95(state.result.bytes, headerInfo = state.result.fileHeader, alt, contentWarningReason) { nip95 ->
|
||||||
nip95attachments = nip95attachments + nip95
|
nip95attachments = nip95attachments + nip95
|
||||||
val note = nip95.let { it1 -> account?.consumeNip95(it1.first, it1.second) }
|
val note = nip95.let { it1 -> account?.consumeNip95(it1.first, it1.second) }
|
||||||
|
|
||||||
@@ -630,20 +628,20 @@ open class ShortNotePostViewModel :
|
|||||||
urlPreviews.update(message)
|
urlPreviews.update(message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (it.result is UploadOrchestrator.OrchestratorResult.ServerResult) {
|
} else if (state.result is UploadOrchestrator.OrchestratorResult.ServerResult) {
|
||||||
val iMeta =
|
val iMeta =
|
||||||
IMetaTagBuilder(it.result.url)
|
IMetaTagBuilder(state.result.url)
|
||||||
.apply {
|
.apply {
|
||||||
hash(it.result.fileHeader.hash)
|
hash(state.result.fileHeader.hash)
|
||||||
size(it.result.fileHeader.size)
|
size(state.result.fileHeader.size)
|
||||||
it.result.fileHeader.mimeType
|
state.result.fileHeader.mimeType
|
||||||
?.let { mimeType(it) }
|
?.let { mimeType(it) }
|
||||||
it.result.fileHeader.dim
|
state.result.fileHeader.dim
|
||||||
?.let { dims(it) }
|
?.let { dims(it) }
|
||||||
it.result.fileHeader.blurHash
|
state.result.fileHeader.blurHash
|
||||||
?.let { blurhash(it.blurhash) }
|
?.let { blurhash(it.blurhash) }
|
||||||
it.result.magnet?.let { magnet(it) }
|
state.result.magnet?.let { magnet(it) }
|
||||||
it.result.uploadedHash?.let { originalHash(it) }
|
state.result.uploadedHash?.let { originalHash(it) }
|
||||||
|
|
||||||
alt?.let { alt(it) }
|
alt?.let { alt(it) }
|
||||||
contentWarningReason?.let { sensitiveContent(contentWarningReason) }
|
contentWarningReason?.let { sensitiveContent(contentWarningReason) }
|
||||||
@@ -651,7 +649,7 @@ open class ShortNotePostViewModel :
|
|||||||
|
|
||||||
iMetaAttachments.replace(iMeta.url, iMeta)
|
iMetaAttachments.replace(iMeta.url, iMeta)
|
||||||
|
|
||||||
message = message.insertUrlAtCursor(it.result.url)
|
message = message.insertUrlAtCursor(state.result.url)
|
||||||
urlPreviews.update(message)
|
urlPreviews.update(message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -677,7 +675,7 @@ open class ShortNotePostViewModel :
|
|||||||
pTags = null
|
pTags = null
|
||||||
|
|
||||||
wantsPoll = false
|
wantsPoll = false
|
||||||
zapRecipients = mutableStateListOf<HexKey>()
|
zapRecipients = mutableStateListOf()
|
||||||
pollOptions = newStateMapPollOptions()
|
pollOptions = newStateMapPollOptions()
|
||||||
valueMaximum = null
|
valueMaximum = null
|
||||||
valueMinimum = null
|
valueMinimum = null
|
||||||
@@ -685,7 +683,7 @@ open class ShortNotePostViewModel :
|
|||||||
closedAt = null
|
closedAt = null
|
||||||
|
|
||||||
wantsInvoice = false
|
wantsInvoice = false
|
||||||
wantsZapraiser = false
|
wantsZapRaiser = false
|
||||||
zapRaiserAmount.value = null
|
zapRaiserAmount.value = null
|
||||||
|
|
||||||
wantsForwardZapTo = false
|
wantsForwardZapTo = false
|
||||||
@@ -706,21 +704,9 @@ open class ShortNotePostViewModel :
|
|||||||
|
|
||||||
emojiSuggestions?.reset()
|
emojiSuggestions?.reset()
|
||||||
|
|
||||||
showRelaysDialog = false
|
|
||||||
|
|
||||||
reloadRelaySet()
|
|
||||||
|
|
||||||
draftTag.rotate()
|
draftTag.rotate()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reloadRelaySet() {
|
|
||||||
val account = accountViewModel?.account ?: return
|
|
||||||
|
|
||||||
relayList =
|
|
||||||
account.outboxRelays.flow.value
|
|
||||||
.toImmutableList()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteMediaToUpload(selected: SelectedMediaProcessing) {
|
fun deleteMediaToUpload(selected: SelectedMediaProcessing) {
|
||||||
this.multiOrchestrator?.remove(selected)
|
this.multiOrchestrator?.remove(selected)
|
||||||
}
|
}
|
||||||
@@ -733,8 +719,8 @@ open class ShortNotePostViewModel :
|
|||||||
updateMessage(TextFieldValue(message.text + " " + it))
|
updateMessage(TextFieldValue(message.text + " " + it))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateMessage(it: TextFieldValue) {
|
override fun updateMessage(newMessage: TextFieldValue) {
|
||||||
message = it
|
message = newMessage
|
||||||
urlPreviews.update(message)
|
urlPreviews.update(message)
|
||||||
|
|
||||||
if (message.selection.collapsed) {
|
if (message.selection.collapsed) {
|
||||||
@@ -793,8 +779,12 @@ open class ShortNotePostViewModel :
|
|||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
iMetaAttachments.downloadAndPrepare(
|
iMetaAttachments.downloadAndPrepare(
|
||||||
item.link.url,
|
item.link.url,
|
||||||
{ Amethyst.instance.okHttpClients.getHttpClient(accountViewModel?.account?.shouldUseTorForImageDownload(item.link.url) ?: false) },
|
) {
|
||||||
)
|
Amethyst.instance.okHttpClients.getHttpClient(
|
||||||
|
accountViewModel?.account?.shouldUseTorForImageDownload(item.link.url)
|
||||||
|
?: false,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
message = message.replaceCurrentWord(wordToInsert)
|
message = message.replaceCurrentWord(wordToInsert)
|
||||||
@@ -811,13 +801,13 @@ open class ShortNotePostViewModel :
|
|||||||
message.text.isNotBlank() &&
|
message.text.isNotBlank() &&
|
||||||
!isUploadingImage &&
|
!isUploadingImage &&
|
||||||
!wantsInvoice &&
|
!wantsInvoice &&
|
||||||
(!wantsZapraiser || zapRaiserAmount.value != null) &&
|
(!wantsZapRaiser || zapRaiserAmount.value != null) &&
|
||||||
(
|
(
|
||||||
!wantsPoll ||
|
!wantsPoll ||
|
||||||
(
|
(
|
||||||
pollOptions.values.all { it.isNotEmpty() } &&
|
pollOptions.values.all { it.isNotEmpty() } &&
|
||||||
isValidvalueMinimum.value &&
|
isValidValueMinimum.value &&
|
||||||
isValidvalueMaximum.value
|
isValidValueMaximum.value
|
||||||
)
|
)
|
||||||
) &&
|
) &&
|
||||||
multiOrchestrator == null
|
multiOrchestrator == null
|
||||||
@@ -857,11 +847,11 @@ open class ShortNotePostViewModel :
|
|||||||
|
|
||||||
fun checkMinMax() {
|
fun checkMinMax() {
|
||||||
if ((valueMinimum ?: 0) > (valueMaximum ?: Long.MAX_VALUE)) {
|
if ((valueMinimum ?: 0) > (valueMaximum ?: Long.MAX_VALUE)) {
|
||||||
isValidvalueMinimum.value = false
|
isValidValueMinimum.value = false
|
||||||
isValidvalueMaximum.value = false
|
isValidValueMaximum.value = false
|
||||||
} else {
|
} else {
|
||||||
isValidvalueMinimum.value = true
|
isValidValueMinimum.value = true
|
||||||
isValidvalueMaximum.value = true
|
isValidValueMaximum.value = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -237,18 +237,18 @@ class NostrClient(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun sendIfExists(
|
fun sendIfExists(
|
||||||
signedEvent: Event,
|
event: Event,
|
||||||
connectedRelay: NormalizedRelayUrl,
|
connectedRelay: NormalizedRelayUrl,
|
||||||
) {
|
) {
|
||||||
relayPool.getRelay(connectedRelay)?.send(signedEvent)
|
relayPool.getRelay(connectedRelay)?.send(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun send(
|
fun send(
|
||||||
signedEvent: Event,
|
event: Event,
|
||||||
relayList: Set<NormalizedRelayUrl>,
|
relayList: Set<NormalizedRelayUrl>,
|
||||||
) {
|
) {
|
||||||
eventOutbox.markAsSending(signedEvent, relayList)
|
eventOutbox.markAsSending(event, relayList)
|
||||||
relayPool.send(signedEvent, relayList)
|
relayPool.send(event, relayList)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun close(subscriptionId: String) {
|
fun close(subscriptionId: String) {
|
||||||
|
|||||||
Reference in New Issue
Block a user