Merge pull request #4096 from SillyTavern/TopbarFadeMUIAndGetWorldEntryRefactors UI performance optimizations and refactoring
Signed| @@ -55,6 +55,7 @@ | ||
| 55 | 55 | |
| 56 | 56 | /* Flashing for highlighting animation */ |
| 57 | 57 | @keyframes flash { |
| 58 | + | |
| 58 | 59 | 0%, |
| 59 | 60 | 50%, |
| 60 | 61 | 100% { |
| @@ -122,3 +123,12 @@ | ||
| 122 | 123 | border-top-color: var(--progFlashColor); |
| 123 | 124 | } |
| 124 | 125 | } |
| 126 | + | |
| 127 | +/* Scroll delay animations */ | |
| 128 | +@keyframes hide-scroll { | |
| 129 | + | |
| 130 | + from, | |
| 131 | + to { | |
| 132 | + overflow-y: hidden; | |
| 133 | + } | |
| 134 | +} | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | #rm_print_characters_block.group_overlay_mode_select .character_select { |
| 2 | 2 | transition: background-color 0.4svar(--animation-duration-3x) ease; |
| 3 | 3 | background-color: rgba(170, 170, 170, 0.15); |
| 4 | 4 | } |
| 5 | 5 | |
| @@ -18,7 +18,7 @@ | ||
| 18 | 18 | |
| 19 | 19 | #load-spinner { |
| 20 | 20 | --spinner-size: 2em; |
| 21 | 21 | transition: all 300msvar(--animation-duration-2x) ease-out; |
| 22 | 22 | opacity: 1; |
| 23 | 23 | top: calc(50% - var(--spinner-size) / 2); |
| 24 | 24 | left: calc(50% - var(--spinner-size) / 2); |
| @@ -23,7 +23,7 @@ body.login .userSelect { | ||
| 23 | 23 | width: 30%; |
| 24 | 24 | cursor: pointer; |
| 25 | 25 | margin: 5px 0; |
| 26 | 26 | transition: background-color 0.15svar(--animation-duration) ease-in-out; |
| 27 | 27 | display: flex; |
| 28 | 28 | align-items: center; |
| 29 | 29 | justify-content: center; |
| @@ -43,7 +43,7 @@ | ||
| 43 | 43 | height: 25px; |
| 44 | 44 | margin-left: 5px; |
| 45 | 45 | opacity: 0.5; |
| 46 | 46 | transition: all 250msvar(--animation-duration-2x); |
| 47 | 47 | position: unset !important; |
| 48 | 48 | } |
| 49 | 49 | |
| @@ -237,6 +237,15 @@ | ||
| 237 | 237 | top: var(--topBarBlockSize) !important; |
| 238 | 238 | left: 0 !important; |
| 239 | 239 | backdrop-filter: blur(calc(var(--SmartThemeBlurStrength) * 2)); |
| 240 | + | |
| 241 | + @starting-style { | |
| 242 | + height: 0; | |
| 243 | + } | |
| 244 | + } | |
| 245 | + | |
| 246 | + #left-nav-panel:not(.openDrawer), | |
| 247 | + #right-nav-panel:not(.openDrawer) { | |
| 248 | + height: 0; | |
| 240 | 249 | } |
| 241 | 250 | |
| 242 | 251 | /* |
| @@ -79,7 +79,7 @@ | ||
| 79 | 79 | justify-content: center; |
| 80 | 80 | margin-left: 0.25em; |
| 81 | 81 | cursor: pointer; |
| 82 | 82 | transition: 0.3svar(--animation-duration-2x) ease-in-out; |
| 83 | 83 | height: 20px; |
| 84 | 84 | width: 20px; |
| 85 | 85 | filter: drop-shadow(0px 0px 2px black); |
| @@ -239,7 +239,7 @@ | ||
| 239 | 239 | flex-direction: column; |
| 240 | 240 | justify-content: center; |
| 241 | 241 | margin-left: 0.25em; |
| 242 | 242 | transition: 0.3svar(--animation-duration-2x) ease-in-out; |
| 243 | 243 | filter: drop-shadow(0px 0px 2px black); |
| 244 | 244 | } |
| 245 | 245 | |
| @@ -172,7 +172,7 @@ | ||
| 172 | 172 | #rm_group_members .group_member:not(.disabled) .right_menu_button[data-action="disable"] { |
| 173 | 173 | opacity: 0.4; |
| 174 | 174 | filter: brightness(0.5); |
| 175 | 175 | transition: all 0.2svar(--animation-duration-2x) ease-in-out; |
| 176 | 176 | } |
| 177 | 177 | |
| 178 | 178 | /* #rm_group_members .right_menu_button[data-action="speak"]:hover, */ |
| @@ -125,7 +125,7 @@ | ||
| 125 | 125 | background-color: unset; |
| 126 | 126 | color: var(--SmartThemeBodyColor); |
| 127 | 127 | opacity: 0.5; |
| 128 | 128 | transition: opacity 200msvar(--animation-duration-2x) ease-in-out; |
| 129 | 129 | position: relative; |
| 130 | 130 | } |
| 131 | 131 | |
| @@ -203,7 +203,7 @@ | ||
| 203 | 203 | /* Styling for choice remove icon */ |
| 204 | 204 | span.select2.select2-container .select2-selection__choice__remove { |
| 205 | 205 | cursor: pointer; |
| 206 | 206 | transition: background-color 0.3svar(--animation-duration-2x); |
| 207 | 207 | color: var(--SmartThemeBodyColor); |
| 208 | 208 | background-color: var(--black50a); |
| 209 | 209 | } |
| @@ -220,7 +220,7 @@ span.select2.select2-container .select2-selection__choice__remove:hover { | ||
| 220 | 220 | |
| 221 | 221 | .select2_choice_clickable_buttonstyle+span.select2-container .select2-selection__choice__display { |
| 222 | 222 | cursor: pointer; |
| 223 | 223 | transition: background-color 0.3svar(--animation-duration-2x); |
| 224 | 224 | color: var(--SmartThemeBodyColor); |
| 225 | 225 | background-color: var(--black50a); |
| 226 | 226 | white-space: break-spaces; |
| @@ -332,6 +332,10 @@ | ||
| 332 | 332 | overflow: hidden; |
| 333 | 333 | } |
| 334 | 334 | |
| 335 | +.overflowYScroll { | |
| 336 | + overflow-y: scroll; | |
| 337 | +} | |
| 338 | + | |
| 335 | 339 | .padding0 { |
| 336 | 340 | padding: 0; |
| 337 | 341 | } |
| @@ -480,7 +484,7 @@ | ||
| 480 | 484 | } |
| 481 | 485 | |
| 482 | 486 | .hoverglow { |
| 483 | 487 | transition: opacity 200msvar(--animation-duration-2x); |
| 484 | 488 | } |
| 485 | 489 | |
| 486 | 490 | .hoverglow:hover { |
| @@ -167,7 +167,7 @@ | ||
| 167 | 167 | } |
| 168 | 168 | |
| 169 | 169 | .rm_tag_filter .tag.actionable { |
| 170 | 170 | transition: opacity 200msvar(--animation-duration-2x); |
| 171 | 171 | } |
| 172 | 172 | |
| 173 | 173 | .rm_tag_filter .tag:hover { |
| @@ -19,6 +19,7 @@ body:not(.tts) #ttsExtensionNarrateAll { | ||
| 19 | 19 | } |
| 20 | 20 | |
| 21 | 21 | body.no-hotswap .hotswap, |
| 22 | +body.no-hotswap .hotswap~hr, | |
| 22 | 23 | body.no-timer .mes_timer, |
| 23 | 24 | body.no-timestamps .timestamp, |
| 24 | 25 | body.no-tokenCount .tokenCounterDisplay, |
| @@ -28,6 +29,12 @@ body.hideChatAvatars .mesAvatarWrapper .avatar { | ||
| 28 | 29 | display: none !important; |
| 29 | 30 | } |
| 30 | 31 | |
| 32 | +body.no-hotswap #CharListButtonAndHotSwaps .flex-container { | |
| 33 | + flex-wrap: nowrap; | |
| 34 | + align-items: flex-end; | |
| 35 | + flex-flow: row; | |
| 36 | +} | |
| 37 | + | |
| 31 | 38 | body.hideChatAvatars .last_mes:not(.smallSysMes) { |
| 32 | 39 | padding-bottom: 20px !important; |
| 33 | 40 | } |
| @@ -198,7 +198,11 @@ | ||
| 198 | 198 | } |
| 199 | 199 | |
| 200 | 200 | .world_entry { |
| 201 | 201 | transition: opacity 500msvar(--animation-duration-3x); |
| 202 | +} | |
| 203 | + | |
| 204 | +.world_entry_edit { | |
| 205 | + display: contents; | |
| 202 | 206 | } |
| 203 | 207 | |
| 204 | 208 | .disabledWIEntry { |
| @@ -267,7 +271,7 @@ select.keyselect+span.select2-container .select2-selection--multiple { | ||
| 267 | 271 | |
| 268 | 272 | opacity: 0.5; |
| 269 | 273 | color: var(--SmartThemeBodyColor); |
| 270 | 274 | transition: opacity 0.3svar(--animation-duration-2x); |
| 271 | 275 | } |
| 272 | 276 | |
| 273 | 277 | .switch_input_type_icon:hover { |
| @@ -5457,10 +5457,12 @@ | ||
| 5457 | 5457 | <div class="right_menu_button fa-solid fa-list-ul" id="rm_button_characters" title="Select/Create Characters" data-i18n="[title]Select/Create Characters"></div> |
| 5458 | 5458 | </div> |
| 5459 | 5459 | <div id="HotSwapWrapper" class="alignitemscenter flex-container margin0auto wide100p"> |
| 5460 | 5460 | <div class="hotswap avatars_inline scroll-reset-container expander" data-i18n="[no_favs]Favorite characters to add them to HotSwaps" no_favs="Favorite characters to add them to HotSwaps"></div> |
| 5461 | 5461 | </div> |
| 5462 | + <hr class="wide100p"> | |
| 5462 | 5463 | </div> |
| 5463 | 5464 | <hr/div> |
| 5465 | + | |
| 5464 | 5466 | <!-- this div structure must be preserved until group peeking can adjust --> |
| 5465 | 5467 | <div id="rm_PinAndTabs"> |
| 5466 | 5468 | <div id="right-nav-panel-tabs" class=""> |
| @@ -5485,6 +5487,8 @@ | ||
| 5485 | 5487 | </div> |
| 5486 | 5488 | </div> |
| 5487 | 5489 | <!-- end group peeking cope structure--> |
| 5490 | + | |
| 5491 | + <div class="scrollableInner"> | |
| 5488 | 5492 | <div name="Solo Char Create/Edit Panel" id="rm_ch_create_block" class="right_menu flex-container flexFlowColumn" style="display: none;"> |
| 5489 | 5493 | <form id="form_create" action="javascript:void(null);" method="post" enctype="multipart/form-data"> |
| 5490 | 5494 | <div id="avatar-and-name-block"> |
| @@ -5820,6 +5824,7 @@ | ||
| 5820 | 5824 | </div> |
| 5821 | 5825 | <div id="rm_print_characters_block" class="flexFlowColumn"></div> |
| 5822 | 5826 | </div> |
| 5827 | + </div> | |
| 5823 | 5828 | </nav> |
| 5824 | 5829 | </div> |
| 5825 | 5830 | </div> |
| @@ -6195,79 +6200,7 @@ | ||
| 6195 | 6200 | </div> |
| 6196 | 6201 | </div> |
| 6197 | 6202 | <div id="entry_edit_template" class="template_element"> |
| 6198 | 6203 | <div class="world_entryworld_entry_edit"> |
| 6199 | - <form class="world_entry_form wi-card-entry"> | |
| 6200 | - <div class="inline-drawer wide100p"> | |
| 6201 | - <div class="inline-drawer-header gap5px padding0"> | |
| 6202 | - <span class="drag-handle">☰</span> | |
| 6203 | - <div class="gap5px world_entry_thin_controls wide100p alignitemscenter"> | |
| 6204 | - <div class="inline-drawer-toggle fa-fw fa-solid fa-circle-chevron-down inline-drawer-icon down"></div> | |
| 6205 | - <div class="fa-solid fa-toggle-on killSwitch" name="entryKillSwitch" data-i18n="[title]Toggle entry's active state." title="Toggle entry's active state."></div> | |
| 6206 | - <div class="flex-container alignitemscenter wide100p"> | |
| 6207 | - <div class="WIEntryTitleAndStatus flex-container flex1 alignitemscenter"> | |
| 6208 | - <div class="flex-container flex1"> | |
| 6209 | - <textarea class="text_pole" rows="1" name="comment" data-i18n="[placeholder]Entry Title/Memo" placeholder="Entry Title/Memo"></textarea> | |
| 6210 | - </div> | |
| 6211 | - <!-- <span class="world_entry_form_position_value"></span> --> | |
| 6212 | - <select data-i18n="[title]WI Entry Status:🔵 Constant🟢 Normal🔗 Vectorized" title="WI Entry Status: 🔵 Constant 🟢 Normal 🔗 Vectorized" name="entryStateSelector" class="text_pole widthNatural margin0"> | |
| 6213 | - <option value="constant" title="Constant" data-i18n="[title]WI_Entry_Status_Constant">🔵</option> | |
| 6214 | - <option value="normal" title="Normal" data-i18n="[title]WI_Entry_Status_Normal">🟢</option> | |
| 6215 | - <option value="vectorized" title="Vectorized" data-i18n="[title]WI_Entry_Status_Vectorized">🔗</option> | |
| 6216 | - </select> | |
| 6217 | - </div> | |
| 6218 | - <div class="WIEnteryHeaderControls flex-container"> | |
| 6219 | - <div name="PositionBlock" class="world_entry_form_control world_entry_form_radios wi-enter-footer-text"> | |
| 6220 | - <label for="position" class="WIEntryHeaderTitleMobile" data-i18n="Position:">Position:</label> | |
| 6221 | - <select name="position" class="text_pole widthNatural margin0" data-i18n="[title]T_Position" title="↑Char: Before Character Definitions ↓Char: After Character Definitions ↑EM: Before Example Messages ↓EM: After Example Messages ↑AN: Before Author's Note ↓AN: After Author's Note @D ⚙️: at Depth (System) @D 👤: at Depth (User) @D 🤖: at Depth (Assistant)"> | |
| 6222 | - <option value="0" data-role="" data-i18n="Before Char Defs"> | |
| 6223 | - ↑Char | |
| 6224 | - </option> | |
| 6225 | - <option value="1" data-role="" data-i18n="After Char Defs"> | |
| 6226 | - ↓Char | |
| 6227 | - </option> | |
| 6228 | - <option value="5" data-role="" data-i18n="Before EM"> | |
| 6229 | - ↑EM | |
| 6230 | - </option> | |
| 6231 | - <option value="6" data-role="" data-i18n="After EM"> | |
| 6232 | - ↓EM | |
| 6233 | - </option> | |
| 6234 | - <option value="2" data-role="" data-i18n="Before AN"> | |
| 6235 | - ↑AN | |
| 6236 | - </option> | |
| 6237 | - <option value="3" data-role="" data-i18n="After AN"> | |
| 6238 | - ↓AN | |
| 6239 | - </option> | |
| 6240 | - <option value="4" data-role="0" data-i18n="at Depth System"> | |
| 6241 | - @D ⚙️ | |
| 6242 | - </option> | |
| 6243 | - <option value="4" data-role="1" data-i18n="at Depth User"> | |
| 6244 | - @D 👤 | |
| 6245 | - </option> | |
| 6246 | - <option value="4" data-role="2" data-i18n="at Depth AI"> | |
| 6247 | - @D 🤖 | |
| 6248 | - </option> | |
| 6249 | - </select> | |
| 6250 | - </div> | |
| 6251 | - <div class="world_entry_form_control wi-enter-footer-text flex-container flexNoGap"> | |
| 6252 | - <label for="depth" class="WIEntryHeaderTitleMobile" data-i18n="Depth:">Depth:</label> | |
| 6253 | - <input title="Depth" class="text_pole wideMax100px margin0" type="number" name="depth" data-i18n="[title]Depth" placeholder="" min="0" max="9999" /> | |
| 6254 | - </div> | |
| 6255 | - <div class="world_entry_form_control wi-enter-footer-text flex-container flexNoGap"> | |
| 6256 | - <label for="order" class="WIEntryHeaderTitleMobile" data-i18n="Order:">Order:</label> | |
| 6257 | - <input title="Order" data-i18n="[title]Order" class="text_pole wideMax100px margin0" type="number" name="order" placeholder="" min="0" max="9999" /> | |
| 6258 | - </div> | |
| 6259 | - <div class="world_entry_form_control wi-enter-footer-text flex-container flexNoGap probabilityContainer"> | |
| 6260 | - <label for="order" class="WIEntryHeaderTitleMobile" data-i18n="Trigger %:">Trigger %:</label> | |
| 6261 | - <input title="Probability" data-i18n="[title]Probability" class="text_pole wideMax100px margin0" type="number" name="probability" placeholder="" min="0" max="100" /> | |
| 6262 | - </div> | |
| 6263 | - </div> | |
| 6264 | - </div> | |
| 6265 | - </div> | |
| 6266 | - <i class="menu_button move_entry_button fa-solid fa-right-left" title="Move Entry to Another Lorebook" data-i18n="[title]Move Entry to Another Lorebook"></i> | |
| 6267 | - <i class="menu_button duplicate_entry_button fa-solid fa-paste" title="Duplicate world info entry" data-i18n="[title]Duplicate world info entry" type="submit" value=""></i> | |
| 6268 | - <i class="menu_button delete_entry_button fa-solid fa-trash-can" title="Delete world info entry" data-i18n="[title]Delete world info entry" type="submit" value=""></i> | |
| 6269 | - </div> | |
| 6270 | - <div class="inline-drawer-content flex-container paddingBottom5px wide100p"> | |
| 6271 | 6204 | <div class="flex-container wide100p alignitemscenter"> |
| 6272 | 6205 | <div name="keywordsAndLogicBlock" class="flex-container wide100p alignitemscenter"> |
| 6273 | 6206 | <div class="world_entry_form_control keyprimary flex1"> |
| @@ -6364,13 +6297,13 @@ | ||
| 6364 | 6297 | </span> |
| 6365 | 6298 | <div> |
| 6366 | 6299 | <label class="checkbox flex-container alignitemscenter flexNoGap"> |
| 6367 | 6300 | <input type="checkbox" name="exclude_recursionexcludeRecursion" /> |
| 6368 | 6301 | <span data-i18n="Non-recursable (will not be activated by another)"> |
| 6369 | 6302 | Non-recursable (will not be activated by another) |
| 6370 | 6303 | </span> |
| 6371 | 6304 | </label> |
| 6372 | 6305 | <label class="checkbox flex-container alignitemscenter flexNoGap"> |
| 6373 | 6306 | <input type="checkbox" name="prevent_recursionpreventRecursion" /> |
| 6374 | 6307 | <span data-i18n="Prevent further recursion (this entry will not activate others)"> |
| 6375 | 6308 | Prevent further recursion (will not activate others) |
| 6376 | 6309 | </span> |
| @@ -6559,6 +6492,81 @@ | ||
| 6559 | 6492 | </div> |
| 6560 | 6493 | </div> |
| 6561 | 6494 | </div> |
| 6495 | + <div class="world_entry"> | |
| 6496 | + <form class="world_entry_form wi-card-entry"> | |
| 6497 | + <div class="inline-drawer wide100p"> | |
| 6498 | + <div class="inline-drawer-header gap5px padding0"> | |
| 6499 | + <span class="drag-handle">☰</span> | |
| 6500 | + <div class="gap5px world_entry_thin_controls wide100p alignitemscenter"> | |
| 6501 | + <div class="inline-drawer-toggle fa-fw fa-solid fa-circle-chevron-down inline-drawer-icon down"></div> | |
| 6502 | + <div class="fa-solid fa-toggle-on killSwitch" name="entryKillSwitch" data-i18n="[title]Toggle entry's active state." title="Toggle entry's active state."></div> | |
| 6503 | + <div class="flex-container alignitemscenter wide100p"> | |
| 6504 | + <div class="WIEntryTitleAndStatus flex-container flex1 alignitemscenter"> | |
| 6505 | + <div class="flex-container flex1"> | |
| 6506 | + <textarea class="text_pole" rows="1" name="comment" data-i18n="[placeholder]Entry Title/Memo" placeholder="Entry Title/Memo"></textarea> | |
| 6507 | + </div> | |
| 6508 | + <!-- <span class="world_entry_form_position_value"></span> --> | |
| 6509 | + <select data-i18n="[title]WI Entry Status:🔵 Constant🟢 Normal🔗 Vectorized" title="WI Entry Status: 🔵 Constant 🟢 Normal 🔗 Vectorized" name="entryStateSelector" class="text_pole widthNatural margin0"> | |
| 6510 | + <option value="constant" title="Constant" data-i18n="[title]WI_Entry_Status_Constant">🔵</option> | |
| 6511 | + <option value="normal" title="Normal" data-i18n="[title]WI_Entry_Status_Normal">🟢</option> | |
| 6512 | + <option value="vectorized" title="Vectorized" data-i18n="[title]WI_Entry_Status_Vectorized">🔗</option> | |
| 6513 | + </select> | |
| 6514 | + </div> | |
| 6515 | + <div class="WIEnteryHeaderControls flex-container"> | |
| 6516 | + <div name="PositionBlock" class="world_entry_form_control world_entry_form_radios wi-enter-footer-text"> | |
| 6517 | + <label for="position" class="WIEntryHeaderTitleMobile" data-i18n="Position:">Position:</label> | |
| 6518 | + <select name="position" class="text_pole widthNatural margin0" data-i18n="[title]T_Position" title="↑Char: Before Character Definitions ↓Char: After Character Definitions ↑EM: Before Example Messages ↓EM: After Example Messages ↑AN: Before Author's Note ↓AN: After Author's Note @D ⚙️: at Depth (System) @D 👤: at Depth (User) @D 🤖: at Depth (Assistant)"> | |
| 6519 | + <option value="0" data-role="" data-i18n="Before Char Defs"> | |
| 6520 | + ↑Char | |
| 6521 | + </option> | |
| 6522 | + <option value="1" data-role="" data-i18n="After Char Defs"> | |
| 6523 | + ↓Char | |
| 6524 | + </option> | |
| 6525 | + <option value="5" data-role="" data-i18n="Before EM"> | |
| 6526 | + ↑EM | |
| 6527 | + </option> | |
| 6528 | + <option value="6" data-role="" data-i18n="After EM"> | |
| 6529 | + ↓EM | |
| 6530 | + </option> | |
| 6531 | + <option value="2" data-role="" data-i18n="Before AN"> | |
| 6532 | + ↑AN | |
| 6533 | + </option> | |
| 6534 | + <option value="3" data-role="" data-i18n="After AN"> | |
| 6535 | + ↓AN | |
| 6536 | + </option> | |
| 6537 | + <option value="4" data-role="0" data-i18n="at Depth System"> | |
| 6538 | + @D ⚙️ | |
| 6539 | + </option> | |
| 6540 | + <option value="4" data-role="1" data-i18n="at Depth User"> | |
| 6541 | + @D 👤 | |
| 6542 | + </option> | |
| 6543 | + <option value="4" data-role="2" data-i18n="at Depth AI"> | |
| 6544 | + @D 🤖 | |
| 6545 | + </option> | |
| 6546 | + </select> | |
| 6547 | + </div> | |
| 6548 | + <div class="world_entry_form_control wi-enter-footer-text flex-container flexNoGap"> | |
| 6549 | + <label for="depth" class="WIEntryHeaderTitleMobile" data-i18n="Depth:">Depth:</label> | |
| 6550 | + <input title="Depth" class="text_pole wideMax100px margin0" type="number" name="depth" data-i18n="[title]Depth" placeholder="" min="0" max="9999" /> | |
| 6551 | + </div> | |
| 6552 | + <div class="world_entry_form_control wi-enter-footer-text flex-container flexNoGap"> | |
| 6553 | + <label for="order" class="WIEntryHeaderTitleMobile" data-i18n="Order:">Order:</label> | |
| 6554 | + <input title="Order" data-i18n="[title]Order" class="text_pole wideMax100px margin0" type="number" name="order" placeholder="" min="0" max="9999" /> | |
| 6555 | + </div> | |
| 6556 | + <div class="world_entry_form_control wi-enter-footer-text flex-container flexNoGap probabilityContainer"> | |
| 6557 | + <label for="order" class="WIEntryHeaderTitleMobile" data-i18n="Trigger %:">Trigger %:</label> | |
| 6558 | + <input title="Probability" data-i18n="[title]Probability" class="text_pole wideMax100px margin0" type="number" name="probability" placeholder="" min="0" max="100" /> | |
| 6559 | + </div> | |
| 6560 | + </div> | |
| 6561 | + </div> | |
| 6562 | + </div> | |
| 6563 | + <i class="menu_button move_entry_button fa-solid fa-right-left" title="Move Entry to Another Lorebook" data-i18n="[title]Move Entry to Another Lorebook"></i> | |
| 6564 | + <i class="menu_button duplicate_entry_button fa-solid fa-paste" title="Duplicate world info entry" data-i18n="[title]Duplicate world info entry" type="submit" value=""></i> | |
| 6565 | + <i class="menu_button delete_entry_button fa-solid fa-trash-can" title="Delete world info entry" data-i18n="[title]Delete world info entry" type="submit" value=""></i> | |
| 6566 | + </div> | |
| 6567 | + <div class="inline-drawer-content inline-drawer-outlet flex-container paddingBottom5px wide100p "> | |
| 6568 | + <!-- Outlet for world_entry_edit --> | |
| 6569 | + </div> | |
| 6562 | 6570 | </div> |
| 6563 | 6571 | </form> |
| 6564 | 6572 | </div> |
| @@ -10,7 +10,6 @@ import { | ||
| 10 | 10 | SVGInject, |
| 11 | 11 | Popper, |
| 12 | 12 | initLibraryShims, |
| 13 | - slideToggle, | |
| 14 | 13 | default as libs, |
| 15 | 14 | } from './lib.js'; |
| 16 | 15 | |
| @@ -10320,86 +10319,43 @@ function doDrawerOpenClick() { | ||
| 10320 | 10319 | /** |
| 10321 | 10320 | * Event handler to open or close a navbar drawer when a navbar icon is clicked. |
| 10322 | 10321 | * Handles click events on .drawer-toggle elements. |
| 10323 | 10322 | * @returns {Promise<void>} |
| 10324 | 10323 | */ |
| 10325 | 10324 | export async function doNavbarIconClick() { |
| 10326 | 10325 | const icon = $(this).find('.drawer-icon'); |
| 10327 | 10326 | const drawer = $(this).parent().find('.drawer-content'); |
| 10328 | - if (drawer.hasClass('resizing')) { return; } | |
| 10329 | 10327 | const drawerWasOpenAlready = $(this).parent().find('.drawer-content').hasClass('openDrawer'); |
| 10330 | 10328 | const targetDrawerID = $(this).parent().find('.drawer-content').attr('id'); |
| 10331 | - const pinnedDrawerClicked = drawer.hasClass('pinnedOpen'); | |
| 10329 | + | |
| 10332 | - | |
| 10330 | + if (!drawerWasOpenAlready) { | |
| 10333 | - if (!drawerWasOpenAlready) { //to open the drawer | |
| 10331 | + const $openDrawers = $('.openDrawer:not(.pinnedOpen)'); | |
| 10334 | - $('.openDrawer').not('.pinnedOpen').addClass('resizing').each((_, el) => { | |
| 10332 | + const $openIcons = $('.openIcon:not(.drawerPinnedOpen)'); | |
| 10335 | - slideToggle(el, { | |
| 10333 | + for (const iconEl of $openIcons) { | |
| 10336 | - ...getSlideToggleOptions(), | |
| 10334 | + $(iconEl).toggleClass('closedIcon openIcon'); | |
| 10337 | - onAnimationEnd: function (el) { | |
| 10335 | + } | |
| 10338 | - el.closest('.drawer-content').classList.remove('resizing'); | |
| 10336 | + for (const el of $openDrawers) { | |
| 10339 | - }, | |
| 10337 | + $(el).toggleClass('closedDrawer openDrawer'); | |
| 10340 | - }); | |
| 10338 | + } | |
| 10341 | - }); | |
| 10339 | + if ($openDrawers.length) { | |
| 10342 | - $('.openIcon').not('.drawerPinnedOpen').toggleClass('closedIcon openIcon'); | |
| 10340 | + await delay(animation_duration); | |
| 10343 | - $('.openDrawer').not('.pinnedOpen').toggleClass('closedDrawer openDrawer'); | |
| 10341 | + } | |
| 10344 | 10342 | icon.toggleClass('openIcon closedIcon'); |
| 10345 | 10343 | drawer.toggleClass('openDrawer closedDrawer'); |
| 10346 | 10344 | |
| 10347 | - //console.log(targetDrawerID); | |
| 10348 | 10345 | if (targetDrawerID === 'right-nav-panel') { |
| 10349 | - $(this).closest('.drawer').find('.drawer-content').addClass('resizing').each((_, el) => { | |
| 10350 | - slideToggle(el, { | |
| 10351 | - ...getSlideToggleOptions(), | |
| 10352 | - elementDisplayStyle: 'flex', | |
| 10353 | - onAnimationEnd: function (el) { | |
| 10354 | - el.closest('.drawer-content').classList.remove('resizing'); | |
| 10355 | 10346 | favsToHotswap(); |
| 10356 | 10347 | $('#rm_print_characters_block').trigger('scroll'); |
| 10357 | - }, | |
| 10358 | - }); | |
| 10359 | - }); | |
| 10360 | - } else { | |
| 10361 | - $(this).closest('.drawer').find('.drawer-content').addClass('resizing').each((_, el) => { | |
| 10362 | - slideToggle(el, { | |
| 10363 | - ...getSlideToggleOptions(), | |
| 10364 | - onAnimationEnd: function (el) { | |
| 10365 | - el.closest('.drawer-content').classList.remove('resizing'); | |
| 10366 | - }, | |
| 10367 | - }); | |
| 10368 | - }); | |
| 10369 | 10348 | } |
| 10370 | 10349 | |
| 10371 | 10350 | // Set the height of "autoSetHeight" textareas within the drawer to their scroll height |
| 10372 | 10351 | if (!CSS.supports('field-sizing', 'content')) { |
| 10373 | 10352 | const textareas = $(this).closest('.drawer').find('.drawer-content textarea.autoSetHeight').each(async function () {; |
| 10374 | - await resetScrollHeight($(this)); | |
| 10353 | + for (const textarea of textareas) { | |
| 10375 | - return; | |
| 10354 | + await resetScrollHeight($(textarea)); | |
| 10376 | - }); | |
| 10377 | 10355 | } |
| 10378 | - | |
| 10379 | - } else if (drawerWasOpenAlready) { //to close manually | |
| 10380 | - icon.toggleClass('closedIcon openIcon'); | |
| 10381 | - | |
| 10382 | - if (pinnedDrawerClicked) { | |
| 10383 | - $(drawer).addClass('resizing').each((_, el) => { | |
| 10384 | - slideToggle(el, { | |
| 10385 | - ...getSlideToggleOptions(), | |
| 10386 | - onAnimationEnd: function (el) { | |
| 10387 | - el.classList.remove('resizing'); | |
| 10388 | - }, | |
| 10389 | - }); | |
| 10390 | - }); | |
| 10391 | 10356 | } |
| 10392 | - else { | |
| 10357 | + } else if (drawerWasOpenAlready) { | |
| 10393 | - $('.openDrawer').not('.pinnedOpen').addClass('resizing').each((_, el) => { | |
| 10358 | + icon.toggleClass('closedIcon openIcon'); | |
| 10394 | - slideToggle(el, { | |
| 10395 | - ...getSlideToggleOptions(), | |
| 10396 | - onAnimationEnd: function (el) { | |
| 10397 | - el.closest('.drawer-content').classList.remove('resizing'); | |
| 10398 | - }, | |
| 10399 | - }); | |
| 10400 | - }); | |
| 10401 | - } | |
| 10402 | - | |
| 10403 | 10359 | drawer.toggleClass('closedDrawer openDrawer'); |
| 10404 | 10360 | } |
| 10405 | 10361 | } |
| @@ -12028,8 +11984,8 @@ jQuery(async function () { | ||
| 12028 | 11984 | |
| 12029 | 11985 | $('.drawer-toggle').on('click', doNavbarIconClick); |
| 12030 | 11986 | |
| 12031 | 11987 | $('html').on('touchstart mousedown', async function (e) { |
| 12032 | 11988 | varconst clickTarget = $(e.target); |
| 12033 | 11989 | |
| 12034 | 11990 | if (isExportPopupOpen |
| 12035 | 11991 | && clickTarget.closest('#export_button').length == 0 |
| @@ -12050,28 +12006,21 @@ jQuery(async function () { | ||
| 12050 | 12006 | '#toast-container', |
| 12051 | 12007 | '.select2-results', |
| 12052 | 12008 | ]; |
| 12009 | + | |
| 12053 | 12010 | for (const id of forbiddenTargets) { |
| 12054 | 12011 | if (clickTarget.closest(id).length > 0) { |
| 12055 | 12012 | return; |
| 12056 | 12013 | } |
| 12057 | 12014 | } |
| 12058 | 12015 | |
| 12059 | - var targetParentHasOpenDrawer = clickTarget.parents('.openDrawer').length; | |
| 12016 | + // This autocloses open drawers that are not pinned if a click happens inside the app which does not target them. | |
| 12060 | - if (clickTarget.hasClass('drawer-icon') == false && !clickTarget.hasClass('openDrawer')) { | |
| 12017 | + const targetParentHasOpenDrawer = clickTarget.parents('.openDrawer').length; | |
| 12061 | - if ($('.openDrawer').length !== 0) { | |
| 12018 | + if (!clickTarget.hasClass('drawer-icon') && !clickTarget.hasClass('openDrawer')) { | |
| 12062 | - if (targetParentHasOpenDrawer === 0) { | |
| 12019 | + const $openDrawers = $('.openDrawer').not('.pinnedOpen'); | |
| 12063 | - //console.log($('.openDrawer').not('.pinnedOpen').length); | |
| 12020 | + if ($openDrawers.length && targetParentHasOpenDrawer === 0) { | |
| 12064 | - $('.openDrawer').not('.pinnedOpen').addClass('resizing').each((_, el) => { | |
| 12021 | + // Toggle icon and drawer classes | |
| 12065 | - slideToggle(el, { | |
| 12066 | - ...getSlideToggleOptions(), | |
| 12067 | - onAnimationEnd: (el) => { | |
| 12068 | - el.closest('.drawer-content').classList.remove('resizing'); | |
| 12069 | - }, | |
| 12070 | - }); | |
| 12071 | - }); | |
| 12072 | 12022 | $('.openIcon').not('.drawerPinnedOpen').toggleClass('closedIcon openIcon'); |
| 12073 | 12023 | $('.openDrawer').not('.pinnedOpen')openDrawers.toggleClass('closedDrawer openDrawer'); |
| 12074 | - } | |
| 12075 | 12024 | } |
| 12076 | 12025 | } |
| 12077 | 12026 | }); |
| @@ -12085,6 +12034,7 @@ jQuery(async function () { | ||
| 12085 | 12034 | const drawerContent = drawer.find('>.inline-drawer-content'); |
| 12086 | 12035 | icon.toggleClass('down up'); |
| 12087 | 12036 | icon.toggleClass('fa-circle-chevron-down fa-circle-chevron-up'); |
| 12037 | + drawer.trigger('inline-drawer-toggle'); | |
| 12088 | 12038 | drawerContent.stop().slideToggle({ |
| 12089 | 12039 | complete: () => { |
| 12090 | 12040 | $(this).css('height', ''); |
| @@ -12181,7 +12131,7 @@ jQuery(async function () { | ||
| 12181 | 12131 | if (!(e.target instanceof HTMLElement)) return; |
| 12182 | 12132 | if (e.target.matches('#OpenAllWIEntries')) { |
| 12183 | 12133 | document.querySelectorAll('#world_popup_entries_list .inline-drawer').forEach((/** @type {HTMLElement} */ drawer) => { |
| 12184 | 12134 | delay(0).then(() => toggleDrawer(drawer, true)); |
| 12185 | 12135 | }); |
| 12186 | 12136 | } else if (e.target.matches('#CloseAllWIEntries')) { |
| 12187 | 12137 | document.querySelectorAll('#world_popup_entries_list .inline-drawer').forEach((/** @type {HTMLElement} */ drawer) => { |
| @@ -1,4 +1,4 @@ | ||
| 1 | 1 | import { DOMPurify, Bowser, slideToggle } from '../lib.js'; |
| 2 | 2 | |
| 3 | 3 | import { |
| 4 | 4 | characters, |
| @@ -19,7 +19,7 @@ import { | ||
| 19 | 19 | menu_type, |
| 20 | 20 | substituteParams, |
| 21 | 21 | sendTextareaMessage, |
| 22 | 22 | getSlideToggleOptionsdoNavbarIconClick, |
| 23 | 23 | } from '../script.js'; |
| 24 | 24 | |
| 25 | 25 | import { |
| @@ -473,54 +473,72 @@ const saveUserInputDebounced = debounce(saveUserInput); | ||
| 473 | 473 | |
| 474 | 474 | // Make the DIV element draggable: |
| 475 | 475 | |
| 476 | -export function dragElement(elmnt) { | |
| 476 | +/** | |
| 477 | - var isHeaderBeingDragged = false; | |
| 477 | + * Make the given element draggable. This is used for Moving UI. | |
| 478 | - var isMouseDown = false; | |
| 478 | + * @param {JQuery} $elmnt - The element to make draggable. | |
| 479 | + */ | |
| 480 | +export function dragElement($elmnt) { | |
| 481 | + let actionType = null; // "drag" or "resize" | |
| 482 | + let isMouseDown = false; | |
| 479 | 483 | |
| 480 | 484 | varlet pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0; |
| 481 | 485 | varlet height, width, top, left, right, bottom, |
| 482 | 486 | maxX, maxY, winHeight, winWidth, |
| 483 | 487 | topbar, topBarFirstX, topBarLastY; |
| 484 | 488 | |
| 485 | 489 | varconst elmntName = $elmnt.attr('id'); |
| 486 | - console.debug(`dragElement called for ${elmntName}`); | |
| 487 | 490 | const elmntNameEscaped = $.escapeSelector(elmntName); |
| 488 | 491 | const $elmntHeader = $(`#${elmntNameEscaped}header`); |
| 489 | 492 | |
| 490 | - if (elmntHeader.length) { | |
| 493 | + // Helper: Save position/size to state and emit events | |
| 491 | - elmntHeader.off('mousedown').on('mousedown', (e) => { //listener for drag handle repositioning | |
| 494 | + function savePositionAndSize() { | |
| 492 | - isHeaderBeingDragged = true; | |
| 495 | + if (!power_user.movingUIState[elmntName]) power_user.movingUIState[elmntName] = {}; | |
| 493 | - isMouseDown = true; | |
| 496 | + power_user.movingUIState[elmntName].top = top; | |
| 494 | - observer.observe(elmnt.get(0), { attributes: true, attributeFilter: ['style'] }); | |
| 497 | + power_user.movingUIState[elmntName].left = left; | |
| 495 | - dragMouseDown(e); | |
| 498 | + power_user.movingUIState[elmntName].right = right; | |
| 496 | - }); | |
| 499 | + power_user.movingUIState[elmntName].bottom = bottom; | |
| 497 | - $(elmnt).off('mousedown').on('mousedown', () => { //listener for resize | |
| 500 | + power_user.movingUIState[elmntName].margin = 'unset'; | |
| 498 | - isMouseDown = true; | |
| 501 | + if (actionType === 'resize') { | |
| 499 | - observer.observe(elmnt.get(0), { attributes: true, attributeFilter: ['style'] }); | |
| 502 | + power_user.movingUIState[elmntName].width = width; | |
| 500 | - }); | |
| 503 | + power_user.movingUIState[elmntName].height = height; | |
| 504 | + eventSource.emit('resizeUI', elmntName); | |
| 505 | + } | |
| 506 | + saveSettingsDebounced(); | |
| 501 | 507 | } |
| 502 | 508 | |
| 509 | + // Helper: Clamp element within viewport | |
| 510 | + function clampToViewport() { | |
| 511 | + if (top <= 0) $elmnt.css('top', '0px'); | |
| 512 | + else if (maxY >= winHeight) $elmnt.css('top', winHeight - maxY + top - 1 + 'px'); | |
| 513 | + if (left <= 0) $elmnt.css('left', '0px'); | |
| 514 | + else if (maxX >= winWidth) $elmnt.css('left', winWidth - maxX + left - 1 + 'px'); | |
| 515 | + } | |
| 516 | + | |
| 517 | + // Observer for style changes (position/size) | |
| 503 | 518 | const observer = new MutationObserver((mutations) => { |
| 504 | 519 | const $target = $(mutations[0].target); |
| 505 | - if (!$(target).is(':visible') //abort if element is invisible | |
| 520 | + if ( | |
| 506 | - || $(target).hasClass('resizing') //being auto-resized by other JS code | |
| 521 | + !$target.is(':visible') || | |
| 507 | - || Number((String(target.height).replace('px', ''))) < 50 //too short | |
| 522 | + $target.hasClass('resizing') || | |
| 508 | - || Number((String(target.width).replace('px', ''))) < 50 //too narrow | |
| 523 | + $target.height() < 50 || | |
| 509 | - || power_user.movingUI === false // if MUI is not turned on | |
| 524 | + $target.width() < 50 || | |
| 510 | - || isMobile() // if it's a mobile screen | |
| 525 | + power_user.movingUI === false || | |
| 526 | + isMobile() || | |
| 527 | + !isMouseDown | |
| 511 | 528 | ) { |
| 529 | + observer.disconnect(); | |
| 512 | 530 | return; |
| 513 | 531 | } |
| 514 | 532 | |
| 515 | 533 | const style = getComputedStyle($target[0]); |
| 516 | 534 | height = parseInt(style.height); |
| 517 | 535 | width = parseInt(style.width); |
| 518 | 536 | top = parseInt(style.top); |
| 519 | 537 | left = parseInt(style.left); |
| 520 | 538 | right = parseInt(style.right); |
| 521 | 539 | bottom = parseInt(style.bottom); |
| 522 | 540 | maxX = parseInt(width + left); |
| 523 | 541 | maxY = parseInt(height + top); |
| 524 | 542 | winWidth = window.innerWidth; |
| 525 | 543 | winHeight = window.innerHeight; |
| 526 | 544 | |
| @@ -529,182 +547,119 @@ export function dragElement(elmnt) { | ||
| 529 | 547 | topBarFirstX = parseInt(topbarstyle.marginInline); |
| 530 | 548 | topBarLastY = parseInt(topbarstyle.height); |
| 531 | 549 | |
| 532 | - //prepare an empty poweruser object for the item being altered if we don't have one already | |
| 550 | + // Prepare state object if missing | |
| 533 | 551 | if (!power_user.movingUIState[elmntName]) power_user.movingUIState[elmntName] = {}; |
| 534 | - console.debug(`adding config property for ${elmntName}`); | |
| 535 | - power_user.movingUIState[elmntName] = {}; | |
| 536 | - } | |
| 537 | 552 | |
| 538 | - //handle resizing | |
| 553 | + if (actionType === 'resize') { | |
| 539 | - if (!isHeaderBeingDragged && isMouseDown) { //if user is dragging the resize handle (not in header) | |
| 540 | - let imgHeight, imgWidth, imageAspectRatio; | |
| 541 | 554 | let containerAspectRatio = height / width; |
| 542 | - | |
| 555 | + if ($elmnt.attr('id').startsWith('zoomFor_')) { | |
| 543 | - //force aspect ratio for zoomed avatars | |
| 556 | + const zoomedAvatarImage = $elmnt.find('.zoomed_avatar_img'); | |
| 544 | - if ($(elmnt).attr('id').startsWith('zoomFor_')) { | |
| 557 | + const imgHeight = zoomedAvatarImage.height(); | |
| 545 | 558 | letconst zoomedAvatarImageimgWidth = $(elmnt)zoomedAvatarImage.findwidth('.zoomed_avatar_img'); |
| 546 | - imgHeight = zoomedAvatarImage.height(); | |
| 559 | + const imageAspectRatio = imgHeight / imgWidth; | |
| 547 | - imgWidth = zoomedAvatarImage.width(); | |
| 548 | - imageAspectRatio = imgHeight / imgWidth; | |
| 549 | - | |
| 550 | - // Maintain aspect ratio | |
| 551 | 560 | if (containerAspectRatio !== imageAspectRatio) { |
| 552 | 561 | $elmnt.css('width', $elmnt.width()); |
| 553 | 562 | $elmnt.css('height', $elmnt.width() * imageAspectRatio); |
| 554 | - } | |
| 555 | - | |
| 556 | - // Prevent resizing offscreen | |
| 557 | - if (top + elmnt.height() >= winHeight) { | |
| 558 | - elmnt.css('height', winHeight - top - 1 + 'px'); | |
| 559 | - elmnt.css('width', (winHeight - top - 1) / imageAspectRatio + 'px'); | |
| 560 | 563 | } |
| 561 | - | |
| 564 | + if (top + $elmnt.height() >= winHeight) { | |
| 562 | - if (left + elmnt.width() >= winWidth) { | |
| 565 | + $elmnt.css('height', winHeight - top - 1 + 'px'); | |
| 563 | 566 | $elmnt.css('width', winWidth(winHeight - lefttop - 1) / imageAspectRatio + 'px'); |
| 564 | - elmnt.css('height', (winWidth - left - 1) * imageAspectRatio + 'px'); | |
| 565 | 567 | } |
| 566 | - } else { //prevent divs that are not zoomedAvatars from resizing offscreen | |
| 568 | + if (left + $elmnt.width() >= winWidth) { | |
| 567 | - | |
| 569 | + $elmnt.css('width', winWidth - left - 1 + 'px'); | |
| 568 | - if (top + elmnt.height() >= winHeight) { | |
| 570 | + $elmnt.css('height', (winWidth - left - 1) * imageAspectRatio + 'px'); | |
| 569 | - elmnt.css('height', winHeight - top - 1 + 'px'); | |
| 570 | - } | |
| 571 | - | |
| 572 | - if (left + elmnt.width() >= winWidth) { | |
| 573 | - elmnt.css('width', winWidth - left - 1 + 'px'); | |
| 574 | 571 | } |
| 572 | + } else { | |
| 573 | + if (top + $elmnt.height() >= winHeight) $elmnt.css('height', winHeight - top - 1 + 'px'); | |
| 574 | + if (left + $elmnt.width() >= winWidth) $elmnt.css('width', winWidth - left - 1 + 'px'); | |
| 575 | 575 | } |
| 576 | - | |
| 577 | - //prevent resizing from top left into the top bar | |
| 578 | 576 | if (top < topBarLastY && maxX >= topBarFirstX && left <= topBarFirstX) { |
| 579 | 577 | $elmnt.css('width', width - 1 + 'px'); |
| 580 | - } | |
| 581 | - | |
| 582 | - //set css to prevent weird resize behavior (does not save) | |
| 583 | - elmnt.css('left', left); | |
| 584 | - elmnt.css('top', top); | |
| 585 | - | |
| 586 | - //set a listener for mouseup to save new width/height | |
| 587 | - $(window).off('mouseup').on('mouseup', () => { | |
| 588 | - console.log(`Saving ${elmntName} Height/Width`); | |
| 589 | - // check if the height or width actually changed | |
| 590 | - if (power_user.movingUIState[elmntName].width === elmnt.width() && power_user.movingUIState[elmntName].height === elmnt.height()) { | |
| 591 | - console.log('no change detected, aborting save'); | |
| 592 | - return; | |
| 593 | 578 | } |
| 594 | - | |
| 579 | + $elmnt.css({ left, top }); | |
| 595 | - power_user.movingUIState[elmntName].width = width; | |
| 580 | + $elmnt.off('mouseup').on('mouseup', () => { | |
| 596 | - power_user.movingUIState[elmntName].height = height; | |
| 581 | + if ( | |
| 597 | - eventSource.emit('resizeUI', elmntName); | |
| 582 | + power_user.movingUIState[elmntName].width === $elmnt.width() && | |
| 598 | - saveSettingsDebounced(); | |
| 583 | + power_user.movingUIState[elmntName].height === $elmnt.height() | |
| 599 | 584 | imgHeight =) nullreturn; |
| 600 | - imgWidth = null; | |
| 585 | + savePositionAndSize(); | |
| 601 | - height = null; | |
| 586 | + observer.disconnect(); | |
| 602 | - width = null; | |
| 603 | - | |
| 604 | - containerAspectRatio = null; | |
| 605 | - imageAspectRatio = null; | |
| 606 | - $(window).off('mouseup'); | |
| 607 | 587 | }); |
| 588 | + } else if (actionType === 'drag') { | |
| 589 | + clampToViewport(); | |
| 608 | 590 | } |
| 609 | 591 | |
| 610 | - //only record position changes if header is being dragged | |
| 592 | + // Always update position in state | |
| 611 | - power_user.movingUIState[elmntName].top = top; | |
| 593 | + savePositionAndSize(); | |
| 612 | - power_user.movingUIState[elmntName].left = left; | |
| 613 | - power_user.movingUIState[elmntName].right = right; | |
| 614 | - power_user.movingUIState[elmntName].bottom = bottom; | |
| 615 | - power_user.movingUIState[elmntName].margin = 'unset'; | |
| 616 | - | |
| 617 | - //handle dragging hit detection to prevent dragging offscreen | |
| 618 | - if (isHeaderBeingDragged && isMouseDown) { | |
| 619 | - | |
| 620 | - if (top <= 0) { | |
| 621 | - elmnt.css('top', '0px'); | |
| 622 | - } else if (maxY >= winHeight) { | |
| 623 | - elmnt.css('top', winHeight - maxY + top - 1 + 'px'); | |
| 624 | - } | |
| 625 | - | |
| 626 | - if (left <= 0) { | |
| 627 | - elmnt.css('left', '0px'); | |
| 628 | - } else if (maxX >= winWidth) { | |
| 629 | - elmnt.css('left', winWidth - maxX + left - 1 + 'px'); | |
| 630 | - } | |
| 631 | - } | |
| 632 | - | |
| 633 | - // Check if the element header exists and set the reposition listener on the grabber in the header | |
| 634 | - if (elmntHeader.length) { | |
| 635 | - elmntHeader.off('mousedown').on('mousedown', (e) => { | |
| 636 | - dragMouseDown(e); | |
| 637 | - }); | |
| 638 | - } else { //if no header, put the listener on the elmnt itself. | |
| 639 | - elmnt.off('mousedown').on('mousedown', dragMouseDown); | |
| 640 | - } | |
| 641 | 594 | }); |
| 642 | 595 | |
| 596 | + // Mouse event handlers | |
| 643 | 597 | function dragMouseDown(e) { |
| 644 | - | |
| 645 | 598 | if (e) { |
| 646 | 599 | isHeaderBeingDraggedactionType = true'drag'; |
| 600 | + isMouseDown = true; | |
| 647 | 601 | e.preventDefault(); |
| 648 | 602 | pos3 = e.clientX; //mouse X at click |
| 649 | 603 | pos4 = e.clientY; //mouse Y at click |
| 650 | 604 | } |
| 651 | 605 | $(document).on('mouseup', closeDragElement); |
| 652 | 606 | $(document).on('mousemove', elementDrag); |
| 653 | 607 | } |
| 654 | 608 | |
| 655 | 609 | function elementDrag(e) { |
| 656 | 610 | if (!power_user.movingUIState[elmntName]) power_user.movingUIState[elmntName] = {}; |
| 657 | - power_user.movingUIState[elmntName] = {}; | |
| 658 | - } | |
| 659 | - | |
| 660 | - e = e || window.event; | |
| 661 | 611 | e.preventDefault(); |
| 662 | - | |
| 612 | + pos1 = pos3 - e.clientX; | |
| 663 | - pos1 = pos3 - e.clientX; //X change amt (-1 or 1) | |
| 613 | + pos2 = pos4 - e.clientY; | |
| 664 | - pos2 = pos4 - e.clientY; //Y change amt (-1 or 1) | |
| 614 | + pos3 = e.clientX; | |
| 665 | 615 | pos3pos4 = e.clientXclientY; //new mouse X |
| 666 | - pos4 = e.clientY; //new mouse Y | |
| 616 | + $elmnt.attr('data-dragged', 'true'); | |
| 667 | - | |
| 617 | + $elmnt.css('left', ($elmnt.offset().left - pos1) + 'px'); | |
| 668 | - elmnt.attr('data-dragged', 'true'); | |
| 618 | + $elmnt.css('top', ($elmnt.offset().top - pos2) + 'px'); | |
| 669 | - | |
| 619 | + $elmnt.css('margin', 'unset'); | |
| 670 | - //first set css to computed values to avoid CSS NaN results from 'auto', etc | |
| 620 | + $elmnt.css('height', height); | |
| 671 | 621 | $elmnt.css('leftwidth', (elmnt.offset().left) + 'px'width); |
| 672 | - elmnt.css('top', (elmnt.offset().top) + 'px'); | |
| 673 | - | |
| 674 | - //then update element position styles to account for drag changes | |
| 675 | - elmnt.css('margin', 'unset'); | |
| 676 | - elmnt.css('left', (elmnt.offset().left - pos1) + 'px'); | |
| 677 | - elmnt.css('top', (elmnt.offset().top - pos2) + 'px'); | |
| 678 | - /* elmnt.css('right', ((winWidth - maxX) + 'px')); | |
| 679 | - elmnt.css('bottom', ((winHeight - maxY) + 'px')); */ | |
| 680 | - | |
| 681 | - // Height/Width here are for visuals only, and are not saved to settings. | |
| 682 | - // This is required because some divs do hot have a set width/height | |
| 683 | - // and will default to shrink to min value of 100px set in CSS file | |
| 684 | - elmnt.css('height', height); | |
| 685 | - elmnt.css('width', width); | |
| 686 | - return; | |
| 687 | 622 | } |
| 688 | 623 | |
| 689 | 624 | function closeDragElement() { |
| 690 | - console.debug('drag finished'); | |
| 691 | - isHeaderBeingDragged = false; | |
| 692 | 625 | isMouseDown = false; |
| 626 | + actionType = null; | |
| 693 | 627 | $(document).off('mouseup', closeDragElement); |
| 694 | 628 | $(document).off('mousemove', elementDrag); |
| 695 | 629 | $('body')elmnt.cssattr('overflowdata-dragged', 'false'); |
| 696 | - // Clear the "data-dragged" attribute | |
| 697 | - elmnt.attr('data-dragged', 'false'); | |
| 698 | 630 | observer.disconnect(); |
| 699 | - console.debug(`Saving ${elmntName} UI position`); | |
| 631 | + savePositionAndSize(); | |
| 700 | - saveSettingsDebounced(); | |
| 701 | - top = null; | |
| 702 | - left = null; | |
| 703 | - right = null; | |
| 704 | - bottom = null; | |
| 705 | - maxX = null; | |
| 706 | - maxY = null; | |
| 707 | 632 | } |
| 633 | + | |
| 634 | + // Setup event listeners | |
| 635 | + if ($elmntHeader.length) { | |
| 636 | + $elmntHeader.off('mousedown').on('mousedown', (e) => { | |
| 637 | + if ($(e.target).hasClass('drag-grabber')) { | |
| 638 | + actionType = 'drag'; | |
| 639 | + isMouseDown = true; | |
| 640 | + observer.observe($elmnt[0], { attributes: true, attributeFilter: ['style'] }); | |
| 641 | + dragMouseDown(e); | |
| 642 | + } | |
| 643 | + }); | |
| 644 | + } | |
| 645 | + | |
| 646 | + $elmnt.off('mousedown').on('mousedown', (e) => { | |
| 647 | + const rect = $elmnt[0].getBoundingClientRect(); | |
| 648 | + const resizeMargin = 16; | |
| 649 | + const isNearRight = e.clientX > rect.right - resizeMargin; | |
| 650 | + const isNearBottom = e.clientY > rect.bottom - resizeMargin; | |
| 651 | + if (isNearRight && isNearBottom) { | |
| 652 | + actionType = 'resize'; | |
| 653 | + isMouseDown = true; | |
| 654 | + observer.observe($elmnt[0], { attributes: true, attributeFilter: ['style'] }); | |
| 655 | + } | |
| 656 | + }); | |
| 657 | + | |
| 658 | + $elmnt.off('mouseup').on('mouseup', () => { | |
| 659 | + isMouseDown = false; | |
| 660 | + actionType = null; | |
| 661 | + observer.disconnect(); | |
| 662 | + }); | |
| 708 | 663 | } |
| 709 | 664 | |
| 710 | 665 | export async function initMovingUI() { |
| @@ -775,9 +730,8 @@ export function initRossMods() { | ||
| 775 | 730 | $(RightNavDrawerIcon).removeClass('drawerPinnedOpen'); |
| 776 | 731 | |
| 777 | 732 | if ($(RightNavPanel).hasClass('openDrawer') && $('.openDrawer').length > 1) { |
| 778 | - slideToggle(RightNavPanel, getSlideToggleOptions()); | |
| 733 | + const toggle = $('#unimportantYes'); | |
| 779 | - $(RightNavDrawerIcon).toggleClass('closedIcon openIcon'); | |
| 734 | + doNavbarIconClick.call(toggle); | |
| 780 | - $(RightNavPanel).toggleClass('openDrawer closedDrawer'); | |
| 781 | 735 | } |
| 782 | 736 | } |
| 783 | 737 | }); |
| @@ -793,14 +747,13 @@ export function initRossMods() { | ||
| 793 | 747 | $(LeftNavDrawerIcon).removeClass('drawerPinnedOpen'); |
| 794 | 748 | |
| 795 | 749 | if ($(LeftNavPanel).hasClass('openDrawer') && $('.openDrawer').length > 1) { |
| 796 | - slideToggle(LeftNavPanel, getSlideToggleOptions()); | |
| 750 | + const toggle = $('#ai-config-button>.drawer-toggle'); | |
| 797 | - $(LeftNavDrawerIcon).toggleClass('closedIcon openIcon'); | |
| 751 | + doNavbarIconClick.call(toggle); | |
| 798 | - $(LeftNavPanel).toggleClass('openDrawer closedDrawer'); | |
| 799 | 752 | } |
| 800 | 753 | } |
| 801 | 754 | }); |
| 802 | 755 | |
| 803 | 756 | $(WIPanelPin).on('click', async function () { |
| 804 | 757 | accountStorage.setItem('WINavLockOn', $(WIPanelPin).prop('checked')); |
| 805 | 758 | if ($(WIPanelPin).prop('checked') == true) { |
| 806 | 759 | console.debug('adding pin class to WI'); |
| @@ -813,9 +766,8 @@ export function initRossMods() { | ||
| 813 | 766 | |
| 814 | 767 | if ($(WorldInfo).hasClass('openDrawer') && $('.openDrawer').length > 1) { |
| 815 | 768 | console.debug('closing WI after lock removal'); |
| 816 | - slideToggle(WorldInfo, getSlideToggleOptions()); | |
| 769 | + const toggle = $('#WI-SP-button>.drawer-toggle'); | |
| 817 | - $(WIDrawerIcon).toggleClass('closedIcon openIcon'); | |
| 770 | + doNavbarIconClick.call(toggle); | |
| 818 | - $(WorldInfo).toggleClass('openDrawer closedDrawer'); | |
| 819 | 771 | } |
| 820 | 772 | } |
| 821 | 773 | }); |
| @@ -1,9 +1,11 @@ | ||
| 1 | 1 | import { |
| 2 | + MAX_INJECTION_DEPTH, | |
| 2 | 3 | animation_duration, |
| 3 | 4 | chat_metadata, |
| 4 | 5 | eventSource, |
| 5 | 6 | event_types, |
| 6 | 7 | extension_prompt_roles, |
| 8 | + extension_prompt_types, | |
| 7 | 9 | saveSettingsDebounced, |
| 8 | 10 | this_chid, |
| 9 | 11 | } from '../script.js'; |
| @@ -347,7 +349,7 @@ export function setFloatingPrompt() { | ||
| 347 | 349 | } |
| 348 | 350 | |
| 349 | 351 | if (lastMessageNumber <= 0 || chat_metadata[metadata_keys.interval] <= 0) { |
| 350 | 352 | context.setExtensionPrompt(MODULE_NAME, '', extension_prompt_types.NONE, MAX_INJECTION_DEPTH); |
| 351 | 353 | $('#extension_floating_counter').text('(disabled)'); |
| 352 | 354 | shouldWIAddPrompt = false; |
| 353 | 355 | return; |
| @@ -380,7 +382,7 @@ export function setFloatingPrompt() { | ||
| 380 | 382 | } |
| 381 | 383 | context.setExtensionPrompt( |
| 382 | 384 | MODULE_NAME, |
| 383 | 385 | String(prompt), |
| 384 | 386 | chat_metadata[metadata_keys.position], |
| 385 | 387 | chat_metadata[metadata_keys.depth], |
| 386 | 388 | extension_settings.note.allowWIScan, |
| @@ -396,37 +398,38 @@ function onANMenuItemClick() { | ||
| 396 | 398 | } |
| 397 | 399 | |
| 398 | 400 | //show AN if it's hidden |
| 399 | - if ($('#floatingPrompt').css('display') !== 'flex') { | |
| 401 | + const $ANcontainer = $('#floatingPrompt'); | |
| 400 | - $('#floatingPrompt').addClass('resizing'); | |
| 402 | + if ($ANcontainer.css('display') !== 'flex') { | |
| 401 | 403 | $('#floatingPrompt')ANcontainer.cssaddClass('display', 'flexresizing'); |
| 402 | 404 | $('#floatingPrompt')ANcontainer.css('opacitydisplay', 0.0'flex'); |
| 403 | - $('#floatingPrompt').transition({ | |
| 405 | + $ANcontainer.css('opacity', 0.0); | |
| 406 | + $ANcontainer.transition({ | |
| 404 | 407 | opacity: 1.0, |
| 405 | 408 | duration: animation_duration, |
| 406 | 409 | }, async function () { |
| 407 | 410 | await delay(50); |
| 408 | 411 | $('#floatingPrompt')ANcontainer.removeClass('resizing'); |
| 409 | 412 | }); |
| 410 | 413 | |
| 411 | 414 | //auto-open the main AN inline drawer |
| 412 | 415 | if ($('#ANBlockToggle') |
| 413 | 416 | .siblings('.inline-drawer-content') |
| 414 | 417 | .css('display') !== 'block') { |
| 415 | 418 | $('#floatingPrompt')ANcontainer.addClass('resizing'); |
| 416 | 419 | $('#ANBlockToggle').clicktrigger('click'); |
| 417 | 420 | } |
| 418 | 421 | } else { |
| 419 | 422 | //hide AN if it's already displayed |
| 420 | 423 | $('#floatingPrompt')ANcontainer.addClass('resizing'); |
| 421 | 424 | $('#floatingPrompt')ANcontainer.transition({ |
| 422 | 425 | opacity: 0.0, |
| 423 | 426 | duration: animation_duration, |
| 424 | 427 | }, async function () { |
| 425 | 428 | await delay(50); |
| 426 | 429 | $('#floatingPrompt')ANcontainer.removeClass('resizing'); |
| 427 | 430 | }); |
| 428 | 431 | setTimeout(function () { |
| 429 | 432 | $('#floatingPrompt')ANcontainer.hide(); |
| 430 | 433 | }, animation_duration); |
| 431 | 434 | } |
| 432 | 435 | |
| @@ -65,7 +65,7 @@ | ||
| 65 | 65 | .asset-download-button-text { |
| 66 | 66 | font: bold 20px "Quicksand", san-serif; |
| 67 | 67 | color: #ffffff; |
| 68 | 68 | transition: all 0.2svar(--animation-duration-2x); |
| 69 | 69 | } |
| 70 | 70 | |
| 71 | 71 | .asset-download-button-loading .asset-download-button-text { |
| @@ -4,6 +4,8 @@ import { | ||
| 4 | 4 | characters, |
| 5 | 5 | getRequestHeaders, |
| 6 | 6 | event_types, |
| 7 | + animation_duration, | |
| 8 | + animation_easing, | |
| 7 | 9 | } from '../../../script.js'; |
| 8 | 10 | import { groups, selected_group } from '../../group-chats.js'; |
| 9 | 11 | import { loadFileToDocument, delay, getBase64Async, getSanitizedFilename } from '../../utils.js'; |
| @@ -32,7 +34,15 @@ let galleryMaxRows = 3; | ||
| 32 | 34 | $('#movingDivs').on('click', '.dragClose', function () { |
| 33 | 35 | const relatedId = $(this).data('related-id'); |
| 34 | 36 | if (!relatedId) return; |
| 35 | 37 | const relatedElement = $(`#movingDivs > .draggable[id="${relatedId}"]`).remove(); |
| 38 | + relatedElement.transition({ | |
| 39 | + opacity: 0, | |
| 40 | + duration: animation_duration, | |
| 41 | + easing: animation_easing, | |
| 42 | + complete: () => { | |
| 43 | + relatedElement.remove(); | |
| 44 | + }, | |
| 45 | + }); | |
| 36 | 46 | }); |
| 37 | 47 | |
| 38 | 48 | const CUSTOM_GALLERY_REMOVED_EVENT = 'galleryRemoved'; |
| @@ -373,7 +383,7 @@ async function makeMovable(url) { | ||
| 373 | 383 | const id = 'gallery'; |
| 374 | 384 | const template = $('#generic_draggable_template').html(); |
| 375 | 385 | const newElement = $(template); |
| 376 | 386 | newElement.css({ 'background-color',: 'var(--SmartThemeBlurTintColor)', 'opacity': 0 }); |
| 377 | 387 | newElement.attr('forChar', id); |
| 378 | 388 | newElement.attr('id', id); |
| 379 | 389 | newElement.find('.drag-grabber').attr('id', `${id}header`); |
| @@ -505,6 +515,11 @@ async function makeMovable(url) { | ||
| 505 | 515 | loadMovingUIState(); |
| 506 | 516 | $(`.draggable[forChar="${id}"]`).css('display', 'block'); |
| 507 | 517 | dragElement(newElement); |
| 518 | + newElement.transition({ | |
| 519 | + opacity: 1, | |
| 520 | + duration: animation_duration, | |
| 521 | + easing: animation_easing, | |
| 522 | + }); | |
| 508 | 523 | |
| 509 | 524 | $(`.draggable[forChar="${id}"] img`).on('dragstart', (e) => { |
| 510 | 525 | console.log('saw drag on avatar!'); |
| @@ -16,6 +16,7 @@ import { | ||
| 16 | 16 | getMaxContextSize, |
| 17 | 17 | setExtensionPrompt, |
| 18 | 18 | streamingProcessor, |
| 19 | + animation_easing, | |
| 19 | 20 | } from '../../../script.js'; |
| 20 | 21 | import { is_group_generating, selected_group } from '../../group-chats.js'; |
| 21 | 22 | import { loadMovingUIState } from '../../power-user.js'; |
| @@ -972,6 +973,7 @@ function doPopout(e) { | ||
| 972 | 973 | </div>`; |
| 973 | 974 | const newElement = $(template); |
| 974 | 975 | newElement.attr('id', 'summaryExtensionPopout') |
| 976 | + .css('opacity', 0) | |
| 975 | 977 | .removeClass('zoomed_avatar') |
| 976 | 978 | .addClass('draggable') |
| 977 | 979 | .empty(); |
| @@ -980,13 +982,13 @@ function doPopout(e) { | ||
| 980 | 982 | originalElement.html('<div class="flex-container alignitemscenter justifyCenter wide100p"><small>Currently popped out</small></div>'); |
| 981 | 983 | newElement.append(controlBarHtml).append(originalHTMLClone); |
| 982 | 984 | $('body').append(newElement); |
| 985 | + newElement.transition({ opacity: 1, duration: animation_duration, easing: animation_easing }); | |
| 983 | 986 | $('#summaryExtensionDrawerContents').addClass('scrollableInnerFull'); |
| 984 | 987 | setMemoryContext(prevSummaryBoxContents, false); //paste prev summary box contents into popout box |
| 985 | 988 | setupListeners(); |
| 986 | 989 | loadSettings(); |
| 987 | 990 | loadMovingUIState(); |
| 988 | 991 | |
| 989 | - $('#summaryExtensionPopout').fadeIn(animation_duration); | |
| 990 | 992 | dragElement(newElement); |
| 991 | 993 | |
| 992 | 994 | //setup listener for close button to restore extensions menu |
| @@ -18,7 +18,7 @@ | ||
| 18 | 18 | #qr--bar { |
| 19 | 19 | outline: none; |
| 20 | 20 | margin: 0; |
| 21 | - transition: 0.3s; | |
| 21 | + transition: var(--animation-duration-2x); | |
| 22 | 22 | opacity: 0.7; |
| 23 | 23 | display: flex; |
| 24 | 24 | align-items: center; |
| @@ -34,14 +34,12 @@ | ||
| 34 | 34 | right: 0.25em; |
| 35 | 35 | top: 0; |
| 36 | 36 | } |
| 37 | - | |
| 38 | 37 | /*hide QR popout for mobile*/ |
| 39 | 38 | @media screen and (max-width: 1000px) { |
| 40 | 39 | #qr--bar > #qr--popoutTrigger { |
| 41 | 40 | display: none; |
| 42 | 41 | } |
| 43 | 42 | } |
| 44 | - | |
| 45 | 43 | #qr--bar.popoutVisible { |
| 46 | 44 | padding-right: 2.5em; |
| 47 | 45 | } |
| @@ -61,9 +59,8 @@ | ||
| 61 | 59 | aspect-ratio: 1 / 1; |
| 62 | 60 | font-size: 20px; |
| 63 | 61 | opacity: 0.5; |
| 64 | 62 | transition: all 250msvar(--animation-duration-2x); |
| 65 | 63 | } |
| 66 | - | |
| 67 | 64 | #qr--popout > .qr--body { |
| 68 | 65 | overflow-y: auto; |
| 69 | 66 | } |
| @@ -124,7 +121,7 @@ | ||
| 124 | 121 | padding: 3px 5px; |
| 125 | 122 | margin: 3px 0; |
| 126 | 123 | cursor: pointer; |
| 127 | - transition: 0.3s; | |
| 124 | + transition: var(--animation-duration-2x); | |
| 128 | 125 | display: flex; |
| 129 | 126 | align-items: center; |
| 130 | 127 | justify-content: center; |
| @@ -248,7 +245,7 @@ | ||
| 248 | 245 | display: flex; |
| 249 | 246 | align-items: center; |
| 250 | 247 | opacity: 0; |
| 251 | 248 | transition: 100msvar(--animation-duration); |
| 252 | 249 | margin: -2px 0 -11px 0; |
| 253 | 250 | position: relative; |
| 254 | 251 | } |
| @@ -461,7 +458,7 @@ | ||
| 461 | 458 | cursor: not-allowed; |
| 462 | 459 | opacity: 0.5; |
| 463 | 460 | pointer-events: none; |
| 464 | - transition: 200ms; | |
| 461 | + transition: var(--animation-duration-2x); | |
| 465 | 462 | border-color: transparent; |
| 466 | 463 | } |
| 467 | 464 | .popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor.qr--isExecuting.qr--isPaused #qr--modal-debugButtons .menu_button:not(#qr--modal-minimize, #qr--modal-maximize) { |
| @@ -492,7 +489,7 @@ | ||
| 492 | 489 | width: 6px; |
| 493 | 490 | background-color: var(--SmartThemeBorderColor); |
| 494 | 491 | border: 2px solid var(--SmartThemeBlurTintColor); |
| 495 | 492 | transition: border-color 200msvar(--animation-duration-2x), background-color 200msvar(--animation-duration-2x); |
| 496 | 493 | cursor: w-resize; |
| 497 | 494 | } |
| 498 | 495 | .popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor.qr--isExecuting #qr--resizeHandle:hover { |
| @@ -574,7 +571,7 @@ | ||
| 574 | 571 | gap: 1em; |
| 575 | 572 | text-align: left; |
| 576 | 573 | opacity: 0.75; |
| 577 | - transition: 200ms; | |
| 574 | + transition: var(--animation-duration-2x); | |
| 578 | 575 | cursor: pointer; |
| 579 | 576 | } |
| 580 | 577 | .popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label .qr--modal-switcherList .qr--modal-switcherItem:hover, |
| @@ -736,7 +733,7 @@ | ||
| 736 | 733 | display: flex; |
| 737 | 734 | } |
| 738 | 735 | .popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-executeButtons #qr--modal-execute { |
| 739 | - transition: 200ms; | |
| 736 | + transition: var(--animation-duration-2x); | |
| 740 | 737 | filter: grayscale(0); |
| 741 | 738 | } |
| 742 | 739 | .popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-executeButtons #qr--modal-execute.qr--busy { |
| @@ -825,7 +822,7 @@ | ||
| 825 | 822 | position: absolute; |
| 826 | 823 | inset: 0; |
| 827 | 824 | right: calc(100% - var(--prog) * 1%); |
| 828 | - transition: 200ms; | |
| 825 | + transition: var(--animation-duration-2x); | |
| 829 | 826 | } |
| 830 | 827 | .popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-executeProgress.qr--paused:after { |
| 831 | 828 | animation-name: qr--progressPulse; |
| @@ -1053,7 +1050,7 @@ | ||
| 1053 | 1050 | white-space: pre; |
| 1054 | 1051 | font-weight: normal; |
| 1055 | 1052 | box-shadow: 0 0 0; |
| 1056 | - transition: 200ms; | |
| 1053 | + transition: var(--animation-duration-2x); | |
| 1057 | 1054 | } |
| 1058 | 1055 | .popup:has(.qr--transferModal) .popup-button-ok:after { |
| 1059 | 1056 | content: 'Transfer'; |
| @@ -1068,7 +1065,7 @@ | ||
| 1068 | 1065 | white-space: pre; |
| 1069 | 1066 | font-weight: normal; |
| 1070 | 1067 | box-shadow: 0 0 0; |
| 1071 | - transition: 200ms; | |
| 1068 | + transition: var(--animation-duration-2x); | |
| 1072 | 1069 | } |
| 1073 | 1070 | .popup:has(.qr--transferModal) .qr--copy:after { |
| 1074 | 1071 | content: 'Copy'; |
| @@ -1,11 +1,16 @@ | ||
| 1 | 1 | @keyframes qr--success { |
| 2 | - 0%, 100% { | |
| 2 | + | |
| 3 | + 0%, | |
| 4 | + 100% { | |
| 3 | 5 | color: var(--SmartThemeBodyColor); |
| 4 | 6 | } |
| 5 | - 25%, 75% { | |
| 7 | + | |
| 8 | + 25%, | |
| 9 | + 75% { | |
| 6 | 10 | color: rgb(81, 163, 81); |
| 7 | 11 | } |
| 8 | 12 | } |
| 13 | + | |
| 9 | 14 | &.qr--success { |
| 10 | 15 | animation-name: qr--success; |
| 11 | 16 | animation-duration: 3s; |
| @@ -13,10 +18,11 @@ | ||
| 13 | 18 | animation-delay: 0s; |
| 14 | 19 | animation-iteration-count: 1; |
| 15 | 20 | } |
| 21 | + | |
| 16 | 22 | #qr--bar { |
| 17 | 23 | outline: none; |
| 18 | 24 | margin: 0; |
| 19 | - transition: 0.3s; | |
| 25 | + transition: var(--animation-duration-2x); | |
| 20 | 26 | opacity: 0.7; |
| 21 | 27 | display: flex; |
| 22 | 28 | align-items: center; |
| @@ -33,6 +39,14 @@ | ||
| 33 | 39 | top: 0; |
| 34 | 40 | } |
| 35 | 41 | } |
| 42 | + | |
| 43 | +/*hide QR popout for mobile*/ | |
| 44 | +@media screen and (max-width: 1000px) { | |
| 45 | + #qr--bar>#qr--popoutTrigger { | |
| 46 | + display: none; | |
| 47 | + } | |
| 48 | +} | |
| 49 | + | |
| 36 | 50 | #qr--bar.popoutVisible { |
| 37 | 51 | padding-right: 2.5em; |
| 38 | 52 | } |
| @@ -54,7 +68,7 @@ | ||
| 54 | 68 | aspect-ratio: 1 / 1; |
| 55 | 69 | font-size: 20px; |
| 56 | 70 | opacity: 0.5; |
| 57 | 71 | transition: all 250msvar(--animation-duration-2x); |
| 58 | 72 | } |
| 59 | 73 | } |
| 60 | 74 | } |
| @@ -68,17 +82,21 @@ | ||
| 68 | 82 | #qr--popout>.qr--body { |
| 69 | 83 | >.qr--buttons { |
| 70 | 84 | --qr--color: transparent; |
| 85 | + | |
| 71 | 86 | &.qr--color { |
| 72 | 87 | background-color: var(--qr--color); |
| 73 | 88 | } |
| 89 | + | |
| 74 | 90 | &.qr--borderColor { |
| 75 | 91 | background-color: transparent; |
| 76 | 92 | border-left: 5px solid var(--qr--color); |
| 77 | 93 | border-right: 5px solid var(--qr--color); |
| 78 | 94 | } |
| 95 | + | |
| 79 | 96 | &:has(.qr--buttons.qr--color) { |
| 80 | 97 | margin: 5px; |
| 81 | 98 | } |
| 99 | + | |
| 82 | 100 | margin: 0; |
| 83 | 101 | padding: 0; |
| 84 | 102 | display: flex; |
| @@ -89,6 +107,7 @@ | ||
| 89 | 107 | |
| 90 | 108 | >.qr--buttons { |
| 91 | 109 | display: contents; |
| 110 | + | |
| 92 | 111 | &.qr--color { |
| 93 | 112 | .qr--button:before { |
| 94 | 113 | content: ''; |
| @@ -97,11 +116,14 @@ | ||
| 97 | 116 | inset: -5px; |
| 98 | 117 | z-index: -1; |
| 99 | 118 | } |
| 119 | + | |
| 100 | 120 | &.qr--borderColor { |
| 101 | 121 | .qr--button:before { |
| 102 | 122 | display: none; |
| 103 | 123 | } |
| 104 | - &:before, &:after { | |
| 124 | + | |
| 125 | + &:before, | |
| 126 | + &:after { | |
| 105 | 127 | content: ''; |
| 106 | 128 | width: 5px; |
| 107 | 129 | background-color: var(--qr--color); |
| @@ -118,7 +140,7 @@ | ||
| 118 | 140 | padding: 3px 5px; |
| 119 | 141 | margin: 3px 0; |
| 120 | 142 | cursor: pointer; |
| 121 | - transition: 0.3s; | |
| 143 | + transition: var(--animation-duration-2x); | |
| 122 | 144 | display: flex; |
| 123 | 145 | align-items: center; |
| 124 | 146 | justify-content: center; |
| @@ -132,6 +154,7 @@ | ||
| 132 | 154 | .qr--hidden { |
| 133 | 155 | display: none; |
| 134 | 156 | } |
| 157 | + | |
| 135 | 158 | .qr--button-icon { |
| 136 | 159 | margin: 0 0.5em; |
| 137 | 160 | } |
| @@ -274,18 +297,22 @@ | ||
| 274 | 297 | display: flex; |
| 275 | 298 | align-items: center; |
| 276 | 299 | opacity: 0; |
| 277 | 300 | transition: 100msvar(--animation-duration); |
| 278 | 301 | margin: -2px 0 -11px 0; |
| 279 | 302 | position: relative; |
| 303 | + | |
| 280 | 304 | .qr--actions { |
| 281 | 305 | display: flex; |
| 282 | 306 | gap: 0.25em; |
| 283 | 307 | flex: 0 0 auto; |
| 308 | + | |
| 284 | 309 | .qr--action { |
| 285 | 310 | margin: 0; |
| 286 | 311 | } |
| 287 | 312 | } |
| 288 | - &:before, &:after { | |
| 313 | + | |
| 314 | + &:before, | |
| 315 | + &:after { | |
| 289 | 316 | content: ""; |
| 290 | 317 | display: block; |
| 291 | 318 | flex: 1 1 auto; |
| @@ -293,10 +320,13 @@ | ||
| 293 | 320 | margin: 0 1em; |
| 294 | 321 | height: 0; |
| 295 | 322 | } |
| 296 | - &:hover, &:focus-within { | |
| 323 | + | |
| 324 | + &:hover, | |
| 325 | + &:focus-within { | |
| 297 | 326 | opacity: 1; |
| 298 | 327 | } |
| 299 | 328 | } |
| 329 | + | |
| 300 | 330 | >.qr--set-item .qr--content { |
| 301 | 331 | display: flex; |
| 302 | 332 | flex-direction: row; |
| @@ -336,9 +366,11 @@ | ||
| 336 | 366 | display: flex; |
| 337 | 367 | align-items: center; |
| 338 | 368 | gap: 0.5em; |
| 369 | + | |
| 339 | 370 | .qr--set-itemIcon:not(.fa-solid) { |
| 340 | 371 | display: none; |
| 341 | 372 | } |
| 373 | + | |
| 342 | 374 | .qr--set-itemLabel { |
| 343 | 375 | min-width: 24px; |
| 344 | 376 | } |
| @@ -384,6 +416,7 @@ | ||
| 384 | 416 | align-items: baseline; |
| 385 | 417 | } |
| 386 | 418 | } |
| 419 | + | |
| 387 | 420 | >#qr--autoExec { |
| 388 | 421 | .checkbox_label { |
| 389 | 422 | text-wrap: nowrap; |
| @@ -433,44 +466,52 @@ | ||
| 433 | 466 | bottom: unset; |
| 434 | 467 | margin: unset; |
| 435 | 468 | padding: 0; |
| 469 | + | |
| 436 | 470 | &::backdrop { |
| 437 | 471 | backdrop-filter: unset; |
| 438 | 472 | background-color: transparent; |
| 439 | 473 | } |
| 474 | + | |
| 440 | 475 | .popup-body { |
| 441 | 476 | flex: 0 0 auto; |
| 442 | 477 | height: min-content; |
| 443 | 478 | width: min-content; |
| 444 | 479 | } |
| 480 | + | |
| 445 | 481 | .popup-content { |
| 446 | 482 | flex: 0 0 auto; |
| 447 | 483 | margin-top: 0; |
| 448 | 484 | |
| 449 | 485 | >#qr--modalEditor { |
| 450 | 486 | max-height: 50vh; |
| 487 | + | |
| 451 | 488 | >#qr--main, |
| 452 | 489 | >#qr--resizeHandle, |
| 453 | 490 | >#qr--qrOptions>h3, |
| 454 | 491 | >#qr--qrOptions>#qr--modal-executeButtons, |
| 455 | 492 | > #qr--qrOptions > #qr--modal-executeProgress { |
| 456 | - { | |
| 457 | 493 | display: none; |
| 458 | 494 | } |
| 495 | + | |
| 459 | 496 | #qr--qrOptions { |
| 460 | 497 | width: auto; |
| 461 | 498 | } |
| 499 | + | |
| 462 | 500 | #qr--modal-debugButtons .qr--modal-debugButton#qr--modal-maximize { |
| 463 | 501 | display: flex; |
| 464 | 502 | } |
| 503 | + | |
| 465 | 504 | #qr--modal-debugButtons .qr--modal-debugButton#qr--modal-minimize { |
| 466 | 505 | display: none; |
| 467 | 506 | } |
| 507 | + | |
| 468 | 508 | #qr--modal-debugState { |
| 469 | 509 | padding-top: 0; |
| 470 | 510 | } |
| 471 | 511 | } |
| 472 | 512 | } |
| 473 | 513 | } |
| 514 | + | |
| 474 | 515 | &:has(.qr--isExecuting) { |
| 475 | 516 | .popup-controls { |
| 476 | 517 | display: none; |
| @@ -481,10 +522,12 @@ | ||
| 481 | 522 | z-index: 50000; |
| 482 | 523 | pointer-events: none; |
| 483 | 524 | background-color: rgb(47 150 180 / 0.5); |
| 525 | + | |
| 484 | 526 | &.qr--unresolved { |
| 485 | 527 | background-color: rgb(255 255 0 / 0.5); |
| 486 | 528 | } |
| 487 | 529 | } |
| 530 | + | |
| 488 | 531 | .qr--highlight-secondary { |
| 489 | 532 | position: absolute; |
| 490 | 533 | z-index: 50000; |
| @@ -505,6 +548,7 @@ | ||
| 505 | 548 | overflow: hidden; |
| 506 | 549 | |
| 507 | 550 | &.qr--isExecuting { |
| 551 | + | |
| 508 | 552 | #qr--main>h3:first-child, |
| 509 | 553 | #qr--main>.qr--labels, |
| 510 | 554 | #qr--main>.qr--modal-messageContainer>.qr--modal-editorSettings, |
| @@ -512,28 +556,32 @@ | ||
| 512 | 556 | #qr--qrOptions>#qr--ctxEditor, |
| 513 | 557 | #qr--qrOptions>.qr--ctxEditorActions, |
| 514 | 558 | #qr--qrOptions>.qr--ctxEditorActions+h3, |
| 515 | 559 | #qr--qrOptions > .qr--ctxEditorActions + h3 + div { |
| 516 | - { | |
| 517 | 560 | display: none; |
| 518 | 561 | } |
| 562 | + | |
| 519 | 563 | #qr--main>.qr--modal-messageContainer>#qr--modal-messageHolder>#qr--modal-message { |
| 520 | 564 | visibility: hidden; |
| 521 | 565 | } |
| 566 | + | |
| 522 | 567 | #qr--modal-debugButtons { |
| 523 | 568 | display: flex; |
| 569 | + | |
| 524 | 570 | .menu_button:not(#qr--modal-minimize, #qr--modal-maximize) { |
| 525 | 571 | cursor: not-allowed; |
| 526 | 572 | opacity: 0.5; |
| 527 | 573 | pointer-events: none; |
| 528 | - transition: 200ms; | |
| 574 | + transition: var(--animation-duration-2x); | |
| 529 | 575 | border-color: transparent; |
| 530 | 576 | } |
| 531 | 577 | } |
| 578 | + | |
| 532 | 579 | &.qr--isPaused #qr--modal-debugButtons { |
| 533 | 580 | .menu_button:not(#qr--modal-minimize, #qr--modal-maximize) { |
| 534 | 581 | cursor: pointer; |
| 535 | 582 | opacity: 1; |
| 536 | 583 | pointer-events: all; |
| 584 | + | |
| 537 | 585 | &#qr--modal-resume { |
| 538 | 586 | animation-name: qr--debugPulse; |
| 539 | 587 | animation-duration: 1500ms; |
| @@ -541,31 +589,38 @@ | ||
| 541 | 589 | animation-delay: 0s; |
| 542 | 590 | animation-iteration-count: infinite; |
| 543 | 591 | } |
| 592 | + | |
| 544 | 593 | &#qr--modal-resume { |
| 545 | 594 | border-color: rgb(81, 163, 81); |
| 546 | 595 | } |
| 596 | + | |
| 547 | 597 | &#qr--modal-step { |
| 548 | 598 | border-color: var(--SmartThemeQuoteColor); |
| 549 | 599 | } |
| 600 | + | |
| 550 | 601 | &#qr--modal-stepInto { |
| 551 | 602 | border-color: var(--SmartThemeQuoteColor); |
| 552 | 603 | } |
| 604 | + | |
| 553 | 605 | &#qr--modal-stepOut { |
| 554 | 606 | border-color: var(--SmartThemeQuoteColor); |
| 555 | 607 | } |
| 556 | 608 | } |
| 557 | 609 | } |
| 610 | + | |
| 558 | 611 | #qr--resizeHandle { |
| 559 | 612 | width: 6px; |
| 560 | 613 | background-color: var(--SmartThemeBorderColor); |
| 561 | 614 | border: 2px solid var(--SmartThemeBlurTintColor); |
| 562 | 615 | transition: border-color 200msvar(--animation-duration-2x), background-color 200msvar(--animation-duration-2x); |
| 563 | 616 | cursor: w-resize; |
| 617 | + | |
| 564 | 618 | &:hover { |
| 565 | 619 | background-color: var(--SmartThemeQuoteColor); |
| 566 | 620 | border-color: var(--SmartThemeQuoteColor); |
| 567 | 621 | } |
| 568 | 622 | } |
| 623 | + | |
| 569 | 624 | #qr--qrOptions { |
| 570 | 625 | width: var(--width, auto); |
| 571 | 626 | } |
| @@ -576,38 +631,48 @@ | ||
| 576 | 631 | display: flex; |
| 577 | 632 | flex-direction: column; |
| 578 | 633 | overflow: hidden; |
| 634 | + | |
| 579 | 635 | >.qr--labels { |
| 580 | 636 | flex: 0 0 auto; |
| 581 | 637 | display: flex; |
| 582 | 638 | flex-direction: row; |
| 583 | 639 | gap: 0.5em; |
| 584 | 640 | padding: 1px; |
| 585 | - > label, > .label { | |
| 641 | + | |
| 642 | + >label, | |
| 643 | + >.label { | |
| 586 | 644 | flex: 1 1 1px; |
| 587 | 645 | display: flex; |
| 588 | 646 | flex-direction: column; |
| 589 | 647 | position: relative; |
| 648 | + | |
| 590 | 649 | &.qr--fit { |
| 591 | 650 | flex: 0 0 auto; |
| 592 | 651 | justify-content: center; |
| 593 | 652 | } |
| 653 | + | |
| 594 | 654 | .qr--inputGroup { |
| 595 | 655 | display: flex; |
| 596 | 656 | align-items: baseline; |
| 597 | 657 | gap: 0.5em; |
| 658 | + | |
| 598 | 659 | input { |
| 599 | 660 | flex: 1 1 auto; |
| 600 | 661 | } |
| 601 | 662 | } |
| 663 | + | |
| 602 | 664 | .qr--labelText { |
| 603 | 665 | flex: 1 1 auto; |
| 604 | 666 | } |
| 667 | + | |
| 605 | 668 | .qr--labelHint { |
| 606 | 669 | flex: 1 1 auto; |
| 607 | 670 | } |
| 671 | + | |
| 608 | 672 | input { |
| 609 | 673 | flex: 0 0 auto; |
| 610 | 674 | } |
| 675 | + | |
| 611 | 676 | .qr--modal-switcherList { |
| 612 | 677 | background-color: var(--stcdx--bgColor); |
| 613 | 678 | border: 1px solid var(--SmartThemeBorderColor); |
| @@ -625,25 +690,32 @@ | ||
| 625 | 690 | list-style: none; |
| 626 | 691 | z-index: 40000; |
| 627 | 692 | max-width: 100%; |
| 693 | + | |
| 628 | 694 | .qr--modal-switcherItem { |
| 629 | 695 | display: flex; |
| 630 | 696 | gap: 1em; |
| 631 | 697 | text-align: left; |
| 632 | 698 | opacity: 0.75; |
| 633 | - transition: 200ms; | |
| 699 | + transition: var(--animation-duration-2x); | |
| 634 | 700 | cursor: pointer; |
| 701 | + | |
| 635 | 702 | &:hover { |
| 636 | 703 | opacity: 1; |
| 637 | 704 | } |
| 705 | + | |
| 638 | 706 | &.qr--current { |
| 639 | 707 | opacity: 1; |
| 640 | - .qr--label, .qr--id { | |
| 708 | + | |
| 709 | + .qr--label, | |
| 710 | + .qr--id { | |
| 641 | 711 | font-weight: bold; |
| 642 | 712 | } |
| 643 | 713 | } |
| 644 | 714 | } |
| 715 | + | |
| 645 | 716 | .qr--label { |
| 646 | 717 | white-space: nowrap; |
| 718 | + | |
| 647 | 719 | .menu_button { |
| 648 | 720 | display: inline-block; |
| 649 | 721 | height: min-content; |
| @@ -651,11 +723,19 @@ | ||
| 651 | 723 | margin: 0 0.5em 0 0; |
| 652 | 724 | } |
| 653 | 725 | } |
| 726 | + | |
| 654 | 727 | .qr--id { |
| 655 | 728 | opacity: 0.5; |
| 656 | - &:before { content: "["; } | |
| 729 | + | |
| 657 | - &:after { content: "]"; } | |
| 730 | + &:before { | |
| 731 | + content: "["; | |
| 658 | 732 | } |
| 733 | + | |
| 734 | + &:after { | |
| 735 | + content: "]"; | |
| 736 | + } | |
| 737 | + } | |
| 738 | + | |
| 659 | 739 | .qr--message { |
| 660 | 740 | height: 1lh; |
| 661 | 741 | overflow: hidden; |
| @@ -666,11 +746,13 @@ | ||
| 666 | 746 | } |
| 667 | 747 | } |
| 668 | 748 | } |
| 749 | + | |
| 669 | 750 | >.qr--modal-messageContainer { |
| 670 | 751 | flex: 1 1 auto; |
| 671 | 752 | display: flex; |
| 672 | 753 | flex-direction: column; |
| 673 | 754 | overflow: hidden; |
| 755 | + | |
| 674 | 756 | >.qr--modal-editorSettings { |
| 675 | 757 | display: flex; |
| 676 | 758 | flex-wrap: wrap; |
| @@ -679,38 +761,48 @@ | ||
| 679 | 761 | color: var(--grey70); |
| 680 | 762 | font-size: smaller; |
| 681 | 763 | align-items: baseline; |
| 764 | + | |
| 682 | 765 | >.checkbox_label { |
| 683 | 766 | white-space: nowrap; |
| 767 | + | |
| 684 | 768 | >input { |
| 685 | 769 | font-size: inherit; |
| 686 | 770 | } |
| 687 | 771 | } |
| 688 | 772 | } |
| 773 | + | |
| 689 | 774 | >#qr--modal-messageHolder { |
| 690 | 775 | flex: 1 1 auto; |
| 691 | 776 | display: grid; |
| 692 | 777 | text-align: left; |
| 693 | 778 | overflow: hidden; |
| 779 | + | |
| 694 | 780 | &.qr--noSyntax { |
| 695 | 781 | >#qr--modal-messageSyntax { |
| 696 | 782 | display: none; |
| 697 | 783 | } |
| 784 | + | |
| 698 | 785 | >#qr--modal-message { |
| 699 | 786 | background-color: var(--ac-style-color-background); |
| 700 | 787 | color: var(--ac-style-color-text); |
| 701 | - &::-webkit-scrollbar, &::-webkit-scrollbar-thumb { | |
| 788 | + | |
| 789 | + &::-webkit-scrollbar, | |
| 790 | + &::-webkit-scrollbar-thumb { | |
| 702 | 791 | visibility: visible; |
| 703 | 792 | cursor: unset; |
| 704 | 793 | } |
| 794 | + | |
| 705 | 795 | &::selection { |
| 706 | 796 | color: unset; |
| 707 | 797 | background-color: rgba(108 171 251 / 0.25); |
| 798 | + | |
| 708 | 799 | @supports (color: rgb(from white r g b / 0.25)) { |
| 709 | 800 | background-color: rgb(from var(--ac-style-color-matchedText) r g b / 0.25); |
| 710 | 801 | } |
| 711 | 802 | } |
| 712 | 803 | } |
| 713 | 804 | } |
| 805 | + | |
| 714 | 806 | >#qr--modal-messageSyntax { |
| 715 | 807 | grid-column: 1; |
| 716 | 808 | grid-row: 1; |
| @@ -720,10 +812,12 @@ | ||
| 720 | 812 | overflow: hidden; |
| 721 | 813 | min-width: 100%; |
| 722 | 814 | width: 0; |
| 815 | + | |
| 723 | 816 | >#qr--modal-messageSyntaxInner { |
| 724 | 817 | height: 100%; |
| 725 | 818 | } |
| 726 | 819 | } |
| 820 | + | |
| 727 | 821 | >#qr--modal-message { |
| 728 | 822 | background-color: transparent; |
| 729 | 823 | color: transparent; |
| @@ -731,19 +825,25 @@ | ||
| 731 | 825 | grid-row: 1; |
| 732 | 826 | caret-color: var(--ac-style-color-text); |
| 733 | 827 | overflow: auto; |
| 734 | - &::-webkit-scrollbar, &::-webkit-scrollbar-thumb { | |
| 828 | + | |
| 829 | + &::-webkit-scrollbar, | |
| 830 | + &::-webkit-scrollbar-thumb { | |
| 735 | 831 | visibility: hidden; |
| 736 | 832 | cursor: default; |
| 737 | 833 | } |
| 834 | + | |
| 738 | 835 | &::selection { |
| 739 | 836 | color: transparent; |
| 740 | 837 | background-color: rgba(108 171 251 / 0.25); |
| 838 | + | |
| 741 | 839 | @supports (color: rgb(from white r g b / 0.25)) { |
| 742 | 840 | background-color: rgb(from var(--ac-style-color-matchedText) r g b / 0.25); |
| 743 | 841 | } |
| 744 | 842 | } |
| 745 | 843 | } |
| 746 | - #qr--modal-message, #qr--modal-messageSyntaxInner { | |
| 844 | + | |
| 845 | + #qr--modal-message, | |
| 846 | + #qr--modal-messageSyntaxInner { | |
| 747 | 847 | font-family: var(--monoFontFamily); |
| 748 | 848 | padding: 0.75em; |
| 749 | 849 | margin: 0; |
| @@ -756,10 +856,12 @@ | ||
| 756 | 856 | } |
| 757 | 857 | } |
| 758 | 858 | } |
| 859 | + | |
| 759 | 860 | #qr--modal-icon { |
| 760 | 861 | height: 100%; |
| 761 | 862 | aspect-ratio: 1 / 1; |
| 762 | 863 | } |
| 864 | + | |
| 763 | 865 | #qr--modal-executeButtons { |
| 764 | 866 | display: flex; |
| 765 | 867 | gap: 1em; |
| @@ -778,7 +880,7 @@ | ||
| 778 | 880 | } |
| 779 | 881 | |
| 780 | 882 | #qr--modal-execute { |
| 781 | - transition: 200ms; | |
| 883 | + transition: var(--animation-duration-2x); | |
| 782 | 884 | filter: grayscale(0); |
| 783 | 885 | |
| 784 | 886 | &.qr--busy { |
| @@ -819,16 +921,20 @@ | ||
| 819 | 921 | border-color: rgb(215, 136, 114); |
| 820 | 922 | } |
| 821 | 923 | } |
| 924 | + | |
| 822 | 925 | #qr--modal-debugButtons { |
| 823 | 926 | display: none; |
| 824 | 927 | gap: 1em; |
| 928 | + | |
| 825 | 929 | .qr--modal-debugButton { |
| 826 | 930 | aspect-ratio: 1.25 / 1; |
| 827 | 931 | width: 2.25em; |
| 828 | 932 | position: relative; |
| 933 | + | |
| 829 | 934 | &:not(.fa-solid) { |
| 830 | 935 | border-width: 1px; |
| 831 | 936 | border-style: solid; |
| 937 | + | |
| 832 | 938 | &:after { |
| 833 | 939 | content: ''; |
| 834 | 940 | position: absolute; |
| @@ -839,18 +945,23 @@ | ||
| 839 | 945 | mask-repeat: no-repeat; |
| 840 | 946 | } |
| 841 | 947 | } |
| 948 | + | |
| 842 | 949 | &#qr--modal-resume:after { |
| 843 | 950 | mask-image: url('/img/step-resume.svg'); |
| 844 | 951 | } |
| 952 | + | |
| 845 | 953 | &#qr--modal-step:after { |
| 846 | 954 | mask-image: url('/img/step-over.svg'); |
| 847 | 955 | } |
| 956 | + | |
| 848 | 957 | &#qr--modal-stepInto:after { |
| 849 | 958 | mask-image: url('/img/step-into.svg'); |
| 850 | 959 | } |
| 960 | + | |
| 851 | 961 | &#qr--modal-stepOut:after { |
| 852 | 962 | mask-image: url('/img/step-out.svg'); |
| 853 | 963 | } |
| 964 | + | |
| 854 | 965 | &#qr--modal-maximize { |
| 855 | 966 | display: none; |
| 856 | 967 | } |
| @@ -879,7 +990,7 @@ | ||
| 879 | 990 | position: absolute; |
| 880 | 991 | inset: 0; |
| 881 | 992 | right: calc(100% - var(--prog) * 1%); |
| 882 | - transition: 200ms; | |
| 993 | + transition: var(--animation-duration-2x); | |
| 883 | 994 | } |
| 884 | 995 | |
| 885 | 996 | &.qr--paused:after { |
| @@ -941,11 +1052,14 @@ | ||
| 941 | 1052 | width: 0; |
| 942 | 1053 | white-space: pre-wrap; |
| 943 | 1054 | } |
| 1055 | + | |
| 944 | 1056 | #qr--modal-debugState { |
| 945 | 1057 | display: none; |
| 1058 | + | |
| 946 | 1059 | &.qr--active { |
| 947 | 1060 | display: block; |
| 948 | 1061 | } |
| 1062 | + | |
| 949 | 1063 | text-align: left; |
| 950 | 1064 | font-size: smaller; |
| 951 | 1065 | font-family: var(--monoFontFamily); |
| @@ -961,6 +1075,7 @@ | ||
| 961 | 1075 | display: grid; |
| 962 | 1076 | grid-template-columns: 0fr 1fr 1fr; |
| 963 | 1077 | column-gap: 0em; |
| 1078 | + | |
| 964 | 1079 | .qr--title { |
| 965 | 1080 | grid-column: 1 / 4; |
| 966 | 1081 | font-weight: bold; |
| @@ -969,47 +1084,66 @@ | ||
| 969 | 1084 | padding: 0.25em; |
| 970 | 1085 | margin-top: 0.5em; |
| 971 | 1086 | } |
| 972 | - .qr--var, .qr--macro, .qr--pipe { | |
| 1087 | + | |
| 1088 | + .qr--var, | |
| 1089 | + .qr--macro, | |
| 1090 | + .qr--pipe { | |
| 973 | 1091 | display: contents; |
| 1092 | + | |
| 974 | 1093 | &:nth-child(2n + 1) { |
| 975 | - .qr--key, .qr--val { | |
| 1094 | + | |
| 1095 | + .qr--key, | |
| 1096 | + .qr--val { | |
| 976 | 1097 | background-color: rgb(from var(--SmartThemeEmColor) r g b / 0.25); |
| 977 | 1098 | } |
| 1099 | + | |
| 978 | 1100 | .qr--val { |
| 979 | 1101 | &:nth-child(2n) { |
| 980 | 1102 | background-color: rgb(from var(--SmartThemeEmColor) r g b / 0.125); |
| 981 | 1103 | } |
| 1104 | + | |
| 982 | 1105 | &:hover { |
| 983 | 1106 | background-color: rgb(from var(--SmartThemeEmColor) r g b / 0.5); |
| 984 | 1107 | } |
| 985 | 1108 | } |
| 986 | 1109 | } |
| 1110 | + | |
| 987 | 1111 | &:nth-child(2n) { |
| 988 | 1112 | .qr--val { |
| 989 | 1113 | &:nth-child(2n) { |
| 990 | 1114 | background-color: rgb(from var(--SmartThemeEmColor) r g b / 0.0625); |
| 991 | 1115 | } |
| 1116 | + | |
| 992 | 1117 | &:hover { |
| 993 | 1118 | background-color: rgb(from var(--SmartThemeEmColor) r g b / 0.5); |
| 994 | 1119 | } |
| 995 | 1120 | } |
| 996 | 1121 | } |
| 1122 | + | |
| 997 | 1123 | &.qr--isHidden { |
| 998 | - .qr--key, .qr--val { | |
| 1124 | + | |
| 1125 | + .qr--key, | |
| 1126 | + .qr--val { | |
| 999 | 1127 | opacity: 0.5; |
| 1000 | 1128 | } |
| 1001 | 1129 | } |
| 1130 | + | |
| 1002 | 1131 | .qr--val { |
| 1003 | 1132 | grid-column: 2 / 4; |
| 1133 | + | |
| 1004 | 1134 | &.qr--singleCol { |
| 1005 | 1135 | grid-column: unset; |
| 1006 | 1136 | } |
| 1137 | + | |
| 1007 | 1138 | &.qr--simple { |
| 1008 | - &:before, &:after { | |
| 1139 | + | |
| 1140 | + &:before, | |
| 1141 | + &:after { | |
| 1009 | 1142 | content: '"'; |
| 1010 | 1143 | color: var(--SmartThemeQuoteColor); |
| 1011 | 1144 | } |
| 1012 | 1145 | } |
| 1146 | + | |
| 1013 | 1147 | &.qr--unresolved { |
| 1014 | 1148 | &:after { |
| 1015 | 1149 | content: '-UNRESOLVED-'; |
| @@ -1019,21 +1153,36 @@ | ||
| 1019 | 1153 | } |
| 1020 | 1154 | } |
| 1021 | 1155 | } |
| 1156 | + | |
| 1022 | 1157 | .qr--key { |
| 1023 | 1158 | margin-left: 0.5em; |
| 1024 | 1159 | padding-right: 1em; |
| 1025 | - &:after { content: ": "; } | |
| 1160 | + | |
| 1161 | + &:after { | |
| 1162 | + content: ": "; | |
| 1026 | 1163 | } |
| 1027 | - .qr--pipe, .qr--macro { | |
| 1164 | + } | |
| 1165 | + | |
| 1166 | + .qr--pipe, | |
| 1167 | + .qr--macro { | |
| 1028 | 1168 | >.qr--key { |
| 1029 | - &:before { content: "{{"; } | |
| 1169 | + &:before { | |
| 1030 | - &:after { content: "}}: "; } | |
| 1170 | + content: "{{"; | |
| 1171 | + } | |
| 1172 | + | |
| 1173 | + &:after { | |
| 1174 | + content: "}}: "; | |
| 1175 | + } | |
| 1031 | 1176 | } |
| 1032 | 1177 | } |
| 1178 | + | |
| 1033 | 1179 | .qr--scope { |
| 1034 | 1180 | display: contents; |
| 1181 | + | |
| 1035 | 1182 | .qr--pipe { |
| 1036 | - .qr--key, .qr--val { | |
| 1183 | + | |
| 1184 | + .qr--key, | |
| 1185 | + .qr--val { | |
| 1037 | 1186 | opacity: 0.5; |
| 1038 | 1187 | } |
| 1039 | 1188 | } |
| @@ -1043,6 +1192,7 @@ | ||
| 1043 | 1192 | .qr--stack { |
| 1044 | 1193 | display: grid; |
| 1045 | 1194 | grid-template-columns: 1fr 0fr; |
| 1195 | + | |
| 1046 | 1196 | .qr--title { |
| 1047 | 1197 | grid-column: 1 / 3; |
| 1048 | 1198 | font-weight: bold; |
| @@ -1051,16 +1201,22 @@ | ||
| 1051 | 1201 | padding: 0.25em; |
| 1052 | 1202 | margin-top: 1em; |
| 1053 | 1203 | } |
| 1204 | + | |
| 1054 | 1205 | .qr--item { |
| 1055 | 1206 | display: contents; |
| 1207 | + | |
| 1056 | 1208 | &:nth-child(2n + 1) { |
| 1057 | - .qr--name, .qr--source { | |
| 1209 | + | |
| 1210 | + .qr--name, | |
| 1211 | + .qr--source { | |
| 1058 | 1212 | background-color: rgb(from var(--SmartThemeEmColor) r g b / 0.25); |
| 1059 | 1213 | } |
| 1060 | 1214 | } |
| 1215 | + | |
| 1061 | 1216 | .qr--name { |
| 1062 | 1217 | margin-left: 0.5em; |
| 1063 | 1218 | } |
| 1219 | + | |
| 1064 | 1220 | .qr--source { |
| 1065 | 1221 | opacity: 0.5; |
| 1066 | 1222 | text-align: right; |
| @@ -1086,6 +1242,7 @@ | ||
| 1086 | 1242 | } |
| 1087 | 1243 | |
| 1088 | 1244 | @keyframes qr--debugPulse { |
| 1245 | + | |
| 1089 | 1246 | 0%, |
| 1090 | 1247 | 100% { |
| 1091 | 1248 | border-color: rgb(81, 163, 81); |
| @@ -1098,6 +1255,7 @@ | ||
| 1098 | 1255 | |
| 1099 | 1256 | .popup.qr--hide { |
| 1100 | 1257 | opacity: 0 !important; |
| 1258 | + | |
| 1101 | 1259 | &::backdrop { |
| 1102 | 1260 | opacity: 0 !important; |
| 1103 | 1261 | } |
| @@ -1117,14 +1275,16 @@ | ||
| 1117 | 1275 | overflow: hidden; |
| 1118 | 1276 | font-weight: bold; |
| 1119 | 1277 | } |
| 1278 | + | |
| 1120 | 1279 | display: flex; |
| 1121 | 1280 | align-items: center; |
| 1122 | 1281 | flex-direction: column; |
| 1123 | 1282 | white-space: pre; |
| 1124 | 1283 | font-weight: normal; |
| 1125 | 1284 | box-shadow: 0 0 0; |
| 1126 | - transition: 200ms; | |
| 1285 | + transition: var(--animation-duration-2x); | |
| 1127 | 1286 | } |
| 1287 | + | |
| 1128 | 1288 | .qr--copy { |
| 1129 | 1289 | &:after { |
| 1130 | 1290 | content: 'Copy'; |
| @@ -1132,24 +1292,28 @@ | ||
| 1132 | 1292 | overflow: hidden; |
| 1133 | 1293 | font-weight: bold; |
| 1134 | 1294 | } |
| 1295 | + | |
| 1135 | 1296 | display: flex; |
| 1136 | 1297 | align-items: center; |
| 1137 | 1298 | flex-direction: column; |
| 1138 | 1299 | white-space: pre; |
| 1139 | 1300 | font-weight: normal; |
| 1140 | 1301 | box-shadow: 0 0 0; |
| 1141 | - transition: 200ms; | |
| 1302 | + transition: var(--animation-duration-2x); | |
| 1142 | 1303 | } |
| 1304 | + | |
| 1143 | 1305 | &:has(.qr--transferSelect:focus) { |
| 1144 | 1306 | .popup-button-ok { |
| 1145 | 1307 | font-weight: bold; |
| 1146 | 1308 | box-shadow: 0 0 10px; |
| 1147 | 1309 | } |
| 1310 | + | |
| 1148 | 1311 | &.qr--isCopy { |
| 1149 | 1312 | .popup-button-ok { |
| 1150 | 1313 | font-weight: normal; |
| 1151 | 1314 | box-shadow: 0 0 0; |
| 1152 | 1315 | } |
| 1316 | + | |
| 1153 | 1317 | .qr--copy { |
| 1154 | 1318 | font-weight: bold; |
| 1155 | 1319 | box-shadow: 0 0 10px; |
| @@ -24,7 +24,7 @@ | ||
| 24 | 24 | |
| 25 | 25 | #scoped_scripts_block { |
| 26 | 26 | opacity: 1; |
| 27 | 27 | transition: opacity 0.2svar(--animation-duration-2x) ease-in-out; |
| 28 | 28 | } |
| 29 | 29 | |
| 30 | 30 | #scoped_scripts_block .move_to_scoped { |
| @@ -78,7 +78,7 @@ input.enable_scoped { | ||
| 78 | 78 | cursor: pointer; |
| 79 | 79 | opacity: 0.5; |
| 80 | 80 | filter: grayscale(0.5); |
| 81 | 81 | transition: opacity 0.2svar(--animation-duration-2x) ease-in-out; |
| 82 | 82 | } |
| 83 | 83 | |
| 84 | 84 | .regex-toggle-off:hover { |
| @@ -25,7 +25,7 @@ | ||
| 25 | 25 | outline: none; |
| 26 | 26 | border: none; |
| 27 | 27 | cursor: pointer; |
| 28 | - transition: 0.3s; | |
| 28 | + transition: var(--animation-duration-2x); | |
| 29 | 29 | opacity: 0.7; |
| 30 | 30 | align-items: center; |
| 31 | 31 | justify-content: center; |
| @@ -2153,20 +2153,22 @@ export function getFreeName(name, list, numberFormatter = (n) => ` #${n}`) { | ||
| 2153 | 2153 | */ |
| 2154 | 2154 | export function toggleDrawer(drawer, expand = true) { |
| 2155 | 2155 | /** @type {HTMLElement} */ |
| 2156 | 2156 | const icon = drawer.querySelector(':scope > .inline-drawer-header .inline-drawer-icon'); |
| 2157 | 2157 | /** @type {HTMLElement} */ |
| 2158 | 2158 | const content = drawer.querySelector(':scope > .inline-drawer-content'); |
| 2159 | 2159 | |
| 2160 | 2160 | if (expand) { |
| 2161 | - icon.classList.remove('up', 'fa-circle-chevron-up'); | |
| 2162 | - icon.classList.add('down', 'fa-circle-chevron-down'); | |
| 2163 | - content.style.display = 'block'; | |
| 2164 | - } else { | |
| 2165 | 2161 | icon.classList.remove('down', 'fa-circle-chevron-down'); |
| 2166 | 2162 | icon.classList.add('up', 'fa-circle-chevron-up'); |
| 2163 | + content.style.display = 'block'; | |
| 2164 | + } else { | |
| 2165 | + icon.classList.remove('up', 'fa-circle-chevron-up'); | |
| 2166 | + icon.classList.add('down', 'fa-circle-chevron-down'); | |
| 2167 | 2167 | content.style.display = 'none'; |
| 2168 | 2168 | } |
| 2169 | 2169 | |
| 2170 | + drawer.dispatchEvent(new CustomEvent('inline-drawer-toggle', { bubbles: true })); | |
| 2171 | + | |
| 2170 | 2172 | // Set the height of "autoSetHeight" textareas within the inline-drawer to their scroll height |
| 2171 | 2173 | if (!CSS.supports('field-sizing', 'content')) { |
| 2172 | 2174 | content.querySelectorAll('textarea.autoSetHeight').forEach(resetScrollHeight); |
| @@ -58,7 +58,8 @@ export const scan_state = { | ||
| 58 | 58 | MIN_ACTIVATIONS: 3, |
| 59 | 59 | }; |
| 60 | 60 | |
| 61 | 61 | const WI_ENTRY_EDIT_TEMPLATEWI_ENTRY_HEADER_TEMPLATE = $('#entry_edit_template .world_entry'); |
| 62 | +const WI_ENTRY_EDIT_TEMPLATE = $('#entry_edit_template .world_entry_edit'); | |
| 62 | 63 | |
| 63 | 64 | export let world_info = {}; |
| 64 | 65 | export let selected_world_info = []; |
| @@ -85,6 +86,7 @@ const saveSettingsDebounced = debounce(() => { | ||
| 85 | 86 | }, debounce_timeout.relaxed); |
| 86 | 87 | const sortFn = (a, b) => b.order - a.order; |
| 87 | 88 | let updateEditor = (navigation, flashOnNav = true) => { console.debug('Triggered WI navigation', navigation, flashOnNav); }; |
| 89 | +let isSaveWorldInfoDisabled = false; | |
| 88 | 90 | |
| 89 | 91 | // Do not optimize. updateEditor is a function that is updated by the displayWorldEntries with new data. |
| 90 | 92 | export const worldInfoFilter = new FilterHelper(() => updateEditor()); |
| @@ -965,6 +967,7 @@ export function reloadEditor(file, loadIfNotSelected = false) { | ||
| 965 | 967 | } |
| 966 | 968 | } |
| 967 | 969 | |
| 970 | +//MARK: regWISlashCommands | |
| 968 | 971 | function registerWorldInfoSlashCommands() { |
| 969 | 972 | /** |
| 970 | 973 | * Gets a *rough* approximation of the current chat context. |
| @@ -1754,12 +1757,12 @@ function registerWorldInfoSlashCommands() { | ||
| 1754 | 1757 | */ |
| 1755 | 1758 | export async function showWorldEditor(name) { |
| 1756 | 1759 | if (!name) { |
| 1757 | 1760 | await hideWorldEditor(); |
| 1758 | 1761 | return; |
| 1759 | 1762 | } |
| 1760 | 1763 | |
| 1761 | 1764 | const wiData = await loadWorldInfo(name); |
| 1762 | 1765 | await displayWorldEntries(name, wiData); |
| 1763 | 1766 | } |
| 1764 | 1767 | |
| 1765 | 1768 | /** |
| @@ -1815,8 +1818,8 @@ export async function updateWorldInfoList() { | ||
| 1815 | 1818 | } |
| 1816 | 1819 | } |
| 1817 | 1820 | |
| 1818 | 1821 | async function hideWorldEditor() { |
| 1819 | 1822 | await displayWorldEntries(null, null); |
| 1820 | 1823 | } |
| 1821 | 1824 | |
| 1822 | 1825 | function getWIElement(name) { |
| @@ -1937,15 +1940,72 @@ function updateWorldEntryKeyOptionsCache(keyOptions, { remove = false, reset = f | ||
| 1937 | 1940 | worldEntryKeyOptionsCache.sort((a, b) => b.count - a.count || a.text.localeCompare(b.text)); |
| 1938 | 1941 | } |
| 1939 | 1942 | |
| 1940 | -function displayWorldEntries(name, data, navigation = navigation_option.none, flashOnNav = true) { | |
| 1943 | +function clearEntryList($list) { | |
| 1941 | - updateEditor = (navigation, flashOnNav = true) => displayWorldEntries(name, data, navigation, flashOnNav); | |
| 1944 | + console.time('clearEntryList'); | |
| 1942 | 1945 | |
| 1943 | - const worldEntriesList = $('#world_popup_entries_list'); | |
| 1946 | + if (!$list.children().length) { | |
| 1947 | + console.debug('List already empty, skipping cleanup.'); | |
| 1948 | + console.timeEnd('clearEntryList'); | |
| 1949 | + return; | |
| 1950 | + } | |
| 1951 | + | |
| 1952 | + // Step 1: Clean all <option> elements within <select> | |
| 1953 | + $list.find('option').each(function () { | |
| 1954 | + const $option = $(this); | |
| 1955 | + $option.off(); | |
| 1956 | + $.cleanData([$option[0]]); | |
| 1957 | + $option.remove(); | |
| 1958 | + }); | |
| 1959 | + | |
| 1960 | + // Step 2: Clean all <select> elements | |
| 1961 | + $list.find('select').each(function () { | |
| 1962 | + const $select = $(this); | |
| 1963 | + // Remove Select2-related data and container if present | |
| 1964 | + if ($select.data('select2')) { | |
| 1965 | + try { | |
| 1966 | + $select.select2('destroy'); | |
| 1967 | + } catch (e) { | |
| 1968 | + console.debug('Select2 destroy failed:', e); | |
| 1969 | + } | |
| 1970 | + } | |
| 1971 | + const $container = $select.parent(); | |
| 1972 | + if ($container.length) { | |
| 1973 | + $container.find('*').off(); | |
| 1974 | + $.cleanData($container.find('*').get()); | |
| 1975 | + $container.remove(); | |
| 1976 | + } | |
| 1977 | + | |
| 1978 | + $select.off(); | |
| 1979 | + $.cleanData([$select[0]]); | |
| 1980 | + }); | |
| 1981 | + | |
| 1982 | + // Step 3: Clean <div>, <span>, <input> | |
| 1983 | + $list.find('div, span, input').each(function () { | |
| 1984 | + const $elem = $(this); | |
| 1985 | + $elem.off(); | |
| 1986 | + $.cleanData([$elem[0]]); | |
| 1987 | + $elem.remove(); | |
| 1988 | + }); | |
| 1989 | + | |
| 1990 | + const totalElementsOfAnyKindLeftInList = $list.children().length; | |
| 1991 | + | |
| 1992 | + // Final cleanup | |
| 1993 | + if (totalElementsOfAnyKindLeftInList) { | |
| 1994 | + console.time('empty'); | |
| 1995 | + $list.empty(); | |
| 1996 | + console.timeEnd('empty'); | |
| 1997 | + } | |
| 1944 | 1998 | |
| 1945 | - // We save costly performance by removing all events before emptying. Because we know there are no relevant event handlers reacting on removing elements | |
| 1999 | + console.timeEnd('clearEntryList'); | |
| 1946 | - // This prevents jQuery from actually going through all registered events on the controls for each entry when removing it | |
| 2000 | +} | |
| 1947 | - worldEntriesList.find('*').off(); | |
| 2001 | + | |
| 1948 | - worldEntriesList.empty().show(); | |
| 2002 | +//MARK: displayWorldEntries | |
| 2003 | +async function displayWorldEntries(name, data, navigation = navigation_option.none, flashOnNav = true) { | |
| 2004 | + updateEditor = async (navigation, flashOnNav = true) => await displayWorldEntries(name, data, navigation, flashOnNav); | |
| 2005 | + | |
| 2006 | + const worldEntriesList = $('#world_popup_entries_list'); | |
| 2007 | + clearEntryList(worldEntriesList); | |
| 2008 | + worldEntriesList.show(); | |
| 1949 | 2009 | |
| 1950 | 2010 | if (!data || !('entries' in data)) { |
| 1951 | 2011 | $('#world_popup_new').off('click').on('click', nullWorldInfo); |
| @@ -2038,22 +2098,39 @@ function displayWorldEntries(name, data, navigation = navigation_option.none, fl | ||
| 2038 | 2098 | formatNavigator: PAGINATION_TEMPLATE, |
| 2039 | 2099 | showNavigator: true, |
| 2040 | 2100 | callback: async function (/** @type {object[]} */ page) { |
| 2041 | - // We save costly performance by removing all events before emptying. Because we know there are no relevant event handlers reacting on removing elements | |
| 2101 | + try { | |
| 2042 | - // This prevents jQuery from actually going through all registered events on the controls for each entry when removing it | |
| 2102 | + // Prevent saveWorldInfo from firing timeouts while rendering the list | |
| 2043 | - worldEntriesList.find('*').off(); | |
| 2103 | + isSaveWorldInfoDisabled = true; | |
| 2044 | - worldEntriesList.empty(); | |
| 2104 | + clearEntryList(worldEntriesList); | |
| 2045 | 2105 | |
| 2046 | 2106 | const keywordHeaders = await renderTemplateAsync('worldInfoKeywordHeaders'); |
| 2047 | - const blocksPromises = page.map(async (entry) => await getWorldEntry(name, data, entry)).filter(x => x); | |
| 2107 | + const blocks = []; | |
| 2048 | - const blocks = await Promise.all(blocksPromises); | |
| 2108 | + | |
| 2109 | + for (const entry of page) { | |
| 2110 | + try { | |
| 2111 | + const block = await getWorldEntry(name, data, entry); | |
| 2112 | + if (block) { | |
| 2113 | + blocks.push(block); | |
| 2114 | + } | |
| 2115 | + } catch (error) { | |
| 2116 | + console.error(`Error while processing entry ${entry.uid}:`, error); | |
| 2117 | + } | |
| 2118 | + } | |
| 2119 | + | |
| 2049 | 2120 | const isCustomOrder = $('#world_info_sort_order').find(':selected').data('rule') === 'custom'; |
| 2050 | 2121 | if (!isCustomOrder) { |
| 2051 | 2122 | blocks.forEach(block => { |
| 2052 | 2123 | block.find('.drag-handle').remove(); |
| 2053 | 2124 | }); |
| 2054 | 2125 | } |
| 2126 | + | |
| 2055 | 2127 | worldEntriesList.append(keywordHeaders); |
| 2056 | 2128 | worldEntriesList.append(blocks); |
| 2129 | + } catch (error) { | |
| 2130 | + console.error('Error while rendering WI entries:', error); | |
| 2131 | + } finally { | |
| 2132 | + isSaveWorldInfoDisabled = false; | |
| 2133 | + } | |
| 2057 | 2134 | }, |
| 2058 | 2135 | afterSizeSelectorChange: function (e) { |
| 2059 | 2136 | accountStorage.setItem(storageKey, e.target.value); |
| @@ -2173,7 +2250,7 @@ function displayWorldEntries(name, data, navigation = navigation_option.none, fl | ||
| 2173 | 2250 | if (selectedIndex !== -1) { |
| 2174 | 2251 | $('#world_editor_select').val(selectedIndex).trigger('change'); |
| 2175 | 2252 | } else { |
| 2176 | 2253 | await hideWorldEditor(); |
| 2177 | 2254 | } |
| 2178 | 2255 | } |
| 2179 | 2256 | }); |
| @@ -2211,6 +2288,7 @@ function displayWorldEntries(name, data, navigation = navigation_option.none, fl | ||
| 2211 | 2288 | await saveWorldInfo(name, data); |
| 2212 | 2289 | }, |
| 2213 | 2290 | }); |
| 2291 | + | |
| 2214 | 2292 | //$("#world_popup_entries_list").disableSelection(); |
| 2215 | 2293 | } |
| 2216 | 2294 | |
| @@ -2453,51 +2531,32 @@ export function parseRegexFromString(input) { | ||
| 2453 | 2531 | } |
| 2454 | 2532 | } |
| 2455 | 2533 | |
| 2456 | -export async function getWorldEntry(name, data, entry) { | |
| 2534 | +//MARK: getWorldEntry | |
| 2457 | - if (!data.entries[entry.uid]) { | |
| 2535 | +function enableKeysInputHelper({ template, entry, entryPropName, originalDataValueName, name, data }) { | |
| 2458 | - return; | |
| 2459 | - } | |
| 2460 | - | |
| 2461 | - const template = WI_ENTRY_EDIT_TEMPLATE.clone(); | |
| 2462 | - template.data('uid', entry.uid); | |
| 2463 | - template.attr('uid', entry.uid); | |
| 2464 | - | |
| 2465 | - // Init default state of WI Key toggle (=> true) | |
| 2466 | - if (typeof power_user.wi_key_input_plaintext === 'undefined') power_user.wi_key_input_plaintext = true; | |
| 2467 | - | |
| 2468 | - /** Function to build the keys input controls @param {string} entryPropName @param {string} originalDataValueName */ | |
| 2469 | - function enableKeysInput(entryPropName, originalDataValueName) { | |
| 2470 | 2536 | const isFancyInput = !isMobile() && !power_user.wi_key_input_plaintext; |
| 2471 | 2537 | const input = isFancyInput ? template.find(`select[name="${entryPropName}"]`) : template.find(`textarea[name="${entryPropName}"]`); |
| 2472 | 2538 | input.data('uid', entry.uid); |
| 2473 | 2539 | input.on('click', function (event) { |
| 2474 | - // Prevent closing the drawer on clicking the input | |
| 2475 | 2540 | event.stopPropagation(); |
| 2476 | 2541 | }); |
| 2477 | 2542 | |
| 2478 | 2543 | function templateStyling(/** @type {Select2Option} */ item, { searchStyle = false } = {}) { |
| 2479 | 2544 | const content = $('<span>').addClass('item').text(item.text).attr('title', `${item.text}\n\nClick to edit`); |
| 2480 | 2545 | const isRegex = isValidRegex(item.text); |
| 2481 | 2546 | if (isRegex) { |
| 2482 | 2547 | content.html(highlightRegex(item.text)); |
| 2483 | 2548 | content.addClass('regex_item').prepend($('<span>').addClass('regex_icon').text('•*').attr('title', 'Regex')); |
| 2484 | 2549 | } |
| 2485 | - | |
| 2486 | 2550 | if (searchStyle && item.count) { |
| 2487 | - // Build a wrapping element | |
| 2551 | + const wrapper = $('<span>').addClass('result_block').append(content); | |
| 2488 | - const wrapper = $('<span>').addClass('result_block') | |
| 2489 | - .append(content); | |
| 2490 | 2552 | wrapper.append($('<span>').addClass('item_count').text(item.count).attr('title', `Used as a key ${item.count} ${item.count != 1 ? 'times' : 'time'} in this lorebook`)); |
| 2491 | 2553 | return wrapper; |
| 2492 | 2554 | } |
| 2493 | - | |
| 2494 | 2555 | return content; |
| 2495 | 2556 | } |
| 2496 | 2557 | |
| 2497 | 2558 | if (isFancyInput) { |
| 2498 | - // First initialize existing values as options, before initializing select2, to speed up performance | |
| 2499 | 2559 | select2ModifyOptions(input, entry[entryPropName], { select: true, changeEventArgs: { skipReset: true, noSave: true } }); |
| 2500 | - | |
| 2501 | 2560 | input.select2({ |
| 2502 | 2561 | ajax: dynamicSelect2DataViaAjax(() => worldEntryKeyOptionsCache), |
| 2503 | 2562 | tags: true, |
| @@ -2507,12 +2566,18 @@ export async function getWorldEntry(name, data, entry) { | ||
| 2507 | 2566 | templateResult: item => templateStyling(item, { searchStyle: true }), |
| 2508 | 2567 | templateSelection: item => templateStyling(item), |
| 2509 | 2568 | }); |
| 2510 | - input.on('change', async function (_, { skipReset, noSave } = {}) { | |
| 2569 | + | |
| 2570 | + // TypeScript-safe event handler | |
| 2571 | + /** | |
| 2572 | + * @param {Event} _event | |
| 2573 | + * @param {{ skipReset?: boolean, noSave?: boolean }} [arg] | |
| 2574 | + */ | |
| 2575 | + input.on('change', async function (_event, arg) { | |
| 2511 | 2576 | const uid = $(this).data('uid'); |
| 2512 | - /** @type {string[]} */ | |
| 2513 | 2577 | const keys = ($(this).select2('data')).map(x => x.text); |
| 2514 | - | |
| 2578 | + const skipReset = arg?.skipReset ?? false; | |
| 2515 | - !skipReset && await resetScrollHeight(this); | |
| 2579 | + const noSave = arg?.noSave ?? false; | |
| 2580 | + if (!skipReset) await resetScrollHeight(this); | |
| 2516 | 2581 | if (!noSave) { |
| 2517 | 2582 | data.entries[uid][entryPropName] = keys; |
| 2518 | 2583 | setWIOriginalDataValue(data, uid, originalDataValueName, data.entries[uid][entryPropName]); |
| @@ -2520,37 +2585,34 @@ export async function getWorldEntry(name, data, entry) { | ||
| 2520 | 2585 | } |
| 2521 | 2586 | $(this).toggleClass('empty', !data.entries[uid][entryPropName].length); |
| 2522 | 2587 | }); |
| 2588 | + | |
| 2523 | 2589 | input.toggleClass('empty', !entry[entryPropName].length); |
| 2524 | 2590 | input.on('select2:select', /** @type {function(*):void} */ event => updateWorldEntryKeyOptionsCache([event.params.data])); |
| 2525 | 2591 | input.on('select2:unselect', /** @type {function(*):void} */ event => updateWorldEntryKeyOptionsCache([event.params.data], { remove: true })); |
| 2526 | 2592 | |
| 2527 | 2593 | select2ChoiceClickSubscribe(input, target => { |
| 2528 | 2594 | const key = $(target.closest('.regex-highlight, .item')).text(); |
| 2529 | - console.debug('Editing WI key', key); | |
| 2530 | - | |
| 2531 | - // Remove the current key from the actual selection | |
| 2532 | 2595 | const selected = input.val(); |
| 2533 | 2596 | if (!Array.isArray(selected)) return; |
| 2534 | 2597 | var index = selected.indexOf(getSelect2OptionId(key)); |
| 2535 | 2598 | if (index > -1) selected.splice(index, 1); |
| 2536 | 2599 | input.val(selected).trigger('change'); |
| 2537 | - // Manually update the cache, that change event is not gonna trigger it | |
| 2538 | 2600 | updateWorldEntryKeyOptionsCache([key], { remove: true }); |
| 2539 | - | |
| 2601 | + input.next('span.select2-container').find('textarea').val(key).trigger('input'); | |
| 2540 | - // We need to "hack" the actual text input into the currently open textarea | |
| 2541 | - input.next('span.select2-container').find('textarea') | |
| 2542 | - .val(key).trigger('input'); | |
| 2543 | 2602 | }, { openDrawer: true }); |
| 2544 | - } | |
| 2603 | + } else { | |
| 2545 | - else { | |
| 2546 | - // Compatibility with mobile devices. On mobile we need a text input field, not a select option control, so we need its own event handlers | |
| 2547 | 2604 | template.find(`select[name="${entryPropName}"]`).hide(); |
| 2548 | 2605 | input.show(); |
| 2549 | - | |
| 2606 | + /** | |
| 2550 | - input.on('input', async function (_, { skipReset, noSave } = {}) { | |
| 2607 | + * @param {Event} _event | |
| 2608 | + * @param {{ skipReset?: boolean, noSave?: boolean }} [arg] | |
| 2609 | + */ | |
| 2610 | + input.on('change', async function (_event, arg) { | |
| 2551 | 2611 | const uid = $(this).data('uid'); |
| 2552 | 2612 | const value = String($(this).val()); |
| 2553 | - !skipReset && await resetScrollHeight(this); | |
| 2613 | + const skipReset = arg?.skipReset ?? false; | |
| 2614 | + const noSave = arg?.noSave ?? false; | |
| 2615 | + if (!skipReset) await resetScrollHeight(this); | |
| 2554 | 2616 | if (!noSave) { |
| 2555 | 2617 | data.entries[uid][entryPropName] = splitKeywordsAndRegexes(value); |
| 2556 | 2618 | setWIOriginalDataValue(data, uid, originalDataValueName, data.entries[uid][entryPropName]); |
| @@ -2563,98 +2625,43 @@ export async function getWorldEntry(name, data, entry) { | ||
| 2563 | 2625 | return { isFancy: isFancyInput, control: input }; |
| 2564 | 2626 | } |
| 2565 | 2627 | |
| 2566 | - // key | |
| 2628 | +/** | |
| 2567 | - const keyInput = enableKeysInput('key', 'keys'); | |
| 2629 | + * Helper to handle match checkboxes for WI entries. | |
| 2568 | - | |
| 2630 | + */ | |
| 2569 | - // keysecondary | |
| 2631 | +function handleMatchCheckboxHelper({ template, entry, fieldName, data, name }) { | |
| 2570 | - const keySecondaryInput = enableKeysInput('keysecondary', 'secondary_keys'); | |
| 2632 | + const key = originalWIDataKeyMap[fieldName]; | |
| 2571 | - | |
| 2633 | + const checkBoxElem = template.find(`input[type="checkbox"][name="${fieldName}"]`); | |
| 2572 | - // draw key input switch button | |
| 2634 | + checkBoxElem.data('uid', entry.uid); | |
| 2573 | 2635 | template.find('.switch_input_type_icon')checkBoxElem.on('clickinput', async function () { |
| 2574 | - power_user.wi_key_input_plaintext = !power_user.wi_key_input_plaintext; | |
| 2575 | - saveSettingsDebounced(); | |
| 2576 | - | |
| 2577 | - // Just redraw the panel | |
| 2578 | - const uid = ($(this).parents('.world_entry')).data('uid'); | |
| 2579 | - updateEditor(uid, false); | |
| 2580 | - | |
| 2581 | - $(`.world_entry[uid="${uid}"] .inline-drawer-icon`).trigger('click'); | |
| 2582 | - // setTimeout(() => { | |
| 2583 | - // }, debounce_timeout.standard); | |
| 2584 | - }).each((_, icon) => { | |
| 2585 | - $(icon).attr('title', $(icon).data(power_user.wi_key_input_plaintext ? 'tooltip-on' : 'tooltip-off')); | |
| 2586 | - $(icon).text($(icon).data(power_user.wi_key_input_plaintext ? 'icon-on' : 'icon-off')); | |
| 2587 | - }); | |
| 2588 | - | |
| 2589 | - // logic AND/NOT | |
| 2590 | - const selectiveLogicDropdown = template.find('select[name="entryLogicType"]'); | |
| 2591 | - selectiveLogicDropdown.data('uid', entry.uid); | |
| 2592 | - | |
| 2593 | - selectiveLogicDropdown.on('click', function (event) { | |
| 2594 | - event.stopPropagation(); | |
| 2595 | - }); | |
| 2596 | - | |
| 2597 | - selectiveLogicDropdown.on('input', async function () { | |
| 2598 | 2636 | const uid = $(this).data('uid'); |
| 2599 | 2637 | const value = Number($(this).valprop()'checked'); |
| 2600 | 2638 | data.entries[uid].selectiveLogic[fieldName] = !isNaN(value) ? value : world_info_logic.AND_ANY; |
| 2601 | 2639 | setWIOriginalDataValue(data, uid, 'selectiveLogic'key, data.entries[uid].selectiveLogic[fieldName]); |
| 2602 | 2640 | await saveWorldInfo(name, data); |
| 2603 | 2641 | }); |
| 2604 | - | |
| 2642 | + checkBoxElem.prop('checked', !!entry[fieldName]).trigger('input'); | |
| 2605 | - template | |
| 2606 | - .find(`select[name="entryLogicType"] option[value=${entry.selectiveLogic}]`) | |
| 2607 | - .prop('selected', true) | |
| 2608 | - .trigger('input'); | |
| 2609 | - | |
| 2610 | - // Character filter | |
| 2611 | - const characterFilterLabel = template.find('label[for="characterFilter"] > small'); | |
| 2612 | - characterFilterLabel.text(entry.characterFilter?.isExclude ? 'Exclude Character(s)' : 'Filter to Character(s)'); | |
| 2613 | - | |
| 2614 | - // exclude characters checkbox | |
| 2615 | - const characterExclusionInput = template.find('input[name="character_exclusion"]'); | |
| 2616 | - characterExclusionInput.data('uid', entry.uid); | |
| 2617 | - characterExclusionInput.on('input', async function () { | |
| 2618 | - const uid = $(this).data('uid'); | |
| 2619 | - const value = $(this).prop('checked'); | |
| 2620 | - characterFilterLabel.text(value ? 'Exclude Character(s)' : 'Filter to Character(s)'); | |
| 2621 | - if (data.entries[uid].characterFilter) { | |
| 2622 | - if (!value && data.entries[uid].characterFilter.names.length === 0 && data.entries[uid].characterFilter.tags.length === 0) { | |
| 2623 | - delete data.entries[uid].characterFilter; | |
| 2624 | - } else { | |
| 2625 | - data.entries[uid].characterFilter.isExclude = value; | |
| 2626 | - } | |
| 2627 | - } else if (value) { | |
| 2628 | - Object.assign( | |
| 2629 | - data.entries[uid], | |
| 2630 | - { | |
| 2631 | - characterFilter: { | |
| 2632 | - isExclude: true, | |
| 2633 | - names: [], | |
| 2634 | - tags: [], | |
| 2635 | - }, | |
| 2636 | - }, | |
| 2637 | - ); | |
| 2638 | 2643 | } |
| 2639 | 2644 | |
| 2640 | - // Verify names to exist in the system | |
| 2645 | +/** | |
| 2641 | - if (data.entries[uid]?.characterFilter?.names?.length > 0) { | |
| 2646 | + * Helper to update position/order display. | |
| 2642 | - for (const name of [...data.entries[uid].characterFilter.names]) { | |
| 2647 | + */ | |
| 2643 | - if (!getContext().characters.find(x => x.avatar.replace(/\.[^/.]+$/, '') === name)) { | |
| 2648 | +function updatePosOrdDisplayHelper({ template, data, uid }) { | |
| 2644 | - console.warn(`World Info: Character ${name} not found. Removing from the entry filter.`, entry); | |
| 2649 | + let entry = data.entries[uid]; | |
| 2645 | - data.entries[uid].characterFilter.names = data.entries[uid].characterFilter.names.filter(x => x !== name); | |
| 2650 | + let posText = entry.position; | |
| 2646 | - } | |
| 2651 | + switch (entry.position) { | |
| 2652 | + case 0: posText = '↑CD'; break; | |
| 2653 | + case 1: posText = 'CD↓'; break; | |
| 2654 | + case 2: posText = '↑AN'; break; | |
| 2655 | + case 3: posText = 'AN↓'; break; | |
| 2656 | + case 4: posText = `@D${entry.depth}`; break; | |
| 2647 | 2657 | } |
| 2658 | + template.find('.world_entry_form_position_value').text(`(${posText} ${entry.order})`); | |
| 2648 | 2659 | } |
| 2649 | 2660 | |
| 2650 | - setWIOriginalDataValue(data, uid, 'character_filter', data.entries[uid].characterFilter); | |
| 2661 | +/** | |
| 2651 | - await saveWorldInfo(name, data); | |
| 2662 | + * Helper to initialize character filter select2. | |
| 2652 | - }); | |
| 2663 | + */ | |
| 2653 | - characterExclusionInput.prop('checked', entry.characterFilter?.isExclude ?? false).trigger('input'); | |
| 2664 | +function initCharacterFilterSelect2Helper(characterFilter, t) { | |
| 2654 | - | |
| 2655 | - const characterFilter = template.find('select[name="characterFilter"]'); | |
| 2656 | - characterFilter.data('uid', entry.uid); | |
| 2657 | - | |
| 2658 | 2665 | if (!isMobile()) { |
| 2659 | 2666 | $(characterFilter).select2({ |
| 2660 | 2667 | width: '100%', |
| @@ -2663,7 +2670,12 @@ export async function getWorldEntry(name, data, entry) { | ||
| 2663 | 2670 | closeOnSelect: false, |
| 2664 | 2671 | }); |
| 2665 | 2672 | } |
| 2673 | +} | |
| 2666 | 2674 | |
| 2675 | +/** | |
| 2676 | + * Helper to fill character and tag options for character filter. | |
| 2677 | + */ | |
| 2678 | +function fillCharacterAndTagOptionsHelper({ characterFilter, entry, getContext }) { | |
| 2667 | 2679 | const characters = getContext().characters; |
| 2668 | 2680 | characters.forEach((character) => { |
| 2669 | 2681 | const option = document.createElement('option'); |
| @@ -2673,7 +2685,6 @@ export async function getWorldEntry(name, data, entry) { | ||
| 2673 | 2685 | option.setAttribute('data-type', 'character'); |
| 2674 | 2686 | characterFilter.append(option); |
| 2675 | 2687 | }); |
| 2676 | - | |
| 2677 | 2688 | const tags = getContext().tags; |
| 2678 | 2689 | tags.forEach((tag) => { |
| 2679 | 2690 | const option = document.createElement('option'); |
| @@ -2683,14 +2694,17 @@ export async function getWorldEntry(name, data, entry) { | ||
| 2683 | 2694 | option.setAttribute('data-type', 'tag'); |
| 2684 | 2695 | characterFilter.append(option); |
| 2685 | 2696 | }); |
| 2697 | +} | |
| 2686 | 2698 | |
| 2699 | +/** | |
| 2700 | + * Helper to handle character filter changes. | |
| 2701 | + */ | |
| 2702 | +function handleCharacterFilterChangeHelper({ characterFilter, data, entry, name, world_names, getContext, setWIOriginalDataValue, saveWorldInfo, t }) { | |
| 2687 | 2703 | characterFilter.on('mousedown change', async function (e) { |
| 2688 | - // If there's no world names, don't do anything | |
| 2689 | 2704 | if (world_names.length === 0) { |
| 2690 | 2705 | e.preventDefault(); |
| 2691 | 2706 | return; |
| 2692 | 2707 | } |
| 2693 | - | |
| 2694 | 2708 | const uid = $(this).data('uid'); |
| 2695 | 2709 | const selected = $(this).find(':selected'); |
| 2696 | 2710 | if ((!selected || selected?.length === 0) && !data.entries[uid].characterFilter?.isExclude) { |
| @@ -2712,361 +2726,99 @@ export async function getWorldEntry(name, data, entry) { | ||
| 2712 | 2726 | setWIOriginalDataValue(data, uid, 'character_filter', data.entries[uid].characterFilter); |
| 2713 | 2727 | await saveWorldInfo(name, data); |
| 2714 | 2728 | }); |
| 2715 | - | |
| 2716 | - // comment | |
| 2717 | - const commentInput = template.find('textarea[name="comment"]'); | |
| 2718 | - const commentToggle = template.find('input[name="addMemo"]'); | |
| 2719 | - commentInput.data('uid', entry.uid); | |
| 2720 | - commentInput.on('input', async function (_, { skipReset } = {}) { | |
| 2721 | - const uid = $(this).data('uid'); | |
| 2722 | - const value = $(this).val(); | |
| 2723 | - !skipReset && await resetScrollHeight(this); | |
| 2724 | - data.entries[uid].comment = value; | |
| 2725 | - | |
| 2726 | - setWIOriginalDataValue(data, uid, 'comment', data.entries[uid].comment); | |
| 2727 | - await saveWorldInfo(name, data); | |
| 2728 | - }); | |
| 2729 | - commentToggle.data('uid', entry.uid); | |
| 2730 | - commentToggle.on('input', async function () { | |
| 2731 | - const uid = $(this).data('uid'); | |
| 2732 | - const value = $(this).prop('checked'); | |
| 2733 | - //console.log(value) | |
| 2734 | - const commentContainer = $(this) | |
| 2735 | - .closest('.world_entry') | |
| 2736 | - .find('.commentContainer'); | |
| 2737 | - data.entries[uid].addMemo = value; | |
| 2738 | - await saveWorldInfo(name, data); | |
| 2739 | - value ? commentContainer.show() : commentContainer.hide(); | |
| 2740 | - }); | |
| 2741 | - | |
| 2742 | - commentInput.val(entry.comment).trigger('input', { skipReset: true }); | |
| 2743 | - //initScrollHeight(commentInput); | |
| 2744 | - commentToggle.prop('checked', true /* entry.addMemo */).trigger('input'); | |
| 2745 | - commentToggle.parent().hide(); | |
| 2746 | - | |
| 2747 | - // content | |
| 2748 | - const counter = template.find('.world_entry_form_token_counter'); | |
| 2749 | - const countTokensDebounced = debounce(async function (counter, value) { | |
| 2750 | - const numberOfTokens = await getTokenCountAsync(value); | |
| 2751 | - $(counter).text(numberOfTokens); | |
| 2752 | - }, debounce_timeout.relaxed); | |
| 2753 | - | |
| 2754 | - const contentInputId = `world_entry_content_${entry.uid}`; | |
| 2755 | - const contentInput = template.find('textarea[name="content"]'); | |
| 2756 | - contentInput.data('uid', entry.uid); | |
| 2757 | - contentInput.attr('id', contentInputId); | |
| 2758 | - contentInput.on('input', async function (_, { skipCount } = {}) { | |
| 2759 | - const uid = $(this).data('uid'); | |
| 2760 | - const value = $(this).val(); | |
| 2761 | - data.entries[uid].content = value; | |
| 2762 | - | |
| 2763 | - setWIOriginalDataValue(data, uid, 'content', data.entries[uid].content); | |
| 2764 | - await saveWorldInfo(name, data); | |
| 2765 | - | |
| 2766 | - if (skipCount) { | |
| 2767 | - return; | |
| 2768 | - } | |
| 2769 | - | |
| 2770 | - // count tokens | |
| 2771 | - countTokensDebounced(counter, value); | |
| 2772 | - }); | |
| 2773 | - contentInput.val(entry.content).trigger('input', { skipCount: true }); | |
| 2774 | - | |
| 2775 | - const contentExpandButton = template.find('.editor_maximize'); | |
| 2776 | - contentExpandButton.attr('data-for', contentInputId); | |
| 2777 | - | |
| 2778 | - template.find('.inline-drawer-toggle').on('click', function () { | |
| 2779 | - if (counter.data('first-run')) { | |
| 2780 | - counter.data('first-run', false); | |
| 2781 | - countTokensDebounced(counter, contentInput.val()); | |
| 2782 | - if (!keyInput.isFancy) initScrollHeight(keyInput.control); | |
| 2783 | - if (!keySecondaryInput.isFancy) initScrollHeight(keySecondaryInput.control); | |
| 2784 | 2729 | } |
| 2785 | - }); | |
| 2786 | - | |
| 2787 | - // selective | |
| 2788 | - const selectiveInput = template.find('input[name="selective"]'); | |
| 2789 | - selectiveInput.data('uid', entry.uid); | |
| 2790 | - selectiveInput.on('input', async function () { | |
| 2791 | - const uid = $(this).data('uid'); | |
| 2792 | - const value = $(this).prop('checked'); | |
| 2793 | - data.entries[uid].selective = value; | |
| 2794 | - | |
| 2795 | - setWIOriginalDataValue(data, uid, 'selective', data.entries[uid].selective); | |
| 2796 | - await saveWorldInfo(name, data); | |
| 2797 | - | |
| 2798 | - const keysecondary = $(this) | |
| 2799 | - .closest('.world_entry') | |
| 2800 | - .find('.keysecondary'); | |
| 2801 | 2730 | |
| 2802 | - const keysecondarytextpole = $(this) | |
| 2731 | +/** | |
| 2803 | - .closest('.world_entry') | |
| 2732 | + * Helper to handle probability input. | |
| 2804 | - .find('.keysecondarytextpole'); | |
| 2805 | - | |
| 2806 | - const keyprimaryselect = $(this) | |
| 2807 | - .closest('.world_entry') | |
| 2808 | - .find('.keyprimaryselect'); | |
| 2809 | - | |
| 2810 | - const keyprimaryHeight = keyprimaryselect.outerHeight(); | |
| 2811 | - keysecondarytextpole.css('height', keyprimaryHeight + 'px'); | |
| 2812 | - | |
| 2813 | - value ? keysecondary.show() : keysecondary.hide(); | |
| 2814 | - | |
| 2815 | - }); | |
| 2816 | - //forced on, ignored if empty | |
| 2817 | - selectiveInput.prop('checked', true /* entry.selective */).trigger('input'); | |
| 2818 | - selectiveInput.parent().hide(); | |
| 2819 | - | |
| 2820 | - | |
| 2821 | - // constant | |
| 2822 | - /* | |
| 2823 | - const constantInput = template.find('input[name="constant"]'); | |
| 2824 | - constantInput.data("uid", entry.uid); | |
| 2825 | - constantInput.on("input", async function () { | |
| 2826 | - const uid = $(this).data("uid"); | |
| 2827 | - const value = $(this).prop("checked"); | |
| 2828 | - data.entries[uid].constant = value; | |
| 2829 | - setOriginalDataValue(data, uid, "constant", data.entries[uid].constant); | |
| 2830 | - await saveWorldInfo(name, data); | |
| 2831 | - }); | |
| 2832 | - constantInput.prop("checked", entry.constant).trigger("input"); | |
| 2833 | 2733 | */ |
| 2834 | - | |
| 2734 | +function handleProbabilityInputHelper({ probabilityInput, data, entry, name, setWIOriginalDataValue, saveWorldInfo }) { | |
| 2835 | - // order | |
| 2836 | - const orderInput = template.find('input[name="order"]'); | |
| 2837 | - orderInput.data('uid', entry.uid); | |
| 2838 | - orderInput.on('input', async function () { | |
| 2839 | - const uid = $(this).data('uid'); | |
| 2840 | - const value = Number($(this).val()); | |
| 2841 | - | |
| 2842 | - data.entries[uid].order = !isNaN(value) ? value : 0; | |
| 2843 | - updatePosOrdDisplay(uid); | |
| 2844 | - setWIOriginalDataValue(data, uid, 'insertion_order', data.entries[uid].order); | |
| 2845 | - await saveWorldInfo(name, data); | |
| 2846 | - }); | |
| 2847 | - orderInput.val(entry.order).trigger('input'); | |
| 2848 | - orderInput.css('width', 'calc(3em + 15px)'); | |
| 2849 | - | |
| 2850 | - // group | |
| 2851 | - const groupInput = template.find('input[name="group"]'); | |
| 2852 | - groupInput.data('uid', entry.uid); | |
| 2853 | - groupInput.on('input', async function () { | |
| 2854 | - const uid = $(this).data('uid'); | |
| 2855 | - const value = String($(this).val()).trim(); | |
| 2856 | - | |
| 2857 | - data.entries[uid].group = value; | |
| 2858 | - setWIOriginalDataValue(data, uid, 'extensions.group', data.entries[uid].group); | |
| 2859 | - await saveWorldInfo(name, data); | |
| 2860 | - }); | |
| 2861 | - groupInput.val(entry.group ?? '').trigger('input'); | |
| 2862 | - setTimeout(() => createEntryInputAutocomplete(groupInput, getInclusionGroupCallback(data), { allowMultiple: true }), 1); | |
| 2863 | - | |
| 2864 | - // inclusion priority | |
| 2865 | - const groupOverrideInput = template.find('input[name="groupOverride"]'); | |
| 2866 | - groupOverrideInput.data('uid', entry.uid); | |
| 2867 | - groupOverrideInput.on('input', async function () { | |
| 2868 | - const uid = $(this).data('uid'); | |
| 2869 | - const value = $(this).prop('checked'); | |
| 2870 | - data.entries[uid].groupOverride = value; | |
| 2871 | - setWIOriginalDataValue(data, uid, 'extensions.group_override', data.entries[uid].groupOverride); | |
| 2872 | - await saveWorldInfo(name, data); | |
| 2873 | - }); | |
| 2874 | - groupOverrideInput.prop('checked', entry.groupOverride).trigger('input'); | |
| 2875 | - | |
| 2876 | - // group weight | |
| 2877 | - const groupWeightInput = template.find('input[name="groupWeight"]'); | |
| 2878 | - groupWeightInput.data('uid', entry.uid); | |
| 2879 | - groupWeightInput.on('input', async function () { | |
| 2880 | - const uid = $(this).data('uid'); | |
| 2881 | - let value = Number($(this).val()); | |
| 2882 | - const min = Number($(this).attr('min')); | |
| 2883 | - const max = Number($(this).attr('max')); | |
| 2884 | - | |
| 2885 | - // Clamp the value | |
| 2886 | - if (value < min) { | |
| 2887 | - value = min; | |
| 2888 | - $(this).val(min); | |
| 2889 | - } else if (value > max) { | |
| 2890 | - value = max; | |
| 2891 | - $(this).val(max); | |
| 2892 | - } | |
| 2893 | - | |
| 2894 | - data.entries[uid].groupWeight = !isNaN(value) ? Math.abs(value) : 1; | |
| 2895 | - setWIOriginalDataValue(data, uid, 'extensions.group_weight', data.entries[uid].groupWeight); | |
| 2896 | - await saveWorldInfo(name, data); | |
| 2897 | - }); | |
| 2898 | - groupWeightInput.val(entry.groupWeight ?? DEFAULT_WEIGHT).trigger('input'); | |
| 2899 | - | |
| 2900 | - // sticky | |
| 2901 | - const sticky = template.find('input[name="sticky"]'); | |
| 2902 | - sticky.data('uid', entry.uid); | |
| 2903 | - sticky.on('input', async function () { | |
| 2904 | - const uid = $(this).data('uid'); | |
| 2905 | - const value = Number($(this).val()); | |
| 2906 | - data.entries[uid].sticky = !isNaN(value) ? value : null; | |
| 2907 | - | |
| 2908 | - setWIOriginalDataValue(data, uid, 'extensions.sticky', data.entries[uid].sticky); | |
| 2909 | - await saveWorldInfo(name, data); | |
| 2910 | - }); | |
| 2911 | - sticky.val(entry.sticky > 0 ? entry.sticky : '').trigger('input'); | |
| 2912 | - | |
| 2913 | - // cooldown | |
| 2914 | - const cooldown = template.find('input[name="cooldown"]'); | |
| 2915 | - cooldown.data('uid', entry.uid); | |
| 2916 | - cooldown.on('input', async function () { | |
| 2917 | - const uid = $(this).data('uid'); | |
| 2918 | - const value = Number($(this).val()); | |
| 2919 | - data.entries[uid].cooldown = !isNaN(value) ? value : null; | |
| 2920 | - | |
| 2921 | - setWIOriginalDataValue(data, uid, 'extensions.cooldown', data.entries[uid].cooldown); | |
| 2922 | - await saveWorldInfo(name, data); | |
| 2923 | - }); | |
| 2924 | - cooldown.val(entry.cooldown > 0 ? entry.cooldown : '').trigger('input'); | |
| 2925 | - | |
| 2926 | - // delay | |
| 2927 | - const delay = template.find('input[name="delay"]'); | |
| 2928 | - delay.data('uid', entry.uid); | |
| 2929 | - delay.on('input', async function () { | |
| 2930 | - const uid = $(this).data('uid'); | |
| 2931 | - const value = Number($(this).val()); | |
| 2932 | - data.entries[uid].delay = !isNaN(value) ? value : null; | |
| 2933 | - | |
| 2934 | - setWIOriginalDataValue(data, uid, 'extensions.delay', data.entries[uid].delay); | |
| 2935 | - await saveWorldInfo(name, data); | |
| 2936 | - }); | |
| 2937 | - delay.val(entry.delay > 0 ? entry.delay : '').trigger('input'); | |
| 2938 | - | |
| 2939 | - // probability | |
| 2940 | - if (entry.probability === undefined) { | |
| 2941 | - entry.probability = null; | |
| 2942 | - } | |
| 2943 | - | |
| 2944 | - // depth | |
| 2945 | - const depthInput = template.find('input[name="depth"]'); | |
| 2946 | - depthInput.data('uid', entry.uid); | |
| 2947 | - | |
| 2948 | - depthInput.on('input', async function () { | |
| 2949 | - const uid = $(this).data('uid'); | |
| 2950 | - const value = Number($(this).val()); | |
| 2951 | - | |
| 2952 | - data.entries[uid].depth = !isNaN(value) ? value : 0; | |
| 2953 | - updatePosOrdDisplay(uid); | |
| 2954 | - setWIOriginalDataValue(data, uid, 'extensions.depth', data.entries[uid].depth); | |
| 2955 | - await saveWorldInfo(name, data); | |
| 2956 | - }); | |
| 2957 | - depthInput.val(entry.depth ?? DEFAULT_DEPTH).trigger('input'); | |
| 2958 | - depthInput.css('width', 'calc(3em + 15px)'); | |
| 2959 | - | |
| 2960 | - // Hide by default unless depth is specified | |
| 2961 | - if (entry.position === world_info_position.atDepth) { | |
| 2962 | - //depthInput.parent().hide(); | |
| 2963 | - } | |
| 2964 | - | |
| 2965 | - const probabilityInput = template.find('input[name="probability"]'); | |
| 2966 | 2735 | probabilityInput.data('uid', entry.uid); |
| 2967 | 2736 | probabilityInput.on('input', async function () { |
| 2968 | 2737 | const uid = $(this).data('uid'); |
| 2969 | 2738 | const value = Number($(this).val()); |
| 2970 | - | |
| 2971 | 2739 | data.entries[uid].probability = !isNaN(value) ? value : null; |
| 2972 | - | |
| 2973 | - // Clamp probability to 0-100 | |
| 2974 | 2740 | if (data.entries[uid].probability !== null) { |
| 2975 | 2741 | data.entries[uid].probability = Math.min(100, Math.max(0, data.entries[uid].probability)); |
| 2976 | - | |
| 2977 | 2742 | if (data.entries[uid].probability !== value) { |
| 2978 | 2743 | $(this).val(data.entries[uid].probability); |
| 2979 | 2744 | } |
| 2980 | 2745 | } |
| 2981 | - | |
| 2982 | 2746 | setWIOriginalDataValue(data, uid, 'extensions.probability', data.entries[uid].probability); |
| 2983 | 2747 | await saveWorldInfo(name, data); |
| 2984 | 2748 | }); |
| 2985 | 2749 | probabilityInput.val(entry.probability).trigger('input'); |
| 2986 | 2750 | probabilityInput.css('width', 'calc(3em + 15px)'); |
| 2987 | - | |
| 2988 | - // probability toggle | |
| 2989 | - if (entry.useProbability === undefined) { | |
| 2990 | - entry.useProbability = false; | |
| 2991 | 2751 | } |
| 2992 | 2752 | |
| 2993 | - const probabilityToggle = template.find('input[name="useProbability"]'); | |
| 2753 | +/** | |
| 2754 | + * Helper to handle probability toggle. | |
| 2755 | + */ | |
| 2756 | +function handleProbabilityToggleHelper({ probabilityToggle, data, entry, name, probabilityInput, setWIOriginalDataValue, saveWorldInfo }) { | |
| 2994 | 2757 | probabilityToggle.data('uid', entry.uid); |
| 2995 | 2758 | probabilityToggle.on('input', async function () { |
| 2996 | 2759 | const uid = $(this).data('uid'); |
| 2997 | 2760 | const value = $(this).prop('checked'); |
| 2998 | 2761 | data.entries[uid].useProbability = value; |
| 2999 | 2762 | const probabilityContainer = $(this).closest('.world_entry').find('.probabilityContainer'); |
| 3000 | - .closest('.world_entry') | |
| 3001 | - .find('.probabilityContainer'); | |
| 3002 | 2763 | await saveWorldInfo(name, data); |
| 3003 | 2764 | value ? probabilityContainer.show() : probabilityContainer.hide(); |
| 3004 | - | |
| 3005 | 2765 | if (value && data.entries[uid].probability === null) { |
| 3006 | 2766 | data.entries[uid].probability = 100; |
| 3007 | 2767 | } |
| 3008 | - | |
| 3009 | 2768 | if (!value) { |
| 3010 | 2769 | data.entries[uid].probability = null; |
| 3011 | 2770 | } |
| 3012 | - | |
| 3013 | 2771 | probabilityInput.val(data.entries[uid].probability).trigger('input'); |
| 3014 | 2772 | }); |
| 3015 | - //forced on, 100% by default | |
| 2773 | + probabilityToggle.prop('checked', true).trigger('input'); | |
| 3016 | - probabilityToggle.prop('checked', true /* entry.useProbability */).trigger('input'); | |
| 3017 | 2774 | probabilityToggle.parent().hide(); |
| 3018 | - | |
| 3019 | - // position | |
| 3020 | - if (entry.position === undefined) { | |
| 3021 | - entry.position = 0; | |
| 3022 | 2775 | } |
| 3023 | 2776 | |
| 3024 | - const positionInput = template.find('select[name="position"]'); | |
| 2777 | +/** | |
| 3025 | - //initScrollHeight(positionInput); | |
| 2778 | + * Helper to handle select2 dropdowns for boolean selects. | |
| 3026 | - positionInput.data('uid', entry.uid); | |
| 2779 | + */ | |
| 3027 | - positionInput.on('click', function (event) { | |
| 2780 | +function handleBooleanSelectHelper({ selectElem, entry, entryKey, data, name, setWIOriginalDataValue, saveWorldInfo }) { | |
| 3028 | - // Prevent closing the drawer on clicking the input | |
| 2781 | + selectElem.data('uid', entry.uid); | |
| 3029 | - event.stopPropagation(); | |
| 2782 | + selectElem.on('input', async function () { | |
| 2783 | + const uid = $(this).data('uid'); | |
| 2784 | + const value = $(this).val(); | |
| 2785 | + data.entries[uid][entryKey] = value === 'null' ? null : value === 'true'; | |
| 2786 | + setWIOriginalDataValue(data, uid, `extensions.${entryKey.replace(/[A-Z]/g, m => `_${m.toLowerCase()}`)}`, data.entries[uid][entryKey]); | |
| 2787 | + await saveWorldInfo(name, data); | |
| 3030 | 2788 | }); |
| 3031 | - positionInput.on('input', async function () { | |
| 2789 | + selectElem.val((entry[entryKey] === null || entry[entryKey] === undefined) ? 'null' : entry[entryKey] ? 'true' : 'false').trigger('input'); | |
| 2790 | +} | |
| 2791 | + | |
| 2792 | +/** | |
| 2793 | + * Helper to handle input fields for numbers. | |
| 2794 | + */ | |
| 2795 | +function handleNumberInputHelper({ inputElem, entry, entryKey, data, name, setWIOriginalDataValue, saveWorldInfo, min, max, clamp = false }) { | |
| 2796 | + inputElem.data('uid', entry.uid); | |
| 2797 | + inputElem.on('input', async function () { | |
| 3032 | 2798 | const uid = $(this).data('uid'); |
| 3033 | 2799 | constlet value = Number($(this).val()); |
| 3034 | - data.entries[uid].position = !isNaN(value) ? value : 0; | |
| 2800 | + if (clamp) { | |
| 3035 | 2801 | if (value ===< world_info_position.atDepthmin) { |
| 3036 | - depthInput.prop('disabled', false); | |
| 2802 | + value = min; | |
| 3037 | - depthInput.css('visibility', 'visible'); | |
| 2803 | + $(this).val(min); | |
| 3038 | - //depthInput.parent().show(); | |
| 2804 | + } else if (value > max) { | |
| 3039 | - const role = Number($(this).find(':selected').data('role')); | |
| 2805 | + value = max; | |
| 3040 | - data.entries[uid].role = role; | |
| 2806 | + $(this).val(max); | |
| 3041 | - } else { | |
| 3042 | - depthInput.prop('disabled', true); | |
| 3043 | - depthInput.css('visibility', 'hidden'); | |
| 3044 | - data.entries[uid].role = null; | |
| 3045 | - //depthInput.parent().hide(); | |
| 3046 | 2807 | } |
| 3047 | - updatePosOrdDisplay(uid); | |
| 2808 | + } | |
| 3048 | - // Spec v2 only supports before_char and after_char | |
| 2809 | + data.entries[uid][entryKey] = !isNaN(value) ? value : null; | |
| 3049 | - setWIOriginalDataValue(data, uid, 'position', data.entries[uid].position == 0 ? 'before_char' : 'after_char'); | |
| 2810 | + setWIOriginalDataValue(data, uid, `extensions.${entryKey.replace(/[A-Z]/g, m => `_${m.toLowerCase()}`)}`, data.entries[uid][entryKey]); | |
| 3050 | - // Write the original value as extensions field | |
| 3051 | - setWIOriginalDataValue(data, uid, 'extensions.position', data.entries[uid].position); | |
| 3052 | - setWIOriginalDataValue(data, uid, 'extensions.role', data.entries[uid].role); | |
| 3053 | 2811 | await saveWorldInfo(name, data); |
| 3054 | 2812 | }); |
| 2813 | + inputElem.val(entry[entryKey] ?? (clamp ? min : '')).trigger('input'); | |
| 2814 | +} | |
| 3055 | 2815 | |
| 3056 | - const roleValue = entry.position === world_info_position.atDepth ? String(entry.role ?? extension_prompt_roles.SYSTEM) : ''; | |
| 2816 | +/** | |
| 3057 | - template | |
| 2817 | + * Helper to handle tri-state selector for constant/normal/vectorized. | |
| 3058 | - .find(`select[name="position"] option[value="${entry.position}"][data-role="${roleValue}"]`) | |
| 2818 | + */ | |
| 3059 | - .prop('selected', true) | |
| 2819 | +function handleEntryStateSelectorHelper({ entryStateSelector, entry, data, name, setWIOriginalDataValue, saveWorldInfo }) { | |
| 3060 | - .trigger('input'); | |
| 3061 | - | |
| 3062 | - //add UID above content box (less important doesn't need to be always visible) | |
| 3063 | - template.find('.world_entry_form_uid_value').text(`(UID: ${entry.uid})`); | |
| 3064 | - | |
| 3065 | - //new tri-state selector for constant/normal/vectorized | |
| 3066 | - const entryStateSelector = template.find('select[name="entryStateSelector"]'); | |
| 3067 | 2820 | entryStateSelector.data('uid', entry.uid); |
| 3068 | 2821 | entryStateSelector.on('click', function (event) { |
| 3069 | - // Prevent closing the drawer on clicking the input | |
| 3070 | 2822 | event.stopPropagation(); |
| 3071 | 2823 | }); |
| 3072 | 2824 | entryStateSelector.on('input', async function () { |
| @@ -3093,12 +2845,17 @@ export async function getWorldEntry(name, data, entry) { | ||
| 3093 | 2845 | break; |
| 3094 | 2846 | } |
| 3095 | 2847 | await saveWorldInfo(name, data); |
| 3096 | - | |
| 3097 | 2848 | }); |
| 2849 | + const entryState = () => entry.constant === true ? 'constant' : entry.vectorized === true ? 'vectorized' : 'normal'; | |
| 2850 | + entryStateSelector.find(`option[value=${entryState()}]`).prop('selected', true).trigger('input'); | |
| 2851 | +} | |
| 3098 | 2852 | |
| 3099 | - const entryKillSwitch = template.find('div[name="entryKillSwitch"]'); | |
| 2853 | +/** | |
| 2854 | + * Helper to handle kill switch toggle. | |
| 2855 | + */ | |
| 2856 | +function handleEntryKillSwitchHelper({ entryKillSwitch, entry, data, name, setWIOriginalDataValue, saveWorldInfo, template }) { | |
| 3100 | 2857 | entryKillSwitch.data('uid', entry.uid); |
| 3101 | 2858 | entryKillSwitch.on('click', async function (event) { |
| 3102 | 2859 | const uid = entry.uid; |
| 3103 | 2860 | data.entries[uid].disable = !data.entries[uid].disable; |
| 3104 | 2861 | const isActive = !data.entries[uid].disable; |
| @@ -3107,104 +2864,114 @@ export async function getWorldEntry(name, data, entry) { | ||
| 3107 | 2864 | entryKillSwitch.toggleClass('fa-toggle-off', !isActive); |
| 3108 | 2865 | entryKillSwitch.toggleClass('fa-toggle-on', isActive); |
| 3109 | 2866 | await saveWorldInfo(name, data); |
| 3110 | - | |
| 3111 | 2867 | }); |
| 3112 | - | |
| 3113 | - const entryState = function () { | |
| 3114 | - if (entry.constant === true) { | |
| 3115 | - return 'constant'; | |
| 3116 | - } else if (entry.vectorized === true) { | |
| 3117 | - return 'vectorized'; | |
| 3118 | - } else { | |
| 3119 | - return 'normal'; | |
| 3120 | - } | |
| 3121 | - }; | |
| 3122 | - | |
| 3123 | 2868 | const isActive = !entry.disable; |
| 3124 | 2869 | template.toggleClass('disabledWIEntry', !isActive); |
| 3125 | 2870 | entryKillSwitch.toggleClass('fa-toggle-off', !isActive); |
| 3126 | 2871 | entryKillSwitch.toggleClass('fa-toggle-on', isActive); |
| 2872 | +} | |
| 2873 | + | |
| 2874 | +/** | |
| 2875 | + * Main function to build the WI entry editor template. | |
| 2876 | + */ | |
| 2877 | +export async function getWorldEntry(name, data, entry) { | |
| 2878 | + if (!data.entries[entry.uid]) return; | |
| 3127 | 2879 | |
| 3128 | - template | |
| 2880 | + const headerTemplate = WI_ENTRY_HEADER_TEMPLATE.clone(); | |
| 3129 | - .find(`select[name="entryStateSelector"] option[value=${entryState()}]`) | |
| 2881 | + headerTemplate.data('uid', entry.uid); | |
| 3130 | 2882 | headerTemplate.propattr('selecteduid', trueentry.uid); |
| 3131 | - .trigger('input'); | |
| 3132 | 2883 | |
| 3133 | - // exclude recursion | |
| 2884 | + if (typeof power_user.wi_key_input_plaintext === 'undefined') power_user.wi_key_input_plaintext = true; | |
| 3134 | - const excludeRecursionInput = template.find('input[name="exclude_recursion"]'); | |
| 2885 | + | |
| 3135 | - excludeRecursionInput.data('uid', entry.uid); | |
| 2886 | + // Comment | |
| 3136 | - excludeRecursionInput.on('input', async function () { | |
| 2887 | + const commentInput = headerTemplate.find('textarea[name="comment"]'); | |
| 2888 | + commentInput.data('uid', entry.uid); | |
| 2889 | + commentInput.on('input', async function (_, { skipReset } = {}) { | |
| 3137 | 2890 | const uid = $(this).data('uid'); |
| 3138 | 2891 | const value = $(this).propval('checked'); |
| 3139 | - data.entries[uid].excludeRecursion = value; | |
| 2892 | + !skipReset && await resetScrollHeight(this); | |
| 3140 | - setWIOriginalDataValue(data, uid, 'extensions.exclude_recursion', data.entries[uid].excludeRecursion); | |
| 2893 | + data.entries[uid].comment = value; | |
| 2894 | + setWIOriginalDataValue(data, uid, 'comment', data.entries[uid].comment); | |
| 3141 | 2895 | await saveWorldInfo(name, data); |
| 3142 | 2896 | }); |
| 3143 | 2897 | excludeRecursionInputcommentInput.propval('checked', entry.excludeRecursioncomment).trigger('input', { skipReset: true }); |
| 3144 | 2898 | |
| 3145 | 2899 | // prevent recursionOrder |
| 3146 | 2900 | const preventRecursionInputorderInput = templateheaderTemplate.find('input[name="prevent_recursionorder"]'); |
| 3147 | 2901 | preventRecursionInputorderInput.data('uid', entry.uid); |
| 3148 | 2902 | preventRecursionInputorderInput.on('input', async function () { |
| 3149 | 2903 | const uid = $(this).data('uid'); |
| 3150 | 2904 | const value = Number($(this).propval('checked')); |
| 3151 | 2905 | data.entries[uid].preventRecursionorder = !isNaN(value) ? value : 0; |
| 3152 | - setWIOriginalDataValue(data, uid, 'extensions.prevent_recursion', data.entries[uid].preventRecursion); | |
| 2906 | + updatePosOrdDisplayHelper({ template: headerTemplate, data, uid }); | |
| 2907 | + setWIOriginalDataValue(data, uid, 'insertion_order', data.entries[uid].order); | |
| 3153 | 2908 | await saveWorldInfo(name, data); |
| 3154 | 2909 | }); |
| 3155 | 2910 | preventRecursionInputorderInput.propval('checked', entry.preventRecursionorder).trigger('input'); |
| 3156 | - | |
| 2911 | + orderInput.css('width', 'calc(3em + 15px)'); | |
| 3157 | - // delay until recursion | |
| 3158 | - // delay until recursion level | |
| 3159 | - const delayUntilRecursionInput = template.find('input[name="delay_until_recursion"]'); | |
| 3160 | - delayUntilRecursionInput.data('uid', entry.uid); | |
| 3161 | - const delayUntilRecursionLevelInput = template.find('input[name="delayUntilRecursionLevel"]'); | |
| 3162 | - delayUntilRecursionLevelInput.data('uid', entry.uid); | |
| 3163 | - delayUntilRecursionInput.on('input', async function () { | |
| 3164 | - const uid = $(this).data('uid'); | |
| 3165 | - const toggled = $(this).prop('checked'); | |
| 3166 | 2912 | |
| 3167 | - // If the value contains a number, we'll take that one (set by the level input), otherwise we can use true/false switch | |
| 2913 | + // Probability | |
| 3168 | - const value = toggled ? data.entries[uid].delayUntilRecursion || true : false; | |
| 2914 | + handleProbabilityInputHelper({ probabilityInput: headerTemplate.find('input[name="probability"]'), data, entry, name, setWIOriginalDataValue, saveWorldInfo }); | |
| 3169 | 2915 | |
| 3170 | - if (!toggled) delayUntilRecursionLevelInput.val(''); | |
| 2916 | + // Depth | |
| 2917 | + handleNumberInputHelper({ | |
| 2918 | + inputElem: headerTemplate.find('input[name="depth"]'), | |
| 2919 | + entry, entryKey: 'depth', data, name, setWIOriginalDataValue, saveWorldInfo, | |
| 2920 | + min: 0, max: MAX_SCAN_DEPTH, clamp: false, | |
| 2921 | + }); | |
| 2922 | + headerTemplate.find('input[name="depth"]').css('width', 'calc(3em + 15px)'); | |
| 3171 | 2923 | |
| 3172 | - data.entries[uid].delayUntilRecursion = value; | |
| 2924 | + // Position | |
| 3173 | - setWIOriginalDataValue(data, uid, 'extensions.delay_until_recursion', data.entries[uid].delayUntilRecursion); | |
| 2925 | + if (entry.position === undefined) entry.position = 0; | |
| 2926 | + const positionInput = headerTemplate.find('select[name="position"]'); | |
| 2927 | + positionInput.data('uid', entry.uid); | |
| 2928 | + positionInput.on('click', e => e.stopPropagation()); | |
| 2929 | + positionInput.on('input', async function () { | |
| 2930 | + const uid = $(this).data('uid'); | |
| 2931 | + const value = Number($(this).val()); | |
| 2932 | + data.entries[uid].position = !isNaN(value) ? value : 0; | |
| 2933 | + const depthInput = headerTemplate.find('input[name="depth"]'); | |
| 2934 | + if (value === world_info_position.atDepth) { | |
| 2935 | + depthInput.prop('disabled', false); | |
| 2936 | + depthInput.css('visibility', 'visible'); | |
| 2937 | + const role = Number($(this).find(':selected').data('role')); | |
| 2938 | + data.entries[uid].role = role; | |
| 2939 | + } else { | |
| 2940 | + depthInput.prop('disabled', true); | |
| 2941 | + depthInput.css('visibility', 'hidden'); | |
| 2942 | + data.entries[uid].role = null; | |
| 2943 | + } | |
| 2944 | + updatePosOrdDisplayHelper({ template: headerTemplate, data, uid }); | |
| 2945 | + setWIOriginalDataValue(data, uid, 'position', data.entries[uid].position == 0 ? 'before_char' : 'after_char'); | |
| 2946 | + setWIOriginalDataValue(data, uid, 'extensions.position', data.entries[uid].position); | |
| 2947 | + setWIOriginalDataValue(data, uid, 'extensions.role', data.entries[uid].role); | |
| 3174 | 2948 | await saveWorldInfo(name, data); |
| 3175 | 2949 | }); |
| 3176 | - delayUntilRecursionInput.prop('checked', entry.delayUntilRecursion).trigger('input'); | |
| 2950 | + const roleValue = entry.position === world_info_position.atDepth ? String(entry.role ?? extension_prompt_roles.SYSTEM) : ''; | |
| 3177 | - delayUntilRecursionLevelInput.on('input', async function () { | |
| 2951 | + headerTemplate.find(`select[name="position"] option[value="${entry.position}"][data-role="${roleValue}"]`).prop('selected', true).trigger('input'); | |
| 3178 | - const uid = $(this).data('uid'); | |
| 3179 | - const content = $(this).val(); | |
| 3180 | - const value = content === '' ? (typeof data.entries[uid].delayUntilRecursion === 'boolean' ? data.entries[uid].delayUntilRecursion : true) | |
| 3181 | - : content === 1 ? true | |
| 3182 | - : !isNaN(Number(content)) ? Number(content) | |
| 3183 | - : false; | |
| 3184 | 2952 | |
| 3185 | - data.entries[uid].delayUntilRecursion = value; | |
| 2953 | + // Tri-state selector | |
| 3186 | - setWIOriginalDataValue(data, uid, 'extensions.delay_until_recursion', data.entries[uid].delayUntilRecursion); | |
| 2954 | + handleEntryStateSelectorHelper({ | |
| 3187 | - await saveWorldInfo(name, data); | |
| 2955 | + entryStateSelector: headerTemplate.find('select[name="entryStateSelector"]'), | |
| 2956 | + entry, data, name, setWIOriginalDataValue, saveWorldInfo, | |
| 2957 | + }); | |
| 2958 | + | |
| 2959 | + // Kill switch | |
| 2960 | + handleEntryKillSwitchHelper({ | |
| 2961 | + entryKillSwitch: headerTemplate.find('div[name="entryKillSwitch"]'), | |
| 2962 | + entry, data, name, setWIOriginalDataValue, saveWorldInfo, template: headerTemplate, | |
| 3188 | 2963 | }); |
| 3189 | - // No need to retrigger inpout event, we'll just set the curret current value. It was edited/saved above already | |
| 3190 | - delayUntilRecursionLevelInput.val(['number', 'string'].includes(typeof entry.delayUntilRecursion) ? entry.delayUntilRecursion : '').trigger('input'); | |
| 3191 | 2964 | |
| 3192 | 2965 | // duplicateDuplicate/delete/move buttonbuttons |
| 3193 | - const duplicateButton = template.find('.duplicate_entry_button'); | |
| 2966 | + headerTemplate.find('.duplicate_entry_button').data('uid', entry.uid).on('click', async function () { | |
| 3194 | - duplicateButton.data('uid', entry.uid); | |
| 3195 | - duplicateButton.on('click', async function () { | |
| 3196 | 2967 | const uid = $(this).data('uid'); |
| 3197 | 2968 | const entryentryDup = duplicateWorldInfoEntry(data, uid); |
| 3198 | 2969 | if (entryentryDup) { |
| 3199 | 2970 | await saveWorldInfo(name, data); |
| 3200 | 2971 | updateEditor(entryentryDup.uid); |
| 3201 | 2972 | } |
| 3202 | 2973 | }); |
| 3203 | - | |
| 2974 | + headerTemplate.find('.delete_entry_button').data('uid', entry.uid).on('click', async function (e) { | |
| 3204 | - // delete button | |
| 3205 | - const deleteButton = template.find('.delete_entry_button'); | |
| 3206 | - deleteButton.data('uid', entry.uid); | |
| 3207 | - deleteButton.on('click', async function (e) { | |
| 3208 | 2975 | e.stopPropagation(); |
| 3209 | 2976 | const uid = $(this).data('uid'); |
| 3210 | 2977 | const deleted = await deleteWorldInfoEntry(data, uid); |
| @@ -3213,36 +2980,24 @@ export async function getWorldEntry(name, data, entry) { | ||
| 3213 | 2980 | await saveWorldInfo(name, data); |
| 3214 | 2981 | updateEditor(navigation_option.previous); |
| 3215 | 2982 | }); |
| 3216 | - | |
| 2983 | + headerTemplate.find('.move_entry_button').attr('data-uid', entry.uid).attr('data-current-world', name).on('click', async function (e) { | |
| 3217 | - // move button | |
| 3218 | - const moveButton = template.find('.move_entry_button'); | |
| 3219 | - moveButton.attr('data-uid', entry.uid); | |
| 3220 | - moveButton.attr('data-current-world', name); | |
| 3221 | - moveButton.on('click', async function (e) { | |
| 3222 | 2984 | e.stopPropagation(); |
| 3223 | 2985 | const sourceUid = $(this).attr('data-uid'); |
| 3224 | 2986 | const sourceWorld = $(this).attr('data-current-world'); |
| 3225 | 2987 | const sourceWorldInfo = await loadWorldInfo(sourceWorld); |
| 3226 | 2988 | if (!sourceWorldInfo) {return; |
| 3227 | - return; | |
| 3228 | - } | |
| 3229 | 2989 | const sourceName = sourceWorldInfo.entries[sourceUid]?.comment; |
| 3230 | 2990 | if (sourceName === undefined) {return; |
| 3231 | - return; | |
| 3232 | - } | |
| 3233 | - | |
| 3234 | 2991 | const select = document.createElement('select'); |
| 3235 | 2992 | select.id = 'move_entry_target_select'; |
| 3236 | 2993 | select.classList.add('text_pole', 'wide100p', 'marginTop10'); |
| 3237 | - | |
| 3238 | 2994 | const defaultOption = document.createElement('option'); |
| 3239 | 2995 | defaultOption.value = ''; |
| 3240 | 2996 | defaultOption.textContent = `-- ${t`Select Target Lorebook`} --`; |
| 3241 | 2997 | select.appendChild(defaultOption); |
| 3242 | - | |
| 3243 | 2998 | let selectableWorldCount = 0; |
| 3244 | 2999 | world_names.forEach(worldName => { |
| 3245 | 3000 | if (worldName !== sourceWorld) { // Exclude current world |
| 3246 | 3001 | const option = document.createElement('option'); |
| 3247 | 3002 | option.value = world_names.indexOf(worldName).toString(); |
| 3248 | 3003 | option.textContent = worldName; |
| @@ -3250,143 +3005,327 @@ export async function getWorldEntry(name, data, entry) { | ||
| 3250 | 3005 | selectableWorldCount++; |
| 3251 | 3006 | } |
| 3252 | 3007 | }); |
| 3253 | - | |
| 3254 | 3008 | if (selectableWorldCount === 0) { |
| 3255 | 3009 | toastr.warning(t`There are no other lorebooks to move to.`); |
| 3256 | 3010 | return; |
| 3257 | 3011 | } |
| 3258 | - | |
| 3259 | - // Create wrapper div | |
| 3260 | 3012 | const wrapper = document.createElement('div'); |
| 3261 | 3013 | wrapper.textContent = t`Move '${sourceName}' to:`; |
| 3262 | - | |
| 3263 | - // Create container and append elements | |
| 3264 | 3014 | const container = document.createElement('div'); |
| 3265 | 3015 | container.appendChild(wrapper); |
| 3266 | 3016 | container.appendChild(select); |
| 3267 | - | |
| 3268 | 3017 | let selectedWorldIndex = -1; |
| 3269 | 3018 | select.addEventListener('change', function () { |
| 3270 | 3019 | selectedWorldIndex = this.value === '' ? -1 : Number(this.value); |
| 3271 | 3020 | }); |
| 3272 | - | |
| 3273 | 3021 | const popupConfirm = await callGenericPopup(container, POPUP_TYPE.CONFIRM, '', { |
| 3274 | 3022 | okButton: t`Move`, |
| 3275 | 3023 | cancelButton: t`Cancel`, |
| 3276 | 3024 | }); |
| 3277 | 3025 | if (!popupConfirm) {return; |
| 3026 | + if (selectedWorldIndex === -1) return; | |
| 3027 | + const selectedValue = world_names[selectedWorldIndex]; | |
| 3028 | + if (!selectedValue) { | |
| 3029 | + toastr.warning(t`Please select a target lorebook.`); | |
| 3278 | 3030 | return; |
| 3279 | 3031 | } |
| 3032 | + await moveWorldInfoEntry(sourceWorld, selectedValue, sourceUid); | |
| 3033 | + }); | |
| 3280 | 3034 | |
| 3281 | - if (selectedWorldIndex === -1) { | |
| 3035 | + let drawerInitialized = false; | |
| 3036 | + let drawerDestroyTimeout = null; | |
| 3037 | + headerTemplate.find('.inline-drawer').on('inline-drawer-toggle', function () { | |
| 3038 | + if (drawerDestroyTimeout) { | |
| 3039 | + clearTimeout(drawerDestroyTimeout); | |
| 3040 | + drawerDestroyTimeout = null; | |
| 3041 | + } | |
| 3042 | + if (drawerInitialized) { | |
| 3043 | + drawerDestroyTimeout = setTimeout(() => { | |
| 3044 | + // Drawer was reopened, so we don't destroy it | |
| 3045 | + if (editOutlet.is(':visible')) { | |
| 3282 | 3046 | return; |
| 3283 | 3047 | } |
| 3048 | + drawerInitialized = false; | |
| 3049 | + clearEntryList(editOutlet); | |
| 3050 | + drawerDestroyTimeout = null; | |
| 3051 | + }, debounce_timeout.relaxed); | |
| 3052 | + } else { | |
| 3053 | + drawerInitialized = true; | |
| 3054 | + addEditorDrawerContent(); | |
| 3055 | + } | |
| 3056 | + }); | |
| 3284 | 3057 | |
| 3285 | - const selectedValue = world_names[selectedWorldIndex]; | |
| 3058 | + const editOutlet = headerTemplate.find('.inline-drawer-outlet'); | |
| 3286 | 3059 | |
| 3287 | 3060 | if function addEditorDrawerContent(!selectedValue) { |
| 3288 | - toastr.warning(t`Please select a target lorebook.`); | |
| 3061 | + const editTemplate = WI_ENTRY_EDIT_TEMPLATE.clone(); | |
| 3289 | - return; | |
| 3062 | + | |
| 3063 | + // UID display | |
| 3064 | + editTemplate.find('.world_entry_form_uid_value').text(`(UID: ${entry.uid})`); | |
| 3065 | + | |
| 3066 | + // Key inputs | |
| 3067 | + const keyInput = enableKeysInputHelper({ template: editTemplate, entry, entryPropName: 'key', originalDataValueName: 'keys', name, data }); | |
| 3068 | + const keySecondaryInput = enableKeysInputHelper({ template: editTemplate, entry, entryPropName: 'keysecondary', originalDataValueName: 'secondary_keys', name, data }); | |
| 3069 | + if (!keyInput.isFancy) initScrollHeight(keyInput.control); | |
| 3070 | + if (!keySecondaryInput.isFancy) initScrollHeight(keySecondaryInput.control); | |
| 3071 | + | |
| 3072 | + // Key input switch | |
| 3073 | + editTemplate.find('.switch_input_type_icon').on('click', function () { | |
| 3074 | + power_user.wi_key_input_plaintext = !power_user.wi_key_input_plaintext; | |
| 3075 | + saveSettingsDebounced(); | |
| 3076 | + const uid = ($(this).parents('.world_entry')).data('uid'); | |
| 3077 | + updateEditor(uid, false); | |
| 3078 | + $(`.world_entry[uid="${uid}"] .inline-drawer-icon`).trigger('click'); | |
| 3079 | + }).each((_, icon) => { | |
| 3080 | + $(icon).attr('title', $(icon).data(power_user.wi_key_input_plaintext ? 'tooltip-on' : 'tooltip-off')); | |
| 3081 | + $(icon).text($(icon).data(power_user.wi_key_input_plaintext ? 'icon-on' : 'icon-off')); | |
| 3082 | + }); | |
| 3083 | + | |
| 3084 | + // Probability toggle | |
| 3085 | + handleProbabilityToggleHelper({ | |
| 3086 | + probabilityToggle: editTemplate.find('input[name="useProbability"]'), | |
| 3087 | + data, entry, name, | |
| 3088 | + probabilityInput: headerTemplate.find('input[name="probability"]'), | |
| 3089 | + setWIOriginalDataValue, saveWorldInfo, | |
| 3090 | + }); | |
| 3091 | + | |
| 3092 | + // Comment toggle | |
| 3093 | + const commentToggle = editTemplate.find('input[name="addMemo"]'); | |
| 3094 | + commentToggle.data('uid', entry.uid); | |
| 3095 | + commentToggle.on('input', async function () { | |
| 3096 | + const uid = $(this).data('uid'); | |
| 3097 | + const value = $(this).prop('checked'); | |
| 3098 | + const commentContainer = $(this).closest('.world_entry').find('.commentContainer'); | |
| 3099 | + data.entries[uid].addMemo = value; | |
| 3100 | + await saveWorldInfo(name, data); | |
| 3101 | + value ? commentContainer.show() : commentContainer.hide(); | |
| 3102 | + }); | |
| 3103 | + commentToggle.prop('checked', true).trigger('input'); | |
| 3104 | + commentToggle.parent().hide(); | |
| 3105 | + | |
| 3106 | + // Logic AND/NOT | |
| 3107 | + const selectiveLogicDropdown = editTemplate.find('select[name="entryLogicType"]'); | |
| 3108 | + selectiveLogicDropdown.data('uid', entry.uid); | |
| 3109 | + selectiveLogicDropdown.on('click', e => e.stopPropagation()); | |
| 3110 | + selectiveLogicDropdown.on('input', async function () { | |
| 3111 | + const uid = $(this).data('uid'); | |
| 3112 | + const value = Number($(this).val()); | |
| 3113 | + data.entries[uid].selectiveLogic = !isNaN(value) ? value : world_info_logic.AND_ANY; | |
| 3114 | + setWIOriginalDataValue(data, uid, 'selectiveLogic', data.entries[uid].selectiveLogic); | |
| 3115 | + await saveWorldInfo(name, data); | |
| 3116 | + }); | |
| 3117 | + editTemplate.find(`select[name="entryLogicType"] option[value=${entry.selectiveLogic}]`).prop('selected', true).trigger('input'); | |
| 3118 | + | |
| 3119 | + // Selective | |
| 3120 | + const selectiveInput = editTemplate.find('input[name="selective"]'); | |
| 3121 | + selectiveInput.data('uid', entry.uid); | |
| 3122 | + selectiveInput.on('input', async function () { | |
| 3123 | + const uid = $(this).data('uid'); | |
| 3124 | + const value = $(this).prop('checked'); | |
| 3125 | + data.entries[uid].selective = value; | |
| 3126 | + setWIOriginalDataValue(data, uid, 'selective', data.entries[uid].selective); | |
| 3127 | + await saveWorldInfo(name, data); | |
| 3128 | + const keysecondary = $(this).closest('.world_entry').find('.keysecondary'); | |
| 3129 | + const keysecondarytextpole = $(this).closest('.world_entry').find('.keysecondarytextpole'); | |
| 3130 | + const keyprimaryselect = $(this).closest('.world_entry').find('.keyprimaryselect'); | |
| 3131 | + const keyprimaryHeight = keyprimaryselect.outerHeight(); | |
| 3132 | + keysecondarytextpole.css('height', keyprimaryHeight + 'px'); | |
| 3133 | + value ? keysecondary.show() : keysecondary.hide(); | |
| 3134 | + }); | |
| 3135 | + selectiveInput.prop('checked', true).trigger('input'); | |
| 3136 | + selectiveInput.parent().hide(); | |
| 3137 | + | |
| 3138 | + // Character filter | |
| 3139 | + const characterFilterLabel = editTemplate.find('label[for="characterFilter"] > small'); | |
| 3140 | + characterFilterLabel.text(entry.characterFilter?.isExclude ? 'Exclude Character(s)' : 'Filter to Character(s)'); | |
| 3141 | + const characterExclusionInput = editTemplate.find('input[name="character_exclusion"]'); | |
| 3142 | + characterExclusionInput.data('uid', entry.uid); | |
| 3143 | + characterExclusionInput.on('input', async function () { | |
| 3144 | + const uid = $(this).data('uid'); | |
| 3145 | + const value = $(this).prop('checked'); | |
| 3146 | + characterFilterLabel.text(value ? 'Exclude Character(s)' : 'Filter to Character(s)'); | |
| 3147 | + if (data.entries[uid].characterFilter) { | |
| 3148 | + if (!value && data.entries[uid].characterFilter.names.length === 0 && data.entries[uid].characterFilter.tags.length === 0) { | |
| 3149 | + delete data.entries[uid].characterFilter; | |
| 3150 | + } else { | |
| 3151 | + data.entries[uid].characterFilter.isExclude = value; | |
| 3290 | 3152 | } |
| 3153 | + } else if (value) { | |
| 3154 | + Object.assign(data.entries[uid], { characterFilter: { isExclude: true, names: [], tags: [] } }); | |
| 3155 | + } | |
| 3156 | + if (data.entries[uid]?.characterFilter?.names?.length > 0) { | |
| 3157 | + for (const name of [...data.entries[uid].characterFilter.names]) { | |
| 3158 | + if (!getContext().characters.find(x => x.avatar.replace(/\.[^/.]+$/, '') === name)) { | |
| 3159 | + data.entries[uid].characterFilter.names = data.entries[uid].characterFilter.names.filter(x => x !== name); | |
| 3160 | + } | |
| 3161 | + } | |
| 3162 | + } | |
| 3163 | + setWIOriginalDataValue(data, uid, 'character_filter', data.entries[uid].characterFilter); | |
| 3164 | + await saveWorldInfo(name, data); | |
| 3165 | + }); | |
| 3166 | + characterExclusionInput.prop('checked', entry.characterFilter?.isExclude ?? false).trigger('input'); | |
| 3291 | 3167 | |
| 3292 | - await moveWorldInfoEntry(sourceWorld, selectedValue, sourceUid); | |
| 3168 | + const characterFilter = editTemplate.find('select[name="characterFilter"]'); | |
| 3169 | + characterFilter.data('uid', entry.uid); | |
| 3170 | + initCharacterFilterSelect2Helper(characterFilter, t); | |
| 3171 | + fillCharacterAndTagOptionsHelper({ characterFilter, entry, getContext }); | |
| 3172 | + handleCharacterFilterChangeHelper({ | |
| 3173 | + characterFilter, data, entry, name, world_names, getContext, setWIOriginalDataValue, saveWorldInfo, t, | |
| 3174 | + }); | |
| 3175 | + | |
| 3176 | + // Content | |
| 3177 | + const counter = editTemplate.find('.world_entry_form_token_counter'); | |
| 3178 | + const countTokensDebounced = debounce(async function (counter, value) { | |
| 3179 | + const numberOfTokens = await getTokenCountAsync(value); | |
| 3180 | + $(counter).text(numberOfTokens); | |
| 3181 | + }, debounce_timeout.relaxed); | |
| 3182 | + const contentInputId = `world_entry_content_${entry.uid}`; | |
| 3183 | + const contentInput = editTemplate.find('textarea[name="content"]'); | |
| 3184 | + contentInput.data('uid', entry.uid); | |
| 3185 | + contentInput.attr('id', contentInputId); | |
| 3186 | + contentInput.on('input', async function (_, { skipCount } = {}) { | |
| 3187 | + const uid = $(this).data('uid'); | |
| 3188 | + const value = $(this).val(); | |
| 3189 | + data.entries[uid].content = value; | |
| 3190 | + setWIOriginalDataValue(data, uid, 'content', data.entries[uid].content); | |
| 3191 | + await saveWorldInfo(name, data); | |
| 3192 | + if (!skipCount) countTokensDebounced(counter, value); | |
| 3293 | 3193 | }); |
| 3194 | + contentInput.val(entry.content).trigger('input', { skipCount: true }); | |
| 3195 | + editTemplate.find('.editor_maximize').attr('data-for', contentInputId); | |
| 3294 | 3196 | |
| 3295 | 3197 | // scanScan depth |
| 3296 | 3198 | const scanDepthInput = templateeditTemplate.find('input[name="scanDepth"]'); |
| 3297 | 3199 | scanDepthInput.data('uid', entry.uid); |
| 3298 | 3200 | scanDepthInput.on('input', async function () { |
| 3299 | 3201 | const uid = $(this).data('uid'); |
| 3300 | 3202 | const isEmpty = $(this).val() === ''; |
| 3301 | 3203 | const value = Number($(this).val()); |
| 3302 | - | |
| 3303 | - // Clamp if necessary | |
| 3304 | 3204 | if (value < 0) { |
| 3305 | 3205 | $(this).val(0).trigger('input'); |
| 3306 | 3206 | toastr.warning('Scan depth cannot be negative'); |
| 3307 | 3207 | return; |
| 3308 | 3208 | } |
| 3309 | - | |
| 3310 | 3209 | if (value > MAX_SCAN_DEPTH) { |
| 3311 | 3210 | $(this).val(MAX_SCAN_DEPTH).trigger('input'); |
| 3312 | 3211 | toastr.warning(`Scan depth cannot exceed ${MAX_SCAN_DEPTH}`); |
| 3313 | 3212 | return; |
| 3314 | 3213 | } |
| 3315 | - | |
| 3316 | 3214 | data.entries[uid].scanDepth = !isEmpty && !isNaN(value) && value >= 0 && value <= MAX_SCAN_DEPTH ? Math.floor(value) : null; |
| 3317 | 3215 | setWIOriginalDataValue(data, uid, 'extensions.scan_depth', data.entries[uid].scanDepth); |
| 3318 | 3216 | await saveWorldInfo(name, data); |
| 3319 | 3217 | }); |
| 3320 | 3218 | scanDepthInput.val(entry.scanDepth ?? null).trigger('input'); |
| 3321 | 3219 | |
| 3322 | - // case sensitive select | |
| 3220 | + // Group | |
| 3323 | 3221 | const caseSensitiveSelectgroupInput = templateeditTemplate.find('selectinput[name="caseSensitivegroup"]'); |
| 3324 | 3222 | caseSensitiveSelect groupInput.data('uid', entry.uid); |
| 3325 | 3223 | caseSensitiveSelect groupInput.on('input', async function () { |
| 3326 | 3224 | const uid = $(this).data('uid'); |
| 3327 | 3225 | const value = String($(this).val()).trim(); |
| 3328 | - | |
| 3226 | + data.entries[uid].group = value; | |
| 3329 | - data.entries[uid].caseSensitive = value === 'null' ? null : value === 'true'; | |
| 3227 | + setWIOriginalDataValue(data, uid, 'extensions.group', data.entries[uid].group); | |
| 3330 | - setWIOriginalDataValue(data, uid, 'extensions.case_sensitive', data.entries[uid].caseSensitive); | |
| 3331 | 3228 | await saveWorldInfo(name, data); |
| 3332 | 3229 | }); |
| 3333 | - caseSensitiveSelect.val((entry.caseSensitive === null || entry.caseSensitive === undefined) ? 'null' : entry.caseSensitive ? 'true' : 'false').trigger('input'); | |
| 3230 | + groupInput.val(entry.group ?? '').trigger('input'); | |
| 3231 | + setTimeout(() => createEntryInputAutocomplete(groupInput, getInclusionGroupCallback(data), { allowMultiple: true }), 1); | |
| 3334 | 3232 | |
| 3335 | - // match whole words select | |
| 3233 | + // Inclusion priority | |
| 3336 | 3234 | const matchWholeWordsSelectgroupOverrideInput = templateeditTemplate.find('selectinput[name="matchWholeWordsgroupOverride"]'); |
| 3337 | 3235 | matchWholeWordsSelect groupOverrideInput.data('uid', entry.uid); |
| 3338 | 3236 | matchWholeWordsSelect groupOverrideInput.on('input', async function () { |
| 3339 | 3237 | const uid = $(this).data('uid'); |
| 3340 | 3238 | const value = $(this).valprop('checked'); |
| 3341 | - | |
| 3239 | + data.entries[uid].groupOverride = value; | |
| 3342 | - data.entries[uid].matchWholeWords = value === 'null' ? null : value === 'true'; | |
| 3240 | + setWIOriginalDataValue(data, uid, 'extensions.group_override', data.entries[uid].groupOverride); | |
| 3343 | - setWIOriginalDataValue(data, uid, 'extensions.match_whole_words', data.entries[uid].matchWholeWords); | |
| 3344 | 3241 | await saveWorldInfo(name, data); |
| 3345 | 3242 | }); |
| 3346 | - matchWholeWordsSelect.val((entry.matchWholeWords === null || entry.matchWholeWords === undefined) ? 'null' : entry.matchWholeWords ? 'true' : 'false').trigger('input'); | |
| 3243 | + groupOverrideInput.prop('checked', entry.groupOverride).trigger('input'); | |
| 3347 | 3244 | |
| 3348 | - // use group scoring select | |
| 3245 | + // Group weight | |
| 3349 | - const useGroupScoringSelect = template.find('select[name="useGroupScoring"]'); | |
| 3246 | + handleNumberInputHelper({ | |
| 3350 | - useGroupScoringSelect.data('uid', entry.uid); | |
| 3247 | + inputElem: editTemplate.find('input[name="groupWeight"]'), | |
| 3351 | - useGroupScoringSelect.on('input', async function () { | |
| 3248 | + entry, entryKey: 'groupWeight', data, name, setWIOriginalDataValue, saveWorldInfo, | |
| 3352 | - const uid = $(this).data('uid'); | |
| 3249 | + min: 1, max: 10000, clamp: true, | |
| 3353 | - const value = $(this).val(); | |
| 3250 | + }); | |
| 3354 | 3251 | |
| 3355 | - data.entries[uid].useGroupScoring = value === 'null' ? null : value === 'true'; | |
| 3252 | + // Sticky, cooldown, delay | |
| 3356 | - setWIOriginalDataValue(data, uid, 'extensions.use_group_scoring', data.entries[uid].useGroupScoring); | |
| 3253 | + handleNumberInputHelper({ | |
| 3357 | - await saveWorldInfo(name, data); | |
| 3254 | + inputElem: editTemplate.find('input[name="sticky"]'), | |
| 3255 | + entry, entryKey: 'sticky', data, name, setWIOriginalDataValue, saveWorldInfo, | |
| 3256 | + min: 1, max: 10000, clamp: false, | |
| 3257 | + }); | |
| 3258 | + handleNumberInputHelper({ | |
| 3259 | + inputElem: editTemplate.find('input[name="cooldown"]'), | |
| 3260 | + entry, entryKey: 'cooldown', data, name, setWIOriginalDataValue, saveWorldInfo, | |
| 3261 | + min: 1, max: 10000, clamp: false, | |
| 3262 | + }); | |
| 3263 | + handleNumberInputHelper({ | |
| 3264 | + inputElem: editTemplate.find('input[name="delay"]'), | |
| 3265 | + entry, entryKey: 'delay', data, name, setWIOriginalDataValue, saveWorldInfo, | |
| 3266 | + min: 1, max: 10000, clamp: false, | |
| 3358 | 3267 | }); |
| 3359 | - useGroupScoringSelect.val((entry.useGroupScoring === null || entry.useGroupScoring === undefined) ? 'null' : entry.useGroupScoring ? 'true' : 'false').trigger('input'); | |
| 3360 | 3268 | |
| 3361 | - function handleMatchCheckbox(fieldName) { | |
| 3269 | + // Exclude/prevent recursion | |
| 3362 | - const key = originalWIDataKeyMap[fieldName]; | |
| 3270 | + handleMatchCheckboxHelper({ template: editTemplate, entry, fieldName: 'excludeRecursion', data, name }); | |
| 3363 | - const checkBoxElem = template.find(`input[type="checkbox"][name="${fieldName}"]`); | |
| 3271 | + handleMatchCheckboxHelper({ template: editTemplate, entry, fieldName: 'preventRecursion', data, name }); | |
| 3364 | - checkBoxElem.data('uid', entry.uid); | |
| 3365 | - checkBoxElem.on('input', async function () { | |
| 3366 | - const uid = $(this).data('uid'); | |
| 3367 | - const value = $(this).prop('checked'); | |
| 3368 | 3272 | |
| 3369 | - data.entries[uid][fieldName] = value; | |
| 3273 | + // Delay until recursion | |
| 3370 | - setWIOriginalDataValue(data, uid, key, data.entries[uid][fieldName]); | |
| 3274 | + const delayUntilRecursionInput = editTemplate.find('input[name="delay_until_recursion"]'); | |
| 3275 | + delayUntilRecursionInput.data('uid', entry.uid); | |
| 3276 | + const delayUntilRecursionLevelInput = editTemplate.find('input[name="delayUntilRecursionLevel"]'); | |
| 3277 | + delayUntilRecursionLevelInput.data('uid', entry.uid); | |
| 3278 | + delayUntilRecursionInput.on('input', async function () { | |
| 3279 | + const uid = $(this).data('uid'); | |
| 3280 | + const toggled = $(this).prop('checked'); | |
| 3281 | + const value = toggled ? data.entries[uid].delayUntilRecursion || true : false; | |
| 3282 | + if (!toggled) delayUntilRecursionLevelInput.val(''); | |
| 3283 | + data.entries[uid].delayUntilRecursion = value; | |
| 3284 | + setWIOriginalDataValue(data, uid, 'extensions.delay_until_recursion', data.entries[uid].delayUntilRecursion); | |
| 3371 | 3285 | await saveWorldInfo(name, data); |
| 3372 | 3286 | }); |
| 3373 | 3287 | checkBoxElemdelayUntilRecursionInput.prop('checked', !!entry[fieldName].delayUntilRecursion).trigger('input'); |
| 3374 | - } | |
| 3288 | + delayUntilRecursionLevelInput.on('input', async function () { | |
| 3289 | + const uid = $(this).data('uid'); | |
| 3290 | + const content = $(this).val(); | |
| 3291 | + const value = content === '' ? (typeof data.entries[uid].delayUntilRecursion === 'boolean' ? data.entries[uid].delayUntilRecursion : true) | |
| 3292 | + : content === 1 ? true | |
| 3293 | + : !isNaN(Number(content)) ? Number(content) | |
| 3294 | + : false; | |
| 3295 | + data.entries[uid].delayUntilRecursion = value; | |
| 3296 | + setWIOriginalDataValue(data, uid, 'extensions.delay_until_recursion', data.entries[uid].delayUntilRecursion); | |
| 3297 | + await saveWorldInfo(name, data); | |
| 3298 | + }); | |
| 3299 | + delayUntilRecursionLevelInput.val(['number', 'string'].includes(typeof entry.delayUntilRecursion) ? entry.delayUntilRecursion : '').trigger('input'); | |
| 3300 | + | |
| 3301 | + // Boolean selects | |
| 3302 | + handleBooleanSelectHelper({ | |
| 3303 | + selectElem: editTemplate.find('select[name="caseSensitive"]'), | |
| 3304 | + entry, entryKey: 'caseSensitive', data, name, setWIOriginalDataValue, saveWorldInfo, | |
| 3305 | + }); | |
| 3306 | + handleBooleanSelectHelper({ | |
| 3307 | + selectElem: editTemplate.find('select[name="matchWholeWords"]'), | |
| 3308 | + entry, entryKey: 'matchWholeWords', data, name, setWIOriginalDataValue, saveWorldInfo, | |
| 3309 | + }); | |
| 3310 | + handleBooleanSelectHelper({ | |
| 3311 | + selectElem: editTemplate.find('select[name="useGroupScoring"]'), | |
| 3312 | + entry, entryKey: 'useGroupScoring', data, name, setWIOriginalDataValue, saveWorldInfo, | |
| 3313 | + }); | |
| 3375 | 3314 | |
| 3376 | - handleMatchCheckbox('matchPersonaDescription'); | |
| 3315 | + // Match checkboxes | |
| 3377 | - handleMatchCheckbox('matchCharacterDescription'); | |
| 3316 | + handleMatchCheckboxHelper({ template: editTemplate, entry, fieldName: 'matchPersonaDescription', data, name }); | |
| 3378 | - handleMatchCheckbox('matchCharacterPersonality'); | |
| 3317 | + handleMatchCheckboxHelper({ template: editTemplate, entry, fieldName: 'matchCharacterDescription', data, name }); | |
| 3379 | - handleMatchCheckbox('matchCharacterDepthPrompt'); | |
| 3318 | + handleMatchCheckboxHelper({ template: editTemplate, entry, fieldName: 'matchCharacterPersonality', data, name }); | |
| 3380 | - handleMatchCheckbox('matchScenario'); | |
| 3319 | + handleMatchCheckboxHelper({ template: editTemplate, entry, fieldName: 'matchCharacterDepthPrompt', data, name }); | |
| 3381 | - handleMatchCheckbox('matchCreatorNotes'); | |
| 3320 | + handleMatchCheckboxHelper({ template: editTemplate, entry, fieldName: 'matchScenario', data, name }); | |
| 3321 | + handleMatchCheckboxHelper({ template: editTemplate, entry, fieldName: 'matchCreatorNotes', data, name }); | |
| 3382 | 3322 | |
| 3383 | 3323 | // automationAutomation idID |
| 3384 | 3324 | const automationIdInput = templateeditTemplate.find('input[name="automationId"]'); |
| 3385 | 3325 | automationIdInput.data('uid', entry.uid); |
| 3386 | 3326 | automationIdInput.on('input', async function () { |
| 3387 | 3327 | const uid = $(this).data('uid'); |
| 3388 | 3328 | const value = $(this).val(); |
| 3389 | - | |
| 3390 | 3329 | data.entries[uid].automationId = value; |
| 3391 | 3330 | setWIOriginalDataValue(data, uid, 'extensions.automation_id', data.entries[uid].automationId); |
| 3392 | 3331 | await saveWorldInfo(name, data); |
| @@ -3394,33 +3333,15 @@ export async function getWorldEntry(name, data, entry) { | ||
| 3394 | 3333 | automationIdInput.val(entry.automationId ?? '').trigger('input'); |
| 3395 | 3334 | setTimeout(() => createEntryInputAutocomplete(automationIdInput, getAutomationIdCallback(data)), 1); |
| 3396 | 3335 | |
| 3397 | - template.find('.inline-drawer-content').css('display', 'none'); //entries start collapsed | |
| 3336 | + countTokensDebounced(counter, contentInput.val()); | |
| 3398 | 3337 | |
| 3399 | - function updatePosOrdDisplay(uid) { | |
| 3338 | + editTemplate.find('.inline-drawer-content').css('display', 'none'); | |
| 3400 | - // display position/order info left of keyword box | |
| 3339 | + editOutlet.append(editTemplate); | |
| 3401 | - let entry = data.entries[uid]; | |
| 3402 | - let posText = entry.position; | |
| 3403 | - switch (entry.position) { | |
| 3404 | - case 0: | |
| 3405 | - posText = '↑CD'; | |
| 3406 | - break; | |
| 3407 | - case 1: | |
| 3408 | - posText = 'CD↓'; | |
| 3409 | - break; | |
| 3410 | - case 2: | |
| 3411 | - posText = '↑AN'; | |
| 3412 | - break; | |
| 3413 | - case 3: | |
| 3414 | - posText = 'AN↓'; | |
| 3415 | - break; | |
| 3416 | - case 4: | |
| 3417 | - posText = `@D${entry.depth}`; | |
| 3418 | - break; | |
| 3419 | - } | |
| 3420 | - template.find('.world_entry_form_position_value').text(`(${posText} ${entry.order})`); | |
| 3421 | 3340 | } |
| 3422 | 3341 | |
| 3423 | - return template; | |
| 3342 | + headerTemplate.find('.inline-drawer-content').css('display', 'none'); | |
| 3343 | + | |
| 3344 | + return headerTemplate; | |
| 3424 | 3345 | } |
| 3425 | 3346 | |
| 3426 | 3347 | /** |
| @@ -3661,6 +3582,11 @@ async function _save(name, data) { | ||
| 3661 | 3582 | * @return {Promise<void>} A promise that resolves when the world info is saved |
| 3662 | 3583 | */ |
| 3663 | 3584 | export async function saveWorldInfo(name, data, immediately = false) { |
| 3585 | + // Saving is temporarily disabled | |
| 3586 | + if (isSaveWorldInfoDisabled) { | |
| 3587 | + return; | |
| 3588 | + } | |
| 3589 | + | |
| 3664 | 3590 | if (!name || !data) { |
| 3665 | 3591 | return; |
| 3666 | 3592 | } |
| @@ -3819,7 +3745,7 @@ export async function createNewWorldInfo(worldName, { interactive = false } = {} | ||
| 3819 | 3745 | if (selectedIndex !== -1) { |
| 3820 | 3746 | $('#world_editor_select').val(selectedIndex).trigger('change'); |
| 3821 | 3747 | } else { |
| 3822 | 3748 | await hideWorldEditor(); |
| 3823 | 3749 | } |
| 3824 | 3750 | |
| 3825 | 3751 | return true; |
| @@ -4067,6 +3993,8 @@ function parseDecorators(content) { | ||
| 4067 | 3993 | * @property {Set<any>} allActivatedEntries All entries. |
| 4068 | 3994 | * @returns {Promise<WIActivated>} The world info activated. |
| 4069 | 3995 | */ |
| 3996 | + | |
| 3997 | +//MARK: checkWorldInfo | |
| 4070 | 3998 | export async function checkWorldInfo(chat, maxContext, isDryRun, globalScanData) { |
| 4071 | 3999 | const context = getContext(); |
| 4072 | 4000 | const buffer = new WorldInfoBuffer(chat, globalScanData); |
| @@ -5385,7 +5313,7 @@ export function initWorldInfo() { | ||
| 5385 | 5313 | const selectedIndex = String($('#world_editor_select').find(':selected').val()); |
| 5386 | 5314 | |
| 5387 | 5315 | if (selectedIndex === '') { |
| 5388 | 5316 | await hideWorldEditor(); |
| 5389 | 5317 | } else { |
| 5390 | 5318 | const worldName = world_names[selectedIndex]; |
| 5391 | 5319 | showWorldEditor(worldName); |
| @@ -5537,9 +5465,12 @@ export function initWorldInfo() { | ||
| 5537 | 5465 | select2ChoiceClickSubscribe($('#world_info'), target => { |
| 5538 | 5466 | const name = $(target).text(); |
| 5539 | 5467 | const selectedIndex = world_names.indexOf(name); |
| 5540 | - if (selectedIndex !== -1) { | |
| 5468 | + const alreadySelectedInEditor = $('#world_editor_select option:selected').text() === name; | |
| 5469 | + if (selectedIndex !== -1 && !alreadySelectedInEditor) { | |
| 5541 | 5470 | $('#world_editor_select').val(selectedIndex).trigger('change'); |
| 5542 | 5471 | console.log('Quick selection of world', name); |
| 5472 | + } else { | |
| 5473 | + console.warn('lets not reload an already loaded list yes?'); | |
| 5543 | 5474 | } |
| 5544 | 5475 | }, { buttonStyle: true, closeDrawer: true }); |
| 5545 | 5476 | } |
| @@ -14,6 +14,7 @@ | ||
| 14 | 14 | @import url(css/data-maid.css); |
| 15 | 15 | |
| 16 | 16 | :root { |
| 17 | + interpolate-size: allow-keywords; | |
| 17 | 18 | --doc-height: 100%; |
| 18 | 19 | --transparent: rgba(0, 0, 0, 0); |
| 19 | 20 | |
| @@ -122,7 +123,9 @@ | ||
| 122 | 123 | --inline-avatar-small-factor: 0.6; |
| 123 | 124 | |
| 124 | 125 | --animation-duration: 125ms; |
| 125 | 126 | --animation-duration-slow2x: calc(var(--animation-duration) * 32); |
| 127 | + --animation-duration-3x: calc(var(--animation-duration) * 3); | |
| 128 | + --animation-duration-slow: var(--animation-duration-3x); | |
| 126 | 129 | } |
| 127 | 130 | |
| 128 | 131 | * { |
| @@ -719,7 +722,7 @@ hr { | ||
| 719 | 722 | position: absolute; |
| 720 | 723 | width: 100%; |
| 721 | 724 | height: 100%; |
| 722 | 725 | transition: background-image 0.5svar(--animation-duration-3x) ease-in-out; |
| 723 | 726 | } |
| 724 | 727 | |
| 725 | 728 | /* Background fitting options */ |
| @@ -835,7 +838,7 @@ body.reduced-motion #bg_custom { | ||
| 835 | 838 | cursor: -webkit-grab; |
| 836 | 839 | display: none; |
| 837 | 840 | filter: drop-shadow(0px 0px 0px black); |
| 838 | 841 | transition: all 250msvar(--animation-duration-2x); |
| 839 | 842 | font-size: calc(var(--mainFontSize)*1.3); |
| 840 | 843 | } |
| 841 | 844 | |
| @@ -851,7 +854,7 @@ body .panelControlBar { | ||
| 851 | 854 | min-width: 55px; |
| 852 | 855 | justify-content: flex-end; |
| 853 | 856 | gap: 0px; |
| 854 | 857 | transition: all 250msvar(--animation-duration-2x); |
| 855 | 858 | } |
| 856 | 859 | |
| 857 | 860 | .zoomed_avatar .panelControlBar { |
| @@ -973,7 +976,7 @@ body .panelControlBar { | ||
| 973 | 976 | display: flex; |
| 974 | 977 | align-items: center; |
| 975 | 978 | justify-content: center; |
| 976 | 979 | transition: opacity 300msvar(--animation-duration-2x); |
| 977 | 980 | } |
| 978 | 981 | |
| 979 | 982 | #rightSendForm>div:hover, |
| @@ -1000,7 +1003,7 @@ body .panelControlBar { | ||
| 1000 | 1003 | padding-right: 2px; |
| 1001 | 1004 | place-self: center; |
| 1002 | 1005 | cursor: pointer; |
| 1003 | - transition: 0.3s; | |
| 1006 | + transition: var(--animation-duration-2x); | |
| 1004 | 1007 | opacity: 0.7; |
| 1005 | 1008 | } |
| 1006 | 1009 | |
| @@ -1047,7 +1050,7 @@ body .panelControlBar { | ||
| 1047 | 1050 | padding-right: 2px; |
| 1048 | 1051 | place-self: center; |
| 1049 | 1052 | cursor: pointer; |
| 1050 | - transition: 0.3s; | |
| 1053 | + transition: var(--animation-duration-2x); | |
| 1051 | 1054 | opacity: 1; |
| 1052 | 1055 | display: none; |
| 1053 | 1056 | |
| @@ -1094,7 +1097,7 @@ body .panelControlBar { | ||
| 1094 | 1097 | z-index: 2001; |
| 1095 | 1098 | margin-left: 10px; |
| 1096 | 1099 | padding: 0; |
| 1097 | - transition: 0.3s; | |
| 1100 | + transition: var(--animation-duration-2x); | |
| 1098 | 1101 | display: flex; |
| 1099 | 1102 | align-items: center; |
| 1100 | 1103 | order: 2; |
| @@ -1337,7 +1340,7 @@ body.swipeAllMessages .mes:not(.last_mes) .swipes-counter { | ||
| 1337 | 1340 | border: var(--avatar-base-border-radius) solid var(--SmartThemeBodyColor); |
| 1338 | 1341 | margin: var(--avatar-base-border-radius); |
| 1339 | 1342 | cursor: pointer; |
| 1340 | 1343 | transition: filter 0.2svar(--animation-duration) ease-in-out; |
| 1341 | 1344 | } |
| 1342 | 1345 | |
| 1343 | 1346 | .add_avatar:hover { |
| @@ -1350,7 +1353,7 @@ body.swipeAllMessages .mes:not(.last_mes) .swipes-counter { | ||
| 1350 | 1353 | border-radius: var(--avatar-base-border-radius-round); |
| 1351 | 1354 | border-style: none; |
| 1352 | 1355 | flex: 1; |
| 1353 | - transition: 250ms; | |
| 1356 | + transition: var(--animation-duration-2x); | |
| 1354 | 1357 | } |
| 1355 | 1358 | |
| 1356 | 1359 | .last_mes .mesAvatarWrapper { |
| @@ -1542,7 +1545,7 @@ button { | ||
| 1542 | 1545 | 100% var(--progWidthClip), |
| 1543 | 1546 | 100% 100%, |
| 1544 | 1547 | 0% 100%); |
| 1545 | 1548 | transition: clip-path 200msvar(--animation-duration-2x); |
| 1546 | 1549 | } |
| 1547 | 1550 | |
| 1548 | 1551 | #send_textarea:placeholder-shown { |
| @@ -2493,8 +2496,8 @@ body[data-stscript-style] .hljs.language-stscript { | ||
| 2493 | 2496 | margin: 3px; |
| 2494 | 2497 | opacity: 0.75; |
| 2495 | 2498 | filter: grayscale(1); |
| 2496 | 2499 | -webkit-transition: all 250msvar(--animation-duration-2x) ease-in-out; |
| 2497 | 2500 | transition: all 250msvar(--animation-duration-2x) ease-in-out; |
| 2498 | 2501 | } |
| 2499 | 2502 | |
| 2500 | 2503 | #character_popup .editor_maximize:hover { |
| @@ -2648,8 +2651,8 @@ input[type="file"] { | ||
| 2648 | 2651 | margin-top: 0; |
| 2649 | 2652 | padding: 1px; |
| 2650 | 2653 | filter: grayscale(1) brightness(75%); |
| 2651 | 2654 | -webkit-transition: all 0.5svar(--animation-duration-3x) ease-in-out; |
| 2652 | 2655 | transition: all 0.5svar(--animation-duration-3x) ease-in-out; |
| 2653 | 2656 | } |
| 2654 | 2657 | |
| 2655 | 2658 | .right_menu_button:hover { |
| @@ -2669,7 +2672,7 @@ input[type="file"] { | ||
| 2669 | 2672 | #lm_button_panel_pin_div, |
| 2670 | 2673 | #WI_button_panel_pin_div { |
| 2671 | 2674 | opacity: 0.5; |
| 2672 | - transition: 0.3s; | |
| 2675 | + transition: var(--animation-duration-2x); | |
| 2673 | 2676 | } |
| 2674 | 2677 | |
| 2675 | 2678 | #rm_button_panel_pin_div:hover, |
| @@ -2805,7 +2808,6 @@ input[type="file"] { | ||
| 2805 | 2808 | } |
| 2806 | 2809 | |
| 2807 | 2810 | #rm_extensions_block { |
| 2808 | - display: none; | |
| 2809 | 2811 | overflow-y: auto; |
| 2810 | 2812 | } |
| 2811 | 2813 | |
| @@ -2830,6 +2832,7 @@ input[type="file"] { | ||
| 2830 | 2832 | margin: 0; |
| 2831 | 2833 | right: unset; |
| 2832 | 2834 | width: calc(((100dvw - var(--sheldWidth)) / 2) - 1px); |
| 2835 | + height: unset; | |
| 2833 | 2836 | |
| 2834 | 2837 | } |
| 2835 | 2838 | |
| @@ -2871,7 +2874,7 @@ input[type="file"] { | ||
| 2871 | 2874 | aspect-ratio: 1 / 1; |
| 2872 | 2875 | font-size: 20px; |
| 2873 | 2876 | opacity: 0.5; |
| 2874 | 2877 | transition: all 250msvar(--animation-duration-2x); |
| 2875 | 2878 | } |
| 2876 | 2879 | |
| 2877 | 2880 | .floating_panel_maximize:hover, |
| @@ -2885,7 +2888,7 @@ input[type="file"] { | ||
| 2885 | 2888 | aspect-ratio: 1 / 1; |
| 2886 | 2889 | font-size: calc(var(--mainFontSize)*1.3); |
| 2887 | 2890 | opacity: 0.5; |
| 2888 | 2891 | transition: all 250msvar(--animation-duration-2x); |
| 2889 | 2892 | filter: drop-shadow(0px 0px 2px black); |
| 2890 | 2893 | text-shadow: none; |
| 2891 | 2894 | } |
| @@ -2934,7 +2937,6 @@ select option:not(:checked) { | ||
| 2934 | 2937 | /*#######################################################################*/ |
| 2935 | 2938 | |
| 2936 | 2939 | #rm_api_block { |
| 2937 | - display: none; | |
| 2938 | 2940 | overflow-y: auto; |
| 2939 | 2941 | } |
| 2940 | 2942 | |
| @@ -3021,7 +3023,7 @@ select option:not(:checked) { | ||
| 3021 | 3023 | |
| 3022 | 3024 | #rm_characters_block { |
| 3023 | 3025 | display: flex; |
| 3024 | 3026 | overflow-y: autohidden; |
| 3025 | 3027 | flex-direction: column; |
| 3026 | 3028 | height: 100%; |
| 3027 | 3029 | } |
| @@ -3321,7 +3323,7 @@ input[type=search]:focus::-webkit-search-cancel-button { | ||
| 3321 | 3323 | text-shadow: none; |
| 3322 | 3324 | margin: 0; |
| 3323 | 3325 | filter: drop-shadow(0px 0px 3px white); |
| 3324 | 3326 | transition: opacity 0.2svar(--animation-duration-2x) ease-in-out; |
| 3325 | 3327 | display: none; |
| 3326 | 3328 | } |
| 3327 | 3329 | |
| @@ -3474,7 +3476,7 @@ input[type=search]:focus::-webkit-search-cancel-button { | ||
| 3474 | 3476 | border: 1px solid var(--SmartThemeBorderColor); |
| 3475 | 3477 | border-radius: 10px; |
| 3476 | 3478 | cursor: pointer; |
| 3477 | - transition: 0.2s; | |
| 3479 | + transition: var(--animation-duration-2x); | |
| 3478 | 3480 | } |
| 3479 | 3481 | |
| 3480 | 3482 | .avatar-container { |
| @@ -3769,7 +3771,7 @@ grammarly-extension { | ||
| 3769 | 3771 | width: min-content; |
| 3770 | 3772 | cursor: pointer; |
| 3771 | 3773 | margin: 5px 0; |
| 3772 | - transition: 0.3s; | |
| 3774 | + transition: var(--animation-duration-2x); | |
| 3773 | 3775 | display: flex; |
| 3774 | 3776 | align-items: center; |
| 3775 | 3777 | justify-content: center; |
| @@ -3835,7 +3837,7 @@ grammarly-extension { | ||
| 3835 | 3837 | background-color: var(--black30a); |
| 3836 | 3838 | border: 1px solid var(--SmartThemeBorderColor); |
| 3837 | 3839 | cursor: grab; |
| 3838 | 3840 | transition: background-color 200msvar(--animation-duration-2x) ease-in-out; |
| 3839 | 3841 | position: relative; |
| 3840 | 3842 | user-select: none; |
| 3841 | 3843 | display: flex; |
| @@ -4009,7 +4011,7 @@ input[type="checkbox"]::before { | ||
| 4009 | 4011 | width: 0.65em; |
| 4010 | 4012 | height: 0.65em; |
| 4011 | 4013 | transform: scale(0); |
| 4012 | 4014 | transition: 120msvar(--animation-duration) transform ease-in-out; |
| 4013 | 4015 | box-shadow: inset 1em 1em var(--SmartThemeCheckboxTickColor); |
| 4014 | 4016 | transform-origin: bottom left; |
| 4015 | 4017 | clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%); |
| @@ -4181,6 +4183,13 @@ input[type='checkbox'].del_checkbox { | ||
| 4181 | 4183 | background-repeat: no-repeat !important; |
| 4182 | 4184 | box-shadow: inset 0 0 2px var(--black50a) !important; |
| 4183 | 4185 | cursor: ew-resize !important; |
| 4186 | +} | |
| 4187 | + | |
| 4188 | +/* | |
| 4189 | + * Setting a z-index will allow scrollbar to display properly in Firefox, | |
| 4190 | + * while constraining to open drawers fixes a single frame linger in Chrome. | |
| 4191 | + */ | |
| 4192 | +.drawer-content.openDrawer .neo-range-slider { | |
| 4184 | 4193 | z-index: 1; |
| 4185 | 4194 | } |
| 4186 | 4195 | |
| @@ -4345,7 +4354,7 @@ input[type="range"]::-webkit-slider-thumb { | ||
| 4345 | 4354 | border-radius: 100%; |
| 4346 | 4355 | box-shadow: 0 0 3px black; |
| 4347 | 4356 | */ |
| 4348 | 4357 | transition: all 250msvar(--animation-duration-2x); |
| 4349 | 4358 | } |
| 4350 | 4359 | |
| 4351 | 4360 | .topRightInset { |
| @@ -4365,7 +4374,7 @@ input[type="range"]::-webkit-slider-thumb { | ||
| 4365 | 4374 | font-weight: 400; |
| 4366 | 4375 | text-decoration: none; |
| 4367 | 4376 | border-bottom: 2px dashed red; |
| 4368 | - transition: 0.3s; | |
| 4377 | + transition: var(--animation-duration-2x); | |
| 4369 | 4378 | } |
| 4370 | 4379 | |
| 4371 | 4380 | .whitespacenowrap { |
| @@ -4398,7 +4407,7 @@ input[type="range"]::-webkit-slider-thumb { | ||
| 4398 | 4407 | gap: 4px; |
| 4399 | 4408 | flex-wrap: nowrap; |
| 4400 | 4409 | justify-content: flex-end; |
| 4401 | 4410 | transition: all 200msvar(--animation-duration-2x); |
| 4402 | 4411 | overflow-x: hidden; |
| 4403 | 4412 | padding: 1px; |
| 4404 | 4413 | } |
| @@ -4410,7 +4419,7 @@ input[type="range"]::-webkit-slider-thumb { | ||
| 4410 | 4419 | .mes_button, |
| 4411 | 4420 | .extraMesButtons>div { |
| 4412 | 4421 | cursor: pointer; |
| 4413 | 4422 | transition: opacity 0.2svar(--animation-duration-2x) ease-in-out; |
| 4414 | 4423 | filter: drop-shadow(0px 0px 2px black); |
| 4415 | 4424 | opacity: 0.3; |
| 4416 | 4425 | padding: 1px 3px; |
| @@ -4441,7 +4450,7 @@ input[type="range"]::-webkit-slider-thumb { | ||
| 4441 | 4450 | cursor: pointer; |
| 4442 | 4451 | padding-bottom: 5px; |
| 4443 | 4452 | filter: drop-shadow(0px 0px 2px black); |
| 4444 | 4453 | transition: 0.3svar(--animation-duration-2x) ease-in-out; |
| 4445 | 4454 | } |
| 4446 | 4455 | |
| 4447 | 4456 | .mes_reasoning_actions { |
| @@ -4776,7 +4785,7 @@ body .ui-slider-handle { | ||
| 4776 | 4785 | text-align: center; |
| 4777 | 4786 | margin-left: 0; |
| 4778 | 4787 | opacity: 1 !important; |
| 4779 | 4788 | transition: filter 200msvar(--animation-duration-2x); |
| 4780 | 4789 | filter: brightness(1.2); |
| 4781 | 4790 | } |
| 4782 | 4791 | |
| @@ -4834,7 +4843,7 @@ body .ui-widget-content li { | ||
| 4834 | 4843 | align-items: center; |
| 4835 | 4844 | cursor: pointer; |
| 4836 | 4845 | opacity: 0.5; |
| 4837 | 4846 | transition: opacity 200msvar(--animation-duration-2x); |
| 4838 | 4847 | } |
| 4839 | 4848 | |
| 4840 | 4849 | body .ui-widget-content li:hover { |
| @@ -4996,34 +5005,6 @@ a:hover { | ||
| 4996 | 5005 | /* Right nav panel and nav-toggle */ |
| 4997 | 5006 | /* ############################################################# */ |
| 4998 | 5007 | |
| 4999 | -#right-nav-panel { | |
| 5000 | - width: calc((100vw - var(--sheldWidth) - 2px) /2); | |
| 5001 | - width: calc((100dvw - var(--sheldWidth) - 2px) /2); | |
| 5002 | - max-height: calc(100vh - var(--topBarBlockSize)); | |
| 5003 | - max-height: calc(100dvh - var(--topBarBlockSize)); | |
| 5004 | - height: calc(100vh - var(--topBarBlockSize)); | |
| 5005 | - height: calc(100dvh - var(--topBarBlockSize)); | |
| 5006 | - position: fixed; | |
| 5007 | - top: 0; | |
| 5008 | - margin: 0; | |
| 5009 | - right: 0; | |
| 5010 | - left: calc(100% - var(--sheldWidth) /2 + var(--sheldWidth) +1px); | |
| 5011 | - padding: 5px; | |
| 5012 | - margin-bottom: 5px; | |
| 5013 | - backdrop-filter: blur(calc(var(--SmartThemeBlurStrength))); | |
| 5014 | - background-color: var(--SmartThemeBlurTintColor); | |
| 5015 | - -webkit-backdrop-filter: blur(calc(var(--SmartThemeBlurStrength))); | |
| 5016 | - z-index: 3000; | |
| 5017 | - | |
| 5018 | - border: 1px solid var(--SmartThemeBorderColor); | |
| 5019 | - | |
| 5020 | - box-shadow: none; | |
| 5021 | - border-radius: 10px; | |
| 5022 | - overflow: hidden; | |
| 5023 | - flex-flow: column; | |
| 5024 | - min-width: 100px; | |
| 5025 | -} | |
| 5026 | - | |
| 5027 | 5008 | #nav-toggle { |
| 5028 | 5009 | position: fixed; |
| 5029 | 5010 | right: 13px; |
| @@ -5047,7 +5028,7 @@ a:hover { | ||
| 5047 | 5028 | display: none; |
| 5048 | 5029 | position: relative; |
| 5049 | 5030 | width: fit-content; |
| 5050 | 5031 | transition: all 0.1svar(--animation-duration); |
| 5051 | 5032 | padding: 0.5rem; |
| 5052 | 5033 | } |
| 5053 | 5034 | |
| @@ -5239,7 +5220,7 @@ body:not(.sd) .mes_img_swipes { | ||
| 5239 | 5220 | border-radius: 10px; |
| 5240 | 5221 | padding: 2px 5px; |
| 5241 | 5222 | border: 1px solid var(--SmartThemeBorderColor); |
| 5242 | 5223 | transition: all 250msvar(--animation-duration-2x); |
| 5243 | 5224 | } |
| 5244 | 5225 | |
| 5245 | 5226 | .standoutHeader.inline-drawer-header { |
| @@ -5322,12 +5303,12 @@ body:has(#character_popup.open) #top-settings-holder:has(.drawer-content.openDra | ||
| 5322 | 5303 | } |
| 5323 | 5304 | |
| 5324 | 5305 | .drawer-icon.openIcon { |
| 5325 | 5306 | transition: all 0.275svar(--animation-duration-2x); |
| 5326 | 5307 | } |
| 5327 | 5308 | |
| 5328 | 5309 | .drawer-icon.closedIcon { |
| 5329 | 5310 | opacity: 0.3; |
| 5330 | 5311 | transition: all 0.275svar(--animation-duration-2x); |
| 5331 | 5312 | } |
| 5332 | 5313 | |
| 5333 | 5314 | .drawer-icon.closedIcon:hover { |
| @@ -5390,7 +5371,7 @@ body:has(#character_popup.open) #top-settings-holder:has(.drawer-content.openDra | ||
| 5390 | 5371 | border: 1px solid var(--SmartThemeBorderColor); |
| 5391 | 5372 | min-width: 450px; |
| 5392 | 5373 | width: var(--sheldWidth); |
| 5393 | 5374 | overflow-y: autohidden; |
| 5394 | 5375 | max-height: calc(100vh - calc(var(--topBarBlockSize) + var(--bottomFormBlockSize))); |
| 5395 | 5376 | max-height: calc(100dvh - calc(var(--topBarBlockSize) + var(--bottomFormBlockSize))); |
| 5396 | 5377 | display: none; |
| @@ -5399,9 +5380,30 @@ body:has(#character_popup.open) #top-settings-holder:has(.drawer-content.openDra | ||
| 5399 | 5380 | left: 0; |
| 5400 | 5381 | right: 0; |
| 5401 | 5382 | margin: 0 auto; |
| 5383 | + height: 0; | |
| 5402 | 5384 | backdrop-filter: blur(calc(var(--SmartThemeBlurStrength))); |
| 5403 | 5385 | -webkit-backdrop-filter: blur(calc(var(--SmartThemeBlurStrength))); |
| 5404 | 5386 | /* z-index: 1000 !important; */ |
| 5387 | + transition-property: height, display; | |
| 5388 | + transition-duration: var(--animation-duration-2x); | |
| 5389 | + transition-timing-function: ease-in-out; | |
| 5390 | + transition-behavior: allow-discrete; | |
| 5391 | +} | |
| 5392 | + | |
| 5393 | +#movingDivs>.drawer-content { | |
| 5394 | + height: unset; | |
| 5395 | +} | |
| 5396 | + | |
| 5397 | +.drawer-content.openDrawer { | |
| 5398 | + display: block; | |
| 5399 | + height: auto; | |
| 5400 | + height: calc-size(auto, size); | |
| 5401 | + overflow-y: auto; | |
| 5402 | + animation: hide-scroll var(--animation-duration-2x) backwards; | |
| 5403 | + | |
| 5404 | + @starting-style { | |
| 5405 | + height: 0; | |
| 5406 | + } | |
| 5405 | 5407 | } |
| 5406 | 5408 | |
| 5407 | 5409 | body.movingUI .inline-drawer-maximize { |
| @@ -5428,8 +5430,7 @@ body:not(.movingUI) .drawer-content.maximized { | ||
| 5428 | 5430 | .fillLeft { |
| 5429 | 5431 | width: calc((100vw - var(--sheldWidth) - 2px) /2); |
| 5430 | 5432 | width: calc((100dvw - var(--sheldWidth) - 2px) /2); |
| 5431 | - height: calc(100vh - var(--topBarBlockSize)); | |
| 5433 | + height: 0; | |
| 5432 | - height: calc(100dvh - var(--topBarBlockSize)); | |
| 5433 | 5434 | max-height: calc(100vh - var(--topBarBlockSize)); |
| 5434 | 5435 | max-height: calc(100dvh - var(--topBarBlockSize)); |
| 5435 | 5436 | position: fixed; |
| @@ -5443,6 +5444,66 @@ body:not(.movingUI) .drawer-content.maximized { | ||
| 5443 | 5444 | border: 1px solid var(--SmartThemeBorderColor); |
| 5444 | 5445 | } |
| 5445 | 5446 | |
| 5447 | +.fillLeft.openDrawer { | |
| 5448 | + overflow-y: hidden; | |
| 5449 | + height: calc(100vh - var(--topBarBlockSize)); | |
| 5450 | + height: calc(100dvh - var(--topBarBlockSize)); | |
| 5451 | + height: calc-size((100dvh - var(--topBarBlockSize)), size); | |
| 5452 | + | |
| 5453 | + @starting-style { | |
| 5454 | + height: 0; | |
| 5455 | + } | |
| 5456 | +} | |
| 5457 | + | |
| 5458 | +.fillRight { | |
| 5459 | + width: calc((100vw - var(--sheldWidth) - 2px) /2); | |
| 5460 | + width: calc((100dvw - var(--sheldWidth) - 2px) /2); | |
| 5461 | + max-height: calc(100vh - var(--topBarBlockSize)); | |
| 5462 | + max-height: calc(100dvh - var(--topBarBlockSize)); | |
| 5463 | + height: 0; | |
| 5464 | + position: fixed; | |
| 5465 | + top: 0; | |
| 5466 | + margin: 0; | |
| 5467 | + right: 0; | |
| 5468 | + left: calc(100% - var(--sheldWidth) /2 + var(--sheldWidth) +1px); | |
| 5469 | + padding: 5px; | |
| 5470 | + margin-bottom: 5px; | |
| 5471 | + backdrop-filter: blur(calc(var(--SmartThemeBlurStrength))); | |
| 5472 | + background-color: var(--SmartThemeBlurTintColor); | |
| 5473 | + -webkit-backdrop-filter: blur(calc(var(--SmartThemeBlurStrength))); | |
| 5474 | + z-index: 3000; | |
| 5475 | + | |
| 5476 | + border: 1px solid var(--SmartThemeBorderColor); | |
| 5477 | + | |
| 5478 | + box-shadow: none; | |
| 5479 | + border-radius: 10px; | |
| 5480 | + overflow: hidden; | |
| 5481 | + flex-flow: column; | |
| 5482 | + min-width: 100px; | |
| 5483 | +} | |
| 5484 | + | |
| 5485 | +.fillRight.openDrawer { | |
| 5486 | + display: flex; | |
| 5487 | + height: calc(100vh - var(--topBarBlockSize)); | |
| 5488 | + height: calc(100dvh - var(--topBarBlockSize)); | |
| 5489 | + height: calc-size((100dvh - var(--topBarBlockSize)), size); | |
| 5490 | + | |
| 5491 | + @starting-style { | |
| 5492 | + height: 0; | |
| 5493 | + } | |
| 5494 | +} | |
| 5495 | + | |
| 5496 | +/* | |
| 5497 | +.fillRight #rm_print_characters_block { | |
| 5498 | + overflow-y: hidden; | |
| 5499 | +} | |
| 5500 | + | |
| 5501 | +.fillRight.openDrawer #rm_print_characters_block { | |
| 5502 | + overflow-y: auto; | |
| 5503 | + animation: hide-scroll var(--animation-duration-2x) backwards; | |
| 5504 | +} | |
| 5505 | +*/ | |
| 5506 | + | |
| 5446 | 5507 | .scrollableInner { |
| 5447 | 5508 | overflow-x: hidden; |
| 5448 | 5509 | height: calc(100% - 30px); |
| @@ -5709,7 +5770,7 @@ body:not(.movingUI) .drawer-content.maximized { | ||
| 5709 | 5770 | aspect-ratio: 1 / 1; |
| 5710 | 5771 | font-size: 20px; |
| 5711 | 5772 | opacity: 0.5; |
| 5712 | 5773 | transition: all 250msvar(--animation-duration-2x); |
| 5713 | 5774 | } |
| 5714 | 5775 | |
| 5715 | 5776 | /* #groupMemberListPopout, |
| @@ -5796,7 +5857,7 @@ body:not(.movingUI) .drawer-content.maximized { | ||
| 5796 | 5857 | color: var(--SmartThemeBodyColor); |
| 5797 | 5858 | border: 1px solid var(--SmartThemeBorderColor); |
| 5798 | 5859 | border-radius: 5px; |
| 5799 | 5860 | transition: opacity 0.2svar(--animation-duration-2x); |
| 5800 | 5861 | opacity: 0.8; |
| 5801 | 5862 | cursor: pointer; |
| 5802 | 5863 | } |
| @@ -5988,7 +6049,7 @@ body:not(.movingUI) .drawer-content.maximized { | ||
| 5988 | 6049 | margin: 7px; |
| 5989 | 6050 | width: calc(100% - 7px); |
| 5990 | 6051 | box-sizing: border-box; |
| 5991 | 6052 | transition: transform 0.2svar(--animation-duration-2x) ease-in-out, background-color 0.2svar(--animation-duration-2x) ease-in-out, border 0.2svar(--animation-duration-2x) ease-in-out; |
| 5992 | 6053 | } |
| 5993 | 6054 | |
| 5994 | 6055 | .model-card .details-container { |
| @@ -6000,7 +6061,7 @@ body:not(.movingUI) .drawer-content.maximized { | ||
| 6000 | 6061 | transform: scale(1.01); |
| 6001 | 6062 | background-color: #444; |
| 6002 | 6063 | /* Smooth transition */ |
| 6003 | 6064 | transition: transform 0.2svar(--animation-duration-2x) ease-in-out, background-color 0.2svar(--animation-duration-2x) ease-in-out; |
| 6004 | 6065 | } |
| 6005 | 6066 | |
| 6006 | 6067 | .model-card.selected { |