feat: add compose and search home screen quick actions

This commit is contained in:
CMK 2021-07-26 17:31:39 +08:00
parent 4db73d4f74
commit b07a6f8ba9
12 changed files with 502 additions and 10 deletions

View File

@ -1,4 +1,6 @@
{
"NSCameraUsageDescription": "Used to take photo for post status",
"NSPhotoLibraryAddUsageDescription": "Used to save photo into the Photo Library"
}
"NSPhotoLibraryAddUsageDescription": "Used to save photo into the Photo Library",
"NewPostShortcutItemTitle": "New Post",
"SearchShortcutItemTitle": "Search"
}

View File

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1250"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DB427DD125BAA00100D1B89D"
BuildableName = "Mastodon.app"
BlueprintName = "Mastodon"
ReferencedContainer = "container:Mastodon.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "ASDK - Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DB427DE725BAA00100D1B89D"
BuildableName = "MastodonTests.xctest"
BlueprintName = "MastodonTests"
ReferencedContainer = "container:Mastodon.xcodeproj">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DB427DF225BAA00100D1B89D"
BuildableName = "MastodonUITests.xctest"
BlueprintName = "MastodonUITests"
ReferencedContainer = "container:Mastodon.xcodeproj">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DB89B9F525C10FD0008580ED"
BuildableName = "CoreDataStackTests.xctest"
BlueprintName = "CoreDataStackTests"
ReferencedContainer = "container:Mastodon.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "ASDK - Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DB427DD125BAA00100D1B89D"
BuildableName = "Mastodon.app"
BlueprintName = "Mastodon"
ReferencedContainer = "container:Mastodon.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "ASDK - Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DB427DD125BAA00100D1B89D"
BuildableName = "Mastodon.app"
BlueprintName = "Mastodon"
ReferencedContainer = "container:Mastodon.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "ASDK - Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "ASDK - Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -0,0 +1,110 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1250"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DB427DD125BAA00100D1B89D"
BuildableName = "Mastodon.app"
BlueprintName = "Mastodon"
ReferencedContainer = "container:Mastodon.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DB427DE725BAA00100D1B89D"
BuildableName = "MastodonTests.xctest"
BlueprintName = "MastodonTests"
ReferencedContainer = "container:Mastodon.xcodeproj">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DB427DF225BAA00100D1B89D"
BuildableName = "MastodonUITests.xctest"
BlueprintName = "MastodonUITests"
ReferencedContainer = "container:Mastodon.xcodeproj">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DB89B9F525C10FD0008580ED"
BuildableName = "CoreDataStackTests.xctest"
BlueprintName = "CoreDataStackTests"
ReferencedContainer = "container:Mastodon.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
disableMainThreadChecker = "YES"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DB427DD125BAA00100D1B89D"
BuildableName = "Mastodon.app"
BlueprintName = "Mastodon"
ReferencedContainer = "container:Mastodon.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DB427DD125BAA00100D1B89D"
BuildableName = "Mastodon.app"
BlueprintName = "Mastodon"
ReferencedContainer = "container:Mastodon.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1250"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DB427DD125BAA00100D1B89D"
BuildableName = "Mastodon.app"
BlueprintName = "Mastodon"
ReferencedContainer = "container:Mastodon.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DB427DE725BAA00100D1B89D"
BuildableName = "MastodonTests.xctest"
BlueprintName = "MastodonTests"
ReferencedContainer = "container:Mastodon.xcodeproj">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DB427DF225BAA00100D1B89D"
BuildableName = "MastodonUITests.xctest"
BlueprintName = "MastodonUITests"
ReferencedContainer = "container:Mastodon.xcodeproj">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DB89B9F525C10FD0008580ED"
BuildableName = "CoreDataStackTests.xctest"
BlueprintName = "CoreDataStackTests"
ReferencedContainer = "container:Mastodon.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DB427DD125BAA00100D1B89D"
BuildableName = "Mastodon.app"
BlueprintName = "Mastodon"
ReferencedContainer = "container:Mastodon.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DB427DD125BAA00100D1B89D"
BuildableName = "Mastodon.app"
BlueprintName = "Mastodon"
ReferencedContainer = "container:Mastodon.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1250"
wasCreatedForAppExtension = "YES"
version = "2.0">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DBF8AE12263293E400C9C23C"
BuildableName = "NotificationService.appex"
BlueprintName = "NotificationService"
ReferencedContainer = "container:Mastodon.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DB427DD125BAA00100D1B89D"
BuildableName = "Mastodon.app"
BlueprintName = "Mastodon"
ReferencedContainer = "container:Mastodon.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = ""
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
launchStyle = "0"
askForAppToLaunch = "Yes"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES"
launchAutomaticallySubstyle = "2">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DB427DD125BAA00100D1B89D"
BuildableName = "Mastodon.app"
BlueprintName = "Mastodon"
ReferencedContainer = "container:Mastodon.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES"
launchAutomaticallySubstyle = "2">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DB427DD125BAA00100D1B89D"
BuildableName = "Mastodon.app"
BlueprintName = "Mastodon"
ReferencedContainer = "container:Mastodon.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -7,12 +7,12 @@
<key>AppShared.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>24</integer>
<integer>21</integer>
</dict>
<key>CoreDataStack.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>22</integer>
<integer>23</integer>
</dict>
<key>Mastodon - ASDK.xcscheme_^#shared#^_</key>
<dict>
@ -42,7 +42,7 @@
<key>ShareActionExtension.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>21</integer>
<integer>22</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>

View File

@ -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

View File

@ -86,5 +86,24 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIApplicationShortcutItems</key>
<array>
<dict>
<key>UIApplicationShortcutItemType</key>
<string>org.joinmastodon.app.new-post</string>
<key>UIApplicationShortcutItemIconSymbolName</key>
<string>square.and.pencil</string>
<key>UIApplicationShortcutItemTitle</key>
<string>NewPostShortcutItemTitle</string>
</dict>
<dict>
<key>UIApplicationShortcutItemType</key>
<string>org.joinmastodon.app.search</string>
<key>UIApplicationShortcutItemIconSymbolName</key>
<string>magnifyingglass</string>
<key>UIApplicationShortcutItemTitle</key>
<string>SearchShortcutItemTitle</string>
</dict>
</array>
</dict>
</plist>

View File

@ -1,2 +1,4 @@
"NSCameraUsageDescription" = "Used to take photo for post status";
"NSPhotoLibraryAddUsageDescription" = "Used to save photo into the Photo Library";
"NSPhotoLibraryAddUsageDescription" = "Used to save photo into the Photo Library";
"NewPostShortcutItemTitle" = "New Post";
"SearchShortcutItemTitle" = "Search";

View File

@ -1,2 +1,4 @@
"NSCameraUsageDescription" = "Used to take photo for post status";
"NSPhotoLibraryAddUsageDescription" = "Used to save photo into the Photo Library";
"NSPhotoLibraryAddUsageDescription" = "Used to save photo into the Photo Library";
"NewPostShortcutItemTitle" = "New Post";
"SearchShortcutItemTitle" = "Search";

View File

@ -1,2 +0,0 @@
"NSCameraUsageDescription" = "Used to take photo for post status";
"NSPhotoLibraryAddUsageDescription" = "Used to save photo into the Photo Library";

View File

@ -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