From 63362ae88f7e9ea0cc60c2d238d8393d737f1c19 Mon Sep 17 00:00:00 2001 From: Ryan Magilton <69179298+RyfiGames@users.noreply.github.com> Date: Sat, 7 Oct 2023 00:39:23 -0400 Subject: [PATCH] fix(ui): Check for changes before re-rendering JS blocks (#2018) * Check for changes before re-rendering * Add settings toggle for this feature --- src/main.ts | 13 +++++++++++++ src/settings.ts | 3 +++ src/ui/views/js-view.ts | 12 ++++++++++-- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/main.ts b/src/main.ts index 76fef2d1..932825b8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -447,6 +447,19 @@ class GeneralSettingsTab extends PluginSettingTab { }) ); + new Setting(this.containerEl) + .setName("Check Changes Before Re-Rendering") + .setDesc( + "If enabled, JS views will only re-render when the generated HTML is changed. This may fix flickering" + + " issues, but also break complicated views with interactive elements." + ) + .addToggle(toggle => + toggle.setValue(this.plugin.settings.checkHTMLBeforeRerender).onChange(async value => { + await this.plugin.updateSettings({ checkHTMLBeforeRerender: value }); + this.plugin.index.touch(); + }) + ); + let dformat = new Setting(this.containerEl) .setName("Date Format") .setDesc( diff --git a/src/settings.ts b/src/settings.ts index 5199765a..732ce239 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -21,6 +21,8 @@ export interface QuerySettings { refreshEnabled: boolean; /** The interval that views are refreshed, by default. */ refreshInterval: number; + /** Whether or not views should only re-render when underlying HTML is changed */ + checkHTMLBeforeRerender: boolean; /** The default format that dates are rendered in (using luxon's moment-like formatting). */ defaultDateFormat: string; /** The default format that date-times are rendered in (using luxons moment-like formatting). */ @@ -45,6 +47,7 @@ export const DEFAULT_QUERY_SETTINGS: QuerySettings = { warnOnEmptyResult: true, refreshEnabled: true, refreshInterval: 2500, + checkHTMLBeforeRerender: false, defaultDateFormat: "MMMM dd, yyyy", defaultDateTimeFormat: "h:mm a - MMMM dd, yyyy", maxRecursiveRenderDepth: 4, diff --git a/src/ui/views/js-view.ts b/src/ui/views/js-view.ts index 1eef95de..f44282e1 100644 --- a/src/ui/views/js-view.ts +++ b/src/ui/views/js-view.ts @@ -11,8 +11,8 @@ export class DataviewJSRenderer extends DataviewRefreshableRenderer { } async render() { - this.container.innerHTML = ""; if (!this.settings.enableDataviewJs) { + this.container.innerHTML = ""; this.containerEl.innerHTML = ""; renderErrorPre( this.container, @@ -23,11 +23,19 @@ export class DataviewJSRenderer extends DataviewRefreshableRenderer { // Assume that the code is javascript, and try to eval it. try { + const dummyHTML = this.container.cloneNode() as HTMLElement; await asyncEvalInContext( DataviewJSRenderer.PREAMBLE + this.script, - new DataviewInlineApi(this.api, this, this.container, this.origin) + new DataviewInlineApi(this.api, this, dummyHTML, this.origin) ); + if (!this.settings.checkHTMLBeforeRerender || dummyHTML.innerHTML != this.container.innerHTML) { + this.container.innerHTML = ""; + while (dummyHTML.firstChild) { + this.container.appendChild(dummyHTML.firstChild); + } + } } catch (e) { + this.container.innerHTML = ""; this.containerEl.innerHTML = ""; renderErrorPre(this.container, "Evaluation Error: " + e.stack); }