Implement mark as unread window for accounts that need it. Issue #1407
This commit is contained in:
parent
8acd6a039a
commit
0e72811429
@ -14,25 +14,28 @@ import Foundation
|
|||||||
user interface as much as possible. For example some sync services don't allow
|
user interface as much as possible. For example some sync services don't allow
|
||||||
feeds to be in the root folder of the account.
|
feeds to be in the root folder of the account.
|
||||||
*/
|
*/
|
||||||
public struct AccountBehaviors: OptionSet {
|
public typealias AccountBehaviors = [AccountBehavior]
|
||||||
|
|
||||||
|
public enum AccountBehavior: Equatable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Account doesn't support copies of a feed that are in a folder to be made to the root folder.
|
Account doesn't support copies of a feed that are in a folder to be made to the root folder.
|
||||||
*/
|
*/
|
||||||
public static let disallowFeedCopyInRootFolder = AccountBehaviors(rawValue: 1)
|
case disallowFeedCopyInRootFolder
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Account doesn't support feeds in the root folder.
|
Account doesn't support feeds in the root folder.
|
||||||
*/
|
*/
|
||||||
public static let disallowFeedInRootFolder = AccountBehaviors(rawValue: 2)
|
case disallowFeedInRootFolder
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Account doesn't support OPML imports
|
Account doesn't support OPML imports
|
||||||
*/
|
*/
|
||||||
public static let disallowOPMLImports = AccountBehaviors(rawValue: 4)
|
case disallowOPMLImports
|
||||||
|
|
||||||
|
/**
|
||||||
|
Account doesn't allow mark as read after a period of days
|
||||||
|
*/
|
||||||
|
case disallowMarkAsUnreadAfterPeriod(Int)
|
||||||
|
|
||||||
public let rawValue: Int
|
|
||||||
public init(rawValue: Int) {
|
|
||||||
self.rawValue = rawValue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ final class FeedlyAccountDelegate: AccountDelegate {
|
|||||||
|
|
||||||
// TODO: Kiel, if you decide not to support OPML import you will have to disallow it in the behaviors
|
// TODO: Kiel, if you decide not to support OPML import you will have to disallow it in the behaviors
|
||||||
// See https://developer.feedly.com/v3/opml/
|
// See https://developer.feedly.com/v3/opml/
|
||||||
var behaviors: AccountBehaviors = [.disallowFeedInRootFolder]
|
var behaviors: AccountBehaviors = [.disallowFeedInRootFolder, .disallowMarkAsUnreadAfterPeriod(31)]
|
||||||
|
|
||||||
let isOPMLImportSupported = false
|
let isOPMLImportSupported = false
|
||||||
|
|
||||||
|
@ -64,6 +64,25 @@ extension Article {
|
|||||||
return datePublished ?? dateModified ?? status.dateArrived
|
return datePublished ?? dateModified ?? status.dateArrived
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isAvailableToMarkUnread: Bool {
|
||||||
|
guard let markUnreadWindow = account?.behaviors.compactMap( { behavior -> Int? in
|
||||||
|
switch behavior {
|
||||||
|
case .disallowMarkAsUnreadAfterPeriod(let days):
|
||||||
|
return days
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}).first else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if logicalDatePublished.byAdding(days: markUnreadWindow) > Date() {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func iconImage() -> IconImage? {
|
func iconImage() -> IconImage? {
|
||||||
if let authors = authors, authors.count == 1, let author = authors.first {
|
if let authors = authors, authors.count == 1, let author = authors.first {
|
||||||
if let image = appDelegate.authorAvatarDownloader.image(for: author) {
|
if let image = appDelegate.authorAvatarDownloader.image(for: author) {
|
||||||
|
@ -157,9 +157,11 @@ class ArticleViewController: UIViewController {
|
|||||||
|
|
||||||
if article.status.read {
|
if article.status.read {
|
||||||
readBarButtonItem.image = AppAssets.circleOpenImage
|
readBarButtonItem.image = AppAssets.circleOpenImage
|
||||||
|
readBarButtonItem.isEnabled = article.isAvailableToMarkUnread
|
||||||
readBarButtonItem.accLabelText = NSLocalizedString("Mark Article Unread", comment: "Mark Article Unread")
|
readBarButtonItem.accLabelText = NSLocalizedString("Mark Article Unread", comment: "Mark Article Unread")
|
||||||
} else {
|
} else {
|
||||||
readBarButtonItem.image = AppAssets.circleClosedImage
|
readBarButtonItem.image = AppAssets.circleClosedImage
|
||||||
|
readBarButtonItem.isEnabled = true
|
||||||
readBarButtonItem.accLabelText = NSLocalizedString("Selected - Mark Article Unread", comment: "Selected - Mark Article Unread")
|
readBarButtonItem.accLabelText = NSLocalizedString("Selected - Mark Article Unread", comment: "Selected - Mark Article Unread")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,7 +264,9 @@ extension WebViewController: UIContextMenuInteractionDelegate {
|
|||||||
if let action = self.nextArticleAction() {
|
if let action = self.nextArticleAction() {
|
||||||
actions.append(action)
|
actions.append(action)
|
||||||
}
|
}
|
||||||
actions.append(self.toggleReadAction())
|
if let action = self.toggleReadAction() {
|
||||||
|
actions.append(action)
|
||||||
|
}
|
||||||
actions.append(self.toggleStarredAction())
|
actions.append(self.toggleStarredAction())
|
||||||
if let action = self.nextUnreadArticleAction() {
|
if let action = self.nextUnreadArticleAction() {
|
||||||
actions.append(action)
|
actions.append(action)
|
||||||
@ -642,10 +644,11 @@ private extension WebViewController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func toggleReadAction() -> UIAction {
|
func toggleReadAction() -> UIAction? {
|
||||||
let read = article?.status.read ?? false
|
guard let article = article, !article.status.read || article.isAvailableToMarkUnread else { return nil }
|
||||||
let title = read ? NSLocalizedString("Mark as Unread", comment: "Mark as Unread") : NSLocalizedString("Mark as Read", comment: "Mark as Read")
|
|
||||||
let readImage = read ? AppAssets.circleClosedImage : AppAssets.circleOpenImage
|
let title = article.status.read ? NSLocalizedString("Mark as Unread", comment: "Mark as Unread") : NSLocalizedString("Mark as Read", comment: "Mark as Read")
|
||||||
|
let readImage = article.status.read ? AppAssets.circleClosedImage : AppAssets.circleOpenImage
|
||||||
return UIAction(title: title, image: readImage) { [weak self] action in
|
return UIAction(title: title, image: readImage) { [weak self] action in
|
||||||
self?.coordinator.toggleReadForCurrentArticle()
|
self?.coordinator.toggleReadForCurrentArticle()
|
||||||
}
|
}
|
||||||
|
@ -217,6 +217,7 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner
|
|||||||
|
|
||||||
override func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
|
override func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
|
||||||
guard let article = dataSource.itemIdentifier(for: indexPath) else { return nil }
|
guard let article = dataSource.itemIdentifier(for: indexPath) else { return nil }
|
||||||
|
guard !article.status.read || article.isAvailableToMarkUnread else { return nil }
|
||||||
|
|
||||||
// Set up the read action
|
// Set up the read action
|
||||||
let readTitle = article.status.read ?
|
let readTitle = article.status.read ?
|
||||||
@ -314,7 +315,10 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner
|
|||||||
guard let self = self else { return nil }
|
guard let self = self else { return nil }
|
||||||
|
|
||||||
var actions = [UIAction]()
|
var actions = [UIAction]()
|
||||||
actions.append(self.toggleArticleReadStatusAction(article))
|
if let action = self.toggleArticleReadStatusAction(article) {
|
||||||
|
actions.append(action)
|
||||||
|
}
|
||||||
|
|
||||||
actions.append(self.toggleArticleStarStatusAction(article))
|
actions.append(self.toggleArticleStarStatusAction(article))
|
||||||
|
|
||||||
if let action = self.markAboveAsReadAction(article) {
|
if let action = self.markAboveAsReadAction(article) {
|
||||||
@ -672,7 +676,8 @@ private extension MasterTimelineViewController {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func toggleArticleReadStatusAction(_ article: Article) -> UIAction {
|
func toggleArticleReadStatusAction(_ article: Article) -> UIAction? {
|
||||||
|
guard !article.status.read || article.isAvailableToMarkUnread else { return nil }
|
||||||
|
|
||||||
let title = article.status.read ?
|
let title = article.status.read ?
|
||||||
NSLocalizedString("Mark as Unread", comment: "Mark as Unread") :
|
NSLocalizedString("Mark as Unread", comment: "Mark as Unread") :
|
||||||
|
@ -1008,6 +1008,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func toggleRead(_ article: Article) {
|
func toggleRead(_ article: Article) {
|
||||||
|
guard !article.status.read || article.isAvailableToMarkUnread else { return }
|
||||||
markArticlesWithUndo([article], statusKey: .read, flag: !article.status.read)
|
markArticlesWithUndo([article], statusKey: .read, flag: !article.status.read)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user