Add OSS upload and Kingfisher image support
This commit is contained in:
81
suixinkan/Core/UI/RemoteImage.swift
Normal file
81
suixinkan/Core/UI/RemoteImage.swift
Normal file
@ -0,0 +1,81 @@
|
||||
//
|
||||
// RemoteImage.swift
|
||||
// suixinkan
|
||||
//
|
||||
// Created by Codex on 2026/6/22.
|
||||
//
|
||||
|
||||
import Kingfisher
|
||||
import SwiftUI
|
||||
|
||||
/// 网络图片组件,统一使用 Kingfisher 加载和缓存远程图片。
|
||||
struct RemoteImage<Placeholder: View>: View {
|
||||
let urlString: String?
|
||||
let contentMode: SwiftUI.ContentMode
|
||||
@ViewBuilder let placeholder: () -> Placeholder
|
||||
|
||||
@State private var didFail = false
|
||||
|
||||
/// 初始化网络图片组件。
|
||||
init(
|
||||
urlString: String?,
|
||||
contentMode: SwiftUI.ContentMode = .fill,
|
||||
@ViewBuilder placeholder: @escaping () -> Placeholder
|
||||
) {
|
||||
self.urlString = urlString
|
||||
self.contentMode = contentMode
|
||||
self.placeholder = placeholder
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
Group {
|
||||
if let url = imageURL, !didFail {
|
||||
KFImage(url)
|
||||
.placeholder { placeholder() }
|
||||
.onFailure { _ in didFail = true }
|
||||
.resizable()
|
||||
.cacheOriginalImage()
|
||||
.aspectRatio(contentMode: contentMode)
|
||||
} else {
|
||||
placeholder()
|
||||
}
|
||||
}
|
||||
.onChange(of: normalizedURLString) { _, _ in
|
||||
didFail = false
|
||||
}
|
||||
}
|
||||
|
||||
private var imageURL: URL? {
|
||||
guard let normalizedURLString else { return nil }
|
||||
return URL(string: normalizedURLString)
|
||||
}
|
||||
|
||||
private var normalizedURLString: String? {
|
||||
let text = urlString?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
||||
return text.isEmpty ? nil : text
|
||||
}
|
||||
}
|
||||
|
||||
/// 远程头像组件,提供统一的圆形头像占位和 Kingfisher 加载逻辑。
|
||||
struct RemoteAvatarImage: View {
|
||||
let urlString: String
|
||||
let systemImageName: String
|
||||
let iconSize: CGFloat
|
||||
|
||||
/// 初始化远程头像组件。
|
||||
init(urlString: String, systemImageName: String = "person.fill", iconSize: CGFloat = 44) {
|
||||
self.urlString = urlString
|
||||
self.systemImageName = systemImageName
|
||||
self.iconSize = iconSize
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
RemoteImage(urlString: urlString, contentMode: .fill) {
|
||||
Image(systemName: systemImageName)
|
||||
.font(.system(size: iconSize, weight: .semibold))
|
||||
.foregroundStyle(AppDesign.primary)
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.background(AppDesign.primarySoft)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user