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/AppDelegate.swift b/Mac/AppDelegate.swift index 44dc42137..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 { @@ -386,19 +386,19 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, alert.buttons[0].keyEquivalent = "\r" - let response = alert.runModal() + _ = alert.runModal() } } // 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/Base.lproj/Preferences.storyboard b/Mac/Base.lproj/Preferences.storyboard index ec3c0ba73..ddf26b887 100644 --- a/Mac/Base.lproj/Preferences.storyboard +++ b/Mac/Base.lproj/Preferences.storyboard @@ -527,16 +527,16 @@ - + - + - + - + @@ -643,7 +643,7 @@ - + @@ -698,16 +698,16 @@ - + - + - + - + @@ -810,7 +810,7 @@ - + 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/CrashReporter/CrashReportWindowController.swift b/Mac/CrashReporter/CrashReportWindowController.swift index 7c7ce9ee7..5579e0ef3 100644 --- a/Mac/CrashReporter/CrashReportWindowController.swift +++ b/Mac/CrashReporter/CrashReportWindowController.swift @@ -8,7 +8,7 @@ import AppKit -final class CrashReportWindowController: NSWindowController { +@MainActor final class CrashReportWindowController: NSWindowController { @IBOutlet var textView: NSTextView! { didSet { diff --git a/Mac/CrashReporter/CrashReporter.swift b/Mac/CrashReporter/CrashReporter.swift index b37810a9d..09d1db06b 100644 --- a/Mac/CrashReporter/CrashReporter.swift +++ b/Mac/CrashReporter/CrashReporter.swift @@ -16,7 +16,7 @@ import CrashReporter // At some point this code should probably move into RSCore, so Rainier and any other // future apps can use it. -struct CrashReporter { +@MainActor struct CrashReporter { struct DefaultsKey { static let sendCrashLogsAutomaticallyKey = "SendCrashLogsAutomatically" 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/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? 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/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/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/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! 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/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! 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/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? 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/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/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? 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/Preferences/Accounts/AccountCell.swift b/Mac/Preferences/Accounts/AccountCell.swift index 7a1dbecef..b6fb2eef3 100644 --- a/Mac/Preferences/Accounts/AccountCell.swift +++ b/Mac/Preferences/Accounts/AccountCell.swift @@ -8,7 +8,7 @@ import AppKit -class AccountCell: NSTableCellView { +@MainActor class AccountCell: NSTableCellView { private var originalImage: NSImage? diff --git a/Mac/Preferences/Accounts/AccountsAddCloudKitWindowController.swift b/Mac/Preferences/Accounts/AccountsAddCloudKitWindowController.swift index 6c01d9ef9..945453122 100644 --- a/Mac/Preferences/Accounts/AccountsAddCloudKitWindowController.swift +++ b/Mac/Preferences/Accounts/AccountsAddCloudKitWindowController.swift @@ -17,7 +17,7 @@ enum AccountsAddCloudKitWindowControllerError: LocalizedError { } } -class AccountsAddCloudKitWindowController: NSWindowController { +@MainActor class AccountsAddCloudKitWindowController: NSWindowController { @IBOutlet weak var limitationsAndSolutionsTextField: NSTextField! diff --git a/Mac/Preferences/Accounts/AccountsAddLocalWindowController.swift b/Mac/Preferences/Accounts/AccountsAddLocalWindowController.swift index 8aedbccd7..373ffea30 100644 --- a/Mac/Preferences/Accounts/AccountsAddLocalWindowController.swift +++ b/Mac/Preferences/Accounts/AccountsAddLocalWindowController.swift @@ -9,7 +9,7 @@ import AppKit import Account -class AccountsAddLocalWindowController: NSWindowController { +@MainActor class AccountsAddLocalWindowController: NSWindowController { @IBOutlet private weak var nameTextField: NSTextField! @IBOutlet private weak var localAccountNameTextField: NSTextField! diff --git a/Mac/Preferences/Accounts/AccountsDetailViewController.swift b/Mac/Preferences/Accounts/AccountsDetailViewController.swift index 3fe5487ee..6b395249e 100644 --- a/Mac/Preferences/Accounts/AccountsDetailViewController.swift +++ b/Mac/Preferences/Accounts/AccountsDetailViewController.swift @@ -9,7 +9,7 @@ import AppKit import Account -final class AccountsDetailViewController: NSViewController, NSTextFieldDelegate { +@MainActor final class AccountsDetailViewController: NSViewController, NSTextFieldDelegate { @IBOutlet weak var typeLabel: NSTextField! @IBOutlet weak var nameTextField: NSTextField! diff --git a/Mac/Preferences/Accounts/AccountsFeedbinWindowController.swift b/Mac/Preferences/Accounts/AccountsFeedbinWindowController.swift index 6ac802851..687e0c864 100644 --- a/Mac/Preferences/Accounts/AccountsFeedbinWindowController.swift +++ b/Mac/Preferences/Accounts/AccountsFeedbinWindowController.swift @@ -12,7 +12,7 @@ import RSCore import RSWeb import Secrets -class AccountsFeedbinWindowController: NSWindowController, Logging { +@MainActor class AccountsFeedbinWindowController: NSWindowController, Logging { @IBOutlet weak var signInTextField: NSTextField! @IBOutlet weak var noAccountTextField: NSTextField! diff --git a/Mac/Preferences/Accounts/AccountsNewsBlurWindowController.swift b/Mac/Preferences/Accounts/AccountsNewsBlurWindowController.swift index 0af42818e..9cb726e17 100644 --- a/Mac/Preferences/Accounts/AccountsNewsBlurWindowController.swift +++ b/Mac/Preferences/Accounts/AccountsNewsBlurWindowController.swift @@ -12,7 +12,7 @@ import RSWeb import RSCore import Secrets -class AccountsNewsBlurWindowController: NSWindowController, Logging { +@MainActor class AccountsNewsBlurWindowController: NSWindowController, Logging { @IBOutlet weak var signInTextField: NSTextField! @IBOutlet weak var noAccountTextField: NSTextField! diff --git a/Mac/Preferences/Accounts/AccountsPreferencesViewController.swift b/Mac/Preferences/Accounts/AccountsPreferencesViewController.swift index 307f5b8b5..66a0173cb 100644 --- a/Mac/Preferences/Accounts/AccountsPreferencesViewController.swift +++ b/Mac/Preferences/Accounts/AccountsPreferencesViewController.swift @@ -17,7 +17,7 @@ protocol AccountsPreferencesAddAccountDelegate { } // MARK: - AccountsPreferencesViewController -final class AccountsPreferencesViewController: NSViewController { +@MainActor final class AccountsPreferencesViewController: NSViewController { @IBOutlet weak var tableView: NSTableView! @IBOutlet weak var detailView: NSView! diff --git a/Mac/Preferences/Accounts/AccountsReaderAPIWindowController.swift b/Mac/Preferences/Accounts/AccountsReaderAPIWindowController.swift index b127003db..e282f327e 100644 --- a/Mac/Preferences/Accounts/AccountsReaderAPIWindowController.swift +++ b/Mac/Preferences/Accounts/AccountsReaderAPIWindowController.swift @@ -12,7 +12,7 @@ import RSWeb import RSCore import Secrets -class AccountsReaderAPIWindowController: NSWindowController, Logging { +@MainActor class AccountsReaderAPIWindowController: NSWindowController, Logging { @IBOutlet weak var titleImageView: NSImageView! @IBOutlet weak var titleLabel: NSTextField! diff --git a/Mac/Preferences/Advanced/AdvancedPreferencesViewController.swift b/Mac/Preferences/Advanced/AdvancedPreferencesViewController.swift index a48e9fe91..53ccc3aee 100644 --- a/Mac/Preferences/Advanced/AdvancedPreferencesViewController.swift +++ b/Mac/Preferences/Advanced/AdvancedPreferencesViewController.swift @@ -8,11 +8,10 @@ import AppKit -final class AdvancedPreferencesViewController: NSViewController { +@MainActor final class AdvancedPreferencesViewController: NSViewController { @IBOutlet var releaseBuildsButton: NSButton! @IBOutlet var testBuildsButton: NSButton! - @IBOutlet weak var privacyPolicyTextField: NSTextField! let releaseBuildsURL = Bundle.main.infoDictionary!["SUFeedURL"]! as! String let testBuildsURL = Bundle.main.infoDictionary!["FeedURLForTestBuilds"]! as! String @@ -35,7 +34,6 @@ final class AdvancedPreferencesViewController: NSViewController { NotificationCenter.default.addObserver(self, selector: #selector(userDefaultsDidChange(_:)), name: UserDefaults.didChangeNotification, object: nil) didRegisterForNotification = true } - privacyPolicyTextField.attributedStringValue = AppAssets.privacyPolicyLink } @IBAction func updateTypeButtonClicked(_ sender: Any?) { diff --git a/Mac/Preferences/ExtensionPoints/ExtensionPointDetailViewController.swift b/Mac/Preferences/ExtensionPoints/ExtensionPointDetailViewController.swift index f94d0ae59..0a97d68ae 100644 --- a/Mac/Preferences/ExtensionPoints/ExtensionPointDetailViewController.swift +++ b/Mac/Preferences/ExtensionPoints/ExtensionPointDetailViewController.swift @@ -8,7 +8,7 @@ import Cocoa -class ExtensionPointDetailViewController: NSViewController { +@MainActor class ExtensionPointDetailViewController: NSViewController { @IBOutlet weak var imageView: NSImageView! @IBOutlet weak var titleLabel: NSTextField! diff --git a/Mac/Preferences/ExtensionPoints/ExtensionPointEnableWindowController.swift b/Mac/Preferences/ExtensionPoints/ExtensionPointEnableWindowController.swift index f8aed7ff5..1af42d40e 100644 --- a/Mac/Preferences/ExtensionPoints/ExtensionPointEnableWindowController.swift +++ b/Mac/Preferences/ExtensionPoints/ExtensionPointEnableWindowController.swift @@ -11,7 +11,7 @@ import AuthenticationServices import OAuthSwift import Secrets -class ExtensionPointEnableWindowController: NSWindowController { +@MainActor class ExtensionPointEnableWindowController: NSWindowController { @IBOutlet weak var imageView: NSImageView! @IBOutlet weak var titleLabel: NSTextField! diff --git a/Mac/Preferences/ExtensionPoints/ExtensionPointPreferencesViewController.swift b/Mac/Preferences/ExtensionPoints/ExtensionPointPreferencesViewController.swift index d79525d30..16a797a80 100644 --- a/Mac/Preferences/ExtensionPoints/ExtensionPointPreferencesViewController.swift +++ b/Mac/Preferences/ExtensionPoints/ExtensionPointPreferencesViewController.swift @@ -16,7 +16,7 @@ protocol ExtensionPointPreferencesEnabler: AnyObject { func enable(_ extensionPointType: ExtensionPoint.Type) } -final class ExtensionPointPreferencesViewController: NSViewController { +@MainActor final class ExtensionPointPreferencesViewController: NSViewController { @IBOutlet weak var tableView: NSTableView! @IBOutlet weak var detailView: NSView! diff --git a/Mac/Preferences/General/GeneralPrefencesViewController.swift b/Mac/Preferences/General/GeneralPrefencesViewController.swift index 19fa9b7a0..0b55a756d 100644 --- a/Mac/Preferences/General/GeneralPrefencesViewController.swift +++ b/Mac/Preferences/General/GeneralPrefencesViewController.swift @@ -11,7 +11,7 @@ import RSCore import RSWeb import UserNotifications -final class GeneralPreferencesViewController: NSViewController { +@MainActor final class GeneralPreferencesViewController: NSViewController { private var userNotificationSettings: UNNotificationSettings? diff --git a/Mac/Preferences/PreferencesControlsBackgroundView.swift b/Mac/Preferences/PreferencesControlsBackgroundView.swift index 36353dd6b..307109c50 100644 --- a/Mac/Preferences/PreferencesControlsBackgroundView.swift +++ b/Mac/Preferences/PreferencesControlsBackgroundView.swift @@ -9,7 +9,7 @@ import AppKit import RSCore -final class PreferencesControlsBackgroundView: NSView { +@MainActor final class PreferencesControlsBackgroundView: NSView { private let lightModeFillColor = NSColor(white: 0.97, alpha: 1.0) private let darkModeFillColor = NSColor(red: 0.32, green: 0.34, blue: 0.35, alpha: 1.0) diff --git a/Mac/Preferences/PreferencesTableViewBackgroundView.swift b/Mac/Preferences/PreferencesTableViewBackgroundView.swift index 34548e429..df9fce2db 100644 --- a/Mac/Preferences/PreferencesTableViewBackgroundView.swift +++ b/Mac/Preferences/PreferencesTableViewBackgroundView.swift @@ -8,7 +8,7 @@ import AppKit -final class PreferencesTableViewBackgroundView: NSView { +@MainActor final class PreferencesTableViewBackgroundView: NSView { let lightBorderColor = NSColor(white: 0.71, alpha: 1.0) let darkBorderColor = NSColor(red: 0.41, green: 0.43, blue: 0.44, alpha: 1.0) diff --git a/Mac/Preferences/PreferencesWindowController.swift b/Mac/Preferences/PreferencesWindowController.swift index 738aa5d81..f4d7b898f 100644 --- a/Mac/Preferences/PreferencesWindowController.swift +++ b/Mac/Preferences/PreferencesWindowController.swift @@ -28,7 +28,7 @@ private struct ToolbarItemIdentifier { static let Advanced = "Advanced" } -class PreferencesWindowController : NSWindowController, NSToolbarDelegate { +@MainActor class PreferencesWindowController : NSWindowController, NSToolbarDelegate { private let windowWidth = CGFloat(512.0) // Width is constant for all views; only the height changes private var viewControllers = [String: NSViewController]() diff --git a/Mac/Scriptability/AppDelegate+Scriptability.swift b/Mac/Scriptability/AppDelegate+Scriptability.swift index 07f3057c2..a16334eaf 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 @@ -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() diff --git a/Shared/Article Extractor/ArticleExtractor.swift b/Shared/Article Extractor/ArticleExtractor.swift index 1fd4d151b..1b6cdd4f3 100644 --- a/Shared/Article Extractor/ArticleExtractor.swift +++ b/Shared/Article Extractor/ArticleExtractor.swift @@ -40,10 +40,10 @@ class ArticleExtractor: Logging { let clientURL = "https://extract.feedbin.com/parser" let username = SecretsManager.provider.mercuryClientId - let signiture = articleLink.hmacUsingSHA1(key: SecretsManager.provider.mercuryClientSecret) + let signature = articleLink.hmacUsingSHA1(key: SecretsManager.provider.mercuryClientSecret) if let base64URL = articleLink.data(using: .utf8)?.base64EncodedString() { - let fullURL = "\(clientURL)/\(username)/\(signiture)?base64_url=\(base64URL)" + let fullURL = "\(clientURL)/\(username)/\(signature)?base64_url=\(base64URL)" if let url = URL(string: fullURL) { self.url = url return diff --git a/Shared/ArticleStyles/ArticleThemesManager.swift b/Shared/ArticleStyles/ArticleThemesManager.swift index 2ac447450..4c872195f 100644 --- a/Shared/ArticleStyles/ArticleThemesManager.swift +++ b/Shared/ArticleStyles/ArticleThemesManager.swift @@ -90,7 +90,9 @@ final class ArticleThemesManager: NSObject, NSFilePresenter, Logging { do { currentTheme = try articleThemeWithThemeName(currentThemeName) } catch { - appDelegate.presentThemeImportError(error) + Task { @MainActor in + appDelegate.presentThemeImportError(error) + } } } diff --git a/Shared/Exporters/OPMLExporter.swift b/Shared/Exporters/OPMLExporter.swift index cba135a17..46d232e11 100644 --- a/Shared/Exporters/OPMLExporter.swift +++ b/Shared/Exporters/OPMLExporter.swift @@ -10,7 +10,7 @@ import Foundation import Account import RSCore -struct OPMLExporter { +@MainActor struct OPMLExporter { static func OPMLString(with account: Account, title: String) -> String { diff --git a/Shared/Extensions/CacheCleaner.swift b/Shared/Extensions/CacheCleaner.swift index b80896c5d..14046d523 100644 --- a/Shared/Extensions/CacheCleaner.swift +++ b/Shared/Extensions/CacheCleaner.swift @@ -10,7 +10,7 @@ import Foundation import RSWeb import RSCore -struct CacheCleaner: Logging { +@MainActor struct CacheCleaner: Logging { static func purgeIfNecessary() { diff --git a/Shared/Importers/DefaultFeeds.opml b/Shared/Importers/DefaultFeeds.opml index 04132dbaa..ecac3d91e 100644 --- a/Shared/Importers/DefaultFeeds.opml +++ b/Shared/Importers/DefaultFeeds.opml @@ -5,12 +5,17 @@ + + + + + diff --git a/Shared/Importers/DefaultFeedsImporter.swift b/Shared/Importers/DefaultFeedsImporter.swift index 8ed67d3b9..d02b2cec3 100644 --- a/Shared/Importers/DefaultFeedsImporter.swift +++ b/Shared/Importers/DefaultFeedsImporter.swift @@ -10,7 +10,7 @@ import Foundation import Account import RSCore -struct DefaultFeedsImporter { +@MainActor struct DefaultFeedsImporter { static func importDefaultFeeds(account: Account) { let defaultFeedsURL = Bundle.main.url(forResource: "DefaultFeeds", withExtension: "opml")! 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/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] { 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) 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..81947ebac 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! @@ -195,7 +195,9 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate, Logging { do { try ArticleThemeDownloader.shared.handleFile(at: location) } catch { - self.presentError(error) + Task { @MainActor in + self.presentError(error) + } } } task.resume() 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) } } 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: