Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix bug with ordered lists #101

Merged
merged 1 commit into from
Sep 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .idea/artifacts/common_desktop_1_0_0_beta02.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/artifacts/common_js_1_0_0_beta02.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/artifacts/desktop_jvm_1_0_0_beta02.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/artifacts/richeditor_compose_desktop_1_0_0_beta02.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/artifacts/richeditor_compose_js_1_0_0_beta02.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/artifacts/web_js_1_0_0_beta02.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/kotlinc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -416,15 +416,19 @@ class RichTextState internal constructor(
previousParagraphType.number + 1
else 1

adjustOrderedListsNumbers(
val newTextFieldValue = adjustOrderedListsNumbers(
startParagraphIndex = index + 1,
startNumber = orderedListNumber + 1,
textFieldValue = textFieldValue,
)

val newType = RichParagraph.Type.OrderedList(number = orderedListNumber)
updateParagraphType(
paragraph = paragraph,
newType = newType
updateTextFieldValue(
newTextFieldValue = updateParagraphType(
paragraph = paragraph,
newType = newType,
textFieldValue = newTextFieldValue,
),
)
}

Expand All @@ -443,54 +447,61 @@ class RichTextState internal constructor(
resetParagraphType(paragraph = paragraph)
}

private fun updateParagraphType(paragraph: RichParagraph, newType: RichParagraph.Type) {
private fun updateParagraphType(
paragraph: RichParagraph,
newType: RichParagraph.Type,
) {
updateTextFieldValue(
newTextFieldValue = updateParagraphType(
paragraph = paragraph,
newType = newType,
textFieldValue = this.textFieldValue,
)
)
}

private fun updateParagraphType(
paragraph: RichParagraph,
newType: RichParagraph.Type,
textFieldValue: TextFieldValue,
): TextFieldValue {
val selection = textFieldValue.selection
val paragraphOldStartTextLength = paragraph.type.startText.length
val paragraphFirstChildStartIndex = paragraph.getFirstNonEmptyChild()?.textRange?.min ?: selection.min
val textFieldValueDiff = this.textFieldValue.text.length - textFieldValue.text.length
val firstNonEmptyChildIndex = paragraph.getFirstNonEmptyChild()?.textRange?.min?.let {
if (it >= selection.min) it - textFieldValueDiff
else it
}
val paragraphFirstChildStartIndex = firstNonEmptyChildIndex ?: selection.min

paragraph.type = newType

// If the paragraph type start text length didn't change, we don't need to update the text field value
if (paragraphOldStartTextLength == newType.startText.length) return textFieldValue

val beforeText = textFieldValue.text.substring(0, paragraphFirstChildStartIndex - paragraphOldStartTextLength)
val afterText = textFieldValue.text.substring(paragraphFirstChildStartIndex)

val newSelectionMin =
if (selection.min > paragraphFirstChildStartIndex) selection.min + newType.startText.length - paragraphOldStartTextLength
else paragraphFirstChildStartIndex + newType.startText.length - paragraphOldStartTextLength
else if (selection.min == paragraphFirstChildStartIndex) paragraphFirstChildStartIndex + newType.startText.length - paragraphOldStartTextLength
else selection.min
val newSelectionMax =
if (selection.max > paragraphFirstChildStartIndex) selection.max + newType.startText.length - paragraphOldStartTextLength
else paragraphFirstChildStartIndex + newType.startText.length - paragraphOldStartTextLength
updateTextFieldValue(
newTextFieldValue = textFieldValue.copy(
text = beforeText + newType.startText + afterText,
selection = TextRange(
newSelectionMin,
newSelectionMax,
),
)
else if (selection.max == paragraphFirstChildStartIndex) paragraphFirstChildStartIndex + newType.startText.length - paragraphOldStartTextLength
else selection.max

return textFieldValue.copy(
text = beforeText + newType.startText + afterText,
selection = TextRange(
newSelectionMin,
newSelectionMax,
),
)
}

private fun resetParagraphType(paragraph: RichParagraph) {
val paragraphStartIndex = paragraph.getFirstNonEmptyChild()?.textRange?.min ?: selection.min

val oldType = paragraph.type
paragraph.type = RichParagraph.Type.Default

val beforeText = textFieldValue.text.substring(0, paragraphStartIndex - oldType.startText.length)
val afterText = textFieldValue.text.substring(paragraphStartIndex)
val newSelectionMin =
if (selection.min > paragraphStartIndex) selection.min - oldType.startText.length
else paragraphStartIndex - oldType.startText.length
val newSelectionMax =
if (selection.max > paragraphStartIndex) selection.max - oldType.startText.length
else paragraphStartIndex - oldType.startText.length
updateTextFieldValue(
newTextFieldValue = textFieldValue.copy(
text = beforeText + afterText,
selection = TextRange(
newSelectionMin,
newSelectionMax
),
)
)
updateParagraphType(paragraph, RichParagraph.Type.Default)
}

/**
Expand Down Expand Up @@ -727,8 +738,11 @@ class RichTextState internal constructor(
// Check deleted paragraphs
val minParagraphIndex = richParagraphList.indexOf(minRichSpan.paragraph)
val maxParagraphIndex = richParagraphList.indexOf(maxRichSpan.paragraph)
if (minParagraphIndex < maxParagraphIndex - 1 && !singleParagraphMode)

// Remove paragraphs between the min and max paragraphs
if (minParagraphIndex < maxParagraphIndex - 1 && !singleParagraphMode) {
richParagraphList.removeRange(minParagraphIndex + 1, maxParagraphIndex)
}

// Get the first non-empty child of the min paragraph
val minFirstNonEmptyChild = minRichSpan.paragraph.getFirstNonEmptyChild()
Expand Down Expand Up @@ -758,6 +772,12 @@ class RichTextState internal constructor(
)

minRichSpan.paragraph.type = RichParagraph.Type.Default

tempTextFieldValue = adjustOrderedListsNumbers(
startParagraphIndex = minParagraphIndex + 1,
startNumber = 1,
textFieldValue = tempTextFieldValue,
)
}

// Handle Remove the max paragraph custom text
Expand All @@ -770,6 +790,12 @@ class RichTextState internal constructor(
)

maxRichSpan.paragraph.type = RichParagraph.Type.Default

tempTextFieldValue = adjustOrderedListsNumbers(
startParagraphIndex = maxParagraphIndex + 1,
startNumber = 1,
textFieldValue = tempTextFieldValue,
)
}

// Remove spans from the max paragraph
Expand Down Expand Up @@ -910,17 +936,24 @@ class RichTextState internal constructor(
private fun adjustOrderedListsNumbers(
startParagraphIndex: Int,
startNumber: Int,
) {
textFieldValue: TextFieldValue,
): TextFieldValue {
var newTextFieldValue = textFieldValue
var number = startNumber
// Update the paragraph type of the paragraphs after the new paragraph
for (i in (startParagraphIndex)..richParagraphList.lastIndex) {
for (i in (startParagraphIndex)..(richParagraphList.lastIndex)) {
val currentParagraph = richParagraphList[i]
val currentParagraphType = currentParagraph.type
if (currentParagraphType is RichParagraph.Type.OrderedList) {
currentParagraph.type = RichParagraph.Type.OrderedList(number = number)
newTextFieldValue = updateParagraphType(
paragraph = currentParagraph,
newType = RichParagraph.Type.OrderedList(number = number),
textFieldValue = newTextFieldValue,
)
} else break
number++
}
return newTextFieldValue
}

private fun checkOrderedListsNumbers(
Expand All @@ -938,7 +971,11 @@ class RichTextState internal constructor(
val currentParagraph = richParagraphList[i]
val currentParagraphType = currentParagraph.type
if (currentParagraphType is RichParagraph.Type.OrderedList) {
currentParagraph.type = RichParagraph.Type.OrderedList(number = number)
tempTextFieldValue = updateParagraphType(
paragraph = currentParagraph,
newType = RichParagraph.Type.OrderedList(number = number),
textFieldValue = tempTextFieldValue,
)
number++
}
else if (i >= endParagraphIndex) break
Expand Down Expand Up @@ -1002,9 +1039,10 @@ class RichTextState internal constructor(
// Update the paragraph type of the paragraphs after the new paragraph
val newParagraphType = newParagraph.type
if (newParagraphType is RichParagraph.Type.OrderedList) {
adjustOrderedListsNumbers(
tempTextFieldValue = adjustOrderedListsNumbers(
startParagraphIndex = paragraphIndex + 2,
startNumber = newParagraphType.number + 1,
textFieldValue = tempTextFieldValue,
)
}

Expand Down
2 changes: 1 addition & 1 deletion sample/common/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ kotlin {
implementation(libs.voyager.navigator)

// WindowInsets
// implementation("com.moriatsushi.insetsx:insetsx:0.1.0-alpha10")
implementation("com.moriatsushi.insetsx:insetsx:0.1.0-alpha10")
}
}

Expand Down