mirror of
https://github.com/kiwix/kiwix-apple.git
synced 2025-09-25 21:05:09 -04:00
Book detail bookmark
This commit is contained in:
parent
b39774f521
commit
8ab153b0e8
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,7 @@
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.8.1369</string>
|
||||
<string>1.8.1454</string>
|
||||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
<false/>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
|
@ -13,7 +13,7 @@ function getSnippet() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
getSnippet();
|
||||
getSnippet();
|
||||
|
@ -19,10 +19,10 @@
|
||||
<color key="sectionIndexBackgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="BookmarkCell" rowHeight="66" id="HDv-lO-b6r" customClass="BookmarkCell" customModule="Kiwix" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="120" width="375" height="66"/>
|
||||
<rect key="frame" x="0.0" y="119.5" width="375" height="66"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="HDv-lO-b6r" id="OAl-D1-ec7">
|
||||
<frame key="frameInset" width="375" height="65"/>
|
||||
<frame key="frameInset" width="375" height="65.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="U1x-fn-tr7">
|
||||
@ -64,10 +64,10 @@
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="BookmarkSnippetCell" rowHeight="149" id="o5A-Xv-pf5" customClass="BookmarkSnippetCell" customModule="Kiwix" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="186" width="375" height="149"/>
|
||||
<rect key="frame" x="0.0" y="185.5" width="375" height="149"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="o5A-Xv-pf5" id="KOC-sh-r2Q">
|
||||
<frame key="frameInset" width="375" height="148"/>
|
||||
<frame key="frameInset" width="375" height="148.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Iw0-U5-FqV">
|
||||
@ -155,7 +155,7 @@
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="b4G-fm-Sda" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1853" y="1137"/>
|
||||
<point key="canvasLocation" x="2791.1999999999998" y="1136.5817091454273"/>
|
||||
</scene>
|
||||
<!--Navigation Controller-->
|
||||
<scene sceneID="QEZ-t8-ULC">
|
||||
@ -183,18 +183,118 @@
|
||||
<scene sceneID="SVz-ni-k6U">
|
||||
<objects>
|
||||
<tableViewController storyboardIdentifier="BookmarkController" id="uLf-Kw-kC4" customClass="BookmarkController" customModule="Kiwix" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" id="e97-aT-3rg">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="18" sectionFooterHeight="18" id="e97-aT-3rg">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="Cell" id="jws-Kz-Krn">
|
||||
<rect key="frame" x="0.0" y="28" width="375" height="44"/>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="BookmarkCell" rowHeight="66" id="5PG-FL-cxF" customClass="BookmarkCell" customModule="Kiwix" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="119.5" width="375" height="66"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="jws-Kz-Krn" id="l4Q-UL-tNB">
|
||||
<frame key="frameInset" width="375" height="43"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="5PG-FL-cxF" id="xaN-IW-A8Q">
|
||||
<frame key="frameInset" width="375" height="65.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="8C5-aP-W5f">
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="22" id="8Wa-GZ-Fdn"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="kTX-Se-1Tr">
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleFootnote"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="MLn-gx-0vX">
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="50" id="HZd-Cl-V3K"/>
|
||||
<constraint firstAttribute="height" constant="50" id="uiV-Hq-hDX"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="8C5-aP-W5f" firstAttribute="leading" secondItem="MLn-gx-0vX" secondAttribute="trailing" constant="8" id="20T-Gb-4xa"/>
|
||||
<constraint firstItem="8C5-aP-W5f" firstAttribute="leading" secondItem="xaN-IW-A8Q" secondAttribute="leadingMargin" constant="58" id="7x4-8l-TKY"/>
|
||||
<constraint firstItem="kTX-Se-1Tr" firstAttribute="trailing" secondItem="xaN-IW-A8Q" secondAttribute="trailingMargin" id="CXv-MZ-OHC"/>
|
||||
<constraint firstItem="8C5-aP-W5f" firstAttribute="top" secondItem="xaN-IW-A8Q" secondAttribute="topMargin" constant="2" id="JnU-bN-UVz"/>
|
||||
<constraint firstItem="8C5-aP-W5f" firstAttribute="trailing" secondItem="xaN-IW-A8Q" secondAttribute="trailingMargin" id="LKT-j4-l4Q"/>
|
||||
<constraint firstItem="MLn-gx-0vX" firstAttribute="centerY" secondItem="xaN-IW-A8Q" secondAttribute="centerY" id="W6U-dK-Zdl"/>
|
||||
<constraint firstItem="kTX-Se-1Tr" firstAttribute="top" secondItem="8C5-aP-W5f" secondAttribute="bottom" constant="4" id="eQC-OL-FVO"/>
|
||||
<constraint firstItem="kTX-Se-1Tr" firstAttribute="leading" secondItem="xaN-IW-A8Q" secondAttribute="leadingMargin" constant="58" id="vEP-KN-deT"/>
|
||||
<constraint firstAttribute="bottomMargin" secondItem="kTX-Se-1Tr" secondAttribute="bottom" constant="2" id="vZz-lW-ir3"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<connections>
|
||||
<outlet property="subtitleLabel" destination="kTX-Se-1Tr" id="t7e-sO-Zlg"/>
|
||||
<outlet property="thumbImageView" destination="MLn-gx-0vX" id="ZqQ-DD-eY6"/>
|
||||
<outlet property="titleLabel" destination="8C5-aP-W5f" id="PLm-CK-x4Q"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="BookmarkSnippetCell" rowHeight="149" id="63j-xA-eDr" customClass="BookmarkSnippetCell" customModule="Kiwix" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="185.5" width="375" height="149"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="63j-xA-eDr" id="vOo-g4-SUY">
|
||||
<frame key="frameInset" width="375" height="148.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ucm-1R-oq2">
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="22" id="kPD-8s-fMo"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ZiC-LW-CAz">
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="19.5" id="Z3G-7m-zmO"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleFootnote"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="fb7-cw-RPA">
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="50" id="BXW-1c-V8W"/>
|
||||
<constraint firstAttribute="width" constant="50" id="Ur8-fD-YFg"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="justified" lineBreakMode="tailTruncation" numberOfLines="4" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="z7h-P0-nCy">
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleCaption2"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="Ucm-1R-oq2" firstAttribute="leading" secondItem="vOo-g4-SUY" secondAttribute="leadingMargin" constant="58" id="3T4-1H-XTZ"/>
|
||||
<constraint firstItem="ZiC-LW-CAz" firstAttribute="trailing" secondItem="vOo-g4-SUY" secondAttribute="trailingMargin" id="7OF-sG-pOp"/>
|
||||
<constraint firstAttribute="topMargin" secondItem="fb7-cw-RPA" secondAttribute="top" id="I19-z3-SCp"/>
|
||||
<constraint firstItem="Ucm-1R-oq2" firstAttribute="top" secondItem="vOo-g4-SUY" secondAttribute="topMargin" constant="2" id="Ipo-0d-gf4"/>
|
||||
<constraint firstItem="Ucm-1R-oq2" firstAttribute="leading" secondItem="fb7-cw-RPA" secondAttribute="trailing" constant="8" id="JYn-IL-cun"/>
|
||||
<constraint firstItem="z7h-P0-nCy" firstAttribute="bottom" secondItem="vOo-g4-SUY" secondAttribute="bottomMargin" id="JgH-Vt-DP2"/>
|
||||
<constraint firstItem="z7h-P0-nCy" firstAttribute="trailing" secondItem="vOo-g4-SUY" secondAttribute="trailingMargin" id="Omn-e2-gEG"/>
|
||||
<constraint firstItem="Ucm-1R-oq2" firstAttribute="trailing" secondItem="vOo-g4-SUY" secondAttribute="trailingMargin" id="Qra-DT-kjm"/>
|
||||
<constraint firstItem="ZiC-LW-CAz" firstAttribute="top" secondItem="Ucm-1R-oq2" secondAttribute="bottom" constant="4" id="Wlg-pC-5Nu"/>
|
||||
<constraint firstItem="z7h-P0-nCy" firstAttribute="top" secondItem="ZiC-LW-CAz" secondAttribute="bottom" constant="10.5" id="Y78-ff-8Lx"/>
|
||||
<constraint firstItem="fb7-cw-RPA" firstAttribute="centerY" secondItem="vOo-g4-SUY" secondAttribute="centerY" id="fWN-qd-SxN"/>
|
||||
<constraint firstAttribute="leadingMargin" secondItem="z7h-P0-nCy" secondAttribute="leading" id="gsJ-BE-Vvk"/>
|
||||
<constraint firstItem="ZiC-LW-CAz" firstAttribute="leading" secondItem="vOo-g4-SUY" secondAttribute="leadingMargin" constant="58" id="sKe-A0-zxB"/>
|
||||
</constraints>
|
||||
<variation key="default">
|
||||
<mask key="constraints">
|
||||
<exclude reference="fWN-qd-SxN"/>
|
||||
</mask>
|
||||
</variation>
|
||||
</tableViewCellContentView>
|
||||
<connections>
|
||||
<outlet property="snippetLabel" destination="z7h-P0-nCy" id="S6G-Ol-b0B"/>
|
||||
<outlet property="subtitleLabel" destination="ZiC-LW-CAz" id="Q1y-pr-E0m"/>
|
||||
<outlet property="thumbImageView" destination="fb7-cw-RPA" id="1WQ-SQ-QDN"/>
|
||||
<outlet property="titleLabel" destination="Ucm-1R-oq2" id="uil-XC-kpb"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
</prototypes>
|
||||
<connections>
|
||||
@ -202,10 +302,20 @@
|
||||
<outlet property="delegate" destination="uLf-Kw-kC4" id="eAm-IZ-3SL"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
<toolbarItems/>
|
||||
<navigationItem key="navigationItem" id="uvo-qe-heC">
|
||||
<barButtonItem key="rightBarButtonItem" systemItem="edit" id="Vy8-bG-jxx">
|
||||
<connections>
|
||||
<action selector="editButtonTapped:" destination="uLf-Kw-kC4" id="WYd-PY-qFx"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
</navigationItem>
|
||||
<simulatedNavigationBarMetrics key="simulatedTopBarMetrics" prompted="NO"/>
|
||||
<simulatedToolbarMetrics key="simulatedBottomBarMetrics"/>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="kQh-IS-Ttn" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1455" y="1720"/>
|
||||
<point key="canvasLocation" x="2676" y="1787"/>
|
||||
</scene>
|
||||
<!--BookmarkHUD-->
|
||||
<scene sceneID="eMu-pk-jX5">
|
||||
@ -315,7 +425,25 @@
|
||||
</connections>
|
||||
</tapGestureRecognizer>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="2604" y="1137"/>
|
||||
<point key="canvasLocation" x="3543.1999999999998" y="1136.5817091454273"/>
|
||||
</scene>
|
||||
<!--Navigation Controller-->
|
||||
<scene sceneID="pBB-bl-wh0">
|
||||
<objects>
|
||||
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="epu-ol-vd5" sceneMemberID="viewController">
|
||||
<toolbarItems/>
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" id="7Ri-xB-OG0">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</navigationBar>
|
||||
<nil name="viewControllers"/>
|
||||
<connections>
|
||||
<segue destination="uLf-Kw-kC4" kind="relationship" relationship="rootViewController" id="oTY-iv-avG"/>
|
||||
</connections>
|
||||
</navigationController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="qOY-S3-xOp" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1560.8" y="1764.4677661169417"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
|
@ -34,18 +34,23 @@ class BasicBookCell: UITableViewCell {
|
||||
|
||||
override func setHighlighted(highlighted: Bool, animated: Bool) {
|
||||
super.setHighlighted(highlighted, animated: animated)
|
||||
setHasPicIndicatorColor()
|
||||
setIndicatorColor()
|
||||
}
|
||||
|
||||
override func setSelected(selected: Bool, animated: Bool) {
|
||||
super.setSelected(selected, animated: animated)
|
||||
setIndicatorColor()
|
||||
}
|
||||
|
||||
// MARK: Shorthand properties
|
||||
|
||||
var hasPic: Bool = false {
|
||||
didSet {
|
||||
setHasPicIndicatorColor()
|
||||
setIndicatorColor()
|
||||
}
|
||||
}
|
||||
|
||||
private func setHasPicIndicatorColor() {
|
||||
private func setIndicatorColor() {
|
||||
hasPicIndicator.backgroundColor = hasPic ? AppColors.hasPicTintColor : UIColor.lightGrayColor()
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.8.1373</string>
|
||||
<string>1.8.1458</string>
|
||||
<key>NSExtension</key>
|
||||
<dict>
|
||||
<key>NSExtensionMainStoryboard</key>
|
||||
|
@ -62,7 +62,7 @@
|
||||
973DD4191D343F2F009D45DB /* libzim.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 973DD40E1D343F2F009D45DB /* libzim.a */; };
|
||||
973DD4281D36E3E4009D45DB /* SettingSingleSwitchTBVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 973DD4271D36E3E4009D45DB /* SettingSingleSwitchTBVC.swift */; };
|
||||
974F33C41D99BBEB00879D35 /* 1.8.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = 974F33C31D99BBEB00879D35 /* 1.8.xcmappingmodel */; };
|
||||
974F33C61D99CAD700879D35 /* BookmarkMigrationOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 974F33C51D99CAD700879D35 /* BookmarkMigrationOperation.swift */; };
|
||||
974F33C61D99CAD700879D35 /* BookmarkOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 974F33C51D99CAD700879D35 /* BookmarkOperation.swift */; };
|
||||
974F42821D47E19A00F8074C /* SettingWidgetBookmarksTBVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 974F42811D47E19A00F8074C /* SettingWidgetBookmarksTBVC.swift */; };
|
||||
975227821D020560001D1DDE /* Indexer.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 975227811D020560001D1DDE /* Indexer.storyboard */; };
|
||||
975227B01D021539001D1DDE /* IndexerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 975227AF1D021539001D1DDE /* IndexerController.swift */; };
|
||||
@ -283,7 +283,7 @@
|
||||
973DD40E1D343F2F009D45DB /* libzim.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libzim.a; path = Kiwix/libkiwix/iOS/libzim.a; sourceTree = "<group>"; };
|
||||
973DD4271D36E3E4009D45DB /* SettingSingleSwitchTBVC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SettingSingleSwitchTBVC.swift; path = "Kiwix-iOS/Controller/Setting/SettingSingleSwitchTBVC.swift"; sourceTree = SOURCE_ROOT; };
|
||||
974F33C31D99BBEB00879D35 /* 1.8.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; name = 1.8.xcmappingmodel; path = Kiwix/CoreData/Migration/1.8.xcmappingmodel; sourceTree = SOURCE_ROOT; };
|
||||
974F33C51D99CAD700879D35 /* BookmarkMigrationOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BookmarkMigrationOperation.swift; sourceTree = "<group>"; };
|
||||
974F33C51D99CAD700879D35 /* BookmarkOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BookmarkOperation.swift; sourceTree = "<group>"; };
|
||||
974F42811D47E19A00F8074C /* SettingWidgetBookmarksTBVC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SettingWidgetBookmarksTBVC.swift; path = "Kiwix-iOS/Controller/Setting/SettingWidgetBookmarksTBVC.swift"; sourceTree = SOURCE_ROOT; };
|
||||
975227811D020560001D1DDE /* Indexer.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = Indexer.storyboard; path = "Kiwix-OSX/StoryBoards/Indexer.storyboard"; sourceTree = SOURCE_ROOT; };
|
||||
975227AF1D021539001D1DDE /* IndexerController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = IndexerController.swift; path = "Kiwix-OSX/Controllers/IndexerController.swift"; sourceTree = SOURCE_ROOT; };
|
||||
@ -984,7 +984,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9764CBD21D8083AA00072D6A /* ArticleOperation.swift */,
|
||||
974F33C51D99CAD700879D35 /* BookmarkMigrationOperation.swift */,
|
||||
974F33C51D99CAD700879D35 /* BookmarkOperation.swift */,
|
||||
97DF259B1D6F7612001648A3 /* BookOperation.swift */,
|
||||
97D6811C1D6F70AC00E5FA99 /* GlobalQueue.swift */,
|
||||
97D6811D1D6F70AC00E5FA99 /* RefreshLibraryOperation.swift */,
|
||||
@ -1514,7 +1514,7 @@
|
||||
970E68B61D37E224001E8514 /* SettingSearchHistoryTBVC.swift in Sources */,
|
||||
97C005D81D64B99E004352E8 /* LibrarySplitViewController.swift in Sources */,
|
||||
97FDACC41D85A3B300DEDACB /* Language+CoreDataProperties.swift in Sources */,
|
||||
974F33C61D99CAD700879D35 /* BookmarkMigrationOperation.swift in Sources */,
|
||||
974F33C61D99CAD700879D35 /* BookmarkOperation.swift in Sources */,
|
||||
97A8AD871D6CF38000584ED1 /* EmptyTableConfigExtension.swift in Sources */,
|
||||
971A102E1D022AD5007FC62C /* TableViewCells.swift in Sources */,
|
||||
97DF259D1D6F9053001648A3 /* URLSessionDownloadTaskOperation.swift in Sources */,
|
||||
|
@ -33,53 +33,5 @@
|
||||
endingLineNumber = "37">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
shouldBeEnabled = "Yes"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Kiwix/Operations/BookmarkMigrationOperation.swift"
|
||||
timestampString = "496692057.397729"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "27"
|
||||
endingLineNumber = "27"
|
||||
landmarkName = "execute()"
|
||||
landmarkType = "7">
|
||||
<Locations>
|
||||
<Location
|
||||
shouldBeEnabled = "Yes"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
symbolName = "Kiwix.BookmarkMigrationOperation.(execute () -> ()).(closure #1)"
|
||||
moduleName = "Kiwix"
|
||||
usesParentBreakpointCondition = "Yes"
|
||||
urlString = "file:///Volumes/Data/Developer/Kiwix/Kiwix/Operations/BookmarkMigrationOperation.swift"
|
||||
timestampString = "496794457.332421"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "27"
|
||||
endingLineNumber = "27"
|
||||
offsetFromSymbolStart = "28">
|
||||
</Location>
|
||||
<Location
|
||||
shouldBeEnabled = "Yes"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
symbolName = "Kiwix.BookmarkMigrationOperation.(execute () -> ()).(closure #1).(closure #1)"
|
||||
moduleName = "Kiwix"
|
||||
usesParentBreakpointCondition = "Yes"
|
||||
urlString = "file:///Volumes/Data/Developer/Kiwix/Kiwix/Operations/BookmarkMigrationOperation.swift"
|
||||
timestampString = "496794457.333823"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "27"
|
||||
endingLineNumber = "27"
|
||||
offsetFromSymbolStart = "36">
|
||||
</Location>
|
||||
</Locations>
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
</Breakpoints>
|
||||
</Bucket>
|
||||
|
@ -1,38 +0,0 @@
|
||||
//
|
||||
// BookmarkMigrationOperation.swift
|
||||
// Kiwix
|
||||
//
|
||||
// Created by Chris Li on 9/26/16.
|
||||
// Copyright © 2016 Chris. All rights reserved.
|
||||
//
|
||||
|
||||
import CoreData
|
||||
import Operations
|
||||
|
||||
class BookmarkMigrationOperation: Operation {
|
||||
private let context: NSManagedObjectContext
|
||||
|
||||
override init() {
|
||||
self.context = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
|
||||
context.parentContext = NSManagedObjectContext.mainQueueContext
|
||||
context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
|
||||
|
||||
super.init()
|
||||
addCondition(MutuallyExclusive<GlobalQueue>())
|
||||
name = String(self)
|
||||
}
|
||||
|
||||
override func execute() {
|
||||
context.performBlockAndWait {
|
||||
let pids = Book.fetchLocal(self.context).flatMap({$1.pid})
|
||||
for pid in pids {
|
||||
var books = Book.fetch(pid: pid, context: self.context)
|
||||
let latestBook = books.removeFirst()
|
||||
for book in books {
|
||||
book.articles.forEach({$0.book = latestBook})
|
||||
}
|
||||
}
|
||||
if self.context.hasChanges {_ = try? self.context.save()}
|
||||
}
|
||||
}
|
||||
}
|
81
Kiwix/Operations/BookmarkOperation.swift
Normal file
81
Kiwix/Operations/BookmarkOperation.swift
Normal file
@ -0,0 +1,81 @@
|
||||
//
|
||||
// BookmarkMigrationOperation.swift
|
||||
// Kiwix
|
||||
//
|
||||
// Created by Chris Li on 9/26/16.
|
||||
// Copyright © 2016 Chris. All rights reserved.
|
||||
//
|
||||
|
||||
import CoreData
|
||||
import Operations
|
||||
|
||||
class BookmarkMigrationOperation: Operation {
|
||||
private let context: NSManagedObjectContext
|
||||
|
||||
override init() {
|
||||
self.context = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
|
||||
context.parentContext = NSManagedObjectContext.mainQueueContext
|
||||
context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
|
||||
|
||||
super.init()
|
||||
addCondition(MutuallyExclusive<GlobalQueue>())
|
||||
name = String(self)
|
||||
}
|
||||
|
||||
override func execute() {
|
||||
context.performBlockAndWait {
|
||||
let pids = Book.fetchLocal(self.context).flatMap({$1.pid})
|
||||
for pid in pids {
|
||||
var books = Book.fetch(pid: pid, context: self.context)
|
||||
let latestBook = books.removeFirst()
|
||||
for book in books {
|
||||
book.articles.forEach({$0.book = latestBook})
|
||||
}
|
||||
}
|
||||
if self.context.hasChanges {_ = try? self.context.save()}
|
||||
}
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
class BookmarkTrashOperation: Operation {
|
||||
private let context: NSManagedObjectContext
|
||||
private let articles: [Article]
|
||||
|
||||
init(articles: [Article]) {
|
||||
self.context = NSManagedObjectContext.mainQueueContext
|
||||
self.articles = articles
|
||||
|
||||
super.init()
|
||||
addCondition(MutuallyExclusive<BookmarkController>())
|
||||
name = String(self)
|
||||
}
|
||||
|
||||
override func execute() {
|
||||
context.performBlock {
|
||||
self.articles.forEach() {
|
||||
$0.isBookmarked = false
|
||||
$0.bookmarkDate = nil
|
||||
}
|
||||
|
||||
// Get books whose zim file removed, but are retain by bookmarks, and whose bookmarks are all removed
|
||||
let books = Set(self.articles.flatMap({$0.book}))
|
||||
.filter({Article.fetchBookmarked(in: $0, with: self.context).count == 0 && $0.state == .Retained})
|
||||
books.forEach({ (book) in
|
||||
if let _ = book.meta4URL {
|
||||
book.state = .Cloud
|
||||
} else {
|
||||
self.context.deleteObject(book)
|
||||
}
|
||||
})
|
||||
|
||||
if self.context.hasChanges {_ = try? self.context.save()}
|
||||
}
|
||||
|
||||
if articles.count > 0 {
|
||||
produceOperation(UpdateWidgetDataSourceOperation())
|
||||
}
|
||||
|
||||
finish()
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user