fix(mobile): image preview can dismiss if image load error

Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
Innei 2025-03-25 14:48:51 +08:00
parent 81fc94c946
commit 626e54dd84
No known key found for this signature in database
GPG Key ID: 0F62D33977F021F7
5 changed files with 69 additions and 33 deletions

View File

@ -154,20 +154,27 @@ public class ImageCarouselViewController: UIPageViewController,
}
private func saveImageToPhotos() {
if let vc = viewControllers?.first as? ImageCarouselViewControllerProtocol {
if let vc = viewControllers?.first as? ImageCarouselViewControllerProtocol,
!vc.isLoadError()
{
vc.saveImageToPhotos()
}
}
private func copyImageToClipboard() {
if let vc = viewControllers?.first as? ImageCarouselViewControllerProtocol {
if let vc = viewControllers?.first as? ImageCarouselViewControllerProtocol,
!vc.isLoadError()
{
vc.copyImageToClipboard()
}
}
private func shareImage() {
if let vc = viewControllers?.first as? ImageCarouselViewControllerProtocol {
if let vc = viewControllers?.first as? ImageCarouselViewControllerProtocol,
!vc.isLoadError()
{
vc.shareImage()
}
}

View File

@ -12,4 +12,5 @@ protocol ImageCarouselViewControllerProtocol {
func copyImageToClipboard()
func shareImage()
func isLoadError() -> Bool
}

View File

@ -2,30 +2,40 @@ import Foundation
import SDWebImage
public protocol ImageLoader {
func loadImage(_ url: URL, placeholder: UIImage?, imageView: UIImageView, completion: @escaping (_ image: UIImage?) -> Void)
func loadImage(
_ url: URL, placeholder: UIImage?, imageView: UIImageView,
completion: @escaping (UIImage?) -> Void, onError: @escaping (Error) -> Void)
}
struct SDWebImageLoader: ImageLoader {
func loadImage(_ url: URL, placeholder: UIImage?, imageView: UIImageView, completion: @escaping (UIImage?) -> Void) {
guard var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false) else { return }
urlComponents.scheme = "https"
guard let httpsURL = urlComponents.url else { return }
imageView.sd_setImage(
with: httpsURL,
placeholderImage: placeholder,
options: [],
progress: nil) {(img, err, type, url) in
DispatchQueue.main.async {
completion(img)
}
if let error = err {
print("Error: \(error.localizedDescription)")
if let nsError = error as NSError? {
print("Error Code: \(nsError.code), Domain: \(nsError.domain)")
}
}
}
func loadImage(
_ url: URL, placeholder: UIImage?, imageView: UIImageView,
completion: @escaping (UIImage?) -> Void, onError: @escaping (Error) -> Void
) {
guard var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false) else {
return
}
urlComponents.scheme = "https"
guard let httpsURL = urlComponents.url else { return }
imageView.sd_setImage(
with: httpsURL,
placeholderImage: placeholder,
options: [],
progress: nil
) { (img, err, type, url) in
DispatchQueue.main.async {
completion(img)
}
if let error = err {
print("Error: \(error.localizedDescription)")
if let nsError = error as NSError? {
print("Error Code: \(nsError.code), Domain: \(nsError.domain)")
}
DispatchQueue.main.async {
onError(error)
}
}
}
}
}

View File

@ -37,6 +37,8 @@ class ImageViewerController: UIViewController,
private var sourceView: UIImageView? = nil
private var _error: Error? = nil
init(
index: Int,
imageItem: ImageItem,
@ -111,13 +113,23 @@ class ImageViewerController: UIViewController,
if imageView.image == nil {
imageView.image = UIImage(systemName: "photo")?.withTintColor(
.gray, renderingMode: .alwaysOriginal)
imageView.frame = .init(origin: .zero, size: .init(width: 100, height: 100))
self.layout()
}
self.layout()
imageLoader.loadImage(url, placeholder: placeholder, imageView: imageView) { (image) in
DispatchQueue.main.async { [weak self] in
self?.layout()
self?.activityIndicator.stopAnimating()
}
imageLoader.loadImage(url, placeholder: placeholder, imageView: imageView) {
[weak self] (image) in
self?.layout()
self?.activityIndicator.stopAnimating()
} onError: { [weak self] error in
self?.imageView.image = UIImage(systemName: "exclamationmark.triangle.fill")?
.withTintColor(.red, renderingMode: .alwaysOriginal)
self?.imageView.frame = .init(origin: .zero, size: .init(width: 30, height: 30))
self?.layout()
SPIndicator.present(
title: "Image Load Error", message: error.localizedDescription, preset: .error)
self?.activityIndicator.stopAnimating()
self?._error = error
}
default:
break
@ -335,6 +347,11 @@ extension ImageViewerController: UIScrollViewDelegate {
extension ImageViewerController: ImageCarouselViewControllerProtocol {
public func isLoadError() -> Bool {
guard let error = _error else { return false }
return true
}
public func saveImageToPhotos() {
guard let image = imageView.image else { return }

View File

@ -75,6 +75,7 @@ extension ImageViewerTransitionPresentationAnimator: UIViewControllerAnimatedTra
dummyImageView.contentMode = imageContentMode
dummyImageView.alpha = 1.0
dummyImageView.image = image
dummyImageView.isUserInteractionEnabled = false
return dummyImageView
}
@ -98,7 +99,7 @@ extension ImageViewerTransitionPresentationAnimator: UIViewControllerAnimatedTra
transitionVC.targetView?.tintColor = sourceView.tintColor
var dummyImageView: UIImageView?
if let image = sourceView.image {
if sourceView.image != nil {
dummyImageView = createDummyImageView(
frame: sourceView.frameRelativeToWindow(),
image: sourceView.image)