diff --git a/Kiwix-iOS/Controller/Bookmark/BookmarkController.swift b/Kiwix-iOS/Controller/Bookmark/BookmarkController.swift
index 1f25f46f..ea52671c 100644
--- a/Kiwix-iOS/Controller/Bookmark/BookmarkController.swift
+++ b/Kiwix-iOS/Controller/Bookmark/BookmarkController.swift
@@ -8,8 +8,10 @@
import UIKit
import CoreData
+import Operations
+import DZNEmptyDataSet
-class BookmarkController: UITableViewController, NSFetchedResultsControllerDelegate {
+class BookmarkController: UITableViewController, NSFetchedResultsControllerDelegate, DZNEmptyDataSetSource, DZNEmptyDataSetDelegate {
var book: Book?
@@ -17,8 +19,77 @@ class BookmarkController: UITableViewController, NSFetchedResultsControllerDeleg
override func viewDidLoad() {
super.viewDidLoad()
+ title = LocalizedStrings.bookmarks
+ clearsSelectionOnViewWillAppear = true
+ tableView.estimatedRowHeight = 66.0
+ tableView.rowHeight = UITableViewAutomaticDimension
+ tableView.allowsMultipleSelectionDuringEditing = true
+ tableView.emptyDataSetSource = self
+ tableView.emptyDataSetDelegate = self
}
+ override func setEditing(editing: Bool, animated: Bool) {
+ super.setEditing(editing, animated: animated)
+ navigationItem.leftBarButtonItem = editing ? UIBarButtonItem(barButtonSystemItem: .Trash) : nil
+ navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: editing ? .Done : .Edit)
+ navigationItem.leftBarButtonItem?.target = self
+ navigationItem.leftBarButtonItem?.action = #selector(BookmarkController.trashButtonTapped(_:))
+ navigationItem.rightBarButtonItem?.target = self
+ navigationItem.rightBarButtonItem?.action = #selector(BookmarkController.editButtonTapped(_:))
+ }
+
+ // MARK: - Action
+
+ func trash(articles articles: [Article]) {
+ let operation = BookmarkTrashOperation(articles: articles)
+ operation.addObserver(DidFinishObserver { _ in
+ NSOperationQueue.mainQueue().addOperationWithBlock({
+ guard self.fetchedResultController.fetchedObjects?.count == 0 else {return}
+ self.navigationController?.popViewControllerAnimated(true)
+ })
+ })
+ GlobalQueue.shared.addOperation(operation)
+ }
+
+ func trashButtonTapped(sender: UIBarButtonItem) {
+ guard editing else {return}
+ guard let selectedIndexPathes = tableView.indexPathsForSelectedRows else {return}
+ let articles = selectedIndexPathes.flatMap() {fetchedResultController.objectAtIndexPath($0) as? Article}
+ trash(articles: articles)
+ }
+
+ @IBAction func editButtonTapped(sender: UIBarButtonItem) {
+ setEditing(!editing, animated: true)
+ }
+
+ // MARK: - Empty table datasource & delegate
+
+ func imageForEmptyDataSet(scrollView: UIScrollView!) -> UIImage! {
+ return UIImage(named: "BookmarkColor")
+ }
+
+ func titleForEmptyDataSet(scrollView: UIScrollView!) -> NSAttributedString! {
+ let text = NSLocalizedString("Bookmarks", comment: "Bookmarks view title")
+ let attributes = [NSFontAttributeName: UIFont.boldSystemFontOfSize(18.0),
+ NSForegroundColorAttributeName: UIColor.darkGrayColor()]
+ return NSAttributedString(string: text, attributes: attributes)
+ }
+
+ func descriptionForEmptyDataSet(scrollView: UIScrollView!) -> NSAttributedString! {
+ let text = NSLocalizedString("To add a bookmark, long press the star button when reading an article", comment: "Bookmarks view message")
+ let style = NSMutableParagraphStyle()
+ style.lineBreakMode = .ByWordWrapping
+ style.alignment = .Center
+ let attributes = [NSFontAttributeName: UIFont.boldSystemFontOfSize(14.0),
+ NSForegroundColorAttributeName: UIColor.lightGrayColor(),
+ NSParagraphStyleAttributeName: style]
+ return NSAttributedString(string: text, attributes: attributes)
+ }
+
+ func spaceHeightForEmptyDataSet(scrollView: UIScrollView!) -> CGFloat {
+ return 30.0
+ }
+
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
@@ -32,9 +103,15 @@ class BookmarkController: UITableViewController, NSFetchedResultsControllerDeleg
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let article = fetchedResultController.objectAtIndexPath(indexPath) as? Article
- let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
- cell.textLabel?.text = article?.title
- return cell
+ if let _ = article?.snippet {
+ let cell = tableView.dequeueReusableCellWithIdentifier("BookmarkSnippetCell", forIndexPath: indexPath)
+ configureSnippetCell(cell, atIndexPath: indexPath)
+ return cell
+ } else {
+ let cell = tableView.dequeueReusableCellWithIdentifier("BookmarkCell", forIndexPath: indexPath)
+ configureCell(cell, atIndexPath: indexPath)
+ return cell
+ }
}
func configureCell(cell: UITableViewCell, atIndexPath indexPath: NSIndexPath) {
@@ -49,6 +126,49 @@ class BookmarkController: UITableViewController, NSFetchedResultsControllerDeleg
cell.subtitleLabel.text = article.book?.title
}
+ func configureSnippetCell(cell: UITableViewCell, atIndexPath indexPath: NSIndexPath) {
+ configureCell(cell, atIndexPath: indexPath)
+
+ guard let cell = cell as? BookmarkSnippetCell else {return}
+ guard let article = fetchedResultController.objectAtIndexPath(indexPath) as? Article else {return}
+ cell.snippetLabel.text = article.snippet
+ }
+
+ // MARK: - Table view delegate
+
+ override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
+ guard !tableView.editing else {return}
+ defer {dismissViewControllerAnimated(true, completion: nil)}
+ guard let article = fetchedResultController.objectAtIndexPath(indexPath) as? Article,
+ let url = article.url else {return}
+ trash(articles: [article])
+
+ let operation = ArticleLoadOperation(url: url)
+ GlobalQueue.shared.add(load: operation)
+ }
+
+ override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
+ return true
+ }
+
+ override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {}
+
+ override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
+ let remove = UITableViewRowAction(style: .Destructive, title: LocalizedStrings.remove) { (action, indexPath) -> Void in
+ guard let article = self.fetchedResultController.objectAtIndexPath(indexPath) as? Article else {return}
+ let context = NSManagedObjectContext.mainQueueContext
+ context.performBlockAndWait({ () -> Void in
+ article.isBookmarked = false
+ })
+ self.trash(articles: [article])
+ }
+ return [remove]
+ }
+
+ override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
+ return CGFloat.min
+ }
+
// MARK: - Fetched Result Controller Delegate
let managedObjectContext = NSManagedObjectContext.mainQueueContext
@@ -93,17 +213,17 @@ class BookmarkController: UITableViewController, NSFetchedResultsControllerDeleg
switch type {
case .Insert:
guard let newIndexPath = newIndexPath else {return}
- tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Fade)
+ tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Left)
case .Delete:
guard let indexPath = indexPath else {return}
- tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
+ tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Right)
case .Update:
guard let indexPath = indexPath, let cell = tableView.cellForRowAtIndexPath(indexPath) else {return}
configureCell(cell, atIndexPath: indexPath)
case .Move:
guard let indexPath = indexPath, let newIndexPath = newIndexPath else {return}
- tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
- tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Fade)
+ tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Right)
+ tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Left)
}
}
diff --git a/Kiwix-iOS/Controller/Library/BookDetailController.swift b/Kiwix-iOS/Controller/Library/BookDetailController.swift
index 8c9a69f0..2f812977 100644
--- a/Kiwix-iOS/Controller/Library/BookDetailController.swift
+++ b/Kiwix-iOS/Controller/Library/BookDetailController.swift
@@ -24,7 +24,10 @@ class BookDetailController: UITableViewController, DZNEmptyDataSetSource, DZNEmp
private(set) var sectionHeaders = [String?]()
private(set) var sectionFooters = [String?]()
private(set) var cellTitles = [[String]]()
- private(set) var bookmarkCount = 0
+ var bookmarkCount: Int? {
+ guard let book = book else {return nil}
+ return Article.fetchBookmarked(in: book, with: NSManagedObjectContext.mainQueueContext).count
+ }
override func viewDidLoad() {
super.viewDidLoad()
@@ -41,8 +44,10 @@ class BookDetailController: UITableViewController, DZNEmptyDataSetSource, DZNEmp
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
- configureViews()
book?.addObserver(self, forKeyPath: "stateRaw", options: .New, context: context)
+ configureViews()
+ tableView.reloadEmptyDataSet()
+ tableView.reloadData()
}
override func viewWillDisappear(animated: Bool) {
@@ -104,7 +109,6 @@ class BookDetailController: UITableViewController, DZNEmptyDataSetSource, DZNEmp
}
func configureBookmarkSection(with book: Book) {
- bookmarkCount = Article.fetchBookmarked(in: book, with: NSManagedObjectContext.mainQueueContext).count
guard bookmarkCount > 0 else {return}
sectionHeaders.append(nil)
sectionFooters.append(nil)
@@ -143,6 +147,10 @@ class BookDetailController: UITableViewController, DZNEmptyDataSetSource, DZNEmp
}
func configureViews() {
+ sectionHeaders.removeAll()
+ sectionFooters.removeAll()
+ cellTitles.removeAll()
+
guard let book = book else {return}
configureStaticHeader(with: book)
configureIndicators(with: book)
@@ -152,7 +160,6 @@ class BookDetailController: UITableViewController, DZNEmptyDataSetSource, DZNEmp
configureBookInfoSection(with: book)
configurePIDSection(with: book)
configureURLSection(with: book)
- tableView.reloadEmptyDataSet()
}
// MARK: - Table view data source
@@ -194,7 +201,7 @@ class BookDetailController: UITableViewController, DZNEmptyDataSetSource, DZNEmp
case LocalizedStrings.bookmarks:
let cell = tableView.dequeueReusableCellWithIdentifier("DetailSegueCell", forIndexPath: indexPath)
cell.textLabel?.text = title
- cell.detailTextLabel?.text = "\(bookmarkCount)"
+ cell.detailTextLabel?.text = String(bookmarkCount ?? 0)
return cell
default:
let cell = tableView.dequeueReusableCellWithIdentifier("RightDetailCell", forIndexPath: indexPath)
diff --git a/Kiwix-iOS/Controller/Main/JSInjection.swift b/Kiwix-iOS/Controller/Main/JSInjection.swift
index e6cf9fd9..f5eab7a3 100644
--- a/Kiwix-iOS/Controller/Main/JSInjection.swift
+++ b/Kiwix-iOS/Controller/Main/JSInjection.swift
@@ -54,6 +54,6 @@ class JSInjection {
let path = NSBundle.mainBundle().pathForResource("getSnippet", ofType: "js"),
let jString = try? String(contentsOfFile: path),
let snippet = context.evaluateScript(jString).toString() else {return nil}
- return snippet
+ return snippet == "null" ? nil : snippet
}
}
diff --git a/Kiwix-iOS/Info.plist b/Kiwix-iOS/Info.plist
index ad26be19..eac698ed 100644
--- a/Kiwix-iOS/Info.plist
+++ b/Kiwix-iOS/Info.plist
@@ -49,7 +49,7 @@
CFBundleVersion
- 1.8.1369
+ 1.8.1454
ITSAppUsesNonExemptEncryption
LSRequiresIPhoneOS
diff --git a/Kiwix-iOS/JavaScripts/getSnippet.js b/Kiwix-iOS/JavaScripts/getSnippet.js
index 20acba76..d508e013 100644
--- a/Kiwix-iOS/JavaScripts/getSnippet.js
+++ b/Kiwix-iOS/JavaScripts/getSnippet.js
@@ -13,7 +13,7 @@ function getSnippet() {
}
}
}
-
}
+ return null;
}
-getSnippet();
\ No newline at end of file
+getSnippet();
diff --git a/Kiwix-iOS/Storyboard/Bookmark.storyboard b/Kiwix-iOS/Storyboard/Bookmark.storyboard
index c0edf51e..522cb765 100644
--- a/Kiwix-iOS/Storyboard/Bookmark.storyboard
+++ b/Kiwix-iOS/Storyboard/Bookmark.storyboard
@@ -19,10 +19,10 @@
-
+
-
+
-
+
-
+