您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Automaticly color theme changer
// ==UserScript== // @name Web3 OKX Color Theme Addon // @namespace http://tampermonkey.net/ // @version 2 // @description Automaticly color theme changer // @author mamiis // @match https://web3.okx.com/* // @grant none // @license MIT // ==/UserScript== (function(){ 'use strict'; let UP_COLOR = {r:37, g:167, b:80}; let DOWN_COLOR = {r:202,g:63, b:100}; // Chart filters artık UP_COLOR ve DOWN_COLOR'dan bağımsız let CHART_FILTERS = { green: { hue: 210, saturation: 1.6, brightness: 1.05 }, red: { hue: 280, saturation: 1.3, brightness: 1.1 } }; let activeModal = null; let currentColorType = null; function loadUserSettings() { try { const saved = localStorage.getItem('okx_color_settings'); if (saved) { const settings = JSON.parse(saved); if (settings.upColor) UP_COLOR = settings.upColor; if (settings.downColor) DOWN_COLOR = settings.downColor; if (settings.filters) CHART_FILTERS = settings.filters; } } catch (e) { console.log('Settings not loaded, using defaults'); } } function saveUserSettings() { try { const settings = { upColor: UP_COLOR, downColor: DOWN_COLOR, filters: CHART_FILTERS }; localStorage.setItem('okx_color_settings', JSON.stringify(settings)); } catch (e) { console.log('Settings not saved'); } } function applySettings() { kickAll(); applyChartColorFilters(); } function refreshPage() { window.location.reload(); } function toggleThemeForRefresh() { const themeButtons = document.querySelectorAll('.nav-r-theme-item'); if (themeButtons.length >= 3) { const currentTheme = document.querySelector('.nav-r-theme-item.nav-r-th-it-sel'); if (currentTheme) { const lightTheme = themeButtons[1]; if (lightTheme && !lightTheme.classList.contains('nav-r-th-it-sel')) { lightTheme.click(); setTimeout(() => { currentTheme.click(); setTimeout(() => { applySettings(); setTimeout(refreshPage, 100); }, 100); }, 100); } else { const darkTheme = themeButtons[2]; if (darkTheme && !darkTheme.classList.contains('nav-r-th-it-sel')) { darkTheme.click(); setTimeout(() => { currentTheme.click(); setTimeout(() => { applySettings(); setTimeout(refreshPage, 100); }, 100); }, 100); } else { applySettings(); setTimeout(refreshPage, 100); } } } else { applySettings(); setTimeout(refreshPage, 100); } } else { applySettings(); setTimeout(refreshPage, 100); } } /* ---------- IMPROVED COLOR PICKER MENU ---------- */ function addColorPickerToMenu() { const themeSection = document.querySelector('.nav-r-pan-item:has(.nav-r-item-name)'); if (!themeSection || !themeSection.querySelector('.nav-r-theme-box')) { setTimeout(addColorPickerToMenu, 1000); return; } if (document.querySelector('.nav-r-color-picker-item')) { return; } const colorPickerHTML = ` <div class="nav-r-pan-item nav-r-color-picker-item" style="margin: 8px 0;"> <span class="nav-r-item-name">Chart Colors</span> <div class="nav-r-theme-box" style="display: flex; align-items: center; gap: 4px; margin: 0 -2px;"> <button type="button" class="nav-r-theme-item nav-r-color-item" data-color="up" title="Up Color"> <div class="color-swatch" style="width: 100%; height: 100%; background-color: rgb(${UP_COLOR.r}, ${UP_COLOR.g}, ${UP_COLOR.b})"></div> </button> <button type="button" class="nav-r-theme-item nav-r-color-item" data-color="down" title="Down Color"> <div class="color-swatch" style="width: 100%; height: 100%; background-color: rgb(${DOWN_COLOR.r}, ${DOWN_COLOR.g}, ${DOWN_COLOR.b})"></div> </button> <button type="button" class="nav-r-theme-item nav-r-color-item" data-color="reset" title="Reset to Default Colors"> <i class="icon okx-header-footer-reset"></i> </button> <button type="button" class="nav-r-theme-item nav-r-apply-item" data-action="apply" title="Apply and Refresh"> <i class="icon okx-header-footer-check"></i> </button> </div> </div> `; themeSection.insertAdjacentHTML('afterend', colorPickerHTML); addColorPickerStyles(); addColorPickerEvents(); } function addColorPickerStyles() { const style = document.createElement('style'); style.textContent = ` .nav-r-color-picker-item { min-height: 36px !important; padding: 2px 0 !important; } .nav-r-color-picker-item .nav-r-item-name { margin-bottom: 2px !important; display: block; } .nav-r-color-picker-item .nav-r-theme-box { display: flex !important; align-items: center !important; gap: 4px !important; margin: 0 -2px !important; margin-top: 2px !important; } .nav-r-color-picker-item .nav-r-theme-item { position: relative; width: 30px !important; height: 30px !important; border-radius: 6px; border: 2px solid var(--border-color, #2a2a2a); background: transparent; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); padding: 0 !important; margin: 0 !important; overflow: hidden; flex-shrink: 0; box-sizing: border-box !important; } .nav-r-color-picker-item .nav-r-theme-item:hover { border-color: #cccccc; transform: translateY(-2px); box-shadow: 0 4px 12px rgba(204, 204, 204, 0.3); } .nav-r-color-picker-item .color-swatch { width: 100% !important; height: 100% !important; border-radius: 4px; border: 1px solid rgba(255,255,255,0.3); transition: all 0.3s ease; display: block !important; box-sizing: border-box !important; margin: 0 !important; padding: 0 !important; min-width: 100% !important; min-height: 100% !important; } .nav-r-color-picker-item .nav-r-theme-item:hover .color-swatch { transform: scale(1.01); } .nav-r-color-picker-item .nav-r-theme-item i { font-size: 14px; color: var(--text-color, #fff); transition: all 0.3s ease; display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; } .nav-r-color-picker-item .nav-r-theme-item:hover i { color: #cccccc; } .nav-r-apply-item { background: linear-gradient(135deg, #666666, #888888) !important; border: none !important; } .nav-r-apply-item:hover { background: linear-gradient(135deg, #888888, #aaaaaa) !important; transform: translateY(-2px) scale(1.05); } /* Improved Color Picker Modal */ .color-picker-modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.8); display: flex; align-items: center; justify-content: center; z-index: 10000; opacity: 0; animation: modalFadeIn 0.3s ease forwards; } @keyframes modalFadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes modalFadeOut { from { opacity: 1; } to { opacity: 0; } } .color-picker-content { background: #1a1a1a; border-radius: 16px; padding: 20px; width: 350px; max-width: 90vw; border: 1px solid #333; box-shadow: 0 20px 40px rgba(0,0,0,0.5); transform: scale(0.9); animation: contentSlideIn 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards; } @keyframes contentSlideIn { from { transform: scale(0.9); opacity: 0; } to { transform: scale(1); opacity: 1; } } @keyframes contentSlideOut { from { transform: scale(1); opacity: 1; } to { transform: scale(0.9); opacity: 0; } } .color-picker-title { color: white; margin-bottom: 12px; font-size: 16px; text-align: center; font-weight: 600; } .color-type-switcher { display: flex; gap: 6px; margin-bottom: 12px; justify-content: center; } .color-type-btn { padding: 6px 10px; border: 1px solid #333; background: #2a2a2a; color: white; border-radius: 6px; cursor: pointer; transition: all 0.3s ease; font-size: 11px; flex: 1; max-width: 100px; } .color-type-btn:hover { background: #3a3a3a; } .color-type-btn.active { background: #444; border-color: #666; } .color-categories-container { max-height: 350px; overflow-y: auto; padding-right: 3px; margin-bottom: 12px; } .color-category { margin-bottom: 12px; } .color-category-title { color: white; font-size: 11px; font-weight: 600; margin-bottom: 5px; padding-bottom: 2px; border-bottom: 1px solid #333; } .color-category-grid { display: flex; flex-wrap: wrap; gap: 3px; margin-bottom: 6px; } .color-option { width: 24px; height: 24px; border-radius: 3px; border: 2px solid transparent; cursor: pointer; transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); position: relative; flex-shrink: 0; } .color-option:hover { transform: scale(1.15); border-color: #cccccc; box-shadow: 0 4px 8px rgba(204, 204, 204, 0.3); } .color-option.selected { border-color: #cccccc; border-width: 2px; box-shadow: 0 0 0 2px rgba(204, 204, 204, 0.3); } .color-picker-actions { display: flex; gap: 8px; margin-top: 10px; } .color-action-btn { flex: 1; padding: 8px 12px; border: none; border-radius: 6px; cursor: pointer; font-size: 12px; font-weight: 600; transition: all 0.3s ease; text-align: center; } .color-apply-btn { background: linear-gradient(135deg, #666666, #888888); color: white; } .color-apply-btn:hover { background: linear-gradient(135deg, #888888, #aaaaaa); transform: translateY(-1px); } .color-default-btn { background: linear-gradient(135deg, #444444, #666666); color: white; } .color-default-btn:hover { background: linear-gradient(135deg, #666666, #888888); transform: translateY(-1px); } /* Scrollbar styling */ .color-categories-container::-webkit-scrollbar { width: 4px; } .color-categories-container::-webkit-scrollbar-track { background: #2a2a2a; border-radius: 2px; } .color-categories-container::-webkit-scrollbar-thumb { background: #555; border-radius: 2px; } .color-categories-container::-webkit-scrollbar-thumb:hover { background: #777; } `; document.head.appendChild(style); } function addColorPickerEvents() { document.addEventListener('click', function(e) { if (e.target.closest('.nav-r-color-item')) { const btn = e.target.closest('.nav-r-color-item'); e.stopPropagation(); const colorType = btn.getAttribute('data-color'); if (colorType === 'reset') { resetToDefaultColors(); } else { closeActiveModal(); setTimeout(() => { showColorPicker(colorType); }, 50); } } if (e.target.closest('.nav-r-apply-item')) { const btn = e.target.closest('.nav-r-apply-item'); toggleThemeForRefresh(); showNotification('Colors applied successfully!'); } }); } function showNotification(message) { const oldNotifications = document.querySelectorAll('.okx-color-notification'); oldNotifications.forEach(notif => notif.remove()); const notification = document.createElement('div'); notification.className = 'okx-color-notification'; notification.style.cssText = ` position: fixed; top: 20px; right: 24px; background: #4CAF50; color: white; padding: 10px 20px; border-radius: 4px; z-index: 10001; font-size: 14px; animation: slideIn 0.3s ease; `; notification.textContent = message; document.body.appendChild(notification); setTimeout(() => { notification.remove(); }, 3000); } function closeActiveModal() { if (activeModal) { const escapeHandler = activeModal._escapeHandler; if (escapeHandler) { document.removeEventListener('keydown', escapeHandler); } activeModal.style.animation = 'modalFadeOut 0.2s ease forwards'; const content = activeModal.querySelector('.color-picker-content'); if (content) { content.style.animation = 'contentSlideOut 0.2s ease forwards'; } setTimeout(() => { if (activeModal && activeModal.parentNode) { activeModal.parentNode.removeChild(activeModal); } activeModal = null; currentColorType = null; }, 200); } } function showColorPicker(colorType) { if (activeModal) { closeActiveModal(); setTimeout(() => { createColorPickerModal(colorType); }, 250); } else { createColorPickerModal(colorType); } } function createColorPickerModal(colorType) { currentColorType = colorType; const colorCategories = [ { name: "Red", colors: ["#8B0000","#A52A2A","#B22222","#DC143C","#FF0000","#FF4D4D","#FF6666","#FF8080","#FF9999"] }, { name: "Orange", colors: ["#FF4500","#FF5500","#FF6600","#FF7518","#FF7F50","#FF8C42","#FFA500","#FFB347","#FFC966"] }, { name: "Yellow", colors: ["#FFD700","#FFE135","#FFE600","#FFEA00","#FFF200","#FFF700","#FFFC00","#FFFF33","#FFFF66"] }, { name: "Green", colors: ["#006400","#008000","#228B22","#2E8B57","#3CB371","#66CDAA","#7FFF00","#90EE90","#98FB98"] }, { name: "Blue", colors: ["#00008B","#0000CD","#0000FF","#1E90FF","#4169E1","#4682B4","#5F9EA0","#6495ED","#87CEFA"] }, { name: "Purple", colors: ["#4B0082","#6A0DAD","#7B68EE","#8A2BE2","#9400D3","#9932CC","#BA55D3","#DA70D6","#EE82EE"] }, { name: "Gray", colors: ["#2F4F4F","#4F4F4F","#696969","#808080","#A9A9A9","#B0B0B0","#C0C0C0","#D3D3D3","#E0E0E0"] }, { name: "Brown", colors: ["#4B3621","#5C4033","#6B4226","#8B4513","#A0522D","#A0522D","#CD853F","#D2691E","#F4A460"] }, { name: "Light Gray", colors: ["#DCDCDC","#E0E0E0","#E5E5E5","#EBEBEB","#F0F0F0","#F5F5F5","#FAFAFA","#FCFCFC","#FFFFFF"] } ]; const currentColor = colorType === 'up' ? UP_COLOR : DOWN_COLOR; activeModal = document.createElement('div'); activeModal.className = 'color-picker-modal'; activeModal.innerHTML = ` <div class="color-picker-content"> <div class="color-picker-title"> Select ${colorType === 'up' ? 'Up Color' : 'Down Color'} </div> <div class="color-type-switcher"> <button class="color-type-btn ${colorType === 'up' ? 'active' : ''}" data-type="up">Up Color</button> <button class="color-type-btn ${colorType === 'down' ? 'active' : ''}" data-type="down">Down Color</button> </div> <div class="color-categories-container"> ${colorCategories.map(category => ` <div class="color-category"> <div class="color-category-title">${category.name}</div> <div class="color-category-grid"> ${category.colors.map((color, index) => { const isSelected = color === rgbToHex(currentColor.r, currentColor.g, currentColor.b); return ` <div class="color-option ${isSelected ? 'selected' : ''}" style="background-color: ${color}" data-color="${color}" title="${color}"> </div> `; }).join('')} </div> </div> `).join('')} </div> <div class="color-picker-actions"> <button class="color-action-btn color-default-btn" data-action="default">Default Colors</button> <button class="color-action-btn color-apply-btn" data-action="apply">Apply Colors</button> </div> </div> `; document.body.appendChild(activeModal); // Color type switcher events activeModal.querySelectorAll('.color-type-btn').forEach(btn => { btn.addEventListener('click', function(e) { e.stopPropagation(); const newType = this.getAttribute('data-type'); if (newType !== currentColorType) { closeActiveModal(); setTimeout(() => { showColorPicker(newType); }, 50); } }); }); // Selection events - BU KISIM DEĞİŞTİ: Artık CHART_FILTERS güncellenmiyor activeModal.querySelectorAll('.color-option').forEach((option) => { option.addEventListener('click', function(e) { e.stopPropagation(); const selectedHex = this.getAttribute('data-color'); const parsedColor = parseHexColor(selectedHex); // Apply the color directly without affecting chart filters if (currentColorType === 'up') { UP_COLOR = parsedColor; } else { DOWN_COLOR = parsedColor; } // Update selection visually activeModal.querySelectorAll('.color-option').forEach(opt => { opt.classList.remove('selected'); }); this.classList.add('selected'); // Immediately update swatches and apply settings updateColorSwatches(); applySettings(); saveUserSettings(); showNotification(`${currentColorType === 'up' ? 'Up' : 'Down'} color updated to ${selectedHex}`); }); }); // Action buttons activeModal.querySelectorAll('.color-action-btn').forEach(btn => { btn.addEventListener('click', function(e) { e.stopPropagation(); const action = this.getAttribute('data-action'); if (action === 'apply') { applySettings(); updateColorSwatches(); saveUserSettings(); showNotification('Applying colors and refreshing page...'); closeActiveModal(); setTimeout(() => { toggleThemeForRefresh(); }, 500); } else if (action === 'default') { resetToDefaultColors(); closeActiveModal(); } }); }); // Close on background click activeModal.addEventListener('click', function(e) { if (e.target === activeModal) { closeActiveModal(); } }); // Close on Escape key const escapeHandler = function(e) { if (e.key === 'Escape') { closeActiveModal(); } }; document.addEventListener('keydown', escapeHandler); activeModal._escapeHandler = escapeHandler; } function rgbToHex(r, g, b) { return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase(); } function resetToDefaultColors() { UP_COLOR = { r: 37, g: 167, b: 80 }; DOWN_COLOR = { r: 202, g: 63, b: 100 }; // Chart filters artık dinamik olduğu için sabit değerlere gerek yok // CHART_FILTERS değişkenini kaldırabilirsiniz veya boş bırakabilirsiniz saveUserSettings(); applySettings(); updateColorSwatches(); showNotification('Default colors restored!'); setTimeout(() => { toggleThemeForRefresh(); }, 1000); } function updateColorSwatches() { const upSwatch = document.querySelector('.nav-r-color-item[data-color="up"] .color-swatch'); const downSwatch = document.querySelector('.nav-r-color-item[data-color="down"] .color-swatch'); if (upSwatch) { upSwatch.style.backgroundColor = `rgb(${UP_COLOR.r}, ${UP_COLOR.g}, ${UP_COLOR.b})`; } if (downSwatch) { downSwatch.style.backgroundColor = `rgb(${DOWN_COLOR.r}, ${DOWN_COLOR.g}, ${DOWN_COLOR.b})`; } } /* ---------- EXISTING FUNCTIONS (Fixed) ---------- */ const hexRegex = /#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})\b/g; const rgbRegex = /rgba?\([^\)]+\)/gi; const hslRegex = /hsla?\([^\)]+\)/gi; const _tmp = document.createElement('div'); _tmp.style.position = 'absolute'; _tmp.style.left = '-9999px'; _tmp.style.width = _tmp.style.height = '1px'; document.documentElement.appendChild(_tmp); function clamp(v, a=0, b=255){ return Math.max(a, Math.min(b, v)); } function parseHexColor(str){ let s = str.replace('#',''); if(s.length === 3) s = s.split('').map(ch => ch+ch).join(''); else if(s.length === 4) s = s.split('').map(ch => ch+ch).join(''); let r=0,g=0,b=0,a=1; if(s.length === 6){ r = parseInt(s.substr(0,2),16); g = parseInt(s.substr(2,2),16); b = parseInt(s.substr(4,2),16); } else if(s.length === 8){ r = parseInt(s.substr(0,2),16); g = parseInt(s.substr(2,2),16); b = parseInt(s.substr(4,2),16); a = parseInt(s.substr(6,2),16) / 255; } return {r,g,b,a}; } function parseRgbString(str){ const nums = str.match(/[\d\.%]+/g); if(!nums) return null; let [r,g,b,a] = [0,0,0,1]; if(nums.length >= 3){ const parseComponent = (v) => v.endsWith('%') ? Math.round(parseFloat(v) * 2.55) : Math.round(parseFloat(v)); r = parseComponent(nums[0]); g = parseComponent(nums[1]); b = parseComponent(nums[2]); } if(nums.length >= 4) a = parseFloat(nums[3]); return {r,g,b,a}; } function parseHslString(str){ const parts = str.match(/[\d\.%]+/g); if(!parts) return null; let h = parseFloat(parts[0]), s = parseFloat(parts[1]) / 100, l = parseFloat(parts[2]) / 100; let a = parts.length >= 4 ? parseFloat(parts[3]) : 1; const rgb = hslToRgb(h, s, l); return {r: Math.round(rgb.r), g: Math.round(rgb.g), b: Math.round(rgb.b), a}; } function hslToRgb(h, s, l){ h = ((h % 360) + 360) % 360; const c = (1 - Math.abs(2*l - 1)) * s; const x = c * (1 - Math.abs((h / 60) % 2 - 1)); const m = l - c/2; let r=0,g=0,b=0; if(h < 60) { r=c; g=x; b=0; } else if(h < 120) { r=x; g=c; b=0; } else if(h < 180) { r=0; g=c; b=x; } else if(h < 240) { r=0; g=x; b=c; } else if(h < 300) { r=x; g=0; b=c; } else { r=c; g=0; b=x; } return { r: (r+m)*255, g: (g+m)*255, b: (b+m)*255 }; } function rgbToHsl(r,g,b){ r/=255; g/=255; b/=255; const max = Math.max(r,g,b), min = Math.min(r,g,b); let h=0,s=0,l=(max+min)/2; if(max !== min){ const d = max - min; s = l > 0.5 ? d / (2 - max - min) : d / (max + min); switch(max){ case r: h = ((g - b) / d + (g < b ? 6 : 0)) * 60; break; case g: h = ((b - r) / d + 2) * 60; break; case b: h = ((r - g) / d + 4) * 60; break; } } return {h, s, l}; } function parseColorString(str){ if(!str) return null; str = str.trim(); if(str.toLowerCase() === 'transparent' || str === 'none') return {r:0,g:0,b:0,a:0}; try{ if(str[0] === '#') return parseHexColor(str); if(str.toLowerCase().startsWith('rgb')) return parseRgbString(str); if(str.toLowerCase().startsWith('hsl')) return parseHslString(str); _tmp.style.color = ''; _tmp.style.color = str; const cs = getComputedStyle(_tmp).color; return parseRgbString(cs); }catch(e){ return null; } } function rgbaToCss(o){ const a = (typeof o.a === 'number') ? o.a : 1; return `rgba(${Math.round(o.r)}, ${Math.round(o.g)}, ${Math.round(o.b)}, ${+a.toFixed(3)})`; } // BU FONKSİYON DEĞİŞTİ: Artık UP_COLOR ve DOWN_COLOR doğrudan kullanılıyor function shouldConvertByHue(rgba){ if(!rgba || rgba.a === 0) return null; // Özel div için istisna - bu renk değişmesin const {h,s,l} = rgbToHsl(rgba.r, rgba.g, rgba.b); if(rgba.r === 230 && rgba.g === 181 && rgba.b === 117) return null; if(s > 0.08 && h >= 70 && h <= 170) return 'greenish'; if(s > 0.08 && (h <= 25 || h >= 335)) return 'reddish'; return null; } // BU FONKSİYON DEĞİŞTİ: Artık CHART_FILTERS yerine UP_COLOR ve DOWN_COLOR kullanılıyor function convertBasedOnDetection(rgba){ const det = shouldConvertByHue(rgba); if(!det) return rgba; if(det === 'greenish'){ return { ...UP_COLOR, a: rgba.a }; } else if(det === 'reddish'){ return { ...DOWN_COLOR, a: rgba.a }; } return rgba; } function replaceColorTokensInText(text){ if(!text || typeof text !== 'string') return text; let out = text; out = out.replace(hexRegex, (m) => { const p = parseColorString(m); if(!p) return m; const conv = convertBasedOnDetection(p); if(conv && (conv.r !== p.r || conv.g !== p.g || conv.b !== p.b || conv.a !== p.a)) return rgbaToCss(conv); return m; }).replace(rgbRegex, (m) => { const p = parseColorString(m); if(!p) return m; const conv = convertBasedOnDetection(p); if(conv && (conv.r !== p.r || conv.g !== p.g || conv.b !== p.b || conv.a !== p.a)) return rgbaToCss(conv); return m; }).replace(hslRegex, (m) => { const p = parseColorString(m); if(!p) return m; const conv = convertBasedOnDetection(p); if(conv && (conv.r !== p.r || conv.g !== p.g || conv.b !== p.b || conv.a !== p.a)) return rgbaToCss(conv); return m; }); return out; } function processCssRuleList(rules){ for(let i=0;i<rules.length;i++){ const rule = rules[i]; try{ if(rule.type === CSSRule.STYLE_RULE){ const style = rule.style; for(let j=0;j<style.length;j++){ const prop = style[j], val = style.getPropertyValue(prop); const newVal = replaceColorTokensInText(val); if(newVal !== val) try{ style.setProperty(prop, newVal, style.getPropertyPriority(prop)); }catch(e){} } } else if(rule.cssRules) processCssRuleList(rule.cssRules); }catch(e){ continue; } } } function processStyleSheets(){ for(const sheet of document.styleSheets){ try{ if(sheet.cssRules) processCssRuleList(sheet.cssRules); }catch(e){} } } function processStyleTags(){ document.querySelectorAll('style').forEach(tag=>{ try{ const old = tag.textContent, neu = replaceColorTokensInText(old); if(neu !== old) tag.textContent = neu; }catch(e){} }); } function processInlineAndSvg(root=document){ root.querySelectorAll('[style]').forEach(el=>{ try{ const old = el.getAttribute('style'), neu = replaceColorTokensInText(old); if(neu !== old) el.setAttribute('style', neu); }catch(e){} }); root.querySelectorAll('[fill],[stroke]').forEach(el=>{ ['fill','stroke'].forEach(attr=>{ try{ if(el.hasAttribute(attr)){ const old = el.getAttribute(attr), neu = replaceColorTokensInText(old); if(neu !== old) el.setAttribute(attr, neu); } }catch(e){} }); }); } const computedCheckProps = ['background-color','color','border-top-color','border-right-color','border-bottom-color','border-left-color','outline-color','caret-color','column-rule-color']; function isTransparentValue(v){ if(!v) return true; v = v.trim(); return v === 'transparent' || v === 'rgba(0, 0, 0, 0)' || v === 'initial' || v === 'none'; } function processComputedStylesBatch(elements, start=0){ const batch = 250, end = Math.min(elements.length, start + batch); for(let i=start;i<end;i++){ const el = elements[i]; try{ const cs = getComputedStyle(el); computedCheckProps.forEach(prop=>{ try{ const val = cs.getPropertyValue(prop); if(!val || isTransparentValue(val)) return; const parsed = parseColorString(val); if(!parsed) return; const conv = convertBasedOnDetection(parsed); if(conv && (conv.r !== parsed.r || conv.g !== parsed.g || conv.b !== parsed.b || conv.a !== parsed.a)) el.style.setProperty(prop, rgbaToCss(conv), 'important'); }catch(e){} }); try{ const bs = cs.getPropertyValue('box-shadow'); if(bs && bs !== 'none' && /#|rgba?\(|hsla?\(/i.test(bs)){ const newBs = replaceColorTokensInText(bs); if(newBs !== bs) el.style.setProperty('box-shadow', newBs, 'important'); } }catch(e){} try{ const bg = cs.getPropertyValue('background-image'); if(bg && bg !== 'none' && /#|rgba?\(|hsla?\(/i.test(bg)){ const newBg = replaceColorTokensInText(bg); if(newBg !== bg) el.style.setProperty('background-image', newBg, 'important'); } }catch(e){} }catch(e){} } if(end < elements.length) setTimeout(()=> processComputedStylesBatch(elements, end), 20); } function processAllComputedStylesRoot(root=document){ const elements = Array.from(root.querySelectorAll('*')); processComputedStylesBatch(elements, 0); } function patchCanvasContext(ctx){ try{ if(!ctx || ctx.__colorPatched) return; ctx.__colorPatched = true; const convertMaybe = (v) => { if(typeof v !== 'string') return v; const parsed = parseColorString(v); if(!parsed) return v; const conv = convertBasedOnDetection(parsed); if(conv && (conv.r !== parsed.r || conv.g !== parsed.g || conv.b !== parsed.b || conv.a !== parsed.a)) return rgbaToCss(conv); return v; }; let _fill = ctx.fillStyle, _stroke = ctx.strokeStyle, _shadow = ctx.shadowColor; Object.defineProperty(ctx, 'fillStyle', { get(){ return _fill; }, set(v){ _fill = convertMaybe(v); } }); Object.defineProperty(ctx, 'strokeStyle', { get(){ return _stroke; }, set(v){ _stroke = convertMaybe(v); } }); Object.defineProperty(ctx, 'shadowColor', { get(){ return _shadow; }, set(v){ _shadow = convertMaybe(v); } }); }catch(e){} } const origGetCtx = HTMLCanvasElement.prototype.getContext; HTMLCanvasElement.prototype.getContext = function(type, ...args){ const ctx = origGetCtx.apply(this, [type, ...args]); try{ if(type === '2d' && ctx && (!this.closest || !this.closest('.tv-lightweight-charts'))) patchCanvasContext(ctx); }catch(e){} return ctx; }; // Yeni fonksiyon: Chart canvas'ını direkt override et function overrideChartCanvas() { setTimeout(() => { const canvases = document.querySelectorAll('.tv-lightweight-charts canvas'); canvases.forEach(canvas => { const ctx = canvas.getContext('2d'); if (ctx && !ctx.__colorOverridden) { ctx.__colorOverridden = true; const origFill = ctx.fill; const origStroke = ctx.stroke; const origFillRect = ctx.fillRect; const origStrokeRect = ctx.strokeRect; // Fill override ctx.fill = function() { if (this.fillStyle) { if (this.fillStyle === '#26a69a' || this.fillStyle === '#25a750' || this.fillStyle === 'rgb(38, 166, 154)' || this.fillStyle === 'rgb(37, 167, 80)') { this.fillStyle = rgbaToCss(UP_COLOR); } else if (this.fillStyle === '#ef5350' || this.fillStyle === '#ca3f64' || this.fillStyle === 'rgb(239, 83, 80)' || this.fillStyle === 'rgb(202, 63, 100)') { this.fillStyle = rgbaToCss(DOWN_COLOR); } } return origFill.apply(this, arguments); }; // Stroke override ctx.stroke = function() { if (this.strokeStyle) { if (this.strokeStyle === '#26a69a' || this.strokeStyle === '#25a750' || this.strokeStyle === 'rgb(38, 166, 154)' || this.strokeStyle === 'rgb(37, 167, 80)') { this.strokeStyle = rgbaToCss(UP_COLOR); } else if (this.strokeStyle === '#ef5350' || this.strokeStyle === '#ca3f64' || this.strokeStyle === 'rgb(239, 83, 80)' || this.strokeStyle === 'rgb(202, 63, 100)') { this.strokeStyle = rgbaToCss(DOWN_COLOR); } } return origStroke.apply(this, arguments); }; // FillRect override ctx.fillRect = function(x, y, w, h) { if (this.fillStyle) { if (this.fillStyle === '#26a69a' || this.fillStyle === '#25a750' || this.fillStyle === 'rgb(38, 166, 154)' || this.fillStyle === 'rgb(37, 167, 80)') { this.fillStyle = rgbaToCss(UP_COLOR); } else if (this.fillStyle === '#ef5350' || this.fillStyle === '#ca3f64' || this.fillStyle === 'rgb(239, 83, 80)' || this.fillStyle === 'rgb(202, 63, 100)') { this.fillStyle = rgbaToCss(DOWN_COLOR); } } return origFillRect.apply(this, arguments); }; } }); }, 1000); } // Chart observer'ı ekle - chart değişikliklerini takip et function observeChartChanges() { const chartObserver = new MutationObserver(() => { const charts = document.querySelectorAll('.tv-lightweight-charts'); if (charts.length > 0) { applyChartColorFilters(); } }); chartObserver.observe(document.body, { childList: true, subtree: true }); } // BU FONKSİYON DEĞİŞTİ: Chart filtreleri artık UP_COLOR ve DOWN_COLOR'a göre dinamik olarak hesaplanıyor // BU FONKSİYON TAMAMEN DEĞİŞTİ: Chart renkleri için daha etkili bir yaklaşım function applyChartColorFilters() { try { const oldStyle = document.getElementById('okx-chart-colors-style'); if (oldStyle) oldStyle.remove(); const chartStyle = document.createElement('style'); chartStyle.id = 'okx-chart-colors-style'; chartStyle.textContent = ` /* TradingView chart renklerini komple değiştir */ .tv-lightweight-charts * { fill: ${rgbaToCss(UP_COLOR)} !important; stroke: ${rgbaToCss(UP_COLOR)} !important; color: ${rgbaToCss(UP_COLOR)} !important; } /* Yeşil/Yukarı renkli elemanlar */ .tv-lightweight-charts [fill="#26a69a"], .tv-lightweight-charts [fill="#25a750"], .tv-lightweight-charts [fill*="26a69a"], .tv-lightweight-charts [fill*="25a750"], .tv-lightweight-charts [stroke="#26a69a"], .tv-lightweight-charts [stroke="#25a750"], .tv-lightweight-charts [stroke*="26a69a"], .tv-lightweight-charts [stroke*="25a750"], .tv-lightweight-charts [style*="26a69a"], .tv-lightweight-charts [style*="25a750"] { fill: ${rgbaToCss(UP_COLOR)} !important; stroke: ${rgbaToCss(UP_COLOR)} !important; } /* Kırmızı/Aşağı renkli elemanlar */ .tv-lightweight-charts [fill="#ef5350"], .tv-lightweight-charts [fill="#ca3f64"], .tv-lightweight-charts [fill*="ef5350"], .tv-lightweight-charts [fill*="ca3f64"], .tv-lightweight-charts [stroke="#ef5350"], .tv-lightweight-charts [stroke="#ca3f64"], .tv-lightweight-charts [stroke*="ef5350"], .tv-lightweight-charts [stroke*="ca3f64"], .tv-lightweight-charts [style*="ef5350"], .tv-lightweight-charts [style*="ca3f64"] { fill: ${rgbaToCss(DOWN_COLOR)} !important; stroke: ${rgbaToCss(DOWN_COLOR)} !important; } /* Canvas filtreleri - daha agresif yaklaşım */ .tv-lightweight-charts canvas { filter: none !important; } /* Özel olarak chart çubukları için */ .tv-lightweight-charts [fill="rgba(38, 166, 154, 0.2)"], .tv-lightweight-charts [fill="rgba(37, 167, 80, 0.2)"] { fill: ${rgbaToCss({...UP_COLOR, a: 0.2})} !important; } .tv-lightweight-charts [fill="rgba(239, 83, 80, 0.2)"], .tv-lightweight-charts [fill="rgba(202, 63, 100, 0.2)"] { fill: ${rgbaToCss({...DOWN_COLOR, a: 0.2})} !important; } /* Chart arkaplanındaki metin renkleri */ .tv-lightweight-charts text, .tv-lightweight-charts tspan { fill: ${rgbaToCss(UP_COLOR)} !important; color: ${rgbaToCss(UP_COLOR)} !important; } `; document.head.appendChild(chartStyle); // Canvas context'ini de override et overrideChartCanvas(); } catch (e) { console.error('Chart style error:', e); } } function monitorChartColors() { const origFill = CanvasRenderingContext2D.prototype.fill; const origStroke = CanvasRenderingContext2D.prototype.stroke; const origFillRect = CanvasRenderingContext2D.prototype.fillRect; CanvasRenderingContext2D.prototype.fill = function() { if (this.fillStyle && typeof this.fillStyle === 'string') { const parsed = parseColorString(this.fillStyle); if (parsed) { const converted = convertBasedOnDetection(parsed); if (converted && (converted.r !== parsed.r || converted.g !== parsed.g || converted.b !== parsed.b)) this.fillStyle = rgbaToCss(converted); } } origFill.apply(this, arguments); }; CanvasRenderingContext2D.prototype.stroke = function() { if (this.strokeStyle && typeof this.strokeStyle === 'string') { const parsed = parseColorString(this.strokeStyle); if (parsed) { const converted = convertBasedOnDetection(parsed); if (converted && (converted.r !== parsed.r || converted.g !== parsed.g || converted.b !== parsed.b)) this.strokeStyle = rgbaToCss(converted); } } origStroke.apply(this, arguments); }; CanvasRenderingContext2D.prototype.fillRect = function(x, y, w, h) { if (this.fillStyle && typeof this.fillStyle === 'string') { const parsed = parseColorString(this.fillStyle); if (parsed) { const converted = convertBasedOnDetection(parsed); if (converted && (converted.r !== parsed.r || converted.g !== parsed.g || converted.b !== parsed.b)) this.fillStyle = rgbaToCss(converted); } } origFillRect.apply(this, arguments); }; } function processNodeAndChildren(node){ try{ if(node.nodeType !== 1) return; processInlineAndSvg(node); processAllComputedStylesRoot(node); }catch(e){} } const mo = new MutationObserver((mutations)=>{ const added = []; for(const m of mutations){ if(m.type === 'attributes'){ const target = m.target; try{ if(['style','class','fill','stroke'].includes(m.attributeName)) processNodeAndChildren(target); }catch(e){} } if(m.addedNodes) m.addedNodes.forEach(n => { if(n.nodeType === 1) added.push(n); }); } if(added.length) setTimeout(()=> added.forEach(n => processNodeAndChildren(n)), 10); }); function kickAll(){ try{ processStyleSheets(); processStyleTags(); processInlineAndSvg(document); processAllComputedStylesRoot(document); applyChartColorFilters(); }catch(e){} } function init() { loadUserSettings(); kickAll(); mo.observe(document.body || document.documentElement, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class', 'fill', 'stroke'] }); monitorChartColors(); addColorPickerToMenu(); observeChartChanges(); // BU SATIRI EKLEYİN const menuObserver = new MutationObserver(() => addColorPickerToMenu()); menuObserver.observe(document.body, { childList: true, subtree: true }); window.addEventListener('load', () => { setTimeout(kickAll, 500); setTimeout(kickAll, 2000); setTimeout(kickAll, 5000); setTimeout(addColorPickerToMenu, 1000); setTimeout(applyChartColorFilters, 1500); // BU SATIRI EKLEYİN }); let lastUrl = location.href; setInterval(() => { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(() => { kickAll(); addColorPickerToMenu(); applyChartColorFilters(); // BU SATIRI EKLEYİN }, 1000); } }, 1000); } if(document.body) init(); else window.addEventListener('DOMContentLoaded', init); })();