mirror of
https://github.com/kiwix/kiwix-apple.git
synced 2025-09-09 04:06:57 -04:00
Format
This commit is contained in:
parent
fdac0fce0c
commit
6df6e9ba9e
@ -5,16 +5,16 @@
|
||||
// Copyright © 2023 Chris Li. All rights reserved.
|
||||
//
|
||||
|
||||
import WebKit
|
||||
import CoreLocation
|
||||
import WebKit
|
||||
|
||||
final class BrowserNavDelegate: NSObject, WKNavigationDelegate {
|
||||
|
||||
@Published private(set) var externalURL: URL?
|
||||
|
||||
func webView(_ webView: WKWebView,
|
||||
decidePolicyFor navigationAction: WKNavigationAction,
|
||||
decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
|
||||
decisionHandler: @escaping (WKNavigationActionPolicy) -> Void)
|
||||
{
|
||||
guard let url = navigationAction.request.url else { decisionHandler(.cancel); return }
|
||||
if url.isKiwixURL, let redirectedURL = ZimFileService.shared.getRedirectedURL(url: url) {
|
||||
DispatchQueue.main.async { webView.load(URLRequest(url: redirectedURL)) }
|
||||
@ -38,9 +38,9 @@ final class BrowserNavDelegate: NSObject, WKNavigationDelegate {
|
||||
let coordinate = url.absoluteString.replacingOccurrences(of: "geo:", with: "")
|
||||
if let url = URL(string: "http://maps.apple.com/?ll=\(coordinate)") {
|
||||
#if os(macOS)
|
||||
NSWorkspace.shared.open(url)
|
||||
NSWorkspace.shared.open(url)
|
||||
#elseif os(iOS)
|
||||
UIApplication.shared.open(url)
|
||||
UIApplication.shared.open(url)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -50,14 +50,14 @@ final class BrowserNavDelegate: NSObject, WKNavigationDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
|
||||
func webView(_ webView: WKWebView, didFinish _: WKNavigation!) {
|
||||
webView.evaluateJavaScript("expandAllDetailTags(); getOutlineItems();")
|
||||
#if os(iOS)
|
||||
webView.adjustTextSize()
|
||||
webView.adjustTextSize()
|
||||
#endif
|
||||
}
|
||||
|
||||
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
|
||||
func webView(_: WKWebView, didFailProvisionalNavigation _: WKNavigation!, withError error: Error) {
|
||||
let error = error as NSError
|
||||
guard error.code != NSURLErrorCancelled else { return }
|
||||
NotificationCenter.default.post(
|
||||
|
@ -11,7 +11,7 @@ final class BrowserScriptHandler: NSObject, WKScriptMessageHandler {
|
||||
@Published private(set) var outlineItems = [OutlineItem]()
|
||||
@Published private(set) var outlineItemTree = [OutlineItem]()
|
||||
|
||||
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
|
||||
func userContentController(_: WKUserContentController, didReceive message: WKScriptMessage) {
|
||||
if message.name == "headings", let headings = message.body as? [[String: String]] {
|
||||
DispatchQueue.global(qos: .userInitiated).async {
|
||||
self.generateOutlineList(headings: headings)
|
||||
@ -24,7 +24,7 @@ final class BrowserScriptHandler: NSObject, WKScriptMessageHandler {
|
||||
/// - Parameter headings: list of heading element data retrieved from webview
|
||||
private func generateOutlineList(headings: [[String: String]]) {
|
||||
let allLevels = headings.compactMap { Int($0["tag"]?.suffix(1) ?? "") }
|
||||
let offset = allLevels.filter({ $0 == 1 }).count == 1 ? 2 : allLevels.min() ?? 0
|
||||
let offset = allLevels.filter { $0 == 1 }.count == 1 ? 2 : allLevels.min() ?? 0
|
||||
let outlineItems: [OutlineItem] = headings.enumerated().compactMap { index, heading in
|
||||
guard let id = heading["id"],
|
||||
let text = heading["text"],
|
||||
|
@ -14,17 +14,17 @@ import WebKit
|
||||
import OrderedCollections
|
||||
|
||||
final class BrowserViewModel: NSObject, ObservableObject,
|
||||
NSFetchedResultsControllerDelegate
|
||||
NSFetchedResultsControllerDelegate
|
||||
{
|
||||
static private var cache = OrderedDictionary<NSManagedObjectID, BrowserViewModel>()
|
||||
|
||||
private static var cache = OrderedDictionary<NSManagedObjectID, BrowserViewModel>()
|
||||
|
||||
static func getCached(tabID: NSManagedObjectID) -> BrowserViewModel {
|
||||
let viewModel = cache[tabID] ?? BrowserViewModel(tabID: tabID)
|
||||
cache.removeValue(forKey: tabID)
|
||||
cache[tabID] = viewModel
|
||||
return viewModel
|
||||
}
|
||||
|
||||
|
||||
static func purgeCache() {
|
||||
guard cache.count > 10 else { return }
|
||||
let range = 0 ..< cache.count - 5
|
||||
@ -33,9 +33,9 @@ final class BrowserViewModel: NSObject, ObservableObject,
|
||||
}
|
||||
cache.removeSubrange(range)
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
|
||||
@Published private(set) var canGoBack = false
|
||||
@Published private(set) var canGoForward = false
|
||||
@Published private(set) var articleTitle: String = ""
|
||||
@ -60,10 +60,10 @@ final class BrowserViewModel: NSObject, ObservableObject,
|
||||
private var cancellables: Set<AnyCancellable> = []
|
||||
|
||||
// MARK: - Lifecycle
|
||||
|
||||
|
||||
init(tabID: NSManagedObjectID? = nil) {
|
||||
self.tabID = tabID
|
||||
self.webView = WKWebView(frame: .zero, configuration: WebViewConfiguration())
|
||||
webView = WKWebView(frame: .zero, configuration: WebViewConfiguration())
|
||||
scriptHandler = BrowserScriptHandler()
|
||||
navDelegate = BrowserNavDelegate()
|
||||
uiDelegate = BrowserUIDelegate()
|
||||
@ -93,7 +93,7 @@ final class BrowserViewModel: NSObject, ObservableObject,
|
||||
|
||||
// configure web view
|
||||
webView.allowsBackForwardNavigationGestures = true
|
||||
webView.configuration.defaultWebpagePreferences.preferredContentMode = .mobile // for font adjustment to work
|
||||
webView.configuration.defaultWebpagePreferences.preferredContentMode = .mobile // for font adjustment to work
|
||||
webView.configuration.userContentController.removeScriptMessageHandler(forName: "headings")
|
||||
webView.configuration.userContentController.add(scriptHandler, name: "headings")
|
||||
webView.navigationDelegate = navDelegate
|
||||
@ -103,7 +103,7 @@ final class BrowserViewModel: NSObject, ObservableObject,
|
||||
if webView.url != nil {
|
||||
webView.evaluateJavaScript("getOutlineItems();")
|
||||
}
|
||||
|
||||
|
||||
// setup web view property observers
|
||||
canGoBackObserver = webView.observe(\.canGoBack, options: .initial) { [weak self] webView, _ in
|
||||
self?.canGoBack = webView.canGoBack
|
||||
@ -129,24 +129,25 @@ final class BrowserViewModel: NSObject, ObservableObject,
|
||||
guard let url, let zimFileID = UUID(uuidString: url.host ?? "") else { return nil }
|
||||
return try? Database.viewContext.fetch(ZimFile.fetchRequest(fileID: zimFileID)).first
|
||||
}()
|
||||
|
||||
|
||||
// update view model
|
||||
self?.articleTitle = title ?? ""
|
||||
self?.zimFileName = zimFile?.name ?? ""
|
||||
self?.url = url
|
||||
|
||||
|
||||
// update tab data
|
||||
if let tabID = self?.tabID,
|
||||
let tab = try? Database.viewContext.existingObject(with: tabID) as? Tab,
|
||||
let title {
|
||||
let title
|
||||
{
|
||||
tab.title = title
|
||||
tab.zimFile = zimFile
|
||||
}
|
||||
|
||||
|
||||
// setup bookmark fetched results controller
|
||||
self?.bookmarkFetchedResultsController = NSFetchedResultsController(
|
||||
fetchRequest: Bookmark.fetchRequest(predicate: {
|
||||
if let url = url {
|
||||
if let url {
|
||||
return NSPredicate(format: "articleURL == %@", url as CVarArg)
|
||||
} else {
|
||||
return NSPredicate(format: "articleURL == nil")
|
||||
@ -160,44 +161,45 @@ final class BrowserViewModel: NSObject, ObservableObject,
|
||||
try? self?.bookmarkFetchedResultsController?.performFetch()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func updateLastOpened() {
|
||||
guard let tabID, let tab = try? Database.viewContext.existingObject(with: tabID) as? Tab else { return }
|
||||
tab.lastOpened = Date()
|
||||
}
|
||||
|
||||
|
||||
func persistState() {
|
||||
guard let tabID, let tab = try? Database.viewContext.existingObject(with: tabID) as? Tab else { return }
|
||||
tab.interactionState = webView.interactionState as? Data
|
||||
try? Database.viewContext.save()
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Content Loading
|
||||
|
||||
|
||||
func load(url: URL) {
|
||||
guard webView.url != url else { return }
|
||||
webView.load(URLRequest(url: url))
|
||||
}
|
||||
|
||||
|
||||
func loadRandomArticle(zimFileID: UUID? = nil) {
|
||||
let zimFileID = zimFileID ?? UUID(uuidString: webView.url?.host ?? "")
|
||||
guard let url = ZimFileService.shared.getRandomPageURL(zimFileID: zimFileID) else { return }
|
||||
load(url: url)
|
||||
}
|
||||
|
||||
|
||||
func loadMainArticle(zimFileID: UUID? = nil) {
|
||||
let zimFileID = zimFileID ?? UUID(uuidString: webView.url?.host ?? "")
|
||||
guard let url = ZimFileService.shared.getMainPageURL(zimFileID: zimFileID) else { return }
|
||||
load(url: url)
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Bookmark
|
||||
|
||||
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>,
|
||||
didChangeContentWith snapshot: NSDiffableDataSourceSnapshotReference) {
|
||||
|
||||
func controller(_: NSFetchedResultsController<NSFetchRequestResult>,
|
||||
didChangeContentWith snapshot: NSDiffableDataSourceSnapshotReference)
|
||||
{
|
||||
articleBookmarked = !snapshot.itemIdentifiers.isEmpty
|
||||
}
|
||||
|
||||
|
||||
func createBookmark(url: URL? = nil) {
|
||||
guard let url = url ?? webView.url else { return }
|
||||
Database.performBackgroundTask { context in
|
||||
@ -217,7 +219,7 @@ final class BrowserViewModel: NSObject, ObservableObject,
|
||||
try? context.save()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func deleteBookmark(url: URL? = nil) {
|
||||
guard let url = url ?? webView.url else { return }
|
||||
Database.performBackgroundTask { context in
|
||||
@ -227,9 +229,9 @@ final class BrowserViewModel: NSObject, ObservableObject,
|
||||
try? context.save()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Outline
|
||||
|
||||
|
||||
/// Scroll to an outline item
|
||||
/// - Parameter outlineItemID: ID of the outline item to scroll to
|
||||
func scrollTo(outlineItemID: String) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user