From 39cbefc01e603f084cad874d98dd1a21bcd9ea23 Mon Sep 17 00:00:00 2001 From: Stuart Breckenridge Date: Sat, 14 Jun 2025 14:44:47 +0800 Subject: [PATCH 01/14] =?UTF-8?q?=F0=9F=94=A5=20Removes=20updateNavigation?= =?UTF-8?q?BarSubtitle=20from=20Feeds?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/MainFeed/MainFeedViewController.swift | 40 +---------------------- 1 file changed, 1 insertion(+), 39 deletions(-) diff --git a/iOS/MainFeed/MainFeedViewController.swift b/iOS/MainFeed/MainFeedViewController.swift index 829a91265..eead0a72e 100644 --- a/iOS/MainFeed/MainFeedViewController.swift +++ b/iOS/MainFeed/MainFeedViewController.swift @@ -18,7 +18,6 @@ import SafariServices class MainFeedViewController: UITableViewController, UndoableCommandRunner { @IBOutlet weak var filterButton: UIBarButtonItem! - private var refreshProgressView: RefreshProgressView? @IBOutlet weak var addNewItemButton: UIBarButtonItem! { didSet { if #available(iOS 14, *) { @@ -72,7 +71,6 @@ class MainFeedViewController: UITableViewController, UndoableCommandRunner { NotificationCenter.default.addObserver(self, selector: #selector(contentSizeCategoryDidChange), name: UIContentSizeCategory.didChangeNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(willEnterForeground(_:)), name: UIApplication.willEnterForegroundNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(displayNameDidChange(_:)), name: .DisplayNameDidChange, object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(progressDidChange(_:)), name: .combinedRefreshProgressDidChange, object: nil) registerForTraitChanges([UITraitPreferredContentSizeCategory.self], target: self, action: #selector(preferredContentSizeCategoryDidChange)) @@ -81,7 +79,7 @@ class MainFeedViewController: UITableViewController, UndoableCommandRunner { } override func viewWillAppear(_ animated: Bool) { - navigationController?.isToolbarHidden = false + navigationController?.isToolbarHidden = false updateUI() super.viewWillAppear(animated) @@ -180,10 +178,6 @@ class MainFeedViewController: UITableViewController, UndoableCommandRunner { updateUI() } - @objc func progressDidChange(_ note: Notification) { - updateNavigationBarSubtitle() - } - // MARK: Table View override func numberOfSections(in tableView: UITableView) -> Int { @@ -661,11 +655,9 @@ class MainFeedViewController: UITableViewController, UndoableCommandRunner { } else { setFilterButtonToInactive() } - refreshProgressView?.update() addNewItemButton?.isEnabled = !AccountManager.shared.activeAccounts.isEmpty configureContextMenu() - updateNavigationBarSubtitle() } @objc @@ -699,37 +691,7 @@ class MainFeedViewController: UITableViewController, UndoableCommandRunner { } } - func updateNavigationBarSubtitle() { - let progress = AccountManager.shared.combinedRefreshProgress - - if progress.isComplete { - if let accountLastArticleFetchEndTime = AccountManager.shared.lastArticleFetchEndTime { - if Date() > accountLastArticleFetchEndTime.addingTimeInterval(60) { - let relativeDateTimeFormatter = RelativeDateTimeFormatter() - relativeDateTimeFormatter.dateTimeStyle = .named - let refreshed = relativeDateTimeFormatter.localizedString(for: accountLastArticleFetchEndTime, relativeTo: Date()) - let localizedRefreshText = NSLocalizedString("Updated %@", comment: "Updated") - let refreshText = NSString.localizedStringWithFormat(localizedRefreshText as NSString, refreshed) as String - navigationController?.navigationBar.topItem?.subtitle = refreshText - } else { - navigationController?.navigationBar.topItem?.subtitle = NSLocalizedString("Updated Just Now", comment: "Updated Just Now") - } - } else { - navigationController?.navigationBar.topItem?.subtitle = "" - } - - } else { - navigationController?.navigationBar.topItem?.subtitle = NSLocalizedString("Updating...", comment: "Updating...") - } - - scheduleNavigationBarSubtitleUpdate() - } - func scheduleNavigationBarSubtitleUpdate() { - DispatchQueue.main.asyncAfter(deadline: .now() + 60) { [weak self] in - self?.updateNavigationBarSubtitle() - } - } func focus() { becomeFirstResponder() From 9dd088fac998f4aee365c940a4e60b2243db4458 Mon Sep 17 00:00:00 2001 From: Stuart Breckenridge Date: Sat, 14 Jun 2025 14:45:27 +0800 Subject: [PATCH 02/14] =?UTF-8?q?=F0=9F=94=A5=20Removes=20subtitle=20code?= =?UTF-8?q?=20from=20Timeline?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/MainTimeline/MainTimelineViewController.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/iOS/MainTimeline/MainTimelineViewController.swift b/iOS/MainTimeline/MainTimelineViewController.swift index a78866f4a..42c90e8f8 100644 --- a/iOS/MainTimeline/MainTimelineViewController.swift +++ b/iOS/MainTimeline/MainTimelineViewController.swift @@ -195,14 +195,13 @@ class MainTimelineViewController: UITableViewController, UndoableCommandRunner { if navigationController?.navigationBar.isHidden ?? false { navigationController?.navigationBar.alpha = 0 } - navigationController?.navigationBar.topItem?.subtitle = nil + super.viewWillAppear(animated) } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(true) isTimelineViewControllerPending = false - if navigationController?.navigationBar.alpha == 0 { UIView.animate(withDuration: 0.5) { self.navigationController?.navigationBar.alpha = 1 From 2c757a70c4ddf2b7ab58d6933346fb4c8682f06f Mon Sep 17 00:00:00 2001 From: Stuart Breckenridge Date: Sat, 14 Jun 2025 14:45:57 +0800 Subject: [PATCH 03/14] =?UTF-8?q?=F0=9F=92=84=20Add=20Navigation=20Subtitl?= =?UTF-8?q?e=20logic=20to=20SceneCoord?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/SceneCoordinator.swift | 103 ++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/iOS/SceneCoordinator.swift b/iOS/SceneCoordinator.swift index 5475255ed..71c9e5efd 100644 --- a/iOS/SceneCoordinator.swift +++ b/iOS/SceneCoordinator.swift @@ -39,6 +39,7 @@ struct FeedNode: Hashable { } } + class SceneCoordinator: NSObject, UndoableCommandRunner { var undoableCommands = [UndoableCommand]() @@ -83,6 +84,9 @@ class SceneCoordinator: NSObject, UndoableCommandRunner { var isTimelineViewControllerPending = false var isArticleViewControllerPending = false + /// `Bool` to track whether a refresh is scheduled. + private var isRefreshScheduled: Bool = false + private(set) var sortDirection = AppDefaults.shared.timelineSortDirection { didSet { if sortDirection != oldValue { @@ -272,7 +276,11 @@ class SceneCoordinator: NSObject, UndoableCommandRunner { return appDelegate.unreadCount > 0 } - var timelineUnreadCount: Int = 0 + var timelineUnreadCount: Int = 0 { + didSet { + updateNavigationBarSubtitles(nil) + } + } init(rootSplitViewController: RootSplitViewController) { self.rootSplitViewController = rootSplitViewController @@ -312,6 +320,8 @@ class SceneCoordinator: NSObject, UndoableCommandRunner { NotificationCenter.default.addObserver(self, selector: #selector(willEnterForeground(_:)), name: UIApplication.willEnterForegroundNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(importDownloadedTheme(_:)), name: .didEndDownloadingTheme, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(themeDownloadDidFail(_:)), name: .didFailToImportThemeWithError, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(updateNavigationBarSubtitles(_:)), name: .combinedRefreshProgressDidChange, object: nil) + } func restoreWindowState(_ activity: NSUserActivity?) { @@ -539,6 +549,94 @@ class SceneCoordinator: NSObject, UndoableCommandRunner { self.rootSplitViewController.presentError(error, dismiss: nil) } } + + + /// Updates navigation bar subtitles in response to feed selection, unread count changes, + /// `combinedRefreshProgressDidChange` notifications, and a timed refresh every + /// 60s. + /// + /// Subtitles are handled differently on iPhone and iPad. + /// + /// `MainFeedViewController` + /// - When refreshing: Feeds will display "Updating..." on both iPhone and iPad. + /// - When refreshed: Feeds will display "Updated <#relative_time#>" on both iPhone and iPad. + /// + /// `MainTimelineViewController` + /// - Where the unread count for the timeline is > 0, this is displayed on both iPhone and iPad. + /// - If the timeline count is 0, the iPhone follows the same logic as `MainFeedViewController` + /// - Specific to iPad, if the unread count is 0, the iPad will not display a subtitle. The refresh text + /// will generally be visible in the sidebar and there's no need to display it twice. + /// + /// - Parameter note: Optional `Notification` + @objc func updateNavigationBarSubtitles(_ note: Notification?) { + let progress = AccountManager.shared.combinedRefreshProgress + + if progress.isComplete { + if let accountLastArticleFetchEndTime = AccountManager.shared.lastArticleFetchEndTime { + if Date.now > accountLastArticleFetchEndTime.addingTimeInterval(60) { + let relativeDateTimeFormatter = RelativeDateTimeFormatter() + relativeDateTimeFormatter.dateTimeStyle = .named + let refreshed = relativeDateTimeFormatter.localizedString(for: accountLastArticleFetchEndTime, relativeTo: Date()) + let localizedRefreshText = NSLocalizedString("Updated %@", comment: "Updated") + let refreshText = NSString.localizedStringWithFormat(localizedRefreshText as NSString, refreshed) as String + + // Update Feeds with Updated text + self.mainFeedViewController?.navigationItem.subtitle = refreshText + + // If unread count > 0, add unread string to timeline + if let _ = timelineFeed, timelineUnreadCount > 0 { + let localizedUnreadCount = NSLocalizedString("%i Unread", comment: "14 Unread") + let unreadCount = NSString.localizedStringWithFormat(localizedUnreadCount as NSString, timelineUnreadCount) as String + self.mainTimelineViewController?.navigationItem.subtitle = unreadCount + } else { + // When unread count == 0, iPhone timeline displays Updated Just Now; iPad is blank + if UIDevice.current.userInterfaceIdiom == .phone { + self.mainTimelineViewController?.navigationItem.subtitle = refreshText + } else { + self.mainTimelineViewController?.navigationItem.subtitle = "" + } + } + } else { + // Use 'Updated Just Now' while <60s have passed since refresh. + self.mainFeedViewController?.navigationItem.subtitle = NSLocalizedString("Updated Just Now", comment: "Updated Just Now") + + // If unread count > 0, add unread string to timeline + if let _ = timelineFeed, timelineUnreadCount > 0 { + let localizedUnreadCount = NSLocalizedString("%i Unread", comment: "14 Unread") + let refreshTextWithUnreadCount = NSString.localizedStringWithFormat(localizedUnreadCount as NSString, timelineUnreadCount) as String + self.mainTimelineViewController?.navigationItem.subtitle = refreshTextWithUnreadCount + } else { + // When unread count == 0, iPhone timeline displays Updated Just Now; iPad is blank + if UIDevice.current.userInterfaceIdiom == .phone { + self.mainTimelineViewController?.navigationItem.subtitle = NSLocalizedString("Updated Just Now", comment: "Updated Just Now") + } else { + self.mainTimelineViewController?.navigationItem.subtitle = "" + } + } + } + } else { + self.mainFeedViewController?.navigationItem.subtitle = "" + self.mainTimelineViewController?.navigationItem.subtitle = "" + } + } else { + // Updating in progress, apply to both iPhone and iPad Feeds. + self.mainFeedViewController?.navigationItem.subtitle = NSLocalizedString("Updating...", comment: "Updating...") + } + + scheduleNavigationBarSubtitleUpdate() + + } + + func scheduleNavigationBarSubtitleUpdate() { + if isRefreshScheduled { + return + } + isRefreshScheduled = true + DispatchQueue.main.asyncAfter(deadline: .now() + 60) { [weak self] in + self?.isRefreshScheduled = false + self?.updateNavigationBarSubtitles(nil) + } + } // MARK: API @@ -735,6 +833,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner { } }() selectFeed(indexPath: indexPath, animations: animations, deselectArticle: deselectArticle, completion: completion) + updateNavigationBarSubtitles(nil) } func selectFeed(indexPath: IndexPath?, animations: Animations = [], deselectArticle: Bool = true, completion: (() -> Void)? = nil) { @@ -773,6 +872,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner { } } + updateNavigationBarSubtitles(nil) } @@ -2212,4 +2312,5 @@ private extension SceneCoordinator { return true } + } From 057ab42036fcb36f346cf73b2f399a4eeb6fd549 Mon Sep 17 00:00:00 2001 From: Stuart Breckenridge Date: Sat, 14 Jun 2025 14:46:41 +0800 Subject: [PATCH 04/14] =?UTF-8?q?=F0=9F=92=84=20Removes=20Unread=20count?= =?UTF-8?q?=20from=20MainTimelineView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit + adjusts contraints to ensure icon and title are centred. --- iOS/MainTimeline/MainTimelineTitleView.swift | 4 +- iOS/MainTimeline/MainTimelineTitleView.xib | 55 +++++++++++--------- 2 files changed, 31 insertions(+), 28 deletions(-) diff --git a/iOS/MainTimeline/MainTimelineTitleView.swift b/iOS/MainTimeline/MainTimelineTitleView.swift index 7a68a4493..3c4ca49df 100644 --- a/iOS/MainTimeline/MainTimelineTitleView.swift +++ b/iOS/MainTimeline/MainTimelineTitleView.swift @@ -33,7 +33,7 @@ class MainTimelineTitleView: UIView { } func buttonize() { - heightAnchor.constraint(equalToConstant: 40.0).isActive = true + heightAnchor.constraint(equalToConstant: 25.0).isActive = true accessibilityTraits = .button if #available(iOS 13.4, *) { addInteraction(pointerInteraction) @@ -41,7 +41,7 @@ class MainTimelineTitleView: UIView { } func debuttonize() { - heightAnchor.constraint(equalToConstant: 40.0).isActive = true + heightAnchor.constraint(equalToConstant: 25.0).isActive = true accessibilityTraits.remove(.button) if #available(iOS 13.4, *) { removeInteraction(pointerInteraction) diff --git a/iOS/MainTimeline/MainTimelineTitleView.xib b/iOS/MainTimeline/MainTimelineTitleView.xib index 9ea9ed250..2c75c4244 100644 --- a/iOS/MainTimeline/MainTimelineTitleView.xib +++ b/iOS/MainTimeline/MainTimelineTitleView.xib @@ -1,9 +1,8 @@ - + - - + @@ -11,38 +10,43 @@ - + - - - - - - - + + + + + + + + + + + + + - - + + + + + + - - - - - - - + + @@ -50,7 +54,6 @@ - From 3834e6693ce0afc8929081a40e050052d163260e Mon Sep 17 00:00:00 2001 From: Stuart Breckenridge Date: Sat, 14 Jun 2025 16:05:01 +0800 Subject: [PATCH 05/14] =?UTF-8?q?=F0=9F=94=A7=20Updates=20xcconfig?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NetNewsWire.xcodeproj/project.pbxproj | 10 ---------- xcconfig/NetNewsWire_iOSapp_target.xcconfig | 5 +++++ xcconfig/NetNewsWire_macapp_target.xcconfig | 1 + 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/NetNewsWire.xcodeproj/project.pbxproj b/NetNewsWire.xcodeproj/project.pbxproj index 75c4065b9..41dd76ac5 100644 --- a/NetNewsWire.xcodeproj/project.pbxproj +++ b/NetNewsWire.xcodeproj/project.pbxproj @@ -1464,11 +1464,6 @@ baseConfigurationReferenceAnchor = 84719F372DB9C60400EEF332 /* xcconfig */; baseConfigurationReferenceRelativePath = NetNewsWire_iOSapp_target.xcconfig; buildSettings = { - SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; - SUPPORTS_MACCATALYST = NO; - SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; - SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; - TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; @@ -1477,11 +1472,6 @@ baseConfigurationReferenceAnchor = 84719F372DB9C60400EEF332 /* xcconfig */; baseConfigurationReferenceRelativePath = NetNewsWire_iOSapp_target.xcconfig; buildSettings = { - SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; - SUPPORTS_MACCATALYST = NO; - SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; - SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; - TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; }; diff --git a/xcconfig/NetNewsWire_iOSapp_target.xcconfig b/xcconfig/NetNewsWire_iOSapp_target.xcconfig index 3c5f63c71..cd5380c77 100644 --- a/xcconfig/NetNewsWire_iOSapp_target.xcconfig +++ b/xcconfig/NetNewsWire_iOSapp_target.xcconfig @@ -44,3 +44,8 @@ PRODUCT_NAME = NetNewsWire CLANG_ENABLE_MODULES = YES SWIFT_OBJC_BRIDGING_HEADER = iOS/Resources/NetNewsWire-iOS-Bridging-Header.h SWIFT_VERSION = 5.7 +SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; +SUPPORTS_MACCATALYST = NO; +SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; +SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; +TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/xcconfig/NetNewsWire_macapp_target.xcconfig b/xcconfig/NetNewsWire_macapp_target.xcconfig index 600a8a2a1..13d4b1a36 100644 --- a/xcconfig/NetNewsWire_macapp_target.xcconfig +++ b/xcconfig/NetNewsWire_macapp_target.xcconfig @@ -37,3 +37,4 @@ DEVELOPER_ENTITLEMENTS = CODE_SIGN_ENTITLEMENTS = Mac/Resources/NetNewsWire$(DEVELOPER_ENTITLEMENTS).entitlements PRODUCT_BUNDLE_IDENTIFIER = $(ORGANIZATION_IDENTIFIER).NetNewsWire-Evergreen +MACOSX_DEPLOYMENT_TARGET = 26.0 From 0dc9ce56acf97bcb94621413e4c3f36bafaa5ae8 Mon Sep 17 00:00:00 2001 From: Stuart Breckenridge Date: Sat, 14 Jun 2025 16:05:52 +0800 Subject: [PATCH 06/14] =?UTF-8?q?=F0=9F=92=84=20Fixes=20constraints=20for?= =?UTF-8?q?=20macOS=2026?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows scroll view to go under the toolbar. --- Shared/Extensions/NSView-Extensions.swift | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/Shared/Extensions/NSView-Extensions.swift b/Shared/Extensions/NSView-Extensions.swift index e9449208e..2c5aff1d0 100644 --- a/Shared/Extensions/NSView-Extensions.swift +++ b/Shared/Extensions/NSView-Extensions.swift @@ -11,20 +11,10 @@ import AppKit extension NSView { func constraintsToMakeSubViewFullSize(_ subview: NSView) -> [NSLayoutConstraint] { - - if #available(macOS 11, *) { - let leadingConstraint = NSLayoutConstraint(item: subview, attribute: .leading, relatedBy: .equal, toItem: self.safeAreaLayoutGuide, attribute: .leading, multiplier: 1.0, constant: 0.0) - let trailingConstraint = NSLayoutConstraint(item: subview, attribute: .trailing, relatedBy: .equal, toItem: self.safeAreaLayoutGuide, attribute: .trailing, multiplier: 1.0, constant: 0.0) - let topConstraint = NSLayoutConstraint(item: subview, attribute: .top, relatedBy: .equal, toItem: self.safeAreaLayoutGuide, attribute: .top, multiplier: 1.0, constant: 0.0) - let bottomConstraint = NSLayoutConstraint(item: subview, attribute: .bottom, relatedBy: .equal, toItem: self.safeAreaLayoutGuide, attribute: .bottom, multiplier: 1.0, constant: 0.0) - return [leadingConstraint, trailingConstraint, topConstraint, bottomConstraint] - } else { - let leadingConstraint = NSLayoutConstraint(item: subview, attribute: .leading, relatedBy: .equal, toItem: self, attribute: .leading, multiplier: 1.0, constant: 0.0) - let trailingConstraint = NSLayoutConstraint(item: subview, attribute: .trailing, relatedBy: .equal, toItem: self, attribute: .trailing, multiplier: 1.0, constant: 0.0) - let topConstraint = NSLayoutConstraint(item: subview, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1.0, constant: 0.0) - let bottomConstraint = NSLayoutConstraint(item: subview, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1.0, constant: 0.0) - return [leadingConstraint, trailingConstraint, topConstraint, bottomConstraint] - } - + let leadingConstraint = NSLayoutConstraint(item: subview, attribute: .leading, relatedBy: .equal, toItem: self, attribute: .leading, multiplier: 1.0, constant: 0.0) + let trailingConstraint = NSLayoutConstraint(item: subview, attribute: .trailing, relatedBy: .equal, toItem: self, attribute: .trailing, multiplier: 1.0, constant: 0.0) + let topConstraint = NSLayoutConstraint(item: subview, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1.0, constant: 0.0) + let bottomConstraint = NSLayoutConstraint(item: subview, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1.0, constant: 0.0) + return [leadingConstraint, trailingConstraint, topConstraint, bottomConstraint] } } From 00b8affe5f8dc900a5a1190addff4686164b81fd Mon Sep 17 00:00:00 2001 From: Stuart Breckenridge Date: Fri, 20 Jun 2025 16:01:58 +0800 Subject: [PATCH 07/14] =?UTF-8?q?=F0=9F=92=84=20Updates=20unread=20count?= =?UTF-8?q?=20text=20to=20be=20subtle=20(macOS)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Mac/MainWindow/Sidebar/Cell/SidebarCell.swift | 2 +- Mac/MainWindow/Sidebar/UnreadCountView.swift | 30 ++++++++++++++----- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/Mac/MainWindow/Sidebar/Cell/SidebarCell.swift b/Mac/MainWindow/Sidebar/Cell/SidebarCell.swift index d3154e2c8..190e48321 100644 --- a/Mac/MainWindow/Sidebar/Cell/SidebarCell.swift +++ b/Mac/MainWindow/Sidebar/Cell/SidebarCell.swift @@ -78,6 +78,7 @@ class SidebarCell : NSTableCellView { override var backgroundStyle: NSView.BackgroundStyle { didSet { updateFaviconImage() + unreadCountView.isSelected = (backgroundStyle != .normal) } } @@ -164,4 +165,3 @@ private extension SidebarCell { } } - diff --git a/Mac/MainWindow/Sidebar/UnreadCountView.swift b/Mac/MainWindow/Sidebar/UnreadCountView.swift index 25ee1c2a4..75ab94e6b 100644 --- a/Mac/MainWindow/Sidebar/UnreadCountView.swift +++ b/Mac/MainWindow/Sidebar/UnreadCountView.swift @@ -13,11 +13,9 @@ class UnreadCountView : NSView { struct Appearance { static let padding = NSEdgeInsets(top: 1.0, left: 7.0, bottom: 1.0, right: 7.0) static let cornerRadius: CGFloat = 8.0 - static let backgroundColor = NSColor(named: "SidebarUnreadCountBackground")! - static let textColor = NSColor(named: "SidebarUnreadCountText")! - static let textSize: CGFloat = 11.0 - static let textFont = NSFont.systemFont(ofSize: textSize, weight: NSFont.Weight.semibold) - static let textAttributes: [NSAttributedString.Key: AnyObject] = [NSAttributedString.Key.foregroundColor: textColor, NSAttributedString.Key.font: textFont, NSAttributedString.Key.kern: NSNull()] + static let backgroundColor = NSColor.clear + static let textSize: CGFloat = 13.0 + static let textFont = NSFont.systemFont(ofSize: textSize, weight: NSFont.Weight.regular) } var unreadCount = 0 { @@ -30,6 +28,24 @@ class UnreadCountView : NSView { return unreadCount < 1 ? "" : "\(unreadCount)" } + var isSelected: Bool = false { + didSet { + needsDisplay = true + } + } + + private var currentTextColor: NSColor { + return isSelected ? NSColor.white : NSColor.tertiaryLabelColor + } + + private var textAttributes: [NSAttributedString.Key: AnyObject] { + return [ + .foregroundColor: currentTextColor, + .font: Appearance.textFont, + .kern: NSNull() + ] + } + private var intrinsicContentSizeIsValid = false private var _intrinsicContentSize = NSZeroSize @@ -66,7 +82,7 @@ class UnreadCountView : NSView { return cachedSize } - var size = unreadCountString.size(withAttributes: Appearance.textAttributes) + var size = unreadCountString.size(withAttributes: textAttributes) size.height = ceil(size.height) size.width = ceil(size.width) @@ -89,7 +105,7 @@ class UnreadCountView : NSView { path.fill() if unreadCount > 0 { - unreadCountString.draw(at: textRect().origin, withAttributes: Appearance.textAttributes) + unreadCountString.draw(at: textRect().origin, withAttributes: textAttributes) } } } From cabaa32be581e6390e50495c849ce76c10966176 Mon Sep 17 00:00:00 2001 From: Stuart Breckenridge Date: Fri, 20 Jun 2025 19:48:15 +0800 Subject: [PATCH 08/14] =?UTF-8?q?=F0=9F=94=A5=20Removes=20unused=20#availa?= =?UTF-8?q?ble=20checks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Mac/AppAssets.swift | 128 +++++------------- Mac/AppDelegate.swift | 22 +-- ...ltinSmartFeedInspectorViewController.swift | 4 +- .../FolderInspectorViewController.swift | 8 +- Mac/MainWindow/AddFeed/FolderTreeMenu.swift | 1 + .../Detail/DetailWebViewController.swift | 16 --- .../Sidebar/Cell/SidebarCellAppearance.swift | 6 +- .../Cell/TimelineCellAppearance.swift | 6 +- .../Timeline/TimelineTableRowView.swift | 21 +-- .../Timeline/TimelineViewController.swift | 4 +- .../AccountsFeedbinWindowController.swift | 6 +- .../AccountsNewsBlurWindowController.swift | 6 +- .../AccountsReaderAPIWindowController.swift | 6 +- .../Accounts/AddAccountsView.swift | 56 +++----- 14 files changed, 80 insertions(+), 210 deletions(-) diff --git a/Mac/AppAssets.swift b/Mac/AppAssets.swift index 13244e996..456ce37fd 100644 --- a/Mac/AppAssets.swift +++ b/Mac/AppAssets.swift @@ -50,7 +50,7 @@ struct AppAssets { static let nnwFeedIcon = RSImage(named: "nnwFeedIcon")! - @available(macOS 11.0, *) + static var addNewSidebarItemImage: RSImage = { return NSImage(systemSymbolName: "plus", accessibilityDescription: nil)! }() @@ -67,12 +67,12 @@ struct AppAssets { return RSImage(named: "articleExtractorOn")! }() - @available(macOS 11.0, *) + static var articleTheme: RSImage = { return NSImage(systemSymbolName: "doc.richtext", accessibilityDescription: nil)! }() - @available(macOS 11.0, *) + static var cleanUpImage: RSImage = { return NSImage(systemSymbolName: "wind", accessibilityDescription: nil)! }() @@ -90,19 +90,11 @@ struct AppAssets { }() static var filterActive: RSImage = { - if #available(macOS 11.0, *) { - return NSImage(systemSymbolName: "line.horizontal.3.decrease.circle.fill", accessibilityDescription: nil)! - } else { - return RSImage(named: "filterActive")! - } + return NSImage(systemSymbolName: "line.horizontal.3.decrease.circle.fill", accessibilityDescription: nil)! }() static var filterInactive: RSImage = { - if #available(macOS 11.0, *) { - return NSImage(systemSymbolName: "line.horizontal.3.decrease.circle", accessibilityDescription: nil)! - } else { - return RSImage(named: "filterInactive")! - } + return NSImage(systemSymbolName: "line.horizontal.3.decrease.circle", accessibilityDescription: nil)! }() static var iconLightBackgroundColor: NSColor = { @@ -146,64 +138,48 @@ struct AppAssets { }() static var mainFolderImage: IconImage { - if #available(macOS 11.0, *) { - let image = NSImage(systemSymbolName: "folder", accessibilityDescription: nil)! - let preferredColor = NSColor(named: "AccentColor")! - return IconImage(image, isSymbol: true, isBackgroundSuppressed: true, preferredColor: preferredColor.cgColor) - } else { - return IconImage(RSImage(named: NSImage.folderName)!) - } + let image = NSImage(systemSymbolName: "folder", accessibilityDescription: nil)! + let preferredColor = NSColor(named: "AccentColor")! + return IconImage(image, isSymbol: true, isBackgroundSuppressed: true, preferredColor: preferredColor.cgColor) } static var markAllAsReadImage: RSImage = { return RSImage(named: "markAllAsRead")! }() - @available(macOS 11.0, *) + static var nextUnreadImage: RSImage = { return NSImage(systemSymbolName: "chevron.down.circle", accessibilityDescription: nil)! }() - @available(macOS 11.0, *) + static var openInBrowserImage: RSImage = { return NSImage(systemSymbolName: "safari", accessibilityDescription: nil)! }() static var preferencesToolbarAccountsImage: RSImage = { - if #available(macOS 11.0, *) { - return NSImage(systemSymbolName: "at", accessibilityDescription: nil)! - } else { - return NSImage(named: NSImage.userAccountsName)! - } + return NSImage(systemSymbolName: "at", accessibilityDescription: nil)! }() static var preferencesToolbarGeneralImage: RSImage = { - if #available(macOS 11.0, *) { - return NSImage(systemSymbolName: "gearshape", accessibilityDescription: nil)! - } else { - return NSImage(named: NSImage.preferencesGeneralName)! - } + return NSImage(systemSymbolName: "gearshape", accessibilityDescription: nil)! }() static var preferencesToolbarAdvancedImage: RSImage = { - if #available(macOS 11.0, *) { - return NSImage(systemSymbolName: "gearshape.2", accessibilityDescription: nil)! - } else { - return NSImage(named: NSImage.advancedName)! - } + return NSImage(systemSymbolName: "gearshape.2", accessibilityDescription: nil)! }() - @available(macOS 11.0, *) + static var readClosedImage: RSImage = { return NSImage(systemSymbolName: "largecircle.fill.circle", accessibilityDescription: nil)! }() - @available(macOS 11.0, *) + static var readOpenImage: RSImage = { return NSImage(systemSymbolName: "circle", accessibilityDescription: nil)! }() - @available(macOS 11.0, *) + static var refreshImage: RSImage = { return NSImage(systemSymbolName: "arrow.clockwise", accessibilityDescription: nil)! }() @@ -212,34 +188,30 @@ struct AppAssets { return IconImage(RSImage(named: NSImage.smartBadgeTemplateName)!, isSymbol: true, isBackgroundSuppressed: true) }() - @available(macOS 11.0, *) + static var shareImage: RSImage = { return NSImage(systemSymbolName: "square.and.arrow.up", accessibilityDescription: nil)! }() - @available(macOS 11.0, *) + static var sidebarToggleImage: RSImage = { return NSImage(systemSymbolName: "sidebar.left", accessibilityDescription: nil)! }() - @available(macOS 11.0, *) + static var starClosedImage: RSImage = { return NSImage(systemSymbolName: "star.fill", accessibilityDescription: nil)! }() - @available(macOS 11.0, *) + static var starOpenImage: RSImage = { return NSImage(systemSymbolName: "star", accessibilityDescription: nil)! }() static var starredFeedImage: IconImage = { - if #available(macOS 11.0, *) { - let image = NSImage(systemSymbolName: "star.fill", accessibilityDescription: nil)! - let preferredColor = NSColor(named: "StarColor")! - return IconImage(image, isSymbol: true, isBackgroundSuppressed: true, preferredColor: preferredColor.cgColor) - } else { - return IconImage(RSImage(named: NSImage.smartBadgeTemplateName)!, isBackgroundSuppressed: true) - } + let image = NSImage(systemSymbolName: "star.fill", accessibilityDescription: nil)! + let preferredColor = NSColor(named: "StarColor")! + return IconImage(image, isSymbol: true, isBackgroundSuppressed: true, preferredColor: preferredColor.cgColor) }() static var timelineSeparatorColor: NSColor = { @@ -255,61 +227,35 @@ struct AppAssets { }() static var todayFeedImage: IconImage = { - if #available(macOS 11.0, *) { - let image = NSImage(systemSymbolName: "sun.max.fill", accessibilityDescription: nil)! - let preferredColor = NSColor.orange - return IconImage(image, isSymbol: true, isBackgroundSuppressed: true, preferredColor: preferredColor.cgColor) - } else { - return IconImage(RSImage(named: NSImage.smartBadgeTemplateName)!, isBackgroundSuppressed: true) - } + let image = NSImage(systemSymbolName: "sun.max.fill", accessibilityDescription: nil)! + let preferredColor = NSColor.orange + return IconImage(image, isSymbol: true, isBackgroundSuppressed: true, preferredColor: preferredColor.cgColor) }() static var unreadFeedImage: IconImage = { - if #available(macOS 11.0, *) { - let image = NSImage(systemSymbolName: "largecircle.fill.circle", accessibilityDescription: nil)! - let preferredColor = NSColor(named: "AccentColor")! - return IconImage(image, isSymbol: true, isBackgroundSuppressed: true, preferredColor: preferredColor.cgColor) - } else { - return IconImage(RSImage(named: NSImage.smartBadgeTemplateName)!, isBackgroundSuppressed: true) - } + let image = NSImage(systemSymbolName: "largecircle.fill.circle", accessibilityDescription: nil)! + let preferredColor = NSColor(named: "AccentColor")! + return IconImage(image, isSymbol: true, isBackgroundSuppressed: true, preferredColor: preferredColor.cgColor) }() static var swipeMarkReadImage: RSImage = { - if #available(OSX 11.0, *) { - return RSImage(systemSymbolName: "circle", accessibilityDescription: "Mark Read")! - .withSymbolConfiguration(.init(scale: .large))! - } else { - // TODO: remove swipeMarkRead asset when dropping support for macOS 10.15 - return RSImage(named: "swipeMarkRead")! - } + return RSImage(systemSymbolName: "circle", accessibilityDescription: "Mark Read")! + .withSymbolConfiguration(.init(scale: .large))! }() static var swipeMarkUnreadImage: RSImage = { - if #available(OSX 11.0, *) { - return RSImage(systemSymbolName: "largecircle.fill.circle", accessibilityDescription: "Mark Unread")! - .withSymbolConfiguration(.init(scale: .large))! - } else { - // TODO: remove swipeMarkUnread asset when dropping support for macOS 10.15 - return RSImage(named: "swipeMarkUnread")! - } + return RSImage(systemSymbolName: "largecircle.fill.circle", accessibilityDescription: "Mark Unread")! + .withSymbolConfiguration(.init(scale: .large))! }() static var swipeMarkStarredImage: RSImage = { - if #available(OSX 11.0, *) { - return RSImage(systemSymbolName: "star.fill", accessibilityDescription: "Star")! - .withSymbolConfiguration(.init(scale: .large))! - } else { - return RSImage(named: "swipeMarkStarred")! - } + return RSImage(systemSymbolName: "star.fill", accessibilityDescription: "Star")! + .withSymbolConfiguration(.init(scale: .large))! }() static var swipeMarkUnstarredImage: RSImage = { - if #available(OSX 11.0, *) { - return RSImage(systemSymbolName: "star", accessibilityDescription: "Unstar")! - .withSymbolConfiguration(.init(scale: .large))! - } else { - return RSImage(named: "swipeMarkUnstarred")! - } + return RSImage(systemSymbolName: "star", accessibilityDescription: "Unstar")! + .withSymbolConfiguration(.init(scale: .large))! }() static var starColor: NSColor = { diff --git a/Mac/AppDelegate.swift b/Mac/AppDelegate.swift index 79a53d955..adf91c8a5 100644 --- a/Mac/AppDelegate.swift +++ b/Mac/AppDelegate.swift @@ -798,30 +798,20 @@ internal extension AppDelegate { attrs[.font] = NSFont.systemFont(ofSize: NSFont.smallSystemFontSize) attrs[.foregroundColor] = NSColor.textColor - if #available(macOS 11.0, *) { - let titleParagraphStyle = NSMutableParagraphStyle() - titleParagraphStyle.alignment = .center - attrs[.paragraphStyle] = titleParagraphStyle - } - + let titleParagraphStyle = NSMutableParagraphStyle() + titleParagraphStyle.alignment = .center + attrs[.paragraphStyle] = titleParagraphStyle + let websiteText = NSMutableAttributedString() websiteText.append(NSAttributedString(string: NSLocalizedString("Author‘s website:", comment: "Author's Website"), attributes: attrs)) - if #available(macOS 11.0, *) { - websiteText.append(NSAttributedString(string: "\n")) - } else { - websiteText.append(NSAttributedString(string: " ")) - } + websiteText.append(NSAttributedString(string: "\n")) attrs[.link] = theme.creatorHomePage websiteText.append(NSAttributedString(string: theme.creatorHomePage, attributes: attrs)) let textViewWidth: CGFloat - if #available(macOS 11.0, *) { - textViewWidth = 200 - } else { - textViewWidth = 400 - } + textViewWidth = 200 let textView = NSTextView(frame: CGRect(x: 0, y: 0, width: textViewWidth, height: 15)) textView.isEditable = false diff --git a/Mac/Inspector/BuiltinSmartFeedInspectorViewController.swift b/Mac/Inspector/BuiltinSmartFeedInspectorViewController.swift index bbd1a928d..3c6c7b908 100644 --- a/Mac/Inspector/BuiltinSmartFeedInspectorViewController.swift +++ b/Mac/Inspector/BuiltinSmartFeedInspectorViewController.swift @@ -64,8 +64,6 @@ private extension BuiltinSmartFeedInspectorViewController { func updateUI() { nameTextField?.stringValue = smartFeed?.nameForDisplay ?? "" windowTitle = smartFeed?.nameForDisplay ?? NSLocalizedString("Smart Feed Inspector", comment: "Smart Feed Inspector window title") - if #available(macOS 11.0, *) { - smartFeedImageView?.image = smartFeed?.smallIcon?.image - } + smartFeedImageView?.image = smartFeed?.smallIcon?.image } } diff --git a/Mac/Inspector/FolderInspectorViewController.swift b/Mac/Inspector/FolderInspectorViewController.swift index d67dfca80..63f76b0d7 100644 --- a/Mac/Inspector/FolderInspectorViewController.swift +++ b/Mac/Inspector/FolderInspectorViewController.swift @@ -47,11 +47,9 @@ final class FolderInspectorViewController: NSViewController, Inspector { override func viewDidLoad() { updateUI() - if #available(macOS 11.0, *) { - let image = NSImage(systemSymbolName: "folder", accessibilityDescription: nil)! - folderImageView.image = image - folderImageView.contentTintColor = NSColor.controlAccentColor - } + let image = NSImage(systemSymbolName: "folder", accessibilityDescription: nil)! + folderImageView.image = image + folderImageView.contentTintColor = NSColor.controlAccentColor NotificationCenter.default.addObserver(self, selector: #selector(displayNameDidChange(_:)), name: .DisplayNameDidChange, object: nil) } diff --git a/Mac/MainWindow/AddFeed/FolderTreeMenu.swift b/Mac/MainWindow/AddFeed/FolderTreeMenu.swift index 87250dd6b..bc271e743 100644 --- a/Mac/MainWindow/AddFeed/FolderTreeMenu.swift +++ b/Mac/MainWindow/AddFeed/FolderTreeMenu.swift @@ -29,6 +29,7 @@ class FolderTreeMenu { } let menuItem = NSMenuItem(title: account.nameForDisplay, action: nil, keyEquivalent: "") + menuItem.image = AppAssets.image(for: <#T##AccountType#>) menuItem.representedObject = childNode.representedObject if account.behaviors.contains(.disallowFeedInRootFolder) { diff --git a/Mac/MainWindow/Detail/DetailWebViewController.swift b/Mac/MainWindow/Detail/DetailWebViewController.swift index 2f82fed78..b026fbc7d 100644 --- a/Mac/MainWindow/Detail/DetailWebViewController.swift +++ b/Mac/MainWindow/Detail/DetailWebViewController.swift @@ -120,19 +120,6 @@ final class DetailWebViewController: NSViewController { view = webView - // Use the safe area layout guides if they are available. - if #available(OSX 11.0, *) { - // These constraints have been removed as they were unsatisfiable after removing NSBox. - } else { - let constraints = [ - webView.topAnchor.constraint(equalTo: view.topAnchor), - webView.bottomAnchor.constraint(equalTo: view.bottomAnchor), - webView.leadingAnchor.constraint(equalTo: view.leadingAnchor), - webView.trailingAnchor.constraint(equalTo: view.trailingAnchor), - ] - NSLayoutConstraint.activate(constraints) - } - // Hide the web view until the first reload (navigation) is complete (plus some delay) to avoid the awful white flash that happens on the initial display in dark mode. // See bug #901. webView.isHidden = true @@ -346,9 +333,6 @@ private extension DetailWebViewController { func fetchScrollInfo(_ completion: @escaping (ScrollInfo?) -> Void) { var javascriptString = "var x = {contentHeight: document.body.scrollHeight, offsetY: document.body.scrollTop}; x" - if #available(macOS 10.15, *) { - javascriptString = "var x = {contentHeight: document.body.scrollHeight, offsetY: window.pageYOffset}; x" - } webView.evaluateJavaScript(javascriptString) { (info, error) in guard let info = info as? [String: Any] else { diff --git a/Mac/MainWindow/Sidebar/Cell/SidebarCellAppearance.swift b/Mac/MainWindow/Sidebar/Cell/SidebarCellAppearance.swift index 7a082b434..c13996732 100644 --- a/Mac/MainWindow/Sidebar/Cell/SidebarCellAppearance.swift +++ b/Mac/MainWindow/Sidebar/Cell/SidebarCellAppearance.swift @@ -23,11 +23,7 @@ struct SidebarCellAppearance: Equatable { textFieldFontSize = 11 case .large: imageSize = CGSize(width: 22, height: 22) - if #available(macOS 11.0, *) { - textFieldFontSize = 15 - } else { - textFieldFontSize = 13 - } + textFieldFontSize = 15 default: imageSize = CGSize(width: 19, height: 19) textFieldFontSize = 13 diff --git a/Mac/MainWindow/Timeline/Cell/TimelineCellAppearance.swift b/Mac/MainWindow/Timeline/Cell/TimelineCellAppearance.swift index dbfdf045b..83e5a81c5 100644 --- a/Mac/MainWindow/Timeline/Cell/TimelineCellAppearance.swift +++ b/Mac/MainWindow/Timeline/Cell/TimelineCellAppearance.swift @@ -56,11 +56,7 @@ struct TimelineCellAppearance: Equatable { self.showIcon = showIcon - if #available(macOS 11.0, *) { - cellPadding = NSEdgeInsets(top: 8.0, left: 4.0, bottom: 10.0, right: 4.0) - } else { - cellPadding = NSEdgeInsets(top: 8.0, left: 18.0, bottom: 10.0, right: 18.0) - } + cellPadding = NSEdgeInsets(top: 8.0, left: 4.0, bottom: 10.0, right: 4.0) let margin = self.cellPadding.left + self.unreadCircleDimension + self.unreadCircleMarginRight self.boxLeftMargin = margin diff --git a/Mac/MainWindow/Timeline/TimelineTableRowView.swift b/Mac/MainWindow/Timeline/TimelineTableRowView.swift index bf42f4edd..54d87479c 100644 --- a/Mac/MainWindow/Timeline/TimelineTableRowView.swift +++ b/Mac/MainWindow/Timeline/TimelineTableRowView.swift @@ -59,21 +59,12 @@ class TimelineTableRowView : NSTableRowView { separator!.wantsLayer = true separator!.layer?.backgroundColor = AppAssets.timelineSeparatorColor.cgColor addSubview(separator!) - if #available(macOS 11.0, *) { - NSLayoutConstraint.activate([ - separator!.leadingAnchor.constraint(equalTo: cellView.leadingAnchor, constant: 20), - separator!.trailingAnchor.constraint(equalTo: cellView.trailingAnchor, constant: -4), - separator!.heightAnchor.constraint(equalToConstant: 1), - separator!.bottomAnchor.constraint(equalTo: bottomAnchor, constant: 0) - ]) - } else { - NSLayoutConstraint.activate([ - separator!.leadingAnchor.constraint(equalTo: cellView.leadingAnchor, constant: 34), - separator!.trailingAnchor.constraint(equalTo: cellView.trailingAnchor, constant: -28), - separator!.heightAnchor.constraint(equalToConstant: 1), - separator!.bottomAnchor.constraint(equalTo: bottomAnchor, constant: 0) - ]) - } + NSLayoutConstraint.activate([ + separator!.leadingAnchor.constraint(equalTo: cellView.leadingAnchor, constant: 20), + separator!.trailingAnchor.constraint(equalTo: cellView.trailingAnchor, constant: -4), + separator!.heightAnchor.constraint(equalToConstant: 1), + separator!.bottomAnchor.constraint(equalTo: bottomAnchor, constant: 0) + ]) } } diff --git a/Mac/MainWindow/Timeline/TimelineViewController.swift b/Mac/MainWindow/Timeline/TimelineViewController.swift index f19276b9f..bf9e886b1 100644 --- a/Mac/MainWindow/Timeline/TimelineViewController.swift +++ b/Mac/MainWindow/Timeline/TimelineViewController.swift @@ -208,9 +208,7 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr tableView.setDraggingSourceOperationMask(.copy, forLocal: false) tableView.keyboardDelegate = keyboardDelegate - if #available(macOS 11.0, *) { - tableView.style = .inset - } + tableView.style = .inset if !didRegisterForNotifications { NotificationCenter.default.addObserver(self, selector: #selector(statusesDidChange(_:)), name: .StatusesDidChange, object: nil) diff --git a/Mac/Preferences/Accounts/AccountsFeedbinWindowController.swift b/Mac/Preferences/Accounts/AccountsFeedbinWindowController.swift index 444e152d0..3a4112ca4 100644 --- a/Mac/Preferences/Accounts/AccountsFeedbinWindowController.swift +++ b/Mac/Preferences/Accounts/AccountsFeedbinWindowController.swift @@ -133,10 +133,8 @@ class AccountsFeedbinWindowController: NSWindowController { // MARK: Autofill func enableAutofill() { - if #available(macOS 11, *) { - usernameTextField.contentType = .username - passwordTextField.contentType = .password - } + usernameTextField.contentType = .username + passwordTextField.contentType = .password } } diff --git a/Mac/Preferences/Accounts/AccountsNewsBlurWindowController.swift b/Mac/Preferences/Accounts/AccountsNewsBlurWindowController.swift index 00f47778e..9c70fceb5 100644 --- a/Mac/Preferences/Accounts/AccountsNewsBlurWindowController.swift +++ b/Mac/Preferences/Accounts/AccountsNewsBlurWindowController.swift @@ -129,10 +129,8 @@ class AccountsNewsBlurWindowController: NSWindowController { // MARK: Autofill func enableAutofill() { - if #available(macOS 11, *) { - usernameTextField.contentType = .username - passwordTextField.contentType = .password - } + usernameTextField.contentType = .username + passwordTextField.contentType = .password } } diff --git a/Mac/Preferences/Accounts/AccountsReaderAPIWindowController.swift b/Mac/Preferences/Accounts/AccountsReaderAPIWindowController.swift index a9e831afd..846c4f9a4 100644 --- a/Mac/Preferences/Accounts/AccountsReaderAPIWindowController.swift +++ b/Mac/Preferences/Accounts/AccountsReaderAPIWindowController.swift @@ -197,10 +197,8 @@ class AccountsReaderAPIWindowController: NSWindowController { // MARK: Autofill func enableAutofill() { - if #available(macOS 11, *) { - usernameTextField.contentType = .username - passwordTextField.contentType = .password - } + usernameTextField.contentType = .username + passwordTextField.contentType = .password } } diff --git a/Mac/Preferences/Accounts/AddAccountsView.swift b/Mac/Preferences/Accounts/AddAccountsView.swift index c8a496ad2..e43463125 100644 --- a/Mac/Preferences/Accounts/AddAccountsView.swift +++ b/Mac/Preferences/Accounts/AddAccountsView.swift @@ -102,45 +102,23 @@ struct AddAccountsView: View { HStack(spacing: 12) { Spacer() - if #available(OSX 11.0, *) { - Button(action: { - parent?.dismiss(nil) - }, label: { - Text("Cancel") - .frame(width: 76) - }) - .help("Cancel") - .keyboardShortcut(.cancelAction) - - } else { - Button(action: { - parent?.dismiss(nil) - }, label: { - Text("Cancel") - .frame(width: 76) - }) - .accessibility(label: Text("Add Account")) - } - if #available(OSX 11.0, *) { - Button(action: { - addAccountDelegate?.presentSheetForAccount(selectedAccount) - parent?.dismiss(nil) - }, label: { - Text("Continue") - .frame(width: 76) - }) - .help("Add Account") - .keyboardShortcut(.defaultAction) - - } else { - Button(action: { - addAccountDelegate?.presentSheetForAccount(selectedAccount) - parent?.dismiss(nil) - }, label: { - Text("Continue") - .frame(width: 76) - }) - } + Button(action: { + parent?.dismiss(nil) + }, label: { + Text("Cancel") + .frame(width: 76) + }) + .help("Cancel") + .keyboardShortcut(.cancelAction) + Button(action: { + addAccountDelegate?.presentSheetForAccount(selectedAccount) + parent?.dismiss(nil) + }, label: { + Text("Continue") + .frame(width: 76) + }) + .help("Add Account") + .keyboardShortcut(.defaultAction) } .padding(.top, 12) .padding(.bottom, 4) From 0483e9bb9db5dec4ee9b4d92fa69005be7d773a2 Mon Sep 17 00:00:00 2001 From: Stuart Breckenridge Date: Fri, 20 Jun 2025 19:50:52 +0800 Subject: [PATCH 09/14] =?UTF-8?q?=F0=9F=94=A5=20Don=E2=80=99t=20use=20imag?= =?UTF-8?q?e=20there!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Mac/MainWindow/AddFeed/FolderTreeMenu.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Mac/MainWindow/AddFeed/FolderTreeMenu.swift b/Mac/MainWindow/AddFeed/FolderTreeMenu.swift index bc271e743..87250dd6b 100644 --- a/Mac/MainWindow/AddFeed/FolderTreeMenu.swift +++ b/Mac/MainWindow/AddFeed/FolderTreeMenu.swift @@ -29,7 +29,6 @@ class FolderTreeMenu { } let menuItem = NSMenuItem(title: account.nameForDisplay, action: nil, keyEquivalent: "") - menuItem.image = AppAssets.image(for: <#T##AccountType#>) menuItem.representedObject = childNode.representedObject if account.behaviors.contains(.disallowFeedInRootFolder) { From 05907db70a063abe455b59ab78d74e95d2f1c956 Mon Sep 17 00:00:00 2001 From: Stuart Breckenridge Date: Fri, 20 Jun 2025 20:02:10 +0800 Subject: [PATCH 10/14] =?UTF-8?q?=F0=9F=92=84=20Move=20sidebar=20toggle=20?= =?UTF-8?q?to=20sidebar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Mac/MainWindow/MainWindowController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mac/MainWindow/MainWindowController.swift b/Mac/MainWindow/MainWindowController.swift index a0b9932c5..0f90b85b1 100644 --- a/Mac/MainWindow/MainWindowController.swift +++ b/Mac/MainWindow/MainWindowController.swift @@ -854,11 +854,11 @@ extension MainWindowController: NSToolbarDelegate { func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] { [ + NSToolbarItem.Identifier.toggleSidebar, .flexibleSpace, .refresh, .newSidebarItemMenu, .sidebarTrackingSeparator, - NSToolbarItem.Identifier.toggleSidebar, .markAllAsRead, .toggleReadArticlesFilter, .timelineTrackingSeparator, From f9a7a0891f0ef970f0ffb59fdd94d55ae782dc34 Mon Sep 17 00:00:00 2001 From: Stuart Breckenridge Date: Fri, 20 Jun 2025 21:58:19 +0800 Subject: [PATCH 11/14] =?UTF-8?q?=F0=9F=92=84=20Updates=20several=20macOS?= =?UTF-8?q?=20pdfs=20to=20symbols?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ArticleExtractorOff.pdf | Bin 4210 -> 0 bytes .../Contents.json | 16 -- .../Article Extractor Off.svg | 158 ++++++++++++++++++ .../Contents.json | 12 ++ .../ArticleExtractorOn.pdf | Bin 4100 -> 0 bytes .../articleExtractorOn.imageset/Contents.json | 16 -- .../Article Extractor On.svg | 158 ++++++++++++++++++ .../Contents.json | 12 ++ .../markAllAsRead.imageset/Contents.json | 16 -- .../markAllAsRead.imageset/markAllAsRead.pdf | Bin 4173 -> 0 bytes .../markAllAsRead.symbolset/Contents.json | 12 ++ .../markAllAsRead.symbolset/markAsRead3.svg | 150 +++++++++++++++++ 12 files changed, 502 insertions(+), 48 deletions(-) delete mode 100644 Mac/Resources/Assets.xcassets/articleExtractorOff.imageset/ArticleExtractorOff.pdf delete mode 100644 Mac/Resources/Assets.xcassets/articleExtractorOff.imageset/Contents.json create mode 100644 Mac/Resources/Assets.xcassets/articleExtractorOff.symbolset/Article Extractor Off.svg create mode 100644 Mac/Resources/Assets.xcassets/articleExtractorOff.symbolset/Contents.json delete mode 100644 Mac/Resources/Assets.xcassets/articleExtractorOn.imageset/ArticleExtractorOn.pdf delete mode 100644 Mac/Resources/Assets.xcassets/articleExtractorOn.imageset/Contents.json create mode 100644 Mac/Resources/Assets.xcassets/articleExtractorOn.symbolset/Article Extractor On.svg create mode 100644 Mac/Resources/Assets.xcassets/articleExtractorOn.symbolset/Contents.json delete mode 100644 Mac/Resources/Assets.xcassets/markAllAsRead.imageset/Contents.json delete mode 100644 Mac/Resources/Assets.xcassets/markAllAsRead.imageset/markAllAsRead.pdf create mode 100644 Mac/Resources/Assets.xcassets/markAllAsRead.symbolset/Contents.json create mode 100644 Mac/Resources/Assets.xcassets/markAllAsRead.symbolset/markAsRead3.svg diff --git a/Mac/Resources/Assets.xcassets/articleExtractorOff.imageset/ArticleExtractorOff.pdf b/Mac/Resources/Assets.xcassets/articleExtractorOff.imageset/ArticleExtractorOff.pdf deleted file mode 100644 index d1a8f11c870452e8c9777742b68cb1ecb6619fde..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4210 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 diff --git a/Mac/Resources/Assets.xcassets/articleExtractorOff.imageset/Contents.json b/Mac/Resources/Assets.xcassets/articleExtractorOff.imageset/Contents.json deleted file mode 100644 index a0b6f11cb..000000000 --- a/Mac/Resources/Assets.xcassets/articleExtractorOff.imageset/Contents.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "images" : [ - { - "filename" : "ArticleExtractorOff.pdf", - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - }, - "properties" : { - "preserves-vector-representation" : true, - "template-rendering-intent" : "template" - } -} diff --git a/Mac/Resources/Assets.xcassets/articleExtractorOff.symbolset/Article Extractor Off.svg b/Mac/Resources/Assets.xcassets/articleExtractorOff.symbolset/Article Extractor Off.svg new file mode 100644 index 000000000..95c2b0801 --- /dev/null +++ b/Mac/Resources/Assets.xcassets/articleExtractorOff.symbolset/Article Extractor Off.svg @@ -0,0 +1,158 @@ + + + Article Extractor Off + + + + + + + + + + + + Weight/Scale Variations + + + Ultralight + + + Thin + + + Light + + + Regular + + + Medium + + + Semibold + + + Bold + + + Heavy + + + Black + + + + + + + + + + + + + Design Variations + + + Symbols are supported in up to nine weights and three scales. + + + For optimal layout with text and other symbols, vertically align + + + symbols with the adjacent text. + + + + + + + + Margins + + + Leading and trailing margins on the left and right side of each symbol + + + can be adjusted by modifying the width of the blue rectangles. + + + Modifications are automatically applied proportionally to all + + + scales and weights. + + + + + + Exporting + + + Symbols should be outlined when exporting to ensure the + + + design is preserved when submitting to Xcode. + + + Template v.1.0 + + + Generated from circle + + + Typeset at 100 points + + + Small + + + Medium + + + Large + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Mac/Resources/Assets.xcassets/articleExtractorOff.symbolset/Contents.json b/Mac/Resources/Assets.xcassets/articleExtractorOff.symbolset/Contents.json new file mode 100644 index 000000000..255ead96d --- /dev/null +++ b/Mac/Resources/Assets.xcassets/articleExtractorOff.symbolset/Contents.json @@ -0,0 +1,12 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "symbols" : [ + { + "filename" : "Article Extractor Off.svg", + "idiom" : "universal" + } + ] +} diff --git a/Mac/Resources/Assets.xcassets/articleExtractorOn.imageset/ArticleExtractorOn.pdf b/Mac/Resources/Assets.xcassets/articleExtractorOn.imageset/ArticleExtractorOn.pdf deleted file mode 100644 index 59cf13d37c1109fe37782db5294d52b1e0f08c8c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4100 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 nJr0Jn$3byOI7|urzg_-R1&K^;(9h~2nQ diff --git a/Mac/Resources/Assets.xcassets/articleExtractorOn.imageset/Contents.json b/Mac/Resources/Assets.xcassets/articleExtractorOn.imageset/Contents.json deleted file mode 100644 index ba8f780d4..000000000 --- a/Mac/Resources/Assets.xcassets/articleExtractorOn.imageset/Contents.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "images" : [ - { - "filename" : "ArticleExtractorOn.pdf", - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - }, - "properties" : { - "preserves-vector-representation" : true, - "template-rendering-intent" : "template" - } -} diff --git a/Mac/Resources/Assets.xcassets/articleExtractorOn.symbolset/Article Extractor On.svg b/Mac/Resources/Assets.xcassets/articleExtractorOn.symbolset/Article Extractor On.svg new file mode 100644 index 000000000..de5808f1f --- /dev/null +++ b/Mac/Resources/Assets.xcassets/articleExtractorOn.symbolset/Article Extractor On.svg @@ -0,0 +1,158 @@ + + + Article Extractor On + + + + + + + + + + + + Weight/Scale Variations + + + Ultralight + + + Thin + + + Light + + + Regular + + + Medium + + + Semibold + + + Bold + + + Heavy + + + Black + + + + + + + + + + + + + Design Variations + + + Symbols are supported in up to nine weights and three scales. + + + For optimal layout with text and other symbols, vertically align + + + symbols with the adjacent text. + + + + + + + + Margins + + + Leading and trailing margins on the left and right side of each symbol + + + can be adjusted by modifying the width of the blue rectangles. + + + Modifications are automatically applied proportionally to all + + + scales and weights. + + + + + + Exporting + + + Symbols should be outlined when exporting to ensure the + + + design is preserved when submitting to Xcode. + + + Template v.1.0 + + + Generated from circle + + + Typeset at 100 points + + + Small + + + Medium + + + Large + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Mac/Resources/Assets.xcassets/articleExtractorOn.symbolset/Contents.json b/Mac/Resources/Assets.xcassets/articleExtractorOn.symbolset/Contents.json new file mode 100644 index 000000000..14e45223b --- /dev/null +++ b/Mac/Resources/Assets.xcassets/articleExtractorOn.symbolset/Contents.json @@ -0,0 +1,12 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "symbols" : [ + { + "filename" : "Article Extractor On.svg", + "idiom" : "universal" + } + ] +} diff --git a/Mac/Resources/Assets.xcassets/markAllAsRead.imageset/Contents.json b/Mac/Resources/Assets.xcassets/markAllAsRead.imageset/Contents.json deleted file mode 100644 index 9937c57c5..000000000 --- a/Mac/Resources/Assets.xcassets/markAllAsRead.imageset/Contents.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "images" : [ - { - "filename" : "markAllAsRead.pdf", - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - }, - "properties" : { - "preserves-vector-representation" : true, - "template-rendering-intent" : "template" - } -} diff --git a/Mac/Resources/Assets.xcassets/markAllAsRead.imageset/markAllAsRead.pdf b/Mac/Resources/Assets.xcassets/markAllAsRead.imageset/markAllAsRead.pdf deleted file mode 100644 index 420f9d49c1a7280664082f35f6a782e67485f4c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4173 zcmai%2{e@L`^POKj6!8k^(1RqhB1Rg_Gw6COLone!B~s2XDds#>{$vSWLK1R$e#2X zYm$&`*@=)b`HkMU-`oHHzW?)o&U2pUKG%KS*L|P+`d;UJE+IV)EeUB!C|Ia%=IhL2 z!N%j>whk~9fB>!-2k^yvH+^7wd^g>{oPdr$o6AT==t zep1{EK2`}v26H58zlmTNf0dJvwpJ+6o|AM=ugW43m#S^AS;1$av%qPfwH#%UOfD!A zSbpt*>^3elPE5QPW?Z@IK=D?$vKhWmBt3;){kK)$is^!yD@j z3}t+DMtxGM?i-q+vN@j%5^E=MwN_Wt=T5JU_HpenST_;RTCB$HPLLU_<@s_zC35%V z?7Oc9;LFVy$s^|)da~~CtNR9LP2L~*!y?Bv*Eifr(8d9(C&8Pas%5|1#}$ffC`WV% zLL++yBT(IyCCGd=-R3u$b?b^P{a)DubD!X%wyJqAKNYb~e0<67!+c*-)DvUj-_0S} znSSp0itZ^{EjFiiOEDk5s@Z;Emp9dai(^(g3&zo$8GtF9gW_NI?hNK?sK98*}jBvsF7G@ z6sw)_py}9;I)0z-U}{x)S$qJ@@ECBHCf?<^ArY`c_+JB2d1}-i0@8$A)iDW$RGBO37;E&377;FBqshT?_YP*5`766#N3*_$=FC{MBlBu0 zY-2o~(rG#|GFLr3Vz=r)Tt}m~cL&r$Frf{S%{Jj!S!}jAcD%c7n~sN_meqvz)ugR0 z2(hCnXMV5+U$X{%uNe0^7HituzcpJ@+ogKTDWz211b&}42jDBB`c z=#yRUZAKi?2$@bZvn@I>u=D5&4TK}j`t6)>wo`<& z=R+zplO?ECfaWU$P1X3LjZQ+z;Jf!a4gnMC`X((cOt~8neJE|BjGVvHdqou zCw}7ye-QL0{Ww4q5_FlJ{sFz@WjeeH=((!$dm6B+^m|&*yAC&L27`TjL09jXz=$td6=PR z`6ePImpqx_M<2#Wv>D%syeb8d- zkxAio?}l^Z9IJQOn%&nhx6d?!1Nj3_O~jt=XcCEIHUl}{VLS5x5OfkWV&`L;W1@r{ zZIRUveu^Rpgt7aySzyGT-G8szfaDjxn#h3+6XZ4!6icfLHbOcGSPCl%6VD`eUBDvT zcuZBSP-TKyfVB`?!X>>VQDF|0HovCY$W;aHS`{A^AN4$gBTrohO^Q4V`|oO0!{bZiR8S)?`(S zQYcb0JtrA+50j3Gz})=|Yu6WQNC-}-K87k(nXl*<$~(iSHjwAjUsI)9b>Rc<1LPz^ z?g@DyalU=?^cUhLGfoI+J|jBAKf^au`NrT-3*^QQ)POfHIx)IFI(9>Lww5$S8ikkR zt@azllE0sGId?l*AlWvVHaWKF$~D&^j-iYq=OWY~#6j2r?J(j%9+E7MAr+9kGD#WM zvis9};R_XY5xzCM4&PcAlok^C()k+sc=@jJrO0-`c+*|dyV7UU=VUvp?9EtSfXrsh z=3ZDqlG9e+8rcd}Mk!>MmMs@Z^eI0XD^@DCd0J^=mwUCc=eT8pq`91GwMDg|ml{e( z%0$Y#Tz@rNSwE{Z>q!%$$vp7Qt6t#4jVRTJ%}=u7rTvwhl7p{oNKqeq#x^xZS4~`q%s3TR84m-};3(FS6>N|5PKAM`AXuW%^(0cLp z?OdOS-_NrsMVUlpaE)HWf2vFmbM0sMu}&(3b9KY2)7+<}hVb*^@su z`=Yc^V#2d&*JZKiFmzjIou z-&)XOkc&=jPu(;0A~Wo;CFia?kEFP4iSUw7%{A`;Z!eGpMpHw*t^RWC>;Bh>s2DCC zE-$SvM7!n?LRZsIGeuJ;#YEh+a#}0eEE>pH;yQhT(@)UTt#G@4OecJ5=`(n0MG|W9 zpmOPh+l!gPZcX5DfJ zw-*me33(pUr;*ZT8DWDgLvkXg=uoOJK6yO1{u(@8m=u?kD+Vp>EBpf=QngbxpeBTl ztT=B8RT3dewaVr~)a%~hhgPl~&r#`%zar{xYFnRr|HqYYm!kzA3f(njsdRWgZim2S zz0rSrbarz(ecGk_WY6WGxMSS7tFj?w(cz{E=fDBl z82WZb^&Cr8o!ikLCresMi#ZE*O?H9Sff~z~*W*cuP()s5ORUF`;^45{ zQ@JE~OH4w?v#DF1u9Q#T)cuYZ&+9>RYj;5MXB5^yckY~C%{+W@#3$0fXkLVpwe_;s zEYd9d-N$zkFQ35iepmb^=7R<@PWGIXxb$%U_Ga`}T6*OhI~`Jd59gzY3RzwOU)4H7 z*P|l1!!KMXDA!d@_h*zr<7Z**SZys63KhlQi|=$6f70}GyI9mVU(D6r|L5w zST6U`OnZ8)U|2Uj5NZed{JbZ&xdCx93tVUgGKlyt(s+ECM zNII`orL}-4MUbMuN00eF+iYL!j!qev3T+bm@p3!4uQ)5fi%hh`bhWKH_ARDe(jI@> zsIdEP%Xtp_WqQC1znWhVIbPg&X)BnLO}5$WjGtdZ?VysgVlH{zX5RbiE$nPNJFy+I z@h_}=fT{;lMiT|8tpe0mitFQbu~m?&S)EyAz+MibH}^70MZaiX*ggZs^)=r!U8f7H5f!j25lh*=zE~u2)+Q7)_(%N zH$jXF>C`5ZKwYIl5|FA*i z6sY(6KjT5+GSoc(Z=2k2`x4yHcqg3O&o12%?~4Nzs11^lEK|gN~Di2iv L3khkWw7~xXAShKF diff --git a/Mac/Resources/Assets.xcassets/markAllAsRead.symbolset/Contents.json b/Mac/Resources/Assets.xcassets/markAllAsRead.symbolset/Contents.json new file mode 100644 index 000000000..5a1bb0402 --- /dev/null +++ b/Mac/Resources/Assets.xcassets/markAllAsRead.symbolset/Contents.json @@ -0,0 +1,12 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "symbols" : [ + { + "filename" : "markAsRead3.svg", + "idiom" : "universal" + } + ] +} diff --git a/Mac/Resources/Assets.xcassets/markAllAsRead.symbolset/markAsRead3.svg b/Mac/Resources/Assets.xcassets/markAllAsRead.symbolset/markAsRead3.svg new file mode 100644 index 000000000..070af7a07 --- /dev/null +++ b/Mac/Resources/Assets.xcassets/markAllAsRead.symbolset/markAsRead3.svg @@ -0,0 +1,150 @@ + + + markAllAsRead2 + + + + + + + Weight/Scale Variations + + + Ultralight + + + Thin + + + Light + + + Regular + + + Medium + + + Semibold + + + Bold + + + Heavy + + + Black + + + + + + + + + + + + + Design Variations + + + Symbols are supported in up to nine weights and three scales. + + + For optimal layout with text and other symbols, vertically align + + + symbols with the adjacent text. + + + + + + + + Margins + + + Leading and trailing margins on the left and right side of each symbol + + + can be adjusted by modifying the width of the blue rectangles. + + + Modifications are automatically applied proportionally to all + + + scales and weights. + + + + + + Exporting + + + Symbols should be outlined when exporting to ensure the + + + design is preserved when submitting to Xcode. + + + Template v.1.0 + + + Generated from circle + + + Typeset at 100 points + + + Small + + + Medium + + + Large + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From ece3d14478f87645a1924fdccc24ccb71b020b03 Mon Sep 17 00:00:00 2001 From: Stuart Breckenridge Date: Fri, 20 Jun 2025 21:58:44 +0800 Subject: [PATCH 12/14] =?UTF-8?q?=F0=9F=92=84=20Adds=20images=20to=20sideb?= =?UTF-8?q?ar=20menu=20items?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Mac/AppAssets.swift | 24 ++++++++++++++++++- ...idebarViewController+ContextualMenus.swift | 21 +++++++++------- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/Mac/AppAssets.swift b/Mac/AppAssets.swift index 456ce37fd..4af87d03f 100644 --- a/Mac/AppAssets.swift +++ b/Mac/AppAssets.swift @@ -76,6 +76,14 @@ struct AppAssets { static var cleanUpImage: RSImage = { return NSImage(systemSymbolName: "wind", accessibilityDescription: nil)! }() + + static var copyImage: RSImage = { + return NSImage(systemSymbolName: "document.on.document", accessibilityDescription: nil)! + }() + + static var deleteImage: RSImage = { + return NSImage(systemSymbolName: "xmark.bin", accessibilityDescription: nil)! + }() static var marsEditIcon: RSImage = { return RSImage(named: "MarsEditIcon")! @@ -143,8 +151,15 @@ struct AppAssets { return IconImage(image, isSymbol: true, isBackgroundSuppressed: true, preferredColor: preferredColor.cgColor) } + + static var markAllAsReadMenuImage: RSImage = { + let image = RSImage(named: "markAllAsRead") + return image! + }() + static var markAllAsReadImage: RSImage = { - return RSImage(named: "markAllAsRead")! + let image = RSImage(named: "markAllAsRead") + return image! }() @@ -152,6 +167,9 @@ struct AppAssets { return NSImage(systemSymbolName: "chevron.down.circle", accessibilityDescription: nil)! }() + static var notificationImage: RSImage = { + return NSImage(systemSymbolName: "bell.badge", accessibilityDescription: nil)! + }() static var openInBrowserImage: RSImage = { return NSImage(systemSymbolName: "safari", accessibilityDescription: nil)! @@ -184,6 +202,10 @@ struct AppAssets { return NSImage(systemSymbolName: "arrow.clockwise", accessibilityDescription: nil)! }() + static var renameImage: RSImage = { + return NSImage(systemSymbolName: "pencil", accessibilityDescription: nil)! + }() + static var searchFeedImage: IconImage = { return IconImage(RSImage(named: NSImage.smartBadgeTemplateName)!, isSymbol: true, isBackgroundSuppressed: true) }() diff --git a/Mac/MainWindow/Sidebar/SidebarViewController+ContextualMenus.swift b/Mac/MainWindow/Sidebar/SidebarViewController+ContextualMenus.swift index 3944c1bfd..4bff3aca6 100644 --- a/Mac/MainWindow/Sidebar/SidebarViewController+ContextualMenus.swift +++ b/Mac/MainWindow/Sidebar/SidebarViewController+ContextualMenus.swift @@ -216,23 +216,23 @@ private extension SidebarViewController { } if let homePageURL = webFeed.homePageURL, let _ = URL(string: homePageURL) { - let item = menuItem(NSLocalizedString("Open Home Page", comment: "Command"), #selector(openHomePageFromContextualMenu(_:)), homePageURL) + let item = menuItem(NSLocalizedString("Open Home Page", comment: "Command"), #selector(openHomePageFromContextualMenu(_:)), homePageURL, image: AppAssets.openInBrowserImage) menu.addItem(item) menu.addItem(NSMenuItem.separator()) } - let copyFeedURLItem = menuItem(NSLocalizedString("Copy Feed URL", comment: "Command"), #selector(copyURLFromContextualMenu(_:)), webFeed.url) + let copyFeedURLItem = menuItem(NSLocalizedString("Copy Feed URL", comment: "Command"), #selector(copyURLFromContextualMenu(_:)), webFeed.url, image: AppAssets.copyImage) menu.addItem(copyFeedURLItem) if let homePageURL = webFeed.homePageURL { - let item = menuItem(NSLocalizedString("Copy Home Page URL", comment: "Command"), #selector(copyURLFromContextualMenu(_:)), homePageURL) + let item = menuItem(NSLocalizedString("Copy Home Page URL", comment: "Command"), #selector(copyURLFromContextualMenu(_:)), homePageURL, image: AppAssets.copyImage) menu.addItem(item) } menu.addItem(NSMenuItem.separator()) let notificationText = webFeed.notificationDisplayName.capitalized - let notificationMenuItem = menuItem(notificationText, #selector(toggleNotificationsFromContextMenu(_:)), webFeed) + let notificationMenuItem = menuItem(notificationText, #selector(toggleNotificationsFromContextMenu(_:)), webFeed, image: AppAssets.notificationImage) if webFeed.isNotifyAboutNewArticles == nil || webFeed.isNotifyAboutNewArticles! == false { notificationMenuItem.state = .off } else { @@ -241,7 +241,7 @@ private extension SidebarViewController { menu.addItem(notificationMenuItem) let articleExtractorText = NSLocalizedString("Always Use Reader View", comment: "Always Use Reader View") - let articleExtractorMenuItem = menuItem(articleExtractorText, #selector(toggleArticleExtractorFromContextMenu(_:)), webFeed) + let articleExtractorMenuItem = menuItem(articleExtractorText, #selector(toggleArticleExtractorFromContextMenu(_:)), webFeed, image: AppAssets.articleExtractorOff) if webFeed.isArticleExtractorAlwaysOn == nil || webFeed.isArticleExtractorAlwaysOn! == false { articleExtractorMenuItem.state = .off @@ -301,17 +301,17 @@ private extension SidebarViewController { func markAllReadMenuItem(_ objects: [Any]) -> NSMenuItem { - return menuItem(NSLocalizedString("Mark All as Read", comment: "Command"), #selector(markObjectsReadFromContextualMenu(_:)), objects) + return menuItem(NSLocalizedString("Mark All as Read", comment: "Command"), #selector(markObjectsReadFromContextualMenu(_:)), objects, image: AppAssets.markAllAsReadMenuImage) } func deleteMenuItem(_ objects: [Any]) -> NSMenuItem { - return menuItem(NSLocalizedString("Delete", comment: "Command"), #selector(deleteFromContextualMenu(_:)), objects) + return menuItem(NSLocalizedString("Delete", comment: "Command"), #selector(deleteFromContextualMenu(_:)), objects, image: AppAssets.deleteImage) } func renameMenuItem(_ object: Any) -> NSMenuItem { - return menuItem(NSLocalizedString("Rename", comment: "Command"), #selector(renameFromContextualMenu(_:)), object) + return menuItem(NSLocalizedString("Rename", comment: "Command"), #selector(renameFromContextualMenu(_:)), object, image: AppAssets.renameImage) } func anyObjectInArrayHasNonZeroUnreadCount(_ objects: [Any]) -> Bool { @@ -341,11 +341,14 @@ private extension SidebarViewController { return object is WebFeed || object is Folder } - func menuItem(_ title: String, _ action: Selector, _ representedObject: Any) -> NSMenuItem { + func menuItem(_ title: String, _ action: Selector, _ representedObject: Any, image: RSImage?) -> NSMenuItem { let item = NSMenuItem(title: title, action: action, keyEquivalent: "") item.representedObject = representedObject item.target = self + if let image { + item.image = image + } return item } From c5184b610c36bd455714b0e2e28e75d0df9ba6df Mon Sep 17 00:00:00 2001 From: Stuart Breckenridge Date: Fri, 20 Jun 2025 22:09:28 +0800 Subject: [PATCH 13/14] =?UTF-8?q?=E2=9C=A8=20Bubbles=20and=20Sparkles=20fo?= =?UTF-8?q?r=20cleaning,=20images=20on=20tl?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Mac/AppAssets.swift | 2 +- ...melineViewController+ContextualMenus.swift | 27 ++++++++++--------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/Mac/AppAssets.swift b/Mac/AppAssets.swift index 4af87d03f..7d34bc9fb 100644 --- a/Mac/AppAssets.swift +++ b/Mac/AppAssets.swift @@ -74,7 +74,7 @@ struct AppAssets { static var cleanUpImage: RSImage = { - return NSImage(systemSymbolName: "wind", accessibilityDescription: nil)! + return NSImage(systemSymbolName: "bubbles.and.sparkles", accessibilityDescription: nil)! }() static var copyImage: RSImage = { diff --git a/Mac/MainWindow/Timeline/TimelineViewController+ContextualMenus.swift b/Mac/MainWindow/Timeline/TimelineViewController+ContextualMenus.swift index 1cc5d6e3e..32ce32ac0 100644 --- a/Mac/MainWindow/Timeline/TimelineViewController+ContextualMenus.swift +++ b/Mac/MainWindow/Timeline/TimelineViewController+ContextualMenus.swift @@ -222,36 +222,36 @@ private extension TimelineViewController { func markReadMenuItem(_ articles: [Article]) -> NSMenuItem { - return menuItem(NSLocalizedString("Mark as Read", comment: "Command"), #selector(markArticlesReadFromContextualMenu(_:)), articles) + return menuItem(NSLocalizedString("Mark as Read", comment: "Command"), #selector(markArticlesReadFromContextualMenu(_:)), articles, image: AppAssets.swipeMarkReadImage) } func markUnreadMenuItem(_ articles: [Article]) -> NSMenuItem { - return menuItem(NSLocalizedString("Mark as Unread", comment: "Command"), #selector(markArticlesUnreadFromContextualMenu(_:)), articles) + return menuItem(NSLocalizedString("Mark as Unread", comment: "Command"), #selector(markArticlesUnreadFromContextualMenu(_:)), articles, image: AppAssets.swipeMarkUnreadImage) } func markStarredMenuItem(_ articles: [Article]) -> NSMenuItem { - return menuItem(NSLocalizedString("Mark as Starred", comment: "Command"), #selector(markArticlesStarredFromContextualMenu(_:)), articles) + return menuItem(NSLocalizedString("Mark as Starred", comment: "Command"), #selector(markArticlesStarredFromContextualMenu(_:)), articles, image: AppAssets.swipeMarkStarredImage) } func markUnstarredMenuItem(_ articles: [Article]) -> NSMenuItem { - return menuItem(NSLocalizedString("Mark as Unstarred", comment: "Command"), #selector(markArticlesUnstarredFromContextualMenu(_:)), articles) + return menuItem(NSLocalizedString("Mark as Unstarred", comment: "Command"), #selector(markArticlesUnstarredFromContextualMenu(_:)), articles, image: AppAssets.swipeMarkUnstarredImage) } func markAboveReadMenuItem(_ articles: [Article]) -> NSMenuItem { - return menuItem(NSLocalizedString("Mark Above as Read", comment: "Command"), #selector(markAboveArticlesReadFromContextualMenu(_:)), articles) + return menuItem(NSLocalizedString("Mark Above as Read", comment: "Command"), #selector(markAboveArticlesReadFromContextualMenu(_:)), articles, image: nil) } func markBelowReadMenuItem(_ articles: [Article]) -> NSMenuItem { - return menuItem(NSLocalizedString("Mark Below as Read", comment: "Command"), #selector(markBelowArticlesReadFromContextualMenu(_:)), articles) + return menuItem(NSLocalizedString("Mark Below as Read", comment: "Command"), #selector(markBelowArticlesReadFromContextualMenu(_:)), articles, image: nil) } func selectFeedInSidebarMenuItem(_ feed: WebFeed) -> NSMenuItem { let localizedMenuText = NSLocalizedString("Select “%@” in Sidebar", comment: "Command") let formattedMenuText = NSString.localizedStringWithFormat(localizedMenuText as NSString, feed.nameForDisplay) - return menuItem(formattedMenuText as String, #selector(selectFeedInSidebarFromContextualMenu(_:)), feed) + return menuItem(formattedMenuText as String, #selector(selectFeedInSidebarFromContextualMenu(_:)), feed, image: nil) } func markAllAsReadMenuItem(_ feed: WebFeed) -> NSMenuItem? { @@ -266,28 +266,31 @@ private extension TimelineViewController { let localizedMenuText = NSLocalizedString("Mark All as Read in “%@”", comment: "Command") let menuText = NSString.localizedStringWithFormat(localizedMenuText as NSString, feed.nameForDisplay) as String - return menuItem(menuText, #selector(markAllInFeedAsRead(_:)), articles) + return menuItem(menuText, #selector(markAllInFeedAsRead(_:)), articles, image: AppAssets.markAllAsReadImage) } func openInBrowserMenuItem(_ urlString: String) -> NSMenuItem { - return menuItem(NSLocalizedString("Open in Browser", comment: "Command"), #selector(openInBrowserFromContextualMenu(_:)), urlString) + return menuItem(NSLocalizedString("Open in Browser", comment: "Command"), #selector(openInBrowserFromContextualMenu(_:)), urlString, image: AppAssets.openInBrowserImage) } func copyArticleURLMenuItem(_ urlString: String) -> NSMenuItem { - return menuItem(NSLocalizedString("Copy Article URL", comment: "Command"), #selector(copyURLFromContextualMenu(_:)), urlString) + return menuItem(NSLocalizedString("Copy Article URL", comment: "Command"), #selector(copyURLFromContextualMenu(_:)), urlString, image: AppAssets.copyImage) } func copyExternalURLMenuItem(_ urlString: String) -> NSMenuItem { - return menuItem(NSLocalizedString("Copy External URL", comment: "Command"), #selector(copyURLFromContextualMenu(_:)), urlString) + return menuItem(NSLocalizedString("Copy External URL", comment: "Command"), #selector(copyURLFromContextualMenu(_:)), urlString, image: AppAssets.copyImage) } - func menuItem(_ title: String, _ action: Selector, _ representedObject: Any) -> NSMenuItem { + func menuItem(_ title: String, _ action: Selector, _ representedObject: Any, image: RSImage?) -> NSMenuItem { let item = NSMenuItem(title: title, action: action, keyEquivalent: "") item.representedObject = representedObject item.target = self + if let image { + item.image = image + } return item } } From c3a30c527cef6544b2ba8a8df5b1be985e1edc9c Mon Sep 17 00:00:00 2001 From: Stuart Breckenridge Date: Fri, 20 Jun 2025 22:14:39 +0800 Subject: [PATCH 14/14] =?UTF-8?q?=F0=9F=92=84=20Large=20symbols=20don?= =?UTF-8?q?=E2=80=99t=20appear=20to=20be=20required?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Mac/AppAssets.swift | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Mac/AppAssets.swift b/Mac/AppAssets.swift index 7d34bc9fb..cefbe0423 100644 --- a/Mac/AppAssets.swift +++ b/Mac/AppAssets.swift @@ -262,22 +262,18 @@ struct AppAssets { static var swipeMarkReadImage: RSImage = { return RSImage(systemSymbolName: "circle", accessibilityDescription: "Mark Read")! - .withSymbolConfiguration(.init(scale: .large))! }() static var swipeMarkUnreadImage: RSImage = { return RSImage(systemSymbolName: "largecircle.fill.circle", accessibilityDescription: "Mark Unread")! - .withSymbolConfiguration(.init(scale: .large))! }() static var swipeMarkStarredImage: RSImage = { return RSImage(systemSymbolName: "star.fill", accessibilityDescription: "Star")! - .withSymbolConfiguration(.init(scale: .large))! }() static var swipeMarkUnstarredImage: RSImage = { return RSImage(systemSymbolName: "star", accessibilityDescription: "Unstar")! - .withSymbolConfiguration(.init(scale: .large))! }() static var starColor: NSColor = {