diff --git a/Shared/CoreData/Book.swift b/Shared/CoreData/Book.swift index c4762eae..0c457057 100644 --- a/Shared/CoreData/Book.swift +++ b/Shared/CoreData/Book.swift @@ -18,45 +18,45 @@ import CoreData class Book: NSManagedObject { // MARK: - Fetch - + class func fetchAll(context: NSManagedObjectContext) -> [Book] { let request = Book.fetchRequest() as! NSFetchRequest return (try? context.fetch(request)) ?? [Book]() } - + class func fetch(states: [BookState], context: NSManagedObjectContext) -> [Book] { let request = Book.fetchRequest() as! NSFetchRequest request.predicate = NSPredicate(format: "stateRaw IN %@", states.map({ $0.rawValue }) ) return (try? context.fetch(request)) ?? [Book]() } - + class func fetch(id: String, context: NSManagedObjectContext) -> Book? { let request = Book.fetchRequest() as! NSFetchRequest request.predicate = NSPredicate(format: "id = %@", id) return (try? context.fetch(request))?.first } - + class func fetch(pid: String, context: NSManagedObjectContext) -> [Book] { let request = Book.fetchRequest() as! NSFetchRequest request.predicate = NSPredicate(format: "pid = %@", pid) request.sortDescriptors = [NSSortDescriptor(key: "date", ascending: false)] return (try? context.fetch(request)) ?? [Book]() } - + // MARK: - Properties - + var url: URL? { guard let meta4URL = meta4URL else {return nil} var urlComponents = URLComponents(string: meta4URL.replacingOccurrences(of: ".meta4", with: "")) urlComponents?.scheme = "https" return urlComponents?.url } - + var state: BookState { get { return BookState(rawValue: Int(stateRaw)) ?? .cloud } set { stateRaw = Int16(newValue.rawValue) } } - + @objc var sectionIndex: Int { get { switch state { @@ -71,26 +71,26 @@ class Book: NSManagedObject { } } } - + // MARK: - Properties Description - + static private let dateFormatter: DateFormatter = { let formatter = DateFormatter() formatter.dateFormat = "MM-dd-yyyy" formatter.dateStyle = .medium return formatter }() - + var dateDescription: String? { guard let date = date else {return nil} return Book.dateFormatter.string(from: date) } - + var fileSizeDescription: String? { guard fileSize != 0 else {return nil} return ByteCountFormatter.string(fromByteCount: fileSize, countStyle: .file) } - + var articleCountDescription: String? { guard articleCount != 0 else {return nil} return BookArticleCountFormatter.string(num: articleCount) + (articleCount > 1 ? " articles" : " article") @@ -111,7 +111,7 @@ class BookArticleCountFormatter { enum BookState: Int { case cloud = 0, downloadQueued, downloading, downloadPaused, downloadError, local, retained - + var shortLocalizedDescription: String { switch self { case .cloud: @@ -138,14 +138,13 @@ enum BookCategory: String { case wikipedia case wikiquote case wikisource - case wikispecies case wikiversity case wikivoyage case wiktionary - + case ted case vikidia case stackExchange - + case other } diff --git a/Shared/Model/ZimFile.swift b/Shared/Model/ZimFile.swift index a853e1c7..24336cde 100644 --- a/Shared/Model/ZimFile.swift +++ b/Shared/Model/ZimFile.swift @@ -104,7 +104,6 @@ class ZimFile: Object { case wikipedia case wikiquote case wikisource - case wikispecies case wikiversity case wikivoyage case wiktionary @@ -127,8 +126,6 @@ class ZimFile: Object { return NSLocalizedString("Wikiquote", comment: "Zim File Category") case .wikisource: return NSLocalizedString("Wikisource", comment: "Zim File Category") - case .wikispecies: - return NSLocalizedString("Wikispecies", comment: "Zim File Category") case .wikiversity: return NSLocalizedString("Wikiversity", comment: "Zim File Category") case .wikivoyage: @@ -158,8 +155,6 @@ class ZimFile: Object { return #imageLiteral(resourceName: "Wikiquote") case .wikisource: return #imageLiteral(resourceName: "Wikisource") - case .wikispecies: - return #imageLiteral(resourceName: "Wikispecies") case .wikiversity: return #imageLiteral(resourceName: "Wikiversity") case .wikivoyage: diff --git a/iOS/Assets.xcassets/Logo/Wikispecies.imageset/Contents.json b/iOS/Assets.xcassets/Logo/Wikispecies.imageset/Contents.json deleted file mode 100644 index 89ff2017..00000000 --- a/iOS/Assets.xcassets/Logo/Wikispecies.imageset/Contents.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "Wikispecies.png", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/iOS/Assets.xcassets/Logo/Wikispecies.imageset/Wikispecies.png b/iOS/Assets.xcassets/Logo/Wikispecies.imageset/Wikispecies.png deleted file mode 100644 index 56fafac7..00000000 Binary files a/iOS/Assets.xcassets/Logo/Wikispecies.imageset/Wikispecies.png and /dev/null differ diff --git a/iOS/Controller/Library/LibraryMasterController.swift b/iOS/Controller/Library/LibraryMasterController.swift index c79f2ad3..422ae099 100644 --- a/iOS/Controller/Library/LibraryMasterController.swift +++ b/iOS/Controller/Library/LibraryMasterController.swift @@ -15,18 +15,19 @@ class LibraryMasterController: UIViewController, UIDocumentPickerDelegate, UITab private let tableView = UITableView(frame: .zero, style: .grouped) private let refreshControl = UIRefreshControl() private let searchController = UISearchController(searchResultsController: LibrarySearchController()) - + private var sections: [Section] = [.category] private let categories: [ZimFile.Category] = [ - .wikipedia, .wikibooks, .wikinews, .wikiquote, .wikisource, .wikispecies, - .wikiversity, .wikivoyage, .wiktionary, .vikidia, .ted, .stackExchange, .other] - + .wikipedia, .wikibooks, .wikinews, .wikiquote, .wikisource, .wikiversity, + .wikivoyage, .wiktionary, .vikidia, .ted, .stackExchange, .other] + // MARK: - Database - + /* Note: localZimFilesCount & downloadZimFilesCount are kept here as a cache of the row count of each section, since tableview update for each section is submitted separately. */ + private var localZimFilesCount: Int = 0 private var downloadZimFilesCount: Int = 0 private let localZimFiles: Results? = { @@ -46,9 +47,9 @@ class LibraryMasterController: UIViewController, UIDocumentPickerDelegate, UITab }() private var localZimFilesChangeToken: NotificationToken? private var downloadZimFilesChangeToken: NotificationToken? - + // MARK: - Overrides - + override func loadView() { view = tableView tableView.delegate = self @@ -60,7 +61,7 @@ class LibraryMasterController: UIViewController, UIDocumentPickerDelegate, UITab tableView.register(TableViewCell.self, forCellReuseIdentifier: "CategoryCell") tableView.separatorInset = UIEdgeInsets(top: 0, left: tableView.separatorInset.left + 42, bottom: 0, right: 0) } - + override func viewDidLoad() { super.viewDidLoad() title = NSLocalizedString("Library", comment: "Library title") @@ -68,7 +69,7 @@ class LibraryMasterController: UIViewController, UIDocumentPickerDelegate, UITab navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(openDocumentPicker)) refreshControl.addTarget(self, action: #selector(refreshControlPulled), for: .valueChanged) refreshControl.attributedTitle = NSAttributedString(string: NSLocalizedString("Pull to refresh", comment: "Library: refresh control")) - + if #available(iOS 11.0, *) { navigationItem.searchController = searchController searchController.searchBar.autocapitalizationType = .none @@ -76,44 +77,44 @@ class LibraryMasterController: UIViewController, UIDocumentPickerDelegate, UITab searchController.searchResultsUpdater = searchController.searchResultsController as? LibrarySearchController definesPresentationContext = true } - + if splitViewController?.traitCollection.horizontalSizeClass == .regular { let firstIndexPath = IndexPath(row: 0, section: 0) tableView.delegate?.tableView?(tableView, didSelectRowAt: firstIndexPath) } - + if #available(iOS 11.0, *) { navigationController?.navigationBar.prefersLargeTitles = true navigationItem.largeTitleDisplayMode = .always } } - + override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) configureSections() configureChangeToken() } - + override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) localZimFilesChangeToken = nil downloadZimFilesChangeToken = nil } - + // MARK: - Utilities - + func selectFirstCategory() { guard let index = sections.firstIndex(of: .category) else {return} let indexPath = IndexPath(row: 0, section: index) tableView.delegate?.tableView?(tableView, didSelectRowAt: indexPath) } - + // MARK: - UIControl Actions - + @objc func dismissController() { dismiss(animated: true, completion: nil) } - + @objc func refreshControlPulled() { let operation = LibraryRefreshOperation(updateExisting: true) operation.completionBlock = { @@ -129,9 +130,9 @@ class LibraryMasterController: UIViewController, UIDocumentPickerDelegate, UITab controller.delegate = self present(controller, animated: true) } - + // MARK: - Configurations - + private func configureSections() { if let localZimFiles = localZimFiles { localZimFilesCount = localZimFiles.count @@ -152,7 +153,7 @@ class LibraryMasterController: UIViewController, UIDocumentPickerDelegate, UITab } tableView.reloadData() } - + private func configureChangeToken() { localZimFilesChangeToken = localZimFiles?.observe({ (changes) in switch changes { @@ -163,12 +164,12 @@ class LibraryMasterController: UIViewController, UIDocumentPickerDelegate, UITab self.sections.insert(.local, at: 0) self.tableView.insertSections(IndexSet([0]), with: .fade) } - + if results.count == 0, let sectionIndex = self.sections.firstIndex(of: .local) { self.sections.remove(at: sectionIndex) self.tableView.deleteSections(IndexSet([sectionIndex]), with: .fade) } - + if let sectionIndex = self.sections.firstIndex(of: .local) { self.tableView.deleteRows(at: deletions.map({ IndexPath(row: $0, section: sectionIndex) }), with: .fade) self.tableView.insertRows(at: insertions.map({ IndexPath(row: $0, section: sectionIndex) }), with: .fade) @@ -193,12 +194,12 @@ class LibraryMasterController: UIViewController, UIDocumentPickerDelegate, UITab self.sections.insert(.download, at: sectionIndex) self.tableView.insertSections(IndexSet([sectionIndex]), with: .fade) } - + if results.count == 0, let sectionIndex = self.sections.firstIndex(of: .download) { self.sections.remove(at: sectionIndex) self.tableView.deleteSections(IndexSet([sectionIndex]), with: .fade) } - + if let sectionIndex = self.sections.firstIndex(of: .download) { self.tableView.deleteRows(at: deletions.map({ IndexPath(row: $0, section: sectionIndex) }), with: .fade) self.tableView.insertRows(at: insertions.map({ IndexPath(row: $0, section: sectionIndex) }), with: .fade) @@ -214,9 +215,9 @@ class LibraryMasterController: UIViewController, UIDocumentPickerDelegate, UITab } }) } - + // MARK: - UIDocumentPickerDelegate - + func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) { if let _ = ZimMultiReader.getMetaData(url: url) { present(FileImportController(fileURL: url), animated: true) @@ -224,13 +225,13 @@ class LibraryMasterController: UIViewController, UIDocumentPickerDelegate, UITab present(FileImportAlertController(fileName: url.lastPathComponent), animated: true) } } - + // MARK: - UITableViewDataSource & Delegates - + func numberOfSections(in tableView: UITableView) -> Int { return sections.count } - + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { switch sections[section] { case .local: @@ -241,7 +242,7 @@ class LibraryMasterController: UIViewController, UIDocumentPickerDelegate, UITab return categories.count } } - + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { switch sections[indexPath.section] { case .local: @@ -262,7 +263,7 @@ class LibraryMasterController: UIViewController, UIDocumentPickerDelegate, UITab return cell } } - + func configure(localCell cell: TableViewCell, row: Int, animated: Bool = false) { guard let zimFile = localZimFiles?[row] else {return} cell.titleLabel.text = zimFile.title @@ -271,7 +272,7 @@ class LibraryMasterController: UIViewController, UIDocumentPickerDelegate, UITab cell.thumbImageView.contentMode = .scaleAspectFit cell.accessoryType = .disclosureIndicator } - + func configure(downloadCell cell: TableViewCell, row: Int, animated: Bool = false) { guard let zimFile = downloadZimFiles?[row] else {return} cell.titleLabel.text = zimFile.title @@ -295,7 +296,7 @@ class LibraryMasterController: UIViewController, UIDocumentPickerDelegate, UITab cell.thumbImageView.contentMode = .scaleAspectFit cell.accessoryType = .disclosureIndicator } - + func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { switch sections[section] { case .local: @@ -306,7 +307,7 @@ class LibraryMasterController: UIViewController, UIDocumentPickerDelegate, UITab return NSLocalizedString("Categories", comment: "Library section headers") } } - + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) switch sections[indexPath.section] { @@ -323,8 +324,8 @@ class LibraryMasterController: UIViewController, UIDocumentPickerDelegate, UITab showDetailViewController(UINavigationController(rootViewController: controller), sender: nil) } } - + // MARK: - Type Definition - + enum Section { case local, download, category } }