deep-linking-sample/Apps/Wikipedia/ContinueReadingWidget/WMFTodayContinueReadingWidgetViewController.swift
Javier Cicchelli 9bcdaa697b [Setup] Basic project structure (#1)
This PR contains all the work related to setting up this project as required to implement the [Assignment](https://repo.rock-n-code.com/rock-n-code/deep-linking-assignment/wiki/Assignment) on top, as intended.

To summarise this work:
- [x] created a new **Xcode** project;
- [x] cloned the `Wikipedia` app and inserted it into the **Xcode** project;
- [x] created the `Locations` app and also, its `Libraries` package;
- [x] created the `Shared` package to share dependencies between the apps;
- [x] added a `Makefile` file and implemented some **environment** and **help** commands.

Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
Reviewed-on: rock-n-code/deep-linking-assignment#1
2023-04-08 18:37:13 +00:00

174 lines
6.4 KiB
Swift

import UIKit
import NotificationCenter
import WMF
@available(*, deprecated, message: "TODO: Rework into iOS 14 home screen widget")
class WMFTodayContinueReadingWidgetViewController: ExtensionViewController, NCWidgetProviding {
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var daysAgoView: UIView!
@IBOutlet weak var daysAgoLabel: UILabel!
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var textLabel: UILabel!
@IBOutlet weak var emptyView: UIView!
@IBOutlet weak var emptyTitleLabel: UILabel!
@IBOutlet weak var emptyDescriptionLabel: UILabel!
@IBOutlet var imageWidthConstraint: NSLayoutConstraint!
@IBOutlet var titleLabelTrailingConstraint: NSLayoutConstraint!
var articleURL: URL?
override func apply(theme: Theme) {
super.apply(theme: theme)
guard viewIfLoaded != nil else {
return
}
titleLabel.textColor = theme.colors.primaryText
textLabel.textColor = theme.colors.secondaryText
emptyTitleLabel.textColor = theme.colors.primaryText
emptyDescriptionLabel.textColor = theme.colors.secondaryText
daysAgoLabel.textColor = theme.colors.overlayText
daysAgoView.backgroundColor = theme.colors.overlayBackground
}
override func viewDidLoad() {
super.viewDidLoad()
imageView.accessibilityIgnoresInvertColors = true
emptyDescriptionLabel.text = WMFLocalizedString("continue-reading-empty-title", value:"No recently read articles", comment: "No recently read articles")
emptyDescriptionLabel.text = WMFLocalizedString("continue-reading-empty-description", value:"Explore Wikipedia for more articles to read", comment: "Explore Wikipedia for more articles to read")
view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.handleTapGestureRecognizer(_:))))
}
@objc func handleTapGestureRecognizer(_ recognizer: UITapGestureRecognizer) {
switch recognizer.state {
case .ended:
continueReading(self)
default:
break
}
}
func widgetPerformUpdate(completionHandler: @escaping (NCUpdateResult) -> Void) {
WidgetController.shared.startWidgetUpdateTask(completionHandler) { (dataStore, completion) in
self.updateView(with: dataStore) { didUpdate in
if didUpdate {
completion(.newData)
} else {
completion(.noData)
}
}
}
}
var emptyViewHidden: Bool = false {
didSet {
emptyView.isHidden = emptyViewHidden
titleLabel.isHidden = !emptyViewHidden
textLabel.isHidden = !emptyViewHidden
imageView.isHidden = !emptyViewHidden
daysAgoView.isHidden = !emptyViewHidden
}
}
var collapseImageAndWidenLabels: Bool = true {
didSet {
imageWidthConstraint.constant = collapseImageAndWidenLabels ? 0 : 86
titleLabelTrailingConstraint.constant = collapseImageAndWidenLabels ? 0 : 10
self.imageView.alpha = self.collapseImageAndWidenLabels ? 0 : 1
self.view.layoutIfNeeded()
}
}
func updateView(with dataStore: MWKDataStore, completion: @escaping (Bool) -> Void) {
let article: WMFArticle
if let openArticleURL = dataStore.viewContext.openArticleURL, let openArticle = dataStore.fetchArticle(with: openArticleURL) {
article = openArticle
} else if let mostRecentHistoryEntry = dataStore.viewContext.mostRecentlyReadArticle {
article = mostRecentHistoryEntry
} else {
completion(false)
return
}
let newArticleURL: URL?
if let fragment = article.viewedFragment {
newArticleURL = article.url?.wmf_URL(withFragment: fragment)
} else {
newArticleURL = article.url
}
guard newArticleURL != nil, newArticleURL?.absoluteString != articleURL?.absoluteString else {
completion(false)
return
}
articleURL = newArticleURL
textLabel.text = nil
titleLabel.text = nil
imageView.image = nil
imageView.isHidden = true
daysAgoLabel.text = nil
daysAgoView.isHidden = true
emptyViewHidden = true
if let subtitle = article.capitalizedWikidataDescriptionOrSnippet {
self.textLabel.text = subtitle
} else {
self.textLabel.text = nil
}
if let date = article.viewedDate {
self.daysAgoView.isHidden = false
self.daysAgoLabel.text = (date as NSDate).wmf_localizedRelativeDateStringFromLocalDateToNow()
} else {
self.daysAgoView.isHidden = true
}
self.titleLabel.attributedText = article.displayTitleHTML.byAttributingHTML(with: .headline, matching: traitCollection)
let combinedCompletion = {
self.updatePreferredContentSize()
completion(true)
}
if let imageURL = article.imageURL(forWidth: self.traitCollection.wmf_nearbyThumbnailWidth) {
self.collapseImageAndWidenLabels = false
self.imageView.wmf_imageController = dataStore.cacheController
self.imageView.wmf_setImage(with: imageURL, detectFaces: true, onGPU: true, failure: { (error) in
self.collapseImageAndWidenLabels = true
combinedCompletion()
}) {
self.collapseImageAndWidenLabels = false
combinedCompletion()
}
} else {
self.collapseImageAndWidenLabels = true
combinedCompletion()
}
}
func updatePreferredContentSize() {
var fitSize = UIView.layoutFittingCompressedSize
fitSize.width = view.bounds.size.width
fitSize = view.systemLayoutSizeFitting(fitSize, withHorizontalFittingPriority: UILayoutPriority.required, verticalFittingPriority: UILayoutPriority.defaultLow)
preferredContentSize = fitSize
}
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
updatePreferredContentSize()
}
@IBAction func continueReading(_ sender: AnyObject) {
openApp(with: articleURL)
}
}