2023-07-20 19:32:15 +02:00
import {
saveSettingsDebounced ,
scrollChatToBottom ,
characters ,
callPopup ,
getStatus ,
reloadMarkdownProcessor ,
reloadCurrentChat ,
getRequestHeaders ,
substituteParams ,
eventSource ,
event _types ,
getCurrentChatId ,
printCharacters ,
setCharacterId ,
2023-08-27 22:20:43 +02:00
setEditedMessageId ,
renderTemplate ,
2023-07-20 19:32:15 +02:00
} from "../script.js" ;
2023-09-14 14:56:01 +02:00
import { isMobile , initMovingUI , favsToHotswap } from "./RossAscends-mods.js" ;
2023-07-20 19:32:15 +02:00
import {
groups ,
resetSelectedGroup ,
} from "./group-chats.js" ;
2023-08-23 20:17:45 +02:00
import {
instruct _presets ,
loadInstructMode ,
selectInstructPreset ,
} from "./instruct-mode.js" ;
2023-07-20 19:32:15 +02:00
import { registerSlashCommand } from "./slash-commands.js" ;
2023-08-23 01:38:43 +02:00
import { tokenizers } from "./tokenizers.js" ;
2023-07-20 19:32:15 +02:00
2023-09-14 14:56:01 +02:00
import { countOccurrences , debounce , delay , isOdd , resetScrollHeight , sortMoments , timestampToMoment } from "./utils.js" ;
2023-07-20 19:32:15 +02:00
export {
loadPowerUserSettings ,
loadMovingUIState ,
collapseNewlines ,
playMessageSound ,
2023-08-18 22:13:15 +02:00
sortEntitiesList ,
2023-07-20 19:32:15 +02:00
fixMarkdown ,
power _user ,
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 ;
2023-08-25 00:06:52 +02:00
const defaultStoryString = "{{#if system}}{{system}}\n{{/if}}{{#if description}}{{description}}\n{{/if}}{{#if personality}}{{char}}'s personality: {{personality}}\n{{/if}}{{#if scenario}}Scenario: {{scenario}}\n{{/if}}{{#if persona}}{{persona}}\n{{/if}}" ;
2023-08-17 21:47:34 +02:00
const defaultExampleSeparator = '***' ;
const defaultChatStart = '***' ;
2023-08-29 17:04:10 +02:00
export const ui _mode = {
SIMPLE : 0 ,
POWER : 1 ,
}
2023-07-20 19:32:15 +02:00
const avatar _styles = {
ROUND : 0 ,
RECTANGULAR : 1 ,
}
export const chat _styles = {
DEFAULT : 0 ,
BUBBLES : 1 ,
DOCUMENT : 2 ,
}
const send _on _enter _options = {
DISABLED : - 1 ,
AUTO : 0 ,
ENABLED : 1 ,
}
export const persona _description _positions = {
2023-08-28 23:09:41 +02:00
IN _PROMPT : 0 ,
/ * *
* @ deprecated Use persona _description _positions . IN _PROMPT instead .
* /
2023-07-20 19:32:15 +02:00
AFTER _CHAR : 1 ,
TOP _AN : 2 ,
BOTTOM _AN : 3 ,
}
let power _user = {
2023-08-04 13:17:05 +02:00
tokenizer : tokenizers . BEST _MATCH ,
2023-07-20 19:32:15 +02:00
token _padding : 64 ,
collapse _newlines : false ,
pin _examples : false ,
2023-08-19 18:25:07 +02:00
strip _examples : false ,
2023-07-20 19:32:15 +02:00
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 ,
markdown _escape _strings : '' ,
2023-08-29 17:04:10 +02:00
ui _mode : ui _mode . POWER ,
2023-07-20 19:32:15 +02:00
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 ,
2023-08-14 00:43:16 +02:00
timestamp _model _icon : false ,
2023-07-20 19:32:15 +02:00
mesIDDisplay _enabled : false ,
max _context _unlocked : false ,
2023-08-31 16:10:01 +02:00
message _token _count _enabled : false ,
2023-09-14 14:23:51 +02:00
expand _message _actions : false ,
2023-07-20 19:32:15 +02:00
prefer _character _prompt : true ,
prefer _character _jailbreak : true ,
2023-08-24 00:37:44 +02:00
quick _continue : false ,
2023-08-24 14:13:04 +02:00
continue _on _send : false ,
2023-07-20 19:32:15 +02:00
trim _spaces : true ,
2023-08-04 22:49:55 +02:00
relaxed _api _urls : false ,
2023-08-30 15:31:53 +02:00
disable _group _trimming : false ,
2023-07-20 19:32:15 +02:00
2023-08-19 19:18:39 +02:00
default _instruct : '' ,
2023-07-20 19:32:15 +02:00
instruct : {
enabled : false ,
2023-08-25 22:34:08 +02:00
preset : "Alpaca" ,
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}}.\n" ,
input _sequence : "### Instruction:" ,
output _sequence : "### Response:" ,
first _output _sequence : "" ,
last _output _sequence : "" ,
system _sequence _prefix : "" ,
system _sequence _suffix : "" ,
stop _sequence : "" ,
separator _sequence : "" ,
2023-07-20 19:32:15 +02:00
wrap : true ,
2023-08-25 22:34:08 +02:00
macro : true ,
2023-07-20 19:32:15 +02:00
names : false ,
2023-08-08 16:11:38 +02:00
names _force _groups : true ,
2023-08-25 22:34:08 +02:00
activation _regex : "" ,
2023-07-20 19:32:15 +02:00
} ,
2023-08-26 12:09:47 +02:00
default _context : 'Default' ,
2023-08-17 21:47:34 +02:00
context : {
preset : 'Default' ,
story _string : defaultStoryString ,
chat _start : defaultChatStart ,
example _separator : defaultExampleSeparator ,
} ,
2023-07-20 19:32:15 +02:00
personas : { } ,
default _persona : null ,
persona _descriptions : { } ,
persona _description : '' ,
2023-08-28 23:09:41 +02:00
persona _description _position : persona _description _positions . IN _PROMPT ,
2023-08-03 13:24:45 +02:00
persona _show _notifications : true ,
2023-07-20 19:32:15 +02:00
custom _stopping _strings : '' ,
2023-08-04 16:53:49 +02:00
custom _stopping _strings _macro : true ,
2023-07-27 23:38:43 +02:00
fuzzy _search : false ,
2023-08-10 10:47:17 +02:00
encode _tags : false ,
2023-08-12 12:10:41 +02:00
lazy _load : 0 ,
2023-09-08 21:44:06 +02:00
servers : [ ] ,
2023-07-20 19:32:15 +02:00
} ;
let themes = [ ] ;
let movingUIPresets = [ ] ;
2023-08-23 20:17:45 +02:00
export let context _presets = [ ] ;
2023-07-20 19:32:15 +02:00
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' ,
2023-08-14 00:43:16 +02:00
timestamp _model _icon : 'TimestampModelIcon' ,
2023-07-20 19:32:15 +02:00
mesIDDisplay _enabled : 'mesIDDisplayEnabled' ,
2023-08-31 16:10:01 +02:00
message _token _count _enabled : 'MessageTokenCountEnabled' ,
2023-09-14 14:23:51 +02:00
expand _message _actions : 'ExpandMessageActions' ,
2023-07-20 19:32:15 +02:00
} ;
let browser _has _focus = true ;
2023-08-27 22:20:43 +02:00
const debug _functions = [ ] ;
2023-07-20 19:32:15 +02:00
2023-09-14 14:56:01 +02:00
const setHotswapsDebounced = debounce ( favsToHotswap , 500 ) ;
2023-08-29 17:04:10 +02:00
export function switchSimpleMode ( ) {
$ ( '[data-newbie-hidden]' ) . each ( function ( ) {
$ ( this ) . toggleClass ( 'displayNone' , power _user . ui _mode === ui _mode . SIMPLE ) ;
} ) ;
}
2023-07-20 19:32:15 +02:00
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' ) ;
2023-08-22 12:07:24 +02:00
if ( audio instanceof HTMLAudioElement ) {
audio . volume = 0.8 ;
audio . pause ( ) ;
audio . currentTime = 0 ;
audio . play ( ) ;
}
2023-07-20 19:32:15 +02:00
}
2023-08-22 12:07:24 +02:00
/ * *
* Replaces consecutive newlines with a single newline .
* @ param { string } x String to be processed .
* @ returns { string } Processed string .
* @ example
* collapseNewlines ( "\n\n\n" ) ; // "\n"
* /
2023-07-20 19:32:15 +02:00
function collapseNewlines ( x ) {
return x . replaceAll ( /\n+/g , "\n" ) ;
}
2023-08-22 12:07:24 +02:00
/ * *
* Fix formatting problems in markdown .
* @ param { string } text Text to be processed .
2023-08-31 13:39:31 +02:00
* @ param { boolean } forDisplay Whether the text is being processed for display .
2023-08-22 12:07:24 +02:00
* @ returns { string } Processed text .
* @ example
* "^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
* "^example * text* * harder problem *\n" // "^example *text* *harder problem*\n"
* /
2023-08-31 13:39:31 +02:00
function fixMarkdown ( text , forDisplay ) {
2023-07-20 19:32:15 +02:00
// Find pairs of formatting characters and capture the text in between them
2023-07-29 00:09:54 +02:00
const format = /([\*_]{1,2})([\s\S]*?)\1/gm ;
2023-07-20 19:32:15 +02:00
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 ] ;
2023-07-29 00:35:36 +02:00
let replacementText = matchText . replace ( /(\*|_)([\t \u00a0\u1680\u2000-\u200a\u202f\u205f\u3000\ufeff]+)|([\t \u00a0\u1680\u2000-\u200a\u202f\u205f\u3000\ufeff]+)(\*|_)/g , '$1$4' ) ;
2023-07-20 19:32:15 +02:00
newText = newText . slice ( 0 , matches [ i ] . index ) + replacementText + newText . slice ( matches [ i ] . index + matchText . length ) ;
}
2023-08-31 13:39:31 +02:00
// Don't auto-fix asterisks if this is a message clean-up procedure.
// It botches the continue function. Apply this to display only.
if ( ! forDisplay ) {
return newText ;
}
const splitText = newText . split ( '\n' ) ;
// Fix asterisks, and quotes that are not paired
for ( let index = 0 ; index < splitText . length ; index ++ ) {
const line = splitText [ index ] ;
const charsToCheck = [ '*' , '"' ] ;
for ( const char of charsToCheck ) {
if ( line . includes ( char ) && isOdd ( countOccurrences ( line , char ) ) ) {
splitText [ index ] = line . trimEnd ( ) + char ;
}
}
}
newText = splitText . join ( '\n' ) ;
2023-07-20 19:32:15 +02:00
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 ) ;
}
2023-08-14 00:43:16 +02:00
function switchIcons ( ) {
const value = localStorage . getItem ( storage _keys . timestamp _model _icon ) ;
power _user . timestamp _model _icon = value === null ? true : value == "true" ;
$ ( "body" ) . toggleClass ( "no-modelIcons" , ! power _user . timestamp _model _icon ) ;
$ ( "#messageModelIconEnabled" ) . prop ( "checked" , power _user . timestamp _model _icon ) ;
}
2023-08-31 16:10:01 +02:00
function switchTokenCount ( ) {
const value = localStorage . getItem ( storage _keys . message _token _count _enabled ) ;
power _user . message _token _count _enabled = value === null ? false : value == "true" ;
$ ( "body" ) . toggleClass ( "no-tokenCount" , ! power _user . message _token _count _enabled ) ;
$ ( "#messageTokensEnabled" ) . prop ( "checked" , power _user . message _token _count _enabled ) ;
}
2023-09-14 14:23:51 +02:00
function switchMessageActions ( ) {
const value = localStorage . getItem ( storage _keys . expand _message _actions ) ;
power _user . expand _message _actions = value === null ? false : value == "true" ;
$ ( "body" ) . toggleClass ( "expandMessageActions" , power _user . expand _message _actions ) ;
$ ( "#expandMessageActions" ) . prop ( "checked" , power _user . expand _message _actions ) ;
}
2023-07-20 19:32:15 +02:00
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 ) ;
}
2023-08-25 00:06:52 +02:00
async function applyFontScale ( type ) {
2023-07-20 19:32:15 +02:00
power _user . font _scale = Number ( localStorage . getItem ( storage _keys . font _scale ) ? ? 1 ) ;
2023-08-25 00:06:52 +02:00
//this is to allow forced setting on page load, theme swap, etc
if ( type === 'forced' ) {
document . documentElement . style . setProperty ( '--fontScale' , power _user . font _scale ) ;
} else {
//this is to prevent the slider from updating page in real time
$ ( "#font_scale" ) . off ( 'mouseup touchend' ) . on ( 'mouseup touchend' , ( ) => {
document . documentElement . style . setProperty ( '--fontScale' , power _user . font _scale ) ;
} )
}
2023-07-20 19:32:15 +02:00
$ ( "#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 ) ;
2023-08-25 00:06:52 +02:00
await applyFontScale ( 'forced' ) ;
2023-07-20 19:32:15 +02:00
}
} ,
{
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-08-31 16:10:01 +02:00
localStorage . setItem ( storage _keys . chat _width , String ( power _user . chat _width ) ) ;
2023-07-20 19:32:15 +02:00
applyChatWidth ( ) ;
}
} ,
{
key : 'timer_enabled' ,
action : async ( ) => {
2023-08-31 16:10:01 +02:00
localStorage . setItem ( storage _keys . timer _enabled , String ( power _user . timer _enabled ) ) ;
2023-07-20 19:32:15 +02:00
switchTimer ( ) ;
}
} ,
{
key : 'timestamps_enabled' ,
action : async ( ) => {
2023-08-31 16:10:01 +02:00
localStorage . setItem ( storage _keys . timestamps _enabled , String ( power _user . timestamps _enabled ) ) ;
2023-07-20 19:32:15 +02:00
switchTimestamps ( ) ;
}
} ,
2023-08-14 00:43:16 +02:00
{
key : 'timestamp_model_icon' ,
action : async ( ) => {
2023-08-31 16:10:01 +02:00
localStorage . setItem ( storage _keys . timestamp _model _icon , String ( power _user . timestamp _model _icon ) ) ;
2023-08-14 00:43:16 +02:00
switchIcons ( ) ;
}
} ,
2023-08-31 16:10:01 +02:00
{
key : 'message_token_count' ,
action : async ( ) => {
localStorage . setItem ( storage _keys . message _token _count _enabled , String ( power _user . message _token _count _enabled ) ) ;
switchTokenCount ( ) ;
}
} ,
2023-07-20 19:32:15 +02:00
{
key : 'mesIDDisplay_enabled' ,
action : async ( ) => {
2023-08-31 16:10:01 +02:00
localStorage . setItem ( storage _keys . mesIDDisplay _enabled , String ( power _user . mesIDDisplay _enabled ) ) ;
2023-07-20 19:32:15 +02:00
switchMesIDDisplay ( ) ;
}
} ,
2023-09-14 14:23:51 +02:00
{
key : 'expand_message_actions' ,
action : async ( ) => {
localStorage . setItem ( storage _keys . expand _message _actions , String ( power _user . expand _message _actions ) ) ;
switchMessageActions ( ) ;
}
} ,
2023-07-20 19:32:15 +02:00
{
key : 'hotswap_enabled' ,
action : async ( ) => {
2023-08-31 16:10:01 +02:00
localStorage . setItem ( storage _keys . hotswap _enabled , String ( power _user . hotswap _enabled ) ) ;
2023-07-20 19:32:15 +02:00
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 ( )
}
2023-08-27 22:20:43 +02:00
/ * *
* Register a function to be executed when the debug menu is opened .
* @ param { string } functionId Unique ID for the function .
* @ param { string } name Name of the function .
* @ param { string } description Description of the function .
* @ param { function } func Function to be executed .
* /
export function registerDebugFunction ( functionId , name , description , func ) {
debug _functions . push ( { functionId , name , description , func } ) ;
}
function showDebugMenu ( ) {
const template = renderTemplate ( 'debug' , { functions : debug _functions } ) ;
callPopup ( template , 'text' , '' , { wide : true , large : true } ) ;
}
2023-07-20 19:32:15 +02:00
switchUiMode ( ) ;
2023-08-25 00:06:52 +02:00
applyFontScale ( 'forced' ) ;
2023-07-20 19:32:15 +02:00
applyThemeColor ( ) ;
applyChatWidth ( ) ;
applyAvatarStyle ( ) ;
applyBlurStrength ( ) ;
applyShadowWidth ( ) ;
switchMovingUI ( ) ;
noShadows ( ) ;
switchHotswap ( ) ;
switchTimer ( ) ;
switchTimestamps ( ) ;
2023-08-14 00:43:16 +02:00
switchIcons ( ) ;
2023-07-20 19:32:15 +02:00
switchMesIDDisplay ( ) ;
2023-08-31 16:10:01 +02:00
switchTokenCount ( ) ;
2023-09-14 14:23:51 +02:00
switchMessageActions ( ) ;
2023-07-20 19:32:15 +02:00
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 ;
}
2023-08-17 21:47:34 +02:00
if ( data . context !== undefined ) {
context _presets = data . context ;
}
2023-07-20 19:32:15 +02:00
// 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-08-27 21:14:39 +02:00
if ( power _user . tokenizer === tokenizers . LEGACY ) {
power _user . tokenizer = tokenizers . GPT2 ;
}
2023-08-04 22:49:55 +02:00
$ ( '#relaxed_api_urls' ) . prop ( "checked" , power _user . relaxed _api _urls ) ;
2023-07-20 19:32:15 +02:00
$ ( '#trim_spaces' ) . prop ( "checked" , power _user . trim _spaces ) ;
2023-08-24 14:13:04 +02:00
$ ( '#continue_on_send' ) . prop ( "checked" , power _user . continue _on _send ) ;
2023-08-24 00:37:44 +02:00
$ ( '#quick_continue' ) . prop ( "checked" , power _user . quick _continue ) ;
$ ( '#mes_continue' ) . css ( 'display' , power _user . quick _continue ? '' : 'none' ) ;
2023-07-20 19:32:15 +02:00
$ ( '#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 ) ;
2023-08-04 16:53:49 +02:00
$ ( "#custom_stopping_strings_macro" ) . prop ( "checked" , power _user . custom _stopping _strings _macro ) ;
2023-07-27 23:38:43 +02:00
$ ( '#fuzzy_search_checkbox' ) . prop ( "checked" , power _user . fuzzy _search ) ;
2023-08-03 13:24:45 +02:00
$ ( '#persona_show_notifications' ) . prop ( "checked" , power _user . persona _show _notifications ) ;
2023-08-10 10:47:17 +02:00
$ ( '#encode_tags' ) . prop ( "checked" , power _user . encode _tags ) ;
2023-08-12 12:10:41 +02:00
$ ( '#lazy_load' ) . val ( Number ( power _user . lazy _load ) ) ;
2023-07-20 19:32:15 +02:00
$ ( "#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 ) ;
$ ( ` #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 ) ;
2023-08-19 18:25:07 +02:00
$ ( "#remove-examples-checkbox" ) . prop ( "checked" , power _user . strip _examples ) ;
2023-07-20 19:32:15 +02:00
$ ( "#always-force-name2-checkbox" ) . prop ( "checked" , power _user . always _force _name2 ) ;
$ ( "#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 ) ;
2023-08-30 15:31:53 +02:00
$ ( '#disable_group_trimming' ) . prop ( "checked" , power _user . disable _group _trimming ) ;
2023-07-20 19:32:15 +02:00
$ ( "#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 ) ;
2023-08-14 00:43:16 +02:00
$ ( "#messageModelIconEnabled" ) . prop ( "checked" , power _user . timestamp _model _icon ) ;
2023-07-20 19:32:15 +02:00
$ ( "#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 ) ;
2023-08-29 17:04:10 +02:00
$ ( "#ui_mode_select" ) . val ( power _user . ui _mode ) . find ( ` option[value=" ${ power _user . ui _mode } "] ` ) . attr ( 'selected' , true ) ;
2023-07-20 19:32:15 +02:00
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 ) ;
reloadMarkdownProcessor ( power _user . render _formulas ) ;
2023-08-20 22:29:43 +02:00
loadInstructMode ( data ) ;
2023-08-17 21:47:34 +02:00
loadContextSettings ( ) ;
2023-07-20 19:32:15 +02:00
loadMaxContextUnlocked ( ) ;
switchWaifuMode ( ) ;
switchSpoilerMode ( ) ;
loadMovingUIState ( ) ;
loadCharListState ( ) ;
2023-08-29 17:04:10 +02:00
switchSimpleMode ( ) ;
2023-07-20 19:32:15 +02:00
}
async function loadCharListState ( ) {
2023-08-19 14:58:17 +02:00
if ( document . querySelector ( '.character_select' ) !== null ) {
2023-07-20 19:32:15 +02:00
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 ( ) {
2023-08-26 20:27:37 +02:00
const elements = [ $ ( '#max_context' ) , $ ( '#rep_pen_range' ) , $ ( '#rep_pen_range_textgenerationwebui' ) ] ;
2023-07-20 19:32:15 +02:00
const maxValue = power _user . max _context _unlocked ? MAX _CONTEXT _UNLOCKED : MAX _CONTEXT _DEFAULT ;
2023-08-26 20:27:37 +02:00
for ( const element of elements ) {
element . attr ( 'max' , maxValue ) ;
const value = Number ( element . val ( ) ) ;
if ( value >= maxValue ) {
element . val ( maxValue ) . trigger ( 'input' ) ;
}
2023-07-20 19:32:15 +02:00
}
}
2023-08-17 21:47:34 +02:00
function loadContextSettings ( ) {
const controls = [
{ id : "context_story_string" , property : "story_string" , isCheckbox : false } ,
{ id : "context_example_separator" , property : "example_separator" , isCheckbox : false } ,
{ id : "context_chat_start" , property : "chat_start" , isCheckbox : false } ,
] ;
controls . forEach ( control => {
const $element = $ ( ` # ${ control . id } ` ) ;
if ( control . isCheckbox ) {
$element . prop ( 'checked' , power _user . context [ control . property ] ) ;
} else {
$element . val ( power _user . context [ control . property ] ) ;
}
$element . on ( 'input' , function ( ) {
power _user . context [ control . property ] = control . isCheckbox ? ! ! $ ( this ) . prop ( 'checked' ) : $ ( this ) . val ( ) ;
saveSettingsDebounced ( ) ;
2023-08-25 21:04:06 +02:00
if ( ! control . isCheckbox ) {
resetScrollHeight ( $element ) ;
}
2023-08-17 21:47:34 +02:00
} ) ;
} ) ;
context _presets . forEach ( ( preset ) => {
const name = preset . name ;
const option = document . createElement ( 'option' ) ;
option . value = name ;
option . innerText = name ;
option . selected = name === power _user . context . preset ;
$ ( '#context_presets' ) . append ( option ) ;
} ) ;
$ ( '#context_presets' ) . on ( 'change' , function ( ) {
2023-08-22 13:30:49 +02:00
const name = String ( $ ( this ) . find ( ':selected' ) . val ( ) ) ;
2023-08-17 21:47:34 +02:00
const preset = context _presets . find ( x => x . name === name ) ;
if ( ! preset ) {
return ;
}
power _user . context . preset = name ;
controls . forEach ( control => {
if ( preset [ control . property ] !== undefined ) {
power _user . context [ control . property ] = preset [ control . property ] ;
const $element = $ ( ` # ${ control . id } ` ) ;
if ( control . isCheckbox ) {
$element . prop ( 'checked' , power _user . context [ control . property ] ) . trigger ( 'input' ) ;
} else {
$element . val ( power _user . context [ control . property ] ) . trigger ( 'input' ) ;
}
}
} ) ;
2023-08-23 20:17:45 +02:00
2023-08-23 22:22:52 +02:00
// Select matching instruct preset
2023-08-23 20:17:45 +02:00
for ( const instruct _preset of instruct _presets ) {
// If instruct preset matches the context template
if ( instruct _preset . name === name ) {
2023-08-23 22:22:52 +02:00
selectInstructPreset ( instruct _preset . name ) ;
break ;
2023-08-23 20:17:45 +02:00
}
}
2023-08-26 12:09:47 +02:00
highlightDefaultContext ( ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( '#context_set_default' ) . on ( 'click' , function ( ) {
if ( power _user . context . preset !== power _user . default _context ) {
power _user . default _context = power _user . context . preset ;
$ ( this ) . addClass ( 'default' ) ;
toastr . info ( ` Default context template set to ${ power _user . default _context } ` ) ;
highlightDefaultContext ( ) ;
saveSettingsDebounced ( ) ;
}
2023-08-17 21:47:34 +02:00
} ) ;
2023-08-26 12:09:47 +02:00
highlightDefaultContext ( ) ;
}
function highlightDefaultContext ( ) {
$ ( '#context_set_default' ) . toggleClass ( 'default' , power _user . default _context === power _user . context . preset ) ;
2023-08-26 14:52:23 +02:00
$ ( '#context_set_default' ) . toggleClass ( 'disabled' , power _user . default _context === power _user . context . preset ) ;
$ ( '#context_delete_preset' ) . toggleClass ( 'disabled' , power _user . default _context === power _user . context . preset ) ;
2023-08-17 21:47:34 +02:00
}
2023-07-27 23:38:43 +02:00
export function fuzzySearchCharacters ( searchValue ) {
const fuse = new Fuse ( characters , {
keys : [
{ name : 'data.name' , weight : 5 } ,
{ name : 'data.description' , weight : 3 } ,
{ name : 'data.mes_example' , weight : 3 } ,
{ name : 'data.scenario' , weight : 2 } ,
{ name : 'data.personality' , weight : 2 } ,
{ name : 'data.first_mes' , weight : 2 } ,
{ name : 'data.creator_notes' , weight : 2 } ,
{ name : 'data.creator' , weight : 1 } ,
{ name : 'data.tags' , weight : 1 } ,
{ name : 'data.alternate_greetings' , weight : 1 }
] ,
includeScore : true ,
ignoreLocation : true ,
threshold : 0.2 ,
} ) ;
const results = fuse . search ( searchValue ) ;
2023-08-14 16:35:48 +02:00
console . debug ( 'Characters fuzzy search results for ' + searchValue , results ) ;
2023-07-27 23:38:43 +02:00
const indices = results . map ( x => x . refIndex ) ;
return indices ;
}
2023-08-22 00:51:31 +02:00
export function fuzzySearchWorldInfo ( data , searchValue ) {
const fuse = new Fuse ( data , {
keys : [
{ name : 'key' , weight : 3 } ,
{ name : 'content' , weight : 3 } ,
{ name : 'comment' , weight : 2 } ,
{ name : 'keysecondary' , weight : 2 } ,
{ name : 'uid' , weight : 1 } ,
] ,
includeScore : true ,
ignoreLocation : true ,
threshold : 0.2 ,
} ) ;
const results = fuse . search ( searchValue ) ;
console . debug ( 'World Info fuzzy search results for ' + searchValue , results ) ;
return results . map ( x => x . item ? . uid ) ;
}
2023-08-14 16:35:48 +02:00
export function fuzzySearchGroups ( searchValue ) {
const fuse = new Fuse ( groups , {
keys : [
{ name : 'name' , weight : 3 } ,
{ name : 'members' , weight : 1 } ,
] ,
includeScore : true ,
ignoreLocation : true ,
threshold : 0.2 ,
} ) ;
const results = fuse . search ( searchValue ) ;
console . debug ( 'Groups fuzzy search results for ' + searchValue , results ) ;
const ids = results . map ( x => String ( x . item ? . id ) ) . filter ( x => x ) ;
return ids ;
}
2023-08-26 00:32:39 +02:00
/ * *
* Renders a story string template with the given parameters .
* @ param { object } params Template parameters .
* @ returns { string } The rendered story string .
* /
2023-08-17 21:47:34 +02:00
export function renderStoryString ( params ) {
try {
2023-08-26 00:32:39 +02:00
// compile the story string template into a function, with no HTML escaping
2023-08-18 12:53:54 +02:00
const compiledTemplate = Handlebars . compile ( power _user . context . story _string , { noEscape : true } ) ;
2023-08-26 00:32:39 +02:00
// render the story string template with the given params
2023-08-17 21:47:34 +02:00
let output = compiledTemplate ( params ) ;
2023-08-26 00:32:39 +02:00
// substitute {{macro}} params that are not defined in the story string
2023-08-17 21:47:34 +02:00
output = substituteParams ( output , params . user , params . char ) ;
2023-08-26 00:32:39 +02:00
// remove leading whitespace
output = output . trimStart ( ) ;
// add a newline to the end of the story string if it doesn't have one
if ( ! output . endsWith ( '\n' ) ) {
output += '\n' ;
}
2023-08-17 21:47:34 +02:00
return output ;
} catch ( e ) {
toastr . error ( 'Check the story string template for validity' , 'Error rendering story string' ) ;
console . error ( 'Error rendering story string' , e ) ;
2023-08-26 00:32:39 +02:00
throw e ; // rethrow the error
2023-08-17 21:47:34 +02:00
}
}
2023-07-20 19:32:15 +02:00
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 ;
}
2023-09-10 13:30:29 +02:00
const a = first [ power _user . sort _field ] ;
const b = second [ power _user . sort _field ] ;
2023-08-31 18:30:56 +02:00
2023-09-10 13:30:29 +02:00
if ( power _user . sort _field === 'create_date' ) {
return sortMoments ( timestampToMoment ( b ) , timestampToMoment ( a ) ) ;
}
2023-08-31 18:30:56 +02:00
2023-09-10 13:30:29 +02:00
switch ( power _user . sort _rule ) {
case 'boolean' :
2023-07-20 19:32:15 +02:00
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 :
2023-09-10 13:30:29 +02:00
return typeof a == "string"
? a . localeCompare ( b )
: a - b ;
2023-07-20 19:32:15 +02:00
}
} ;
2023-08-22 13:30:49 +02:00
/ * *
* Sorts an array of entities based on the current sort settings
* @ param { any [ ] } entities An array of objects with an ` item ` property
* /
2023-08-18 22:13:15 +02:00
function sortEntitiesList ( entities ) {
if ( power _user . sort _field == undefined || entities . length === 0 ) {
2023-07-20 19:32:15 +02:00
return ;
}
2023-08-18 22:13:15 +02:00
entities . sort ( ( a , b ) => sortFunc ( a . item , b . item ) ) ;
2023-07-20 19:32:15 +02:00
}
2023-08-22 13:30:49 +02:00
2023-07-20 19:32:15 +02:00
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 ,
2023-08-14 00:43:16 +02:00
timestamp _model _icon : power _user . timestamp _model _icon ,
2023-07-20 19:32:15 +02:00
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
}
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' )
2023-08-22 13:30:49 +02:00
let numMesToDel = Number ( text ) ;
let lastMesID = Number ( $ ( '.last_mes' ) . attr ( 'mesid' ) ) ;
2023-07-20 19:32:15 +02:00
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 ;
}
2023-08-22 13:30:49 +02:00
/ * *
* Converts an HSL color value to RGB .
* @ param { number } h Hue value
* @ param { number } s Saturation value
* @ param { number } l Luminance value
* @ return { Array } The RGB representation
* /
2023-07-20 19:32:15 +02:00
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 } ` )
2023-08-22 13:30:49 +02:00
return 0.2126 * Number ( rLuminance ) + 0.7152 * Number ( gLuminance ) + 0.0722 * Number ( bLuminance ) ;
2023-07-20 19:32:15 +02:00
}
//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) ` ;
}
}
2023-08-25 23:12:11 +02:00
/ * *
* Gets the custom stopping strings from the power user settings .
2023-08-28 23:47:35 +02:00
* @ param { number | undefined } limit Number of strings to return . If 0 or undefined , returns all strings .
2023-08-25 23:12:11 +02:00
* @ returns { string [ ] } An array of custom stopping strings
* /
export function getCustomStoppingStrings ( limit = undefined ) {
2023-07-20 19:32:15 +02:00
try {
2023-08-25 23:12:11 +02:00
// If there's no custom stopping strings, return an empty array
if ( ! power _user . custom _stopping _strings ) {
return [ ] ;
}
2023-07-20 19:32:15 +02:00
// Parse the JSON string
2023-08-28 23:47:35 +02:00
let strings = JSON . parse ( power _user . custom _stopping _strings ) ;
2023-07-20 19:32:15 +02:00
// Make sure it's an array
if ( ! Array . isArray ( strings ) ) {
return [ ] ;
}
2023-08-28 23:47:35 +02:00
// Make sure all the elements are strings.
strings = strings . filter ( ( s ) => typeof s === 'string' ) ;
// Substitute params if necessary
if ( power _user . custom _stopping _strings _macro ) {
strings = strings . map ( x => substituteParams ( x ) ) ;
}
// Apply the limit. If limit is 0, return all strings.
if ( limit > 0 ) {
strings = strings . slice ( 0 , limit ) ;
}
return strings ;
2023-07-20 19:32:15 +02:00
} 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
2023-09-14 14:56:01 +02:00
setHotswapsDebounced ( ) ;
2023-07-20 19:32:15 +02:00
} ) ;
// Settings that go to settings.json
$ ( "#collapse-newlines-checkbox" ) . change ( function ( ) {
power _user . collapse _newlines = ! ! $ ( this ) . prop ( "checked" ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#pin-examples-checkbox" ) . change ( function ( ) {
2023-08-19 18:25:07 +02:00
if ( $ ( this ) . prop ( "checked" ) ) {
$ ( "#remove-examples-checkbox" ) . prop ( "checked" , false ) . prop ( "disabled" , true ) ;
power _user . strip _examples = false ;
} else {
$ ( "#remove-examples-checkbox" ) . prop ( "disabled" , false ) ;
}
2023-07-20 19:32:15 +02:00
power _user . pin _examples = ! ! $ ( this ) . prop ( "checked" ) ;
saveSettingsDebounced ( ) ;
} ) ;
2023-08-19 18:25:07 +02:00
$ ( "#remove-examples-checkbox" ) . change ( function ( ) {
if ( $ ( this ) . prop ( "checked" ) ) {
$ ( "#pin-examples-checkbox" ) . prop ( "checked" , false ) . prop ( "disabled" , true ) ;
power _user . pin _examples = false ;
} else {
$ ( "#pin-examples-checkbox" ) . prop ( "disabled" , false ) ;
}
power _user . strip _examples = ! ! $ ( this ) . prop ( "checked" ) ;
saveSettingsDebounced ( ) ;
} ) ;
2023-07-20 19:32:15 +02:00
// 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 ( ) ;
} ) ;
$ ( "#markdown_escape_strings" ) . on ( 'input' , function ( ) {
2023-08-22 13:30:49 +02:00
power _user . markdown _escape _strings = String ( $ ( this ) . val ( ) ) ;
2023-07-20 19:32:15 +02:00
saveSettingsDebounced ( ) ;
reloadMarkdownProcessor ( power _user . render _formulas ) ;
} ) ;
$ ( "#start_reply_with" ) . on ( 'input' , function ( ) {
2023-08-22 13:30:49 +02:00
power _user . user _prompt _bias = String ( $ ( this ) . val ( ) ) ;
2023-07-20 19:32:15 +02:00
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 ( ) ;
2023-09-14 14:56:01 +02:00
setHotswapsDebounced ( ) ;
2023-07-20 19:32:15 +02:00
} ) ;
$ ( ` 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 ( ) {
2023-08-22 13:30:49 +02:00
const themeSelected = String ( $ ( this ) . find ( ':selected' ) . val ( ) ) ;
2023-07-20 19:32:15 +02:00
power _user . theme = themeSelected ;
applyTheme ( themeSelected ) ;
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#movingUIPresets" ) . on ( 'change' , async function ( ) {
console . log ( 'saw MUI preset change' )
2023-08-22 13:30:49 +02:00
const movingUIPresetSelected = String ( $ ( this ) . find ( ':selected' ) . val ( ) ) ;
2023-07-20 19:32:15 +02:00
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 ( ) ;
} ) ;
2023-08-18 22:13:15 +02:00
2023-07-20 19:32:15 +02:00
$ ( "#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' ) ;
2023-08-18 22:13:15 +02:00
printCharacters ( ) ;
2023-07-20 19:32:15 +02:00
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 ( ) {
2023-08-22 13:30:49 +02:00
power _user . auto _swipe _blacklist = String ( $ ( this ) . val ( ) )
2023-07-20 19:32:15 +02:00
. 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 ( ) {
2023-08-22 13:30:49 +02:00
const number = Number ( $ ( this ) . val ( ) ) ;
2023-07-20 19:32:15 +02:00
if ( ! isNaN ( number ) ) {
power _user . auto _swipe _minimum _length = number ;
saveSettingsDebounced ( ) ;
}
} ) ;
$ ( '#auto_swipe_blacklist_threshold' ) . on ( 'input' , function ( ) {
2023-08-22 13:30:49 +02:00
const number = Number ( $ ( this ) . val ( ) ) ;
2023-07-20 19:32:15 +02:00
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 ( ) ;
} ) ;
$ ( "#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 ;
2023-08-22 13:30:49 +02:00
localStorage . setItem ( storage _keys . timer _enabled , String ( power _user . timer _enabled ) ) ;
2023-07-20 19:32:15 +02:00
switchTimer ( ) ;
} ) ;
$ ( "#messageTimestampsEnabled" ) . on ( "input" , function ( ) {
const value = ! ! $ ( this ) . prop ( 'checked' ) ;
power _user . timestamps _enabled = value ;
2023-08-22 13:30:49 +02:00
localStorage . setItem ( storage _keys . timestamps _enabled , String ( power _user . timestamps _enabled ) ) ;
2023-07-20 19:32:15 +02:00
switchTimestamps ( ) ;
} ) ;
2023-08-14 00:43:16 +02:00
$ ( "#messageModelIconEnabled" ) . on ( "input" , function ( ) {
const value = ! ! $ ( this ) . prop ( 'checked' ) ;
power _user . timestamp _model _icon = value ;
2023-08-22 13:30:49 +02:00
localStorage . setItem ( storage _keys . timestamp _model _icon , String ( power _user . timestamp _model _icon ) ) ;
2023-08-14 00:43:16 +02:00
switchIcons ( ) ;
} ) ;
2023-08-31 16:10:01 +02:00
$ ( "#messageTokensEnabled" ) . on ( "input" , function ( ) {
const value = ! ! $ ( this ) . prop ( 'checked' ) ;
power _user . message _token _count _enabled = value ;
localStorage . setItem ( storage _keys . message _token _count _enabled , String ( power _user . message _token _count _enabled ) ) ;
switchTokenCount ( ) ;
} ) ;
2023-09-14 14:23:51 +02:00
$ ( "#expandMessageActions" ) . on ( "input" , function ( ) {
const value = ! ! $ ( this ) . prop ( 'checked' ) ;
power _user . expand _message _actions = value ;
localStorage . setItem ( storage _keys . expand _message _actions , String ( power _user . expand _message _actions ) ) ;
switchMessageActions ( ) ;
} ) ;
2023-07-20 19:32:15 +02:00
$ ( "#mesIDDisplayEnabled" ) . on ( "input" , function ( ) {
const value = ! ! $ ( this ) . prop ( 'checked' ) ;
power _user . mesIDDisplay _enabled = value ;
2023-08-22 13:30:49 +02:00
localStorage . setItem ( storage _keys . mesIDDisplay _enabled , String ( power _user . mesIDDisplay _enabled ) ) ;
2023-07-20 19:32:15 +02:00
switchMesIDDisplay ( ) ;
} ) ;
$ ( "#hotswapEnabled" ) . on ( "input" , function ( ) {
const value = ! ! $ ( this ) . prop ( 'checked' ) ;
power _user . hotswap _enabled = value ;
2023-08-22 13:30:49 +02:00
localStorage . setItem ( storage _keys . hotswap _enabled , String ( power _user . hotswap _enabled ) ) ;
2023-07-20 19:32:15 +02:00
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 ( ) ;
} ) ;
2023-08-24 14:13:04 +02:00
$ ( "#continue_on_send" ) . on ( "input" , function ( ) {
const value = ! ! $ ( this ) . prop ( 'checked' ) ;
power _user . continue _on _send = value ;
saveSettingsDebounced ( ) ;
} ) ;
2023-08-24 00:37:44 +02:00
$ ( "#quick_continue" ) . on ( "input" , function ( ) {
2023-07-20 19:32:15 +02:00
const value = ! ! $ ( this ) . prop ( 'checked' ) ;
2023-08-24 00:37:44 +02:00
power _user . quick _continue = value ;
$ ( "#mes_continue" ) . css ( 'display' , value ? '' : 'none' ) ;
2023-07-20 19:32:15 +02:00
saveSettingsDebounced ( ) ;
} ) ;
$ ( "#trim_spaces" ) . on ( "input" , function ( ) {
const value = ! ! $ ( this ) . prop ( 'checked' ) ;
power _user . trim _spaces = value ;
saveSettingsDebounced ( ) ;
} ) ;
2023-08-04 22:49:55 +02:00
$ ( "#relaxed_api_urls" ) . on ( "input" , function ( ) {
const value = ! ! $ ( this ) . prop ( 'checked' ) ;
power _user . relaxed _api _urls = value ;
saveSettingsDebounced ( ) ;
} ) ;
2023-07-20 19:32:15 +02:00
$ ( '#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 ( ) {
2023-08-22 13:30:49 +02:00
power _user . custom _stopping _strings = String ( $ ( this ) . val ( ) ) ;
2023-07-20 19:32:15 +02:00
saveSettingsDebounced ( ) ;
} ) ;
2023-08-04 16:53:49 +02:00
$ ( "#custom_stopping_strings_macro" ) . change ( function ( ) {
2023-08-04 17:15:42 +02:00
power _user . custom _stopping _strings _macro = ! ! $ ( this ) . prop ( "checked" ) ;
2023-08-04 16:53:49 +02:00
saveSettingsDebounced ( ) ;
} ) ;
2023-07-27 23:38:43 +02:00
$ ( '#fuzzy_search_checkbox' ) . on ( 'input' , function ( ) {
power _user . fuzzy _search = ! ! $ ( this ) . prop ( 'checked' ) ;
saveSettingsDebounced ( ) ;
} ) ;
2023-08-03 13:24:45 +02:00
$ ( '#persona_show_notifications' ) . on ( 'input' , function ( ) {
power _user . persona _show _notifications = ! ! $ ( this ) . prop ( 'checked' ) ;
saveSettingsDebounced ( ) ;
} ) ;
2023-08-10 10:47:17 +02:00
$ ( '#encode_tags' ) . on ( 'input' , async function ( ) {
power _user . encode _tags = ! ! $ ( this ) . prop ( 'checked' ) ;
await reloadCurrentChat ( ) ;
saveSettingsDebounced ( ) ;
} ) ;
2023-08-12 12:10:41 +02:00
$ ( '#lazy_load' ) . on ( 'input' , function ( ) {
power _user . lazy _load = Number ( $ ( this ) . val ( ) ) ;
saveSettingsDebounced ( ) ;
} ) ;
2023-08-30 15:31:53 +02:00
$ ( '#disable_group_trimming' ) . on ( 'input' , function ( ) {
power _user . disable _group _trimming = ! ! $ ( this ) . prop ( 'checked' ) ;
saveSettingsDebounced ( ) ;
} ) ;
2023-08-27 22:20:43 +02:00
$ ( '#debug_menu' ) . on ( 'click' , function ( ) {
showDebugMenu ( ) ;
} ) ;
2023-08-29 17:04:10 +02:00
$ ( "#ui_mode_select" ) . on ( 'change' , function ( ) {
const value = $ ( this ) . find ( ':selected' ) . val ( ) ;
power _user . ui _mode = Number ( value ) ;
saveSettingsDebounced ( ) ;
switchSimpleMode ( ) ;
} ) ;
2023-08-27 22:20:43 +02:00
$ ( document ) . on ( 'click' , '#debug_table [data-debug-function]' , function ( ) {
const functionId = $ ( this ) . data ( 'debug-function' ) ;
const functionRecord = debug _functions . find ( f => f . functionId === functionId ) ;
if ( functionRecord ) {
functionRecord . func ( ) ;
} else {
console . warn ( ` Debug function ${ functionId } not found ` ) ;
}
} ) ;
2023-07-20 19:32:15 +02:00
$ ( 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 ) ;
} ) ;