This commit is contained in:
Brent Simmons 2019-04-08 17:34:49 -07:00
commit 3588ce8e2b
5 changed files with 57 additions and 81 deletions

View File

@ -15,30 +15,28 @@ struct ArticleRenderer {
private let article: Article? private let article: Article?
private let articleStyle: ArticleStyle private let articleStyle: ArticleStyle
private let appearance: NSAppearance?
private let title: String private let title: String
private init(article: Article?, style: ArticleStyle, appearance: NSAppearance?) { private init(article: Article?, style: ArticleStyle) {
self.article = article self.article = article
self.articleStyle = style self.articleStyle = style
self.appearance = appearance
self.title = article?.title ?? "" self.title = article?.title ?? ""
} }
// MARK: - API // MARK: - API
static func articleHTML(article: Article, style: ArticleStyle, appearance: NSAppearance?) -> String { static func articleHTML(article: Article, style: ArticleStyle) -> String {
let renderer = ArticleRenderer(article: article, style: style, appearance: appearance) let renderer = ArticleRenderer(article: article, style: style)
return renderer.articleHTML return renderer.articleHTML
} }
static func multipleSelectionHTML(style: ArticleStyle, appearance: NSAppearance?) -> String { static func multipleSelectionHTML(style: ArticleStyle) -> String {
let renderer = ArticleRenderer(article: nil, style: style, appearance: appearance) let renderer = ArticleRenderer(article: nil, style: style)
return renderer.multipleSelectionHTML return renderer.multipleSelectionHTML
} }
static func noSelectionHTML(style: ArticleStyle, appearance: NSAppearance?) -> String { static func noSelectionHTML(style: ArticleStyle) -> String {
let renderer = ArticleRenderer(article: nil, style: style, appearance: appearance) let renderer = ArticleRenderer(article: nil, style: style)
return renderer.noSelectionHTML return renderer.noSelectionHTML
} }
} }
@ -338,8 +336,7 @@ private extension ArticleRenderer {
""" """
let appearanceClass = appearance?.isDarkMode ?? false ? "dark" : "light" s += "\n\n</head><body onload='startup()'>\n\n"
s += "\n\n</head><body id='bodyId' onload='startup()' class=\(appearanceClass)>\n\n"
s += body s += body
s += "\n\n</body></html>" s += "\n\n</body></html>"

View File

@ -40,11 +40,6 @@ final class DetailWebView: WKWebView {
super.willOpenMenu(menu, with: event) super.willOpenMenu(menu, with: event)
} }
override func viewDidChangeEffectiveAppearance() {
let bodyClass = effectiveAppearance.isDarkMode ? "dark" : "light"
evaluateJavaScript("document.getElementById('bodyId').className = '\(bodyClass)'")
}
override func viewWillStartLiveResize() { override func viewWillStartLiveResize() {
super.viewWillStartLiveResize() super.viewWillStartLiveResize()
evaluateJavaScript("document.body.style.overflow = 'hidden';", completionHandler: nil) evaluateJavaScript("document.body.style.overflow = 'hidden';", completionHandler: nil)

View File

@ -62,12 +62,8 @@ final class DetailWebViewController: NSViewController, WKUIDelegate {
view = webview view = webview
DispatchQueue.main.async {
// Must do this async, because reloadHTML references view.effectiveAppearance,
// which causes loadView to get called. Infinite loop.
self.reloadHTML() self.reloadHTML()
} }
}
// MARK: Scrolling // MARK: Scrolling
@ -119,17 +115,16 @@ private extension DetailWebViewController {
func reloadHTML() { func reloadHTML() {
let style = ArticleStylesManager.shared.currentStyle let style = ArticleStylesManager.shared.currentStyle
let appearance = view.effectiveAppearance
let html: String let html: String
var baseURL: URL? = nil var baseURL: URL? = nil
switch state { switch state {
case .noSelection: case .noSelection:
html = ArticleRenderer.noSelectionHTML(style: style, appearance: appearance) html = ArticleRenderer.noSelectionHTML(style: style)
case .multipleSelection: case .multipleSelection:
html = ArticleRenderer.multipleSelectionHTML(style: style, appearance: appearance) html = ArticleRenderer.multipleSelectionHTML(style: style)
case .article(let article): case .article(let article):
html = ArticleRenderer.articleHTML(article: article, style: style, appearance: appearance) html = ArticleRenderer.articleHTML(article: article, style: style)
baseURL = article.baseURL baseURL = article.baseURL
} }

View File

@ -28,73 +28,62 @@ a:hover {
transform: translateX(-55%) translateY(-50%); transform: translateX(-55%) translateY(-50%);
} }
/* Light mode */ :root {
--body-color: #444;
body.light { --body-background-color: -apple-system-text-background;
color: #444; --link-color: hsla(215, 99%, 43%, 1);
background-color: -apple-system-text-background; --header-table-border-color: rgba(0, 0, 0, 0.1);
--header-color: rgba(0, 0, 0, 0.3);
--header-link-color: rgba(0, 0, 0, 0.3);
--body-code-color: #666;
--system-message-color: #cbcbcb;
--feedlink-color: rgba(0, 0, 0, 0.6);
} }
body.light a, body.light a:link, body.light a:visited { @media(prefers-color-scheme: dark) {
color: hsla(215, 99%, 43%, 1); :root {
} --body-color: #d2d2d2;
body.light .headerTable { --body-background-color: #2d2d2d;
border-bottom: 1px solid rgba(0, 0, 0, 0.1); --link-color: #4490e2;
} --header-table-border-color: rgba(255, 255, 255, 0.1);
body.light .header { --header-color: #d2d2d2;
color: rgba(0, 0, 0, 0.3); --header-link-color: #4490e2;
} --body-code-color: #b2b2b2;
body.light .header a:link, body.light .header a:visited { --system-message-color: #5f5f5f
color: rgba(0, 0, 0, 0.3); }
}
body.light .articleDateline, body.light .articleDateLine.a:link, body.light .articleDateline a:visited {
color: rgba(0, 0, 0, 0.3);
} }
body.light code, body.light pre { body {
color: #666; color: var(--body-color);
background-color: var(--body-background-color);
} }
.light > .systemMessage { body a, body a:link, body a:visited {
color: #cbcbcb; color: var(--link-color);
}
body .headerTable {
border-bottom: 1px solid var(--header-table-border-color);
}
body .header {
color: var(--header-color);
}
body .header a:link, body .header a:visited {
color: var(--header-link-color);
}
body .articleDateline, body .articleDateLine.a:link, body .articleDateline a:visited {
color: var(--header-color);
} }
/* Dark mode */ body code, body pre {
color: var(--body-code-color);
body.dark {
color: #d2d2d2;
background-color: #2d2d2d;
}
body.dark a, body.dark a:link, body.dark a:visited {
color: #4490e2;
}
body.dark .headerTable {
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
} }
body.dark .header a:link, body.dark .header a:visited { body > .systemMessage {
color: #4490e2; color: var(--system-message-color);
}
body.dark .header {
color: #d2d2d2;
}
body.dark .articleDateline {
color: #d2d2d2;
}
body.dark .articleDateline, body.dark .articleDateLine.a:link, body.dark .articleDateline a:visited {
color: #d2d2d2;
}
body.dark code, body.dark pre {
color: #b2b2b2;
}
.dark > .systemMessage {
color: #5f5f5f;
} }
.feedlink a:link, .feedlink a:visited { .feedlink a:link, .feedlink a:visited {
color: rgba(0, 0, 0, 0.6); color: var(--feed-link-color);
} }
.avatar img { .avatar img {
border-radius: 4px; border-radius: 4px;

View File

@ -20,7 +20,7 @@ import RSCore
static let articleUTIInternalType = NSPasteboard.PasteboardType(rawValue: articleUTIInternal) static let articleUTIInternalType = NSPasteboard.PasteboardType(rawValue: articleUTIInternal)
private lazy var renderedHTML: String = { private lazy var renderedHTML: String = {
return ArticleRenderer.articleHTML(article: article, style: ArticleStylesManager.shared.currentStyle, appearance: nil) return ArticleRenderer.articleHTML(article: article, style: ArticleStylesManager.shared.currentStyle)
}() }()
init(article: Article) { init(article: Article) {