From 890a926fddae473f17352f38e4d51d8b5da43855 Mon Sep 17 00:00:00 2001 From: Brandon Titus Date: Thu, 24 Oct 2024 18:49:40 -0600 Subject: [PATCH 1/4] Add Longest Episode story --- podcasts.xcodeproj/project.pbxproj | 4 + .../EndOfYear2024StoriesModel.swift | 14 ++ .../End of Year 2024/EndOfYear2024Story.swift | 1 + .../2024/LongestEpisode2024Story.swift | 127 ++++++++++++++++++ .../Contents.json | 12 ++ .../playback-sticker-phew.svg | 6 + 6 files changed, 164 insertions(+) create mode 100644 podcasts/End of Year/Stories/2024/LongestEpisode2024Story.swift create mode 100644 podcasts/EndOfYear.xcassets/playback-sticker-phew.imageset/Contents.json create mode 100644 podcasts/EndOfYear.xcassets/playback-sticker-phew.imageset/playback-sticker-phew.svg diff --git a/podcasts.xcodeproj/project.pbxproj b/podcasts.xcodeproj/project.pbxproj index f71b12d93..426459af6 100644 --- a/podcasts.xcodeproj/project.pbxproj +++ b/podcasts.xcodeproj/project.pbxproj @@ -1721,6 +1721,7 @@ F5F6DA702BBE1109009B1934 /* CategoryButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5F6DA6F2BBE1109009B1934 /* CategoryButtonStyle.swift */; }; F5F6DA822BC0B512009B1934 /* CategoriesModalPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5F6DA812BC0B512009B1934 /* CategoriesModalPicker.swift */; }; F5F884632CC9EAA6002BED2C /* Humane-Bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = F5F884622CC9EAA6002BED2C /* Humane-Bold.otf */; }; + F5F884652CCA86AE002BED2C /* LongestEpisode2024Story.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5F884642CCA86AA002BED2C /* LongestEpisode2024Story.swift */; }; F5F89B1E2C88B40A00013118 /* ShareButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5F89B1D2C88B40A00013118 /* ShareButton.swift */; }; F5F8F3182CC314250071DD0E /* IntroStory2024.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5F8F3172CC314250071DD0E /* IntroStory2024.swift */; }; F5FE747B2C223A6100DF2EAA /* ShareImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5FF61222BD07E3A00190711 /* ShareImageView.swift */; }; @@ -3659,6 +3660,7 @@ F5F6DA6F2BBE1109009B1934 /* CategoryButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryButtonStyle.swift; sourceTree = ""; }; F5F6DA812BC0B512009B1934 /* CategoriesModalPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoriesModalPicker.swift; sourceTree = ""; }; F5F884622CC9EAA6002BED2C /* Humane-Bold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Humane-Bold.otf"; sourceTree = ""; }; + F5F884642CCA86AA002BED2C /* LongestEpisode2024Story.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LongestEpisode2024Story.swift; sourceTree = ""; }; F5F89B1D2C88B40A00013118 /* ShareButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareButton.swift; sourceTree = ""; }; F5F8F3172CC314250071DD0E /* IntroStory2024.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntroStory2024.swift; sourceTree = ""; }; F5FF611F2BD076BA00190711 /* Sharing.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Sharing.xcassets; sourceTree = ""; }; @@ -7874,6 +7876,7 @@ F53C3E822CC73538004F3581 /* TopSpotStory2024.swift */, F581ED412CC6F19300A19860 /* ListeningTime2024Story.swift */, F5D527372CC81AA700682CD5 /* EpilogueStory2024.swift */, + F5F884642CCA86AA002BED2C /* LongestEpisode2024Story.swift */, F581ED432CC6F3A400A19860 /* Top5Podcasts2024Story.swift */, ); path = 2024; @@ -9491,6 +9494,7 @@ C7FAFF5D2941844C00329B40 /* CancelConfirmationViewModel.swift in Sources */, BD14CCDF1D7D3CB800DB4547 /* SelectedPodcastCell.swift in Sources */, BD93FDA120157B2000F6EF55 /* PodcastImageView.swift in Sources */, + F5F884652CCA86AE002BED2C /* LongestEpisode2024Story.swift in Sources */, BDD5253A20477E4400AAD211 /* NSObject+AppDelegate.swift in Sources */, 8B14E3B029B9159B0069B6F2 /* SearchHistoryModel.swift in Sources */, C7080C5D2923070200D7A432 /* PlusAccountUpgradePrompt.swift in Sources */, diff --git a/podcasts/End of Year/End of Year 2024/EndOfYear2024StoriesModel.swift b/podcasts/End of Year/End of Year 2024/EndOfYear2024StoriesModel.swift index e8d04d389..144bda43a 100644 --- a/podcasts/End of Year/End of Year 2024/EndOfYear2024StoriesModel.swift +++ b/podcasts/End of Year/End of Year 2024/EndOfYear2024StoriesModel.swift @@ -24,6 +24,13 @@ class EndOfYear2024StoriesModel: StoryModel { data.listeningTime = listeningTime } + // Longest episode + if let longestEpisode = dataManager.longestEpisode(in: Self.year), + let podcast = longestEpisode.parentPodcast() { + data.longestEpisode = longestEpisode + data.longestEpisodePodcast = podcast + stories.append(.longestEpisode) + } } func story(for storyNumber: Int) -> any StoryView { @@ -34,6 +41,8 @@ class EndOfYear2024StoriesModel: StoryModel { return Top5Podcasts2024Story(top5Podcasts: data.topPodcasts) case .listeningTime: return ListeningTime2024Story(listeningTime: data.listeningTime) + case .longestEpisode: + return LongestEpisode2024Story(episode: data.longestEpisode, podcast: data.longestEpisodePodcast) case .epilogue: return EpilogueStory2024() } @@ -91,4 +100,9 @@ class EndOfYear2024StoriesData { var topPodcasts: [TopPodcast] = [] var listeningTime: Double = 0 + + var longestEpisode: Episode! + + var longestEpisodePodcast: Podcast! + } diff --git a/podcasts/End of Year/End of Year 2024/EndOfYear2024Story.swift b/podcasts/End of Year/End of Year 2024/EndOfYear2024Story.swift index e226b896b..2af5afa66 100644 --- a/podcasts/End of Year/End of Year 2024/EndOfYear2024Story.swift +++ b/podcasts/End of Year/End of Year 2024/EndOfYear2024Story.swift @@ -2,5 +2,6 @@ enum EndOfYear2024Story: CaseIterable { case intro case top5Podcasts case listeningTime + case longestEpisode case epilogue } diff --git a/podcasts/End of Year/Stories/2024/LongestEpisode2024Story.swift b/podcasts/End of Year/Stories/2024/LongestEpisode2024Story.swift new file mode 100644 index 000000000..55951fa91 --- /dev/null +++ b/podcasts/End of Year/Stories/2024/LongestEpisode2024Story.swift @@ -0,0 +1,127 @@ +import SwiftUI +import PocketCastsDataModel + +struct LongestEpisode2024Story: ShareableStory { + @Environment(\.renderForSharing) var renderForSharing: Bool + @Environment(\.animated) var animated: Bool + + @ObservedObject private var animationViewModel = PlayPauseAnimationViewModel(duration: 0.8, animation: Animation.spring(_:)) + + var identifier: String = "longest_episode" + + let episode: Episode + + let podcast: Podcast + + @State var firstCover: Double = 0.4 + @State var secondCover: Double = 0.32 + @State var thirdCover: Double = 0.24 + @State var fourthCover: Double = 0.16 + @State var fifthCover: Double = 0.08 + @State var sixthCover: Double = 0 + + var backgroundColor = Color(hex: "#E0EFAD") + + var tintColor: Color { + .white + } + + var body: some View { + GeometryReader { geometry in + VStack { + ZStack { + covers(geometry: geometry) + let stickerSize = CGSize(width: 194, height: 135) + Image("playback-sticker-phew") + .resizable() + .frame(width: stickerSize.width, height: stickerSize.height) + .position(x: -6, y: 40, for: stickerSize, in: geometry.frame(in: .local), corner: .topTrailing) + } + .frame(height: geometry.size.height * 0.65) + VStack(alignment: .leading, spacing: 16) { + let timeString = episode.playedUpTo.storyTimeDescriptionForSharing + Text("The longest episode you listened to was \(timeString)") + .font(.system(size: 31, weight: .bold)) + Text("It was \"\(episode.title ?? "unknown")\" from \"\(podcast.title ?? "unknown")\"") + .font(.system(size: 15, weight: .light)) + } + } + } + .background(backgroundColor) + .onAppear { + if animated { + setInitialCoverOffsetForAnimation() + animationViewModel.play() + } + } + } + + @ViewBuilder func covers(geometry: GeometryProxy) -> some View { + PodcastCoverContainer(geometry: geometry) { + ZStack { + PodcastCover(podcastUuid: podcast.uuid) + .frame(width: geometry.size.width * 0.5, height: geometry.size.width * 0.5) + .offset(x: -geometry.size.width * firstCover, y: geometry.size.width * firstCover) + .modifier(animationViewModel.animate($firstCover, to: 0.4)) + + PodcastCover(podcastUuid: podcast.uuid) + .frame(width: geometry.size.width * 0.55, height: geometry.size.width * 0.55) + .offset(x: -geometry.size.width * secondCover, y: geometry.size.width * secondCover) + .modifier(animationViewModel.animate($secondCover, to: 0.32)) + + PodcastCover(podcastUuid: podcast.uuid) + .frame(width: geometry.size.width * 0.6, height: geometry.size.width * 0.6) + .offset(x: -geometry.size.width * thirdCover, y: geometry.size.width * thirdCover) + .modifier(animationViewModel.animate($thirdCover, to: 0.24)) + + PodcastCover(podcastUuid: podcast.uuid) + .frame(width: geometry.size.width * 0.65, height: geometry.size.width * 0.65) + .offset(x: -geometry.size.width * fourthCover, y: geometry.size.width * fourthCover) + .modifier(animationViewModel.animate($fourthCover, to: 0.16)) + + PodcastCover(podcastUuid: podcast.uuid) + .frame(width: geometry.size.width * 0.7, height: geometry.size.width * 0.7) + .offset(x: -geometry.size.width * fifthCover, y: geometry.size.width * fifthCover) + .modifier(animationViewModel.animate($fifthCover, to: 0.08)) + + PodcastCover(podcastUuid: podcast.uuid, higherQuality: true) + .frame(width: geometry.size.width * 0.75, height: geometry.size.width * 0.75) + .offset(x: -geometry.size.width * sixthCover, y: geometry.size.width * sixthCover) + .modifier(animationViewModel.animate($sixthCover, to: 0)) + } + .offset(x: geometry.size.width * 0.04, y: geometry.size.height * 0.09) + } + } + + func onAppear() { + Analytics.track(.endOfYearStoryShown, story: identifier) + } + + func onPause() { + animationViewModel.pause() + } + + func onResume() { + animationViewModel.play() + } + + func willShare() { + Analytics.track(.endOfYearStoryShare, story: identifier) + } + + func sharingAssets() -> [Any] { + [ + StoryShareableProvider.new(AnyView(self)), + StoryShareableText(L10n.eoyStoryLongestEpisodeShareText("%1$@"), episode: episode) + ] + } + + private func setInitialCoverOffsetForAnimation() { + firstCover = 0.8 + secondCover = 0.8 + thirdCover = 0.8 + fourthCover = 0.8 + fifthCover = 0.8 + sixthCover = 0.8 + } +} diff --git a/podcasts/EndOfYear.xcassets/playback-sticker-phew.imageset/Contents.json b/podcasts/EndOfYear.xcassets/playback-sticker-phew.imageset/Contents.json new file mode 100644 index 000000000..3373da359 --- /dev/null +++ b/podcasts/EndOfYear.xcassets/playback-sticker-phew.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "playback-sticker-phew.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/podcasts/EndOfYear.xcassets/playback-sticker-phew.imageset/playback-sticker-phew.svg b/podcasts/EndOfYear.xcassets/playback-sticker-phew.imageset/playback-sticker-phew.svg new file mode 100644 index 000000000..91855e611 --- /dev/null +++ b/podcasts/EndOfYear.xcassets/playback-sticker-phew.imageset/playback-sticker-phew.svg @@ -0,0 +1,6 @@ + + + + + + From caa3dc1976c4119c46d765f8fb120125212c6bc9 Mon Sep 17 00:00:00 2001 From: Brandon Titus Date: Sun, 27 Oct 2024 15:05:20 -0600 Subject: [PATCH 2/4] Tweak spacing for smaller devices --- .../2024/LongestEpisode2024Story.swift | 87 ++++++++++--------- .../Stories/Views/PodcastCover.swift | 29 +------ podcasts/End of Year/Views/StoriesView.swift | 6 +- 3 files changed, 53 insertions(+), 69 deletions(-) diff --git a/podcasts/End of Year/Stories/2024/LongestEpisode2024Story.swift b/podcasts/End of Year/Stories/2024/LongestEpisode2024Story.swift index 55951fa91..be10a504e 100644 --- a/podcasts/End of Year/Stories/2024/LongestEpisode2024Story.swift +++ b/podcasts/End of Year/Stories/2024/LongestEpisode2024Story.swift @@ -28,23 +28,28 @@ struct LongestEpisode2024Story: ShareableStory { var body: some View { GeometryReader { geometry in - VStack { + let isSmallScreen = geometry.size.height <= 600 + VStack(alignment: .leading) { + Spacer() ZStack { - covers(geometry: geometry) + covers() let stickerSize = CGSize(width: 194, height: 135) Image("playback-sticker-phew") .resizable() .frame(width: stickerSize.width, height: stickerSize.height) - .position(x: -6, y: 40, for: stickerSize, in: geometry.frame(in: .local), corner: .topTrailing) + .position(x: -6, y: 0, for: stickerSize, in: geometry.frame(in: .global), corner: .topTrailing) } - .frame(height: geometry.size.height * 0.65) - VStack(alignment: .leading, spacing: 16) { + .frame(width: geometry.size.width * 0.9) + .padding(.top, isSmallScreen ? 0 : 20) + VStack(alignment: .leading, spacing: isSmallScreen ? 4 : 16) { let timeString = episode.playedUpTo.storyTimeDescriptionForSharing Text("The longest episode you listened to was \(timeString)") - .font(.system(size: 31, weight: .bold)) + .font(.system(size: 31, weight: .bold)) Text("It was \"\(episode.title ?? "unknown")\" from \"\(podcast.title ?? "unknown")\"") - .font(.system(size: 15, weight: .light)) + .font(.system(size: 15, weight: .light)) } + .padding(.horizontal, 24) + .padding(.bottom, isSmallScreen ? 4 : 16) } } .background(backgroundColor) @@ -56,40 +61,42 @@ struct LongestEpisode2024Story: ShareableStory { } } - @ViewBuilder func covers(geometry: GeometryProxy) -> some View { - PodcastCoverContainer(geometry: geometry) { - ZStack { - PodcastCover(podcastUuid: podcast.uuid) - .frame(width: geometry.size.width * 0.5, height: geometry.size.width * 0.5) - .offset(x: -geometry.size.width * firstCover, y: geometry.size.width * firstCover) - .modifier(animationViewModel.animate($firstCover, to: 0.4)) - - PodcastCover(podcastUuid: podcast.uuid) - .frame(width: geometry.size.width * 0.55, height: geometry.size.width * 0.55) - .offset(x: -geometry.size.width * secondCover, y: geometry.size.width * secondCover) - .modifier(animationViewModel.animate($secondCover, to: 0.32)) - - PodcastCover(podcastUuid: podcast.uuid) - .frame(width: geometry.size.width * 0.6, height: geometry.size.width * 0.6) - .offset(x: -geometry.size.width * thirdCover, y: geometry.size.width * thirdCover) - .modifier(animationViewModel.animate($thirdCover, to: 0.24)) - - PodcastCover(podcastUuid: podcast.uuid) - .frame(width: geometry.size.width * 0.65, height: geometry.size.width * 0.65) - .offset(x: -geometry.size.width * fourthCover, y: geometry.size.width * fourthCover) - .modifier(animationViewModel.animate($fourthCover, to: 0.16)) - - PodcastCover(podcastUuid: podcast.uuid) - .frame(width: geometry.size.width * 0.7, height: geometry.size.width * 0.7) - .offset(x: -geometry.size.width * fifthCover, y: geometry.size.width * fifthCover) - .modifier(animationViewModel.animate($fifthCover, to: 0.08)) - - PodcastCover(podcastUuid: podcast.uuid, higherQuality: true) - .frame(width: geometry.size.width * 0.75, height: geometry.size.width * 0.75) - .offset(x: -geometry.size.width * sixthCover, y: geometry.size.width * sixthCover) - .modifier(animationViewModel.animate($sixthCover, to: 0)) + @ViewBuilder func covers() -> some View { + GeometryReader { geometry in + PodcastCoverContainer(geometry: geometry) { + ZStack { + PodcastCover(podcastUuid: podcast.uuid) + .frame(width: geometry.size.width * 0.5, height: geometry.size.width * 0.5) + .offset(x: -geometry.size.width * firstCover, y: geometry.size.width * firstCover) + .modifier(animationViewModel.animate($firstCover, to: 0.4)) + + PodcastCover(podcastUuid: podcast.uuid) + .frame(width: geometry.size.width * 0.55, height: geometry.size.width * 0.55) + .offset(x: -geometry.size.width * secondCover, y: geometry.size.width * secondCover) + .modifier(animationViewModel.animate($secondCover, to: 0.32)) + + PodcastCover(podcastUuid: podcast.uuid) + .frame(width: geometry.size.width * 0.6, height: geometry.size.width * 0.6) + .offset(x: -geometry.size.width * thirdCover, y: geometry.size.width * thirdCover) + .modifier(animationViewModel.animate($thirdCover, to: 0.24)) + + PodcastCover(podcastUuid: podcast.uuid) + .frame(width: geometry.size.width * 0.65, height: geometry.size.width * 0.65) + .offset(x: -geometry.size.width * fourthCover, y: geometry.size.width * fourthCover) + .modifier(animationViewModel.animate($fourthCover, to: 0.16)) + + PodcastCover(podcastUuid: podcast.uuid) + .frame(width: geometry.size.width * 0.7, height: geometry.size.width * 0.7) + .offset(x: -geometry.size.width * fifthCover, y: geometry.size.width * fifthCover) + .modifier(animationViewModel.animate($fifthCover, to: 0.08)) + + PodcastCover(podcastUuid: podcast.uuid, higherQuality: true) + .frame(width: geometry.size.width * 0.75, height: geometry.size.width * 0.75) + .offset(x: -geometry.size.width * sixthCover, y: geometry.size.width * sixthCover) + .modifier(animationViewModel.animate($sixthCover, to: 0)) + } + .offset(x: geometry.size.width * 0.04, y: geometry.size.height * 0.09) } - .offset(x: geometry.size.width * 0.04, y: geometry.size.height * 0.09) } } diff --git a/podcasts/End of Year/Stories/Views/PodcastCover.swift b/podcasts/End of Year/Stories/Views/PodcastCover.swift index c32aa401b..7cd020e3c 100644 --- a/podcasts/End of Year/Stories/Views/PodcastCover.swift +++ b/podcasts/End of Year/Stories/Views/PodcastCover.swift @@ -16,7 +16,6 @@ struct PodcastCover: View { /// If the artwork needs a bigger image with higher quality var higherQuality: Bool = false - @State private var image: UIImage? @Environment(\.renderForSharing) var renderForSharing: Bool private var rectangleColor: Color? { @@ -40,36 +39,10 @@ struct PodcastCover: View { .modifier(NormalCoverShadow()) } } - .opacity(image != nil ? 1 : 0.2) .blendMode(.multiply) - ImageView(image: image) + PodcastImage(uuid: podcastUuid, size: .page) .cornerRadius(big ? 8 : 4) - - .onAppear { - if renderForSharing { - loadImage() - } - } - - Action { - if !renderForSharing { - loadImage() - } - } - } - } - - private func loadImage() { - image = nil - let size = higherQuality ? 680 : 280 - KingfisherManager.shared.retrieveImage(with: ServerHelper.imageUrl(podcastUuid: podcastUuid, size: size)) { result in - switch result { - case .success(let result): - image = result.image - default: - break - } } } } diff --git a/podcasts/End of Year/Views/StoriesView.swift b/podcasts/End of Year/Views/StoriesView.swift index a74ec8c00..792547e26 100644 --- a/podcasts/End of Year/Views/StoriesView.swift +++ b/podcasts/End of Year/Views/StoriesView.swift @@ -41,7 +41,11 @@ struct StoriesView: View { // Manually set the zIndex order to ensure we can change the order when needed model.story(index: model.currentStoryIndex) .zIndex(3) - .ignoresSafeArea(edges: .bottom) + .modify { + if model.overlaidShareView() != nil { + $0.ignoresSafeArea(edges: .bottom) + } + } .environment(\.animated, true) if model.shouldShowUpsell() { From 3a8af4ba3b2f2e685cb70fa77586ae9db3a5f078 Mon Sep 17 00:00:00 2001 From: Brandon Titus Date: Tue, 29 Oct 2024 12:34:20 -0600 Subject: [PATCH 3/4] Adjust colors for Longest Episode Story --- .../Stories/2024/LongestEpisode2024Story.swift | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/podcasts/End of Year/Stories/2024/LongestEpisode2024Story.swift b/podcasts/End of Year/Stories/2024/LongestEpisode2024Story.swift index be10a504e..0e89992d6 100644 --- a/podcasts/End of Year/Stories/2024/LongestEpisode2024Story.swift +++ b/podcasts/End of Year/Stories/2024/LongestEpisode2024Story.swift @@ -20,11 +20,8 @@ struct LongestEpisode2024Story: ShareableStory { @State var fifthCover: Double = 0.08 @State var sixthCover: Double = 0 - var backgroundColor = Color(hex: "#E0EFAD") - - var tintColor: Color { - .white - } + private let backgroundColor = Color(hex: "#E0EFAD") + private let foregroundColor = Color.black var body: some View { GeometryReader { geometry in @@ -53,6 +50,7 @@ struct LongestEpisode2024Story: ShareableStory { } } .background(backgroundColor) + .foregroundStyle(foregroundColor) .onAppear { if animated { setInitialCoverOffsetForAnimation() From db6f280acae680f4813c7c1724592196cfa42a7d Mon Sep 17 00:00:00 2001 From: Brandon Titus Date: Tue, 29 Oct 2024 12:34:32 -0600 Subject: [PATCH 4/4] Add localized strings for Longest Episode Story --- .../Stories/2024/LongestEpisode2024Story.swift | 4 ++-- podcasts/Strings+Generated.swift | 8 ++++++++ podcasts/en.lproj/Localizable.strings | 6 ++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/podcasts/End of Year/Stories/2024/LongestEpisode2024Story.swift b/podcasts/End of Year/Stories/2024/LongestEpisode2024Story.swift index 0e89992d6..967b4fb79 100644 --- a/podcasts/End of Year/Stories/2024/LongestEpisode2024Story.swift +++ b/podcasts/End of Year/Stories/2024/LongestEpisode2024Story.swift @@ -40,9 +40,9 @@ struct LongestEpisode2024Story: ShareableStory { .padding(.top, isSmallScreen ? 0 : 20) VStack(alignment: .leading, spacing: isSmallScreen ? 4 : 16) { let timeString = episode.playedUpTo.storyTimeDescriptionForSharing - Text("The longest episode you listened to was \(timeString)") + Text(L10n.playback2024LongestEpisodeTitle(timeString)) .font(.system(size: 31, weight: .bold)) - Text("It was \"\(episode.title ?? "unknown")\" from \"\(podcast.title ?? "unknown")\"") + Text(L10n.playback2024LongestEpisodeDescription(episode.title ?? "unknown", podcast.title ?? "unknown")) .font(.system(size: 15, weight: .light)) } .padding(.horizontal, 24) diff --git a/podcasts/Strings+Generated.swift b/podcasts/Strings+Generated.swift index df1b7d265..b00e827db 100644 --- a/podcasts/Strings+Generated.swift +++ b/podcasts/Strings+Generated.swift @@ -1754,6 +1754,14 @@ internal enum L10n { internal static func playback2024ListeningTimeDescription(_ p1: Any) -> String { return L10n.tr("Localizable", "playback_2024_listening_time_description", String(describing: p1)) } + /// It was "%1$@" from "%2$@" + internal static func playback2024LongestEpisodeDescription(_ p1: Any, _ p2: Any) -> String { + return L10n.tr("Localizable", "playback_2024_longest_episode_description", String(describing: p1), String(describing: p2)) + } + /// The longest episode you listened to was %1$@ + internal static func playback2024LongestEpisodeTitle(_ p1: Any) -> String { + return L10n.tr("Localizable", "playback_2024_longest_episode_title", String(describing: p1)) + } /// View My Playback 2024 internal static var playback2024ViewYear: String { return L10n.tr("Localizable", "playback_2024_view_year") } /// All podcasts diff --git a/podcasts/en.lproj/Localizable.strings b/podcasts/en.lproj/Localizable.strings index 56ac89636..d751029df 100644 --- a/podcasts/en.lproj/Localizable.strings +++ b/podcasts/en.lproj/Localizable.strings @@ -3557,6 +3557,12 @@ /* A description used to indicate the number of days and hours spent listening to podcasts in the last year */ "playback_2024_listening_time_description" = "%1$@ total listening to podcasts"; +/* A title shown with the amount of time listened on the Longest Episode screen of Playback 2024 */ +"playback_2024_longest_episode_title" = "The longest episode you listened to was %1$@"; + +/* A description shown on the Longest Episode screen of Playback 2024 with the episode title and podcast title */ +"playback_2024_longest_episode_description" = "It was \"%1$@\" from \"%2$@\""; + /* Label of the End of Year dismiss button */ "eoy_not_now" = "Not Now";