mirror of
https://github.com/kiwix/kiwix-apple.git
synced 2025-09-26 05:18:31 -04:00
Commit
This commit is contained in:
parent
783fe2640c
commit
b9e01de6fc
@ -21,9 +21,24 @@ class BookmarkCollectionController: UIViewController, UICollectionViewDataSource
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func dismiss(_ sender: UIBarButtonItem) {
|
||||
dismiss(animated: true, completion: nil)
|
||||
}
|
||||
|
||||
func configureItemWidth(collectionViewWidth: CGFloat) {
|
||||
let itemsPerRow = ((collectionViewWidth - 10) / 300).rounded()
|
||||
self.itemWidth = floor((collectionViewWidth - (itemsPerRow + 1) * 10) / itemsPerRow)
|
||||
}
|
||||
|
||||
// MARK: - override
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
collectionView.alwaysBounceVertical = true
|
||||
|
||||
if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
|
||||
layout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
|
||||
}
|
||||
}
|
||||
|
||||
override func viewDidLayoutSubviews() {
|
||||
@ -36,15 +51,6 @@ class BookmarkCollectionController: UIViewController, UICollectionViewDataSource
|
||||
collectionView.collectionViewLayout.invalidateLayout()
|
||||
}
|
||||
|
||||
@IBAction func dismiss(_ sender: UIBarButtonItem) {
|
||||
dismiss(animated: true, completion: nil)
|
||||
}
|
||||
|
||||
func configureItemWidth(collectionViewWidth: CGFloat) {
|
||||
let itemsPerRow = ((collectionViewWidth - 10) / 300).rounded()
|
||||
self.itemWidth = floor((collectionViewWidth - (itemsPerRow + 1) * 10) / itemsPerRow)
|
||||
}
|
||||
|
||||
// MARK: - UICollectionView Data Source
|
||||
|
||||
func numberOfSections(in collectionView: UICollectionView) -> Int {
|
||||
@ -56,7 +62,7 @@ class BookmarkCollectionController: UIViewController, UICollectionViewDataSource
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! BookmarkCollectionCell
|
||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell2", for: indexPath) as! BookmarkCollectionCell
|
||||
let article = fetchedResultController.object(at: indexPath)
|
||||
cell.titleLabel.text = article.title
|
||||
cell.snippetLabel.text = article.snippet
|
||||
@ -70,12 +76,9 @@ class BookmarkCollectionController: UIViewController, UICollectionViewDataSource
|
||||
return CGSize(width: itemWidth, height: itemWidth)
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
|
||||
return UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
|
||||
}
|
||||
|
||||
// MARK: - NSFetchedResultsControllerDelegate
|
||||
|
||||
var blocks = [() -> Void]()
|
||||
var blockOperations: [BlockOperation] = []
|
||||
let managedObjectContext = AppDelegate.persistentContainer.viewContext
|
||||
lazy var fetchedResultController: NSFetchedResultsController<Article> = {
|
||||
@ -86,9 +89,62 @@ class BookmarkCollectionController: UIViewController, UICollectionViewDataSource
|
||||
|
||||
let cacheName = ["BookmarkFRC", self.book?.title ?? "All", Bundle.buildVersion].joined(separator: "_")
|
||||
let controller = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext, sectionNameKeyPath: nil, cacheName: cacheName)
|
||||
// controller.delegate = self
|
||||
controller.delegate = self
|
||||
try? controller.performFetch()
|
||||
return controller as! NSFetchedResultsController<Article>
|
||||
}()
|
||||
|
||||
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
|
||||
switch type {
|
||||
case .insert:
|
||||
guard collectionView.numberOfSections > 0,
|
||||
let newIndexPath = newIndexPath,
|
||||
collectionView.numberOfItems(inSection: newIndexPath.section) > 0 else {
|
||||
shouldReloadCollectionView = true
|
||||
break
|
||||
}
|
||||
blocks.append({ self.collectionView.insertItems(at: [newIndexPath]) })
|
||||
case .delete:
|
||||
guard let indexPath = indexPath else {break}
|
||||
blocks.append({ self.collectionView.reloadItems(at: [indexPath]) })
|
||||
case .move:
|
||||
guard let indexPath = indexPath, let newIndexPath = newIndexPath else {break}
|
||||
blocks.append({ self.collectionView.moveItem(at: indexPath, to: newIndexPath) })
|
||||
case .update:
|
||||
guard let indexPath = indexPath, collectionView.numberOfItems(inSection: indexPath.section) != 1 else {
|
||||
self.shouldReloadCollectionView = true
|
||||
break
|
||||
}
|
||||
blocks.append({ self.collectionView.deleteItems(at: [indexPath]) })
|
||||
}
|
||||
}
|
||||
|
||||
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {
|
||||
|
||||
switch type {
|
||||
case .insert:
|
||||
blocks.append({ self.collectionView.insertSections(IndexSet(integer: sectionIndex)) })
|
||||
case .delete:
|
||||
blocks.append({ self.collectionView.deleteSections(IndexSet(integer: sectionIndex)) })
|
||||
case .move:
|
||||
break
|
||||
case .update:
|
||||
blocks.append({ self.collectionView.reloadSections(IndexSet(integer: sectionIndex)) })
|
||||
}
|
||||
}
|
||||
|
||||
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
|
||||
OperationQueue.main.addOperation({
|
||||
if self.shouldReloadCollectionView {
|
||||
self.collectionView.reloadData()
|
||||
} else {
|
||||
self.collectionView.performBatchUpdates({
|
||||
self.blocks.forEach({ $0() })
|
||||
}, completion: { (completed) in
|
||||
self.blocks.removeAll()
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,20 +34,45 @@
|
||||
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||
</collectionViewFlowLayout>
|
||||
<cells>
|
||||
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="Cell" id="lfi-9s-ZjZ" customClass="BookmarkCollectionCell" customModule="Kiwix" customModuleProvider="target">
|
||||
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="Cell2" id="Qh9-Dg-cx2" customClass="BookmarkCollectionCell2" customModule="Kiwix" customModuleProvider="target">
|
||||
<rect key="frame" x="104" y="0.0" width="207" height="169"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
||||
<rect key="frame" x="0.0" y="0.0" width="207" height="169"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="CQi-0M-O0e">
|
||||
<rect key="frame" x="63" y="117" width="44" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="HlJ-Gh-ypg">
|
||||
<rect key="frame" x="0.0" y="0.0" width="207" height="169"/>
|
||||
</imageView>
|
||||
</subviews>
|
||||
</view>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="HlJ-Gh-ypg" secondAttribute="bottom" id="XNJ-UB-503"/>
|
||||
<constraint firstAttribute="trailing" secondItem="HlJ-Gh-ypg" secondAttribute="trailing" id="YMT-pX-wS0"/>
|
||||
<constraint firstItem="HlJ-Gh-ypg" firstAttribute="leading" secondItem="Qh9-Dg-cx2" secondAttribute="leading" id="Yzl-2O-HbG"/>
|
||||
<constraint firstItem="HlJ-Gh-ypg" firstAttribute="top" secondItem="Qh9-Dg-cx2" secondAttribute="top" id="k0W-oo-MeX"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outlet property="thumbImageView" destination="HlJ-Gh-ypg" id="PGR-cg-qZH"/>
|
||||
</connections>
|
||||
</collectionViewCell>
|
||||
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="Cell" id="lfi-9s-ZjZ" customClass="BookmarkCollectionCell" customModule="Kiwix" customModuleProvider="target">
|
||||
<rect key="frame" x="104" y="179" width="207" height="169"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
||||
<rect key="frame" x="0.0" y="0.0" width="207" height="169"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="CQi-0M-O0e">
|
||||
<rect key="frame" x="8" y="129" width="32" height="32"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="32" id="3bz-bb-cig"/>
|
||||
<constraint firstAttribute="width" constant="32" id="aFo-L8-O71"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="LK0-aY-C9L">
|
||||
<rect key="frame" x="8" y="37" width="191" height="18"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||
<rect key="frame" x="8" y="29" width="191" height="17"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
@ -60,15 +85,42 @@
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="9EM-Do-qfE">
|
||||
<rect key="frame" x="8" y="124" width="191" height="2"/>
|
||||
<color key="backgroundColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="2" id="y4a-qe-lIJ"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Alw-Di-WEl">
|
||||
<rect key="frame" x="48" y="128" width="31" height="13.333333333333343"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="12"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="HLG-V7-emv">
|
||||
<rect key="frame" x="153" y="131" width="46" height="30"/>
|
||||
<state key="normal" title="Button"/>
|
||||
</button>
|
||||
</subviews>
|
||||
</view>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstItem="LK0-aY-C9L" firstAttribute="top" secondItem="YA4-yb-hoI" secondAttribute="bottom" constant="8" id="95I-Gx-tc1"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="9EM-Do-qfE" secondAttribute="trailing" id="0H3-5k-m0f"/>
|
||||
<constraint firstItem="LK0-aY-C9L" firstAttribute="top" secondItem="YA4-yb-hoI" secondAttribute="bottom" id="95I-Gx-tc1"/>
|
||||
<constraint firstItem="CQi-0M-O0e" firstAttribute="top" secondItem="9EM-Do-qfE" secondAttribute="bottom" constant="3" id="9jg-Ou-dzI"/>
|
||||
<constraint firstItem="Alw-Di-WEl" firstAttribute="leading" secondItem="CQi-0M-O0e" secondAttribute="trailing" constant="8" id="Eoq-GI-7la"/>
|
||||
<constraint firstItem="Alw-Di-WEl" firstAttribute="top" secondItem="9EM-Do-qfE" secondAttribute="bottom" constant="2" id="GkX-zd-iqc"/>
|
||||
<constraint firstItem="9EM-Do-qfE" firstAttribute="top" relation="greaterThanOrEqual" secondItem="LK0-aY-C9L" secondAttribute="bottom" id="Hju-Lg-iT1"/>
|
||||
<constraint firstItem="YA4-yb-hoI" firstAttribute="top" secondItem="lfi-9s-ZjZ" secondAttribute="topMargin" id="MCl-Il-92w"/>
|
||||
<constraint firstAttribute="bottomMargin" secondItem="HLG-V7-emv" secondAttribute="bottom" id="MLR-CH-oRZ"/>
|
||||
<constraint firstItem="LK0-aY-C9L" firstAttribute="trailing" secondItem="lfi-9s-ZjZ" secondAttribute="trailingMargin" id="Uyi-Wf-Cnt"/>
|
||||
<constraint firstAttribute="leadingMargin" secondItem="CQi-0M-O0e" secondAttribute="leading" id="ZX6-PL-WbD"/>
|
||||
<constraint firstItem="YA4-yb-hoI" firstAttribute="trailing" secondItem="lfi-9s-ZjZ" secondAttribute="trailingMargin" id="hLA-Zn-QPh"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="HLG-V7-emv" secondAttribute="trailing" id="lIe-ot-ssw"/>
|
||||
<constraint firstItem="YA4-yb-hoI" firstAttribute="leading" secondItem="lfi-9s-ZjZ" secondAttribute="leadingMargin" id="rW4-0u-SSB"/>
|
||||
<constraint firstAttribute="bottomMargin" secondItem="CQi-0M-O0e" secondAttribute="bottom" id="v5E-tX-8bf"/>
|
||||
<constraint firstAttribute="leadingMargin" secondItem="9EM-Do-qfE" secondAttribute="leading" id="wFD-yH-9vp"/>
|
||||
<constraint firstItem="LK0-aY-C9L" firstAttribute="leading" secondItem="lfi-9s-ZjZ" secondAttribute="leadingMargin" id="zBD-zk-mO8"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
|
@ -122,16 +122,38 @@ class BookmarkCollectionCell: UICollectionViewCell {
|
||||
@IBOutlet weak var snippetLabel: UILabel!
|
||||
}
|
||||
|
||||
class ArticleCell: FavIconAndPicIndicatorCell {
|
||||
class BookmarkCollectionCell2: UICollectionViewCell {
|
||||
override func awakeFromNib() {
|
||||
clipsToBounds = false
|
||||
backgroundColor = UIColor.clear
|
||||
layer.masksToBounds = false
|
||||
layer.shadowColor = UIColor.lightGray.cgColor
|
||||
layer.shadowOpacity = 0.5
|
||||
layer.shadowOffset = CGSize.zero
|
||||
layer.shadowRadius = 1.0
|
||||
|
||||
contentView.clipsToBounds = true
|
||||
contentView.backgroundColor = UIColor.white
|
||||
contentView.layer.masksToBounds = true
|
||||
contentView.layer.cornerRadius = 2.0
|
||||
|
||||
thumbImageView.layer.cornerRadius = 4.0
|
||||
thumbImageView.clipsToBounds = true
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
layer.shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: 2.0).cgPath
|
||||
}
|
||||
|
||||
@IBOutlet weak var thumbImageView: UIImageView!
|
||||
@IBOutlet weak var titleLabel: UILabel!
|
||||
}
|
||||
|
||||
class ArticleSnippetCell: ArticleCell {
|
||||
@IBOutlet weak var snippetLabel: UILabel!
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// MARK: - last time refactor
|
||||
|
||||
// MARK: - Bookmark Cell
|
||||
|
Loading…
x
Reference in New Issue
Block a user