replies timeline only, appview-less bluesky client
1export type Theme = Record<string, string> & { 2 bg: string; 3 fg: string; 4 accent: string; 5 accent2: string; 6}; 7 8export const defaultTheme: Theme = { 9 bg: '#11001c', 10 fg: '#f8fafc', 11 accent: '#ec4899', 12 accent2: '#8b5cf6' 13}; 14 15export const hashColor = (input: string): string => { 16 let hash: number; 17 18 const id = input.split(':').pop() || input; 19 20 hash = 0; 21 for (let i = 0; i < Math.min(10, id.length); i++) { 22 hash = (hash << 4) + id.charCodeAt(i); 23 } 24 hash = hash >>> 0; 25 26 // magic mixing 27 hash ^= hash >>> 16; 28 hash = Math.imul(hash, 0x21f0aaad); 29 hash ^= hash >>> 15; 30 hash = hash >>> 0; 31 32 const hue = hash % 360; 33 const saturation = 0.8 + ((hash >>> 10) % 20) * 0.01; // 80-100% 34 const lightness = 0.45 + ((hash >>> 20) % 35) * 0.01; // 45-80% 35 36 const rgb = hslToRgb(hue, saturation, lightness); 37 const hex = rgb.map((value) => value.toString(16).padStart(2, '0')).join(''); 38 39 return `#${hex}`; 40}; 41 42const hslToRgb = (h: number, s: number, l: number): [number, number, number] => { 43 const c = (1 - Math.abs(2 * l - 1)) * s; 44 const hPrime = h / 60; 45 const x = c * (1 - Math.abs((hPrime % 2) - 1)); 46 const m = l - c / 2; 47 48 let r: number, g: number, b: number; 49 50 if (hPrime < 1) { 51 r = c; 52 g = x; 53 b = 0; 54 } else if (hPrime < 2) { 55 r = x; 56 g = c; 57 b = 0; 58 } else if (hPrime < 3) { 59 r = 0; 60 g = c; 61 b = x; 62 } else if (hPrime < 4) { 63 r = 0; 64 g = x; 65 b = c; 66 } else if (hPrime < 5) { 67 r = x; 68 g = 0; 69 b = c; 70 } else { 71 r = c; 72 g = 0; 73 b = x; 74 } 75 76 return [Math.round((r + m) * 255), Math.round((g + m) * 255), Math.round((b + m) * 255)]; 77};