Skip to content

Commit 10c95a5

Browse files
committed
WIP - Updated AGP dependency and fixed add characters logic
1 parent acaf3be commit 10c95a5

File tree

4 files changed

+135
-159
lines changed

4 files changed

+135
-159
lines changed
+1-100
Original file line numberDiff line numberDiff line change
@@ -1,102 +1,3 @@
11
{
2-
"spans": [
3-
{
4-
"insert": "Android Quill",
5-
"attributes": {
6-
"bold": true,
7-
"header": 1
8-
}
9-
},
10-
{
11-
"insert": "\n"
12-
},
13-
{
14-
"insert": "\nRich",
15-
"attributes": {
16-
"bold": true,
17-
"header": 2
18-
}
19-
},
20-
{
21-
"insert": " text ",
22-
"attributes": {
23-
"header": 2
24-
}
25-
},
26-
{
27-
"insert": "editor for Android",
28-
"attributes": {
29-
"bold": true,
30-
"header": 2
31-
}
32-
},
33-
{
34-
"insert": "\n"
35-
},
36-
{
37-
"insert": "Quill component for Android\n",
38-
"attributes": {
39-
"header": 3,
40-
"italic": true
41-
}
42-
},
43-
{
44-
"insert": "Bullet Journal",
45-
"attributes": {
46-
"bold": true
47-
}
48-
},
49-
{
50-
"insert": ":\nTrack personal and group journals (ToDo, Note, Ledger) from multiple views with timely reminders",
51-
"attributes": {
52-
"bold": true
53-
}
54-
},
55-
{
56-
"insert": "\n"
57-
},
58-
{
59-
"insert": "Share your tasks and notes with teammates, and see changes as they happen in real-time, across all devices",
60-
"attributes": {}
61-
},
62-
{
63-
"insert": "\n"
64-
},
65-
{
66-
"insert": "Splitting bills with friends can never be easier.",
67-
"attributes": {
68-
"list": "bullet"
69-
}
70-
},
71-
{
72-
"insert": "\n"
73-
},
74-
{
75-
"insert": "Testing span addition to the editor.",
76-
"attributes": {
77-
"list": "bullet"
78-
}
79-
},
80-
{
81-
"insert": "\n"
82-
},
83-
{
84-
"insert": "Start creating a group and invite your friends to join.",
85-
"attributes": {
86-
"list": "bullet"
87-
}
88-
},
89-
{
90-
"insert": "\n"
91-
},
92-
{
93-
"insert": "Create a BuJo of Ledger type to see expense or balance summary.",
94-
"attributes": {
95-
"list": "bullet"
96-
}
97-
},
98-
{
99-
"insert": "\n"
100-
}
101-
]
2+
"spans": [{"insert":"Android Quill","attributes":{"bold":true,"header":1}},{"insert":"\n","attributes":{}},{"insert":"\nRich text editor for Android","attributes":{"bold":true,"header":2}},{"insert":"\n","attributes":{}},{"insert":"Quill component for Android\n","attributes":{"header":3,"italic":true}},{"insert":"Bullet Journal :\nTrack personal and group journals (ToDo, Note, Ledger) from multiple views with timely reminders","attributes":{"bold":true}},{"insert":"\nShare your tasks and notes with teammates, and see changes as they happen in real-time, across all devices\n","attributes":{}},{"insert":"Splitting bills with friends can never be easier.","attributes":{"list":"bullet"}},{"insert":"\n","attributes":{}},{"insert":"Testing span addition to the editor.","attributes":{"list":"bullet"}},{"insert":"\n","attributes":{}},{"insert":"Start creating a group and invite your friends to join.","attributes":{"list":"bullet"}},{"insert":"\n","attributes":{}},{"insert":"Create a BuJo of Ledger type to see expense or balance summary.","attributes":{"bold":true,"list":"bullet"}},{"insert":"\n","attributes":{}}]
1023
}

build.gradle

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Top-level build file where you can add configuration options common to all sub-projects/modules.
22
plugins {
3-
id 'com.android.application' version '8.0.2' apply false
4-
id 'com.android.library' version '8.0.2' apply false
3+
id 'com.android.application' version '8.2.1' apply false
4+
id 'com.android.library' version '8.2.1' apply false
55
id 'org.jetbrains.kotlin.android' version '1.7.20' apply false
66
id 'io.github.gradle-nexus.publish-plugin' version "1.3.0"
77
}

editor/src/main/java/com/canopas/editor/ui/data/QuillTextManager.kt

+131-56
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class QuillTextManager(quillSpan: QuillSpan) {
3232
val endIndex = fromIndex + (span.insert?.length ?: 0) - 1
3333

3434
attributes?.let {
35-
val style = mutableListOf<TextSpanStyle>()
35+
val textSpanStyles = mutableListOf<TextSpanStyle>()
3636

3737
if (it.header != null) {
3838
when (it.header) {
@@ -43,30 +43,30 @@ class QuillTextManager(quillSpan: QuillSpan) {
4343
5 -> TextSpanStyle.H5Style
4444
6 -> TextSpanStyle.H6Style
4545
else -> null
46-
}?.let { it1 -> style.add(it1) }
46+
}?.let { headerStyle -> textSpanStyles.add(headerStyle) }
4747
}
4848

4949
if (it.bold == true) {
50-
style.add(TextSpanStyle.BoldStyle)
50+
textSpanStyles.add(TextSpanStyle.BoldStyle)
5151
}
5252

5353
if (it.italic == true) {
54-
style.add(TextSpanStyle.ItalicStyle)
54+
textSpanStyles.add(TextSpanStyle.ItalicStyle)
5555
}
5656

5757
if (it.underline == true) {
58-
style.add(TextSpanStyle.UnderlineStyle)
58+
textSpanStyles.add(TextSpanStyle.UnderlineStyle)
5959
}
6060

6161
if (it.list == ListType.bullet) {
62-
style.add(TextSpanStyle.BulletStyle)
62+
textSpanStyles.add(TextSpanStyle.BulletStyle)
6363
}
6464

6565
quillTextSpans.add(
6666
QuillTextSpan(
6767
from = fromIndex,
6868
to = endIndex,
69-
style = style
69+
style = textSpanStyles
7070
)
7171
)
7272
} ?: run {
@@ -108,6 +108,11 @@ class QuillTextManager(quillSpan: QuillSpan) {
108108
val nextSpan = quillTextSpans.getOrNull(index + 1)
109109
val nextInsert =
110110
nextSpan?.let { editableText.substring(nextSpan.from, nextSpan.to + 1) }
111+
if (insert.last() != ' ' && insert.last() != '\n' && nextInsert != null &&
112+
nextInsert.first() != ' ' && nextInsert.first() != '\n'
113+
) {
114+
insert += " "
115+
}
111116
if (nextInsert == " " || nextInsert == "") {
112117
insert += nextInsert
113118
}
@@ -131,18 +136,6 @@ class QuillTextManager(quillSpan: QuillSpan) {
131136
return QuillSpan(groupedSpans)
132137
}
133138

134-
private fun TextSpanStyle.headerLevel(): Int? {
135-
return when (this) {
136-
TextSpanStyle.H1Style -> 1
137-
TextSpanStyle.H2Style -> 2
138-
TextSpanStyle.H3Style -> 3
139-
TextSpanStyle.H4Style -> 4
140-
TextSpanStyle.H5Style -> 5
141-
TextSpanStyle.H6Style -> 6
142-
else -> null
143-
}
144-
}
145-
146139
internal fun setEditable(editable: Editable) {
147140
editable.append(editableText)
148141
this.editable = editable
@@ -216,7 +209,7 @@ class QuillTextManager(quillSpan: QuillSpan) {
216209
val matchingSpans = mutableListOf<TextSpanStyle>()
217210

218211
for (part in quillTextSpans) {
219-
val partRange = TextRange(part.from, part.to)
212+
val partRange = TextRange(part.from, part.to.coerceAtLeast(0))
220213
if (selection.overlaps(partRange)) {
221214
part.style.let {
222215
matchingSpans.addAll(it)
@@ -383,35 +376,80 @@ class QuillTextManager(quillSpan: QuillSpan) {
383376
val fromIndex = selection.min
384377
val toIndex = selection.max
385378

386-
val selectedParts = quillTextSpans.filter { part ->
387-
part.from < toIndex && part.to >= fromIndex
379+
val selectedSpan = quillTextSpans.find {
380+
it.from <= fromIndex && it.to >= toIndex
388381
}
389-
val startParts = quillTextSpans.filter { fromIndex - 1 in it.from..it.to }
390-
val endParts = quillTextSpans.filter { toIndex in it.from..it.to }
391-
392-
val updateToIndex: (QuillTextSpan, Int) -> Unit = { part, index ->
393-
val partIndex = quillTextSpans.indexOf(part)
394-
quillTextSpans[partIndex] = part.copy(to = index)
395-
}
396-
397-
val updateFromIndex: (QuillTextSpan, Int) -> Unit = { part, index ->
398-
val partIndex = quillTextSpans.indexOf(part)
399-
quillTextSpans[partIndex] = part.copy(from = index)
400-
}
401-
402-
if (startParts.isEmpty() && endParts.isEmpty() && selectedParts.isNotEmpty()) {
403-
quillTextSpans.add(
404-
QuillTextSpan(
405-
from = fromIndex,
406-
to = toIndex - 1,
407-
style = listOf(style)
382+
if (selectedSpan != null) {
383+
if (fromIndex == selectedSpan.from && toIndex < selectedSpan.to) {
384+
val index = quillTextSpans.indexOf(selectedSpan)
385+
quillTextSpans.removeAt(index)
386+
quillTextSpans.add(
387+
index,
388+
QuillTextSpan(
389+
from = fromIndex,
390+
to = toIndex - 1,
391+
style = selectedSpan.style + listOf(style)
392+
)
408393
)
409-
)
410-
} else if (startParts.map { it.style }.any { it.contains(style) }) {
411-
startParts.filter { it.style == style }.forEach { updateToIndex(it, toIndex - 1) }
412-
} else if (endParts.map { it.style }.any { it.contains(style) }) {
413-
endParts.filter { it.style == style }
414-
.forEach { part -> updateFromIndex(part, fromIndex) }
394+
quillTextSpans.add(
395+
index + 1,
396+
QuillTextSpan(
397+
from = toIndex,
398+
to = selectedSpan.to,
399+
style = selectedSpan.style
400+
)
401+
)
402+
} else if (fromIndex > selectedSpan.from && toIndex < selectedSpan.to) {
403+
val index = quillTextSpans.indexOf(selectedSpan)
404+
quillTextSpans.removeAt(index)
405+
quillTextSpans.add(
406+
index,
407+
QuillTextSpan(
408+
from = selectedSpan.from,
409+
to = fromIndex - 1,
410+
style = selectedSpan.style
411+
)
412+
)
413+
quillTextSpans.add(
414+
index + 1,
415+
QuillTextSpan(
416+
from = fromIndex,
417+
to = toIndex - 1,
418+
style = selectedSpan.style + listOf(style)
419+
)
420+
)
421+
quillTextSpans.add(
422+
index + 2,
423+
QuillTextSpan(
424+
from = toIndex,
425+
to = selectedSpan.to,
426+
style = selectedSpan.style
427+
)
428+
)
429+
} else if (fromIndex > selectedSpan.from && toIndex == selectedSpan.to) {
430+
val index = quillTextSpans.indexOf(selectedSpan)
431+
quillTextSpans.removeAt(index)
432+
quillTextSpans.add(
433+
index,
434+
QuillTextSpan(
435+
from = selectedSpan.from,
436+
to = fromIndex - 1,
437+
style = selectedSpan.style
438+
)
439+
)
440+
quillTextSpans.add(
441+
index + 1,
442+
QuillTextSpan(
443+
from = fromIndex,
444+
to = toIndex - 1,
445+
style = selectedSpan.style + listOf(style)
446+
)
447+
)
448+
} else {
449+
val index = quillTextSpans.indexOf(selectedSpan)
450+
quillTextSpans[index] =
451+
selectedSpan.copy(style = selectedSpan.style + listOf(style))
452+
}
415453
} else {
416454
quillTextSpans.add(
417455
QuillTextSpan(
@@ -421,7 +459,6 @@ class QuillTextManager(quillSpan: QuillSpan) {
421459
)
422460
)
423461
}
424-
425462
updateText()
426463
}
427464

@@ -486,14 +523,38 @@ class QuillTextManager(quillSpan: QuillSpan) {
486523
selectedStyles = processSpan(it, typedCharsCount, startTypeIndex, selectedStyles)
487524
}
488525

489-
selectedStyles.forEach {
490-
quillTextSpans.add(
491-
QuillTextSpan(
492-
from = startTypeIndex,
493-
to = startTypeIndex + typedCharsCount - 1,
494-
style = listOf(it)
526+
selectedStyles.forEach { style ->
527+
val currentSpan = quillTextSpans.find {
528+
it.from <= startTypeIndex && it.to >= startTypeIndex
529+
}
530+
if (currentSpan != null) {
531+
val index = quillTextSpans.indexOf(currentSpan)
532+
quillTextSpans.removeAt(index)
533+
quillTextSpans.add(
534+
index,
535+
currentSpan.copy(
536+
from = currentSpan.from,
537+
to = startTypeIndex - 1,
538+
style = currentSpan.style
539+
)
495540
)
496-
)
541+
quillTextSpans.add(
542+
index + 1,
543+
currentSpan.copy(
544+
from = startTypeIndex,
545+
to = startTypeIndex + typedCharsCount - 1,
546+
style = currentSpan.style + listOf(style)
547+
)
548+
)
549+
quillTextSpans.add(
550+
index + 2,
551+
currentSpan.copy(
552+
from = startTypeIndex + typedCharsCount,
553+
to = currentSpan.to,
554+
style = currentSpan.style
555+
)
556+
)
557+
}
497558
}
498559
}
499560

@@ -513,7 +574,9 @@ class QuillTextManager(quillSpan: QuillSpan) {
513574
if (selectedStyles.any { it in richTextSpan.style }) {
514575
quillTextSpans[index] = richTextSpan.copy(to = newToIndex)
515576
updatedSelectedStyle =
516-
selectedStyles.filterNot { it in richTextSpan.style }.toMutableList()
577+
selectedStyles.filterNot {
578+
it in richTextSpan.style
579+
}.toMutableList()
517580
} else {
518581
if (forward) {
519582
quillTextSpans[index] = richTextSpan.copy(
@@ -635,6 +698,18 @@ class QuillTextManager(quillSpan: QuillSpan) {
635698
return headers.contains(this)
636699
}
637700

701+
private fun TextSpanStyle.headerLevel(): Int? {
702+
return when (this) {
703+
TextSpanStyle.H1Style -> 1
704+
TextSpanStyle.H2Style -> 2
705+
TextSpanStyle.H3Style -> 3
706+
TextSpanStyle.H4Style -> 4
707+
TextSpanStyle.H5Style -> 5
708+
TextSpanStyle.H6Style -> 6
709+
else -> null
710+
}
711+
}
712+
638713
internal inline fun <reified T> Editable.removeSpans() {
639714
val allSpans = getSpans(0, length, T::class.java)
640715
for (span in allSpans) {

0 commit comments

Comments
 (0)