π¨ Personalize o fundo do Chess.com com Imagens e Videos! πΌοΈ Use vΓdeos e imagens personalizados, crie cenΓ‘rios incrΓveis e deixe seu xadrez com a sua identidade. πβ¨
// ==UserScript==
// @name πΌοΈπ Chess.com Background
// @namespace http://tampermonkey.net/
// @version 7.7
// @description π¨ Personalize o fundo do Chess.com com Imagens e Videos! πΌοΈ Use vΓdeos e imagens personalizados, crie cenΓ‘rios incrΓveis e deixe seu xadrez com a sua identidade. πβ¨
// @author aerus15
// @match *://*.chess.com/*
// @grant GM_addStyle
// @run-at document-start
// ==/UserScript====
(function() {
'use strict';
const DB_NAME = 'ChessBgDB';
const STORE_NAME = 'bgStore';
function initDB() {
return new Promise((resolve, reject) => {
const request = indexedDB.open(DB_NAME, 1);
request.onupgradeneeded = (e) => {
const db = e.target.result;
if (!db.objectStoreNames.contains(STORE_NAME)) {
db.createObjectStore(STORE_NAME);
}
};
request.onsuccess = () => resolve(request.result);
request.onerror = (e) => reject(e);
});
}
async function saveImageToDB(file) {
const db = await initDB();
return new Promise((resolve, reject) => {
const tx = db.transaction(STORE_NAME, 'readwrite');
const store = tx.objectStore(STORE_NAME);
const request = store.put(file, 'current_bg_image');
request.onsuccess = () => resolve();
request.onerror = (e) => reject(e);
});
}
async function loadImageFromDB() {
const db = await initDB();
return new Promise((resolve, reject) => {
const tx = db.transaction(STORE_NAME, 'readonly');
const store = tx.objectStore(STORE_NAME);
const request = store.get('current_bg_image');
request.onsuccess = () => resolve(request.result);
request.onerror = (e) => reject(e);
});
}
const css = `
.board-layout-sidebar,
#board-layout-sidebar,
.play-controller-sidebar,
.computer-sidebar-component,
.analysis-sidebar-component,
.live-game-sidebar-component,
.sidebar-component,
[data-test-id="sidebar"] {
display: none !important;
width: 0 !important;
visibility: hidden !important;
opacity: 0 !important;
pointer-events: none !important;
}
body.reveal-chess-ui .board-layout-sidebar,
body.reveal-chess-ui #board-layout-sidebar,
body.reveal-chess-ui .play-controller-sidebar,
body.reveal-chess-ui .computer-sidebar-component,
body.reveal-chess-ui .analysis-sidebar-component,
body.reveal-chess-ui .live-game-sidebar-component,
body.reveal-chess-ui .sidebar-component,
body.reveal-chess-ui [data-test-id="sidebar"],
body.reveal-chess-ui .layout-right,
body.reveal-chess-ui [data-cy="analysis-panel"],
body.reveal-chess-ui .game-overview,
body.reveal-chess-ui .vertical-move-list,
body.reveal-chess-ui .analysis-tools {
display: flex !important;
width: clamp(250px, 30vw, 350px) !important;
min-width: 300px !important;
max-width: 400px !important;
visibility: visible !important;
opacity: 1 !important;
pointer-events: auto !important;
background: rgba(30, 30, 30, 0.95) !important;
backdrop-filter: blur(8px) !important;
z-index: 2147483647 !important;
position: fixed !important;
right: 0 !important;
top: 0 !important;
bottom: 0 !important;
height: 100vh !important;
overflow-y: auto !important;
box-shadow: -5px 0 20px rgba(0,0,0,0.8) !important;
transform: none !important;
clip: auto !important;
clip-path: none !important;
margin: 0 !important;
padding: 0 !important;
}
.board-layout-main {
margin: 0 auto !important;
}
body,
html,
#sb,
.v5-section-content-wrapper,
.v-board-wrapper,
.layout-board,
.layout-main,
.board-layout {
background: transparent !important;
background-color: transparent !important;
background-image: none !important;
}
#custom-bg-video,
#custom-bg-img {
position: fixed !important;
top: 0 !important;
left: 0 !important;
width: 100vw !important;
height: 100vh !important;
object-fit: var(--bg-fit, cover) !important;
filter: brightness(var(--bg-brightness, 100%)) contrast(var(--bg-contrast, 100%)) saturate(var(--bg-saturate, 100%)) hue-rotate(var(--bg-hue, 0deg)) !important;
z-index: -9999 !important;
pointer-events: none !important;
transform: translateZ(0) !important;
backface-visibility: hidden !important;
will-change: transform !important;
opacity: 0.85 !important;
image-rendering: auto !important;
display: none !important;
}
#custom-bg-video.active,
#custom-bg-img.active {
display: block !important;
}
#bg-main-toggle {
position: fixed;
left: 15px;
bottom: 220px;
z-index: 100000;
background: rgba(0,0,0,0.6);
color: white;
border: 1px solid rgba(255,255,255,0.2);
border-radius: 50%;
width: 36px;
height: 36px;
cursor: pointer;
font-size: 18px;
display: flex;
justify-content: center;
align-items: center;
box-shadow: 0 4px 10px rgba(0,0,0,0.5);
transition: 0.3s;
}
#bg-main-toggle:hover {
background: rgba(0,0,0,0.9);
transform: scale(1.1);
}
#bg-main-menu {
position: fixed;
left: 15px;
bottom: 265px;
z-index: 99999;
background: rgba(0,0,0,0.85);
padding: 12px;
border-radius: 8px;
border: 1px solid rgba(255,255,255,0.2);
display: none;
flex-direction: column;
gap: 10px;
box-shadow: 0 4px 15px rgba(0,0,0,0.5);
backdrop-filter: blur(5px);
width: 170px;
}
#bg-main-menu.open {
display: flex;
}
.bg-menu-btn {
background: rgba(0,0,0,0.5);
color: white;
border: 1px solid rgba(255,255,255,0.2);
padding: 8px;
border-radius: 6px;
cursor: pointer;
font-size: 12px;
transition: 0.2s;
text-align: center;
width: 100%;
box-sizing: border-box;
}
.bg-menu-btn:hover {
background: rgba(255,255,255,0.2);
transform: scale(1.03);
}
#bg-auto-prompt {
width: 100%;
background: rgba(0,0,0,0.6);
color: white;
border: 1px solid rgba(255,255,255,0.3);
padding: 8px;
border-radius: 6px;
font-size: 12px;
box-sizing: border-box;
outline: none;
text-align: center;
}
#bg-auto-prompt::placeholder {
color: rgba(255,255,255,0.6);
}
#bg-auto-img-btn { font-weight: bold; color: #4CAF50; border-color: #4CAF50; }
#bg-save-mural-btn { font-weight: bold; color: #FFD700; border-color: #FFD700; }
#bg-mural-btn { font-weight: bold; color: #00BCD4; border-color: #00BCD4; }
#bg-settings-btn { font-weight: bold; color: #FF9800; border-color: #FF9800; }
.bg-menu-divider {
height: 1px;
background: rgba(255,255,255,0.2);
margin: 2px 0;
width: 100%;
}
#bg-settings-panel,
#bg-mural-panel {
position: fixed;
left: 200px;
bottom: 265px;
background: rgba(0,0,0,0.95);
color: white;
padding: 15px;
border-radius: 8px;
border: 1px solid rgba(255,255,255,0.2);
z-index: 99999;
display: none;
flex-direction: column;
gap: 12px;
font-family: sans-serif;
font-size: 13px;
box-shadow: 0 4px 15px rgba(0,0,0,0.5);
backdrop-filter: blur(5px);
}
#bg-settings-panel { width: 220px; }
#bg-mural-panel { width: 320px; max-height: 400px; overflow-y: auto; }
#bg-settings-panel.open,
#bg-mural-panel.open {
display: flex;
}
#bg-settings-panel label {
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
}
#bg-settings-panel input[type="range"] { width: 120px; cursor: pointer; }
#bg-settings-panel input[type="checkbox"] { cursor: pointer; width: 16px; height: 16px; }
#bg-setting-reset {
margin-top: 5px;
background: #444;
color: white;
border: 1px solid rgba(255,255,255,0.2);
padding: 8px;
border-radius: 4px;
cursor: pointer;
transition: 0.2s;
font-weight: bold;
}
#bg-setting-reset:hover { background: #555; }
.mural-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
}
.mural-item {
position: relative;
border: 1px solid rgba(255,255,255,0.2);
border-radius: 4px;
overflow: hidden;
background: #111;
display: flex;
flex-direction: column;
}
.mural-item img {
width: 100%;
height: 90px;
object-fit: cover;
cursor: pointer;
transition: 0.2s;
}
.mural-item img:hover { transform: scale(1.05); }
.mural-item-actions {
display: flex;
justify-content: space-between;
align-items: center;
padding: 6px 8px;
background: rgba(0, 0, 0, 0.9);
position: absolute;
bottom: 0;
width: 100%;
box-sizing: border-box;
}
.mural-item-actions a,
.mural-item-actions button {
color: white;
font-size: 11px;
text-decoration: none;
background: none;
border: none;
cursor: pointer;
padding: 0;
font-weight: bold;
}
.mural-item-actions a:hover { color: #00BCD4; text-decoration: underline; }
.mural-item-actions button { color: #ff4444; }
.mural-item-actions button:hover { color: #ff0000; transform: scale(1.1); }
`;
if (typeof GM_addStyle !== "undefined") {
GM_addStyle(css);
} else {
const style = document.createElement('style');
style.textContent = css;
document.head.appendChild(style);
}
const STORAGE_KEY = 'chess_video_url_stream';
const STORAGE_TYPE_KEY = 'chess_video_type';
const PROMPT_KEY = 'chess_auto_prompt';
const SEEDS_KEY = 'chess_used_seeds';
const AI_MODE_KEY = 'chess_ai_mode';
function optimizeVideo(video) {
video.autoplay = true;
video.loop = true;
video.muted = true;
video.playsInline = true;
video.preload = "metadata";
video.disablePictureInPicture = true;
video.setAttribute('webkit-playsinline', 'true');
video.style.contain = 'strict';
video.playbackRate = 1.0;
video.addEventListener('loadeddata', () => {
video.play().catch(() => {});
});
video.addEventListener('canplay', () => {
video.play().catch(() => {});
});
video.addEventListener('stalled', () => {});
video.addEventListener('error', (e) => {});
const attemptPlay = () => {
const p = video.play();
if (p !== undefined) {
p.catch(() => {
setTimeout(attemptPlay, 1000);
});
}
};
attemptPlay();
}
function createVideoElement() {
let video = document.getElementById('custom-bg-video');
if (video) return video;
video = document.createElement('video');
video.id = 'custom-bg-video';
optimizeVideo(video);
document.body.appendChild(video);
return video;
}
function createImageElement() {
let img = document.getElementById('custom-bg-img');
if (img) return img;
img = document.createElement('img');
img.id = 'custom-bg-img';
img.style.contain = 'strict';
document.body.appendChild(img);
return img;
}
function setVideoURL(url) {
const video = createVideoElement();
const img = createImageElement();
if (!url) return;
img.classList.remove('active');
video.classList.add('active');
video.pause();
video.src = '';
video.removeAttribute('src');
video.load();
requestAnimationFrame(() => {
video.src = url;
video.load();
const startPlayback = () => {
const promise = video.play();
if (promise !== undefined) {
promise.catch(() => {
setTimeout(startPlayback, 1000);
});
}
};
startPlayback();
});
localStorage.setItem(STORAGE_KEY, url);
localStorage.setItem(STORAGE_TYPE_KEY, 'video');
}
function setImageSource(url) {
const img = createImageElement();
const video = createVideoElement();
video.classList.remove('active');
video.pause();
video.src = '';
video.removeAttribute('src');
video.load();
img.src = url;
img.classList.add('active');
}
function createUI() {
const toggleBtn = document.createElement('button');
toggleBtn.id = 'bg-main-toggle';
toggleBtn.innerHTML = 'β¦';
toggleBtn.title = 'Menu de Fundo';
const menu = document.createElement('div');
menu.id = 'bg-main-menu';
toggleBtn.addEventListener('click', () => {
menu.classList.toggle('open');
document.getElementById('bg-settings-panel')?.classList.remove('open');
document.getElementById('bg-mural-panel')?.classList.remove('open');
});
const fileBtn = document.createElement('button');
fileBtn.className = 'bg-menu-btn';
fileBtn.textContent = 'Arquivo Local';
const urlBtn = document.createElement('button');
urlBtn.className = 'bg-menu-btn';
urlBtn.textContent = 'URL VΓdeo';
const imgBtn = document.createElement('button');
imgBtn.className = 'bg-menu-btn';
imgBtn.textContent = 'Imagem URL';
const div1 = document.createElement('div');
div1.className = 'bg-menu-divider';
const promptInput = document.createElement('input');
promptInput.id = 'bg-auto-prompt';
promptInput.type = 'text';
promptInput.placeholder = 'Palavra chave (Ex: cars)';
promptInput.value = localStorage.getItem(PROMPT_KEY) || '';
promptInput.addEventListener('input', (e) => localStorage.setItem(PROMPT_KEY, e.target.value));
const aiModeContainer = document.createElement('div');
aiModeContainer.style.cssText = 'display:flex; align-items:center; gap:5px; color:white; font-size:12px; margin: 2px 0; justify-content:center;';
const aiModeCheckbox = document.createElement('input');
aiModeCheckbox.type = 'checkbox';
aiModeCheckbox.id = 'bg-ai-mode';
aiModeCheckbox.style.cssText = 'cursor:pointer; width:14px; height:14px; margin:0;';
aiModeCheckbox.checked = localStorage.getItem(AI_MODE_KEY) === 'true';
aiModeCheckbox.addEventListener('change', (e) => {
localStorage.setItem(AI_MODE_KEY, e.target.checked);
});
const aiModeLabel = document.createElement('label');
aiModeLabel.htmlFor = 'bg-ai-mode';
aiModeLabel.textContent = 'Modo I.A (Pollinations)';
aiModeLabel.style.cursor = 'pointer';
aiModeContainer.appendChild(aiModeCheckbox);
aiModeContainer.appendChild(aiModeLabel);
const autoImgBtn = document.createElement('button');
autoImgBtn.id = 'bg-auto-img-btn';
autoImgBtn.className = 'bg-menu-btn';
autoImgBtn.textContent = 'Gerar Auto Fundo';
const input = document.createElement('input');
input.type = 'file';
input.accept = 'video/*';
input.style.display = 'none';
const inputImg = document.createElement('input');
inputImg.type = 'file';
inputImg.accept = 'image/*';
inputImg.style.display = 'none';
fileBtn.addEventListener('click', () => input.click());
imgBtn.addEventListener('click', () => inputImg.click());
input.addEventListener('change', (e) => {
const file = e.target.files[0];
if (!file) return;
const blobURL = URL.createObjectURL(file);
setVideoURL(blobURL);
});
inputImg.addEventListener('change', async (e) => {
const file = e.target.files[0];
if (!file) return;
try {
await saveImageToDB(file);
const blobURL = URL.createObjectURL(file);
setImageSource(blobURL);
localStorage.setItem(STORAGE_KEY, 'indexeddb_image');
localStorage.setItem(STORAGE_TYPE_KEY, 'image');
} catch (error) {
const reader = new FileReader();
reader.onload = function(event) {
const result = event.target.result;
setImageSource(result);
try {
localStorage.setItem(STORAGE_KEY, result);
localStorage.setItem(STORAGE_TYPE_KEY, 'image');
} catch (err) {
const fallbackBlob = URL.createObjectURL(file);
setImageSource(fallbackBlob);
localStorage.setItem(STORAGE_KEY, fallbackBlob);
localStorage.setItem(STORAGE_TYPE_KEY, 'image');
}
};
reader.readAsDataURL(file);
}
});
urlBtn.addEventListener('click', () => {
const current = localStorage.getItem(STORAGE_KEY) || '';
const url = prompt('Cole URL direta do vΓdeo (.mp4):', current);
if (!url) return;
setVideoURL(url);
});
let currentRequestId = 0;
autoImgBtn.addEventListener('click', () => {
const reqId = ++currentRequestId;
const originalText = autoImgBtn.textContent;
autoImgBtn.textContent = 'Carregando...';
let usedSeeds = JSON.parse(localStorage.getItem(SEEDS_KEY) || '[]');
let seed;
do {
seed = Math.floor(Math.random() * 999999999) + 1;
} while (usedSeeds.includes(seed));
usedSeeds.push(seed);
if (usedSeeds.length > 1000) usedSeeds.shift();
localStorage.setItem(SEEDS_KEY, JSON.stringify(usedSeeds));
const promptVal = promptInput.value.trim();
const isAiMode = aiModeCheckbox.checked;
let url;
if (isAiMode) {
const finalPrompt = promptVal || 'beautiful landscape, 16:9, high resolution, masterpiece';
url = `https://image.pollinations.ai/prompt/${encodeURIComponent(finalPrompt)}?width=1920&height=1080&nologo=true&seed=${seed}`;
} else {
if (promptVal) {
const formattedPrompt = promptVal.replace(/\s+/g, ',');
url = `https://loremflickr.com/1920/1080/${encodeURIComponent(formattedPrompt)}?lock=${seed}&cb=${Date.now()}`;
} else {
url = `https://picsum.photos/seed/${seed}/1920/1080`;
}
}
const tempImg = new Image();
tempImg.onload = () => {
if (reqId !== currentRequestId) return;
setImageSource(url);
localStorage.setItem(STORAGE_KEY, url);
localStorage.setItem(STORAGE_TYPE_KEY, 'image');
autoImgBtn.textContent = originalText;
};
tempImg.onerror = () => {
if (reqId !== currentRequestId) return;
autoImgBtn.textContent = 'Erro! Tentando de novo...';
setTimeout(() => {
if (reqId === currentRequestId) {
autoImgBtn.textContent = originalText;
autoImgBtn.click();
}
}, 1000);
};
tempImg.src = url;
});
menu.appendChild(fileBtn);
menu.appendChild(urlBtn);
menu.appendChild(imgBtn);
menu.appendChild(div1);
menu.appendChild(promptInput);
menu.appendChild(aiModeContainer);
menu.appendChild(autoImgBtn);
document.body.appendChild(toggleBtn);
document.body.appendChild(menu);
document.body.appendChild(input);
document.body.appendChild(inputImg);
}
function createMuralUI() {
const menu = document.getElementById('bg-main-menu');
const div2 = document.createElement('div');
div2.className = 'bg-menu-divider';
const saveMuralBtn = document.createElement('button');
saveMuralBtn.id = 'bg-save-mural-btn';
saveMuralBtn.className = 'bg-menu-btn';
saveMuralBtn.textContent = 'Salvar Imagem';
const muralBtn = document.createElement('button');
muralBtn.id = 'bg-mural-btn';
muralBtn.className = 'bg-menu-btn';
muralBtn.textContent = 'Mural de Imagens';
const muralPanel = document.createElement('div');
muralPanel.id = 'bg-mural-panel';
muralPanel.innerHTML = `
<div style="font-weight:bold;margin-bottom:5px;border-bottom:1px solid rgba(255,255,255,0.2);padding-bottom:8px;text-align:center;position:relative;">
Mural de Imagens Salvas
<span id="close-mural" style="position:absolute;right:0;top:0;cursor:pointer;color:#ff4444;padding:0 5px;font-weight:bold;">X</span>
</div>
<div class="mural-grid" id="mural-grid"></div>
`;
menu.appendChild(div2);
menu.appendChild(saveMuralBtn);
menu.appendChild(muralBtn);
document.body.appendChild(muralPanel);
function renderMural() {
const grid = document.getElementById('mural-grid');
grid.innerHTML = '';
let saved = JSON.parse(localStorage.getItem('chess_mural_images') || '[]');
if(saved.length === 0) {
grid.innerHTML = '<div style="grid-column:1/-1;text-align:center;color:#aaa;padding:20px 0;">Nenhuma imagem salva</div>';
return;
}
saved.forEach((item, index) => {
const div = document.createElement('div');
div.className = 'mural-item';
const isDB = (item.url === 'indexeddb_image');
const imgSrc = isDB ? '' : item.url;
div.innerHTML = `
<img src="${imgSrc}" title="Clique para aplicar como fundo">
<div class="mural-item-actions">
<a href="${isDB ? '#' : item.url}" target="_blank" title="${isDB ? 'Imagem Local (PC)' : 'Abrir imagem original para baixar'}">Fonte</a>
<button data-index="${index}" class="del-mural-btn" title="Remover do mural">Remover</button>
</div>
`;
grid.appendChild(div);
const imgEl = div.querySelector('img');
if (isDB) {
loadImageFromDB().then(file => {
if (file) {
const tempUrl = URL.createObjectURL(file);
imgEl.src = tempUrl;
div.querySelector('a').href = tempUrl;
}
});
}
imgEl.addEventListener('click', () => {
if (isDB) {
loadImageFromDB().then(file => {
if (file) {
setImageSource(URL.createObjectURL(file));
localStorage.setItem(STORAGE_KEY, 'indexeddb_image');
localStorage.setItem(STORAGE_TYPE_KEY, 'image');
}
});
} else {
setImageSource(item.url);
localStorage.setItem(STORAGE_KEY, item.url);
localStorage.setItem(STORAGE_TYPE_KEY, 'image');
}
});
});
document.querySelectorAll('.del-mural-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
const idx = e.target.getAttribute('data-index');
let savedList = JSON.parse(localStorage.getItem('chess_mural_images') || '[]');
savedList.splice(idx, 1);
localStorage.setItem('chess_mural_images', JSON.stringify(savedList));
renderMural();
});
});
}
muralBtn.addEventListener('click', () => {
renderMural();
muralPanel.classList.toggle('open');
const settingsPanel = document.getElementById('bg-settings-panel');
if(settingsPanel) settingsPanel.classList.remove('open');
});
document.getElementById('close-mural').addEventListener('click', () => {
muralPanel.classList.remove('open');
});
saveMuralBtn.addEventListener('click', () => {
const currentUrl = localStorage.getItem(STORAGE_KEY);
const currentType = localStorage.getItem(STORAGE_TYPE_KEY);
if (currentType === 'image' && currentUrl) {
let saved = JSON.parse(localStorage.getItem('chess_mural_images') || '[]');
if (!saved.some(i => i.url === currentUrl)) {
saved.push({ url: currentUrl, timestamp: Date.now() });
localStorage.setItem('chess_mural_images', JSON.stringify(saved));
const originalText = saveMuralBtn.textContent;
saveMuralBtn.textContent = 'Salvo no Mural!';
saveMuralBtn.style.color = '#4CAF50';
saveMuralBtn.style.borderColor = '#4CAF50';
if (muralPanel.classList.contains('open')) renderMural();
setTimeout(() => {
saveMuralBtn.textContent = originalText;
saveMuralBtn.style.color = 'white';
saveMuralBtn.style.borderColor = 'rgba(255,255,255,0.2)';
}, 2000);
} else {
const originalText = saveMuralBtn.textContent;
saveMuralBtn.textContent = 'JΓ‘ estΓ‘ salvo!';
setTimeout(() => saveMuralBtn.textContent = originalText, 2000);
}
} else {
const originalText = saveMuralBtn.textContent;
saveMuralBtn.textContent = 'Apenas Imagens!';
saveMuralBtn.style.color = 'red';
saveMuralBtn.style.borderColor = 'red';
setTimeout(() => {
saveMuralBtn.textContent = originalText;
saveMuralBtn.style.color = 'white';
saveMuralBtn.style.borderColor = 'rgba(255,255,255,0.2)';
}, 2000);
}
});
}
function createSettingsUI() {
const menu = document.getElementById('bg-main-menu');
const div3 = document.createElement('div');
div3.className = 'bg-menu-divider';
const btn = document.createElement('button');
btn.id = 'bg-settings-btn';
btn.className = 'bg-menu-btn';
btn.textContent = 'Ajustes';
const panel = document.createElement('div');
panel.id = 'bg-settings-panel';
panel.innerHTML = `
<div style="font-weight:bold;margin-bottom:5px;border-bottom:1px solid rgba(255,255,255,0.2);padding-bottom:8px;text-align:center;">Ajustes de Fundo</div>
<label title="Estica a imagem para preencher 100% da tela sem cortar e sem bordas pretas.">
Enquadrar Tela
<input type="checkbox" id="bg-setting-fit" ${localStorage.getItem('chess_bg_fit') === 'fill' ? 'checked' : ''}>
</label>
<label>
Brilho
<input type="range" id="bg-setting-brightness" min="0" max="200" value="${localStorage.getItem('chess_bg_brightness') || '100'}">
</label>
<label>
Contraste
<input type="range" id="bg-setting-contrast" min="0" max="200" value="${localStorage.getItem('chess_bg_contrast') || '100'}">
</label>
<label>
SaturaΓ§Γ£o
<input type="range" id="bg-setting-saturate" min="0" max="200" value="${localStorage.getItem('chess_bg_saturate') || '100'}">
</label>
<label>
Matiz
<input type="range" id="bg-setting-hue" min="0" max="360" value="${localStorage.getItem('chess_bg_hue') || '0'}">
</label>
<button id="bg-setting-reset">Restaurar PadrΓ΅es</button>
`;
menu.appendChild(div3);
menu.appendChild(btn);
document.body.appendChild(panel);
btn.addEventListener('click', () => {
panel.classList.toggle('open');
const muralPanel = document.getElementById('bg-mural-panel');
if (muralPanel) muralPanel.classList.remove('open');
});
const fitInput = document.getElementById('bg-setting-fit');
const brightInput = document.getElementById('bg-setting-brightness');
const contrastInput = document.getElementById('bg-setting-contrast');
const saturateInput = document.getElementById('bg-setting-saturate');
const hueInput = document.getElementById('bg-setting-hue');
const resetBtn = document.getElementById('bg-setting-reset');
function applyFilters() {
const root = document.documentElement;
root.style.setProperty('--bg-fit', localStorage.getItem('chess_bg_fit') || 'cover');
root.style.setProperty('--bg-brightness', (localStorage.getItem('chess_bg_brightness') || '100') + '%');
root.style.setProperty('--bg-contrast', (localStorage.getItem('chess_bg_contrast') || '100') + '%');
root.style.setProperty('--bg-saturate', (localStorage.getItem('chess_bg_saturate') || '100') + '%');
root.style.setProperty('--bg-hue', (localStorage.getItem('chess_bg_hue') || '0') + 'deg');
}
fitInput.addEventListener('change', (e) => {
localStorage.setItem('chess_bg_fit', e.target.checked ? 'fill' : 'cover');
applyFilters();
});
const updateFilters = () => {
localStorage.setItem('chess_bg_brightness', brightInput.value);
localStorage.setItem('chess_bg_contrast', contrastInput.value);
localStorage.setItem('chess_bg_saturate', saturateInput.value);
localStorage.setItem('chess_bg_hue', hueInput.value);
applyFilters();
};
brightInput.addEventListener('input', updateFilters);
contrastInput.addEventListener('input', updateFilters);
saturateInput.addEventListener('input', updateFilters);
hueInput.addEventListener('input', updateFilters);
resetBtn.addEventListener('click', () => {
fitInput.checked = false;
brightInput.value = 100;
contrastInput.value = 100;
saturateInput.value = 100;
hueInput.value = 0;
localStorage.setItem('chess_bg_fit', 'cover');
updateFilters();
});
applyFilters();
}
function restoreSavedVideo() {
const saved = localStorage.getItem(STORAGE_KEY);
const type = localStorage.getItem(STORAGE_TYPE_KEY) || 'video';
if (saved) {
if (type === 'image') {
if (saved === 'indexeddb_image') {
loadImageFromDB().then(file => {
if (file) {
setImageSource(URL.createObjectURL(file));
}
}).catch(e => console.error(e));
} else {
if (saved.startsWith('blob:')) return;
setImageSource(saved);
}
} else {
setVideoURL(saved);
}
}
}
function setupRevealHotkey() {
let isIPressed = false;
let revealInterval = null;
const forceShow = () => {
const els = document.querySelectorAll('.board-layout-sidebar, #board-layout-sidebar, .play-controller-sidebar, .computer-sidebar-component, .analysis-sidebar-component, .live-game-sidebar-component, .sidebar-component, [data-test-id="sidebar"], .layout-right, .game-overview, .vertical-move-list, [data-cy="analysis-panel"], .analysis-tools');
els.forEach(el => {
let parent = el.parentElement;
while (parent && parent.tagName !== 'BODY' && parent.tagName !== 'HTML') {
if (parent.dataset.forcedVisibleByGemini !== 'true') {
const style = window.getComputedStyle(parent);
if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0' || style.transform !== 'none') {
parent.style.setProperty('display', 'block', 'important');
parent.style.setProperty('visibility', 'visible', 'important');
parent.style.setProperty('opacity', '1', 'important');
parent.style.setProperty('transform', 'none', 'important');
parent.dataset.forcedVisibleByGemini = 'true';
}
}
parent = parent.parentElement;
}
el.style.setProperty('display', 'flex', 'important');
el.style.setProperty('visibility', 'visible', 'important');
el.style.setProperty('opacity', '1', 'important');
el.style.setProperty('pointer-events', 'auto', 'important');
el.style.setProperty('z-index', '2147483647', 'important');
el.style.setProperty('position', 'fixed', 'important');
el.style.setProperty('right', '0', 'important');
el.style.setProperty('top', '0', 'important');
el.style.setProperty('bottom', '0', 'important');
el.style.setProperty('height', '100vh', 'important');
el.style.setProperty('width', 'clamp(250px, 30vw, 350px)', 'important');
el.style.setProperty('min-width', '300px', 'important');
el.style.setProperty('max-width', '400px', 'important');
el.style.setProperty('transform', 'none', 'important');
el.style.setProperty('clip', 'auto', 'important');
el.style.setProperty('clip-path', 'none', 'important');
el.style.setProperty('margin', '0', 'important');
el.style.setProperty('padding', '0', 'important');
el.style.setProperty('background', 'rgba(30, 30, 30, 0.95)', 'important');
});
};
const forceHide = () => {
const els = document.querySelectorAll('.board-layout-sidebar, #board-layout-sidebar, .play-controller-sidebar, .computer-sidebar-component, .analysis-sidebar-component, .live-game-sidebar-component, .sidebar-component, [data-test-id="sidebar"], .layout-right, .game-overview, .vertical-move-list, [data-cy="analysis-panel"], .analysis-tools');
els.forEach(el => {
let parent = el.parentElement;
while (parent && parent.tagName !== 'BODY' && parent.tagName !== 'HTML') {
if (parent.dataset.forcedVisibleByGemini === 'true') {
parent.style.removeProperty('display');
parent.style.removeProperty('visibility');
parent.style.removeProperty('opacity');
parent.style.removeProperty('transform');
delete parent.dataset.forcedVisibleByGemini;
}
parent = parent.parentElement;
}
el.style.removeProperty('display');
el.style.removeProperty('visibility');
el.style.removeProperty('opacity');
el.style.removeProperty('pointer-events');
el.style.removeProperty('z-index');
el.style.removeProperty('position');
el.style.removeProperty('right');
el.style.removeProperty('top');
el.style.removeProperty('bottom');
el.style.removeProperty('height');
el.style.removeProperty('width');
el.style.removeProperty('min-width');
el.style.removeProperty('max-width');
el.style.removeProperty('transform');
el.style.removeProperty('clip');
el.style.removeProperty('clip-path');
el.style.removeProperty('margin');
el.style.removeProperty('padding');
el.style.removeProperty('background');
});
};
document.addEventListener('keydown', (e) => {
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.isContentEditable) {
return;
}
if ((e.key === 'i' || e.key === 'I') && !isIPressed) {
isIPressed = true;
document.body.classList.add('reveal-chess-ui');
forceShow();
revealInterval = setInterval(forceShow, 50);
}
});
document.addEventListener('keyup', (e) => {
if (e.key === 'i' || e.key === 'I') {
isIPressed = false;
document.body.classList.remove('reveal-chess-ui');
if (revealInterval) {
clearInterval(revealInterval);
revealInterval = null;
}
forceHide();
}
});
}
function init() {
createVideoElement();
createImageElement();
createUI();
createMuralUI();
createSettingsUI();
restoreSavedVideo();
setupRevealHotkey();
}
if (document.readyState === 'loading') {
window.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();