133 lines
5.7 KiB
Swift
133 lines
5.7 KiB
Swift
import SwiftUI
|
|
import SwiftData
|
|
|
|
struct ModelManagementView: View {
|
|
@ObservedObject var whisperState: WhisperState
|
|
@State private var customModelToEdit: CustomCloudModel?
|
|
@StateObject private var aiService = AIService()
|
|
@StateObject private var customModelManager = CustomModelManager.shared
|
|
@EnvironmentObject private var enhancementService: AIEnhancementService
|
|
@Environment(\.modelContext) private var modelContext
|
|
@StateObject private var whisperPrompt = WhisperPrompt()
|
|
|
|
// State for the unified alert
|
|
@State private var isShowingDeleteAlert = false
|
|
@State private var alertTitle = ""
|
|
@State private var alertMessage = ""
|
|
@State private var deleteActionClosure: () -> Void = {}
|
|
|
|
var body: some View {
|
|
ScrollView {
|
|
VStack(alignment: .leading, spacing: 24) {
|
|
defaultModelSection
|
|
languageSelectionSection
|
|
availableModelsSection
|
|
}
|
|
.padding(40)
|
|
}
|
|
.frame(minWidth: 600, minHeight: 500)
|
|
.background(Color(NSColor.controlBackgroundColor))
|
|
.alert(isPresented: $isShowingDeleteAlert) {
|
|
Alert(
|
|
title: Text(alertTitle),
|
|
message: Text(alertMessage),
|
|
primaryButton: .destructive(Text("Delete"), action: deleteActionClosure),
|
|
secondaryButton: .cancel()
|
|
)
|
|
}
|
|
}
|
|
|
|
private var defaultModelSection: some View {
|
|
VStack(alignment: .leading, spacing: 8) {
|
|
Text("Default Model")
|
|
.font(.headline)
|
|
.foregroundColor(.secondary)
|
|
Text(whisperState.currentTranscriptionModel?.displayName ?? "No model selected")
|
|
.font(.title2)
|
|
.fontWeight(.bold)
|
|
}
|
|
.padding()
|
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
.background(CardBackground(isSelected: false))
|
|
.cornerRadius(10)
|
|
}
|
|
|
|
private var languageSelectionSection: some View {
|
|
LanguageSelectionView(whisperState: whisperState, displayMode: .full, whisperPrompt: whisperPrompt)
|
|
}
|
|
|
|
private var availableModelsSection: some View {
|
|
VStack(alignment: .leading, spacing: 16) {
|
|
HStack {
|
|
Text("Available Models")
|
|
.font(.title3)
|
|
.fontWeight(.semibold)
|
|
|
|
Text("(\(whisperState.allAvailableModels.count))")
|
|
.foregroundColor(.secondary)
|
|
.font(.subheadline)
|
|
|
|
Spacer()
|
|
}
|
|
|
|
VStack(spacing: 12) {
|
|
ForEach(whisperState.allAvailableModels, id: \.id) { model in
|
|
ModelCardRowView(
|
|
model: model,
|
|
isDownloaded: whisperState.availableModels.contains { $0.name == model.name },
|
|
isCurrent: whisperState.currentTranscriptionModel?.name == model.name,
|
|
downloadProgress: whisperState.downloadProgress,
|
|
modelURL: whisperState.availableModels.first { $0.name == model.name }?.url,
|
|
deleteAction: {
|
|
if let customModel = model as? CustomCloudModel {
|
|
alertTitle = "Delete Custom Model"
|
|
alertMessage = "Are you sure you want to delete the custom model '\(customModel.displayName)'?"
|
|
deleteActionClosure = {
|
|
customModelManager.removeCustomModel(withId: customModel.id)
|
|
whisperState.refreshAllAvailableModels()
|
|
}
|
|
isShowingDeleteAlert = true
|
|
} else if let downloadedModel = whisperState.availableModels.first(where: { $0.name == model.name }) {
|
|
alertTitle = "Delete Model"
|
|
alertMessage = "Are you sure you want to delete the model '\(downloadedModel.name)'?"
|
|
deleteActionClosure = {
|
|
Task {
|
|
await whisperState.deleteModel(downloadedModel)
|
|
}
|
|
}
|
|
isShowingDeleteAlert = true
|
|
}
|
|
},
|
|
setDefaultAction: {
|
|
Task {
|
|
await whisperState.setDefaultTranscriptionModel(model)
|
|
}
|
|
},
|
|
downloadAction: {
|
|
if let localModel = model as? LocalModel {
|
|
Task {
|
|
await whisperState.downloadModel(localModel)
|
|
}
|
|
}
|
|
},
|
|
editAction: model.provider == .custom ? { customModel in
|
|
customModelToEdit = customModel
|
|
} : nil
|
|
)
|
|
}
|
|
|
|
// Add Custom Model Card at the bottom
|
|
AddCustomModelCardView(
|
|
customModelManager: customModelManager,
|
|
editingModel: customModelToEdit
|
|
) {
|
|
// Refresh the models when a new custom model is added
|
|
whisperState.refreshAllAvailableModels()
|
|
customModelToEdit = nil // Clear editing state
|
|
}
|
|
}
|
|
}
|
|
.padding()
|
|
}
|
|
}
|