Fixes image uploading crash

This commit is contained in:
Vitor Pamplona
2026-03-31 20:17:14 -04:00
parent 5cd83bbaa4
commit 9b2fbcbf56
8 changed files with 224 additions and 193 deletions
+6 -1
View File
@@ -1,7 +1,12 @@
<a id="v1.07.5"></a>
# [Release v1.07.5: Image upload fix](https://github.com/vitorpamplona/amethyst/releases/tag/v1.07.5) - 2026-03-31
- Fixes Image uploads crashing the app
<a id="v1.07.4"></a> <a id="v1.07.4"></a>
# [Release v1.07.4: NWC fix](https://github.com/vitorpamplona/amethyst/releases/tag/v1.07.4) - 2026-03-31 # [Release v1.07.4: NWC fix](https://github.com/vitorpamplona/amethyst/releases/tag/v1.07.4) - 2026-03-31
- Fixes Nostr wallet connect receiving the secret. - Fixes Nostr wallet connect receiving the secret.
<a id="v1.07.3"></a> <a id="v1.07.3"></a>
# [Release v1.07.3: GIF Keyboard](https://github.com/vitorpamplona/amethyst/releases/tag/v1.07.3) - 2026-03-31 # [Release v1.07.3: GIF Keyboard](https://github.com/vitorpamplona/amethyst/releases/tag/v1.07.3) - 2026-03-31
@@ -205,47 +205,50 @@ open class EditPostViewModel : ViewModel() {
) )
if (results.allGood) { if (results.allGood) {
results.successful.forEach { state -> val urls =
if (state.result is UploadOrchestrator.OrchestratorResult.NIP95Result) { results.successful.mapNotNull { state ->
val nip95 = if (state.result is UploadOrchestrator.OrchestratorResult.NIP95Result) {
myAccount.createNip95( val nip95 =
byteArray = state.result.bytes, myAccount.createNip95(
headerInfo = state.result.fileHeader, byteArray = state.result.bytes,
alt = alt, headerInfo = state.result.fileHeader,
contentWarningReason = if (sensitiveContent) "" else null, alt = alt,
) contentWarningReason = if (sensitiveContent) "" else null,
nip95attachments = nip95attachments + nip95 )
val note = nip95.let { it1 -> account.consumeNip95(it1.first, it1.second) } nip95attachments = nip95attachments + nip95
val note = nip95.let { it1 -> account.consumeNip95(it1.first, it1.second) }
note?.let { note?.let {
message = message.insertUrlAtCursor("nostr:" + it.toNEvent()) "nostr:" + it.toNEvent()
}
} else if (state.result is UploadOrchestrator.OrchestratorResult.ServerResult) {
val iMeta =
IMetaTagBuilder(state.result.url)
.apply {
hash(state.result.fileHeader.hash)
size(state.result.fileHeader.size)
state.result.fileHeader.mimeType
?.let { mimeType(it) }
state.result.fileHeader.dim
?.let { dims(it) }
state.result.fileHeader.blurHash
?.let { blurhash(it.blurhash) }
state.result.magnet?.let { magnet(it) }
state.result.uploadedHash?.let { originalHash(it) }
alt?.let { alt(it) }
if (sensitiveContent) sensitiveContent("")
}.build()
iMetaAttachments = iMetaAttachments.filter { it.url != iMeta.url } + iMeta
state.result.url
} else {
null
} }
urlPreview = findUrlInMessage()
} else if (state.result is UploadOrchestrator.OrchestratorResult.ServerResult) {
val iMeta =
IMetaTagBuilder(state.result.url)
.apply {
hash(state.result.fileHeader.hash)
size(state.result.fileHeader.size)
state.result.fileHeader.mimeType
?.let { mimeType(it) }
state.result.fileHeader.dim
?.let { dims(it) }
state.result.fileHeader.blurHash
?.let { blurhash(it.blurhash) }
state.result.magnet?.let { magnet(it) }
state.result.uploadedHash?.let { originalHash(it) }
alt?.let { alt(it) }
if (sensitiveContent) sensitiveContent("")
}.build()
iMetaAttachments = iMetaAttachments.filter { it.url != iMeta.url } + iMeta
message = message.insertUrlAtCursor(state.result.url)
urlPreview = findUrlInMessage()
} }
}
message = message.insertUrlAtCursor(urls.joinToString(" "))
urlPreview = findUrlInMessage()
this@EditPostViewModel.multiOrchestrator = null this@EditPostViewModel.multiOrchestrator = null
} else { } else {
@@ -521,41 +521,45 @@ open class CommentPostViewModel :
) )
if (results.allGood) { if (results.allGood) {
results.successful.forEach { state -> val urls =
if (state.result is UploadOrchestrator.OrchestratorResult.NIP95Result) { results.successful.mapNotNull { state ->
val nip95 = account.createNip95(state.result.bytes, headerInfo = state.result.fileHeader, alt, contentWarningReason) if (state.result is UploadOrchestrator.OrchestratorResult.NIP95Result) {
nip95attachments = nip95attachments + nip95 val nip95 = account.createNip95(state.result.bytes, headerInfo = state.result.fileHeader, alt, contentWarningReason)
val note = nip95.let { it1 -> account.consumeNip95(it1.first, it1.second) } nip95attachments = nip95attachments + nip95
val note = nip95.let { it1 -> account.consumeNip95(it1.first, it1.second) }
note?.let { note?.let {
message.insertUrlAtCursor("nostr:" + it.toNEvent()) "nostr:" + it.toNEvent()
urlPreviews.update(message.text.toString()) }
} else if (state.result is UploadOrchestrator.OrchestratorResult.ServerResult) {
val iMeta =
IMetaTagBuilder(state.result.url)
.apply {
hash(state.result.fileHeader.hash)
size(state.result.fileHeader.size)
state.result.fileHeader.mimeType
?.let { mimeType(it) }
state.result.fileHeader.dim
?.let { dims(it) }
state.result.fileHeader.blurHash
?.let { blurhash(it.blurhash) }
state.result.magnet?.let { magnet(it) }
state.result.uploadedHash?.let { originalHash(it) }
alt?.let { alt(it) }
contentWarningReason?.let { sensitiveContent(contentWarningReason) }
}.build()
iMetaAttachments.replace(iMeta.url, iMeta)
state.result.url
} else {
null
} }
} else if (state.result is UploadOrchestrator.OrchestratorResult.ServerResult) {
val iMeta =
IMetaTagBuilder(state.result.url)
.apply {
hash(state.result.fileHeader.hash)
size(state.result.fileHeader.size)
state.result.fileHeader.mimeType
?.let { mimeType(it) }
state.result.fileHeader.dim
?.let { dims(it) }
state.result.fileHeader.blurHash
?.let { blurhash(it.blurhash) }
state.result.magnet?.let { magnet(it) }
state.result.uploadedHash?.let { originalHash(it) }
alt?.let { alt(it) }
contentWarningReason?.let { sensitiveContent(contentWarningReason) }
}.build()
iMetaAttachments.replace(iMeta.url, iMeta)
message.insertUrlAtCursor(state.result.url)
urlPreviews.update(message.text.toString())
} }
}
message.insertUrlAtCursor(urls.joinToString(" "))
urlPreviews.update(message.text.toString())
multiOrchestrator = null multiOrchestrator = null
} else { } else {
@@ -360,24 +360,25 @@ open class ChannelNewMessageViewModel :
) )
if (results.allGood) { if (results.allGood) {
results.successful.forEach { upload -> val urls =
if (upload.result is UploadOrchestrator.OrchestratorResult.NIP95Result) { results.successful.mapNotNull { upload ->
val nip95 = account.createNip95(upload.result.bytes, headerInfo = upload.result.fileHeader, uploadState.caption, uploadState.contentWarningReason) if (upload.result is UploadOrchestrator.OrchestratorResult.NIP95Result) {
nip95attachments = nip95attachments + nip95 val nip95 = account.createNip95(upload.result.bytes, headerInfo = upload.result.fileHeader, uploadState.caption, uploadState.contentWarningReason)
val note = nip95.let { it1 -> account.consumeNip95(it1.first, it1.second) } nip95attachments = nip95attachments + nip95
val note = nip95.let { it1 -> account.consumeNip95(it1.first, it1.second) }
note?.let { note?.toNostrUri()
message.insertUrlAtCursor(it.toNostrUri()) } else if (upload.result is UploadOrchestrator.OrchestratorResult.ServerResult) {
iMetaAttachments.add(upload.result, uploadState.caption, uploadState.contentWarningReason)
upload.result.url
} else {
null
} }
urlPreview = findUrlInMessage()
} else if (upload.result is UploadOrchestrator.OrchestratorResult.ServerResult) {
iMetaAttachments.add(upload.result, uploadState.caption, uploadState.contentWarningReason)
message.insertUrlAtCursor(upload.result.url)
urlPreview = findUrlInMessage()
} }
}
message.insertUrlAtCursor(urls.joinToString(" "))
urlPreview = findUrlInMessage()
uploadState.reset() uploadState.reset()
onceUploaded() onceUploaded()
@@ -519,31 +519,36 @@ class LongFormPostViewModel :
) )
if (results.allGood) { if (results.allGood) {
results.successful.forEach { state -> val urls =
if (state.result is UploadOrchestrator.OrchestratorResult.ServerResult) { results.successful.mapNotNull { state ->
val iMeta = if (state.result is UploadOrchestrator.OrchestratorResult.ServerResult) {
IMetaTagBuilder(state.result.url) val iMeta =
.apply { IMetaTagBuilder(state.result.url)
hash(state.result.fileHeader.hash) .apply {
size(state.result.fileHeader.size) hash(state.result.fileHeader.hash)
state.result.fileHeader.mimeType size(state.result.fileHeader.size)
?.let { mimeType(it) } state.result.fileHeader.mimeType
state.result.fileHeader.dim ?.let { mimeType(it) }
?.let { dims(it) } state.result.fileHeader.dim
state.result.fileHeader.blurHash ?.let { dims(it) }
?.let { blurhash(it.blurhash) } state.result.fileHeader.blurHash
state.result.magnet?.let { magnet(it) } ?.let { blurhash(it.blurhash) }
state.result.uploadedHash?.let { originalHash(it) } state.result.magnet?.let { magnet(it) }
alt?.let { alt(it) } state.result.uploadedHash?.let { originalHash(it) }
contentWarningReason?.let { sensitiveContent(contentWarningReason) } alt?.let { alt(it) }
}.build() contentWarningReason?.let { sensitiveContent(contentWarningReason) }
}.build()
iMetaAttachments.replace(iMeta.url, iMeta) iMetaAttachments.replace(iMeta.url, iMeta)
val markdownImage = "![${alt ?: ""}](${state.result.url})" val markdownImage = "![${alt ?: ""}](${state.result.url})"
message.insertUrlAtCursor(markdownImage) markdownImage
} else {
null
}
} }
}
message.insertUrlAtCursor(urls.joinToString(" "))
multiOrchestrator = null multiOrchestrator = null
} else { } else {
@@ -421,30 +421,35 @@ open class NewProductViewModel :
) )
if (results.allGood) { if (results.allGood) {
results.successful.forEach { val urls =
if (it.result is UploadOrchestrator.OrchestratorResult.ServerResult) { results.successful.mapNotNull {
if (it.result.fileHeader.mimeType if (it.result is UploadOrchestrator.OrchestratorResult.ServerResult) {
?.startsWith("image") == true if (it.result.fileHeader.mimeType
) { ?.startsWith("image") == true
productImages = productImages + ) {
ProductImageMeta( productImages = productImages +
it.result.url, ProductImageMeta(
it.result.fileHeader.mimeType, it.result.url,
it.result.fileHeader.blurHash it.result.fileHeader.mimeType,
?.blurhash, it.result.fileHeader.blurHash
it.result.fileHeader.dim, ?.blurhash,
alt, it.result.fileHeader.dim,
it.result.fileHeader.hash, alt,
it.result.fileHeader.size, it.result.fileHeader.hash,
) it.result.fileHeader.size,
} else { )
iMetaDescription.add(it.result, alt, contentWarningReason) } else {
iMetaDescription.add(it.result, alt, contentWarningReason)
message.insertUrlAtCursor(it.result.url) it.result.url
urlPreviews.update(message.text.toString()) }
} else {
null
} }
} }
}
message.insertUrlAtCursor(urls.joinToString(" "))
urlPreviews.update(message.text.toString())
multiOrchestrator = null multiOrchestrator = null
} else { } else {
@@ -996,41 +996,45 @@ open class ShortNotePostViewModel :
) )
if (results.allGood) { if (results.allGood) {
results.successful.forEach { state -> val urls =
if (state.result is UploadOrchestrator.OrchestratorResult.NIP95Result) { results.successful.mapNotNull { state ->
val nip95 = account.createNip95(state.result.bytes, headerInfo = state.result.fileHeader, alt, contentWarningReason) if (state.result is UploadOrchestrator.OrchestratorResult.NIP95Result) {
nip95attachments = nip95attachments + nip95 val nip95 = account.createNip95(state.result.bytes, headerInfo = state.result.fileHeader, alt, contentWarningReason)
val note = nip95.let { it1 -> account.consumeNip95(it1.first, it1.second) } nip95attachments = nip95attachments + nip95
val note = nip95.let { it1 -> account.consumeNip95(it1.first, it1.second) }
note?.let { note?.let {
message.insertUrlAtCursor("nostr:" + it.toNEvent()) "nostr:" + it.toNEvent()
urlPreviews.update(message.text.toString()) }
} else if (state.result is UploadOrchestrator.OrchestratorResult.ServerResult) {
val iMeta =
IMetaTagBuilder(state.result.url)
.apply {
hash(state.result.fileHeader.hash)
size(state.result.fileHeader.size)
state.result.fileHeader.mimeType
?.let { mimeType(it) }
state.result.fileHeader.dim
?.let { dims(it) }
state.result.fileHeader.blurHash
?.let { blurhash(it.blurhash) }
state.result.magnet?.let { magnet(it) }
state.result.uploadedHash?.let { originalHash(it) }
alt?.let { alt(it) }
contentWarningReason?.let { sensitiveContent(contentWarningReason) }
}.build()
iMetaAttachments.replace(iMeta.url, iMeta)
state.result.url
} else {
null
} }
} else if (state.result is UploadOrchestrator.OrchestratorResult.ServerResult) {
val iMeta =
IMetaTagBuilder(state.result.url)
.apply {
hash(state.result.fileHeader.hash)
size(state.result.fileHeader.size)
state.result.fileHeader.mimeType
?.let { mimeType(it) }
state.result.fileHeader.dim
?.let { dims(it) }
state.result.fileHeader.blurHash
?.let { blurhash(it.blurhash) }
state.result.magnet?.let { magnet(it) }
state.result.uploadedHash?.let { originalHash(it) }
alt?.let { alt(it) }
contentWarningReason?.let { sensitiveContent(contentWarningReason) }
}.build()
iMetaAttachments.replace(iMeta.url, iMeta)
message.insertUrlAtCursor(state.result.url)
urlPreviews.update(message.text.toString())
} }
}
message.insertUrlAtCursor(urls.joinToString(" "))
urlPreviews.update(message.text.toString())
multiOrchestrator = null multiOrchestrator = null
} else { } else {
@@ -464,41 +464,45 @@ class NewPublicMessageViewModel :
) )
if (results.allGood) { if (results.allGood) {
results.successful.forEach { state -> val urls =
if (state.result is UploadOrchestrator.OrchestratorResult.NIP95Result) { results.successful.mapNotNull { state ->
val nip95 = account.createNip95(state.result.bytes, headerInfo = state.result.fileHeader, alt, contentWarningReason) if (state.result is UploadOrchestrator.OrchestratorResult.NIP95Result) {
nip95attachments = nip95attachments + nip95 val nip95 = account.createNip95(state.result.bytes, headerInfo = state.result.fileHeader, alt, contentWarningReason)
val note = nip95.let { it1 -> account.consumeNip95(it1.first, it1.second) } nip95attachments = nip95attachments + nip95
val note = nip95.let { it1 -> account.consumeNip95(it1.first, it1.second) }
note?.let { note?.let {
message.insertUrlAtCursor("nostr:" + it.toNEvent()) "nostr:" + it.toNEvent()
urlPreviews.update(message.text.toString()) }
} else if (state.result is UploadOrchestrator.OrchestratorResult.ServerResult) {
val iMeta =
IMetaTagBuilder(state.result.url)
.apply {
hash(state.result.fileHeader.hash)
size(state.result.fileHeader.size)
state.result.fileHeader.mimeType
?.let { mimeType(it) }
state.result.fileHeader.dim
?.let { dims(it) }
state.result.fileHeader.blurHash
?.let { blurhash(it.blurhash) }
state.result.magnet?.let { magnet(it) }
state.result.uploadedHash?.let { originalHash(it) }
alt?.let { alt(it) }
contentWarningReason?.let { sensitiveContent(contentWarningReason) }
}.build()
iMetaAttachments.replace(iMeta.url, iMeta)
state.result.url
} else {
null
} }
} else if (state.result is UploadOrchestrator.OrchestratorResult.ServerResult) {
val iMeta =
IMetaTagBuilder(state.result.url)
.apply {
hash(state.result.fileHeader.hash)
size(state.result.fileHeader.size)
state.result.fileHeader.mimeType
?.let { mimeType(it) }
state.result.fileHeader.dim
?.let { dims(it) }
state.result.fileHeader.blurHash
?.let { blurhash(it.blurhash) }
state.result.magnet?.let { magnet(it) }
state.result.uploadedHash?.let { originalHash(it) }
alt?.let { alt(it) }
contentWarningReason?.let { sensitiveContent(contentWarningReason) }
}.build()
iMetaAttachments.replace(iMeta.url, iMeta)
message.insertUrlAtCursor(state.result.url)
urlPreviews.update(message.text.toString())
} }
}
message.insertUrlAtCursor(urls.joinToString(" "))
urlPreviews.update(message.text.toString())
multiOrchestrator = null multiOrchestrator = null
} else { } else {