diff --git a/Localization/ios-infoPlist.json b/Localization/ios-infoPlist.json index f25dbcc0..c6db73de 100644 --- a/Localization/ios-infoPlist.json +++ b/Localization/ios-infoPlist.json @@ -1,4 +1,6 @@ { "NSCameraUsageDescription": "Used to take photo for post status", - "NSPhotoLibraryAddUsageDescription": "Used to save photo into the Photo Library" -} \ No newline at end of file + "NSPhotoLibraryAddUsageDescription": "Used to save photo into the Photo Library", + "NewPostShortcutItemTitle": "New Post", + "SearchShortcutItemTitle": "Search" +} diff --git a/Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon - ASDK.xcscheme b/Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon - ASDK.xcscheme new file mode 100644 index 00000000..4ce52bd5 --- /dev/null +++ b/Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon - ASDK.xcscheme @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon - Release.xcscheme b/Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon - Release.xcscheme new file mode 100644 index 00000000..15ecdcbe --- /dev/null +++ b/Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon - Release.xcscheme @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon.xcscheme b/Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon.xcscheme new file mode 100644 index 00000000..70507b96 --- /dev/null +++ b/Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon.xcscheme @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mastodon.xcodeproj/xcshareddata/xcschemes/NotificationService.xcscheme b/Mastodon.xcodeproj/xcshareddata/xcschemes/NotificationService.xcscheme new file mode 100644 index 00000000..b64bfc89 --- /dev/null +++ b/Mastodon.xcodeproj/xcshareddata/xcschemes/NotificationService.xcscheme @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist index a5dbdb34..09d2afef 100644 --- a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,12 +7,12 @@ AppShared.xcscheme_^#shared#^_ orderHint - 24 + 21 CoreDataStack.xcscheme_^#shared#^_ orderHint - 22 + 23 Mastodon - ASDK.xcscheme_^#shared#^_ @@ -42,7 +42,7 @@ ShareActionExtension.xcscheme_^#shared#^_ orderHint - 21 + 22 SuppressBuildableAutocreation diff --git a/Mastodon/Coordinator/SceneCoordinator.swift b/Mastodon/Coordinator/SceneCoordinator.swift index 5aac2b1b..04804dde 100644 --- a/Mastodon/Coordinator/SceneCoordinator.swift +++ b/Mastodon/Coordinator/SceneCoordinator.swift @@ -13,7 +13,7 @@ final public class SceneCoordinator { private weak var scene: UIScene! private weak var sceneDelegate: SceneDelegate! private weak var appContext: AppContext! - private weak var tabBarController: MainTabBarController! + private(set) weak var tabBarController: MainTabBarController! let id = UUID().uuidString diff --git a/Mastodon/Info.plist b/Mastodon/Info.plist index cbb93eab..6143fcdb 100644 --- a/Mastodon/Info.plist +++ b/Mastodon/Info.plist @@ -86,5 +86,24 @@ UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight + UIApplicationShortcutItems + + + UIApplicationShortcutItemType + org.joinmastodon.app.new-post + UIApplicationShortcutItemIconSymbolName + square.and.pencil + UIApplicationShortcutItemTitle + NewPostShortcutItemTitle + + + UIApplicationShortcutItemType + org.joinmastodon.app.search + UIApplicationShortcutItemIconSymbolName + magnifyingglass + UIApplicationShortcutItemTitle + SearchShortcutItemTitle + + diff --git a/Mastodon/Resources/ar.lproj/InfoPlist.strings b/Mastodon/Resources/ar.lproj/InfoPlist.strings index 48566ae3..71086557 100644 --- a/Mastodon/Resources/ar.lproj/InfoPlist.strings +++ b/Mastodon/Resources/ar.lproj/InfoPlist.strings @@ -1,2 +1,4 @@ "NSCameraUsageDescription" = "Used to take photo for post status"; -"NSPhotoLibraryAddUsageDescription" = "Used to save photo into the Photo Library"; \ No newline at end of file +"NSPhotoLibraryAddUsageDescription" = "Used to save photo into the Photo Library"; +"NewPostShortcutItemTitle" = "New Post"; +"SearchShortcutItemTitle" = "Search"; \ No newline at end of file diff --git a/Mastodon/Resources/en.lproj/InfoPlist.strings b/Mastodon/Resources/en.lproj/InfoPlist.strings index 48566ae3..71086557 100644 --- a/Mastodon/Resources/en.lproj/InfoPlist.strings +++ b/Mastodon/Resources/en.lproj/InfoPlist.strings @@ -1,2 +1,4 @@ "NSCameraUsageDescription" = "Used to take photo for post status"; -"NSPhotoLibraryAddUsageDescription" = "Used to save photo into the Photo Library"; \ No newline at end of file +"NSPhotoLibraryAddUsageDescription" = "Used to save photo into the Photo Library"; +"NewPostShortcutItemTitle" = "New Post"; +"SearchShortcutItemTitle" = "Search"; \ No newline at end of file diff --git a/Mastodon/Resources/en.lproj/infoPlist.strings b/Mastodon/Resources/en.lproj/infoPlist.strings deleted file mode 100644 index 48566ae3..00000000 --- a/Mastodon/Resources/en.lproj/infoPlist.strings +++ /dev/null @@ -1,2 +0,0 @@ -"NSCameraUsageDescription" = "Used to take photo for post status"; -"NSPhotoLibraryAddUsageDescription" = "Used to save photo into the Photo Library"; \ No newline at end of file diff --git a/Mastodon/Supporting Files/SceneDelegate.swift b/Mastodon/Supporting Files/SceneDelegate.swift index 6964eef9..05ff8850 100644 --- a/Mastodon/Supporting Files/SceneDelegate.swift +++ b/Mastodon/Supporting Files/SceneDelegate.swift @@ -5,6 +5,7 @@ // Created by MainasuK Cirno on 2021/1/22. // +import os.log import UIKit import Combine import CoreDataStack @@ -25,6 +26,9 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { var fpsIndicator: FPSIndicator? #endif + var savedShortCutItem: UIApplicationShortcutItem? + + let logger = Logger(subsystem: "SceneDelegate", category: "logic") func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = scene as? UIWindowScene else { return } @@ -55,6 +59,11 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { sceneCoordinator.setup() sceneCoordinator.setupOnboardingIfNeeds(animated: false) window.makeKeyAndVisible() + + if let shortcutItem = connectionOptions.shortcutItem { + // Save it off for later when we become active. + savedShortCutItem = shortcutItem + } UserDefaults.shared.observe(\.customUserInterfaceStyle, options: [.initial, .new]) { [weak self] defaults, _ in guard let self = self else { return } @@ -84,6 +93,11 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { // trigger status filter update AppContext.shared.statusFilterService.filterUpdatePublisher.send() + + if let shortcutItem = savedShortCutItem { + _ = handler(shortcutItem: shortcutItem) + savedShortCutItem = nil + } } func sceneWillResignActive(_ scene: UIScene) { @@ -103,7 +117,40 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { AppContext.shared.audioPlaybackService.pauseIfNeed() } +} +extension SceneDelegate { + func windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) { + completionHandler(handler(shortcutItem: shortcutItem)) + } + + private func handler(shortcutItem: UIApplicationShortcutItem) -> Bool { + logger.debug("\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public): \(shortcutItem.type)") + + switch shortcutItem.type { + 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…") + } else { + let composeViewModel = ComposeViewModel(context: AppContext.shared, composeKind: .post) + coordinator?.present(scene: .compose(viewModel: composeViewModel), from: nil, transition: .modal(animated: true, completion: nil)) + logger.debug("\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public): present compose scene") + } + 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") + + if let searchViewController = coordinator?.tabBarController.topMost as? SearchViewController { + searchViewController.searchBarTapPublisher.send() + logger.debug("\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public): trigger search") + } + default: + assertionFailure() + break + } + + return true + } } #if DEBUG