perf: 规则使用JSON5编辑复制

This commit is contained in:
lisonge 2023-12-06 16:28:52 +08:00
parent 4cd992fdda
commit 3c49b60924
3 changed files with 103 additions and 17 deletions

View File

@ -1,6 +1,5 @@
package li.songe.gkd.ui
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
@ -63,6 +62,7 @@ import li.songe.gkd.ui.destinations.GroupItemPageDestination
import li.songe.gkd.util.LocalNavController
import li.songe.gkd.util.ProfileTransitions
import li.songe.gkd.util.appInfoCacheFlow
import li.songe.gkd.util.encodeToJson5String
import li.songe.gkd.util.json
import li.songe.gkd.util.launchAsFn
import li.songe.gkd.util.launchTry
@ -257,7 +257,7 @@ fun AppItemPage(
}
}
TextButton(onClick = {
val groupAppText = json.encodeToString(
val groupAppText = json.encodeToJson5String(
appRaw?.copy(
groups = listOf(showGroupItemVal)
)
@ -291,7 +291,8 @@ fun AppItemPage(
.clickable {
vm.viewModelScope.launchTry(Dispatchers.IO) {
val subsRaw = subsIdToRawFlow.value[subsItemId] ?: return@launchTry
val newSubsRaw = subsRaw.copy(apps = subsRaw.apps
val newSubsRaw = subsRaw.copy(
apps = subsRaw.apps
.toMutableList()
.apply {
set(
@ -321,7 +322,7 @@ fun AppItemPage(
if (editGroupRaw != null && appRawVal != null && subsItemVal != null) {
var source by remember {
mutableStateOf(json.encodeToString(editGroupRaw))
mutableStateOf(json.encodeToJson5String(editGroupRaw))
}
val oldSource = remember { source }
AlertDialog(
@ -365,7 +366,8 @@ fun AppItemPage(
setEditGroupRaw(null)
val subsRaw = subsIdToRawFlow.value[subsItemId] ?: return@TextButton
val newSubsRaw = subsRaw.copy(apps = subsRaw.apps.toMutableList().apply {
set(indexOfFirst { a -> a.id == appRawVal.id },
set(
indexOfFirst { a -> a.id == appRawVal.id },
appRawVal.copy(groups = appRawVal.groups.toMutableList().apply {
set(
indexOfFirst { g -> g.key == newGroupRaw.key }, newGroupRaw
@ -441,7 +443,8 @@ fun AppItemPage(
val newKey = appRawVal.groups.maxBy { g -> g.key }.key + 1
val subsRaw = subsIdToRawFlow.value[subsItemId] ?: return@TextButton
val newSubsRaw = subsRaw.copy(apps = subsRaw.apps.toMutableList().apply {
set(indexOfFirst { a -> a.id == appRawVal.id },
set(
indexOfFirst { a -> a.id == appRawVal.id },
appRawVal.copy(groups = appRawVal.groups + tempGroups.mapIndexed { i, g ->
g.copy(
key = newKey + i

View File

@ -61,6 +61,7 @@ import li.songe.gkd.ui.destinations.AppItemPageDestination
import li.songe.gkd.util.LocalNavController
import li.songe.gkd.util.ProfileTransitions
import li.songe.gkd.util.appInfoCacheFlow
import li.songe.gkd.util.encodeToJson5String
import li.songe.gkd.util.json
import li.songe.gkd.util.launchAsFn
import li.songe.gkd.util.launchTry
@ -306,7 +307,7 @@ fun SubsPage(
val editAppRawVal = editAppRaw
if (editAppRawVal != null && subsItemVal != null && subsRaw != null) {
var source by remember {
mutableStateOf(json.encodeToString(editAppRawVal))
mutableStateOf(json.encodeToJson5String(editAppRawVal))
}
AlertDialog(title = { Text(text = "编辑本地APP规则") }, text = {
OutlinedTextField(
@ -367,9 +368,7 @@ fun SubsPage(
Text(text = "复制", modifier = Modifier
.clickable {
ClipboardUtils.copyText(
json.encodeToString(
menuAppRawVal
)
json.encodeToJson5String(menuAppRawVal)
)
ToastUtils.showShort("复制成功")
menuAppRaw = null

View File

@ -0,0 +1,84 @@
package li.songe.gkd.util
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.serializer
private val json5IdentifierReg = Regex("[a-zA-Z_][a-zA-Z0-9_]*")
/**
* https://spec.json5.org/#strings
*/
private fun escapeString(value: String): String {
val wrapChar = '\''
val sb = StringBuilder()
sb.append(wrapChar)
value.forEach { c ->
val escapeChar = when (c) {
wrapChar -> wrapChar
'\n' -> 'n'
'\r' -> 'r'
'\t' -> 't'
'\b' -> 'b'
'\\' -> '\\'
else -> null
}
if (escapeChar != null) {
sb.append("\\" + escapeChar)
} else {
when (c.code) {
in 0..0xf -> {
sb.append("\\x0" + c.code.toString(16))
}
in 0..0x1f -> {
sb.append("\\x" + c.code.toString(16))
}
else -> {
sb.append(c)
}
}
}
}
sb.append(wrapChar)
return sb.toString()
}
fun convertJsonElementToJson5(element: JsonElement): String {
return when (element) {
is JsonPrimitive -> {
val content = element.content
if (element.isString) {
escapeString(content)
} else {
content
}
}
is JsonObject -> {
// Handle JSON objects
val entries = element.entries.joinToString(",") { (key, value) ->
// If key is a valid identifier, no quotes are needed
if (key.matches(json5IdentifierReg)) {
"$key:${convertJsonElementToJson5(value)}"
} else {
"${escapeString(key)}:${convertJsonElementToJson5(value)}"
}
}
"{$entries}"
}
is JsonArray -> {
val elements = element.joinToString(",") { convertJsonElementToJson5(it) }
"[$elements]"
}
}
}
inline fun <reified T> Json.encodeToJson5String(value: T): String {
return convertJsonElementToJson5(encodeToJsonElement(serializersModule.serializer(), value))
}