New release v2.3.8
This commit is contained in:
@@ -37,9 +37,11 @@ struct ModelSelectorView: View {
|
||||
@State private var filterOnline = false
|
||||
@State private var filterImageGen = false
|
||||
@State private var filterThinking = false
|
||||
@State private var filterFavorites = false
|
||||
@State private var keyboardIndex: Int = -1
|
||||
@State private var sortOrder: ModelSortOrder = .default
|
||||
@State private var selectedInfoModel: ModelInfo? = nil
|
||||
@Bindable private var settings = SettingsService.shared
|
||||
|
||||
private var filteredModels: [ModelInfo] {
|
||||
let q = searchText.lowercased()
|
||||
@@ -54,13 +56,20 @@ struct ModelSelectorView: View {
|
||||
let matchesOnline = !filterOnline || model.capabilities.online
|
||||
let matchesImageGen = !filterImageGen || model.capabilities.imageGeneration
|
||||
let matchesThinking = !filterThinking || model.capabilities.thinking
|
||||
let matchesFavorites = !filterFavorites || settings.favoriteModelIds.contains(model.id)
|
||||
|
||||
return matchesSearch && matchesVision && matchesTools && matchesOnline && matchesImageGen && matchesThinking
|
||||
return matchesSearch && matchesVision && matchesTools && matchesOnline && matchesImageGen && matchesThinking && matchesFavorites
|
||||
}
|
||||
|
||||
let favIds = settings.favoriteModelIds
|
||||
switch sortOrder {
|
||||
case .default:
|
||||
return filtered
|
||||
return filtered.sorted { a, b in
|
||||
let aFav = favIds.contains(a.id)
|
||||
let bFav = favIds.contains(b.id)
|
||||
if aFav != bFav { return aFav }
|
||||
return false
|
||||
}
|
||||
case .priceLowHigh:
|
||||
return filtered.sorted { $0.pricing.prompt < $1.pricing.prompt }
|
||||
case .priceHighLow:
|
||||
@@ -91,6 +100,19 @@ struct ModelSelectorView: View {
|
||||
|
||||
Spacer()
|
||||
|
||||
// Favorites filter star
|
||||
Button(action: { filterFavorites.toggle(); keyboardIndex = -1 }) {
|
||||
Image(systemName: filterFavorites ? "star.fill" : "star")
|
||||
.font(.caption)
|
||||
.padding(.horizontal, 10)
|
||||
.padding(.vertical, 6)
|
||||
.background(filterFavorites ? Color.yellow.opacity(0.25) : Color.gray.opacity(0.1))
|
||||
.foregroundColor(filterFavorites ? .yellow : .secondary)
|
||||
.cornerRadius(6)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.help("Show favorites only")
|
||||
|
||||
// Sort menu
|
||||
Menu {
|
||||
ForEach(ModelSortOrder.allCases, id: \.rawValue) { order in
|
||||
@@ -140,7 +162,9 @@ struct ModelSelectorView: View {
|
||||
model: model,
|
||||
isSelected: model.id == selectedModel?.id,
|
||||
isKeyboardHighlighted: index == keyboardIndex,
|
||||
isFavorite: settings.favoriteModelIds.contains(model.id),
|
||||
onSelect: { onSelect(model) },
|
||||
onFavorite: { settings.toggleFavoriteModel(model.id) },
|
||||
onInfo: { selectedInfoModel = model }
|
||||
)
|
||||
.id(model.id)
|
||||
@@ -249,14 +273,25 @@ struct ModelRowView: View {
|
||||
let model: ModelInfo
|
||||
let isSelected: Bool
|
||||
var isKeyboardHighlighted: Bool = false
|
||||
var isFavorite: Bool = false
|
||||
let onSelect: () -> Void
|
||||
var onFavorite: (() -> Void)? = nil
|
||||
let onInfo: () -> Void
|
||||
|
||||
var body: some View {
|
||||
HStack(alignment: .top, spacing: 8) {
|
||||
// Selectable main content
|
||||
VStack(alignment: .leading, spacing: 6) {
|
||||
HStack {
|
||||
HStack(spacing: 6) {
|
||||
if let onFavorite {
|
||||
Button(action: onFavorite) {
|
||||
Image(systemName: isFavorite ? "star.fill" : "star")
|
||||
.font(.system(size: 13))
|
||||
.foregroundColor(isFavorite ? .yellow : .secondary)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.help(isFavorite ? "Remove from favorites" : "Add to favorites")
|
||||
}
|
||||
Text(model.name)
|
||||
.font(.headline)
|
||||
.foregroundColor(isSelected ? .blue : .primary)
|
||||
|
||||
Reference in New Issue
Block a user