Improve tag emoji assignment
This commit is contained in:
@@ -119,6 +119,12 @@ sealed class CustomIcon : CustomAttribute {
|
||||
}
|
||||
"force_themed_icon" -> ForceThemedIcon
|
||||
"default_placeholder_icon" -> DefaultPlaceholderIcon
|
||||
"custom_text_icon" -> {
|
||||
CustomTextIcon(
|
||||
text = payload.getString("text"),
|
||||
color = payload.getInt("color")
|
||||
)
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
@@ -233,4 +239,17 @@ data object DefaultPlaceholderIcon: CustomIcon() {
|
||||
"type" to "default_placeholder_icon"
|
||||
).toString()
|
||||
}
|
||||
}
|
||||
|
||||
data class CustomTextIcon(
|
||||
val text: String,
|
||||
val color: Int = 0,
|
||||
): CustomIcon() {
|
||||
override fun toDatabaseValue(): String {
|
||||
return jsonObjectOf(
|
||||
"type" to "custom_text_icon",
|
||||
"text" to text,
|
||||
"color" to color,
|
||||
).toString()
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,7 @@ dependencies {
|
||||
ksp(libs.androidx.roomcompiler)
|
||||
api(libs.androidx.room)
|
||||
implementation(libs.koin.android)
|
||||
implementation(libs.emoji4j)
|
||||
|
||||
implementation(project(":core:i18n"))
|
||||
implementation(project(":core:ktx"))
|
||||
|
||||
@@ -36,6 +36,7 @@ import de.mm20.launcher2.database.migrations.Migration_22_23
|
||||
import de.mm20.launcher2.database.migrations.Migration_23_24
|
||||
import de.mm20.launcher2.database.migrations.Migration_24_25
|
||||
import de.mm20.launcher2.database.migrations.Migration_25_26
|
||||
import de.mm20.launcher2.database.migrations.Migration_26_27
|
||||
import de.mm20.launcher2.database.migrations.Migration_6_7
|
||||
import de.mm20.launcher2.database.migrations.Migration_7_8
|
||||
import de.mm20.launcher2.database.migrations.Migration_8_9
|
||||
@@ -55,7 +56,7 @@ import java.util.UUID
|
||||
SearchActionEntity::class,
|
||||
ThemeEntity::class,
|
||||
PluginEntity::class,
|
||||
], version = 26, exportSchema = true
|
||||
], version = 27, exportSchema = true
|
||||
)
|
||||
@TypeConverters(ComponentNameConverter::class)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
@@ -154,6 +155,7 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
Migration_23_24(),
|
||||
Migration_24_25(),
|
||||
Migration_25_26(),
|
||||
Migration_26_27(),
|
||||
).build()
|
||||
if (_instance == null) _instance = instance
|
||||
return instance
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
package de.mm20.launcher2.database.migrations
|
||||
|
||||
import android.content.ContentValues
|
||||
import android.database.sqlite.SQLiteDatabase
|
||||
import android.util.Log
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import com.sigpwned.emoji4j.core.Grapheme
|
||||
import com.sigpwned.emoji4j.core.GraphemeMatcher
|
||||
import de.mm20.launcher2.ktx.jsonObjectOf
|
||||
|
||||
class Migration_26_27 : Migration(26, 27) {
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
Log.d("Tags-Migration", "Migrating tags")
|
||||
db.query("SELECT DISTINCT value FROM CustomAttributes WHERE type = 'tag'").use { cursor ->
|
||||
while (cursor.moveToNext()) {
|
||||
val oldName = cursor.getString(0)
|
||||
val (emoji, newName) = oldName.splitLeadingEmoji()
|
||||
|
||||
if (emoji != null) {
|
||||
db.update(
|
||||
"CustomAttributes",
|
||||
SQLiteDatabase.CONFLICT_FAIL,
|
||||
ContentValues().apply {
|
||||
put("value", newName)
|
||||
}, "type = 'tag' AND value = ?",
|
||||
arrayOf(oldName)
|
||||
)
|
||||
db.insert(
|
||||
"CustomAttributes",
|
||||
SQLiteDatabase.CONFLICT_REPLACE,
|
||||
ContentValues().apply {
|
||||
put("key", "tag://$newName")
|
||||
put("type", "icon")
|
||||
put("value", jsonObjectOf(
|
||||
"type" to "custom_text_icon",
|
||||
"text" to emoji,
|
||||
"color" to 0,
|
||||
).toString())
|
||||
}
|
||||
)
|
||||
db.update(
|
||||
"Searchable",
|
||||
SQLiteDatabase.CONFLICT_IGNORE,
|
||||
ContentValues().apply {
|
||||
put("key", "tag://$newName")
|
||||
put("searchable", jsonObjectOf(
|
||||
"tag" to newName
|
||||
).toString())
|
||||
},
|
||||
"key = ?",
|
||||
arrayOf("tag://$oldName")
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun String.splitLeadingEmoji(): Pair<String?, String> {
|
||||
val matcher = GraphemeMatcher(this)
|
||||
if (!matcher.find()) return null to this.trim()
|
||||
val grapheme = matcher.grapheme()
|
||||
if (grapheme?.type == Grapheme.Type.EMOJI && matcher.start() == 0) {
|
||||
val end = matcher.end()
|
||||
val emoji = this.substring(0, end)
|
||||
val tagName = this.substring(end).takeIf { it.isNotBlank() }
|
||||
if (tagName == null) return emoji to emoji
|
||||
return emoji to tagName
|
||||
}
|
||||
return null to this.trim()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user