feat: add unread notification shortcut handler and updater
This commit is contained in:
parent
b61e7518b5
commit
112fa56ee6
|
@ -114,7 +114,7 @@
|
|||
<key>MastodonIntent.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>31</integer>
|
||||
<integer>20</integer>
|
||||
</dict>
|
||||
<key>MastodonIntents.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
|
@ -129,12 +129,12 @@
|
|||
<key>NotificationService.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>30</integer>
|
||||
<integer>21</integer>
|
||||
</dict>
|
||||
<key>ShareActionExtension.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>32</integer>
|
||||
<integer>22</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>SuppressBuildableAutocreation</key>
|
||||
|
|
|
@ -19,7 +19,7 @@ final public class SceneCoordinator {
|
|||
|
||||
private weak var scene: UIScene!
|
||||
private weak var sceneDelegate: SceneDelegate!
|
||||
private weak var appContext: AppContext!
|
||||
private(set) weak var appContext: AppContext!
|
||||
|
||||
let id = UUID().uuidString
|
||||
|
||||
|
|
|
@ -2,19 +2,6 @@
|
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSExceptionDomains</key>
|
||||
<dict>
|
||||
<key>onion</key>
|
||||
<dict>
|
||||
<key>NSExceptionAllowsInsecureHTTPLoads</key>
|
||||
<true/>
|
||||
<key>NSIncludesSubdomains</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
|
@ -59,6 +46,19 @@
|
|||
</array>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSExceptionDomains</key>
|
||||
<dict>
|
||||
<key>onion</key>
|
||||
<dict>
|
||||
<key>NSExceptionAllowsInsecureHTTPLoads</key>
|
||||
<true/>
|
||||
<key>NSIncludesSubdomains</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>NSUserActivityTypes</key>
|
||||
<array>
|
||||
<string>SendPostIntent</string>
|
||||
|
@ -103,6 +103,10 @@
|
|||
</array>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>remote-notification</string>
|
||||
</array>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>Main</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
|
|
|
@ -106,6 +106,14 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
|
|||
completionHandler([.sound])
|
||||
}
|
||||
|
||||
|
||||
// notification present in the background (or resume from background)
|
||||
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) async -> UIBackgroundFetchResult {
|
||||
let shortcutItems = try? await appContext.notificationService.unreadApplicationShortcutItems()
|
||||
UIApplication.shared.shortcutItems = shortcutItems
|
||||
return .noData
|
||||
}
|
||||
|
||||
// response to user action for notification (e.g. redirect to post)
|
||||
func userNotificationCenter(
|
||||
_ center: UNUserNotificationCenter,
|
||||
|
|
|
@ -110,7 +110,9 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
|||
AppContext.shared.statusFilterService.filterUpdatePublisher.send()
|
||||
|
||||
if let shortcutItem = savedShortCutItem {
|
||||
_ = handler(shortcutItem: shortcutItem)
|
||||
Task {
|
||||
_ = await handler(shortcutItem: shortcutItem)
|
||||
}
|
||||
savedShortCutItem = nil
|
||||
}
|
||||
}
|
||||
|
@ -134,16 +136,45 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
|||
}
|
||||
|
||||
extension SceneDelegate {
|
||||
func windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
|
||||
completionHandler(handler(shortcutItem: shortcutItem))
|
||||
|
||||
func windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem) async -> Bool {
|
||||
return await handler(shortcutItem: shortcutItem)
|
||||
}
|
||||
|
||||
private func handler(shortcutItem: UIApplicationShortcutItem) -> Bool {
|
||||
@MainActor
|
||||
private func handler(shortcutItem: UIApplicationShortcutItem) async -> Bool {
|
||||
logger.debug("\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public): \(shortcutItem.type)")
|
||||
|
||||
switch shortcutItem.type {
|
||||
case NotificationService.unreadShortcutItemIdentifier:
|
||||
coordinator?.switchToTabBar(tab: .notification)
|
||||
guard let coordinator = self.coordinator else { return false }
|
||||
|
||||
guard let accessToken = shortcutItem.userInfo?["accessToken"] as? String else {
|
||||
assertionFailure()
|
||||
return false
|
||||
}
|
||||
let request = MastodonAuthentication.sortedFetchRequest
|
||||
request.predicate = MastodonAuthentication.predicate(userAccessToken: accessToken)
|
||||
request.fetchLimit = 1
|
||||
|
||||
guard let authentication = try? coordinator.appContext.managedObjectContext.fetch(request).first else {
|
||||
assertionFailure()
|
||||
return false
|
||||
}
|
||||
|
||||
let _isActive = try? await coordinator.appContext.authenticationService.activeMastodonUser(
|
||||
domain: authentication.domain,
|
||||
userID: authentication.userID
|
||||
)
|
||||
.singleOutput()
|
||||
.get()
|
||||
|
||||
guard _isActive == true else {
|
||||
return false
|
||||
}
|
||||
|
||||
coordinator.switchToTabBar(tab: .notification)
|
||||
|
||||
case "org.joinmastodon.app.new-post":
|
||||
if coordinator?.tabBarController.topMost is ComposeViewController {
|
||||
logger.debug("\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public): composing…")
|
||||
|
@ -160,6 +191,7 @@ extension SceneDelegate {
|
|||
logger.debug("\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public): not authenticated")
|
||||
}
|
||||
}
|
||||
|
||||
case "org.joinmastodon.app.search":
|
||||
coordinator?.switchToTabBar(tab: .search)
|
||||
logger.debug("\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public): select search tab")
|
||||
|
@ -168,6 +200,7 @@ extension SceneDelegate {
|
|||
searchViewController.searchBarTapPublisher.send()
|
||||
logger.debug("\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public): trigger search")
|
||||
}
|
||||
|
||||
default:
|
||||
assertionFailure()
|
||||
break
|
||||
|
|
Loading…
Reference in New Issue