@@ -5,8 +5,8 @@ import Foundation
55/// (read/feed?q=query)
66///
77public struct ReaderFeed : Decodable {
8- public let url : URL
9- public let title : String
8+ public let url : URL ?
9+ public let title : String ?
1010 public let feedDescription : String ?
1111 public let feedID : String ?
1212 public let blogID : String ?
@@ -26,15 +26,7 @@ public struct ReaderFeed: Decodable {
2626
2727 private enum DataKeys : CodingKey {
2828 case site
29- }
30-
31- private enum SiteKeys : CodingKey {
32- case description
33- case icon
34- }
35-
36- private enum IconKeys : CodingKey {
37- case img
29+ case feed
3830 }
3931
4032 public init ( from decoder: Decoder ) throws {
@@ -44,32 +36,77 @@ public struct ReaderFeed: Decodable {
4436 // - We want to decode whatever we can get, and not fail if neither of those exist
4537 let rootContainer = try decoder. container ( keyedBy: CodingKeys . self)
4638
47- url = try rootContainer. decode ( URL . self, forKey: . url)
48- title = try rootContainer. decode ( String . self, forKey: . title)
39+ var feedURL = try ? rootContainer. decodeIfPresent ( URL . self, forKey: . url)
40+ var title = try ? rootContainer. decodeIfPresent ( String . self, forKey: . title)
4941 feedID = try ? rootContainer. decode ( String . self, forKey: . feedID)
5042 blogID = try ? rootContainer. decode ( String . self, forKey: . blogID)
5143
5244 var feedDescription : String ?
5345 var blavatarURL : URL ?
5446
47+ // Try to parse both site and feed data from meta.data
5548 do {
5649 let metaContainer = try rootContainer. nestedContainer ( keyedBy: MetaKeys . self, forKey: . meta)
5750 let dataContainer = try metaContainer. nestedContainer ( keyedBy: DataKeys . self, forKey: . data)
58- let siteContainer = try dataContainer. nestedContainer ( keyedBy: SiteKeys . self, forKey: . site)
59- feedDescription = try ? siteContainer. decode ( String . self, forKey: . description)
6051
61- let iconContainer = try siteContainer. nestedContainer ( keyedBy: IconKeys . self, forKey: . icon)
62- blavatarURL = try ? iconContainer. decode ( URL . self, forKey: . img)
52+ let siteData = try ? dataContainer. decode ( SiteOrFeedData . self, forKey: . site)
53+ let feedData = try ? dataContainer. decode ( SiteOrFeedData . self, forKey: . feed)
54+
55+ // Use data from either source, preferring site data when both are available
56+ feedDescription = siteData? . description ?? feedData? . description
57+ blavatarURL = siteData? . iconURL ?? feedData? . iconURL
58+
59+ // Fixes CMM-1002: in some cases, the backend fails to embed certain fields
60+ // directly in the feed object
61+ if feedURL == nil {
62+ feedURL = siteData? . url ?? feedData? . url
63+ }
64+ if title == nil {
65+ title = siteData? . title ?? feedData? . title
66+ }
6367 } catch {
6468 }
6569
70+ self . url = feedURL
71+ self . title = title
6672 self . feedDescription = feedDescription
6773 self . blavatarURL = blavatarURL
6874 }
6975}
7076
77+ private struct SiteOrFeedData : Decodable {
78+ var title : String ?
79+ var description : String ?
80+ var iconURL : URL ?
81+ var url : URL ?
82+
83+ enum CodingKeys : String , CodingKey {
84+ case description
85+ case icon
86+ case url = " URL "
87+ case name
88+ }
89+
90+ private enum IconKeys : CodingKey {
91+ case img
92+ }
93+
94+ init ( from decoder: Decoder ) throws {
95+ let container = try decoder. container ( keyedBy: CodingKeys . self)
96+
97+ title = try ? container. decodeIfPresent ( String . self, forKey: . name)
98+ description = try ? container. decodeIfPresent ( String . self, forKey: . description)
99+ url = try ? container. decodeIfPresent ( URL . self, forKey: . url)
100+
101+ // Try to decode the icon URL from the nested icon dictionary
102+ if let iconContainer = try ? container. nestedContainer ( keyedBy: IconKeys . self, forKey: . icon) {
103+ iconURL = try ? iconContainer. decode ( URL . self, forKey: . img)
104+ }
105+ }
106+ }
107+
71108extension ReaderFeed : CustomStringConvertible {
72109 public var description : String {
73- return " <Feed | URL: \( url) , title: \( title) , feedID: \( String ( describing: feedID) ) , blogID: \( String ( describing: blogID) ) > "
110+ return " <Feed | URL: \( String ( describing : url) ) , title: \( String ( describing : title) ) , feedID: \( String ( describing: feedID) ) , blogID: \( String ( describing: blogID) ) > "
74111 }
75112}
0 commit comments