From fa508a8bfce5ea6b2fc2aef4a6b1da83ae8efb0a Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Sat, 1 Apr 2023 22:13:40 -0700 Subject: [PATCH 01/18] Remove references to Tweetbot. --- iOS/TitleActivityItemSource.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/iOS/TitleActivityItemSource.swift b/iOS/TitleActivityItemSource.swift index fff0609aa..ef5d9c3cc 100644 --- a/iOS/TitleActivityItemSource.swift +++ b/iOS/TitleActivityItemSource.swift @@ -29,8 +29,6 @@ class TitleActivityItemSource: NSObject, UIActivityItemSource { switch activityType.rawValue { case "com.omnigroup.OmniFocus3.iOS.QuickEntry", "com.culturedcode.ThingsiPhone.ShareExtension", - "com.tapbots.Tweetbot4.shareextension", - "com.tapbots.Tweetbot6.shareextension", "com.buffer.buffer.Buffer": return title default: From 402c5e7bbb18328e94174a7c2bf6607993222835 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Wed, 5 Apr 2023 09:24:43 -0700 Subject: [PATCH 02/18] Continue adopting @MainActor. --- Mac/AppDelegate.swift | 112 +++++++++--------- Mac/Browser.swift | 2 +- Mac/ErrorHandler.swift | 7 +- .../About/CreditsNetNewsWireView.swift | 4 +- Mac/MainWindow/ArticleExtractorButton.swift | 2 +- Mac/MainWindow/MainWindow.swift | 2 +- Mac/MainWindow/MainWindowController.swift | 2 +- .../Sidebar/Cell/SidebarCellAppearance.swift | 2 +- .../Sidebar/Cell/SidebarCellLayout.swift | 2 +- .../Renaming/RenameWindowController.swift | 2 +- .../Sidebar/SidebarDeleteItemsAlert.swift | 2 +- .../Sidebar/SidebarOutlineDataSource.swift | 2 +- .../Sidebar/SidebarOutlineView.swift | 2 +- .../Sidebar/SidebarStatusBarView.swift | 2 +- .../URLPasteboardWriter+NetNewsWire.swift | 2 +- .../AppDelegate+Scriptability.swift | 2 +- .../ArticleStyles/ArticleThemesManager.swift | 4 +- 17 files changed, 77 insertions(+), 76 deletions(-) diff --git a/Mac/AppDelegate.swift b/Mac/AppDelegate.swift index 7d80f7bf3..16ec251f3 100644 --- a/Mac/AppDelegate.swift +++ b/Mac/AppDelegate.swift @@ -110,7 +110,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, private var crashReporter: PLCrashReporter! #endif - override init() { + @MainActor override init() { NSWindow.allowsAutomaticWindowTabbing = false super.init() @@ -136,19 +136,19 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, } // MARK: - API - func showAddFolderSheetOnWindow(_ window: NSWindow) { + @MainActor func showAddFolderSheetOnWindow(_ window: NSWindow) { addFolderWindowController = AddFolderWindowController() addFolderWindowController!.runSheetOnWindow(window) } - func showAddWebFeedSheetOnWindow(_ window: NSWindow, urlString: String?, name: String?, account: Account?, folder: Folder?) { + @MainActor func showAddWebFeedSheetOnWindow(_ window: NSWindow, urlString: String?, name: String?, account: Account?, folder: Folder?) { addFeedController = AddFeedController(hostWindow: window) addFeedController?.showAddFeedSheet(.webFeed, urlString, name, account, folder) } // MARK: - NSApplicationDelegate - func applicationWillFinishLaunching(_ notification: Notification) { + @MainActor func applicationWillFinishLaunching(_ notification: Notification) { installAppleEventHandlers() CacheCleaner.purgeIfNecessary() @@ -179,7 +179,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, appName = (Bundle.main.infoDictionary!["CFBundleExecutable"]! as! String) } - func applicationDidFinishLaunching(_ note: Notification) { + @MainActor func applicationDidFinishLaunching(_ note: Notification) { #if MAC_APP_STORE || TEST checkForUpdatesMenuItem.isHidden = true @@ -292,7 +292,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, } - func application(_ application: NSApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([NSUserActivityRestoring]) -> Void) -> Bool { + @MainActor func application(_ application: NSApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([NSUserActivityRestoring]) -> Void) -> Bool { guard let mainWindowController = mainWindowController else { return false } @@ -300,7 +300,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, return true } - func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool { + @MainActor func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool { // https://github.com/brentsimmons/NetNewsWire/issues/522 // I couldn’t reproduce the crashing bug, but it appears to happen on creating a main window // and its views and view controllers. The check below is so that the app does nothing @@ -314,26 +314,26 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, return false } - func applicationDidBecomeActive(_ notification: Notification) { + @MainActor func applicationDidBecomeActive(_ notification: Notification) { fireOldTimers() } - func applicationDidResignActive(_ notification: Notification) { + @MainActor func applicationDidResignActive(_ notification: Notification) { ArticleStringFormatter.emptyCaches() saveState() } - func application(_ application: NSApplication, didReceiveRemoteNotification userInfo: [String : Any]) { + @MainActor func application(_ application: NSApplication, didReceiveRemoteNotification userInfo: [String : Any]) { AccountManager.shared.receiveRemoteNotification(userInfo: userInfo) } - func application(_ sender: NSApplication, openFile filename: String) -> Bool { + @MainActor func application(_ sender: NSApplication, openFile filename: String) -> Bool { guard filename.hasSuffix(ArticleTheme.nnwThemeSuffix) else { return false } importTheme(filename: filename) return true } - func applicationWillTerminate(_ notification: Notification) { + @MainActor func applicationWillTerminate(_ notification: Notification) { shuttingDown = true saveState() @@ -347,7 +347,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, while !isShutDownSyncDone && RunLoop.current.run(mode: .default, before: timeout) && timeout > Date() { } } - func presentThemeImportError(_ error: Error) { + @MainActor func presentThemeImportError(_ error: Error) { var informativeText: String = "" if let decodingError = error as? DecodingError { @@ -392,13 +392,13 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, // MARK: Notifications - @objc func unreadCountDidChange(_ note: Notification) { + @MainActor @objc func unreadCountDidChange(_ note: Notification) { if note.object is AccountManager { unreadCount = AccountManager.shared.unreadCount } } - @objc func webFeedSettingDidChange(_ note: Notification) { + @MainActor @objc func webFeedSettingDidChange(_ note: Notification) { guard let feed = note.object as? WebFeed, let key = note.userInfo?[WebFeed.WebFeedSettingUserInfoKey] as? String else { return } @@ -407,14 +407,14 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, } } - @objc func inspectableObjectsDidChange(_ note: Notification) { + @MainActor @objc func inspectableObjectsDidChange(_ note: Notification) { guard let inspectorWindowController = inspectorWindowController, inspectorWindowController.isOpen else { return } inspectorWindowController.objects = objectsForInspector() } - @objc func userDefaultsDidChange(_ note: Notification) { + @MainActor @objc func userDefaultsDidChange(_ note: Notification) { updateSortMenuItems() updateGroupByFeedMenuItem() @@ -426,11 +426,11 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, updateDockBadge() } - @objc func didWakeNotification(_ note: Notification) { + @MainActor @objc func didWakeNotification(_ note: Notification) { fireOldTimers() } - @objc func importDownloadedTheme(_ note: Notification) { + @MainActor @objc func importDownloadedTheme(_ note: Notification) { guard let userInfo = note.userInfo, let url = userInfo["url"] as? URL else { return @@ -442,7 +442,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, // MARK: Main Window - func createMainWindowController() -> MainWindowController { + @MainActor func createMainWindowController() -> MainWindowController { let controller: MainWindowController controller = windowControllerWithName("MainWindow") as! MainWindowController @@ -453,13 +453,13 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, return controller } - func windowControllerWithName(_ storyboardName: String) -> NSWindowController { + @MainActor func windowControllerWithName(_ storyboardName: String) -> NSWindowController { let storyboard = NSStoryboard(name: NSStoryboard.Name(storyboardName), bundle: nil) return storyboard.instantiateInitialController()! as! NSWindowController } @discardableResult - func createAndShowMainWindow() -> MainWindowController { + @MainActor func createAndShowMainWindow() -> MainWindowController { let controller = createMainWindowController() controller.showWindow(self) @@ -471,7 +471,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, return controller } - func createAndShowMainWindowIfNecessary() { + @MainActor func createAndShowMainWindowIfNecessary() { if mainWindowController == nil { createAndShowMainWindow() } else { @@ -479,7 +479,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, } } - func removeMainWindow(_ windowController: MainWindowController) { + @MainActor func removeMainWindow(_ windowController: MainWindowController) { guard mainWindowControllers.count > 1 else { return } if let index = mainWindowControllers.firstIndex(of: windowController) { mainWindowControllers.remove(at: index) @@ -487,7 +487,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, } // MARK: NSUserInterfaceValidations - func validateUserInterfaceItem(_ item: NSValidatedUserInterfaceItem) -> Bool { + @MainActor func validateUserInterfaceItem(_ item: NSValidatedUserInterfaceItem) -> Bool { if shuttingDown { return false } @@ -533,11 +533,11 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, // MARK: UNUserNotificationCenterDelegate - func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { + @MainActor func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { completionHandler([.banner, .badge, .sound]) } - func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { + @MainActor func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { let userInfo = response.notification.request.content.userInfo @@ -553,7 +553,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, } // MARK: Add Feed - func addWebFeed(_ urlString: String?, name: String? = nil, account: Account? = nil, folder: Folder? = nil) { + @MainActor func addWebFeed(_ urlString: String?, name: String? = nil, account: Account? = nil, folder: Folder? = nil) { createAndShowMainWindowIfNecessary() if mainWindowController!.isDisplayingSheet { @@ -564,13 +564,13 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, } // MARK: - Dock Badge - @objc func updateDockBadge() { + @MainActor @objc func updateDockBadge() { let label = unreadCount > 0 ? "\(unreadCount)" : "" NSApplication.shared.dockTile.badgeLabel = label } // MARK: - Actions - @IBAction func showPreferences(_ sender: Any?) { + @MainActor @IBAction func showPreferences(_ sender: Any?) { if preferencesWindowController == nil { preferencesWindowController = windowControllerWithName("Preferences") } @@ -578,35 +578,35 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, preferencesWindowController!.showWindow(self) } - @IBAction func newMainWindow(_ sender: Any?) { + @MainActor @IBAction func newMainWindow(_ sender: Any?) { createAndShowMainWindow() } - @IBAction func showMainWindow(_ sender: Any?) { + @MainActor @IBAction func showMainWindow(_ sender: Any?) { createAndShowMainWindowIfNecessary() mainWindowController?.window?.makeKey() } - @IBAction func refreshAll(_ sender: Any?) { + @MainActor @IBAction func refreshAll(_ sender: Any?) { AccountManager.shared.refreshAll(errorHandler: ErrorHandler.present) } - @IBAction func showAddWebFeedWindow(_ sender: Any?) { + @MainActor @IBAction func showAddWebFeedWindow(_ sender: Any?) { addWebFeed(nil) } - @IBAction func showAddRedditFeedWindow(_ sender: Any?) { + @MainActor @IBAction func showAddRedditFeedWindow(_ sender: Any?) { createAndShowMainWindowIfNecessary() addFeedController = AddFeedController(hostWindow: mainWindowController!.window!) addFeedController?.showAddFeedSheet(.redditFeed) } - @IBAction func showAddFolderWindow(_ sender: Any?) { + @MainActor @IBAction func showAddFolderWindow(_ sender: Any?) { createAndShowMainWindowIfNecessary() showAddFolderSheetOnWindow(mainWindowController!.window!) } - @IBAction func showKeyboardShortcutsWindow(_ sender: Any?) { + @MainActor @IBAction func showKeyboardShortcutsWindow(_ sender: Any?) { if keyboardShortcutsWindowController == nil { keyboardShortcutsWindowController = WebViewWindowController(title: NSLocalizedString("Keyboard Shortcuts", comment: "window title")) @@ -625,7 +625,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, keyboardShortcutsWindowController!.showWindow(self) } - @IBAction func toggleInspectorWindow(_ sender: Any?) { + @MainActor @IBAction func toggleInspectorWindow(_ sender: Any?) { if inspectorWindowController == nil { inspectorWindowController = (windowControllerWithName("Inspector") as! InspectorWindowController) } @@ -639,7 +639,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, } } - @IBAction func importOPMLFromFile(_ sender: Any?) { + @MainActor @IBAction func importOPMLFromFile(_ sender: Any?) { createAndShowMainWindowIfNecessary() if mainWindowController!.isDisplayingSheet { return @@ -649,7 +649,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, importOPMLController?.runSheetOnWindow(mainWindowController!.window!) } - @IBAction func importNNW3FromFile(_ sender: Any?) { + @MainActor @IBAction func importNNW3FromFile(_ sender: Any?) { createAndShowMainWindowIfNecessary() if mainWindowController!.isDisplayingSheet { return @@ -657,7 +657,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, NNW3ImportController.askUserToImportNNW3Subscriptions(window: mainWindowController!.window!) } - @IBAction func exportOPML(_ sender: Any?) { + @MainActor @IBAction func exportOPML(_ sender: Any?) { createAndShowMainWindowIfNecessary() if mainWindowController!.isDisplayingSheet { return @@ -667,30 +667,30 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, exportOPMLController?.runSheetOnWindow(mainWindowController!.window!) } - @IBAction func addAppNews(_ sender: Any?) { + @MainActor @IBAction func addAppNews(_ sender: Any?) { if AccountManager.shared.anyAccountHasNetNewsWireNewsSubscription() { return } addWebFeed(AccountManager.netNewsWireNewsURL, name: "NetNewsWire News") } - @IBAction func openWebsite(_ sender: Any?) { + @MainActor @IBAction func openWebsite(_ sender: Any?) { Browser.open("https://netnewswire.com/", inBackground: false) } - @IBAction func showHelp(_ sender: Any?) { + @MainActor @IBAction func showHelp(_ sender: Any?) { Browser.open("https://netnewswire.com/help/mac/6.1/en/", inBackground: false) } - @IBAction func gotoToday(_ sender: Any?) { + @MainActor @IBAction func gotoToday(_ sender: Any?) { createAndShowMainWindowIfNecessary() mainWindowController!.gotoToday(sender) } - @IBAction func gotoAllUnread(_ sender: Any?) { + @MainActor @IBAction func gotoAllUnread(_ sender: Any?) { createAndShowMainWindowIfNecessary() mainWindowController!.gotoAllUnread(sender) @@ -702,27 +702,27 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, mainWindowController!.gotoStarred(sender) } - @IBAction func sortByOldestArticleOnTop(_ sender: Any?) { + @MainActor @IBAction func sortByOldestArticleOnTop(_ sender: Any?) { AppDefaults.shared.timelineSortDirection = .orderedAscending } - @IBAction func sortByNewestArticleOnTop(_ sender: Any?) { + @MainActor @IBAction func sortByNewestArticleOnTop(_ sender: Any?) { AppDefaults.shared.timelineSortDirection = .orderedDescending } - @IBAction func groupByFeedToggled(_ sender: NSMenuItem) { + @MainActor @IBAction func groupByFeedToggled(_ sender: NSMenuItem) { AppDefaults.shared.timelineGroupByFeed.toggle() } - @IBAction func checkForUpdates(_ sender: Any?) { + @MainActor @IBAction func checkForUpdates(_ sender: Any?) { #if !MAC_APP_STORE && !TEST self.softwareUpdater.checkForUpdates() #endif } - @IBAction func showAbout(_ sender: Any?) { + @MainActor @IBAction func showAbout(_ sender: Any?) { if #available(macOS 12, *) { for window in NSApplication.shared.windows { if window.identifier == .aboutNetNewsWire { @@ -741,7 +741,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, // MARK: - NSMenuDelegate -extension AppDelegate: NSMenuDelegate { +@MainActor extension AppDelegate: NSMenuDelegate { public func menuNeedsUpdate(_ menu: NSMenu) { let newShareMenu = mainWindowController?.shareMenu @@ -760,7 +760,7 @@ extension AppDelegate: NSMenuDelegate { } // MARK: - Debug Menu -extension AppDelegate { +@MainActor extension AppDelegate { @IBAction func debugSearch(_ sender: Any?) { AccountManager.shared.defaultAccount.debugRunSearch() @@ -832,7 +832,7 @@ extension AppDelegate { } -internal extension AppDelegate { +@MainActor internal extension AppDelegate { func fireOldTimers() { // It’s possible there’s a refresh timer set to go off in the past. @@ -1007,7 +1007,7 @@ extension AppDelegate : ScriptingAppDelegate { } } -extension AppDelegate: NSWindowRestoration { +@MainActor extension AppDelegate: NSWindowRestoration { @objc static func restoreWindow(withIdentifier identifier: NSUserInterfaceItemIdentifier, state: NSCoder, completionHandler: @escaping (NSWindow?, Error?) -> Void) { var mainWindow: NSWindow? = nil @@ -1021,7 +1021,7 @@ extension AppDelegate: NSWindowRestoration { // Handle Notification Actions -private extension AppDelegate { +@MainActor private extension AppDelegate { func handleMarkAsRead(userInfo: [AnyHashable: Any]) { markArticle(userInfo: userInfo, statusKey: .read) diff --git a/Mac/Browser.swift b/Mac/Browser.swift index 7b47dad85..7b0ad4d3f 100644 --- a/Mac/Browser.swift +++ b/Mac/Browser.swift @@ -9,7 +9,7 @@ import Foundation import RSWeb -struct Browser { +@MainActor struct Browser { /// The user-specified default browser for opening web pages. /// diff --git a/Mac/ErrorHandler.swift b/Mac/ErrorHandler.swift index 4ec6f59be..1d332359c 100644 --- a/Mac/ErrorHandler.swift +++ b/Mac/ErrorHandler.swift @@ -10,16 +10,13 @@ import AppKit import Account import RSCore -struct ErrorHandler: Logging { +@MainActor struct ErrorHandler: Logging { - - public static func present(_ error: Error) { NSApplication.shared.presentError(error) } - + public static func log(_ error: Error) { ErrorHandler.logger.error("\(error.localizedDescription, privacy: .public)") } - } diff --git a/Mac/MainWindow/About/CreditsNetNewsWireView.swift b/Mac/MainWindow/About/CreditsNetNewsWireView.swift index 88a63fe75..f72318696 100644 --- a/Mac/MainWindow/About/CreditsNetNewsWireView.swift +++ b/Mac/MainWindow/About/CreditsNetNewsWireView.swift @@ -66,7 +66,9 @@ struct CreditsNetNewsWireView: View, LoadableAboutData { .onTapGesture { guard let url = appCredit.url else { return } if let _ = URL(string: url) { - Browser.open(url, inBackground: false) + Task { @MainActor in + Browser.open(url, inBackground: false) + } } } } diff --git a/Mac/MainWindow/ArticleExtractorButton.swift b/Mac/MainWindow/ArticleExtractorButton.swift index d5d30ccf8..1ea097769 100644 --- a/Mac/MainWindow/ArticleExtractorButton.swift +++ b/Mac/MainWindow/ArticleExtractorButton.swift @@ -15,7 +15,7 @@ enum ArticleExtractorButtonState { case off } -class ArticleExtractorButton: NSButton { +@MainActor final class ArticleExtractorButton: NSButton { public var rightClickAction: Selector? diff --git a/Mac/MainWindow/MainWindow.swift b/Mac/MainWindow/MainWindow.swift index 4fe147deb..18409f76a 100644 --- a/Mac/MainWindow/MainWindow.swift +++ b/Mac/MainWindow/MainWindow.swift @@ -8,7 +8,7 @@ import Foundation -class MainWindow: NSWindow { +@MainActor class MainWindow: NSWindow { override func sendEvent(_ event: NSEvent) { diff --git a/Mac/MainWindow/MainWindowController.swift b/Mac/MainWindow/MainWindowController.swift index 9e7e485e4..514ad4040 100644 --- a/Mac/MainWindow/MainWindowController.swift +++ b/Mac/MainWindow/MainWindowController.swift @@ -16,7 +16,7 @@ enum TimelineSourceMode { case regular, search } -class MainWindowController : NSWindowController, NSUserInterfaceValidations { +@MainActor final class MainWindowController : NSWindowController, NSUserInterfaceValidations { @IBOutlet weak var articleThemePopUpButton: NSPopUpButton? diff --git a/Mac/MainWindow/Sidebar/Cell/SidebarCellAppearance.swift b/Mac/MainWindow/Sidebar/Cell/SidebarCellAppearance.swift index c13996732..e5824ba6a 100644 --- a/Mac/MainWindow/Sidebar/Cell/SidebarCellAppearance.swift +++ b/Mac/MainWindow/Sidebar/Cell/SidebarCellAppearance.swift @@ -8,7 +8,7 @@ import AppKit -struct SidebarCellAppearance: Equatable { +@MainActor struct SidebarCellAppearance: Equatable { let imageSize: CGSize let imageMarginRight: CGFloat = 4.0 diff --git a/Mac/MainWindow/Sidebar/Cell/SidebarCellLayout.swift b/Mac/MainWindow/Sidebar/Cell/SidebarCellLayout.swift index e054b924a..ed9e91a94 100644 --- a/Mac/MainWindow/Sidebar/Cell/SidebarCellLayout.swift +++ b/Mac/MainWindow/Sidebar/Cell/SidebarCellLayout.swift @@ -11,7 +11,7 @@ import RSCore // image - title - unreadCount -struct SidebarCellLayout { +@MainActor struct SidebarCellLayout { let faviconRect: CGRect let titleRect: CGRect diff --git a/Mac/MainWindow/Sidebar/Renaming/RenameWindowController.swift b/Mac/MainWindow/Sidebar/Renaming/RenameWindowController.swift index 5cb8b6309..41d1dd07b 100644 --- a/Mac/MainWindow/Sidebar/Renaming/RenameWindowController.swift +++ b/Mac/MainWindow/Sidebar/Renaming/RenameWindowController.swift @@ -13,7 +13,7 @@ protocol RenameWindowControllerDelegate { func renameWindowController(_ windowController: RenameWindowController, didRenameObject: Any, withNewName: String) } -final class RenameWindowController: NSWindowController { +@MainActor final class RenameWindowController: NSWindowController { @IBOutlet var renamePrompt: NSTextField! @IBOutlet var newTitleTextField: NSTextField! diff --git a/Mac/MainWindow/Sidebar/SidebarDeleteItemsAlert.swift b/Mac/MainWindow/Sidebar/SidebarDeleteItemsAlert.swift index 899c29cf1..571137231 100644 --- a/Mac/MainWindow/Sidebar/SidebarDeleteItemsAlert.swift +++ b/Mac/MainWindow/Sidebar/SidebarDeleteItemsAlert.swift @@ -10,7 +10,7 @@ import AppKit import RSTree import Account -enum SidebarDeleteItemsAlert { +@MainActor enum SidebarDeleteItemsAlert { /// Builds a delete confirmation dialog for the supplied nodes static func build(_ nodes: [Node]) -> NSAlert { diff --git a/Mac/MainWindow/Sidebar/SidebarOutlineDataSource.swift b/Mac/MainWindow/Sidebar/SidebarOutlineDataSource.swift index 7e0478d5f..a4fb7b5e9 100644 --- a/Mac/MainWindow/Sidebar/SidebarOutlineDataSource.swift +++ b/Mac/MainWindow/Sidebar/SidebarOutlineDataSource.swift @@ -492,7 +492,7 @@ private extension SidebarOutlineDataSource { return true } - func acceptSingleNonLocalFeedDrop(_ outlineView: NSOutlineView, _ draggedFeed: PasteboardWebFeed, _ parentNode: Node, _ index: Int) -> Bool { + @MainActor func acceptSingleNonLocalFeedDrop(_ outlineView: NSOutlineView, _ draggedFeed: PasteboardWebFeed, _ parentNode: Node, _ index: Int) -> Bool { guard nodeIsDropTarget(parentNode), index == NSOutlineViewDropOnItemIndex else { return false } diff --git a/Mac/MainWindow/Sidebar/SidebarOutlineView.swift b/Mac/MainWindow/Sidebar/SidebarOutlineView.swift index 2be34e87c..eefc29a63 100644 --- a/Mac/MainWindow/Sidebar/SidebarOutlineView.swift +++ b/Mac/MainWindow/Sidebar/SidebarOutlineView.swift @@ -10,7 +10,7 @@ import AppKit import RSCore import RSTree -class SidebarOutlineView : NSOutlineView { +@MainActor class SidebarOutlineView : NSOutlineView { @IBOutlet var keyboardDelegate: KeyboardDelegate! diff --git a/Mac/MainWindow/Sidebar/SidebarStatusBarView.swift b/Mac/MainWindow/Sidebar/SidebarStatusBarView.swift index 315ea4ae3..6a85a6f9f 100644 --- a/Mac/MainWindow/Sidebar/SidebarStatusBarView.swift +++ b/Mac/MainWindow/Sidebar/SidebarStatusBarView.swift @@ -12,7 +12,7 @@ import Articles import RSWeb import Account -final class SidebarStatusBarView: NSView { +@MainActor final class SidebarStatusBarView: NSView { @IBOutlet var progressIndicator: NSProgressIndicator! @IBOutlet var progressLabel: NSTextField! diff --git a/Mac/MainWindow/URLPasteboardWriter+NetNewsWire.swift b/Mac/MainWindow/URLPasteboardWriter+NetNewsWire.swift index 81c3e3ce4..0d3a9488e 100644 --- a/Mac/MainWindow/URLPasteboardWriter+NetNewsWire.swift +++ b/Mac/MainWindow/URLPasteboardWriter+NetNewsWire.swift @@ -8,7 +8,7 @@ import RSCore -extension URLPasteboardWriter { +@MainActor extension URLPasteboardWriter { /// Copy URL strings, alerting the user the first time the array of URL strings contains `nil`. /// - Parameters: diff --git a/Mac/Scriptability/AppDelegate+Scriptability.swift b/Mac/Scriptability/AppDelegate+Scriptability.swift index 07f3057c2..bcae9ee55 100644 --- a/Mac/Scriptability/AppDelegate+Scriptability.swift +++ b/Mac/Scriptability/AppDelegate+Scriptability.swift @@ -39,7 +39,7 @@ extension AppDelegate : AppDelegateAppleEvents { NSAppleEventManager.shared().setEventHandler(self, andSelector: #selector(AppDelegate.getURL(_:_:)), forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL)) } - @objc func getURL(_ event: NSAppleEventDescriptor, _ withReplyEvent: NSAppleEventDescriptor) { + @MainActor @objc func getURL(_ event: NSAppleEventDescriptor, _ withReplyEvent: NSAppleEventDescriptor) { guard var urlString = event.paramDescriptor(forKeyword: keyDirectObject)?.stringValue else { return diff --git a/Shared/ArticleStyles/ArticleThemesManager.swift b/Shared/ArticleStyles/ArticleThemesManager.swift index 7a9685d47..eb01b766b 100644 --- a/Shared/ArticleStyles/ArticleThemesManager.swift +++ b/Shared/ArticleStyles/ArticleThemesManager.swift @@ -81,7 +81,9 @@ final class ArticleThemesManager: NSObject, NSFilePresenter, Logging { do { currentTheme = try articleThemeWithThemeName(currentThemeName) } catch { - appDelegate.presentThemeImportError(error) + Task { @MainActor in + appDelegate.presentThemeImportError(error) + } } } } From ed730b45a2a934f5f1c5a4167bd99c248fa9fed2 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Wed, 5 Apr 2023 12:28:24 -0700 Subject: [PATCH 03/18] Continue adopting @MainActor. --- Mac/MainWindow/Sidebar/Cell/SidebarCell.swift | 2 +- Mac/MainWindow/Timeline/TimelineContainerView.swift | 2 +- Mac/MainWindow/Timeline/TimelineContainerViewController.swift | 2 +- Mac/MainWindow/Timeline/TimelineTableRowView.swift | 2 +- Mac/MainWindow/Timeline/TimelineTableView.swift | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Mac/MainWindow/Sidebar/Cell/SidebarCell.swift b/Mac/MainWindow/Sidebar/Cell/SidebarCell.swift index 0ec462a19..ffc1162be 100644 --- a/Mac/MainWindow/Sidebar/Cell/SidebarCell.swift +++ b/Mac/MainWindow/Sidebar/Cell/SidebarCell.swift @@ -11,7 +11,7 @@ import RSCore import Account import RSTree -class SidebarCell : NSTableCellView { +@MainActor final class SidebarCell : NSTableCellView { var iconImage: IconImage? { didSet { diff --git a/Mac/MainWindow/Timeline/TimelineContainerView.swift b/Mac/MainWindow/Timeline/TimelineContainerView.swift index e75475405..6a8b42298 100644 --- a/Mac/MainWindow/Timeline/TimelineContainerView.swift +++ b/Mac/MainWindow/Timeline/TimelineContainerView.swift @@ -8,7 +8,7 @@ import AppKit -final class TimelineContainerView: NSView { +@MainActor final class TimelineContainerView: NSView { private var contentViewConstraints: [NSLayoutConstraint]? diff --git a/Mac/MainWindow/Timeline/TimelineContainerViewController.swift b/Mac/MainWindow/Timeline/TimelineContainerViewController.swift index c697a1a0c..81ec39b30 100644 --- a/Mac/MainWindow/Timeline/TimelineContainerViewController.swift +++ b/Mac/MainWindow/Timeline/TimelineContainerViewController.swift @@ -17,7 +17,7 @@ protocol TimelineContainerViewControllerDelegate: AnyObject { } -final class TimelineContainerViewController: NSViewController { +@MainActor final class TimelineContainerViewController: NSViewController { @IBOutlet weak var viewOptionsPopUpButton: NSPopUpButton! @IBOutlet weak var newestToOldestMenuItem: NSMenuItem! diff --git a/Mac/MainWindow/Timeline/TimelineTableRowView.swift b/Mac/MainWindow/Timeline/TimelineTableRowView.swift index 54d87479c..d4598ef1e 100644 --- a/Mac/MainWindow/Timeline/TimelineTableRowView.swift +++ b/Mac/MainWindow/Timeline/TimelineTableRowView.swift @@ -8,7 +8,7 @@ import AppKit -class TimelineTableRowView : NSTableRowView { +@MainActor final class TimelineTableRowView : NSTableRowView { private var separator: NSView? diff --git a/Mac/MainWindow/Timeline/TimelineTableView.swift b/Mac/MainWindow/Timeline/TimelineTableView.swift index e70bbed17..f5d8a9469 100644 --- a/Mac/MainWindow/Timeline/TimelineTableView.swift +++ b/Mac/MainWindow/Timeline/TimelineTableView.swift @@ -9,7 +9,7 @@ import AppKit import RSCore -class TimelineTableView: NSTableView { +@MainActor final class TimelineTableView: NSTableView { weak var keyboardDelegate: KeyboardDelegate? From 1f9305eb9a0896d8d05ac453fd8a3ce342485a67 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Wed, 5 Apr 2023 18:27:52 -0700 Subject: [PATCH 04/18] Fix warning about not being in a @MainActor context. --- Mac/Scriptability/AppDelegate+Scriptability.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Mac/Scriptability/AppDelegate+Scriptability.swift b/Mac/Scriptability/AppDelegate+Scriptability.swift index bcae9ee55..a16334eaf 100644 --- a/Mac/Scriptability/AppDelegate+Scriptability.swift +++ b/Mac/Scriptability/AppDelegate+Scriptability.swift @@ -63,7 +63,9 @@ extension AppDelegate : AppDelegateAppleEvents { do { try ArticleThemeDownloader.shared.handleFile(at: location) } catch { - self.presentThemeImportError(error) + Task { @MainActor in + self.presentThemeImportError(error) + } } } task.resume() From 8bbf4d8c6057bf3acb58a005d457b657bd691923 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Wed, 5 Apr 2023 18:35:34 -0700 Subject: [PATCH 05/18] Continue adopting @MainActor. --- Account/Sources/Account/AccountManager.swift | 6 ++++-- Mac/MainWindow/Detail/DetailIconSchemeHandler.swift | 2 +- Mac/MainWindow/Detail/DetailStatusBarView.swift | 2 +- Mac/MainWindow/Detail/DetailViewController.swift | 2 +- Mac/MainWindow/Detail/DetailWebView.swift | 2 +- Mac/MainWindow/Detail/DetailWebViewController.swift | 2 +- 6 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Account/Sources/Account/AccountManager.swift b/Account/Sources/Account/AccountManager.swift index 0989691cc..abdf4d154 100644 --- a/Account/Sources/Account/AccountManager.swift +++ b/Account/Sources/Account/AccountManager.swift @@ -246,7 +246,7 @@ public final class AccountManager: UnreadCountProvider { } } - public func refreshAll(errorHandler: @escaping (Error) -> Void, completion: (() -> Void)? = nil) { + public func refreshAll(errorHandler: @escaping @MainActor (Error) -> Void, completion: (() -> Void)? = nil) { guard let reachability = try? Reachability(hostname: "apple.com"), reachability.connection != .unavailable else { return } let group = DispatchGroup() @@ -259,7 +259,9 @@ public final class AccountManager: UnreadCountProvider { case .success: break case .failure(let error): - errorHandler(error) + Task { @MainActor in + errorHandler(error) + } } } } diff --git a/Mac/MainWindow/Detail/DetailIconSchemeHandler.swift b/Mac/MainWindow/Detail/DetailIconSchemeHandler.swift index 4aee30c11..334605cbe 100644 --- a/Mac/MainWindow/Detail/DetailIconSchemeHandler.swift +++ b/Mac/MainWindow/Detail/DetailIconSchemeHandler.swift @@ -10,7 +10,7 @@ import Foundation import WebKit import Articles -class DetailIconSchemeHandler: NSObject, WKURLSchemeHandler { +final class DetailIconSchemeHandler: NSObject, WKURLSchemeHandler { var currentArticle: Article? diff --git a/Mac/MainWindow/Detail/DetailStatusBarView.swift b/Mac/MainWindow/Detail/DetailStatusBarView.swift index eea5f72d2..119f5b112 100644 --- a/Mac/MainWindow/Detail/DetailStatusBarView.swift +++ b/Mac/MainWindow/Detail/DetailStatusBarView.swift @@ -9,7 +9,7 @@ import AppKit import Articles -final class DetailStatusBarView: NSView { +@MainActor final class DetailStatusBarView: NSView { @IBOutlet var urlLabel: NSTextField! diff --git a/Mac/MainWindow/Detail/DetailViewController.swift b/Mac/MainWindow/Detail/DetailViewController.swift index bcfd2533a..e4b099bf4 100644 --- a/Mac/MainWindow/Detail/DetailViewController.swift +++ b/Mac/MainWindow/Detail/DetailViewController.swift @@ -20,7 +20,7 @@ enum DetailState: Equatable { case extracted(Article, ExtractedArticle, CGFloat?) } -final class DetailViewController: NSViewController, WKUIDelegate { +@MainActor final class DetailViewController: NSViewController, WKUIDelegate { @IBOutlet var containerView: DetailContainerView! @IBOutlet var statusBarView: DetailStatusBarView! diff --git a/Mac/MainWindow/Detail/DetailWebView.swift b/Mac/MainWindow/Detail/DetailWebView.swift index 56f5d7812..5bdf0cbfc 100644 --- a/Mac/MainWindow/Detail/DetailWebView.swift +++ b/Mac/MainWindow/Detail/DetailWebView.swift @@ -10,7 +10,7 @@ import AppKit import WebKit import RSCore -final class DetailWebView: WKWebView { +@MainActor final class DetailWebView: WKWebView { weak var keyboardDelegate: KeyboardDelegate? diff --git a/Mac/MainWindow/Detail/DetailWebViewController.swift b/Mac/MainWindow/Detail/DetailWebViewController.swift index 6d669cf5f..36c691c42 100644 --- a/Mac/MainWindow/Detail/DetailWebViewController.swift +++ b/Mac/MainWindow/Detail/DetailWebViewController.swift @@ -17,7 +17,7 @@ protocol DetailWebViewControllerDelegate: AnyObject { func mouseDidExit(_: DetailWebViewController) } -final class DetailWebViewController: NSViewController { +@MainActor final class DetailWebViewController: NSViewController { weak var delegate: DetailWebViewControllerDelegate? var webView: DetailWebView! From 052884cafc0097dca4501ce68030d347a4149dc2 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Wed, 5 Apr 2023 18:47:48 -0700 Subject: [PATCH 06/18] Continue adopting @MainActor. --- Mac/MainWindow/AddFeed/AddFeedController.swift | 2 +- Mac/MainWindow/AddFeed/AddFeedWIndowController.swift | 4 ++-- Mac/MainWindow/AddRedditFeedWindowController.swift | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Mac/MainWindow/AddFeed/AddFeedController.swift b/Mac/MainWindow/AddFeed/AddFeedController.swift index 941fca98b..38c27414b 100644 --- a/Mac/MainWindow/AddFeed/AddFeedController.swift +++ b/Mac/MainWindow/AddFeed/AddFeedController.swift @@ -22,7 +22,7 @@ import RSParser // Else, // display error sheet. -class AddFeedController: AddFeedWindowControllerDelegate { +@MainActor final class AddFeedController: AddFeedWindowControllerDelegate { private let hostWindow: NSWindow private var addFeedWindowController: AddFeedWindowController? diff --git a/Mac/MainWindow/AddFeed/AddFeedWIndowController.swift b/Mac/MainWindow/AddFeed/AddFeedWIndowController.swift index e574d7fa5..50ad03701 100644 --- a/Mac/MainWindow/AddFeed/AddFeedWIndowController.swift +++ b/Mac/MainWindow/AddFeed/AddFeedWIndowController.swift @@ -14,7 +14,7 @@ enum AddFeedWindowControllerType { case redditFeed } -protocol AddFeedWindowControllerDelegate: AnyObject { +@MainActor protocol AddFeedWindowControllerDelegate: AnyObject { // userEnteredURL will have already been validated and normalized. func addFeedWindowController(_: AddFeedWindowController, userEnteredURL: URL, userEnteredTitle: String?, container: Container) @@ -22,7 +22,7 @@ protocol AddFeedWindowControllerDelegate: AnyObject { } -protocol AddFeedWindowController { +@MainActor protocol AddFeedWindowController { var window: NSWindow? { get } func runSheetOnWindow(_ hostWindow: NSWindow) diff --git a/Mac/MainWindow/AddRedditFeedWindowController.swift b/Mac/MainWindow/AddRedditFeedWindowController.swift index 55056ad34..0d07abccb 100644 --- a/Mac/MainWindow/AddRedditFeedWindowController.swift +++ b/Mac/MainWindow/AddRedditFeedWindowController.swift @@ -12,7 +12,7 @@ import RSTree import Articles import Account -class AddRedditFeedWindowController : NSWindowController, AddFeedWindowController { +@MainActor final class AddRedditFeedWindowController : NSWindowController, AddFeedWindowController { @IBOutlet weak var typePopupButton: NSPopUpButton! @IBOutlet weak var typeDescriptionLabel: NSTextField! From f495730066ca450a532b3216af6c0051ba1f82fd Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Wed, 5 Apr 2023 19:04:52 -0700 Subject: [PATCH 07/18] Continue adopting @MainActor. --- Mac/MainWindow/AddFeed/AddWebFeedWindowController.swift | 2 +- Mac/MainWindow/AddFeed/FolderTreeMenu.swift | 2 +- Mac/MainWindow/AddFolder/AddFolderWindowController.swift | 2 +- Mac/MainWindow/NNW3/NNW3ImportController.swift | 2 +- Mac/MainWindow/NNW3/NNW3OpenPanelAccessoryViewController.swift | 2 +- Mac/MainWindow/OPML/ExportOPMLWindowController.swift | 2 +- Mac/MainWindow/OPML/ImportOPMLWindowController.swift | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Mac/MainWindow/AddFeed/AddWebFeedWindowController.swift b/Mac/MainWindow/AddFeed/AddWebFeedWindowController.swift index 16c8a4d72..40b6f6301 100644 --- a/Mac/MainWindow/AddFeed/AddWebFeedWindowController.swift +++ b/Mac/MainWindow/AddFeed/AddWebFeedWindowController.swift @@ -12,7 +12,7 @@ import RSTree import Articles import Account -class AddWebFeedWindowController : NSWindowController, AddFeedWindowController { +@MainActor final class AddWebFeedWindowController : NSWindowController, AddFeedWindowController { @IBOutlet var urlTextField: NSTextField! @IBOutlet var nameTextField: NSTextField! diff --git a/Mac/MainWindow/AddFeed/FolderTreeMenu.swift b/Mac/MainWindow/AddFeed/FolderTreeMenu.swift index 87250dd6b..1c696f0dc 100644 --- a/Mac/MainWindow/AddFeed/FolderTreeMenu.swift +++ b/Mac/MainWindow/AddFeed/FolderTreeMenu.swift @@ -11,7 +11,7 @@ import RSCore import RSTree import Account -class FolderTreeMenu { +@MainActor final class FolderTreeMenu { static func createFolderPopupMenu(with rootNode: Node, restrictToSpecialAccounts: Bool = false) -> NSMenu { diff --git a/Mac/MainWindow/AddFolder/AddFolderWindowController.swift b/Mac/MainWindow/AddFolder/AddFolderWindowController.swift index 84053ee20..08cc50310 100644 --- a/Mac/MainWindow/AddFolder/AddFolderWindowController.swift +++ b/Mac/MainWindow/AddFolder/AddFolderWindowController.swift @@ -10,7 +10,7 @@ import AppKit import Articles import Account -class AddFolderWindowController : NSWindowController { +@MainActor final class AddFolderWindowController : NSWindowController { @IBOutlet var folderNameTextField: NSTextField! @IBOutlet var accountPopupButton: NSPopUpButton! diff --git a/Mac/MainWindow/NNW3/NNW3ImportController.swift b/Mac/MainWindow/NNW3/NNW3ImportController.swift index 32084490e..b36c1e7ee 100644 --- a/Mac/MainWindow/NNW3/NNW3ImportController.swift +++ b/Mac/MainWindow/NNW3/NNW3ImportController.swift @@ -9,7 +9,7 @@ import AppKit import Account -struct NNW3ImportController { +@MainActor struct NNW3ImportController { /// Import NNW3 subscriptions if they exist. /// Return true if Subscriptions.plist was found and subscriptions were imported. diff --git a/Mac/MainWindow/NNW3/NNW3OpenPanelAccessoryViewController.swift b/Mac/MainWindow/NNW3/NNW3OpenPanelAccessoryViewController.swift index 110377b11..a8c2484c2 100644 --- a/Mac/MainWindow/NNW3/NNW3OpenPanelAccessoryViewController.swift +++ b/Mac/MainWindow/NNW3/NNW3OpenPanelAccessoryViewController.swift @@ -9,7 +9,7 @@ import AppKit import Account -final class NNW3OpenPanelAccessoryViewController: NSViewController { +@MainActor final class NNW3OpenPanelAccessoryViewController: NSViewController { @IBOutlet weak var accountPopUpButton: NSPopUpButton! diff --git a/Mac/MainWindow/OPML/ExportOPMLWindowController.swift b/Mac/MainWindow/OPML/ExportOPMLWindowController.swift index 4b2ce20a6..0ff8284e0 100644 --- a/Mac/MainWindow/OPML/ExportOPMLWindowController.swift +++ b/Mac/MainWindow/OPML/ExportOPMLWindowController.swift @@ -9,7 +9,7 @@ import AppKit import Account -class ExportOPMLWindowController: NSWindowController { +@MainActor final class ExportOPMLWindowController: NSWindowController { @IBOutlet weak var accountPopUpButton: NSPopUpButton! private weak var hostWindow: NSWindow? diff --git a/Mac/MainWindow/OPML/ImportOPMLWindowController.swift b/Mac/MainWindow/OPML/ImportOPMLWindowController.swift index f0737fe93..3a53c3de3 100644 --- a/Mac/MainWindow/OPML/ImportOPMLWindowController.swift +++ b/Mac/MainWindow/OPML/ImportOPMLWindowController.swift @@ -9,7 +9,7 @@ import AppKit import Account -class ImportOPMLWindowController: NSWindowController { +@MainActor final class ImportOPMLWindowController: NSWindowController { @IBOutlet weak var accountPopUpButton: NSPopUpButton! private weak var hostWindow: NSWindow? From c7d4e43da7e0effe96ea585b053df156f22a428f Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Wed, 5 Apr 2023 19:08:47 -0700 Subject: [PATCH 08/18] Continue adopting @MainActor. --- Mac/Inspector/BuiltinSmartFeedInspectorViewController.swift | 2 +- Mac/Inspector/FolderInspectorViewController.swift | 2 +- Mac/Inspector/InspectorWindowController.swift | 4 ++-- Mac/Inspector/NothingInspectorViewController.swift | 2 +- Mac/Inspector/WebFeedInspectorViewController.swift | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Mac/Inspector/BuiltinSmartFeedInspectorViewController.swift b/Mac/Inspector/BuiltinSmartFeedInspectorViewController.swift index 3c6c7b908..72bca9099 100644 --- a/Mac/Inspector/BuiltinSmartFeedInspectorViewController.swift +++ b/Mac/Inspector/BuiltinSmartFeedInspectorViewController.swift @@ -8,7 +8,7 @@ import AppKit -final class BuiltinSmartFeedInspectorViewController: NSViewController, Inspector { +@MainActor final class BuiltinSmartFeedInspectorViewController: NSViewController, Inspector { @IBOutlet var nameTextField: NSTextField? @IBOutlet weak var smartFeedImageView: NSImageView! diff --git a/Mac/Inspector/FolderInspectorViewController.swift b/Mac/Inspector/FolderInspectorViewController.swift index 63f76b0d7..6e12f248d 100644 --- a/Mac/Inspector/FolderInspectorViewController.swift +++ b/Mac/Inspector/FolderInspectorViewController.swift @@ -10,7 +10,7 @@ import AppKit import Account import RSCore -final class FolderInspectorViewController: NSViewController, Inspector { +@MainActor final class FolderInspectorViewController: NSViewController, Inspector { @IBOutlet var nameTextField: NSTextField? @IBOutlet weak var folderImageView: NSImageView! diff --git a/Mac/Inspector/InspectorWindowController.swift b/Mac/Inspector/InspectorWindowController.swift index 2686f86c4..078de1439 100644 --- a/Mac/Inspector/InspectorWindowController.swift +++ b/Mac/Inspector/InspectorWindowController.swift @@ -8,7 +8,7 @@ import AppKit -protocol Inspector: AnyObject { +@MainActor protocol Inspector: AnyObject { var objects: [Any]? { get set } var isFallbackInspector: Bool { get } // Can handle nothing-to-inspect or unexpected type of objects. @@ -20,7 +20,7 @@ protocol Inspector: AnyObject { typealias InspectorViewController = Inspector & NSViewController -final class InspectorWindowController: NSWindowController { +@MainActor final class InspectorWindowController: NSWindowController { class var shouldOpenAtStartup: Bool { return UserDefaults.standard.bool(forKey: DefaultsKey.windowIsOpen) diff --git a/Mac/Inspector/NothingInspectorViewController.swift b/Mac/Inspector/NothingInspectorViewController.swift index 376e6a594..168513e5e 100644 --- a/Mac/Inspector/NothingInspectorViewController.swift +++ b/Mac/Inspector/NothingInspectorViewController.swift @@ -8,7 +8,7 @@ import AppKit -final class NothingInspectorViewController: NSViewController, Inspector { +@MainActor final class NothingInspectorViewController: NSViewController, Inspector { @IBOutlet var nothingTextField: NSTextField? @IBOutlet var multipleTextField: NSTextField? diff --git a/Mac/Inspector/WebFeedInspectorViewController.swift b/Mac/Inspector/WebFeedInspectorViewController.swift index 58c24b254..123961828 100644 --- a/Mac/Inspector/WebFeedInspectorViewController.swift +++ b/Mac/Inspector/WebFeedInspectorViewController.swift @@ -11,7 +11,7 @@ import Articles import Account import UserNotifications -final class WebFeedInspectorViewController: NSViewController, Inspector { +@MainActor final class WebFeedInspectorViewController: NSViewController, Inspector { @IBOutlet weak var iconView: IconView! @IBOutlet weak var nameTextField: NSTextField? From 7e51998a466eda493716c76da8fa86093f2b4bc5 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Wed, 5 Apr 2023 19:27:51 -0700 Subject: [PATCH 09/18] Continue adopting @MainActor. --- iOS/AppDelegate.swift | 24 ++++++++++++------------ iOS/RootSplitViewController.swift | 2 +- iOS/SceneCoordinator.swift | 2 +- iOS/SceneDelegate.swift | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/iOS/AppDelegate.swift b/iOS/AppDelegate.swift index bf145a3b0..7592430f0 100644 --- a/iOS/AppDelegate.swift +++ b/iOS/AppDelegate.swift @@ -57,7 +57,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD var isSyncArticleStatusRunning = false var isWaitingForSyncTasks = false - override init() { + @MainActor override init() { super.init() appDelegate = self @@ -76,7 +76,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD NotificationCenter.default.addObserver(self, selector: #selector(unreadCountDidChange(_:)), name: .UnreadCountDidChange, object: nil) } - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + @MainActor func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { AppDefaults.registerDefaults() let isFirstRun = AppDefaults.shared.isFirstRun @@ -124,7 +124,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD } - func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { + @MainActor func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { DispatchQueue.main.async { self.resumeDatabaseProcessingIfNecessary() AccountManager.shared.receiveRemoteNotification(userInfo: userInfo) { @@ -134,17 +134,17 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD } } - func applicationWillTerminate(_ application: UIApplication) { + @MainActor func applicationWillTerminate(_ application: UIApplication) { shuttingDown = true } - func applicationDidEnterBackground(_ application: UIApplication) { + @MainActor func applicationDidEnterBackground(_ application: UIApplication) { IconImageCache.shared.emptyCache() } // MARK: Notifications - @objc func unreadCountDidChange(_ note: Notification) { + @MainActor @objc func unreadCountDidChange(_ note: Notification) { if note.object is AccountManager { unreadCount = AccountManager.shared.unreadCount } @@ -152,21 +152,21 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD // MARK: - API - func manualRefresh(errorHandler: @escaping (Error) -> ()) { + @MainActor func manualRefresh(errorHandler: @escaping (Error) -> ()) { UIApplication.shared.connectedScenes.compactMap( { $0.delegate as? SceneDelegate } ).forEach { $0.cleanUp(conditional: true) } AccountManager.shared.refreshAll(errorHandler: errorHandler) } - func resumeDatabaseProcessingIfNecessary() { + @MainActor func resumeDatabaseProcessingIfNecessary() { if AccountManager.shared.isSuspended { AccountManager.shared.resumeAll() logger.info("Application processing resumed.") } } - func prepareAccountsForBackground() { + @MainActor func prepareAccountsForBackground() { extensionFeedAddRequestFile.suspend() syncTimer?.invalidate() scheduleBackgroundFeedRefresh() @@ -175,7 +175,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD waitForSyncTasksToFinish() } - func prepareAccountsForForeground() { + @MainActor func prepareAccountsForForeground() { extensionFeedAddRequestFile.resume() syncTimer?.update() @@ -215,7 +215,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD } - func presentThemeImportError(_ error: Error) { + @MainActor func presentThemeImportError(_ error: Error) { let windowScene = { let scenes = UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene } return scenes.filter { $0.activationState == .foregroundActive }.first ?? scenes.first @@ -228,7 +228,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD // MARK: App Initialization -private extension AppDelegate { +@MainActor private extension AppDelegate { private func initializeDownloaders() { let tempDir = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first! diff --git a/iOS/RootSplitViewController.swift b/iOS/RootSplitViewController.swift index 7b8c9d0c0..2c1075634 100644 --- a/iOS/RootSplitViewController.swift +++ b/iOS/RootSplitViewController.swift @@ -9,7 +9,7 @@ import UIKit import Account -class RootSplitViewController: UISplitViewController { +final class RootSplitViewController: UISplitViewController { var coordinator: SceneCoordinator! diff --git a/iOS/SceneCoordinator.swift b/iOS/SceneCoordinator.swift index 85f4febc5..6aa712981 100644 --- a/iOS/SceneCoordinator.swift +++ b/iOS/SceneCoordinator.swift @@ -52,7 +52,7 @@ struct FeedNode: Hashable { } } -class SceneCoordinator: NSObject, UndoableCommandRunner, Logging { +final class SceneCoordinator: NSObject, UndoableCommandRunner, Logging { var undoableCommands = [UndoableCommand]() var undoManager: UndoManager? { diff --git a/iOS/SceneDelegate.swift b/iOS/SceneDelegate.swift index 4c2fc6966..3513932b4 100644 --- a/iOS/SceneDelegate.swift +++ b/iOS/SceneDelegate.swift @@ -12,7 +12,7 @@ import Account import Zip import RSCore -class SceneDelegate: UIResponder, UIWindowSceneDelegate, Logging { +@MainActor final class SceneDelegate: UIResponder, UIWindowSceneDelegate, Logging { var window: UIWindow? var coordinator: SceneCoordinator! From fa0d00d72d481d690597293c218c073ffe83d775 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Wed, 5 Apr 2023 19:36:18 -0700 Subject: [PATCH 10/18] Continue adopting @MainActor. --- iOS/KeyboardManager.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iOS/KeyboardManager.swift b/iOS/KeyboardManager.swift index 981fa5eb4..0c3788be7 100644 --- a/iOS/KeyboardManager.swift +++ b/iOS/KeyboardManager.swift @@ -15,7 +15,7 @@ enum KeyboardType: String { case detail = "DetailKeyboardShortcuts" } -class KeyboardManager { +@MainActor final class KeyboardManager { private(set) var _keyCommands: [UIKeyCommand] var keyCommands: [UIKeyCommand] { From 2502c6a55137bf86111cb2ae3c53412dc5894d49 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Thu, 6 Apr 2023 13:06:17 -0700 Subject: [PATCH 11/18] Fix warning about unneeded try. --- iOS/Settings/ArticleThemesTableViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iOS/Settings/ArticleThemesTableViewController.swift b/iOS/Settings/ArticleThemesTableViewController.swift index deefb41e9..3ab6d9557 100644 --- a/iOS/Settings/ArticleThemesTableViewController.swift +++ b/iOS/Settings/ArticleThemesTableViewController.swift @@ -114,7 +114,7 @@ extension ArticleThemesTableViewController: UIDocumentPickerDelegate { func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) { guard let url = urls.first else { return } - try ArticleThemeImporter.importTheme(controller: self, filename: url.standardizedFileURL.path) + ArticleThemeImporter.importTheme(controller: self, filename: url.standardizedFileURL.path) } } From 59d3bf278a2abb57970c7f9d47803ec849c673f6 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Thu, 6 Apr 2023 21:47:57 -0700 Subject: [PATCH 12/18] Fix concurrency warning. --- iOS/SceneDelegate.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/iOS/SceneDelegate.swift b/iOS/SceneDelegate.swift index 3513932b4..81947ebac 100644 --- a/iOS/SceneDelegate.swift +++ b/iOS/SceneDelegate.swift @@ -195,7 +195,9 @@ import RSCore do { try ArticleThemeDownloader.shared.handleFile(at: location) } catch { - self.presentError(error) + Task { @MainActor in + self.presentError(error) + } } } task.resume() From 22f9dbacff238e5d7da7fbb5c402945daae12dac Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Thu, 6 Apr 2023 21:53:45 -0700 Subject: [PATCH 13/18] Continue adopting @MainActor. --- iOS/MasterFeed/Cell/MasterFeedTableViewCell.swift | 2 +- iOS/MasterFeed/Cell/MasterFeedTableViewCellLayout.swift | 2 +- .../Cell/MasterFeedTableViewSectionHeaderLayout.swift | 2 +- iOS/MasterFeed/Cell/MasterFeedUnreadCountView.swift | 2 +- iOS/MasterFeed/RefreshProgressView.swift | 2 +- iOS/MasterTimeline/MasterTimelineUnreadCountView.swift | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/iOS/MasterFeed/Cell/MasterFeedTableViewCell.swift b/iOS/MasterFeed/Cell/MasterFeedTableViewCell.swift index c2e84c7c0..13eeac341 100644 --- a/iOS/MasterFeed/Cell/MasterFeedTableViewCell.swift +++ b/iOS/MasterFeed/Cell/MasterFeedTableViewCell.swift @@ -15,7 +15,7 @@ protocol MasterFeedTableViewCellDelegate: AnyObject { func masterFeedTableViewCellDisclosureDidToggle(_ sender: MasterFeedTableViewCell, expanding: Bool) } -class MasterFeedTableViewCell : VibrantTableViewCell { +@MainActor final class MasterFeedTableViewCell : VibrantTableViewCell { weak var delegate: MasterFeedTableViewCellDelegate? diff --git a/iOS/MasterFeed/Cell/MasterFeedTableViewCellLayout.swift b/iOS/MasterFeed/Cell/MasterFeedTableViewCellLayout.swift index d4c7338bb..1f1e266fb 100644 --- a/iOS/MasterFeed/Cell/MasterFeedTableViewCellLayout.swift +++ b/iOS/MasterFeed/Cell/MasterFeedTableViewCellLayout.swift @@ -9,7 +9,7 @@ import UIKit import RSCore -struct MasterFeedTableViewCellLayout { +@MainActor struct MasterFeedTableViewCellLayout { private static let indentWidth = CGFloat(integerLiteral: 15) private static let editingControlIndent = CGFloat(integerLiteral: 40) diff --git a/iOS/MasterFeed/Cell/MasterFeedTableViewSectionHeaderLayout.swift b/iOS/MasterFeed/Cell/MasterFeedTableViewSectionHeaderLayout.swift index 73dce3f69..eeacff01f 100644 --- a/iOS/MasterFeed/Cell/MasterFeedTableViewSectionHeaderLayout.swift +++ b/iOS/MasterFeed/Cell/MasterFeedTableViewSectionHeaderLayout.swift @@ -9,7 +9,7 @@ import UIKit import RSCore -struct MasterFeedTableViewSectionHeaderLayout { +@MainActor struct MasterFeedTableViewSectionHeaderLayout { private static let labelMarginRight = CGFloat(integerLiteral: 8) private static let disclosureButtonSize = CGSize(width: 44, height: 44) diff --git a/iOS/MasterFeed/Cell/MasterFeedUnreadCountView.swift b/iOS/MasterFeed/Cell/MasterFeedUnreadCountView.swift index 17db54492..ce2b7d912 100644 --- a/iOS/MasterFeed/Cell/MasterFeedUnreadCountView.swift +++ b/iOS/MasterFeed/Cell/MasterFeedUnreadCountView.swift @@ -8,7 +8,7 @@ import UIKit -class MasterFeedUnreadCountView : UIView { +@MainActor class MasterFeedUnreadCountView : UIView { var padding: UIEdgeInsets { return UIEdgeInsets(top: 1.0, left: 9.0, bottom: 1.0, right: 9.0) diff --git a/iOS/MasterFeed/RefreshProgressView.swift b/iOS/MasterFeed/RefreshProgressView.swift index 5ecd13e1e..0e72d7738 100644 --- a/iOS/MasterFeed/RefreshProgressView.swift +++ b/iOS/MasterFeed/RefreshProgressView.swift @@ -10,7 +10,7 @@ import SwiftUI import Account -struct RefreshProgressView: View { +@MainActor struct RefreshProgressView: View { static let width: CGFloat = 100 static let height: CGFloat = 5 diff --git a/iOS/MasterTimeline/MasterTimelineUnreadCountView.swift b/iOS/MasterTimeline/MasterTimelineUnreadCountView.swift index 66a7a4b26..a89b37fd7 100644 --- a/iOS/MasterTimeline/MasterTimelineUnreadCountView.swift +++ b/iOS/MasterTimeline/MasterTimelineUnreadCountView.swift @@ -8,7 +8,7 @@ import UIKit -class MasterTimelineUnreadCountView: MasterFeedUnreadCountView { +@MainActor final class MasterTimelineUnreadCountView: MasterFeedUnreadCountView { override var padding: UIEdgeInsets { return UIEdgeInsets(top: 2.0, left: 9.0, bottom: 2.0, right: 9.0) From a28deb8b05cd6f1d1e68ab9648f7bd3dcff0d0ad Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Sat, 8 Apr 2023 10:39:20 -0700 Subject: [PATCH 14/18] Update beta appcast for 6.1.2. --- Appcasts/netnewswire-beta.xml | 187 ++++------------------------------ 1 file changed, 19 insertions(+), 168 deletions(-) diff --git a/Appcasts/netnewswire-beta.xml b/Appcasts/netnewswire-beta.xml index c4699ebef..6db0df038 100755 --- a/Appcasts/netnewswire-beta.xml +++ b/Appcasts/netnewswire-beta.xml @@ -5,8 +5,26 @@ https://ranchero.com/downloads/netnewswire-beta.xml Most recent NetNewsWire changes with links to updates. en - + + NetNewsWire 6.1.2 + Twitter integration has been removed: Twitter has suspended NetNewsWire, and Twitter is removing free access to the Twitter API

+

Since Twitter does not provide RSS feeds, we’ve had to use the Twitter API. Without free access to that API, we can’t read feeds from Twitter.

+

We’ve left your Twitter feeds intact. If you have any starred items from those feeds, they will remain as long as you don’t delete those feeds.

+

You can still read whatever you have already downloaded. However, those feeds will no longer update.

+

Other changes…

+

Fixed a crashing bug that could happen in the sidebar

+

Fixed a bug that could prevent users from accessing BazQux if an article was missing a field

+

Fixed an issue that could prevent Feedly users from syncing if they tried to mark too many articles as read at the same time

+

Updated the Safari extension icon (credit to Louie Mantia for the new icon)

+ ]]>
+ Sat, 08 Apr 2023 10:30:00 -0800 + + 10.15.0 +
+ + NetNewsWire 6.1.1b1 Fixed a bug that could prevent users from accessing BazQux if an article was missing a field

@@ -17,172 +35,5 @@ 10.15.0
- - NetNewsWire 6.1 - Article themes. Several themes ship with the app, and you can create your own. You can change the theme in Preferences or by adding the theme switcher to the toolbar

-

Copy URLs using repaired, rather than raw, feed links

-

Restore article scroll position on relaunching app

-

Added Copy Article URL and Copy External URL commands to the Edit menu

-

Fixed a bug where using cmd-Q wouldn’t always quit the app as quickly as one might prefer

-

Disallow creation of iCloud account in the app if iCloud and iCloud Drive aren’t both enabled

-

Fixed bug showing quote tweets that only included an image

-

Added a hidden pref to suppress downloading/syncing on start: `defaults write com.ranchero.NetNewsWire-Evergreen DevroeSuppressSyncOnLaunch -bool true`

-

Video autoplay is now disallowed

-

Article view now supports RTL layout

-

Fixed a few font and sizing issues

-

Updated built-in feeds

-

Better alignment for items in General Preferences pane

- ]]>
- Thu, 07 Apr 2022 10:05:00 -0700 - - 10.15.0 -
- - - NetNewsWire 6.1b5 - Updated built-in feeds

-

Building on a new Apple Silicon Mac — testing to make sure all’s well

- ]]>
- Mon, 04 Apr 2022 22:10:00 -0700 - - 10.15.0 -
- - - NetNewsWire 6.1b4 - Fixed a few font and sizing issues.

- ]]>
- Sun, 27 Feb 2022 21:50:00 -0800 - - 10.15.0 -
- - - NetNewsWire 6.1b3 - Two new themes: Hyperlegible and NewsFax

-

Change in how built-in themes work: they’re part of the app bundle and they’re not copied into the Themes folder. When a built-in theme changes in a new app release, anyone using that new version gets the changes to the built-in theme

- ]]>
- Thu, 10 Feb 2022 21:35:00 -0800 - - 10.15.0 -
- - - NetNewsWire 6.1b2 - Article themes. Several themes ship with the app, and you can create your own. You can change the theme in Preferences or by adding the theme switcher to the toolbar.

-

Copy URLs using repaired, rather than raw, feed links.

-

Restore article scroll position on relaunching app.

-

Added Copy Article URL and Copy External URL commands to the Edit menu.

-

Fixed a bug where using cmd-Q wouldn’t always quit the app as quickly as one might prefer.

-

Disallow creation of iCloud account in the app if iCloud and iCloud Drive aren’t both enabled.

-

Fixed bug showing quote tweets that only included an image.

-

Added a hidden pref to suppress downloading/syncing on start: `defaults write com.ranchero.NetNewsWire-Evergreen DevroeSuppressSyncOnLaunch -bool true`

-

Video autoplay is now disallowed.

-

Article view now supports RTL layout.

- ]]>
- Mon, 17 Jan 2022 17:45:00 -0800 - - 10.15.0 -
- - - - NetNewsWire 6.0.3 - Same as 6.0.3b2 except for the version number.

- ]]>
- Sun, 05 Sep 2021 12:20:00 -0700 - - 10.15.0 -
- - - - NetNewsWire 6.0.3b2 - Feedly: preserve custom feed names with Feedly when moving them between folders

-

Preferences: use full-width row style in accounts and extensions panes

-

Fixed a crashing bug triggered by running some UI code outside of main thread

-

Fixed a crashing bug that could happen when the app tries to find a feed for a website

-

Fixed a crashing bug that could happen when rendering tweets

-

Changed how images are placed in Twitter articles so that you can better see who Tweeted the image

-

Fixed bug where iCloud syncing could stop prematurely when the sync database has records not in the local database

-

Fixed bug where favicons wouldn’t be found when a home page URL has non-ASCII characters

-

Fixed bug where external URLs in Feedbin feeds might be lost

-

Fixed bug where words prepended with $ wouldn’t appear in Twitter feeds

-

Fixed bug where newlines would be just a space in Twitter feeds

-

Fixed bug where BazQux-synced feeds might stop updating

- ]]>
- Sun, 29 Aug 2021 15:25:00 -0700 - - 10.15.0 -
- - - NetNewsWire 6.0.3b1 - Feedly: handle API change with deleting and don’t show a spurious error

-

NewsBlur: don’t fetch articles marked hidden by NewsBlur

-

FreshRSS: add API endpoint URL example in setup form

-

iCloud: fixed bug not retaining feeds in a folder where the folder hasn’t been synced yet

-

Feeds list: smart feeds remain visible despite Hide Read Feeds setting

-

Keyboard shortcuts: fixed regression where L key wouldn’t go to next unread when feed is all read

-

Twitter extension: fixed weird bug where an extra https:/ could appear in tweet text

- ]]>
- Thu, 20 May 2021 20:00:00 -0700 - - 10.15.0 -
- - - NetNewsWire 6.0.2 - Same as 6.0.2b1 — no changes other than version

- ]]>
- Tue, 20 Apr 2021 17:40:00 -0700 - - 10.15.0 -
- - - NetNewsWire 6.0.2b1 - Inoreader sync: fixed (hopefully) cause of rate limit errors — now doing background sync of statuses much less often - note that this fix needs to be rolled out across all NetNewsWire users in order for it to have full effect

-

Fixed regression with the L key — now works properly again

- ]]>
- Thu, 15 Apr 2021 19:15:00 -0700 - - 10.15.0 -
- - - NetNewsWire 6.0.1 - Adjusted layout of the add account sheet so that it fits on smaller monitors

-

Sidebar: properly scale the smart feed icons when sidebar is set to large size in System Preferences

- ]]>
- Thu, 01 Apr 2021 20:22:00 -0700 - - 10.15.0 -
- - - NetNewsWire 6.0.1b2 - Twitter: fixed a date parsing bug that could affect people in some locales, which would prevent Twitter feeds from working for them

-

Feeds list: fixed bug where newly added feed would be called Untitled past the time when the app actually knows its name

-

Fixed bug where next-unread command wouldn’t wrap around when you got to the bottom of the Feeds list

- ]]>
- Mon, 29 Mar 2021 20:55:00 -0700 - - 10.15.0 -
- - From a0d4894e641b88ceed9caf4c0e4741a34dd0ee3c Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Sat, 8 Apr 2023 10:41:04 -0700 Subject: [PATCH 15/18] Update release appcast for 6.1.2. --- Appcasts/netnewswire-release.xml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Appcasts/netnewswire-release.xml b/Appcasts/netnewswire-release.xml index 7c9cc240e..5475e3878 100755 --- a/Appcasts/netnewswire-release.xml +++ b/Appcasts/netnewswire-release.xml @@ -6,6 +6,24 @@ Most recent NetNewsWire releases (not test builds). en + + NetNewsWire 6.1.2 + Twitter integration has been removed: Twitter has suspended NetNewsWire, and Twitter is removing free access to the Twitter API

+

Since Twitter does not provide RSS feeds, we’ve had to use the Twitter API. Without free access to that API, we can’t read feeds from Twitter.

+

We’ve left your Twitter feeds intact. If you have any starred items from those feeds, they will remain as long as you don’t delete those feeds.

+

You can still read whatever you have already downloaded. However, those feeds will no longer update.

+

Other changes…

+

Fixed a crashing bug that could happen in the sidebar

+

Fixed a bug that could prevent users from accessing BazQux if an article was missing a field

+

Fixed an issue that could prevent Feedly users from syncing if they tried to mark too many articles as read at the same time

+

Updated the Safari extension icon (credit to Louie Mantia for the new icon)

+ ]]>
+ Sat, 08 Apr 2023 10:30:00 -0800 + + 10.15.0 +
+ NetNewsWire 6.1 Date: Sat, 8 Apr 2023 15:16:01 -0700 Subject: [PATCH 16/18] Continue adopting @MainActor. --- .../Cell/MasterTimelineAccessibilityCellLayout.swift | 2 +- iOS/MasterTimeline/MarkAsReadAlertController.swift | 2 +- iOS/MasterTimeline/MasterTimelineDataSource.swift | 2 +- iOS/MasterTimeline/MasterTimelineTitleView.swift | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/iOS/MasterTimeline/Cell/MasterTimelineAccessibilityCellLayout.swift b/iOS/MasterTimeline/Cell/MasterTimelineAccessibilityCellLayout.swift index 7441e5ae8..6c5390ec3 100644 --- a/iOS/MasterTimeline/Cell/MasterTimelineAccessibilityCellLayout.swift +++ b/iOS/MasterTimeline/Cell/MasterTimelineAccessibilityCellLayout.swift @@ -9,7 +9,7 @@ import UIKit import RSCore -struct MasterTimelineAccessibilityCellLayout: MasterTimelineCellLayout { +@MainActor struct MasterTimelineAccessibilityCellLayout: MasterTimelineCellLayout { let height: CGFloat let unreadIndicatorRect: CGRect diff --git a/iOS/MasterTimeline/MarkAsReadAlertController.swift b/iOS/MasterTimeline/MarkAsReadAlertController.swift index 5bbce1406..a0fb3a27a 100644 --- a/iOS/MasterTimeline/MarkAsReadAlertController.swift +++ b/iOS/MasterTimeline/MarkAsReadAlertController.swift @@ -15,7 +15,7 @@ extension UIView: MarkAsReadAlertControllerSourceType {} extension UIBarButtonItem: MarkAsReadAlertControllerSourceType {} -struct MarkAsReadAlertController { +@MainActor struct MarkAsReadAlertController { static func confirm(_ controller: UIViewController?, coordinator: SceneCoordinator?, diff --git a/iOS/MasterTimeline/MasterTimelineDataSource.swift b/iOS/MasterTimeline/MasterTimelineDataSource.swift index 3647a93ae..156b04f28 100644 --- a/iOS/MasterTimeline/MasterTimelineDataSource.swift +++ b/iOS/MasterTimeline/MasterTimelineDataSource.swift @@ -8,7 +8,7 @@ import UIKit -class MasterTimelineDataSource: UITableViewDiffableDataSource where SectionIdentifierType : Hashable, ItemIdentifierType : Hashable { +@MainActor final class MasterTimelineDataSource: UITableViewDiffableDataSource where SectionIdentifierType : Hashable, ItemIdentifierType : Hashable { override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { return true diff --git a/iOS/MasterTimeline/MasterTimelineTitleView.swift b/iOS/MasterTimeline/MasterTimelineTitleView.swift index ae1c31423..4b3c4f52e 100644 --- a/iOS/MasterTimeline/MasterTimelineTitleView.swift +++ b/iOS/MasterTimeline/MasterTimelineTitleView.swift @@ -8,7 +8,7 @@ import UIKit -class MasterTimelineTitleView: UIView { +@MainActor final class MasterTimelineTitleView: UIView { @IBOutlet weak var iconView: IconView! @IBOutlet weak var label: UILabel! From d06632da0bd54a4f57fcb94631a8b3d4ce7445a2 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Sat, 8 Apr 2023 15:42:52 -0700 Subject: [PATCH 17/18] Continue adopting MainActor. --- iOS/MasterFeed/Cell/MasterFeedTableViewSectionHeader.swift | 2 +- iOS/MasterTimeline/Cell/MasterTimelineCellData.swift | 2 +- iOS/MasterTimeline/Cell/MasterTimelineCellLayout.swift | 2 +- iOS/MasterTimeline/Cell/MasterTimelineDefaultCellLayout.swift | 2 +- iOS/MasterTimeline/Cell/MasterTimelineTableViewCell.swift | 2 +- iOS/MasterTimeline/Cell/MasterUnreadIndicatorView.swift | 2 +- iOS/MasterTimeline/Cell/MultilineUILabelSizer.swift | 2 +- iOS/MasterTimeline/Cell/SingleLineUILabelSizer.swift | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/iOS/MasterFeed/Cell/MasterFeedTableViewSectionHeader.swift b/iOS/MasterFeed/Cell/MasterFeedTableViewSectionHeader.swift index 9451a3539..9bfe0e3e4 100644 --- a/iOS/MasterFeed/Cell/MasterFeedTableViewSectionHeader.swift +++ b/iOS/MasterFeed/Cell/MasterFeedTableViewSectionHeader.swift @@ -12,7 +12,7 @@ protocol MasterFeedTableViewSectionHeaderDelegate { func masterFeedTableViewSectionHeaderDisclosureDidToggle(_ sender: MasterFeedTableViewSectionHeader) } -class MasterFeedTableViewSectionHeader: UITableViewHeaderFooterView { +@MainActor class MasterFeedTableViewSectionHeader: UITableViewHeaderFooterView { var delegate: MasterFeedTableViewSectionHeaderDelegate? diff --git a/iOS/MasterTimeline/Cell/MasterTimelineCellData.swift b/iOS/MasterTimeline/Cell/MasterTimelineCellData.swift index fa06cdadc..c016d0523 100644 --- a/iOS/MasterTimeline/Cell/MasterTimelineCellData.swift +++ b/iOS/MasterTimeline/Cell/MasterTimelineCellData.swift @@ -9,7 +9,7 @@ import UIKit import Articles -struct MasterTimelineCellData { +@MainActor struct MasterTimelineCellData { private static let noText = NSLocalizedString("(No Text)", comment: "No Text") diff --git a/iOS/MasterTimeline/Cell/MasterTimelineCellLayout.swift b/iOS/MasterTimeline/Cell/MasterTimelineCellLayout.swift index 6913a3989..44191a49d 100644 --- a/iOS/MasterTimeline/Cell/MasterTimelineCellLayout.swift +++ b/iOS/MasterTimeline/Cell/MasterTimelineCellLayout.swift @@ -21,7 +21,7 @@ protocol MasterTimelineCellLayout { } -extension MasterTimelineCellLayout { +@MainActor extension MasterTimelineCellLayout { static func rectForUnreadIndicator(_ point: CGPoint) -> CGRect { var r = CGRect.zero diff --git a/iOS/MasterTimeline/Cell/MasterTimelineDefaultCellLayout.swift b/iOS/MasterTimeline/Cell/MasterTimelineDefaultCellLayout.swift index 6b2ce58ad..85cf66048 100644 --- a/iOS/MasterTimeline/Cell/MasterTimelineDefaultCellLayout.swift +++ b/iOS/MasterTimeline/Cell/MasterTimelineDefaultCellLayout.swift @@ -9,7 +9,7 @@ import UIKit import RSCore -struct MasterTimelineDefaultCellLayout: MasterTimelineCellLayout { +@MainActor struct MasterTimelineDefaultCellLayout: MasterTimelineCellLayout { static let cellPadding = UIEdgeInsets(top: 12, left: 8, bottom: 12, right: 20) diff --git a/iOS/MasterTimeline/Cell/MasterTimelineTableViewCell.swift b/iOS/MasterTimeline/Cell/MasterTimelineTableViewCell.swift index 88c9fd782..eb628a9ed 100644 --- a/iOS/MasterTimeline/Cell/MasterTimelineTableViewCell.swift +++ b/iOS/MasterTimeline/Cell/MasterTimelineTableViewCell.swift @@ -9,7 +9,7 @@ import UIKit import RSCore -class MasterTimelineTableViewCell: VibrantTableViewCell { +@MainActor class MasterTimelineTableViewCell: VibrantTableViewCell { private let titleView = MasterTimelineTableViewCell.multiLineUILabel() private let summaryView = MasterTimelineTableViewCell.multiLineUILabel() diff --git a/iOS/MasterTimeline/Cell/MasterUnreadIndicatorView.swift b/iOS/MasterTimeline/Cell/MasterUnreadIndicatorView.swift index 32205f0f9..748bdb5cd 100644 --- a/iOS/MasterTimeline/Cell/MasterUnreadIndicatorView.swift +++ b/iOS/MasterTimeline/Cell/MasterUnreadIndicatorView.swift @@ -8,7 +8,7 @@ import UIKit -class MasterUnreadIndicatorView: UIView { +@MainActor class MasterUnreadIndicatorView: UIView { override func layoutSubviews() { super.layoutSubviews() diff --git a/iOS/MasterTimeline/Cell/MultilineUILabelSizer.swift b/iOS/MasterTimeline/Cell/MultilineUILabelSizer.swift index c5859ba42..4764629ff 100644 --- a/iOS/MasterTimeline/Cell/MultilineUILabelSizer.swift +++ b/iOS/MasterTimeline/Cell/MultilineUILabelSizer.swift @@ -26,7 +26,7 @@ struct TextFieldSizeInfo { let numberOfLinesUsed: Int // A two-line text field may only use one line, for instance. This would equal 1, then. } -final class MultilineUILabelSizer { +@MainActor final class MultilineUILabelSizer { private let numberOfLines: Int private let font: UIFont diff --git a/iOS/MasterTimeline/Cell/SingleLineUILabelSizer.swift b/iOS/MasterTimeline/Cell/SingleLineUILabelSizer.swift index 901df9a77..0af756044 100644 --- a/iOS/MasterTimeline/Cell/SingleLineUILabelSizer.swift +++ b/iOS/MasterTimeline/Cell/SingleLineUILabelSizer.swift @@ -12,7 +12,7 @@ import UIKit // Uses a cache. // Main thready only. -final class SingleLineUILabelSizer { +@MainActor final class SingleLineUILabelSizer { let font: UIFont private var cache = [String: CGSize]() From f4e71b41a1d5385c527604429625ad062f5e21bd Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Sat, 8 Apr 2023 15:45:32 -0700 Subject: [PATCH 18/18] Continue adopting MainActor. --- iOS/Article/ArticleExtractorButton.swift | 2 +- iOS/Article/ContextMenuPreviewViewController.swift | 2 +- iOS/Article/ImageTransition.swift | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/iOS/Article/ArticleExtractorButton.swift b/iOS/Article/ArticleExtractorButton.swift index cc1087888..517c7ec00 100644 --- a/iOS/Article/ArticleExtractorButton.swift +++ b/iOS/Article/ArticleExtractorButton.swift @@ -15,7 +15,7 @@ enum ArticleExtractorButtonState { case off } -class ArticleExtractorButton: UIButton { +@MainActor class ArticleExtractorButton: UIButton { private var animatedLayer: CALayer? diff --git a/iOS/Article/ContextMenuPreviewViewController.swift b/iOS/Article/ContextMenuPreviewViewController.swift index 3b7e18219..2d6e3e961 100644 --- a/iOS/Article/ContextMenuPreviewViewController.swift +++ b/iOS/Article/ContextMenuPreviewViewController.swift @@ -9,7 +9,7 @@ import UIKit import Articles -class ContextMenuPreviewViewController: UIViewController { +@MainActor class ContextMenuPreviewViewController: UIViewController { @IBOutlet weak var blogNameLabel: UILabel! @IBOutlet weak var blogAuthorLabel: UILabel! diff --git a/iOS/Article/ImageTransition.swift b/iOS/Article/ImageTransition.swift index 25951b301..dc4a66d6d 100644 --- a/iOS/Article/ImageTransition.swift +++ b/iOS/Article/ImageTransition.swift @@ -8,7 +8,7 @@ import UIKit -class ImageTransition: NSObject, UIViewControllerAnimatedTransitioning { +@MainActor final class ImageTransition: NSObject, UIViewControllerAnimatedTransitioning { private weak var webViewController: WebViewController? private let duration = 0.4