mirror of
https://github.com/FossifyOrg/Gallery.git
synced 2024-11-22 04:28:00 +01:00
Show error message when loading media fails
This commit is contained in:
parent
cf000a6546
commit
642f0ccd06
15 changed files with 152 additions and 32 deletions
|
@ -309,6 +309,18 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen
|
||||||
mVideoSize.y = videoSize.height
|
mVideoSize.y = videoSize.height
|
||||||
setVideoSize()
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,10 @@ import android.view.Menu
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
|
import androidx.appcompat.content.res.AppCompatResources
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
|
@ -820,14 +822,18 @@ class DirectoryAdapter(
|
||||||
}
|
}
|
||||||
|
|
||||||
activity.loadImage(
|
activity.loadImage(
|
||||||
thumbnailType,
|
type = thumbnailType,
|
||||||
directory.tmb,
|
path = directory.tmb,
|
||||||
dirThumbnail,
|
target = dirThumbnail,
|
||||||
scrollHorizontally,
|
horizontalScroll = scrollHorizontally,
|
||||||
animateGifs,
|
animateGifs = animateGifs,
|
||||||
cropThumbnails,
|
cropThumbnails = cropThumbnails,
|
||||||
roundedCorners,
|
roundCorners = roundedCorners,
|
||||||
directory.getKey()
|
signature = directory.getKey(),
|
||||||
|
onError = {
|
||||||
|
dirThumbnail.scaleType = ImageView.ScaleType.CENTER
|
||||||
|
dirThumbnail.setImageDrawable(AppCompatResources.getDrawable(activity, R.drawable.ic_vector_warning_colored))
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,9 @@ import android.os.Looper
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.appcompat.content.res.AppCompatResources
|
||||||
import androidx.core.view.allViews
|
import androidx.core.view.allViews
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.qtalk.recyclerviewfastscroller.RecyclerViewFastScroller
|
import com.qtalk.recyclerviewfastscroller.RecyclerViewFastScroller
|
||||||
|
@ -681,7 +683,19 @@ class MediaAdapter(
|
||||||
|
|
||||||
if (loadImageInstantly) {
|
if (loadImageInstantly) {
|
||||||
activity.loadImage(
|
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 {
|
} else {
|
||||||
mediumThumbnail.setImageDrawable(null)
|
mediumThumbnail.setImageDrawable(null)
|
||||||
|
@ -690,8 +704,19 @@ class MediaAdapter(
|
||||||
val isVisible = visibleItemPaths.contains(medium.path)
|
val isVisible = visibleItemPaths.contains(medium.path)
|
||||||
if (isVisible) {
|
if (isVisible) {
|
||||||
activity.loadImage(
|
activity.loadImage(
|
||||||
medium.type, path, mediumThumbnail, scrollHorizontally, animateGifs, cropThumbnails, roundedCorners,
|
type = medium.type,
|
||||||
medium.getKey(), rotatedImagePaths
|
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)
|
}, IMAGE_LOAD_DELAY)
|
||||||
|
|
|
@ -482,13 +482,29 @@ fun Context.loadImage(
|
||||||
roundCorners: Int,
|
roundCorners: Int,
|
||||||
signature: ObjectKey,
|
signature: ObjectKey,
|
||||||
skipMemoryCacheAtPaths: ArrayList<String>? = null,
|
skipMemoryCacheAtPaths: ArrayList<String>? = null,
|
||||||
|
onError: (() -> Unit)? = null
|
||||||
) {
|
) {
|
||||||
target.isHorizontalScrolling = horizontalScroll
|
target.isHorizontalScrolling = horizontalScroll
|
||||||
if (type == TYPE_SVGS) {
|
if (type == TYPE_SVGS) {
|
||||||
loadSVG(path, target, cropThumbnails, roundCorners, signature)
|
loadSVG(
|
||||||
|
path = path,
|
||||||
|
target = target,
|
||||||
|
cropThumbnails = cropThumbnails,
|
||||||
|
roundCorners = roundCorners,
|
||||||
|
signature = signature
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
val tryLoadingWithPicasso = type == TYPE_IMAGES && path.isPng()
|
loadImageBase(
|
||||||
loadImageBase(path, target, cropThumbnails, roundCorners, signature, skipMemoryCacheAtPaths, animateGifs, tryLoadingWithPicasso)
|
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,
|
animate: Boolean = false,
|
||||||
tryLoadingWithPicasso: Boolean = false,
|
tryLoadingWithPicasso: Boolean = false,
|
||||||
crossFadeDuration: Int = THUMBNAIL_FADE_DURATION_MS,
|
crossFadeDuration: Int = THUMBNAIL_FADE_DURATION_MS,
|
||||||
|
onError: (() -> Unit)? = null
|
||||||
) {
|
) {
|
||||||
val options = RequestOptions()
|
val options = RequestOptions()
|
||||||
.signature(signature)
|
.signature(signature)
|
||||||
|
@ -571,24 +588,25 @@ fun Context.loadImageBase(
|
||||||
.set(WebpDownsampler.USE_SYSTEM_DECODER, false) // CVE-2023-4863
|
.set(WebpDownsampler.USE_SYSTEM_DECODER, false) // CVE-2023-4863
|
||||||
.transition(DrawableTransitionOptions.withCrossFade(crossFadeDuration))
|
.transition(DrawableTransitionOptions.withCrossFade(crossFadeDuration))
|
||||||
|
|
||||||
if (tryLoadingWithPicasso) {
|
builder = builder.listener(object : RequestListener<Drawable> {
|
||||||
builder = builder.listener(object : RequestListener<Drawable> {
|
override fun onLoadFailed(e: GlideException?, model: Any?, targetBitmap: Target<Drawable>, isFirstResource: Boolean): Boolean {
|
||||||
override fun onLoadFailed(e: GlideException?, model: Any?, targetBitmap: Target<Drawable>, isFirstResource: Boolean): Boolean {
|
if (tryLoadingWithPicasso) {
|
||||||
tryLoadingWithPicasso(path, target, cropThumbnails, roundCorners, signature)
|
tryLoadingWithPicasso(path, target, cropThumbnails, roundCorners, signature)
|
||||||
return true
|
} else {
|
||||||
|
onError?.invoke()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResourceReady(
|
return true
|
||||||
resource: Drawable,
|
}
|
||||||
model: Any,
|
|
||||||
targetBitmap: Target<Drawable>,
|
override fun onResourceReady(
|
||||||
dataSource: DataSource,
|
resource: Drawable,
|
||||||
isFirstResource: Boolean,
|
model: Any,
|
||||||
): Boolean {
|
targetBitmap: Target<Drawable>,
|
||||||
return false
|
dataSource: DataSource,
|
||||||
}
|
isFirstResource: Boolean,
|
||||||
})
|
) = false
|
||||||
}
|
})
|
||||||
|
|
||||||
builder.into(target)
|
builder.into(target)
|
||||||
}
|
}
|
||||||
|
|
|
@ -518,6 +518,11 @@ class PhotoFragment : ViewPagerFragment() {
|
||||||
loadImage()
|
loadImage()
|
||||||
// TODO: Implement panorama using a FOSS library
|
// TODO: Implement panorama using a FOSS library
|
||||||
// checkIfPanorama()
|
// checkIfPanorama()
|
||||||
|
} else {
|
||||||
|
binding.errorMessageHolder.errorMessage.apply {
|
||||||
|
setTextColor(if (context.config.blackBackground) Color.WHITE else context.getProperTextColor())
|
||||||
|
fadeIn()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -2,6 +2,7 @@ package org.fossify.gallery.fragments
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
|
import android.graphics.Color
|
||||||
import android.graphics.Point
|
import android.graphics.Point
|
||||||
import android.graphics.SurfaceTexture
|
import android.graphics.SurfaceTexture
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
@ -449,6 +450,20 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
||||||
mVideoSize.y = (videoSize.height / videoSize.pixelWidthHeightRatio).toInt()
|
mVideoSize.y = (videoSize.height / videoSize.pixelWidthHeightRatio).toInt()
|
||||||
setVideoSize()
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ class MyGlideImageDecoder(val degrees: Int, val signature: ObjectKey) : ImageDec
|
||||||
.load(uri.toString().substringAfter("file://"))
|
.load(uri.toString().substringAfter("file://"))
|
||||||
.apply(options)
|
.apply(options)
|
||||||
.transform(RotateTransformation(-degrees))
|
.transform(RotateTransformation(-degrees))
|
||||||
.into(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
|
.submit(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
|
||||||
|
|
||||||
return builder.get()
|
return builder.get()
|
||||||
}
|
}
|
||||||
|
|
6
app/src/main/res/drawable/ic_vector_warning_colored.xml
Normal file
6
app/src/main/res/drawable/ic_vector_warning_colored.xml
Normal 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>
|
|
@ -50,6 +50,10 @@
|
||||||
android:id="@+id/bottom_video_time_holder"
|
android:id="@+id/bottom_video_time_holder"
|
||||||
layout="@layout/bottom_video_time_holder" />
|
layout="@layout/bottom_video_time_holder" />
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/error_message_holder"
|
||||||
|
layout="@layout/layout_media_load_error" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/slide_info"
|
android:id="@+id/slide_info"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
18
app/src/main/res/layout/layout_media_load_error.xml
Normal file
18
app/src/main/res/layout/layout_media_load_error.xml
Normal 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" />
|
|
@ -32,6 +32,10 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/error_message_holder"
|
||||||
|
layout="@layout/layout_media_load_error" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/panorama_outline"
|
android:id="@+id/panorama_outline"
|
||||||
android:layout_width="@dimen/play_outline_size_big"
|
android:layout_width="@dimen/play_outline_size_big"
|
||||||
|
|
|
@ -43,6 +43,10 @@
|
||||||
android:padding="20dp"
|
android:padding="20dp"
|
||||||
android:src="@drawable/ic_play_outline_vector" />
|
android:src="@drawable/ic_play_outline_vector" />
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/error_message_holder"
|
||||||
|
layout="@layout/layout_media_load_error" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/panorama_outline"
|
android:id="@+id/panorama_outline"
|
||||||
android:layout_width="@dimen/play_outline_size_big"
|
android:layout_width="@dimen/play_outline_size_big"
|
||||||
|
|
|
@ -10,7 +10,8 @@
|
||||||
<org.fossify.commons.views.MySquareImageView
|
<org.fossify.commons.views.MySquareImageView
|
||||||
android:id="@+id/medium_thumbnail"
|
android:id="@+id/medium_thumbnail"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" />
|
android:layout_height="match_parent"
|
||||||
|
tools:src="@mipmap/ic_launcher" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/file_type"
|
android:id="@+id/file_type"
|
||||||
|
|
|
@ -16,7 +16,8 @@
|
||||||
<org.fossify.commons.views.MySquareImageView
|
<org.fossify.commons.views.MySquareImageView
|
||||||
android:id="@+id/medium_thumbnail"
|
android:id="@+id/medium_thumbnail"
|
||||||
android:layout_width="@dimen/list_view_folder_thumbnail_size"
|
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
|
<ImageView
|
||||||
android:id="@+id/favorite"
|
android:id="@+id/favorite"
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
<string name="reorder_by_dragging_pro">Reorder folders by dragging (Pro)</string>
|
<string name="reorder_by_dragging_pro">Reorder folders by dragging (Pro)</string>
|
||||||
<string name="restore_to_path">Restoring to \'%s\'</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="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 -->
|
<!-- Filter -->
|
||||||
<string name="filter_media">Filter media</string>
|
<string name="filter_media">Filter media</string>
|
||||||
|
|
Loading…
Reference in a new issue