Show error message when loading media fails

This commit is contained in:
Naveen Singh 2024-09-09 23:44:53 +05:30
parent cf000a6546
commit 642f0ccd06
No known key found for this signature in database
GPG key ID: 35F7D64346B28ED7
15 changed files with 152 additions and 32 deletions

View file

@ -309,6 +309,18 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen
mVideoSize.y = videoSize.height
setVideoSize()
}
override fun onPlayerErrorChanged(error: PlaybackException?) {
binding.errorMessageHolder.errorMessage.apply {
if (error != null) {
text = error.localizedMessage ?: getString(R.string.failed_to_load_media)
setTextColor(if (context.config.blackBackground) Color.WHITE else context.getProperTextColor())
fadeIn()
} else {
beGone()
}
}
}
})
}

View file

@ -11,8 +11,10 @@ import android.view.Menu
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.RelativeLayout
import androidx.annotation.RequiresApi
import androidx.appcompat.content.res.AppCompatResources
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
@ -820,14 +822,18 @@ class DirectoryAdapter(
}
activity.loadImage(
thumbnailType,
directory.tmb,
dirThumbnail,
scrollHorizontally,
animateGifs,
cropThumbnails,
roundedCorners,
directory.getKey()
type = thumbnailType,
path = directory.tmb,
target = dirThumbnail,
horizontalScroll = scrollHorizontally,
animateGifs = animateGifs,
cropThumbnails = cropThumbnails,
roundCorners = roundedCorners,
signature = directory.getKey(),
onError = {
dirThumbnail.scaleType = ImageView.ScaleType.CENTER
dirThumbnail.setImageDrawable(AppCompatResources.getDrawable(activity, R.drawable.ic_vector_warning_colored))
}
)
}

View file

@ -9,7 +9,9 @@ import android.os.Looper
import android.view.Menu
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.Toast
import androidx.appcompat.content.res.AppCompatResources
import androidx.core.view.allViews
import com.bumptech.glide.Glide
import com.qtalk.recyclerviewfastscroller.RecyclerViewFastScroller
@ -681,7 +683,19 @@ class MediaAdapter(
if (loadImageInstantly) {
activity.loadImage(
medium.type, path, mediumThumbnail, scrollHorizontally, animateGifs, cropThumbnails, roundedCorners, medium.getKey(), rotatedImagePaths
type = medium.type,
path = path,
target = mediumThumbnail,
horizontalScroll = scrollHorizontally,
animateGifs = animateGifs,
cropThumbnails = cropThumbnails,
roundCorners = roundedCorners,
signature = medium.getKey(),
skipMemoryCacheAtPaths = rotatedImagePaths,
onError = {
mediumThumbnail.scaleType = ImageView.ScaleType.CENTER
mediumThumbnail.setImageDrawable(AppCompatResources.getDrawable(activity, R.drawable.ic_vector_warning_colored))
}
)
} else {
mediumThumbnail.setImageDrawable(null)
@ -690,8 +704,19 @@ class MediaAdapter(
val isVisible = visibleItemPaths.contains(medium.path)
if (isVisible) {
activity.loadImage(
medium.type, path, mediumThumbnail, scrollHorizontally, animateGifs, cropThumbnails, roundedCorners,
medium.getKey(), rotatedImagePaths
type = medium.type,
path = path,
target = mediumThumbnail,
horizontalScroll = scrollHorizontally,
animateGifs = animateGifs,
cropThumbnails = cropThumbnails,
roundCorners = roundedCorners,
signature = medium.getKey(),
skipMemoryCacheAtPaths = rotatedImagePaths,
onError = {
mediumThumbnail.scaleType = ImageView.ScaleType.CENTER
mediumThumbnail.setImageDrawable(AppCompatResources.getDrawable(activity, R.drawable.ic_vector_warning_colored))
}
)
}
}, IMAGE_LOAD_DELAY)

View file

@ -482,13 +482,29 @@ fun Context.loadImage(
roundCorners: Int,
signature: ObjectKey,
skipMemoryCacheAtPaths: ArrayList<String>? = null,
onError: (() -> Unit)? = null
) {
target.isHorizontalScrolling = horizontalScroll
if (type == TYPE_SVGS) {
loadSVG(path, target, cropThumbnails, roundCorners, signature)
loadSVG(
path = path,
target = target,
cropThumbnails = cropThumbnails,
roundCorners = roundCorners,
signature = signature
)
} else {
val tryLoadingWithPicasso = type == TYPE_IMAGES && path.isPng()
loadImageBase(path, target, cropThumbnails, roundCorners, signature, skipMemoryCacheAtPaths, animateGifs, tryLoadingWithPicasso)
loadImageBase(
path = path,
target = target,
cropThumbnails = cropThumbnails,
roundCorners = roundCorners,
signature = signature,
skipMemoryCacheAtPaths = skipMemoryCacheAtPaths,
animate = animateGifs,
tryLoadingWithPicasso = type == TYPE_IMAGES && path.isPng(),
onError = onError
)
}
}
@ -524,6 +540,7 @@ fun Context.loadImageBase(
animate: Boolean = false,
tryLoadingWithPicasso: Boolean = false,
crossFadeDuration: Int = THUMBNAIL_FADE_DURATION_MS,
onError: (() -> Unit)? = null
) {
val options = RequestOptions()
.signature(signature)
@ -571,24 +588,25 @@ fun Context.loadImageBase(
.set(WebpDownsampler.USE_SYSTEM_DECODER, false) // CVE-2023-4863
.transition(DrawableTransitionOptions.withCrossFade(crossFadeDuration))
if (tryLoadingWithPicasso) {
builder = builder.listener(object : RequestListener<Drawable> {
override fun onLoadFailed(e: GlideException?, model: Any?, targetBitmap: Target<Drawable>, isFirstResource: Boolean): Boolean {
builder = builder.listener(object : RequestListener<Drawable> {
override fun onLoadFailed(e: GlideException?, model: Any?, targetBitmap: Target<Drawable>, isFirstResource: Boolean): Boolean {
if (tryLoadingWithPicasso) {
tryLoadingWithPicasso(path, target, cropThumbnails, roundCorners, signature)
return true
} else {
onError?.invoke()
}
override fun onResourceReady(
resource: Drawable,
model: Any,
targetBitmap: Target<Drawable>,
dataSource: DataSource,
isFirstResource: Boolean,
): Boolean {
return false
}
})
}
return true
}
override fun onResourceReady(
resource: Drawable,
model: Any,
targetBitmap: Target<Drawable>,
dataSource: DataSource,
isFirstResource: Boolean,
) = false
})
builder.into(target)
}

View file

@ -518,6 +518,11 @@ class PhotoFragment : ViewPagerFragment() {
loadImage()
// TODO: Implement panorama using a FOSS library
// checkIfPanorama()
} else {
binding.errorMessageHolder.errorMessage.apply {
setTextColor(if (context.config.blackBackground) Color.WHITE else context.getProperTextColor())
fadeIn()
}
}
}
})

View file

@ -2,6 +2,7 @@ package org.fossify.gallery.fragments
import android.annotation.SuppressLint
import android.content.res.Configuration
import android.graphics.Color
import android.graphics.Point
import android.graphics.SurfaceTexture
import android.net.Uri
@ -449,6 +450,20 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
mVideoSize.y = (videoSize.height / videoSize.pixelWidthHeightRatio).toInt()
setVideoSize()
}
override fun onPlayerErrorChanged(error: PlaybackException?) {
binding.errorMessageHolder.errorMessage.apply {
if (error != null) {
binding.videoPlayOutline.beGone()
text = error.localizedMessage ?: getString(R.string.failed_to_load_media)
setTextColor(if (context.config.blackBackground) Color.WHITE else context.getProperTextColor())
fadeIn()
} else {
beGone()
binding.videoPlayOutline.beVisible()
}
}
}
})
}

View file

@ -23,7 +23,7 @@ class MyGlideImageDecoder(val degrees: Int, val signature: ObjectKey) : ImageDec
.load(uri.toString().substringAfter("file://"))
.apply(options)
.transform(RotateTransformation(-degrees))
.into(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
.submit(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
return builder.get()
}

View file

@ -0,0 +1,6 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="48dp" android:height="48dp" android:viewportWidth="512" android:viewportHeight="512">
<path android:fillColor="#f2a600" android:pathData="M241.06 137.78L130.47 358.96c-4.13 8.55-0.55 18.82 7.98 22.95 2.3 1.11 4.79 1.7 7.34 1.72h221.18c9.49-0.09 17.12-7.85 17.04-17.33a17.23 17.23 0 0 0-1.72-7.34L271.7 137.78a17.16 17.16 0 0 0-30.62 0"/>
<path android:fillColor="#ffcc32" android:pathData="M233.41 153.31L129.63 360.45c-3.89 8.02-0.53 17.67 7.49 21.57 2.11 1.02 4.42 1.57 6.76 1.62h207.36a16.06 16.06 0 0 0 15.91-16.21 16.16 16.16 0 0 0-1.66-6.98L261.92 153.31a15.83 15.83 0 0 0-21.12-7.38 15.95 15.95 0 0 0-7.38 7.38"/>
<path android:fillColor="#424242" android:pathData="M256.37 192.23c9.78 0 17.65 7.87 17.01 17.01l-7.23 102.08c-0.81 5.4-5.83 9.14-11.23 8.34a9.89 9.89 0 0 1-8.34-8.34l-7.23-102.08c-0.64-9.14 7.23-17.01 17.01-17.01m0 136.11c7.04 0 12.76 5.72 12.76 12.76s-5.72 12.76-12.76 12.76-12.76-5.72-12.76-12.76 5.72-12.76 12.76-12.76" android:strokeAlpha="0.2"/>
<path android:fillColor="#fff170" android:pathData="M233.41 168.83c-2.55 3.19-45.51 87.2-45.51 87.2s-3.83 6.38 1.49 10c4.89 3.4 9.36-0.64 11.27-3.83 1.91-3.19 40.83-78.48 42.32-82.09 1.28-3.98 0.38-8.32-2.34-11.48-2.76-2.55-5.53-2.13-7.23 0.21m-54.24 111.24a7.02 7.02 135 1 1 14.04 0 7.02 7.02 0 1 1-14.04 0"/>
</vector>

View file

@ -50,6 +50,10 @@
android:id="@+id/bottom_video_time_holder"
layout="@layout/bottom_video_time_holder" />
<include
android:id="@+id/error_message_holder"
layout="@layout/layout_media_load_error" />
<TextView
android:id="@+id/slide_info"
android:layout_width="wrap_content"

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/error_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginHorizontal="@dimen/bigger_margin"
android:layout_toStartOf="@id/instant_next_item"
android:layout_toEndOf="@id/instant_prev_item"
android:alpha="0"
android:text="@string/failed_to_load_media"
android:textAlignment="center"
android:visibility="gone"
app:drawableTopCompat="@drawable/ic_vector_warning_colored"
tools:alpha="1"
tools:visibility="visible" />

View file

@ -32,6 +32,10 @@
android:layout_height="match_parent"
android:visibility="gone" />
<include
android:id="@+id/error_message_holder"
layout="@layout/layout_media_load_error" />
<ImageView
android:id="@+id/panorama_outline"
android:layout_width="@dimen/play_outline_size_big"

View file

@ -43,6 +43,10 @@
android:padding="20dp"
android:src="@drawable/ic_play_outline_vector" />
<include
android:id="@+id/error_message_holder"
layout="@layout/layout_media_load_error" />
<ImageView
android:id="@+id/panorama_outline"
android:layout_width="@dimen/play_outline_size_big"

View file

@ -10,7 +10,8 @@
<org.fossify.commons.views.MySquareImageView
android:id="@+id/medium_thumbnail"
android:layout_width="match_parent"
android:layout_height="match_parent" />
android:layout_height="match_parent"
tools:src="@mipmap/ic_launcher" />
<TextView
android:id="@+id/file_type"

View file

@ -16,7 +16,8 @@
<org.fossify.commons.views.MySquareImageView
android:id="@+id/medium_thumbnail"
android:layout_width="@dimen/list_view_folder_thumbnail_size"
android:layout_height="@dimen/list_view_folder_thumbnail_size" />
android:layout_height="@dimen/list_view_folder_thumbnail_size"
tools:src="@mipmap/ic_launcher" />
<ImageView
android:id="@+id/favorite"

View file

@ -34,6 +34,7 @@
<string name="reorder_by_dragging_pro">Reorder folders by dragging (Pro)</string>
<string name="restore_to_path">Restoring to \'%s\'</string>
<string name="full_storage_permission_required">Fossify Gallery needs full access to display all your photos and videos. Go to Settings > Permissions > Photos and videos > Allow all.</string>
<string name="failed_to_load_media">Failed to load media.</string>
<!-- Filter -->
<string name="filter_media">Filter media</string>