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_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) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue