InstantPage V2: fall back to 600x300 for zero-dimension map blocks

AI/server-sent .map blocks can arrive with dimensions == 0x0 (the wire
w/h are required Int32, but the sender may put 0; our parse and both
serializers preserve whatever arrives). A zero naturalSize.height hit
instantPageV2MediaFrame's else branch and returned a height-0 frame:
the map collapsed to no space, the caption slid up into it, and the V1
node's pin floated over the caption. A zero-sized MapSnapshotMediaResource
would also make MKMapSnapshotter render nothing.

Substitute PixelDimensions(600, 300) (2:1) whenever width <= 0 ||
height <= 0, feeding effectiveDimensions to BOTH the layout naturalSize
AND the InstantPageMapAttribute so the snapshot resource is non-zero and
actually renders. Scoped to the V2 .map arm; V1 (real web articles)
always carries real dimensions and never trips this.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
isaac 2026-06-02 11:36:18 +02:00
parent 9b1573e87e
commit 071799368d
2 changed files with 17 additions and 2 deletions

View file

@ -843,7 +843,21 @@ private func layoutBlock(
horizontalInset: horizontalInset, context: &context)
case let .map(latitude, longitude, zoom, dimensions, caption):
let naturalSize = CGSize(width: CGFloat(dimensions.width), height: CGFloat(dimensions.height))
// AI/server-sent `.map` blocks can arrive with zero `dimensions` (the wire `w`/`h` are
// required, but the sender may put 0). A zero `naturalSize.height` collapses the media
// frame to height 0 (`instantPageV2MediaFrame`'s else branch) the map takes no space,
// the caption slides up into it, and the pin floats over the caption and a zero-sized
// `MapSnapshotMediaResource` makes `MKMapSnapshotter` render nothing. Substitute a sensible
// default (a 2:1 map strip) for BOTH the layout size and the snapshot resource. Real web
// articles (the V1 renderer) always carry real dimensions, so only the rich-message path
// hits this; the fallback is scoped here rather than in V1 or the wire/parse layer.
let effectiveDimensions: PixelDimensions
if dimensions.width > 0 && dimensions.height > 0 {
effectiveDimensions = dimensions
} else {
effectiveDimensions = PixelDimensions(width: 600, height: 300)
}
let naturalSize = CGSize(width: CGFloat(effectiveDimensions.width), height: CGFloat(effectiveDimensions.height))
let map = TelegramMediaMap(
latitude: latitude,
longitude: longitude,
@ -853,7 +867,7 @@ private func layoutBlock(
liveBroadcastingTimeout: nil,
liveProximityNotificationRadius: nil
)
let mapAttributes: [InstantPageImageAttribute] = [InstantPageMapAttribute(zoom: zoom, dimensions: dimensions.cgSize)]
let mapAttributes: [InstantPageImageAttribute] = [InstantPageMapAttribute(zoom: zoom, dimensions: effectiveDimensions.cgSize)]
let mediaIndex = context.mediaIndexCounter
context.mediaIndexCounter += 1
let instantPageMedia = InstantPageMedia(