mirror of
https://github.com/kiwix/kiwix-apple.git
synced 2025-09-25 21:05:09 -04:00
core data migration
This commit is contained in:
parent
8c7141854f
commit
257943b3a5
@ -94,14 +94,15 @@ class BookDetailController: UITableViewController, DZNEmptyDataSetSource, DZNEmp
|
||||
cellTitles.append([])
|
||||
}
|
||||
|
||||
if let isLocal = book.isLocal?.boolValue {
|
||||
if isLocal {
|
||||
cellTitles[1] = [LocalizedStrings.remove]
|
||||
} else {
|
||||
cellTitles[1] = book.spaceState == .NotEnough ? [LocalizedStrings.spaceNotEnough] : [LocalizedStrings.download]
|
||||
}
|
||||
} else {
|
||||
switch book.state {
|
||||
case .Cloud:
|
||||
cellTitles[1] = book.spaceState == .NotEnough ? [LocalizedStrings.spaceNotEnough] : [LocalizedStrings.download]
|
||||
case .Downloading:
|
||||
cellTitles[1] = [LocalizedStrings.downloading]
|
||||
case .Local:
|
||||
cellTitles[1] = [LocalizedStrings.remove]
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -336,7 +336,7 @@ class CloudBooksController: UITableViewController, NSFetchedResultsControllerDel
|
||||
}
|
||||
|
||||
private var onlineCompoundPredicate: NSCompoundPredicate {
|
||||
let isCloudPredicate = NSPredicate(format: "isLocal == false")
|
||||
let isCloudPredicate = NSPredicate(format: "stateRaw == 0")
|
||||
return NSCompoundPredicate(andPredicateWithSubpredicates: [langPredicate, isCloudPredicate])
|
||||
}
|
||||
|
||||
|
@ -221,7 +221,7 @@ class DownloadTasksController: UITableViewController, NSFetchedResultsController
|
||||
// Remove resume data
|
||||
// Delete downloadTask object and set book to not local
|
||||
downloadTask.book?.removeResumeData()
|
||||
downloadTask.book?.isLocal = NSNumber(bool: false)
|
||||
downloadTask.book?.state = .Cloud
|
||||
self.managedObjectContext.deleteObject(downloadTask)
|
||||
}
|
||||
} else {
|
||||
|
@ -146,7 +146,7 @@ class LocalBooksController: UITableViewController, NSFetchedResultsControllerDel
|
||||
let langDescriptor = NSSortDescriptor(key: "language.name", ascending: true)
|
||||
let titleDescriptor = NSSortDescriptor(key: "title", ascending: true)
|
||||
fetchRequest.sortDescriptors = [langDescriptor, titleDescriptor]
|
||||
fetchRequest.predicate = NSPredicate(format: "isLocal == true")
|
||||
fetchRequest.predicate = NSPredicate(format: "stateRaw >= 2")
|
||||
let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext, sectionNameKeyPath: "language.name", cacheName: "LocalFRC" + NSBundle.buildVersion)
|
||||
fetchedResultsController.delegate = self
|
||||
fetchedResultsController.performFetch(deleteCache: false)
|
||||
|
@ -49,7 +49,7 @@
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.8.1047</string>
|
||||
<string>1.8.1070</string>
|
||||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
<false/>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
|
@ -21,7 +21,7 @@
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.8.1051</string>
|
||||
<string>1.8.1074</string>
|
||||
<key>NSExtension</key>
|
||||
<dict>
|
||||
<key>NSExtensionMainStoryboard</key>
|
||||
|
@ -81,13 +81,13 @@
|
||||
9764F5931D830EF200E0B1C4 /* liblzma.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 9764F5921D830EF200E0B1C4 /* liblzma.tbd */; };
|
||||
9764F5971D8339D500E0B1C4 /* JSInjection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9764F5961D8339D500E0B1C4 /* JSInjection.swift */; };
|
||||
9764F5991D833F2B00E0B1C4 /* KiwixURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9764F5981D833F2B00E0B1C4 /* KiwixURL.swift */; };
|
||||
9764F59F1D83553F00E0B1C4 /* 1.8.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = 9764F59E1D83553F00E0B1C4 /* 1.8.xcmappingmodel */; };
|
||||
9779C3141D4575AD0064CC8E /* NotificationCenter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 97E609F01D103DED00EBCB9D /* NotificationCenter.framework */; };
|
||||
9779C3171D4575AE0064CC8E /* TodayViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9779C3161D4575AE0064CC8E /* TodayViewController.swift */; };
|
||||
9779C31A1D4575AE0064CC8E /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9779C3181D4575AE0064CC8E /* MainInterface.storyboard */; };
|
||||
9779C31E1D4575AE0064CC8E /* Bookmarks.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 9779C3131D4575AD0064CC8E /* Bookmarks.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
9787BC211D9318300030D311 /* WelcomeController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9787BC201D9318300030D311 /* WelcomeController.swift */; };
|
||||
9787BC231D9318570030D311 /* TableOfContentsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9787BC221D9318570030D311 /* TableOfContentsController.swift */; };
|
||||
9787BC271D944E890030D311 /* 1.8.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = 9787BC261D944E890030D311 /* 1.8.xcmappingmodel */; };
|
||||
979C518D1CECAE4C001707F2 /* PreferenceWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979C518B1CECAE4C001707F2 /* PreferenceWindowController.swift */; };
|
||||
979CB60F1D04AD04005E1BA1 /* PreferenceTabController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979CB60E1D04AD04005E1BA1 /* PreferenceTabController.swift */; };
|
||||
979CB6C81D05CF37005E1BA1 /* SearchResultController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979CB6C71D05CF37005E1BA1 /* SearchResultController.swift */; };
|
||||
@ -302,7 +302,6 @@
|
||||
9764F5921D830EF200E0B1C4 /* liblzma.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = liblzma.tbd; path = usr/lib/liblzma.tbd; sourceTree = SDKROOT; };
|
||||
9764F5961D8339D500E0B1C4 /* JSInjection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSInjection.swift; path = Main/JSInjection.swift; sourceTree = "<group>"; };
|
||||
9764F5981D833F2B00E0B1C4 /* KiwixURL.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KiwixURL.swift; sourceTree = "<group>"; };
|
||||
9764F59E1D83553F00E0B1C4 /* 1.8.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; name = 1.8.xcmappingmodel; path = Kiwix/CoreData/Migration/1.8.xcmappingmodel; sourceTree = SOURCE_ROOT; };
|
||||
976A0C801D41619C0006A742 /* DZNEmptyDataSet.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DZNEmptyDataSet.framework; path = "../../../../Users/chrisli/Library/Developer/Xcode/DerivedData/Kiwix-ayxrfhaqnfxzendihdolvkklkmhk/Build/Products/Debug-iphoneos/DZNEmptyDataSet/DZNEmptyDataSet.framework"; sourceTree = "<group>"; };
|
||||
9779C3131D4575AD0064CC8E /* Bookmarks.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = Bookmarks.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
9779C3161D4575AE0064CC8E /* TodayViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayViewController.swift; sourceTree = "<group>"; };
|
||||
@ -310,6 +309,7 @@
|
||||
9779C31B1D4575AE0064CC8E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
9787BC201D9318300030D311 /* WelcomeController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = WelcomeController.swift; path = Others/WelcomeController.swift; sourceTree = "<group>"; };
|
||||
9787BC221D9318570030D311 /* TableOfContentsController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TableOfContentsController.swift; path = Others/TableOfContentsController.swift; sourceTree = "<group>"; };
|
||||
9787BC261D944E890030D311 /* 1.8.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; name = 1.8.xcmappingmodel; path = Kiwix/CoreData/Migration/1.8.xcmappingmodel; sourceTree = SOURCE_ROOT; };
|
||||
979C518B1CECAE4C001707F2 /* PreferenceWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PreferenceWindowController.swift; path = "Kiwix-OSX/Controllers/PreferenceWindowController.swift"; sourceTree = SOURCE_ROOT; };
|
||||
979CB60E1D04AD04005E1BA1 /* PreferenceTabController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PreferenceTabController.swift; path = Controllers/PreferenceTabController.swift; sourceTree = "<group>"; };
|
||||
979CB6C71D05CF37005E1BA1 /* SearchResultController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SearchResultController.swift; path = Controllers/SearchResultController.swift; sourceTree = "<group>"; };
|
||||
@ -545,7 +545,7 @@
|
||||
children = (
|
||||
97D6812F1D6F70EC00E5FA99 /* 1.5.xcmappingmodel */,
|
||||
97D681301D6F70EC00E5FA99 /* MigrationPolicy.swift */,
|
||||
9764F59E1D83553F00E0B1C4 /* 1.8.xcmappingmodel */,
|
||||
9787BC261D944E890030D311 /* 1.8.xcmappingmodel */,
|
||||
);
|
||||
name = Migration;
|
||||
path = Kiwix;
|
||||
@ -1542,7 +1542,7 @@
|
||||
97D681231D6F70AC00E5FA99 /* GlobalQueue.swift in Sources */,
|
||||
97A1FD3B1D6F724E00A80EE2 /* stringTools.cpp in Sources */,
|
||||
97A1FD321D6F723D00A80EE2 /* resourceTools.cpp in Sources */,
|
||||
9764F59F1D83553F00E0B1C4 /* 1.8.xcmappingmodel in Sources */,
|
||||
9787BC271D944E890030D311 /* 1.8.xcmappingmodel in Sources */,
|
||||
971A10321D022AD5007FC62C /* SearchBar.swift in Sources */,
|
||||
97E60A061D10504000EBCB9D /* LibraryBackupTBVC.swift in Sources */,
|
||||
97A1FD451D6F728200A80EE2 /* StringTools.swift in Sources */,
|
||||
|
@ -25,13 +25,13 @@
|
||||
shouldBeEnabled = "Yes"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Kiwix/Operations/GlobalQueue.swift"
|
||||
timestampString = "496186011.525439"
|
||||
filePath = "Kiwix/CoreData/Migration/MigrationPolicy.swift"
|
||||
timestampString = "496258633.225782"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "44"
|
||||
endingLineNumber = "44"
|
||||
landmarkName = "add(load:)"
|
||||
startingLineNumber = "20"
|
||||
endingLineNumber = "20"
|
||||
landmarkName = "bookState(bool:)"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
|
@ -25,11 +25,11 @@ extension Book {
|
||||
@NSManaged var hasPic: Bool
|
||||
@NSManaged var id: String
|
||||
@NSManaged var includeInSearch: Bool
|
||||
@NSManaged var isLocal: NSNumber?
|
||||
@NSManaged var mediaCount: Int64
|
||||
@NSManaged var meta4URL: String?
|
||||
@NSManaged var pid: String?
|
||||
@NSManaged var publisher: String?
|
||||
@NSManaged var stateRaw: Int16
|
||||
@NSManaged var title: String?
|
||||
|
||||
@NSManaged var articles: Set<Article>
|
||||
|
@ -112,7 +112,7 @@ class Book: NSManagedObject {
|
||||
|
||||
class func fetchLocal(context: NSManagedObjectContext) -> [ZimID: Book] {
|
||||
let fetchRequest = NSFetchRequest(entityName: "Book")
|
||||
let predicate = NSPredicate(format: "isLocal = true")
|
||||
let predicate = NSPredicate(format: "stateRaw == 2")
|
||||
fetchRequest.predicate = predicate
|
||||
let localBooks = fetch(fetchRequest, type: Book.self, context: context) ?? [Book]()
|
||||
|
||||
@ -218,6 +218,22 @@ class Book: NSManagedObject {
|
||||
|
||||
// MARK: - States
|
||||
|
||||
var state: BookState {
|
||||
get {
|
||||
switch stateRaw {
|
||||
case 0: return .Cloud
|
||||
case 1: return .Downloading
|
||||
case 2: return .Local
|
||||
case 3: return .Retained
|
||||
case 4: return .Purgeable
|
||||
default: return .Cloud
|
||||
}
|
||||
}
|
||||
set {
|
||||
stateRaw = Int16(newValue.rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
var spaceState: BookSpaceState {
|
||||
guard let freeSpaceInBytes = UIDevice.availableDiskSpace?.freeSize else {return .Enough}
|
||||
if (0.8 * Double(freeSpaceInBytes)) > Double(fileSize) {
|
||||
@ -230,6 +246,11 @@ class Book: NSManagedObject {
|
||||
}
|
||||
}
|
||||
|
||||
enum BookState: Int {
|
||||
case Cloud, Downloading, Local, Retained, Purgeable
|
||||
}
|
||||
|
||||
|
||||
enum BookSpaceState: Int {
|
||||
case Enough, Caution, NotEnough
|
||||
}
|
||||
|
@ -1,11 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="11232" systemVersion="16A319" minimumToolsVersion="Xcode 7.3" sourceLanguage="Objective-C" userDefinedModelVersionIdentifier="1.8">
|
||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="11232" systemVersion="16A323" minimumToolsVersion="Xcode 7.3" sourceLanguage="Objective-C" userDefinedModelVersionIdentifier="1.8">
|
||||
<entity name="Article" representedClassName=".Article" syncable="YES">
|
||||
<attribute name="bookmarkDate" optional="YES" attributeType="Date" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="isBookmarked" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
|
||||
<attribute name="isMainPage" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
|
||||
<attribute name="lastPosition" optional="YES" attributeType="Double" usesScalarValueType="YES" syncable="YES"/>
|
||||
<attribute name="lastReadDate" optional="YES" attributeType="Date" usesScalarValueType="NO" indexed="YES" syncable="YES"/>
|
||||
<attribute name="needsUpdate" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
|
||||
<attribute name="snippet" optional="YES" attributeType="String" syncable="YES"/>
|
||||
<attribute name="thumbImageURL" optional="YES" attributeType="String" syncable="YES"/>
|
||||
<attribute name="title" attributeType="String" syncable="YES"/>
|
||||
@ -35,11 +36,11 @@
|
||||
<attribute name="hasPic" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
|
||||
<attribute name="id" attributeType="String" syncable="YES"/>
|
||||
<attribute name="includeInSearch" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES" syncable="YES"/>
|
||||
<attribute name="isLocal" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="mediaCount" optional="YES" attributeType="Integer 64" minValueString="0" defaultValueString="0" usesScalarValueType="YES" syncable="YES"/>
|
||||
<attribute name="meta4URL" optional="YES" attributeType="String" syncable="YES"/>
|
||||
<attribute name="pid" optional="YES" attributeType="String" syncable="YES"/>
|
||||
<attribute name="publisher" optional="YES" attributeType="String" syncable="YES"/>
|
||||
<attribute name="stateRaw" attributeType="Integer 16" defaultValueString="NO" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="title" optional="YES" attributeType="String" indexed="YES" syncable="YES"/>
|
||||
<relationship name="articles" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="Article" inverseName="book" inverseEntity="Article" syncable="YES"/>
|
||||
<relationship name="downloadTask" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="DownloadTask" inverseName="book" inverseEntity="DownloadTask" syncable="YES"/>
|
||||
@ -90,7 +91,7 @@
|
||||
<relationship name="articles" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Article" inverseName="tags" inverseEntity="Article" syncable="YES"/>
|
||||
</entity>
|
||||
<elements>
|
||||
<element name="Article" positionX="-657" positionY="-153" width="128" height="208"/>
|
||||
<element name="Article" positionX="-657" positionY="-153" width="128" height="225"/>
|
||||
<element name="Book" positionX="-947" positionY="-142" width="128" height="345"/>
|
||||
<element name="DownloadTask" positionX="-657" positionY="90" width="128" height="105"/>
|
||||
<element name="Language" positionX="-657" positionY="216" width="128" height="103"/>
|
||||
|
File diff suppressed because one or more lines are too long
@ -14,3 +14,13 @@ class MigrationPolicy1_5: NSEntityMigrationPolicy {
|
||||
return !bool
|
||||
}
|
||||
}
|
||||
|
||||
class MigrationPolicy1_8: NSEntityMigrationPolicy {
|
||||
func bookState(bool: NSNumber?) -> NSNumber {
|
||||
if let bool = bool?.boolValue {
|
||||
return bool ? NSNumber(integer: 2) : NSNumber(integer: 0)
|
||||
} else {
|
||||
return NSNumber(integer: 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ class DownloadBookOperation: URLSessionDownloadTaskOperation {
|
||||
guard let bookID = self.bookID,
|
||||
let book = Book.fetch(bookID, context: context),
|
||||
let downloadTask = DownloadTask.addOrUpdate(book, context: context) else {return}
|
||||
book.isLocal = nil
|
||||
book.state = .Downloading
|
||||
downloadTask.state = .Queued
|
||||
|
||||
// Overwrite progress
|
||||
@ -75,14 +75,14 @@ class DownloadBookOperation: URLSessionDownloadTaskOperation {
|
||||
context.performBlockAndWait({
|
||||
guard let bookID = self.bookID,
|
||||
let book = Book.fetch(bookID, context: context) else {return}
|
||||
book.isLocal = nil
|
||||
book.state = .Downloading
|
||||
})
|
||||
} else {
|
||||
let context = NSManagedObjectContext.mainQueueContext
|
||||
context.performBlockAndWait({
|
||||
guard let bookID = self.bookID,
|
||||
let book = Book.fetch(bookID, context: context) else {return}
|
||||
book.isLocal = false
|
||||
book.state = .Cloud
|
||||
|
||||
guard let downloadTask = book.downloadTask else {return}
|
||||
context.deleteObject(downloadTask)
|
||||
|
@ -114,7 +114,7 @@ private class Process: Operation, NSXMLParserDelegate, AutomaticInjectionOperati
|
||||
guard let book = Book.fetch(id, context: self.context) else {return}
|
||||
|
||||
// Delete Book object only if book is online, i.e., is not associated with a download task or is not local
|
||||
guard book.isLocal == false else {return}
|
||||
guard book.state == .Cloud else {return}
|
||||
self.context.deleteObject(book)
|
||||
self.hasUpdate = true
|
||||
})
|
||||
|
@ -74,7 +74,7 @@ class ScanLocalBookOperation: Operation {
|
||||
for id in removedZimFileIDs {
|
||||
guard let book = localBooks[id] else {continue}
|
||||
if let _ = book.meta4URL {
|
||||
book.isLocal = false
|
||||
book.state = .Cloud
|
||||
} else {
|
||||
context.deleteObject(book)
|
||||
}
|
||||
@ -86,7 +86,7 @@ class ScanLocalBookOperation: Operation {
|
||||
let book = Book.fetch(id, context: NSManagedObjectContext.mainQueueContext)
|
||||
return book ?? Book.add(reader.metaData, context: NSManagedObjectContext.mainQueueContext)
|
||||
}() else {return}
|
||||
book.isLocal = true
|
||||
book.state = .Local
|
||||
book.hasIndex = reader.hasIndex()
|
||||
book.hasPic = !reader.fileURL.absoluteString!.containsString("nopic")
|
||||
if let downloadTask = book.downloadTask {context.deleteObject(downloadTask)}
|
||||
|
@ -88,7 +88,8 @@ class ZimMultiReader: NSObject, DirectoryMonitorDelegate {
|
||||
|
||||
// MARK: - Loading System
|
||||
|
||||
func data(id: String, contentURLString: String) -> [String: AnyObject]? {
|
||||
func data(host: String, contentURLString: String) -> [String: AnyObject]? {
|
||||
let id = pidMap[host] ?? host
|
||||
guard let reader = readers[id] else {return nil}
|
||||
return reader.dataWithContentURLString(contentURLString) as? [String: AnyObject]
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user