From eff2d2203a13bad769f19a95db503af192923a63 Mon Sep 17 00:00:00 2001 From: Chris Li Date: Wed, 28 Sep 2016 17:00:22 -0400 Subject: [PATCH] Empty Data set for search controllers --- .../Search/SearchBooksController.swift | 56 ++++----- .../Controller/Search/SearchController.swift | 42 ++++++- .../Search/SearchResultController.swift | 118 ++++++++++-------- Kiwix-iOS/Info.plist | 2 +- Kiwix-iOS/Storyboard/Search.storyboard | 2 +- Kiwix-iOSWidgets/Bookmarks/Info.plist | 2 +- .../xcdebugger/Breakpoints_v2.xcbkptlist | 4 +- 7 files changed, 132 insertions(+), 94 deletions(-) diff --git a/Kiwix-iOS/Controller/Search/SearchBooksController.swift b/Kiwix-iOS/Controller/Search/SearchBooksController.swift index 9af7c71b..0b7b14ce 100644 --- a/Kiwix-iOS/Controller/Search/SearchBooksController.swift +++ b/Kiwix-iOS/Controller/Search/SearchBooksController.swift @@ -10,9 +10,8 @@ import UIKit import CoreData import DZNEmptyDataSet -class SearchBooksController: UIViewController, UITableViewDelegate, UITableViewDataSource, NSFetchedResultsControllerDelegate, TableCellDelegate, DZNEmptyDataSetSource, DZNEmptyDataSetDelegate { +class SearchBooksController: SearchTableViewController, UITableViewDelegate, UITableViewDataSource, NSFetchedResultsControllerDelegate, TableCellDelegate { - @IBOutlet weak var tableView: UITableView! @IBOutlet weak var recentSearchContainer: DropShadowView! @IBOutlet weak var recentSearchBarHeight: NSLayoutConstraint! @@ -20,9 +19,6 @@ class SearchBooksController: UIViewController, UITableViewDelegate, UITableViewD super.viewDidLoad() tableView.delegate = self tableView.dataSource = self -// tableView.emptyDataSetSource = self -// tableView.emptyDataSetDelegate = self - tableView.tableHeaderView = UIView() tableView.tableFooterView = UIView() tableView.keyboardDismissMode = .OnDrag } @@ -34,39 +30,12 @@ class SearchBooksController: UIViewController, UITableViewDelegate, UITableViewD } func configureRecentSearchBarHeight() { - let previousHeight = recentSearchBarHeight.constant let newHeight: CGFloat = Preference.recentSearchTerms.count == 0 ? 0.0 : 44.0 - guard previousHeight != newHeight else {return} + guard recentSearchBarHeight.constant != newHeight else {return} recentSearchBarHeight.constant = newHeight recentSearchContainer.setNeedsDisplay() } - // MARK: - Empty table datasource & delegate - - func titleForEmptyDataSet(scrollView: UIScrollView!) -> NSAttributedString! { - let text = NSLocalizedString("No Book Available", comment: "Book Library, book downloader, no book center title") - let attributes = [NSFontAttributeName: UIFont.boldSystemFontOfSize(18.0), - NSForegroundColorAttributeName: UIColor.darkGrayColor()] - return NSAttributedString(string: text, attributes: attributes) - } - - func buttonTitleForEmptyDataSet(scrollView: UIScrollView!, forState state: UIControlState) -> NSAttributedString! { - let text = NSLocalizedString("Download A Book", comment: "Book Library, book downloader, learn more button text") - let attributes = [NSFontAttributeName: UIFont.boldSystemFontOfSize(17.0), NSForegroundColorAttributeName: UIButton().tintColor] - return NSAttributedString(string: text, attributes: attributes) - } - - func verticalOffsetForEmptyDataSet(scrollView: UIScrollView!) -> CGFloat { - return -64.0 - } - - func spaceHeightForEmptyDataSet(scrollView: UIScrollView!) -> CGFloat { - return 0.0 - } - - func emptyDataSetDidTapButton(scrollView: UIScrollView!) { - } - // MARK: - Fetched Results Controller let managedObjectContext = NSManagedObjectContext.mainQueueContext @@ -185,4 +154,25 @@ class SearchBooksController: UIViewController, UITableViewDelegate, UITableViewD func controllerDidChangeContent(controller: NSFetchedResultsController) { tableView.endUpdates() } + + // MARK: - DZNEmptyDataSet + + func titleForEmptyDataSet(scrollView: UIScrollView!) -> NSAttributedString! { + let string = NSLocalizedString("No Books Available", comment: "Search, Book Selector") + let attributes = [NSFontAttributeName: UIFont.systemFontOfSize(18), NSForegroundColorAttributeName: UIColor.darkGrayColor()] + return NSAttributedString(string: string, attributes: attributes) + } + + func descriptionForEmptyDataSet(scrollView: UIScrollView!) -> NSAttributedString! { + let string = NSLocalizedString("Please download or import a book.", comment: "Search, Book Selector") + let paragraph = NSMutableParagraphStyle() + paragraph.lineBreakMode = .ByWordWrapping + paragraph.alignment = .Center + let attributes = [NSFontAttributeName: UIFont.systemFontOfSize(14), NSForegroundColorAttributeName: UIColor.lightGrayColor(), NSParagraphStyleAttributeName: paragraph] + return NSAttributedString(string: string, attributes: attributes) + } + + func verticalOffsetForEmptyDataSet(scrollView: UIScrollView!) -> CGFloat { + return -(tableView.contentInset.bottom + recentSearchBarHeight.constant) / 2.5 + } } diff --git a/Kiwix-iOS/Controller/Search/SearchController.swift b/Kiwix-iOS/Controller/Search/SearchController.swift index 51d36d55..f498a1fb 100644 --- a/Kiwix-iOS/Controller/Search/SearchController.swift +++ b/Kiwix-iOS/Controller/Search/SearchController.swift @@ -7,6 +7,7 @@ // import UIKit +import DZNEmptyDataSet class SearchController: UIViewController, UISearchBarDelegate, UIGestureRecognizerDelegate { @@ -81,5 +82,44 @@ class SearchController: UIViewController, UISearchBarDelegate, UIGestureRecogniz func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool { return touch.view == view ? true : false } - +} + +class SearchTableViewController: UIViewController, DZNEmptyDataSetSource, DZNEmptyDataSetDelegate { + @IBOutlet weak var tableView: UITableView! + + override func viewWillAppear(animated: Bool) { + super.viewWillAppear(animated) + NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(SearchTableViewController.keyboardDidShow(_:)), name: UIKeyboardDidShowNotification, object: nil) + NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(SearchTableViewController.keyboardWillHide(_:)), name: UIKeyboardWillHideNotification, object: nil) + } + + override func viewWillDisappear(animated: Bool) { + super.viewWillDisappear(animated) + tableView.emptyDataSetSource = nil + tableView.emptyDataSetDelegate = nil + NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardDidShowNotification, object: nil) + NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil) + } + + override func viewDidAppear(animated: Bool) { + super.viewDidAppear(animated) + tableView.emptyDataSetSource = self + tableView.emptyDataSetDelegate = self + } + + func keyboardDidShow(notification: NSNotification) { + guard let userInfo = notification.userInfo as? [String: NSValue], + let origin = userInfo[UIKeyboardFrameEndUserInfoKey]?.CGRectValue().origin else {return} + let point = view.convertPoint(origin, fromView: nil) + let buttomInset = view.frame.height - point.y + tableView.contentInset = UIEdgeInsetsMake(0.0, 0, buttomInset, 0) + tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0.0, 0, buttomInset, 0) + tableView.reloadEmptyDataSet() + } + + func keyboardWillHide(notification: NSNotification) { + tableView.contentInset = UIEdgeInsetsMake(0.0, 0, 0, 0) + tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0.0, 0, 0, 0) + tableView.reloadEmptyDataSet() + } } diff --git a/Kiwix-iOS/Controller/Search/SearchResultController.swift b/Kiwix-iOS/Controller/Search/SearchResultController.swift index 53c40ab3..4d8523f7 100644 --- a/Kiwix-iOS/Controller/Search/SearchResultController.swift +++ b/Kiwix-iOS/Controller/Search/SearchResultController.swift @@ -8,57 +8,35 @@ import UIKit import Operations +import DZNEmptyDataSet -class SearchResultController: UIViewController, UITableViewDataSource, UITableViewDelegate { +class SearchResultController: SearchTableViewController, UITableViewDataSource, UITableViewDelegate { - @IBOutlet weak var tableView: UITableView! var searchResults = [SearchResult]() + var shouldShowNoResults = false var shouldClipRoundCorner: Bool { return traitCollection.verticalSizeClass == .Regular && traitCollection.horizontalSizeClass == .Regular } + // MARK: - Override + override func viewDidLoad() { super.viewDidLoad() tableView.estimatedRowHeight = 44.0 tableView.rowHeight = UITableViewAutomaticDimension tableView.keyboardDismissMode = .OnDrag + tableView.emptyDataSetSource = self + tableView.emptyDataSetDelegate = self } override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) { - tableView.contentInset = UIEdgeInsetsMake(0.0, 0, 0, 0) - tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0.0, 0, 0, 0) + guard traitCollection != previousTraitCollection else {return} tableView.layer.cornerRadius = shouldClipRoundCorner ? 10.0 : 0.0 tableView.layer.masksToBounds = shouldClipRoundCorner } - override func viewWillAppear(animated: Bool) { - super.viewWillAppear(animated) - tableView.reloadData() - NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(SearchResultController.keyboardDidShow(_:)), name: UIKeyboardDidShowNotification, object: nil) - NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(SearchResultController.keyboardWillHide(_:)), name: UIKeyboardWillHideNotification, object: nil) - } - - override func viewWillDisappear(animated: Bool) { - super.viewWillDisappear(animated) - searchResults.removeAll() - NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardDidShowNotification, object: nil) - NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil) - } - - func keyboardDidShow(notification: NSNotification) { - guard let userInfo = notification.userInfo as? [String: NSValue] else {return} - guard let keyboardOrigin = userInfo[UIKeyboardFrameEndUserInfoKey]?.CGRectValue().origin else {return} - let point = view.convertPoint(keyboardOrigin, fromView: UIApplication.appDelegate.window) - let buttomInset = view.frame.height - point.y - tableView.contentInset = UIEdgeInsetsMake(0.0, 0, buttomInset, 0) - tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0.0, 0, buttomInset, 0) - } - - func keyboardWillHide(notification: NSNotification) { - tableView.contentInset = UIEdgeInsetsMake(0.0, 0, 0, 0) - tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0.0, 0, 0, 0) - } + // MARK: - func selectFirstResultIfPossible() { guard searchResults.count > 0 else {return} @@ -66,6 +44,40 @@ class SearchResultController: UIViewController, UITableViewDataSource, UITableVi tableView(tableView, didSelectRowAtIndexPath: NSIndexPath(forRow: 0, inSection: 0)) } + func reload(results results: [SearchResult]?) { + if let results = results { + searchResults = results + } else { + searchResults.removeAll() + } + + tableView.tableFooterView = searchResults.count > 0 ? nil : UIView() + tableView.reloadData() + tableView.reloadEmptyDataSet() + + guard searchResults.count > 0 else {return} + self.tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0), atScrollPosition: .Top, animated: true) + } + + func startSearch(searchText: String) { + guard searchText != "" else { + shouldShowNoResults = false + reload(results: nil) + return + } + + let operation = SearchOperation(searchTerm: searchText) + operation.addObserver(DidFinishObserver {(operation, errors) in + guard let operation = operation as? SearchOperation else {return} + NSOperationQueue.mainQueue().addOperationWithBlock({ + self.shouldShowNoResults = true + self.reload(results: operation.results) + }) + }) + GlobalQueue.shared.add(search: operation) + shouldShowNoResults = false + } + // MARK: - Table view data source func numberOfSectionsInTableView(tableView: UITableView) -> Int { @@ -112,30 +124,26 @@ class SearchResultController: UIViewController, UITableViewDataSource, UITableVi GlobalQueue.shared.add(load: operation) } - // MARK: - Search + // MARK: - DZNEmptyDataSet - func startSearch(searchText: String) { - guard searchText != "" else { - searchResults.removeAll() - tableView.reloadData() - return - } - - let operation = SearchOperation(searchTerm: searchText) - operation.addObserver(DidFinishObserver {(operation, errors) in - guard let operation = operation as? SearchOperation else {return} - NSOperationQueue.mainQueue().addOperationWithBlock({ - self.searchResults = operation.results - self.tableView.reloadData() - - guard operation.results.count > 0 else {return} - self.tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0), atScrollPosition: .Top, animated: true) - }) - }) - GlobalQueue.shared.add(search: operation) + func titleForEmptyDataSet(scrollView: UIScrollView!) -> NSAttributedString! { + guard shouldShowNoResults else {return nil} + let string = NSLocalizedString("No Results", comment: "Search, Results") + let attributes = [NSFontAttributeName: UIFont.systemFontOfSize(18), NSForegroundColorAttributeName: UIColor.darkGrayColor()] + return NSAttributedString(string: string, attributes: attributes) + } + + func descriptionForEmptyDataSet(scrollView: UIScrollView!) -> NSAttributedString! { + guard shouldShowNoResults else {return nil} + let string = NSLocalizedString("Please refine your search term.", comment: "Search, Results") + let paragraph = NSMutableParagraphStyle() + paragraph.lineBreakMode = .ByWordWrapping + paragraph.alignment = .Center + let attributes = [NSFontAttributeName: UIFont.systemFontOfSize(14), NSForegroundColorAttributeName: UIColor.lightGrayColor(), NSParagraphStyleAttributeName: paragraph] + return NSAttributedString(string: string, attributes: attributes) + } + + func verticalOffsetForEmptyDataSet(scrollView: UIScrollView!) -> CGFloat { + return -tableView.contentInset.bottom / 2.5 } } - -extension LocalizedStrings { - class var searchAddBookGuide: String {return NSLocalizedString("Add a book to get started", comment: "")} -} diff --git a/Kiwix-iOS/Info.plist b/Kiwix-iOS/Info.plist index b89d7159..202df9c3 100644 --- a/Kiwix-iOS/Info.plist +++ b/Kiwix-iOS/Info.plist @@ -49,7 +49,7 @@ CFBundleVersion - 1.8.1275 + 1.8.1343 ITSAppUsesNonExemptEncryption LSRequiresIPhoneOS diff --git a/Kiwix-iOS/Storyboard/Search.storyboard b/Kiwix-iOS/Storyboard/Search.storyboard index 261fc30f..8028d5cc 100644 --- a/Kiwix-iOS/Storyboard/Search.storyboard +++ b/Kiwix-iOS/Storyboard/Search.storyboard @@ -276,7 +276,7 @@ - + diff --git a/Kiwix-iOSWidgets/Bookmarks/Info.plist b/Kiwix-iOSWidgets/Bookmarks/Info.plist index af0eaaed..59ed41e7 100644 --- a/Kiwix-iOSWidgets/Bookmarks/Info.plist +++ b/Kiwix-iOSWidgets/Bookmarks/Info.plist @@ -21,7 +21,7 @@ CFBundleSignature ???? CFBundleVersion - 1.8.1279 + 1.8.1347 NSExtension NSExtensionMainStoryboard diff --git a/Kiwix.xcworkspace/xcuserdata/chrisli.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/Kiwix.xcworkspace/xcuserdata/chrisli.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist index 843ae66a..0b50c5a2 100644 --- a/Kiwix.xcworkspace/xcuserdata/chrisli.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ b/Kiwix.xcworkspace/xcuserdata/chrisli.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -56,7 +56,7 @@ moduleName = "Kiwix" usesParentBreakpointCondition = "Yes" urlString = "file:///Volumes/Data/Developer/Kiwix/Kiwix/Operations/BookmarkMigrationOperation.swift" - timestampString = "496776740.852799" + timestampString = "496789129.532637" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" startingLineNumber = "27" @@ -71,7 +71,7 @@ moduleName = "Kiwix" usesParentBreakpointCondition = "Yes" urlString = "file:///Volumes/Data/Developer/Kiwix/Kiwix/Operations/BookmarkMigrationOperation.swift" - timestampString = "496776740.853959" + timestampString = "496789129.534098" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" startingLineNumber = "27"