diff --git a/CHANGELOG.md b/CHANGELOG.md
index efd64b454..4c460ab9e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,7 +1,12 @@
+
+# [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
+
# [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.
# [Release v1.07.3: GIF Keyboard](https://github.com/vitorpamplona/amethyst/releases/tag/v1.07.3) - 2026-03-31
diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/EditPostViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/EditPostViewModel.kt
index 4219ce80d..ec1d6db0a 100644
--- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/EditPostViewModel.kt
+++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/EditPostViewModel.kt
@@ -205,47 +205,50 @@ open class EditPostViewModel : ViewModel() {
)
if (results.allGood) {
- results.successful.forEach { state ->
- if (state.result is UploadOrchestrator.OrchestratorResult.NIP95Result) {
- val nip95 =
- myAccount.createNip95(
- byteArray = state.result.bytes,
- headerInfo = state.result.fileHeader,
- alt = alt,
- contentWarningReason = if (sensitiveContent) "" else null,
- )
- nip95attachments = nip95attachments + nip95
- val note = nip95.let { it1 -> account.consumeNip95(it1.first, it1.second) }
+ val urls =
+ results.successful.mapNotNull { state ->
+ if (state.result is UploadOrchestrator.OrchestratorResult.NIP95Result) {
+ val nip95 =
+ myAccount.createNip95(
+ byteArray = state.result.bytes,
+ headerInfo = state.result.fileHeader,
+ alt = alt,
+ contentWarningReason = if (sensitiveContent) "" else null,
+ )
+ nip95attachments = nip95attachments + nip95
+ val note = nip95.let { it1 -> account.consumeNip95(it1.first, it1.second) }
- note?.let {
- message = message.insertUrlAtCursor("nostr:" + it.toNEvent())
+ note?.let {
+ "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
} else {
diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/nip22Comments/CommentPostViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/nip22Comments/CommentPostViewModel.kt
index ca54a47cb..2e5b91c9a 100644
--- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/nip22Comments/CommentPostViewModel.kt
+++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/nip22Comments/CommentPostViewModel.kt
@@ -521,41 +521,45 @@ open class CommentPostViewModel :
)
if (results.allGood) {
- results.successful.forEach { state ->
- if (state.result is UploadOrchestrator.OrchestratorResult.NIP95Result) {
- val nip95 = account.createNip95(state.result.bytes, headerInfo = state.result.fileHeader, alt, contentWarningReason)
- nip95attachments = nip95attachments + nip95
- val note = nip95.let { it1 -> account.consumeNip95(it1.first, it1.second) }
+ val urls =
+ results.successful.mapNotNull { state ->
+ if (state.result is UploadOrchestrator.OrchestratorResult.NIP95Result) {
+ val nip95 = account.createNip95(state.result.bytes, headerInfo = state.result.fileHeader, alt, contentWarningReason)
+ nip95attachments = nip95attachments + nip95
+ val note = nip95.let { it1 -> account.consumeNip95(it1.first, it1.second) }
- note?.let {
- message.insertUrlAtCursor("nostr:" + it.toNEvent())
- urlPreviews.update(message.text.toString())
+ note?.let {
+ "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) }
+ 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
} else {
diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/send/ChannelNewMessageViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/send/ChannelNewMessageViewModel.kt
index 317262c9e..7c2434977 100644
--- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/send/ChannelNewMessageViewModel.kt
+++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/send/ChannelNewMessageViewModel.kt
@@ -360,24 +360,25 @@ open class ChannelNewMessageViewModel :
)
if (results.allGood) {
- results.successful.forEach { upload ->
- if (upload.result is UploadOrchestrator.OrchestratorResult.NIP95Result) {
- val nip95 = account.createNip95(upload.result.bytes, headerInfo = upload.result.fileHeader, uploadState.caption, uploadState.contentWarningReason)
- nip95attachments = nip95attachments + nip95
- val note = nip95.let { it1 -> account.consumeNip95(it1.first, it1.second) }
+ val urls =
+ results.successful.mapNotNull { upload ->
+ if (upload.result is UploadOrchestrator.OrchestratorResult.NIP95Result) {
+ val nip95 = account.createNip95(upload.result.bytes, headerInfo = upload.result.fileHeader, uploadState.caption, uploadState.contentWarningReason)
+ nip95attachments = nip95attachments + nip95
+ val note = nip95.let { it1 -> account.consumeNip95(it1.first, it1.second) }
- note?.let {
- message.insertUrlAtCursor(it.toNostrUri())
+ note?.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()
onceUploaded()
diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip23LongForm/LongFormPostViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip23LongForm/LongFormPostViewModel.kt
index 87bf53a07..1e0dd2324 100644
--- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip23LongForm/LongFormPostViewModel.kt
+++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip23LongForm/LongFormPostViewModel.kt
@@ -519,31 +519,36 @@ class LongFormPostViewModel :
)
if (results.allGood) {
- results.successful.forEach { state ->
- 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()
+ val urls =
+ results.successful.mapNotNull { state ->
+ 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)
+ iMetaAttachments.replace(iMeta.url, iMeta)
- val markdownImage = ""
- message.insertUrlAtCursor(markdownImage)
+ val markdownImage = ""
+ markdownImage
+ } else {
+ null
+ }
}
- }
+
+ message.insertUrlAtCursor(urls.joinToString(" "))
multiOrchestrator = null
} else {
diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip99Classifieds/NewProductViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip99Classifieds/NewProductViewModel.kt
index 392024de8..c49d58960 100644
--- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip99Classifieds/NewProductViewModel.kt
+++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip99Classifieds/NewProductViewModel.kt
@@ -421,30 +421,35 @@ open class NewProductViewModel :
)
if (results.allGood) {
- results.successful.forEach {
- if (it.result is UploadOrchestrator.OrchestratorResult.ServerResult) {
- if (it.result.fileHeader.mimeType
- ?.startsWith("image") == true
- ) {
- productImages = productImages +
- ProductImageMeta(
- it.result.url,
- it.result.fileHeader.mimeType,
- it.result.fileHeader.blurHash
- ?.blurhash,
- it.result.fileHeader.dim,
- alt,
- it.result.fileHeader.hash,
- it.result.fileHeader.size,
- )
- } else {
- iMetaDescription.add(it.result, alt, contentWarningReason)
+ val urls =
+ results.successful.mapNotNull {
+ if (it.result is UploadOrchestrator.OrchestratorResult.ServerResult) {
+ if (it.result.fileHeader.mimeType
+ ?.startsWith("image") == true
+ ) {
+ productImages = productImages +
+ ProductImageMeta(
+ it.result.url,
+ it.result.fileHeader.mimeType,
+ it.result.fileHeader.blurHash
+ ?.blurhash,
+ it.result.fileHeader.dim,
+ alt,
+ it.result.fileHeader.hash,
+ it.result.fileHeader.size,
+ )
+ } else {
+ iMetaDescription.add(it.result, alt, contentWarningReason)
- message.insertUrlAtCursor(it.result.url)
- urlPreviews.update(message.text.toString())
+ it.result.url
+ }
+ } else {
+ null
}
}
- }
+
+ message.insertUrlAtCursor(urls.joinToString(" "))
+ urlPreviews.update(message.text.toString())
multiOrchestrator = null
} else {
diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/ShortNotePostViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/ShortNotePostViewModel.kt
index 71e8bacab..6adf94284 100644
--- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/ShortNotePostViewModel.kt
+++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/ShortNotePostViewModel.kt
@@ -996,41 +996,45 @@ open class ShortNotePostViewModel :
)
if (results.allGood) {
- results.successful.forEach { state ->
- if (state.result is UploadOrchestrator.OrchestratorResult.NIP95Result) {
- val nip95 = account.createNip95(state.result.bytes, headerInfo = state.result.fileHeader, alt, contentWarningReason)
- nip95attachments = nip95attachments + nip95
- val note = nip95.let { it1 -> account.consumeNip95(it1.first, it1.second) }
+ val urls =
+ results.successful.mapNotNull { state ->
+ if (state.result is UploadOrchestrator.OrchestratorResult.NIP95Result) {
+ val nip95 = account.createNip95(state.result.bytes, headerInfo = state.result.fileHeader, alt, contentWarningReason)
+ nip95attachments = nip95attachments + nip95
+ val note = nip95.let { it1 -> account.consumeNip95(it1.first, it1.second) }
- note?.let {
- message.insertUrlAtCursor("nostr:" + it.toNEvent())
- urlPreviews.update(message.text.toString())
+ note?.let {
+ "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) }
+ 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
} else {
diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/publicMessages/NewPublicMessageViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/publicMessages/NewPublicMessageViewModel.kt
index 09cd8f47e..bf88579e0 100644
--- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/publicMessages/NewPublicMessageViewModel.kt
+++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/publicMessages/NewPublicMessageViewModel.kt
@@ -464,41 +464,45 @@ class NewPublicMessageViewModel :
)
if (results.allGood) {
- results.successful.forEach { state ->
- if (state.result is UploadOrchestrator.OrchestratorResult.NIP95Result) {
- val nip95 = account.createNip95(state.result.bytes, headerInfo = state.result.fileHeader, alt, contentWarningReason)
- nip95attachments = nip95attachments + nip95
- val note = nip95.let { it1 -> account.consumeNip95(it1.first, it1.second) }
+ val urls =
+ results.successful.mapNotNull { state ->
+ if (state.result is UploadOrchestrator.OrchestratorResult.NIP95Result) {
+ val nip95 = account.createNip95(state.result.bytes, headerInfo = state.result.fileHeader, alt, contentWarningReason)
+ nip95attachments = nip95attachments + nip95
+ val note = nip95.let { it1 -> account.consumeNip95(it1.first, it1.second) }
- note?.let {
- message.insertUrlAtCursor("nostr:" + it.toNEvent())
- urlPreviews.update(message.text.toString())
+ note?.let {
+ "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) }
+ 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
} else {