1818import { createRegistrar } from "/modules/stdlib/mod.ts" ;
1919import type { ModuleRuntimeContext } from "/modules/stdlib/mod.ts" ;
2020import { NavLink } from "/modules/stdlib/src/registers/navlink.tsx" ;
21+ import { PlaybarButton } from "/modules/stdlib/src/registers/playbarButton.tsx" ;
2122
2223import {
2324 APP_NAME ,
@@ -37,6 +38,8 @@ import { createProviders } from "./providers/index.ts";
3738import { AdjustmentsMenu , TranslationMenu } from "./options-menu.tsx" ;
3839import { TopBarContent } from "./tab-bar.tsx" ;
3940import { openConfig } from "./settings.tsx" ;
41+ import { lyricsReplacementReady , mountLyricsPlaybarStyleWhenReady , watchLyricsHistory } from "./playbar-lifecycle.ts" ;
42+ import type { LyricsHistory } from "./playbar-lifecycle.ts" ;
4043import {
4144 emptyLine ,
4245 GeniusPage ,
@@ -1537,71 +1540,45 @@ class LyricsContainer extends react.Component {
15371540}
15381541
15391542// ============================================================================
1540- // PlaybarButton.js (adapted) — classic IIFE turned into a ctx-scoped function
1543+ // PlaybarButton.js (adapted) — v3 registrar-owned React control
15411544// ============================================================================
15421545
1543- function initPlaybarButton ( ctx : ModuleRuntimeContext ) {
1544- if ( ! Spicetify . Platform ?. History ) {
1545- const retry = window . setTimeout ( ( ) => initPlaybarButton ( ctx ) , 300 ) ;
1546- ctx . defer ( ( ) => window . clearTimeout ( retry ) ) ;
1547- return ;
1548- }
1546+ const PLAYBAR_ICON = `<path d="M13.426 2.574a2.831 2.831 0 0 0-4.797 1.55l3.247 3.247a2.831 2.831 0 0 0 1.55-4.797zM10.5 8.118l-2.619-2.62A63303.13 63303.13 0 0 0 4.74 9.075L2.065 12.12a1.287 1.287 0 0 0 1.816 1.816l3.06-2.688 3.56-3.129zM7.12 4.094a4.331 4.331 0 1 1 4.786 4.786l-3.974 3.493-3.06 2.689a2.787 2.787 0 0 1-3.933-3.933l2.676-3.045 3.505-3.99z"></path>` ;
15491547
1550- const button = new Spicetify . Playbar . Button (
1551- "Lyrics Plus" ,
1552- `<svg role="img" height="16" width="16" aria-hidden="true" viewBox="0 0 16 16" data-encore-id="icon" fill="currentColor"><path d="M13.426 2.574a2.831 2.831 0 0 0-4.797 1.55l3.247 3.247a2.831 2.831 0 0 0 1.55-4.797zM10.5 8.118l-2.619-2.62A63303.13 63303.13 0 0 0 4.74 9.075L2.065 12.12a1.287 1.287 0 0 0 1.816 1.816l3.06-2.688 3.56-3.129zM7.12 4.094a4.331 4.331 0 1 1 4.786 4.786l-3.974 3.493-3.06 2.689a2.787 2.787 0 0 1-3.933-3.933l2.676-3.045 3.505-3.99z"></path></svg>` ,
1553- ( ) =>
1554- Spicetify . Platform . History . location . pathname !== "/lyrics-plus"
1555- ? Spicetify . Platform . History . push ( "/lyrics-plus" )
1556- : Spicetify . Platform . History . goBack ( ) ,
1557- false ,
1558- Spicetify . Platform . History . location . pathname === "/lyrics-plus" ,
1559- false ,
1548+ function LyricsPlusPlaybarButton ( ) {
1549+ const [ history , setHistory ] = react . useState < LyricsHistory | null > ( null ) ;
1550+ const [ visible , setVisible ] = react . useState (
1551+ Spicetify . LocalStorage . get ( "lyrics-plus:visual:playbar-button" ) === "true" ,
15601552 ) ;
1553+ const [ active , setActive ] = react . useState ( false ) ;
15611554
1562- const style = document . createElement ( "style" ) ;
1563- style . innerHTML = `
1564- .main-nowPlayingBar-lyricsButton[data-testid="lyrics-button"] {
1565- display: none !important;
1566- }
1567- li[data-id="/lyrics-plus"] {
1568- display: none;
1569- }
1570- ` ;
1571- style . classList . add ( "lyrics-plus:visual:playbar-button" ) ;
1572-
1573- let registered = false ;
1574- const setPlaybarButton = ( ) => {
1575- if ( registered ) return ;
1576- document . head . appendChild ( style ) ;
1577- button . register ( ) ;
1578- registered = true ;
1579- } ;
1580- const removePlaybarButton = ( ) => {
1581- if ( ! registered ) return ;
1582- style . remove ( ) ;
1583- button . deregister ( ) ;
1584- registered = false ;
1585- } ;
1586-
1587- if ( Spicetify . LocalStorage . get ( "lyrics-plus:visual:playbar-button" ) === "true" ) setPlaybarButton ( ) ;
1588-
1589- const onToggle = ( event : any ) => {
1590- if ( event . detail ?. name === "playbar-button" ) {
1591- if ( event . detail . value ) setPlaybarButton ( ) ;
1592- else removePlaybarButton ( ) ;
1593- }
1594- } ;
1595- window . addEventListener ( "lyrics-plus" , onToggle ) ;
1596-
1597- const unlisten = Spicetify . Platform . History . listen ( ( location : any ) => {
1598- button . active = location . pathname === "/lyrics-plus" ;
1599- } ) ;
1555+ react . useEffect (
1556+ ( ) =>
1557+ watchLyricsHistory (
1558+ ( ) => Spicetify . Platform ?. History ,
1559+ setHistory ,
1560+ ( pathname ) => setActive ( pathname === ROUTE ) ,
1561+ ) ,
1562+ [ ] ,
1563+ ) ;
16001564
1601- ctx . defer ( ( ) => {
1602- removePlaybarButton ( ) ;
1603- window . removeEventListener ( "lyrics-plus" , onToggle ) ;
1604- if ( typeof unlisten === "function" ) unlisten ( ) ;
1565+ react . useEffect ( ( ) => {
1566+ const onToggle = ( event : any ) => {
1567+ if ( event . detail ?. name === "playbar-button" ) setVisible ( Boolean ( event . detail . value ) ) ;
1568+ } ;
1569+ window . addEventListener ( "lyrics-plus" , onToggle ) ;
1570+ return ( ) => window . removeEventListener ( "lyrics-plus" , onToggle ) ;
1571+ } , [ ] ) ;
1572+
1573+ const ready = lyricsReplacementReady ( visible , history ) ;
1574+ react . useEffect ( ( ) => mountLyricsPlaybarStyleWhenReady ( document , ROUTE , visible , history ) , [ visible , history ] ) ;
1575+
1576+ if ( ! ready ) return null ;
1577+ return react . createElement ( PlaybarButton , {
1578+ label : "Lyrics Plus" ,
1579+ icon : PLAYBAR_ICON ,
1580+ isActive : active ,
1581+ onClick : ( ) => ( history . location . pathname !== ROUTE ? history . push ( ROUTE ) : history . goBack ( ) ) ,
16051582 } ) ;
16061583}
16071584
@@ -1616,5 +1593,5 @@ export default function (ctx: ModuleRuntimeContext) {
16161593 react . createElement ( NavLink , { localizedApp : "Lyrics" , appRoutePath : ROUTE , icon : ICON , activeIcon : ICON } ) ,
16171594 ) ;
16181595 registrar . registerRoute ( ROUTE , react . createElement ( LyricsContainer ) ) ;
1619- initPlaybarButton ( ctx ) ;
1596+ registrar . register ( "playbarButton" , react . createElement ( LyricsPlusPlaybarButton ) ) ;
16201597}
0 commit comments