Trust server RECENT filter in map view

This commit is contained in:
Your Name 2025-12-30 17:42:08 -05:00
parent 378fd90dcd
commit 9014189e73
1 changed files with 90 additions and 10 deletions

View File

@ -286,11 +286,49 @@ function buildClusterAreaFeatures(posts) {
const MAX_POOL_POSTS = 160; const MAX_POOL_POSTS = 160;
const MAX_VISIBLE_POSTS = 45; 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 || []; if (!Array.isArray(posts) || posts.length <= maxCount) return posts || [];
const [centerLon, centerLat] = center || []; const [centerLon, centerLat] = center || [];
const now = Date.now(); 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); const coords = getCoords(p);
let dist = 99999; let dist = 99999;
if (coords && Number.isFinite(centerLat) && Number.isFinite(centerLon)) { 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 ageH = Math.max(0, (now - getPostTimeMs(p)) / 3600000);
const score = dist + ageH * 0.4; const score = dist + ageH * 0.4;
return { p, score }; return { p, score };
}); }).sort((a, b) => a.score - b.score);
scored.sort((a, b) => a.score - b.score);
return scored.slice(0, maxCount).map((x) => x.p); 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({ export function usePostsEngine({
@ -802,7 +853,9 @@ export function usePostsEngine({
if (pc !== catCode) return false; if (pc !== catCode) return false;
} }
if (!matchesSubFilter(p, subFilter)) 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; if (!searchResultsRef.current && !matchesSearch(p, searchQuery)) return false;
return true; return true;
}); });
@ -820,7 +873,16 @@ export function usePostsEngine({
v = filterByBounds(vAll, map); v = filterByBounds(vAll, map);
if (v.length > MAX_VISIBLE_POSTS) { if (v.length > MAX_VISIBLE_POSTS) {
const center = map?.getCenter?.(); 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; replacePoolRef.current = false;
lastFetchRef.current = { center: [...resolvedView.center], radiusKm, filterKey, timeFilter, bounds }; lastFetchRef.current = { center: [...resolvedView.center], radiusKm, filterKey, timeFilter, bounds };
@ -1125,7 +1187,16 @@ export function usePostsEngine({
if (cancelled) return; if (cancelled) return;
const posts = Array.isArray(data?.posts) ? data.posts : []; const posts = Array.isArray(data?.posts) ? data.posts : [];
const normalized = posts.map((p) => normalizePostId(p)); 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; searchResultsRef.current = true;
refreshVisibleAndMarkers(timeFilter); refreshVisibleAndMarkers(timeFilter);
trackEvent("search_filter_apply", { trackEvent("search_filter_apply", {
@ -1173,7 +1244,16 @@ export function usePostsEngine({
const map = mapRef.current; const map = mapRef.current;
const center = map?.getCenter?.(); const center = map?.getCenter?.();
const normalized = normalizePostId(p); 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); const catCode = categoryCode(mainFilter);
if (catCode) { if (catCode) {