diff --git a/Evergreen/MainWindow/Detail/ArticleRenderer.swift b/Evergreen/MainWindow/Detail/ArticleRenderer.swift index 3e082485b..3bfa8bee8 100644 --- a/Evergreen/MainWindow/Detail/ArticleRenderer.swift +++ b/Evergreen/MainWindow/Detail/ArticleRenderer.swift @@ -133,6 +133,11 @@ class ArticleRenderer { private func linkWithText(_ text: String, _ href: String) -> String { + return ArticleRenderer.linkWithText(text, href) + } + + private static func linkWithText(_ text: String, _ href: String) -> String { + return "\(text)" } @@ -161,22 +166,29 @@ class ArticleRenderer { d["article_description"] = body d["newsitem_description"] = body + d["avatars"] = "" + if let avatars = avatarsToShow() { + var avatarHTML = "" + var ix = 0 + let ct = avatars.count + for avatar in avatars { + avatarHTML += avatar.html(dimension: 64) + if ix < ct - 1 { + avatarHTML += " " + } + ix += 1 + } + if !avatarHTML.isEmpty { + d["avatars"] = avatarHTML + } + } + var feedLink = "" if let feedTitle = article.feed?.nameForDisplay { feedLink = feedTitle if let feedURL = article.feed?.homePageURL { feedLink = linkWithTextAndClass(feedTitle, feedURL, "feedLink") } - if let feedIcon = article.feed?.iconURL { - let feedIconImage = "" - if let feedURL = article.feed?.homePageURL { - let feedIconImageLink = linkWithText(feedIconImage, feedURL) - feedLink = feedIconImageLink + " " + feedLink - } - else { - feedLink = feedIconImage + " " + feedLink - } - } } d["feedlink"] = feedLink d["feedlink_withfavicon"] = feedLink @@ -191,27 +203,107 @@ class ArticleRenderer { d["date_short"] = shortDate d["byline"] = byline() - d["author_avatar"] = authorAvatar() +// d["author_avatar"] = authorAvatar() return d } - private func authorAvatar() -> String { + struct Avatar { + let imageURL: String + let url: String? - guard let authors = article.authors, authors.count == 1, let author = authors.first else { - return "" - } - guard let avatarURL = author.avatarURL else { - return "" - } + func html(dimension: Int) -> String { - var imageTag = "" - if let authorURL = author.url { - imageTag = linkWithText(imageTag, authorURL) + let imageTag = "\(imageTag)" } + private func singleArticleSpecifiedAuthor() -> Author? { + + // The author of this article, if just one. + + if let authors = article.authors, authors.count == 1 { + return authors.first! + } + return nil + } + + private func singleFeedSpecifiedAuthor() -> Author? { + + if let authors = article.feed?.authors, authors.count == 1 { + return authors.first! + } + return nil + } + + private func feedAvatar() -> Avatar? { + + guard let feedIconURL = article.feed?.iconURL else { + return nil + } + return Avatar(imageURL: feedIconURL, url: article.feed?.homePageURL ?? article.feed?.url) + } + + private func authorAvatar() -> Avatar? { + + if let author = singleArticleSpecifiedAuthor(), let imageURL = author.avatarURL { + return Avatar(imageURL: imageURL, url: author.url) + } + if let author = singleFeedSpecifiedAuthor(), let imageURL = author.avatarURL { + return Avatar(imageURL: imageURL, url: author.url) + } + return nil + } + + private func avatarsToShow() -> [Avatar]? { + + var avatars = [Avatar]() + if let avatar = feedAvatar() { + avatars.append(avatar) + } + if let avatar = authorAvatar() { + avatars.append(avatar) + } + return avatars.isEmpty ? nil : avatars + } + + private func avatarToUse() -> Avatar? { + + // Use author if article specifies an author, otherwise use feed icon. + // If no feed icon, use feed-specified author. + + if let author = singleArticleSpecifiedAuthor(), let imageURL = author.avatarURL { + return Avatar(imageURL: imageURL, url: author.url) + } + if let feedIconURL = article.feed?.iconURL { + return Avatar(imageURL: feedIconURL, url: article.feed?.homePageURL ?? article.feed?.url) + } + if let author = singleFeedSpecifiedAuthor(), let imageURL = author.avatarURL { + return Avatar(imageURL: imageURL, url: author.url) + } + return nil + } + +// private func authorAvatar() -> String { +// +// guard let authors = article.authors, authors.count == 1, let author = authors.first else { +// return "" +// } +// guard let avatarURL = author.avatarURL else { +// return "" +// } +// +// var imageTag = "" +// if let authorURL = author.url { +// imageTag = linkWithText(imageTag, authorURL) +// } +// return "
\(imageTag)
" +// } + private func byline() -> String { guard let authors = article.authors ?? article.feed?.authors, !authors.isEmpty else { @@ -249,7 +341,7 @@ class ArticleRenderer { } - return " • " + byline + return byline } private func renderedHTML() -> String { diff --git a/Evergreen/Resources/styleSheet.css b/Evergreen/Resources/styleSheet.css index f2c18fc2b..6f485f030 100644 --- a/Evergreen/Resources/styleSheet.css +++ b/Evergreen/Resources/styleSheet.css @@ -28,6 +28,16 @@ a:hover { #articleDateline a:link, #articleDateline a:visited { color: rgba(0, 0, 0, 0.4); } +#articleDateline img { + border-radius: 7px; +} +.articleDate { + color: #2db6ff; + text-align: right; + border-bottom: 1px solid rgba(0, 0, 0, 0.5); + padding-bottom: 8px; + margin-bottom: 1em; +} #articleDescription { line-height: 1.5em; } @@ -38,6 +48,30 @@ a:hover { #authorAvatar img { border-radius: 5px; } +.rightAlign { + text-align: right; +} +.leftAlign { + text-align: left; +} +.headerContainer { + border-bottom: 1px solid rgba(0, 0, 0, 0.1); + color: rgba(0, 0, 0, 0.3); +} +.header { + color: rgba(0, 0, 0, 0.3); +} +.headerTable { + width: 100%; +} +.headerContainer img { + border-radius: 7px; + margin-right: 8px; +} +.headerContainer a:link, .headerContainer a:visited { + color: rgba(0, 0, 0, 0.5); +} + .feedIcon { border-radius: 5px; } diff --git a/Evergreen/Resources/template.html b/Evergreen/Resources/template.html index e009a1b1b..a6c324aa0 100644 --- a/Evergreen/Resources/template.html +++ b/Evergreen/Resources/template.html @@ -1,5 +1,14 @@ -
[[feedlink_withfavicon]] [[byline]]
-[[date_medium]]
-

[[newsitem_title]]

+

[[avatars]]

+

[[feedlink]] • [[byline]] • [[date_short]]

+ + +

[[newsitem_title]]

[[newsitem_description]]