Fixes #7: Rendering performance optimizations

- requestAnimationFrame batching: rerenderRpgState() now batches all
  render calls into a single animation frame, reducing reflow/repaint costs

- Lightweight change detection: Render functions use updateIfChanged() to
  skip DOM updates when content hasn't changed, and only re-bind event
  handlers when the DOM was actually updated

- CSS content-visibility: Added content-visibility: auto with
  contain-intrinsic-size to inventory and equipment containers, deferring
  rendering of off-screen content

New file: src/systems/rendering/renderUtils.js (rendering utilities module)
Updated: All render modules + sillytavern.js integration + style.css
This commit is contained in:
2026-07-12 13:10:17 +02:00
parent 1f8591d4ec
commit 24c964c38d
9 changed files with 239 additions and 40 deletions
+8 -4
View File
@@ -23,6 +23,7 @@ import {
import { isItemLocked, setItemLock } from '../generation/lockManager.js';
import { renderAlternatePresentCharacters } from '../ui/alternatePresentCharacters.js';
import { queueThoughtBasedExpressionsUpdate } from '../integration/thoughtBasedExpressions.js';
import { updateIfChanged } from './renderUtils.js';
/**
* Helper to generate lock icon HTML if setting is enabled
@@ -477,13 +478,15 @@ export function renderThoughts({ preserveScroll = false, useCommittedFallback =
html += '</div>';
}
$thoughtsContainer.html(html);
const domUpdated = updateIfChanged($thoughtsContainer, html, 'rpg-thoughts');
debugLog('[RPG Thoughts] ✓ HTML rendered to container');
debugLog('[RPG Thoughts] ✓ HTML rendered to container, updated:', domUpdated);
debugLog('[RPG Thoughts] =======================================================');
// Add event handlers for editable character fields
$thoughtsContainer.find('.rpg-editable').on('blur', function () {
// Only re-bind event handlers if DOM was actually updated
if (domUpdated) {
// Add event handlers for editable character fields
$thoughtsContainer.find('.rpg-editable').on('blur', function () {
const character = $(this).data('character');
const field = $(this).data('field');
const value = $(this).text().trim();
@@ -598,6 +601,7 @@ export function renderThoughts({ preserveScroll = false, useCommittedFallback =
}
}
});
} // end if (domUpdated)
// Remove updating class after animation
if (extensionSettings.enableAnimations) {