Implement Read and Star button functionality

This commit is contained in:
Maurice Parker
2020-07-09 18:44:51 -05:00
parent 3e61c7044b
commit 2d57945e98
12 changed files with 166 additions and 154 deletions

View File

@@ -14,49 +14,90 @@ import RSCore
final class SceneModel: ObservableObject {
@Published var refreshProgressState = RefreshProgressModel.State.none
@Published var readButtonState: ArticleReadButtonState?
@Published var starButtonState: ArticleStarButtonState?
private var refreshProgressModel: RefreshProgressModel? = nil
private var articleIconSchemeHandler: ArticleIconSchemeHandler? = nil
var webViewProvider: WebViewProvider? = nil
var undoManager: UndoManager?
var undoableCommands = [UndoableCommand]()
var sidebarModel: SidebarModel?
var timelineModel: TimelineModel?
var articleModel: ArticleModel?
private var refreshProgressModel: RefreshProgressModel? = nil
private var articleIconSchemeHandler: ArticleIconSchemeHandler? = nil
private var webViewProvider: WebViewProvider? = nil
var articleManager: ArticleManager?
var currentArticle: Article? {
return articleManager?.currentArticle
}
// MARK: Initialization API
/// Prepares the SceneModel to be used in the views
func startup() {
self.refreshProgressModel = RefreshProgressModel()
self.refreshProgressModel!.$state.assign(to: self.$refreshProgressState)
self.articleIconSchemeHandler = ArticleIconSchemeHandler(sceneModel: self)
self.webViewProvider = WebViewProvider(articleIconSchemeHandler: self.articleIconSchemeHandler!)
NotificationCenter.default.addObserver(self, selector: #selector(statusesDidChange(_:)), name: .StatusesDidChange, object: nil)
}
// MARK: Article Status Change API
// MARK: Article Management API
/// Toggles the read indicator for the currently viewable article
func toggleReadForCurrentArticle() {
articleModel?.toggleReadForCurrentArticle()
if let article = articleManager?.currentArticle {
toggleRead(article)
}
}
/// Toggles the read indicator for the given article
func toggleRead(_ article: Article) {
guard !article.status.read || article.isAvailableToMarkUnread else { return }
markArticles([article], statusKey: .read, flag: !article.status.read)
}
/// Toggles the star indicator for the currently viewable article
func toggleStarForCurrentArticle() {
articleModel?.toggleStarForCurrentArticle()
if let article = articleManager?.currentArticle {
toggleStar(article)
}
}
/// Toggles the star indicator for the given article
func toggleStar(_ article: Article) {
markArticles([article], statusKey: .starred, flag: !article.status.starred)
}
// MARK: Resource lookup API
/// Retrieves the article before the given article in the Timeline
func findPrevArticle(_ article: Article) -> Article? {
return timelineModel?.findPrevArticle(article)
}
/// Retrieves the article after the given article in the Timeline
func findNextArticle(_ article: Article) -> Article? {
return timelineModel?.findNextArticle(article)
}
/// Marks the article as read and selects it in the Timeline. Don't call until after the ArticleManager article has been set.
func updateArticleSelection() {
guard let article = currentArticle else { return }
timelineModel?.selectArticle(article)
if article.status.read {
updateArticleState()
} else {
markArticles([article], statusKey: .read, flag: true)
}
}
/// Returns the article with the given articleID
func articleFor(_ articleID: String) -> Article? {
return timelineModel?.articleFor(articleID)
}
@@ -83,28 +124,6 @@ extension SceneModel: TimelineModelDelegate {
}
// MARK: ArticleModelDelegate
extension SceneModel: ArticleModelDelegate {
var articleModelWebViewProvider: WebViewProvider? {
return webViewProvider
}
func findPrevArticle(_: ArticleModel, article: Article) -> Article? {
return timelineModel?.findPrevArticle(article)
}
func findNextArticle(_: ArticleModel, article: Article) -> Article? {
return timelineModel?.findNextArticle(article)
}
func selectArticle(_: ArticleModel, article: Article) {
timelineModel?.selectArticle(article)
}
}
// MARK: UndoableCommandRunner
extension SceneModel: UndoableCommandRunner {
@@ -122,5 +141,33 @@ extension SceneModel: UndoableCommandRunner {
private extension SceneModel {
// MARK: Notifications
@objc func statusesDidChange(_ note: Notification) {
guard let article = currentArticle, let articleIDs = note.userInfo?[Account.UserInfoKey.articleIDs] as? Set<String> else {
return
}
if articleIDs.contains(article.articleID) {
updateArticleState()
}
}
// MARK: State Updates
func updateArticleState() {
guard let article = currentArticle else {
readButtonState = nil
starButtonState = nil
return
}
if article.isAvailableToMarkUnread {
readButtonState = article.status.read ? .off : .on
} else {
readButtonState = nil
}
starButtonState = article.status.starred ? .on : .off
}
}