From 9014189e731f8c9c41dde42e1330ed1611ab9b88 Mon Sep 17 00:00:00 2001 From: Your Name Date: Tue, 30 Dec 2025 17:42:08 -0500 Subject: [PATCH] Trust server RECENT filter in map view --- src/components/Map/usePostsEngine.js | 100 ++++++++++++++++++++++++--- 1 file changed, 90 insertions(+), 10 deletions(-) diff --git a/src/components/Map/usePostsEngine.js b/src/components/Map/usePostsEngine.js index 3583d92..9f64127 100644 --- a/src/components/Map/usePostsEngine.js +++ b/src/components/Map/usePostsEngine.js @@ -286,11 +286,49 @@ function buildClusterAreaFeatures(posts) { const MAX_POOL_POSTS = 160; const MAX_VISIBLE_POSTS = 45; -function prunePosts(posts, center, maxCount) { +function expandBounds(bounds, padRatio = 0.18) { + if (!bounds) return null; + const spanLat = Math.abs(bounds.maxLat - bounds.minLat); + const spanLon = Math.abs(bounds.maxLon - bounds.minLon); + return { + minLat: bounds.minLat - spanLat * padRatio, + maxLat: bounds.maxLat + spanLat * padRatio, + minLon: bounds.minLon - spanLon * padRatio, + maxLon: bounds.maxLon + spanLon * padRatio, + }; +} + +function inBounds(coords, bounds) { + if (!coords || !bounds) return false; + const [lon, lat] = coords; + return ( + Number.isFinite(lat) && + Number.isFinite(lon) && + lat >= bounds.minLat && + lat <= bounds.maxLat && + lon >= bounds.minLon && + lon <= bounds.maxLon + ); +} + +function prunePosts(posts, center, maxCount, bounds) { if (!Array.isArray(posts) || posts.length <= maxCount) return posts || []; const [centerLon, centerLat] = center || []; const now = Date.now(); - const scored = posts.map((p) => { + const paddedBounds = expandBounds(bounds); + const inView = []; + const outView = []; + + for (const p of posts) { + const coords = getCoords(p); + if (paddedBounds && inBounds(coords, paddedBounds)) { + inView.push(p); + } else { + outView.push(p); + } + } + + const scoreList = (arr) => arr.map((p) => { const coords = getCoords(p); let dist = 99999; if (coords && Number.isFinite(centerLat) && Number.isFinite(centerLon)) { @@ -299,9 +337,22 @@ function prunePosts(posts, center, maxCount) { const ageH = Math.max(0, (now - getPostTimeMs(p)) / 3600000); const score = dist + ageH * 0.4; return { p, score }; - }); - scored.sort((a, b) => a.score - b.score); - return scored.slice(0, maxCount).map((x) => x.p); + }).sort((a, b) => a.score - b.score); + + const picked = []; + const inScored = scoreList(inView); + for (const it of inScored) { + if (picked.length >= maxCount) break; + picked.push(it.p); + } + if (picked.length < maxCount) { + const outScored = scoreList(outView); + for (const it of outScored) { + if (picked.length >= maxCount) break; + picked.push(it.p); + } + } + return picked; } export function usePostsEngine({ @@ -802,7 +853,9 @@ export function usePostsEngine({ if (pc !== catCode) return false; } if (!matchesSubFilter(p, subFilter)) return false; - if (!matchesTimeFilter(effectivePostTime(p), tf)) return false; + const skipTimeFilter = + tf === "RECENT" && lastFetchRef.current?.timeFilter === "RECENT"; + if (!skipTimeFilter && !matchesTimeFilter(effectivePostTime(p), tf)) return false; if (!searchResultsRef.current && !matchesSearch(p, searchQuery)) return false; return true; }); @@ -820,7 +873,16 @@ export function usePostsEngine({ v = filterByBounds(vAll, map); if (v.length > MAX_VISIBLE_POSTS) { const center = map?.getCenter?.(); - v = prunePosts(v, [center?.lng, center?.lat], MAX_VISIBLE_POSTS); + let bounds = null; + try { + const b = map?.getBounds?.(); + if (b) { + const sw = b.getSouthWest(); + const ne = b.getNorthEast(); + bounds = { minLat: sw?.lat, minLon: sw?.lng, maxLat: ne?.lat, maxLon: ne?.lng }; + } + } catch {} + v = prunePosts(v, [center?.lng, center?.lat], MAX_VISIBLE_POSTS, bounds); } } @@ -1017,7 +1079,7 @@ export function usePostsEngine({ } } - allPostsRef.current = prunePosts(Array.from(byId.values()), [lng, lat], MAX_POOL_POSTS); + allPostsRef.current = prunePosts(Array.from(byId.values()), [lng, lat], MAX_POOL_POSTS, bounds); replacePoolRef.current = false; lastFetchRef.current = { center: [...resolvedView.center], radiusKm, filterKey, timeFilter, bounds }; @@ -1125,7 +1187,16 @@ export function usePostsEngine({ if (cancelled) return; const posts = Array.isArray(data?.posts) ? data.posts : []; const normalized = posts.map((p) => normalizePostId(p)); - allPostsRef.current = prunePosts(normalized, [lon, lat], MAX_POOL_POSTS); + let bounds = null; + try { + const b = map?.getBounds?.(); + if (b) { + const sw = b.getSouthWest(); + const ne = b.getNorthEast(); + bounds = { minLat: sw?.lat, minLon: sw?.lng, maxLat: ne?.lat, maxLon: ne?.lng }; + } + } catch {} + allPostsRef.current = prunePosts(normalized, [lon, lat], MAX_POOL_POSTS, bounds); searchResultsRef.current = true; refreshVisibleAndMarkers(timeFilter); trackEvent("search_filter_apply", { @@ -1173,7 +1244,16 @@ export function usePostsEngine({ const map = mapRef.current; const center = map?.getCenter?.(); const normalized = normalizePostId(p); - allPostsRef.current = prunePosts([normalized, ...allPostsRef.current], [center?.lng, center?.lat], MAX_POOL_POSTS); + let bounds = null; + try { + const b = map?.getBounds?.(); + if (b) { + const sw = b.getSouthWest(); + const ne = b.getNorthEast(); + bounds = { minLat: sw?.lat, minLon: sw?.lng, maxLat: ne?.lat, maxLon: ne?.lng }; + } + } catch {} + allPostsRef.current = prunePosts([normalized, ...allPostsRef.current], [center?.lng, center?.lat], MAX_POOL_POSTS, bounds); const catCode = categoryCode(mainFilter); if (catCode) {