feat(location): render MSC3488-only locations (uri + description)

The m.location renderer only read the legacy top-level geo_uri, so a location
from a client that sends only the MSC3488 shape (uri under
org.matrix.msc3488.location / m.location) showed as broken. Fall back to that
uri, and display an MSC3488 description above the coordinates when present.
Closes the consume-side gap noted in review of the send-side MSC3488 change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-10 16:12:01 -04:00
co-authored by Claude Opus 4.8
parent 75b94bd39f
commit ea6e89ae56
2 changed files with 16 additions and 2 deletions
+1 -1
View File
@@ -722,7 +722,7 @@ Images and videos can be sent with a caption. The caption and media are sent as
### Location Sharing
`m.location` events render an inline map tile using the coordinates from the event content.
`m.location` events render an inline map tile using the coordinates from the event content. The renderer reads the top-level `geo_uri` and **falls back to the MSC3488 `org.matrix.msc3488.location`/`m.location` `uri`**, so locations from clients that send only the new shape still render (previously they showed as broken); an MSC3488 `description`, if present, is shown above the coordinates.
Sharing your location (composer → location button) sends an **MSC3488-compliant** `m.location` event: the legacy `geo_uri` plus the `org.matrix.msc3488.location` (uri), `org.matrix.msc3488.asset` (`m.self`), and `org.matrix.msc3488.ts`/`m.ts` blocks, and a human-readable `body`. This makes Lotus-shared locations render as proper pins on Element and other clients instead of falling back to plain text.
@@ -514,7 +514,19 @@ type MLocationProps = {
};
export function MLocation({ content }: MLocationProps) {
const { t } = useTranslation();
const geoUri = content.geo_uri;
// 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
// broken.
const msc3488 = (content['org.matrix.msc3488.location'] ?? content['m.location']) as
| { uri?: string; description?: string }
| undefined;
const geoUri =
typeof content.geo_uri === 'string'
? content.geo_uri
: typeof msc3488?.uri === 'string'
? msc3488.uri
: undefined;
if (typeof geoUri !== 'string') return <BrokenContent />;
const location = parseGeoUri(geoUri);
if (!location) return <BrokenContent />;
@@ -522,6 +534,7 @@ export function MLocation({ content }: MLocationProps) {
const lat = parseFloat(location.latitude);
const lon = parseFloat(location.longitude);
if (!isFinite(lat) || !isFinite(lon)) return <BrokenContent />;
const description = typeof msc3488?.description === 'string' ? msc3488.description : undefined;
const mapSrc = `https://www.openstreetmap.org/export/embed.html?bbox=${lon - 0.007},${
lat - 0.004
},${lon + 0.007},${lat + 0.004}&layer=mapnik&marker=${lat},${lon}`;
@@ -542,6 +555,7 @@ export function MLocation({ content }: MLocationProps) {
loading="lazy"
sandbox="allow-scripts"
/>
{description && <Text size="T300">{description}</Text>}
<Text size="T300" priority="300">
{`${lat.toFixed(5)}, ${lon.toFixed(5)}`}
</Text>