From 526ae5832b6696cb2ed2a09a4c19d3cddb47752d Mon Sep 17 00:00:00 2001 From: Renjini R Date: Sat, 13 Jun 2026 18:55:22 +0530 Subject: [PATCH 1/4] fix: nav media query listener leak, case-insensitive channel search, race condition in conduct fetch; feat: random channel button, add Kerala & Tamil Nadu Indian state channels --- channels.json | 15 +++++++++++++++ components/nav.js | 12 ++++++++---- components/slides/Slides.js | 32 ++++++++++++++++++-------------- pages/channels.js | 22 ++++++++++++++++++---- 4 files changed, 59 insertions(+), 22 deletions(-) diff --git a/channels.json b/channels.json index 36b21f5..15cbde7 100644 --- a/channels.json +++ b/channels.json @@ -411,5 +411,20 @@ "type": "island", "url": "https://app.slack.com/client/E09V59WQY1E/C0B7H73EU7L", "id": "C0B7H73EU7L" + }, + { + "channel":"kerala", + "match":"kerala", + "type":"indian-state", + "url": "https://app.slack.com/client/E09V59WQY1E/C08D8B0STPE", + "id":"C08D8B0STPE" + + }, + { + "channel":"tamil-nadu", + "match":"tamil-nadu", + "type":"indian-state", + "url":"https://app.slack.com/client/E09V59WQY1E/C0AU3ELADMK", + "id": "C0AU3ELADMK" } ] diff --git a/components/nav.js b/components/nav.js index d6a3845..4839e38 100644 --- a/components/nav.js +++ b/components/nav.js @@ -158,20 +158,24 @@ function Header({ unfixed, color, bgColor, dark, fixed, ...props }) { } useEffect(() => { - if (typeof window !== 'undefined') { + if (typeof window == 'undefined') return + if (!unfixed) { window.addEventListener('scroll', onScroll) } const mobileQuery = window.matchMedia('(max-width: 48em)') - mobileQuery.addEventListener('change', (e) => { + const handleMobileChange = (e) => { setMobile(e.matches) setToggled(false) - }) - } + } + mobileQuery.addEventListener('change',handleMobileChange) + setMobile(mobileQuery.matches) + return () => { window.removeEventListener('scroll', onScroll) + mobileQuery.removeEventListener('change',handleMobileChange) } }, [unfixed]) diff --git a/components/slides/Slides.js b/components/slides/Slides.js index fe2c2f8..e903d3a 100644 --- a/components/slides/Slides.js +++ b/components/slides/Slides.js @@ -469,22 +469,26 @@ const Slides = ({ isOpen, onClose }) => { return () => window.removeEventListener('keydown', handleKeyDown) }, [isOpen, currentX, currentY, handleAction, onClose]) - useEffect(() => { - if (currentY === 1 && slideData[currentX]?.downSlide?.type === 'fetch') { - setConductData({ content: null, loading: true, error: null }) - fetch('/api/conduct') - .then((res) => { - if (!res.ok) throw new Error('Failed to fetch') + useEffect(()=>{ + if(currentY===1&&slideData[currentX]?.downSlide?.type==='fetch'){ + const controller=new AbortController() + setConductData({content:null,loading:true,error:null}) + fetch('/api/conduct',{signal:controller.signal}) + .then((res)=>{ + if(!res.ok)throw new Error("failed to fetch") return res.text() - }) - .then((html) => { - setConductData({ content: html, loading: false, error: null }) - }) - .catch(() => { - setConductData({ content: null, loading: false, error: true }) - }) + }) + .then((html)=>{ + setConductData({content:html,loading:false,error:null}) + + }) + .catch((err)=>{ + if(err.name==='AbortError')return + setConductData({content:null,loading:false,error:true}) + }) + return()=>controller.abort() } - }, [currentX, currentY]) + },[currentX,currentY]) if (!isOpen) return null diff --git a/pages/channels.js b/pages/channels.js index 343db61..f2933fe 100644 --- a/pages/channels.js +++ b/pages/channels.js @@ -14,6 +14,8 @@ const formatName = (str) => const getTypeLabel = (type) => { if (type === 'us-state') return 'US State' if (type === 'island') return 'Island' + if (type === 'indian-state')return 'Indian State' + return 'Country' } @@ -97,20 +99,24 @@ const FilterButton = ({ active, onClick, children }) => ( {children} ) - +const handleRandomChannel=()=>{ + const random=channels[Math.floor(Math.random()*channels.length)] + window.open(random.url,'_blank','noopener,noreferrer') +} const ChannelsPage = () => { const [search, setSearch] = useState('') const [filter, setFilter] = useState('all') const filtered = useMemo(() => { return channels.filter((c) => { - const matchesSearch = - c.channel.includes(search.toLowerCase()) || - c.match.includes(search.toLowerCase()) + const matchesSearch= + c.channel.toLowerCase().includes(search.toLowerCase())|| + c.match.toLowerCase().includes(search.toLowerCase()) const matchesFilter = filter === 'all' || (filter === 'country' && c.type === 'country') || (filter === 'us-state' && c.type === 'us-state') || + (filter === 'indian-state' && c.type==='indian-state') || (filter === 'island' && c.type === 'island') return matchesSearch && matchesFilter }) @@ -120,7 +126,9 @@ const ChannelsPage = () => { all: channels.length, country: channels.filter((c) => c.type === 'country').length, 'us-state': channels.filter((c) => c.type === 'us-state').length, + 'indian-state':channels.filter((c)=>c.type==='indian-state').length, island: channels.filter((c) => c.type === 'island').length + }), []) return ( @@ -236,6 +244,12 @@ const ChannelsPage = () => { setFilter('island')}> Islands ({counts.island}) + setFilter('indian-state')}> + Indian States({counts['indian-state']}) + + + Random + From d0da73433bf327c4b14ef134078eb112bfeea6cd Mon Sep 17 00:00:00 2001 From: Renjini R Date: Sat, 13 Jun 2026 19:00:35 +0530 Subject: [PATCH 2/4] typo --- components/nav.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/nav.js b/components/nav.js index 4839e38..cee16e9 100644 --- a/components/nav.js +++ b/components/nav.js @@ -158,7 +158,7 @@ function Header({ unfixed, color, bgColor, dark, fixed, ...props }) { } useEffect(() => { - if (typeof window == 'undefined') return + if (typeof window === 'undefined') return if (!unfixed) { window.addEventListener('scroll', onScroll) From ae89d77a63f0a3a2dcf152378047297a85d49407 Mon Sep 17 00:00:00 2001 From: Renjini R Date: Sat, 13 Jun 2026 19:32:39 +0530 Subject: [PATCH 3/4] remove random channel button per review feedback --- pages/channels.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/pages/channels.js b/pages/channels.js index f2933fe..65c14b2 100644 --- a/pages/channels.js +++ b/pages/channels.js @@ -99,10 +99,7 @@ const FilterButton = ({ active, onClick, children }) => ( {children} ) -const handleRandomChannel=()=>{ - const random=channels[Math.floor(Math.random()*channels.length)] - window.open(random.url,'_blank','noopener,noreferrer') -} + const ChannelsPage = () => { const [search, setSearch] = useState('') const [filter, setFilter] = useState('all') @@ -247,9 +244,7 @@ const ChannelsPage = () => { setFilter('indian-state')}> Indian States({counts['indian-state']}) - - Random - + From c1afef8b55673cd8c456813a4c3bfa68178657f2 Mon Sep 17 00:00:00 2001 From: Renjini R Date: Sun, 14 Jun 2026 10:36:26 +0530 Subject: [PATCH 4/4] fix: correct duplicate matchesFilter declaration and formatting --- pages/channels.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pages/channels.js b/pages/channels.js index 65c14b2..b313cf1 100644 --- a/pages/channels.js +++ b/pages/channels.js @@ -15,7 +15,6 @@ const getTypeLabel = (type) => { if (type === 'us-state') return 'US State' if (type === 'island') return 'Island' if (type === 'indian-state')return 'Indian State' - return 'Country' } @@ -105,10 +104,10 @@ const ChannelsPage = () => { const [filter, setFilter] = useState('all') const filtered = useMemo(() => { - return channels.filter((c) => { - const matchesSearch= - c.channel.toLowerCase().includes(search.toLowerCase())|| - c.match.toLowerCase().includes(search.toLowerCase()) + return channels.filter((c) => { + const matchesSearch = + c.channel.toLowerCase().includes(search.toLowerCase()) || + c.match.toLowerCase().includes(search.toLowerCase()) const matchesFilter = filter === 'all' || (filter === 'country' && c.type === 'country') ||