diff --git a/app/src/main/java/com/nextcloud/client/jobs/gallery/GalleryImageGenerationJob.kt b/app/src/main/java/com/nextcloud/client/jobs/gallery/GalleryImageGenerationJob.kt index 5ca2202ea0aa..f71b33b9c44b 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/gallery/GalleryImageGenerationJob.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/gallery/GalleryImageGenerationJob.kt @@ -9,16 +9,13 @@ package com.nextcloud.client.jobs.gallery import android.graphics.Bitmap import android.graphics.Point -import android.media.ThumbnailUtils -import android.os.Build -import android.provider.MediaStore -import android.util.Size import android.view.WindowManager import android.widget.ImageView import androidx.core.content.ContextCompat import com.nextcloud.client.account.User +import com.nextcloud.utils.LocalThumbnailGenerator import com.nextcloud.utils.extensions.isPNG -import com.nextcloud.utils.extensions.toFile +import com.nextcloud.utils.extensions.setMediaThumbnail import com.owncloud.android.MainApp import com.owncloud.android.R import com.owncloud.android.datamodel.FileDataStorageManager @@ -117,26 +114,38 @@ class GalleryImageGenerationJob(private val user: User, private val storageManag return@withContext applyVideoOverlayIfNeeded(file, cached) } - onNewThumbnail() - if (file.isDown) { val local = decodeLocalThumbnail(file) if (local != null) { ThumbnailsCacheManager.addBitmapToCache(cacheKey, local) + onNewThumbnail() return@withContext applyVideoOverlayIfNeeded(file, local) } } val remote = semaphore.withPermit { fetchFromServer(file) } if (remote != null) { + onNewThumbnail() return@withContext applyVideoOverlayIfNeeded(file, remote) } + val sharedThumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache( + ThumbnailsCacheManager.PREFIX_THUMBNAIL + file.remoteId + ) + if (sharedThumbnail != null) { + return@withContext applyVideoOverlayIfNeeded(file, sharedThumbnail) + } + null } private fun decodeLocalThumbnail(file: OCFile): Bitmap? = if (MimeTypeUtil.isVideo(file)) { - createVideoThumbnail(file.storagePath) + LocalThumbnailGenerator.createThumbnail( + file.storagePath, + ThumbnailsCacheManager.getThumbnailDimension(), + ThumbnailsCacheManager.getThumbnailDimension(), + file.mimeType + ) } else { createImageThumbnail(file) } @@ -163,22 +172,6 @@ class GalleryImageGenerationJob(private val user: User, private val storageManag return thumbnail } - private fun createVideoThumbnail(storagePath: String): Bitmap? { - val ioFile = storagePath.toFile() ?: return null - val size = ThumbnailsCacheManager.getThumbnailDimension() - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - try { - ThumbnailUtils.createVideoThumbnail(ioFile, Size(size, size), null) - } catch (e: Exception) { - Log_OC.e(TAG, "Failed to create video thumbnail from local file: ${e.message}") - null - } - } else { - @Suppress("DEPRECATION") - ThumbnailUtils.createVideoThumbnail(storagePath, MediaStore.Images.Thumbnails.MINI_KIND) - } - } - private suspend fun fetchFromServer(file: OCFile): Bitmap? = try { val client = withContext(Dispatchers.IO) { OwnCloudClientManagerFactory.getDefaultSingleton() @@ -216,7 +209,7 @@ class GalleryImageGenerationJob(private val user: User, private val storageManag if (newImage) listener.onNewGalleryImage() if (imageView.isAttachedToWindow) { - imageView.setImageBitmap(bitmap) + imageView.setMediaThumbnail(bitmap) imageView.invalidate() } } diff --git a/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt b/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt index ca8c9144e351..8c1776900051 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt @@ -51,7 +51,6 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.ensureActive import kotlinx.coroutines.withContext -import java.io.File import java.util.concurrent.ConcurrentHashMap import kotlin.random.Random @@ -396,22 +395,18 @@ class FileUploadWorker( var result: RemoteOperationResult try { - val storageManager = operation.storageManager fileUploadEventBroadcaster.sendUploadStarted(operation, context) result = operation.execute(client) - - // only generate a thumbnail if the upload actually succeeded - if (result.isSuccess) { - val task = ThumbnailsCacheManager.ThumbnailGenerationTask(storageManager, user) - val file = File(operation.originalStoragePath) - val remoteId: String? = operation.file.remoteId - task.execute(ThumbnailsCacheManager.ThumbnailGenerationTaskObject(file, remoteId)) - } } catch (e: Exception) { Log_OC.e(TAG, "Error uploading", e) result = RemoteOperationResult(e) } + // only generate a thumbnail if the upload actually succeeded + if (result.isSuccess) { + generateThumbnailFromSourceFile(operation, user) + } + if (!isStopped) { UploadErrorNotificationManager.handleResult( context, @@ -436,6 +431,12 @@ class FileUploadWorker( return@withContext result } + private fun generateThumbnailFromSourceFile(operation: UploadFileOperation, user: User) { + val sourceFile = operation.originalStoragePath.toFile() ?: return + val task = ThumbnailsCacheManager.ThumbnailGenerationTask(operation.storageManager, user) + task.execute(ThumbnailsCacheManager.ThumbnailGenerationTaskObject(sourceFile, operation.file.remoteId)) + } + @Suppress("MagicNumber") private val minProgressUpdateInterval = 750 private var lastUpdateTime = 0L diff --git a/app/src/main/java/com/nextcloud/utils/LocalThumbnailGenerator.kt b/app/src/main/java/com/nextcloud/utils/LocalThumbnailGenerator.kt new file mode 100644 index 000000000000..c4afd5d50960 --- /dev/null +++ b/app/src/main/java/com/nextcloud/utils/LocalThumbnailGenerator.kt @@ -0,0 +1,82 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2026 Alper Ozturk = Build.VERSION_CODES.Q) { + ThumbnailUtils.createVideoThumbnail(file, Size(pxW, pxH), null) + } else { + @Suppress("DEPRECATION") + ThumbnailUtils.createVideoThumbnail(file.absolutePath, MediaStore.Images.Thumbnails.MINI_KIND) + } + } catch (e: Exception) { + Log_OC.d(TAG, "ThumbnailUtils could not decode ${file.name}: ${e.message}") + null + } + + private fun createWithMetadataRetriever(file: File, pxW: Int, pxH: Int): Bitmap? { + val retriever = MediaMetadataRetriever() + + return try { + retriever.setDataSource(file.absolutePath) + retriever.getFrameAtTime(LAST_FRAME)?.scaleDown(pxW, pxH) + } catch (e: Exception) { + Log_OC.e(TAG, "MediaMetadataRetriever could not decode ${file.name}", e) + null + } finally { + try { + retriever.release() + } catch (e: Exception) { + Log_OC.w(TAG, "Failed to release MediaMetadataRetriever: ${e.message}") + } + } + } + + private fun Bitmap.scaleDown(pxW: Int, pxH: Int): Bitmap { + val longestSide = maxOf(width, height) + val limit = maxOf(pxW, pxH) + + return if (longestSide > limit) { + BitmapUtils.scaleBitmap(this, limit.toFloat(), width, height, longestSide) + } else { + this + } + } +} diff --git a/app/src/main/java/com/nextcloud/utils/OCFileUtils.kt b/app/src/main/java/com/nextcloud/utils/OCFileUtils.kt index d16ea8eef159..3797f8fefcb3 100644 --- a/app/src/main/java/com/nextcloud/utils/OCFileUtils.kt +++ b/app/src/main/java/com/nextcloud/utils/OCFileUtils.kt @@ -7,18 +7,15 @@ package com.nextcloud.utils import android.graphics.Color -import android.graphics.drawable.BitmapDrawable -import androidx.core.content.ContextCompat -import androidx.core.graphics.drawable.toBitmap +import android.graphics.drawable.Drawable import androidx.core.graphics.drawable.toDrawable import com.nextcloud.utils.extensions.getBitmapSize import com.nextcloud.utils.extensions.getExifSize import com.owncloud.android.MainApp -import com.owncloud.android.R import com.owncloud.android.datamodel.OCFile import com.owncloud.android.lib.common.utils.Log_OC -import com.owncloud.android.utils.BitmapUtils import com.owncloud.android.utils.MimeTypeUtil +import com.owncloud.android.utils.theme.ViewThemeUtils @Suppress("TooGenericExceptionCaught", "ReturnCount") object OCFileUtils { @@ -56,27 +53,10 @@ object OCFileUtils { return fallbackPair } - fun getMediaPlaceholder(file: OCFile, imageDimension: Pair): BitmapDrawable { + fun getMediaPlaceholder(file: OCFile, viewThemeUtils: ViewThemeUtils): Drawable { val context = MainApp.getAppContext() - val drawableId = if (MimeTypeUtil.isImage(file)) { - R.drawable.file_image - } else if (MimeTypeUtil.isVideo(file)) { - R.drawable.file_movie - } else { - R.drawable.file - } - - val drawable = ContextCompat.getDrawable(context, drawableId) - ?: return Color.GRAY.toDrawable().toBitmap(imageDimension.first, imageDimension.second) - .toDrawable(context.resources) - - val bitmap = BitmapUtils.drawableToBitmap( - drawable, - imageDimension.first, - imageDimension.second - ) - - return bitmap.toDrawable(context.resources) + return MimeTypeUtil.getFileTypeIcon(file.mimeType, file.fileName, context, viewThemeUtils) + ?: Color.GRAY.toDrawable() } } diff --git a/app/src/main/java/com/nextcloud/utils/extensions/ImageViewExtensions.kt b/app/src/main/java/com/nextcloud/utils/extensions/ImageViewExtensions.kt index 896d26dca84e..3f2e08ff272c 100644 --- a/app/src/main/java/com/nextcloud/utils/extensions/ImageViewExtensions.kt +++ b/app/src/main/java/com/nextcloud/utils/extensions/ImageViewExtensions.kt @@ -8,6 +8,7 @@ package com.nextcloud.utils.extensions import android.content.Context +import android.graphics.Bitmap import android.graphics.drawable.GradientDrawable import android.util.TypedValue import android.view.ViewOutlineProvider @@ -15,7 +16,23 @@ import android.widget.ImageView import androidx.annotation.ColorInt import androidx.annotation.DrawableRes import androidx.core.content.ContextCompat +import com.nextcloud.utils.OCFileUtils import com.owncloud.android.R +import com.owncloud.android.datamodel.OCFile +import com.owncloud.android.utils.theme.ViewThemeUtils + +fun ImageView.setMediaPlaceholder(file: OCFile, viewThemeUtils: ViewThemeUtils) { + scaleType = ImageView.ScaleType.FIT_CENTER + val padding = resources.getDimensionPixelSize(R.dimen.standard_padding) + setPadding(padding, padding, padding, padding) + setImageDrawable(OCFileUtils.getMediaPlaceholder(file, viewThemeUtils)) +} + +fun ImageView.setMediaThumbnail(bitmap: Bitmap) { + scaleType = ImageView.ScaleType.CENTER_CROP + setPadding(0, 0, 0, 0) + setImageBitmap(bitmap) +} @JvmOverloads fun ImageView.makeRoundedWithIcon( diff --git a/app/src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java b/app/src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java index 66b215e733dc..628070e96d6c 100644 --- a/app/src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java +++ b/app/src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java @@ -23,11 +23,9 @@ import android.graphics.RectF; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; -import android.media.MediaMetadataRetriever; import android.media.ThumbnailUtils; import android.net.Uri; import android.os.AsyncTask; -import android.provider.MediaStore; import android.text.TextUtils; import android.view.Display; import android.view.View; @@ -38,6 +36,7 @@ import com.nextcloud.client.account.User; import com.nextcloud.client.network.ConnectivityService; import com.nextcloud.utils.BitmapExtensionsKt; +import com.nextcloud.utils.LocalThumbnailGenerator; import com.nextcloud.utils.extensions.OCFileExtensionsKt; import com.nextcloud.utils.extensions.OwnCloudClientExtensionsKt; import com.owncloud.android.MainApp; @@ -212,6 +211,16 @@ public static Bitmap addThumbnailToCache(String imageKey, Bitmap bitmap, String return thumbnail; } + @Nullable + public static Bitmap getCachedMediaBitmap(ServerFileInterface file) { + final Bitmap resizedImage = getBitmapFromDiskCache(PREFIX_RESIZED_IMAGE + file.getRemoteId()); + if (resizedImage != null) { + return resizedImage; + } + + return getBitmapFromDiskCache(PREFIX_THUMBNAIL + file.getRemoteId()); + } + public static void removeFromCache(@Nullable OCFile file) { if (file == null) { return; @@ -601,13 +610,10 @@ private Bitmap doThumbnailFromOCFileInBackground() { if (file instanceof OCFile ocFile && ocFile.isDown()) { Log_OC.d(TAG, "Generating thumbnail from local file: " + ocFile.getFileName()); - Bitmap bitmap; - if (MimeTypeUtil.isVideo(ocFile)) { - bitmap = ThumbnailUtils.createVideoThumbnail(ocFile.getStoragePath(), - MediaStore.Images.Thumbnails.MINI_KIND); - } else { - bitmap = BitmapUtils.decodeSampledBitmapFromFile(ocFile.getStoragePath(), pxW, pxH); - } + Bitmap bitmap = LocalThumbnailGenerator.createThumbnail(ocFile.getStoragePath(), + pxW, + pxH, + ocFile.getMimeType()); if (bitmap != null) { if (PNG_MIMETYPE.equalsIgnoreCase(ocFile.getMimeType())) { @@ -715,10 +721,9 @@ private int getThumbnailDimension() { private Bitmap doFileInBackground() { File file = (File)mFile; - final String imageKey = Objects.requireNonNullElseGet(mImageKey, () -> String.valueOf(file.hashCode())); - - // local file should always generate a thumbnail - mImageKey = PREFIX_THUMBNAIL + mImageKey; + final String imageKey = PREFIX_THUMBNAIL + + Objects.requireNonNullElseGet(mImageKey, () -> String.valueOf(file.hashCode())); + mImageKey = imageKey; // Check disk cache in background thread Bitmap thumbnail = getBitmapFromDiskCache(imageKey); @@ -729,7 +734,7 @@ private Bitmap doFileInBackground() { int pxH; pxW = pxH = getThumbnailDimension(); - Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(file.getAbsolutePath(), pxW, pxH); + Bitmap bitmap = LocalThumbnailGenerator.createThumbnail(file.getAbsolutePath(), pxW, pxH); if (bitmap != null) { thumbnail = addThumbnailToCache(imageKey, bitmap, file.getPath(), pxW, pxH); @@ -749,8 +754,6 @@ public static class MediaThumbnailGenerationTask extends AsyncTask mImageViewReference; private File mFile; private String mImageKey; @@ -777,10 +780,8 @@ protected Bitmap doInBackground(Object... params) { mImageKey = (String) params[1]; } - if (MimeTypeUtil.isImage(mFile)) { - thumbnail = doFileInBackground(mFile, Type.IMAGE); - } else if (MimeTypeUtil.isVideo(mFile)) { - thumbnail = doFileInBackground(mFile, Type.VIDEO); + if (MimeTypeUtil.isImageOrVideo(mFile)) { + thumbnail = doFileInBackground(mFile); } } } // the app should never break due to a problem with thumbnails @@ -826,63 +827,25 @@ protected void onPostExecute(Bitmap bitmap) { } } - private Bitmap doFileInBackground(File file, Type type) { - final String imageKey = Objects.requireNonNullElseGet(mImageKey, () -> String.valueOf(file.hashCode())); + private Bitmap doFileInBackground(File file) { + final String imageKey = PREFIX_THUMBNAIL + + Objects.requireNonNullElseGet(mImageKey, () -> String.valueOf(file.hashCode())); // Check disk cache in background thread Bitmap thumbnail = getBitmapFromDiskCache(imageKey); // Not found in disk cache if (thumbnail == null) { + int px = getThumbnailDimension(); + Bitmap bitmap = LocalThumbnailGenerator.createThumbnail(file.getAbsolutePath(), px, px); - if (Type.IMAGE == type) { - int px = getThumbnailDimension(); - - Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(file.getAbsolutePath(), px, px); - - if (bitmap != null) { - thumbnail = addThumbnailToCache(imageKey, bitmap, file.getPath(), px, px); - } - } else if (Type.VIDEO == type) { - thumbnail = getThumbnailFromMediaRetriever(file); - if (thumbnail != null) { - // Scale down bitmap if too large. - int px = getThumbnailDimension(); - int width = thumbnail.getWidth(); - int height = thumbnail.getHeight(); - int max = Math.max(width, height); - if (max > px) { - thumbnail = BitmapUtils.scaleBitmap(thumbnail, px, width, height, max); - thumbnail = addThumbnailToCache(imageKey, thumbnail, file.getPath(), px, px); - } - } + if (bitmap != null) { + thumbnail = addThumbnailToCache(imageKey, bitmap, file.getPath(), px, px); } } return thumbnail; } - - private Bitmap getThumbnailFromMediaRetriever(File file) { - if (file == null || !file.exists()) { - Log_OC.w(TAG, "Cannot extract thumbnail: file is null or does not exist"); - return null; - } - - var retriever = new MediaMetadataRetriever(); - try { - retriever.setDataSource(file.getAbsolutePath()); - return retriever.getFrameAtTime(-1); - } catch (Throwable t) { - Log_OC.w(TAG, "Failed to create bitmap from video " + file.getAbsolutePath()); - return null; - } finally { - try { - retriever.release(); - } catch (Throwable t) { - Log_OC.w(TAG, "Failed to release retriever"); - } - } - } } public static class AvatarGenerationTask extends AsyncTask { diff --git a/app/src/main/java/com/owncloud/android/ui/adapter/GalleryRowHolder.kt b/app/src/main/java/com/owncloud/android/ui/adapter/GalleryRowHolder.kt index fead84f34822..6886ba16ec2e 100644 --- a/app/src/main/java/com/owncloud/android/ui/adapter/GalleryRowHolder.kt +++ b/app/src/main/java/com/owncloud/android/ui/adapter/GalleryRowHolder.kt @@ -19,6 +19,7 @@ import com.elyeproj.loaderviewlibrary.LoaderImageView import com.nextcloud.android.common.ui.theme.utils.ColorRole import com.nextcloud.utils.OCFileUtils import com.nextcloud.utils.extensions.makeRounded +import com.nextcloud.utils.extensions.setMediaPlaceholder import com.nextcloud.utils.extensions.setVisibleIf import com.owncloud.android.R import com.owncloud.android.databinding.GalleryRowBinding @@ -104,12 +105,10 @@ class GalleryRowHolder( layoutParams = FrameLayout.LayoutParams(width, height) } - val drawable = OCFileUtils.getMediaPlaceholder(file, width to height) val rowCellImageView = ImageView(context).apply { - setImageDrawable(drawable) adjustViewBounds = true - scaleType = ImageView.ScaleType.CENTER_CROP layoutParams = FrameLayout.LayoutParams(width, height) + setMediaPlaceholder(file, viewThemeUtils) } return FrameLayout(context).apply { @@ -163,7 +162,7 @@ class GalleryRowHolder( adjustRowCell(thumbnail, isChecked) adjustCheckBox(checkbox, isChecked) - ocFileListDelegate.bindGalleryRow(shimmer, thumbnail, file, this, dims) + ocFileListDelegate.bindGalleryRow(shimmer, thumbnail, file, this) val endMargin = if (index < row.files.size - 1) smallMargin else zero thumbnail.layoutParams = FrameLayout.LayoutParams(width, height).apply { diff --git a/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListDelegate.kt b/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListDelegate.kt index d871787a4d96..9d820dff9052 100644 --- a/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListDelegate.kt +++ b/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListDelegate.kt @@ -19,8 +19,9 @@ import com.nextcloud.client.jobs.gallery.GalleryImageGenerationJob import com.nextcloud.client.jobs.gallery.GalleryImageGenerationListener import com.nextcloud.client.jobs.upload.FileUploadHelper import com.nextcloud.client.preferences.AppPreferences -import com.nextcloud.utils.OCFileUtils import com.nextcloud.utils.extensions.makeRounded +import com.nextcloud.utils.extensions.setMediaPlaceholder +import com.nextcloud.utils.extensions.setMediaThumbnail import com.nextcloud.utils.extensions.setVisibleIf import com.nextcloud.utils.mdm.MDMConfig import com.owncloud.android.R @@ -104,8 +105,7 @@ class OCFileListDelegate( shimmer: LoaderImageView?, imageView: ImageView, file: OCFile, - galleryRowHolder: GalleryRowHolder, - imageDimension: Pair + galleryRowHolder: GalleryRowHolder ) { // Cancel previous job for this ImageView GalleryImageGenerationJob.cancelPreviousJob(imageView) @@ -113,17 +113,16 @@ class OCFileListDelegate( imageView.tag = file.fileId // set placeholder before async job - val cacheKey = ThumbnailsCacheManager.PREFIX_RESIZED_IMAGE + file.remoteId - val cachedBitmap = ThumbnailsCacheManager.getBitmapFromDiskCache(cacheKey) + val cachedBitmap = ThumbnailsCacheManager.getCachedMediaBitmap(file) if (cachedBitmap != null) { val overlay = if (MimeTypeUtil.isVideo(file)) { ThumbnailsCacheManager.addVideoOverlay(cachedBitmap, context) } else { cachedBitmap } - imageView.setImageBitmap(overlay) + imageView.setMediaThumbnail(overlay) } else { - imageView.setImageDrawable(OCFileUtils.getMediaPlaceholder(file, imageDimension)) + imageView.setMediaPlaceholder(file, viewThemeUtils) } val job = ioScope.launch { diff --git a/app/src/main/java/com/owncloud/android/ui/adapter/ReceiveExternalFilesAdapter.kt b/app/src/main/java/com/owncloud/android/ui/adapter/ReceiveExternalFilesAdapter.kt index cbac02172939..314ae5c7fcf4 100644 --- a/app/src/main/java/com/owncloud/android/ui/adapter/ReceiveExternalFilesAdapter.kt +++ b/app/src/main/java/com/owncloud/android/ui/adapter/ReceiveExternalFilesAdapter.kt @@ -123,7 +123,8 @@ class ReceiveExternalFilesAdapter( @Suppress("NestedBlockDepth") private fun setupThumbnailForImage(thumbnailImageView: ImageView, file: OCFile) { - var thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(file.remoteId.toString()) + val cacheKey = ThumbnailsCacheManager.PREFIX_THUMBNAIL + file.remoteId + var thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(cacheKey) if (thumbnail != null && !file.isUpdateThumbnailNeeded) { thumbnailImageView.setImageBitmap(thumbnail) } else { diff --git a/app/src/main/java/com/owncloud/android/ui/adapter/uploadList/UploadListAdapter.kt b/app/src/main/java/com/owncloud/android/ui/adapter/uploadList/UploadListAdapter.kt index c218bea7d16b..3becb96eaef5 100644 --- a/app/src/main/java/com/owncloud/android/ui/adapter/uploadList/UploadListAdapter.kt +++ b/app/src/main/java/com/owncloud/android/ui/adapter/uploadList/UploadListAdapter.kt @@ -520,7 +520,7 @@ class UploadListAdapter( fakeFile: OCFile, allowedToCreateNewThumbnail: Boolean ) { - val cacheKey = fakeFile.remoteId.toString() + val cacheKey = ThumbnailsCacheManager.PREFIX_THUMBNAIL + fakeFile.remoteId var thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(cacheKey) if (thumbnail != null && !fakeFile.isUpdateThumbnailNeeded) { @@ -552,7 +552,8 @@ class UploadListAdapter( private fun bindLocalThumbnail(holder: ItemViewHolder, item: OCUpload, allowedToCreateNewThumbnail: Boolean) { val file = File(item.localPath) - val thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(file.hashCode().toString()) + val cacheKey = ThumbnailsCacheManager.PREFIX_THUMBNAIL + file.hashCode() + val thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(cacheKey) if (thumbnail != null) { holder.binding.thumbnail.setImageBitmap(thumbnail)