c.ai Background Image Library (Improved)

Customize the chat interface with an improved image library for backgrounds, with multiple rows of thumbnails and click-outside popup closure.

目前为 2024-11-25 提交的版本。查看 最新版本

// ==UserScript==
// @name        c.ai Background Image Library (Improved)
// @namespace   c.ai Background Image Library Improved
// @match       https://character.ai/*
// @grant       none
// @license     MIT
// @version     6.3
// @description Customize the chat interface with an improved image library for backgrounds, with multiple rows of thumbnails and click-outside popup closure.
// @icon        https://i.imgur.com/ynjBqKW.png
// ==/UserScript==

(function () {
  function saveLibrary(library) {
    localStorage.setItem('background_image_library', JSON.stringify(library));
  }

  function getLibrary() {
    return JSON.parse(localStorage.getItem('background_image_library') || '[]');
  }

  function addToLibrary(url) {
    const library = getLibrary();
    if (!url || library.includes(url)) return;
    library.push(url);
    saveLibrary(library);
  }

  function removeFromLibrary(url) {
    const library = getLibrary().filter((image) => image !== url);
    saveLibrary(library);
  }

  function applyBackgroundImage(url) {
    localStorage.setItem('background_image_url', url);
    const css = `
      body {
        background-image: url('${url}');
        background-size: cover;
        background-position: center;
        background-repeat: no-repeat;
      }
    `;
    let styleElement = document.getElementById('customBackgroundStyle');
    if (!styleElement) {
      styleElement = document.createElement('style');
      styleElement.id = 'customBackgroundStyle';
      document.head.appendChild(styleElement);
    }
    styleElement.innerHTML = css;
  }

  function createCustomizationPanel() {
    const panel = document.createElement('div');
    panel.id = 'customizationPanel';
    panel.style.position = 'fixed';
    panel.style.top = '50%';
    panel.style.left = '50%';
    panel.style.transform = 'translate(-50%, -50%)';
    panel.style.backgroundColor = '#1e1e1e';
    panel.style.color = 'white';
    panel.style.borderRadius = '5px';
    panel.style.padding = '20px';
    panel.style.zIndex = '9999';
    panel.style.fontFamily = 'Montserrat, sans-serif';
    panel.style.maxWidth = '1250px'; // 2.5x wider
    panel.style.minWidth = '875px';  // 2.5x wider
    panel.style.width = 'auto'; // Ensure auto width based on content

    const label = document.createElement('label');
    label.textContent = 'Add Image URL to Library:';
    label.style.display = 'block';
    label.style.marginBottom = '5px';

    const input = document.createElement('input');
    input.type = 'text';
    input.placeholder = 'Enter image URL';
    input.style.width = '100%';
    input.style.marginBottom = '10px';

    const addButton = document.createElement('button');
    addButton.textContent = 'Add';
    addButton.style.marginTop = '10px';
    addButton.style.padding = '5px 10px';
    addButton.style.border = 'none';
    addButton.style.borderRadius = '3px';
    addButton.style.backgroundColor = '#444';
    addButton.style.color = 'white';
    addButton.style.fontFamily = 'Montserrat, sans-serif';
    addButton.addEventListener('click', () => {
      const url = input.value.trim();
      if (url) {
        addToLibrary(url);
        input.value = '';
        renderLibrary();
      }
    });

    const libraryContainer = document.createElement('div');
    libraryContainer.id = 'libraryContainer';
    libraryContainer.style.marginTop = '10px';
    libraryContainer.style.overflowX = 'auto';
    libraryContainer.style.display = 'flex';
    libraryContainer.style.flexWrap = 'wrap'; // Allow wrapping into multiple lines
    libraryContainer.style.gap = '15px'; // Increased gap between thumbnails
    libraryContainer.style.paddingBottom = '10px';
    libraryContainer.style.borderTop = '1px solid #555';
    libraryContainer.style.paddingTop = '10px';
    libraryContainer.style.whiteSpace = 'nowrap'; // Prevent wrapping of thumbnails
    libraryContainer.style.maxHeight = '380px';  // Ensure 3 rows of thumbnails
    libraryContainer.style.height = 'auto';

    function renderLibrary() {
      libraryContainer.innerHTML = '';
      const library = getLibrary();
      library.forEach((url) => {
        const imgContainer = document.createElement('div');
        imgContainer.style.position = 'relative';
        imgContainer.style.flex = '0 0 auto'; // Ensures the thumbnail stays at its natural width

        const img = document.createElement('img');
        img.src = url;
        img.alt = 'Preview';
        img.style.width = '99px';  // Half the size
        img.style.height = '64px'; // Half the size
        img.style.objectFit = 'cover';
        img.style.border = '1px solid #fff';
        img.style.borderRadius = '3px';
        img.style.cursor = 'pointer';
        img.title = url;

        img.addEventListener('click', () => {
          applyBackgroundImage(url);
        });

        const removeButton = document.createElement('button');
        removeButton.textContent = '×';
        removeButton.style.position = 'absolute';
        removeButton.style.top = '5px';
        removeButton.style.right = '5px';
        removeButton.style.backgroundColor = 'red';
        removeButton.style.color = 'white';
        removeButton.style.border = 'none';
        removeButton.style.borderRadius = '50%';
        removeButton.style.cursor = 'pointer';
        removeButton.style.width = '20px';
        removeButton.style.height = '20px';
        removeButton.style.textAlign = 'center';
        removeButton.style.fontSize = '12px';
        removeButton.addEventListener('click', (e) => {
          e.stopPropagation();
          removeFromLibrary(url);
          renderLibrary();
        });

        imgContainer.appendChild(img);
        imgContainer.appendChild(removeButton);
        libraryContainer.appendChild(imgContainer);
      });
    }

    panel.appendChild(label);
    panel.appendChild(input);
    panel.appendChild(addButton);
    panel.appendChild(libraryContainer);
    document.body.appendChild(panel);

    renderLibrary();

    // Close the panel when clicking outside of it
    document.addEventListener('click', function closeOnOutsideClick(event) {
      if (!panel.contains(event.target) && !mainButton.contains(event.target)) {
        panel.remove();
        document.removeEventListener('click', closeOnOutsideClick); // Remove the event listener
      }
    });
  }

  function createButton(symbol, onClick) {
    const button = document.createElement('button');
    button.innerHTML = symbol;
    button.style.position = 'fixed';
    button.style.top = '82px';
    button.style.right = '5px';
    button.style.width = '22px';
    button.style.height = '22px';
    button.style.backgroundColor = '#444';
    button.style.color = 'white';
    button.style.border = 'none';
    button.style.borderRadius = '3px';
    button.style.cursor = 'pointer';
    button.style.fontFamily = 'Montserrat, sans-serif';
    button.addEventListener('click', onClick);
    return button;
  }

  const mainButton = createButton('🖼️', () => {
    const panelExists = document.getElementById('customizationPanel');
    if (!panelExists) {
      createCustomizationPanel();
    }
  });

  document.body.appendChild(mainButton);

  const currentImageUrl = localStorage.getItem('background_image_url') || '';
  applyBackgroundImage(currentImageUrl);
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址