diff --git a/plugins/RenameFile/renamefile.css b/plugins/RenameFile/renamefile.css index e50d7828..b1289d2a 100644 --- a/plugins/RenameFile/renamefile.css +++ b/plugins/RenameFile/renamefile.css @@ -1,7 +1,7 @@ .renamefile { - color: unset; + cursor: pointer; &:hover { - text-decoration: unset; + text-decoration: underline; } &:active { color: white; diff --git a/plugins/RenameFile/renamefile.js b/plugins/RenameFile/renamefile.js index cc485b2f..2a438ac8 100644 --- a/plugins/RenameFile/renamefile.js +++ b/plugins/RenameFile/renamefile.js @@ -72,30 +72,46 @@ } } - function wrapElement(element) { - var text = element.textContent.trim(); - var anchor = document.createElement('a'); - anchor.href = '#'; - anchor.textContent = text; - anchor.classList.add('renamefile'); - anchor.title = 'Click to append title to [Title] input field; OR ctrl-key & mouse click to copy title to clipboard; OR shift-key click to copy to [Title] input field; OR alt-key click to copy file URI to clipboard.'; - anchor.addEventListener('click', function(event) { - event.preventDefault(); - AppendTitleField(text, event); - }); - element.innerHTML = ''; - element.appendChild(anchor); + var TITLE_SELECTOR = '.scene-header div.TruncatedText'; + var TOOLTIP = 'Click to append title to [Title] input field; OR ctrl-key & mouse click to copy title to clipboard; OR shift-key click to copy to [Title] input field; OR alt-key click to copy file URI to clipboard.'; + + // Use event delegation instead of replacing the title element. The scene + // title is a React-controlled component; restructuring its DOM (e.g. + // wrapping it in an ) detaches the text node React updates, so the title + // freezes on the previous scene when navigating with Next. By listening on + // document and reading the title at click time, we never touch React's DOM. + document.addEventListener('click', function(event) { + var title = event.target.closest(TITLE_SELECTOR); + if (!title) return; + event.preventDefault(); + AppendTitleField(title.textContent.trim(), event); + }); + + // Non-destructive affordance: add the styling class and tooltip without + // touching the element's children, so React's text node stays intact. + function decorate(element) { + if (!element.classList.contains('renamefile')) { + element.classList.add('renamefile'); + } + if (element.getAttribute('title') !== TOOLTIP) { + element.setAttribute('title', TOOLTIP); + } } - function handleMutations(mutationsList, observer) { - for(const mutation of mutationsList) { - for(const addedNode of mutation.addedNodes) { - if (addedNode.nodeType === Node.ELEMENT_NODE && addedNode.querySelector('.scene-header div.TruncatedText')) { - wrapElement(addedNode.querySelector('.scene-header div.TruncatedText')); - } + function handleMutations(mutationsList) { + for (const mutation of mutationsList) { + for (const addedNode of mutation.addedNodes) { + if (addedNode.nodeType !== Node.ELEMENT_NODE) continue; + var title = addedNode.matches && addedNode.matches(TITLE_SELECTOR) + ? addedNode + : addedNode.querySelector && addedNode.querySelector(TITLE_SELECTOR); + if (title) decorate(title); } } } const observer = new MutationObserver(handleMutations); observer.observe(document.body, { childList: true, subtree: true }); + + var existing = document.querySelector(TITLE_SELECTOR); + if (existing) decorate(existing); })(); diff --git a/plugins/RenameFile/renamefile.yml b/plugins/RenameFile/renamefile.yml index 70ec5e24..15ab39b4 100644 --- a/plugins/RenameFile/renamefile.yml +++ b/plugins/RenameFile/renamefile.yml @@ -1,6 +1,6 @@ name: RenameFile description: Renames video (scene) file names when the user edits the [Title] field located in the scene [Edit] tab. -version: 1.0.0 +version: 1.0.1 url: https://discourse.stashapp.cc/t/renamefile/1334 ui: css: