您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
REXXXCLOUD Customization - Enhanced SoundCloud customization bruh
// ==UserScript== // @name REXXXCLOUD Soundcloud Customization // @namespace http://tampermonkey.net/ // @version 10.1 // @license MIT // @description REXXXCLOUD Customization - Enhanced SoundCloud customization bruh // @author rexxx // @match https://soundcloud.com/* // @grant none // ==/UserScript== (function() { 'use strict'; // Storage keys for description presets and customization const STORAGE_KEYS = { description: 'rexxxcloud_description_presets', customization: 'rexxxcloud_customization_settings' }; let isScriptActive = false; let enhancementAttempts = 0; const MAX_ENHANCEMENT_ATTEMPTS = 50; let customizationPanel = null; let fallingParticles = null; let customStyleElement = null; // Consolidated style element let animationStyleElement = null; // Consolidated animation style element let particleOverlayCanvas = null; // Particle overlay canvas instance // Default customization settings with new options const defaultCustomization = { backgroundType: 'none', // 'none', 'color', 'gradient', 'image', 'gif' backgroundColor: '#1a1a1a', gradientStart: '#1a1a1a', gradientEnd: '#333333', gradientDirection: 'to bottom', backgroundImage: '', backgroundOpacity: 0.3, themeColor: '#ff5500', textColor: '#ffffff', accentColor: '#ff7700', borderRadius: 8, customCSS: '', // Enhanced particle effects fallingParticlesEnabled: false, fallingParticleCount: 20, fallingParticleSpeed: 0.05, // Adjusted speed to be extremely slow fallingParticleSize: 2, fallingParticleColor: '#ffffff', fallingParticleOpacity: 0.7, // Smooth animations smoothAnimationsEnabled: true, hoverAnimationsEnabled: true, buttonAnimationsEnabled: true, transitionDuration: 0.3, // UI Enhancements customCursor: false, cursorTrail: false, buttonGlow: false, textShadow: false, borderGlow: false, // Additional customization options cardHoverEffect: true, volumeBarColor: true, progressBarColor: true, scrollBarColor: true, waveformColor: true, dimUnfocused: false, // New option glassmorphism: false, // New option neonText: false, // New option rainbowText: false, // New option // Waveform customization waveformCustomEnabled: false, waveformHue: 0, // Hue rotation in degrees waveformSaturation: 100, // Saturation percentage waveformBrightness: 100, // Brightness percentage waveformContrast: 100, // Contrast percentage waveformBlur: 0, // Blur in pixels waveformOpacity: 100, // Opacity percentage waveformInvert: false, // Invert colors waveformSepia: 0, // Sepia effect percentage waveformGrayscale: 0, // Grayscale effect percentage toggleKeybind: 'Shift+C' // New keybind setting }; // Enhanced Particle class with more effects class Particle { constructor(x, y, color, size, speed, type = 'normal') { this.x = x; this.y = y; this.vx = (Math.random() - 0.5) * speed * 0.05; // Further reduced horizontal speed this.vy = (Math.random() * 0.5 + 0.5) * speed * 0.5; // Adjusted vertical speed to be consistently downwards and slower this.color = color; this.size = size; this.life = 1.0; this.decay = 0.005; // Slower decay for longer life this.type = type; this.angle = Math.random() * Math.PI * 2; this.rotation = (Math.random() - 0.5) * 0.01; // Slower rotation } update() { this.x += this.vx; this.y += this.vy; this.life -= this.decay; this.angle += this.rotation; if (this.type === 'falling') { this.vy += 0.005; // Very subtle gravity for falling particles } } draw(ctx) { ctx.save(); ctx.globalAlpha = this.life; ctx.fillStyle = this.color; ctx.beginPath(); ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2); ctx.fill(); ctx.restore(); } isDead() { return this.life <= 0 || this.y > window.innerHeight + 50; } } // Enhanced Particle System class ParticleSystem { constructor(canvas) { this.canvas = canvas; this.ctx = canvas.getContext('2d'); this.particles = []; } addParticle(x, y, color, size, speed, type = 'normal') { this.particles.push(new Particle(x, y, color, size, speed, type)); } update() { this.particles = this.particles.filter(particle => { particle.update(); return !particle.isDead(); }); } draw() { this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); this.particles.forEach(particle => particle.draw(this.ctx)); } addFallingParticles(count, color, size, speed) { for (let i = 0; i < count; i++) { const x = Math.random() * this.canvas.width; const y = -10; this.addParticle(x, y, color, size, speed, 'falling'); } } } // Get customization settings function getCustomizationSettings() { const stored = localStorage.getItem(STORAGE_KEYS.customization); return stored ? { ...defaultCustomization, ...JSON.parse(stored) } : defaultCustomization; } // Save customization settings function saveCustomizationSettings(settings) { localStorage.setItem(STORAGE_KEYS.customization, JSON.stringify(settings)); applyCustomization(settings); } // Apply smooth animations function applySmoothAnimations(settings) { if (!settings.smoothAnimationsEnabled) return; const animationCSS = ` /* Smooth transitions for all interactive elements */ * { transition: all ${settings.transitionDuration}s cubic-bezier(0.4, 0, 0.2, 1) !important; } /* Button hover animations */ ${settings.buttonAnimationsEnabled ? ` button, .sc-button, [role="button"] { transform-origin: center !important; transition: all ${settings.transitionDuration}s cubic-bezier(0.4, 0, 0.2, 1) !important; } button:hover, .sc-button:hover, [role="button"]:hover { transform: translateY(-2px) scale(1.02) !important; box-shadow: 0 8px 25px rgba(255, 85, 0, 0.3) !important; } button:active, .sc-button:active, [role="button"]:active { transform: translateY(0px) scale(0.98) !important; } ` : ''} /* Hover animations for interactive elements */ ${settings.hoverAnimationsEnabled ? ` a, .playButton, .soundTitle, [class*="trackItem"] { transition: all ${settings.transitionDuration}s ease !important; } a:hover, .playButton:hover, .soundTitle:hover, [class*="trackItem"]:hover { transform: translateX(5px) !important; text-shadow: 0 0 10px rgba(255, 85, 0, 0.5) !important; } ` : ''} /* Custom cursor */ ${settings.customCursor ? ` * { cursor: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"><circle cx="10" cy="10" r="8" fill="none" stroke="%23ff5500" stroke-width="2"/><circle cx="10" cy="10" r="2" fill="%23ff5500"/></svg>') 10 10, auto !important; } ` : ''} /* Button glow effect */ ${settings.buttonGlow ? ` button, .sc-button, [role="button"] { box-shadow: 0 0 20px rgba(255, 85, 0, 0.3) !important; } ` : ''} /* Text shadow effect */ ${settings.textShadow ? ` h1, h2, h3, .soundTitle, .trackItem__title { text-shadow: 0 0 10px rgba(255, 85, 0, 0.5) !important; } ` : ''} /* Border glow effect */ ${settings.borderGlow ? ` input, textarea, select, .sc-input { box-shadow: 0 0 15px rgba(255, 85, 0, 0.2) !important; border: 1px solid rgba(255, 85, 0, 0.5) !important; } ` : ''} /* Card Hover Effect */ ${settings.cardHoverEffect ? ` .sound__cover, .trackItem__artwork, .playlistTrack__artwork { transition: transform 0.3s ease-in-out, box-shadow 0.3s ease-in-out !important; } .sound__cover:hover, .trackItem__artwork:hover, .playlistTrack__artwork:hover { transform: translateY(-5px) scale(1.02) !important; box-shadow: 0 10px 20px rgba(0, 0, 0, 0.4) !important; } ` : ''} /* Dim Unfocused Elements */ ${settings.dimUnfocused ? ` body:not(:hover) > *:not(#rexxxcloud-customization-panel):not(#rexxxcloud-customization-toggle) { opacity: 0.7 !important; } body:not(:hover) > *:not(#rexxxcloud-customization-panel):not(#rexxxcloud-customization-toggle):hover { opacity: 1 !important; } ` : ''} /* Glassmorphism Effect */ ${settings.glassmorphism ? ` .sc-button, .sc-input, .sc-select, .playbackSoundBadge, .sound__header, .l-listen-hero { background: rgba(255, 255, 255, 0.1) !important; backdrop-filter: blur(10px) saturate(180%) !important; -webkit-backdrop-filter: blur(10px) saturate(180%) !important; border: 1px solid rgba(209, 213, 219, 0.3) !important; border-radius: 10px !important; } ` : ''} /* Neon Text Effect */ ${settings.neonText ? ` h1, h2, h3, .soundTitle, .trackItem__title, a { text-shadow: 0 0 7px #fff, 0 0 10px #fff, 0 0 21px #fff, 0 0 42px ${settings.themeColor}, 0 0 82px ${settings.themeColor}, 0 0 92px ${settings.themeColor}, 0 0 102px ${settings.themeColor}, 0 0 151px ${settings.themeColor} !important; } ` : ''} /* Rainbow Text Effect */ ${settings.rainbowText ? ` @keyframes rexxxcloud-rainbow { 0% { color: #FF0000; } 16% { color: #FF7F00; } 33% { color: #FFFF00; } 50% { color: #00FF00; } 66% { color: #0000FF; } 83% { color: #4B0082; } 100% { color: #9400D3; } } h1, h2, h3, .soundTitle, .trackItem__title, a { animation: rexxxcloud-rainbow 6s linear infinite !important; } ` : ''} `; if (!animationStyleElement) { animationStyleElement = document.createElement('style'); animationStyleElement.id = 'rexxxcloud-animations'; document.head.appendChild(animationStyleElement); } animationStyleElement.textContent = animationCSS; } // Apply customization to the page function applyCustomization(settings) { if (!customStyleElement) { customStyleElement = document.createElement('style'); customStyleElement.id = 'rexxxcloud-custom-styles'; document.head.appendChild(customStyleElement); } let css = ` /* REXXXCLOUD Customization Styles */ :root { --rexxxcloud-theme-color: ${settings.themeColor}; --rexxxcloud-text-color: ${settings.textColor}; --rexxxcloud-accent-color: ${settings.accentColor}; --rexxxcloud-border-radius: ${settings.borderRadius}px; } /* Particle overlay canvas */ #rexxxcloud-particle-overlay { position: fixed !important; top: 0 !important; left: 0 !important; width: 100vw !important; height: 100vh !important; pointer-events: none !important; z-index: 99999 !important; /* Increased z-index */ } /* --- START: Transparent Background CSS --- */ /* Make the main play controls background transparent */ .playControls__bg { background-color: transparent !important; background: transparent !important; } /* Make all control buttons transparent */ .playControls__control, .playControls__control.sc-button, .playControls__control.sc-button-secondary, .playControls__control.sc-button-large, .playControls__control.sc-button-small, .playControls__control.sc-button-icon, .playControl, .skipControl, .shuffleControl, .repeatControl { background-color: transparent !important; background: transparent !important; border: none !important; box-shadow: none !important; } /* Make sound badge action buttons transparent */ .playbackSoundBadge__actions .sc-button, .sc-button-like, .sc-button-follow, .playbackSoundBadge__showQueue, .playbackSoundBadge__like, .sc-button-follow { background-color: transparent !important; background: transparent !important; border: none !important; box-shadow: none !important; } /* Make volume control button transparent */ .volume__button, .volume__speakerIcon { background-color: transparent !important; background: transparent !important; border: none !important; box-shadow: none !important; } /* Make the control panel transparent */ .playControls__panel, .playControlsPanel { background-color: transparent !important; background: transparent !important; } /* Ensure the main play controls container blends well */ .playControls, .playControls__inner, .playControls__wrapper, .playControls__elements { background-color: transparent !important; background: transparent !important; } /* Keep text and icons visible with proper contrast */ .playControls__control svg, .playbackSoundBadge__actions svg, .volume__button svg { color: inherit !important; fill: currentColor !important; } /* Ensure timeline and progress elements remain visible */ .playbackTimeline__progressBackground, .playbackTimeline__progressBar, .playbackTimeline__progressHandle { /* Keep these elements as they are for functionality */ } /* Ensure text elements remain visible */ .playbackTimeline__timePassed, .playbackTimeline__duration, .playbackSoundBadge__titleLink, .playbackSoundBadge__lightLink { /* Keep text styling as is for readability */ } /* --- END: Transparent Background CSS --- */ `; // Background customization if (settings.backgroundType !== 'none') { let backgroundCSS = ''; switch (settings.backgroundType) { case 'color': backgroundCSS = `background-color: ${settings.backgroundColor} !important;`; break; case 'gradient': backgroundCSS = `background: linear-gradient(${settings.gradientDirection}, ${settings.gradientStart}, ${settings.gradientEnd}) !important;`; break; case 'image': case 'gif': if (settings.backgroundImage) { backgroundCSS = ` background-image: url('${settings.backgroundImage}') !important; background-size: cover !important; background-position: center !important; background-repeat: no-repeat !important; background-attachment: fixed !important; `; // Add overlay for opacity control css += ` body::before { content: ''; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, ${1 - settings.backgroundOpacity}); pointer-events: none; z-index: -1; } `; } break; } css += ` body { ${backgroundCSS} } `; } // Glow effect if (settings.glowEffect) { css += ` body { box-shadow: inset 0 0 ${settings.glowIntensity * 10}px var(--rexxxcloud-theme-color) !important; } `; } // Theme color customization css += ` /* Button and accent color customization */ .sc-button-orange, .sc-button-cta, button[class*="orange"], button[class*="cta"], .playButton, .sc-button-play { background-color: var(--rexxxcloud-theme-color) !important; border-color: var(--rexxxcloud-theme-color) !important; } .sc-button-orange:hover, .sc-button-cta:hover, button[class*="orange"]:hover, button[class*="cta"]:hover { background-color: var(--rexxxcloud-accent-color) !important; border-color: var(--rexxxcloud-accent-color) !important; } /* Link colors */ a[class*="soundTitle"], a[class*="trackItem"], .soundTitle__title { color: var(--rexxxcloud-theme-color) !important; } /* Progress bars and sliders */ .playbackTimeline__progressBackground { background-color: transparent !important; background: transparent !important; } .playbackTimeline__progressWrapper { background-color: transparent !important; } ${settings.progressBarColor ? ` .playbackTimeline__progressBar, .volume__sliderWrapper { background-color: var(--rexxxcloud-theme-color) !important; } ` : ''} /* Volume bar color */ ${settings.volumeBarColor ? ` .volume__sliderBackground { background-color: var(--rexxxcloud-accent-color) !important; } ` : ''} /* Scrollbar color */ ${settings.scrollBarColor ? ` ::-webkit-scrollbar-thumb { background: var(--rexxxcloud-theme-color) !important; } ::-webkit-scrollbar-track { background: rgba(var(--rexxxcloud-theme-color), 0.2) !important; } ` : ''} /* Waveform color */ ${settings.waveformColor ? ` .waveform__layer__progress { background-color: var(--rexxxcloud-theme-color) !important; } .waveform__layer__background { background-color: rgba(var(--rexxxcloud-theme-color), 0.3) !important; } ` : ''} /* Advanced Waveform Customization */ ${settings.waveformCustomEnabled ? ` .waveform__layer.waveform__scene canvas { filter: hue-rotate(${settings.waveformHue}deg) saturate(${settings.waveformSaturation}%) brightness(${settings.waveformBrightness}%) contrast(${settings.waveformContrast}%) blur(${settings.waveformBlur}px) opacity(${settings.waveformOpacity}%) ${settings.waveformInvert ? 'invert(1)' : 'invert(0)'} sepia(${settings.waveformSepia}%) grayscale(${settings.waveformGrayscale}%) !important; transition: filter 0.3s ease !important; } ` : ''} /* Hide Master element and its containing iframe */ .sidebarModule:has(.webiEmbeddedModuleIframe[src*="credit-tracker"]) { display: none !important; } /* Custom border radius */ .sc-button, button, input, textarea, .sc-input, .sc-select { border-radius: var(--rexxxcloud-border-radius) !important; } /* Preset dropdown styling */ .rexxxcloud-preset-container select, .rexxxcloud-preset-container button { border-radius: var(--rexxxcloud-border-radius) !important; } /* Customization panel styling */ #rexxxcloud-customization-panel { background: rgba(26, 26, 26, 0.95) !important; border: 1px solid var(--rexxxcloud-theme-color) !important; border-radius: var(--rexxxcloud-border-radius) !important; backdrop-filter: blur(10px) !important; } `; // Add custom CSS if provided if (settings.customCSS) { css += `\n/* Custom CSS */\n${settings.customCSS}`; } customStyleElement.textContent = css; // Apply smooth animations applySmoothAnimations(settings); } // Create particle overlay canvas for particles and effects function createParticleOverlay() { if (!particleOverlayCanvas) { particleOverlayCanvas = document.createElement('canvas'); particleOverlayCanvas.id = 'rexxxcloud-particle-overlay'; document.body.appendChild(particleOverlayCanvas); // Resize canvas when window resizes window.addEventListener('resize', () => { particleOverlayCanvas.width = window.innerWidth; particleOverlayCanvas.height = window.innerHeight; }); } particleOverlayCanvas.width = window.innerWidth; particleOverlayCanvas.height = window.innerHeight; return particleOverlayCanvas; } // Create color picker input function createColorPicker(value, onChange) { const container = document.createElement('div'); container.style.cssText = ` display: flex !important; align-items: center !important; gap: 8px !important; `; const colorInput = document.createElement('input'); colorInput.type = 'color'; colorInput.value = value; colorInput.style.cssText = ` width: 40px !important; height: 30px !important; border: none !important; border-radius: 4px !important; cursor: pointer !important; `; const textInput = document.createElement('input'); textInput.type = 'text'; textInput.value = value; textInput.style.cssText = ` background: #333 !important; color: #fff !important; border: 1px solid #555 !important; border-radius: 4px !important; padding: 4px 8px !important; font-size: 12px !important; width: 80px !important; `; colorInput.addEventListener('change', () => { textInput.value = colorInput.value; onChange(colorInput.value); }); textInput.addEventListener('change', () => { if (/^#[0-9A-F]{6}$/i.test(textInput.value)) { colorInput.value = textInput.value; onChange(textInput.value); } }); container.appendChild(colorInput); container.appendChild(textInput); return container; } // Create enhanced customization panel function createCustomizationPanel() { if (customizationPanel) { customizationPanel.remove(); } const panel = document.createElement('div'); panel.id = 'rexxxcloud-customization-panel'; panel.style.cssText = ` position: fixed !important; top: 20px !important; right: 20px !important; width: 380px !important; max-height: 85vh !important; background: rgba(26, 26, 26, 0.95) !important; border: 1px solid #ff5500 !important; border-radius: 8px !important; padding: 16px !important; z-index: 10000 !important; font-family: Arial, sans-serif !important; font-size: 12px !important; color: #fff !important; overflow-y: auto !important; backdrop-filter: blur(10px) !important; display: none !important; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5) !important; `; const settings = getCustomizationSettings(); panel.innerHTML = ` <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;"> <h3 style="margin: 0; color: #ff5500; font-size: 16px;">🎨 REXXXCLOUD Customization</h3> <button id="rexxxcloud-close-panel" style="background: #dc3545; color: white; border: none; border-radius: 4px; padding: 4px 8px; cursor: pointer; font-size: 12px;">✕</button> </div> <!-- Background Settings --> <h4 style="margin-top: 0; margin-bottom: 10px; color: #ff5500;">🖼️ Background</h4> <div style="margin-bottom: 16px;"> <label style="display: block; margin-bottom: 8px; font-weight: bold;">Background Type:</label> <select id="rexxxcloud-bg-type" style="width: 100%; background: #333; color: #fff; border: 1px solid #555; border-radius: 4px; padding: 6px;"> <option value="none">None</option> <option value="color">Solid Color</option> <option value="gradient">Gradient</option> <option value="image">Image URL</option> <option value="gif">GIF URL</option> </select> </div> <div id="rexxxcloud-bg-color-section" style="margin-bottom: 16px; display: none;"> <label style="display: block; margin-bottom: 8px; font-weight: bold;">Background Color:</label> <div id="rexxxcloud-bg-color-picker"></div> </div> <div id="rexxxcloud-gradient-section" style="margin-bottom: 16px; display: none;"> <label style="display: block; margin-bottom: 8px; font-weight: bold;">Gradient Start:</label> <div id="rexxxcloud-gradient-start-picker" style="margin-bottom: 8px;"></div> <label style="display: block; margin-bottom: 8px; font-weight: bold;">Gradient End:</label> <div id="rexxxcloud-gradient-end-picker" style="margin-bottom: 8px;"></div> <label style="display: block; margin-bottom: 8px; font-weight: bold;">Direction:</label> <select id="rexxxcloud-gradient-direction" style="width: 100%; background: #333; color: #fff; border: 1px solid #555; border-radius: 4px; padding: 6px;"> <option value="to bottom">Top to Bottom</option> <option value="to top">Bottom to Top</option> <option value="to right">Left to Right</option> <option value="to left">Right to Left</option> <option value="45deg">Diagonal ↗</option> <option value="-45deg">Diagonal ↖</option> </select> </div> <div id="rexxxcloud-image-section" style="margin-bottom: 16px; display: none;"> <label style="display: block; margin-bottom: 8px; font-weight: bold;">Image/GIF URL:</label> <input type="text" id="rexxxcloud-bg-image" placeholder="https://example.com/image.jpg" style="width: 100%; background: #333; color: #fff; border: 1px solid #555; border-radius: 4px; padding: 6px; margin-bottom: 8px;"> <label style="display: block; margin-bottom: 8px; font-weight: bold;">Opacity: <span id="rexxxcloud-opacity-value">${settings.backgroundOpacity}</span></label> <input type="range" id="rexxxcloud-bg-opacity" min="0" max="1" step="0.1" value="${settings.backgroundOpacity}" style="width: 100%;"> </div> <!-- Theme Settings --> <h4 style="margin-top: 20px; margin-bottom: 10px; color: #ff5500;">🎨 Theme</h4> <div style="margin-bottom: 16px;"> <label style="display: block; margin-bottom: 8px; font-weight: bold;">Theme Color:</label> <div id="rexxxcloud-theme-color-picker"></div> </div> <div style="margin-bottom: 16px;"> <label style="display: block; margin-bottom: 8px; font-weight: bold;">Accent Color:</label> <div id="rexxxcloud-accent-color-picker"></div> </div> <div style="margin-bottom: 16px;"> <label style="display: block; margin-bottom: 8px; font-weight: bold;">Border Radius: <span id="rexxxcloud-radius-value">${settings.borderRadius}px</span></label> <input type="range" id="rexxxcloud-border-radius" min="0" max="20" value="${settings.borderRadius}" style="width: 100%;"> </div> <!-- Smooth Animations --> <h4 style="margin-top: 20px; margin-bottom: 10px; color: #ff5500;">✨ Smooth Animations</h4> <div style="margin-bottom: 12px;"> <label style="display: flex; align-items: center; gap: 8px; font-weight: bold;"> <input type="checkbox" id="rexxxcloud-smooth-animations-enabled" ${settings.smoothAnimationsEnabled ? 'checked' : ''}> Enable Smooth Animations </label> </div> <div style="margin-bottom: 12px;"> <label style="display: flex; align-items: center; gap: 8px;"> <input type="checkbox" id="rexxxcloud-hover-animations-enabled" ${settings.hoverAnimationsEnabled ? 'checked' : ''}> Hover Animations </label> </div> <div style="margin-bottom: 12px;"> <label style="display: flex; align-items: center; gap: 8px;"> <input type="checkbox" id="rexxxcloud-button-animations-enabled" ${settings.buttonAnimationsEnabled ? 'checked' : ''}> Button Animations </label> </div> <div style="margin-bottom: 12px;"> <label style="display: block; margin-bottom: 4px;">Transition Duration: <span id="rexxxcloud-transition-duration-value">${settings.transitionDuration}s</span></label> <input type="range" id="rexxxcloud-transition-duration" min="0.1" max="1" step="0.1" value="${settings.transitionDuration}" style="width: 100%;"> </div> <!-- Particle Effects --> <h4 style="margin-top: 20px; margin-bottom: 10px; color: #ff5500;">❄️ Particle Effects</h4> <div style="margin-bottom: 12px;"> <label style="display: flex; align-items: center; gap: 8px;"> <input type="checkbox" id="rexxxcloud-falling-particles-enabled" ${settings.fallingParticlesEnabled ? 'checked' : ''}> Falling Particles </label> </div> <div style="margin-bottom: 12px;"> <label style="display: block; margin-bottom: 4px;">Particle Count: <span id="rexxxcloud-falling-particle-count-value">${settings.fallingParticleCount}</span></label> <input type="range" id="rexxxcloud-falling-particle-count" min="5" max="100" value="${settings.fallingParticleCount}" style="width: 100%;"> </div> <div style="margin-bottom: 12px;"> <label style="display: block; margin-bottom: 4px;">Particle Size: <span id="rexxxcloud-falling-particle-size-value">${settings.fallingParticleSize}px</span></label> <input type="range" id="rexxxcloud-falling-particle-size" min="1" max="10" value="${settings.fallingParticleSize}" style="width: 100%;"> </div> <div style="margin-bottom: 12px;"> <label style="display: block; margin-bottom: 8px; font-weight: bold;">Particle Color:</label> <div id="rexxxcloud-falling-particle-color-picker"></div> </div> <!-- UI Enhancements --> <h4 style="margin-top: 20px; margin-bottom: 10px; color: #ff5500;">🎯 UI Enhancements</h4> <div style="margin-bottom: 12px;"> <label style="display: flex; align-items: center; gap: 8px;"> <input type="checkbox" id="rexxxcloud-custom-cursor" ${settings.customCursor ? 'checked' : ''}> Custom Cursor </label> </div> <div style="margin-bottom: 12px;"> <label style="display: flex; align-items: center; gap: 8px;"> <input type="checkbox" id="rexxxcloud-button-glow" ${settings.buttonGlow ? 'checked' : ''}> Button Glow </label> </div> <div style="margin-bottom: 12px;"> <label style="display: flex; align-items: center; gap: 8px;"> <input type="checkbox" id="rexxxcloud-text-shadow" ${settings.textShadow ? 'checked' : ''}> Text Shadow </label> </div> <div style="margin-bottom: 12px;"> <label style="display: flex; align-items: center; gap: 8px;"> <input type="checkbox" id="rexxxcloud-border-glow" ${settings.borderGlow ? 'checked' : ''}> Border Glow </label> </div> <div style="margin-bottom: 12px;"> <label style="display: flex; align-items: center; gap: 8px;"> <input type="checkbox" id="rexxxcloud-card-hover-effect" ${settings.cardHoverEffect ? 'checked' : ''}> Card Hover Effect </label> </div> <div style="margin-bottom: 12px;"> <label style="display: flex; align-items: center; gap: 8px;"> <input type="checkbox" id="rexxxcloud-volume-bar-color" ${settings.volumeBarColor ? 'checked' : ''}> Volume Bar Color </label> </div> <div style="margin-bottom: 12px;"> <label style="display: flex; align-items: center; gap: 8px;"> <input type="checkbox" id="rexxxcloud-progress-bar-color" ${settings.progressBarColor ? 'checked' : ''}> Progress Bar Color </label> </div> <div style="margin-bottom: 12px;"> <label style="display: flex; align-items: center; gap: 8px;"> <input type="checkbox" id="rexxxcloud-scroll-bar-color" ${settings.scrollBarColor ? 'checked' : ''}> Scroll Bar Color </label> </div> <div style="margin-bottom: 12px;"> <label style="display: flex; align-items: center; gap: 8px;"> <input type="checkbox" id="rexxxcloud-waveform-color" ${settings.waveformColor ? 'checked' : ''}> Waveform Color </label> </div> <div style="margin-bottom: 12px;"> <label style="display: flex; align-items: center; gap: 8px;"> <input type="checkbox" id="rexxxcloud-dim-unfocused" ${settings.dimUnfocused ? 'checked' : ''}> Dim Unfocused Elements </label> </div> <div style="margin-bottom: 12px;"> <label style="display: flex; align-items: center; gap: 8px;"> <input type="checkbox" id="rexxxcloud-glassmorphism" ${settings.glassmorphism ? 'checked' : ''}> Glassmorphism Effect </label> </div> <div style="margin-bottom: 12px;"> <label style="display: flex; align-items: center; gap: 8px;"> <input type="checkbox" id="rexxxcloud-neon-text" ${settings.neonText ? 'checked' : ''}> Neon Text Effect </label> </div> <div style="margin-bottom: 12px;"> <label style="display: flex; align-items: center; gap: 8px;"> <input type="checkbox" id="rexxxcloud-rainbow-text" ${settings.rainbowText ? 'checked' : ''}> Rainbow Text Effect </label> </div> <!-- Keybind Setting --> <h4 style="margin-top: 20px; margin-bottom: 10px; color: #ff5500;">⌨️ Keybind Settings</h4> <div style="margin-bottom: 16px;"> <label style="display: block; margin-bottom: 8px; font-weight: bold;">Toggle Panel Keybind:</label> <input type="text" id="rexxxcloud-toggle-keybind" value="${settings.toggleKeybind}" style="width: 100%; background: #333; color: #fff; border: 1px solid #555; border-radius: 4px; padding: 6px;"> </div> <!-- Waveform Customization --> <h4 style="margin-top: 20px; margin-bottom: 10px; color: #ff5500;">🌊 Waveform Customization</h4> <div style="margin-bottom: 12px;"> <label style="display: flex; align-items: center; gap: 8px; font-weight: bold;"> <input type="checkbox" id="rexxxcloud-waveform-custom-enabled" ${settings.waveformCustomEnabled ? 'checked' : ''}> Enable Advanced Waveform Effects </label> </div> <div style="margin-bottom: 12px;"> <label style="display: block; margin-bottom: 4px;">Hue Rotation: <span id="rexxxcloud-waveform-hue-value">${settings.waveformHue}°</span></label> <input type="range" id="rexxxcloud-waveform-hue" min="0" max="360" value="${settings.waveformHue}" style="width: 100%;"> </div> <div style="margin-bottom: 12px;"> <label style="display: block; margin-bottom: 4px;">Saturation: <span id="rexxxcloud-waveform-saturation-value">${settings.waveformSaturation}%</span></label> <input type="range" id="rexxxcloud-waveform-saturation" min="0" max="200" value="${settings.waveformSaturation}" style="width: 100%;"> </div> <div style="margin-bottom: 12px;"> <label style="display: block; margin-bottom: 4px;">Brightness: <span id="rexxxcloud-waveform-brightness-value">${settings.waveformBrightness}%</span></label> <input type="range" id="rexxxcloud-waveform-brightness" min="0" max="200" value="${settings.waveformBrightness}" style="width: 100%;"> </div> <div style="margin-bottom: 12px;"> <label style="display: block; margin-bottom: 4px;">Contrast: <span id="rexxxcloud-waveform-contrast-value">${settings.waveformContrast}%</span></label> <input type="range" id="rexxxcloud-waveform-contrast" min="0" max="200" value="${settings.waveformContrast}" style="width: 100%;"> </div> <div style="margin-bottom: 12px;"> <label style="display: block; margin-bottom: 4px;">Blur: <span id="rexxxcloud-waveform-blur-value">${settings.waveformBlur}px</span></label> <input type="range" id="rexxxcloud-waveform-blur" min="0" max="10" value="${settings.waveformBlur}" style="width: 100%;"> </div> <div style="margin-bottom: 12px;"> <label style="display: block; margin-bottom: 4px;">Opacity: <span id="rexxxcloud-waveform-opacity-value">${settings.waveformOpacity}%</span></label> <input type="range" id="rexxxcloud-waveform-opacity" min="0" max="100" value="${settings.waveformOpacity}" style="width: 100%;"> </div> <div style="margin-bottom: 12px;"> <label style="display: flex; align-items: center; gap: 8px;"> <input type="checkbox" id="rexxxcloud-waveform-invert" ${settings.waveformInvert ? 'checked' : ''}> Invert Colors </label> </div> <div style="margin-bottom: 12px;"> <label style="display: block; margin-bottom: 4px;">Sepia: <span id="rexxxcloud-waveform-sepia-value">${settings.waveformSepia}%</span></label> <input type="range" id="rexxxcloud-waveform-sepia" min="0" max="100" value="${settings.waveformSepia}" style="width: 100%;"> </div> <div style="margin-bottom: 12px;"> <label style="display: block; margin-bottom: 4px;">Grayscale: <span id="rexxxcloud-waveform-grayscale-value">${settings.waveformGrayscale}%</span></label> <input type="range" id="rexxxcloud-waveform-grayscale" min="0" max="100" value="${settings.waveformGrayscale}" style="width: 100%;"> </div> <!-- Custom CSS --> <h4 style="margin-top: 20px; margin-bottom: 10px; color: #ff5500;">💻 Custom CSS</h4> <div style="margin-bottom: 16px;"> <textarea id="rexxxcloud-custom-css" placeholder="/* Add your custom CSS here */" style="width: 100%; height: 80px; background: #333; color: #fff; border: 1px solid #555; border-radius: 4px; padding: 6px; font-family: monospace; font-size: 11px; resize: vertical;">${settings.customCSS}</textarea> </div> <div style="display: flex; gap: 8px;"> <button id="rexxxcloud-save-settings" style="flex: 1; background: #28a745; color: white; border: none; border-radius: 4px; padding: 8px; cursor: pointer; font-size: 12px;">💾 Save</button> <button id="rexxxcloud-reset-settings" style="flex: 1; background: #dc3545; color: white; border: none; border-radius: 4px; padding: 8px; cursor: pointer; font-size: 12px;">🔄 Reset</button> </div> `; document.body.appendChild(panel); customizationPanel = panel; // Initialize all form elements and event listeners initializePanelControls(panel, settings); return panel; } // Initialize panel controls with enhanced functionality function initializePanelControls(panel, settings) { // Get all form elements const bgTypeSelect = panel.querySelector('#rexxxcloud-bg-type'); const bgColorSection = panel.querySelector('#rexxxcloud-bg-color-section'); const gradientSection = panel.querySelector('#rexxxcloud-gradient-section'); const imageSection = panel.querySelector('#rexxxcloud-image-section'); // Set initial values bgTypeSelect.value = settings.backgroundType; // Create color pickers const colorPickers = [ { id: 'rexxxcloud-bg-color-picker', value: settings.backgroundColor, key: 'backgroundColor' }, { id: 'rexxxcloud-gradient-start-picker', value: settings.gradientStart, key: 'gradientStart' }, { id: 'rexxxcloud-gradient-end-picker', value: settings.gradientEnd, key: 'gradientEnd' }, { id: 'rexxxcloud-theme-color-picker', value: settings.themeColor, key: 'themeColor' }, { id: 'rexxxcloud-accent-color-picker', value: settings.accentColor, key: 'accentColor' }, { id: 'rexxxcloud-falling-particle-color-picker', value: settings.fallingParticleColor, key: 'fallingParticleColor' } ]; colorPickers.forEach(({ id, value, key }) => { const picker = createColorPicker(value, (color) => { settings[key] = color; }); panel.querySelector(`#${id}`).appendChild(picker); }); // Show/hide sections based on settings function updateSections() { bgColorSection.style.display = bgTypeSelect.value === 'color' ? 'block' : 'none'; gradientSection.style.display = bgTypeSelect.value === 'gradient' ? 'block' : 'none'; imageSection.style.display = (bgTypeSelect.value === 'image' || bgTypeSelect.value === 'gif') ? 'block' : 'none'; } updateSections(); // Add all event listeners addEnhancedEventListeners(panel, settings, updateSections); } // Enhanced event listeners function addEnhancedEventListeners(panel, settings, updateSections) { // Background controls panel.querySelector('#rexxxcloud-bg-type').addEventListener('change', (e) => { settings.backgroundType = e.target.value; updateSections(); }); // Add listeners for all controls const controls = [ // Basic controls { id: 'rexxxcloud-bg-image', key: 'backgroundImage', type: 'input' }, { id: 'rexxxcloud-bg-opacity', key: 'backgroundOpacity', type: 'range', transform: parseFloat }, { id: 'rexxxcloud-gradient-direction', key: 'gradientDirection', type: 'select' }, { id: 'rexxxcloud-border-radius', key: 'borderRadius', type: 'range', transform: parseInt }, { id: 'rexxxcloud-custom-css', key: 'customCSS', type: 'textarea' }, // Animation controls { id: 'rexxxcloud-smooth-animations-enabled', key: 'smoothAnimationsEnabled', type: 'checkbox' }, { id: 'rexxxcloud-hover-animations-enabled', key: 'hoverAnimationsEnabled', type: 'checkbox' }, { id: 'rexxxcloud-button-animations-enabled', key: 'buttonAnimationsEnabled', type: 'checkbox' }, { id: 'rexxxcloud-transition-duration', key: 'transitionDuration', type: 'range', transform: parseFloat }, // Particle effects { id: 'rexxxcloud-falling-particles-enabled', key: 'fallingParticlesEnabled', type: 'checkbox' }, { id: 'rexxxcloud-falling-particle-count', key: 'fallingParticleCount', type: 'range', transform: parseInt }, { id: 'rexxxcloud-falling-particle-size', key: 'fallingParticleSize', type: 'range', transform: parseInt }, // UI enhancements { id: 'rexxxcloud-custom-cursor', key: 'customCursor', type: 'checkbox' }, { id: 'rexxxcloud-button-glow', key: 'buttonGlow', type: 'checkbox' }, { id: 'rexxxcloud-text-shadow', key: 'textShadow', type: 'checkbox' }, { id: 'rexxxcloud-border-glow', key: 'borderGlow', type: 'checkbox' }, { id: 'rexxxcloud-card-hover-effect', key: 'cardHoverEffect', type: 'checkbox' }, { id: 'rexxxcloud-volume-bar-color', key: 'volumeBarColor', type: 'checkbox' }, { id: 'rexxxcloud-progressBar-color', key: 'progressBarColor', type: 'checkbox' }, { id: 'rexxxcloud-scroll-bar-color', key: 'scrollBarColor', type: 'checkbox' }, { id: 'rexxxcloud-waveform-color', key: 'waveformColor', type: 'checkbox' }, { id: 'rexxxcloud-dim-unfocused', key: 'dimUnfocused', type: 'checkbox' }, // New control { id: 'rexxxcloud-glassmorphism', key: 'glassmorphism', type: 'checkbox' }, // New control { id: 'rexxxcloud-neon-text', key: 'neonText', type: 'checkbox' }, // New control { id: 'rexxxcloud-rainbow-text', key: 'rainbowText', type: 'checkbox' }, // New control // Waveform customization controls { id: 'rexxxcloud-waveform-custom-enabled', key: 'waveformCustomEnabled', type: 'checkbox' }, { id: 'rexxxcloud-waveform-hue', key: 'waveformHue', type: 'range', transform: parseInt }, { id: 'rexxxcloud-waveform-saturation', key: 'waveformSaturation', type: 'range', transform: parseInt }, { id: 'rexxxcloud-waveform-brightness', key: 'waveformBrightness', type: 'range', transform: parseInt }, { id: 'rexxxcloud-waveform-contrast', key: 'waveformContrast', type: 'range', transform: parseInt }, { id: 'rexxxcloud-waveform-blur', key: 'waveformBlur', type: 'range', transform: parseInt }, { id: 'rexxxcloud-waveform-opacity', key: 'waveformOpacity', type: 'range', transform: parseInt }, { id: 'rexxxcloud-waveform-invert', key: 'waveformInvert', type: 'checkbox' }, { id: 'rexxxcloud-waveform-sepia', key: 'waveformSepia', type: 'range', transform: parseInt }, { id: 'rexxxcloud-waveform-grayscale', key: 'waveformGrayscale', type: 'range', transform: parseInt }, // Keybind control { id: 'rexxxcloud-toggle-keybind', key: 'toggleKeybind', type: 'input' } ]; controls.forEach(({ id, key, type, transform }) => { const element = panel.querySelector(`#${id}`); if (element) { const eventType = type === 'checkbox' ? 'change' : 'input'; element.addEventListener(eventType, (e) => { let value = e.target.value; if (type === 'checkbox') { value = e.target.checked; } else if (transform) { value = transform(value); } settings[key] = value; // Update value display for range inputs const valueSpan = panel.querySelector(`#${id}-value`); if (valueSpan && type === 'range') { const unit = id.includes('duration') ? 's' : id.includes('size') || id.includes('radius') || id.includes('intensity') ? 'px' : ''; valueSpan.textContent = value + unit; } }); } }); // Button event listeners panel.querySelector('#rexxxcloud-close-panel').addEventListener('click', () => { panel.style.display = 'none'; }); panel.querySelector('#rexxxcloud-save-settings').addEventListener('click', () => { saveCustomizationSettings(settings); alert('🎉 REXXXCLOUD settings saved! Your enhanced SoundCloud experience is ready!'); }); panel.querySelector('#rexxxcloud-reset-settings').addEventListener('click', () => { if (confirm('Reset all REXXXCLOUD settings to default?')) { saveCustomizationSettings(defaultCustomization); panel.remove(); customizationPanel = null; createCustomizationPanel(); alert('REXXXCLOUD settings reset to default!'); } }); } // Create customization toggle button with enhanced styling function createCustomizationToggle() { const existingToggle = document.querySelector('#rexxxcloud-customization-toggle'); if (existingToggle) { return; } const toggle = document.createElement('button'); toggle.id = 'rexxxcloud-customization-toggle'; toggle.innerHTML = '🎨'; toggle.title = 'REXXXCLOUD Customization by rexxx'; toggle.style.cssText = ` position: fixed !important; top: 20px !important; right: 20px !important; width: 60px !important; height: 60px !important; background: linear-gradient(45deg, #ff5500, #ff7700, #ff9900) !important; color: white !important; border: none !important; border-radius: 50% !important; cursor: pointer !important; font-size: 24px !important; z-index: 9999 !important; box-shadow: 0 6px 20px rgba(255, 85, 0, 0.4) !important; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important; animation: rexxxcloud-toggle-pulse 3s infinite !important; `; // Add enhanced pulsing animation const style = document.createElement('style'); style.textContent = ` @keyframes rexxxcloud-toggle-pulse { 0%, 100% { transform: scale(1) rotate(0deg); box-shadow: 0 6px 20px rgba(255, 85, 0, 0.4); } 25% { transform: scale(1.05) rotate(5deg); box-shadow: 0 8px 25px rgba(255, 85, 0, 0.6); } 50% { transform: scale(1.1) rotate(0deg); box-shadow: 0 10px 30px rgba(255, 85, 0, 0.8); } 75% { transform: scale(1.05) rotate(-5deg); box-shadow: 0 8px 25px rgba(255, 85, 0, 0.6); } } `; document.head.appendChild(style); toggle.addEventListener('mouseenter', () => { toggle.style.transform = 'scale(1.2) rotate(10deg)'; toggle.style.boxShadow = '0 10px 30px rgba(255, 85, 0, 0.8)'; }); toggle.addEventListener('mouseleave', () => { toggle.style.transform = 'scale(1)'; toggle.style.boxShadow = '0 6px 20px rgba(255, 85, 0, 0.4)'; }); toggle.addEventListener('click', () => { if (!customizationPanel) { customizationPanel = createCustomizationPanel(); } const panel = document.querySelector('#rexxxcloud-customization-panel'); if (panel) { panel.style.display = panel.style.display === 'none' ? 'block' : 'none'; } }); document.body.appendChild(toggle); } // Function to handle keyboard shortcuts function setupKeybindListener() { document.removeEventListener("keydown", handleKeybind); document.addEventListener("keydown", handleKeybind); } function handleKeybind(event) { const settings = getCustomizationSettings(); const keybind = settings.toggleKeybind; if (!keybind) return; const parts = keybind.split("+").map(p => p.trim().toLowerCase()); let matches = true; if (parts.includes("shift") && !event.shiftKey) matches = false; if (!parts.includes("shift") && event.shiftKey) matches = false; if (parts.includes("ctrl") && !event.ctrlKey) matches = false; if (!parts.includes("ctrl") && event.ctrlKey) matches = false; if (parts.includes("alt") && !event.altKey) matches = false; if (!parts.includes("alt") && event.altKey) matches = false; const key = parts[parts.length - 1]; if (event.key.toLowerCase() !== key) matches = false; if (matches) { event.preventDefault(); const toggleButton = document.querySelector("#rexxxcloud-customization-toggle"); if (toggleButton) { toggleButton.style.display = toggleButton.style.display === 'none' ? 'block' : 'none'; } } } function getFieldPresets(field) { const stored = localStorage.getItem(STORAGE_KEYS[field]); return stored ? JSON.parse(stored) : []; } // Save presets for description field function saveFieldPresets(field, presets) { localStorage.setItem(STORAGE_KEYS[field], JSON.stringify(presets)); } // Add a preset for description field function addPreset(field, name, value) { const presets = getFieldPresets(field); const filtered = presets.filter(p => p.name !== name); filtered.push({ name, value }); saveFieldPresets(field, filtered); } // Delete a preset function deletePreset(field, name) { const presets = getFieldPresets(field); const filtered = presets.filter(p => p.name !== name); saveFieldPresets(field, filtered); } // Create preset dropdown for description field only function createPresetDropdown(field, inputElement, labelElement) { if (field !== 'description') { return; } const presetContainer = document.createElement('div'); presetContainer.className = `rexxxcloud-preset-${field} rexxxcloud-preset-container`; presetContainer.style.cssText = ` display: inline-flex !important; align-items: center !important; gap: 6px !important; margin-left: 10px !important; font-size: 11px !important; opacity: 0.9 !important; `; // Create the dropdown select const select = document.createElement('select'); select.style.cssText = ` background: #333 !important; color: #fff !important; border: 1px solid #ff5500 !important; border-radius: 6px !important; padding: 4px 8px !important; font-size: 11px !important; min-width: 120px !important; cursor: pointer !important; transition: all 0.3s ease !important; `; // Create save button const saveBtn = document.createElement('button'); saveBtn.innerHTML = '💾'; saveBtn.title = `Save current ${field} as preset`; saveBtn.type = 'button'; saveBtn.style.cssText = ` background: linear-gradient(45deg, #ff5500, #ff7700) !important; color: white !important; border: none !important; border-radius: 4px !important; padding: 4px 6px !important; cursor: pointer !important; font-size: 11px !important; line-height: 1 !important; transition: all 0.3s ease !important; `; // Create delete button const deleteBtn = document.createElement('button'); deleteBtn.innerHTML = '🗑'; deleteBtn.title = `Delete selected ${field} preset`; deleteBtn.type = 'button'; deleteBtn.style.cssText = ` background: linear-gradient(45deg, #dc3545, #e74c3c) !important; color: white !important; border: none !important; border-radius: 4px !important; padding: 4px 6px !important; cursor: pointer !important; font-size: 11px !important; line-height: 1 !important; transition: all 0.3s ease !important; `; // Update dropdown options function updateDropdown() { const presets = getFieldPresets(field); select.innerHTML = `<option value="">📝 Select preset...</option>`; presets.forEach(preset => { const option = document.createElement('option'); option.value = preset.name; option.textContent = preset.name.length > 20 ? preset.name.substring(0, 20) + '...' : preset.name; select.appendChild(option); }); } // Load preset into field select.addEventListener('change', () => { if (select.value) { const presets = getFieldPresets(field); const preset = presets.find(p => p.name === select.value); if (preset) { inputElement.value = preset.value; inputElement.dispatchEvent(new Event('input', { bubbles: true })); inputElement.dispatchEvent(new Event('change', { bubbles: true })); inputElement.focus(); if (inputElement.tagName === 'TEXTAREA') { inputElement.style.height = 'auto'; inputElement.style.height = inputElement.scrollHeight + 'px'; } } } }); // Save current field value as preset saveBtn.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); const currentValue = inputElement.value.trim(); if (!currentValue) { alert(`Please enter some ${field} content before saving a preset.`); return; } const presetName = prompt(`Enter a name for this ${field} preset:`, ''); if (presetName && presetName.trim()) { addPreset(field, presetName.trim(), currentValue); updateDropdown(); select.value = presetName.trim(); alert(`${field.charAt(0).toUpperCase() + field.slice(1)} preset "${presetName}" saved!`); } }); // Delete selected preset deleteBtn.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); if (!select.value) { alert(`Please select a ${field} preset to delete.`); return; } if (confirm(`Delete the "${select.value}" ${field} preset?`)) { deletePreset(field, select.value); updateDropdown(); alert(`${field.charAt(0).toUpperCase() + field.slice(1)} preset deleted!`); } }); presetContainer.appendChild(select); presetContainer.appendChild(saveBtn); presetContainer.appendChild(deleteBtn); // Insert in the best available location if (labelElement && labelElement.parentNode) { labelElement.appendChild(presetContainer); } else if (inputElement && inputElement.parentNode) { inputElement.parentNode.insertBefore(presetContainer, inputElement); } updateDropdown(); return presetContainer; } // Enhanced field detection for description only function findFormElements() { const selectors = { description: [ '#description', 'textarea[name="description"]', 'textarea[placeholder*="descriptions tend to get"]', 'textarea[placeholder*="description"]', 'textarea[aria-label*="description"]' ] }; const labelSelectors = { description: ['label[for="description"]', 'Description'] // Simplified label search }; const found = {}; Object.keys(selectors).forEach(field => { // Find input element for (const selector of selectors[field]) { const element = document.querySelector(selector); if (element) { found[field] = { input: element }; break; } } // Find label element if (found[field]) { for (const labelText of labelSelectors[field]) { let labelElement = document.querySelector(`label[for="${found[field].input.id}"]`); if (!labelElement) { labelElement = Array.from(document.querySelectorAll('label')).find( label => label.textContent.includes(labelText) ); } if (labelElement) { found[field].label = labelElement; break; } } } }); return found; } // Enhanced form detection function enhanceFormFields() { enhancementAttempts++; console.log(`🎵 REXXXCLOUD: Enhancement attempt ${enhancementAttempts}/${MAX_ENHANCEMENT_ATTEMPTS}`); const foundElements = findFormElements(); let enhancedCount = 0; // Only process description field const field = 'description'; const { input, label } = foundElements[field] || {}; if (input) { const existingPreset = document.querySelector(`.rexxxcloud-preset-${field}`); if (!existingPreset) { console.log(`🎵 REXXXCLOUD: Adding preset dropdown for ${field}`); createPresetDropdown(field, input, label); enhancedCount++; } } if (enhancedCount > 0) { console.log(`🎵 REXXXCLOUD: Enhanced ${enhancedCount} fields`); } // Create customization toggle if not exists createCustomizationToggle(); return enhancedCount; } // Smart initialization function smartInit() { if (!isScriptActive) { isScriptActive = true; console.log('🎵 REXXXCLOUD by rexxx - Starting enhanced monitoring...'); } if (!window.location.hostname.includes('soundcloud.com')) { return; } // Apply saved customization settings const settings = getCustomizationSettings(); applyCustomization(settings); // Setup keybind listener setupKeybindListener(); // Initialize falling particles if enabled if (settings.fallingParticlesEnabled) { const particleOverlay = createParticleOverlay(); fallingParticles = new ParticleSystem(particleOverlay); function animateFallingParticles() { if (fallingParticles && settings.fallingParticlesEnabled) { if (Math.random() < 0.1) { // Periodically add new particles fallingParticles.addFallingParticles( Math.floor(Math.random() * settings.fallingParticleCount), settings.fallingParticleColor, settings.fallingParticleSize, settings.fallingParticleSpeed ); } fallingParticles.update(); fallingParticles.draw(); } requestAnimationFrame(animateFallingParticles); } animateFallingParticles(); } else if (fallingParticles) { // If particles were enabled and now disabled, stop animation and clear canvas fallingParticles = null; if (particleOverlayCanvas) { const ctx = particleOverlayCanvas.getContext('2d'); ctx.clearRect(0, 0, particleOverlayCanvas.width, particleOverlayCanvas.height); } } // Look for description field const uploadIndicators = [ 'form', 'textarea[name="description"]', '#description' ]; let hasUploadForm = false; for (const selector of uploadIndicators) { if (document.querySelector(selector)) { hasUploadForm = true; break; } } if (hasUploadForm) { console.log('🎵 REXXXCLOUD: Upload form detected, enhancing description field...'); const enhanced = enhanceFormFields(); if (enhanced === 0 && enhancementAttempts < MAX_ENHANCEMENT_ATTEMPTS) { setTimeout(smartInit, 1000); } } else { createCustomizationToggle(); if (enhancementAttempts < MAX_ENHANCEMENT_ATTEMPTS) { setTimeout(smartInit, 2000); } } // Custom Top Fans Implementation handleTopFans(); } // Function to handle Top Fans function handleTopFans() { // Hide the original top fans section if it exists const originalTopFansSelector = '.ouxtlr0'; // Based on the HTML snippet provided earlier const originalTopFansElement = document.querySelector(originalTopFansSelector); if (originalTopFansElement) { originalTopFansElement.style.display = 'none'; console.log('🎵 REXXXCLOUD: Original Top Fans section hidden.'); } // Find a suitable parent element to insert our custom top fans section // This might need adjustment based on the actual SoundCloud DOM structure const parentElement = document.querySelector('.l-listen-hero'); // Example selector, adjust as needed if (!parentElement) { console.log('🎵 REXXXCLOUD: Could not find parent element for custom Top Fans. Skipping.'); return; } // Remove any previously rendered custom top fans section to ensure refresh const existingCustomTopFans = document.getElementById('rexxxcloud-custom-top-fans'); if (existingCustomTopFans) { existingCustomTopFans.remove(); } // Simulate fetching top fan data (replace with actual data fetching if possible) const topFansData = getSimulatedTopFansData(); // This function needs to be defined if (topFansData && topFansData.length > 0) { const customTopFansSection = document.createElement('div'); customTopFansSection.id = 'rexxxcloud-custom-top-fans'; customTopFansSection.style.cssText = ` margin-top: 20px; padding: 15px; background: rgba(0, 0, 0, 0.2); border-radius: 8px; color: #fff; `; let fansHtml = '<h4 style="margin-top: 0; color: #ff5500;">🏆 Top Fans (REXXXCLOUD)</h4>'; fansHtml += '<ul style="list-style: none; padding: 0;">'; topFansData.forEach((fan, index) => { fansHtml += ` <li style="display: flex; align-items: center; margin-bottom: 10px;"> <span style="font-weight: bold; margin-right: 10px;">${index + 1}.</span> <img src="${fan.avatarUrl}" alt="${fan.name}'s Avatar" style="width: 30px; height: 30px; border-radius: 50%; margin-right: 10px;"> <a href="${fan.profileUrl}" style="color: #fff; text-decoration: none; font-weight: bold;">${fan.name}</a> <span style="color: #ccc;">(${fan.plays} plays)</span> </li> `; }); fansHtml += '</ul>'; customTopFansSection.innerHTML = fansHtml; parentElement.appendChild(customTopFansSection); console.log('🎵 REXXXCLOUD: Custom Top Fans section rendered.'); } else { console.log('🎵 REXXXCLOUD: No Top Fans data available, not rendering custom section.'); } } // Simulated function to get top fan data // In a real scenario, this would involve making an API call to SoundCloud function getSimulatedTopFansData() { // This is placeholder data. You would replace this with actual data fetched from SoundCloud. // Since direct API access for top fans isn't readily available via public SoundCloud APIs // without authentication and specific permissions, this remains a simulation. // If you can find a way to scrape this data or access a private API, integrate it here. const currentTrackId = window.location.pathname.split('/').pop(); // Basic way to get a track ID // Return different data based on track ID for demonstration if (currentTrackId === 'thoughts') { return [ { name: 'DJDanJam$', avatarUrl: 'https://i1.sndcdn.com/avatars-1vCCKrSYGzWUVRFo-99zWPQ-large.jpg', profileUrl: 'https://soundcloud.com/djdanjams', plays: 4 }, { name: 'RRA1NYD4Y$$ (quit)', avatarUrl: 'https://i1.sndcdn.com/avatars-eKNK34U68k7LzLXx-iLlkOA-large.jpg', profileUrl: 'https://soundcloud.com/rra1ny901', plays: 4 }, { name: 'integrity', avatarUrl: 'https://i1.sndcdn.com/avatars-F78bIKKHn7G2RJv3-TWWvkw-large.jpg', profileUrl: 'https://soundcloud.com/hsxrd_cult', plays: 3 }, { name: 'anonymousUser', avatarUrl: 'https://a1.sndcdn.com/images/default_avatar_large.png', profileUrl: 'https://soundcloud.com/Anonymous%20permalink', plays: 2 }, { name: 'exsvyssssss', avatarUrl: 'https://i1.sndcdn.com/avatars-jaqQq2ih5jK4tJ7Q-Mg6nBw-large.jpg', profileUrl: 'https://soundcloud.com/exsvy', plays: 2 } ]; } else if (currentTrackId === 'another-track-id') { return [ { name: 'FanA', avatarUrl: 'https://example.com/fanA.jpg', profileUrl: 'https://soundcloud.com/fana', plays: 10 }, { name: 'FanB', avatarUrl: 'https://example.com/fanB.jpg', profileUrl: 'https://soundcloud.com/fanb', plays: 8 } ]; } else { return []; // No top fans for other tracks } } // Comprehensive observer for dynamic content const observer = new MutationObserver((mutations) => { let shouldReinit = false; let trackChanged = false; mutations.forEach((mutation) => { if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { for (const node of mutation.addedNodes) { if (node.nodeType === 1) { // Check for description field or track changes if (node.querySelector && ( node.querySelector('textarea[name="description"]') || node.querySelector('#description') )) { shouldReinit = true; } // Detect track change by looking for elements commonly updated on track navigation if (node.querySelector && ( node.querySelector(".playbackSoundBadge__titleLink") || // Track title link node.querySelector(".sound__header") // Sound header section )) { trackChanged = true; } } } } }); // Also check for title changes, which reliably indicates a track change if (document.title !== lastDocumentTitle) { lastDocumentTitle = document.title; trackChanged = true; } if (shouldReinit) { console.log('🎵 REXXXCLOUD: Form changes detected, re-enhancing...'); setTimeout(smartInit, 500); } if (trackChanged) { console.log('🎵 REXXXCLOUD: Track changed, re-handling Top Fans...'); setTimeout(handleTopFans, 1000); // Re-run handleTopFans on track change } }); // Start observing observer.observe(document.body, { childList: true, subtree: true, attributes: false }); // URL change detection for SPA navigation let lastUrl = location.href; let lastDocumentTitle = document.title; // Initialize with current document title setInterval(() => { const url = location.href; if (url !== lastUrl) { lastUrl = url; console.log('🎵 REXXXCLOUD: URL changed, reinitializing...'); enhancementAttempts = 0; setTimeout(() => { smartInit(); handleTopFans(); // Also re-handle top fans on URL change }, 1000); } }, 1000); // Initial start if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', smartInit); } else { smartInit(); } console.log('🎵 REXXXCLOUD by rexxx - Enhanced SoundCloud customization loaded and monitoring!'); })();