mirror of
https://github.com/qvacua/vimr.git
synced 2024-11-28 02:54:31 +03:00
GH-339 Make the preview component roughly work
- re-model the view component hierarchy
This commit is contained in:
parent
9b377c9d34
commit
738635ca51
@ -36,6 +36,7 @@
|
||||
4B183E101E06E29C0079E8A8 /* CocoaMarkdown.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 4B183E0D1E06E2940079E8A8 /* CocoaMarkdown.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
4B183E161E07C1420079E8A8 /* preview in Resources */ = {isa = PBXBuildFile; fileRef = 4B183E151E07C1420079E8A8 /* preview */; };
|
||||
4B183E1B1E08748B0079E8A8 /* NeoVimAutoCommandEvent.generated.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B183E1A1E08748B0079E8A8 /* NeoVimAutoCommandEvent.generated.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
4B183E1E1E09931E0079E8A8 /* MarkdownRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B183E1D1E09931E0079E8A8 /* MarkdownRenderer.swift */; };
|
||||
4B22F7F01D7C029400929B0E /* ScorerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B22F7EF1D7C029400929B0E /* ScorerTest.swift */; };
|
||||
4B22F7F21D7C6B9000929B0E /* ImageAndTextTableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B22F7F11D7C6B9000929B0E /* ImageAndTextTableCell.swift */; };
|
||||
4B238BE11D3BF24200CBDD98 /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B238BE01D3BF24200CBDD98 /* Application.swift */; };
|
||||
@ -303,6 +304,7 @@
|
||||
4B183E0D1E06E2940079E8A8 /* CocoaMarkdown.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CocoaMarkdown.framework; path = Carthage/Build/Mac/CocoaMarkdown.framework; sourceTree = SOURCE_ROOT; };
|
||||
4B183E151E07C1420079E8A8 /* preview */ = {isa = PBXFileReference; lastKnownFileType = folder; path = preview; sourceTree = "<group>"; };
|
||||
4B183E1A1E08748B0079E8A8 /* NeoVimAutoCommandEvent.generated.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NeoVimAutoCommandEvent.generated.h; sourceTree = "<group>"; };
|
||||
4B183E1D1E09931E0079E8A8 /* MarkdownRenderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarkdownRenderer.swift; sourceTree = "<group>"; };
|
||||
4B1BB3521D16C5E500CA4FEF /* InputTestView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InputTestView.swift; sourceTree = "<group>"; };
|
||||
4B22F7EF1D7C029400929B0E /* ScorerTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScorerTest.swift; sourceTree = "<group>"; };
|
||||
4B22F7F11D7C6B9000929B0E /* ImageAndTextTableCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageAndTextTableCell.swift; sourceTree = "<group>"; };
|
||||
@ -495,6 +497,7 @@
|
||||
1929BA610ADEA2BA4424FBE5 /* Preview */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4B183E1C1E0992FD0079E8A8 /* Preview Renderers */,
|
||||
1929B8DA5AA33536F0082200 /* PreviewComponent.swift */,
|
||||
1929BB8BCA48637156F92945 /* PreviewService.swift */,
|
||||
);
|
||||
@ -523,6 +526,14 @@
|
||||
name = "File Browser";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4B183E1C1E0992FD0079E8A8 /* Preview Renderers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4B183E1D1E09931E0079E8A8 /* MarkdownRenderer.swift */,
|
||||
);
|
||||
name = "Preview Renderers";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4B1AC1AF1D7F395300898F0B /* Open Quickly */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -1249,6 +1260,7 @@
|
||||
1929BD3F9E609BFADB27584B /* Scorer.swift in Sources */,
|
||||
4B6B0A781DA2A1A500212D6D /* FileOutlineView.swift in Sources */,
|
||||
4BB409EE1DDA77E9005F39A2 /* ProxyWorkspaceBar.swift in Sources */,
|
||||
4B183E1E1E09931E0079E8A8 /* MarkdownRenderer.swift in Sources */,
|
||||
4BAD84E81D7CA8FC00A79CC3 /* OpenQuicklyFilterOperation.swift in Sources */,
|
||||
1929B0E0C3BC59F52713D5A2 /* FoundationCommons.swift in Sources */,
|
||||
1929B3CEE0C1A1850E9CCE2F /* BasicTypes.swift in Sources */,
|
||||
|
@ -12,7 +12,7 @@ enum BufferListAction {
|
||||
case open(buffer: NeoVimBuffer)
|
||||
}
|
||||
|
||||
class BufferListComponent: ViewComponent, NSTableViewDataSource, NSTableViewDelegate {
|
||||
class BufferListComponent: StandardViewComponent, NSTableViewDataSource, NSTableViewDelegate {
|
||||
|
||||
fileprivate var buffers: [NeoVimBuffer] = []
|
||||
fileprivate let bufferList = NSTableView.standardTableView()
|
||||
|
@ -12,6 +12,11 @@ protocol Flow: class {
|
||||
var sink: Observable<Any> { get }
|
||||
}
|
||||
|
||||
protocol ViewComponent: Flow {
|
||||
|
||||
var view: NSView { get }
|
||||
}
|
||||
|
||||
class PublishingFlow: Flow {
|
||||
|
||||
var sink: Observable<Any> {
|
||||
@ -62,7 +67,7 @@ class EmbeddableComponent: Flow {
|
||||
|
||||
fileprivate let subject = PublishSubject<Any>()
|
||||
fileprivate let source: Observable<Any>
|
||||
fileprivate let disposeBag = DisposeBag()
|
||||
let disposeBag = DisposeBag()
|
||||
|
||||
init(source: Observable<Any>) {
|
||||
self.source = source
|
||||
@ -116,10 +121,11 @@ class StandardComponent: NSObject, Flow {
|
||||
}
|
||||
}
|
||||
|
||||
class ViewComponent: NSView, Flow {
|
||||
|
||||
class StandardViewComponent: NSView, ViewComponent {
|
||||
|
||||
var view: NSView {
|
||||
preconditionFailure("Please override")
|
||||
return self
|
||||
}
|
||||
|
||||
var sink: Observable<Any> {
|
||||
|
@ -46,7 +46,7 @@ struct FileBrowserData: StandardPrefData {
|
||||
}
|
||||
}
|
||||
|
||||
class FileBrowserComponent: ViewComponent, ToolDataHolder {
|
||||
class FileBrowserComponent: StandardViewComponent, ToolDataHolder {
|
||||
|
||||
fileprivate let fileView: FileOutlineView
|
||||
fileprivate let fileItemService: FileItemService
|
||||
|
@ -444,18 +444,18 @@ extension MainWindowComponent {
|
||||
let fileBrowserTool = self.tools[.fileBrowser]!
|
||||
|
||||
if fileBrowserTool.isSelected {
|
||||
if fileBrowserTool.viewComponent.isFirstResponder {
|
||||
if fileBrowserTool.viewComponent.view.isFirstResponder {
|
||||
fileBrowserTool.toggle()
|
||||
self.focusNeoVimView(self)
|
||||
} else {
|
||||
fileBrowserTool.viewComponent.beFirstResponder()
|
||||
fileBrowserTool.viewComponent.view.beFirstResponder()
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
fileBrowserTool.toggle()
|
||||
fileBrowserTool.viewComponent.beFirstResponder()
|
||||
fileBrowserTool.viewComponent.view.beFirstResponder()
|
||||
}
|
||||
|
||||
@IBAction func focusNeoVimView(_ sender: Any?) {
|
||||
|
43
VimR/MarkdownRenderer.swift
Normal file
43
VimR/MarkdownRenderer.swift
Normal file
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Tae Won Ha - http://taewon.de - @hataewon
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
import RxSwift
|
||||
import PureLayout
|
||||
import CocoaMarkdown
|
||||
|
||||
enum PreviewRendererAction {
|
||||
|
||||
case htmlString(html: String)
|
||||
case error
|
||||
}
|
||||
|
||||
class MarkdownRenderer: StandardFlow {
|
||||
|
||||
override func subscription(source: Observable<Any>) -> Disposable {
|
||||
return source
|
||||
.filter { $0 is PreviewAction }
|
||||
.map { $0 as! PreviewAction }
|
||||
.subscribe(onNext: { action in
|
||||
switch action {
|
||||
case let .refresh(url):
|
||||
self.render(from: url)
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fileprivate func render(from url: URL) {
|
||||
let doc = CMDocument(contentsOfFile: url.path)
|
||||
let renderer = CMHTMLRenderer(document: doc)
|
||||
|
||||
guard let html = renderer?.render() else {
|
||||
self.publish(event: PreviewRendererAction.error)
|
||||
return
|
||||
}
|
||||
|
||||
self.publish(event: PreviewRendererAction.htmlString(html: html))
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@
|
||||
import Cocoa
|
||||
import RxSwift
|
||||
|
||||
class PrefPane: ViewComponent {
|
||||
class PrefPane: StandardViewComponent {
|
||||
|
||||
// Return true to place this to the upper left corner when the scroll view is bigger than this view.
|
||||
override var isFlipped: Bool {
|
||||
|
@ -8,6 +8,11 @@ import RxSwift
|
||||
import PureLayout
|
||||
import WebKit
|
||||
|
||||
enum PreviewAction {
|
||||
|
||||
case refresh(url: URL)
|
||||
}
|
||||
|
||||
struct PreviewPrefData: StandardPrefData {
|
||||
|
||||
static let `default` = PreviewPrefData()
|
||||
@ -24,23 +29,44 @@ struct PreviewPrefData: StandardPrefData {
|
||||
}
|
||||
}
|
||||
|
||||
class PreviewComponent: ViewComponent {
|
||||
class PreviewComponent: NSView, ViewComponent {
|
||||
|
||||
fileprivate let flow: EmbeddableComponent
|
||||
|
||||
fileprivate let previewService = PreviewService()
|
||||
fileprivate let markdownRenderer: MarkdownRenderer
|
||||
|
||||
let webview = WKWebView(frame: .zero, configuration: WKWebViewConfiguration())
|
||||
fileprivate let webview = WKWebView(frame: .zero, configuration: WKWebViewConfiguration())
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override init(source: Observable<Any>) {
|
||||
super.init(source: source)
|
||||
|
||||
webview.loadHTMLString(self.previewService.emptyPreview(), baseURL: nil)
|
||||
var sink: Observable<Any> {
|
||||
return self.flow.sink
|
||||
}
|
||||
|
||||
override func addViews() {
|
||||
var view: NSView {
|
||||
return self
|
||||
}
|
||||
|
||||
init(source: Observable<Any>) {
|
||||
self.flow = EmbeddableComponent(source: source)
|
||||
self.markdownRenderer = MarkdownRenderer(source: self.flow.sink)
|
||||
|
||||
super.init(frame: .zero)
|
||||
self.configureForAutoLayout()
|
||||
|
||||
self.flow.set(subscription: self.subscription)
|
||||
|
||||
|
||||
self.webview.loadHTMLString(self.previewService.emptyPreview(), baseURL: nil)
|
||||
|
||||
self.addViews()
|
||||
self.addReactions()
|
||||
}
|
||||
|
||||
fileprivate func addViews() {
|
||||
let webview = self.webview
|
||||
webview.configureForAutoLayout()
|
||||
|
||||
@ -49,7 +75,7 @@ class PreviewComponent: ViewComponent {
|
||||
webview.autoPinEdgesToSuperviewEdges()
|
||||
}
|
||||
|
||||
override func subscription(source: Observable<Any>) -> Disposable {
|
||||
fileprivate func subscription(source: Observable<Any>) -> Disposable {
|
||||
return source
|
||||
.filter { $0 is MainWindowAction }
|
||||
.map { $0 as! MainWindowAction }
|
||||
@ -57,7 +83,11 @@ class PreviewComponent: ViewComponent {
|
||||
switch action {
|
||||
|
||||
case let .currentBufferChanged(mainWindow, currentBuffer):
|
||||
NSLog("\(currentBuffer)")
|
||||
guard let url = currentBuffer.url else {
|
||||
return
|
||||
}
|
||||
|
||||
self.flow.publish(event: PreviewAction.refresh(url: url))
|
||||
|
||||
default:
|
||||
return
|
||||
@ -65,4 +95,22 @@ class PreviewComponent: ViewComponent {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fileprivate func addReactions() {
|
||||
self.markdownRenderer.sink
|
||||
.filter { $0 is PreviewRendererAction }
|
||||
.map { $0 as! PreviewRendererAction }
|
||||
.subscribe(onNext: { action in
|
||||
switch action {
|
||||
|
||||
case let .htmlString(html):
|
||||
self.webview.loadHTMLString(html, baseURL: nil)
|
||||
|
||||
case .error:
|
||||
self.webview.loadHTMLString(self.previewService.emptyPreview(), baseURL: nil)
|
||||
|
||||
}
|
||||
})
|
||||
.addDisposableTo(self.flow.disposeBag)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user