mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-07 06:30:19 +08:00
72 lines
2.8 KiB
Swift
72 lines
2.8 KiB
Swift
import Foundation
|
|
|
|
public struct ChatModelPickerSections: Sendable, Equatable {
|
|
public let pinned: [OpenClawChatModelChoice]
|
|
public let recent: [OpenClawChatModelChoice]
|
|
public let remaining: [OpenClawChatModelChoice]
|
|
}
|
|
|
|
@MainActor
|
|
public final class ChatModelPickerStore {
|
|
private static let favoritesKey = "openclaw.chat.modelFavorites"
|
|
private static let recentsKey = "openclaw.chat.modelRecents"
|
|
private static let maxRecents = 5
|
|
|
|
private let defaults: UserDefaults
|
|
|
|
public private(set) var favorites: [String]
|
|
public private(set) var recents: [String]
|
|
|
|
public init(defaults: UserDefaults = .standard) {
|
|
self.defaults = defaults
|
|
self.favorites = defaults.stringArray(forKey: Self.favoritesKey) ?? []
|
|
self.recents = defaults.stringArray(forKey: Self.recentsKey) ?? []
|
|
}
|
|
|
|
public func isFavorite(_ selectionID: String) -> Bool {
|
|
self.favorites.contains(selectionID)
|
|
}
|
|
|
|
public func toggleFavorite(_ selectionID: String) {
|
|
self.favorites = self.defaults.stringArray(forKey: Self.favoritesKey) ?? []
|
|
if self.isFavorite(selectionID) {
|
|
self.favorites.removeAll { $0 == selectionID }
|
|
} else {
|
|
self.favorites.append(selectionID)
|
|
}
|
|
self.defaults.set(self.favorites, forKey: Self.favoritesKey)
|
|
}
|
|
|
|
public func recordRecent(_ selectionID: String) {
|
|
guard !selectionID.isEmpty, selectionID != OpenClawChatViewModel.defaultModelSelectionID else { return }
|
|
self.recents = self.defaults.stringArray(forKey: Self.recentsKey) ?? []
|
|
self.recents.removeAll { $0 == selectionID }
|
|
self.recents.insert(selectionID, at: 0)
|
|
self.recents = Array(self.recents.prefix(Self.maxRecents))
|
|
self.defaults.set(self.recents, forKey: Self.recentsKey)
|
|
}
|
|
|
|
static func sections(
|
|
choices: [OpenClawChatModelChoice],
|
|
favorites: [String],
|
|
recents: [String]) -> ChatModelPickerSections
|
|
{
|
|
var choicesByID: [String: OpenClawChatModelChoice] = [:]
|
|
for choice in choices where choicesByID[choice.selectionID] == nil {
|
|
choicesByID[choice.selectionID] = choice
|
|
}
|
|
|
|
var included = Set<String>()
|
|
let pinned = favorites.compactMap { selectionID -> OpenClawChatModelChoice? in
|
|
guard included.insert(selectionID).inserted else { return nil }
|
|
return choicesByID[selectionID]
|
|
}
|
|
let recent = recents.compactMap { selectionID -> OpenClawChatModelChoice? in
|
|
guard included.insert(selectionID).inserted else { return nil }
|
|
return choicesByID[selectionID]
|
|
}
|
|
let remaining = choices.filter { included.insert($0.selectionID).inserted }
|
|
return ChatModelPickerSections(pinned: pinned, recent: recent, remaining: remaining)
|
|
}
|
|
}
|