1(function() { 2 'use strict'; 3 4 /** 5 * Adjust RGB color brightness by a percentage 6 * @param {number} r - Red value (0-255) 7 * @param {number} g - Green value (0-255) 8 * @param {number} b - Blue value (0-255) 9 * @param {number} percent - Percentage to brighten (positive) or darken (negative) 10 * @returns {Array} - Adjusted [r, g, b] values 11 */ 12 function adjustBrightness(r, g, b, percent) { 13 var amount = Math.round(2.55 * percent); 14 return [ 15 Math.min(255, Math.max(0, r + amount)), 16 Math.min(255, Math.max(0, g + amount)), 17 Math.min(255, Math.max(0, b + amount)) 18 ]; 19 } 20 21 /** 22 * Generate deterministic RGB colors from a string (avatar URL) 23 * Used as fallback when CORS blocks Color Thief extraction 24 * @param {string} str - String to hash (avatar URL) 25 * @returns {Array} - [r, g, b] values 26 */ 27 function hashStringToRGB(str) { 28 var hash = 0; 29 for (var i = 0; i < str.length; i++) { 30 hash = str.charCodeAt(i) + ((hash << 5) - hash); 31 hash = hash & hash; // Convert to 32-bit integer 32 } 33 34 // Generate colors with reasonable saturation and brightness 35 var r = (hash & 0xFF0000) >> 16; 36 var g = (hash & 0x00FF00) >> 8; 37 var b = hash & 0x0000FF; 38 39 // Ensure colors aren't too dark (minimum brightness) 40 r = Math.max(60, r); 41 g = Math.max(60, g); 42 b = Math.max(60, b); 43 44 return [r, g, b]; 45 } 46 47 /** 48 * Apply gradient to banner element 49 * @param {HTMLElement} element - Banner element with data-avatar-url 50 */ 51 function applyGradientFallback(element) { 52 var avatarUrl = element.getAttribute('data-avatar-url'); 53 if (!avatarUrl) { 54 element.classList.remove('bluesky-banner-gradient-pending'); 55 return; 56 } 57 58 // Check if ColorThief is available 59 if (typeof ColorThief === 'undefined') { 60 console.warn('ColorThief library not loaded, using hash-based gradient fallback'); 61 applyHashGradient(element, avatarUrl); 62 return; 63 } 64 65 // Create offscreen image for color extraction 66 var img = new Image(); 67 img.crossOrigin = 'Anonymous'; // Required for Color Thief canvas access 68 69 img.onload = function() { 70 try { 71 var colorThief = new ColorThief(); 72 var dominantColor = colorThief.getColor(img); 73 74 if (dominantColor && dominantColor.length === 3) { 75 var r = dominantColor[0]; 76 var g = dominantColor[1]; 77 var b = dominantColor[2]; 78 79 // Create gradient with brightened second color 80 var brightened = adjustBrightness(r, g, b, 20); 81 var gradient = 'linear-gradient(135deg, rgb(' + r + ',' + g + ',' + b + '), rgb(' + brightened[0] + ',' + brightened[1] + ',' + brightened[2] + '))'; 82 83 element.style.setProperty('--bluesky-banner-gradient', gradient); 84 element.classList.remove('bluesky-banner-gradient-pending'); 85 } else { 86 // Color extraction failed, use hash fallback 87 applyHashGradient(element, avatarUrl); 88 } 89 } catch (error) { 90 console.warn('Color Thief extraction failed, using hash-based gradient:', error); 91 applyHashGradient(element, avatarUrl); 92 } 93 }; 94 95 img.onerror = function() { 96 // CORS error or network failure, use hash-based gradient 97 console.warn('Image load failed (likely CORS), using hash-based gradient'); 98 applyHashGradient(element, avatarUrl); 99 }; 100 101 img.src = avatarUrl; 102 } 103 104 /** 105 * Apply hash-based gradient when Color Thief unavailable or fails 106 * @param {HTMLElement} element - Banner element 107 * @param {string} avatarUrl - Avatar URL to hash 108 */ 109 function applyHashGradient(element, avatarUrl) { 110 var color1 = hashStringToRGB(avatarUrl); 111 var color2 = hashStringToRGB(avatarUrl + '_alt'); // Different hash for second color 112 113 var gradient = 'linear-gradient(135deg, rgb(' + color1[0] + ',' + color1[1] + ',' + color1[2] + '), rgb(' + color2[0] + ',' + color2[1] + ',' + color2[2] + '))'; 114 115 element.style.setProperty('--bluesky-banner-gradient', gradient); 116 element.classList.remove('bluesky-banner-gradient-pending'); 117 } 118 119 /** 120 * Initialize gradient fallback on DOMContentLoaded 121 */
122 function init() { 123 var pendingElements = document.querySelectorAll('.bluesky-banner-gradient-pending'); 124 125 if (pendingElements.length === 0) { 126 return; 127 } 128 129 // Process each banner element 130 for (var i = 0; i < pendingElements.length; i++) { 131 applyGradientFallback(pendingElements[i]); 132 } 133 } 134 135 // Run on DOMContentLoaded 136 if (document.readyState === 'loading') { 137 document.addEventListener('DOMContentLoaded', init); 138 } else { 139 // DOM already loaded 140 init(); 141 } 142})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.