add html email rendering with wkwebview, script/tracker blocking
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
64
Apps/MagnumOpus/Views/MessageWebView.swift
Normal file
64
Apps/MagnumOpus/Views/MessageWebView.swift
Normal file
@@ -0,0 +1,64 @@
|
||||
import SwiftUI
|
||||
import WebKit
|
||||
|
||||
#if os(macOS)
|
||||
struct MessageWebView: NSViewRepresentable {
|
||||
let html: String
|
||||
|
||||
func makeNSView(context: Context) -> WKWebView {
|
||||
let config = WKWebViewConfiguration()
|
||||
config.preferences.isElementFullscreenEnabled = false
|
||||
let prefs = WKWebpagePreferences()
|
||||
prefs.allowsContentJavaScript = false
|
||||
config.defaultWebpagePreferences = prefs
|
||||
let webView = WKWebView(frame: .zero, configuration: config)
|
||||
return webView
|
||||
}
|
||||
|
||||
func updateNSView(_ webView: WKWebView, context: Context) {
|
||||
let sanitized = sanitizeHTML(html)
|
||||
webView.loadHTMLString(sanitized, baseURL: nil)
|
||||
}
|
||||
}
|
||||
#else
|
||||
struct MessageWebView: UIViewRepresentable {
|
||||
let html: String
|
||||
|
||||
func makeUIView(context: Context) -> WKWebView {
|
||||
let config = WKWebViewConfiguration()
|
||||
let prefs = WKWebpagePreferences()
|
||||
prefs.allowsContentJavaScript = false
|
||||
config.defaultWebpagePreferences = prefs
|
||||
let webView = WKWebView(frame: .zero, configuration: config)
|
||||
webView.scrollView.isScrollEnabled = false
|
||||
return webView
|
||||
}
|
||||
|
||||
func updateUIView(_ webView: WKWebView, context: Context) {
|
||||
let sanitized = sanitizeHTML(html)
|
||||
webView.loadHTMLString(sanitized, baseURL: nil)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
private func sanitizeHTML(_ html: String) -> String {
|
||||
var result = html
|
||||
let scriptPattern = "<script[^>]*>[\\s\\S]*?</script>"
|
||||
result = result.replacingOccurrences(of: scriptPattern, with: "", options: .regularExpression)
|
||||
let eventPattern = "\\s+on\\w+\\s*=\\s*\"[^\"]*\""
|
||||
result = result.replacingOccurrences(of: eventPattern, with: "", options: .regularExpression)
|
||||
let imgPattern = "(<img[^>]*?)\\ssrc\\s*=\\s*\"(https?://[^\"]*)\""
|
||||
result = result.replacingOccurrences(of: imgPattern, with: "$1 data-blocked-src=\"$2\"", options: .regularExpression)
|
||||
return """
|
||||
<!DOCTYPE html>
|
||||
<html><head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
body { font-family: -apple-system, system-ui; font-size: 14px; padding: 8px; }
|
||||
img[data-blocked-src] { display: none; }
|
||||
</style>
|
||||
</head><body>
|
||||
\(result)
|
||||
</body></html>
|
||||
"""
|
||||
}
|
||||
Reference in New Issue
Block a user