[feat] pin an unpin models

This commit is contained in:
游薪渝(揽清) 2025-06-20 17:52:14 +08:00
parent 569d23a0ad
commit 018ff22032
3 changed files with 53 additions and 34 deletions

View File

@ -19,10 +19,10 @@ class ModelListViewModel: ObservableObject {
@Published var selectedModel: ModelInfo? @Published var selectedModel: ModelInfo?
private let modelClient = ModelClient() private let modelClient = ModelClient()
private let pinnedModelKey = "com.mnnllm.pinnedModelId" private let pinnedModelKey = "com.mnnllm.pinnedModelIds"
private var pinnedModelId: String? { public var pinnedModelIds: [String] {
get { UserDefaults.standard.string(forKey: pinnedModelKey) } get { UserDefaults.standard.stringArray(forKey: pinnedModelKey) ?? [] }
set { UserDefaults.standard.setValue(newValue, forKey: pinnedModelKey) } set { UserDefaults.standard.setValue(newValue, forKey: pinnedModelKey) }
} }
@ -70,12 +70,12 @@ class ModelListViewModel: ObservableObject {
for i in 0..<fetchedModels.count { for i in 0..<fetchedModels.count {
fetchedModels[i].isDownloaded = ModelStorageManager.shared.isModelDownloaded(fetchedModels[i].modelId) fetchedModels[i].isDownloaded = ModelStorageManager.shared.isModelDownloaded(fetchedModels[i].modelId)
} }
// //
if let pinnedId = pinnedModelId, let idx = fetchedModels.firstIndex(where: { $0.modelId == pinnedId }) { let pinned = pinnedModelIds.reversed().compactMap { id in
let pinned = fetchedModels.remove(at: idx) fetchedModels.first(where: { $0.modelId == id })
fetchedModels.insert(pinned, at: 0)
} }
models = fetchedModels let rest = fetchedModels.filter { !pinnedModelIds.contains($0.modelId) }
models = pinned + rest
} catch { } catch {
showError = true showError = true
errorMessage = "Error: \(error.localizedDescription)" errorMessage = "Error: \(error.localizedDescription)"
@ -126,15 +126,17 @@ class ModelListViewModel: ObservableObject {
guard let index = models.firstIndex(where: { $0.modelId == model.modelId }) else { return } guard let index = models.firstIndex(where: { $0.modelId == model.modelId }) else { return }
let pinned = models.remove(at: index) let pinned = models.remove(at: index)
models.insert(pinned, at: 0) models.insert(pinned, at: 0)
pinnedModelId = model.modelId var ids = pinnedModelIds.filter { $0 != model.modelId }
ids.append(model.modelId)
pinnedModelIds = ids
} }
func unpinModel(_ model: ModelInfo) { func unpinModel(_ model: ModelInfo) {
guard let index = models.firstIndex(where: { $0.modelId == model.modelId }) else { return } guard let index = models.firstIndex(where: { $0.modelId == model.modelId }) else { return }
let unpinned = models.remove(at: index) let unpinned = models.remove(at: index)
let insertIndex = models.firstIndex(where: { !$0.isDownloaded || $0.modelId != model.modelId }) ?? models.endIndex let insertIndex = models.count //
models.insert(unpinned, at: insertIndex) models.insert(unpinned, at: insertIndex)
pinnedModelId = nil pinnedModelIds = pinnedModelIds.filter { $0 != model.modelId }
} }
func deleteModel(_ model: ModelInfo) async { func deleteModel(_ model: ModelInfo) async {

View File

@ -44,29 +44,7 @@ struct ModelListView: View {
} }
} }
.swipeActions(edge: .trailing, allowsFullSwipe: false) { .swipeActions(edge: .trailing, allowsFullSwipe: false) {
if let firstModel = viewModel.filteredModels.first, firstModel.modelId == model.modelId { SwipeActionsView(model: model, viewModel: viewModel)
Button {
viewModel.unpinModel(model)
} label: {
Label("取消置顶", systemImage: "pin.slash")
}.tint(.gray)
} else {
Button {
viewModel.pinModel(model)
} label: {
Label("置顶", systemImage: "pin")
}.tint(.yellow)
}
if model.isDownloaded {
Button(role: .destructive) {
Task {
await viewModel.deleteModel(model)
}
} label: {
Label("Delete", systemImage: "trash")
}
}
} }
} }
} }

View File

@ -0,0 +1,39 @@
//
// SwipeActionsView.swift
// MNNLLMiOS
//
// Created by () on 2025/1/3.
//
import SwiftUI
struct SwipeActionsView: View {
let model: ModelInfo
@ObservedObject var viewModel: ModelListViewModel
var body: some View {
if viewModel.pinnedModelIds.contains(model.modelId) {
Button {
viewModel.unpinModel(model)
} label: {
Label("取消置顶", systemImage: "pin.slash")
}.tint(.gray)
} else {
Button {
viewModel.pinModel(model)
} label: {
Label("置顶", systemImage: "pin")
}.tint(.yellow)
}
if model.isDownloaded {
Button(role: .destructive) {
Task {
await viewModel.deleteModel(model)
}
} label: {
Label("Delete", systemImage: "trash")
}
}
}
}