Merge pull request #3222 from SillyTavern/bg-fitting Add background image fitting options

28c7dbbe1bb6c3d8797c50fa851a54d284471cec

Cohee <18619528+Cohee1207@users.noreply.github.com>

Signed
3 files changed, +65 -1Ignore whitespace
public/index.html+7 -0
@@ -4713,6 +4713,13 @@
4713 Background Image4713 Background Image
4714 </h3>4714 </h3>
4715 <input id="bg-filter" data-i18n="[placeholder]Filter" placeholder="Filter" class="text_pole flex1" type="search" />4715 <input id="bg-filter" data-i18n="[placeholder]Filter" placeholder="Filter" class="text_pole flex1" type="search" />
4716 <select id="background_fitting" class="text_pole" data-i18n="[title]Background Fitting" title="Background Fitting">
4717 <option value="classic" data-i18n="Classic">Classic</option>
4718 <option value="cover" data-i18n="Cover">Cover</option>
4719 <option value="contain" data-i18n="Contain">Contain</option>
4720 <option value="stretch" data-i18n="Stretch">Stretch</option>
4721 <option value="center" data-i18n="Center">Center</option>
4722 </select>
4716 <div id="auto_background" class="menu_button menu_button_icon" data-i18n="[title]Automatically select a background based on the chat context" title="Automatically select a background based on the chat context.">4723 <div id="auto_background" class="menu_button menu_button_icon" data-i18n="[title]Automatically select a background based on the chat context" title="Automatically select a background based on the chat context.">
4717 <i class="fa-solid fa-wand-magic"></i>4724 <i class="fa-solid fa-wand-magic"></i>
4718 <span data-i18n="Auto-select">Auto-select</span>4725 <span data-i18n="Auto-select">Auto-select</span>
public/scripts/backgrounds.js+23 -0
@@ -12,6 +12,7 @@ const LIST_METADATA_KEY = 'chat_backgrounds';
12export let background_settings = {12export let background_settings = {
13 name: '__transparent.png',13 name: '__transparent.png',
14 url: generateUrlParameter('__transparent.png', false),14 url: generateUrlParameter('__transparent.png', false),
15 fitting: 'classic',
15};16};
1617
17export function loadBackgroundSettings(settings) {18export function loadBackgroundSettings(settings) {
@@ -19,7 +20,12 @@ export function loadBackgroundSettings(settings) {
19 if (!backgroundSettings || !backgroundSettings.name || !backgroundSettings.url) {20 if (!backgroundSettings || !backgroundSettings.name || !backgroundSettings.url) {
20 backgroundSettings = background_settings;21 backgroundSettings = background_settings;
21 }22 }
23 if (!backgroundSettings.fitting) {
24 backgroundSettings.fitting = 'classic';
25 }
22 setBackground(backgroundSettings.name, backgroundSettings.url);26 setBackground(backgroundSettings.name, backgroundSettings.url);
27 setFittingClass(backgroundSettings.fitting);
28 $('#background_fitting').val(backgroundSettings.fitting);
23}29}
2430
25/**31/**
@@ -470,6 +476,18 @@ function highlightNewBackground(bg) {
470 flashHighlight(newBg);476 flashHighlight(newBg);
471}477}
472478
479/**
480 * Sets the fitting class for the background element
481 * @param {string} fitting Fitting type
482 */
483function setFittingClass(fitting) {
484 const backgrounds = $('#bg1, #bg_custom');
485 backgrounds.toggleClass('cover', fitting === 'cover');
486 backgrounds.toggleClass('contain', fitting === 'contain');
487 backgrounds.toggleClass('stretch', fitting === 'stretch');
488 backgrounds.toggleClass('center', fitting === 'center');
489}
490
473function onBackgroundFilterInput() {491function onBackgroundFilterInput() {
474 const filterValue = String($(this).val()).toLowerCase();492 const filterValue = String($(this).val()).toLowerCase();
475 $('#bg_menu_content > div').each(function () {493 $('#bg_menu_content > div').each(function () {
@@ -510,4 +528,9 @@ export function initBackgrounds() {
510 helpString: 'Automatically changes the background based on the chat context using the AI request prompt',528 helpString: 'Automatically changes the background based on the chat context using the AI request prompt',
511 }));529 }));
512530
531 $('#background_fitting').on('input', function () {
532 background_settings.fitting = String($(this).val());
533 setFittingClass(background_settings.fitting);
534 saveSettingsDebounced();
535 });
513}536}
public/style.css+35 -1
@@ -141,7 +141,7 @@ body {
141 height: 100dvh;141 height: 100dvh;
142 /*defaults as 100%, then reassigned via JS as pixels, will work on PC and Android*/142 /*defaults as 100%, then reassigned via JS as pixels, will work on PC and Android*/
143 /*height: calc(var(--doc-height) - 1px);*/143 /*height: calc(var(--doc-height) - 1px);*/
144 background-color: var(--greyCAIbg);144 background-color: var(--SmartThemeBlurTintColor);
145 background-repeat: no-repeat;145 background-repeat: no-repeat;
146 background-attachment: fixed;146 background-attachment: fixed;
147 background-size: cover;147 background-size: cover;
@@ -519,6 +519,40 @@ hr {
519 transition: background-image 0.5s ease-in-out;519 transition: background-image 0.5s ease-in-out;
520}520}
521521
522/* Background fitting options */
523#background_fitting {
524 max-width: 6em;
525}
526
527/* Fill/Cover - scales to fill width while maintaining aspect ratio */
528#bg1.cover,
529#bg_custom.cover {
530 background-size: cover;
531 background-position: center;
532}
533
534/* Fit/Contain - shows entire image maintaining aspect ratio */
535#bg1.contain,
536#bg_custom.contain {
537 background-size: contain;
538 background-position: center;
539 background-repeat: no-repeat;
540}
541
542/* Stretch - stretches to fill entire space */
543#bg1.stretch,
544#bg_custom.stretch {
545 background-size: 100% 100%;
546}
547
548/* Center - centers without scaling */
549#bg1.center,
550#bg_custom.center {
551 background-size: auto;
552 background-position: center;
553 background-repeat: no-repeat;
554}
555
522body.reduced-motion #bg1,556body.reduced-motion #bg1,
523body.reduced-motion #bg_custom {557body.reduced-motion #bg_custom {
524 transition: none;558 transition: none;