diff --git a/Kiwix-iOS/Controller/Library/LibraryBooksController.swift b/Kiwix-iOS/Controller/Library/LibraryBooksController.swift index f0f4b1be..e6dd1d23 100644 --- a/Kiwix-iOS/Controller/Library/LibraryBooksController.swift +++ b/Kiwix-iOS/Controller/Library/LibraryBooksController.swift @@ -225,7 +225,7 @@ class LibraryBooksController: CoreDataCollectionBaseController, UICollectionView if isCloudTab { let displayedLanguages = Language.fetch(displayed: true, context: managedObjectContext) return NSCompoundPredicate(andPredicateWithSubpredicates: [ - NSPredicate(format: "stateRaw == 0 OR stateRaw == 1"), + NSPredicate(format: "stateRaw == 0"), displayedLanguages.count > 0 ? NSPredicate(format: "language IN %@", displayedLanguages) : NSPredicate(format: "language.name != nil") ]) } else { @@ -239,6 +239,7 @@ class LibraryBooksController: CoreDataCollectionBaseController, UICollectionView try? fetchedResultController.performFetch() collectionView.reloadData() } + } extension Localized { diff --git a/Kiwix-iOS/Controller/Others/CoreDataCollectionBaseController.swift b/Kiwix-iOS/Controller/Others/CoreDataCollectionBaseController.swift index 23703ad7..962b901e 100644 --- a/Kiwix-iOS/Controller/Others/CoreDataCollectionBaseController.swift +++ b/Kiwix-iOS/Controller/Others/CoreDataCollectionBaseController.swift @@ -13,14 +13,17 @@ class CoreDataCollectionBaseController: UIViewController, NSFetchedResultsContro @IBOutlet weak var collectionView: UICollectionView! - private(set) var shouldReloadCollectionView = false + private(set) var shouldReloadCollectionView = false {didSet{ print("shouldReload: \(shouldReloadCollectionView)")}} private var closures = [() -> Void]() - func controller(_ controller: NSFetchedResultsController, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) { + func controller(_ controller: NSFetchedResultsController, + didChange anObject: Any, at indexPath: IndexPath?, + for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) { switch type { case .insert: guard collectionView.numberOfSections > 0, let newIndexPath = newIndexPath, + newIndexPath.section + 1 <= collectionView.numberOfSections, collectionView.numberOfItems(inSection: newIndexPath.section) > 0 else { shouldReloadCollectionView = true break @@ -58,6 +61,7 @@ class CoreDataCollectionBaseController: UIViewController, NSFetchedResultsContro OperationQueue.main.addOperation({ if self.shouldReloadCollectionView { self.collectionView.reloadData() + self.closures.removeAll() } else { self.collectionView.performBatchUpdates({ self.closures.forEach({ $0() }) diff --git a/Kiwix-iOS/Storyboard/Library.storyboard b/Kiwix-iOS/Storyboard/Library.storyboard index af9329b0..f8d81eb2 100644 --- a/Kiwix-iOS/Storyboard/Library.storyboard +++ b/Kiwix-iOS/Storyboard/Library.storyboard @@ -22,7 +22,7 @@ - + diff --git a/Kiwix/Network/Network.swift b/Kiwix/Network/Network.swift index c0d7814d..0ea698e3 100644 --- a/Kiwix/Network/Network.swift +++ b/Kiwix/Network/Network.swift @@ -30,19 +30,23 @@ class Network: NSObject, URLSessionDelegate, URLSessionTaskDelegate, URLSessionD // MARK: - actions - func start(book: Book) { - guard let url = book.url else {return} - let task = (book.fileSize > 100000000 ? wifiSession: cellularSession).downloadTask(with: url) - task.taskDescription = book.id - task.resume() - - let downloadTask = DownloadTask.fetch(bookID: book.id, context: managedObjectContext) - downloadTask?.state = .queued - - if self.managedObjectContext.hasChanges { try? self.managedObjectContext.save() } - - progresses[book.id] = 0 - if progresses.count == 1 { startTimer() } + func startDownload(bookID: String) { + self.managedObjectContext.perform { + guard let book = Book.fetch(bookID, context: self.managedObjectContext) else {return} + book.state = .local + } +// guard let url = book.url else {return} +// let task = (book.fileSize > 100000000 ? wifiSession: cellularSession).downloadTask(with: url) +// task.taskDescription = book.id +// task.resume() +// +// let downloadTask = DownloadTask.fetch(bookID: book.id, context: managedObjectContext) +// downloadTask?.state = .queued +// +// if self.managedObjectContext.hasChanges { try? self.managedObjectContext.save() } +// +// progresses[book.id] = 0 +// if progresses.count == 1 { startTimer() } } func pause(bookID: String) { @@ -105,18 +109,23 @@ class Network: NSObject, URLSessionDelegate, URLSessionTaskDelegate, URLSessionD // MARK: - URLSessionTaskDelegate func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { - + guard let bookID = task.taskDescription else {return} + if let data = (error as? NSError)?.userInfo[NSURLSessionDownloadTaskResumeData] as? Data { + Preference.resumeData[bookID] = data + self.managedObjectContext.perform({ + guard let book = Book.fetch(bookID, context: self.managedObjectContext) else {return} + book.downloadTask?.state = .paused + }) + } } // MARK: - URLSessionDownloadDelegate - func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didResumeAtOffset fileOffset: Int64, expectedTotalBytes: Int64) { - - } - func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) { managedObjectContext.perform { - guard let bookID = downloadTask.taskDescription else {return} + guard let bookID = downloadTask.taskDescription, + let book = Book.fetch(bookID, context: self.managedObjectContext) else {return} + if book.state != .downloading {book.state = .downloading} self.progresses[bookID] = totalBytesWritten } } diff --git a/Kiwix/Operations/UIProcedure.swift b/Kiwix/Operations/UIProcedure.swift index 6d68ee3a..deefb3c1 100644 --- a/Kiwix/Operations/UIProcedure.swift +++ b/Kiwix/Operations/UIProcedure.swift @@ -88,17 +88,29 @@ extension AlertProcedure { } static func bookMore(context: UIViewController, book: Book) -> AlertProcedure { + assert(Thread.isMainThread, "The more") let alert = AlertProcedure(presentAlertFrom: context, withPreferredStyle: .actionSheet, waitForDismissal: true) alert.title = book.title - alert.add(actionWithTitle: Localized.Library.download, style: .default) { _ in - Network.shared.start(book: book) - alert.finish() - } - alert.add(actionWithTitle: Localized.Library.copyURL, style: .default) { _ in - guard let url = book.url else {return} - UIPasteboard.general.string = url.absoluteString - alert.finish() + if book.state == .cloud { + alert.add(actionWithTitle: Localized.Library.download, style: .default) { _ in + Network.shared.startDownload(bookID: book.id) + alert.finish() + } + alert.add(actionWithTitle: Localized.Library.copyURL, style: .default) { _ in + guard let url = book.url else {return} + UIPasteboard.general.string = url.absoluteString + alert.finish() + } + } else if book.state == .local { + alert.add(actionWithTitle: "set back to cloud", style: .default) { _ in + let context = AppDelegate.persistentContainer.viewContext + context.perform({ + book.state = .cloud + }) + alert.finish() + } } + alert.add(actionWithTitle: Localized.Common.cancel, style: .cancel) { _ in alert.finish() } return alert }