diff --git a/VimR/MainWindowComponent.swift b/VimR/MainWindowComponent.swift index c2089081..08bcb3ac 100644 --- a/VimR/MainWindowComponent.swift +++ b/VimR/MainWindowComponent.swift @@ -6,6 +6,7 @@ import Cocoa import PureLayout import RxSwift +import Swifter enum MainWindowAction { @@ -109,6 +110,8 @@ class MainWindowComponent: WindowComponent, fileprivate let scrollFlow: EmbeddableComponent + fileprivate let httpServer: HttpServer; + // MARK: - API var uuid: String { return self.neoVimView.uuid @@ -141,6 +144,7 @@ class MainWindowComponent: WindowComponent, fileItemService: FileItemService, cwd: URL, urls: [URL] = [], + httpServer: HttpServer, initialData: PrefData) { self.neoVimView = NeoVimView(frame: CGRect.zero, @@ -154,6 +158,8 @@ class MainWindowComponent: WindowComponent, self.scrollFlow = EmbeddableComponent(source: Observable.empty()) + self.httpServer = httpServer + super.init(source: source, nibName: MainWindowComponent.nibName) self.window.delegate = self @@ -213,6 +219,7 @@ class MainWindowComponent: WindowComponent, let previewData = previewToolData.toolData as? PreviewComponent.PrefData ?? PreviewComponent.PrefData.default let preview = PreviewComponent(source: self.sink, scrollSource: self.scrollFlow.sink, + httpServer: self.httpServer, initialData: previewData) let previewConfig = WorkspaceTool.Config(title: "Preview", view: preview, diff --git a/VimR/MainWindowManager.swift b/VimR/MainWindowManager.swift index cf9d7ad3..369e50d0 100644 --- a/VimR/MainWindowManager.swift +++ b/VimR/MainWindowManager.swift @@ -5,6 +5,7 @@ import Cocoa import RxSwift +import Swifter enum MainWindowManagerAction { @@ -19,10 +20,20 @@ class MainWindowManager: StandardFlow { fileprivate let fileItemService: FileItemService fileprivate var data: PrefData + fileprivate let httpServer = HttpServer() // TODO: WRONG: service-ify this!!! + init(source: Observable, fileItemService: FileItemService, initialData: PrefData) { self.fileItemService = fileItemService self.data = initialData + let port = NetUtils.openPort() + NSLog("\(#function): opening a server on port \(port)") + do { + try self.httpServer.start(port) + } catch { + NSLog("ERROR \(#function): could not start the http server on port \(port)") + } + super.init(source: source) } @@ -31,6 +42,7 @@ class MainWindowManager: StandardFlow { fileItemService: self.fileItemService, cwd: cwd, urls: urls, + httpServer: self.httpServer, initialData: self.data) self.mainWindowComponents[mainWindowComponent.uuid] = mainWindowComponent @@ -60,6 +72,10 @@ class MainWindowManager: StandardFlow { return mainWindowComponent } + deinit { + self.httpServer.stop() + } + func close(_ mainWindowComponent: MainWindowComponent, prefData: MainWindowPrefData) { // Save the tools settings of the last closed main window. // TODO: Think about a better time to save this. diff --git a/VimR/MarkdownRenderer.swift b/VimR/MarkdownRenderer.swift index c0b9bfac..de74cb7f 100644 --- a/VimR/MarkdownRenderer.swift +++ b/VimR/MarkdownRenderer.swift @@ -149,8 +149,8 @@ class MarkdownRenderer: NSObject, Flow, PreviewRenderer { fileprivate var currentPreviewPosition = Position(row: 1, column: 1) fileprivate let uuid = UUID().uuidString - fileprivate var server = HttpServer() - fileprivate let port: in_port_t + fileprivate let httpServer: HttpServer + fileprivate let port: Int fileprivate let tempDir = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true) let identifier: String = MarkdownRenderer.identifier @@ -171,7 +171,10 @@ class MarkdownRenderer: NSObject, Flow, PreviewRenderer { let toolbar: NSView? = NSView(forAutoLayout: ()) let menuItems: [NSMenuItem]? - init(source: Observable, scrollSource: Observable, initialData: PrefData) { + init(source: Observable, scrollSource: Observable, httpServer: HttpServer, initialData: PrefData) { + NSLog("\(#function) \(uuid)") + NSLog("\(#function) \(self.tempDir)") + guard let templateUrl = Bundle.main.url(forResource: "template", withExtension: "html", subdirectory: "markdown") @@ -183,17 +186,11 @@ class MarkdownRenderer: NSObject, Flow, PreviewRenderer { preconditionFailure("ERROR Cannot load markdown template") } - self.server.GET["/\(MarkdownRenderer.serverPath)/github-markdown.css"] = shareFile( + self.httpServer = httpServer + self.httpServer.GET["/\(MarkdownRenderer.serverPath)/\(self.uuid)/github-markdown.css"] = shareFile( self.resourceBaesUrl.appendingPathComponent("github-markdown.css").path ) - - self.port = NetUtils.openPort() - NSLog("\(#function): opening a server on port \(port)") - do { - try self.server.start(port) - } catch { - NSLog("ERROR \(#function): could not start the http server on port \(self.port)") - } + self.port = (try? httpServer.port()) ?? 0 self.template = template @@ -257,7 +254,7 @@ class MarkdownRenderer: NSObject, Flow, PreviewRenderer { } deinit { - self.server.stop() + try? FileManager.default.removeItem(at: self.htmlFileUrl()) } func canRender(fileExtension: String) -> Bool { @@ -388,7 +385,7 @@ class MarkdownRenderer: NSObject, Flow, PreviewRenderer { } let html = filledTemplate(body: body, title: url.lastPathComponent) - let htmlFilePath = tempDir.appendingPathComponent("\(MarkdownRenderer.identifier).\(self.uuid).html").path + let htmlFilePath = self.htmlFileUrl().path do { try html.write(toFile: htmlFilePath, atomically: true, encoding: .utf8) } catch { @@ -397,16 +394,22 @@ class MarkdownRenderer: NSObject, Flow, PreviewRenderer { return } - self.server["/\(MarkdownRenderer.serverPath)/:path"] = shareFilesFromDirectory(url.deletingLastPathComponent().path) - self.server.GET["/\(MarkdownRenderer.serverPath)/index.html"] = shareFile(htmlFilePath) + self.httpServer["/\(MarkdownRenderer.serverPath)/\(self.uuid)/:path"] = + shareFilesFromDirectory(url.deletingLastPathComponent().path) + + self.httpServer.GET["/\(MarkdownRenderer.serverPath)/\(self.uuid)/index.html"] = shareFile(htmlFilePath) let urlRequest = URLRequest( - url: URL(string: "http://localhost:\(self.port)/\(MarkdownRenderer.serverPath)/index.html")! + url: URL(string: "http://localhost:\(self.port)/\(MarkdownRenderer.serverPath)/\(self.uuid)/index.html")! ) self.webview.load(urlRequest) self.flow.publish(event: PreviewRendererAction.view(renderer: self, view: self.webview)) } + + fileprivate func htmlFileUrl() -> URL { + return self.tempDir.appendingPathComponent("\(MarkdownRenderer.identifier).\(self.uuid).html") + } } // MARK: - Actions diff --git a/VimR/PreviewComponent.swift b/VimR/PreviewComponent.swift index b9b1cca0..fa8833ad 100644 --- a/VimR/PreviewComponent.swift +++ b/VimR/PreviewComponent.swift @@ -7,6 +7,7 @@ import Cocoa import RxSwift import PureLayout import WebKit +import Swifter class PreviewComponent: NSView, ViewComponent, ToolDataHolder, WKNavigationDelegate { @@ -112,6 +113,8 @@ class PreviewComponent: NSView, ViewComponent, ToolDataHolder, WKNavigationDeleg } } + fileprivate let httpServer: HttpServer + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } @@ -137,14 +140,16 @@ class PreviewComponent: NSView, ViewComponent, ToolDataHolder, WKNavigationDeleg return self } - init(source: Observable, scrollSource: Observable, initialData: PrefData) { + init(source: Observable, scrollSource: Observable, httpServer: HttpServer, initialData: PrefData) { self.flow = EmbeddableComponent(source: source) + self.httpServer = httpServer self.baseUrl = self.previewService.baseUrl() let markdownData = initialData.rendererDatas[MarkdownRenderer.identifier] as? MarkdownRenderer.PrefData ?? MarkdownRenderer.PrefData.default self.markdownRenderer = MarkdownRenderer(source: self.flow.sink, scrollSource: scrollSource, + httpServer: self.httpServer, initialData: markdownData) self.renderers = [ @@ -231,7 +236,7 @@ class PreviewComponent: NSView, ViewComponent, ToolDataHolder, WKNavigationDeleg .throttle(1, latest: true, scheduler: self.scheduler) .filter { $0 is PreviewRendererAction } .map { $0 as! PreviewRendererAction } - .subscribe(onNext: { action in + .subscribe(onNext: { [unowned self] action in guard self.isOpen else { return }