import Foundation import SwiftUI import UniformTypeIdentifiers class ShareBookmarkViewModel: ObservableObject { @Published var url: String? @Published var title: String = "" @Published var labels: [BookmarkLabelDto] = [] @Published var selectedLabels: Set = [] @Published var statusMessage: (text: String, isError: Bool, emoji: String)? = nil @Published var isSaving: Bool = false @Published var searchText: String = "" let extensionContext: NSExtensionContext? // Computed properties for pagination var availableLabels: [BookmarkLabelDto] { return labels.filter { !selectedLabels.contains($0.name) } } // Computed property for filtered labels based on search text var filteredLabels: [BookmarkLabelDto] { if searchText.isEmpty { return availableLabels } else { return availableLabels.filter { $0.name.localizedCaseInsensitiveContains(searchText) } } } var availableLabelPages: [[BookmarkLabelDto]] { let pageSize = Constants.Labels.pageSize let labelsToShow = searchText.isEmpty ? availableLabels : filteredLabels if labelsToShow.count <= pageSize { return [labelsToShow] } else { return stride(from: 0, to: labelsToShow.count, by: pageSize).map { Array(labelsToShow[$0.. $1.count } await MainActor.run { self.labels = Array(sorted) } } } func save() { guard let url = url, !url.isEmpty else { statusMessage = ("No URL found.", true, "❌") return } isSaving = true Task { await SimpleAPI.addBookmark(title: title, url: url, labels: Array(selectedLabels)) { [weak self] message, error in self?.statusMessage = (message, error, error ? "❌" : "✅") self?.isSaving = false if !error { DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { self?.extensionContext?.completeRequest(returningItems: [], completionHandler: nil) } } } } } }