mirror of https://github.com/alibaba/MNN.git
				
				
				
			[feat] pin an unpin models
This commit is contained in:
		
							parent
							
								
									569d23a0ad
								
							
						
					
					
						commit
						018ff22032
					
				|  | @ -19,10 +19,10 @@ class ModelListViewModel: ObservableObject { | |||
|     @Published var selectedModel: ModelInfo? | ||||
|      | ||||
|     private let modelClient = ModelClient() | ||||
|     private let pinnedModelKey = "com.mnnllm.pinnedModelId" | ||||
|     private let pinnedModelKey = "com.mnnllm.pinnedModelIds" | ||||
|      | ||||
|     private var pinnedModelId: String? { | ||||
|         get { UserDefaults.standard.string(forKey: pinnedModelKey) } | ||||
|     public var pinnedModelIds: [String] { | ||||
|         get { UserDefaults.standard.stringArray(forKey: pinnedModelKey) ?? [] } | ||||
|         set { UserDefaults.standard.setValue(newValue, forKey: pinnedModelKey) } | ||||
|     } | ||||
|      | ||||
|  | @ -70,12 +70,12 @@ class ModelListViewModel: ObservableObject { | |||
|             for i in 0..<fetchedModels.count { | ||||
|                 fetchedModels[i].isDownloaded = ModelStorageManager.shared.isModelDownloaded(fetchedModels[i].modelId) | ||||
|             } | ||||
|             // 保持置顶顺序 | ||||
|             if let pinnedId = pinnedModelId, let idx = fetchedModels.firstIndex(where: { $0.modelId == pinnedId }) { | ||||
|                 let pinned = fetchedModels.remove(at: idx) | ||||
|                 fetchedModels.insert(pinned, at: 0) | ||||
|             // 多模型置顶顺序,最新置顶的在最顶部 | ||||
|             let pinned = pinnedModelIds.reversed().compactMap { id in | ||||
|                 fetchedModels.first(where: { $0.modelId == id }) | ||||
|             } | ||||
|             models = fetchedModels | ||||
|             let rest = fetchedModels.filter { !pinnedModelIds.contains($0.modelId) } | ||||
|             models = pinned + rest | ||||
|         } catch { | ||||
|             showError = true | ||||
|             errorMessage = "Error: \(error.localizedDescription)" | ||||
|  | @ -126,15 +126,17 @@ class ModelListViewModel: ObservableObject { | |||
|         guard let index = models.firstIndex(where: { $0.modelId == model.modelId }) else { return } | ||||
|         let pinned = models.remove(at: index) | ||||
|         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) { | ||||
|         guard let index = models.firstIndex(where: { $0.modelId == model.modelId }) else { return } | ||||
|         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) | ||||
|         pinnedModelId = nil | ||||
|         pinnedModelIds = pinnedModelIds.filter { $0 != model.modelId } | ||||
|     } | ||||
|      | ||||
|     func deleteModel(_ model: ModelInfo) async { | ||||
|  |  | |||
|  | @ -44,29 +44,7 @@ struct ModelListView: View { | |||
|                             } | ||||
|                         } | ||||
|                         .swipeActions(edge: .trailing, allowsFullSwipe: false) { | ||||
|                             if let firstModel = viewModel.filteredModels.first, firstModel.modelId == 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") | ||||
|                                 } | ||||
|                             } | ||||
|                             SwipeActionsView(model: model, viewModel: viewModel) | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|  |  | |||
|  | @ -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") | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| }  | ||||
		Loading…
	
		Reference in New Issue