Files
hanzo.ai/lib/public-activity.ts
zeekay fe79d984ad Expose composer and Settings usage and expand live public activity coverage
Testing: production export, typecheck, mobile/desktop composer and paid-Settings browser gates, historical activity/count unit tests and design lint pass. Risk: organization-scoped read-only usage, labelled estimates, public repository metadata only. How to revert: revert this commit and consume app 0.2.46.
2026-10-27 14:55:30 -07:00

32 lines
1.7 KiB
TypeScript

'use client'
import { useEffect, useState } from 'react'
export interface PublicActivity {
repos: number; orgs: number; active30: number; commits: { year: number; month: number; week: number }
read: string; source: string; complete: boolean; from: string; to: string
daily: Record<string, number>; active: Record<string, number>
latest: { repo: string; sha: string; at: string; message: string; url?: string }[]
}
/** Read only complete historical scans; preserve the build snapshot while mirrors catch up. */
export function usePublicActivity(minimumRepositories: number): PublicActivity | null {
const [data, setData] = useState<PublicActivity | null>(null)
useEffect(() => {
const abort = new AbortController()
const read = async () => {
if (document.visibilityState === 'hidden') return
try {
const response = await fetch('https://forge.hanzo.ai/v1/activity?scope=hanzo', { signal: abort.signal, headers: { Accept: 'application/json' } })
if (!response.ok) return
const next: PublicActivity = await response.json()
if (!abort.signal.aborted && next.complete === true && typeof next.repos === 'number' && next.repos >= minimumRepositories && next.daily && next.commits && Array.isArray(next.latest)) setData(next)
} catch { /* A partial mirror scan cannot replace the last complete snapshot. */ }
}
void read()
const timer = setInterval(read, 30000)
window.addEventListener('focus', read)
document.addEventListener('visibilitychange', read)
return () => { abort.abort(); clearInterval(timer); window.removeEventListener('focus', read); document.removeEventListener('visibilitychange', read) }
}, [minimumRepositories])
return data
}