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

Handle link clicks in BasicRichTextEditor #1

Closed
wants to merge 11 commits into from
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import com.mohamedrejeb.richeditor.utils.isSpecifiedFieldsEquals
/**
* A rich span is a part of a rich paragraph.
*/
internal class RichSpan(
class RichSpan(
internal val key: Int? = null,
val children: MutableList<RichSpan> = mutableListOf(),
var paragraph: RichParagraph,
Expand Down Expand Up @@ -58,6 +58,60 @@ internal class RichSpan(
return spanStyle
}

val before: RichSpan? get() {
val parentChildren = parent?.children ?: paragraph.children
val index = parentChildren.indexOf(this)

return if (index > 0) {
val beforeChild = parentChildren[index - 1]
if (beforeChild.isEmpty())
beforeChild.before
else
beforeChild
}
else if (parent?.isEmpty() == true)
parent?.before
else
parent
}

/**
* Get the next rich span in the paragraph
*
* @return The next rich span or null if the rich span is the last in the paragraph
*/
val after: RichSpan? get() {
if (children.isNotEmpty())
return children.first()

var child: RichSpan = this
var parent: RichSpan? = parent

while (parent != null) {
val index = parent.children.indexOf(child)
if (index < parent.children.lastIndex) {
val afterChild = parent.children[index + 1]
return if (afterChild.isEmpty())
afterChild.after
else
afterChild
}
child = parent
parent = parent.parent
}

val index = child.paragraph.children.indexOf(child)
return if (index < child.paragraph.children.lastIndex) {
val afterChild = child.paragraph.children[index + 1]
if (afterChild.isEmpty())
afterChild.after
else
afterChild
}
else
null
}

/**
* Check if the rich span is the first in the paragraph
*
Expand Down Expand Up @@ -119,20 +173,22 @@ internal class RichSpan(
/**
* Get the first non-empty child
*
* @param offset The offset of the text range, just used to correct the [RichSpan] text range
*
* @return The first non-empty child or null if there is no non-empty child
*/
internal fun getFirstNonEmptyChild(offset: Int? = null): RichSpan? {
internal fun getFirstNonEmptyChild(offset: Int = -1): RichSpan? {
children.fastForEach { richSpan ->
if (richSpan.text.isNotEmpty()) {
if (offset != null)
if (offset != -1)
richSpan.textRange = TextRange(offset, offset + richSpan.text.length)

return richSpan
}
else {
val result = richSpan.getFirstNonEmptyChild(offset)
if (result != null) {
if (offset != null)
if (offset != -1)
richSpan.textRange = TextRange(offset, offset + richSpan.text.length)

return result
Expand All @@ -142,6 +198,25 @@ internal class RichSpan(
return null
}

/**
* Get the last non-empty child
*
* @return The last non-empty child or null if there is no non-empty child
*/
internal fun getLastNonEmptyChild(): RichSpan? {
for (i in children.lastIndex downTo 0) {
val richSpan = children[i]
if (richSpan.text.isNotEmpty())
return richSpan

val result = richSpan.getLastNonEmptyChild()
if (result != null)
return result
}

return null
}

/**
* Get the rich span by text index
*
Expand Down Expand Up @@ -231,6 +306,14 @@ internal class RichSpan(
return index to richSpanList
}

/**
* Removes the current rich span from its parent and clears its text.
*/
fun remove() {
text = ""
parent?.children?.remove(this)
}

/**
* Remove text range from the rich span
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,19 @@ interface RichSpanStyle {

override val acceptNewTextInTheEdges: Boolean =
false

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is Link) return false

if (url != other.url) return false

return true
}

override fun hashCode(): Int {
return url.hashCode()
}
}

class Code(
Expand Down Expand Up @@ -115,6 +128,24 @@ interface RichSpanStyle {

override val acceptNewTextInTheEdges: Boolean =
true

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is Code) return false

if (cornerRadius != other.cornerRadius) return false
if (strokeWidth != other.strokeWidth) return false
if (padding != other.padding) return false

return true
}

override fun hashCode(): Int {
var result = cornerRadius.hashCode()
result = 31 * result + strokeWidth.hashCode()
result = 31 * result + padding.hashCode()
return result
}
}

object Default : RichSpanStyle {
Expand Down
Loading