Rationalize the ArticleRenderer API.
This commit is contained in:
parent
9d9afea52a
commit
8de4ff4ee3
|
@ -11,31 +11,20 @@ import RSCore
|
|||
import Articles
|
||||
import Account
|
||||
|
||||
class ArticleRenderer {
|
||||
|
||||
struct ArticleRendererResult {
|
||||
let html: String
|
||||
let baseURL: URL?
|
||||
}
|
||||
|
||||
var articleHTML: String {
|
||||
let body = RSMacroProcessor.renderedText(withTemplate: template(), substitutions: substitutions(), macroStart: "[[", macroEnd: "]]")
|
||||
return renderHTML(withBody: body)
|
||||
}
|
||||
|
||||
var multipleSelectionHTML: String {
|
||||
let body = "<h3 class='systemMessage'>Multiple selection</h3>"
|
||||
return renderHTML(withBody: body)
|
||||
}
|
||||
|
||||
var noSelectionHTML: String {
|
||||
let body = "<h3 class='systemMessage'>No selection</h3>"
|
||||
return renderHTML(withBody: body)
|
||||
}
|
||||
struct ArticleRenderer {
|
||||
|
||||
private let baseURL: URL?
|
||||
private let article: Article?
|
||||
private let articleStyle: ArticleStyle
|
||||
private let appearance: NSAppearance?
|
||||
private let title: String
|
||||
|
||||
init(article: Article?, style: ArticleStyle, appearance: NSAppearance? = nil) {
|
||||
private init(article: Article?, style: ArticleStyle, appearance: NSAppearance?) {
|
||||
self.article = article
|
||||
self.articleStyle = style
|
||||
self.appearance = appearance
|
||||
|
@ -47,12 +36,44 @@ class ArticleRenderer {
|
|||
self.baseURL = nil
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - API
|
||||
|
||||
static func articleHTML(article: Article, style: ArticleStyle, appearance: NSAppearance?) -> ArticleRendererResult {
|
||||
let renderer = ArticleRenderer(article: article, style: style, appearance: appearance)
|
||||
return ArticleRendererResult(html: renderer.articleHTML, baseURL: renderer.baseURL)
|
||||
}
|
||||
|
||||
static func multipleSelectionHTML(style: ArticleStyle, appearance: NSAppearance?) -> ArticleRendererResult {
|
||||
let renderer = ArticleRenderer(article: nil, style: style, appearance: appearance)
|
||||
return ArticleRendererResult(html: renderer.multipleSelectionHTML, baseURL: nil)
|
||||
}
|
||||
|
||||
static func noSelectionHTML(style: ArticleStyle, appearance: NSAppearance?) -> ArticleRendererResult {
|
||||
let renderer = ArticleRenderer(article: nil, style: style, appearance: appearance)
|
||||
return ArticleRendererResult(html: renderer.noSelectionHTML, baseURL: nil)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Private
|
||||
// MARK: - Private
|
||||
|
||||
private extension ArticleRenderer {
|
||||
|
||||
private var articleHTML: String {
|
||||
let body = RSMacroProcessor.renderedText(withTemplate: template(), substitutions: substitutions(), macroStart: "[[", macroEnd: "]]")
|
||||
return renderHTML(withBody: body)
|
||||
}
|
||||
|
||||
private var multipleSelectionHTML: String {
|
||||
let body = "<h3 class='systemMessage'>Multiple selection</h3>"
|
||||
return renderHTML(withBody: body)
|
||||
}
|
||||
|
||||
private var noSelectionHTML: String {
|
||||
let body = "<h3 class='systemMessage'>No selection</h3>"
|
||||
return renderHTML(withBody: body)
|
||||
}
|
||||
|
||||
static var faviconImgTagCache = [Feed: String]()
|
||||
static var feedIconImgTagCache = [Feed: String]()
|
||||
|
||||
|
@ -362,6 +383,5 @@ private extension ArticleRenderer {
|
|||
//print(s)
|
||||
|
||||
return s
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ final class DetailViewController: NSViewController, WKUIDelegate {
|
|||
|
||||
var articles: [Article]? {
|
||||
didSet {
|
||||
if articles == articles {
|
||||
if articles == oldValue {
|
||||
return
|
||||
}
|
||||
statusBarView.mouseoverLink = nil
|
||||
|
@ -43,7 +43,6 @@ final class DetailViewController: NSViewController, WKUIDelegate {
|
|||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(timelineSelectionDidChange(_:)), name: .TimelineSelectionDidChange, object: nil)
|
||||
|
||||
let preferences = WKPreferences()
|
||||
|
@ -74,10 +73,9 @@ final class DetailViewController: NSViewController, WKUIDelegate {
|
|||
containerView.viewController = self
|
||||
}
|
||||
|
||||
// MARK: - Scrolling
|
||||
// MARK: Scrolling
|
||||
|
||||
func canScrollDown(_ callback: @escaping (Bool) -> Void) {
|
||||
|
||||
if webviewIsHidden {
|
||||
callback(false)
|
||||
return
|
||||
|
@ -96,7 +94,7 @@ final class DetailViewController: NSViewController, WKUIDelegate {
|
|||
webview.scrollPageDown(sender)
|
||||
}
|
||||
|
||||
// MARK: - Notifications
|
||||
// MARK: Notifications
|
||||
|
||||
@objc func timelineSelectionDidChange(_ notification: Notification) {
|
||||
|
||||
|
@ -122,7 +120,7 @@ final class DetailViewController: NSViewController, WKUIDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
// MARK: - WKNavigationDelegate
|
||||
// MARK: WKNavigationDelegate
|
||||
|
||||
extension DetailViewController: WKNavigationDelegate {
|
||||
|
||||
|
@ -142,7 +140,7 @@ extension DetailViewController: WKNavigationDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
// MARK: - WKScriptMessageHandler
|
||||
// MARK: WKScriptMessageHandler
|
||||
|
||||
extension DetailViewController: WKScriptMessageHandler {
|
||||
|
||||
|
@ -168,29 +166,29 @@ extension DetailViewController: WKScriptMessageHandler {
|
|||
}
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
// MARK: Private
|
||||
|
||||
private extension DetailViewController {
|
||||
|
||||
func reloadHTML() {
|
||||
let articleRendererResult: ArticleRendererResult
|
||||
let style = ArticleStylesManager.shared.currentStyle
|
||||
let appearance = self.view.effectiveAppearance
|
||||
|
||||
let articleRenderer = ArticleRenderer(article: article,
|
||||
style: ArticleStylesManager.shared.currentStyle,
|
||||
appearance: self.view.effectiveAppearance)
|
||||
|
||||
if article != nil {
|
||||
webview.loadHTMLString(articleRenderer.articleHTML, baseURL: articleRenderer.baseURL)
|
||||
if let articles = articles, articles.count > 1 {
|
||||
articleRendererResult = ArticleRenderer.multipleSelectionHTML(style: style, appearance: appearance)
|
||||
}
|
||||
else if articles != nil {
|
||||
webview.loadHTMLString(articleRenderer.multipleSelectionHTML, baseURL: nil)
|
||||
else if let article = article {
|
||||
articleRendererResult = ArticleRenderer.articleHTML(article: article, style: style, appearance: appearance)
|
||||
}
|
||||
else {
|
||||
webview.loadHTMLString(articleRenderer.noSelectionHTML, baseURL: nil)
|
||||
articleRendererResult = ArticleRenderer.noSelectionHTML(style: style, appearance: appearance)
|
||||
}
|
||||
|
||||
webview.loadHTMLString(articleRendererResult.html, baseURL: articleRendererResult.baseURL)
|
||||
}
|
||||
|
||||
func fetchScrollInfo(_ callback: @escaping (ScrollInfo?) -> Void) {
|
||||
|
||||
let javascriptString = "var x = {contentHeight: document.body.scrollHeight, offsetY: document.body.scrollTop}; x"
|
||||
webview.evaluateJavaScript(javascriptString) { (info, error) in
|
||||
|
||||
|
@ -245,7 +243,7 @@ final class DetailContainerView: NSView {
|
|||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
// MARK: - ScrollInfo
|
||||
|
||||
private struct ScrollInfo {
|
||||
|
||||
|
@ -256,7 +254,6 @@ private struct ScrollInfo {
|
|||
let canScrollUp: Bool
|
||||
|
||||
init(contentHeight: CGFloat, viewHeight: CGFloat, offsetY: CGFloat) {
|
||||
|
||||
self.contentHeight = contentHeight
|
||||
self.viewHeight = viewHeight
|
||||
self.offsetY = offsetY
|
||||
|
|
|
@ -20,8 +20,8 @@ import RSCore
|
|||
static let articleUTIInternalType = NSPasteboard.PasteboardType(rawValue: articleUTIInternal)
|
||||
|
||||
private lazy var renderedHTML: String = {
|
||||
let articleRenderer = ArticleRenderer(article: article, style: ArticleStylesManager.shared.currentStyle)
|
||||
return articleRenderer.articleHTML
|
||||
let articleRendererResult = ArticleRenderer.articleHTML(article: article, style: ArticleStylesManager.shared.currentStyle, appearance: nil)
|
||||
return articleRendererResult.html
|
||||
}()
|
||||
|
||||
init(article: Article) {
|
||||
|
|
Loading…
Reference in New Issue