1
1
mirror of https://github.com/qvacua/vimr.git synced 2024-12-01 18:39:52 +03:00
vimr/VimR/HtmlPreviewTool.swift

162 lines
4.3 KiB
Swift
Raw Normal View History

2017-03-24 19:47:08 +03:00
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Cocoa
import RxSwift
import PureLayout
import WebKit
import Swifter
import EonilFileSystemEvents
fileprivate let fileSystemEventsLatency = 1.0
fileprivate let monitorDispatchQueue = DispatchQueue.global(qos: .userInitiated)
2017-03-24 19:47:08 +03:00
2017-04-02 23:33:25 +03:00
class HtmlPreviewTool: NSView, UiComponent, WKNavigationDelegate {
2017-03-24 19:47:08 +03:00
enum Action {
case selectHtmlFile(URL)
}
typealias StateType = MainWindow.State
let innerCustomToolbar = InnerCustomToolbar()
required init(source: Observable<StateType>, emitter: ActionEmitter, state: StateType) {
2017-04-26 20:40:42 +03:00
self.emit = emitter.typedEmit()
2017-03-24 19:47:08 +03:00
self.uuid = state.uuid
let configuration = WKWebViewConfiguration()
self.webview = WKWebView(frame: CGRect.zero, configuration: configuration)
super.init(frame: .zero)
self.configureForAutoLayout()
2017-04-02 23:33:25 +03:00
self.webview.navigationDelegate = self
2017-03-24 19:47:08 +03:00
self.innerCustomToolbar.htmlPreviewTool = self
self.addViews()
if let serverUrl = state.htmlPreview.server?.payload {
self.webview.load(URLRequest(url: serverUrl))
}
2017-03-24 19:47:08 +03:00
source
.observeOn(MainScheduler.instance)
.subscribe(onNext: { [unowned self] state in
guard let serverUrl = state.htmlPreview.server, let htmlFileUrl = state.htmlPreview.htmlFile else {
self.monitor = nil
return
}
if serverUrl.mark == self.mark {
return
}
self.monitor = FileSystemEventMonitor(pathsToWatch: [htmlFileUrl.path],
2017-04-02 23:12:14 +03:00
latency: fileSystemEventsLatency,
watchRoot: false,
queue: monitorDispatchQueue)
{ [unowned self] events in
2017-04-02 23:33:25 +03:00
self.reloadWebview(with: serverUrl.payload)
}
self.innerCustomToolbar.selectHtmlFile.toolTip = (htmlFileUrl.path as NSString).abbreviatingWithTildeInPath
self.mark = serverUrl.mark
2017-04-02 23:33:25 +03:00
self.reloadWebview(with: serverUrl.payload)
2017-03-24 19:47:08 +03:00
})
.disposed(by: self.disposeBag)
2017-03-24 19:47:08 +03:00
}
2017-04-02 23:33:25 +03:00
fileprivate func reloadWebview(with url: URL) {
self.webview.evaluateJavaScript("document.body.scrollTop") { (result, error) in
self.scrollTop = result as? Int ?? 0
self.webview.load(URLRequest(url: url))
}
}
2017-03-24 19:47:08 +03:00
fileprivate func addViews() {
self.webview.configureForAutoLayout()
self.addSubview(self.webview)
self.webview.autoPinEdgesToSuperviewEdges()
}
2017-04-22 16:56:13 +03:00
fileprivate let emit: (UuidAction<Action>) -> Void
2017-03-24 19:47:08 +03:00
fileprivate let uuid: String
fileprivate var mark = Token()
2017-04-02 23:33:25 +03:00
fileprivate var scrollTop = 0
2017-03-24 19:47:08 +03:00
fileprivate let webview: WKWebView
fileprivate var monitor: FileSystemEventMonitor?
2017-03-24 19:47:08 +03:00
fileprivate let disposeBag = DisposeBag()
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func selectHtmlFile(sender: Any?) {
let panel = NSOpenPanel()
panel.canChooseDirectories = false
panel.allowsMultipleSelection = false
panel.beginSheetModal(for: self.window!) { result in
guard result == NSFileHandlingPanelOKButton else {
return
}
let urls = panel.urls
guard urls.count == 1 else {
return
}
2017-04-22 16:56:13 +03:00
self.emit(UuidAction(uuid: self.uuid, action: .selectHtmlFile(urls[0])))
2017-03-24 19:47:08 +03:00
}
}
2017-04-02 23:33:25 +03:00
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
self.webview.evaluateJavaScript("document.body.scrollTop = \(self.scrollTop)")
}
2017-03-24 19:47:08 +03:00
}
extension HtmlPreviewTool {
class InnerCustomToolbar: NSView {
fileprivate weak var htmlPreviewTool: HtmlPreviewTool? {
didSet {
self.selectHtmlFile.target = self.htmlPreviewTool
}
}
2017-04-02 23:12:14 +03:00
let selectHtmlFile = NSButton(forAutoLayout: ())
2017-03-24 19:47:08 +03:00
init() {
super.init(frame: .zero)
self.configureForAutoLayout()
self.addViews()
}
fileprivate func addViews() {
let selectHtmlFile = self.selectHtmlFile
InnerToolBar.configureToStandardIconButton(button: selectHtmlFile, iconName: .fileCodeO)
selectHtmlFile.toolTip = "Select the HTML file"
selectHtmlFile.action = #selector(HtmlPreviewTool.selectHtmlFile)
self.addSubview(selectHtmlFile)
selectHtmlFile.autoPinEdge(toSuperviewEdge: .top)
selectHtmlFile.autoPinEdge(toSuperviewEdge: .right)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
}