@@ -63,17 +63,77 @@ export const HistoryCard = memo(function HistoryCard({ historyItem, onRefresh })
6363 // Play song
6464 const playSong = async ( ) => {
6565 try {
66- const songData = {
67- id : historyItem . id ,
68- title : historyItem . title ,
69- artist : historyItem . artist ,
70- artwork : historyItem . artwork ,
71- url : historyItem . url ,
72- duration : historyItem . duration ,
73- sourceType : historyItem . sourceType ,
74- isLocal : historyItem . isLocal ,
75- path : historyItem . path ,
76- } ;
66+ // Check if this is a legacy history entry (empty URL and no videoId)
67+ // For these, we need to search YouTube Music by title/artist
68+ const isLegacyEntry = ! historyItem . url && ! historyItem . videoId && historyItem . sourceType === 'online' ;
69+
70+ let songData ;
71+
72+ if ( isLegacyEntry ) {
73+ // Legacy entry without videoId - search YouTube Music first
74+ console . log ( '🔍 History: Legacy entry, searching YTMusic for:' , historyItem . title ) ;
75+ try {
76+ const YouTubeMusicService = require ( '../../Utils/YouTubeMusicService' ) . default ;
77+ const ytResult = await YouTubeMusicService . searchAndStream (
78+ historyItem . title ,
79+ historyItem . artist || ''
80+ ) ;
81+
82+ if ( ytResult && ytResult . url && ! ytResult . error ) {
83+ // Successfully found on YouTube Music
84+ songData = {
85+ id : ytResult . videoId ,
86+ title : historyItem . title ,
87+ artist : historyItem . artist ,
88+ artwork : historyItem . artwork ,
89+ url : ytResult . url ,
90+ headers : ytResult . headers ,
91+ duration : historyItem . duration ,
92+ sourceType : 'online' ,
93+ isLocal : false ,
94+ source : 'ytmusic' ,
95+ videoId : ytResult . videoId ,
96+ _prefetched : true ,
97+ } ;
98+ console . log ( '✅ History: Found on YTMusic:' , ytResult . videoId ) ;
99+ } else {
100+ throw new Error ( 'Could not find song on YouTube Music' ) ;
101+ }
102+ } catch ( searchError ) {
103+ console . error ( '❌ History: YTMusic search failed:' , searchError . message ) ;
104+ ToastAndroid . show ( 'Could not find song' , ToastAndroid . SHORT ) ;
105+ return ;
106+ }
107+ } else {
108+ // Standard case - has URL or videoId
109+ const needsStreamFetch = ! historyItem . url && (
110+ historyItem . videoId ||
111+ historyItem . source === 'ytmusic' ||
112+ historyItem . source === 'spotify' ||
113+ historyItem . source === 'dab'
114+ ) ;
115+
116+ songData = {
117+ // Use videoId as ID if available (for YTMusic playback), otherwise use original ID
118+ id : historyItem . videoId || historyItem . id ,
119+ title : historyItem . title ,
120+ artist : historyItem . artist ,
121+ artwork : historyItem . artwork ,
122+ url : historyItem . url || '' , // Empty URL will trigger stream fetch
123+ duration : historyItem . duration ,
124+ sourceType : historyItem . sourceType ,
125+ isLocal : historyItem . isLocal ,
126+ path : historyItem . path ,
127+ // Include source info for proper stream fetching
128+ source : historyItem . videoId ? 'ytmusic' : historyItem . source ,
129+ videoId : historyItem . videoId ,
130+ spotifyId : historyItem . spotifyId ,
131+ // Flag to trigger stream fetch if URL is empty
132+ _needsStream : needsStreamFetch ,
133+ // Mark if this was mapped from Spotify
134+ mappedFromSpotify : ! ! historyItem . spotifyId ,
135+ } ;
136+ }
77137
78138 await PlayOneSong ( songData ) ;
79139 setIndex ( 1 ) ; // Open full screen player
@@ -209,14 +269,15 @@ export const HistoryCard = memo(function HistoryCard({ historyItem, onRefresh })
209269 } , [ historyItem . id , historyItem . sourceType ] ) ;
210270
211271 return (
212- < View style = { styles . container } >
213- < Pressable
214- onPress = { playSong }
215- android_ripple = { {
216- color : dark ? 'rgba(255, 255, 255, 0.12)' : 'rgba(0, 0, 0, 0.08)' ,
217- borderless : false ,
218- radius : SCREEN_WIDTH * 0.45
219- } }
272+ < Pressable
273+ onPress = { playSong }
274+ android_ripple = { {
275+ color : dark ? 'rgba(255, 255, 255, 0.15)' : 'rgba(0, 0, 0, 0.05)' ,
276+ borderless : false ,
277+ } }
278+ style = { styles . container }
279+ >
280+ < View
220281 style = { styles . pressableContent }
221282 >
222283 < FastImage
@@ -244,11 +305,14 @@ export const HistoryCard = memo(function HistoryCard({ historyItem, onRefresh })
244305 style = { [ styles . artist , { color : colors . textSecondary } ] }
245306 />
246307 </ View >
247- </ Pressable >
308+ </ View >
248309
249310 < Pressable
250311 ref = { buttonRef }
251- onPress = { showMenu }
312+ onPress = { ( e ) => {
313+ e . stopPropagation ( ) ;
314+ showMenu ( ) ;
315+ } }
252316 style = { styles . menuButton }
253317 >
254318 < MaterialCommunityIcons name = "dots-vertical" size = { 22 } color = { colors . text } />
@@ -293,27 +357,32 @@ export const HistoryCard = memo(function HistoryCard({ historyItem, onRefresh })
293357 </ View >
294358 </ TouchableOpacity >
295359 </ Modal >
296- </ View >
360+ </ Pressable >
297361 ) ;
298362} ) ;
299363
300364const getThemedStyles = ( colors , dark ) => StyleSheet . create ( {
301365 container : {
302366 flexDirection : 'row' ,
303367 alignItems : 'center' ,
304- paddingHorizontal : 16 ,
305- paddingVertical : 8 ,
368+ paddingVertical : 6 ,
369+ paddingHorizontal : 10 ,
370+ marginHorizontal : 10 ,
371+ marginVertical : 2 ,
372+ borderRadius : 8 ,
306373 backgroundColor : colors . background ,
307374 } ,
308375 pressableContent : {
309376 flex : 1 ,
310377 flexDirection : 'row' ,
311378 alignItems : 'center' ,
379+ paddingVertical : 6 ,
380+ paddingLeft : 4
312381 } ,
313382 artwork : {
314383 width : 50 ,
315384 height : 50 ,
316- borderRadius : 4 ,
385+ borderRadius : 8 ,
317386 marginRight : 12 ,
318387 } ,
319388 textContainer : {
0 commit comments