diff --git a/Base.lproj/Intents.intentdefinition b/Base.lproj/Intents.intentdefinition new file mode 100644 index 000000000..df98e3ab2 --- /dev/null +++ b/Base.lproj/Intents.intentdefinition @@ -0,0 +1,402 @@ + + + + + INEnums + + + INEnumDisplayName + Post Visibility + INEnumDisplayNameID + Zo4jgJ + INEnumGeneratesHeader + + INEnumName + PostVisibility + INEnumType + Regular + INEnumValues + + + INEnumValueDisplayName + unknown + INEnumValueDisplayNameID + cQxbPW + INEnumValueName + unknown + + + INEnumValueDisplayName + Public + INEnumValueDisplayNameID + dYQ5NN + INEnumValueIndex + 1 + INEnumValueName + public + + + INEnumValueDisplayName + Followers Only + INEnumValueDisplayNameID + ehFLjY + INEnumValueIndex + 2 + INEnumValueName + followersOnly + + + + + INIntentDefinitionModelVersion + 1.2 + INIntentDefinitionNamespace + BvMBE4 + INIntentDefinitionSystemVersion + 20G71 + INIntentDefinitionToolsBuildVersion + 12E507 + INIntentDefinitionToolsVersion + 12.5.1 + INIntents + + + INIntentCategory + share + INIntentConfigurable + + INIntentDescription + Send Post with text content + INIntentDescriptionID + RHxKOw + INIntentInput + content + INIntentKeyParameter + content + INIntentLastParameterTag + 3 + INIntentManagedParameterCombinations + + content,visibility + + INIntentParameterCombinationSupportsBackgroundExecution + + INIntentParameterCombinationTitle + Post ${content} on Mastodon + INIntentParameterCombinationTitleID + WCIR3D + INIntentParameterCombinationUpdatesLinked + + + + INIntentName + SendPost + INIntentParameterCombinations + + content + + INIntentParameterCombinationSubtitle + ${content} + INIntentParameterCombinationSubtitleID + ZS1XaK + INIntentParameterCombinationSupportsBackgroundExecution + + INIntentParameterCombinationTitle + Post + INIntentParameterCombinationTitleID + CsR7G2 + + content,visibility + + INIntentParameterCombinationIsPrimary + + INIntentParameterCombinationSubtitle + ${content}, ${visibility} + INIntentParameterCombinationSubtitleID + ayoYEb + INIntentParameterCombinationSupportsBackgroundExecution + + INIntentParameterCombinationTitle + Post + INIntentParameterCombinationTitleID + dUyuGg + + + INIntentParameters + + + INIntentParameterConfigurable + + INIntentParameterCustomDisambiguation + + INIntentParameterDisplayName + Text Content + INIntentParameterDisplayNameID + 751xkl + INIntentParameterDisplayPriority + 1 + INIntentParameterMetadata + + INIntentParameterMetadataCapitalization + Sentences + INIntentParameterMetadataDefaultValueID + odzH7f + INIntentParameterMetadataMultiline + + + INIntentParameterName + content + INIntentParameterPromptDialogs + + + INIntentParameterPromptDialogCustom + + INIntentParameterPromptDialogType + Configuration + + + INIntentParameterPromptDialogCustom + + INIntentParameterPromptDialogFormatString + What content to post? + INIntentParameterPromptDialogFormatStringID + HZSGTr + INIntentParameterPromptDialogType + Primary + + + INIntentParameterSupportsResolution + + INIntentParameterTag + 1 + INIntentParameterType + String + + + INIntentParameterConfigurable + + INIntentParameterCustomDisambiguation + + INIntentParameterDisplayName + Visibility + INIntentParameterDisplayNameID + ZbSjzC + INIntentParameterDisplayPriority + 2 + INIntentParameterEnumType + PostVisibility + INIntentParameterEnumTypeNamespace + BvMBE4 + INIntentParameterMetadata + + INIntentParameterMetadataDefaultValue + public + + INIntentParameterName + visibility + INIntentParameterPromptDialogs + + + INIntentParameterPromptDialogCustom + + INIntentParameterPromptDialogType + Configuration + + + INIntentParameterPromptDialogCustom + + INIntentParameterPromptDialogType + Primary + + + INIntentParameterPromptDialogCustom + + INIntentParameterPromptDialogFormatString + There are ${count} options matching ‘${visibility}’. + INIntentParameterPromptDialogFormatStringID + apSxMG + INIntentParameterPromptDialogType + DisambiguationIntroduction + + + INIntentParameterPromptDialogCustom + + INIntentParameterPromptDialogFormatString + Just to confirm, you wanted ‘${visibility}’? + INIntentParameterPromptDialogFormatStringID + oGiqmY + INIntentParameterPromptDialogType + Confirmation + + + INIntentParameterSupportsResolution + + INIntentParameterTag + 3 + INIntentParameterType + Integer + + + INIntentResponse + + INIntentResponseCodes + + + INIntentResponseCodeConciseFormatString + Post was sent successfully. + INIntentResponseCodeConciseFormatStringID + k7dbKQ + INIntentResponseCodeFormatString + Post was sent successfully. + INIntentResponseCodeFormatStringID + ryJLwG + INIntentResponseCodeName + success + INIntentResponseCodeSuccess + + + + INIntentResponseCodeConciseFormatString + Posting failed + INIntentResponseCodeConciseFormatStringID + HdGikU + INIntentResponseCodeFormatString + Posting failed. ${failureReason} + INIntentResponseCodeFormatStringID + gfePDu + INIntentResponseCodeName + failure + + + INIntentResponseLastParameterTag + 7 + INIntentResponseOutput + post + INIntentResponseParameters + + + INIntentResponseParameterDisplayName + Post + INIntentResponseParameterDisplayNameID + ZKJSNu + INIntentResponseParameterDisplayPriority + 1 + INIntentResponseParameterName + post + INIntentResponseParameterObjectType + Post + INIntentResponseParameterObjectTypeNamespace + BvMBE4 + INIntentResponseParameterTag + 6 + INIntentResponseParameterType + Object + + + INIntentResponseParameterDisplayName + Failure Reason + INIntentResponseParameterDisplayNameID + KDNTJ4 + INIntentResponseParameterDisplayPriority + 2 + INIntentResponseParameterName + failureReason + INIntentResponseParameterTag + 7 + INIntentResponseParameterType + String + + + + INIntentTitle + Post on Mastodon + INIntentTitleID + 16wxgf + INIntentType + Custom + INIntentVerb + Post + + + INTypes + + + INTypeDisplayName + Post + INTypeDisplayNameID + RxSqsb + INTypeLastPropertyTag + 102 + INTypeName + Post + INTypeProperties + + + INTypePropertyDefault + + INTypePropertyDisplayPriority + 1 + INTypePropertyName + identifier + INTypePropertyTag + 1 + INTypePropertyType + String + + + INTypePropertyDefault + + INTypePropertyDisplayPriority + 2 + INTypePropertyName + displayString + INTypePropertyTag + 2 + INTypePropertyType + String + + + INTypePropertyDefault + + INTypePropertyDisplayPriority + 3 + INTypePropertyName + pronunciationHint + INTypePropertyTag + 3 + INTypePropertyType + String + + + INTypePropertyDefault + + INTypePropertyDisplayPriority + 4 + INTypePropertyName + alternativeSpeakableMatches + INTypePropertySupportsMultipleValues + + INTypePropertyTag + 4 + INTypePropertyType + SpeakableString + + + INTypePropertyDisplayName + URL + INTypePropertyDisplayNameID + rM6dvp + INTypePropertyDisplayPriority + 5 + INTypePropertyName + url + INTypePropertyTag + 101 + INTypePropertyType + URL + + + + + + diff --git a/CoreDataStack/Entity/HomeTimelineIndex.swift b/CoreDataStack/Entity/HomeTimelineIndex.swift index 10b00aaa0..d52d0c3cd 100644 --- a/CoreDataStack/Entity/HomeTimelineIndex.swift +++ b/CoreDataStack/Entity/HomeTimelineIndex.swift @@ -65,7 +65,7 @@ extension HomeTimelineIndex { public let domain: String public let userID: String - public init(domain: String,userID: String) { + public init(domain: String, userID: String) { self.identifier = UUID().uuidString + "@" + domain self.domain = domain self.userID = userID @@ -80,10 +80,20 @@ extension HomeTimelineIndex: Managed { } extension HomeTimelineIndex { - public static func predicate(userID: String) -> NSPredicate { + static func predicate(domain: String) -> NSPredicate { + return NSPredicate(format: "%K == %@", #keyPath(HomeTimelineIndex.domain), domain) + } + + static func predicate(userID: MastodonUser.ID) -> NSPredicate { return NSPredicate(format: "%K == %@", #keyPath(HomeTimelineIndex.userID), userID) } - + + public static func predicate(domain: String, userID: MastodonUser.ID) -> NSPredicate { + return NSCompoundPredicate(andPredicateWithSubpredicates: [ + predicate(domain: domain), + predicate(userID: userID) + ]) + } public static func notDeleted() -> NSPredicate { return NSPredicate(format: "%K == nil", #keyPath(HomeTimelineIndex.deletedAt)) diff --git a/Localization/ios-infoPlist.json b/Localization/ios-infoPlist.json index f25dbcc0e..c6db73de0 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/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index f1351b859..e4b6635c0 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -175,6 +175,9 @@ 5E44BF88AD33646E64727BCF /* Pods_MastodonTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD92E0F10BDE4FE7C4B999F2 /* Pods_MastodonTests.framework */; }; 87FFDA5D898A5C42ADCB35E7 /* Pods_Mastodon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A4ABE34829701A4496C5BB64 /* Pods_Mastodon.framework */; }; B914FC6B0B8AF18573C0B291 /* Pods_NotificationService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 374AA339A20E0FAC75BCDA6D /* Pods_NotificationService.framework */; }; + BBAC710E327AF1EE1DB36A4E /* Pods_MastodonIntent.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F4C94BD75C96D0EFF5F6D961 /* Pods_MastodonIntent.framework */; }; + DB0009A626AEE5DC009B9D2D /* Intents.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = DB0009A926AEE5DC009B9D2D /* Intents.intentdefinition */; settings = {ATTRIBUTES = (no_codegen, ); }; }; + DB0009A726AEE5DC009B9D2D /* Intents.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = DB0009A926AEE5DC009B9D2D /* Intents.intentdefinition */; }; DB00CA972632DDB600A54956 /* CommonOSLog in Frameworks */ = {isa = PBXBuildFile; productRef = DB00CA962632DDB600A54956 /* CommonOSLog */; }; DB0140BD25C40D7500F9F3CF /* CommonOSLog in Frameworks */ = {isa = PBXBuildFile; productRef = DB0140BC25C40D7500F9F3CF /* CommonOSLog */; }; DB0140CF25C42AEE00F9F3CF /* OSLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0140CE25C42AEE00F9F3CF /* OSLog.swift */; }; @@ -374,6 +377,11 @@ DB8AF55025C13703002E6C99 /* MainTabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8AF54F25C13703002E6C99 /* MainTabBarController.swift */; }; DB8AF55D25C138B7002E6C99 /* UIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8AF55C25C138B7002E6C99 /* UIViewController.swift */; }; DB8AF56825C13E2A002E6C99 /* HomeTimelineIndex.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8AF56725C13E2A002E6C99 /* HomeTimelineIndex.swift */; }; + DB8FABC726AEC7B2008E5AF4 /* Intents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DB8FAB9E26AEC3A2008E5AF4 /* Intents.framework */; }; + DB8FABCA26AEC7B2008E5AF4 /* IntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8FABC926AEC7B2008E5AF4 /* IntentHandler.swift */; }; + DB8FABCE26AEC7B2008E5AF4 /* MastodonIntent.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = DB8FABC626AEC7B2008E5AF4 /* MastodonIntent.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + DB8FABD726AEC873008E5AF4 /* AppShared.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DB68047F2637CD4C00430867 /* AppShared.framework */; }; + DB8FABDC26AEC87B008E5AF4 /* CoreDataStack.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DB89B9EE25C10FD0008580ED /* CoreDataStack.framework */; }; DB9282B225F3222800823B15 /* PickServerEmptyStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB9282B125F3222800823B15 /* PickServerEmptyStateView.swift */; }; DB92CF7225E7BB98002C1017 /* PollOptionTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB92CF7125E7BB98002C1017 /* PollOptionTableViewCell.swift */; }; DB938EE62623F50700E5B6C1 /* ThreadViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB938EE52623F50700E5B6C1 /* ThreadViewController.swift */; }; @@ -455,6 +463,17 @@ DBB525642612C988002F1F29 /* MeProfileViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB525632612C988002F1F29 /* MeProfileViewModel.swift */; }; DBB5256E2612D5A1002F1F29 /* ProfileStatusDashboardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB5256D2612D5A1002F1F29 /* ProfileStatusDashboardView.swift */; }; DBB525852612D6DD002F1F29 /* ProfileStatusDashboardMeterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB525842612D6DD002F1F29 /* ProfileStatusDashboardMeterView.swift */; }; + DBB8AB4626AECDE200F6D281 /* SendPostIntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB8AB4526AECDE200F6D281 /* SendPostIntentHandler.swift */; }; + DBB8AB4826AED09C00F6D281 /* MastodonSDK in Frameworks */ = {isa = PBXBuildFile; productRef = DBB8AB4726AED09C00F6D281 /* MastodonSDK */; }; + DBB8AB4A26AED0B500F6D281 /* APIService.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB8AB4926AED0B500F6D281 /* APIService.swift */; }; + DBB8AB4C26AED11300F6D281 /* APIService+APIError.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB98337E25C9452D00AD9700 /* APIService+APIError.swift */; }; + DBB8AB4D26AED12B00F6D281 /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB98338525C945ED00AD9700 /* Strings.swift */; }; + DBB8AB4E26AED12E00F6D281 /* Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB98338625C945ED00AD9700 /* Assets.swift */; }; + DBB8AB4F26AED13F00F6D281 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DB427DDE25BAA00100D1B89D /* Assets.xcassets */; }; + DBB8AB5026AED14400F6D281 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = DB564BCE269F2F83001E39A7 /* Localizable.stringsdict */; }; + DBB8AB5126AED14600F6D281 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = DB3D100F25BAA75E00EAA174 /* Localizable.strings */; }; + DBB8AB5226AED1B300F6D281 /* APIService+Status+Publish.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBFEF07A26A6BCE8006D7ED1 /* APIService+Status+Publish.swift */; }; + DBB8AB5326AED25100F6D281 /* MastodonAuthenticationBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBFEF07626A691FB006D7ED1 /* MastodonAuthenticationBox.swift */; }; DBB9759C262462E1004620BD /* ThreadMetaView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB9759B262462E1004620BD /* ThreadMetaView.swift */; }; DBBC24A826A52F9000398BB9 /* ComposeToolbarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBBC24A726A52F9000398BB9 /* ComposeToolbarView.swift */; }; DBBC24AA26A5301B00398BB9 /* MastodonSDK in Frameworks */ = {isa = PBXBuildFile; productRef = DBBC24A926A5301B00398BB9 /* MastodonSDK */; }; @@ -624,6 +643,27 @@ remoteGlobalIDString = DB89B9ED25C10FD0008580ED; remoteInfo = CoreDataStack; }; + DB8FABCC26AEC7B2008E5AF4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DB427DCA25BAA00100D1B89D /* Project object */; + proxyType = 1; + remoteGlobalIDString = DB8FABC526AEC7B2008E5AF4; + remoteInfo = MastodonIntent; + }; + DB8FABD926AEC873008E5AF4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DB427DCA25BAA00100D1B89D /* Project object */; + proxyType = 1; + remoteGlobalIDString = DB68047E2637CD4C00430867; + remoteInfo = AppShared; + }; + DB8FABDE26AEC87B008E5AF4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DB427DCA25BAA00100D1B89D /* Project object */; + proxyType = 1; + remoteGlobalIDString = DB89B9ED25C10FD0008580ED; + remoteInfo = CoreDataStack; + }; DBC6461A26A170AB00B0E31B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DB427DCA25BAA00100D1B89D /* Project object */; @@ -673,6 +713,7 @@ dstPath = ""; dstSubfolderSpec = 13; files = ( + DB8FABCE26AEC7B2008E5AF4 /* MastodonIntent.appex in Embed App Extensions */, DBC6461C26A170AB00B0E31B /* ShareActionExtension.appex in Embed App Extensions */, DBF8AE1A263293E400C9C23C /* NotificationService.appex in Embed App Extensions */, ); @@ -703,6 +744,7 @@ 0FB3D31D25E534C700AAD544 /* PickServerCategoryCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PickServerCategoryCollectionViewCell.swift; sourceTree = ""; }; 0FB3D33125E5F50E00AAD544 /* PickServerSearchCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PickServerSearchCell.swift; sourceTree = ""; }; 0FB3D33725E6401400AAD544 /* PickServerCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PickServerCell.swift; sourceTree = ""; }; + 159AC43EFE0A1F95FCB358A4 /* Pods-MastodonIntent.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MastodonIntent.release.xcconfig"; path = "Target Support Files/Pods-MastodonIntent/Pods-MastodonIntent.release.xcconfig"; sourceTree = ""; }; 164F0EBB267D4FE400249499 /* BoopSound.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = BoopSound.caf; sourceTree = ""; }; 1D6D967E77A5357E2C6110D9 /* Pods-Mastodon.asdk - debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon.asdk - debug.xcconfig"; path = "Target Support Files/Pods-Mastodon/Pods-Mastodon.asdk - debug.xcconfig"; sourceTree = ""; }; 2D04F42425C255B9003F936F /* APIService+PublicTimeline.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+PublicTimeline.swift"; sourceTree = ""; }; @@ -856,6 +898,7 @@ 77EE917BC055E6621C0452B6 /* Pods-ShareActionExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShareActionExtension.debug.xcconfig"; path = "Target Support Files/Pods-ShareActionExtension/Pods-ShareActionExtension.debug.xcconfig"; sourceTree = ""; }; 7CEFFAE9AF9284B13C0A758D /* Pods-MastodonTests.asdk - debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MastodonTests.asdk - debug.xcconfig"; path = "Target Support Files/Pods-MastodonTests/Pods-MastodonTests.asdk - debug.xcconfig"; sourceTree = ""; }; 819CEC9DCAD8E8E7BD85A7BB /* Pods-Mastodon.asdk.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon.asdk.xcconfig"; path = "Target Support Files/Pods-Mastodon/Pods-Mastodon.asdk.xcconfig"; sourceTree = ""; }; + 861BE60ED27430771CFD578D /* Pods-MastodonIntent.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MastodonIntent.debug.xcconfig"; path = "Target Support Files/Pods-MastodonIntent/Pods-MastodonIntent.debug.xcconfig"; sourceTree = ""; }; 8850E70A1D5FF51432E43653 /* Pods-Mastodon-MastodonUITests.asdk - release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-MastodonUITests.asdk - release.xcconfig"; path = "Target Support Files/Pods-Mastodon-MastodonUITests/Pods-Mastodon-MastodonUITests.asdk - release.xcconfig"; sourceTree = ""; }; 8ED8C4B1F1BA2DCFF2926BB1 /* Pods-Mastodon-NotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-NotificationService.debug.xcconfig"; path = "Target Support Files/Pods-Mastodon-NotificationService/Pods-Mastodon-NotificationService.debug.xcconfig"; sourceTree = ""; }; 9553C689FFA9EBC880CAB78D /* Pods-NotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.debug.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.debug.xcconfig"; sourceTree = ""; }; @@ -872,8 +915,12 @@ B44342AC2B6585F8295F1DDF /* Pods-Mastodon-NotificationService.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-NotificationService.release.xcconfig"; path = "Target Support Files/Pods-Mastodon-NotificationService/Pods-Mastodon-NotificationService.release.xcconfig"; sourceTree = ""; }; BB482D32A7B9825BF5327C4F /* Pods-Mastodon-MastodonUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-MastodonUITests.release.xcconfig"; path = "Target Support Files/Pods-Mastodon-MastodonUITests/Pods-Mastodon-MastodonUITests.release.xcconfig"; sourceTree = ""; }; BD7598A87F4497045EDEF252 /* Pods-Mastodon.asdk - release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon.asdk - release.xcconfig"; path = "Target Support Files/Pods-Mastodon/Pods-Mastodon.asdk - release.xcconfig"; sourceTree = ""; }; + C3789232A52F43529CA67E95 /* Pods-MastodonIntent.asdk - debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MastodonIntent.asdk - debug.xcconfig"; path = "Target Support Files/Pods-MastodonIntent/Pods-MastodonIntent.asdk - debug.xcconfig"; sourceTree = ""; }; CD92E0F10BDE4FE7C4B999F2 /* Pods_MastodonTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MastodonTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D7D7CF93E262178800077512 /* Pods-Mastodon-AppShared.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-AppShared.debug.xcconfig"; path = "Target Support Files/Pods-Mastodon-AppShared/Pods-Mastodon-AppShared.debug.xcconfig"; sourceTree = ""; }; + DB0009A826AEE5DC009B9D2D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.intentdefinition; name = Base; path = Base.lproj/Intents.intentdefinition; sourceTree = ""; }; + DB0009AB26AEE5E3009B9D2D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Intents.strings; sourceTree = ""; }; + DB0009AD26AEE5E4009B9D2D /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Intents.strings; sourceTree = ""; }; DB0140CE25C42AEE00F9F3CF /* OSLog.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OSLog.swift; sourceTree = ""; }; DB023294267F0AB800031745 /* ASMetaEditableTextNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASMetaEditableTextNode.swift; sourceTree = ""; }; DB029E94266A20430062874E /* MastodonAuthenticationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonAuthenticationController.swift; sourceTree = ""; }; @@ -923,7 +970,6 @@ DB3667A7268AE2900027D07F /* ComposeStatusPollItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeStatusPollItem.swift; sourceTree = ""; }; DB3D0FED25BAA42200EAA174 /* MastodonSDK */ = {isa = PBXFileReference; lastKnownFileType = folder; path = MastodonSDK; sourceTree = ""; }; DB3D100E25BAA75E00EAA174 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; - DB3F693926AA97BD00C883AB /* MetaTextKit */ = {isa = PBXFileReference; lastKnownFileType = folder; name = MetaTextKit; path = ../MetaTextKit; sourceTree = ""; }; DB427DD225BAA00100D1B89D /* Mastodon.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Mastodon.app; sourceTree = BUILT_PRODUCTS_DIR; }; DB427DD525BAA00100D1B89D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; DB427DD725BAA00100D1B89D /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -1075,6 +1121,12 @@ DB8AF54F25C13703002E6C99 /* MainTabBarController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainTabBarController.swift; sourceTree = ""; }; DB8AF55C25C138B7002E6C99 /* UIViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIViewController.swift; sourceTree = ""; }; DB8AF56725C13E2A002E6C99 /* HomeTimelineIndex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeTimelineIndex.swift; sourceTree = ""; }; + DB8FAB9E26AEC3A2008E5AF4 /* Intents.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Intents.framework; path = System/Library/Frameworks/Intents.framework; sourceTree = SDKROOT; }; + DB8FABA926AEC3A2008E5AF4 /* IntentsUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IntentsUI.framework; path = System/Library/Frameworks/IntentsUI.framework; sourceTree = SDKROOT; }; + DB8FABC626AEC7B2008E5AF4 /* MastodonIntent.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = MastodonIntent.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + DB8FABC926AEC7B2008E5AF4 /* IntentHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntentHandler.swift; sourceTree = ""; }; + DB8FABCB26AEC7B2008E5AF4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DB8FABD626AEC864008E5AF4 /* MastodonIntent.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = MastodonIntent.entitlements; sourceTree = ""; }; DB9282B125F3222800823B15 /* PickServerEmptyStateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PickServerEmptyStateView.swift; sourceTree = ""; }; DB92CF7125E7BB98002C1017 /* PollOptionTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollOptionTableViewCell.swift; sourceTree = ""; }; DB938EE52623F50700E5B6C1 /* ThreadViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadViewController.swift; sourceTree = ""; }; @@ -1150,6 +1202,8 @@ DBB525632612C988002F1F29 /* MeProfileViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeProfileViewModel.swift; sourceTree = ""; }; DBB5256D2612D5A1002F1F29 /* ProfileStatusDashboardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileStatusDashboardView.swift; sourceTree = ""; }; DBB525842612D6DD002F1F29 /* ProfileStatusDashboardMeterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileStatusDashboardMeterView.swift; sourceTree = ""; }; + DBB8AB4526AECDE200F6D281 /* SendPostIntentHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendPostIntentHandler.swift; sourceTree = ""; }; + DBB8AB4926AED0B500F6D281 /* APIService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APIService.swift; sourceTree = ""; }; DBB9759B262462E1004620BD /* ThreadMetaView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadMetaView.swift; sourceTree = ""; }; DBBC24A726A52F9000398BB9 /* ComposeToolbarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeToolbarView.swift; sourceTree = ""; }; DBBC24AB26A53D9300398BB9 /* ComposeStatusContentTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeStatusContentTableViewCell.swift; sourceTree = ""; }; @@ -1238,6 +1292,8 @@ EE13214BC0246BE5210CCC10 /* Pods-AppShared.asdk.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AppShared.asdk.xcconfig"; path = "Target Support Files/Pods-AppShared/Pods-AppShared.asdk.xcconfig"; sourceTree = ""; }; F31E7502A7E3945B98C6CBAF /* Pods-NotificationService.asdk.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.asdk.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.asdk.xcconfig"; sourceTree = ""; }; F4A2A2D7000E477CA459ADA9 /* Pods_AppShared.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AppShared.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + F4C94BD75C96D0EFF5F6D961 /* Pods_MastodonIntent.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MastodonIntent.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + F920AD4EC23B0D00F5CCA58E /* Pods-MastodonIntent.asdk - release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MastodonIntent.asdk - release.xcconfig"; path = "Target Support Files/Pods-MastodonIntent/Pods-MastodonIntent.asdk - release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -1309,6 +1365,18 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + DB8FABC326AEC7B2008E5AF4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DB8FABC726AEC7B2008E5AF4 /* Intents.framework in Frameworks */, + DB8FABDC26AEC87B008E5AF4 /* CoreDataStack.framework in Frameworks */, + DBB8AB4826AED09C00F6D281 /* MastodonSDK in Frameworks */, + DB8FABD726AEC873008E5AF4 /* AppShared.framework in Frameworks */, + BBAC710E327AF1EE1DB36A4E /* Pods_MastodonIntent.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; DBC6460F26A170AB00B0E31B /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -1442,6 +1510,10 @@ 6130CBE4B26E3C976ACC1688 /* Pods-ShareActionExtension.asdk - debug.xcconfig */, 5CE45680252519F42FEA2D13 /* Pods-ShareActionExtension.asdk - release.xcconfig */, 95AD0663479892A2109EEFD0 /* Pods-ShareActionExtension.release.xcconfig */, + 861BE60ED27430771CFD578D /* Pods-MastodonIntent.debug.xcconfig */, + C3789232A52F43529CA67E95 /* Pods-MastodonIntent.asdk - debug.xcconfig */, + F920AD4EC23B0D00F5CCA58E /* Pods-MastodonIntent.asdk - release.xcconfig */, + 159AC43EFE0A1F95FCB358A4 /* Pods-MastodonIntent.release.xcconfig */, ); path = Pods; sourceTree = ""; @@ -1789,6 +1861,9 @@ F4A2A2D7000E477CA459ADA9 /* Pods_AppShared.framework */, 374AA339A20E0FAC75BCDA6D /* Pods_NotificationService.framework */, A32B0CACBF35F4CC3CFAA043 /* Pods_ShareActionExtension.framework */, + DB8FAB9E26AEC3A2008E5AF4 /* Intents.framework */, + DB8FABA926AEC3A2008E5AF4 /* IntentsUI.framework */, + F4C94BD75C96D0EFF5F6D961 /* Pods_MastodonIntent.framework */, ); name = Frameworks; sourceTree = ""; @@ -1958,9 +2033,9 @@ DB427DC925BAA00100D1B89D = { isa = PBXGroup; children = ( + DB0009A926AEE5DC009B9D2D /* Intents.intentdefinition */, DBF53F5F25C14E88008AAC7B /* Mastodon.xctestplan */, DBF53F6025C14E9D008AAC7B /* MastodonSDK.xctestplan */, - DB3F693926AA97BD00C883AB /* MetaTextKit */, DB3D0FED25BAA42200EAA174 /* MastodonSDK */, DB427DD425BAA00100D1B89D /* Mastodon */, DB427DEB25BAA00100D1B89D /* MastodonTests */, @@ -1970,6 +2045,7 @@ DB89B9FC25C10FD0008580ED /* CoreDataStackTests */, DBF8AE14263293E400C9C23C /* NotificationService */, DBC6461326A170AB00B0E31B /* ShareActionExtension */, + DB8FABC826AEC7B2008E5AF4 /* MastodonIntent */, DB427DD325BAA00100D1B89D /* Products */, 1EBA4F56E920856A3FC84ACB /* Pods */, 3FE14AD363ED19AE7FF210A6 /* Frameworks */, @@ -1988,6 +2064,7 @@ DBF8AE13263293E400C9C23C /* NotificationService.appex */, DB68047F2637CD4C00430867 /* AppShared.framework */, DBC6461226A170AB00B0E31B /* ShareActionExtension.appex */, + DB8FABC626AEC7B2008E5AF4 /* MastodonIntent.appex */, ); name = Products; sourceTree = ""; @@ -2519,6 +2596,18 @@ path = Extension; sourceTree = ""; }; + DB8FABC826AEC7B2008E5AF4 /* MastodonIntent */ = { + isa = PBXGroup; + children = ( + DB8FABD626AEC864008E5AF4 /* MastodonIntent.entitlements */, + DB8FABC926AEC7B2008E5AF4 /* IntentHandler.swift */, + DBB8AB4526AECDE200F6D281 /* SendPostIntentHandler.swift */, + DBB8AB4B26AED0B800F6D281 /* Service */, + DB8FABCB26AEC7B2008E5AF4 /* Info.plist */, + ); + path = MastodonIntent; + sourceTree = ""; + }; DB938EEB2623F52600E5B6C1 /* Thread */ = { isa = PBXGroup; children = ( @@ -2742,6 +2831,14 @@ path = View; sourceTree = ""; }; + DBB8AB4B26AED0B800F6D281 /* Service */ = { + isa = PBXGroup; + children = ( + DBB8AB4926AED0B500F6D281 /* APIService.swift */, + ); + path = Service; + sourceTree = ""; + }; DBBC24BD26A5441A00398BB9 /* ThemeService */ = { isa = PBXGroup; children = ( @@ -2965,6 +3062,7 @@ DB6804852637CD4C00430867 /* PBXTargetDependency */, DB6804CA2637CE3000430867 /* PBXTargetDependency */, DBC6461B26A170AB00B0E31B /* PBXTargetDependency */, + DB8FABCD26AEC7B2008E5AF4 /* PBXTargetDependency */, ); name = Mastodon; packageProductDependencies = ( @@ -3087,6 +3185,29 @@ productReference = DB89B9F625C10FD0008580ED /* CoreDataStackTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; + DB8FABC526AEC7B2008E5AF4 /* MastodonIntent */ = { + isa = PBXNativeTarget; + buildConfigurationList = DB8FABCF26AEC7B2008E5AF4 /* Build configuration list for PBXNativeTarget "MastodonIntent" */; + buildPhases = ( + 625308CC94CCF528BD373740 /* [CP] Check Pods Manifest.lock */, + DB8FABC226AEC7B2008E5AF4 /* Sources */, + DB8FABC326AEC7B2008E5AF4 /* Frameworks */, + DB8FABC426AEC7B2008E5AF4 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + DB8FABDA26AEC873008E5AF4 /* PBXTargetDependency */, + DB8FABDF26AEC87B008E5AF4 /* PBXTargetDependency */, + ); + name = MastodonIntent; + packageProductDependencies = ( + DBB8AB4726AED09C00F6D281 /* MastodonSDK */, + ); + productName = MastodonIntent; + productReference = DB8FABC626AEC7B2008E5AF4 /* MastodonIntent.appex */; + productType = "com.apple.product-type.app-extension"; + }; DBC6461126A170AB00B0E31B /* ShareActionExtension */ = { isa = PBXNativeTarget; buildConfigurationList = DBC6462126A170AB00B0E31B /* Build configuration list for PBXNativeTarget "ShareActionExtension" */; @@ -3171,6 +3292,9 @@ CreatedOnToolsVersion = 12.4; TestTargetID = DB427DD125BAA00100D1B89D; }; + DB8FABC526AEC7B2008E5AF4 = { + CreatedOnToolsVersion = 12.5.1; + }; DBC6461126A170AB00B0E31B = { CreatedOnToolsVersion = 12.5.1; }; @@ -3217,6 +3341,7 @@ DB89B9F525C10FD0008580ED /* CoreDataStackTests */, DBF8AE12263293E400C9C23C /* NotificationService */, DBC6461126A170AB00B0E31B /* ShareActionExtension */, + DB8FABC526AEC7B2008E5AF4 /* MastodonIntent */, ); }; /* End PBXProject section */ @@ -3273,6 +3398,16 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + DB8FABC426AEC7B2008E5AF4 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DBB8AB4F26AED13F00F6D281 /* Assets.xcassets in Resources */, + DBB8AB5126AED14600F6D281 /* Localizable.strings in Resources */, + DBB8AB5026AED14400F6D281 /* Localizable.stringsdict in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; DBC6461026A170AB00B0E31B /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -3333,6 +3468,28 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Mastodon/Pods-Mastodon-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; + 625308CC94CCF528BD373740 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-MastodonIntent-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 641DEA63EE5B048C9A551302 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -3700,6 +3857,7 @@ DB4481CC25EE2AFE00BEFB67 /* PollItem.swift in Sources */, DB44767B260B3B8C00B66B82 /* CustomEmojiPickerInputView.swift in Sources */, 0F20222D261457EE000C64BF /* HashtagTimelineViewModel+LoadOldestState.swift in Sources */, + DB0009A626AEE5DC009B9D2D /* Intents.intentdefinition in Sources */, 5B90C462262599800002E742 /* SettingsSectionHeader.swift in Sources */, DB44768B260B3F2100B66B82 /* CustomEmojiPickerItem.swift in Sources */, 2DF75BA125D0E29D00694EC8 /* StatusProvider+StatusTableViewCellDelegate.swift in Sources */, @@ -3982,6 +4140,22 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + DB8FABC226AEC7B2008E5AF4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DB0009A726AEE5DC009B9D2D /* Intents.intentdefinition in Sources */, + DBB8AB4E26AED12E00F6D281 /* Assets.swift in Sources */, + DBB8AB4626AECDE200F6D281 /* SendPostIntentHandler.swift in Sources */, + DBB8AB5326AED25100F6D281 /* MastodonAuthenticationBox.swift in Sources */, + DBB8AB4A26AED0B500F6D281 /* APIService.swift in Sources */, + DBB8AB4C26AED11300F6D281 /* APIService+APIError.swift in Sources */, + DBB8AB4D26AED12B00F6D281 /* Strings.swift in Sources */, + DBB8AB5226AED1B300F6D281 /* APIService+Status+Publish.swift in Sources */, + DB8FABCA26AEC7B2008E5AF4 /* IntentHandler.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; DBC6460E26A170AB00B0E31B /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -4077,6 +4251,21 @@ target = DB89B9ED25C10FD0008580ED /* CoreDataStack */; targetProxy = DB89BA0125C10FD0008580ED /* PBXContainerItemProxy */; }; + DB8FABCD26AEC7B2008E5AF4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DB8FABC526AEC7B2008E5AF4 /* MastodonIntent */; + targetProxy = DB8FABCC26AEC7B2008E5AF4 /* PBXContainerItemProxy */; + }; + DB8FABDA26AEC873008E5AF4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DB68047E2637CD4C00430867 /* AppShared */; + targetProxy = DB8FABD926AEC873008E5AF4 /* PBXContainerItemProxy */; + }; + DB8FABDF26AEC87B008E5AF4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DB89B9ED25C10FD0008580ED /* CoreDataStack */; + targetProxy = DB8FABDE26AEC87B008E5AF4 /* PBXContainerItemProxy */; + }; DBC6461B26A170AB00B0E31B /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DBC6461126A170AB00B0E31B /* ShareActionExtension */; @@ -4100,6 +4289,16 @@ /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ + DB0009A926AEE5DC009B9D2D /* Intents.intentdefinition */ = { + isa = PBXVariantGroup; + children = ( + DB0009A826AEE5DC009B9D2D /* Base */, + DB0009AB26AEE5E3009B9D2D /* en */, + DB0009AD26AEE5E4009B9D2D /* ar */, + ); + name = Intents.intentdefinition; + sourceTree = ""; + }; DB2B3ABE25E37E15007045F9 /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( @@ -4206,6 +4405,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; + INTENTS_CODEGEN_LANGUAGE = Swift; IPHONEOS_DEPLOYMENT_TARGET = 14.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; @@ -4262,6 +4462,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; + INTENTS_CODEGEN_LANGUAGE = Swift; IPHONEOS_DEPLOYMENT_TARGET = 14.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; @@ -4281,7 +4482,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 45; + CURRENT_PROJECT_VERSION = 47; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -4289,7 +4490,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 0.9.3; + MARKETING_VERSION = 0.9.4; PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -4308,7 +4509,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 45; + CURRENT_PROJECT_VERSION = 47; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -4316,7 +4517,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 0.9.3; + MARKETING_VERSION = 0.9.4; PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -4530,7 +4731,6 @@ DB89BA0A25C10FD0008580ED /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = CoreDataStackTests/Info.plist; @@ -4550,7 +4750,6 @@ DB89BA0B25C10FD0008580ED /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = CoreDataStackTests/Info.plist; @@ -4567,13 +4766,109 @@ }; name = Release; }; + DB8FABD026AEC7B2008E5AF4 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 861BE60ED27430771CFD578D /* Pods-MastodonIntent.debug.xcconfig */; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 47; + DEVELOPMENT_TEAM = 5Z4GVSS33P; + INFOPLIST_FILE = MastodonIntent/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 0.9.4; + PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.MastodonIntent; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "APP_EXTENSION $(inherited)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Debug; + }; + DB8FABD126AEC7B2008E5AF4 /* ASDK - Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = C3789232A52F43529CA67E95 /* Pods-MastodonIntent.asdk - debug.xcconfig */; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 47; + DEVELOPMENT_TEAM = 5Z4GVSS33P; + INFOPLIST_FILE = MastodonIntent/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 0.9.4; + PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.MastodonIntent; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "APP_EXTENSION $(inherited)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = "ASDK - Debug"; + }; + DB8FABD226AEC7B2008E5AF4 /* ASDK - Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F920AD4EC23B0D00F5CCA58E /* Pods-MastodonIntent.asdk - release.xcconfig */; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 47; + DEVELOPMENT_TEAM = 5Z4GVSS33P; + INFOPLIST_FILE = MastodonIntent/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 0.9.4; + PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.MastodonIntent; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "APP_EXTENSION $(inherited)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = "ASDK - Release"; + }; + DB8FABD326AEC7B2008E5AF4 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 159AC43EFE0A1F95FCB358A4 /* Pods-MastodonIntent.release.xcconfig */; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 47; + DEVELOPMENT_TEAM = 5Z4GVSS33P; + INFOPLIST_FILE = MastodonIntent/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 0.9.4; + PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.MastodonIntent; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "APP_EXTENSION $(inherited)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Release; + }; DBC6461D26A170AB00B0E31B /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 77EE917BC055E6621C0452B6 /* Pods-ShareActionExtension.debug.xcconfig */; buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 45; + CURRENT_PROJECT_VERSION = 47; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -4581,7 +4876,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 0.9.3; + MARKETING_VERSION = 0.9.4; PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.ShareActionExtension; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -4597,7 +4892,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 45; + CURRENT_PROJECT_VERSION = 47; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -4605,7 +4900,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 0.9.3; + MARKETING_VERSION = 0.9.4; PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.ShareActionExtension; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -4621,7 +4916,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 45; + CURRENT_PROJECT_VERSION = 47; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -4629,7 +4924,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 0.9.3; + MARKETING_VERSION = 0.9.4; PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.ShareActionExtension; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -4645,7 +4940,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 45; + CURRENT_PROJECT_VERSION = 47; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -4653,7 +4948,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 0.9.3; + MARKETING_VERSION = 0.9.4; PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.ShareActionExtension; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -4715,6 +5010,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; + INTENTS_CODEGEN_LANGUAGE = Swift; IPHONEOS_DEPLOYMENT_TARGET = 14.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; @@ -4735,7 +5031,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 45; + CURRENT_PROJECT_VERSION = 47; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -4743,7 +5039,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 0.9.3; + MARKETING_VERSION = 0.9.4; PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -4827,7 +5123,6 @@ DBCBCC132680BE3E000F5B51 /* ASDK - Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = CoreDataStackTests/Info.plist; @@ -4850,7 +5145,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 45; + CURRENT_PROJECT_VERSION = 47; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -4858,7 +5153,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 0.9.3; + MARKETING_VERSION = 0.9.4; PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.NotificationService; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -4950,6 +5245,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; + INTENTS_CODEGEN_LANGUAGE = Swift; IPHONEOS_DEPLOYMENT_TARGET = 14.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; @@ -4969,7 +5265,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 45; + CURRENT_PROJECT_VERSION = 47; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -4977,7 +5273,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 0.9.3; + MARKETING_VERSION = 0.9.4; PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -5061,7 +5357,6 @@ DBCBCC2326818F6F000F5B51 /* ASDK - Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = CoreDataStackTests/Info.plist; @@ -5084,7 +5379,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 45; + CURRENT_PROJECT_VERSION = 47; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5092,7 +5387,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 0.9.3; + MARKETING_VERSION = 0.9.4; PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.NotificationService; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -5138,7 +5433,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 45; + CURRENT_PROJECT_VERSION = 47; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5146,7 +5441,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 0.9.3; + MARKETING_VERSION = 0.9.4; PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.NotificationService; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -5161,7 +5456,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 45; + CURRENT_PROJECT_VERSION = 47; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5169,7 +5464,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 0.9.3; + MARKETING_VERSION = 0.9.4; PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.NotificationService; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -5258,6 +5553,17 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + DB8FABCF26AEC7B2008E5AF4 /* Build configuration list for PBXNativeTarget "MastodonIntent" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DB8FABD026AEC7B2008E5AF4 /* Debug */, + DB8FABD126AEC7B2008E5AF4 /* ASDK - Debug */, + DB8FABD226AEC7B2008E5AF4 /* ASDK - Release */, + DB8FABD326AEC7B2008E5AF4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; DBC6462126A170AB00B0E31B /* Build configuration list for PBXNativeTarget "ShareActionExtension" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -5482,6 +5788,10 @@ package = DBB525062611EAC0002F1F29 /* XCRemoteSwiftPackageReference "Tabman" */; productName = Tabman; }; + DBB8AB4726AED09C00F6D281 /* MastodonSDK */ = { + isa = XCSwiftPackageProductDependency; + productName = MastodonSDK; + }; DBBC24A926A5301B00398BB9 /* MastodonSDK */ = { isa = XCSwiftPackageProductDependency; productName = MastodonSDK; diff --git a/Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon - ASDK.xcscheme b/Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon - ASDK.xcscheme new file mode 100644 index 000000000..4ce52bd58 --- /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 000000000..15ecdcbe9 --- /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 000000000..70507b96c --- /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 000000000..b64bfc894 --- /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 d28d5cdd8..d5b0a1e96 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 - 20 + 31 CoreDataStack.xcscheme_^#shared#^_ orderHint - 22 + 30 Mastodon - ASDK.xcscheme_^#shared#^_ @@ -34,15 +34,30 @@ orderHint 0 + MastodonIntent.xcscheme_^#shared#^_ + + orderHint + 29 + + MastodonIntents.xcscheme_^#shared#^_ + + orderHint + 35 + + MastodonIntentsUI.xcscheme_^#shared#^_ + + orderHint + 34 + NotificationService.xcscheme_^#shared#^_ orderHint - 24 + 3 ShareActionExtension.xcscheme_^#shared#^_ orderHint - 23 + 28 SuppressBuildableAutocreation diff --git a/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved index dc848b695..c6a46992b 100644 --- a/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -91,6 +91,15 @@ "version": "4.2.2" } }, + { + "package": "MetaTextKit", + "repositoryURL": "https://github.com/TwidereProject/MetaTextKit.git", + "state": { + "branch": null, + "revision": "ccb54189b31d13868d979c33d43566912b765bbd", + "version": "2.1.0" + } + }, { "package": "Nuke", "repositoryURL": "https://github.com/kean/Nuke.git", diff --git a/Mastodon/Coordinator/SceneCoordinator.swift b/Mastodon/Coordinator/SceneCoordinator.swift index 5aac2b1b9..04804dde3 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/Extension/CoreDataStack/Status.swift b/Mastodon/Extension/CoreDataStack/Status.swift index 7b64e6a9d..1c329c852 100644 --- a/Mastodon/Extension/CoreDataStack/Status.swift +++ b/Mastodon/Extension/CoreDataStack/Status.swift @@ -24,7 +24,7 @@ extension Status.Property { reblogsCount: NSNumber(value: entity.reblogsCount), favouritesCount: NSNumber(value: entity.favouritesCount), repliesCount: entity.repliesCount.flatMap { NSNumber(value: $0) }, - url: entity.uri, + url: entity.url ?? entity.uri, inReplyToID: entity.inReplyToID, inReplyToAccountID: entity.inReplyToAccountID, language: entity.language, diff --git a/Mastodon/Extension/MetaLabel.swift b/Mastodon/Extension/MetaLabel.swift index 27f04e068..e5a588e15 100644 --- a/Mastodon/Extension/MetaLabel.swift +++ b/Mastodon/Extension/MetaLabel.swift @@ -26,7 +26,8 @@ extension MetaLabel { layer.masksToBounds = true textContainer.lineBreakMode = .byTruncatingTail - + textContainer.lineFragmentPadding = 0 + let font: UIFont let textColor: UIColor diff --git a/Mastodon/Info.plist b/Mastodon/Info.plist index cbb93eabf..0201333cc 100644 --- a/Mastodon/Info.plist +++ b/Mastodon/Info.plist @@ -44,6 +44,10 @@ LSRequiresIPhoneOS + NSUserActivityTypes + + SendPostIntent + UIApplicationSceneManifest UIApplicationSupportsMultipleScenes @@ -63,6 +67,25 @@ + UIApplicationShortcutItems + + + UIApplicationShortcutItemIconSymbolName + square.and.pencil + UIApplicationShortcutItemTitle + NewPostShortcutItemTitle + UIApplicationShortcutItemType + org.joinmastodon.app.new-post + + + UIApplicationShortcutItemIconSymbolName + magnifyingglass + UIApplicationShortcutItemTitle + SearchShortcutItemTitle + UIApplicationShortcutItemType + org.joinmastodon.app.search + + UIApplicationSupportsIndirectInputEvents UILaunchStoryboardName diff --git a/Mastodon/Mastodon.entitlements b/Mastodon/Mastodon.entitlements index 0135ecdd2..153b958a3 100644 --- a/Mastodon/Mastodon.entitlements +++ b/Mastodon/Mastodon.entitlements @@ -4,6 +4,8 @@ aps-environment development + com.apple.developer.siri + com.apple.security.application-groups group.org.joinmastodon.app diff --git a/Mastodon/Resources/ar.lproj/InfoPlist.strings b/Mastodon/Resources/ar.lproj/InfoPlist.strings index 48566ae36..710865573 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 48566ae36..710865573 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 48566ae36..000000000 --- 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/Scene/Compose/ComposeViewModel.swift b/Mastodon/Scene/Compose/ComposeViewModel.swift index 52af2cb67..9964dd2ba 100644 --- a/Mastodon/Scene/Compose/ComposeViewModel.swift +++ b/Mastodon/Scene/Compose/ComposeViewModel.swift @@ -18,6 +18,8 @@ final class ComposeViewModel: NSObject { static let composeContentLimit: Int = 500 var disposeBag = Set() + + let id = UUID() // input let context: AppContext diff --git a/Mastodon/Scene/Compose/View/ReplicaStatusView.swift b/Mastodon/Scene/Compose/View/ReplicaStatusView.swift index 8948a2f6a..cb34f3ded 100644 --- a/Mastodon/Scene/Compose/View/ReplicaStatusView.swift +++ b/Mastodon/Scene/Compose/View/ReplicaStatusView.swift @@ -99,6 +99,21 @@ final class ReplicaStatusView: UIView { metaText.textView.textContainer.lineFragmentPadding = 0 metaText.textView.textContainerInset = .zero metaText.textView.layer.masksToBounds = false + + metaText.paragraphStyle = { + let style = NSMutableParagraphStyle() + style.lineSpacing = 5 + style.paragraphSpacing = 8 + return style + }() + metaText.textAttributes = [ + .font: UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 17, weight: .regular)), + .foregroundColor: Asset.Colors.Label.primary.color, + ] + metaText.linkAttributes = [ + .font: UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 17, weight: .semibold)), + .foregroundColor: Asset.Colors.brandBlue.color, + ] return metaText }() diff --git a/Mastodon/Scene/HomeTimeline/HomeTimelineViewModel.swift b/Mastodon/Scene/HomeTimeline/HomeTimelineViewModel.swift index 611e95368..0bf1e1041 100644 --- a/Mastodon/Scene/HomeTimeline/HomeTimelineViewModel.swift +++ b/Mastodon/Scene/HomeTimeline/HomeTimelineViewModel.swift @@ -120,9 +120,10 @@ final class HomeTimelineViewModel: NSObject { .sink { [weak self] activeMastodonAuthentication in guard let self = self else { return } guard let mastodonAuthentication = activeMastodonAuthentication else { return } - let activeMastodonUserID = mastodonAuthentication.userID + let domain = mastodonAuthentication.domain + let userID = mastodonAuthentication.userID let predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [ - HomeTimelineIndex.predicate(userID: activeMastodonUserID), + HomeTimelineIndex.predicate(domain: domain, userID: userID), HomeTimelineIndex.notDeleted() ]) self.timelinePredicate.value = predicate diff --git a/Mastodon/Scene/Profile/Header/View/ProfileHeaderView.swift b/Mastodon/Scene/Profile/Header/View/ProfileHeaderView.swift index eb6e06a04..c45a0f648 100644 --- a/Mastodon/Scene/Profile/Header/View/ProfileHeaderView.swift +++ b/Mastodon/Scene/Profile/Header/View/ProfileHeaderView.swift @@ -440,6 +440,7 @@ extension ProfileHeaderView { bringSubviewToFront(bannerContainerView) bringSubviewToFront(nameContainerStackView) + bioMetaText.textView.delegate = self bioMetaText.textView.linkDelegate = self let avatarImageViewSingleTapGestureRecognizer = UITapGestureRecognizer.singleTapGestureRecognizer @@ -522,6 +523,19 @@ extension ProfileHeaderView { } } +// MARK: - UITextViewDelegate +extension ProfileHeaderView: UITextViewDelegate { + func textView(_ textView: UITextView, shouldInteractWith textAttachment: NSTextAttachment, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool { + switch textView { + case bioMetaText.textView: + return false + default: + assertionFailure() + return true + } + } +} + // MARK: - MetaTextViewDelegate extension ProfileHeaderView: MetaTextViewDelegate { func metaTextView(_ metaTextView: MetaTextView, didSelectMeta meta: Meta) { diff --git a/Mastodon/Scene/Search/SearchDetail/SearchResult/SearchResultViewModel+State.swift b/Mastodon/Scene/Search/SearchDetail/SearchResult/SearchResultViewModel+State.swift index 0445ee017..dba71b50e 100644 --- a/Mastodon/Scene/Search/SearchDetail/SearchResult/SearchResultViewModel+State.swift +++ b/Mastodon/Scene/Search/SearchDetail/SearchResult/SearchResultViewModel+State.swift @@ -101,7 +101,7 @@ extension SearchResultViewModel.State { maxID: nil, minID: nil, excludeUnreviewed: nil, - resolve: nil, + resolve: true, limit: nil, offset: _offset, following: nil diff --git a/Mastodon/Scene/Search/SearchDetail/TableViewCell/SearchResultTableViewCell.swift b/Mastodon/Scene/Search/SearchDetail/TableViewCell/SearchResultTableViewCell.swift index 4c1753ff0..d0106a334 100644 --- a/Mastodon/Scene/Search/SearchDetail/TableViewCell/SearchResultTableViewCell.swift +++ b/Mastodon/Scene/Search/SearchDetail/TableViewCell/SearchResultTableViewCell.swift @@ -160,7 +160,7 @@ extension SearchResultTableViewCell { let metaContent = PlaintextMetaContent(string: name) _titleLabel.configure(content: metaContent) } - _subTitleLabel.text = account.acct + _subTitleLabel.text = "@" + account.acct } func config(with account: MastodonUser) { @@ -173,14 +173,15 @@ extension SearchResultTableViewCell { let metaContent = PlaintextMetaContent(string: account.displayNameWithFallback) _titleLabel.configure(content: metaContent) } - _subTitleLabel.text = account.acct + _subTitleLabel.text = "@" + account.acct } func config(with tag: Mastodon.Entity.Tag) { configure(with: AvatarConfigurableViewConfiguration(avatarImageURL: nil)) let image = UIImage(systemName: "number.circle.fill", withConfiguration: UIImage.SymbolConfiguration(pointSize: 34, weight: .regular))!.withRenderingMode(.alwaysTemplate) _imageView.image = image - _titleLabel.text = "#" + tag.name + let metaContent = PlaintextMetaContent(string: "#" + tag.name) + _titleLabel.configure(content: metaContent) guard let histories = tag.history else { _subTitleLabel.text = "" return @@ -195,7 +196,8 @@ extension SearchResultTableViewCell { configure(with: AvatarConfigurableViewConfiguration(avatarImageURL: nil)) let image = UIImage(systemName: "number.circle.fill", withConfiguration: UIImage.SymbolConfiguration(pointSize: 34, weight: .regular))!.withRenderingMode(.alwaysTemplate) _imageView.image = image - _titleLabel.text = "# " + tag.name + let metaContent = PlaintextMetaContent(string: "#" + tag.name) + _titleLabel.configure(content: metaContent) guard let histories = tag.histories?.sorted(by: { $0.createAt.compare($1.createAt) == .orderedAscending }) else { diff --git a/Mastodon/Service/APIService/APIService+APIError.swift b/Mastodon/Service/APIService/APIService+APIError.swift index 37235c2cb..352be4ff4 100644 --- a/Mastodon/Service/APIService/APIService+APIError.swift +++ b/Mastodon/Service/APIService/APIService+APIError.swift @@ -40,7 +40,7 @@ extension APIService { // MARK: - LocalizedError extension APIService.APIError: LocalizedError { - var errorDescription: String? { + public var errorDescription: String? { switch errorReason { case .authenticationMissing: return "Fail to Authenticatie" case .badRequest: return "Bad Request" diff --git a/Mastodon/Service/APIService/APIService+App.swift b/Mastodon/Service/APIService/APIService+App.swift index b5b1d8686..1575e6561 100644 --- a/Mastodon/Service/APIService/APIService+App.swift +++ b/Mastodon/Service/APIService/APIService+App.swift @@ -19,11 +19,13 @@ extension APIService { private static let clientName = "Mastodon for iOS" #endif + private static let appWebsite = "https://joinmastodon.org/apps" + func createApplication(domain: String) -> AnyPublisher, Error> { let query = Mastodon.API.App.CreateQuery( clientName: APIService.clientName, redirectURIs: MastodonAuthenticationController.callbackURL, - website: nil + website: APIService.appWebsite ) return Mastodon.API.App.create( session: session, diff --git a/Mastodon/Service/APIService/APIService+Reblog.swift b/Mastodon/Service/APIService/APIService+Reblog.swift index fd0206145..88da60f25 100644 --- a/Mastodon/Service/APIService/APIService+Reblog.swift +++ b/Mastodon/Service/APIService/APIService+Reblog.swift @@ -104,7 +104,17 @@ extension APIService { APIService.CoreData.merge(status: oldStatus, entity: entity.reblog ?? entity, requestMastodonUser: requestMastodonUser, domain: mastodonAuthenticationBox.domain, networkDate: response.networkDate) switch reblogKind { case .undoReblog: + // update reblogged status oldStatus.update(reblogsCount: NSNumber(value: max(0, oldStatus.reblogsCount.intValue - 1))) + + // remove reblog from statuses + let reblogFroms = oldStatus.reblogFrom?.filter { status in + return status.author.domain == domain && status.author.id == requestMastodonUserID + } ?? Set() + reblogFroms.forEach { reblogFrom in + managedObjectContext.delete(reblogFrom) + } + default: break } diff --git a/Mastodon/Service/AuthenticationService.swift b/Mastodon/Service/AuthenticationService.swift index f6ece0440..0b3c3fa11 100644 --- a/Mastodon/Service/AuthenticationService.swift +++ b/Mastodon/Service/AuthenticationService.swift @@ -130,6 +130,19 @@ extension AuthenticationService { appAuthorization: Mastodon.API.OAuth.Authorization(accessToken: mastodonAuthentication.appAccessToken), userAuthorization: Mastodon.API.OAuth.Authorization(accessToken: mastodonAuthentication.userAccessToken) ) + + // remove home timeline indexes + let homeTimelineIndexRequest = HomeTimelineIndex.sortedFetchRequest + homeTimelineIndexRequest.predicate = HomeTimelineIndex.predicate( + domain: mastodonAuthentication.domain, + userID: mastodonAuthentication.userID + ) + let homeTimelineIndexes = managedObjectContext.safeFetch(homeTimelineIndexRequest) + for homeTimelineIndex in homeTimelineIndexes { + managedObjectContext.delete(homeTimelineIndex) + } + + // remove user authentication managedObjectContext.delete(mastodonAuthentication) isSignOut = true } diff --git a/Mastodon/Service/StatusPublishService.swift b/Mastodon/Service/StatusPublishService.swift index f797d9f6a..ed894f933 100644 --- a/Mastodon/Service/StatusPublishService.swift +++ b/Mastodon/Service/StatusPublishService.swift @@ -7,6 +7,7 @@ import os.log import Foundation +import Intents import Combine import CoreData import CoreDataStack @@ -52,7 +53,7 @@ extension StatusPublishService { os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: composeViewModelDidUpdate", ((#file as NSString).lastPathComponent), #line, #function) self.composeViewModelDidUpdatePublisher.send() - + switch state { case is ComposeViewModel.PublishState.Finish: self.remove(composeViewModel: composeViewModel) diff --git a/Mastodon/Supporting Files/SceneDelegate.swift b/Mastodon/Supporting Files/SceneDelegate.swift index 6964eef91..05ff8850a 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 diff --git a/MastodonIntent/Info.plist b/MastodonIntent/Info.plist new file mode 100644 index 000000000..3c4a6e453 --- /dev/null +++ b/MastodonIntent/Info.plist @@ -0,0 +1,42 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + MastodonIntent + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + $(MARKETING_VERSION) + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSExtension + + NSExtensionAttributes + + IntentsRestrictedWhileLocked + + IntentsRestrictedWhileProtectedDataUnavailable + + IntentsSupported + + SendPostIntent + + + NSExtensionPointIdentifier + com.apple.intents-service + NSExtensionPrincipalClass + $(PRODUCT_MODULE_NAME).IntentHandler + + + diff --git a/MastodonIntent/IntentHandler.swift b/MastodonIntent/IntentHandler.swift new file mode 100644 index 000000000..cb8588d67 --- /dev/null +++ b/MastodonIntent/IntentHandler.swift @@ -0,0 +1,23 @@ +// +// IntentHandler.swift +// MastodonIntent +// +// Created by Cirno MainasuK on 2021-7-26. +// + +import Intents + +class IntentHandler: INExtension { + + override func handler(for intent: INIntent) -> Any { + // This is the default implementation. If you want different objects to handle different intents, + // you can override this and return the handler you want for that particular intent. + switch intent { + case is SendPostIntent: + return SendPostIntentHandler() + default: + return self + } + } + +} diff --git a/MastodonIntent/MastodonIntent.entitlements b/MastodonIntent/MastodonIntent.entitlements new file mode 100644 index 000000000..c3bc3f816 --- /dev/null +++ b/MastodonIntent/MastodonIntent.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.application-groups + + group.org.joinmastodon.app + + + diff --git a/MastodonIntent/SendPostIntentHandler.swift b/MastodonIntent/SendPostIntentHandler.swift new file mode 100644 index 000000000..6d5f739fb --- /dev/null +++ b/MastodonIntent/SendPostIntentHandler.swift @@ -0,0 +1,99 @@ +// +// SendPostIntentHandler.swift +// MastodonIntent +// +// Created by Cirno MainasuK on 2021-7-26. +// + +import Foundation +import Intents +import Combine +import CoreData +import CoreDataStack +import MastodonSDK + +final class SendPostIntentHandler: NSObject, SendPostIntentHandling { + + var disposeBag = Set() + + lazy var coreDataStack = CoreDataStack() + lazy var managedObjectContext = coreDataStack.persistentContainer.viewContext + + func handle(intent: SendPostIntent, completion: @escaping (SendPostIntentResponse) -> Void) { + managedObjectContext.performAndWait { + let request = MastodonAuthentication.sortedFetchRequest + let authentications = (try? self.managedObjectContext.fetch(request)) ?? [] + let _authentication = authentications.sorted(by: { $0.activedAt > $1.activedAt }).first + + guard let authentication = _authentication else { + let failureReason = APIService.APIError.implicit(.authenticationMissing).errorDescription ?? "Fail to Send Post" + completion(SendPostIntentResponse.failure(failureReason: failureReason)) + return + } + + let box = MastodonAuthenticationBox( + domain: authentication.domain, + userID: authentication.userID, + appAuthorization: .init(accessToken: authentication.appAccessToken), + userAuthorization: .init(accessToken: authentication.userAccessToken) + ) + + let visibility: Mastodon.Entity.Status.Visibility = { + switch intent.visibility { + case .unknown: return .public + case .public: return .public + case .followersOnly: return .private + } + }() + let query = Mastodon.API.Statuses.PublishStatusQuery( + status: intent.content, + mediaIDs: nil, + pollOptions: nil, + pollExpiresIn: nil, + inReplyToID: nil, + sensitive: nil, + spoilerText: nil, + visibility: visibility + ) + + APIService.shared.publishStatus( + domain: box.domain, + query: query, + mastodonAuthenticationBox: box + ) + .sink { _completion in + switch _completion { + case .failure(let error): + let failureReason = error.localizedDescription + completion(SendPostIntentResponse.failure(failureReason: failureReason)) + case .finished: + break + } + } receiveValue: { response in + let post = Post(identifier: response.value.id, display: intent.content ?? "") + post.url = URL(string: response.value.url ?? response.value.uri) + let result = SendPostIntentResponse(code: .success, userActivity: nil) + result.post = post + completion(result) + } + .store(in: &disposeBag) + } + + } + + func resolveContent(for intent: SendPostIntent, with completion: @escaping (INStringResolutionResult) -> Void) { + guard let content = intent.content, !content.isEmpty else { + completion(.needsValue()) + return + } + + completion(.success(with: content)) + } + + func resolveVisibility(for intent: SendPostIntent, with completion: @escaping (PostVisibilityResolutionResult) -> Void) { + completion(.success(with: intent.visibility)) + } + + + +} diff --git a/MastodonIntent/Service/APIService.swift b/MastodonIntent/Service/APIService.swift new file mode 100644 index 000000000..0733c08d4 --- /dev/null +++ b/MastodonIntent/Service/APIService.swift @@ -0,0 +1,33 @@ +// +// APIService.swift +// MastodonIntent +// +// Created by Cirno MainasuK on 2021-7-26. +// + +import os.log +import Foundation +import Combine +import CoreData +import CoreDataStack +import MastodonSDK + +// Replica APIService for share extension +final class APIService { + + var disposeBag = Set() + + static let shared = APIService() + + // internal + let session: URLSession + + // output + let error = PassthroughSubject() + + private init() { + self.session = URLSession(configuration: .default) + } + +} + diff --git a/Podfile b/Podfile index cd7dbfd62..b976556b9 100644 --- a/Podfile +++ b/Podfile @@ -39,6 +39,11 @@ target 'ShareActionExtension' do use_frameworks! end +target 'MastodonIntent' do + # Comment the next line if you don't want to use dynamic frameworks + use_frameworks! +end + target 'AppShared' do # Comment the next line if you don't want to use dynamic frameworks use_frameworks! diff --git a/Podfile.lock b/Podfile.lock index 516d109e8..c59f13a9b 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -78,6 +78,6 @@ SPEC CHECKSUMS: Texture: 2f109e937850d94d1d07232041c9c7313ccddb81 "UITextField+Shake": 298ac5a0f239d731bdab999b19b628c956ca0ac3 -PODFILE CHECKSUM: adf1bf30957525fcafb99001323d1c6ad9995b9d +PODFILE CHECKSUM: 1ea006302c191ee52b6206e4957aa78fb66fe690 COCOAPODS: 1.10.1 diff --git a/ar.lproj/Intents.strings b/ar.lproj/Intents.strings new file mode 100644 index 000000000..770b74bb9 --- /dev/null +++ b/ar.lproj/Intents.strings @@ -0,0 +1,52 @@ +"16wxgf" = "Post on Mastodon"; + +"751xkl" = "Text Content"; + +"CsR7G2" = "Post"; + +"HZSGTr" = "What content to post?"; + +"HdGikU" = "Posting failed"; + +"KDNTJ4" = "Failure Reason"; + +"RHxKOw" = "Send Post with text content"; + +"RxSqsb" = "Post"; + +"WCIR3D" = "Post ${content} on Mastodon"; + +"ZKJSNu" = "Post"; + +"ZS1XaK" = "${content}"; + +"ZbSjzC" = "Visibility"; + +"Zo4jgJ" = "Post Visibility"; + +"apSxMG-dYQ5NN" = "There are ${count} options matching ‘Public’."; + +"apSxMG-ehFLjY" = "There are ${count} options matching ‘Followers Only’."; + +"ayoYEb-dYQ5NN" = "${content}, Public"; + +"ayoYEb-ehFLjY" = "${content}, Followers Only"; + +"dUyuGg" = "Post"; + +"dYQ5NN" = "Public"; + +"ehFLjY" = "Followers Only"; + +"gfePDu" = "Posting failed. ${failureReason}"; + +"k7dbKQ" = "Post was sent successfully."; + +"oGiqmY-dYQ5NN" = "Just to confirm, you wanted ‘Public’?"; + +"oGiqmY-ehFLjY" = "Just to confirm, you wanted ‘Followers Only’?"; + +"rM6dvp" = "URL"; + +"ryJLwG" = "Post was sent successfully. "; + diff --git a/en.lproj/Intents.strings b/en.lproj/Intents.strings new file mode 100644 index 000000000..770b74bb9 --- /dev/null +++ b/en.lproj/Intents.strings @@ -0,0 +1,52 @@ +"16wxgf" = "Post on Mastodon"; + +"751xkl" = "Text Content"; + +"CsR7G2" = "Post"; + +"HZSGTr" = "What content to post?"; + +"HdGikU" = "Posting failed"; + +"KDNTJ4" = "Failure Reason"; + +"RHxKOw" = "Send Post with text content"; + +"RxSqsb" = "Post"; + +"WCIR3D" = "Post ${content} on Mastodon"; + +"ZKJSNu" = "Post"; + +"ZS1XaK" = "${content}"; + +"ZbSjzC" = "Visibility"; + +"Zo4jgJ" = "Post Visibility"; + +"apSxMG-dYQ5NN" = "There are ${count} options matching ‘Public’."; + +"apSxMG-ehFLjY" = "There are ${count} options matching ‘Followers Only’."; + +"ayoYEb-dYQ5NN" = "${content}, Public"; + +"ayoYEb-ehFLjY" = "${content}, Followers Only"; + +"dUyuGg" = "Post"; + +"dYQ5NN" = "Public"; + +"ehFLjY" = "Followers Only"; + +"gfePDu" = "Posting failed. ${failureReason}"; + +"k7dbKQ" = "Post was sent successfully."; + +"oGiqmY-dYQ5NN" = "Just to confirm, you wanted ‘Public’?"; + +"oGiqmY-ehFLjY" = "Just to confirm, you wanted ‘Followers Only’?"; + +"rM6dvp" = "URL"; + +"ryJLwG" = "Post was sent successfully. "; +