diff --git a/app/src/main/java/chat/rocket/android/chatroom/presentation/ChatRoomPresenter.kt b/app/src/main/java/chat/rocket/android/chatroom/presentation/ChatRoomPresenter.kt index 9923afe1be..66bff22a26 100644 --- a/app/src/main/java/chat/rocket/android/chatroom/presentation/ChatRoomPresenter.kt +++ b/app/src/main/java/chat/rocket/android/chatroom/presentation/ChatRoomPresenter.kt @@ -89,6 +89,7 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.threeten.bp.Instant import timber.log.Timber +import java.io.InvalidObjectException import java.util.* import javax.inject.Inject @@ -475,7 +476,7 @@ class ChatRoomPresenter @Inject constructor( view.showInvalidFileMessage() } else { val byteArray = - bitmap.getByteArray(mimeType, 100, settings.uploadMaxFileSize()) + bitmap.getByteArray(mimeType, 60, settings.uploadMaxFileSize()) retryIO("uploadFile($roomId, $fileName, $mimeType") { client.uploadFile( roomId, @@ -495,6 +496,7 @@ class ChatRoomPresenter @Inject constructor( Timber.d(ex, "Error uploading image") when (ex) { is RocketChatException -> view.showMessage(ex) + is InvalidObjectException -> view.showInvalidFileSize(bitmap.getByteCount(), settings.uploadMaxFileSize()) else -> view.showGenericErrorMessage() } } finally { diff --git a/util/src/main/java/chat/rocket/android/util/extension/Image.kt b/util/src/main/java/chat/rocket/android/util/extension/Image.kt index 5d2fca6cd8..516dfc8d25 100644 --- a/util/src/main/java/chat/rocket/android/util/extension/Image.kt +++ b/util/src/main/java/chat/rocket/android/util/extension/Image.kt @@ -8,11 +8,7 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentActivity import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -import java.io.ByteArrayInputStream -import java.io.ByteArrayOutputStream -import java.io.InputStream -import java.io.IOException -import java.io.File +import java.io.* import java.text.SimpleDateFormat import java.util.* @@ -37,13 +33,14 @@ suspend fun Bitmap.compressImageAndGetInputStream(mimeType: String): InputStream return inputStream } + /** * Returns a [ByteArray] of a [Bitmap]. * * @param mimeType The MIME type of the [Bitmap]. * @param quality The quality of the [Bitmap] for the resulting [ByteArray]. * @param maxFileSizeAllowed The max file size allowed by the server. Note: The [quality] will be - * decreased minus 10 until the [ByteArray] size fits the [maxFileSizeAllowed] value. + * decreased minus 20 until the [ByteArray] size fits the [maxFileSizeAllowed] value. * @return A [ByteArray] of a [Bitmap] */ suspend fun Bitmap.getByteArray( @@ -55,7 +52,11 @@ suspend fun Bitmap.getByteArray( compressImageAndGetByteArray(mimeType, quality)?.let { if (it.size > maxFileSizeAllowed && maxFileSizeAllowed !in -1..0) { - getByteArray(mimeType, quality - 10, maxFileSizeAllowed) + if (quality == 0 || !mimeType.lossyCompressible()) { + throw InvalidObjectException ("File size too big.") + } + // call this method recursively with lower quality + byteArray = getByteArray(mimeType, quality - 20, maxFileSizeAllowed) } else { byteArray = it } @@ -96,6 +97,18 @@ fun String.getCompressFormat(): Bitmap.CompressFormat { } } +/** + * Returns true if lossy compressible format based on mimeType + */ +fun String.lossyCompressible(): Boolean { + return when { + this.contains("jpeg") -> true + this.contains("png") -> true + this.contains("webp") -> true + else -> false + } +} + fun Fragment.dispatchImageSelection(requestCode: Int) { val intent = Intent(Intent.ACTION_GET_CONTENT) intent.type = "image/*"