Smooth filter transitions

This commit is contained in:
Your Name 2025-12-31 02:36:59 -05:00
parent 0647dc823b
commit c955b122e3
4 changed files with 75 additions and 14 deletions

View File

@ -33,7 +33,7 @@ export default function MapView({
onOpenIslands,
}) {
const { authenticated, username, token, needsEmailVerification } = useAuth();
const CLUSTERS_ENABLED = true;
const CLUSTERS_ENABLED = false;
const HEATMAP_ENABLED = false;
const { containerRef, mapRef, markersRef, expandedElRef, viewParams, hasLastView } =
@ -53,6 +53,15 @@ export default function MapView({
const [subFilter, setSubFilter] = useState("All");
const [mainNewsOnly, setMainNewsOnly] = useState(false);
const debugEnabled = (() => {
try {
return typeof window !== "undefined" &&
new URLSearchParams(window.location.search || "").has("debug");
} catch {
return false;
}
})();
useEffect(() => {
try {
localStorage.setItem(TIME_FILTER_KEY, String(timeHours));
@ -157,7 +166,7 @@ export default function MapView({
[mapRef]
);
const { status, visiblePosts, loadingPosts, loadError, handleIncomingPost, handlePostUpdate } =
const { status, debugStatus, visiblePosts, loadingPosts, loadError, handleIncomingPost, handlePostUpdate } =
usePostsEngine({
theme,
mapRef,
@ -176,6 +185,7 @@ export default function MapView({
onAutoWidenTimeFilter: () => setTimeHours(336),
onSelectPost,
username,
debugEnabled,
});
const [isCreating, setIsCreating] = useState(false);
@ -324,15 +334,24 @@ export default function MapView({
if (queryPostRef.current) return;
const qs = new URLSearchParams(window.location.search || "");
let idRaw = qs.get("post_id") || qs.get("id") || qs.get("p");
let wasSharedLink = false;
if (!idRaw) {
const path = (window.location.pathname || "").trim();
const m = path.match(/^\/p\/(\d+)/);
if (m && m[1]) {
idRaw = m[1];
wasSharedLink = true;
// Clean URL immediately - no post_id in URL, just stay on root
try {
window.history.replaceState(null, "", `/?post_id=${m[1]}`);
window.history.replaceState(null, "", "/");
} catch {}
}
} else {
// If arrived with ?post_id=123, also clean it
wasSharedLink = true;
try {
window.history.replaceState(null, "", "/");
} catch {}
}
if (!idRaw) return;
queryPostRef.current = true;
@ -1211,6 +1230,47 @@ export default function MapView({
<div className="map-stage" ref={stageRef}>
<div ref={containerRef} className="map-container" />
{status && <div className="map-status">{status}</div>}
{debugEnabled && (
<>
<div
className="sw-debug-banner"
style={{
position: "fixed",
top: 62,
left: 8,
zIndex: 99999,
padding: "6px 8px",
background: "rgba(0,0,0,0.8)",
color: "#fff",
fontSize: 12,
borderRadius: 6,
maxWidth: "92vw",
pointerEvents: "none",
}}
>
{debugStatus || "debug active"}
</div>
<div
style={{
position: "fixed",
bottom: 0,
left: 0,
right: 0,
zIndex: 99999,
background: "#ffea00",
color: "#111",
fontWeight: 700,
fontSize: 14,
textAlign: "center",
padding: "4px 0",
letterSpacing: "0.08em",
pointerEvents: "none",
}}
>
DEV DEBUG
</div>
</>
)}
{/* TOP: Search avec suggestions intelligentes */}
<div className="map-overlay map-overlay-top">

View File

@ -372,6 +372,7 @@ export function usePostsEngine({
onAutoWidenTimeFilter,
onSelectPost,
username,
debugEnabled = false,
theme = "blue",
}) {
const allPostsRef = useRef([]);
@ -707,6 +708,7 @@ export function usePostsEngine({
);
const [status, setStatus] = useState("");
const [debugStatus, setDebugStatus] = useState("debug active");
const [visiblePosts, setVisiblePosts] = useState([]);
const [loadingPosts, setLoadingPosts] = useState(false);
const [loadError, setLoadError] = useState("");
@ -735,12 +737,6 @@ export function usePostsEngine({
fullCardPosts = prioritized.fullCardPosts;
simpleMarkerPosts = prioritized.simpleMarkerPosts;
console.log('[usePostsEngine] Prioritized:', {
total: visible.length,
fullCards: fullCardPosts.length,
simpleMarkers: simpleMarkerPosts.length
});
// Combine both types for "wanted" tracking
const wanted = new Map();
for (const post of visible) {
@ -823,8 +819,7 @@ export function usePostsEngine({
replacePoolRef.current = true;
pendingFilterRef.current = `${mainFilter}|${subFilter}|${timeHours}`;
allPostsRef.current = [];
setVisiblePosts([]);
syncMarkers([]);
autoWidenRef.current = false; // Reset auto-widen when user manually changes filter
if (map && clustersEnabled && heatmapEnabled) {
updateClusterAreas(map, []);
}
@ -836,7 +831,7 @@ export function usePostsEngine({
} catch {}
}, 60);
}
}, [mainFilter, subFilter, timeHours, mapRef, syncMarkers, clustersEnabled, heatmapEnabled, updateClusterAreas]);
}, [mainFilter, subFilter, timeHours, mapRef, clustersEnabled, heatmapEnabled, updateClusterAreas]);
const computeVisible = useCallback(
(tf) => {
@ -1104,6 +1099,11 @@ export function usePostsEngine({
// Smooth update: sync markers/clusters + wall without clearing everything
refreshVisibleAndMarkers(timeHours);
const visible = computeVisible(timeHours);
if (debugEnabled) {
const count = Array.isArray(newPosts) ? newPosts.length : 0;
const q = (searchQuery || "").trim();
setDebugStatus(`tf:${timeHours || 0} fetched:${count} visible:${visible.length}${q ? ` q:${q}` : ""}`);
}
const now = Date.now();
if (now - analyticsDebounceRef.current > 4000) {
analyticsDebounceRef.current = now;
@ -1387,5 +1387,5 @@ export function usePostsEngine({
[mapRef, refreshVisibleAndMarkers, timeHours]
);
return { status, visiblePosts, loadingPosts, loadError, handleIncomingPost, handlePostUpdate };
return { status, debugStatus, visiblePosts, loadingPosts, loadError, handleIncomingPost, handlePostUpdate };
}

View File

@ -121,4 +121,4 @@
}
/* Espace pour les bulles */
.below-stage { padding-bottom: 70px; }
.below-stage { padding-bottom: 70px; }

View File

@ -48,6 +48,7 @@
position:relative;
z-index:25;
padding: .25rem .7rem 1.0rem;
transition: opacity 320ms ease, filter 320ms ease;
}
.below-row{