Skip to content

Commit

Permalink
Merge pull request #363 from MohamedRejeb/1.x
Browse files Browse the repository at this point in the history
Fix adding newline toggles back removed span style
  • Loading branch information
MohamedRejeb authored Sep 29, 2024
2 parents d07edeb + 4367b28 commit 116d616
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1400,6 +1400,29 @@ public class RichTextState internal constructor(
}
}

// Set current applied style to min rich span if the paragraph is empty
if (
config.preserveStyleOnEmptyLine &&
minRichSpan.paragraph.isEmpty()
) {
val minParagraphFirstRichSpan =
minRichSpan.paragraph.getFirstNonEmptyChild() ?: run {
val richSpan =
RichSpan(
paragraph = minRichSpan.paragraph,
text = "",
textRange = TextRange(minRemoveIndex, minRemoveIndex),
)

minRichSpan.paragraph.children.add(richSpan)

richSpan
}

minParagraphFirstRichSpan.spanStyle = currentAppliedSpanStyle
minParagraphFirstRichSpan.richSpanStyle = currentAppliedRichSpanStyle
}

checkOrderedListsNumbers(
startParagraphIndex = minParagraphIndex - 1,
endParagraphIndex = minParagraphIndex + 1,
Expand Down Expand Up @@ -1602,13 +1625,22 @@ public class RichTextState internal constructor(
if (tempTextFieldValue.selection.collapsed && newParagraph.isEmpty()) {
val newParagraphFirstRichSpan = newParagraph.getFirstNonEmptyChild()

val isSelectionAtNewRichSpan =
newParagraphFirstRichSpan?.textRange?.min == tempTextFieldValue.selection.min - 1

// Check if the cursor is at the new paragraph
if (
(!config.preserveStyleOnEmptyLine || richSpan.paragraph.isEmpty()) &&
newParagraphFirstRichSpan?.textRange?.min == tempTextFieldValue.selection.min - 1
isSelectionAtNewRichSpan
) {
newParagraphFirstRichSpan.spanStyle = SpanStyle()
newParagraphFirstRichSpan.richSpanStyle = RichSpanStyle.Default
} else if (
config.preserveStyleOnEmptyLine &&
isSelectionAtNewRichSpan
) {
newParagraphFirstRichSpan.spanStyle = currentSpanStyle
newParagraphFirstRichSpan.richSpanStyle = currentRichSpanStyle
}
}

Expand Down Expand Up @@ -2250,10 +2282,11 @@ public class RichTextState internal constructor(
var previousRichSpan: RichSpan
var currentRichSpan: RichSpan = richSpan

val textStartIndex = if (startIndex == type.startRichSpan.textRange.min)
startIndex - richSpan.textRange.min + type.startRichSpan.text.length
else
startIndex - richSpan.textRange.min
val textStartIndex =
if (startIndex == type.startRichSpan.textRange.min)
startIndex - richSpan.textRange.min + type.startRichSpan.text.length
else
startIndex - richSpan.textRange.min

newRichParagraph.type.startRichSpan.paragraph = newRichParagraph
newRichParagraph.type.startRichSpan.textRange = TextRange(
Expand All @@ -2279,6 +2312,7 @@ public class RichTextState internal constructor(
richSpan.textRange.min + beforeText.length
)

// We don't copy the current rich span style to the new rich span
val newRichSpan = RichSpan(
paragraph = newRichParagraph,
parent = null,
Expand Down Expand Up @@ -2441,28 +2475,28 @@ public class RichTextState internal constructor(
if (selection.collapsed) {
val richSpan = getRichSpanByTextIndex(textIndex = selection.min - 1)

if (
config.preserveStyleOnEmptyLine &&
(richSpan == null || (richSpan.isFirstInParagraph && richSpan.paragraph.isEmpty()))
) {
val paragraphBefore =
if (selection.min - 2 < 0)
null
else
getRichParagraphByTextIndex(selection.min - 2)

if (paragraphBefore?.isEmpty() != true) {
toAddRichSpanStyle = currentAppliedRichSpanStyle
toAddSpanStyle = currentAppliedSpanStyle
}
}

currentAppliedRichSpanStyle = richSpan
?.fullStyle
?: RichSpanStyle.Default
currentAppliedSpanStyle = richSpan
?.fullSpanStyle
?: RichSpanStyle.DefaultSpanStyle

// if (
// config.preserveStyleOnEmptyLine &&
// (richSpan == null || (richSpan.isFirstInParagraph && richSpan.paragraph.isEmpty()))
// ) {
// val paragraphBefore =
// if (selection.min - 2 < 0)
// null
// else
// getRichParagraphByTextIndex(selection.min - 2)
//
// if (paragraphBefore == null || paragraphBefore.isNotEmpty()) {
// toAddRichSpanStyle = currentRichSpanStyle
// toAddSpanStyle = currentSpanStyle
// }
// }
} else {
val richSpanList = getRichSpanListByTextRange(selection)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,22 +107,27 @@ internal class RichParagraph(
): RichParagraph? {
var index = offset
val toRemoveIndices = mutableListOf<Int>()

for (i in 0..children.lastIndex) {
val child = children[i]
val result = child.removeTextRange(textRange, index)
val newRichSpan = result.second
if (newRichSpan != null) {

if (newRichSpan != null)
children[i] = newRichSpan
} else {
else
toRemoveIndices.add(i)
}

index = result.first
}

for (i in toRemoveIndices.lastIndex downTo 0) {
children.removeAt(toRemoveIndices[i])
}

if (children.isEmpty()) return null
if (children.isEmpty())
return null

return this
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -694,4 +694,103 @@ class RichTextStateTest {
assertEquals("Hello\nb", richTextState.toText())
}

@OptIn(ExperimentalRichTextApi::class)
@Test
fun testKeepStyleChangesOnLineBreak() {
val richTextState = RichTextState(
initialRichParagraphList = listOf(
RichParagraph(
key = 1,
).also {
it.children.add(
RichSpan(
text = "Hello",
paragraph = it,
spanStyle = SpanStyle(fontWeight = FontWeight.Bold, fontStyle = FontStyle.Italic),
),
)
}
)
)

richTextState.selection = TextRange(5)
richTextState.toggleSpanStyle(SpanStyle(fontWeight = FontWeight.Bold))
richTextState.toggleCodeSpan()
richTextState.onTextFieldValueChange(
TextFieldValue(
text = "Hello\n",
selection = TextRange(6),
)
)

assertEquals("Hello\n", richTextState.toText())
assertEquals(SpanStyle(fontStyle = FontStyle.Italic), richTextState.currentSpanStyle)
assertIs<RichSpanStyle.Code>(richTextState.currentRichSpanStyle)
}

@OptIn(ExperimentalRichTextApi::class)
@Test
fun testKeepSpanStylesOnLineBreakOnTheMiddleOrParagraph() {
val spanStyle = SpanStyle(fontWeight = FontWeight.Bold, fontStyle = FontStyle.Italic)

val richTextState = RichTextState(
initialRichParagraphList = listOf(
RichParagraph(
key = 1,
).also {
it.children.add(
RichSpan(
text = "Hello",
paragraph = it,
spanStyle = spanStyle,
),
)
}
)
)

richTextState.selection = TextRange(3)
richTextState.onTextFieldValueChange(
TextFieldValue(
text = "Hel\nlo",
selection = TextRange(4),
)
)

assertEquals("Hel\nlo", richTextState.toText())
assertEquals(spanStyle, richTextState.currentSpanStyle)
}

@OptIn(ExperimentalRichTextApi::class)
@Test
fun testResetRichSpanStylesOnLineBreakOnTheMiddleOrParagraph() {

val richTextState = RichTextState(
initialRichParagraphList = listOf(
RichParagraph(
key = 1,
).also {
it.children.add(
RichSpan(
text = "Hello",
paragraph = it,
richSpanStyle = RichSpanStyle.Code(),
),
)
}
)
)

richTextState.selection = TextRange(3)
richTextState.onTextFieldValueChange(
TextFieldValue(
text = "Hel\nlo",
selection = TextRange(4),
)
)

assertEquals("Hel\nlo", richTextState.toText())
assertIs<RichSpanStyle.Default>(richTextState.currentRichSpanStyle)
}

}

0 comments on commit 116d616

Please sign in to comment.