Add background image fitting options Closes #3133
| @@ -4713,6 +4713,13 @@ | |||
| 4713 | Background Image | 4713 | 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> |
| @@ -12,6 +12,7 @@ const LIST_METADATA_KEY = 'chat_backgrounds'; | |||
| 12 | export let background_settings = { | 12 | export 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 | }; |
| 16 | 17 | ||
| 17 | export function loadBackgroundSettings(settings) { | 18 | export 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 | } |
| 24 | 30 | ||
| 25 | /** | 31 | /** |
| @@ -470,6 +476,18 @@ function highlightNewBackground(bg) { | |||
| 470 | flashHighlight(newBg); | 476 | flashHighlight(newBg); |
| 471 | } | 477 | } |
| 472 | 478 | ||
| 479 | /** | ||
| 480 | * Sets the fitting class for the background element | ||
| 481 | * @param {string} fitting Fitting type | ||
| 482 | */ | ||
| 483 | function 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 | |||
| 473 | function onBackgroundFilterInput() { | 491 | function 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 | })); |
| 512 | 530 | ||
| 531 | $('#background_fitting').on('input', function () { | ||
| 532 | background_settings.fitting = String($(this).val()); | ||
| 533 | setFittingClass(background_settings.fitting); | ||
| 534 | saveSettingsDebounced(); | ||
| 535 | }); | ||
| 513 | } | 536 | } |
| @@ -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 | } |
| 521 | 521 | ||
| 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 | |||
| 522 | body.reduced-motion #bg1, | 556 | body.reduced-motion #bg1, |
| 523 | body.reduced-motion #bg_custom { | 557 | body.reduced-motion #bg_custom { |
| 524 | transition: none; | 558 | transition: none; |