mirror of
https://github.com/kiwix/kiwix-apple.git
synced 2025-09-07 11:12:27 -04:00

* setup * RootView setup * open url * ReadingView * ReadingView * webview delegate * webview outlint * sidebar * buttons * bar buttons * reader view model * reader view model * ReadingView iOS * NavigationTitleSubtitle * map * introspect * content group * setting navigation * WebViewCoordinator * webview state * outline * root view iOS macos * ios buttons * OutlineMenu * OutlineMenu * outlint tree * webview gesture * bookmark button * merge notification * BookmarkMultiButton * ArticleCell * ArticleCell * data model * iOS bookmarks * bookmark loading * search * RandomArticle * MainArticleMenuButton * MoreActionMenu * swiftui4 * BarSetupModifier * RootView_SwiftUI4 * NavigationItem * purge & renaming * bookmarks * welcome no content * welcome no content * file importer * macos library hookup * library iOS setup * Library * Library setup * buttons * library setup * CategoryList * predicates * grid * settings view * RootView_SwiftUI4 * RootView * root view * RootView_iOS * ios reading view model * rootview * onchange * ios bars * reading view iOS 16 button * bookmark sort * mvoe * project setting * focus * NavigationItemButtons * patches * PageZoomButtons * FocusedSceneValue modifier * pagezoom observer * search view * SearchView * dismiss search * min detail view size * search result * SearchView * resrch * dismiss search on url change * search view * ios search setup * search * macos search * ios search * remove old search * use searchbar * searching * ios memory leak * WebViewConfiguration * macOS webview * refactor * SearchBar setup * search bar setup * SearchBar setup * searchbar * ReadingView * webview ref * outline * sheet * toolbar title outline * compact reading view * settings * recent search * reading view * reading view * SearchView * several small changes * shortcuts * commands buttons * macos command * navigation action * patch * revert * webview retention * navigation focused scene value * ipad keyboard shortcut * macos app min fheight * ios sheet action * macOS 13 build * purge * move * move * indent * settings * file import * rename * GridCommon * library views * purge * remove LibraryTopic * LibraryView_iOS * move * coredata context * add url binding * ZimFileSelection * pass url down * ZimFileDetail * load main page * revert * macos 12 compile * reading view empty title * view model * onboarding view * root view iOS 16 * ios search * root view * OutlineTree * search overlay * library view * library refresh views * view model * view model * LibraryViewModel * zim file detail * zim file detail styling * zim file detail * library detail & refresh * ZimFileContextMenu * directory monitor * LibraryOperations * LibraryOperations * reopen * migration * zim file migration * bookmark migration * comments * open zim file via bookmark * welcome view * hide bookmark section when empty * bookmark context menu setup * bookmark add / delete view model * skip notification * refactor view modifier * remove old code
136 lines
5.2 KiB
Swift
136 lines
5.2 KiB
Swift
//
|
|
// LibraryOperations.swift
|
|
// Kiwix
|
|
//
|
|
// Created by Chris Li on 9/12/22.
|
|
// Copyright © 2022 Chris Li. All rights reserved.
|
|
//
|
|
|
|
import CoreData
|
|
import os
|
|
|
|
struct LibraryOperations {
|
|
private init() {}
|
|
|
|
// MARK: - Open
|
|
|
|
/// Open a zim file with url
|
|
/// - Parameter url: url of the zim file
|
|
static func open(url: URL) {
|
|
guard let metadata = ZimFileService.getMetaData(url: url),
|
|
let fileURLBookmark = ZimFileService.getBookmarkData(url: url) else { return }
|
|
// open the file
|
|
do {
|
|
try ZimFileService.shared.open(bookmark: fileURLBookmark)
|
|
} catch {
|
|
return
|
|
}
|
|
|
|
// upsert zim file in the database
|
|
Database.shared.container.performBackgroundTask { context in
|
|
context.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
|
|
let predicate = NSPredicate(format: "fileID == %@", metadata.fileID as CVarArg)
|
|
let fetchRequest = ZimFile.fetchRequest(predicate: predicate)
|
|
guard let zimFile = try? context.fetch(fetchRequest).first ?? ZimFile(context: context) else { return }
|
|
LibraryOperations.configureZimFile(zimFile, metadata: metadata)
|
|
zimFile.fileURLBookmark = fileURLBookmark
|
|
zimFile.isMissing = false
|
|
if context.hasChanges { try? context.save() }
|
|
}
|
|
}
|
|
|
|
/// Reopen zim files from url bookmark data.
|
|
static func reopen() {
|
|
var successCount = 0
|
|
let context = Database.shared.container.viewContext
|
|
let request = ZimFile.fetchRequest(predicate: ZimFile.withFileURLBookmarkPredicate)
|
|
|
|
guard let zimFiles = try? context.fetch(request) else { return }
|
|
zimFiles.forEach { zimFile in
|
|
guard let data = zimFile.fileURLBookmark else { return }
|
|
do {
|
|
if let data = try ZimFileService.shared.open(bookmark: data) {
|
|
zimFile.fileURLBookmark = data
|
|
}
|
|
zimFile.isMissing = false
|
|
successCount += 1
|
|
} catch ZimFileOpenError.missing {
|
|
zimFile.isMissing = true
|
|
} catch {
|
|
zimFile.fileURLBookmark = nil
|
|
zimFile.isMissing = false
|
|
}
|
|
}
|
|
if context.hasChanges {
|
|
try? context.save()
|
|
}
|
|
|
|
os_log("Reopened %d out of %d zim files", log: Log.LibraryOperations, type: .info, successCount, zimFiles.count)
|
|
}
|
|
|
|
/// Scan a directory and open available zim files inside it
|
|
/// - Parameter url: directory to scan
|
|
static func scanDirectory(_ url: URL) {
|
|
guard let fileURLs = try? FileManager.default.contentsOfDirectory(
|
|
at: url,
|
|
includingPropertiesForKeys: nil,
|
|
options: [.skipsHiddenFiles, .skipsPackageDescendants, .skipsSubdirectoryDescendants]
|
|
).filter({ $0.pathExtension == "zim"}) else { return }
|
|
os_log("Discovered %d probable zim files.", log: Log.LibraryOperations, type: .info, fileURLs.count)
|
|
for fileURL in fileURLs {
|
|
LibraryOperations.open(url: fileURL)
|
|
}
|
|
}
|
|
|
|
// MARK: - Configure
|
|
|
|
/// Configure a zim file object based on its metadata.
|
|
static func configureZimFile(_ zimFile: ZimFile, metadata: ZimFileMetaData) {
|
|
zimFile.articleCount = metadata.articleCount.int64Value
|
|
zimFile.category = metadata.category
|
|
zimFile.created = metadata.creationDate
|
|
zimFile.fileDescription = metadata.fileDescription
|
|
zimFile.fileID = metadata.fileID
|
|
zimFile.flavor = metadata.flavor
|
|
zimFile.hasDetails = metadata.hasDetails
|
|
zimFile.hasPictures = metadata.hasPictures
|
|
zimFile.hasVideos = metadata.hasVideos
|
|
zimFile.languageCode = metadata.languageCode
|
|
zimFile.mediaCount = metadata.mediaCount.int64Value
|
|
zimFile.name = metadata.title
|
|
zimFile.persistentID = metadata.groupIdentifier
|
|
zimFile.requiresServiceWorkers = metadata.requiresServiceWorkers
|
|
zimFile.size = metadata.size.int64Value
|
|
|
|
// Only overwrite favicon data and url if there is a new value
|
|
if let url = metadata.downloadURL { zimFile.downloadURL = url }
|
|
if let url = metadata.faviconURL { zimFile.faviconURL = url }
|
|
}
|
|
|
|
//MARK: - Deletion
|
|
|
|
/// Unlink a zim file from library, and delete the file.
|
|
/// - Parameter zimFile: the zim file to delete
|
|
static func delete(zimFileID: UUID) {
|
|
LibraryOperations.unlink(zimFileID: zimFileID)
|
|
}
|
|
|
|
/// Unlink a zim file from library, but don't delete the file.
|
|
/// - Parameter zimFile: the zim file to unlink
|
|
static func unlink(zimFileID: UUID) {
|
|
ZimFileService.shared.close(fileID: zimFileID)
|
|
|
|
Database.shared.container.performBackgroundTask { context in
|
|
context.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
|
|
guard let zimFile = try? ZimFile.fetchRequest(fileID: zimFileID).execute().first else { return }
|
|
if zimFile.downloadURL == nil {
|
|
context.delete(zimFile)
|
|
} else {
|
|
zimFile.fileURLBookmark = nil
|
|
zimFile.isMissing = false
|
|
}
|
|
if context.hasChanges { try? context.save() }
|
|
}
|
|
}
|
|
}
|