mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
Merge branch 'main' into ios-ui-settings-localised
This commit is contained in:
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -527,16 +527,16 @@
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="7UM-iq-OLB" customClass="PreferencesTableViewBackgroundView" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="44" width="180" height="219"/>
|
||||
<rect key="frame" x="20" y="44" width="180" height="217"/>
|
||||
<subviews>
|
||||
<scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="26" horizontalPageScroll="10" verticalLineScroll="26" verticalPageScroll="10" hasHorizontalScroller="NO" horizontalScrollElasticity="none" translatesAutoresizingMaskIntoConstraints="NO" id="PaF-du-r3c">
|
||||
<rect key="frame" x="1" y="1" width="178" height="217"/>
|
||||
<rect key="frame" x="1" y="1" width="178" height="215"/>
|
||||
<clipView key="contentView" id="cil-Gq-akO">
|
||||
<rect key="frame" x="0.0" y="0.0" width="178" height="217"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="178" height="215"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" tableStyle="fullWidth" columnReordering="NO" columnSelection="YES" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" rowHeight="24" viewBased="YES" id="aTp-KR-y6b">
|
||||
<rect key="frame" x="0.0" y="0.0" width="178" height="217"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="178" height="215"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<size key="intercellSpacing" width="3" height="2"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
@@ -643,7 +643,7 @@
|
||||
<rect key="frame" x="83" y="20" width="117" height="24"/>
|
||||
</customView>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="Y7D-xQ-wep">
|
||||
<rect key="frame" x="208" y="20" width="222" height="243"/>
|
||||
<rect key="frame" x="208" y="20" width="222" height="241"/>
|
||||
</customView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
@@ -698,16 +698,16 @@
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="pjs-G4-byk" customClass="PreferencesTableViewBackgroundView" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="44" width="180" height="219"/>
|
||||
<rect key="frame" x="20" y="44" width="180" height="217"/>
|
||||
<subviews>
|
||||
<scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="26" horizontalPageScroll="10" verticalLineScroll="26" verticalPageScroll="10" hasHorizontalScroller="NO" horizontalScrollElasticity="none" translatesAutoresizingMaskIntoConstraints="NO" id="29T-r2-ckC">
|
||||
<rect key="frame" x="1" y="1" width="178" height="217"/>
|
||||
<rect key="frame" x="1" y="1" width="178" height="215"/>
|
||||
<clipView key="contentView" id="dXw-GY-TP8">
|
||||
<rect key="frame" x="0.0" y="0.0" width="178" height="217"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="178" height="215"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" tableStyle="fullWidth" columnReordering="NO" columnSelection="YES" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" rowHeight="24" viewBased="YES" id="dfn-Vn-oDp">
|
||||
<rect key="frame" x="0.0" y="0.0" width="178" height="217"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="178" height="215"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<size key="intercellSpacing" width="3" height="2"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
@@ -810,7 +810,7 @@
|
||||
<rect key="frame" x="83" y="20" width="117" height="24"/>
|
||||
</customView>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="N1N-pE-gBL">
|
||||
<rect key="frame" x="208" y="20" width="222" height="243"/>
|
||||
<rect key="frame" x="208" y="20" width="222" height="241"/>
|
||||
</customView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import Foundation
|
||||
import RSWeb
|
||||
|
||||
struct Browser {
|
||||
@MainActor struct Browser {
|
||||
|
||||
/// The user-specified default browser for opening web pages.
|
||||
///
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import AppKit
|
||||
|
||||
final class CrashReportWindowController: NSWindowController {
|
||||
@MainActor final class CrashReportWindowController: NSWindowController {
|
||||
|
||||
@IBOutlet var textView: NSTextView! {
|
||||
didSet {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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?
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -15,7 +15,7 @@ enum ArticleExtractorButtonState {
|
||||
case off
|
||||
}
|
||||
|
||||
class ArticleExtractorButton: NSButton {
|
||||
@MainActor final class ArticleExtractorButton: NSButton {
|
||||
|
||||
public var rightClickAction: Selector?
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import Foundation
|
||||
import WebKit
|
||||
import Articles
|
||||
|
||||
class DetailIconSchemeHandler: NSObject, WKURLSchemeHandler {
|
||||
final class DetailIconSchemeHandler: NSObject, WKURLSchemeHandler {
|
||||
|
||||
var currentArticle: Article?
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import AppKit
|
||||
import Articles
|
||||
|
||||
final class DetailStatusBarView: NSView {
|
||||
@MainActor final class DetailStatusBarView: NSView {
|
||||
|
||||
@IBOutlet var urlLabel: NSTextField!
|
||||
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -10,7 +10,7 @@ import AppKit
|
||||
import WebKit
|
||||
import RSCore
|
||||
|
||||
final class DetailWebView: WKWebView {
|
||||
@MainActor final class DetailWebView: WKWebView {
|
||||
|
||||
weak var keyboardDelegate: KeyboardDelegate?
|
||||
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
class MainWindow: NSWindow {
|
||||
@MainActor class MainWindow: NSWindow {
|
||||
|
||||
override func sendEvent(_ event: NSEvent) {
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ enum TimelineSourceMode {
|
||||
case regular, search
|
||||
}
|
||||
|
||||
class MainWindowController : NSWindowController, NSUserInterfaceValidations {
|
||||
@MainActor final class MainWindowController : NSWindowController, NSUserInterfaceValidations {
|
||||
|
||||
@IBOutlet weak var articleThemePopUpButton: NSPopUpButton?
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import AppKit
|
||||
import Account
|
||||
|
||||
final class NNW3OpenPanelAccessoryViewController: NSViewController {
|
||||
@MainActor final class NNW3OpenPanelAccessoryViewController: NSViewController {
|
||||
|
||||
@IBOutlet weak var accountPopUpButton: NSPopUpButton!
|
||||
|
||||
|
||||
@@ -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?
|
||||
|
||||
@@ -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?
|
||||
|
||||
@@ -11,7 +11,7 @@ import RSCore
|
||||
import Account
|
||||
import RSTree
|
||||
|
||||
class SidebarCell : NSTableCellView {
|
||||
@MainActor final class SidebarCell : NSTableCellView {
|
||||
|
||||
var iconImage: IconImage? {
|
||||
didSet {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import AppKit
|
||||
|
||||
struct SidebarCellAppearance: Equatable {
|
||||
@MainActor struct SidebarCellAppearance: Equatable {
|
||||
|
||||
let imageSize: CGSize
|
||||
let imageMarginRight: CGFloat = 4.0
|
||||
|
||||
@@ -11,7 +11,7 @@ import RSCore
|
||||
|
||||
// image - title - unreadCount
|
||||
|
||||
struct SidebarCellLayout {
|
||||
@MainActor struct SidebarCellLayout {
|
||||
|
||||
let faviconRect: CGRect
|
||||
let titleRect: CGRect
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import AppKit
|
||||
import RSCore
|
||||
import RSTree
|
||||
|
||||
class SidebarOutlineView : NSOutlineView {
|
||||
@MainActor class SidebarOutlineView : NSOutlineView {
|
||||
|
||||
@IBOutlet var keyboardDelegate: KeyboardDelegate!
|
||||
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import AppKit
|
||||
|
||||
final class TimelineContainerView: NSView {
|
||||
@MainActor final class TimelineContainerView: NSView {
|
||||
|
||||
private var contentViewConstraints: [NSLayoutConstraint]?
|
||||
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import AppKit
|
||||
|
||||
class TimelineTableRowView : NSTableRowView {
|
||||
@MainActor final class TimelineTableRowView : NSTableRowView {
|
||||
|
||||
private var separator: NSView?
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import AppKit
|
||||
import RSCore
|
||||
|
||||
class TimelineTableView: NSTableView {
|
||||
@MainActor final class TimelineTableView: NSTableView {
|
||||
|
||||
weak var keyboardDelegate: KeyboardDelegate?
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import AppKit
|
||||
|
||||
class AccountCell: NSTableCellView {
|
||||
@MainActor class AccountCell: NSTableCellView {
|
||||
|
||||
private var originalImage: NSImage?
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ enum AccountsAddCloudKitWindowControllerError: LocalizedError {
|
||||
}
|
||||
}
|
||||
|
||||
class AccountsAddCloudKitWindowController: NSWindowController {
|
||||
@MainActor class AccountsAddCloudKitWindowController: NSWindowController {
|
||||
|
||||
@IBOutlet weak var limitationsAndSolutionsTextField: NSTextField!
|
||||
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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?) {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import Cocoa
|
||||
|
||||
class ExtensionPointDetailViewController: NSViewController {
|
||||
@MainActor class ExtensionPointDetailViewController: NSViewController {
|
||||
|
||||
@IBOutlet weak var imageView: NSImageView!
|
||||
@IBOutlet weak var titleLabel: NSTextField!
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -11,7 +11,7 @@ import RSCore
|
||||
import RSWeb
|
||||
import UserNotifications
|
||||
|
||||
final class GeneralPreferencesViewController: NSViewController {
|
||||
@MainActor final class GeneralPreferencesViewController: NSViewController {
|
||||
|
||||
private var userNotificationSettings: UNNotificationSettings?
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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]()
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
<key>NSAppleScriptEnabled</key>
|
||||
<true/>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2002-2022 Brent Simmons. All rights reserved.</string>
|
||||
<string>Copyright © 2002-2023 Brent Simmons. All rights reserved.</string>
|
||||
<key>NSMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -88,7 +88,9 @@ final class ArticleThemesManager: NSObject, NSFilePresenter, Logging, Observable
|
||||
do {
|
||||
currentTheme = try articleThemeWithThemeName(currentThemeName)
|
||||
} catch {
|
||||
appDelegate.presentThemeImportError(error)
|
||||
Task { @MainActor in
|
||||
appDelegate.presentThemeImportError(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import Foundation
|
||||
import Account
|
||||
import RSCore
|
||||
|
||||
struct OPMLExporter {
|
||||
@MainActor struct OPMLExporter {
|
||||
|
||||
static func OPMLString(with account: Account, title: String) -> String {
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import Foundation
|
||||
import RSWeb
|
||||
import RSCore
|
||||
|
||||
struct CacheCleaner: Logging {
|
||||
@MainActor struct CacheCleaner: Logging {
|
||||
|
||||
static func purgeIfNecessary() {
|
||||
|
||||
|
||||
@@ -5,12 +5,17 @@
|
||||
</head>
|
||||
<body>
|
||||
<outline text="BBC News - World" title="BBC News - World" type="rss" version="RSS" htmlUrl="https://www.bbc.com/news" xmlUrl="https://feeds.bbci.co.uk/news/world/rss.xml"/>
|
||||
<outline text="Allen Pike" title="Allen Pike" type="rss" version="RSS" htmlUrl="https://www.allenpike.com/" xmlUrl="https://feeds.allenpike.com/feed/"/>
|
||||
<outline text="Becky Hansmeyer" title="Becky Hansmeyer" type="rss" version="RSS" htmlUrl="https://beckyhansmeyer.com" xmlUrl="https://beckyhansmeyer.com/feed/"/>
|
||||
<outline text="Colossal" title="Colossal" type="rss" version="RSS" htmlUrl="https://www.thisiscolossal.com/" xmlUrl="https://www.thisiscolossal.com/feed/"/>
|
||||
<outline text="Craig Hockenberry" title="Craig Hockenberry" type="rss" version="RSS" htmlUrl="https://furbo.org/" xmlUrl="https://furbo.org/feed/json"/>
|
||||
<outline text="Daring Fireball" title="Daring Fireball" type="rss" version="RSS" htmlUrl="https://daringfireball.net/" xmlUrl="https://daringfireball.net/feeds/json"/>
|
||||
<outline text="inessential" title="inessential" type="rss" version="RSS" htmlUrl="https://inessential.com/" xmlUrl="https://inessential.com/feed.json"/>
|
||||
<outline text="Jason Kottke" title="Jason Kottke" type="rss" version="RSS" htmlUrl="https://kottke.org/" xmlUrl="http://feeds.kottke.org/json"/>
|
||||
<outline text="Julia Evans" title="Julia Evans" type="rss" version="RSS" htmlUrl="https://jvns.ca/" xmlUrl="https://jvns.ca/atom.xml"/>
|
||||
<outline text="Manton Reece" title="Manton Reece" type="rss" version="RSS" htmlUrl="https://manton.org/" xmlUrl="https://www.manton.org/feed/json"/>
|
||||
<outline text="Maurice Parker" title="Maurice Parker" type="rss" version="RSS" htmlUrl="https://vincode.io/" xmlUrl="https://vincode.io/feed.xml"/>
|
||||
<outline text="Michael Tsai" title="Michael Tsai" type="rss" version="RSS" htmlUrl="https://mjtsai.com/blog/" xmlUrl="https://mjtsai.com/blog/feed/"/>
|
||||
<outline text="NetNewsWire Blog" title="NetNewsWire Blog" type="rss" version="RSS" htmlUrl="https://nnw.ranchero.com/" xmlUrl="https://nnw.ranchero.com/feed.json"/>
|
||||
<outline text="One Foot Tsunami" title="One Foot Tsunami" type="rss" version="RSS" htmlUrl="https://onefoottsunami.com/" xmlUrl="https://onefoottsunami.com/feed/json/"/>
|
||||
<outline text="Six Colors" title="Six Colors" type="rss" version="RSS" htmlUrl="https://sixcolors.com/" xmlUrl="https://feedpress.me/sixcolors?type=xml"/>
|
||||
|
||||
@@ -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")!
|
||||
|
||||
@@ -694,7 +694,7 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner, Ma
|
||||
|
||||
private func showTwitterDeprecationAlert() {
|
||||
let alert = UIAlertController(title: NSLocalizedString("Twitter Integration Removed", comment: "Twitter Integration Removed"),
|
||||
message: NSLocalizedString("On February 1, 2023, Twitter announced the end of free access to the Twitter API, effective February 9.\n\nSince 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.\n\nWe’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.\n\nYou can still read whatever you have already downloaded. However, those feeds will no longer update.", comment: "Twitter deprecation message"),
|
||||
message: NSLocalizedString("Twitter has ended free access to the parts of the Twitter API that we need.\n\nSince 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.\n\nWe’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.\n\nYou can still read whatever you have already downloaded. However, those feeds will no longer update.", comment: "Twitter deprecation message"),
|
||||
preferredStyle: .alert)
|
||||
|
||||
alert.addAction(UIAlertAction(title: "OK", style: .cancel))
|
||||
|
||||
@@ -34,7 +34,7 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner
|
||||
private var markAsReadOnScrollWorkItem: DispatchWorkItem?
|
||||
private var markAsReadOnScrollStart: Int?
|
||||
private var markAsReadOnScrollEnd: Int?
|
||||
private var lastVerticlePosition: CGFloat = 0
|
||||
private var lastVerticalPosition: CGFloat = 0
|
||||
|
||||
var mainControllerIdentifier = MainControllerIdentifier.masterTimeline
|
||||
|
||||
@@ -696,7 +696,7 @@ private extension MasterTimelineViewController {
|
||||
}
|
||||
|
||||
func applyChanges(animated: Bool, completion: (() -> Void)? = nil) {
|
||||
lastVerticlePosition = 0
|
||||
lastVerticalPosition = 0
|
||||
|
||||
if coordinator.articles.count == 0 {
|
||||
tableView.rowHeight = tableView.estimatedRowHeight
|
||||
@@ -753,15 +753,15 @@ private extension MasterTimelineViewController {
|
||||
func markAsReadOnScroll() {
|
||||
// Only try to mark if we are scrolling up
|
||||
defer {
|
||||
lastVerticlePosition = tableView.contentOffset.y
|
||||
lastVerticalPosition = tableView.contentOffset.y
|
||||
}
|
||||
guard lastVerticlePosition < tableView.contentOffset.y else {
|
||||
guard lastVerticalPosition < tableView.contentOffset.y else {
|
||||
return
|
||||
}
|
||||
|
||||
// Implement Mark As Read on Scroll where we mark after the leading edge goes a little beyond the safe area inset
|
||||
guard AppDefaults.shared.markArticlesAsReadOnScroll,
|
||||
lastVerticlePosition < tableView.contentOffset.y,
|
||||
lastVerticalPosition < tableView.contentOffset.y,
|
||||
let firstVisibleIndexPath = tableView.indexPathsForVisibleRows?.first else { return }
|
||||
|
||||
let firstVisibleRowRect = tableView.rectForRow(at: firstVisibleIndexPath)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
// High Level Settings common to both the iOS application and any extensions we bundle with it
|
||||
MARKETING_VERSION = 6.1.1
|
||||
CURRENT_PROJECT_VERSION = 6114
|
||||
CURRENT_PROJECT_VERSION = 6115
|
||||
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon
|
||||
|
||||
Reference in New Issue
Block a user