NetNewsWire/Shared/ArticleRendering/ArticleIconSchemeHandler.swift
2025-01-22 21:45:09 -08:00

80 lines
2.7 KiB
Swift
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// ArticleIconSchemeHandler.swift
// NetNewsWire
//
// Created by Brent Simmons on 1/20/25.
// Copyright © 2025 Ranchero Software. All rights reserved.
//
import Foundation
import WebKit
protocol ArticleIconSchemeHandlerDelegate: AnyObject {
func articleIconSchemeHandler(_: ArticleIconSchemeHandler, imageForArticleID: String) -> IconImage?
}
final class ArticleIconSchemeHandler: NSObject, WKURLSchemeHandler {
private weak var delegate: ArticleIconSchemeHandlerDelegate?
private static let headerFields = ["Cache-Control": "no-cache"]
init(delegate: ArticleIconSchemeHandlerDelegate) {
self.delegate = delegate
}
// WKURLSchemeHandler is @MainActor, so this is @MainActor.
func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) {
guard let url = urlSchemeTask.request.url,
let components = URLComponents(url: url, resolvingAgainstBaseURL: false) else {
assertionFailure("Expected URL and components in ArticleIconSchemeHandler.")
urlSchemeTask.didFailWithError(URLError(.fileDoesNotExist))
return
}
let articleID = components.path
guard !articleID.isEmpty else {
assertionFailure("Expected non-empty articleID in ArticleIconSchemeHandler.")
urlSchemeTask.didFailWithError(URLError(.fileDoesNotExist))
return
}
guard let iconImage = delegate?.articleIconSchemeHandler(self, imageForArticleID: articleID) else {
// There may not be an image this is not a programming error.
urlSchemeTask.didFailWithError(URLError(.fileDoesNotExist))
return
}
let iconView = IconView(frame: CGRect(x: 0, y: 0, width: 48, height: 48))
iconView.iconImage = iconImage
let renderedImage = iconView.asImage()
guard let data = renderedImage.dataRepresentation() else {
assertionFailure("Expected non-empty image data ArticleIconSchemeHandler.")
urlSchemeTask.didFailWithError(URLError(.fileDoesNotExist))
return
}
guard let response = HTTPURLResponse(url: url, statusCode: 200, httpVersion: nil, headerFields: Self.headerFields) else {
assertionFailure("Expected to create HTTPURLResponse but failed.")
urlSchemeTask.didFailWithError(URLError(.unknown))
return
}
urlSchemeTask.didReceive(response)
urlSchemeTask.didReceive(data)
urlSchemeTask.didFinish()
}
func webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask) {
urlSchemeTask.didFailWithError(URLError(.unknown))
}
}
// TODO: The above code is re-rendering images multiple times, which is not good
// for performance. Fixing this will probably require some refactoring
// of the entire system for images, so that the code gets some kind of identifier
// probably a URL  so that it has a key for a cache, so it doesnt have to
// re-render images.