Compare commits

..

1 Commits

Author SHA1 Message Date
shenlong-tanwen c97108329e fix: use setRequireOriginal on SDK 29 and above 2026-06-14 07:33:56 +05:30
4 changed files with 34 additions and 12 deletions
@@ -2,6 +2,7 @@ package app.alextran.immich.sync
import android.content.ContentResolver
import android.content.Context
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.MediaStore
@@ -10,6 +11,7 @@ import androidx.annotation.RequiresExtension
import kotlinx.coroutines.currentCoroutineContext
import kotlinx.coroutines.ensureActive
import kotlinx.serialization.json.Json
import java.io.InputStream
@RequiresApi(Build.VERSION_CODES.Q)
@RequiresExtension(extension = Build.VERSION_CODES.R, version = 1)
@@ -124,4 +126,12 @@ class NativeSyncApiImpl30(context: Context) : NativeSyncApiImplBase(context), Na
return result.mapValues { it.value.toList() }
}
override fun openOriginalStream(uri: Uri): InputStream? {
return try {
ctx.contentResolver.openInputStream(MediaStore.setRequireOriginal(uri))
} catch (_: Exception) {
super.openOriginalStream(uri)
}
}
}
@@ -4,7 +4,7 @@ import android.annotation.SuppressLint
import android.content.ContentUris
import android.content.Context
import android.database.Cursor
import androidx.exifinterface.media.ExifInterface
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.ext.SdkExtensions
@@ -30,6 +30,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withPermit
import java.io.File
import java.io.InputStream
import java.security.MessageDigest
import kotlin.coroutines.cancellation.CancellationException
@@ -275,7 +276,7 @@ open class NativeSyncApiImplBase(context: Context) : ImmichPlugin(), ActivityAwa
} catch (e: Exception) {
Log.w(TAG, "Failed to parse image header for asset $assetId", e)
}
// if mimeType is webp but not animated, its just an image.
// if mimeType is webp but not animated, it's just an image.
return PlatformAssetPlaybackStyle.IMAGE
}
@@ -377,7 +378,11 @@ open class NativeSyncApiImplBase(context: Context) : ImmichPlugin(), ActivityAwa
)?.use { cursor -> cursor.count.toLong() } ?: 0L
fun getAssetsForAlbum(albumId: String, updatedTimeCond: Long?, callback: (Result<List<PlatformAsset>>) -> Unit) {
fun getAssetsForAlbum(
albumId: String,
updatedTimeCond: Long?,
callback: (Result<List<PlatformAsset>>) -> Unit
) {
runSync(callback) { getAssetsForAlbum(albumId, updatedTimeCond) }
}
@@ -419,7 +424,7 @@ open class NativeSyncApiImplBase(context: Context) : ImmichPlugin(), ActivityAwa
}.awaitAll()
completeWhenActive(callback, Result.success(results))
} catch (e: CancellationException) {
} catch (_: CancellationException) {
completeWhenActive(
callback, Result.failure(
FlutterError(
@@ -435,6 +440,10 @@ open class NativeSyncApiImplBase(context: Context) : ImmichPlugin(), ActivityAwa
}
}
protected open fun openOriginalStream(uri: Uri): InputStream? {
return ctx.contentResolver.openInputStream(uri)
}
private suspend fun hashAsset(assetId: String): HashResult {
return try {
val assetUri = ContentUris.withAppendedId(
@@ -443,7 +452,7 @@ open class NativeSyncApiImplBase(context: Context) : ImmichPlugin(), ActivityAwa
)
val digest = MessageDigest.getInstance("SHA-1")
ctx.contentResolver.openInputStream(assetUri)?.use { inputStream ->
openOriginalStream(assetUri)?.use { inputStream ->
var bytesRead: Int
val buffer = ByteArray(HASH_BUFFER_SIZE)
while (inputStream.read(buffer).also { bytesRead = it } > 0) {
@@ -476,8 +485,11 @@ open class NativeSyncApiImplBase(context: Context) : ImmichPlugin(), ActivityAwa
syncJob = CoroutineScope(Dispatchers.IO).launch {
try {
completeWhenActive(callback, Result.success(work()))
} catch (e: CancellationException) {
completeWhenActive(callback, Result.failure(FlutterError(SYNC_CANCELLED_CODE, "Sync cancelled", null)))
} catch (_: CancellationException) {
completeWhenActive(
callback,
Result.failure(FlutterError(SYNC_CANCELLED_CODE, "Sync cancelled", null))
)
} catch (e: Exception) {
completeWhenActive(callback, Result.failure(e))
}
+4 -4
View File
@@ -261,6 +261,10 @@
/>
{/if}
{#if show.brokenAsset}
<BrokenAsset class="absolute size-full text-xl" />
{/if}
{#if show.preview}
<ImageLayer
{adaptiveImageLoader}
@@ -286,10 +290,6 @@
{/if}
</div>
{#if show.brokenAsset}
<BrokenAsset class="absolute inset-0 z-10 size-full text-xl" />
{/if}
{#if overlays}
<div class="pointer-events-none absolute inset-0">
{@render overlays()}
@@ -44,7 +44,7 @@ class AssetViewerManager extends BaseEventManager<Events> {
imageLoaderStatus = $state<ImageLoaderStatus | undefined>();
#isImageLoading = $derived.by(() => {
const quality = this.imageLoaderStatus?.quality;
if (!quality || this.imageLoaderStatus?.hasError) {
if (!quality) {
return false;
}
const previewOrOriginalReady = quality.preview === 'success' || quality.original === 'success';