Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exploration of podcast intents #2721

Draft
wants to merge 2 commits into
base: trunk
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions podcasts.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */; };
Expand All @@ -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 */; };
Expand Down Expand Up @@ -3971,13 +3974,16 @@
FF57373C2B4EB5B100F511C7 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
FF5B2A432BB1859B009F3DC2 /* SourceInterfaceNavigationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceInterfaceNavigationView.swift; sourceTree = "<group>"; };
FF5B2A452BB189C7009F3DC2 /* PocketCastsApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PocketCastsApp.swift; sourceTree = "<group>"; };
FF6AA5D02D4D441600554E87 /* TranscriptEntity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranscriptEntity.swift; sourceTree = "<group>"; };
FF6AA5D22D4D57E800554E87 /* SearchPodcasts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchPodcasts.swift; sourceTree = "<group>"; };
FF6BBCED2C53E9D000604A01 /* TranscriptManagerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TranscriptManagerTests.swift; sourceTree = "<group>"; };
FF6BBCEF2C53EA1F00604A01 /* sample.vtt */ = {isa = PBXFileReference; lastKnownFileType = text; path = sample.vtt; sourceTree = "<group>"; };
FF6BBCF12C578CE600604A01 /* TranscriptsDataRetriever.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranscriptsDataRetriever.swift; sourceTree = "<group>"; };
FF7F89E92C2979D900FC0ED5 /* TranscriptViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranscriptViewController.swift; sourceTree = "<group>"; };
FF7F89EC2C2AF6DE00FC0ED5 /* TranscriptManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranscriptManager.swift; sourceTree = "<group>"; };
FF7F89F02C2C0FD600FC0ED5 /* TranscriptModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranscriptModel.swift; sourceTree = "<group>"; };
FF8970752B5FFC5E004ADB23 /* SubscriptionPriceAndOfferView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionPriceAndOfferView.swift; sourceTree = "<group>"; };
FF8EB7F32D4D628800438FA7 /* PodcastsShortcuts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PodcastsShortcuts.swift; sourceTree = "<group>"; };
FF91A0F52B64159D002A0590 /* UIScreen+Sizes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIScreen+Sizes.swift"; sourceTree = "<group>"; };
FF91A0F72B6BBF33002A0590 /* UpgradeRoundedSegmentedControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpgradeRoundedSegmentedControl.swift; sourceTree = "<group>"; };
FF91A0F92B6BBFD1002A0590 /* UpgradeCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpgradeCard.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -6708,6 +6714,7 @@
BDBD53F717019B2A0048C8C5 /* Pocket Casts */ = {
isa = PBXGroup;
children = (
FF6AA5CF2D4D428300554E87 /* AppIntents */,
462EE0B127024FF3003D67DC /* Credentials */,
BD7D337619F7D48E00B907EA /* podcasts.entitlements */,
3FD6E04F2BF735EC003941C0 /* podcasts.prototype.entitlements */,
Expand Down Expand Up @@ -8343,6 +8350,16 @@
name = SharedUI;
sourceTree = "<group>";
};
FF6AA5CF2D4D428300554E87 /* AppIntents */ = {
isa = PBXGroup;
children = (
FF8EB7F32D4D628800438FA7 /* PodcastsShortcuts.swift */,
FF6AA5D22D4D57E800554E87 /* SearchPodcasts.swift */,
FF6AA5D02D4D441600554E87 /* TranscriptEntity.swift */,
);
path = AppIntents;
sourceTree = "<group>";
};
FF7F89E82C2979C000FC0ED5 /* Transcripts */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -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 */,
Expand Down Expand Up @@ -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 */,
Expand Down
16 changes: 16 additions & 0 deletions podcasts/AppIntents/PodcastsShortcuts.swift
Original file line number Diff line number Diff line change
@@ -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 <app name redacted>",
systemImageName: "magnifyingglass"
)
}
}
25 changes: 25 additions & 0 deletions podcasts/AppIntents/SearchPodcasts.swift
Original file line number Diff line number Diff line change
@@ -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
}
45 changes: 45 additions & 0 deletions podcasts/AppIntents/TranscriptEntity.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
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
}
}
2 changes: 2 additions & 0 deletions podcasts/TranscriptViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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] {
Expand Down