Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Mac/AppDefaults.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ final class AppDefaults: Sendable {
static let timelineFontSize = "timelineFontSize"
static let timelineSortDirection = "timelineSortDirection"
static let timelineGroupByFeed = "timelineGroupByFeed"
static let timelineReadFilterEnabled = "timelineReadFilterEnabled"
static let detailFontSize = "detailFontSize"
static let openInBrowserInBackground = "openInBrowserInBackground"
static let subscribeToFeedsInDefaultBrowser = "subscribeToFeedsInDefaultBrowser"
Expand Down Expand Up @@ -149,6 +150,15 @@ final class AppDefaults: Sendable {
}
}

var timelineReadFilterEnabled: Bool {
get {
return UserDefaults.standard.bool(forKey: Key.timelineReadFilterEnabled)
}
set {
UserDefaults.standard.set(newValue, forKey: Key.timelineReadFilterEnabled)
}
}

var detailFontSize: FontSize {
get {
return fontSize(for: Key.detailFontSize)
Expand Down
33 changes: 20 additions & 13 deletions Mac/MainWindow/AddFolder/AddFolderWindowController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,24 +40,16 @@ final class AddFolderWindowController: NSWindowController {
// MARK: - NSViewController

override func windowDidLoad() {
let preferredAccountID = AppDefaults.shared.addFolderAccountID
accountPopupButton.removeAllItems()

let menu = NSMenu()
accountPopupButton.menu = menu

let sortedAccounts = AccountManager.shared.sortedActiveAccounts
let accounts: [Account] = sortedAccounts.filter { !$0.behaviors.contains(.disallowFolderManagement) }

for oneAccount in accounts {

let oneMenuItem = NSMenuItem()
oneMenuItem.title = oneAccount.nameForDisplay
oneMenuItem.representedObject = oneAccount
menu.addItem(oneMenuItem)

if oneAccount.accountID == preferredAccountID {
accountPopupButton.select(oneMenuItem)
let preferredAccountID = AppDefaults.shared.addFolderAccountID
for account in allowedAccountsForFolderCreation() {
let menuItem = addMenuItem(to: menu, for: account)
if account.accountID == preferredAccountID {
accountPopupButton.select(menuItem)
}
}
}
Expand Down Expand Up @@ -98,6 +90,21 @@ extension AddFolderWindowController: NSTextFieldDelegate {

private extension AddFolderWindowController {

func allowedAccountsForFolderCreation() -> [Account] {
AccountManager.shared.sortedActiveAccounts.filter { account in
!account.behaviors.contains(.disallowFolderManagement)
}
}

@discardableResult
func addMenuItem(to menu: NSMenu, for account: Account) -> NSMenuItem {
let menuItem = NSMenuItem()
menuItem.title = account.nameForDisplay
menuItem.representedObject = account
menu.addItem(menuItem)
return menuItem
}

private func addFolderIfNeeded() {
guard let menuItem = accountPopupButton.selectedItem else {
return
Expand Down
32 changes: 20 additions & 12 deletions Mac/MainWindow/MainWindowController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -555,11 +555,11 @@ final class MainWindowController: NSWindowController, NSUserInterfaceValidations
}

@IBAction func toggleReadFeedsFilter(_ sender: Any?) {
sidebarViewController?.toggleReadFilter()
toggleGlobalReadFilter()
}

@IBAction func toggleReadArticlesFilter(_ sender: Any?) {
timelineContainerViewController?.toggleReadFilter()
toggleGlobalReadFilter()
}

@objc func selectArticleTheme(_ menuItem: NSMenuItem) {
Expand Down Expand Up @@ -1045,6 +1045,7 @@ private extension MainWindowController {
sidebarViewController?.restoreState(from: state.sidebarWindowState)

timelineContainerViewController?.restoreState(from: state.timelineWindowState)
syncSidebarReadFilter()
restoreArticleWindowScrollY = state.detailWindowState?.windowScrollY

let isShowingExtractedArticle = state.detailWindowState?.isShowingExtractedArticle ?? false
Expand All @@ -1071,6 +1072,7 @@ private extension MainWindowController {
let articleWindowScrollY = state[UserInfoKey.articleWindowScrollY] as? CGFloat
restoreArticleWindowScrollY = articleWindowScrollY
timelineContainerViewController?.restoreLegacyState(from: state)
syncSidebarReadFilter()

let isShowingExtractedArticle = state[UserInfoKey.isShowingExtractedArticle] as? Bool ?? false
if isShowingExtractedArticle {
Expand All @@ -1081,6 +1083,20 @@ private extension MainWindowController {

// MARK: - Command Validation

func syncSidebarReadFilter() {
let isReadFiltered = AppDefaults.shared.timelineReadFilterEnabled
sidebarViewController?.setReadFilterEnabled(isReadFiltered)
timelineContainerViewController?.setReadFilterEnabled(isReadFiltered)
}

func toggleGlobalReadFilter() {
let newValue = !AppDefaults.shared.timelineReadFilterEnabled
AppDefaults.shared.timelineReadFilterEnabled = newValue
syncSidebarReadFilter()
makeToolbarValidate()
invalidateRestorableState()
}

func canCopyArticleURL() -> Bool {
guard let selectedArticles else {
return false
Expand Down Expand Up @@ -1249,22 +1265,14 @@ private extension MainWindowController {

let showCommand = NSLocalizedString("Show Read Feeds", comment: "Command")
let hideCommand = NSLocalizedString("Hide Read Feeds", comment: "Command")
menuItem.title = sidebarViewController?.isReadFiltered ?? false ? showCommand : hideCommand
menuItem.title = AppDefaults.shared.timelineReadFilterEnabled ? showCommand : hideCommand
return true
}

func validateToggleReadArticles(_ item: NSValidatedUserInterfaceItem) -> Bool {
let showCommand = NSLocalizedString("Show Read Articles", comment: "Command")
let hideCommand = NSLocalizedString("Hide Read Articles", comment: "Command")

guard let isReadFiltered = timelineContainerViewController?.isReadFiltered else {
(item as? NSMenuItem)?.title = hideCommand
if let toolbarItem = item as? NSToolbarItem, let button = toolbarItem.view as? NSButton {
toolbarItem.toolTip = hideCommand
button.image = Assets.Images.filterInactive
}
return false
}
let isReadFiltered = AppDefaults.shared.timelineReadFilterEnabled

if isReadFiltered {
(item as? NSMenuItem)?.title = showCommand
Expand Down
13 changes: 7 additions & 6 deletions Mac/MainWindow/OPML/ImportOPMLWindowController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,20 @@ final class ImportOPMLWindowController: NSWindowController {
if oneAccount.behaviors.contains(.disallowOPMLImports) {
continue
}
addMenuItem(to: menu, for: oneAccount, savedAccountID: savedAccountID)
let menuItem = addMenuItem(to: menu, for: oneAccount)
if oneAccount.accountID == savedAccountID {
accountPopUpButton.select(menuItem)
}
}
}

private func addMenuItem(to menu: NSMenu, for account: Account, savedAccountID: String?) {
@discardableResult
private func addMenuItem(to menu: NSMenu, for account: Account) -> NSMenuItem {
let menuItem = NSMenuItem()
menuItem.title = account.nameForDisplay
menuItem.representedObject = account
menu.addItem(menuItem)

if account.accountID == savedAccountID {
accountPopUpButton.select(menuItem)
}
return menuItem
}

// MARK: API
Expand Down
19 changes: 13 additions & 6 deletions Mac/MainWindow/Sidebar/SidebarViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,10 @@ extension Notification.Name {

var isReadFiltered: Bool {
get {
return treeControllerDelegate.isReadFiltered
return AppDefaults.shared.timelineReadFilterEnabled
}
set {
AppDefaults.shared.timelineReadFilterEnabled = newValue
treeControllerDelegate.isReadFiltered = newValue
}
}
Expand All @@ -69,6 +70,7 @@ extension Notification.Name {
// MARK: - NSViewController

override func viewDidLoad() {
treeControllerDelegate.isReadFiltered = isReadFiltered
outlineView.dataSource = dataSource
outlineView.doubleAction = #selector(doubleClickedSidebar(_:))
outlineView.setDraggingSourceOperationMask([.move, .copy], forLocal: true)
Expand Down Expand Up @@ -518,15 +520,19 @@ extension Notification.Name {
}

func toggleReadFilter() {
if treeControllerDelegate.isReadFiltered {
isReadFiltered = false
} else {
isReadFiltered = true
}
isReadFiltered.toggle()
delegate?.sidebarInvalidatedRestorationState(self)
rebuildTreeAndRestoreSelection()
}

func setReadFilterEnabled(_ isEnabled: Bool) {
guard treeControllerDelegate.isReadFiltered != isEnabled else {
return
}
isReadFiltered = isEnabled
rebuildTreeAndRestoreSelection()
}

}

// MARK: - NSUserInterfaceValidations
Expand Down Expand Up @@ -629,6 +635,7 @@ private extension SidebarViewController {

func rebuildTreeAndReloadDataIfNeeded() {
if !animatingChanges && !BatchUpdate.shared.isPerforming {
treeControllerDelegate.isReadFiltered = isReadFiltered
addAllSelectedToFilterExceptions()
treeController.rebuild()
treeControllerDelegate.resetFilterExceptions()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ final class TimelineContainerViewController: NSViewController {
updateReadFilterButton()
}

func setReadFilterEnabled(_ isEnabled: Bool) {
regularTimelineViewController.setReadFilterEnabled(isEnabled)
updateReadFilterButton()
}

// MARK: State Restoration

func restoreState(from state: TimelineWindowState?) {
Expand Down
Loading