@@ -126,73 +126,78 @@ const FloatingContributors: React.FC<FloatingContributorsProps> = ({
126126 const [ lastFetched , setLastFetched ] = useState < number | null > ( null ) ;
127127 const refreshTimerRef = useRef < NodeJS . Timeout | null > ( null ) ;
128128
129- // Create fallback activities for when API fails
130- const createFallbackActivities = useCallback ( ( ) : ContributorActivity [ ] => {
131- const fallbackContributors = [
132- {
133- login : "sanjay-kv" ,
134- avatar_url : "https://avatars.githubusercontent.com/u/30715153?v=4" ,
135- html_url : "https://github.com/sanjay-kv" ,
136- } ,
137- {
138- login : "recodehive-team" ,
139- avatar_url : "https://avatars.githubusercontent.com/u/150000000?v=4" ,
140- html_url : "https://github.com/recodehive" ,
141- } ,
142- {
143- login : "open-source-contributor" ,
144- avatar_url : "https://avatars.githubusercontent.com/u/583231?v=4" ,
145- html_url : "https://github.com/open-source-contributor" ,
146- } ,
147- {
148- login : "developer" ,
149- avatar_url : "https://avatars.githubusercontent.com/u/9919?v=4" ,
150- html_url : "https://github.com/developer" ,
151- } ,
152- {
153- login : "coder" ,
154- avatar_url : "https://avatars.githubusercontent.com/u/6154722?v=4" ,
155- html_url : "https://github.com/coder" ,
156- } ,
157- ] ;
158-
159- const actions : ContributorActivity [ "action" ] [ ] = [
160- "pushed" ,
161- "created" ,
162- "merged" ,
163- "opened" ,
164- "commented" ,
165- ] ;
166- const timeOffsets = [ 5 , 10 , 30 , 60 , 120 , 240 , 480 ] ; // minutes
167- const messages = [
168- "Updated documentation" ,
169- "Fixed styling issues" ,
170- "Added new feature" ,
171- "Resolved conflict in package.json" ,
172- "Implemented responsive design" ,
173- "Updated dependencies" ,
174- "Fixed typo in README" ,
175- ] ;
176-
177- return fallbackContributors . map ( ( contributor , index ) => {
178- const now = new Date ( ) ;
179- const timestamp = new Date (
180- now . getTime ( ) - timeOffsets [ index % timeOffsets . length ] * 60 * 1000 ,
129+ // When there's no recent event-feed activity, fall back to the repo's
130+ // actual latest push (commits) and latest issue comments instead of mock data.
131+ const fetchRealFallbackActivities = useCallback ( async ( ) : Promise <
132+ ContributorActivity [ ]
133+ > => {
134+ const results : ContributorActivity [ ] = [ ] ;
135+
136+ try {
137+ const commitsResponse = await fetch (
138+ "https://api.github.com/repos/recodehive/recode-website/commits?per_page=5" ,
181139 ) ;
140+ if ( commitsResponse . ok ) {
141+ const commits = await commitsResponse . json ( ) ;
142+ if ( Array . isArray ( commits ) ) {
143+ commits . forEach ( ( commit ) => {
144+ const login = commit . author ?. login ;
145+ if ( ! login || isBotAccount ( login ) ) return ;
146+ const timestamp = new Date (
147+ commit . commit ?. author ?. date ?? Date . now ( ) ,
148+ ) ;
149+ results . push ( {
150+ id : `commit-${ commit . sha } ` ,
151+ contributor : {
152+ login,
153+ avatar_url : commit . author . avatar_url ,
154+ html_url : `https://github.com/${ login } ` ,
155+ } ,
156+ action : "pushed" ,
157+ message : commit . commit ?. message ?. slice ( 0 , 50 ) ,
158+ timestamp,
159+ timeAgo : formatTimeAgo ( timestamp ) ,
160+ } ) ;
161+ } ) ;
162+ }
163+ }
164+ } catch ( e ) {
165+ console . warn ( "Error fetching fallback commits:" , e ) ;
166+ }
167+
168+ try {
169+ const commentsResponse = await fetch (
170+ "https://api.github.com/repos/recodehive/recode-website/issues/comments?per_page=5&sort=created&direction=desc" ,
171+ ) ;
172+ if ( commentsResponse . ok ) {
173+ const comments = await commentsResponse . json ( ) ;
174+ if ( Array . isArray ( comments ) ) {
175+ comments . forEach ( ( comment ) => {
176+ const login = comment . user ?. login ;
177+ if ( ! login || isBotAccount ( login ) ) return ;
178+ const timestamp = new Date ( comment . created_at ?? Date . now ( ) ) ;
179+ results . push ( {
180+ id : `comment-${ comment . id } ` ,
181+ contributor : {
182+ login,
183+ avatar_url : comment . user . avatar_url ,
184+ html_url : `https://github.com/${ login } ` ,
185+ } ,
186+ action : "commented" ,
187+ message : comment . body ?. slice ( 0 , 50 ) ,
188+ timestamp,
189+ timeAgo : formatTimeAgo ( timestamp ) ,
190+ } ) ;
191+ } ) ;
192+ }
193+ }
194+ } catch ( e ) {
195+ console . warn ( "Error fetching fallback comments:" , e ) ;
196+ }
182197
183- return {
184- id : `fallback-${ index } ` ,
185- contributor : {
186- login : contributor . login ,
187- avatar_url : contributor . avatar_url ,
188- html_url : contributor . html_url ,
189- } ,
190- action : actions [ index % actions . length ] ,
191- message : messages [ index % messages . length ] ?. slice ( 0 , 50 ) , // Consistent message length
192- timestamp,
193- timeAgo : formatTimeAgo ( timestamp ) ,
194- } ;
195- } ) ;
198+ return results . sort (
199+ ( a , b ) => b . timestamp . getTime ( ) - a . timestamp . getTime ( ) ,
200+ ) ;
196201 } , [ ] ) ;
197202
198203 // Fetch live data from GitHub
@@ -368,6 +373,26 @@ const FloatingContributors: React.FC<FloatingContributorsProps> = ({
368373 setContributors ( Array . from ( contributorsMap . values ( ) ) ) ;
369374 }
370375 }
376+
377+ // If nothing left after filtering out bots/"other" events, pull the
378+ // repo's real latest push + comments instead of leaving it empty.
379+ const hasVisible = newActivities . some (
380+ ( activity ) =>
381+ ! isBotAccount ( activity . contributor . login ) &&
382+ activity . action !== "other" ,
383+ ) ;
384+ if ( ! hasVisible ) {
385+ const realFallback = await fetchRealFallbackActivities ( ) ;
386+ if ( realFallback . length > 0 ) {
387+ setActivities ( realFallback ) ;
388+ }
389+ }
390+ } else {
391+ // No events at all from the API — use real fallback data.
392+ const realFallback = await fetchRealFallbackActivities ( ) ;
393+ if ( realFallback . length > 0 ) {
394+ setActivities ( realFallback ) ;
395+ }
371396 }
372397
373398 setLastFetched ( now ) ;
@@ -383,32 +408,33 @@ const FloatingContributors: React.FC<FloatingContributorsProps> = ({
383408 } catch ( error ) {
384409 console . warn ( "Error fetching GitHub events:" , error ) ;
385410
386- // Use fallback data if we have no activities yet
411+ // Use the repo's real latest push + comments if we have no activities yet
387412 if ( activities . length === 0 ) {
388- const fallbackActivities = createFallbackActivities ( ) ;
389- setActivities ( fallbackActivities ) ;
390-
391- // Create fallback contributors
392- const contributorsMap = new Map < string , Contributor > ( ) ;
393- fallbackActivities . forEach ( ( activity ) => {
394- const login = activity . contributor . login ;
395- if ( ! contributorsMap . has ( login ) ) {
396- contributorsMap . set ( login , {
397- id : `fallback-${ login } ` ,
398- login,
399- avatar_url : activity . contributor . avatar_url ,
400- contributions : Math . floor ( Math . random ( ) * 50 ) + 10 ,
401- html_url : activity . contributor . html_url ,
402- } ) ;
403- }
404- } ) ;
413+ const realFallback = await fetchRealFallbackActivities ( ) ;
414+ if ( realFallback . length > 0 ) {
415+ setActivities ( realFallback ) ;
416+
417+ const contributorsMap = new Map < string , Contributor > ( ) ;
418+ realFallback . forEach ( ( activity ) => {
419+ const login = activity . contributor . login ;
420+ if ( ! contributorsMap . has ( login ) ) {
421+ contributorsMap . set ( login , {
422+ id : `fallback-${ login } ` ,
423+ login,
424+ avatar_url : activity . contributor . avatar_url ,
425+ contributions : 0 ,
426+ html_url : activity . contributor . html_url ,
427+ } ) ;
428+ }
429+ } ) ;
405430
406- setContributors ( Array . from ( contributorsMap . values ( ) ) ) ;
431+ setContributors ( Array . from ( contributorsMap . values ( ) ) ) ;
432+ }
407433 }
408434
409435 setLoading ( false ) ;
410436 }
411- } , [ activities . length , createFallbackActivities , lastFetched ] ) ;
437+ } , [ activities . length , fetchRealFallbackActivities , lastFetched ] ) ;
412438
413439 // Initialize component and start data fetching
414440 useEffect ( ( ) => {
0 commit comments