feat: 更新素材管理和举报风险地图

This commit is contained in:
2026-07-09 12:20:02 +08:00
parent 9b92d81902
commit 42aca73588
42 changed files with 6164 additions and 1369 deletions

View File

@ -0,0 +1,109 @@
//
// 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
}
}