/* Draw legacy control glyphs in Glass and Bento; restore them on theme changes. */ (function(root) { 'use strict'; const paths = { trash:'', music:'', add:'', close:'', search:'', save:'', play:'', pause:'', next:'', previous:'', repeat:'', edit:'', lyrics:'', share:'', copy:'', check:'', folder:'', settings:'', chapters:'', clock:'', shuffle:'', down:'', right:'', back:'', more:'', television:'', pin:'', devices:'' }; const glyphs = {'๏ผ‹':'add','โœ•':'close','ร—':'close','โœ–':'close','๐Ÿ”':'search','๐Ÿ”Ž':'search','โฌ‡':'save','โค“':'save','๐Ÿ’พ':'save','โ–ถ':'play','โธ':'pause','โญ':'next','โฎ':'previous','โ†ป':'repeat','โ†บ':'repeat','โœŽ':'edit','โœ':'edit','๐Ÿ“':'edit','๐ŸŽค':'lyrics','โ†—':'share','โง‰':'copy','โœ“':'check','๐Ÿ“':'folder','โš™':'settings','๐Ÿ“‹':'chapters','๐Ÿ•˜':'clock','๐Ÿ”€':'shuffle','๐Ÿ“ก':'devices','โ–พ':'down','โ–ธ':'right','โ†':'back','โ‹ฏ':'more','โ‹ฎ':'more','๐Ÿ—‘':'trash','๐ŸŽต':'music'}; function leadingGlyph(text,bento=false) { const mapping=bento?{...glyphs,'๐Ÿ“บ':'television','โฑ':'clock','โ‡…':'settings','๐Ÿ“Œ':'pin','๐ŸŽง':'music','๐Ÿ“š':'folder'}:glyphs; const prefix = text.match(/^\s*/)[0], rest = text.slice(prefix.length); const glyph = Object.keys(mapping).find(key => rest.startsWith(key)); if (!glyph) return null; const length = glyph.length + (rest[glyph.length] === '\uFE0F' ? 1 : 0); return { kind:mapping[glyph], original:prefix+rest.slice(0,length), rest:rest.slice(length) }; } function mount(doc) { const decorations = new Set(), tabLabels = new Map(); let scheduled=false; const selector = '#listPane button, .sidebar button, .smart-item .pl-name, .notes-tab, .notes-fold, .mini-btn, .sidebar .playlist-item:not(.smart-item), .pl-offline-badge.all, .home-pl-offline.all, .home-pl-play, .home-pl-thumb-fallback'; const svg = kind => { const icon=doc.createElementNS('http://www.w3.org/2000/svg','svg'); icon.setAttribute('viewBox','0 0 24 24');icon.setAttribute('aria-hidden','true');icon.classList.add('glass-control-icon');icon.innerHTML=paths[kind];return icon; }; const observer=new root.MutationObserver(schedule), themeObserver=new root.MutationObserver(schedule); function restore(record) { record.svg.remove(); if(record.original.isConnected)record.original.replaceWith(doc.createTextNode(record.original.textContent)); if(record.addedLabel && record.parent.isConnected)record.parent.removeAttribute('aria-label'); } function restoreTab(parent, record) { for(const label of record.labels)if(label.isConnected)label.replaceWith(doc.createTextNode(label.textContent)); for(const [name,value] of Object.entries(record.attributes)) { if(value===null)parent.removeAttribute(name);else parent.setAttribute(name,value); } } function paint() { scheduled=false;observer.disconnect(); const bento=doc.documentElement.dataset.layout==='bento-hub'; const active=bento || doc.documentElement.dataset.layout==='glass-stage'; for(const [parent,record] of tabLabels)if(!active || !parent.isConnected){restoreTab(parent,record);tabLabels.delete(parent);} for(const record of decorations)if(!active || !record.svg.isConnected){restore(record);decorations.delete(record);} if(active) for(const parent of doc.querySelectorAll(selector+(bento?', .service-btn, .np-btn, .ctrl, .empty-icon, .dl-saved-cta, .brand-mark, .upnext-head button, .ph-logo, .saved-badge':''))) { // Existing SVGs already express the action; only legacy glyphs change. if(parent.querySelector('svg:not(.glass-control-icon),.legacy-nav-icon'))continue; for(const node of [...parent.childNodes]) { if(node.nodeType!==3)continue;const match=leadingGlyph(node.textContent,bento);if(!match)continue; const icon=svg(match.kind); if(parent.matches('.pl-offline-badge,.home-pl-offline')) { icon.removeAttribute('aria-hidden'); icon.setAttribute('role','img'); icon.setAttribute('aria-label',parent.title || 'Available offline'); } const original=doc.createElement('span'); original.className='glass-original-glyph';original.textContent=match.original; node.textContent=match.rest;parent.insertBefore(icon,node);parent.insertBefore(original,node); const addedLabel=parent.tagName==='BUTTON'&&!parent.hasAttribute('aria-label')&&!parent.textContent.replace(match.original,'').trim(); if(addedLabel)parent.setAttribute('aria-label',parent.title || ({play:'Play',pause:'Pause',close:'Close',add:'Add',save:'Save'}[match.kind] || match.kind)); decorations.add({parent,svg:icon,original,addedLabel});break; } if(parent.matches('.sidebar .playlist-item:not(.smart-item)')&&!parent.querySelector('svg')) { const icon=svg('folder'); parent.prepend(icon); decorations.add({parent,svg:icon,original:doc.createElement('span'),addedLabel:false}); } if(parent.matches('.notes-tab')&&!parent.querySelector('svg')&&paths[parent.dataset.tab==='markers'?'chapters':parent.dataset.tab]) { const kind=parent.dataset.tab==='markers'?'chapters':parent.dataset.tab,icon=svg(kind);parent.prepend(icon); const original=doc.createElement('span');decorations.add({parent,svg:icon,original,addedLabel:false}); } } if(active)for(const parent of doc.querySelectorAll('.notes-tab')) { if(tabLabels.has(parent))continue; const record={labels:[],attributes:{'aria-label':parent.getAttribute('aria-label'),title:parent.getAttribute('title')}}; const name=parent.dataset.tab==='markers'?'Chapters & bookmarks':parent.dataset.tab==='lyrics'?'Lyrics':'Search'; if(!parent.hasAttribute('aria-label'))parent.setAttribute('aria-label',name); if(!parent.hasAttribute('title'))parent.setAttribute('title',name); for(const node of [...parent.childNodes])if(node.nodeType===3 && node.textContent.trim()) { const label=doc.createElement('span');label.className='glass-tab-label';node.replaceWith(label);label.append(node);record.labels.push(label); } tabLabels.set(parent,record); } if(active)observer.observe(doc.body,{childList:true,subtree:true,characterData:true}); } function schedule(){if(!scheduled){scheduled=true;root.queueMicrotask(paint);}} themeObserver.observe(doc.documentElement,{attributes:true,attributeFilter:['data-layout']});paint(); return ()=>{observer.disconnect();themeObserver.disconnect();for(const record of decorations)restore(record);for(const [parent,record] of tabLabels)restoreTab(parent,record);}; } if(typeof module!=='undefined')module.exports={leadingGlyph,paths}; else if(root.document.readyState==='loading')root.document.addEventListener('DOMContentLoaded',()=>mount(root.document),{once:true}); else mount(root.document); })(typeof window!=='undefined'?window:globalThis);