mirror of
https://github.com/qvacua/vimr.git
synced 2024-10-27 10:23:12 +03:00
GH-405 Retain scroll position after reloading markdown
This commit is contained in:
parent
f5fbc6def3
commit
c22acf29d5
@ -75,6 +75,7 @@ class PreviewTool: NSView, UiComponent, WKNavigationDelegate {
|
|||||||
refreshOnWrite.action = #selector(PreviewTool.refreshOnWriteAction)
|
refreshOnWrite.action = #selector(PreviewTool.refreshOnWriteAction)
|
||||||
|
|
||||||
self.addViews()
|
self.addViews()
|
||||||
|
self.webview.navigationDelegate = self
|
||||||
self.webview.load(URLRequest(url: state.preview.server!))
|
self.webview.load(URLRequest(url: state.preview.server!))
|
||||||
|
|
||||||
source
|
source
|
||||||
@ -98,6 +99,11 @@ class PreviewTool: NSView, UiComponent, WKNavigationDelegate {
|
|||||||
|
|
||||||
guard state.preview.updateDate > self.lastUpdateDate else { return }
|
guard state.preview.updateDate > self.lastUpdateDate else { return }
|
||||||
guard let serverUrl = state.preview.server else { return }
|
guard let serverUrl = state.preview.server else { return }
|
||||||
|
if serverUrl != self.url {
|
||||||
|
self.url = serverUrl
|
||||||
|
self.scrollTop = 0
|
||||||
|
self.previewPosition = Marked(Position.beginning)
|
||||||
|
}
|
||||||
|
|
||||||
self.lastUpdateDate = state.preview.updateDate
|
self.lastUpdateDate = state.preview.updateDate
|
||||||
self.webview.load(URLRequest(url: serverUrl))
|
self.webview.load(URLRequest(url: serverUrl))
|
||||||
@ -111,8 +117,9 @@ class PreviewTool: NSView, UiComponent, WKNavigationDelegate {
|
|||||||
|
|
||||||
self.webviewMessageHandler.source
|
self.webviewMessageHandler.source
|
||||||
.throttle(0.75, latest: true, scheduler: self.scheduler)
|
.throttle(0.75, latest: true, scheduler: self.scheduler)
|
||||||
.subscribe(onNext: { [unowned self] position in
|
.subscribe(onNext: { [unowned self] (position, scrollTop) in
|
||||||
self.previewPosition = Marked(position)
|
self.previewPosition = Marked(position)
|
||||||
|
self.scrollTop = scrollTop
|
||||||
self.emitter.emit(UuidAction(uuid: self.uuid, action: Action.scroll(to: self.previewPosition)))
|
self.emitter.emit(UuidAction(uuid: self.uuid, action: Action.scroll(to: self.previewPosition)))
|
||||||
})
|
})
|
||||||
.addDisposableTo(self.disposeBag)
|
.addDisposableTo(self.disposeBag)
|
||||||
@ -131,6 +138,10 @@ class PreviewTool: NSView, UiComponent, WKNavigationDelegate {
|
|||||||
NSLog("ERROR preview component's webview: \(error)")
|
NSLog("ERROR preview component's webview: \(error)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
|
||||||
|
self.webview.evaluateJavaScript("document.body.scrollTop = \(self.scrollTop)")
|
||||||
|
}
|
||||||
|
|
||||||
fileprivate let emitter: ActionEmitter
|
fileprivate let emitter: ActionEmitter
|
||||||
fileprivate let uuid: String
|
fileprivate let uuid: String
|
||||||
|
|
||||||
@ -139,9 +150,11 @@ class PreviewTool: NSView, UiComponent, WKNavigationDelegate {
|
|||||||
fileprivate let scheduler = ConcurrentDispatchQueueScheduler(qos: .userInitiated)
|
fileprivate let scheduler = ConcurrentDispatchQueueScheduler(qos: .userInitiated)
|
||||||
fileprivate var isOpen = false
|
fileprivate var isOpen = false
|
||||||
|
|
||||||
|
fileprivate var url: URL?
|
||||||
fileprivate var lastUpdateDate = Date.distantPast
|
fileprivate var lastUpdateDate = Date.distantPast
|
||||||
fileprivate var editorPosition = Marked(Position.beginning)
|
fileprivate var editorPosition = Marked(Position.beginning)
|
||||||
fileprivate var previewPosition = Marked(Position.beginning)
|
fileprivate var previewPosition = Marked(Position.beginning)
|
||||||
|
fileprivate var scrollTop = 0
|
||||||
|
|
||||||
fileprivate let userContentController = WKUserContentController()
|
fileprivate let userContentController = WKUserContentController()
|
||||||
fileprivate let webviewMessageHandler = WebviewMessageHandler()
|
fileprivate let webviewMessageHandler = WebviewMessageHandler()
|
||||||
@ -194,7 +207,7 @@ extension PreviewTool {
|
|||||||
|
|
||||||
fileprivate class WebviewMessageHandler: NSObject, WKScriptMessageHandler {
|
fileprivate class WebviewMessageHandler: NSObject, WKScriptMessageHandler {
|
||||||
|
|
||||||
var source: Observable<Position> {
|
var source: Observable<(Position, Int)> {
|
||||||
return self.subject.asObservable()
|
return self.subject.asObservable()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,12 +220,15 @@ fileprivate class WebviewMessageHandler: NSObject, WKScriptMessageHandler {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let lineBegin = msgBody["lineBegin"], let columnBegin = msgBody["columnBegin"] else {
|
guard let lineBegin = msgBody["lineBegin"],
|
||||||
|
let columnBegin = msgBody["columnBegin"],
|
||||||
|
let scrollTop = msgBody["scrollTop"]
|
||||||
|
else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
self.subject.onNext(Position(row: lineBegin, column: columnBegin))
|
self.subject.onNext((Position(row: lineBegin, column: columnBegin), scrollTop))
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate let subject = PublishSubject<Position>()
|
fileprivate let subject = PublishSubject<(Position, Int)>()
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
function positionOfMarkdownElement(element) {
|
function positionOfMarkdownElement(element) {
|
||||||
const regexResult = element.dataset.sourcepos.match(sourceposRegex);
|
const regexResult = element.dataset.sourcepos.match(sourceposRegex);
|
||||||
|
|
||||||
if (regexResult.length != 5) {
|
if (regexResult.length !== 5) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,13 +62,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const result = positionOfMarkdownElement(candidate);
|
const result = positionOfMarkdownElement(candidate);
|
||||||
if (result.lineBegin == lastMarkdownPosition.lineBegin
|
if (result.lineBegin === lastMarkdownPosition.lineBegin
|
||||||
&& result.columnBegin == lastMarkdownPosition.columnBegin
|
&& result.columnBegin === lastMarkdownPosition.columnBegin
|
||||||
&& result.lineEnd == lastMarkdownPosition.lineEnd
|
&& result.lineEnd === lastMarkdownPosition.lineEnd
|
||||||
&& result.columnEnd == lastMarkdownPosition.columnEnd)
|
&& result.columnEnd === lastMarkdownPosition.columnEnd)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
result.scrollTop = document.body.scrollTop;
|
||||||
|
|
||||||
lastMarkdownPosition = result;
|
lastMarkdownPosition = result;
|
||||||
// console.log(`webview scrolled to ${result.lineBegin}:${result.columnBegin}`);
|
// console.log(`webview scrolled to ${result.lineBegin}:${result.columnBegin}`);
|
||||||
@ -110,13 +111,13 @@
|
|||||||
return Math.min(result, entry.rowDistance)
|
return Math.min(result, entry.rowDistance)
|
||||||
}, Number.MAX_SAFE_INTEGER);
|
}, Number.MAX_SAFE_INTEGER);
|
||||||
|
|
||||||
const entriesWithMinRowDistance = entries.filter(entry => entry.rowDistance == minRowDistance);
|
const entriesWithMinRowDistance = entries.filter(entry => entry.rowDistance === minRowDistance);
|
||||||
|
|
||||||
const minColumnDistance = entriesWithMinRowDistance.reduce((result, entry) => {
|
const minColumnDistance = entriesWithMinRowDistance.reduce((result, entry) => {
|
||||||
return Math.min(result, entry.columnDistance)
|
return Math.min(result, entry.columnDistance)
|
||||||
}, Number.MAX_SAFE_INTEGER);
|
}, Number.MAX_SAFE_INTEGER);
|
||||||
|
|
||||||
const candidateEntry = entriesWithMinRowDistance.find(entry => entry.columnDistance == minColumnDistance);
|
const candidateEntry = entriesWithMinRowDistance.find(entry => entry.columnDistance === minColumnDistance);
|
||||||
if (!candidateEntry) {
|
if (!candidateEntry) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user