fix(app): render inline links via UITextView span on iOS (#1257)

AssistantMarkdownLink's native branch wrapped its children in a plain RN
<Text>. On iOS that <Text> sits inside the paragraph's native UITextView
and is not hoisted into a UITextViewChild, so link text (markdown links,
bare URLs, and inline-code path links) was silently dropped — the same
root cause as the bold/italic/strikethrough fix in this PR.

Route the native link through MarkdownTextSpan so it composes as a
UITextViewChild and stays visible + selectable. MarkdownTextSpan now
forwards onPress/accessibilityRole across platforms: tappable on
Android/web; on iOS react-native-uitextview nulls onPress on the root
native view, so reliable tap-to-open is still tracked by #21 — but
visible, selectable, copyable link text strictly beats an invisible one.

Refs #1253

Co-authored-by: Geoffrey <geoffrey.marc@consulting-for.edenred.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Geoffrey Marc
2026-06-01 11:29:59 +08:00
committed by GitHub
co-authored by Geoffrey Claude Opus 4.8
parent 632c48fde3
commit a3b0af9ac0
4 changed files with 76 additions and 13 deletions
@@ -9,6 +9,7 @@ import {
} from "react-native";
import { StyleSheet } from "react-native-unistyles";
import { isNative, isWeb } from "@/constants/platform";
import { MarkdownTextSpan } from "@/components/markdown-text";
import { Shortcut } from "@/components/ui/shortcut";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
import { useStableEvent } from "@/hooks/use-stable-event";
@@ -57,16 +58,21 @@ export function AssistantMarkdownLink({
);
if (isNative) {
// Must be a MarkdownTextSpan, not a plain <Text>: on iOS the link renders
// inside the paragraph's native UITextView, and a plain <Text> nested there
// is not hoisted into a UITextViewChild, so its text is silently dropped
// (the link disappears). The span composes correctly and stays selectable;
// onPress is forwarded (reliable tap-to-open on iOS is tracked by #21).
return (
<FileLinkHoverTooltip filePath={tooltipPath}>
<Text
<MarkdownTextSpan
accessibilityRole="link"
dataSet={monoSurface ? CODE_SURFACE_DATASET : undefined}
monoSurface={monoSurface}
onPress={onPress}
style={style}
>
{children}
</Text>
</MarkdownTextSpan>
</FileLinkHoverTooltip>
);
}