mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-10-11 10:23:00 +02:00
add relay selection to nip 94 and 95 uploads
This commit is contained in:
@@ -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]
|
||||||
|
@@ -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
|
||||||
|
@@ -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()
|
||||||
|
@@ -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 = {
|
||||||
|
@@ -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
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user