diff --git a/public/script.js b/public/script.js index 04eb8bc09..0d7d47e24 100644 --- a/public/script.js +++ b/public/script.js @@ -849,11 +849,9 @@ export let is_send_press = false; //Send generation let this_del_mes = -1; -//message editing and chat scroll position persistence +//message editing var this_edit_mes_chname = ''; var this_edit_mes_id; -var scroll_holder = 0; -var is_use_scroll_holder = false; //settings export let settings; @@ -9727,25 +9725,27 @@ jQuery(async function () { chooseBogusFolder($(this), tagId); }); - /** - * Sets the scroll height of the edit textarea to fit the content. - * @param {HTMLTextAreaElement} e Textarea element to auto-fit - */ - function autoFitEditTextArea(e) { - scroll_holder = chatElement[0].scrollTop; - e.style.height = '0px'; - const newHeight = e.scrollHeight + 4; - e.style.height = `${newHeight}px`; - is_use_scroll_holder = true; - } - const autoFitEditTextAreaDebounced = debounce(autoFitEditTextArea, debounce_timeout.short); - document.addEventListener('input', e => { - if (e.target instanceof HTMLTextAreaElement && e.target.classList.contains('edit_textarea')) { - const scrollbarShown = e.target.clientWidth < e.target.offsetWidth && e.target.offsetHeight >= window.innerHeight * 0.75; - const immediately = (e.target.scrollHeight > e.target.offsetHeight && !scrollbarShown) || e.target.value === ''; - immediately ? autoFitEditTextArea(e.target) : autoFitEditTextAreaDebounced(e.target); + const cssAutofit = CSS.supports('field-sizing', 'content'); + if (!cssAutofit) { + /** + * Sets the scroll height of the edit textarea to fit the content. + * @param {HTMLTextAreaElement} e Textarea element to auto-fit + */ + function autoFitEditTextArea(e) { + e.style.height = '0px'; + const newHeight = e.scrollHeight + 4; + e.style.height = `${newHeight}px`; } - }); + const autoFitEditTextAreaDebounced = debounce(autoFitEditTextArea, debounce_timeout.short); + document.addEventListener('input', e => { + if (e.target instanceof HTMLTextAreaElement && e.target.classList.contains('edit_textarea')) { + const scrollbarShown = e.target.clientWidth < e.target.offsetWidth && e.target.offsetHeight >= window.innerHeight * 0.75; + const immediately = (e.target.scrollHeight > e.target.offsetHeight && !scrollbarShown) || e.target.value === ''; + immediately ? autoFitEditTextArea(e.target) : autoFitEditTextAreaDebounced(e.target); + } + }); + } + const chatElementScroll = document.getElementById('chat'); const chatScrollHandler = function () { if (power_user.waifuMode) { @@ -9767,12 +9767,6 @@ jQuery(async function () { }; chatElementScroll.addEventListener('wheel', chatScrollHandler, { passive: true }); chatElementScroll.addEventListener('touchmove', chatScrollHandler, { passive: true }); - chatElementScroll.addEventListener('scroll', function () { - if (is_use_scroll_holder) { - this.scrollTop = scroll_holder; - is_use_scroll_holder = false; - } - }, { passive: true }); $(document).on('click', '.mes', function () { //when a 'delete message' parent div is clicked @@ -10511,14 +10505,16 @@ jQuery(async function () { .closest('.mes_block') .find('.mes_text') .append( - '', + '', ); $('#curEditTextarea').val(text); let edit_textarea = $(this) .closest('.mes_block') .find('.edit_textarea'); - edit_textarea.height(0); - edit_textarea.height(edit_textarea[0].scrollHeight); + if (!cssAutofit) { + edit_textarea.height(0); + edit_textarea.height(edit_textarea[0].scrollHeight); + } edit_textarea.focus(); edit_textarea[0].setSelectionRange( //this sets the cursor at the end of the text String(edit_textarea.val()).length, diff --git a/public/scripts/RossAscends-mods.js b/public/scripts/RossAscends-mods.js index 750e9cdd2..acef7b5f6 100644 --- a/public/scripts/RossAscends-mods.js +++ b/public/scripts/RossAscends-mods.js @@ -887,7 +887,40 @@ export function initRossMods() { saveSettingsDebounced(); }); + const cssAutofit = CSS.supports('field-sizing', 'content'); + + if (cssAutofit) { + let lastHeight = chatBlock.offsetHeight; + const chatBlockResizeObserver = new ResizeObserver((entries) => { + for (const entry of entries) { + if (entry.target !== chatBlock) { + continue; + } + + const threshold = 1; + const newHeight = chatBlock.offsetHeight; + const deltaHeight = newHeight - lastHeight; + const isScrollAtBottom = Math.abs(chatBlock.scrollHeight - chatBlock.scrollTop - newHeight) <= threshold; + + if (!isScrollAtBottom && Math.abs(deltaHeight) > threshold) { + chatBlock.scrollTop -= deltaHeight; + } + lastHeight = newHeight; + } + }); + + chatBlockResizeObserver.observe(chatBlock); + } + sendTextArea.addEventListener('input', () => { + saveUserInputDebounced(); + + if (cssAutofit) { + // Unset modifications made with a manual resize + sendTextArea.style.height = 'auto'; + return; + } + const hasContent = sendTextArea.value !== ''; const fitsCurrentSize = sendTextArea.scrollHeight <= sendTextArea.offsetHeight; const isScrollbarShown = sendTextArea.clientWidth < sendTextArea.offsetWidth; @@ -895,7 +928,6 @@ export function initRossMods() { const needsDebounce = hasContent && (fitsCurrentSize || (isScrollbarShown && isHalfScreenHeight)); if (needsDebounce) autoFitSendTextAreaDebounced(); else autoFitSendTextArea(); - saveUserInputDebounced(); }); restoreUserInput(); diff --git a/public/style.css b/public/style.css index c9033bcad..d47c8aaf6 100644 --- a/public/style.css +++ b/public/style.css @@ -1264,6 +1264,7 @@ button { text-shadow: 0px 0px calc(var(--shadowWidth) * 1px) var(--SmartThemeShadowColor); flex: 1; order: 3; + field-sizing: content; --progColor: rgb(146, 190, 252); --progFlashColor: rgb(215, 136, 114); @@ -4111,6 +4112,7 @@ input[type="range"]::-webkit-slider-thumb { line-height: calc(var(--mainFontSize) + .25rem); max-height: 75vh; max-height: 75dvh; + field-sizing: content; } #anchor_order {