From c3144f181e44b37d05b979abbebd3cf54885bea7 Mon Sep 17 00:00:00 2001 From: Alexis Drai Date: Sun, 21 May 2023 21:47:27 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=A7=99=20Improve=20Podcast=20view?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bdnpColor.colorset/Contents.json | 38 ++++++++++ .../bewjtColor.colorset/Contents.json | 38 ++++++++++ .../dgsColor.colorset/Contents.json | 38 ++++++++++ .../jjgoColor.colorset/Contents.json | 38 ++++++++++ .../jjhoColor.colorset/Contents.json | 38 ++++++++++ .../onracColor.colorset/Contents.json | 38 ++++++++++ .../spyColor.colorset/Contents.json | 38 ++++++++++ .../Colors.xcassets/unchanging/Contents.json | 6 ++ .../backgroundDark.colorset/Contents.json | 38 ++++++++++ .../backgroundLight.colorset/Contents.json | 38 ++++++++++ .../primaryDark.colorset/Contents.json | 38 ++++++++++ .../primaryLight.colorset/Contents.json | 38 ++++++++++ .../secondaryDark.colorset/Contents.json | 38 ++++++++++ .../secondaryLight.colorset/Contents.json | 38 ++++++++++ PodcastsClone/Model/Podcast.swift | 19 ++++- .../View/Episode/EpisodeViewCell.swift | 76 +++++++++---------- PodcastsClone/View/Extensions/Color.swift | 6 ++ .../View/Podcast/PodcastDetailView.swift | 23 +++--- .../View/Podcast/PodcastViewCell.swift | 30 ++++++-- PodcastsClone/View/Stubs/Stub.swift | 69 +++++++++++++---- 20 files changed, 652 insertions(+), 71 deletions(-) create mode 100644 PodcastsClone/Assets.xcassets/bdnpColor.colorset/Contents.json create mode 100644 PodcastsClone/Assets.xcassets/bewjtColor.colorset/Contents.json create mode 100644 PodcastsClone/Assets.xcassets/dgsColor.colorset/Contents.json create mode 100644 PodcastsClone/Assets.xcassets/jjgoColor.colorset/Contents.json create mode 100644 PodcastsClone/Assets.xcassets/jjhoColor.colorset/Contents.json create mode 100644 PodcastsClone/Assets.xcassets/onracColor.colorset/Contents.json create mode 100644 PodcastsClone/Assets.xcassets/spyColor.colorset/Contents.json create mode 100644 PodcastsClone/Colors.xcassets/unchanging/Contents.json create mode 100644 PodcastsClone/Colors.xcassets/unchanging/backgroundDark.colorset/Contents.json create mode 100644 PodcastsClone/Colors.xcassets/unchanging/backgroundLight.colorset/Contents.json create mode 100644 PodcastsClone/Colors.xcassets/unchanging/primaryDark.colorset/Contents.json create mode 100644 PodcastsClone/Colors.xcassets/unchanging/primaryLight.colorset/Contents.json create mode 100644 PodcastsClone/Colors.xcassets/unchanging/secondaryDark.colorset/Contents.json create mode 100644 PodcastsClone/Colors.xcassets/unchanging/secondaryLight.colorset/Contents.json diff --git a/PodcastsClone/Assets.xcassets/bdnpColor.colorset/Contents.json b/PodcastsClone/Assets.xcassets/bdnpColor.colorset/Contents.json new file mode 100644 index 0000000..56df92b --- /dev/null +++ b/PodcastsClone/Assets.xcassets/bdnpColor.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.620", + "green" : "0.870", + "red" : "0.910" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.620", + "green" : "0.870", + "red" : "0.910" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/PodcastsClone/Assets.xcassets/bewjtColor.colorset/Contents.json b/PodcastsClone/Assets.xcassets/bewjtColor.colorset/Contents.json new file mode 100644 index 0000000..5547f36 --- /dev/null +++ b/PodcastsClone/Assets.xcassets/bewjtColor.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.560", + "green" : "0.230", + "red" : "0.080" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.560", + "green" : "0.230", + "red" : "0.080" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/PodcastsClone/Assets.xcassets/dgsColor.colorset/Contents.json b/PodcastsClone/Assets.xcassets/dgsColor.colorset/Contents.json new file mode 100644 index 0000000..f68554d --- /dev/null +++ b/PodcastsClone/Assets.xcassets/dgsColor.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.000", + "green" : "0.810", + "red" : "1.000" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.000", + "green" : "0.810", + "red" : "1.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/PodcastsClone/Assets.xcassets/jjgoColor.colorset/Contents.json b/PodcastsClone/Assets.xcassets/jjgoColor.colorset/Contents.json new file mode 100644 index 0000000..bd14b20 --- /dev/null +++ b/PodcastsClone/Assets.xcassets/jjgoColor.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.700", + "green" : "0.670", + "red" : "0.010" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.700", + "green" : "0.670", + "red" : "0.010" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/PodcastsClone/Assets.xcassets/jjhoColor.colorset/Contents.json b/PodcastsClone/Assets.xcassets/jjhoColor.colorset/Contents.json new file mode 100644 index 0000000..c6b0321 --- /dev/null +++ b/PodcastsClone/Assets.xcassets/jjhoColor.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.350", + "green" : "0.040", + "red" : "0.080" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.350", + "green" : "0.040", + "red" : "0.080" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/PodcastsClone/Assets.xcassets/onracColor.colorset/Contents.json b/PodcastsClone/Assets.xcassets/onracColor.colorset/Contents.json new file mode 100644 index 0000000..6a153bc --- /dev/null +++ b/PodcastsClone/Assets.xcassets/onracColor.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.340", + "green" : "0.130", + "red" : "0.050" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.340", + "green" : "0.130", + "red" : "0.050" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/PodcastsClone/Assets.xcassets/spyColor.colorset/Contents.json b/PodcastsClone/Assets.xcassets/spyColor.colorset/Contents.json new file mode 100644 index 0000000..23dc698 --- /dev/null +++ b/PodcastsClone/Assets.xcassets/spyColor.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.750", + "green" : "0.080", + "red" : "0.030" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.750", + "green" : "0.080", + "red" : "0.030" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/PodcastsClone/Colors.xcassets/unchanging/Contents.json b/PodcastsClone/Colors.xcassets/unchanging/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/PodcastsClone/Colors.xcassets/unchanging/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/PodcastsClone/Colors.xcassets/unchanging/backgroundDark.colorset/Contents.json b/PodcastsClone/Colors.xcassets/unchanging/backgroundDark.colorset/Contents.json new file mode 100644 index 0000000..6af7322 --- /dev/null +++ b/PodcastsClone/Colors.xcassets/unchanging/backgroundDark.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.100", + "green" : "0.100", + "red" : "0.100" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.100", + "green" : "0.100", + "red" : "0.100" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/PodcastsClone/Colors.xcassets/unchanging/backgroundLight.colorset/Contents.json b/PodcastsClone/Colors.xcassets/unchanging/backgroundLight.colorset/Contents.json new file mode 100644 index 0000000..0119781 --- /dev/null +++ b/PodcastsClone/Colors.xcassets/unchanging/backgroundLight.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.900", + "green" : "0.900", + "red" : "0.900" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.900", + "green" : "0.900", + "red" : "0.900" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/PodcastsClone/Colors.xcassets/unchanging/primaryDark.colorset/Contents.json b/PodcastsClone/Colors.xcassets/unchanging/primaryDark.colorset/Contents.json new file mode 100644 index 0000000..f5ed17a --- /dev/null +++ b/PodcastsClone/Colors.xcassets/unchanging/primaryDark.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.910", + "green" : "0.910", + "red" : "0.910" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.910", + "green" : "0.910", + "red" : "0.910" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/PodcastsClone/Colors.xcassets/unchanging/primaryLight.colorset/Contents.json b/PodcastsClone/Colors.xcassets/unchanging/primaryLight.colorset/Contents.json new file mode 100644 index 0000000..d6445cb --- /dev/null +++ b/PodcastsClone/Colors.xcassets/unchanging/primaryLight.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.090", + "green" : "0.090", + "red" : "0.090" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.090", + "green" : "0.090", + "red" : "0.090" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/PodcastsClone/Colors.xcassets/unchanging/secondaryDark.colorset/Contents.json b/PodcastsClone/Colors.xcassets/unchanging/secondaryDark.colorset/Contents.json new file mode 100644 index 0000000..36f354c --- /dev/null +++ b/PodcastsClone/Colors.xcassets/unchanging/secondaryDark.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "0.800", + "blue" : "0.800", + "green" : "0.800", + "red" : "0.800" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "0.800", + "blue" : "0.800", + "green" : "0.800", + "red" : "0.800" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/PodcastsClone/Colors.xcassets/unchanging/secondaryLight.colorset/Contents.json b/PodcastsClone/Colors.xcassets/unchanging/secondaryLight.colorset/Contents.json new file mode 100644 index 0000000..a5f421f --- /dev/null +++ b/PodcastsClone/Colors.xcassets/unchanging/secondaryLight.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "0.800", + "blue" : "0.250", + "green" : "0.250", + "red" : "0.250" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "0.800", + "blue" : "0.250", + "green" : "0.250", + "red" : "0.250" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/PodcastsClone/Model/Podcast.swift b/PodcastsClone/Model/Podcast.swift index c3d3736..1c72367 100644 --- a/PodcastsClone/Model/Podcast.swift +++ b/PodcastsClone/Model/Podcast.swift @@ -17,9 +17,23 @@ struct Podcast { var rating: Double var reviews: Int var genre: String + var frequency: String + var backgroundColor: Color + var backgroundIsDark: Bool init( - id: UUID, image: UIImage, title: String, by: String, episodes: [Episode], rating: Double, reviews: Int, genre: String) { + id: UUID, + image: UIImage, + title: String, + by: String, + episodes: [Episode], + rating: Double, + reviews: Int, + genre: String, + frequency: String = "Unknown", + backgroundColor: Color = Color.theme.background, + backgroundIsDark: Bool = false + ) { self.id = id self.image = image self.title = title @@ -28,6 +42,9 @@ struct Podcast { self.rating = rating self.reviews = reviews self.genre = genre + self.frequency = frequency + self.backgroundColor = backgroundColor + self.backgroundIsDark = backgroundIsDark } diff --git a/PodcastsClone/View/Episode/EpisodeViewCell.swift b/PodcastsClone/View/Episode/EpisodeViewCell.swift index 89e05a1..9255216 100644 --- a/PodcastsClone/View/Episode/EpisodeViewCell.swift +++ b/PodcastsClone/View/Episode/EpisodeViewCell.swift @@ -12,51 +12,44 @@ struct EpisodeViewCell: View { let episode: Episode - private let formatter: DateFormatter = { - // TODO display date smartly - // TODAY - // 1-6D AGO - // 14 MAY (no year if same year as now) - let formatter = DateFormatter() - formatter.dateFormat = "dd/MM/yyyy" - return formatter - }() - var body: some View { - VStack(alignment: .leading) { - // TODO make divider reach the edge on the right + VStack { Divider() .foregroundColor(Color.theme.backgroundSecondary) - - Text(formatter.string(from: episode.publicationDate)) - .font(.subheadline) - .foregroundColor(Color.theme.secondary) - - (Text(episode.title) - .font(.headline) - .foregroundColor(Color.theme.primary) - + Text("\n\(episode.description)") - .font(.body) - .foregroundColor(Color.theme.secondary)) - .lineLimit(4) - .truncationMode(.tail) + .edgesIgnoringSafeArea(.trailing) + .padding(.leading) - HStack { - Image(systemName: "play.fill") - .foregroundColor(Color.theme.accent) - .padding() - .background(Color.theme.backgroundSecondary) - .clipShape(Circle()) - Text(timeString(time: episode.duration)) - .foregroundColor(Color.theme.accent) - Spacer() - Text(Strings.threeDots) + VStack(alignment: .leading) { + + Text(formatter.localizedString(for: episode.publicationDate, relativeTo: Date())) + .font(.subheadline) .foregroundColor(Color.theme.secondary) - .padding(.horizontal) + + (Text(episode.title) + .font(.headline) + .foregroundColor(Color.theme.primary) + + Text("\n\(episode.description)") + .font(.body) + .foregroundColor(Color.theme.secondary)) + .lineLimit(4) + .truncationMode(.tail) + + HStack { + Image(systemName: "play.fill") + .foregroundColor(Color.theme.accent) + .padding() + .background(Color.theme.backgroundSecondary) + .clipShape(Circle()) + Text(timeString(time: episode.duration)) + .foregroundColor(Color.theme.accent) + Spacer() + Text(Strings.threeDots) + .foregroundColor(Color.theme.secondary) + .padding(.horizontal) + } } - + .padding() } - .padding() } private func timeString(time: TimeInterval) -> String { @@ -73,6 +66,13 @@ struct EpisodeViewCell: View { return timeComponents.joined(separator: " ") } + + private let formatter: RelativeDateTimeFormatter = { + let formatter = RelativeDateTimeFormatter() + formatter.unitsStyle = .full + return formatter + }() + } struct EpisodeViewCell_Previews: PreviewProvider { diff --git a/PodcastsClone/View/Extensions/Color.swift b/PodcastsClone/View/Extensions/Color.swift index 31adeee..eb92b8a 100644 --- a/PodcastsClone/View/Extensions/Color.swift +++ b/PodcastsClone/View/Extensions/Color.swift @@ -19,4 +19,10 @@ struct ColorTheme { let backgroundSecondary = Color("backgroundSecondary") let accent = Color("accent") let shadow = Color("shadow") + let unchangingPrimaryDark = Color("primaryDark") + let unchangingPrimaryLight = Color("primaryLight") + let unchangingSecondaryDark = Color("secondaryDark") + let unchangingSecondaryLight = Color("secondaryLight") + let unchangingBackgroundDark = Color("backgroundDark") + let unchangingBackgroundLight = Color("backgroundLight") } diff --git a/PodcastsClone/View/Podcast/PodcastDetailView.swift b/PodcastsClone/View/Podcast/PodcastDetailView.swift index 0c0166c..225d214 100644 --- a/PodcastsClone/View/Podcast/PodcastDetailView.swift +++ b/PodcastsClone/View/Podcast/PodcastDetailView.swift @@ -14,40 +14,38 @@ struct PodcastDetailView: View { var body: some View { ScrollView { ZStack() { - // TODO make this background the same as the dominant color of the podcast logo - Color.theme.background.ignoresSafeArea(.all, edges: .all) + podcast.backgroundColor.ignoresSafeArea(.all, edges: .all) VStack(alignment: .center) { - // TODO make content of the VStack below switch to dark mode if the ZStack's background is dark, and vice versa VStack(alignment: .center) { Image(uiImage: podcast.image) .resizable() .scaledToFit() .cornerRadius(12) - .shadow(color: Color.theme.shadow, radius: 10, x: 0, y: 10) + .shadow(color: Color.theme.unchangingPrimaryLight, radius: 10, x: 0, y: 5) .padding(.horizontal, 48) .padding(.vertical, 16) Text(podcast.title) .font(.title) - .foregroundColor(Color.theme.primary) + .foregroundColor(podcast.backgroundIsDark ? Color.theme.unchangingPrimaryDark : Color.theme.unchangingPrimaryLight) .multilineTextAlignment(.center) Text(podcast.by) .font(.headline) - .foregroundColor(Color.theme.secondary) + .foregroundColor(podcast.backgroundIsDark ? Color.theme.unchangingSecondaryDark : Color.theme.unchangingSecondaryLight) .multilineTextAlignment(.center) Button(action: {}) { HStack { Image(systemName: "play.fill") + .padding(.horizontal, 4) Text(Strings.latestEpisode) }} - .foregroundColor(Color.theme.primary) .padding(.vertical) .padding(.horizontal, 64) - .background(Color.theme.backgroundSecondary) - .foregroundColor(Color.theme.primary) + .background(podcast.backgroundIsDark ? Color.theme.unchangingBackgroundLight : Color.theme.unchangingBackgroundDark) + .foregroundColor(podcast.backgroundIsDark ? Color.theme.unchangingPrimaryLight : Color.theme.unchangingPrimaryDark) .clipShape(RoundedRectangle(cornerSize: CGSize(width: 12.0, height: 12.0))) // TODO replace '...' with Strings.readFurtherPrompt @@ -55,13 +53,15 @@ struct PodcastDetailView: View { .lineLimit(3) .truncationMode(.tail) .padding() + .foregroundColor(podcast.backgroundIsDark ? Color.theme.unchangingPrimaryDark : Color.theme.unchangingPrimaryLight) HStack() { - Text("\(Image(systemName: "star.fill")) \(podcast.rating, specifier: "%.1f") (\(podcast.reviews)) \(Strings.classySeparator) \(podcast.genre)") + Text("\(Image(systemName: "star.fill")) \(podcast.rating, specifier: "%.1f") (\(podcast.reviews)) \(Strings.classySeparator) \(podcast.genre) \(Strings.classySeparator) \(podcast.frequency)") .padding(.horizontal) Spacer() } + .foregroundColor(podcast.backgroundIsDark ? Color.theme.unchangingSecondaryDark : Color.theme.unchangingSecondaryLight) } Divider() @@ -91,6 +91,7 @@ struct PodcastDetailView: View { struct PodcastDetailView_Previews: PreviewProvider { static var previews: some View { - PodcastDetailView(podcast: Stub.podcasts[0]) + PodcastDetailView(podcast: Stub.podcasts[2]) + PodcastDetailView(podcast: Stub.podcasts[2]) } } diff --git a/PodcastsClone/View/Podcast/PodcastViewCell.swift b/PodcastsClone/View/Podcast/PodcastViewCell.swift index 139f2ff..cf0d27e 100644 --- a/PodcastsClone/View/Podcast/PodcastViewCell.swift +++ b/PodcastsClone/View/Podcast/PodcastViewCell.swift @@ -20,19 +20,35 @@ struct PodcastViewCell: View { Text(podcast.title) .foregroundColor(Color.theme.primary) - // TODO display relative date more smartly - // TODAY - // 1-6D AGO - // 14 MAY (no year if same year as now) - Text("Updated \(podcast.episodes.first?.publicationDate ?? Date(), style: .relative) ago") - .foregroundColor(Color.theme.secondary) + Text("Updated \(smartDate(podcast.episodes.first?.publicationDate ?? Date()))") .foregroundColor(Color.theme.secondary) .font(.footnote) } } + + func smartDate(_ date: Date) -> String { + let calendar = Calendar.current + let now = Date() + let components = calendar.dateComponents([.day, .year], from: date, to: now) + + if let day = components.day { + switch day { + case 0: + return "Today" + case 1..<7: + return "\(day)d ago" + default: + let formatter = DateFormatter() + formatter.dateFormat = "dd MMMM yyyy" + return formatter.string(from: date) + } + } else { + return "Unknown" + } + } } struct PodcastViewCell_Previews: PreviewProvider { static var previews: some View { - PodcastViewCell(podcast: Stub.podcasts[0]) + PodcastViewCell(podcast: Stub.podcasts[1]) } } diff --git a/PodcastsClone/View/Stubs/Stub.swift b/PodcastsClone/View/Stubs/Stub.swift index 8761b72..97f6c4f 100644 --- a/PodcastsClone/View/Stubs/Stub.swift +++ b/PodcastsClone/View/Stubs/Stub.swift @@ -12,37 +12,60 @@ struct Stub { static let episodes: [Episode] = [ Episode( id: UUID(), - publicationDate: Date.now.addingTimeInterval(-10000000), + publicationDate: Date.now.addingTimeInterval(-1000000000), title: "A New Ipsum", description: "Stand in doorway, unwilling to chose whether to stay in or go out more napping, more napping all the napping is exhausting sleep i'm bored inside, let me out i'm lonely outside, let me in i can't make up my mind whether to go in or out, guess i'll just stand partway in and partway out, contemplating the universe for half an hour how dare you nudge me with your foot?!?! leap into the air in greatest offense!", duration: 3463 ), Episode( id: UUID(), - publicationDate: Date.now.addingTimeInterval(-100000), + publicationDate: Date.now.addingTimeInterval(-1000000), title: "Return of the Hooman", description: "Catch mouse and gave it as a present mewl for food at 4am drink water out of the faucet and have secret plans. Stretch chase dog then run away. Kitty. Mouse if it fits, i sits. Bite off human's toes. If human is on laptop sit on the keyboard.", duration: 4480 ), Episode( id: UUID(), - publicationDate: Date.now.addingTimeInterval(-1000000), + publicationDate: Date.now.addingTimeInterval(-100000000), title: "Cat Ipsum Strikes Back", description: "Chase after silly colored fish toys around the house i want to go outside let me go outside nevermind inside is better or get video posted to internet for chasing red dot eat owner's food wack the mini furry mouse so cat meoooow i iz master of hoomaan, not hoomaan master of i, oooh damn dat dog but stuff and things. Cats making all the muffins.", duration: 4028 ), ] + static let episodesOld = Stub.episodes.map { episode in + Episode( + id: episode.id, + publicationDate: Date.now.addingTimeInterval((episode.publicationDate.timeIntervalSinceNow - Date.now.timeIntervalSinceNow) * 10), + title: episode.title, + description: episode.description, + duration: episode.duration + ) + } + + static let episodesRecent = Stub.episodes.map { episode in + Episode( + id: episode.id, + publicationDate: Date.now.addingTimeInterval((episode.publicationDate.timeIntervalSinceNow - Date.now.timeIntervalSinceNow) / 10.0), + title: episode.title, + description: episode.description, + duration: episode.duration + ) + } + static let podcasts: [Podcast] = [ Podcast( id: UUID(), image: UIImage(named: "jjho_logo")!, title: "Podcast Title 1", by: "Author 1", - episodes: episodes, + episodes: episodesOld, rating: 4.2, reviews: 2139, - genre: "Genre 1" + genre: "Genre 1", + frequency: "Weekly", + backgroundColor: Color("jjhoColor"), + backgroundIsDark: true ), Podcast( id: UUID(), @@ -52,27 +75,36 @@ struct Stub { episodes: episodes, rating: 4.2, reviews: 211, - genre: "Genre 2" + genre: "Genre 2", + frequency: "Twice weekly", + backgroundColor: Color("jjgoColor"), + backgroundIsDark: true ), Podcast( id: UUID(), image: UIImage(named: "spy_logo")!, title: "Podcast Title 3", by: "Author 3", - episodes: episodes, + episodes: episodesRecent, rating: 4.812039, reviews: 3981, - genre: "Genre 3" + genre: "Genre 3", + frequency: "Complete", + backgroundColor: Color("spyColor"), + backgroundIsDark: true ), Podcast( id: UUID(), image: UIImage(named: "bdnp_logo")!, title: "Podcast Title 4", by: "Author 4", - episodes: episodes, + episodes: episodesOld, rating: 4.2, reviews: 211, - genre: "Genre 4" + genre: "Genre 4", + frequency: "Monthly", + backgroundColor: Color("bdnpColor"), + backgroundIsDark: false ), Podcast( id: UUID(), @@ -82,17 +114,23 @@ struct Stub { episodes: episodes, rating: 4.2, reviews: 211, - genre: "Genre 5" + genre: "Genre 5", + frequency: "Daily", + backgroundColor: Color("bewjtColor"), + backgroundIsDark: true ), Podcast( id: UUID(), image: UIImage(named: "onrac_logo")!, title: "Podcast Title 6", by: "Author 6", - episodes: episodes, + episodes: episodesRecent, rating: 4.2, reviews: 211, - genre: "Genre 6" + genre: "Genre 6", + frequency: "Weekly", + backgroundColor: Color("onracColor"), + backgroundIsDark: true ), Podcast( id: UUID(), @@ -102,7 +140,10 @@ struct Stub { episodes: episodes, rating: 4.2, reviews: 211, - genre: "Genre 7" + genre: "Genre 7", + frequency: "Complete", + backgroundColor: Color("dgsColor"), + backgroundIsDark: false ), ] }