diff --git a/github_tracker b/github_tracker new file mode 160000 index 00000000..286b724c --- /dev/null +++ b/github_tracker @@ -0,0 +1 @@ +Subproject commit 286b724c8c203d309f84c09c9f7e835306227040 diff --git a/netlify.toml b/netlify.toml new file mode 100644 index 00000000..f707725b --- /dev/null +++ b/netlify.toml @@ -0,0 +1,17 @@ +[build] + command = "npm install && npm run build" + publish = "dist" + environment = { NODE_VERSION = "18" } + +[[headers]] + for = "/*" + [headers.values] + X-Frame-Options = "DENY" + X-Content-Type-Options = "nosniff" + Referrer-Policy = "strict-origin-when-cross-origin" + Strict-Transport-Security = "max-age=63072000; includeSubDomains; preload" + +[[redirects]] + from = "/*" + to = "/index.html" + status = 200 diff --git a/public/_headers b/public/_headers new file mode 100644 index 00000000..0af4b09d --- /dev/null +++ b/public/_headers @@ -0,0 +1,5 @@ +/* + X-Frame-Options: DENY + X-Content-Type-Options: nosniff + Referrer-Policy: strict-origin-when-cross-origin + Strict-Transport-Security: max-age=63072000; includeSubDomains; preload diff --git a/public/_redirects b/public/_redirects index 4e31746d..5b1b4300 100644 --- a/public/_redirects +++ b/public/_redirects @@ -1,2 +1,2 @@ -/* /index.html 200 +/* /index.html 200 diff --git a/src/components/ActivityFeed.tsx b/src/components/ActivityFeed.tsx index d770dfee..763570ec 100644 --- a/src/components/ActivityFeed.tsx +++ b/src/components/ActivityFeed.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react"; +import { useEffect, useRef, useState } from "react"; interface EventType { id: string; @@ -12,6 +12,8 @@ interface EventType { export default function ActivityFeed({ username }: { username: string }) { const [events, setEvents] = useState([]); const [loading, setLoading] = useState(true); + const isMounted = useRef(true); + const hasLoadedOnce = useRef(false); // 🕒 time ago function const getTimeAgo = (dateString: string) => { @@ -26,27 +28,39 @@ export default function ActivityFeed({ username }: { username: string }) { }; useEffect(() => { - const fetchEvents = async () => { + isMounted.current = true; + + const fetchEvents = async (isBackground = false) => { try { - setLoading(true); + if (!isBackground || !hasLoadedOnce.current) { + setLoading(true); + } const res = await fetch( `https://api.github.com/users/${username}/events` ); const data = await res.json(); - setEvents(data); + if (!isMounted.current) return; + + setEvents(data || []); + hasLoadedOnce.current = true; setLoading(false); } catch (err) { console.error(err); - setLoading(false); + if (isMounted.current) { + setLoading(false); + } } }; fetchEvents(); - const interval = setInterval(fetchEvents, 30000); - return () => clearInterval(interval); + const interval = setInterval(() => fetchEvents(true), 120000); + return () => { + isMounted.current = false; + clearInterval(interval); + }; }, [username]); return (