mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-08-08 06:46:11 +00:00
Route oversize send failure to the active conversation
Addresses review feedback: the size-cap error was posted to the main mesh timeline, so a user sending from a private chat or channel never saw it. rejectIfOversized now posts to the private conversation (addPrivateMessageNoUnread) or channel (addChannelMessage) the send originated from, falling back to the main timeline for public sends. Adds regression tests for both routings.
This commit is contained in:
parent
c3bc911bcd
commit
0721c39f89
@ -82,18 +82,42 @@ class MediaSendingManager(
|
||||
private var pendingAutomaticTimeoutRequestId: String? = null
|
||||
|
||||
/**
|
||||
* Enforce the send-size cap with a user-visible failure.
|
||||
* Returns true if the file is oversized and the send was aborted.
|
||||
* Enforce the send-size cap with a user-visible failure posted to the
|
||||
* conversation the user is sending from. Returns true if the file is
|
||||
* oversized and the send was aborted.
|
||||
*/
|
||||
private fun rejectIfOversized(file: java.io.File): Boolean {
|
||||
private fun rejectIfOversized(
|
||||
file: java.io.File,
|
||||
toPeerIDOrNull: String?,
|
||||
channelOrNull: String?
|
||||
): Boolean {
|
||||
val size = file.length()
|
||||
if (size <= MAX_FILE_SIZE) return false
|
||||
Log.e(TAG, "❌ File too large: $size bytes (max: $MAX_FILE_SIZE)")
|
||||
val sizeMb = size / (1024 * 1024)
|
||||
val maxMb = MAX_FILE_SIZE / (1024 * 1024)
|
||||
messageManager.addSystemMessage(
|
||||
"cannot send ${file.name}: file is too large (${sizeMb} MB, max $maxMb MB)"
|
||||
)
|
||||
val text = "cannot send ${file.name}: file is too large (${sizeMb} MB, max $maxMb MB)"
|
||||
when {
|
||||
toPeerIDOrNull != null -> {
|
||||
val sys = BitchatMessage(
|
||||
sender = "system",
|
||||
content = text,
|
||||
timestamp = Date(),
|
||||
isRelay = false
|
||||
)
|
||||
messageManager.addPrivateMessageNoUnread(toPeerIDOrNull, sys)
|
||||
}
|
||||
channelOrNull != null -> {
|
||||
val sys = BitchatMessage(
|
||||
sender = "system",
|
||||
content = text,
|
||||
timestamp = Date(),
|
||||
isRelay = false
|
||||
)
|
||||
messageManager.addChannelMessage(channelOrNull, sys)
|
||||
}
|
||||
else -> messageManager.addSystemMessage(text)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@ -119,7 +143,7 @@ class MediaSendingManager(
|
||||
return@withContext null
|
||||
}
|
||||
|
||||
if (rejectIfOversized(file)) {
|
||||
if (rejectIfOversized(file, toPeerIDOrNull, channelOrNull)) {
|
||||
return@withContext null
|
||||
}
|
||||
|
||||
@ -163,7 +187,7 @@ class MediaSendingManager(
|
||||
return@withContext null
|
||||
}
|
||||
|
||||
if (rejectIfOversized(file)) {
|
||||
if (rejectIfOversized(file, toPeerIDOrNull, channelOrNull)) {
|
||||
return@withContext null
|
||||
}
|
||||
|
||||
@ -207,7 +231,7 @@ class MediaSendingManager(
|
||||
return@withContext null
|
||||
}
|
||||
|
||||
if (rejectIfOversized(file)) {
|
||||
if (rejectIfOversized(file, toPeerIDOrNull, channelOrNull)) {
|
||||
return@withContext null
|
||||
}
|
||||
|
||||
|
||||
@ -287,6 +287,43 @@ class MediaSendingManagerMigrationTest {
|
||||
assertTrue(messages.none { it.type == com.bitchat.android.model.BitchatMessageType.Image })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `oversized file failure is posted to the private conversation and nothing is sent`() {
|
||||
val bigFile = kotlin.io.path.createTempFile("oversized-private", ".jpg").toFile()
|
||||
try {
|
||||
bigFile.writeBytes(ByteArray(11 * 1024 * 1024) { 0x42 })
|
||||
|
||||
manager.sendImageNote(peerID, null, bigFile.absolutePath)
|
||||
|
||||
val messages = state.privateChats.value[peerID].orEmpty()
|
||||
assertEquals(1, messages.size)
|
||||
assertTrue(messages.single().content.contains("too large"))
|
||||
assertTrue(messages.none { it.type == com.bitchat.android.model.BitchatMessageType.Image })
|
||||
assertTrue(state.getMessagesValue().none { it.content.contains("too large") })
|
||||
verify(mesh, never()).prepareFilePrivate(any(), any(), any(), any())
|
||||
} finally {
|
||||
bigFile.delete()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `oversized file failure is posted to the channel and nothing is sent`() {
|
||||
val bigFile = kotlin.io.path.createTempFile("oversized-channel", ".jpg").toFile()
|
||||
try {
|
||||
bigFile.writeBytes(ByteArray(11 * 1024 * 1024) { 0x42 })
|
||||
|
||||
manager.sendImageNote(null, "#test", bigFile.absolutePath)
|
||||
|
||||
val channelMessages = state.getChannelMessagesValue()["#test"].orEmpty()
|
||||
assertEquals(1, channelMessages.size)
|
||||
assertTrue(channelMessages.single().content.contains("too large"))
|
||||
assertTrue(state.getMessagesValue().none { it.content.contains("too large") })
|
||||
verify(mesh, never()).prepareFilePrivate(any(), any(), any(), any())
|
||||
} finally {
|
||||
bigFile.delete()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `cancelled consent cannot later send or echo`() {
|
||||
whenever(mesh.prepareFilePrivate(eq(peerID), any(), any(), eq(false)))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user