fix: no attachment broadcast fix

This commit is contained in:
gosangam
2026-08-29 18:56:45 +05:30
parent 03c8799f22
commit 0f382ed885
4 changed files with 18 additions and 5 deletions
+1 -1
View File
@@ -190,7 +190,7 @@ export function MessageGroup({
{/* An optimistic bubble for a captionless attachment has {/* An optimistic bubble for a captionless attachment has
nothing to draw until the server answers — say so rather nothing to draw until the server answers — say so rather
than render an empty box. */} than render an empty box. */}
{m.pending && !m.body && m.attachments.length === 0 && ( {m.pending && !m.body && !m.attachments?.length && (
<span className="italic opacity-80"> <span className="italic opacity-80">
Sending attachment… Sending attachment…
</span> </span>
+3 -1
View File
@@ -60,7 +60,9 @@ export function BroadcastModal() {
} }
}, [item, dismissing]); }, [item, dismissing]);
if (!item) return null; // Guard on the shape, not just presence: a malformed payload must not put
// an empty modal over every page in the app.
if (!item?.id || !item.title) return null;
return ( return (
<ResponsiveDialog <ResponsiveDialog
+8 -2
View File
@@ -18,8 +18,14 @@ async function call<T>(path: string, init?: RequestInit): Promise<T> {
}); });
if (!res.ok) throw new Error(`broadcast request failed: ${res.status}`); if (!res.ok) throw new Error(`broadcast request failed: ${res.status}`);
if (res.status === 204) return undefined as T; if (res.status === 204) return undefined as T;
const json = await res.json(); const body = (await res.json().catch(() => ({}))) as {
return (json?.data ?? json) as T; data?: T;
success?: boolean;
};
// NOT `body.data ?? body`: /pending answers {data: null} when nothing is
// waiting, and `??` would fall through and hand back the whole envelope —
// which is truthy, so the modal would try to render it as an announcement.
return (body.data ?? (null as unknown as T)) as T;
} }
export type Broadcast = { export type Broadcast = {
+6 -1
View File
@@ -29,10 +29,15 @@ export function buildEntityTree(
body: string, body: string,
entities: MessageEntity[], entities: MessageEntity[],
): EntityNode[] { ): EntityNode[] {
// Defensive on both inputs: this renders content from the network, and a
// missing body should show nothing rather than take down the screen it is
// on. The broadcast modal renders through here too, and it mounts on every
// page — so a crash here is not confined to chat.
const text = body ?? "";
const sorted = [...(entities ?? [])].sort( const sorted = [...(entities ?? [])].sort(
(a, b) => a.offset - b.offset || b.length - a.length, (a, b) => a.offset - b.offset || b.length - a.length,
); );
return build(body, 0, body.length, sorted); return build(text, 0, text.length, sorted);
} }
function build( function build(