1
1
mirror of https://github.com/qvacua/vimr.git synced 2024-11-24 11:37:32 +03:00

GH-339 React to opening

This commit is contained in:
Tae Won Ha 2016-12-23 12:15:26 +01:00
parent 738635ca51
commit 1ce679da9d
No known key found for this signature in database
GPG Key ID: E40743465B5B8B44
17 changed files with 210 additions and 55 deletions

View File

@ -4,3 +4,4 @@ github "eonil/FileSystemEvents" "master"
github "sparkle-project/Sparkle" == 1.14.0
github "qvacua/CocoaFontAwesome" "master"
github "qvacua/CocoaMarkdown" "master"
github "sindresorhus/github-markdown-css" == 2.4.1

View File

@ -5,3 +5,4 @@ github "Quick/Nimble" "v5.1.0"
github "PureLayout/PureLayout" "v3.0.2"
github "ReactiveX/RxSwift" "3.0.1"
github "sparkle-project/Sparkle" "1.14.0"
github "sindresorhus/github-markdown-css" "v2.4.1"

View File

@ -37,6 +37,7 @@
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 */; };
4B19164C1E0B1D53007EA025 /* github-markdown.css in Resources */ = {isa = PBXBuildFile; fileRef = 4B19164B1E0B1D53007EA025 /* github-markdown.css */; };
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 */; };
@ -305,6 +306,7 @@
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>"; };
4B19164B1E0B1D53007EA025 /* github-markdown.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; name = "github-markdown.css"; path = "Carthage/Checkouts/github-markdown-css/github-markdown.css"; sourceTree = SOURCE_ROOT; };
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>"; };
@ -685,6 +687,7 @@
4B97E2CF1D33F92200FC0660 /* resources */ = {
isa = PBXGroup;
children = (
4B19164B1E0B1D53007EA025 /* github-markdown.css */,
4B183E151E07C1420079E8A8 /* preview */,
4BEBA50C1CFF374B00673FDF /* MainMenu.xib */,
4B97E2CE1D33F53D00FC0660 /* MainWindow.xib */,
@ -1102,6 +1105,7 @@
4BDF50171D77540900D8FBC3 /* OpenQuicklyWindow.xib in Resources */,
4B37ADB91D6E471B00970D55 /* vimr in Resources */,
4BB409E51DD68CCC005F39A2 /* FileBrowserMenu.xib in Resources */,
4B19164C1E0B1D53007EA025 /* github-markdown.css in Resources */,
4BEBA50E1CFF374B00673FDF /* MainMenu.xib in Resources */,
4B97E2CC1D33F53D00FC0660 /* MainWindow.xib in Resources */,
4B029F1A1D45E349004EE0D3 /* PrefWindow.xib in Resources */,

View File

@ -16,6 +16,7 @@ enum MainWindowAction {
case changeFileBrowserSelection(mainWindow: MainWindowComponent, url: URL)
case close(mainWindow: MainWindowComponent, mainWindowPrefData: MainWindowPrefData)
case toggleTool(tool: WorkspaceTool)
case currentBufferChanged(mainWindow: MainWindowComponent, buffer: NeoVimBuffer)
}
@ -339,6 +340,10 @@ extension MainWindowComponent {
func resizeDidEnd(workspace: Workspace) {
self.neoVimView.exitResizeMode()
}
func toggled(tool: WorkspaceTool) {
self.publish(event: MainWindowAction.toggleTool(tool: tool))
}
}
// MARK: - File Menu Item Actions

View File

@ -8,25 +8,36 @@ import RxSwift
import PureLayout
import CocoaMarkdown
enum PreviewRendererAction {
protocol PreviewRenderer: class {
case htmlString(html: String)
case error
}
class MarkdownRenderer: StandardFlow {
enum PreviewRendererAction {
case htmlString(renderer: PreviewRenderer, html: String)
case error(renderer: PreviewRenderer)
}
class MarkdownRenderer: StandardFlow, PreviewRenderer {
fileprivate let extensions = Set([ "md", "markdown", ])
fileprivate func canRender(fileExtension: String) -> Bool {
return extensions.contains(fileExtension)
}
override func subscription(source: Observable<Any>) -> Disposable {
return source
.filter { $0 is PreviewAction }
.map { $0 as! PreviewAction }
.subscribe(onNext: { action in
.map { action in
switch action {
case let .refresh(url):
self.render(from: url)
case let .automaticRefresh(url):
return url
}
})
}
.filter { self.canRender(fileExtension: $0.pathExtension) }
.subscribe(onNext: { [unowned self] url in self.render(from: url) })
}
fileprivate func render(from url: URL) {
@ -38,6 +49,6 @@ class MarkdownRenderer: StandardFlow {
return
}
self.publish(event: PreviewRendererAction.htmlString(html: html))
self.publish(event: PreviewRendererAction.htmlString(renderer: self, html: html))
}
}

View File

@ -10,7 +10,7 @@ import WebKit
enum PreviewAction {
case refresh(url: URL)
case automaticRefresh(url: URL)
}
struct PreviewPrefData: StandardPrefData {
@ -38,6 +38,12 @@ class PreviewComponent: NSView, ViewComponent {
fileprivate let webview = WKWebView(frame: .zero, configuration: WKWebViewConfiguration())
fileprivate var currentRenderer: PreviewRenderer?
fileprivate let renderers: [PreviewRenderer]
fileprivate var isOpen = false
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@ -54,13 +60,16 @@ class PreviewComponent: NSView, ViewComponent {
self.flow = EmbeddableComponent(source: source)
self.markdownRenderer = MarkdownRenderer(source: self.flow.sink)
self.renderers = [
self.markdownRenderer,
]
super.init(frame: .zero)
self.configureForAutoLayout()
self.flow.set(subscription: self.subscription)
self.webview.loadHTMLString(self.previewService.emptyPreview(), baseURL: nil)
self.webview.loadHTMLString(self.previewService.emptyHtml(), baseURL: nil)
self.addViews()
self.addReactions()
@ -82,12 +91,18 @@ class PreviewComponent: NSView, ViewComponent {
.subscribe(onNext: { action in
switch action {
case let .currentBufferChanged(mainWindow, currentBuffer):
case let .currentBufferChanged(_, currentBuffer):
guard let url = currentBuffer.url else {
return
}
self.flow.publish(event: PreviewAction.refresh(url: url))
self.flow.publish(event: PreviewAction.automaticRefresh(url: url))
case let .toggleTool(tool):
guard tool.view == self else {
return
}
self.isOpen = tool.isSelected
default:
return
@ -100,14 +115,18 @@ class PreviewComponent: NSView, ViewComponent {
self.markdownRenderer.sink
.filter { $0 is PreviewRendererAction }
.map { $0 as! PreviewRendererAction }
.subscribe(onNext: { action in
.subscribe(onNext: { [unowned self] action in
guard self.isOpen else {
return
}
switch action {
case let .htmlString(html):
case let .htmlString(_, html):
self.webview.loadHTMLString(html, baseURL: nil)
case .error:
self.webview.loadHTMLString(self.previewService.emptyPreview(), baseURL: nil)
self.webview.loadHTMLString(self.previewService.errorHtml(), baseURL: nil)
}
})

View File

@ -7,25 +7,52 @@ import Foundation
class PreviewService {
fileprivate let emptyPreviewHtml: String
fileprivate let empty: String
fileprivate let error: String
fileprivate let saveFirst: String
init() {
guard let emptyUrl = Bundle.main.url(forResource: "empty", withExtension: "html", subdirectory: "preview") else {
preconditionFailure("No empty.html!")
}
guard let emptyUrl = Bundle.main.url(forResource: "empty-preview",
withExtension: "html",
subdirectory: "preview")
guard let errorUrl = Bundle.main.url(forResource: "error", withExtension: "html", subdirectory: "preview") else {
preconditionFailure("No error.html!")
}
guard let saveFirstUrl = Bundle.main.url(forResource: "error",
withExtension: "html",
subdirectory: "preview")
else {
preconditionFailure("No empty-preview.html!")
preconditionFailure("No save-first.html!")
}
guard let emptyHtml = try? String(contentsOf: emptyUrl) else {
preconditionFailure("Error getting empty-preview.html!")
preconditionFailure("Error getting empty.html!")
}
self.emptyPreviewHtml = emptyHtml
guard let errorHtml = try? String(contentsOf: errorUrl) else {
preconditionFailure("Error getting error.html!")
}
guard let saveFirstHtml = try? String(contentsOf: saveFirstUrl) else {
preconditionFailure("Error getting save-first.html!")
}
self.empty = emptyHtml
self.error = errorHtml
self.saveFirst = saveFirstHtml
}
func emptyPreview() -> String {
return self.emptyPreviewHtml
func emptyHtml() -> String {
return self.empty
}
func errorHtml() -> String {
return self.error
}
func saveFirstHtml() -> String {
return self.saveFirst
}
}

View File

@ -20,6 +20,8 @@ protocol WorkspaceDelegate: class {
func resizeWillStart(workspace: Workspace)
func resizeDidEnd(workspace: Workspace)
func toggled(tool: WorkspaceTool)
}
class Workspace: NSView, WorkspaceBarDelegate {
@ -196,6 +198,10 @@ extension Workspace {
func resizeDidEnd(workspaceBar: WorkspaceBar) {
self.delegate?.resizeDidEnd(workspace: self)
}
func toggle(tool: WorkspaceTool) {
self.delegate?.toggled(tool: tool)
}
}
// MARK: - Layout

View File

@ -10,6 +10,8 @@ protocol WorkspaceBarDelegate: class {
func resizeWillStart(workspaceBar: WorkspaceBar)
func resizeDidEnd(workspaceBar: WorkspaceBar)
func toggle(tool: WorkspaceTool)
}
/**
@ -835,5 +837,6 @@ extension WorkspaceBar {
self.relayout()
self.delegate?.resizeDidEnd(workspaceBar: self)
self.delegate?.toggle(tool: tool)
}
}

View File

@ -110,8 +110,8 @@ class WorkspaceTool: NSView {
}
func toggle() {
self.delegate?.toggle(self)
self.isSelected = !self.isSelected
self.delegate?.toggle(self)
}
fileprivate func addViews() {

62
VimR/preview/base.css Normal file
View File

@ -0,0 +1,62 @@
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
body {
font-family: -apple-system, sans-serif;
}
#message {
text-align: center;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.info-text {
font-size: small;
color: gray;
}

View File

@ -1,13 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Empty</title>
</head>
<body style="font-family: -apple-system; background-color: white;">
<div style="text-align: center; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);">
<span style="font-size: x-large;">😶</span><br>
<span style="font-size: small; color: gray;">no preview...</span>
</div>
</body>
</html>

14
VimR/preview/empty.html Normal file
View File

@ -0,0 +1,14 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="base.css">
<title>Empty</title>
</head>
<body>
<div id="message">
<h1>😶</h1>
<span class="info-text">no preview...</span>
</div>
</body>
</html>

14
VimR/preview/error.html Normal file
View File

@ -0,0 +1,14 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="base.css">
<title>Error</title>
</head>
<body>
<div id="message">
<h1>😱</h1>
<span class="info-text">There was an error...</span>
</div>
</body>
</html>

View File

@ -1,13 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Empty</title>
</head>
<body style="font-family: -apple-system; background-color: white;">
<div style="text-align: center; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);">
<span style="font-size: x-large;">😌</span><br>
<span style="font-size: small; color: gray;">save the file first for preview...</span>
</div>
</body>
</html>

View File

@ -0,0 +1,14 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="base.css">
<title>Error</title>
</head>
<body>
<div id="message">
<h1>😶</h1>
<span class="info-text">Save first for preview</span>
</div>
</body>
</html>

2
neovim

@ -1 +1 @@
Subproject commit 3fa28dc5807196447f1da8ca793fd0b048fedea1
Subproject commit 157d037a7c1f28c3e6a518f34608f68682535ed3