Files
suixinkan_uikit/suixinkan/UI/Common/MediaPreviewItem.swift

110 lines
3.3 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// MediaPreviewItem.swift
// suixinkan
//
import UIKit
///
public struct MediaPreviewItem: Hashable {
///
public enum MediaType: Equatable {
case image
case video
}
///
public enum Source {
case remoteImage(URL)
case localImageFile(URL)
case image(UIImage)
case remoteVideo(URL)
case localVideoFile(URL)
}
/// Diffable Data Source
public let id: UUID
///
public let source: Source
///
public init(id: UUID = UUID(), source: Source) {
self.id = id
self.source = source
}
///
public var mediaType: MediaType {
switch source {
case .remoteImage, .localImageFile, .image:
return .image
case .remoteVideo, .localVideoFile:
return .video
}
}
///
public var isImage: Bool {
mediaType == .image
}
///
public var isVideo: Bool {
mediaType == .video
}
/// nil
public static func remoteImage(_ urlString: String) -> MediaPreviewItem? {
makeRemoteURL(from: urlString).map { MediaPreviewItem(source: .remoteImage($0)) }
}
/// nil
public static func remoteVideo(_ urlString: String) -> MediaPreviewItem? {
makeRemoteURL(from: urlString).map { MediaPreviewItem(source: .remoteVideo($0)) }
}
///
public static func localImage(url: URL) -> MediaPreviewItem {
MediaPreviewItem(source: .localImageFile(url))
}
///
public static func image(_ image: UIImage) -> MediaPreviewItem {
MediaPreviewItem(source: .image(image))
}
///
public static func localVideo(url: URL) -> MediaPreviewItem {
MediaPreviewItem(source: .localVideoFile(url))
}
///
public static func clampedStartIndex(_ startIndex: Int, itemCount: Int) -> Int {
guard itemCount > 0 else { return 0 }
return min(max(0, startIndex), itemCount - 1)
}
///
public static func currentItem(in items: [MediaPreviewItem], startIndex: Int) -> MediaPreviewItem? {
guard !items.isEmpty else { return nil }
return items[clampedStartIndex(startIndex, itemCount: items.count)]
}
public static func == (lhs: MediaPreviewItem, rhs: MediaPreviewItem) -> Bool {
lhs.id == rhs.id
}
public func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
private static func makeRemoteURL(from text: String) -> URL? {
let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines)
guard !trimmed.isEmpty, let url = URL(string: trimmed) else { return nil }
guard let scheme = url.scheme?.lowercased(), ["http", "https"].contains(scheme) else { return nil }
return url
}
}