fix: Prevent crash when sending a post while media is uploading (#923)

Previous code used `filterIsInstance<Ok<UploadEvent.FinishedEvent>>()`.

This can fail at runtime with class cast exception because the type in
`Ok<...>` is erased so `filterIsInstance` was accepting any `Ok`
`Result`. Later attempts to operate on it as a `.FinishedEvent`
generated the run time error.

Fix that by explicitly checking the type of the `Ok` result in `first`
instead.
This commit is contained in:
Nik Clayton 2024-09-03 13:05:33 +02:00 committed by GitHub
parent c90445364b
commit 69b87a3c44
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 7 additions and 3 deletions

View File

@ -42,6 +42,7 @@ import app.pachli.util.getMediaSize
import com.github.michaelbull.result.Err import com.github.michaelbull.result.Err
import com.github.michaelbull.result.Ok import com.github.michaelbull.result.Ok
import com.github.michaelbull.result.Result import com.github.michaelbull.result.Result
import com.github.michaelbull.result.get
import com.github.michaelbull.result.mapEither import com.github.michaelbull.result.mapEither
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import java.io.File import java.io.File
@ -56,7 +57,6 @@ import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flow
@ -233,8 +233,12 @@ class MediaUploader @Inject constructor(
suspend fun getMediaUploadState(localId: Int): Result<UploadEvent.FinishedEvent, MediaUploaderError> { suspend fun getMediaUploadState(localId: Int): Result<UploadEvent.FinishedEvent, MediaUploaderError> {
return uploads[localId]?.flow return uploads[localId]?.flow
?.filterIsInstance<Ok<UploadEvent.FinishedEvent>>() // Can't use filterIsInstance<Ok<UploadEvent.FinishedEvent>> here because the type
?.first() // inside Ok<...> is erased, so the first Ok<_> result is returned, crashing with a
// class cast error if it's a ProgressEvent.
// Kotlin doesn't warn about this, see
// https://discuss.kotlinlang.org/t/is-as-operators-are-unsafe-for-reified-types/22470
?.first { it.get() is UploadEvent.FinishedEvent } as? Ok<UploadEvent.FinishedEvent>
?: Err(MediaUploaderError.UploadIdNotFoundError(localId)) ?: Err(MediaUploaderError.UploadIdNotFoundError(localId))
} }