feat: AI 模型支持 On-Demand Resources 按需下载
- 新增 ODRManager 管理模型资源下载 - EditorView 添加下载进度 UI - Package.swift 移除内嵌模型资源 - 减小应用包体积约 64MB 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -37,6 +37,9 @@ struct EditorView: View {
|
||||
|
||||
// AI 超分辨率
|
||||
@State private var aiEnhanceEnabled: Bool = false
|
||||
@State private var aiModelNeedsDownload: Bool = false
|
||||
@State private var aiModelDownloading: Bool = false
|
||||
@State private var aiModelDownloadProgress: Double = 0
|
||||
|
||||
// 视频诊断
|
||||
@State private var videoDiagnosis: VideoDiagnosis?
|
||||
@@ -370,10 +373,45 @@ struct EditorView: View {
|
||||
}
|
||||
}
|
||||
.tint(.purple)
|
||||
.disabled(!AIEnhancer.isAvailable())
|
||||
.disabled(!AIEnhancer.isAvailable() || aiModelDownloading)
|
||||
.onChange(of: aiEnhanceEnabled) { _, newValue in
|
||||
if newValue {
|
||||
checkAndDownloadModel()
|
||||
}
|
||||
}
|
||||
|
||||
if aiEnhanceEnabled {
|
||||
// 模型下载进度
|
||||
if aiModelDownloading {
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
HStack(spacing: 8) {
|
||||
ProgressView()
|
||||
.scaleEffect(0.8)
|
||||
Text("正在下载 AI 模型...")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
|
||||
ProgressView(value: aiModelDownloadProgress)
|
||||
.tint(.purple)
|
||||
|
||||
Text(String(format: "%.0f%%", aiModelDownloadProgress * 100))
|
||||
.font(.caption2)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
.padding(.leading, 4)
|
||||
}
|
||||
|
||||
if aiEnhanceEnabled && !aiModelDownloading {
|
||||
VStack(alignment: .leading, spacing: 6) {
|
||||
if aiModelNeedsDownload {
|
||||
HStack(spacing: 4) {
|
||||
Image(systemName: "arrow.down.circle")
|
||||
.foregroundStyle(.orange)
|
||||
.font(.caption)
|
||||
Text("首次使用需下载 AI 模型(约 64MB)")
|
||||
.font(.caption)
|
||||
}
|
||||
}
|
||||
HStack(spacing: 4) {
|
||||
Image(systemName: "sparkles")
|
||||
.foregroundStyle(.purple)
|
||||
@@ -415,6 +453,10 @@ struct EditorView: View {
|
||||
.padding(16)
|
||||
.background(Color.purple.opacity(0.1))
|
||||
.clipShape(RoundedRectangle(cornerRadius: 12))
|
||||
.task {
|
||||
// 检查模型是否需要下载
|
||||
aiModelNeedsDownload = await AIEnhancer.needsDownload()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - 兼容模式开关
|
||||
@@ -681,6 +723,46 @@ struct EditorView: View {
|
||||
return CropRect(x: cropX, y: cropY, width: cropWidth, height: cropHeight)
|
||||
}
|
||||
|
||||
private func checkAndDownloadModel() {
|
||||
guard aiEnhanceEnabled else { return }
|
||||
|
||||
Task {
|
||||
// 检查是否需要下载
|
||||
let needsDownload = await AIEnhancer.needsDownload()
|
||||
|
||||
await MainActor.run {
|
||||
aiModelNeedsDownload = needsDownload
|
||||
}
|
||||
|
||||
if needsDownload {
|
||||
await MainActor.run {
|
||||
aiModelDownloading = true
|
||||
aiModelDownloadProgress = 0
|
||||
}
|
||||
|
||||
do {
|
||||
try await AIEnhancer.downloadModel { progress in
|
||||
Task { @MainActor in
|
||||
aiModelDownloadProgress = progress
|
||||
}
|
||||
}
|
||||
|
||||
await MainActor.run {
|
||||
aiModelDownloading = false
|
||||
aiModelNeedsDownload = false
|
||||
}
|
||||
} catch {
|
||||
await MainActor.run {
|
||||
aiModelDownloading = false
|
||||
// 下载失败时禁用 AI 增强
|
||||
aiEnhanceEnabled = false
|
||||
}
|
||||
print("Failed to download AI model: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func startProcessing() {
|
||||
Analytics.shared.log(.editorGenerateClick, parameters: [
|
||||
"trimStart": trimStart,
|
||||
|
||||
Reference in New Issue
Block a user