From b16d7129d0cfff2e761c0eab32600a6fb4cc21bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Est=C3=AAv=C3=A3o?= Date: Fri, 31 Jan 2025 20:12:43 +0000 Subject: [PATCH 1/2] Start search podcast intent --- podcasts.xcodeproj/project.pbxproj | 20 +++++++++++++++++ podcasts/AppIntents/PodcastsShortcuts.swift | 16 +++++++++++++ podcasts/AppIntents/SearchPodcasts.swift | 25 +++++++++++++++++++++ podcasts/AppIntents/TranscriptEntity.swift | 9 ++++++++ 4 files changed, 70 insertions(+) create mode 100644 podcasts/AppIntents/PodcastsShortcuts.swift create mode 100644 podcasts/AppIntents/SearchPodcasts.swift create mode 100644 podcasts/AppIntents/TranscriptEntity.swift diff --git a/podcasts.xcodeproj/project.pbxproj b/podcasts.xcodeproj/project.pbxproj index 1227f2b0e..1c98b1b12 100644 --- a/podcasts.xcodeproj/project.pbxproj +++ b/podcasts.xcodeproj/project.pbxproj @@ -1959,6 +1959,8 @@ FF54BCAA2C5A2F4D00A342E5 /* TranscriptFormat.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF54BCA82C5A2F3900A342E5 /* TranscriptFormat.swift */; }; FF5B2A442BB1859B009F3DC2 /* SourceInterfaceNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF5B2A432BB1859B009F3DC2 /* SourceInterfaceNavigationView.swift */; }; FF5B2A462BB189C7009F3DC2 /* PocketCastsApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF5B2A452BB189C7009F3DC2 /* PocketCastsApp.swift */; }; + FF6AA5D12D4D441600554E87 /* TranscriptEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF6AA5D02D4D441600554E87 /* TranscriptEntity.swift */; }; + FF6AA5D32D4D57F500554E87 /* SearchPodcasts.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF6AA5D22D4D57E800554E87 /* SearchPodcasts.swift */; }; FF6BBCEE2C53E9D000604A01 /* TranscriptManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF6BBCED2C53E9D000604A01 /* TranscriptManagerTests.swift */; }; FF6BBCF02C53EA1F00604A01 /* sample.vtt in Resources */ = {isa = PBXBuildFile; fileRef = FF6BBCEF2C53EA1F00604A01 /* sample.vtt */; }; FF6BBCF22C578CE600604A01 /* TranscriptsDataRetriever.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF6BBCF12C578CE600604A01 /* TranscriptsDataRetriever.swift */; }; @@ -1967,6 +1969,7 @@ FF7F89EF2C2AF7B600FC0ED5 /* SwiftSubtitles in Frameworks */ = {isa = PBXBuildFile; productRef = FF7F89EE2C2AF7B600FC0ED5 /* SwiftSubtitles */; }; FF7F89F12C2C0FD600FC0ED5 /* TranscriptModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF7F89F02C2C0FD600FC0ED5 /* TranscriptModel.swift */; }; FF8970762B5FFC5E004ADB23 /* SubscriptionPriceAndOfferView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF8970752B5FFC5E004ADB23 /* SubscriptionPriceAndOfferView.swift */; }; + FF8EB7F42D4D629700438FA7 /* PodcastsShortcuts.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF8EB7F32D4D628800438FA7 /* PodcastsShortcuts.swift */; }; FF91A0F62B64159D002A0590 /* UIScreen+Sizes.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF91A0F52B64159D002A0590 /* UIScreen+Sizes.swift */; }; FF91A0F82B6BBF33002A0590 /* UpgradeRoundedSegmentedControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF91A0F72B6BBF33002A0590 /* UpgradeRoundedSegmentedControl.swift */; }; FF91A0FA2B6BBFD1002A0590 /* UpgradeCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF91A0F92B6BBFD1002A0590 /* UpgradeCard.swift */; }; @@ -3971,6 +3974,8 @@ FF57373C2B4EB5B100F511C7 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; FF5B2A432BB1859B009F3DC2 /* SourceInterfaceNavigationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceInterfaceNavigationView.swift; sourceTree = ""; }; FF5B2A452BB189C7009F3DC2 /* PocketCastsApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PocketCastsApp.swift; sourceTree = ""; }; + FF6AA5D02D4D441600554E87 /* TranscriptEntity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranscriptEntity.swift; sourceTree = ""; }; + FF6AA5D22D4D57E800554E87 /* SearchPodcasts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchPodcasts.swift; sourceTree = ""; }; FF6BBCED2C53E9D000604A01 /* TranscriptManagerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TranscriptManagerTests.swift; sourceTree = ""; }; FF6BBCEF2C53EA1F00604A01 /* sample.vtt */ = {isa = PBXFileReference; lastKnownFileType = text; path = sample.vtt; sourceTree = ""; }; FF6BBCF12C578CE600604A01 /* TranscriptsDataRetriever.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranscriptsDataRetriever.swift; sourceTree = ""; }; @@ -3978,6 +3983,7 @@ FF7F89EC2C2AF6DE00FC0ED5 /* TranscriptManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranscriptManager.swift; sourceTree = ""; }; FF7F89F02C2C0FD600FC0ED5 /* TranscriptModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranscriptModel.swift; sourceTree = ""; }; FF8970752B5FFC5E004ADB23 /* SubscriptionPriceAndOfferView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionPriceAndOfferView.swift; sourceTree = ""; }; + FF8EB7F32D4D628800438FA7 /* PodcastsShortcuts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PodcastsShortcuts.swift; sourceTree = ""; }; FF91A0F52B64159D002A0590 /* UIScreen+Sizes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIScreen+Sizes.swift"; sourceTree = ""; }; FF91A0F72B6BBF33002A0590 /* UpgradeRoundedSegmentedControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpgradeRoundedSegmentedControl.swift; sourceTree = ""; }; FF91A0F92B6BBFD1002A0590 /* UpgradeCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpgradeCard.swift; sourceTree = ""; }; @@ -6708,6 +6714,7 @@ BDBD53F717019B2A0048C8C5 /* Pocket Casts */ = { isa = PBXGroup; children = ( + FF6AA5CF2D4D428300554E87 /* AppIntents */, 462EE0B127024FF3003D67DC /* Credentials */, BD7D337619F7D48E00B907EA /* podcasts.entitlements */, 3FD6E04F2BF735EC003941C0 /* podcasts.prototype.entitlements */, @@ -8343,6 +8350,16 @@ name = SharedUI; sourceTree = ""; }; + FF6AA5CF2D4D428300554E87 /* AppIntents */ = { + isa = PBXGroup; + children = ( + FF8EB7F32D4D628800438FA7 /* PodcastsShortcuts.swift */, + FF6AA5D22D4D57E800554E87 /* SearchPodcasts.swift */, + FF6AA5D02D4D441600554E87 /* TranscriptEntity.swift */, + ); + path = AppIntents; + sourceTree = ""; + }; FF7F89E82C2979C000FC0ED5 /* Transcripts */ = { isa = PBXGroup; children = ( @@ -9934,12 +9951,14 @@ C7FAFF5D2941844C00329B40 /* CancelConfirmationViewModel.swift in Sources */, BD14CCDF1D7D3CB800DB4547 /* SelectedPodcastCell.swift in Sources */, BD93FDA120157B2000F6EF55 /* PodcastImageView.swift in Sources */, + FF6AA5D12D4D441600554E87 /* TranscriptEntity.swift in Sources */, F5F884652CCA86AE002BED2C /* LongestEpisode2024Story.swift in Sources */, BDD5253A20477E4400AAD211 /* NSObject+AppDelegate.swift in Sources */, 8B14E3B029B9159B0069B6F2 /* SearchHistoryModel.swift in Sources */, C7080C5D2923070200D7A432 /* PlusAccountUpgradePrompt.swift in Sources */, 8B44446729785BD0007E0AA8 /* SocialLoginFactory.swift in Sources */, 46305CED272AFA5F003AC87B /* UserDefaults+Helpers.swift in Sources */, + FF6AA5D32D4D57F500554E87 /* SearchPodcasts.swift in Sources */, BD2F3BA22366C0DA00416633 /* PlayerContainerViewController+Update.swift in Sources */, 8BDE43082AC34A7600C2D5C9 /* RatePodcastViewModel.swift in Sources */, 8B2E055228F88D7300C2DBDE /* EndOfYearPromptCell.swift in Sources */, @@ -10124,6 +10143,7 @@ F5F0C9B02CCEA5BE003D295D /* SubscriptionBadge2024.swift in Sources */, C7C4CAEB28AB05A800CFC8CF /* AnalyticsLoggingAdapter.swift in Sources */, 4007B050230E201A008DDCF5 /* WhatsNewDetailViewController.swift in Sources */, + FF8EB7F42D4D629700438FA7 /* PodcastsShortcuts.swift in Sources */, 8B907F182AA8E1F100926F4F /* MiniPlayerViewController+TransitionDelegate.swift in Sources */, BD35E91A1D45BBDA00CAE2A7 /* EmailHelper.swift in Sources */, BDDF8AA6240CE85D009BA263 /* PodcastViewController+Swipe.swift in Sources */, diff --git a/podcasts/AppIntents/PodcastsShortcuts.swift b/podcasts/AppIntents/PodcastsShortcuts.swift new file mode 100644 index 000000000..10bc87e49 --- /dev/null +++ b/podcasts/AppIntents/PodcastsShortcuts.swift @@ -0,0 +1,16 @@ +import AppIntents + +@available(iOS 17.2, *) +struct PodcastsShortcuts: AppShortcutsProvider { + static var appShortcuts: [AppShortcut] { + AppShortcut( + intent: SearchPodcasts(), + phrases: [ + "Find \(\.$criteria) in \(.applicationName)", + "Search for \(\.$criteria) in \(.applicationName)", + ], + shortTitle: "Search ", + systemImageName: "magnifyingglass" + ) + } +} diff --git a/podcasts/AppIntents/SearchPodcasts.swift b/podcasts/AppIntents/SearchPodcasts.swift new file mode 100644 index 000000000..baa93c0e0 --- /dev/null +++ b/podcasts/AppIntents/SearchPodcasts.swift @@ -0,0 +1,25 @@ +import Foundation +import AppIntents + +@available(iOS 17.2, *) +@AssistantIntent(schema: .system.search) +struct SearchPodcasts: AppIntent { + + static var title: LocalizedStringResource = "Search Podcasts" + + static var description = IntentDescription("Opens the app and serchs.") + + static var openAppWhenRun: Bool = true + + @MainActor + func perform() async throws -> some IntentResult { + NavigationManager.sharedManager.navigateTo(NavigationManager.settingsProfileKey) + + return .result() + } + + static var searchScopes: [StringSearchScope] = [.general] + + @Parameter(title: "Criteria") + var criteria: StringSearchCriteria +} diff --git a/podcasts/AppIntents/TranscriptEntity.swift b/podcasts/AppIntents/TranscriptEntity.swift new file mode 100644 index 000000000..7a28a01a7 --- /dev/null +++ b/podcasts/AppIntents/TranscriptEntity.swift @@ -0,0 +1,9 @@ +// +// TranscriptEntity.swift +// podcasts +// +// Created by Sérgio Estêvão on 31/01/2025. +// Copyright © 2025 Shifty Jelly. All rights reserved. +// + +import Foundation From 998c4ab5a8c880727fcf50e4a16c5f2713aa2619 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Est=C3=AAv=C3=A3o?= Date: Tue, 11 Feb 2025 09:30:18 +0000 Subject: [PATCH 2/2] Add intent entity for Transcripts model --- podcasts/AppIntents/TranscriptEntity.swift | 52 ++++++++++++++++++---- podcasts/TranscriptViewController.swift | 2 + 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/podcasts/AppIntents/TranscriptEntity.swift b/podcasts/AppIntents/TranscriptEntity.swift index 7a28a01a7..7b7e0d0d8 100644 --- a/podcasts/AppIntents/TranscriptEntity.swift +++ b/podcasts/AppIntents/TranscriptEntity.swift @@ -1,9 +1,45 @@ -// -// TranscriptEntity.swift -// podcasts -// -// Created by Sérgio Estêvão on 31/01/2025. -// Copyright © 2025 Shifty Jelly. All rights reserved. -// - import Foundation +import CoreLocation +import AppIntents +import CoreTransferable + +@available(iOS 18.0, *) +@AssistantEntity(schema: .journal.entry) +struct TranscriptEntryEntity { + struct TranscriptEntryEntityQuery: EntityStringQuery { + func entities(for identifiers: [TranscriptEntryEntity.ID]) async throws -> [TranscriptEntryEntity] { [] } + func entities(matching string: String) async throws -> [TranscriptEntryEntity] { [] } + } + + static var defaultQuery = TranscriptEntryEntityQuery() + var displayRepresentation: DisplayRepresentation { "Transcript Representation" } + + let id = UUID() + + var title: String? + var message: AttributedString? + var mediaItems: [IntentFile] + var entryDate: Date? + var location: CLPlacemark? + + var entryText: String { + return NSAttributedString(message ?? "").string + } +} + +@available(iOS 18.0, *) +extension TranscriptEntryEntity: Transferable { + public static var transferRepresentation: some TransferRepresentation { + ProxyRepresentation(exporting: \.entryText) + } +} + +@available(iOS 18.0, *) +extension TranscriptModel { + + var appEntity: TranscriptEntryEntity { + let entity = TranscriptEntryEntity() + entity.message = AttributedString(attributedText) + return entity + } +} diff --git a/podcasts/TranscriptViewController.swift b/podcasts/TranscriptViewController.swift index 7d530f2c9..0e72d3e69 100644 --- a/podcasts/TranscriptViewController.swift +++ b/podcasts/TranscriptViewController.swift @@ -383,6 +383,8 @@ class TranscriptViewController: PlayerItemViewController { if resetPosition { transcriptView.setContentOffset(.zero, animated: false) } + var userActivity = NSUserActivity(activityType: "au.com.shiftyjelly.podcasts.journal.entry") + userActivity.appEntityIdentifier = "" } private func makeStyle(alignment: NSTextAlignment = .natural) -> [NSAttributedString.Key: Any] {