s4s-packager / wkwebview /WebView /ViewController.swift
soiz1's picture
Upload 225 files
7aec436 verified
import Cocoa
import WebKit
class ViewController: NSViewController, WKNavigationDelegate, WKUIDelegate, WKScriptMessageHandler {
@IBOutlet var webView: WKWebView!
var windowTitle: String = "Window Title"
override func loadView() {
super.loadView()
let configUrl = Bundle.main.url(forResource: "application_config", withExtension: "json")!
let configContents = try! Data(contentsOf: configUrl);
let configParsed = try! JSONSerialization.jsonObject(with: configContents, options: [])
var width = 480
var height = 360
var background = NSColor.black.cgColor
if let dict = configParsed as? [String: Any] {
if let title = dict["title"] as? String {
self.windowTitle = title
}
if let number = dict["width"] as? Int {
width = number
}
if let number = dict["height"] as? Int {
height = number
}
if let color = dict["background"] as? [Int] {
background = NSColor(
red: CGFloat(color[0]) / 255.0,
green: CGFloat(color[1]) / 255.0,
blue: CGFloat(color[2]) / 255.0,
alpha: CGFloat(color[3])
).cgColor
}
}
view.wantsLayer = true
view.layer?.backgroundColor = background
view.frame = CGRect(x: 0, y: 0, width: width, height: height)
webView.navigationDelegate = self
webView.uiDelegate = self
webView.configuration.userContentController.add(self, name: "download")
webView.configuration.preferences.setValue(true, forKey: "allowFileAccessFromFileURLs")
#if DEBUG
webView.configuration.preferences.setValue(true, forKey: "developerExtrasEnabled")
#endif
webView.isHidden = true
}
override func viewDidLoad() {
super.viewDidLoad()
let url = Bundle.main.url(forResource: "index", withExtension: "html")!
webView.loadFileURL(url, allowingReadAccessTo: url.deletingLastPathComponent())
}
override func viewDidAppear() {
super.viewDidAppear()
view.window?.title = windowTitle
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
// The packager will use window.ExternalDownloadHelper instead of native JS file downloads.
// We use this because older versions of macOS's WKWebView do not handle file downloads
// properly or at all.
webView.evaluateJavaScript("""
window.ExternalDownloadHelper = {
download: (filename, blob) => {
const reader = new FileReader();
reader.onload = () => {
const array = Array.from(new Uint8Array(reader.result));
webkit.messageHandlers.download.postMessage({
name: filename,
data: array
});
};
reader.onerror = () => {
console.error(reader.error);
};
reader.readAsArrayBuffer(blob);
}
};
""")
webView.isHidden = false
}
func webView(_ webView: WKWebView, runOpenPanelWith parameters: WKOpenPanelParameters, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping ([URL]?) -> Void) {
// Used by list import.
let panel = NSOpenPanel()
panel.canChooseFiles = true
panel.canChooseDirectories = false
panel.allowsMultipleSelection = parameters.allowsMultipleSelection
panel.allowedFileTypes = ["txt", "csv", "tsv"]
panel.allowsOtherFileTypes = true
panel.begin { (result) -> Void in
if result == NSApplication.ModalResponse.OK, let url = panel.url {
completionHandler([url])
} else {
completionHandler(nil)
}
}
}
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
// Used by window.ExternalDownloadHelper which is used by list export.
if message.name == "download",
let body = message.body as? NSDictionary,
let name = body["name"] as? NSString,
let rawData = body["data"] as? [UInt8] {
let panel = NSSavePanel()
panel.allowsOtherFileTypes = true
panel.nameFieldStringValue = name as String
panel.allowedFileTypes = ["txt"]
panel.begin { (result) -> Void in
if result == NSApplication.ModalResponse.OK, let url = panel.url {
let data = Data(rawData)
try! data.write(to: url)
}
}
}
}
@available(macOS 12.0, *)
func webView(_ webView: WKWebView, requestMediaCapturePermissionFor origin: WKSecurityOrigin, initiatedByFrame frame: WKFrameInfo, type: WKMediaCaptureType, decisionHandler: @escaping (WKPermissionDecision) -> Void) {
// macOS will already show a permission prompt.
// This code prevents WKWebView from showing an additional permission prompt each time.
decisionHandler(WKPermissionDecision.grant)
}
func webViewDidClose(_ webView: WKWebView) {
// Implements window.close()
self.view.window?.close();
}
}