From 330933b60dc7c6ef842fc0cbe36c7e348b0ccae5 Mon Sep 17 00:00:00 2001 From: Chris Li Date: Tue, 24 Jan 2017 11:33:03 -0500 Subject: [PATCH] Language filter --- .../Library/LibraryBooksController.swift | 18 +- .../Library/LibraryLanguageController.swift | 161 +++++++++++++++++- Kiwix-iOS/Storyboard/Library.storyboard | 122 +++++++------ Kiwix.xcodeproj/project.pbxproj | 12 +- 4 files changed, 247 insertions(+), 66 deletions(-) diff --git a/Kiwix-iOS/Controller/Library/LibraryBooksController.swift b/Kiwix-iOS/Controller/Library/LibraryBooksController.swift index e9d821f9..c79394ad 100644 --- a/Kiwix-iOS/Controller/Library/LibraryBooksController.swift +++ b/Kiwix-iOS/Controller/Library/LibraryBooksController.swift @@ -49,6 +49,16 @@ class LibraryBooksController: CoreDataCollectionBaseController, UICollectionView collectionView.collectionViewLayout.invalidateLayout() } + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + if segue.identifier == "showLangFilter" { + let nav = segue.destination as? UINavigationController + let controller = nav?.topViewController as? LibraryLanguageController + controller?.dismissBlock = {[unowned self] in + print("sdjk") + } + } + } + // MARK: - Refresh private(set) var isRefreshing = false // used to control text on empty table view @@ -111,7 +121,6 @@ class LibraryBooksController: CoreDataCollectionBaseController, UICollectionView let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! LibraryCollectionCell let book = fetchedResultController.object(at: indexPath) - print(book.meta4URL) cell.delegate = self cell.imageView.image = UIImage(data: book.favIcon ?? Data()) cell.titleLabel.text = book.title @@ -155,7 +164,6 @@ class LibraryBooksController: CoreDataCollectionBaseController, UICollectionView let titleDescriptor = NSSortDescriptor(key: "title", ascending: true) fetchRequest.sortDescriptors = [langDescriptor, titleDescriptor] fetchRequest.predicate = NSPredicate(format: "language.name != nil") -//// fetchRequest.predicate = self.onlineCompoundPredicate let controller = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext, @@ -165,3 +173,9 @@ class LibraryBooksController: CoreDataCollectionBaseController, UICollectionView return controller as! NSFetchedResultsController }() } + +extension Localized { + class Library { + + } +} diff --git a/Kiwix-iOS/Controller/Library/LibraryLanguageController.swift b/Kiwix-iOS/Controller/Library/LibraryLanguageController.swift index 109e2b2f..32f9d00f 100644 --- a/Kiwix-iOS/Controller/Library/LibraryLanguageController.swift +++ b/Kiwix-iOS/Controller/Library/LibraryLanguageController.swift @@ -2,22 +2,167 @@ // LibraryLanguageController.swift // Kiwix // -// Created by Chris Li on 1/23/17. +// Created by Chris Li on 1/24/17. // Copyright © 2017 Chris Li. All rights reserved. // import UIKit +import CoreData +import DZNEmptyDataSet -class LibraryLanguageController: CoreDataTableBaseController { +class LibraryLanguageController: UITableViewController, NSFetchedResultsControllerDelegate, DZNEmptyDataSetSource, DZNEmptyDataSetDelegate { + + @IBOutlet weak var langNameSegmentedControl: UISegmentedControl! + @IBAction func segmentedControlChanged(_ sender: UISegmentedControl) { + Preference.LangFilter.displayInOriginalLocale = !Preference.LangFilter.displayInOriginalLocale + tableView.reloadRows(at: tableView.indexPathsForVisibleRows ?? [IndexPath](), with: .automatic) + } + @IBAction func doneButtonTapped(_ sender: UIBarButtonItem) { + dismiss(animated: true, completion: nil) + } + + private let managedObjectContext = AppDelegate.persistentContainer.viewContext + private var initialShowLanguageSet = Set() + private var showLanguages = [Language]() + private var hideLanguages = [Language]() + var dismissBlock: (() -> Void)? override func viewDidLoad() { super.viewDidLoad() - - // Do any additional setup after loading the view. + + showLanguages = Language.fetch(displayed: true, context: managedObjectContext) + hideLanguages = Language.fetch(displayed: false, context: managedObjectContext) + initialShowLanguageSet = Set(showLanguages) + + configureSegmentedControls() + sort() } - - @IBAction func dismissButtonTapped(_ sender: UIBarButtonItem) { - dismiss(animated: true, completion: nil) + + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + dismissBlock?() + } + + func configureSegmentedControls() { + langNameSegmentedControl.selectedSegmentIndex = Preference.LangFilter.displayInOriginalLocale == true ? 1 : 0 + langNameSegmentedControl.setTitle((Locale.current as NSLocale).displayName(forKey: NSLocale.Key.identifier, value: Locale.preferredLangCodes[0]), forSegmentAt: 0) + langNameSegmentedControl.setTitle(Localized.Library.LanguageFilter.original, forSegmentAt: 1) + } + + // MARK: - Sort + + func sort() { + showLanguages = sortByCountDesc(languages: showLanguages) + hideLanguages = sortByCountDesc(languages: hideLanguages) + } + + func sortByCountDesc(languages: [Language]) -> [Language] { + return languages.sorted { (language0, language1) -> Bool in + let count0 = language0.books.count + let count1 = language1.books.count + guard count0 != count1 else { + return alphabeticalAscCompare(language0: language0, language1: language1, + byOriginalLocale: Preference.LangFilter.displayInOriginalLocale) + } + return count0 > count1 + } + } + + private func alphabeticalAscCompare(language0: Language, language1: Language, byOriginalLocale: Bool) -> Bool { + if byOriginalLocale { + guard let name0 = language0.nameInOriginalLocale, + let name1 = language1.nameInOriginalLocale else {return false} + return name0.compare(name1) == .orderedAscending + } else { + guard let name0 = language0.nameInCurrentLocale, + let name1 = language1.nameInCurrentLocale else {return false} + return name0.compare(name1) == .orderedAscending + } + } + + // MARK: - Table view data source + + override func numberOfSections(in tableView: UITableView) -> Int { + return 2 + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return section == 0 ? showLanguages.count : hideLanguages.count + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) + if indexPath.section == 0 { + configureCell(cell, atIndexPath: indexPath, language: showLanguages[indexPath.row]) + } else { + configureCell(cell, atIndexPath: indexPath, language: hideLanguages[indexPath.row]) + } + return cell + } + + func configureCell(_ cell: UITableViewCell, atIndexPath indexPath: IndexPath, language: Language) { + cell.textLabel?.text = Preference.LangFilter.displayInOriginalLocale ? language.nameInOriginalLocale : language.nameInCurrentLocale + cell.detailTextLabel?.text = language.books.count.description + } + + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + if showLanguages.count == 0 { + return section == 0 ? "" : Localized.Library.LanguageFilter.all + " " + } else { + return section == 0 ? Localized.Library.LanguageFilter.showing : Localized.Library.LanguageFilter.hiding + } + } + + // MARK: - Table view delegate + + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + func animateUpdates(_ originalIndexPath: IndexPath, destinationIndexPath: IndexPath) { + tableView.beginUpdates() + tableView.deleteRows(at: [indexPath], with: .right) + tableView.insertRows(at: [destinationIndexPath], with: .right) + tableView.headerView(forSection: 0)?.textLabel?.text = self.tableView(tableView, titleForHeaderInSection: 0) + tableView.headerView(forSection: 1)?.textLabel?.text = self.tableView(tableView, titleForHeaderInSection: 1) + tableView.endUpdates() + } + + if indexPath.section == 0 { + let language = showLanguages[indexPath.row] + language.isDisplayed = false + hideLanguages.append(language) + showLanguages.remove(at: indexPath.row) + hideLanguages = sortByCountDesc(languages: hideLanguages) + + guard let row = hideLanguages.index(of: language) else {tableView.reloadData(); return} + let destinationIndexPath = IndexPath(row: row, section: 1) + animateUpdates(indexPath, destinationIndexPath: destinationIndexPath) + } else { + let language = hideLanguages[indexPath.row] + language.isDisplayed = true + showLanguages.append(language) + hideLanguages.remove(at: indexPath.row) + showLanguages = sortByCountDesc(languages: showLanguages) + + guard let row = showLanguages.index(of: language) else {tableView.reloadData(); return} + let destinationIndexPath = IndexPath(row: row, section: 0) + animateUpdates(indexPath, destinationIndexPath: destinationIndexPath) + } + } + + override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { + if section == 0 { + return showLanguages.count == 0 ? CGFloat.leastNormalMagnitude : 44 + } else { + return 30 + } + } +} + +extension Localized.Library { + class LanguageFilter { + static let title = NSLocalizedString("Languages", comment: "Library, Language Filter") + static let all = NSLocalizedString("ALL", comment: "Library, Language Filter") + static let showing = NSLocalizedString("SHOWING", comment: "Library, Language Filter") + static let hiding = NSLocalizedString("HIDING", comment: "Library, Language Filter") + static let original = NSLocalizedString("Original", comment: "Library, Language Filter") } - } diff --git a/Kiwix-iOS/Storyboard/Library.storyboard b/Kiwix-iOS/Storyboard/Library.storyboard index 445250c9..77c926e6 100644 --- a/Kiwix-iOS/Storyboard/Library.storyboard +++ b/Kiwix-iOS/Storyboard/Library.storyboard @@ -52,7 +52,7 @@ - + @@ -175,7 +175,7 @@ - + @@ -189,46 +189,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -286,22 +246,88 @@ - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Kiwix.xcodeproj/project.pbxproj b/Kiwix.xcodeproj/project.pbxproj index 4e501c49..a4e6393d 100644 --- a/Kiwix.xcodeproj/project.pbxproj +++ b/Kiwix.xcodeproj/project.pbxproj @@ -11,7 +11,6 @@ 9705D5941E368189005292AC /* Library.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9705D5931E368189005292AC /* Library.storyboard */; }; 9705D5961E368712005292AC /* LibraryBooksController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9705D5951E368712005292AC /* LibraryBooksController.swift */; }; 9705D5981E368933005292AC /* CoreDataCollectionBaseController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9705D5971E368933005292AC /* CoreDataCollectionBaseController.swift */; }; - 9705D59A1E36B876005292AC /* LibraryLanguageController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9705D5991E36B876005292AC /* LibraryLanguageController.swift */; }; 970A2A221DD562CB0078BB7C /* BookOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 970A2A211DD562CB0078BB7C /* BookOperations.swift */; }; 970E7F741D9DB0FC00741290 /* 1.8.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = 970E7F731D9DB0FC00741290 /* 1.8.xcmappingmodel */; }; 970E7F831DA0305000741290 /* WelcomeController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 970E7F7F1DA0305000741290 /* WelcomeController.swift */; }; @@ -36,6 +35,7 @@ 973208271DD2238B00EDD3DC /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97D6811C1D6F70AC00E5FA99 /* Queue.swift */; }; 973208291DD223DB00EDD3DC /* RefreshLibrary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 973208281DD223DB00EDD3DC /* RefreshLibrary.swift */; }; 9734E54E1D289D060061C39B /* Welcome.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9734E54D1D289D060061C39B /* Welcome.storyboard */; }; + 9737F6211E379D0700961020 /* LibraryLanguageController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9737F6201E379D0700961020 /* LibraryLanguageController.swift */; }; 973A5C921DEA3F5600C7804C /* CoreDataTableBaseController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 973A5C911DEA3F5600C7804C /* CoreDataTableBaseController.swift */; }; 973A5C951DEA6DD000C7804C /* URLResponseCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 973A5C931DEA6CA900C7804C /* URLResponseCache.swift */; }; 973A5C991DEBC54800C7804C /* CloudKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 973A5C981DEBC54800C7804C /* CloudKit.swift */; }; @@ -96,7 +96,6 @@ 97BC0FBF1DD90A65004BBAD1 /* JSInjection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97BC0FBD1DD90A65004BBAD1 /* JSInjection.swift */; }; 97BC0FC01DD90A65004BBAD1 /* MainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97BC0FBE1DD90A65004BBAD1 /* MainController.swift */; }; 97BC0FC21DD92B62004BBAD1 /* Buttons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97BC0FC11DD92B62004BBAD1 /* Buttons.swift */; }; - 97C005D61D64B3B0004352E8 /* Library--old.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C005D51D64B3B0004352E8 /* Library--old.storyboard */; }; 97C2C26A1DDCC58500A9CC64 /* ArticleOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9764CBD21D8083AA00072D6A /* ArticleOperation.swift */; }; 97C601DC1D7F15C400362D4F /* Bookmark.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C601DB1D7F15C400362D4F /* Bookmark.storyboard */; }; 97C601DE1D7F342100362D4F /* HTMLHeading.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97C601DD1D7F342100362D4F /* HTMLHeading.swift */; }; @@ -163,7 +162,6 @@ 9705D5931E368189005292AC /* Library.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Library.storyboard; sourceTree = ""; }; 9705D5951E368712005292AC /* LibraryBooksController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LibraryBooksController.swift; sourceTree = ""; }; 9705D5971E368933005292AC /* CoreDataCollectionBaseController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataCollectionBaseController.swift; sourceTree = ""; }; - 9705D5991E36B876005292AC /* LibraryLanguageController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LibraryLanguageController.swift; sourceTree = ""; }; 970912551D7F452C00BBD5A1 /* 1.8.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = 1.8.xcdatamodel; sourceTree = ""; }; 970A2A211DD562CB0078BB7C /* BookOperations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BookOperations.swift; sourceTree = ""; }; 970E7F731D9DB0FC00741290 /* 1.8.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; name = 1.8.xcmappingmodel; path = Kiwix/CoreData/Migration/1.8.xcmappingmodel; sourceTree = SOURCE_ROOT; }; @@ -191,6 +189,7 @@ 973208251DD21E9C00EDD3DC /* CoreDataContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataContainer.swift; sourceTree = ""; }; 973208281DD223DB00EDD3DC /* RefreshLibrary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RefreshLibrary.swift; sourceTree = ""; }; 9734E54D1D289D060061C39B /* Welcome.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = Welcome.storyboard; path = "Kiwix-iOS/Storyboard/Welcome.storyboard"; sourceTree = SOURCE_ROOT; }; + 9737F6201E379D0700961020 /* LibraryLanguageController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LibraryLanguageController.swift; sourceTree = ""; }; 973A5C911DEA3F5600C7804C /* CoreDataTableBaseController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataTableBaseController.swift; sourceTree = ""; }; 973A5C931DEA6CA900C7804C /* URLResponseCache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLResponseCache.swift; sourceTree = ""; }; 973A5C981DEBC54800C7804C /* CloudKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CloudKit.swift; sourceTree = ""; }; @@ -265,7 +264,6 @@ 97BC0FBD1DD90A65004BBAD1 /* JSInjection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSInjection.swift; sourceTree = ""; }; 97BC0FBE1DD90A65004BBAD1 /* MainController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainController.swift; sourceTree = ""; }; 97BC0FC11DD92B62004BBAD1 /* Buttons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Buttons.swift; sourceTree = ""; }; - 97C005D51D64B3B0004352E8 /* Library--old.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = "Library--old.storyboard"; path = "Kiwix-iOS/Storyboard/Library--old.storyboard"; sourceTree = SOURCE_ROOT; }; 97C601DB1D7F15C400362D4F /* Bookmark.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Bookmark.storyboard; sourceTree = ""; }; 97C601DD1D7F342100362D4F /* HTMLHeading.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTMLHeading.swift; sourceTree = ""; }; 97D0E9921DDA487E0029530E /* SearchBaseController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchBaseController.swift; sourceTree = ""; }; @@ -625,7 +623,6 @@ 975227CA1D0227E8001D1DDE /* Main.storyboard */, 97C601DB1D7F15C400362D4F /* Bookmark.storyboard */, 9705D5931E368189005292AC /* Library.storyboard */, - 97C005D51D64B3B0004352E8 /* Library--old.storyboard */, 97F03CE11D2440470040D26E /* Search.storyboard */, 976C1DCF1E3000B6005EDEC4 /* Setting.storyboard */, 9734E54D1D289D060061C39B /* Welcome.storyboard */, @@ -728,7 +725,7 @@ isa = PBXGroup; children = ( 9705D5951E368712005292AC /* LibraryBooksController.swift */, - 9705D5991E36B876005292AC /* LibraryLanguageController.swift */, + 9737F6201E379D0700961020 /* LibraryLanguageController.swift */, ); path = Library; sourceTree = ""; @@ -979,7 +976,6 @@ 975227CD1D0227E8001D1DDE /* Main.storyboard in Resources */, 976C1DD01E3000B6005EDEC4 /* Setting.storyboard in Resources */, 971A10801D022F74007FC62C /* Pic_I.png in Resources */, - 97C005D61D64B3B0004352E8 /* Library--old.storyboard in Resources */, 971A107F1D022F74007FC62C /* ImportBookLearnMore.html in Resources */, 971A107E1D022F74007FC62C /* DownloaderLearnMore.html in Resources */, ); @@ -1102,7 +1098,7 @@ 9705D5961E368712005292AC /* LibraryBooksController.swift in Sources */, 97D681391D6F711A00E5FA99 /* DownloadTask.swift in Sources */, 977B954D1DD4C40400F6F62B /* ScanLocalBook.swift in Sources */, - 9705D59A1E36B876005292AC /* LibraryLanguageController.swift in Sources */, + 9737F6211E379D0700961020 /* LibraryLanguageController.swift in Sources */, 97D681321D6F70EC00E5FA99 /* MigrationPolicy.swift in Sources */, 976C1DCB1E2FD5FC005EDEC4 /* TableOfContentsController.swift in Sources */, 976C1DD81E327328005EDEC4 /* FontSizeController.swift in Sources */,