mirror of
https://github.com/kiwix/kiwix-apple.git
synced 2025-09-24 04:03:03 -04:00
Cleaner logic in LibraryOnlineTBVC & LibRefreshOp
This commit is contained in:
parent
a6e03b6fec
commit
4fec367d75
@ -9,11 +9,11 @@
|
||||
import UIKit
|
||||
import CoreData
|
||||
|
||||
class LibraryOnlineTBVC: UITableViewController, NSFetchedResultsControllerDelegate, BookTableCellDelegate, LTBarButtonItemDelegate, RefreshLibraryOperationDelegate, DZNEmptyDataSetSource, DZNEmptyDataSetDelegate {
|
||||
class LibraryOnlineTBVC: UITableViewController, NSFetchedResultsControllerDelegate, BookTableCellDelegate, LTBarButtonItemDelegate, DZNEmptyDataSetSource, DZNEmptyDataSetDelegate {
|
||||
|
||||
var booksShowingDetail = Set<Book>()
|
||||
weak var refreshOperation: RefreshLibraryOperation?
|
||||
var messsageLabelConfigTimer: NSTimer?
|
||||
var refreshing = false
|
||||
|
||||
// MARK: - Override
|
||||
|
||||
@ -26,18 +26,20 @@ class LibraryOnlineTBVC: UITableViewController, NSFetchedResultsControllerDelega
|
||||
tableView.emptyDataSetSource = self
|
||||
tableView.emptyDataSetDelegate = self
|
||||
|
||||
reconnectToExistingRefreshOperation()
|
||||
refreshLibraryForTheFirstTime()
|
||||
configureToolBar()
|
||||
}
|
||||
|
||||
override func viewWillAppear(animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
segmentedControl.selectedSegmentIndex = 0
|
||||
configureRefreshStatus()
|
||||
messsageLabelConfigTimer = NSTimer.scheduledTimerWithTimeInterval(60.0, target: self, selector: #selector(configureMessage), userInfo: nil, repeats: true)
|
||||
}
|
||||
|
||||
override func viewDidAppear(animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
refreshLibraryForTheFirstTime()
|
||||
}
|
||||
|
||||
override func viewWillDisappear(animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
messsageLabelConfigTimer?.invalidate()
|
||||
@ -68,38 +70,40 @@ class LibraryOnlineTBVC: UITableViewController, NSFetchedResultsControllerDelega
|
||||
startRefresh(invokedAutomatically: false)
|
||||
}
|
||||
|
||||
// MARK: - RefreshLibraryOperationDelegate
|
||||
|
||||
func refreshDidStart() {
|
||||
configureRefreshStatus()
|
||||
configureToolBarVisibility(animated: true)
|
||||
}
|
||||
|
||||
func refreshDidFinish() {
|
||||
configureRefreshStatus()
|
||||
configureToolBarVisibility(animated: true)
|
||||
}
|
||||
|
||||
// MARK: - Others
|
||||
|
||||
func reconnectToExistingRefreshOperation() {
|
||||
guard let operation = refreshOperation ??
|
||||
UIApplication.globalOperationQueue.operation(String(RefreshLibraryOperation)) as? RefreshLibraryOperation
|
||||
else {return}
|
||||
refreshOperation = operation
|
||||
operation.delegate = self
|
||||
}
|
||||
|
||||
func refreshLibraryForTheFirstTime() {
|
||||
guard Preference.libraryLastRefreshTime == nil else {return}
|
||||
startRefresh(invokedAutomatically: true)
|
||||
}
|
||||
|
||||
func startRefresh(invokedAutomatically invokedAutomatically: Bool) {
|
||||
let refreshOperation = RefreshLibraryOperation(invokedAutomatically: invokedAutomatically)
|
||||
refreshOperation.delegate = self
|
||||
let refreshOperation = RefreshLibraryOperation(invokedAutomatically: invokedAutomatically) { (errorCode) in
|
||||
defer {
|
||||
NSOperationQueue.mainQueue().addOperationWithBlock({
|
||||
self.refreshing = false
|
||||
self.configureMessage()
|
||||
self.configureRotatingStatus()
|
||||
self.configureEmptyTableBackground()
|
||||
})
|
||||
}
|
||||
if let errorCode = errorCode {
|
||||
if errorCode == .NetworkError {
|
||||
let alertOperation = RefreshLibraryInternetRequiredAlert(presentationContext: self)
|
||||
UIApplication.appDelegate.globalOperationQueue.addOperation(alertOperation)
|
||||
}
|
||||
} else {
|
||||
guard !Preference.libraryHasShownPreferredLanguagePrompt else {return}
|
||||
let operation = RefreshLibraryLanguageFilterAlert(libraryOnlineTBVC: self)
|
||||
UIApplication.appDelegate.globalOperationQueue.addOperation(operation)
|
||||
}
|
||||
}
|
||||
|
||||
refreshing = true
|
||||
configureMessage()
|
||||
configureRotatingStatus()
|
||||
configureEmptyTableBackground()
|
||||
UIApplication.globalOperationQueue.addOperation(refreshOperation)
|
||||
self.refreshOperation = refreshOperation
|
||||
}
|
||||
|
||||
// MARK: - ToolBar Button
|
||||
@ -126,15 +130,13 @@ class LibraryOnlineTBVC: UITableViewController, NSFetchedResultsControllerDelega
|
||||
setToolbarItems(toolBarItems, animated: false)
|
||||
|
||||
configureToolBarVisibility(animated: false)
|
||||
configureMessage(isRefreshing: false)
|
||||
configureMessage()
|
||||
}
|
||||
|
||||
func configureToolBarVisibility(animated animated: Bool) {
|
||||
navigationController?.setToolbarHidden(fetchedResultController.fetchedObjects?.count == 0, animated: animated)
|
||||
}
|
||||
|
||||
func configureMessage(isRefreshing isRefreshing: Bool = false) {
|
||||
if !isRefreshing {
|
||||
func configureMessage() {
|
||||
if refreshing {
|
||||
messageButton.text = LocalizedStrings.refreshing
|
||||
} else {
|
||||
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)
|
||||
@ -150,15 +152,18 @@ class LibraryOnlineTBVC: UITableViewController, NSFetchedResultsControllerDelega
|
||||
return string
|
||||
}()
|
||||
messageButton.text = localizedBookCountString + "\n" + localizedRefreshTimeString
|
||||
} else {
|
||||
messageButton.text = LocalizedStrings.refreshing
|
||||
}
|
||||
}
|
||||
|
||||
func configureRefreshStatus() {
|
||||
let executing = refreshOperation?.executing ?? false
|
||||
executing ? refreshLibButton.startRotating() : refreshLibButton.stopRotating()
|
||||
configureMessage(isRefreshing: executing)
|
||||
func configureToolBarVisibility(animated animated: Bool) {
|
||||
navigationController?.setToolbarHidden(fetchedResultController.fetchedObjects?.count == 0, animated: animated)
|
||||
}
|
||||
|
||||
func configureRotatingStatus() {
|
||||
refreshing ? refreshLibButton.startRotating() : refreshLibButton.stopRotating()
|
||||
}
|
||||
|
||||
func configureEmptyTableBackground() {
|
||||
tableView.reloadEmptyDataSet()
|
||||
}
|
||||
|
||||
@ -187,7 +192,7 @@ class LibraryOnlineTBVC: UITableViewController, NSFetchedResultsControllerDelega
|
||||
}
|
||||
|
||||
func buttonTitleForEmptyDataSet(scrollView: UIScrollView!, forState state: UIControlState) -> NSAttributedString! {
|
||||
if let _ = refreshOperation {
|
||||
if refreshing == true {
|
||||
let text = NSLocalizedString("Refreshing...", comment: "Book Library, book downloader, refreshing button text")
|
||||
let attributes = [NSFontAttributeName: UIFont.boldSystemFontOfSize(17.0), NSForegroundColorAttributeName: UIColor.darkGrayColor()]
|
||||
return NSAttributedString(string: text, attributes: attributes)
|
||||
@ -207,7 +212,7 @@ class LibraryOnlineTBVC: UITableViewController, NSFetchedResultsControllerDelega
|
||||
}
|
||||
|
||||
func emptyDataSetDidTapButton(scrollView: UIScrollView!) {
|
||||
guard self.refreshOperation == nil else {return}
|
||||
guard !refreshing else {return}
|
||||
startRefresh(invokedAutomatically: false)
|
||||
}
|
||||
|
||||
@ -310,7 +315,7 @@ class LibraryOnlineTBVC: UITableViewController, NSFetchedResultsControllerDelega
|
||||
fetchedResultController.fetchRequest.predicate = onlineCompoundPredicate
|
||||
fetchedResultController.performFetch(deleteCache: true)
|
||||
tableView.reloadData()
|
||||
configureMessage(isRefreshing: false)
|
||||
configureMessage()
|
||||
}
|
||||
|
||||
private var langPredicate: NSPredicate {
|
||||
@ -360,5 +365,7 @@ class LibraryOnlineTBVC: UITableViewController, NSFetchedResultsControllerDelega
|
||||
|
||||
func controllerDidChangeContent(controller: NSFetchedResultsController) {
|
||||
tableView.endUpdates()
|
||||
configureToolBarVisibility(animated: true)
|
||||
configureMessage()
|
||||
}
|
||||
}
|
||||
|
@ -11,21 +11,20 @@ import CoreData
|
||||
|
||||
class RefreshLibraryOperation: GroupOperation {
|
||||
|
||||
weak var delegate: RefreshLibraryOperationDelegate?
|
||||
weak var presentationContext: LibraryOnlineTBVC?
|
||||
var completionHandler: (() -> Void)?
|
||||
var completionHandler: ((errorCode: Int?) -> Void)?
|
||||
|
||||
init(invokedAutomatically: Bool, presentationContext: LibraryOnlineTBVC? = nil, completionHandler: (() -> Void)? = nil) {
|
||||
init(invokedAutomatically: Bool, completionHandler: ((errorCode: Int?) -> Void)?) {
|
||||
super.init(operations: [])
|
||||
|
||||
name = String(RefreshLibraryOperation)
|
||||
self.completionHandler = completionHandler
|
||||
|
||||
// 1.Parse
|
||||
let parseOperation = ParseLibraryOperation()
|
||||
|
||||
// 0.Download library
|
||||
let url = NSURL(string: "http://www.kiwix.org/library.xml")!
|
||||
let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) -> Void in
|
||||
let task = NSURLSession.sharedSession().dataTaskWithURL(url) { [unowned parseOperation] (data, response, error) -> Void in
|
||||
if let error = error {self.aggregateError(error)}
|
||||
parseOperation.xmlData = data
|
||||
}
|
||||
@ -33,24 +32,9 @@ class RefreshLibraryOperation: GroupOperation {
|
||||
fetchOperation.addObserver(NetworkObserver())
|
||||
fetchOperation.addCondition(ReachabilityCondition(host: url, allowCellular: Preference.libraryRefreshAllowCellularData))
|
||||
|
||||
let stateObserver = BlockObserver(
|
||||
startHandler: { (operation) -> Void in
|
||||
NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
|
||||
self.delegate?.refreshDidStart()
|
||||
})
|
||||
},
|
||||
produceHandler: nil) { (operation, errors) -> Void in
|
||||
NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
|
||||
self.delegate?.refreshDidFinish()
|
||||
})
|
||||
}
|
||||
addObserver(stateObserver)
|
||||
|
||||
addCondition(MutuallyExclusive<RefreshLibraryOperation>())
|
||||
if invokedAutomatically {
|
||||
addCondition(AllowAutoRefreshCondition())
|
||||
addCondition(LibraryIsOldCondition())
|
||||
addCondition(ReachabilityCondition(host: url, allowCellular: Preference.libraryRefreshAllowCellularData))
|
||||
}
|
||||
|
||||
addOperation(fetchOperation)
|
||||
@ -59,22 +43,10 @@ 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))
|
||||
}
|
||||
completionHandler?(errorCode: errors.first?.code)
|
||||
}
|
||||
}
|
||||
|
||||
protocol RefreshLibraryOperationDelegate: class {
|
||||
func refreshDidStart()
|
||||
func refreshDidFinish()
|
||||
}
|
||||
|
||||
class ParseLibraryOperation: Operation, NSXMLParserDelegate {
|
||||
var xmlData: NSData?
|
||||
let context: NSManagedObjectContext
|
||||
@ -91,7 +63,7 @@ class ParseLibraryOperation: Operation, NSXMLParserDelegate {
|
||||
}
|
||||
|
||||
override func execute() {
|
||||
guard let data = xmlData else {return}
|
||||
guard let data = xmlData else {finish(); return}
|
||||
let xmlParser = NSXMLParser(data: data)
|
||||
xmlParser.delegate = self
|
||||
xmlParser.parse()
|
||||
@ -106,7 +78,7 @@ class ParseLibraryOperation: Operation, NSXMLParserDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
@objc internal func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, var attributes attributeDict: [String : String]) {
|
||||
@objc internal func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
|
||||
guard elementName == "book" else {return}
|
||||
guard let id = attributeDict["id"] else {return}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user