mirror of
https://github.com/SimpleMobileTools/Simple-Notes.git
synced 2025-03-19 18:10:07 +01:00
Merge pull request #658 from Dejvino/bugfix/615
Fix #615: Use a locale-aware Collator for sorting Checklists
This commit is contained in:
commit
16229704ea
@ -0,0 +1,79 @@
|
||||
package com.simplemobiletools.notes.pro.helpers
|
||||
|
||||
import java.text.Collator
|
||||
|
||||
/**
|
||||
* Collator-based string comparator
|
||||
*
|
||||
* Adapted from AlphanumericComparator to support numerical collation.
|
||||
*/
|
||||
class CollatorBasedComparator: Comparator<String> {
|
||||
override fun compare(string1: String, string2: String): Int {
|
||||
val collator = getCollator()
|
||||
|
||||
var thisMarker = 0
|
||||
var thatMarker = 0
|
||||
|
||||
while (thisMarker < string1.length && thatMarker < string2.length) {
|
||||
val thisChunk = getChunk(string1, string1.length, thisMarker)
|
||||
thisMarker += thisChunk.length
|
||||
|
||||
val thatChunk = getChunk(string2, string2.length, thatMarker)
|
||||
thatMarker += thatChunk.length
|
||||
|
||||
val result = if (isDigit(thisChunk[0]) && isDigit(thatChunk[0])) {
|
||||
collateNumerically(thisChunk, thatChunk)
|
||||
} else {
|
||||
collator.compare(thisChunk, thatChunk)
|
||||
}
|
||||
|
||||
if (result != 0) {
|
||||
return coerceResult(result)
|
||||
}
|
||||
}
|
||||
|
||||
return coerceResult(string1.length - string2.length)
|
||||
}
|
||||
|
||||
private fun collateNumerically(string1: String, string2: String): Int {
|
||||
var result: Int
|
||||
result = string1.length - string2.length
|
||||
if (result == 0) {
|
||||
// equal length, the first different number counts
|
||||
for (i in string1.indices) {
|
||||
result = string1[i] - string2[i]
|
||||
if (result != 0) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun getChunk(string: String, length: Int, marker: Int): String {
|
||||
var current = marker
|
||||
var c = string[current]
|
||||
val chunk = StringBuilder(c.toString())
|
||||
current++
|
||||
val chunkOfDigits = isDigit(c)
|
||||
while (current < length) {
|
||||
c = string[current]
|
||||
if (isDigit(c) != chunkOfDigits) {
|
||||
break
|
||||
}
|
||||
chunk.append(c)
|
||||
current++
|
||||
}
|
||||
return chunk.toString()
|
||||
}
|
||||
|
||||
private fun isDigit(ch: Char) = ch in '0'..'9'
|
||||
private fun coerceResult(compareToResult: Int) = compareToResult.coerceIn(-1, 1)
|
||||
|
||||
private fun getCollator(): Collator {
|
||||
val collator = Collator.getInstance()
|
||||
collator.strength = Collator.PRIMARY
|
||||
collator.decomposition = Collator.CANONICAL_DECOMPOSITION
|
||||
return collator
|
||||
}
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
package com.simplemobiletools.notes.pro.models
|
||||
|
||||
import com.simplemobiletools.commons.helpers.AlphanumericComparator
|
||||
import com.simplemobiletools.commons.helpers.SORT_BY_TITLE
|
||||
import com.simplemobiletools.commons.helpers.SORT_DESCENDING
|
||||
import com.simplemobiletools.notes.pro.helpers.CollatorBasedComparator
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@ -19,7 +19,7 @@ data class ChecklistItem(
|
||||
|
||||
override fun compareTo(other: ChecklistItem): Int {
|
||||
var result = when {
|
||||
sorting and SORT_BY_TITLE != 0 -> AlphanumericComparator().compare(title.lowercase(), other.title.lowercase())
|
||||
sorting and SORT_BY_TITLE != 0 -> CollatorBasedComparator().compare(title, other.title)
|
||||
else -> dateCreated.compareTo(other.dateCreated)
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user