mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2024-12-23 15:40:37 +00:00
Add AppIntent service + post to Mastodon intent
This commit is contained in:
parent
abcd4cc321
commit
4e4d903c44
11 changed files with 109 additions and 7 deletions
|
@ -42,6 +42,8 @@
|
|||
9F35DB4729506F6600B3281A /* NotificationTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F35DB4629506F6600B3281A /* NotificationTab.swift */; };
|
||||
9F35DB4A29506FA100B3281A /* Notifications in Frameworks */ = {isa = PBXBuildFile; productRef = 9F35DB4929506FA100B3281A /* Notifications */; };
|
||||
9F35DB4C2952005C00B3281A /* MessagesTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F35DB4B2952005C00B3281A /* MessagesTab.swift */; };
|
||||
9F37BDDB2BE36E22007F28AD /* PostIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F37BDDA2BE36E22007F28AD /* PostIntent.swift */; };
|
||||
9F37BDDD2BE37193007F28AD /* AppIntentService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F37BDDC2BE37193007F28AD /* AppIntentService.swift */; };
|
||||
9F38A7332ACEA26100DBCD66 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 9F38A7322ACEA26100DBCD66 /* Localizable.xcstrings */; };
|
||||
9F38A7342ACEA26100DBCD66 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 9F38A7322ACEA26100DBCD66 /* Localizable.xcstrings */; };
|
||||
9F38A7352ACEA26100DBCD66 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 9F38A7322ACEA26100DBCD66 /* Localizable.xcstrings */; };
|
||||
|
@ -196,6 +198,8 @@
|
|||
9F35DB4629506F6600B3281A /* NotificationTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationTab.swift; sourceTree = "<group>"; };
|
||||
9F35DB4829506F7F00B3281A /* Notifications */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Notifications; path = Packages/Notifications; sourceTree = "<group>"; };
|
||||
9F35DB4B2952005C00B3281A /* MessagesTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessagesTab.swift; sourceTree = "<group>"; };
|
||||
9F37BDDA2BE36E22007F28AD /* PostIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostIntent.swift; sourceTree = "<group>"; };
|
||||
9F37BDDC2BE37193007F28AD /* AppIntentService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppIntentService.swift; sourceTree = "<group>"; };
|
||||
9F38A7322ACEA26100DBCD66 /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = "<group>"; };
|
||||
9F398AA32935F90100A889F2 /* Models */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Models; path = Packages/Models; sourceTree = "<group>"; };
|
||||
9F398AA52935FE8A00A889F2 /* AppRegistry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppRegistry.swift; sourceTree = "<group>"; };
|
||||
|
@ -349,6 +353,15 @@
|
|||
path = IceCubesNotifications;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9F37BDD92BE36E08007F28AD /* IceCubesAppIntents */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9F37BDDA2BE36E22007F28AD /* PostIntent.swift */,
|
||||
9F37BDDC2BE37193007F28AD /* AppIntentService.swift */,
|
||||
);
|
||||
path = IceCubesAppIntents;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9F398AB429360A5800A889F2 /* App */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -454,6 +467,7 @@
|
|||
DD31E2E5297FB68B00A4BE29 /* IceCubesApp.xcconfig */,
|
||||
9F7D939529800B0300EE6B7A /* IceCubesApp-release.xcconfig */,
|
||||
9FBFE63B292A715500C250E9 /* IceCubesApp */,
|
||||
9F37BDD92BE36E08007F28AD /* IceCubesAppIntents */,
|
||||
E9DF41FD29830FEC0003AAD2 /* IceCubesActionExtension */,
|
||||
9F2A5417296AB631009B2D7C /* IceCubesNotifications */,
|
||||
9FAD858929743F7400496AB1 /* IceCubesShareExtension */,
|
||||
|
@ -828,6 +842,8 @@
|
|||
9F15D6042B3DC2180008C220 /* NavigationSheet.swift in Sources */,
|
||||
9FA6FD6229C04A8800E2312C /* TranslationSettingsView.swift in Sources */,
|
||||
9F35DB4C2952005C00B3281A /* MessagesTab.swift in Sources */,
|
||||
9F37BDDB2BE36E22007F28AD /* PostIntent.swift in Sources */,
|
||||
9F37BDDD2BE37193007F28AD /* AppIntentService.swift in Sources */,
|
||||
9FAD85CF2975B68900496AB1 /* SideBarView.swift in Sources */,
|
||||
9FAE4ACB293783B000772766 /* SettingsTab.swift in Sources */,
|
||||
9FC14EF42B494D940006CEE1 /* RemoteTimelinesSettingView.swift in Sources */,
|
||||
|
|
|
@ -85,7 +85,10 @@ extension View {
|
|||
StatusEditor.MainView(mode: .replyTo(status: status))
|
||||
.withEnvironments()
|
||||
case let .newStatusEditor(visibility):
|
||||
StatusEditor.MainView(mode: .new(visibility: visibility))
|
||||
StatusEditor.MainView(mode: .new(text: nil, visibility: visibility))
|
||||
.withEnvironments()
|
||||
case let .prefilledStatusEditor(text, visibility):
|
||||
StatusEditor.MainView(mode: .new(text: text, visibility: visibility))
|
||||
.withEnvironments()
|
||||
case let .editStatusEditor(status):
|
||||
StatusEditor.MainView(mode: .edit(status: status))
|
||||
|
|
|
@ -2,6 +2,7 @@ import Env
|
|||
import MediaUI
|
||||
import StatusKit
|
||||
import SwiftUI
|
||||
import AppIntents
|
||||
|
||||
extension IceCubesApp {
|
||||
var appScene: some Scene {
|
||||
|
@ -22,6 +23,7 @@ extension IceCubesApp {
|
|||
.environment(theme)
|
||||
.environment(watcher)
|
||||
.environment(pushNotificationsService)
|
||||
.environment(appIntentService)
|
||||
.environment(\.isSupporter, isSupporter)
|
||||
.sheet(item: $quickLook.selectedMediaAttachment) { selectedMediaAttachment in
|
||||
MediaUIView(selectedAttachment: selectedMediaAttachment,
|
||||
|
@ -47,6 +49,12 @@ extension IceCubesApp {
|
|||
}
|
||||
}
|
||||
}
|
||||
.onChange(of: appIntentService.handledIntent) { _, _ in
|
||||
if let intent = appIntentService.handledIntent?.intent {
|
||||
handleIntent(intent)
|
||||
appIntentService.handledIntent = nil
|
||||
}
|
||||
}
|
||||
.withModelContainer()
|
||||
}
|
||||
#if targetEnvironment(macCatalyst)
|
||||
|
@ -74,7 +82,9 @@ extension IceCubesApp {
|
|||
Group {
|
||||
switch destination.wrappedValue {
|
||||
case let .newStatusEditor(visibility):
|
||||
StatusEditor.MainView(mode: .new(visibility: visibility))
|
||||
StatusEditor.MainView(mode: .new(text: nil, visibility: visibility))
|
||||
case let .prefilledStatusEditor(text, visibility):
|
||||
StatusEditor.MainView(mode: .new(text: text, visibility: visibility))
|
||||
case let .editStatusEditor(status):
|
||||
StatusEditor.MainView(mode: .edit(status: status))
|
||||
case let .quoteStatusEditor(status):
|
||||
|
@ -115,4 +125,16 @@ extension IceCubesApp {
|
|||
.defaultSize(width: 1200, height: 1000)
|
||||
.windowResizability(.contentMinSize)
|
||||
}
|
||||
|
||||
private func handleIntent(_ intent: any AppIntent) {
|
||||
if let postIntent = appIntentService.handledIntent?.intent as? PostIntent {
|
||||
#if os(visionOS) || os(macOS)
|
||||
openWindow(value: WindowDestinationEditor.prefilledStatusEditor(text: postIntent.content ?? "",
|
||||
visibility: userPreferences.postVisibility))
|
||||
#else
|
||||
appRouterPath.presentedSheet = .prefilledStatusEditor(text: postIntent.content ?? "",
|
||||
visibility: userPreferences.postVisibility)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ struct IceCubesApp: App {
|
|||
@State var currentAccount = CurrentAccount.shared
|
||||
@State var userPreferences = UserPreferences.shared
|
||||
@State var pushNotificationsService = PushNotificationsService.shared
|
||||
@State var appIntentService = AppIntentService.shared
|
||||
@State var watcher = StreamWatcher.shared
|
||||
@State var quickLook = QuickLook.shared
|
||||
@State var theme = Theme.shared
|
||||
|
|
|
@ -39936,6 +39936,12 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Post content" : {
|
||||
|
||||
},
|
||||
"Post to Mastodon" : {
|
||||
|
||||
},
|
||||
"report.action.send" : {
|
||||
"localizations" : {
|
||||
|
@ -80466,6 +80472,9 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Use Ice Cubes to post text to Mastodon" : {
|
||||
|
||||
}
|
||||
},
|
||||
"version" : "1.0"
|
||||
|
|
25
IceCubesAppIntents/AppIntentService.swift
Normal file
25
IceCubesAppIntents/AppIntentService.swift
Normal file
|
@ -0,0 +1,25 @@
|
|||
import SwiftUI
|
||||
import AppIntents
|
||||
|
||||
@Observable
|
||||
public class AppIntentService: @unchecked Sendable {
|
||||
struct HandledIntent: Equatable {
|
||||
static func == (lhs: AppIntentService.HandledIntent, rhs: AppIntentService.HandledIntent) -> Bool {
|
||||
lhs.id == rhs.id
|
||||
}
|
||||
|
||||
let id: String
|
||||
let intent: any AppIntent
|
||||
|
||||
init(intent: any AppIntent) {
|
||||
self.id = UUID().uuidString
|
||||
self.intent = intent
|
||||
}
|
||||
}
|
||||
|
||||
public static let shared = AppIntentService()
|
||||
|
||||
var handledIntent: HandledIntent?
|
||||
|
||||
private init() { }
|
||||
}
|
20
IceCubesAppIntents/PostIntent.swift
Normal file
20
IceCubesAppIntents/PostIntent.swift
Normal file
|
@ -0,0 +1,20 @@
|
|||
import Foundation
|
||||
import AppIntents
|
||||
|
||||
struct PostIntent: AppIntent {
|
||||
static let title: LocalizedStringResource = "Post to Mastodon"
|
||||
static var description: IntentDescription {
|
||||
get {
|
||||
"Use Ice Cubes to post text to Mastodon"
|
||||
}
|
||||
}
|
||||
static let openAppWhenRun: Bool = true
|
||||
|
||||
@Parameter(title: "Post content")
|
||||
var content: String?
|
||||
|
||||
func perform() async throws -> some IntentResult {
|
||||
AppIntentService.shared.handledIntent = .init(intent: self)
|
||||
return .result()
|
||||
}
|
||||
}
|
|
@ -31,6 +31,7 @@ public enum RouterDestination: Hashable {
|
|||
|
||||
public enum WindowDestinationEditor: Hashable, Codable {
|
||||
case newStatusEditor(visibility: Models.Visibility)
|
||||
case prefilledStatusEditor(text: String, visibility: Models.Visibility)
|
||||
case editStatusEditor(status: Status)
|
||||
case replyToStatusEditor(status: Status)
|
||||
case quoteStatusEditor(status: Status)
|
||||
|
@ -52,6 +53,7 @@ public enum SheetDestination: Identifiable, Hashable {
|
|||
}
|
||||
|
||||
case newStatusEditor(visibility: Models.Visibility)
|
||||
case prefilledStatusEditor(text: String, visibility: Models.Visibility)
|
||||
case editStatusEditor(status: Status)
|
||||
case replyToStatusEditor(status: Status)
|
||||
case quoteStatusEditor(status: Status)
|
||||
|
@ -78,7 +80,7 @@ public enum SheetDestination: Identifiable, Hashable {
|
|||
public var id: String {
|
||||
switch self {
|
||||
case .editStatusEditor, .newStatusEditor, .replyToStatusEditor, .quoteStatusEditor,
|
||||
.mentionStatusEditor, .quoteLinkStatusEditor:
|
||||
.mentionStatusEditor, .quoteLinkStatusEditor, .prefilledStatusEditor:
|
||||
"statusEditor"
|
||||
case .listCreate:
|
||||
"listCreate"
|
||||
|
|
|
@ -161,7 +161,7 @@ extension StatusEditor {
|
|||
|
||||
Button {
|
||||
// all SEVM have the same visibility value
|
||||
followUpSEVMs.append(ViewModel(mode: .new(visibility: focusedSEVM.visibility)))
|
||||
followUpSEVMs.append(ViewModel(mode: .new(text: nil, visibility: focusedSEVM.visibility)))
|
||||
} label: {
|
||||
Image(systemName: "arrowshape.turn.up.left.circle.fill")
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import UIKit
|
|||
public extension StatusEditor.ViewModel {
|
||||
enum Mode {
|
||||
case replyTo(status: Status)
|
||||
case new(visibility: Models.Visibility)
|
||||
case new(text: String?, visibility: Models.Visibility)
|
||||
case edit(status: Status)
|
||||
case quote(status: Status)
|
||||
case quoteLink(link: URL)
|
||||
|
|
|
@ -301,7 +301,11 @@ public extension StatusEditor {
|
|||
|
||||
func prepareStatusText() {
|
||||
switch mode {
|
||||
case let .new(visibility):
|
||||
case let .new(text, visibility):
|
||||
if let text {
|
||||
statusText = .init(string: text)
|
||||
selectedRange = .init(location: text.utf16.count, length: 0)
|
||||
}
|
||||
self.visibility = visibility
|
||||
case let .shareExtension(items):
|
||||
itemsProvider = items
|
||||
|
@ -557,7 +561,7 @@ public extension StatusEditor {
|
|||
!statusText.string.contains(url.absoluteString)
|
||||
{
|
||||
embeddedStatus = nil
|
||||
mode = .new(visibility: visibility)
|
||||
mode = .new(text: nil, visibility: visibility)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue