2023-07-20 19:32:15 +02:00
import {
saveSettingsDebounced ,
scrollChatToBottom ,
characters ,
callPopup ,
getStatus ,
reloadMarkdownProcessor ,
reloadCurrentChat ,
getRequestHeaders ,
substituteParams ,
updateVisibleDivs ,
eventSource ,
event _types ,
getCurrentChatId ,
printCharacters ,
name1 ,
name2 ,
setCharacterId ,
setEditedMessageId
} from "../script.js" ;
import { favsToHotswap , isMobile , initMovingUI } from "./RossAscends-mods.js" ;
import {
groups ,
resetSelectedGroup ,
selected _group ,
} from "./group-chats.js" ;
import { registerSlashCommand } from "./slash-commands.js" ;
import { delay , debounce } from "./utils.js" ;
export {
loadPowerUserSettings ,
loadMovingUIState ,
collapseNewlines ,
playMessageSound ,
sortGroupMembers ,
sortCharactersList ,
fixMarkdown ,
power _user ,
pygmalion _options ,
tokenizers ,
send _on _enter _options ,
} ;
2023-07-23 22:52:31 +02:00
export const MAX _CONTEXT _DEFAULT = 4096 ;
2023-07-20 19:32:15 +02:00
const MAX _CONTEXT _UNLOCKED = 65536 ;
const avatar _styles = {
ROUND : 0 ,
RECTANGULAR : 1 ,
}
export const chat _styles = {
DEFAULT : 0 ,
BUBBLES : 1 ,
DOCUMENT : 2 ,
}
const pygmalion _options = {
DISABLED : - 1 ,
AUTO : 0 ,
ENABLED : 1 ,
}
const tokenizers = {
NONE : 0 ,
GPT3 : 1 ,
CLASSIC : 2 ,
LLAMA : 3 ,
NERD : 4 ,
NERD2 : 5 ,
API : 6 ,
}
const send _on _enter _options = {
DISABLED : - 1 ,
AUTO : 0 ,
ENABLED : 1 ,
}
export const persona _description _positions = {
BEFORE _CHAR : 0 ,
AFTER _CHAR : 1 ,
TOP _AN : 2 ,
BOTTOM _AN : 3 ,
}
let power _user = {
tokenizer : tokenizers . CLASSIC ,
token _padding : 64 ,
collapse _newlines : false ,
pygmalion _formatting : pygmalion _options . AUTO ,
pin _examples : false ,
disable _description _formatting : false ,
disable _scenario _formatting : false ,
disable _personality _formatting : false ,
disable _examples _formatting : false ,
disable _start _formatting : false ,
trim _sentences : false ,
include _newline : false ,
always _force _name2 : false ,
user _prompt _bias : '' ,
show _user _prompt _bias : true ,
multigen : false ,
multigen _first _chunk : 50 ,
multigen _next _chunks : 30 ,
custom _chat _separator : '' ,
markdown _escape _strings : '' ,
fast _ui _mode : true ,
avatar _style : avatar _styles . ROUND ,
chat _display : chat _styles . DEFAULT ,
chat _width : 50 ,
never _resize _avatars : false ,
show _card _avatar _urls : false ,
play _message _sound : false ,
play _sound _unfocused : true ,
auto _save _msg _edits : false ,
confirm _message _delete : true ,
sort _field : 'name' ,
sort _order : 'asc' ,
sort _rule : null ,
font _scale : 1 ,
blur _strength : 10 ,
shadow _width : 2 ,
main _text _color : ` ${ getComputedStyle ( document . documentElement ) . getPropertyValue ( '--SmartThemeBodyColor' ) . trim ( ) } ` ,
italics _text _color : ` ${ getComputedStyle ( document . documentElement ) . getPropertyValue ( '--SmartThemeEmColor' ) . trim ( ) } ` ,
quote _text _color : ` ${ getComputedStyle ( document . documentElement ) . getPropertyValue ( '--SmartThemeQuoteColor' ) . trim ( ) } ` ,
blur _tint _color : ` ${ getComputedStyle ( document . documentElement ) . getPropertyValue ( '--SmartThemeBlurTintColor' ) . trim ( ) } ` ,
user _mes _blur _tint _color : ` ${ getComputedStyle ( document . documentElement ) . getPropertyValue ( '--SmartThemeUserMesBlurTintColor' ) . trim ( ) } ` ,
bot _mes _blur _tint _color : ` ${ getComputedStyle ( document . documentElement ) . getPropertyValue ( '--SmartThemeBotMesBlurTintColor' ) . trim ( ) } ` ,
shadow _color : ` ${ getComputedStyle ( document . documentElement ) . getPropertyValue ( '--SmartThemeShadowColor' ) . trim ( ) } ` ,
waifuMode : false ,
movingUI : false ,
movingUIState : { } ,
movingUIPreset : '' ,
noShadows : false ,
theme : 'Default (Dark) 1.7.1' ,
auto _swipe : false ,
auto _swipe _minimum _length : 0 ,
auto _swipe _blacklist : [ ] ,
auto _swipe _blacklist _threshold : 2 ,
auto _scroll _chat _to _bottom : true ,
auto _fix _generated _markdown : true ,
send _on _enter : send _on _enter _options . AUTO ,
console _log _prompts : false ,
render _formulas : false ,
allow _name1 _display : false ,
allow _name2 _display : false ,
//removeXML: false,
hotswap _enabled : true ,
timer _enabled : true ,
timestamps _enabled : true ,
mesIDDisplay _enabled : false ,
max _context _unlocked : false ,
prefer _character _prompt : true ,
prefer _character _jailbreak : true ,
continue _on _send : false ,
trim _spaces : true ,
instruct : {
enabled : false ,
wrap : true ,
names : false ,
system _prompt : "Below is an instruction that describes a task. Write a response that appropriately completes the request.\n\nWrite {{char}}'s next reply in a fictional roleplay chat between {{user}} and {{char}}. Write 1 reply only." ,
system _sequence : '' ,
stop _sequence : '' ,
input _sequence : '### Instruction:' ,
output _sequence : '### Response:' ,
preset : 'Alpaca' ,
separator _sequence : '' ,
macro : false ,
} ,
personas : { } ,
default _persona : null ,
persona _descriptions : { } ,
persona _description : '' ,
persona _description _position : persona _description _positions . BEFORE _CHAR ,
custom _stopping _strings : '' ,
} ;
let themes = [ ] ;
let movingUIPresets = [ ] ;
let instruct _presets = [ ] ;
const storage _keys = {
fast _ui _mode : "TavernAI_fast_ui_mode" ,
avatar _style : "TavernAI_avatar_style" ,
chat _display : "TavernAI_chat_display" ,
chat _width : "chat_width" ,
font _scale : "TavernAI_font_scale" ,
main _text _color : "TavernAI_main_text_color" ,
italics _text _color : "TavernAI_italics_text_color" ,
quote _text _color : "TavernAI_quote_text_color" ,
blur _tint _color : "TavernAI_blur_tint_color" ,
user _mes _blur _tint _color : "TavernAI_user_mes_blur_tint_color" ,
bot _mes _blur _tint _color : "TavernAI_bot_mes_blur_tint_color" ,
blur _strength : "TavernAI_blur_strength" ,
shadow _color : "TavernAI_shadow_color" ,
shadow _width : "TavernAI_shadow_width" ,
waifuMode : "TavernAI_waifuMode" ,
movingUI : "TavernAI_movingUI" ,
noShadows : "TavernAI_noShadows" ,
hotswap _enabled : 'HotswapEnabled' ,
timer _enabled : 'TimerEnabled' ,
timestamps _enabled : 'TimestampsEnabled' ,
mesIDDisplay _enabled : 'mesIDDisplayEnabled' ,
} ;
let browser _has _focus = true ;
function playMessageSound ( ) {
if ( ! power _user . play _message _sound ) {
return ;
}
if ( power _user . play _sound _unfocused && browser _has _focus ) {
return ;
}
const audio = document . getElementById ( 'audio_message_sound' ) ;
audio . volume = 0.8 ;
audio . pause ( ) ;
audio . currentTime = 0 ;
audio . play ( ) ;
}
function collapseNewlines ( x ) {
return x . replaceAll ( /\n+/g , "\n" ) ;
}
function fixMarkdown ( text ) {
// fix formatting problems in markdown
// e.g.:
// "^example * text*\n" -> "^example *text*\n"
// "^*example * text\n" -> "^*example* text\n"
// "^example *text *\n" -> "^example *text*\n"
// "^* example * text\n" -> "^*example* text\n"
// take note that the side you move the asterisk depends on where its pairing is
// i.e. both of the following strings have the same broken asterisk ' * ',
// but you move the first to the left and the second to the right, to match the non-broken asterisk "^example * text*\n" "^*example * text\n"
// and you HAVE to handle the cases where multiple pairs of asterisks exist in the same line
// i.e. "^example * text* * harder problem *\n" -> "^example *text* *harder problem*\n"
// Find pairs of formatting characters and capture the text in between them
const format = /(\*|_|~){1,2}([\s\S]*?)\1{1,2}/gm ;
let matches = [ ] ;
let match ;
while ( ( match = format . exec ( text ) ) !== null ) {
matches . push ( match ) ;
}
// Iterate through the matches and replace adjacent spaces immediately beside formatting characters
let newText = text ;
for ( let i = matches . length - 1 ; i >= 0 ; i -- ) {
let matchText = matches [ i ] [ 0 ] ;
let replacementText = matchText . replace ( /(\*|_|~)(\s+)|(\s+)(\*|_|~)/g , '$1$4' ) ;
newText = newText . slice ( 0 , matches [ i ] . index ) + replacementText + newText . slice ( matches [ i ] . index + matchText . length ) ;
}
return newText ;
}
function switchHotswap ( ) {
const value = localStorage . getItem ( storage _keys . hotswap _enabled ) ;
power _user . hotswap _enabled = value === null ? true : value == "true" ;
$ ( "body" ) . toggleClass ( "no-hotswap" , ! power _user . hotswap _enabled ) ;
$ ( "#hotswapEnabled" ) . prop ( "checked" , power _user . hotswap _enabled ) ;
}
function switchTimer ( ) {
const value = localStorage . getItem ( storage _keys . timer _enabled ) ;
power _user . timer _enabled = value === null ? true : value == "true" ;
$ ( "body" ) . toggleClass ( "no-timer" , ! power _user . timer _enabled ) ;
$ ( "#messageTimerEnabled" ) . prop ( "checked" , power _user . timer _enabled ) ;
}
function switchTimestamps ( ) {
const value = localStorage . getItem ( storage _keys . timestamps _enabled ) ;
power _user . timestamps _enabled = value === null ? true : value == "true" ;
$ ( "body" ) . toggleClass ( "no-timestamps" , ! power _user . timestamps _enabled ) ;
$ ( "#messageTimestampsEnabled" ) . prop ( "checked" , power _user . timestamps _enabled ) ;
}
function switchMesIDDisplay ( ) {
const value = localStorage . getItem ( storage _keys . mesIDDisplay _enabled ) ;
power _user . mesIDDisplay _enabled = value === null ? true : value == "true" ;
$ ( "body" ) . toggleClass ( "no-mesIDDisplay" , ! power _user . mesIDDisplay _enabled ) ;
$ ( "#MesIDDisplayEnabled" ) . prop ( "checked" , power _user . mesIDDisplay _enabled ) ;
}
function switchUiMode ( ) {
const fastUi = localStorage . getItem ( storage _keys . fast _ui _mode ) ;
power _user . fast _ui _mode = fastUi === null ? true : fastUi == "true" ;
$ ( "body" ) . toggleClass ( "no-blur" , power _user . fast _ui _mode ) ;
$ ( "#fast_ui_mode" ) . prop ( "checked" , power _user . fast _ui _mode ) ;
}
function toggleWaifu ( ) {
$ ( "#waifuMode" ) . trigger ( "click" ) ;
}
function switchWaifuMode ( ) {
$ ( "body" ) . toggleClass ( "waifuMode" , power _user . waifuMode ) ;
$ ( "#waifuMode" ) . prop ( "checked" , power _user . waifuMode ) ;
scrollChatToBottom ( ) ;
}
function switchSpoilerMode ( ) {
if ( power _user . spoiler _free _mode ) {
$ ( "#description_div" ) . hide ( ) ;
$ ( "#description_textarea" ) . hide ( ) ;
$ ( "#firstmessage_textarea" ) . hide ( ) ;
$ ( "#first_message_div" ) . hide ( ) ;
$ ( "#spoiler_free_desc" ) . show ( ) ;
}
else {
$ ( "#description_div" ) . show ( ) ;
$ ( "#description_textarea" ) . show ( ) ;
$ ( "#firstmessage_textarea" ) . show ( ) ;
$ ( "#first_message_div" ) . show ( ) ;
$ ( "#spoiler_free_desc" ) . hide ( ) ;
}
}
function peekSpoilerMode ( ) {
$ ( "#description_div" ) . toggle ( ) ;
$ ( "#description_textarea" ) . toggle ( ) ;
$ ( "#firstmessage_textarea" ) . toggle ( ) ;
$ ( "#first_message_div" ) . toggle ( ) ;
}
function switchMovingUI ( ) {
const movingUI = localStorage . getItem ( storage _keys . movingUI ) ;
power _user . movingUI = movingUI === null ? false : movingUI == "true" ;
$ ( "body" ) . toggleClass ( "movingUI" , power _user . movingUI ) ;
if ( power _user . movingUI === true ) {
initMovingUI ( )
if ( power _user . movingUIState ) {
loadMovingUIState ( ) ;
}
} ;
}
function noShadows ( ) {
const noShadows = localStorage . getItem ( storage _keys . noShadows ) ;
power _user . noShadows = noShadows === null ? false : noShadows == "true" ;
$ ( "body" ) . toggleClass ( "noShadows" , power _user . noShadows ) ;
$ ( "#noShadowsmode" ) . prop ( "checked" , power _user . noShadows ) ;
scrollChatToBottom ( ) ;
}
function applyAvatarStyle ( ) {
power _user . avatar _style = Number ( localStorage . getItem ( storage _keys . avatar _style ) ? ? avatar _styles . ROUND ) ;
$ ( "body" ) . toggleClass ( "big-avatars" , power _user . avatar _style === avatar _styles . RECTANGULAR ) ;
$ ( ` input[name="avatar_style"][value=" ${ power _user . avatar _style } "] ` ) . prop ( "checked" , true ) ;
}
function applyChatDisplay ( ) {
if ( ! power _user . chat _display === ( null || undefined ) ) {
console . debug ( 'applyChatDisplay: saw no chat display type defined' )
return
}
console . debug ( ` applyChatDisplay: applying ${ power _user . chat _display } ` )
$ ( ` #chat_display option[value= ${ power _user . chat _display } ] ` ) . attr ( "selected" , true )
switch ( power _user . chat _display ) {
case 0 : {
console . log ( 'applying default chat' )
$ ( "body" ) . removeClass ( "bubblechat" ) ;
$ ( "body" ) . removeClass ( "documentstyle" ) ;
break
}
case 1 : {
console . log ( 'applying bubblechat' )
$ ( "body" ) . addClass ( "bubblechat" ) ;
$ ( "body" ) . removeClass ( "documentstyle" ) ;
break
}
case 2 : {
console . log ( 'applying document style' )
$ ( "body" ) . removeClass ( "bubblechat" ) ;
$ ( "body" ) . addClass ( "documentstyle" ) ;
break
}
}
}
function applyChatWidth ( ) {
power _user . chat _width = Number ( localStorage . getItem ( storage _keys . chat _width ) ? ? 50 ) ;
let r = document . documentElement ;
r . style . setProperty ( '--sheldWidth' , ` ${ power _user . chat _width } vw ` ) ;
$ ( '#chat_width_slider' ) . val ( power _user . chat _width ) ;
}
async function applyThemeColor ( type ) {
if ( type === 'main' ) {
document . documentElement . style . setProperty ( '--SmartThemeBodyColor' , power _user . main _text _color ) ;
}
if ( type === 'italics' ) {
document . documentElement . style . setProperty ( '--SmartThemeEmColor' , power _user . italics _text _color ) ;
}
if ( type === 'quote' ) {
document . documentElement . style . setProperty ( '--SmartThemeQuoteColor' , power _user . quote _text _color ) ;
}
/ * i f ( t y p e = = = ' f a s t U I B G ' ) {
document . documentElement . style . setProperty ( '--SmartThemeFastUIBGColor' , power _user . fastui _bg _color ) ;
} * /
if ( type === 'blurTint' ) {
document . documentElement . style . setProperty ( '--SmartThemeBlurTintColor' , power _user . blur _tint _color ) ;
}
if ( type === 'userMesBlurTint' ) {
document . documentElement . style . setProperty ( '--SmartThemeUserMesBlurTintColor' , power _user . user _mes _blur _tint _color ) ;
}
if ( type === 'botMesBlurTint' ) {
document . documentElement . style . setProperty ( '--SmartThemeBotMesBlurTintColor' , power _user . bot _mes _blur _tint _color ) ;
}
if ( type === 'shadow' ) {
document . documentElement . style . setProperty ( '--SmartThemeShadowColor' , power _user . shadow _color ) ;
}
}
async function applyBlurStrength ( ) {
power _user . blur _strength = Number ( localStorage . getItem ( storage _keys . blur _strength ) ? ? 1 ) ;
document . documentElement . style . setProperty ( '--blurStrength' , power _user . blur _strength ) ;
$ ( "#blur_strength_counter" ) . text ( power _user . blur _strength ) ;
$ ( "#blur_strength" ) . val ( power _user . blur _strength ) ;
}
async function applyShadowWidth ( ) {
power _user . shadow _width = Number ( localStorage . getItem ( storage _keys . shadow _width ) ? ? 2 ) ;
document . documentElement . style . setProperty ( '--shadowWidth' , power _user . shadow _width ) ;
$ ( "#shadow_width_counter" ) . text ( power _user . shadow _width ) ;
$ ( "#shadow_width" ) . val ( power _user . shadow _width ) ;
}
async function applyFontScale ( ) {
power _user . font _scale = Number ( localStorage . getItem ( storage _keys . font _scale ) ? ? 1 ) ;
document . documentElement . style . setProperty ( '--fontScale' , power _user . font _scale ) ;
$ ( "#font_scale_counter" ) . text ( power _user . font _scale ) ;
$ ( "#font_scale" ) . val ( power _user . font _scale ) ;
}
async function applyTheme ( name ) {
const theme = themes . find ( x => x . name == name ) ;
if ( ! theme ) {
return ;
}
const themeProperties = [
{ key : 'main_text_color' , selector : '#main-text-color-picker' , type : 'main' } ,
{ key : 'italics_text_color' , selector : '#italics-color-picker' , type : 'italics' } ,
{ key : 'quote_text_color' , selector : '#quote-color-picker' , type : 'quote' } ,
{ key : 'blur_tint_color' , selector : '#blur-tint-color-picker' , type : 'blurTint' } ,
{ key : 'user_mes_blur_tint_color' , selector : '#user-mes-blur-tint-color-picker' , type : 'userMesBlurTint' } ,
{ key : 'bot_mes_blur_tint_color' , selector : '#bot-mes-blur-tint-color-picker' , type : 'botMesBlurTint' } ,
{ key : 'shadow_color' , selector : '#shadow-color-picker' , type : 'shadow' } ,
{
key : 'blur_strength' ,
action : async ( ) => {
localStorage . setItem ( storage _keys . blur _strength , power _user . blur _strength ) ;
await applyBlurStrength ( ) ;
}
} ,
{
key : 'shadow_width' ,
action : async ( ) => {
localStorage . setItem ( storage _keys . shadow _width , power _user . shadow _width ) ;
await applyShadowWidth ( ) ;
}
} ,
{
key : 'font_scale' ,
action : async ( ) => {
localStorage . setItem ( storage _keys . font _scale , power _user . font _scale ) ;
await applyFontScale ( ) ;
}
} ,
{
key : 'fast_ui_mode' ,
action : async ( ) => {
localStorage . setItem ( storage _keys . fast _ui _mode , power _user . fast _ui _mode ) ;
switchUiMode ( ) ;
}
} ,
{
key : 'waifuMode' ,
action : async ( ) => {
localStorage . setItem ( storage _keys . waifuMode , power _user . waifuMode ) ;
switchWaifuMode ( ) ;
}
} ,
{
key : 'chat_display' ,
action : async ( ) => {
localStorage . setItem ( storage _keys . chat _display , power _user . chat _display ) ;
applyChatDisplay ( ) ;
}
} ,
{
key : 'avatar_style' ,
action : async ( ) => {
localStorage . setItem ( storage _keys . avatar _style , power _user . avatar _style ) ;
applyAvatarStyle ( ) ;
}
} ,
{
key : 'noShadows' ,
action : async ( ) => {
localStorage . setItem ( storage _keys . noShadows , power _user . noShadows ) ;
noShadows ( ) ;
}
} ,
{
key : 'chat_width' ,
action : async ( ) => {
2023-07-22 17:09:50 +02:00
// If chat width is not set, set it to 50
if ( ! power _user . chat _width ) {
power _user . chat _width = 50 ;
}
2023-07-20 19:32:15 +02:00
localStorage . setItem ( storage _keys . chat _width , power _user . chat _width ) ;
applyChatWidth ( ) ;
}
} ,
{
key : 'timer_enabled' ,
action : async ( ) => {
localStorage . setItem ( storage _keys . timer _enabled , power _user . timer _enabled ) ;
switchTimer ( ) ;
}
} ,
{
key : 'timestamps_enabled' ,
action : async ( ) => {
localStorage . setItem ( storage _keys . timestamps _enabled , power _user . timestamps _enabled ) ;
switchTimestamps ( ) ;
}
} ,
{
key : 'mesIDDisplay_enabled' ,
action : async ( ) => {
localStorage . setItem ( storage _keys . mesIDDisplay _enabled , power _user . mesIDDisplay _enabled ) ;
switchMesIDDisplay ( ) ;
}
} ,
{
key : 'hotswap_enabled' ,
action : async ( ) => {
localStorage . setItem ( storage _keys . hotswap _enabled , power _user . hotswap _enabled ) ;
switchHotswap ( ) ;
}
}
] ;
for ( const { key , selector , type , action } of themeProperties ) {
if ( theme [ key ] !== undefined ) {
power _user [ key ] = theme [ key ] ;
if ( selector ) $ ( selector ) . attr ( 'color' , power _user [ key ] ) ;
if ( type ) await applyThemeColor ( type ) ;
if ( action ) await action ( ) ;
} else {
if ( selector ) { $ ( selector ) . attr ( 'color' , 'rgba(0,0,0,0)' ) } ;
console . debug ( ` Empty theme key: ${ key } ` ) ;
power _user [ key ] = '' ;
}
}
console . log ( 'theme applied: ' + name ) ;
}
async function applyMovingUIPreset ( name ) {
resetMovablePanels ( 'quiet' )
const movingUIPreset = movingUIPresets . find ( x => x . name == name ) ;
if ( ! movingUIPreset ) {
return ;
}
power _user . movingUIState = movingUIPreset . movingUIState ;
console . log ( 'MovingUI Preset applied: ' + name ) ;
loadMovingUIState ( )
}
switchUiMode ( ) ;
applyFontScale ( ) ;
applyThemeColor ( ) ;
applyChatWidth ( ) ;
applyAvatarStyle ( ) ;
applyBlurStrength ( ) ;
applyShadowWidth ( ) ;
switchMovingUI ( ) ;
noShadows ( ) ;
switchHotswap ( ) ;
switchTimer ( ) ;
switchTimestamps ( ) ;
switchMesIDDisplay ( ) ;
function loadPowerUserSettings ( settings , data ) {
// Load from settings.json
if ( settings . power _user !== undefined ) {
Object . assign ( power _user , settings . power _user ) ;
}
if ( data . themes !== undefined ) {
themes = data . themes ;
}
if ( data . movingUIPresets !== undefined ) {
movingUIPresets = data . movingUIPresets ;
}
if ( data . instruct !== undefined ) {
instruct _presets = data . instruct ;
}
// These are still local storage
const fastUi = localStorage . getItem ( storage _keys . fast _ui _mode ) ;
const movingUI = localStorage . getItem ( storage _keys . movingUI ) ;
const noShadows = localStorage . getItem ( storage _keys . noShadows ) ;
const hotswap = localStorage . getItem ( storage _keys . hotswap _enabled ) ;
const timer = localStorage . getItem ( storage _keys . timer _enabled ) ;
const timestamps = localStorage . getItem ( storage _keys . timestamps _enabled ) ;
const mesIDDisplay = localStorage . getItem ( storage _keys . mesIDDisplay _enabled ) ;
power _user . fast _ui _mode = fastUi === null ? true : fastUi == "true" ;
power _user . movingUI = movingUI === null ? false : movingUI == "true" ;
power _user . noShadows = noShadows === null ? false : noShadows == "true" ;
power _user . hotswap _enabled = hotswap === null ? true : hotswap == "true" ;
power _user . timer _enabled = timer === null ? true : timer == "true" ;
power _user . timestamps _enabled = timestamps === null ? true : timestamps == "true" ;
power _user . mesIDDisplay _enabled = mesIDDisplay === null ? true : mesIDDisplay == "true" ;
power _user . avatar _style = Number ( localStorage . getItem ( storage _keys . avatar _style ) ? ? avatar _styles . ROUND ) ;
//power_user.chat_display = Number(localStorage.getItem(storage_keys.chat_display) ?? chat_styles.DEFAULT);
power _user . chat _width = Number ( localStorage . getItem ( storage _keys . chat _width ) ? ? 50 ) ;
power _user . font _scale = Number ( localStorage . getItem ( storage _keys . font _scale ) ? ? 1 ) ;
power _user . blur _strength = Number ( localStorage . getItem ( storage _keys . blur _strength ) ? ? 10 ) ;
if ( power _user . chat _display === '' ) {
power _user . chat _display = chat _styles . DEFAULT ;
}
if ( power _user . waifuMode === '' ) {
power _user . waifuMode = false ;
}
2023-07-22 17:09:50 +02:00
if ( power _user . chat _width === '' ) {
power _user . chat _width = 50 ;
}
2023-07-20 19:32:15 +02:00
$ ( '#trim_spaces' ) . prop ( "checked" , power _user . trim _spaces ) ;
$ ( '#continue_on_send' ) . prop ( "checked" , power _user . continue _on _send ) ;
$ ( '#auto_swipe' ) . prop ( "checked" , power _user . auto _swipe ) ;
$ ( '#auto_swipe_minimum_length' ) . val ( power _user . auto _swipe _minimum _length ) ;
$ ( '#auto_swipe_blacklist' ) . val ( power _user . auto _swipe _blacklist . join ( ", " ) ) ;
$ ( '#auto_swipe_blacklist_threshold' ) . val ( power _user . auto _swipe _blacklist _threshold ) ;
$ ( '#custom_stopping_strings' ) . val ( power _user . custom _stopping _strings ) ;
$ ( "#console_log_prompts" ) . prop ( "checked" , power _user . console _log _prompts ) ;
$ ( '#auto_fix_generated_markdown' ) . prop ( "checked" , power _user . auto _fix _generated _markdown ) ;
$ ( '#auto_scroll_chat_to_bottom' ) . prop ( "checked" , power _user . auto _scroll _chat _to _bottom ) ;
$ ( ` #tokenizer option[value=" ${ power _user . tokenizer } "] ` ) . attr ( 'selected' , true ) ;
$ ( ` #pygmalion_formatting option[value= ${ power _user . pygmalion _formatting } ] ` ) . attr ( "selected" , true ) ;
$ ( ` #send_on_enter option[value= ${ power _user . send _on _enter } ] ` ) . attr ( "selected" , true ) ;
$ ( "#import_card_tags" ) . prop ( "checked" , power _user . import _card _tags ) ;
$ ( "#confirm_message_delete" ) . prop ( "checked" , power _user . confirm _message _delete !== undefined ? ! ! power _user . confirm _message _delete : true ) ;
$ ( "#spoiler_free_mode" ) . prop ( "checked" , power _user . spoiler _free _mode ) ;
$ ( "#collapse-newlines-checkbox" ) . prop ( "checked" , power _user . collapse _newlines ) ;
$ ( "#pin-examples-checkbox" ) . prop ( "checked" , power _user . pin _examples ) ;
$ ( "#disable-description-formatting-checkbox" ) . prop ( "checked" , power _user . disable _description _formatting ) ;
$ ( "#disable-scenario-formatting-checkbox" ) . prop ( "checked" , power _user . disable _scenario _formatting ) ;
$ ( "#disable-personality-formatting-checkbox" ) . prop ( "checked" , power _user . disable _personality _formatting ) ;
$ ( "#always-force-name2-checkbox" ) . prop ( "checked" , power _user . always _force _name2 ) ;
$ ( "#disable-examples-formatting-checkbox" ) . prop ( "checked" , power _user . disable _examples _formatting ) ;
$ ( '#disable-start-formatting-checkbox' ) . prop ( "checked" , power _user . disable _start _formatting ) ;
$ ( "#trim_sentences_checkbox" ) . prop ( "checked" , power _user . trim _sentences ) ;
$ ( "#include_newline_checkbox" ) . prop ( "checked" , power _user . include _newline ) ;
$ ( '#render_formulas' ) . prop ( "checked" , power _user . render _formulas ) ;
$ ( "#custom_chat_separator" ) . val ( power _user . custom _chat _separator ) ;
$ ( "#markdown_escape_strings" ) . val ( power _user . markdown _escape _strings ) ;
$ ( "#fast_ui_mode" ) . prop ( "checked" , power _user . fast _ui _mode ) ;
$ ( "#waifuMode" ) . prop ( "checked" , power _user . waifuMode ) ;
$ ( "#movingUImode" ) . prop ( "checked" , power _user . movingUI ) ;
$ ( "#noShadowsmode" ) . prop ( "checked" , power _user . noShadows ) ;
$ ( "#start_reply_with" ) . val ( power _user . user _prompt _bias ) ;
$ ( "#chat-show-reply-prefix-checkbox" ) . prop ( "checked" , power _user . show _user _prompt _bias ) ;
$ ( "#multigen" ) . prop ( "checked" , power _user . multigen ) ;
$ ( "#multigen_first_chunk" ) . val ( power _user . multigen _first _chunk ) ;
$ ( "#multigen_next_chunks" ) . val ( power _user . multigen _next _chunks ) ;
$ ( "#play_message_sound" ) . prop ( "checked" , power _user . play _message _sound ) ;
$ ( "#play_sound_unfocused" ) . prop ( "checked" , power _user . play _sound _unfocused ) ;
$ ( "#never_resize_avatars" ) . prop ( "checked" , power _user . never _resize _avatars ) ;
$ ( "#show_card_avatar_urls" ) . prop ( "checked" , power _user . show _card _avatar _urls ) ;
$ ( "#auto_save_msg_edits" ) . prop ( "checked" , power _user . auto _save _msg _edits ) ;
$ ( "#allow_name1_display" ) . prop ( "checked" , power _user . allow _name1 _display ) ;
$ ( "#allow_name2_display" ) . prop ( "checked" , power _user . allow _name2 _display ) ;
//$("#removeXML").prop("checked", power_user.removeXML);
$ ( "#hotswapEnabled" ) . prop ( "checked" , power _user . hotswap _enabled ) ;
$ ( "#messageTimerEnabled" ) . prop ( "checked" , power _user . timer _enabled ) ;
$ ( "#messageTimestampsEnabled" ) . prop ( "checked" , power _user . timestamps _enabled ) ;
$ ( "#mesIDDisplayEnabled" ) . prop ( "checked" , power _user . mesIDDisplay _enabled ) ;
$ ( "#prefer_character_prompt" ) . prop ( "checked" , power _user . prefer _character _prompt ) ;
$ ( "#prefer_character_jailbreak" ) . prop ( "checked" , power _user . prefer _character _jailbreak ) ;
$ ( ` input[name="avatar_style"][value=" ${ power _user . avatar _style } "] ` ) . prop ( "checked" , true ) ;
$ ( ` #chat_display option[value= ${ power _user . chat _display } ] ` ) . attr ( "selected" , true ) . trigger ( 'change' ) ;
$ ( '#chat_width_slider' ) . val ( power _user . chat _width ) ;
$ ( "#token_padding" ) . val ( power _user . token _padding ) ;
$ ( "#font_scale" ) . val ( power _user . font _scale ) ;
$ ( "#font_scale_counter" ) . text ( power _user . font _scale ) ;
$ ( "#blur_strength" ) . val ( power _user . blur _strength ) ;
$ ( "#blur_strength_counter" ) . text ( power _user . blur _strength ) ;
$ ( "#shadow_width" ) . val ( power _user . shadow _width ) ;
$ ( "#shadow_width_counter" ) . text ( power _user . shadow _width ) ;
$ ( "#main-text-color-picker" ) . attr ( 'color' , power _user . main _text _color ) ;
$ ( "#italics-color-picker" ) . attr ( 'color' , power _user . italics _text _color ) ;
$ ( "#quote-color-picker" ) . attr ( 'color' , power _user . quote _text _color ) ;
//$("#fastui-bg-color-picker").attr('color', power_user.fastui_bg_color);
$ ( "#blur-tint-color-picker" ) . attr ( 'color' , power _user . blur _tint _color ) ;
$ ( "#user-mes-blur-tint-color-picker" ) . attr ( 'color' , power _user . user _mes _blur _tint _color ) ;
$ ( "#bot-mes-blur-tint-color-picker" ) . attr ( 'color' , power _user . bot _mes _blur _tint _color ) ;
$ ( "#shadow-color-picker" ) . attr ( 'color' , power _user . shadow _color ) ;
for ( const theme of themes ) {
const option = document . createElement ( 'option' ) ;
option . value = theme . name ;
option . innerText = theme . name ;
option . selected = theme . name == power _user . theme ;
$ ( "#themes" ) . append ( option ) ;
}
for ( const movingUIPreset of movingUIPresets ) {
const option = document . createElement ( 'option' ) ;
option . value = movingUIPreset . name ;
option . innerText = movingUIPreset . name ;
option . selected = movingUIPreset . name == power _user . movingUIPreset ;
$ ( "#movingUIPresets" ) . append ( option ) ;
}
$ ( ` #character_sort_order option[data-order=" ${ power _user . sort _order } "][data-field=" ${ power _user . sort _field } "] ` ) . prop ( "selected" , true ) ;
sortCharactersList ( ) ;
reloadMarkdownProcessor ( power _user . render _formulas ) ;
loadInstructMode ( ) ;
loadMaxContextUnlocked ( ) ;
switchWaifuMode ( ) ;
switchSpoilerMode ( ) ;
loadMovingUIState ( ) ;
loadCharListState ( ) ;
}
async function loadCharListState ( ) {
if ( document . getElementById ( 'CharID0' ) !== null ) {
console . debug ( 'setting charlist state to...' )
if ( power _user . charListGrid === true ) {
console . debug ( '..to grid' )
$ ( "#charListGridToggle" ) . trigger ( 'click' )
} else { console . debug ( '..to list' ) }
} else {
console . debug ( 'charlist not ready yet' )
await delay ( 100 )
loadCharListState ( ) ;
}
}
function loadMovingUIState ( ) {
if ( isMobile ( ) === false
&& power _user . movingUIState
&& power _user . movingUI === true ) {
console . debug ( 'loading movingUI state' )
for ( var elmntName of Object . keys ( power _user . movingUIState ) ) {
var elmntState = power _user . movingUIState [ elmntName ] ;
try {
var elmnt = $ ( '#' + $ . escapeSelector ( elmntName ) ) ;
if ( elmnt . length ) {
console . debug ( ` loading state for ${ elmntName } ` )
elmnt . css ( elmntState ) ;
} else {
console . debug ( ` skipping ${ elmntName } because it doesn't exist in the DOM ` )
}
} catch ( err ) {
console . debug ( ` error occurred while processing ${ elmntName } : ${ err } ` )
}
}
} else {
console . debug ( 'skipping movingUI state load' )
return
}
}
function loadMaxContextUnlocked ( ) {
$ ( '#max_context_unlocked' ) . prop ( 'checked' , power _user . max _context _unlocked ) ;
$ ( '#max_context_unlocked' ) . on ( 'change' , function ( ) {
power _user . max _context _unlocked = ! ! $ ( this ) . prop ( 'checked' ) ;
switchMaxContextSize ( ) ;
saveSettingsDebounced ( ) ;
} ) ;
switchMaxContextSize ( ) ;
}
function switchMaxContextSize ( ) {
const element = $ ( '#max_context' ) ;
const maxValue = power _user . max _context _unlocked ? MAX _CONTEXT _UNLOCKED : MAX _CONTEXT _DEFAULT ;
element . attr ( 'max' , maxValue ) ;
const value = Number ( element . val ( ) ) ;
if ( value >= maxValue ) {
element . val ( maxValue ) . trigger ( 'input' ) ;
}
}
function loadInstructMode ( ) {
const controls = [
{ id : "instruct_enabled" , property : "enabled" , isCheckbox : true } ,
{ id : "instruct_wrap" , property : "wrap" , isCheckbox : true } ,
{ id : "instruct_system_prompt" , property : "system_prompt" , isCheckbox : false } ,
{ id : "instruct_system_sequence" , property : "system_sequence" , isCheckbox : false } ,
{ id : "instruct_separator_sequence" , property : "separator_sequence" , isCheckbox : false } ,
{ id : "instruct_input_sequence" , property : "input_sequence" , isCheckbox : false } ,
{ id : "instruct_output_sequence" , property : "output_sequence" , isCheckbox : false } ,
{ id : "instruct_stop_sequence" , property : "stop_sequence" , isCheckbox : false } ,
{ id : "instruct_names" , property : "names" , isCheckbox : true } ,
{ id : "instruct_macro" , property : "macro" , isCheckbox : true } ,
] ;
controls . forEach ( control => {
const $element = $ ( ` # ${ control . id } ` ) ;
if ( control . isCheckbox ) {
$element . prop ( 'checked' , power _user . instruct [ control . property ] ) ;
} else {
$element . val ( power _user . instruct [ control . property ] ) ;
}
$element . on ( 'input' , function ( ) {
power _user . instruct [ control . property ] = control . isCheckbox ? $ ( this ) . prop ( 'checked' ) : $ ( this ) . val ( ) ;
saveSettingsDebounced ( ) ;
} ) ;
} ) ;
instruct _presets . forEach ( ( preset ) => {
const name = preset . name ;
const option = document . createElement ( 'option' ) ;
option . value = name ;
option . innerText = name ;
option . selected = name === power _user . instruct . preset ;
$ ( '#instruct_presets' ) . append ( option ) ;
} ) ;
$ ( '#instruct_presets' ) . on ( 'change' , function ( ) {
const name = $ ( this ) . find ( ':selected' ) . val ( ) ;
const preset = instruct _presets . find ( x => x . name === name ) ;
if ( ! preset ) {
return ;
}
power _user . instruct . preset = name ;
controls . forEach ( control => {
if ( preset [ control . property ] !== undefined ) {
power _user . instruct [ control . property ] = preset [ control . property ] ;
const $element = $ ( ` # ${ control . id } ` ) ;
if ( control . isCheckbox ) {
$element . prop ( 'checked' , power _user . instruct [ control . property ] ) . trigger ( 'input' ) ;
} else {
$element . val ( power _user . instruct [ control . property ] ) . trigger ( 'input' ) ;
}
}
} ) ;
} ) ;
}
export function formatInstructModeChat ( name , mes , isUser , isNarrator , forceAvatar , name1 , name2 ) {
const includeNames = isNarrator ? false : ( power _user . instruct . names || ! ! selected _group || ! ! forceAvatar ) ;
let sequence = ( isUser || isNarrator ) ? power _user . instruct . input _sequence : power _user . instruct . output _sequence ;
if ( power _user . instruct . macro ) {
sequence = substituteParams ( sequence , name1 , name2 ) ;
}
const separator = power _user . instruct . wrap ? '\n' : '' ;
const separatorSequence = power _user . instruct . separator _sequence && ! isUser
? power _user . instruct . separator _sequence
: ( power _user . instruct . wrap ? '\n' : '' ) ;
const textArray = includeNames ? [ sequence , ` ${ name } : ${ mes } ` , separatorSequence ] : [ sequence , mes , separatorSequence ] ;
const text = textArray . filter ( x => x ) . join ( separator ) ;
return text ;
}
export function formatInstructStoryString ( story , systemPrompt ) {
// If the character has a custom system prompt AND user has it preferred, use that instead of the default
systemPrompt = power _user . prefer _character _prompt && systemPrompt ? systemPrompt : power _user . instruct . system _prompt ;
const sequence = power _user . instruct . system _sequence || '' ;
const prompt = substituteParams ( systemPrompt , name1 , name2 , power _user . instruct . system _prompt ) || '' ;
const separator = power _user . instruct . wrap ? '\n' : '' ;
const textArray = [ sequence , prompt + '\n' + story ] ;
const text = textArray . filter ( x => x ) . join ( separator ) ;
return text ;
}
export function formatInstructModePrompt ( name , isImpersonate , promptBias , name1 , name2 ) {
const includeNames = power _user . instruct . names || ! ! selected _group ;
let sequence = isImpersonate ? power _user . instruct . input _sequence : power _user . instruct . output _sequence ;
if ( power _user . instruct . macro ) {
sequence = substituteParams ( sequence , name1 , name2 ) ;
}
const separator = power _user . instruct . wrap ? '\n' : '' ;
let text = includeNames ? ( separator + sequence + separator + ` ${ name } : ` ) : ( separator + sequence ) ;
if ( ! isImpersonate && promptBias ) {
text += ( includeNames ? promptBias : ( separator + promptBias ) ) ;
}
return text . trimEnd ( ) ;
}
const sortFunc = ( a , b ) => power _user . sort _order == 'asc' ? compareFunc ( a , b ) : compareFunc ( b , a ) ;
const compareFunc = ( first , second ) => {
if ( power _user . sort _order == 'random' ) {
return Math . random ( ) > 0.5 ? 1 : - 1 ;
}
switch ( power _user . sort _rule ) {
case 'boolean' :
const a = first [ power _user . sort _field ] ;
const b = second [ power _user . sort _field ] ;
if ( a === true || a === 'true' ) return 1 ; // Prioritize 'true' or true
if ( b === true || b === 'true' ) return - 1 ; // Prioritize 'true' or true
if ( a && ! b ) return - 1 ; // Move truthy values to the end
if ( ! a && b ) return 1 ; // Move falsy values to the beginning
if ( a === b ) return 0 ; // Sort equal values normally
return a < b ? - 1 : 1 ; // Sort non-boolean values normally
default :
return typeof first [ power _user . sort _field ] == "string"
? first [ power _user . sort _field ] . localeCompare ( second [ power _user . sort _field ] )
: first [ power _user . sort _field ] - second [ power _user . sort _field ] ;
}
} ;
function sortCharactersList ( ) {
const arr1 = groups . map ( x => ( {
item : x ,
id : x . id ,
selector : '.group_select' ,
attribute : 'grid' ,
} ) )
const arr2 = characters . map ( ( x , index ) => ( {
item : x ,
id : index ,
selector : '.character_select' ,
attribute : 'chid' ,
} ) ) ;
const array = [ ... arr1 , ... arr2 ] ;
if ( power _user . sort _field == undefined || array . length === 0 ) {
return ;
}
let orderedList = array . slice ( ) . sort ( ( a , b ) => sortFunc ( a . item , b . item ) ) ;
for ( const item of array ) {
$ ( ` ${ item . selector } [ ${ item . attribute } =" ${ item . id } "] ` ) . css ( { 'order' : orderedList . indexOf ( item ) } ) ;
}
updateVisibleDivs ( '#rm_print_characters_block' , true ) ;
}
function sortGroupMembers ( selector ) {
if ( power _user . sort _field == undefined || characters . length === 0 ) {
return ;
}
let orderedList = characters . slice ( ) . sort ( sortFunc ) ;
for ( let i = 0 ; i < characters . length ; i ++ ) {
$ ( ` ${ selector } [chid=" ${ i } "] ` ) . css ( { 'order' : orderedList . indexOf ( characters [ i ] ) } ) ;
}
}
async function saveTheme ( ) {
const name = await callPopup ( 'Enter a theme preset name:' , 'input' ) ;
if ( ! name ) {
return ;
}
const theme = {
name ,
blur _strength : power _user . blur _strength ,
main _text _color : power _user . main _text _color ,
italics _text _color : power _user . italics _text _color ,
quote _text _color : power _user . quote _text _color ,
//fastui_bg_color: power_user.fastui_bg_color,
blur _tint _color : power _user . blur _tint _color ,
user _mes _blur _tint _color : power _user . user _mes _blur _tint _color ,
bot _mes _blur _tint _color : power _user . bot _mes _blur _tint _color ,
shadow _color : power _user . shadow _color ,
shadow _width : power _user . shadow _width ,
font _scale : power _user . font _scale ,
fast _ui _mode : power _user . fast _ui _mode ,
waifuMode : power _user . waifuMode ,
avatar _style : power _user . avatar _style ,
chat _display : power _user . chat _display ,
noShadows : power _user . noShadows ,
chat _width : power _user . chat _width ,
timer _enabled : power _user . timer _enabled ,
timestamps _enabled : power _user . timestamps _enabled ,
mesIDDisplay _enabled : power _user . mesIDDisplay _enabled ,
hotswap _enabled : power _user . hotswap _enabled ,
} ;
const response = await fetch ( '/savetheme' , {
method : 'POST' ,
headers : getRequestHeaders ( ) ,
body : JSON . stringify ( theme )
} ) ;
if ( response . ok ) {
const themeIndex = themes . findIndex ( x => x . name == name ) ;
if ( themeIndex == - 1 ) {
themes . push ( theme ) ;
const option = document . createElement ( 'option' ) ;
option . selected = true ;
option . value = name ;
option . innerText = name ;
$ ( '#themes' ) . append ( option ) ;
}
else {
themes [ themeIndex ] = theme ;
$ ( ` #themes option[value=" ${ name } "] ` ) . attr ( 'selected' , true ) ;
}
power _user . theme = name ;
saveSettingsDebounced ( ) ;
}
}
async function saveMovingUI ( ) {
const name = await callPopup ( 'Enter a name for the MovingUI Preset:' , 'input' ) ;
if ( ! name ) {
return ;
}
const movingUIPreset = {
name ,
movingUIState : power _user . movingUIState
}
console . log ( movingUIPreset )
const response = await fetch ( '/savemovingui' , {
method : 'POST' ,
headers : getRequestHeaders ( ) ,
body : JSON . stringify ( movingUIPreset )
} ) ;
if ( response . ok ) {
const movingUIPresetIndex = movingUIPresets . findIndex ( x => x . name == name ) ;
if ( movingUIPresetIndex == - 1 ) {
movingUIPresets . push ( movingUIPreset ) ;
const option = document . createElement ( 'option' ) ;
option . selected = true ;
option . value = name ;
option . innerText = name ;
$ ( '#movingUIPresets' ) . append ( option ) ;
}
else {
movingUIPresets [ movingUIPresetIndex ] = movingUIPreset ;
$ ( ` #movingUIPresets option[value=" ${ name } "] ` ) . attr ( 'selected' , true ) ;
}
power _user . movingUIPreset = name ;
saveSettingsDebounced ( ) ;
} else {
toastr . warning ( 'failed to save MovingUI state.' )
}
}
async function resetMovablePanels ( type ) {
const panelIds = [
'sheld' ,
'left-nav-panel' ,
'right-nav-panel' ,
'WorldInfo' ,
'floatingPrompt' ,
'expression-holder' ,
'groupMemberListPopout'
] ;
const panelStyles = [ 'top' , 'left' , 'right' , 'bottom' , 'height' , 'width' , 'margin' , ] ;
panelIds . forEach ( ( id ) => {
const panel = document . getElementById ( id ) ;
if ( panel ) {
$ ( panel ) . addClass ( 'resizing' ) ;
panelStyles . forEach ( ( style ) => {
panel . style [ style ] = '' ;
} ) ;
}
} ) ;
const zoomedAvatars = document . querySelectorAll ( '.zoomed_avatar' ) ;
if ( zoomedAvatars . length > 0 ) {
zoomedAvatars . forEach ( ( avatar ) => {
avatar . classList . add ( 'resizing' ) ;
panelStyles . forEach ( ( style ) => {
avatar . style [ style ] = '' ;
} ) ;
} ) ;
}
$ ( '[data-dragged="true"]' ) . removeAttr ( 'data-dragged' ) ;
await delay ( 50 )
power _user . movingUIState = { } ;
//if user manually resets panels, deselect the current preset
if ( type !== 'quiet' && type !== 'resize' ) {
power _user . movingUIPreset = 'Default'
$ ( ` #movingUIPresets option[value="Default"] ` ) . prop ( 'selected' , true ) ;
}
saveSettingsDebounced ( ) ;
eventSource . emit ( event _types . MOVABLE _PANELS _RESET ) ;
eventSource . once ( event _types . SETTINGS _UPDATED , ( ) => {
$ ( ".resizing" ) . removeClass ( 'resizing' ) ;
//if happening as part of preset application, do it quietly.
if ( type === 'quiet' ) {
return
2023-07-22 17:09:50 +02:00
//if happening due to resize, tell user.
2023-07-20 19:32:15 +02:00
} else if ( type === 'resize' ) {
toastr . warning ( 'Panel positions reset due to zoom/resize' ) ;
2023-07-22 17:09:50 +02:00
//if happening due to manual button press
2023-07-20 19:32:15 +02:00
} else {
toastr . success ( 'Panel positions reset' ) ;
}
} ) ;
}
function doNewChat ( ) {
setTimeout ( ( ) => {
$ ( "#option_start_new_chat" ) . trigger ( 'click' ) ;
} , 1 ) ;
//$("#dialogue_popup").hide();
setTimeout ( ( ) => {
$ ( "#dialogue_popup_ok" ) . trigger ( 'click' ) ;
} , 1 ) ;
}
function doRandomChat ( ) {
resetSelectedGroup ( ) ;
2023-07-24 16:22:51 +02:00
setCharacterId ( Math . floor ( Math . random ( ) * characters . length ) . toString ( ) ) ;
2023-07-20 19:32:15 +02:00
setTimeout ( ( ) => {
reloadCurrentChat ( ) ;
} , 1 ) ;
}
async function doMesCut ( _ , text ) {
console . debug ( ` was asked to cut message id # ${ text } ` )
//reject invalid args or no args
if ( text && isNaN ( text ) || ! text ) {
toastr . error ( ` Must enter a single number only, non-number characters disallowed. ` )
return
}
//reject attempts to delete firstmes
if ( text === '0' ) {
toastr . error ( 'Cannot delete the First Message' )
return
}
let mesIDToCut = Number ( text ) . toFixed ( 0 )
let mesToCut = $ ( "#chat" ) . find ( ` .mes[mesid= ${ mesIDToCut } ] ` )
if ( ! mesToCut . length ) {
toastr . error ( ` Could not find message with ID: ${ mesIDToCut } ` )
return
}
setEditedMessageId ( mesIDToCut ) ;
mesToCut . find ( '.mes_edit_delete' ) . trigger ( 'click' , { fromSlashCommand : true } ) ;
}
async function doDelMode ( _ , text ) {
//first enter delmode
$ ( "#option_delete_mes" ) . trigger ( 'click' )
//reject invalid args
if ( text && isNaN ( text ) ) {
toastr . warning ( 'Must enter a number or nothing.' )
await delay ( 300 ) //unsure why 300 is neccessary here, but any shorter and it wont see the delmode UI
$ ( "#dialogue_del_mes_cancel" ) . trigger ( 'click' ) ;
return
}
//parse valid args
if ( text ) {
await delay ( 300 ) //same as above, need event signal for 'entered del mode'
console . debug ( 'parsing msgs to del' )
let numMesToDel = Number ( text ) . toFixed ( 0 )
let lastMesID = $ ( '.last_mes' ) . attr ( 'mesid' )
let oldestMesIDToDel = lastMesID - numMesToDel + 1 ;
//disallow targeting first message
if ( oldestMesIDToDel <= 0 ) {
oldestMesIDToDel = 1
}
let oldestMesToDel = $ ( '#chat' ) . find ( ` .mes[mesid= ${ oldestMesIDToDel } ] ` )
let oldestDelMesCheckbox = $ ( oldestMesToDel ) . find ( '.del_checkbox' ) ;
let newLastMesID = oldestMesIDToDel - 1 ;
console . debug ( ` DelMesReport -- numMesToDel: ${ numMesToDel } , lastMesID: ${ lastMesID } , oldestMesIDToDel: ${ oldestMesIDToDel } , newLastMesID: ${ newLastMesID } ` )
oldestDelMesCheckbox . trigger ( 'click' ) ;
let trueNumberOfDeletedMessage = lastMesID - oldestMesIDToDel + 1
//await delay(1)
$ ( '#dialogue_del_mes_ok' ) . trigger ( 'click' ) ;
toastr . success ( ` Deleted ${ trueNumberOfDeletedMessage } messages. ` )
return
}
}
function doResetPanels ( ) {
$ ( "#movingUIreset" ) . trigger ( 'click' ) ;
}
function setAvgBG ( ) {
const bgimg = new Image ( ) ;
bgimg . src = $ ( '#bg1' )
. css ( 'background-image' )
. replace ( /^url\(['"]?/ , '' )
. replace ( /['"]?\)$/ , '' ) ;
/ * c o n s t c h a r A v a t a r = n e w I m a g e ( )
charAvatar . src = $ ( "#avatar_load_preview" )
. attr ( 'src' )
. replace ( /^url\(['"]?/ , '' )
. replace ( /['"]?\)$/ , '' ) ;
const userAvatar = new Image ( )
userAvatar . src = $ ( "#user_avatar_block .avatar.selected img" )
. attr ( 'src' )
. replace ( /^url\(['"]?/ , '' )
. replace ( /['"]?\)$/ , '' ) ; * /
bgimg . onload = function ( ) {
var rgb = getAverageRGB ( bgimg ) ;
//console.log(`average color of the bg is:`)
//console.log(rgb);
$ ( "#blur-tint-color-picker" ) . attr ( 'color' , 'rgb(' + rgb . r + ',' + rgb . g + ',' + rgb . b + ')' ) ;
const backgroundColorString = $ ( "#blur-tint-color-picker" ) . attr ( 'color' )
. replace ( 'rgba' , '' )
. replace ( 'rgb' , '' )
. replace ( '(' , '[' )
. replace ( ')' , ']' ) ; //[50, 120, 200, 1]; // Example background color
const backgroundColorArray = JSON . parse ( backgroundColorString ) //[200, 200, 200, 1]
console . log ( backgroundColorArray )
$ ( "#main-text-color-picker" ) . attr ( 'color' , getReadableTextColor ( backgroundColorArray ) ) ;
console . log ( $ ( "#main-text-color-picker" ) . attr ( 'color' ) ) ; // Output: 'rgba(0, 47, 126, 1)'
}
/ * c h a r A v a t a r . o n l o a d = f u n c t i o n ( ) {
var rgb = getAverageRGB ( charAvatar ) ;
//console.log(`average color of the AI avatar is:`);
//console.log(rgb);
$ ( "#bot-mes-blur-tint-color-picker" ) . attr ( 'color' , 'rgb(' + rgb . r + ',' + rgb . g + ',' + rgb . b + ')' ) ;
}
userAvatar . onload = function ( ) {
var rgb = getAverageRGB ( userAvatar ) ;
//console.log(`average color of the user avatar is:`);
//console.log(rgb);
$ ( "#user-mes-blur-tint-color-picker" ) . attr ( 'color' , 'rgb(' + rgb . r + ',' + rgb . g + ',' + rgb . b + ')' ) ;
} * /
function getAverageRGB ( imgEl ) {
var blockSize = 5 , // only visit every 5 pixels
defaultRGB = { r : 0 , g : 0 , b : 0 } , // for non-supporting envs
canvas = document . createElement ( 'canvas' ) ,
context = canvas . getContext && canvas . getContext ( '2d' ) ,
data , width , height ,
i = - 4 ,
length ,
rgb = { r : 0 , g : 0 , b : 0 } ,
count = 0 ;
if ( ! context ) {
return defaultRGB ;
}
height = canvas . height = imgEl . naturalHeight || imgEl . offsetHeight || imgEl . height ;
width = canvas . width = imgEl . naturalWidth || imgEl . offsetWidth || imgEl . width ;
context . drawImage ( imgEl , 0 , 0 ) ;
try {
data = context . getImageData ( 0 , 0 , width , height ) ;
} catch ( e ) {
/* security error, img on diff domain */ alert ( 'x' ) ;
return defaultRGB ;
}
length = data . data . length ;
while ( ( i += blockSize * 4 ) < length ) {
++ count ;
rgb . r += data . data [ i ] ;
rgb . g += data . data [ i + 1 ] ;
rgb . b += data . data [ i + 2 ] ;
}
// ~~ used to floor values
rgb . r = ~ ~ ( rgb . r / count ) ;
rgb . g = ~ ~ ( rgb . g / count ) ;
rgb . b = ~ ~ ( rgb . b / count ) ;
return rgb ;
}
function hslToRgb ( h , s , l ) {
const hueToRgb = ( p , q , t ) => {
if ( t < 0 ) t += 1 ;
if ( t > 1 ) t -= 1 ;
if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t ;
if ( t < 1 / 2 ) return q ;
if ( t < 2 / 3 ) return p + ( q - p ) * ( 2 / 3 - t ) * 6 ;
return p ;
} ;
if ( s === 0 ) {
return [ l , l , l ] ;
}
const q = l < 0.5 ? l * ( 1 + s ) : l + s - l * s ;
const p = 2 * l - q ;
const r = hueToRgb ( p , q , h + 1 / 3 ) ;
const g = hueToRgb ( p , q , h ) ;
const b = hueToRgb ( p , q , h - 1 / 3 ) ;
return [ r * 255 , g * 255 , b * 255 ] ;
}
function rgbToLuminance ( r , g , b ) {
console . log ( r , g , b )
const gammaCorrect = ( color ) => {
return color <= 0.03928
? color / 12.92
: Math . pow ( ( color + 0.055 ) / 1.055 , 2.4 ) ;
} ;
const rsRGB = r / 255 ;
const gsRGB = g / 255 ;
const bsRGB = b / 255 ;
const rLuminance = gammaCorrect ( rsRGB ) . toFixed ( 2 ) ;
const gLuminance = gammaCorrect ( gsRGB ) . toFixed ( 2 ) ;
const bLuminance = gammaCorrect ( bsRGB ) . toFixed ( 2 ) ;
console . log ( ` rLum ${ rLuminance } , gLum ${ gLuminance } , bLum ${ bLuminance } ` )
return 0.2126 * rLuminance + 0.7152 * gLuminance + 0.0722 * bLuminance ;
}
//this version keeps BG and main text in same hue
/ * f u n c t i o n g e t R e a d a b l e T e x t C o l o r ( r g b ) {
const [ r , g , b ] = rgb ;
// Convert RGB to HSL
const rgbToHsl = ( r , g , b ) => {
const max = Math . max ( r , g , b ) ;
const min = Math . min ( r , g , b ) ;
const d = max - min ;
const l = ( max + min ) / 2 ;
if ( d === 0 ) return [ 0 , 0 , l ] ;
const s = l > 0.5 ? d / ( 2 - max - min ) : d / ( max + min ) ;
const h = ( ( ) => {
switch ( max ) {
case r :
return ( g - b ) / d + ( g < b ? 6 : 0 ) ;
case g :
return ( b - r ) / d + 2 ;
case b :
return ( r - g ) / d + 4 ;
}
} ) ( ) / 6 ;
return [ h , s , l ] ;
} ;
const [ h , s , l ] = rgbToHsl ( r / 255 , g / 255 , b / 255 ) ;
// Calculate appropriate text color based on background color
const targetLuminance = l > 0.5 ? 0.2 : 0.8 ;
const targetSaturation = s > 0.5 ? s - 0.2 : s + 0.2 ;
const [ rNew , gNew , bNew ] = hslToRgb ( h , targetSaturation , targetLuminance ) ;
// Return the text color in RGBA format
return ` rgba( ${ rNew . toFixed ( 0 ) } , ${ gNew . toFixed ( 0 ) } , ${ bNew . toFixed ( 0 ) } , 1) ` ;
} * /
//this version makes main text complimentary color to BG color
function getReadableTextColor ( rgb ) {
const [ r , g , b ] = rgb ;
// Convert RGB to HSL
const rgbToHsl = ( r , g , b ) => {
const max = Math . max ( r , g , b ) ;
const min = Math . min ( r , g , b ) ;
const d = max - min ;
const l = ( max + min ) / 2 ;
if ( d === 0 ) return [ 0 , 0 , l ] ;
const s = l > 0.5 ? d / ( 2 - max - min ) : d / ( max + min ) ;
const h = ( ( ) => {
switch ( max ) {
case r :
return ( g - b ) / d + ( g < b ? 6 : 0 ) ;
case g :
return ( b - r ) / d + 2 ;
case b :
return ( r - g ) / d + 4 ;
}
} ) ( ) / 6 ;
return [ h , s , l ] ;
} ;
const [ h , s , l ] = rgbToHsl ( r / 255 , g / 255 , b / 255 ) ;
// Calculate complementary color based on background color
const complementaryHue = ( h + 0.5 ) % 1 ;
const complementarySaturation = s > 0.5 ? s - 0.6 : s + 0.6 ;
const complementaryLuminance = l > 0.5 ? 0.2 : 0.8 ;
// Convert complementary color back to RGB
const [ rNew , gNew , bNew ] = hslToRgb ( complementaryHue , complementarySaturation , complementaryLuminance ) ;
// Return the text color in RGBA format
return ` rgba( ${ rNew . toFixed ( 0 ) } , ${ gNew . toFixed ( 0 ) } , ${ bNew . toFixed ( 0 ) } , 1) ` ;
}
}
export function getCustomStoppingStrings ( ) {
try {
// Parse the JSON string
const strings = JSON . parse ( power _user . custom _stopping _strings ) ;
// Make sure it's an array
if ( ! Array . isArray ( strings ) ) {
return [ ] ;
}
// Make sure all the elements are strings
return strings . filter ( ( s ) => typeof s === 'string' ) ;
} catch ( error ) {
// If there's an error, return an empty array
console . warn ( 'Error parsing custom stopping strings:' , error ) ;
return [ ] ;
}
}
$ ( document ) . ready ( ( ) => {
$ ( window ) . on ( 'resize' , async ( ) => {
if ( isMobile ( ) ) {
return
}
//console.log('Window resized!');
const zoomLevel = Number ( window . devicePixelRatio ) . toFixed ( 2 ) ;
const winWidth = window . innerWidth ;
const winHeight = window . innerHeight ;
console . debug ( ` Zoom: ${ zoomLevel } , X: ${ winWidth } , Y: ${ winHeight } ` ) ;
if ( Object . keys ( power _user . movingUIState ) . length > 0 ) {
resetMovablePanels ( 'resize' ) ;
}
// Adjust layout and styling here
} ) ;
// Settings that go to settings.json
$ ( "#collapse-newlines-checkbox" ) . change ( function ( ) {
power _user . collapse _newlines = ! ! $ ( this ) . prop ( "checked" ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#pygmalion_formatting" ) . change ( function ( e ) {
power _user . pygmalion _formatting = Number ( $ ( this ) . find ( ":selected" ) . val ( ) ) ;
getStatus ( ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#pin-examples-checkbox" ) . change ( function ( ) {
power _user . pin _examples = ! ! $ ( this ) . prop ( "checked" ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#disable-description-formatting-checkbox" ) . change ( function ( ) {
power _user . disable _description _formatting = ! ! $ ( this ) . prop ( 'checked' ) ;
saveSettingsDebounced ( ) ;
} )
$ ( "#disable-scenario-formatting-checkbox" ) . change ( function ( ) {
power _user . disable _scenario _formatting = ! ! $ ( this ) . prop ( 'checked' ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#disable-personality-formatting-checkbox" ) . change ( function ( ) {
power _user . disable _personality _formatting = ! ! $ ( this ) . prop ( 'checked' ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#disable-examples-formatting-checkbox" ) . change ( function ( ) {
power _user . disable _examples _formatting = ! ! $ ( this ) . prop ( 'checked' ) ;
saveSettingsDebounced ( ) ;
} )
$ ( "#disable-start-formatting-checkbox" ) . change ( function ( ) {
power _user . disable _start _formatting = ! ! $ ( this ) . prop ( 'checked' ) ;
saveSettingsDebounced ( ) ;
} ) ;
// include newline is the child of trim sentences
// if include newline is checked, trim sentences must be checked
// if trim sentences is unchecked, include newline must be unchecked
$ ( "#trim_sentences_checkbox" ) . change ( function ( ) {
power _user . trim _sentences = ! ! $ ( this ) . prop ( "checked" ) ;
if ( ! $ ( this ) . prop ( "checked" ) ) {
$ ( "#include_newline_checkbox" ) . prop ( "checked" , false ) ;
power _user . include _newline = false ;
}
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#include_newline_checkbox" ) . change ( function ( ) {
power _user . include _newline = ! ! $ ( this ) . prop ( "checked" ) ;
if ( $ ( this ) . prop ( "checked" ) ) {
$ ( "#trim_sentences_checkbox" ) . prop ( "checked" , true ) ;
power _user . trim _sentences = true ;
}
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#always-force-name2-checkbox" ) . change ( function ( ) {
power _user . always _force _name2 = ! ! $ ( this ) . prop ( "checked" ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#custom_chat_separator" ) . on ( 'input' , function ( ) {
power _user . custom _chat _separator = $ ( this ) . val ( ) ;
saveSettingsDebounced ( ) ;
reloadMarkdownProcessor ( power _user . render _formulas ) ;
} ) ;
$ ( "#markdown_escape_strings" ) . on ( 'input' , function ( ) {
power _user . markdown _escape _strings = $ ( this ) . val ( ) ;
saveSettingsDebounced ( ) ;
reloadMarkdownProcessor ( power _user . render _formulas ) ;
} ) ;
$ ( "#start_reply_with" ) . on ( 'input' , function ( ) {
power _user . user _prompt _bias = $ ( this ) . val ( ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#chat-show-reply-prefix-checkbox" ) . change ( function ( ) {
power _user . show _user _prompt _bias = ! ! $ ( this ) . prop ( "checked" ) ;
reloadCurrentChat ( ) ;
saveSettingsDebounced ( ) ;
} )
$ ( "#multigen" ) . change ( function ( ) {
power _user . multigen = $ ( this ) . prop ( "checked" ) ;
saveSettingsDebounced ( ) ;
} ) ;
// Settings that go to local storage
$ ( "#fast_ui_mode" ) . change ( function ( ) {
power _user . fast _ui _mode = $ ( this ) . prop ( "checked" ) ;
localStorage . setItem ( storage _keys . fast _ui _mode , power _user . fast _ui _mode ) ;
switchUiMode ( ) ;
} ) ;
$ ( "#waifuMode" ) . on ( 'change' , ( ) => {
power _user . waifuMode = $ ( '#waifuMode' ) . prop ( "checked" ) ;
saveSettingsDebounced ( ) ;
switchWaifuMode ( ) ;
} ) ;
$ ( "#movingUImode" ) . change ( function ( ) {
power _user . movingUI = $ ( this ) . prop ( "checked" ) ;
localStorage . setItem ( storage _keys . movingUI , power _user . movingUI ) ;
switchMovingUI ( ) ;
} ) ;
$ ( "#noShadowsmode" ) . change ( function ( ) {
power _user . noShadows = $ ( this ) . prop ( "checked" ) ;
localStorage . setItem ( storage _keys . noShadows , power _user . noShadows ) ;
noShadows ( ) ;
} ) ;
$ ( "#movingUIreset" ) . on ( 'click' , resetMovablePanels ) ;
$ ( ` input[name="avatar_style"] ` ) . on ( 'input' , function ( e ) {
power _user . avatar _style = Number ( e . target . value ) ;
localStorage . setItem ( storage _keys . avatar _style , power _user . avatar _style ) ;
applyAvatarStyle ( ) ;
} ) ;
$ ( "#chat_display" ) . on ( 'change' , function ( ) {
console . debug ( '###CHAT DISPLAY SELECTOR CHANGE###' )
const value = $ ( this ) . find ( ':selected' ) . val ( ) ;
power _user . chat _display = Number ( value ) ;
saveSettingsDebounced ( ) ;
applyChatDisplay ( ) ;
} ) ;
$ ( '#chat_width_slider' ) . on ( 'input' , function ( e ) {
power _user . chat _width = Number ( e . target . value ) ;
localStorage . setItem ( storage _keys . chat _width , power _user . chat _width ) ;
applyChatWidth ( ) ;
} ) ;
$ ( ` input[name="font_scale"] ` ) . on ( 'input' , async function ( e ) {
power _user . font _scale = Number ( e . target . value ) ;
$ ( "#font_scale_counter" ) . text ( power _user . font _scale ) ;
localStorage . setItem ( storage _keys . font _scale , power _user . font _scale ) ;
await applyFontScale ( ) ;
} ) ;
$ ( ` input[name="blur_strength"] ` ) . on ( 'input' , async function ( e ) {
power _user . blur _strength = Number ( e . target . value ) ;
$ ( "#blur_strength_counter" ) . text ( power _user . blur _strength ) ;
localStorage . setItem ( storage _keys . blur _strength , power _user . blur _strength ) ;
await applyBlurStrength ( ) ;
} ) ;
$ ( ` input[name="shadow_width"] ` ) . on ( 'input' , async function ( e ) {
power _user . shadow _width = Number ( e . target . value ) ;
$ ( "#shadow_width_counter" ) . text ( power _user . shadow _width ) ;
localStorage . setItem ( storage _keys . shadow _width , power _user . shadow _width ) ;
await applyShadowWidth ( ) ;
} ) ;
$ ( "#main-text-color-picker" ) . on ( 'change' , ( evt ) => {
power _user . main _text _color = evt . detail . rgba ;
applyThemeColor ( 'main' ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#italics-color-picker" ) . on ( 'change' , ( evt ) => {
power _user . italics _text _color = evt . detail . rgba ;
applyThemeColor ( 'italics' ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#quote-color-picker" ) . on ( 'change' , ( evt ) => {
power _user . quote _text _color = evt . detail . rgba ;
applyThemeColor ( 'quote' ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#blur-tint-color-picker" ) . on ( 'change' , ( evt ) => {
power _user . blur _tint _color = evt . detail . rgba ;
applyThemeColor ( 'blurTint' ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#user-mes-blur-tint-color-picker" ) . on ( 'change' , ( evt ) => {
power _user . user _mes _blur _tint _color = evt . detail . rgba ;
applyThemeColor ( 'userMesBlurTint' ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#bot-mes-blur-tint-color-picker" ) . on ( 'change' , ( evt ) => {
power _user . bot _mes _blur _tint _color = evt . detail . rgba ;
applyThemeColor ( 'botMesBlurTint' ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#shadow-color-picker" ) . on ( 'change' , ( evt ) => {
power _user . shadow _color = evt . detail . rgba ;
applyThemeColor ( 'shadow' ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#themes" ) . on ( 'change' , function ( ) {
const themeSelected = $ ( this ) . find ( ':selected' ) . val ( ) ;
power _user . theme = themeSelected ;
applyTheme ( themeSelected ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#movingUIPresets" ) . on ( 'change' , async function ( ) {
console . log ( 'saw MUI preset change' )
const movingUIPresetSelected = $ ( this ) . find ( ':selected' ) . val ( ) ;
power _user . movingUIPreset = movingUIPresetSelected ;
applyMovingUIPreset ( movingUIPresetSelected ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#ui-preset-save-button" ) . on ( 'click' , saveTheme ) ;
$ ( "#movingui-preset-save-button" ) . on ( 'click' , saveMovingUI ) ;
$ ( "#never_resize_avatars" ) . on ( 'input' , function ( ) {
power _user . never _resize _avatars = ! ! $ ( this ) . prop ( 'checked' ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#show_card_avatar_urls" ) . on ( 'input' , function ( ) {
power _user . show _card _avatar _urls = ! ! $ ( this ) . prop ( 'checked' ) ;
printCharacters ( ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#play_message_sound" ) . on ( 'input' , function ( ) {
power _user . play _message _sound = ! ! $ ( this ) . prop ( 'checked' ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#play_sound_unfocused" ) . on ( 'input' , function ( ) {
power _user . play _sound _unfocused = ! ! $ ( this ) . prop ( 'checked' ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#auto_save_msg_edits" ) . on ( 'input' , function ( ) {
power _user . auto _save _msg _edits = ! ! $ ( this ) . prop ( 'checked' ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#character_sort_order" ) . on ( 'change' , function ( ) {
power _user . sort _field = $ ( this ) . find ( ":selected" ) . data ( 'field' ) ;
power _user . sort _order = $ ( this ) . find ( ":selected" ) . data ( 'order' ) ;
power _user . sort _rule = $ ( this ) . find ( ":selected" ) . data ( 'rule' ) ;
sortCharactersList ( ) ;
favsToHotswap ( ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#multigen_first_chunk" ) . on ( 'input' , function ( ) {
power _user . multigen _first _chunk = Number ( $ ( this ) . val ( ) ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#multigen_next_chunks" ) . on ( 'input' , function ( ) {
power _user . multigen _next _chunks = Number ( $ ( this ) . val ( ) ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( '#auto_swipe' ) . on ( 'input' , function ( ) {
power _user . auto _swipe = ! ! $ ( this ) . prop ( 'checked' ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( '#auto_swipe_blacklist' ) . on ( 'input' , function ( ) {
power _user . auto _swipe _blacklist = $ ( this ) . val ( )
. split ( "," )
. map ( str => str . trim ( ) )
. filter ( str => str ) ;
console . log ( "power_user.auto_swipe_blacklist" , power _user . auto _swipe _blacklist )
saveSettingsDebounced ( ) ;
} ) ;
$ ( '#auto_swipe_minimum_length' ) . on ( 'input' , function ( ) {
const number = parseInt ( $ ( this ) . val ( ) ) ;
if ( ! isNaN ( number ) ) {
power _user . auto _swipe _minimum _length = number ;
saveSettingsDebounced ( ) ;
}
} ) ;
$ ( '#auto_swipe_blacklist_threshold' ) . on ( 'input' , function ( ) {
const number = parseInt ( $ ( this ) . val ( ) ) ;
if ( ! isNaN ( number ) ) {
power _user . auto _swipe _blacklist _threshold = number ;
saveSettingsDebounced ( ) ;
}
} ) ;
$ ( '#auto_fix_generated_markdown' ) . on ( 'input' , function ( ) {
power _user . auto _fix _generated _markdown = ! ! $ ( this ) . prop ( 'checked' ) ;
reloadCurrentChat ( ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#console_log_prompts" ) . on ( 'input' , function ( ) {
power _user . console _log _prompts = ! ! $ ( this ) . prop ( 'checked' ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( '#auto_scroll_chat_to_bottom' ) . on ( "input" , function ( ) {
power _user . auto _scroll _chat _to _bottom = ! ! $ ( this ) . prop ( 'checked' ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#tokenizer" ) . on ( 'change' , function ( ) {
const value = $ ( this ) . find ( ':selected' ) . val ( ) ;
power _user . tokenizer = Number ( value ) ;
saveSettingsDebounced ( ) ;
// Trigger character editor re-tokenize
$ ( "#rm_ch_create_block" ) . trigger ( 'input' ) ;
$ ( "#character_popup" ) . trigger ( 'input' ) ;
} ) ;
$ ( "#send_on_enter" ) . on ( 'change' , function ( ) {
const value = $ ( this ) . find ( ':selected' ) . val ( ) ;
power _user . send _on _enter = Number ( value ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#import_card_tags" ) . on ( 'input' , function ( ) {
power _user . import _card _tags = ! ! $ ( this ) . prop ( 'checked' ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#confirm_message_delete" ) . on ( 'input' , function ( ) {
power _user . confirm _message _delete = ! ! $ ( this ) . prop ( 'checked' ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#render_formulas" ) . on ( "input" , function ( ) {
power _user . render _formulas = ! ! $ ( this ) . prop ( 'checked' ) ;
reloadMarkdownProcessor ( power _user . render _formulas ) ;
reloadCurrentChat ( ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#reload_chat" ) . on ( 'click' , function ( ) {
const currentChatId = getCurrentChatId ( ) ;
if ( currentChatId !== undefined && currentChatId !== null ) {
reloadCurrentChat ( ) ;
}
} ) ;
$ ( "#allow_name1_display" ) . on ( "input" , function ( ) {
power _user . allow _name1 _display = ! ! $ ( this ) . prop ( 'checked' ) ;
reloadCurrentChat ( ) ;
saveSettingsDebounced ( ) ;
} )
$ ( "#allow_name2_display" ) . on ( "input" , function ( ) {
power _user . allow _name2 _display = ! ! $ ( this ) . prop ( 'checked' ) ;
reloadCurrentChat ( ) ;
saveSettingsDebounced ( ) ;
} ) ;
/ * $ ( " # r e m o v e X M L " ) . o n ( " i n p u t " , f u n c t i o n ( ) {
power _user . removeXML = ! ! $ ( this ) . prop ( 'checked' ) ;
reloadCurrentChat ( ) ;
saveSettingsDebounced ( ) ;
} ) ; * /
$ ( "#token_padding" ) . on ( "input" , function ( ) {
power _user . token _padding = Number ( $ ( this ) . val ( ) ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#messageTimerEnabled" ) . on ( "input" , function ( ) {
const value = ! ! $ ( this ) . prop ( 'checked' ) ;
power _user . timer _enabled = value ;
localStorage . setItem ( storage _keys . timer _enabled , power _user . timer _enabled ) ;
switchTimer ( ) ;
} ) ;
$ ( "#messageTimestampsEnabled" ) . on ( "input" , function ( ) {
const value = ! ! $ ( this ) . prop ( 'checked' ) ;
power _user . timestamps _enabled = value ;
localStorage . setItem ( storage _keys . timestamps _enabled , power _user . timestamps _enabled ) ;
switchTimestamps ( ) ;
} ) ;
$ ( "#mesIDDisplayEnabled" ) . on ( "input" , function ( ) {
const value = ! ! $ ( this ) . prop ( 'checked' ) ;
power _user . mesIDDisplay _enabled = value ;
localStorage . setItem ( storage _keys . mesIDDisplay _enabled , power _user . mesIDDisplay _enabled ) ;
switchMesIDDisplay ( ) ;
} ) ;
$ ( "#hotswapEnabled" ) . on ( "input" , function ( ) {
const value = ! ! $ ( this ) . prop ( 'checked' ) ;
power _user . hotswap _enabled = value ;
localStorage . setItem ( storage _keys . hotswap _enabled , power _user . hotswap _enabled ) ;
switchHotswap ( ) ;
} ) ;
$ ( "#prefer_character_prompt" ) . on ( "input" , function ( ) {
const value = ! ! $ ( this ) . prop ( 'checked' ) ;
power _user . prefer _character _prompt = value ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#prefer_character_jailbreak" ) . on ( "input" , function ( ) {
const value = ! ! $ ( this ) . prop ( 'checked' ) ;
power _user . prefer _character _jailbreak = value ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#continue_on_send" ) . on ( "input" , function ( ) {
const value = ! ! $ ( this ) . prop ( 'checked' ) ;
power _user . continue _on _send = value ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#trim_spaces" ) . on ( "input" , function ( ) {
const value = ! ! $ ( this ) . prop ( 'checked' ) ;
power _user . trim _spaces = value ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( '#spoiler_free_mode' ) . on ( 'input' , function ( ) {
power _user . spoiler _free _mode = ! ! $ ( this ) . prop ( 'checked' ) ;
switchSpoilerMode ( ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( '#spoiler_free_desc_button' ) . on ( 'click' , function ( ) {
peekSpoilerMode ( ) ;
$ ( this ) . toggleClass ( 'fa-eye fa-eye-slash' ) ;
} ) ;
$ ( '#custom_stopping_strings' ) . on ( 'input' , function ( ) {
power _user . custom _stopping _strings = $ ( this ) . val ( ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( window ) . on ( 'focus' , function ( ) {
browser _has _focus = true ;
} ) ;
$ ( window ) . on ( 'blur' , function ( ) {
browser _has _focus = false ;
} ) ;
registerSlashCommand ( 'vn' , toggleWaifu , [ ] , ' – swaps Visual Novel Mode On/Off' , false , true ) ;
registerSlashCommand ( 'newchat' , doNewChat , [ 'newchat' ] , ' – start a new chat with current character' , true , true ) ;
registerSlashCommand ( 'random' , doRandomChat , [ 'random' ] , ' – start a new chat with a random character' , true , true ) ;
registerSlashCommand ( 'delmode' , doDelMode , [ 'del' ] , '<span class="monospace">(optional number)</span> – enter message deletion mode, and auto-deletes N messages if numeric argument is provided' , true , true ) ;
registerSlashCommand ( 'cut' , doMesCut , [ ] , ' <span class="monospace">(requred number)</span> – cuts the specified message from the chat' , true , true ) ;
registerSlashCommand ( 'resetpanels' , doResetPanels , [ 'resetui' ] , ' – resets UI panels to original state.' , true , true ) ;
registerSlashCommand ( 'bgcol' , setAvgBG , [ ] , ' – WIP test of auto-bg avg coloring' , true , true ) ;
} ) ;