diff --git a/core/Sources/BookmarksCore/Model/ItemViewModel.swift b/core/Sources/BookmarksCore/Model/ItemViewModel.swift index aa4d5393..ac83166e 100644 --- a/core/Sources/BookmarksCore/Model/ItemViewModel.swift +++ b/core/Sources/BookmarksCore/Model/ItemViewModel.swift @@ -18,6 +18,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +#if os(macOS) + import Combine import SwiftUI @@ -25,7 +27,7 @@ import Interact class ItemViewModel: ObservableObject, Runnable { - let store: Store + let extensionModel: SafariExtensionModel let pinboard: Pinboard let tab: Tab @@ -36,13 +38,11 @@ class ItemViewModel: ObservableObject, Runnable { @Published var suggestions: [String] = [] @Published var tokens: [String] = [] - @Published var input: String = "" - @Published var newSuggestions: [String] = [] var cancellables: [AnyCancellable] = [] - init(store: Store, pinboard: Pinboard, tab: Tab) { - self.store = store + init(extensionModel: SafariExtensionModel, pinboard: Pinboard, tab: Tab) { + self.extensionModel = extensionModel self.pinboard = pinboard self.tab = tab self.title = tab.title @@ -69,14 +69,6 @@ class ItemViewModel: ObservableObject, Runnable { } } - $input - .debounce(for: 0.1, scheduler: DispatchQueue.main) - .filter { !$0.isEmpty } - .receive(on: DispatchQueue.main) - .map { [store] in store.suggestions(prefix: $0, existing: [], count: 1) } - .assign(to: \.newSuggestions, on: self) - .store(in: &cancellables) - } func stop() { @@ -91,7 +83,7 @@ class ItemViewModel: ObservableObject, Runnable { post.tags = tokens _ = try await pinboard.postsAdd(post) DispatchQueue.main.async { - self.store.close(self.tab) + self.extensionModel.close(self.tab) } } else { let post = Pinboard.Post(href: self.tab.url, @@ -99,7 +91,7 @@ class ItemViewModel: ObservableObject, Runnable { tags: tokens) _ = try await pinboard.postsAdd(post) DispatchQueue.main.async { - self.store.close(self.tab) + self.extensionModel.close(self.tab) } } } catch { @@ -110,18 +102,20 @@ class ItemViewModel: ObservableObject, Runnable { func close() { withAnimation { - store.close(tab) + extensionModel.close(tab) } } func remove() { withAnimation { - store.close(tab) + extensionModel.close(tab) } } func activate() { - store.activate(tab) + extensionModel.activate(tab) } } + +#endif diff --git a/core/Sources/BookmarksCore/Model/SafariExtensionModel.swift b/core/Sources/BookmarksCore/Model/SafariExtensionModel.swift index a8563c74..8a4fb3d4 100644 --- a/core/Sources/BookmarksCore/Model/SafariExtensionModel.swift +++ b/core/Sources/BookmarksCore/Model/SafariExtensionModel.swift @@ -23,13 +23,16 @@ import SafariServices import SwiftUI -public class SafariExtensionModel: ObservableObject, Store { +public class SafariExtensionModel: ObservableObject { let settings = Settings() + let tagsModel: TagsModel @Published public var tabs: [Tab] = [] - var tags = Trie() + private static let database: Database = { + try! Database(path: Database.sharedStoreURL) + }() public var pinboard: Pinboard? { guard let apiKey = settings.pinboardApiKey else { @@ -39,29 +42,12 @@ public class SafariExtensionModel: ObservableObject, Store { } public init() { - - } - - public func update() { - // TODO: Show the authentication state to the user. - guard let pinboard = pinboard else { - return - } - Task { - do { - let tags = try await pinboard.tagsGet() - let trie = Trie(words: tags.keys.map({ $0.lowercased() })) - DispatchQueue.main.async { - self.tags = trie - } - } catch { - NSLog("Failed to get tags with error \(error)") - } - } + self.tagsModel = TagsModel(database: Self.database) + tagsModel.start() } - public func suggestions(prefix: String, existing: [String], count: Int) -> [String] { - tags.suggestions(for: prefix, count: count) + @MainActor public func suggestions(prefix: String, existing: [String], count: Int) -> [String] { + return tagsModel.suggestions(candidate: prefix, existing: existing, count: count) } public func close(_ tab: Tab) { diff --git a/core/Sources/BookmarksCore/Model/Store.swift b/core/Sources/BookmarksCore/Model/Store.swift deleted file mode 100644 index 147044ba..00000000 --- a/core/Sources/BookmarksCore/Model/Store.swift +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2020-2023 InSeven Limited -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -import Combine -import SwiftUI - -public protocol Store { - - func close(_ tab: Tab) - func activate(_ tab: Tab) - func suggestions(prefix: String, existing: [String], count: Int) -> [String] - -} diff --git a/core/Sources/BookmarksCore/Views/ItemView.swift b/core/Sources/BookmarksCore/Views/ItemView.swift index 7edb8158..c903429b 100644 --- a/core/Sources/BookmarksCore/Views/ItemView.swift +++ b/core/Sources/BookmarksCore/Views/ItemView.swift @@ -26,14 +26,14 @@ import WrappingHStack public struct ItemView: View { - let store: Store + var extensionModel: SafariExtensionModel @StateObject var model: ItemViewModel @State var title: String? = nil - public init(store: Store, pinboard: Pinboard, tab: Tab) { - self.store = store - _model = StateObject(wrappedValue: ItemViewModel(store: store, pinboard: pinboard, tab: tab)) + public init(extensionModel: SafariExtensionModel, pinboard: Pinboard, tab: Tab) { + self.extensionModel = extensionModel + _model = StateObject(wrappedValue: ItemViewModel(extensionModel: extensionModel, pinboard: pinboard, tab: tab)) } struct LayoutMetrics { @@ -62,7 +62,7 @@ public struct ItemView: View { Divider() TokenView("Add tags...", tokens: $model.tokens) { candidate, existing, count in - return store.suggestions(prefix: candidate, existing: existing, count: count) + return extensionModel.suggestions(prefix: candidate, existing: existing, count: count) } .padding(.horizontal, 6) diff --git a/macos/SafariExtension/ContentView.swift b/macos/SafariExtension/ContentView.swift index e067e2fb..c5ffae5d 100644 --- a/macos/SafariExtension/ContentView.swift +++ b/macos/SafariExtension/ContentView.swift @@ -34,7 +34,7 @@ struct ContentView: View { List { if let pinboard = extensionModel.pinboard { ForEach(Array(extensionModel.tabs)) { tab in - ItemView(store: extensionModel, pinboard: pinboard, tab: tab) + ItemView(extensionModel: extensionModel, pinboard: pinboard, tab: tab) Divider() } } else {