| import { DOMPurify, Bowser } from '../lib.js'; |
|
|
| import { |
| characters, |
| online_status, |
| main_api, |
| is_send_press, |
| max_context, |
| saveSettingsDebounced, |
| active_group, |
| active_character, |
| setActiveGroup, |
| setActiveCharacter, |
| getEntitiesList, |
| buildAvatarList, |
| selectCharacterById, |
| eventSource, |
| menu_type, |
| substituteParams, |
| sendTextareaMessage, |
| doNavbarIconClick, |
| isSwipingAllowed, |
| } from '../script.js'; |
|
|
| import { |
| power_user, |
| send_on_enter_options, |
| } from './power-user.js'; |
|
|
| import { selected_group, is_group_generating, openGroupById } from './group-chats.js'; |
| import { getTagKeyForEntity, applyTagsOnCharacterSelect } from './tags.js'; |
| import { |
| SECRET_KEYS, |
| secret_state, |
| } from './secrets.js'; |
| import { debounce, getStringHash, isValidUrl } from './utils.js'; |
| import { chat_completion_sources, oai_settings } from './openai.js'; |
| import { getTokenCountAsync } from './tokenizers.js'; |
| import { textgen_types, textgenerationwebui_settings as textgen_settings, getTextGenServer } from './textgen-settings.js'; |
| import { debounce_timeout, SWIPE_SOURCE } from './constants.js'; |
|
|
| import { Popup } from './popup.js'; |
| import { accountStorage } from './util/AccountStorage.js'; |
| import { getCurrentUserHandle } from './user.js'; |
| import { kai_settings } from './kai-settings.js'; |
|
|
| var RPanelPin = document.getElementById('rm_button_panel_pin'); |
| var LPanelPin = document.getElementById('lm_button_panel_pin'); |
| var WIPanelPin = document.getElementById('WI_panel_pin'); |
|
|
| var RightNavPanel = document.getElementById('right-nav-panel'); |
| var RightNavDrawerIcon = document.getElementById('rightNavDrawerIcon'); |
| var LeftNavPanel = document.getElementById('left-nav-panel'); |
| var LeftNavDrawerIcon = document.getElementById('leftNavDrawerIcon'); |
| var WorldInfo = document.getElementById('WorldInfo'); |
| var WIDrawerIcon = document.getElementById('WIDrawerIcon'); |
|
|
| var SelectedCharacterTab = document.getElementById('rm_button_selected_ch'); |
|
|
| var connection_made = false; |
| var retry_delay = 500; |
| let counterNonce = Date.now(); |
|
|
| const observerConfig = { childList: true, subtree: true }; |
| const countTokensDebounced = debounce(RA_CountCharTokens, debounce_timeout.relaxed); |
| const countTokensShortDebounced = debounce(RA_CountCharTokens, debounce_timeout.short); |
| const checkStatusDebounced = debounce(RA_checkOnlineStatus, debounce_timeout.short); |
|
|
| const observer = new MutationObserver(function (mutations) { |
| mutations.forEach(function (mutation) { |
| if (!(mutation.target instanceof HTMLElement)) { |
| return; |
| } |
| if (mutation.target.classList.contains('online_status_text')) { |
| checkStatusDebounced(); |
| } else if (mutation.target.parentNode === SelectedCharacterTab) { |
| countTokensShortDebounced(); |
| } else if (mutation.target.classList.contains('mes_text')) { |
| for (const element of mutation.target.getElementsByTagName('math')) { |
| element.childNodes.forEach(function (child) { |
| if (child.nodeType === Node.TEXT_NODE) { |
| child.textContent = ''; |
| } |
| }); |
| } |
| } |
| }); |
| }); |
|
|
| observer.observe(document.documentElement, observerConfig); |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| export function humanizeGenTime(total_gen_time) { |
|
|
| |
| let time_spent = total_gen_time || 0; |
| time_spent = Math.floor(time_spent / 1000); |
| let seconds = time_spent % 60; |
| time_spent = Math.floor(time_spent / 60); |
| let minutes = time_spent % 60; |
| time_spent = Math.floor(time_spent / 60); |
| let hours = time_spent % 24; |
| time_spent = Math.floor(time_spent / 24); |
| let days = time_spent; |
| let result = ''; |
| if (days > 0) { result += `${days} Days, `; } |
| if (hours > 0) { result += `${hours} Hours, `; } |
| if (minutes > 0) { result += `${minutes} Minutes, `; } |
| result += `${seconds} Seconds`; |
| return result; |
| } |
|
|
| |
| |
| |
| var parsedUA = null; |
|
|
| export function getParsedUA() { |
| if (!parsedUA) { |
| try { |
| parsedUA = Bowser.parse(navigator.userAgent); |
| } catch { |
| |
| } |
| } |
|
|
| return parsedUA; |
| } |
|
|
| |
| |
| |
| |
| export function isMobile() { |
| const mobileTypes = ['mobile', 'tablet']; |
|
|
| return mobileTypes.includes(getParsedUA()?.platform?.type); |
| } |
|
|
| export function shouldSendOnEnter() { |
| if (!power_user) { |
| return false; |
| } |
|
|
| switch (power_user.send_on_enter) { |
| case send_on_enter_options.DISABLED: |
| return false; |
| case send_on_enter_options.AUTO: |
| return !isMobile(); |
| case send_on_enter_options.ENABLED: |
| return true; |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| export function humanizedDateTime(timestamp = Date.now()) { |
| const date = new Date(timestamp); |
| const dt = { |
| year: date.getFullYear(), |
| month: date.getMonth() + 1, |
| day: date.getDate(), |
| hour: date.getHours(), |
| minute: date.getMinutes(), |
| second: date.getSeconds(), |
| millisecond: date.getMilliseconds(), |
| }; |
| for (const key in dt) { |
| const padLength = key === 'millisecond' ? 3 : 2; |
| dt[key] = dt[key].toString().padStart(padLength, '0'); |
| } |
| return `${dt.year}-${dt.month}-${dt.day}@${dt.hour}h${dt.minute}m${dt.second}s${dt.millisecond}ms`; |
| } |
|
|
| |
| |
| |
| |
| |
| export function getMessageTimeStamp(timestamp = Date.now()) { |
| const date = new Date(timestamp); |
| return date.toISOString(); |
| } |
|
|
|
|
| |
| $('#rm_button_create').on('click', function () { |
| $(SelectedCharacterTab).children('h2').html(''); |
| }); |
| |
| $('#rm_ch_create_block').on('input', function () { countTokensDebounced(); }); |
| |
| $('#character_popup').on('input', function () { countTokensDebounced(); }); |
| |
| export async function RA_CountCharTokens() { |
| counterNonce = Date.now(); |
| const counterNonceLocal = counterNonce; |
| let total_tokens = 0; |
| let permanent_tokens = 0; |
|
|
| const tokenCounters = document.querySelectorAll('[data-token-counter]'); |
| for (const tokenCounter of tokenCounters) { |
| if (counterNonceLocal !== counterNonce) { |
| return; |
| } |
|
|
| const counter = $(tokenCounter); |
| const input = $(document.getElementById(counter.data('token-counter'))); |
| const isPermanent = counter.data('token-permanent') === true; |
| const value = String(input.val()); |
|
|
| if (input.length === 0) { |
| counter.text('Invalid input reference'); |
| continue; |
| } |
|
|
| if (!value) { |
| input.data('last-value-hash', ''); |
| counter.text(0); |
| continue; |
| } |
|
|
| const valueHash = getStringHash(value); |
|
|
| if (input.data('last-value-hash') === valueHash) { |
| total_tokens += Number(counter.text()); |
| permanent_tokens += isPermanent ? Number(counter.text()) : 0; |
| } else { |
| |
| const valueToCount = menu_type === 'create' ? value : substituteParams(value); |
| const tokens = await getTokenCountAsync(valueToCount); |
|
|
| if (counterNonceLocal !== counterNonce) { |
| return; |
| } |
|
|
| counter.text(tokens); |
| total_tokens += tokens; |
| permanent_tokens += isPermanent ? tokens : 0; |
| input.data('last-value-hash', valueHash); |
| } |
| } |
|
|
| |
| const tokenLimit = Math.max(((main_api !== 'openai' ? max_context : oai_settings.openai_max_context) / 2), 1024); |
| const showWarning = (total_tokens > tokenLimit); |
| $('#result_info_total_tokens').text(total_tokens); |
| $('#result_info_permanent_tokens').text(permanent_tokens); |
| $('#result_info_text').toggleClass('neutral_warning', showWarning); |
| $('#chartokenwarning').toggle(showWarning); |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| async function RA_autoloadchat() { |
| |
| if (active_character !== null && active_character !== undefined) { |
| const active_character_id = characters.findIndex(x => getTagKeyForEntity(x) === active_character); |
| if (active_character_id !== -1) { |
| await selectCharacterById(active_character_id); |
|
|
| |
| const selectedCharElement = $(`#rm_print_characters_block .character_select[chid="${active_character_id}"]`); |
| applyTagsOnCharacterSelect.call(selectedCharElement); |
| } else { |
| setActiveCharacter(null); |
| saveSettingsDebounced(); |
| console.warn(`Currently active character with ID ${active_character} not found. Resetting to no active character.`); |
| } |
| } |
|
|
| if (active_group !== null && active_group !== undefined) { |
| if (active_character) { |
| console.warn('Active character and active group are both set. Only active character will be loaded. Resetting active group.'); |
| setActiveGroup(null); |
| saveSettingsDebounced(); |
| } else { |
| const result = await openGroupById(String(active_group)); |
| if (!result) { |
| setActiveGroup(null); |
| saveSettingsDebounced(); |
| console.warn(`Currently active group with ID ${active_group} not found. Resetting to no active group.`); |
| } |
| } |
| } |
| } |
|
|
| export async function favsToHotswap() { |
| const entities = getEntitiesList({ doFilter: false }); |
| const container = $('#right-nav-panel .hotswap'); |
|
|
| |
| |
| const FAVS_LIMIT = 25; |
| const favs = entities.filter(x => x.item.fav || x.item.fav == 'true').slice(0, FAVS_LIMIT); |
|
|
| |
| if (favs.length == 0) { |
| container.html(`<small><span><i class="fa-solid fa-star"></i> ${DOMPurify.sanitize(container.attr('no_favs'))}</span></small>`); |
| return; |
| } |
|
|
| buildAvatarList(container, favs, { interactable: true, highlightFavs: false }); |
| } |
|
|
| |
| function RA_checkOnlineStatus() { |
| if (online_status == 'no_connection') { |
| const send_textarea = $('#send_textarea'); |
| send_textarea.attr('placeholder', send_textarea.attr('no_connection_text')); |
| $('#send_form').addClass('no-connection'); |
| $('#send_but').addClass('displayNone'); |
| $('#mes_continue').addClass('displayNone'); |
| $('#mes_impersonate').addClass('displayNone'); |
| $('#API-status-top').removeClass('fa-plug'); |
| $('#API-status-top').addClass('fa-plug-circle-exclamation redOverlayGlow'); |
| connection_made = false; |
| } else { |
| if (online_status !== undefined && online_status !== 'no_connection') { |
| const send_textarea = $('#send_textarea'); |
| send_textarea.attr('placeholder', send_textarea.attr('connected_text')); |
| $('#send_form').removeClass('no-connection'); |
| $('#API-status-top').removeClass('fa-plug-circle-exclamation redOverlayGlow'); |
| $('#API-status-top').addClass('fa-plug'); |
| connection_made = true; |
| retry_delay = 100; |
|
|
| if (!is_send_press && !(selected_group && is_group_generating)) { |
| $('#send_but').removeClass('displayNone'); |
| $('#mes_continue').removeClass('displayNone'); |
| $('#mes_impersonate').removeClass('displayNone'); |
| } |
| } |
| } |
| } |
| |
|
|
| function RA_autoconnect(PrevApi) { |
| |
| if (SECRET_KEYS === undefined || online_status === undefined) { |
| setTimeout(RA_autoconnect, 100); |
| return; |
| } |
| if (online_status === 'no_connection' && power_user.auto_connect) { |
| switch (main_api) { |
| case 'kobold': |
| if (kai_settings.api_server && isValidUrl(kai_settings.api_server)) { |
| $('#api_button').trigger('click'); |
| } |
| break; |
| case 'novel': |
| if (secret_state[SECRET_KEYS.NOVEL]) { |
| $('#api_button_novel').trigger('click'); |
| } |
| break; |
| case 'textgenerationwebui': |
| if ((textgen_settings.type === textgen_types.MANCER && secret_state[SECRET_KEYS.MANCER]) |
| || (textgen_settings.type === textgen_types.TOGETHERAI && secret_state[SECRET_KEYS.TOGETHERAI]) |
| || (textgen_settings.type === textgen_types.INFERMATICAI && secret_state[SECRET_KEYS.INFERMATICAI]) |
| || (textgen_settings.type === textgen_types.DREAMGEN && secret_state[SECRET_KEYS.DREAMGEN]) |
| || (textgen_settings.type === textgen_types.OPENROUTER && secret_state[SECRET_KEYS.OPENROUTER]) |
| || (textgen_settings.type === textgen_types.FEATHERLESS && secret_state[SECRET_KEYS.FEATHERLESS]) |
| ) { |
| $('#api_button_textgenerationwebui').trigger('click'); |
| } |
| else if (isValidUrl(getTextGenServer())) { |
| $('#api_button_textgenerationwebui').trigger('click'); |
| } |
| break; |
| case 'openai': |
| if (((secret_state[SECRET_KEYS.OPENAI] || oai_settings.reverse_proxy) && oai_settings.chat_completion_source == chat_completion_sources.OPENAI) |
| || ((secret_state[SECRET_KEYS.CLAUDE] || oai_settings.reverse_proxy) && oai_settings.chat_completion_source == chat_completion_sources.CLAUDE) |
| || (secret_state[SECRET_KEYS.OPENROUTER] && oai_settings.chat_completion_source == chat_completion_sources.OPENROUTER) |
| || (secret_state[SECRET_KEYS.AI21] && oai_settings.chat_completion_source == chat_completion_sources.AI21) |
| || (secret_state[SECRET_KEYS.MAKERSUITE] && oai_settings.chat_completion_source == chat_completion_sources.MAKERSUITE) |
| || (secret_state[SECRET_KEYS.VERTEXAI] && oai_settings.chat_completion_source == chat_completion_sources.VERTEXAI && oai_settings.vertexai_auth_mode === 'express') |
| || (secret_state[SECRET_KEYS.VERTEXAI_SERVICE_ACCOUNT] && oai_settings.chat_completion_source == chat_completion_sources.VERTEXAI && oai_settings.vertexai_auth_mode === 'full') |
| || (secret_state[SECRET_KEYS.MISTRALAI] && oai_settings.chat_completion_source == chat_completion_sources.MISTRALAI) |
| || (secret_state[SECRET_KEYS.COHERE] && oai_settings.chat_completion_source == chat_completion_sources.COHERE) |
| || (secret_state[SECRET_KEYS.PERPLEXITY] && oai_settings.chat_completion_source == chat_completion_sources.PERPLEXITY) |
| || (secret_state[SECRET_KEYS.GROQ] && oai_settings.chat_completion_source == chat_completion_sources.GROQ) |
| || (secret_state[SECRET_KEYS.CHUTES] && oai_settings.chat_completion_source == chat_completion_sources.CHUTES) |
| || (secret_state[SECRET_KEYS.SILICONFLOW] && oai_settings.chat_completion_source == chat_completion_sources.SILICONFLOW) |
| || (secret_state[SECRET_KEYS.ELECTRONHUB] && oai_settings.chat_completion_source == chat_completion_sources.ELECTRONHUB) |
| || (secret_state[SECRET_KEYS.NANOGPT] && oai_settings.chat_completion_source == chat_completion_sources.NANOGPT) |
| || (secret_state[SECRET_KEYS.DEEPSEEK] && oai_settings.chat_completion_source == chat_completion_sources.DEEPSEEK) |
| || (secret_state[SECRET_KEYS.XAI] && oai_settings.chat_completion_source == chat_completion_sources.XAI) |
| || (secret_state[SECRET_KEYS.AIMLAPI] && oai_settings.chat_completion_source == chat_completion_sources.AIMLAPI) |
| || (secret_state[SECRET_KEYS.MOONSHOT] && oai_settings.chat_completion_source == chat_completion_sources.MOONSHOT) |
| || (secret_state[SECRET_KEYS.FIREWORKS] && oai_settings.chat_completion_source == chat_completion_sources.FIREWORKS) |
| || (secret_state[SECRET_KEYS.COMETAPI] && oai_settings.chat_completion_source == chat_completion_sources.COMETAPI) |
| || (secret_state[SECRET_KEYS.ZAI] && oai_settings.chat_completion_source == chat_completion_sources.ZAI) |
| || (oai_settings.chat_completion_source === chat_completion_sources.POLLINATIONS) |
| || (isValidUrl(oai_settings.custom_url) && oai_settings.chat_completion_source == chat_completion_sources.CUSTOM) |
| || (secret_state[SECRET_KEYS.AZURE_OPENAI] && oai_settings.chat_completion_source == chat_completion_sources.AZURE_OPENAI) |
| ) { |
| $('#api_button_openai').trigger('click'); |
| } |
| break; |
| } |
|
|
| if (!connection_made) { |
| retry_delay = Math.min(retry_delay * 2, 30000); |
| |
| |
| } |
| } |
| } |
|
|
| function OpenNavPanels() { |
| if (!isMobile()) { |
| |
| if (accountStorage.getItem('NavLockOn') == 'true' && accountStorage.getItem('NavOpened') == 'true') { |
| |
| $('#rightNavDrawerIcon').trigger('click'); |
| } |
|
|
| |
| if (accountStorage.getItem('LNavLockOn') == 'true' && accountStorage.getItem('LNavOpened') == 'true') { |
| console.debug('RA -- clicking left nav to open'); |
| $('#leftNavDrawerIcon').trigger('click'); |
| } |
|
|
| |
| if (accountStorage.getItem('WINavLockOn') == 'true' && accountStorage.getItem('WINavOpened') == 'true') { |
| console.debug('RA -- clicking WI to open'); |
| $('#WIDrawerIcon').trigger('click'); |
| } |
| } |
| } |
|
|
| const getUserInputKey = () => getCurrentUserHandle() + '_userInput'; |
|
|
| function restoreUserInput() { |
| if (!power_user.restore_user_input) { |
| console.debug('restoreUserInput disabled'); |
| return; |
| } |
|
|
| const userInput = localStorage.getItem(getUserInputKey()); |
| if (userInput) { |
| $('#send_textarea').val(userInput)[0].dispatchEvent(new Event('input', { bubbles: true })); |
| } |
| } |
|
|
| function saveUserInput() { |
| const userInput = String($('#send_textarea').val()); |
| localStorage.setItem(getUserInputKey(), userInput); |
| console.debug('User Input -- ', userInput); |
| } |
| const saveUserInputDebounced = debounce(saveUserInput); |
|
|
| |
|
|
| |
| |
| |
| |
| export function dragElement($elmnt) { |
| let actionType = null; |
| let isMouseDown = false; |
|
|
| let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0; |
| let height, width, top, left, right, bottom, |
| maxX, maxY, winHeight, winWidth; |
|
|
| const elmntName = $elmnt.attr('id'); |
| const elmntNameEscaped = $.escapeSelector(elmntName); |
| const $elmntHeader = $(`#${elmntNameEscaped}header`); |
|
|
| |
| function savePositionAndSize() { |
| if (!power_user.movingUIState[elmntName]) power_user.movingUIState[elmntName] = {}; |
| power_user.movingUIState[elmntName].top = top; |
| power_user.movingUIState[elmntName].left = left; |
| power_user.movingUIState[elmntName].right = right; |
| power_user.movingUIState[elmntName].bottom = bottom; |
| power_user.movingUIState[elmntName].margin = 'unset'; |
| if (actionType === 'resize') { |
| power_user.movingUIState[elmntName].width = width; |
| power_user.movingUIState[elmntName].height = height; |
| eventSource.emit('resizeUI', elmntName); |
| } |
| saveSettingsDebounced(); |
| } |
|
|
| |
| function clampToViewport() { |
| if (top <= 0) $elmnt.css('top', '0px'); |
| else if (maxY >= winHeight) $elmnt.css('top', winHeight - maxY + top - 1 + 'px'); |
| if (left <= 0) $elmnt.css('left', '0px'); |
| else if (maxX >= winWidth) $elmnt.css('left', winWidth - maxX + left - 1 + 'px'); |
| } |
|
|
| |
| const observer = new MutationObserver((mutations) => { |
| const $target = $(mutations[0].target); |
| if ( |
| !$target.is(':visible') || |
| $target.hasClass('resizing') || |
| $target.height() < 50 || |
| $target.width() < 50 || |
| power_user.movingUI === false || |
| isMobile() || |
| !isMouseDown |
| ) { |
| observer.disconnect(); |
| return; |
| } |
|
|
| const element = ($target[0]); |
| const style = getComputedStyle(element); |
| height = parseInt(style.height); |
| width = parseInt(style.width); |
| top = parseInt(style.top); |
| left = parseInt(style.left); |
| right = parseInt(style.right); |
| bottom = parseInt(style.bottom); |
| maxX = width + left; |
| maxY = height + top; |
| winWidth = window.innerWidth; |
| winHeight = window.innerHeight; |
|
|
| |
| if (!power_user.movingUIState[elmntName]) power_user.movingUIState[elmntName] = {}; |
|
|
| if (actionType === 'resize') { |
| let containerAspectRatio = height / width; |
| if ($elmnt.attr('id').startsWith('zoomFor_')) { |
| const zoomedAvatarImage = $elmnt.find('.zoomed_avatar_img'); |
| const imgHeight = zoomedAvatarImage.height(); |
| const imgWidth = zoomedAvatarImage.width(); |
| const imageAspectRatio = imgHeight / imgWidth; |
| if (containerAspectRatio !== imageAspectRatio) { |
| $elmnt.css('width', $elmnt.width()); |
| $elmnt.css('height', $elmnt.width() * imageAspectRatio); |
| } |
| if (top + $elmnt.height() >= winHeight) { |
| $elmnt.css('height', winHeight - top - 1 + 'px'); |
| $elmnt.css('width', (winHeight - top - 1) / imageAspectRatio + 'px'); |
| } |
| if (left + $elmnt.width() >= winWidth) { |
| $elmnt.css('width', winWidth - left - 1 + 'px'); |
| $elmnt.css('height', (winWidth - left - 1) * imageAspectRatio + 'px'); |
| } |
| } else { |
| if (top + $elmnt.height() >= winHeight) $elmnt.css('height', winHeight - top - 1 + 'px'); |
| if (left + $elmnt.width() >= winWidth) $elmnt.css('width', winWidth - left - 1 + 'px'); |
| } |
| |
| |
| |
| $elmnt.css({ left, top }); |
| $elmnt.off('mouseup').on('mouseup', () => { |
| if ( |
| power_user.movingUIState[elmntName].width === $elmnt.width() && |
| power_user.movingUIState[elmntName].height === $elmnt.height() |
| ) return; |
| savePositionAndSize(); |
| observer.disconnect(); |
| }); |
| } else if (actionType === 'drag') { |
| clampToViewport(); |
| } |
|
|
| |
| savePositionAndSize(); |
| }); |
|
|
| |
| function dragMouseDown(e) { |
| if (e) { |
| actionType = 'drag'; |
| isMouseDown = true; |
| e.preventDefault(); |
| pos3 = e.clientX; |
| pos4 = e.clientY; |
| } |
| $(document).on('mouseup', closeDragElement); |
| $(document).on('mousemove', elementDrag); |
| } |
|
|
| function elementDrag(e) { |
| if (!power_user.movingUIState[elmntName]) power_user.movingUIState[elmntName] = {}; |
| e.preventDefault(); |
| pos1 = pos3 - e.clientX; |
| pos2 = pos4 - e.clientY; |
| pos3 = e.clientX; |
| pos4 = e.clientY; |
| $elmnt.attr('data-dragged', 'true'); |
| $elmnt.css('left', ($elmnt.offset().left - pos1) + 'px'); |
| $elmnt.css('top', ($elmnt.offset().top - pos2) + 'px'); |
| $elmnt.css('margin', 'unset'); |
| $elmnt.css('height', height); |
| $elmnt.css('width', width); |
| } |
|
|
| function closeDragElement() { |
| isMouseDown = false; |
| actionType = null; |
| $(document).off('mouseup', closeDragElement); |
| $(document).off('mousemove', elementDrag); |
| $elmnt.attr('data-dragged', 'false'); |
| observer.disconnect(); |
| savePositionAndSize(); |
| } |
|
|
| |
| if ($elmntHeader.length) { |
| $elmntHeader.off('mousedown').on('mousedown', (e) => { |
| if ($(e.target).hasClass('drag-grabber')) { |
| actionType = 'drag'; |
| isMouseDown = true; |
| observer.observe($elmnt[0], { attributes: true, attributeFilter: ['style'] }); |
| dragMouseDown(e); |
| } |
| }); |
| } |
|
|
| $elmnt.off('mousedown').on('mousedown', (e) => { |
| const rect = $elmnt[0].getBoundingClientRect(); |
| const resizeMargin = 16; |
| const isNearRight = e.clientX > rect.right - resizeMargin; |
| const isNearBottom = e.clientY > rect.bottom - resizeMargin; |
| if (isNearRight && isNearBottom) { |
| actionType = 'resize'; |
| isMouseDown = true; |
| observer.observe($elmnt[0], { attributes: true, attributeFilter: ['style'] }); |
| } |
| }); |
|
|
| $elmnt.off('mouseup').on('mouseup', () => { |
| isMouseDown = false; |
| actionType = null; |
| observer.disconnect(); |
| }); |
| } |
|
|
| export async function initMovingUI() { |
| if (!isMobile() && power_user.movingUI === true) { |
| console.debug('START MOVING UI'); |
| dragElement($('#sheld')); |
| dragElement($('#left-nav-panel')); |
| dragElement($('#right-nav-panel')); |
| dragElement($('#WorldInfo')); |
| dragElement($('#floatingPrompt')); |
| dragElement($('#logprobsViewer')); |
| dragElement($('#cfgConfig')); |
| } |
| } |
|
|
| |
| const sendTextArea = document.querySelector('#send_textarea'); |
| const chatBlock = document.getElementById('chat'); |
| const isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1; |
|
|
| |
| |
| |
| function autoFitSendTextArea() { |
| const originalScrollBottom = chatBlock.scrollHeight - (chatBlock.scrollTop + chatBlock.offsetHeight); |
|
|
| sendTextArea.style.height = '1px'; |
| const newHeight = sendTextArea.scrollHeight; |
| sendTextArea.style.height = `${newHeight}px`; |
|
|
| if (!isFirefox) { |
| chatBlock.scrollTop = chatBlock.scrollHeight - (chatBlock.offsetHeight + originalScrollBottom); |
| } |
| } |
| export const autoFitSendTextAreaDebounced = debounce(autoFitSendTextArea, debounce_timeout.short); |
|
|
| |
|
|
| export function initRossMods() { |
| |
| checkStatusDebounced(); |
|
|
| if (power_user.auto_load_chat) { |
| RA_autoloadchat(); |
| } |
|
|
| if (power_user.auto_connect) { |
| RA_autoconnect(); |
| } |
|
|
| $('#main_api').on('change', function () { |
| var PrevAPI = main_api; |
| setTimeout(() => RA_autoconnect(PrevAPI), 100); |
| }); |
|
|
| $('#api_button').on('click', () => checkStatusDebounced()); |
|
|
| |
| $(RPanelPin).on('click', function () { |
| accountStorage.setItem('NavLockOn', $(RPanelPin).prop('checked')); |
| if ($(RPanelPin).prop('checked') == true) { |
| |
| $(RightNavPanel).addClass('pinnedOpen'); |
| $(RightNavDrawerIcon).addClass('drawerPinnedOpen'); |
| } else { |
| |
| $(RightNavPanel).removeClass('pinnedOpen'); |
| $(RightNavDrawerIcon).removeClass('drawerPinnedOpen'); |
|
|
| if ($(RightNavPanel).hasClass('openDrawer') && $('.openDrawer').length > 1) { |
| const toggle = $('#unimportantYes'); |
| doNavbarIconClick.call(toggle); |
| } |
| } |
| }); |
| $(LPanelPin).on('click', function () { |
| accountStorage.setItem('LNavLockOn', $(LPanelPin).prop('checked')); |
| if ($(LPanelPin).prop('checked') == true) { |
| |
| $(LeftNavPanel).addClass('pinnedOpen'); |
| $(LeftNavDrawerIcon).addClass('drawerPinnedOpen'); |
| } else { |
| |
| $(LeftNavPanel).removeClass('pinnedOpen'); |
| $(LeftNavDrawerIcon).removeClass('drawerPinnedOpen'); |
|
|
| if ($(LeftNavPanel).hasClass('openDrawer') && $('.openDrawer').length > 1) { |
| const toggle = $('#ai-config-button>.drawer-toggle'); |
| doNavbarIconClick.call(toggle); |
| } |
| } |
| }); |
|
|
| $(WIPanelPin).on('click', async function () { |
| accountStorage.setItem('WINavLockOn', $(WIPanelPin).prop('checked')); |
| if ($(WIPanelPin).prop('checked') == true) { |
| console.debug('adding pin class to WI'); |
| $(WorldInfo).addClass('pinnedOpen'); |
| $(WIDrawerIcon).addClass('drawerPinnedOpen'); |
| } else { |
| console.debug('removing pin class from WI'); |
| $(WorldInfo).removeClass('pinnedOpen'); |
| $(WIDrawerIcon).removeClass('drawerPinnedOpen'); |
|
|
| if ($(WorldInfo).hasClass('openDrawer') && $('.openDrawer').length > 1) { |
| console.debug('closing WI after lock removal'); |
| const toggle = $('#WI-SP-button>.drawer-toggle'); |
| doNavbarIconClick.call(toggle); |
| } |
| } |
| }); |
|
|
| if (!isMobile()) { |
| |
| $(RPanelPin).prop('checked', accountStorage.getItem('NavLockOn') == 'true'); |
| if (accountStorage.getItem('NavLockOn') == 'true') { |
| |
| $(RightNavPanel).addClass('pinnedOpen'); |
| $(RightNavDrawerIcon).addClass('drawerPinnedOpen'); |
| } |
| if ($(RPanelPin).prop('checked')) { |
| console.debug('setting pin class via checkbox state'); |
| $(RightNavPanel).addClass('pinnedOpen'); |
| $(RightNavDrawerIcon).addClass('drawerPinnedOpen'); |
| } |
| |
| $(LPanelPin).prop('checked', accountStorage.getItem('LNavLockOn') === 'true'); |
| if (accountStorage.getItem('LNavLockOn') == 'true') { |
| |
| $(LeftNavPanel).addClass('pinnedOpen'); |
| $(LeftNavDrawerIcon).addClass('drawerPinnedOpen'); |
| } |
| if ($(LPanelPin).prop('checked')) { |
| console.debug('setting pin class via checkbox state'); |
| $(LeftNavPanel).addClass('pinnedOpen'); |
| $(LeftNavDrawerIcon).addClass('drawerPinnedOpen'); |
| } |
|
|
| |
| $(WIPanelPin).prop('checked', accountStorage.getItem('WINavLockOn') === 'true'); |
| if (accountStorage.getItem('WINavLockOn') == 'true') { |
| |
| $(WorldInfo).addClass('pinnedOpen'); |
| $(WIDrawerIcon).addClass('drawerPinnedOpen'); |
| } |
|
|
| if ($(WIPanelPin).prop('checked')) { |
| console.debug('setting pin class via checkbox state'); |
| $(WorldInfo).addClass('pinnedOpen'); |
| $(WIDrawerIcon).addClass('drawerPinnedOpen'); |
| } |
| } |
|
|
|
|
| |
| $('#rightNavDrawerIcon').on('click', function () { |
| if (!$('#rightNavDrawerIcon').hasClass('openIcon')) { |
| accountStorage.setItem('NavOpened', 'true'); |
| } else { accountStorage.setItem('NavOpened', 'false'); } |
| }); |
|
|
| |
| $('#leftNavDrawerIcon').on('click', function () { |
| if (!$('#leftNavDrawerIcon').hasClass('openIcon')) { |
| accountStorage.setItem('LNavOpened', 'true'); |
| } else { accountStorage.setItem('LNavOpened', 'false'); } |
| }); |
|
|
| |
| $('#WorldInfo').on('click', function () { |
| if (!$('#WorldInfo').hasClass('openIcon')) { |
| accountStorage.setItem('WINavOpened', 'true'); |
| } else { accountStorage.setItem('WINavOpened', 'false'); } |
| }); |
|
|
| var chatbarInFocus = false; |
| $('#send_textarea').on('focus', function () { |
| chatbarInFocus = true; |
| }); |
|
|
| $('#send_textarea').on('blur', function () { |
| chatbarInFocus = false; |
| }); |
|
|
| setTimeout(() => { |
| OpenNavPanels(); |
| }, 300); |
|
|
| $(SelectedCharacterTab).on('click', function () { accountStorage.setItem('SelectedNavTab', 'rm_button_selected_ch'); }); |
| $('#rm_button_characters').on('click', function () { accountStorage.setItem('SelectedNavTab', 'rm_button_characters'); }); |
|
|
| |
|
|
| |
| $(document).on('click', '.character_select', function () { |
| const characterId = $(this).attr('data-chid'); |
| setActiveCharacter(characterId); |
| setActiveGroup(null); |
| saveSettingsDebounced(); |
| }); |
|
|
| $(document).on('click', '.group_select', function () { |
| const groupId = $(this).attr('data-chid') || $(this).attr('data-grid'); |
| setActiveCharacter(null); |
| setActiveGroup(groupId); |
| 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) { |
| |
| sendTextArea.style.height = 'auto'; |
| return; |
| } |
|
|
| const hasContent = sendTextArea.value !== ''; |
| const fitsCurrentSize = sendTextArea.scrollHeight <= sendTextArea.offsetHeight; |
| const isScrollbarShown = sendTextArea.clientWidth < sendTextArea.offsetWidth; |
| const isHalfScreenHeight = sendTextArea.offsetHeight >= window.innerHeight / 2; |
| const needsDebounce = hasContent && (fitsCurrentSize || (isScrollbarShown && isHalfScreenHeight)); |
| if (needsDebounce) autoFitSendTextAreaDebounced(); |
| else autoFitSendTextArea(); |
| }); |
|
|
| restoreUserInput(); |
|
|
| |
| document.addEventListener('swiped-left', function (e) { |
| if (power_user.gestures === false) { |
| return; |
| } |
| if (Popup.util.isPopupOpen()) { |
| return; |
| } |
| if (!$(e.target).closest('#sheld').length) { |
| return; |
| } |
| if ($('#curEditTextarea').length) { |
| |
| |
| |
| return; |
| } |
| var SwipeButR = $('.swipe_right:last'); |
| var SwipeTargetMesClassParent = $(e.target).closest('.last_mes'); |
| if (SwipeTargetMesClassParent !== null) { |
| if (SwipeButR.is(':visible')) { |
| SwipeButR.trigger('click'); |
| } |
| } |
| }); |
| document.addEventListener('swiped-right', function (e) { |
| if (power_user.gestures === false) { |
| return; |
| } |
| if (Popup.util.isPopupOpen()) { |
| return; |
| } |
| if (!$(e.target).closest('#sheld').length) { |
| return; |
| } |
| if ($('#curEditTextarea').length) { |
| |
| |
| |
| return; |
| } |
| var SwipeButL = $('.swipe_left:last'); |
| var SwipeTargetMesClassParent = $(e.target).closest('.last_mes'); |
| if (SwipeTargetMesClassParent !== null) { |
| if (SwipeButL.is(':visible')) { |
| SwipeButL.trigger('click'); |
| } |
| } |
| }); |
|
|
|
|
| function isInputElementInFocus() { |
| |
| var focused = $(':focus'); |
| if (focused.is('input') || focused.is('textarea') || focused.prop('contenteditable') == 'true') { |
| if (focused.attr('id') === 'send_textarea') { |
| return false; |
| } |
| return true; |
| } |
| return false; |
| } |
|
|
| function isModifiedKeyboardEvent(event) { |
| return (event instanceof KeyboardEvent && |
| (event.shiftKey || |
| event.ctrlKey || |
| event.altKey || |
| event.metaKey)); |
| } |
|
|
| $(document).on('keydown', async function (event) { |
| await processHotkeys(event.originalEvent); |
| }); |
|
|
| const hotkeyTargets = { |
| 'send_textarea': sendTextArea, |
| 'dialogue_popup_input': document.querySelector('#dialogue_popup_input'), |
| }; |
|
|
| |
| |
| |
| |
| async function processHotkeys(event) { |
| |
| if (Popup.util.isPopupOpen()) { |
| return; |
| } |
|
|
| |
| if (document.activeElement == hotkeyTargets['send_textarea']) { |
| const sendOnEnter = shouldSendOnEnter(); |
| if (!event.isComposing && !event.shiftKey && !event.ctrlKey && !event.altKey && event.key == 'Enter' && sendOnEnter) { |
| event.preventDefault(); |
| sendTextareaMessage(); |
| return; |
| } |
| } |
| if (document.activeElement == hotkeyTargets['dialogue_popup_input'] && !isMobile()) { |
| if (!event.shiftKey && !event.ctrlKey && event.key == 'Enter') { |
| event.preventDefault(); |
| $('#dialogue_popup_ok').trigger('click'); |
| return; |
| } |
| } |
| |
| if (event.shiftKey && event.ctrlKey && event.key == 'ArrowUp') { |
| event.preventDefault(); |
| let contextLine = $('.lastInContext'); |
| if (contextLine.length !== 0) { |
| $('#chat').animate({ |
| scrollTop: contextLine.offset().top - $('#chat').offset().top + $('#chat').scrollTop(), |
| }, 300); |
| } else { toastr.warning('Context line not found, send a message first!'); } |
| return; |
| } |
| |
| if (event.shiftKey && event.ctrlKey && event.key == 'ArrowDown') { |
| event.preventDefault(); |
| $('#chat').animate({ |
| scrollTop: $('#chat').prop('scrollHeight'), |
| }, 300); |
| return; |
| } |
|
|
| |
| if ((event.altKey || (event.altKey && event.ctrlKey)) && event.key == 'Enter') { |
| if (is_send_press == false) { |
| console.debug('Continuing with Alt+Enter'); |
| $('#option_continue').trigger('click'); |
| return; |
| } |
| } |
|
|
| |
| if (event.ctrlKey && event.key == 'Enter') { |
| const editMesDone = $('.mes_edit_done:visible'); |
| const reasoningMesDone = $('.mes_reasoning_edit_done:visible'); |
| if (editMesDone.length > 0) { |
| console.debug('Accepting edits with Ctrl+Enter'); |
| $('#send_textarea').trigger('focus'); |
| editMesDone.trigger('click'); |
| return; |
| } else if (reasoningMesDone.length > 0) { |
| console.debug('Accepting edits with Ctrl+Enter'); |
| $('#send_textarea').trigger('focus'); |
| reasoningMesDone.trigger('click'); |
| return; |
| } |
| else if (is_send_press == false) { |
| const skipConfirmKey = 'RegenerateWithCtrlEnter'; |
| const skipConfirm = accountStorage.getItem(skipConfirmKey) === 'true'; |
| function doRegenerate() { |
| console.debug('Regenerating with Ctrl+Enter'); |
| $('#option_regenerate').trigger('click'); |
| $('#options').hide(); |
| } |
|
|
| |
| if ($('#send_textarea').val() !== '') { |
| if (shouldSendOnEnter()) { |
| console.debug('Sending with Ctrl+Enter'); |
| event.preventDefault(); |
| sendTextareaMessage(); |
| } else { |
| console.debug('Text area is not empty, but send on enter is disabled'); |
| } |
| return; |
| } |
|
|
| if (skipConfirm) { |
| doRegenerate(); |
| } else { |
| let regenerateWithCtrlEnter = false; |
| const result = await Popup.show.confirm('Regenerate Message', 'Are you sure you want to regenerate the latest message?', { |
| customInputs: [{ id: 'regenerateWithCtrlEnter', label: 'Don\'t ask again' }], |
| onClose: (popup) => { |
| regenerateWithCtrlEnter = Boolean(popup.inputResults.get('regenerateWithCtrlEnter') ?? false); |
| }, |
| }); |
| if (!result) { |
| return; |
| } |
|
|
| accountStorage.setItem(skipConfirmKey, String(regenerateWithCtrlEnter)); |
| doRegenerate(); |
| } |
| return; |
| } else { |
| console.debug('Ctrl+Enter ignored'); |
| } |
| } |
|
|
| |
| function isNanogallery2LightboxActive() { |
| |
| return document.body.classList.contains('nGY2_body_scrollbar'); |
| } |
|
|
| if (event.key == 'ArrowLeft') { |
| if ( |
| isSwipingAllowed() && |
| !isNanogallery2LightboxActive() && |
| $('#send_textarea').val() === '' && |
| $('#character_popup').css('display') === 'none' && |
| $('#shadow_select_chat_popup').css('display') === 'none' && |
| !isInputElementInFocus() && |
| !isModifiedKeyboardEvent(event) && |
| !(document.activeElement instanceof HTMLVideoElement) |
| ) { |
| $('.swipe_left:last').trigger('click', { source: SWIPE_SOURCE.KEYBOARD, repeated: event.repeat }); |
| return; |
| } |
| } |
| if (event.key == 'ArrowRight') { |
| if ( |
| isSwipingAllowed() && |
| !isNanogallery2LightboxActive() && |
| $('#send_textarea').val() === '' && |
| $('#character_popup').css('display') === 'none' && |
| $('#shadow_select_chat_popup').css('display') === 'none' && |
| !isInputElementInFocus() && |
| !isModifiedKeyboardEvent(event) && |
| !(document.activeElement instanceof HTMLVideoElement) |
| ) { |
| $('.swipe_right:last').trigger('click', { source: SWIPE_SOURCE.KEYBOARD, repeated: event.repeat }); |
| return; |
| } |
| } |
|
|
|
|
| if (event.ctrlKey && event.key == 'ArrowUp') { |
| if ( |
| hotkeyTargets['send_textarea'].value === '' && |
| chatbarInFocus === true && |
| ($('.swipe_right:last').css('display') === 'flex' || $('.last_mes').attr('is_system') === 'true') && |
| $('#character_popup').css('display') === 'none' && |
| $('#shadow_select_chat_popup').css('display') === 'none' |
| ) { |
| const isUserMesList = document.querySelectorAll('div[is_user="true"]'); |
| const lastIsUserMes = isUserMesList[isUserMesList.length - 1]; |
| const editMes = lastIsUserMes.querySelector('.mes_block .mes_edit'); |
| if (editMes !== null) { |
| $(editMes).trigger('click'); |
| return; |
| } |
| } |
| } |
|
|
| if (event.key == 'ArrowUp') { |
| console.log('got uparrow input'); |
| if ( |
| hotkeyTargets['send_textarea'].value === '' && |
| chatbarInFocus === true && |
| |
| $('.last_mes .mes_buttons').is(':visible') && |
| $('#character_popup').css('display') === 'none' && |
| $('#shadow_select_chat_popup').css('display') === 'none' |
| ) { |
| const lastMes = document.querySelector('.last_mes'); |
| const editMes = lastMes.querySelector('.mes_block .mes_edit'); |
| if (editMes !== null) { |
| $(editMes).trigger('click'); |
| return; |
| } |
| } |
| } |
|
|
| if (event.key == 'Escape') { |
| |
| |
| if ($('#curEditTextarea').is(':visible') || $('#mes_stop').is(':visible')) { |
| console.debug('escape key, but deferring to script.js routines'); |
| return; |
| } |
|
|
| if ($('#dialogue_popup').is(':visible')) { |
| if ($('#dialogue_popup_cancel').is(':visible')) { |
| $('#dialogue_popup_cancel').trigger('click'); |
| return; |
| } else { |
| $('#dialogue_popup_ok').trigger('click'); |
| return; |
| } |
| } |
|
|
| if ($('#select_chat_popup').is(':visible')) { |
| $('#select_chat_cross').trigger('click'); |
| return; |
| } |
|
|
| if ($('#character_popup').is(':visible')) { |
| $('#character_cross').trigger('click'); |
| return; |
| } |
|
|
| if ($('#dialogue_del_mes_cancel').is(':visible')) { |
| $('#dialogue_del_mes_cancel').trigger('click'); |
| return; |
| } |
|
|
| if ($('.drawer-content') |
| .not('#WorldInfo') |
| .not('#left-nav-panel') |
| .not('#right-nav-panel') |
| .not('#floatingPrompt') |
| .not('#cfgConfig') |
| .not('#logprobsViewer') |
| .not('#movingDivs > div') |
| .is(':visible')) { |
| let visibleDrawerContent = $('.drawer-content:visible') |
| .not('#WorldInfo') |
| .not('#left-nav-panel') |
| .not('#right-nav-panel') |
| .not('#floatingPrompt') |
| .not('#cfgConfig') |
| .not('#logprobsViewer') |
| .not('#movingDivs > div'); |
| $(visibleDrawerContent).parent().find('.drawer-icon').trigger('click'); |
| return; |
| } |
|
|
| if ($('#floatingPrompt').is(':visible')) { |
| $('#ANClose').trigger('click'); |
| return; |
| } |
|
|
| if ($('#WorldInfo').is(':visible')) { |
| $('#WIDrawerIcon').trigger('click'); |
| return; |
| } |
|
|
| if ($('#cfgConfig').is(':visible')) { |
| $('#CFGClose').trigger('click'); |
| return; |
| } |
|
|
| if ($('#logprobsViewer').is(':visible')) { |
| $('#logprobsViewerClose').trigger('click'); |
| return; |
| } |
|
|
| $('#movingDivs > div').each(function () { |
| if ($(this).is(':visible')) { |
| $('#movingDivs > div .floating_panel_close').trigger('click'); |
| return; |
| } |
| }); |
|
|
| if ($('#left-nav-panel').is(':visible') && |
| $(LPanelPin).prop('checked') === false) { |
| $('#leftNavDrawerIcon').trigger('click'); |
| return; |
| } |
|
|
| if ($('#right-nav-panel').is(':visible') && |
| $(RPanelPin).prop('checked') === false) { |
| $('#rightNavDrawerIcon').trigger('click'); |
| return; |
| } |
| if ($('.draggable').is(':visible')) { |
| |
| $('.draggable:first').remove(); |
| return; |
| } |
| } |
|
|
|
|
|
|
|
|
| if (event.ctrlKey && /^[1-9]$/.test(event.key)) { |
| |
| |
| console.log('Ctrl +' + event.key + ' pressed!'); |
| } |
| } |
| } |
|
|