2.5.0 #10
@@ -25,7 +25,6 @@ import SwiftUI
|
||||
|
||||
struct CombineConversationsSheet: View {
|
||||
@Environment(\.dismiss) var dismiss
|
||||
@Environment(ChatViewModel.self) private var chatViewModel
|
||||
|
||||
let conversations: [Conversation]
|
||||
var onCompleted: (Conversation) -> Void
|
||||
@@ -37,6 +36,8 @@ struct CombineConversationsSheet: View {
|
||||
@State private var errorMessage: String?
|
||||
@State private var mergeModel: ModelInfo?
|
||||
@State private var mergeProvider: Settings.Provider
|
||||
@State private var mergeModels: [ModelInfo] = []
|
||||
@State private var isLoadingMergeModels = false
|
||||
@State private var showModelPicker = false
|
||||
|
||||
private let settings = SettingsService.shared
|
||||
@@ -50,11 +51,8 @@ struct CombineConversationsSheet: View {
|
||||
}
|
||||
|
||||
private var mergeModelLabel: String? {
|
||||
if let mergeModel {
|
||||
return "\(mergeProvider.displayName) / \(mergeModel.name)"
|
||||
}
|
||||
guard let model = settings.defaultModel, !model.isEmpty else { return nil }
|
||||
return "\(settings.defaultProvider.displayName) / \(model)"
|
||||
guard let mergeModel else { return nil }
|
||||
return "\(mergeProvider.displayName) / \(mergeModel.name)"
|
||||
}
|
||||
|
||||
private var isValid: Bool {
|
||||
@@ -125,12 +123,37 @@ struct CombineConversationsSheet: View {
|
||||
Label("No model selected", systemImage: "exclamationmark.triangle.fill")
|
||||
.font(.caption).foregroundStyle(.orange)
|
||||
}
|
||||
Button("Change…") {
|
||||
|
||||
Menu {
|
||||
ForEach(ProviderRegistry.shared.configuredProviders, id: \.self) { p in
|
||||
Button {
|
||||
switchMergeProvider(to: p)
|
||||
} label: {
|
||||
HStack {
|
||||
Image(systemName: p.iconName)
|
||||
Text(p.displayName)
|
||||
if p == mergeProvider { Image(systemName: "checkmark") }
|
||||
}
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
Text(mergeProvider.displayName)
|
||||
}
|
||||
.menuStyle(.borderlessButton)
|
||||
.fixedSize()
|
||||
.font(.caption)
|
||||
.disabled(isProcessing || isLoadingMergeModels)
|
||||
|
||||
Button("Change Model…") {
|
||||
showModelPicker = true
|
||||
}
|
||||
.buttonStyle(.link)
|
||||
.font(.caption)
|
||||
.disabled(isProcessing)
|
||||
.disabled(isProcessing || isLoadingMergeModels || mergeModels.isEmpty)
|
||||
|
||||
if isLoadingMergeModels {
|
||||
ProgressView().controlSize(.mini)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -173,26 +196,46 @@ struct CombineConversationsSheet: View {
|
||||
}
|
||||
.frame(minWidth: 520, idealWidth: 560, minHeight: 460, idealHeight: 520)
|
||||
.task {
|
||||
if chatViewModel.availableModels.count <= 10 {
|
||||
await chatViewModel.loadAvailableModels()
|
||||
}
|
||||
if mergeModel == nil, let defaultModel = settings.defaultModel {
|
||||
mergeModel = chatViewModel.availableModels.first(where: { $0.id == defaultModel })
|
||||
await loadMergeModels()
|
||||
if let defaultModel = settings.defaultModel {
|
||||
mergeModel = mergeModels.first(where: { $0.id == defaultModel })
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $showModelPicker) {
|
||||
ModelSelectorView(
|
||||
models: chatViewModel.availableModels,
|
||||
models: mergeModels,
|
||||
selectedModel: mergeModel,
|
||||
onSelect: { model in
|
||||
mergeModel = model
|
||||
mergeProvider = chatViewModel.inferProviderPublic(from: model.id) ?? mergeProvider
|
||||
showModelPicker = false
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private func switchMergeProvider(to newProvider: Settings.Provider) {
|
||||
guard newProvider != mergeProvider else { return }
|
||||
mergeProvider = newProvider
|
||||
mergeModel = nil
|
||||
mergeModels = []
|
||||
Task { await loadMergeModels() }
|
||||
}
|
||||
|
||||
private func loadMergeModels() async {
|
||||
guard let provider = ProviderRegistry.shared.getProvider(for: mergeProvider) else {
|
||||
mergeModels = []
|
||||
return
|
||||
}
|
||||
isLoadingMergeModels = true
|
||||
defer { isLoadingMergeModels = false }
|
||||
do {
|
||||
mergeModels = try await provider.listModels()
|
||||
} catch {
|
||||
Log.api.error("Failed to load models for merge provider \(mergeProvider.rawValue): \(error.localizedDescription)")
|
||||
mergeModels = []
|
||||
}
|
||||
}
|
||||
|
||||
private func combine() {
|
||||
isProcessing = true
|
||||
errorMessage = nil
|
||||
|
||||
Reference in New Issue
Block a user