Trust server RECENT filter in map view
This commit is contained in:
parent
378fd90dcd
commit
9014189e73
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue