feat: Refactor PostDetailModal with unified post type system

- Add unified getPostType() detection for 6 post types: link, story, picture, video, live, camera
- Create dedicated Hero components for each post type
- Quebec511 cameras now use proxy stream /live/api/stream/{id}
- Fix media URLs to use relative paths (same origin)
- Add scroll lock when modal is open
- Generic link display (domain name instead of "Read article")
- Stories with images show gallery, text-only shows gradient
- Support long text content with proper scrolling
- Add i18n keys for modal (EN/FR/ES)
- markerManager.js now dispatches React event for all post types

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Your Name 2026-01-20 05:36:51 +00:00
parent 471d5ab544
commit 37f879556e
6 changed files with 730 additions and 743 deletions

View File

@ -1,7 +1,7 @@
{ {
"name": "sociowire-frontend", "name": "sociowire-frontend",
"private": true, "private": true,
"version": "0.0.66", "version": "0.0.75",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite --host 0.0.0.0", "dev": "vite --host 0.0.0.0",

View File

@ -1189,13 +1189,6 @@ function openCameraOverlay({ map, post, theme, fullScreen, interactionState }) {
export function openCenteredOverlay({ map, post, theme, fullScreen = false }) { export function openCenteredOverlay({ map, post, theme, fullScreen = false }) {
if (!map) return; if (!map) return;
if (post?.content_type === "live") {
try {
window.dispatchEvent(new CustomEvent("livekit-open", { detail: post }));
} catch {}
return;
}
// Weather posts open in a dedicated WeatherModal // Weather posts open in a dedicated WeatherModal
if (post?.content_type === "weather") { if (post?.content_type === "weather") {
try { try {
@ -1204,6 +1197,13 @@ export function openCenteredOverlay({ map, post, theme, fullScreen = false }) {
return; return;
} }
// Use the React PostDetailModal for ALL post types (including live, camera, video, etc.)
try {
window.dispatchEvent(new CustomEvent("sw:openPostDetail", { detail: { post } }));
} catch {}
return;
// LEGACY CODE BELOW - kept for reference but not used anymore
closeCenteredOverlay(map, { force: true, reason: "switch", skipHistory: true }); closeCenteredOverlay(map, { force: true, reason: "switch", skipHistory: true });
const interactionState = { const interactionState = {

File diff suppressed because it is too large Load Diff

View File

@ -283,5 +283,15 @@
"online": "Online", "online": "Online",
"offline": "Offline", "offline": "Offline",
"typing": "typing..." "typing": "typing..."
},
"postModal": {
"readArticle": "Read full article",
"noComments": "No comments yet",
"writeComment": "Write a comment...",
"truthScore": "Truth Score",
"votes": "votes",
"viewers": "viewers",
"streamUnavailable": "Stream unavailable",
"connecting": "Connecting..."
} }
} }

View File

@ -283,5 +283,15 @@
"online": "En línea", "online": "En línea",
"offline": "Desconectado", "offline": "Desconectado",
"typing": "escribiendo..." "typing": "escribiendo..."
},
"postModal": {
"readArticle": "Leer artículo completo",
"noComments": "Sin comentarios aún",
"writeComment": "Escribe un comentario...",
"truthScore": "Puntuación de verdad",
"votes": "votos",
"viewers": "espectadores",
"streamUnavailable": "Stream no disponible",
"connecting": "Conectando..."
} }
} }

View File

@ -286,5 +286,15 @@
"online": "En ligne", "online": "En ligne",
"offline": "Hors ligne", "offline": "Hors ligne",
"typing": "en train d'écrire..." "typing": "en train d'écrire..."
},
"postModal": {
"readArticle": "Lire l'article complet",
"noComments": "Aucun commentaire",
"writeComment": "Écrire un commentaire...",
"truthScore": "Score de vérité",
"votes": "votes",
"viewers": "spectateurs",
"streamUnavailable": "Stream indisponible",
"connecting": "Connexion..."
} }
} }