update widget

This commit is contained in:
Chris Li 2016-11-07 17:15:36 -05:00
parent fcb596577b
commit f5772ab056
3 changed files with 44 additions and 44 deletions

View File

@ -49,7 +49,7 @@
</dict> </dict>
</array> </array>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.8.1871</string> <string>1.8.1872</string>
<key>ITSAppUsesNonExemptEncryption</key> <key>ITSAppUsesNonExemptEncryption</key>
<false/> <false/>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>

View File

@ -21,7 +21,7 @@
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.8.1871</string> <string>1.8.1872</string>
<key>NSExtension</key> <key>NSExtension</key>
<dict> <dict>
<key>NSExtensionMainStoryboard</key> <key>NSExtensionMainStoryboard</key>

View File

@ -13,15 +13,15 @@ class TodayViewController: UIViewController, NCWidgetProviding, UICollectionView
@IBOutlet weak var collectionView: UICollectionView! @IBOutlet weak var collectionView: UICollectionView!
private let hInset: CGFloat = 15.0 fileprivate let hInset: CGFloat = 15.0
private let vInset: CGFloat = 10.0 fileprivate let vInset: CGFloat = 10.0
private var itemSize = CGSizeZero fileprivate var itemSize = CGSize.zero
private var itemsPerRow: CGFloat = 5 fileprivate var itemsPerRow: CGFloat = 5
private var rowCount: CGFloat = 1 fileprivate var rowCount: CGFloat = 1
private var maxRowCount: CGFloat = 1 fileprivate var maxRowCount: CGFloat = 1
private var hasUpdate = true fileprivate var hasUpdate = true
private var bookmarks = [NSDictionary]() fileprivate var bookmarks = [NSDictionary]()
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
@ -33,15 +33,15 @@ class TodayViewController: UIViewController, NCWidgetProviding, UICollectionView
updateUI() updateUI()
} }
override func viewWillAppear(animated: Bool) { override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated) super.viewWillAppear(animated)
updateData() updateData()
calculateItemSize(collectionViewWidth: collectionView.frame.width) calculateItemSize(collectionViewWidth: collectionView.frame.width)
updateUI() updateUI()
} }
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) { override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator) super.viewWillTransition(to: size, with: coordinator)
calculateItemSize(collectionViewWidth: size.width) calculateItemSize(collectionViewWidth: size.width)
updateUI() updateUI()
} }
@ -49,11 +49,11 @@ class TodayViewController: UIViewController, NCWidgetProviding, UICollectionView
// MARK: - Update & Calculation // MARK: - Update & Calculation
func updateData() { func updateData() {
guard let defaults = NSUserDefaults(suiteName: "group.kiwix") else {return} guard let defaults = UserDefaults(suiteName: "group.kiwix") else {return}
guard let bookmarks = defaults.objectForKey("bookmarks") as? [NSDictionary] else {return} guard let bookmarks = defaults.object(forKey: "bookmarks") as? [NSDictionary] else {return}
hasUpdate = self.bookmarks != bookmarks hasUpdate = self.bookmarks != bookmarks
self.bookmarks = bookmarks self.bookmarks = bookmarks
maxRowCount = CGFloat(max(1, min(defaults.integerForKey("BookmarkWidgetMaxRowCount"), 3))) maxRowCount = CGFloat(max(1, min(defaults.integer(forKey: "BookmarkWidgetMaxRowCount"), 3)))
} }
func updateUI() { func updateUI() {
@ -62,98 +62,98 @@ class TodayViewController: UIViewController, NCWidgetProviding, UICollectionView
NCWidgetController.widgetController().setHasContent(bookmarks.count > 0, forWidgetWithBundleIdentifier: "self.Kiwix.Bookmarks") NCWidgetController.widgetController().setHasContent(bookmarks.count > 0, forWidgetWithBundleIdentifier: "self.Kiwix.Bookmarks")
} }
func calculateItemSize(collectionViewWidth collectionViewWidth: CGFloat) { func calculateItemSize(collectionViewWidth: CGFloat) {
itemsPerRow = max(5, min(round(collectionViewWidth / 70), 10)) itemsPerRow = max(5, min(round(collectionViewWidth / 70), 10))
let itemWidth = (collectionViewWidth - (itemsPerRow + 1) * hInset) / itemsPerRow let itemWidth = (collectionViewWidth - (itemsPerRow + 1) * hInset) / itemsPerRow
let titles = bookmarks.flatMap({$0.objectForKey("title") as? String}) let titles = bookmarks.flatMap({$0.object(forKey: "title") as? String})
let labelHeights = titles.map({$0.heightWithConstrainedWidth(itemWidth, font: UIFont.systemFontOfSize(10.0, weight: UIFontWeightMedium))}) let labelHeights = titles.map({$0.heightWithConstrainedWidth(itemWidth, font: UIFont.systemFont(ofSize: 10.0, weight: UIFontWeightMedium))})
let labelMaxHeight = max(12.0, min((labelHeights.maxElement() ?? 12.0), 24.0)) let labelMaxHeight = max(12.0, min((labelHeights.max() ?? 12.0), 24.0))
let itemHeight = itemWidth + 2.0 + labelMaxHeight // itemHeight (1:1 ration) + label top spacing + label height let itemHeight = itemWidth + 2.0 + labelMaxHeight // itemHeight (1:1 ration) + label top spacing + label height
itemSize = CGSizeMake(itemWidth, itemHeight) itemSize = CGSize(width: itemWidth, height: itemHeight)
rowCount = min(ceil(CGFloat(bookmarks.count) / CGFloat(itemsPerRow)), maxRowCount) rowCount = min(ceil(CGFloat(bookmarks.count) / CGFloat(itemsPerRow)), maxRowCount)
let collectionViewHeight = itemHeight * rowCount + hInset * rowCount let collectionViewHeight = itemHeight * rowCount + hInset * rowCount
preferredContentSize = CGSizeMake(0, max(1, collectionViewHeight)) preferredContentSize = CGSize(width: 0, height: max(1, collectionViewHeight))
} }
// MARK: - NCWidgetProviding // MARK: - NCWidgetProviding
func widgetMarginInsetsForProposedMarginInsets(defaultMarginInsets: UIEdgeInsets) -> UIEdgeInsets { func widgetMarginInsets(forProposedMarginInsets defaultMarginInsets: UIEdgeInsets) -> UIEdgeInsets {
return UIEdgeInsetsZero return UIEdgeInsets.zero
} }
func widgetPerformUpdateWithCompletionHandler(completionHandler: ((NCUpdateResult) -> Void)) { func widgetPerformUpdate(completionHandler: (@escaping (NCUpdateResult) -> Void)) {
updateData() updateData()
calculateItemSize(collectionViewWidth: collectionView.frame.width) calculateItemSize(collectionViewWidth: collectionView.frame.width)
updateUI() updateUI()
completionHandler(hasUpdate ? .NewData : .NoData) completionHandler(hasUpdate ? .newData : .noData)
hasUpdate = false hasUpdate = false
} }
// MARK: - UICollectionViewDataSource // MARK: - UICollectionViewDataSource
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int { func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1 return 1
} }
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return min(bookmarks.count, Int(itemsPerRow * rowCount)) return min(bookmarks.count, Int(itemsPerRow * rowCount))
} }
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("BookmarkWidgetCell", forIndexPath: indexPath) let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "BookmarkWidgetCell", for: indexPath)
configureCell(cell, atIndexPath: indexPath) configureCell(cell, atIndexPath: indexPath)
return cell return cell
} }
func configureCell(cell: UICollectionViewCell, atIndexPath indexPath: NSIndexPath) { func configureCell(_ cell: UICollectionViewCell, atIndexPath indexPath: IndexPath) {
guard let cell = cell as? BookmarkWidgetCell else {return} guard let cell = cell as? BookmarkWidgetCell else {return}
let bookmark = bookmarks[indexPath.item] let bookmark = bookmarks[indexPath.item]
guard let title = bookmark["title"] as? String, guard let title = bookmark["title"] as? String,
let thumbImageData = bookmark["thumbImageData"] as? NSData else {return} let thumbImageData = bookmark["thumbImageData"] as? Data else {return}
cell.label.text = title cell.label.text = title
cell.imageView.image = UIImage(data: thumbImageData) cell.imageView.image = UIImage(data: thumbImageData)
if #available(iOS 10, *) { if #available(iOS 10, *) {
cell.label.textColor = UIColor.darkGrayColor() cell.label.textColor = UIColor.darkGray
} }
} }
// MARK: - UICollectionViewDelegate // MARK: - UICollectionViewDelegate
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) { func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let bookmark = bookmarks[indexPath.item] let bookmark = bookmarks[indexPath.item]
guard let urlString = bookmark["url"] as? String, guard let urlString = bookmark["url"] as? String,
let url = NSURL(string: urlString) else {return} let url = URL(string: urlString) else {return}
extensionContext?.openURL(url, completionHandler: { (completed) in extensionContext?.open(url, completionHandler: { (completed) in
collectionView.deselectItemAtIndexPath(indexPath, animated: true) collectionView.deselectItem(at: indexPath, animated: true)
}) })
} }
// MARK: - UICollectionViewDelegateFlowLayout // MARK: - UICollectionViewDelegateFlowLayout
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return itemSize return itemSize
} }
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return hInset return hInset
} }
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return vInset return vInset
} }
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsetsMake(vInset, hInset, vInset, hInset) return UIEdgeInsetsMake(vInset, hInset, vInset, hInset)
} }
} }
private extension String { private extension String {
func heightWithConstrainedWidth(width: CGFloat, font: UIFont) -> CGFloat { func heightWithConstrainedWidth(_ width: CGFloat, font: UIFont) -> CGFloat {
let constraintRect = CGSize(width: width, height: CGFloat.max) let constraintRect = CGSize(width: width, height: CGFloat.greatestFiniteMagnitude)
let boundingBox = self.boundingRectWithSize(constraintRect, options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil) let boundingBox = self.boundingRect(with: constraintRect, options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
return boundingBox.height return boundingBox.height
} }
} }