replaceText static method
Replaces a block-local text range without flattening unaffected rich-text
runs. The inserted text takes the explicitly supplied run attributes
(a null value clears them), or else those of typingStyle or of the run
immediately before/after the caret.
Range endpoints may be supplied in either direction and are clamped to
the block after normalization.
Implementation
static TextStory replaceText({
required TextStory story,
required int blockIndex,
required int start,
required int end,
required String text,
({TextRunAttributes? value})? attributes,
TextRun? typingStyle,
}) {
final block = story.blocks[blockIndex];
final length = block.plainText.length;
final safeStart = math.min(start, end).clamp(0, length);
final safeEnd = math.max(start, end).clamp(0, length);
final insertionStyle = typingStyle ?? _styleAt(block.runs, safeStart);
final replacement = text.isEmpty
? const <TextRun>[]
: [
insertionStyle.copyWith(
text: text,
attributes: attributes == null
? insertionStyle.attributes
: attributes.value,
),
];
final retained = [
...sliceTextRuns(block.runs, 0, safeStart),
...replacement,
...sliceTextRuns(block.runs, safeEnd, length),
];
return story.replaceBlock(
block.copyWith(
runs: retained.isEmpty
? [_styleAt(block.runs, safeStart).copyWith(text: '')]
: _mergeRuns(retained),
),
);
}