mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
Merge branch 'main' into super-cut
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,26 @@
|
||||
<link>https://ranchero.com/downloads/netnewswire-beta.xml</link>
|
||||
<description>Most recent NetNewsWire changes with links to updates.</description>
|
||||
<language>en</language>
|
||||
|
||||
|
||||
<item>
|
||||
<title>NetNewsWire 6.1.2</title>
|
||||
<description><![CDATA[
|
||||
<p><b>Twitter integration has been removed:</b> Twitter has suspended NetNewsWire, and Twitter is removing free access to the Twitter API</p>
|
||||
<p>Since Twitter does not provide RSS feeds, we’ve had to use the Twitter API. Without free access to that API, we can’t read feeds from Twitter.</p>
|
||||
<p>We’ve left your Twitter feeds intact. If you have any starred items from those feeds, they will remain as long as you don’t delete those feeds.</p>
|
||||
<p>You can still read whatever you have already downloaded. However, those feeds will no longer update.</p>
|
||||
<p>Other changes…</p>
|
||||
<p>Fixed a crashing bug that could happen in the sidebar</p>
|
||||
<p>Fixed a bug that could prevent users from accessing BazQux if an article was missing a field</p>
|
||||
<p>Fixed an issue that could prevent Feedly users from syncing if they tried to mark too many articles as read at the same time</p>
|
||||
<p>Updated the Safari extension icon (credit to Louie Mantia for the new icon)</p>
|
||||
]]></description>
|
||||
<pubDate>Sat, 08 Apr 2023 10:30:00 -0800</pubDate>
|
||||
<enclosure url="https://github.com/Ranchero-Software/NetNewsWire/releases/download/mac-6.1.2/NetNewsWire6.1.2.zip" sparkle:version="6114" sparkle:shortVersionString="6.1.2" length="10873540" type="application/zip" />
|
||||
<sparkle:minimumSystemVersion>10.15.0</sparkle:minimumSystemVersion>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>NetNewsWire 6.1.1b1</title>
|
||||
<description><![CDATA[
|
||||
<p>Fixed a bug that could prevent users from accessing BazQux if an article was missing a field</p>
|
||||
@@ -17,172 +35,5 @@
|
||||
<sparkle:minimumSystemVersion>10.15.0</sparkle:minimumSystemVersion>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>NetNewsWire 6.1</title>
|
||||
<description><![CDATA[
|
||||
<p>Article themes. Several themes ship with the app, and you can create your own. You can change the theme in Preferences or by adding the theme switcher to the toolbar</p>
|
||||
<p>Copy URLs using repaired, rather than raw, feed links</p>
|
||||
<p>Restore article scroll position on relaunching app</p>
|
||||
<p>Added Copy Article URL and Copy External URL commands to the Edit menu</p>
|
||||
<p>Fixed a bug where using cmd-Q wouldn’t always quit the app as quickly as one might prefer</p>
|
||||
<p>Disallow creation of iCloud account in the app if iCloud and iCloud Drive aren’t both enabled</p>
|
||||
<p>Fixed bug showing quote tweets that only included an image</p>
|
||||
<p>Added a hidden pref to suppress downloading/syncing on start: `defaults write com.ranchero.NetNewsWire-Evergreen DevroeSuppressSyncOnLaunch -bool true`</p>
|
||||
<p>Video autoplay is now disallowed</p>
|
||||
<p>Article view now supports RTL layout</p>
|
||||
<p>Fixed a few font and sizing issues</p>
|
||||
<p>Updated built-in feeds</p>
|
||||
<p>Better alignment for items in General Preferences pane</p>
|
||||
]]></description>
|
||||
<pubDate>Thu, 07 Apr 2022 10:05:00 -0700</pubDate>
|
||||
<enclosure url="https://github.com/Ranchero-Software/NetNewsWire/releases/download/mac-6.1/NetNewsWire6.1.zip" sparkle:version="6106" sparkle:shortVersionString="6.1" length="10923258" type="application/zip" />
|
||||
<sparkle:minimumSystemVersion>10.15.0</sparkle:minimumSystemVersion>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>NetNewsWire 6.1b5</title>
|
||||
<description><![CDATA[
|
||||
<p>Updated built-in feeds</p>
|
||||
<p>Building on a new Apple Silicon Mac — testing to make sure all’s well</p>
|
||||
]]></description>
|
||||
<pubDate>Mon, 04 Apr 2022 22:10:00 -0700</pubDate>
|
||||
<enclosure url="https://github.com/Ranchero-Software/NetNewsWire/releases/download/mac-6.1b5/NetNewsWire6.1b5.zip" sparkle:version="6104" sparkle:shortVersionString="6.1b5" length="10922681" type="application/zip" />
|
||||
<sparkle:minimumSystemVersion>10.15.0</sparkle:minimumSystemVersion>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>NetNewsWire 6.1b4</title>
|
||||
<description><![CDATA[
|
||||
<p>Fixed a few font and sizing issues.</p>
|
||||
]]></description>
|
||||
<pubDate>Sun, 27 Feb 2022 21:50:00 -0800</pubDate>
|
||||
<enclosure url="https://github.com/Ranchero-Software/NetNewsWire/releases/download/mac-6.1b4/NetNewsWire6.1b4.zip" sparkle:version="6103" sparkle:shortVersionString="6.1b4" length="10897726" type="application/zip" />
|
||||
<sparkle:minimumSystemVersion>10.15.0</sparkle:minimumSystemVersion>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>NetNewsWire 6.1b3</title>
|
||||
<description><![CDATA[
|
||||
<p>Two new themes: Hyperlegible and NewsFax</p>
|
||||
<p>Change in how built-in themes work: they’re part of the app bundle and they’re not copied into the Themes folder. When a built-in theme changes in a new app release, anyone using that new version gets the changes to the built-in theme</p>
|
||||
]]></description>
|
||||
<pubDate>Thu, 10 Feb 2022 21:35:00 -0800</pubDate>
|
||||
<enclosure url="https://github.com/Ranchero-Software/NetNewsWire/releases/download/mac-6.1b3/NetNewsWire6.1b3.zip" sparkle:version="6102" sparkle:shortVersionString="6.1b3" length="10893987" type="application/zip" />
|
||||
<sparkle:minimumSystemVersion>10.15.0</sparkle:minimumSystemVersion>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>NetNewsWire 6.1b2</title>
|
||||
<description><![CDATA[
|
||||
<p>Article themes. Several themes ship with the app, and you can create your own. You can change the theme in Preferences or by adding the theme switcher to the toolbar.</p>
|
||||
<p>Copy URLs using repaired, rather than raw, feed links.</p>
|
||||
<p>Restore article scroll position on relaunching app.</p>
|
||||
<p>Added Copy Article URL and Copy External URL commands to the Edit menu.</p>
|
||||
<p>Fixed a bug where using cmd-Q wouldn’t always quit the app as quickly as one might prefer.</p>
|
||||
<p>Disallow creation of iCloud account in the app if iCloud and iCloud Drive aren’t both enabled.</p>
|
||||
<p>Fixed bug showing quote tweets that only included an image.</p>
|
||||
<p>Added a hidden pref to suppress downloading/syncing on start: `defaults write com.ranchero.NetNewsWire-Evergreen DevroeSuppressSyncOnLaunch -bool true`</p>
|
||||
<p>Video autoplay is now disallowed.</p>
|
||||
<p>Article view now supports RTL layout.</p>
|
||||
]]></description>
|
||||
<pubDate>Mon, 17 Jan 2022 17:45:00 -0800</pubDate>
|
||||
<enclosure url="https://github.com/Ranchero-Software/NetNewsWire/releases/download/mac-6.1b2/NetNewsWire6.1b2.zip" sparkle:version="6101" sparkle:shortVersionString="6.1b2" length="10841318" type="application/zip" />
|
||||
<sparkle:minimumSystemVersion>10.15.0</sparkle:minimumSystemVersion>
|
||||
</item>
|
||||
|
||||
|
||||
<item>
|
||||
<title>NetNewsWire 6.0.3</title>
|
||||
<description><![CDATA[
|
||||
<p>Same as 6.0.3b2 except for the version number.</p>
|
||||
]]></description>
|
||||
<pubDate>Sun, 05 Sep 2021 12:20:00 -0700</pubDate>
|
||||
<enclosure url="https://github.com/Ranchero-Software/NetNewsWire/releases/download/mac-6.0.3/NetNewsWire6.0.3.zip" sparkle:version="6035" sparkle:shortVersionString="6.0.3" length="10477066" type="application/zip" />
|
||||
<sparkle:minimumSystemVersion>10.15.0</sparkle:minimumSystemVersion>
|
||||
</item>
|
||||
|
||||
|
||||
<item>
|
||||
<title>NetNewsWire 6.0.3b2</title>
|
||||
<description><![CDATA[
|
||||
<p>Feedly: preserve custom feed names with Feedly when moving them between folders</p>
|
||||
<p>Preferences: use full-width row style in accounts and extensions panes</p>
|
||||
<p>Fixed a crashing bug triggered by running some UI code outside of main thread</p>
|
||||
<p>Fixed a crashing bug that could happen when the app tries to find a feed for a website</p>
|
||||
<p>Fixed a crashing bug that could happen when rendering tweets</p>
|
||||
<p>Changed how images are placed in Twitter articles so that you can better see who Tweeted the image</p>
|
||||
<p>Fixed bug where iCloud syncing could stop prematurely when the sync database has records not in the local database</p>
|
||||
<p>Fixed bug where favicons wouldn’t be found when a home page URL has non-ASCII characters</p>
|
||||
<p>Fixed bug where external URLs in Feedbin feeds might be lost</p>
|
||||
<p>Fixed bug where words prepended with $ wouldn’t appear in Twitter feeds</p>
|
||||
<p>Fixed bug where newlines would be just a space in Twitter feeds</p>
|
||||
<p>Fixed bug where BazQux-synced feeds might stop updating</p>
|
||||
]]></description>
|
||||
<pubDate>Sun, 29 Aug 2021 15:25:00 -0700</pubDate>
|
||||
<enclosure url="https://github.com/Ranchero-Software/NetNewsWire/releases/download/mac-6.0.3b2/NetNewsWire6.0.3b2.zip" sparkle:version="6034" sparkle:shortVersionString="6.0.3b2" length="10477006" type="application/zip" />
|
||||
<sparkle:minimumSystemVersion>10.15.0</sparkle:minimumSystemVersion>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>NetNewsWire 6.0.3b1</title>
|
||||
<description><![CDATA[
|
||||
<p>Feedly: handle API change with deleting and don’t show a spurious error</p>
|
||||
<p>NewsBlur: don’t fetch articles marked hidden by NewsBlur</p>
|
||||
<p>FreshRSS: add API endpoint URL example in setup form</p>
|
||||
<p>iCloud: fixed bug not retaining feeds in a folder where the folder hasn’t been synced yet</p>
|
||||
<p>Feeds list: smart feeds remain visible despite Hide Read Feeds setting</p>
|
||||
<p>Keyboard shortcuts: fixed regression where L key wouldn’t go to next unread when feed is all read</p>
|
||||
<p>Twitter extension: fixed weird bug where an extra https:/ could appear in tweet text</p>
|
||||
]]></description>
|
||||
<pubDate>Thu, 20 May 2021 20:00:00 -0700</pubDate>
|
||||
<enclosure url="https://github.com/Ranchero-Software/NetNewsWire/releases/download/mac-6.0.3b1/NetNewsWire6.0.3b1.zip" sparkle:version="6033" sparkle:shortVersionString="6.0.3b1" length="10463681" type="application/zip" />
|
||||
<sparkle:minimumSystemVersion>10.15.0</sparkle:minimumSystemVersion>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>NetNewsWire 6.0.2</title>
|
||||
<description><![CDATA[
|
||||
<p>Same as 6.0.2b1 — no changes other than version</p>
|
||||
]]></description>
|
||||
<pubDate>Tue, 20 Apr 2021 17:40:00 -0700</pubDate>
|
||||
<enclosure url="https://github.com/Ranchero-Software/NetNewsWire/releases/download/mac-6.0.2/NetNewsWire6.0.2.zip" sparkle:version="6032" sparkle:shortVersionString="6.0.2" length="10453603" type="application/zip" />
|
||||
<sparkle:minimumSystemVersion>10.15.0</sparkle:minimumSystemVersion>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>NetNewsWire 6.0.2b1</title>
|
||||
<description><![CDATA[
|
||||
<p>Inoreader sync: fixed (hopefully) cause of rate limit errors — now doing background sync of statuses much less often - note that this fix needs to be rolled out across all NetNewsWire users in order for it to have full effect</p>
|
||||
<p>Fixed regression with the L key — now works properly again</p>
|
||||
]]></description>
|
||||
<pubDate>Thu, 15 Apr 2021 19:15:00 -0700</pubDate>
|
||||
<enclosure url="https://github.com/Ranchero-Software/NetNewsWire/releases/download/mac-6.0.2b1/NetNewsWire6.0.2b1.zip" sparkle:version="6031" sparkle:shortVersionString="6.0.2b1" length="10453628" type="application/zip" />
|
||||
<sparkle:minimumSystemVersion>10.15.0</sparkle:minimumSystemVersion>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>NetNewsWire 6.0.1</title>
|
||||
<description><![CDATA[
|
||||
<p>Adjusted layout of the add account sheet so that it fits on smaller monitors</p>
|
||||
<p>Sidebar: properly scale the smart feed icons when sidebar is set to large size in System Preferences </p>
|
||||
]]></description>
|
||||
<pubDate>Thu, 01 Apr 2021 20:22:00 -0700</pubDate>
|
||||
<enclosure url="https://github.com/Ranchero-Software/NetNewsWire/releases/download/mac-6.0.1/NetNewsWire6.0.1.zip" sparkle:version="6030" sparkle:shortVersionString="6.0.1" length="10448727" type="application/zip" />
|
||||
<sparkle:minimumSystemVersion>10.15.0</sparkle:minimumSystemVersion>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>NetNewsWire 6.0.1b2</title>
|
||||
<description><![CDATA[
|
||||
<p>Twitter: fixed a date parsing bug that could affect people in some locales, which would prevent Twitter feeds from working for them</p>
|
||||
<p>Feeds list: fixed bug where newly added feed would be called Untitled past the time when the app actually knows its name</p>
|
||||
<p>Fixed bug where next-unread command wouldn’t wrap around when you got to the bottom of the Feeds list</p>
|
||||
]]></description>
|
||||
<pubDate>Mon, 29 Mar 2021 20:55:00 -0700</pubDate>
|
||||
<enclosure url="https://github.com/Ranchero-Software/NetNewsWire/releases/download/mac-6.0.1b2/NetNewsWire6.0.1b2.zip" sparkle:version="6029" sparkle:shortVersionString="6.0.1b2" length="10445067" type="application/zip" />
|
||||
<sparkle:minimumSystemVersion>10.15.0</sparkle:minimumSystemVersion>
|
||||
</item>
|
||||
|
||||
|
||||
</channel>
|
||||
</rss>
|
||||
|
||||
@@ -6,6 +6,24 @@
|
||||
<description>Most recent NetNewsWire releases (not test builds).</description>
|
||||
<language>en</language>
|
||||
|
||||
<item>
|
||||
<title>NetNewsWire 6.1.2</title>
|
||||
<description><![CDATA[
|
||||
<p><b>Twitter integration has been removed:</b> Twitter has suspended NetNewsWire, and Twitter is removing free access to the Twitter API</p>
|
||||
<p>Since Twitter does not provide RSS feeds, we’ve had to use the Twitter API. Without free access to that API, we can’t read feeds from Twitter.</p>
|
||||
<p>We’ve left your Twitter feeds intact. If you have any starred items from those feeds, they will remain as long as you don’t delete those feeds.</p>
|
||||
<p>You can still read whatever you have already downloaded. However, those feeds will no longer update.</p>
|
||||
<p>Other changes…</p>
|
||||
<p>Fixed a crashing bug that could happen in the sidebar</p>
|
||||
<p>Fixed a bug that could prevent users from accessing BazQux if an article was missing a field</p>
|
||||
<p>Fixed an issue that could prevent Feedly users from syncing if they tried to mark too many articles as read at the same time</p>
|
||||
<p>Updated the Safari extension icon (credit to Louie Mantia for the new icon)</p>
|
||||
]]></description>
|
||||
<pubDate>Sat, 08 Apr 2023 10:30:00 -0800</pubDate>
|
||||
<enclosure url="https://github.com/Ranchero-Software/NetNewsWire/releases/download/mac-6.1.2/NetNewsWire6.1.2.zip" sparkle:version="6114" sparkle:shortVersionString="6.1.2" length="10873540" type="application/zip" />
|
||||
<sparkle:minimumSystemVersion>10.15.0</sparkle:minimumSystemVersion>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>NetNewsWire 6.1</title>
|
||||
<description><![CDATA[
|
||||
|
||||
@@ -110,7 +110,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
private var crashReporter: PLCrashReporter!
|
||||
#endif
|
||||
|
||||
override init() {
|
||||
@MainActor override init() {
|
||||
NSWindow.allowsAutomaticWindowTabbing = false
|
||||
super.init()
|
||||
|
||||
@@ -136,19 +136,19 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
}
|
||||
|
||||
// MARK: - API
|
||||
func showAddFolderSheetOnWindow(_ window: NSWindow) {
|
||||
@MainActor func showAddFolderSheetOnWindow(_ window: NSWindow) {
|
||||
addFolderWindowController = AddFolderWindowController()
|
||||
addFolderWindowController!.runSheetOnWindow(window)
|
||||
}
|
||||
|
||||
func showAddWebFeedSheetOnWindow(_ window: NSWindow, urlString: String?, name: String?, account: Account?, folder: Folder?) {
|
||||
@MainActor func showAddWebFeedSheetOnWindow(_ window: NSWindow, urlString: String?, name: String?, account: Account?, folder: Folder?) {
|
||||
addFeedController = AddFeedController(hostWindow: window)
|
||||
addFeedController?.showAddFeedSheet(.webFeed, urlString, name, account, folder)
|
||||
}
|
||||
|
||||
// MARK: - NSApplicationDelegate
|
||||
|
||||
func applicationWillFinishLaunching(_ notification: Notification) {
|
||||
@MainActor func applicationWillFinishLaunching(_ notification: Notification) {
|
||||
installAppleEventHandlers()
|
||||
|
||||
CacheCleaner.purgeIfNecessary()
|
||||
@@ -179,7 +179,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
appName = (Bundle.main.infoDictionary!["CFBundleExecutable"]! as! String)
|
||||
}
|
||||
|
||||
func applicationDidFinishLaunching(_ note: Notification) {
|
||||
@MainActor func applicationDidFinishLaunching(_ note: Notification) {
|
||||
|
||||
#if MAC_APP_STORE || TEST
|
||||
checkForUpdatesMenuItem.isHidden = true
|
||||
@@ -292,7 +292,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
|
||||
}
|
||||
|
||||
func application(_ application: NSApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([NSUserActivityRestoring]) -> Void) -> Bool {
|
||||
@MainActor func application(_ application: NSApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([NSUserActivityRestoring]) -> Void) -> Bool {
|
||||
guard let mainWindowController = mainWindowController else {
|
||||
return false
|
||||
}
|
||||
@@ -300,7 +300,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
return true
|
||||
}
|
||||
|
||||
func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool {
|
||||
@MainActor func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool {
|
||||
// https://github.com/brentsimmons/NetNewsWire/issues/522
|
||||
// I couldn’t reproduce the crashing bug, but it appears to happen on creating a main window
|
||||
// and its views and view controllers. The check below is so that the app does nothing
|
||||
@@ -314,26 +314,26 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
return false
|
||||
}
|
||||
|
||||
func applicationDidBecomeActive(_ notification: Notification) {
|
||||
@MainActor func applicationDidBecomeActive(_ notification: Notification) {
|
||||
fireOldTimers()
|
||||
}
|
||||
|
||||
func applicationDidResignActive(_ notification: Notification) {
|
||||
@MainActor func applicationDidResignActive(_ notification: Notification) {
|
||||
ArticleStringFormatter.emptyCaches()
|
||||
saveState()
|
||||
}
|
||||
|
||||
func application(_ application: NSApplication, didReceiveRemoteNotification userInfo: [String : Any]) {
|
||||
@MainActor func application(_ application: NSApplication, didReceiveRemoteNotification userInfo: [String : Any]) {
|
||||
AccountManager.shared.receiveRemoteNotification(userInfo: userInfo)
|
||||
}
|
||||
|
||||
func application(_ sender: NSApplication, openFile filename: String) -> Bool {
|
||||
@MainActor func application(_ sender: NSApplication, openFile filename: String) -> Bool {
|
||||
guard filename.hasSuffix(ArticleTheme.nnwThemeSuffix) else { return false }
|
||||
importTheme(filename: filename)
|
||||
return true
|
||||
}
|
||||
|
||||
func applicationWillTerminate(_ notification: Notification) {
|
||||
@MainActor func applicationWillTerminate(_ notification: Notification) {
|
||||
shuttingDown = true
|
||||
saveState()
|
||||
|
||||
@@ -347,7 +347,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
while !isShutDownSyncDone && RunLoop.current.run(mode: .default, before: timeout) && timeout > Date() { }
|
||||
}
|
||||
|
||||
func presentThemeImportError(_ error: Error) {
|
||||
@MainActor func presentThemeImportError(_ error: Error) {
|
||||
var informativeText: String = ""
|
||||
|
||||
if let decodingError = error as? DecodingError {
|
||||
@@ -392,13 +392,13 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
|
||||
// MARK: Notifications
|
||||
|
||||
@objc func unreadCountDidChange(_ note: Notification) {
|
||||
@MainActor @objc func unreadCountDidChange(_ note: Notification) {
|
||||
if note.object is AccountManager {
|
||||
unreadCount = AccountManager.shared.unreadCount
|
||||
}
|
||||
}
|
||||
|
||||
@objc func webFeedSettingDidChange(_ note: Notification) {
|
||||
@MainActor @objc func webFeedSettingDidChange(_ note: Notification) {
|
||||
guard let feed = note.object as? WebFeed, let key = note.userInfo?[WebFeed.WebFeedSettingUserInfoKey] as? String else {
|
||||
return
|
||||
}
|
||||
@@ -407,14 +407,14 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
}
|
||||
}
|
||||
|
||||
@objc func inspectableObjectsDidChange(_ note: Notification) {
|
||||
@MainActor @objc func inspectableObjectsDidChange(_ note: Notification) {
|
||||
guard let inspectorWindowController = inspectorWindowController, inspectorWindowController.isOpen else {
|
||||
return
|
||||
}
|
||||
inspectorWindowController.objects = objectsForInspector()
|
||||
}
|
||||
|
||||
@objc func userDefaultsDidChange(_ note: Notification) {
|
||||
@MainActor @objc func userDefaultsDidChange(_ note: Notification) {
|
||||
updateSortMenuItems()
|
||||
updateGroupByFeedMenuItem()
|
||||
|
||||
@@ -426,11 +426,11 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
updateDockBadge()
|
||||
}
|
||||
|
||||
@objc func didWakeNotification(_ note: Notification) {
|
||||
@MainActor @objc func didWakeNotification(_ note: Notification) {
|
||||
fireOldTimers()
|
||||
}
|
||||
|
||||
@objc func importDownloadedTheme(_ note: Notification) {
|
||||
@MainActor @objc func importDownloadedTheme(_ note: Notification) {
|
||||
guard let userInfo = note.userInfo,
|
||||
let url = userInfo["url"] as? URL else {
|
||||
return
|
||||
@@ -442,7 +442,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
|
||||
// MARK: Main Window
|
||||
|
||||
func createMainWindowController() -> MainWindowController {
|
||||
@MainActor func createMainWindowController() -> MainWindowController {
|
||||
let controller: MainWindowController
|
||||
controller = windowControllerWithName("MainWindow") as! MainWindowController
|
||||
|
||||
@@ -453,13 +453,13 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
return controller
|
||||
}
|
||||
|
||||
func windowControllerWithName(_ storyboardName: String) -> NSWindowController {
|
||||
@MainActor func windowControllerWithName(_ storyboardName: String) -> NSWindowController {
|
||||
let storyboard = NSStoryboard(name: NSStoryboard.Name(storyboardName), bundle: nil)
|
||||
return storyboard.instantiateInitialController()! as! NSWindowController
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
func createAndShowMainWindow() -> MainWindowController {
|
||||
@MainActor func createAndShowMainWindow() -> MainWindowController {
|
||||
let controller = createMainWindowController()
|
||||
controller.showWindow(self)
|
||||
|
||||
@@ -471,7 +471,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
return controller
|
||||
}
|
||||
|
||||
func createAndShowMainWindowIfNecessary() {
|
||||
@MainActor func createAndShowMainWindowIfNecessary() {
|
||||
if mainWindowController == nil {
|
||||
createAndShowMainWindow()
|
||||
} else {
|
||||
@@ -479,7 +479,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
}
|
||||
}
|
||||
|
||||
func removeMainWindow(_ windowController: MainWindowController) {
|
||||
@MainActor func removeMainWindow(_ windowController: MainWindowController) {
|
||||
guard mainWindowControllers.count > 1 else { return }
|
||||
if let index = mainWindowControllers.firstIndex(of: windowController) {
|
||||
mainWindowControllers.remove(at: index)
|
||||
@@ -487,7 +487,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
}
|
||||
|
||||
// MARK: NSUserInterfaceValidations
|
||||
func validateUserInterfaceItem(_ item: NSValidatedUserInterfaceItem) -> Bool {
|
||||
@MainActor func validateUserInterfaceItem(_ item: NSValidatedUserInterfaceItem) -> Bool {
|
||||
if shuttingDown {
|
||||
return false
|
||||
}
|
||||
@@ -533,11 +533,11 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
|
||||
// MARK: UNUserNotificationCenterDelegate
|
||||
|
||||
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
|
||||
@MainActor func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
|
||||
completionHandler([.banner, .badge, .sound])
|
||||
}
|
||||
|
||||
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
|
||||
@MainActor func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
|
||||
|
||||
let userInfo = response.notification.request.content.userInfo
|
||||
|
||||
@@ -553,7 +553,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
}
|
||||
|
||||
// MARK: Add Feed
|
||||
func addWebFeed(_ urlString: String?, name: String? = nil, account: Account? = nil, folder: Folder? = nil) {
|
||||
@MainActor func addWebFeed(_ urlString: String?, name: String? = nil, account: Account? = nil, folder: Folder? = nil) {
|
||||
createAndShowMainWindowIfNecessary()
|
||||
|
||||
if mainWindowController!.isDisplayingSheet {
|
||||
@@ -564,13 +564,13 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
}
|
||||
|
||||
// MARK: - Dock Badge
|
||||
@objc func updateDockBadge() {
|
||||
@MainActor @objc func updateDockBadge() {
|
||||
let label = unreadCount > 0 ? "\(unreadCount)" : ""
|
||||
NSApplication.shared.dockTile.badgeLabel = label
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
@IBAction func showPreferences(_ sender: Any?) {
|
||||
@MainActor @IBAction func showPreferences(_ sender: Any?) {
|
||||
if preferencesWindowController == nil {
|
||||
preferencesWindowController = windowControllerWithName("Preferences")
|
||||
}
|
||||
@@ -578,35 +578,35 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
preferencesWindowController!.showWindow(self)
|
||||
}
|
||||
|
||||
@IBAction func newMainWindow(_ sender: Any?) {
|
||||
@MainActor @IBAction func newMainWindow(_ sender: Any?) {
|
||||
createAndShowMainWindow()
|
||||
}
|
||||
|
||||
@IBAction func showMainWindow(_ sender: Any?) {
|
||||
@MainActor @IBAction func showMainWindow(_ sender: Any?) {
|
||||
createAndShowMainWindowIfNecessary()
|
||||
mainWindowController?.window?.makeKey()
|
||||
}
|
||||
|
||||
@IBAction func refreshAll(_ sender: Any?) {
|
||||
@MainActor @IBAction func refreshAll(_ sender: Any?) {
|
||||
AccountManager.shared.refreshAll(errorHandler: ErrorHandler.present)
|
||||
}
|
||||
|
||||
@IBAction func showAddWebFeedWindow(_ sender: Any?) {
|
||||
@MainActor @IBAction func showAddWebFeedWindow(_ sender: Any?) {
|
||||
addWebFeed(nil)
|
||||
}
|
||||
|
||||
@IBAction func showAddRedditFeedWindow(_ sender: Any?) {
|
||||
@MainActor @IBAction func showAddRedditFeedWindow(_ sender: Any?) {
|
||||
createAndShowMainWindowIfNecessary()
|
||||
addFeedController = AddFeedController(hostWindow: mainWindowController!.window!)
|
||||
addFeedController?.showAddFeedSheet(.redditFeed)
|
||||
}
|
||||
|
||||
@IBAction func showAddFolderWindow(_ sender: Any?) {
|
||||
@MainActor @IBAction func showAddFolderWindow(_ sender: Any?) {
|
||||
createAndShowMainWindowIfNecessary()
|
||||
showAddFolderSheetOnWindow(mainWindowController!.window!)
|
||||
}
|
||||
|
||||
@IBAction func showKeyboardShortcutsWindow(_ sender: Any?) {
|
||||
@MainActor @IBAction func showKeyboardShortcutsWindow(_ sender: Any?) {
|
||||
if keyboardShortcutsWindowController == nil {
|
||||
|
||||
keyboardShortcutsWindowController = WebViewWindowController(title: NSLocalizedString("Keyboard Shortcuts", comment: "window title"))
|
||||
@@ -625,7 +625,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
keyboardShortcutsWindowController!.showWindow(self)
|
||||
}
|
||||
|
||||
@IBAction func toggleInspectorWindow(_ sender: Any?) {
|
||||
@MainActor @IBAction func toggleInspectorWindow(_ sender: Any?) {
|
||||
if inspectorWindowController == nil {
|
||||
inspectorWindowController = (windowControllerWithName("Inspector") as! InspectorWindowController)
|
||||
}
|
||||
@@ -639,7 +639,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func importOPMLFromFile(_ sender: Any?) {
|
||||
@MainActor @IBAction func importOPMLFromFile(_ sender: Any?) {
|
||||
createAndShowMainWindowIfNecessary()
|
||||
if mainWindowController!.isDisplayingSheet {
|
||||
return
|
||||
@@ -649,7 +649,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
importOPMLController?.runSheetOnWindow(mainWindowController!.window!)
|
||||
}
|
||||
|
||||
@IBAction func importNNW3FromFile(_ sender: Any?) {
|
||||
@MainActor @IBAction func importNNW3FromFile(_ sender: Any?) {
|
||||
createAndShowMainWindowIfNecessary()
|
||||
if mainWindowController!.isDisplayingSheet {
|
||||
return
|
||||
@@ -657,7 +657,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
NNW3ImportController.askUserToImportNNW3Subscriptions(window: mainWindowController!.window!)
|
||||
}
|
||||
|
||||
@IBAction func exportOPML(_ sender: Any?) {
|
||||
@MainActor @IBAction func exportOPML(_ sender: Any?) {
|
||||
createAndShowMainWindowIfNecessary()
|
||||
if mainWindowController!.isDisplayingSheet {
|
||||
return
|
||||
@@ -667,30 +667,30 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
exportOPMLController?.runSheetOnWindow(mainWindowController!.window!)
|
||||
}
|
||||
|
||||
@IBAction func addAppNews(_ sender: Any?) {
|
||||
@MainActor @IBAction func addAppNews(_ sender: Any?) {
|
||||
if AccountManager.shared.anyAccountHasNetNewsWireNewsSubscription() {
|
||||
return
|
||||
}
|
||||
addWebFeed(AccountManager.netNewsWireNewsURL, name: "NetNewsWire News")
|
||||
}
|
||||
|
||||
@IBAction func openWebsite(_ sender: Any?) {
|
||||
@MainActor @IBAction func openWebsite(_ sender: Any?) {
|
||||
|
||||
Browser.open("https://netnewswire.com/", inBackground: false)
|
||||
}
|
||||
|
||||
@IBAction func showHelp(_ sender: Any?) {
|
||||
@MainActor @IBAction func showHelp(_ sender: Any?) {
|
||||
|
||||
Browser.open("https://netnewswire.com/help/mac/6.1/en/", inBackground: false)
|
||||
}
|
||||
|
||||
@IBAction func gotoToday(_ sender: Any?) {
|
||||
@MainActor @IBAction func gotoToday(_ sender: Any?) {
|
||||
|
||||
createAndShowMainWindowIfNecessary()
|
||||
mainWindowController!.gotoToday(sender)
|
||||
}
|
||||
|
||||
@IBAction func gotoAllUnread(_ sender: Any?) {
|
||||
@MainActor @IBAction func gotoAllUnread(_ sender: Any?) {
|
||||
|
||||
createAndShowMainWindowIfNecessary()
|
||||
mainWindowController!.gotoAllUnread(sender)
|
||||
@@ -702,27 +702,27 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
mainWindowController!.gotoStarred(sender)
|
||||
}
|
||||
|
||||
@IBAction func sortByOldestArticleOnTop(_ sender: Any?) {
|
||||
@MainActor @IBAction func sortByOldestArticleOnTop(_ sender: Any?) {
|
||||
|
||||
AppDefaults.shared.timelineSortDirection = .orderedAscending
|
||||
}
|
||||
|
||||
@IBAction func sortByNewestArticleOnTop(_ sender: Any?) {
|
||||
@MainActor @IBAction func sortByNewestArticleOnTop(_ sender: Any?) {
|
||||
|
||||
AppDefaults.shared.timelineSortDirection = .orderedDescending
|
||||
}
|
||||
|
||||
@IBAction func groupByFeedToggled(_ sender: NSMenuItem) {
|
||||
@MainActor @IBAction func groupByFeedToggled(_ sender: NSMenuItem) {
|
||||
AppDefaults.shared.timelineGroupByFeed.toggle()
|
||||
}
|
||||
|
||||
@IBAction func checkForUpdates(_ sender: Any?) {
|
||||
@MainActor @IBAction func checkForUpdates(_ sender: Any?) {
|
||||
#if !MAC_APP_STORE && !TEST
|
||||
self.softwareUpdater.checkForUpdates()
|
||||
#endif
|
||||
}
|
||||
|
||||
@IBAction func showAbout(_ sender: Any?) {
|
||||
@MainActor @IBAction func showAbout(_ sender: Any?) {
|
||||
if #available(macOS 12, *) {
|
||||
for window in NSApplication.shared.windows {
|
||||
if window.identifier == .aboutNetNewsWire {
|
||||
@@ -741,7 +741,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
|
||||
// MARK: - NSMenuDelegate
|
||||
|
||||
extension AppDelegate: NSMenuDelegate {
|
||||
@MainActor extension AppDelegate: NSMenuDelegate {
|
||||
|
||||
public func menuNeedsUpdate(_ menu: NSMenu) {
|
||||
let newShareMenu = mainWindowController?.shareMenu
|
||||
@@ -760,7 +760,7 @@ extension AppDelegate: NSMenuDelegate {
|
||||
}
|
||||
|
||||
// MARK: - Debug Menu
|
||||
extension AppDelegate {
|
||||
@MainActor extension AppDelegate {
|
||||
|
||||
@IBAction func debugSearch(_ sender: Any?) {
|
||||
AccountManager.shared.defaultAccount.debugRunSearch()
|
||||
@@ -832,7 +832,7 @@ extension AppDelegate {
|
||||
|
||||
}
|
||||
|
||||
internal extension AppDelegate {
|
||||
@MainActor internal extension AppDelegate {
|
||||
|
||||
func fireOldTimers() {
|
||||
// It’s possible there’s a refresh timer set to go off in the past.
|
||||
@@ -1007,7 +1007,7 @@ extension AppDelegate : ScriptingAppDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
extension AppDelegate: NSWindowRestoration {
|
||||
@MainActor extension AppDelegate: NSWindowRestoration {
|
||||
|
||||
@objc static func restoreWindow(withIdentifier identifier: NSUserInterfaceItemIdentifier, state: NSCoder, completionHandler: @escaping (NSWindow?, Error?) -> Void) {
|
||||
var mainWindow: NSWindow? = nil
|
||||
@@ -1021,7 +1021,7 @@ extension AppDelegate: NSWindowRestoration {
|
||||
|
||||
// Handle Notification Actions
|
||||
|
||||
private extension AppDelegate {
|
||||
@MainActor private extension AppDelegate {
|
||||
|
||||
func handleMarkAsRead(userInfo: [AnyHashable: Any]) {
|
||||
markArticle(userInfo: userInfo, statusKey: .read)
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import Foundation
|
||||
import RSWeb
|
||||
|
||||
struct Browser {
|
||||
@MainActor struct Browser {
|
||||
|
||||
/// The user-specified default browser for opening web pages.
|
||||
///
|
||||
|
||||
@@ -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)")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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?
|
||||
|
||||
@@ -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?
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -86,11 +86,15 @@ final class ArticleThemesManager: NSObject, NSFilePresenter, Logging {
|
||||
}
|
||||
|
||||
func presentedSubitemDidChange(at url: URL) {
|
||||
themeNames = buildThemeNames()
|
||||
do {
|
||||
currentTheme = try articleThemeWithThemeName(currentThemeName)
|
||||
} catch {
|
||||
appDelegate.presentThemeImportError(error)
|
||||
if url.lastPathComponent.localizedCaseInsensitiveContains("nnwtheme") {
|
||||
themeNames = buildThemeNames()
|
||||
do {
|
||||
currentTheme = try articleThemeWithThemeName(currentThemeName)
|
||||
} catch {
|
||||
Task { @MainActor in
|
||||
appDelegate.presentThemeImportError(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -15,7 +15,7 @@ enum ArticleExtractorButtonState {
|
||||
case off
|
||||
}
|
||||
|
||||
class ArticleExtractorButton: UIButton {
|
||||
@MainActor class ArticleExtractorButton: UIButton {
|
||||
|
||||
private var animatedLayer: CALayer?
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import UIKit
|
||||
import Articles
|
||||
|
||||
class ContextMenuPreviewViewController: UIViewController {
|
||||
@MainActor class ContextMenuPreviewViewController: UIViewController {
|
||||
|
||||
@IBOutlet weak var blogNameLabel: UILabel!
|
||||
@IBOutlet weak var blogAuthorLabel: UILabel!
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
class ImageTransition: NSObject, UIViewControllerAnimatedTransitioning {
|
||||
@MainActor final class ImageTransition: NSObject, UIViewControllerAnimatedTransitioning {
|
||||
|
||||
private weak var webViewController: WebViewController?
|
||||
private let duration = 0.4
|
||||
|
||||
@@ -15,7 +15,7 @@ enum KeyboardType: String {
|
||||
case detail = "DetailKeyboardShortcuts"
|
||||
}
|
||||
|
||||
class KeyboardManager {
|
||||
@MainActor final class KeyboardManager {
|
||||
|
||||
private(set) var _keyCommands: [UIKeyCommand]
|
||||
var keyCommands: [UIKeyCommand] {
|
||||
|
||||
@@ -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?
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -12,7 +12,7 @@ protocol MasterFeedTableViewSectionHeaderDelegate {
|
||||
func masterFeedTableViewSectionHeaderDisclosureDidToggle(_ sender: MasterFeedTableViewSectionHeader)
|
||||
}
|
||||
|
||||
class MasterFeedTableViewSectionHeader: UITableViewHeaderFooterView {
|
||||
@MainActor class MasterFeedTableViewSectionHeader: UITableViewHeaderFooterView {
|
||||
|
||||
var delegate: MasterFeedTableViewSectionHeaderDelegate?
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import UIKit
|
||||
import RSCore
|
||||
|
||||
struct MasterTimelineAccessibilityCellLayout: MasterTimelineCellLayout {
|
||||
@MainActor struct MasterTimelineAccessibilityCellLayout: MasterTimelineCellLayout {
|
||||
|
||||
let height: CGFloat
|
||||
let unreadIndicatorRect: CGRect
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import UIKit
|
||||
import Articles
|
||||
|
||||
struct MasterTimelineCellData {
|
||||
@MainActor struct MasterTimelineCellData {
|
||||
|
||||
private static let noText = NSLocalizedString("(No Text)", comment: "No Text")
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ protocol MasterTimelineCellLayout {
|
||||
|
||||
}
|
||||
|
||||
extension MasterTimelineCellLayout {
|
||||
@MainActor extension MasterTimelineCellLayout {
|
||||
|
||||
static func rectForUnreadIndicator(_ point: CGPoint) -> CGRect {
|
||||
var r = CGRect.zero
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import UIKit
|
||||
import RSCore
|
||||
|
||||
struct MasterTimelineDefaultCellLayout: MasterTimelineCellLayout {
|
||||
@MainActor struct MasterTimelineDefaultCellLayout: MasterTimelineCellLayout {
|
||||
|
||||
static let cellPadding = UIEdgeInsets(top: 12, left: 8, bottom: 12, right: 20)
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import UIKit
|
||||
import RSCore
|
||||
|
||||
class MasterTimelineTableViewCell: VibrantTableViewCell {
|
||||
@MainActor class MasterTimelineTableViewCell: VibrantTableViewCell {
|
||||
|
||||
private let titleView = MasterTimelineTableViewCell.multiLineUILabel()
|
||||
private let summaryView = MasterTimelineTableViewCell.multiLineUILabel()
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
class MasterUnreadIndicatorView: UIView {
|
||||
@MainActor class MasterUnreadIndicatorView: UIView {
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
@@ -26,7 +26,7 @@ struct TextFieldSizeInfo {
|
||||
let numberOfLinesUsed: Int // A two-line text field may only use one line, for instance. This would equal 1, then.
|
||||
}
|
||||
|
||||
final class MultilineUILabelSizer {
|
||||
@MainActor final class MultilineUILabelSizer {
|
||||
|
||||
private let numberOfLines: Int
|
||||
private let font: UIFont
|
||||
|
||||
@@ -12,7 +12,7 @@ import UIKit
|
||||
// Uses a cache.
|
||||
// Main thready only.
|
||||
|
||||
final class SingleLineUILabelSizer {
|
||||
@MainActor final class SingleLineUILabelSizer {
|
||||
|
||||
let font: UIFont
|
||||
private var cache = [String: CGSize]()
|
||||
|
||||
@@ -15,7 +15,7 @@ extension UIView: MarkAsReadAlertControllerSourceType {}
|
||||
extension UIBarButtonItem: MarkAsReadAlertControllerSourceType {}
|
||||
|
||||
|
||||
struct MarkAsReadAlertController {
|
||||
@MainActor struct MarkAsReadAlertController {
|
||||
|
||||
static func confirm<T>(_ controller: UIViewController?,
|
||||
coordinator: SceneCoordinator?,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
class MasterTimelineDataSource<SectionIdentifierType, ItemIdentifierType>: UITableViewDiffableDataSource<SectionIdentifierType, ItemIdentifierType> where SectionIdentifierType : Hashable, ItemIdentifierType : Hashable {
|
||||
@MainActor final class MasterTimelineDataSource<SectionIdentifierType, ItemIdentifierType>: UITableViewDiffableDataSource<SectionIdentifierType, ItemIdentifierType> where SectionIdentifierType : Hashable, ItemIdentifierType : Hashable {
|
||||
|
||||
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
|
||||
return true
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
class MasterTimelineTitleView: UIView {
|
||||
@MainActor final class MasterTimelineTitleView: UIView {
|
||||
|
||||
@IBOutlet weak var iconView: IconView!
|
||||
@IBOutlet weak var label: UILabel!
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import UIKit
|
||||
import Account
|
||||
|
||||
class RootSplitViewController: UISplitViewController {
|
||||
final class RootSplitViewController: UISplitViewController {
|
||||
|
||||
var coordinator: SceneCoordinator!
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ struct FeedNode: Hashable {
|
||||
}
|
||||
}
|
||||
|
||||
class SceneCoordinator: NSObject, UndoableCommandRunner, Logging {
|
||||
final class SceneCoordinator: NSObject, UndoableCommandRunner, Logging {
|
||||
|
||||
var undoableCommands = [UndoableCommand]()
|
||||
var undoManager: UndoManager? {
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user