From a25777a77aab763da3324dbb645f6f360c02bf06 Mon Sep 17 00:00:00 2001 From: Jared Vititoe Date: Sat, 12 Sep 2026 20:28:41 -0400 Subject: [PATCH] fix(privacy): location map loads on click; CollapsibleBody tracks reduced motion live m.location mounted an openstreetmap.org iframe on render, acting as a read beacon; it's now behind a "Load map" button. CollapsibleBody uses useReducedMotion() instead of a one-time matchMedia snapshot. Fixes #66 Fixes #85 Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA --- .../components/message/MsgTypeRenderers.tsx | 54 +++++++++++++------ 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/src/app/components/message/MsgTypeRenderers.tsx b/src/app/components/message/MsgTypeRenderers.tsx index 379068c31..dd2c894a0 100644 --- a/src/app/components/message/MsgTypeRenderers.tsx +++ b/src/app/components/message/MsgTypeRenderers.tsx @@ -15,6 +15,7 @@ import { MessageVerificationRequestContent, } from './content'; import { useMessageTranslation } from '../../hooks/useMessageTranslation'; +import { useReducedMotion } from '../../hooks/useReducedMotion'; import { languageName } from '../../utils/translation/langUtils'; import { IAudioContent, @@ -62,8 +63,9 @@ function CollapsibleBody({ eventId, children }: CollapsibleBodyProps) { return () => observer.disconnect(); }, []); - const prefersReducedMotion = - typeof window !== 'undefined' && window.matchMedia('(prefers-reduced-motion: reduce)').matches; + // A one-time matchMedia() read never updated if the OS setting changed mid-session + // (Gitea #85); useReducedMotion subscribes to the change event instead. + const prefersReducedMotion = useReducedMotion(); return (
@@ -633,6 +635,13 @@ type MLocationProps = { }; export function MLocation({ content }: MLocationProps) { const { t } = useTranslation(); + // The OpenStreetMap iframe used to mount unconditionally on render, silently + // handing the sender's coordinates (and this client's IP/UA) to + // openstreetmap.org for every location message rendered, autoplay or not. + // Gate it behind an explicit click instead (Gitea #66). There's no + // location-specific auto-load setting in settings.ts to opt back into this, + // so it always requires a click. + const [mapLoaded, setMapLoaded] = useState(false); // Prefer the legacy top-level geo_uri, but fall back to the MSC3488 extensible // location block so events from clients that only send the new shape (uri under // org.matrix.msc3488.location / m.location) still render instead of appearing @@ -660,20 +669,33 @@ export function MLocation({ content }: MLocationProps) { return ( -