diff --git a/Kiwix.xcodeproj/project.pbxproj b/Kiwix.xcodeproj/project.pbxproj index 3068241b..900955fd 100644 --- a/Kiwix.xcodeproj/project.pbxproj +++ b/Kiwix.xcodeproj/project.pbxproj @@ -539,7 +539,6 @@ 9714D8D61C6E5C2600AABCA7 /* LTBarButtonItem.swift */, 9787E87B1C3D696E0000F529 /* RefreshHUD.swift */, 973381681C343F2C0016CEFB /* Logo.swift */, - 97999D881C52D27D003CAFF3 /* SearchBar.swift */, ); name = View; sourceTree = ""; @@ -582,6 +581,7 @@ 978C587B1C1CCCA30077AE47 /* Coredata */ = { isa = PBXGroup; children = ( + 97999D881C52D27D003CAFF3 /* SearchBar.swift */, 978C589D1C1CD8750077AE47 /* Properties */, 978C58901C1CD86E0077AE47 /* Book.swift */, 978C588E1C1CD86E0077AE47 /* Language.swift */, diff --git a/Kiwix/AlertOperations.swift b/Kiwix/AlertOperations.swift index 8366de04..9b610fba 100644 --- a/Kiwix/AlertOperations.swift +++ b/Kiwix/AlertOperations.swift @@ -35,9 +35,9 @@ class SpaceNotEnoughAlert: AlertOperation { } } -class LanguageFilterAlert: AlertOperation { +class RefreshLibraryLanguageFilterAlert: AlertOperation { let context = UIApplication.appDelegate.managedObjectContext - init(libraryOnlineTBVC: LibraryOnlineTBVC) { + init(libraryOnlineTBVC: LibraryOnlineTBVC?) { super.init(presentationContext: libraryOnlineTBVC) var preferredLanguageCodes = [String]() @@ -77,7 +77,7 @@ class LanguageFilterAlert: AlertOperation { guard let code = language.code else {continue} language.isDisplayed = preferredLanguageCodes.contains(code) } - libraryOnlineTBVC.refreshFetchedResultController() + libraryOnlineTBVC?.refreshFetchedResultController() }) } addAction(LocalizedStrings.cancel) @@ -91,3 +91,15 @@ class LanguageFilterAlert: AlertOperation { return a + " " + LocalizedStrings.and + " " + b } } + +class RefreshLibraryInternetRequiredAlert: AlertOperation { + override init(presentationContext: UIViewController?) { + super.init(presentationContext: presentationContext) + + let comment = "Library: Internet Required Alert" + + title = NSLocalizedString("Internet Connection Required", comment: comment) + message = NSLocalizedString("You need to connect to the Internet to refresh the library.", comment: comment) + addAction(LocalizedStrings.ok) + } +} diff --git a/Kiwix/AppDelegate.swift b/Kiwix/AppDelegate.swift index 7dbda577..f4956437 100644 --- a/Kiwix/AppDelegate.swift +++ b/Kiwix/AppDelegate.swift @@ -1,4 +1,3 @@ - // AppDelegate.swift // Kiwix // diff --git a/Kiwix/BookTableCell.swift b/Kiwix/BookTableCell.swift index 1dbe6cc9..748bfa26 100644 --- a/Kiwix/BookTableCell.swift +++ b/Kiwix/BookTableCell.swift @@ -10,7 +10,7 @@ import UIKit // MARK: - Normal Cells -class ScopeBookCell: UITableViewCell { +class BasicBookCell: UITableViewCell { private let hasPicIndicatorOrange = UIColor(red: 1, green: 0.5, blue: 0, alpha: 1) private let hasIndexIndicatorBlue = UIColor(red: 0.304706, green: 0.47158, blue: 1, alpha: 1) diff --git a/Kiwix/BookmarkTBVC.swift b/Kiwix/BookmarkTBVC.swift index 333a6335..4bb9357f 100644 --- a/Kiwix/BookmarkTBVC.swift +++ b/Kiwix/BookmarkTBVC.swift @@ -63,7 +63,7 @@ class BookmarkTBVC: UITableViewController, NSFetchedResultsControllerDelegate { } func configureCell(cell: UITableViewCell, atIndexPath indexPath: NSIndexPath) { - guard let cell = cell as? ArticleSnippetCell else {return} + guard let cell = cell as? ArticleCell else {return} guard let article = fetchedResultController.objectAtIndexPath(indexPath) as? Article else {return} guard let book = article.book else {return} diff --git a/Kiwix/HelpDocuments/LocalBookLearnMore.html b/Kiwix/HelpDocuments/LocalBookLearnMore.html index e3d0de7c..417e1b41 100644 --- a/Kiwix/HelpDocuments/LocalBookLearnMore.html +++ b/Kiwix/HelpDocuments/LocalBookLearnMore.html @@ -312,15 +312,26 @@ sup { -

Download a book

+

Add a book

-

Downloaded books will show up here automatically.

+ -

Import a book

+

About picture and index

-

Books added through iTunes will be automatically detected too. They instantly become searchable.

+ + +

Happy Reading!

diff --git a/Kiwix/HelpDocuments/LocalBookLearnMore.md b/Kiwix/HelpDocuments/LocalBookLearnMore.md index 5fd2bbdf..6da66910 100644 --- a/Kiwix/HelpDocuments/LocalBookLearnMore.md +++ b/Kiwix/HelpDocuments/LocalBookLearnMore.md @@ -1,9 +1,11 @@ -## Download a book -Downloaded books will show up here automatically. +## Add a book +* Download a book in app +* Add books through iTunes File Sharing. They will show up here automatically. -## Import a book -Books added through iTunes File Sharing will be detected automatically. They instantly become searchable. +## About picture and index +* Drawing indicates book has pictures +* Drawing indicates kiwix can find a idx folder associated with the book + * To add index, rename the idx folder to zim file name + .idx. For example, if the zim file is xyz.zim or xyz.zimaa, xyz.zimab, etc., name the idx folder xyz.zim.idx + * You may have to restart the app for Kiwix to recognize the idx folder -You can also include / exclude a book in search by going to main interface -> search bar -> search setting (the wrench icon). - -> Q: What does I \ No newline at end of file +###
Happy Reading!
\ No newline at end of file diff --git a/Kiwix/Library.storyboard b/Kiwix/Library.storyboard index 9f605bc9..e913f54c 100644 --- a/Kiwix/Library.storyboard +++ b/Kiwix/Library.storyboard @@ -3,6 +3,7 @@ + @@ -358,78 +359,119 @@ - + - + - - + + - - + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - + - - - - - + + + + + @@ -481,8 +523,8 @@ - - + + diff --git a/Kiwix/LibraryDownloadTBVC.swift b/Kiwix/LibraryDownloadTBVC.swift index 50a979e7..b59c9667 100644 --- a/Kiwix/LibraryDownloadTBVC.swift +++ b/Kiwix/LibraryDownloadTBVC.swift @@ -93,7 +93,8 @@ class LibraryDownloadTBVC: UITableViewController, NSFetchedResultsControllerDele } func configureMessage() { - guard let count = fetchedResultController.fetchedObjects?.count else {return} + guard let sectionInfos = fetchedResultController.sections else {messageButton.text = nil; return} + let count = sectionInfos.reduce(0) {$0 + $1.numberOfObjects} let localizedString = String.localizedStringWithFormat(NSLocalizedString("%d download tasks", comment: "Book Library, book downloader message"), count) messageButton.text = localizedString } @@ -227,12 +228,12 @@ class LibraryDownloadTBVC: UITableViewController, NSFetchedResultsControllerDele let book = downloadTask.book else {return} Network.sharedInstance.cancel(book) book.isLocal = false + FileManager.removeResumeData(book) let context = UIApplication.appDelegate.managedObjectContext context.performBlockAndWait({ () -> Void in book.isLocal = false context.deleteObject(downloadTask) }) - } return [remove] } diff --git a/Kiwix/LibraryLocalBookDetailTBVC.swift b/Kiwix/LibraryLocalBookDetailTBVC.swift index c4468812..a175e1c7 100644 --- a/Kiwix/LibraryLocalBookDetailTBVC.swift +++ b/Kiwix/LibraryLocalBookDetailTBVC.swift @@ -11,27 +11,53 @@ import UIKit class LibraryLocalBookDetailTBVC: UITableViewController { var book: Book? + let sections = [LocalizedStrings.info, LocalizedStrings.file] + let titles = [[LocalizedStrings.title, LocalizedStrings.creationDate, LocalizedStrings.articleCount, LocalizedStrings.mediaCount], + [LocalizedStrings.size, LocalizedStrings.fileName]] override func viewDidLoad() { super.viewDidLoad() title = book?.title } + override func viewWillAppear(animated: Bool) { + super.viewWillAppear(animated) + navigationController?.toolbarHidden = true + } + + override func viewWillDisappear(animated: Bool) { + super.viewWillDisappear(animated) + navigationController?.toolbarHidden = false + } + // MARK: - Table view data source override func numberOfSectionsInTableView(tableView: UITableView) -> Int { - return book == nil ? 0 : 1 + return book == nil ? 0 : sections.count } override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return 1 + return titles[section].count } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) - // Configure the cell... + cell.textLabel?.text = titles[indexPath.section][indexPath.row] + cell.detailTextLabel?.text = "placehold" return cell } } + +extension LocalizedStrings { + class var info: String {return NSLocalizedString("Info", comment: "Book Detail")} + class var title: String {return NSLocalizedString("Title", comment: "Book Detail")} + class var creationDate: String {return NSLocalizedString("Creation Date", comment: "Book Detail")} + class var articleCount: String {return NSLocalizedString("Article Count", comment: "Book Detail")} + class var mediaCount: String {return NSLocalizedString("Media Count", comment: "Book Detail")} + + class var file: String {return NSLocalizedString("File", comment: "Book Detail")} + class var size: String {return NSLocalizedString("size", comment: "Book Detail")} + class var fileName: String {return NSLocalizedString("File Name", comment: "Book Detail")} +} diff --git a/Kiwix/LibraryLocalTBVC.swift b/Kiwix/LibraryLocalTBVC.swift index 7c0b96fe..b6268147 100644 --- a/Kiwix/LibraryLocalTBVC.swift +++ b/Kiwix/LibraryLocalTBVC.swift @@ -135,12 +135,14 @@ class LibraryLocalTBVC: UITableViewController, NSFetchedResultsControllerDelegat func configureCell(cell: UITableViewCell, atIndexPath indexPath: NSIndexPath) { guard let book = fetchedResultController.objectAtIndexPath(indexPath) as? Book else {return} - guard let cell = cell as? LocalBookCell else {return} + guard let cell = cell as? BasicBookCell else {return} cell.titleLabel.text = book.title - cell.hasPicIndicator.backgroundColor = book.hasPic ? UIColor.havePicTintColor : UIColor.lightGrayColor() - cell.favIcon.image = UIImage(data: book.favIcon ?? NSData()) cell.subtitleLabel.text = book.detailedDescription1 + + cell.favIcon.image = UIImage(data: book.favIcon ?? NSData()) + cell.hasPic = book.hasPic + cell.hasIndex = book.hasIndex } // MARK: Other Data Source @@ -187,6 +189,9 @@ class LibraryLocalTBVC: UITableViewController, NSFetchedResultsControllerDelegat self.managedObjectContext.performBlock({ () -> Void in if let id = book.id, let zimURL = ZIMMultiReader.sharedInstance.readers[id]?.fileURL { FileManager.removeItem(atURL: zimURL) + + let indexFolderURL = zimURL.URLByAppendingPathExtension("idx") + FileManager.removeItem(atURL: indexFolderURL) } if let _ = book.url { diff --git a/Kiwix/LibraryOnlineTBVC.swift b/Kiwix/LibraryOnlineTBVC.swift index 304528ec..f128c14b 100644 --- a/Kiwix/LibraryOnlineTBVC.swift +++ b/Kiwix/LibraryOnlineTBVC.swift @@ -78,10 +78,6 @@ class LibraryOnlineTBVC: UITableViewController, NSFetchedResultsControllerDelega func refreshDidFinish() { configureRefreshStatus() configureToolBarVisibility(animated: true) - - guard !Preference.libraryHasShownPreferredLanguagePrompt else {return} - let langFilterOperation = LanguageFilterAlert(libraryOnlineTBVC: self) - UIApplication.appDelegate.globalOperationQueue.addOperation(langFilterOperation) } // MARK: - Others @@ -139,7 +135,8 @@ class LibraryOnlineTBVC: UITableViewController, NSFetchedResultsControllerDelega func configureMessage(isRefreshing isRefreshing: Bool = false) { if !isRefreshing { - guard let count = fetchedResultController.fetchedObjects?.count else {messageButton.text = nil; return} + guard let sectionInfos = fetchedResultController.sections else {messageButton.text = nil; return} + let count = sectionInfos.reduce(0) {$0 + $1.numberOfObjects} let localizedBookCountString = String.localizedStringWithFormat(NSLocalizedString("%d book(s) available for download", comment: "Book Library, online book catalogue message"), count) guard count > 0 else {messageButton.text = localizedBookCountString; return} guard let lastRefreshTime = Preference.libraryLastRefreshTime else {messageButton.text = localizedBookCountString; return} diff --git a/Kiwix/Main.storyboard b/Kiwix/Main.storyboard index 5c36142a..7519725b 100644 --- a/Kiwix/Main.storyboard +++ b/Kiwix/Main.storyboard @@ -372,7 +372,7 @@ - + @@ -402,7 +402,7 @@ - + + + + + + + @@ -506,7 +512,7 @@ - + @@ -1005,7 +1011,7 @@ - + @@ -1089,42 +1095,11 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/Kiwix/MainVC.swift b/Kiwix/MainVC.swift index 5cb0c4e0..d442231a 100644 --- a/Kiwix/MainVC.swift +++ b/Kiwix/MainVC.swift @@ -30,7 +30,7 @@ class MainVC: UIViewController { super.viewDidLoad() webView.delegate = self - webView.scrollView.delegate = self + webView.scrollView.delegate = nil navigationItem.titleView = searchBar searchBar.delegate = self diff --git a/Kiwix/RefreshLibraryOperation.swift b/Kiwix/RefreshLibraryOperation.swift index 745740d2..9edb684d 100644 --- a/Kiwix/RefreshLibraryOperation.swift +++ b/Kiwix/RefreshLibraryOperation.swift @@ -12,8 +12,10 @@ import CoreData class RefreshLibraryOperation: GroupOperation { weak var delegate: RefreshLibraryOperationDelegate? + weak var presentationContext: LibraryOnlineTBVC? var completionHandler: (() -> Void)? - init(invokedAutomatically: Bool = true, completionHandler: (() -> Void)? = nil) { + + init(invokedAutomatically: Bool, presentationContext: LibraryOnlineTBVC? = nil, completionHandler: (() -> Void)? = nil) { super.init(operations: []) name = String(RefreshLibraryOperation) @@ -48,6 +50,7 @@ class RefreshLibraryOperation: GroupOperation { if invokedAutomatically { addCondition(AllowAutoRefreshCondition()) addCondition(LibraryIsOldCondition()) + addCondition(ReachabilityCondition(host: url, allowCellular: Preference.libraryRefreshAllowCellularData)) } addOperation(fetchOperation) @@ -56,7 +59,14 @@ class RefreshLibraryOperation: GroupOperation { } override func finished(errors: [NSError]) { - + if let firstError = errors.first { + if firstError.code == .NetworkError { + produceOperation(RefreshLibraryInternetRequiredAlert(presentationContext: presentationContext)) + } + } else { + guard !Preference.libraryHasShownPreferredLanguagePrompt else {return} + produceOperation(RefreshLibraryLanguageFilterAlert(libraryOnlineTBVC: presentationContext)) + } } } diff --git a/Kiwix/SearchHistoryTBVC.swift b/Kiwix/SearchHistoryTBVC.swift index e790180e..8d40ec18 100644 --- a/Kiwix/SearchHistoryTBVC.swift +++ b/Kiwix/SearchHistoryTBVC.swift @@ -14,8 +14,6 @@ class SearchHistoryTBVC: UITableViewController, NSFetchedResultsControllerDelega override func viewDidLoad() { super.viewDidLoad() } - - // MARK: - Fetched Results Controller @@ -53,6 +51,17 @@ class SearchHistoryTBVC: UITableViewController, NSFetchedResultsControllerDelega cell.textLabel?.text = article.title } + // MARK: - Table view delegates + + override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { + guard let mainVC = parentViewController?.parentViewController?.parentViewController as? MainVC, + let article = fetchedResultController.objectAtIndexPath(indexPath) as? Article else {return} + mainVC.hideSearch() + mainVC.load(article.url) + + tableView.deselectRowAtIndexPath(indexPath, animated: true) + } + // MARK: - Fetched Result Controller Delegate func controllerWillChangeContent(controller: NSFetchedResultsController) { diff --git a/Kiwix/SearchScopeSelectTBVC.swift b/Kiwix/SearchScopeSelectTBVC.swift index 5027664e..8c6ee345 100644 --- a/Kiwix/SearchScopeSelectTBVC.swift +++ b/Kiwix/SearchScopeSelectTBVC.swift @@ -24,7 +24,7 @@ class SearchScopeSelectTBVC: UITableViewController, NSFetchedResultsControllerDe let titleDescriptor = NSSortDescriptor(key: "title", ascending: true) fetchRequest.sortDescriptors = [langDescriptor, titleDescriptor] fetchRequest.predicate = NSPredicate(format: "isLocal == true") - let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext, sectionNameKeyPath: "language.name", cacheName: "ScopeFRC") + let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext, sectionNameKeyPath: nil, cacheName: "ScopeFRC") fetchedResultsController.delegate = self fetchedResultsController.performFetch(deleteCache: false) return fetchedResultsController @@ -37,12 +37,8 @@ class SearchScopeSelectTBVC: UITableViewController, NSFetchedResultsControllerDe } override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - if section == 0 { - guard let sectionInfo = fetchedResultController.sections?[section] else {return 0} - return sectionInfo.numberOfObjects - } else { - return 0 - } + guard let sectionInfo = fetchedResultController.sections?[section] else {return 0} + return sectionInfo.numberOfObjects } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { @@ -53,7 +49,7 @@ class SearchScopeSelectTBVC: UITableViewController, NSFetchedResultsControllerDe func configureCell(cell: UITableViewCell, atIndexPath indexPath: NSIndexPath) { guard let book = fetchedResultController.objectAtIndexPath(indexPath) as? Book else {return} - guard let cell = cell as? ScopeBookCell else {return} + guard let cell = cell as? BasicBookCell else {return} cell.titleLabel.text = book.title cell.subtitleLabel.text = book.detailedDescription @@ -76,7 +72,6 @@ class SearchScopeSelectTBVC: UITableViewController, NSFetchedResultsControllerDe // MARK: Table view delegate override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - //guard tableView.numberOfSections > 1 else {return 0.0} guard let headerText = self.tableView(tableView, titleForHeaderInSection: section) else {return 0.0} guard headerText != "" else {return 0.0} return 20.0