add relay selection to nip 94 and 95 uploads

This commit is contained in:
greenart7c3
2023-07-17 11:15:19 -03:00
parent 0d63441611
commit d730eeb9a1
5 changed files with 66 additions and 20 deletions

View File

@@ -628,19 +628,19 @@ class Account(
return Pair(data, signedEvent) return Pair(data, signedEvent)
} }
fun sendNip95(data: FileStorageEvent, signedEvent: FileStorageHeaderEvent): Note? { fun sendNip95(data: FileStorageEvent, signedEvent: FileStorageHeaderEvent, relayList: List<Relay>? = null): Note? {
if (!isWriteable()) return null if (!isWriteable()) return null
Client.send(data) Client.send(data, relayList = relayList)
LocalCache.consume(data, null) LocalCache.consume(data, null)
Client.send(signedEvent) Client.send(signedEvent, relayList = relayList)
LocalCache.consume(signedEvent, null) LocalCache.consume(signedEvent, null)
return LocalCache.notes[signedEvent.id] return LocalCache.notes[signedEvent.id]
} }
fun sendHeader(headerInfo: FileHeader): Note? { fun sendHeader(headerInfo: FileHeader, relayList: List<Relay>? = null): Note? {
if (!isWriteable()) return null if (!isWriteable()) return null
val signedEvent = FileHeaderEvent.create( val signedEvent = FileHeaderEvent.create(
@@ -655,7 +655,7 @@ class Account(
privateKey = loggedIn.privKey!! privateKey = loggedIn.privKey!!
) )
Client.send(signedEvent) Client.send(signedEvent, relayList = relayList)
LocalCache.consume(signedEvent, null) LocalCache.consume(signedEvent, null)
return LocalCache.notes[signedEvent.id] return LocalCache.notes[signedEvent.id]

View File

@@ -11,6 +11,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.vitorpamplona.amethyst.model.* import com.vitorpamplona.amethyst.model.*
import com.vitorpamplona.amethyst.service.FileHeader import com.vitorpamplona.amethyst.service.FileHeader
import com.vitorpamplona.amethyst.service.relays.Relay
import com.vitorpamplona.amethyst.ui.components.MediaCompressor import com.vitorpamplona.amethyst.ui.components.MediaCompressor
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
@@ -56,7 +57,7 @@ open class NewMediaModel : ViewModel() {
} }
} }
fun upload(context: Context) { fun upload(context: Context, relayList: List<Relay>? = null) {
isUploadingImage = true isUploadingImage = true
val contentResolver = context.contentResolver val contentResolver = context.contentResolver
@@ -78,7 +79,7 @@ open class NewMediaModel : ViewModel() {
uploadingPercentage.value = 0.2f uploadingPercentage.value = 0.2f
uploadingDescription.value = "Loading" uploadingDescription.value = "Loading"
contentResolver.openInputStream(fileUri)?.use { contentResolver.openInputStream(fileUri)?.use {
createNIP95Record(it.readBytes(), contentType, description, sensitiveContent) createNIP95Record(it.readBytes(), contentType, description, sensitiveContent, relayList = relayList)
} }
?: run { ?: run {
viewModelScope.launch { viewModelScope.launch {
@@ -98,7 +99,7 @@ open class NewMediaModel : ViewModel() {
server = serverToUse, server = serverToUse,
contentResolver = contentResolver, contentResolver = contentResolver,
onSuccess = { imageUrl, mimeType -> onSuccess = { imageUrl, mimeType ->
createNIP94Record(imageUrl, mimeType, description, sensitiveContent) createNIP94Record(imageUrl, mimeType, description, sensitiveContent, relayList = relayList)
}, },
onError = { onError = {
isUploadingImage = false isUploadingImage = false
@@ -138,7 +139,7 @@ open class NewMediaModel : ViewModel() {
return !isUploadingImage && galleryUri != null && selectedServer != null return !isUploadingImage && galleryUri != null && selectedServer != null
} }
fun createNIP94Record(imageUrl: String, mimeType: String?, description: String, sensitiveContent: Boolean) { fun createNIP94Record(imageUrl: String, mimeType: String?, description: String, sensitiveContent: Boolean, relayList: List<Relay>? = null) {
uploadingPercentage.value = 0.40f uploadingPercentage.value = 0.40f
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
uploadingDescription.value = "Server Processing" uploadingDescription.value = "Server Processing"
@@ -162,7 +163,7 @@ open class NewMediaModel : ViewModel() {
onReady = { onReady = {
uploadingPercentage.value = 0.90f uploadingPercentage.value = 0.90f
uploadingDescription.value = "Sending" uploadingDescription.value = "Sending"
account?.sendHeader(it) account?.sendHeader(it, relayList)
uploadingPercentage.value = 1.00f uploadingPercentage.value = 1.00f
isUploadingImage = false isUploadingImage = false
onceUploaded() onceUploaded()
@@ -191,7 +192,7 @@ open class NewMediaModel : ViewModel() {
} }
} }
fun createNIP95Record(bytes: ByteArray, mimeType: String?, description: String, sensitiveContent: Boolean) { fun createNIP95Record(bytes: ByteArray, mimeType: String?, description: String, sensitiveContent: Boolean, relayList: List<Relay>? = null) {
uploadingPercentage.value = 0.30f uploadingPercentage.value = 0.30f
uploadingDescription.value = "Hashing" uploadingDescription.value = "Hashing"
@@ -210,7 +211,7 @@ open class NewMediaModel : ViewModel() {
if (nip95 != null) { if (nip95 != null) {
uploadingDescription.value = "Sending" uploadingDescription.value = "Sending"
uploadingPercentage.value = 0.60f uploadingPercentage.value = 0.60f
account?.sendNip95(nip95.first, nip95.second) account?.sendNip95(nip95.first, nip95.second, relayList)
} }
uploadingPercentage.value = 1.00f uploadingPercentage.value = 1.00f

View File

@@ -7,17 +7,21 @@ import android.util.Size
import android.widget.Toast import android.widget.Toast
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
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.WindowInsets import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.rememberScrollState 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.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme import androidx.compose.material.MaterialTheme
import androidx.compose.material.OutlinedTextField import androidx.compose.material.OutlinedTextField
import androidx.compose.material.Surface import androidx.compose.material.Surface
@@ -33,6 +37,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.KeyboardCapitalization import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@@ -70,6 +75,17 @@ fun NewMediaView(uri: Uri, onClose: () -> Unit, postViewModel: NewMediaModel, ac
} }
} }
var showRelaysDialog by remember {
mutableStateOf(false)
}
var relayList = account.activeRelays()?.filter {
it.write
}?.map {
it
} ?: account.convertLocalRelays().filter {
it.write
}
Dialog( Dialog(
onDismissRequest = { onClose() }, onDismissRequest = { onClose() },
properties = DialogProperties( properties = DialogProperties(
@@ -82,6 +98,19 @@ fun NewMediaView(uri: Uri, onClose: () -> Unit, postViewModel: NewMediaModel, ac
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
) { ) {
if (showRelaysDialog) {
RelaySelectionDialog(
list = relayList,
onClose = {
showRelaysDialog = false
},
onPost = {
relayList = it
},
account = account
)
}
Column( Column(
modifier = Modifier.padding(start = 10.dp, end = 10.dp, top = 10.dp) modifier = Modifier.padding(start = 10.dp, end = 10.dp, top = 10.dp)
.fillMaxWidth() .fillMaxWidth()
@@ -97,10 +126,26 @@ fun NewMediaView(uri: Uri, onClose: () -> Unit, postViewModel: NewMediaModel, ac
onClose() onClose()
}) })
Box {
IconButton(
modifier = Modifier.align(Alignment.Center),
onClick = {
showRelaysDialog = true
}
) {
Icon(
painter = painterResource(R.drawable.relays),
contentDescription = null,
modifier = Modifier.height(25.dp),
tint = MaterialTheme.colors.onBackground
)
}
}
PostButton( PostButton(
onPost = { onPost = {
onClose() onClose()
postViewModel.upload(context) postViewModel.upload(context, relayList)
postViewModel.selectedServer?.let { account.changeDefaultFileServer(it) } postViewModel.selectedServer?.let { account.changeDefaultFileServer(it) }
}, },
isActive = postViewModel.canPost() isActive = postViewModel.canPost()

View File

@@ -300,7 +300,7 @@ fun NewPostView(onClose: () -> Unit, baseReplyTo: Note? = null, quote: Note? = n
url, url,
account.defaultFileServer, account.defaultFileServer,
onAdd = { description, server, sensitiveContent -> onAdd = { description, server, sensitiveContent ->
postViewModel.upload(url, description, sensitiveContent, server, context) postViewModel.upload(url, description, sensitiveContent, server, context, relayList)
account.changeDefaultFileServer(server) account.changeDefaultFileServer(server)
}, },
onCancel = { onCancel = {

View File

@@ -194,7 +194,7 @@ open class NewPostViewModel() : ViewModel() {
cancel() cancel()
} }
fun upload(galleryUri: Uri, description: String, sensitiveContent: Boolean, server: ServersAvailable, context: Context) { fun upload(galleryUri: Uri, description: String, sensitiveContent: Boolean, server: ServersAvailable, context: Context, relayList: List<Relay>? = null) {
isUploadingImage = true isUploadingImage = true
contentToAddUrl = null contentToAddUrl = null
@@ -209,7 +209,7 @@ open class NewPostViewModel() : ViewModel() {
onReady = { fileUri, contentType, size -> onReady = { fileUri, contentType, size ->
if (server == ServersAvailable.NIP95) { if (server == ServersAvailable.NIP95) {
contentResolver.openInputStream(fileUri)?.use { contentResolver.openInputStream(fileUri)?.use {
createNIP95Record(it.readBytes(), contentType, description, sensitiveContent) createNIP95Record(it.readBytes(), contentType, description, sensitiveContent, relayList = relayList)
} }
} else { } else {
ImageUploader.uploadImage( ImageUploader.uploadImage(
@@ -385,7 +385,7 @@ open class NewPostViewModel() : ViewModel() {
} }
} }
fun createNIP94Record(imageUrl: String, mimeType: String?, description: String, sensitiveContent: Boolean) { fun createNIP94Record(imageUrl: String, mimeType: String?, description: String, sensitiveContent: Boolean, relayList: List<Relay>? = null) {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
// Images don't seem to be ready immediately after upload // Images don't seem to be ready immediately after upload
FileHeader.prepare( FileHeader.prepare(
@@ -394,7 +394,7 @@ open class NewPostViewModel() : ViewModel() {
description, description,
sensitiveContent, sensitiveContent,
onReady = { onReady = {
val note = account?.sendHeader(it) val note = account?.sendHeader(it, relayList = relayList)
isUploadingImage = false isUploadingImage = false
@@ -416,7 +416,7 @@ open class NewPostViewModel() : ViewModel() {
} }
} }
fun createNIP95Record(bytes: ByteArray, mimeType: String?, description: String, sensitiveContent: Boolean) { fun createNIP95Record(bytes: ByteArray, mimeType: String?, description: String, sensitiveContent: Boolean, relayList: List<Relay>? = null) {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
FileHeader.prepare( FileHeader.prepare(
bytes, bytes,
@@ -426,7 +426,7 @@ open class NewPostViewModel() : ViewModel() {
sensitiveContent, sensitiveContent,
onReady = { onReady = {
val nip95 = account?.createNip95(bytes, headerInfo = it) val nip95 = account?.createNip95(bytes, headerInfo = it)
val note = nip95?.let { it1 -> account?.sendNip95(it1.first, it1.second) } val note = nip95?.let { it1 -> account?.sendNip95(it1.first, it1.second, relayList = relayList) }
isUploadingImage = false isUploadingImage = false