core data migration

This commit is contained in:
Chris Li 2016-09-22 14:10:48 -04:00
parent 8c7141854f
commit 257943b3a5
17 changed files with 67 additions and 351 deletions

View File

@ -94,14 +94,15 @@ class BookDetailController: UITableViewController, DZNEmptyDataSetSource, DZNEmp
cellTitles.append([]) cellTitles.append([])
} }
if let isLocal = book.isLocal?.boolValue { switch book.state {
if isLocal { case .Cloud:
cellTitles[1] = [LocalizedStrings.remove] cellTitles[1] = book.spaceState == .NotEnough ? [LocalizedStrings.spaceNotEnough] : [LocalizedStrings.download]
} else { case .Downloading:
cellTitles[1] = book.spaceState == .NotEnough ? [LocalizedStrings.spaceNotEnough] : [LocalizedStrings.download]
}
} else {
cellTitles[1] = [LocalizedStrings.downloading] cellTitles[1] = [LocalizedStrings.downloading]
case .Local:
cellTitles[1] = [LocalizedStrings.remove]
default:
break
} }
} }

View File

@ -336,7 +336,7 @@ class CloudBooksController: UITableViewController, NSFetchedResultsControllerDel
} }
private var onlineCompoundPredicate: NSCompoundPredicate { private var onlineCompoundPredicate: NSCompoundPredicate {
let isCloudPredicate = NSPredicate(format: "isLocal == false") let isCloudPredicate = NSPredicate(format: "stateRaw == 0")
return NSCompoundPredicate(andPredicateWithSubpredicates: [langPredicate, isCloudPredicate]) return NSCompoundPredicate(andPredicateWithSubpredicates: [langPredicate, isCloudPredicate])
} }

View File

@ -221,7 +221,7 @@ class DownloadTasksController: UITableViewController, NSFetchedResultsController
// Remove resume data // Remove resume data
// Delete downloadTask object and set book to not local // Delete downloadTask object and set book to not local
downloadTask.book?.removeResumeData() downloadTask.book?.removeResumeData()
downloadTask.book?.isLocal = NSNumber(bool: false) downloadTask.book?.state = .Cloud
self.managedObjectContext.deleteObject(downloadTask) self.managedObjectContext.deleteObject(downloadTask)
} }
} else { } else {

View File

@ -146,7 +146,7 @@ class LocalBooksController: UITableViewController, NSFetchedResultsControllerDel
let langDescriptor = NSSortDescriptor(key: "language.name", ascending: true) let langDescriptor = NSSortDescriptor(key: "language.name", ascending: true)
let titleDescriptor = NSSortDescriptor(key: "title", ascending: true) let titleDescriptor = NSSortDescriptor(key: "title", ascending: true)
fetchRequest.sortDescriptors = [langDescriptor, titleDescriptor] 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) let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext, sectionNameKeyPath: "language.name", cacheName: "LocalFRC" + NSBundle.buildVersion)
fetchedResultsController.delegate = self fetchedResultsController.delegate = self
fetchedResultsController.performFetch(deleteCache: false) fetchedResultsController.performFetch(deleteCache: false)

View File

@ -49,7 +49,7 @@
</dict> </dict>
</array> </array>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.8.1047</string> <string>1.8.1070</string>
<key>ITSAppUsesNonExemptEncryption</key> <key>ITSAppUsesNonExemptEncryption</key>
<false/> <false/>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>

View File

@ -21,7 +21,7 @@
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.8.1051</string> <string>1.8.1074</string>
<key>NSExtension</key> <key>NSExtension</key>
<dict> <dict>
<key>NSExtensionMainStoryboard</key> <key>NSExtensionMainStoryboard</key>

View File

@ -81,13 +81,13 @@
9764F5931D830EF200E0B1C4 /* liblzma.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 9764F5921D830EF200E0B1C4 /* liblzma.tbd */; }; 9764F5931D830EF200E0B1C4 /* liblzma.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 9764F5921D830EF200E0B1C4 /* liblzma.tbd */; };
9764F5971D8339D500E0B1C4 /* JSInjection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9764F5961D8339D500E0B1C4 /* JSInjection.swift */; }; 9764F5971D8339D500E0B1C4 /* JSInjection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9764F5961D8339D500E0B1C4 /* JSInjection.swift */; };
9764F5991D833F2B00E0B1C4 /* KiwixURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9764F5981D833F2B00E0B1C4 /* KiwixURL.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 */; }; 9779C3141D4575AD0064CC8E /* NotificationCenter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 97E609F01D103DED00EBCB9D /* NotificationCenter.framework */; };
9779C3171D4575AE0064CC8E /* TodayViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9779C3161D4575AE0064CC8E /* TodayViewController.swift */; }; 9779C3171D4575AE0064CC8E /* TodayViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9779C3161D4575AE0064CC8E /* TodayViewController.swift */; };
9779C31A1D4575AE0064CC8E /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9779C3181D4575AE0064CC8E /* MainInterface.storyboard */; }; 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, ); }; }; 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 */; }; 9787BC211D9318300030D311 /* WelcomeController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9787BC201D9318300030D311 /* WelcomeController.swift */; };
9787BC231D9318570030D311 /* TableOfContentsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9787BC221D9318570030D311 /* TableOfContentsController.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 */; }; 979C518D1CECAE4C001707F2 /* PreferenceWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979C518B1CECAE4C001707F2 /* PreferenceWindowController.swift */; };
979CB60F1D04AD04005E1BA1 /* PreferenceTabController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979CB60E1D04AD04005E1BA1 /* PreferenceTabController.swift */; }; 979CB60F1D04AD04005E1BA1 /* PreferenceTabController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979CB60E1D04AD04005E1BA1 /* PreferenceTabController.swift */; };
979CB6C81D05CF37005E1BA1 /* SearchResultController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979CB6C71D05CF37005E1BA1 /* SearchResultController.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; }; 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>"; }; 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>"; }; 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>"; }; 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; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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; }; 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>"; }; 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>"; }; 979CB6C71D05CF37005E1BA1 /* SearchResultController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SearchResultController.swift; path = Controllers/SearchResultController.swift; sourceTree = "<group>"; };
@ -545,7 +545,7 @@
children = ( children = (
97D6812F1D6F70EC00E5FA99 /* 1.5.xcmappingmodel */, 97D6812F1D6F70EC00E5FA99 /* 1.5.xcmappingmodel */,
97D681301D6F70EC00E5FA99 /* MigrationPolicy.swift */, 97D681301D6F70EC00E5FA99 /* MigrationPolicy.swift */,
9764F59E1D83553F00E0B1C4 /* 1.8.xcmappingmodel */, 9787BC261D944E890030D311 /* 1.8.xcmappingmodel */,
); );
name = Migration; name = Migration;
path = Kiwix; path = Kiwix;
@ -1542,7 +1542,7 @@
97D681231D6F70AC00E5FA99 /* GlobalQueue.swift in Sources */, 97D681231D6F70AC00E5FA99 /* GlobalQueue.swift in Sources */,
97A1FD3B1D6F724E00A80EE2 /* stringTools.cpp in Sources */, 97A1FD3B1D6F724E00A80EE2 /* stringTools.cpp in Sources */,
97A1FD321D6F723D00A80EE2 /* resourceTools.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 */, 971A10321D022AD5007FC62C /* SearchBar.swift in Sources */,
97E60A061D10504000EBCB9D /* LibraryBackupTBVC.swift in Sources */, 97E60A061D10504000EBCB9D /* LibraryBackupTBVC.swift in Sources */,
97A1FD451D6F728200A80EE2 /* StringTools.swift in Sources */, 97A1FD451D6F728200A80EE2 /* StringTools.swift in Sources */,

View File

@ -25,13 +25,13 @@
shouldBeEnabled = "Yes" shouldBeEnabled = "Yes"
ignoreCount = "0" ignoreCount = "0"
continueAfterRunningActions = "No" continueAfterRunningActions = "No"
filePath = "Kiwix/Operations/GlobalQueue.swift" filePath = "Kiwix/CoreData/Migration/MigrationPolicy.swift"
timestampString = "496186011.525439" timestampString = "496258633.225782"
startingColumnNumber = "9223372036854775807" startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807"
startingLineNumber = "44" startingLineNumber = "20"
endingLineNumber = "44" endingLineNumber = "20"
landmarkName = "add(load:)" landmarkName = "bookState(bool:)"
landmarkType = "7"> landmarkType = "7">
</BreakpointContent> </BreakpointContent>
</BreakpointProxy> </BreakpointProxy>

View File

@ -25,11 +25,11 @@ extension Book {
@NSManaged var hasPic: Bool @NSManaged var hasPic: Bool
@NSManaged var id: String @NSManaged var id: String
@NSManaged var includeInSearch: Bool @NSManaged var includeInSearch: Bool
@NSManaged var isLocal: NSNumber?
@NSManaged var mediaCount: Int64 @NSManaged var mediaCount: Int64
@NSManaged var meta4URL: String? @NSManaged var meta4URL: String?
@NSManaged var pid: String? @NSManaged var pid: String?
@NSManaged var publisher: String? @NSManaged var publisher: String?
@NSManaged var stateRaw: Int16
@NSManaged var title: String? @NSManaged var title: String?
@NSManaged var articles: Set<Article> @NSManaged var articles: Set<Article>

View File

@ -112,7 +112,7 @@ class Book: NSManagedObject {
class func fetchLocal(context: NSManagedObjectContext) -> [ZimID: Book] { class func fetchLocal(context: NSManagedObjectContext) -> [ZimID: Book] {
let fetchRequest = NSFetchRequest(entityName: "Book") let fetchRequest = NSFetchRequest(entityName: "Book")
let predicate = NSPredicate(format: "isLocal = true") let predicate = NSPredicate(format: "stateRaw == 2")
fetchRequest.predicate = predicate fetchRequest.predicate = predicate
let localBooks = fetch(fetchRequest, type: Book.self, context: context) ?? [Book]() let localBooks = fetch(fetchRequest, type: Book.self, context: context) ?? [Book]()
@ -218,6 +218,22 @@ class Book: NSManagedObject {
// MARK: - States // 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 { var spaceState: BookSpaceState {
guard let freeSpaceInBytes = UIDevice.availableDiskSpace?.freeSize else {return .Enough} guard let freeSpaceInBytes = UIDevice.availableDiskSpace?.freeSize else {return .Enough}
if (0.8 * Double(freeSpaceInBytes)) > Double(fileSize) { 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 { enum BookSpaceState: Int {
case Enough, Caution, NotEnough case Enough, Caution, NotEnough
} }

View File

@ -1,11 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?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"> <entity name="Article" representedClassName=".Article" syncable="YES">
<attribute name="bookmarkDate" optional="YES" attributeType="Date" usesScalarValueType="NO" 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="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="isMainPage" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
<attribute name="lastPosition" optional="YES" attributeType="Double" 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="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="snippet" optional="YES" attributeType="String" syncable="YES"/>
<attribute name="thumbImageURL" optional="YES" attributeType="String" syncable="YES"/> <attribute name="thumbImageURL" optional="YES" attributeType="String" syncable="YES"/>
<attribute name="title" 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="hasPic" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
<attribute name="id" attributeType="String" syncable="YES"/> <attribute name="id" attributeType="String" syncable="YES"/>
<attribute name="includeInSearch" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES" 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="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="meta4URL" optional="YES" attributeType="String" syncable="YES"/>
<attribute name="pid" 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="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"/> <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="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"/> <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"/> <relationship name="articles" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Article" inverseName="tags" inverseEntity="Article" syncable="YES"/>
</entity> </entity>
<elements> <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="Book" positionX="-947" positionY="-142" width="128" height="345"/>
<element name="DownloadTask" positionX="-657" positionY="90" width="128" height="105"/> <element name="DownloadTask" positionX="-657" positionY="90" width="128" height="105"/>
<element name="Language" positionX="-657" positionY="216" width="128" height="103"/> <element name="Language" positionX="-657" positionY="216" width="128" height="103"/>

File diff suppressed because one or more lines are too long

View File

@ -14,3 +14,13 @@ class MigrationPolicy1_5: NSEntityMigrationPolicy {
return !bool 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)
}
}
}

View File

@ -31,7 +31,7 @@ class DownloadBookOperation: URLSessionDownloadTaskOperation {
guard let bookID = self.bookID, guard let bookID = self.bookID,
let book = Book.fetch(bookID, context: context), let book = Book.fetch(bookID, context: context),
let downloadTask = DownloadTask.addOrUpdate(book, context: context) else {return} let downloadTask = DownloadTask.addOrUpdate(book, context: context) else {return}
book.isLocal = nil book.state = .Downloading
downloadTask.state = .Queued downloadTask.state = .Queued
// Overwrite progress // Overwrite progress
@ -75,14 +75,14 @@ class DownloadBookOperation: URLSessionDownloadTaskOperation {
context.performBlockAndWait({ context.performBlockAndWait({
guard let bookID = self.bookID, guard let bookID = self.bookID,
let book = Book.fetch(bookID, context: context) else {return} let book = Book.fetch(bookID, context: context) else {return}
book.isLocal = nil book.state = .Downloading
}) })
} else { } else {
let context = NSManagedObjectContext.mainQueueContext let context = NSManagedObjectContext.mainQueueContext
context.performBlockAndWait({ context.performBlockAndWait({
guard let bookID = self.bookID, guard let bookID = self.bookID,
let book = Book.fetch(bookID, context: context) else {return} let book = Book.fetch(bookID, context: context) else {return}
book.isLocal = false book.state = .Cloud
guard let downloadTask = book.downloadTask else {return} guard let downloadTask = book.downloadTask else {return}
context.deleteObject(downloadTask) context.deleteObject(downloadTask)

View File

@ -114,7 +114,7 @@ private class Process: Operation, NSXMLParserDelegate, AutomaticInjectionOperati
guard let book = Book.fetch(id, context: self.context) else {return} 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 // 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.context.deleteObject(book)
self.hasUpdate = true self.hasUpdate = true
}) })

View File

@ -74,7 +74,7 @@ class ScanLocalBookOperation: Operation {
for id in removedZimFileIDs { for id in removedZimFileIDs {
guard let book = localBooks[id] else {continue} guard let book = localBooks[id] else {continue}
if let _ = book.meta4URL { if let _ = book.meta4URL {
book.isLocal = false book.state = .Cloud
} else { } else {
context.deleteObject(book) context.deleteObject(book)
} }
@ -86,7 +86,7 @@ class ScanLocalBookOperation: Operation {
let book = Book.fetch(id, context: NSManagedObjectContext.mainQueueContext) let book = Book.fetch(id, context: NSManagedObjectContext.mainQueueContext)
return book ?? Book.add(reader.metaData, context: NSManagedObjectContext.mainQueueContext) return book ?? Book.add(reader.metaData, context: NSManagedObjectContext.mainQueueContext)
}() else {return} }() else {return}
book.isLocal = true book.state = .Local
book.hasIndex = reader.hasIndex() book.hasIndex = reader.hasIndex()
book.hasPic = !reader.fileURL.absoluteString!.containsString("nopic") book.hasPic = !reader.fileURL.absoluteString!.containsString("nopic")
if let downloadTask = book.downloadTask {context.deleteObject(downloadTask)} if let downloadTask = book.downloadTask {context.deleteObject(downloadTask)}

View File

@ -88,7 +88,8 @@ class ZimMultiReader: NSObject, DirectoryMonitorDelegate {
// MARK: - Loading System // 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} guard let reader = readers[id] else {return nil}
return reader.dataWithContentURLString(contentURLString) as? [String: AnyObject] return reader.dataWithContentURLString(contentURLString) as? [String: AnyObject]
} }