Skip to content

Commit

Permalink
Merge pull request #14 from vadiole/feature/block-selector
Browse files Browse the repository at this point in the history
feature/block selector
  • Loading branch information
vadiole committed Jul 15, 2023
2 parents 5c7456b + 805edb1 commit 9b4f244
Show file tree
Hide file tree
Showing 24 changed files with 1,011 additions and 103 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ android {
applicationId = "vadiole.unicode"
minSdk = 26
targetSdk = 33
versionCode = 131
versionName = "1.3.1"
versionCode = 140
versionName = "1.4.0"
resourceConfigurations.addAll(listOf("en"))
setProperty("archivesBaseName", "unicode-v$versionName")
}
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

<intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/kotlin/vadiole/unicode/data/Block.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ class Block(val id: Int, val start: Int, val end: Int, val name: String) {
codePoint.value > end -> -1
else -> 0
}
}
}
14 changes: 7 additions & 7 deletions app/src/main/kotlin/vadiole/unicode/data/CharObj.kt
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package vadiole.unicode.data

import java.util.Locale
import vadiole.unicode.utils.extension.leftPad
import java.util.*

class CharObj(val id: Int, val codePoint: Int, val name: String, val version: String, val blockName: String) {
val char: String = String(Character.toChars(codePoint))
val hex = codePoint.toString(16).uppercase(Locale.ENGLISH).leftPad(4, '0')
class CharObj(val id: Int, val codePointRaw: Int, val name: String, val version: String, val blockName: String) {
val char: String = String(Character.toChars(codePointRaw))
val hex = codePointRaw.toString(16).uppercase(Locale.ENGLISH).leftPad(4, '0')
val infoValues: Array<String> = arrayOf(
"U+$hex",
"&#$codePoint",
"&#$codePointRaw",
"\\$hex",
version,
)
val link = "vadiole.github.io/unicode?c=$codePoint"
}
val link = "vadiole.github.io/unicode?c=$codePointRaw"
}
40 changes: 39 additions & 1 deletion app/src/main/kotlin/vadiole/unicode/data/CodePoint.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,42 @@ package vadiole.unicode.data
value class CodePoint(val value: Int) {
val char: String
get() = String(Character.toChars(value))
}
}

@JvmInline
value class CodePointArray(val storage: IntArray) : Collection<CodePoint> {
constructor(size: Int) : this(IntArray(size))

override val size: Int get() = storage.size

override fun isEmpty() = storage.isEmpty()

override fun iterator(): Iterator<CodePoint> = object : Iterator<CodePoint> {
private var index = 0
override fun hasNext() = index < storage.size
override fun next() = if (index < storage.size) CodePoint(storage[index++]) else throw NoSuchElementException(index.toString())
}

override fun containsAll(elements: Collection<CodePoint>) = elements.all { storage.contains(it.value) }

override fun contains(element: CodePoint): Boolean = storage.contains(element.value)

operator fun get(index: Int) = CodePoint(storage[index])

operator fun set(index: Int, value: CodePoint) {
storage[index] = value.value
}
}

inline fun CodePointArray(size: Int, init: (Int) -> CodePoint): CodePointArray {
return CodePointArray(IntArray(size) { index -> (init(index)).value })
}

inline fun CodePointArray.filterMaybe(predicate: (CodePoint) -> Boolean): CodePointArray {
val filtered = storage.filterTo(ArrayList(size)) { predicate(CodePoint(it)) }
return CodePointArray(filtered.toIntArray())
}

fun CodePointArray.binarySearch(element: CodePoint, fromIndex: Int = 0, toIndex: Int = size): Int {
return java.util.Arrays.binarySearch(storage, fromIndex, toIndex, element.value)
}
85 changes: 53 additions & 32 deletions app/src/main/kotlin/vadiole/unicode/data/UnicodeStorage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteDatabase.OPEN_READONLY
import android.database.sqlite.SQLiteDatabase.openDatabase
import vadiole.unicode.utils.extension.io
import android.util.Log
import java.io.File
import kotlin.system.measureTimeMillis
import vadiole.unicode.utils.extension.io

class UnicodeStorage(private val context: Context) {
var database: SQLiteDatabase? = null
Expand All @@ -27,7 +29,6 @@ class UnicodeStorage(private val context: Context) {
context.filesDir.listFiles()!!.forEach { file ->
file.deleteOnExit()
}
@Suppress("BlockingMethodInNonBlockingContext")
context.assets.open(databaseName).use { input ->
database.outputStream().use { output ->
input.copyTo(output)
Expand All @@ -37,7 +38,7 @@ class UnicodeStorage(private val context: Context) {
return@io database.absolutePath
}

suspend fun getCodePoints(count: Int): List<CodePoint> = io {
suspend fun getCodePoints(count: Int): CodePointArray = io {
val query = if (count > 0) {
"SELECT code_point FROM char WHERE id < ? LIMIT ?"
} else {
Expand All @@ -48,33 +49,33 @@ class UnicodeStorage(private val context: Context) {
} else {
null
}
val result = mutableListOf<CodePoint>()
val result: CodePointArray
openDatabase().rawQuery(query, args).use { cursor ->
val codePointIndex = cursor.getColumnIndex("code_point")
while (cursor.moveToNext()) {
val codePoint = CodePoint(
value = cursor.getInt(codePointIndex),
)
result.add(codePoint)
result = CodePointArray(cursor.count) {
cursor.moveToNext()
CodePoint(value = cursor.getInt(codePointIndex))
}
}

return@io result
}

suspend fun getBlocks(): List<Block> = io {
val result = mutableListOf<Block>()
suspend fun getBlocks(): Array<Block> = io {
val result: Array<Block>
openDatabase().rawQuery(queryGetBlocks, null).use { cursor ->
val idIndex = cursor.getColumnIndex("id")
val endIndex = cursor.getColumnIndex("end")
val nameIndex = cursor.getColumnIndex("name")
while (cursor.moveToNext()) {
val block = Block(
var lastEnd = 0
result = Array(cursor.count) {
cursor.moveToNext()
Block(
id = cursor.getInt(idIndex),
start = (result.lastOrNull()?.end ?: -1) + 1,
end = cursor.getInt(endIndex),
start = lastEnd + 1,
end = cursor.getInt(endIndex).also { lastEnd = it },
name = cursor.getString(nameIndex),
)
result.add(block)
}
}
return@io result
Expand All @@ -92,7 +93,7 @@ class UnicodeStorage(private val context: Context) {
cursor.moveToNext()
result = CharObj(
id = cursor.getInt(charIdIndex),
codePoint = cursor.getInt(codePointIndex),
codePointRaw = cursor.getInt(codePointIndex),
name = cursor.getString(charNameIndex),
version = cursor.getString(versionIndex),
blockName = cursor.getString(blockNameIndex),
Expand All @@ -101,21 +102,33 @@ class UnicodeStorage(private val context: Context) {
return@io result
}

suspend fun findCharsByName(input: String): Array<SearchResult> = io {
val args = arrayOf("%$input%", input, "$input%")
openDatabase().rawQuery(queryFindChars, args).use { cursor ->
val rowsCount = cursor.count
val codePointIndex = cursor.getColumnIndex("code_point")
val nameIndex = cursor.getColumnIndex("name")
val result = Array(rowsCount) {
cursor.moveToPosition(it)
val codePoint = cursor.getInt(codePointIndex)
val name = cursor.getString(nameIndex)
SearchResult(CodePoint(codePoint), name)
suspend fun findCharsByName(input: String, count: Int): Array<SearchResult> = io {
val query = if (count > 0) {
"$queryFindChars LIMIT $count"
} else {
queryFindChars
}
val args = arrayOf(
"%$input%",
input, "% $input", "$input %", "$input%", "% $input %",
)
val result: Array<SearchResult>
measureTimeMillis {
openDatabase().rawQuery(query, args).use { cursor ->
val rowsCount = cursor.count
val codePointIndex = cursor.getColumnIndex("code_point")
val nameIndex = cursor.getColumnIndex("name")
result = Array(rowsCount) {
cursor.moveToPosition(it)
val codePoint = cursor.getInt(codePointIndex)
val name = cursor.getString(nameIndex)
SearchResult(CodePoint(codePoint), name)
}
}
return@io result
}.also {
Log.d("UnicodeStorage", "perf $it")
}

return@io result
}

companion object {
Expand All @@ -127,7 +140,15 @@ class UnicodeStorage(private val context: Context) {
private const val queryGetBlocks = "SELECT id, `end`, name FROM block"
private const val queryFindChars = "SELECT id, code_point, name " +
"FROM char " +
"WHERE name LIKE ?" +
"ORDER BY (CASE WHEN name = ? THEN 1 WHEN name LIKE ? THEN 2 ELSE 3 END), name"
"WHERE name LIKE ? " +
"ORDER BY (" +
"CASE " +
"WHEN name = ? THEN 1 " +
"WHEN name LIKE ? THEN 2 " +
"WHEN name LIKE ? THEN 4 " +
"WHEN name LIKE ? THEN 3 " +
"WHEN name LIKE ? THEN 5 " +
"ELSE 6 END), " +
"id"
}
}
12 changes: 6 additions & 6 deletions app/src/main/kotlin/vadiole/unicode/ui/NavigationView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import androidx.core.view.doOnLayout
import androidx.dynamicanimation.animation.DynamicAnimation
import androidx.dynamicanimation.animation.SpringAnimation
import androidx.dynamicanimation.animation.SpringForce
import kotlin.math.PI
import kotlin.math.abs
import kotlin.math.atan
import kotlin.math.hypot
import vadiole.unicode.UnicodeApp.Companion.themeManager
import vadiole.unicode.UnicodeApp.Companion.unicodeStorage
import vadiole.unicode.UnicodeApp.Companion.userConfig
Expand All @@ -26,10 +30,6 @@ import vadiole.unicode.utils.extension.frameParams
import vadiole.unicode.utils.extension.isVisible
import vadiole.unicode.utils.extension.matchParent
import vadiole.unicode.utils.extension.with
import kotlin.math.PI
import kotlin.math.abs
import kotlin.math.atan
import kotlin.math.hypot

class NavigationView(context: Context) : FrameLayout(context), ThemeDelegate {
private val scaledTouchSlop = ViewConfiguration.get(context).scaledTouchSlop
Expand Down Expand Up @@ -57,7 +57,7 @@ class NavigationView(context: Context) : FrameLayout(context), ThemeDelegate {
visibility = View.GONE
}
private val detailsDelegate = object : DetailsSheet.Delegate {
override fun findInTable(codePoint: Int) {
override fun findInTable(codePoint: CodePoint) {
hideDetailsBottomSheet()
tableScreen.hideSearch()
tableScreen.scrollToChar(codePoint)
Expand Down Expand Up @@ -265,4 +265,4 @@ class NavigationView(context: Context) : FrameLayout(context), ThemeDelegate {
override fun applyTheme() {
dimView.setBackgroundColor(themeManager.getColor(key_dialogDim))
}
}
}
20 changes: 18 additions & 2 deletions app/src/main/kotlin/vadiole/unicode/ui/common/CollectionView.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
package vadiole.unicode.ui.common

import android.content.Context
import android.os.Build
import android.view.View
import androidx.recyclerview.widget.RecyclerView

open class CollectionView(context: Context) : RecyclerView(context) {

var isScrollEnabled = true

init {
overScrollMode = View.OVER_SCROLL_ALWAYS
overScrollMode = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
OVER_SCROLL_ALWAYS
} else {
OVER_SCROLL_NEVER
}
clipToPadding = false
clipChildren = false
itemAnimator = null
Expand All @@ -16,4 +24,12 @@ open class CollectionView(context: Context) : RecyclerView(context) {
abstract class Adapter : RecyclerView.Adapter<Cell>()

class Cell(cell: View) : ViewHolder(cell)
}

override fun canScrollVertically(direction: Int): Boolean {
return isScrollEnabled && super.canScrollVertically(direction)
}

override fun canScrollHorizontally(direction: Int): Boolean {
return isScrollEnabled && super.canScrollHorizontally(direction)
}
}
Loading

0 comments on commit 9b4f244

Please sign in to comment.