1- import React from "react" ;
1+ import React , { useState , useEffect } from "react" ;
22import { useOutletContext , Link } from "react-router-dom" ;
33import { formatDurationTrack , formatDurationShow , formatDate , truncate } from "./helpers/utils" ;
44import TagBadges from "./controls/TagBadges" ;
@@ -10,8 +10,32 @@ import CoverArt from "./CoverArt";
1010import { FontAwesomeIcon } from "@fortawesome/react-fontawesome" ;
1111import { faScissors } from "@fortawesome/free-solid-svg-icons" ;
1212
13+ const SHIMMER_GRADIENT = 'linear-gradient(90deg, transparent 0%, transparent 20%, rgba(171, 217, 255, 0.45) 45%, rgba(171, 217, 255, 0.45) 55%, transparent 80%, transparent 100%)' ;
14+ const FOCUS_BOX_SHADOW = 'inset 0 -3px 0 #ABD9FF' ;
15+
1316const Tracks = ( { tracks, viewStyle, numbering = false , omitSecondary = false , highlight, trackRefs, trackSlug } ) => {
14- const { playTrack, activeTrack, setCustomPlaylist } = useOutletContext ( ) ;
17+ const { playTrack, activeTrack, setCustomPlaylist, isPlaying } = useOutletContext ( ) ;
18+ const [ isDarkMode , setIsDarkMode ] = useState (
19+ typeof window !== 'undefined' && window . matchMedia ( '(prefers-color-scheme: dark)' ) . matches
20+ ) ;
21+
22+ useEffect ( ( ) => {
23+ const mediaQuery = window . matchMedia ( '(prefers-color-scheme: dark)' ) ;
24+ const handleChange = ( e ) => setIsDarkMode ( e . matches ) ;
25+ mediaQuery . addEventListener ( 'change' , handleChange ) ;
26+ return ( ) => mediaQuery . removeEventListener ( 'change' , handleChange ) ;
27+ } , [ ] ) ;
28+
29+ // Override DarkReader's color modifications, matching the play button's approach
30+ useEffect ( ( ) => {
31+ if ( ! isDarkMode ) return ;
32+ document . querySelectorAll ( '.track-shimmer' ) . forEach ( el => {
33+ el . style . setProperty ( 'background' , SHIMMER_GRADIENT , 'important' ) ;
34+ } ) ;
35+ document . querySelectorAll ( '.track-item.focus' ) . forEach ( el => {
36+ el . style . setProperty ( 'box-shadow' , FOCUS_BOX_SHADOW , 'important' ) ;
37+ } ) ;
38+ } , [ isDarkMode , activeTrack ?. id , trackSlug , isPlaying ] ) ;
1539
1640 const handleTrackClick = ( track ) => {
1741 if ( track . audio_status === 'missing' ) return ;
@@ -49,20 +73,22 @@ const Tracks = ({ tracks, viewStyle, numbering = false, omitSecondary = false, h
4973 const { actualDuration, isExcerpt } = calculateTrackDetails ( track ) ;
5074 const hasMissingAudio = track . audio_status === 'missing' ;
5175 const shouldFocus = viewStyle === "show" && track . slug === trackSlug ;
76+ const isActive = track . id === activeTrack ?. id ;
5277
5378 return (
5479 < li
5580 key = { track . id }
5681 className = { [
5782 "list-item" ,
5883 viewStyle === "show" ? "track-item" : "" ,
59- track . id === activeTrack ?. id ? "active-item" : "" ,
84+ isActive ? "active-item" : "" ,
6085 shouldFocus ? "focus" : "" ,
6186 hasMissingAudio ? "no-audio" : ""
6287 ] . filter ( Boolean ) . join ( " " ) }
6388 onClick = { ( ) => handleTrackClick ( track ) }
6489 ref = { trackRefs ? ( el ) => ( trackRefs . current [ track . position - 1 ] = el ) : null }
6590 >
91+ { isActive && isPlaying && < span className = "track-shimmer" /> }
6692 < div className = "main-row" >
6793 { numbering && < span className = "leftside-numbering" > #{ index + 1 } </ span > }
6894 < span className = "leftside-primary" >
0 commit comments