Skip to content

Commit

Permalink
perf: 规则使用JSON5编辑复制
Browse files Browse the repository at this point in the history
  • Loading branch information
lisonge committed Dec 6, 2023
1 parent 4cd992f commit 3c49b60
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 17 deletions.
29 changes: 16 additions & 13 deletions app/src/main/kotlin/li/songe/gkd/ui/AppItemPage.kt
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -257,7 +257,7 @@ fun AppItemPage(
}
}
TextButton(onClick = {
val groupAppText = json.encodeToString(
val groupAppText = json.encodeToJson5String(
appRaw?.copy(
groups = listOf(showGroupItemVal)
)
Expand Down Expand Up @@ -291,14 +291,15 @@ fun AppItemPage(
.clickable {
vm.viewModelScope.launchTry(Dispatchers.IO) {
val subsRaw = subsIdToRawFlow.value[subsItemId] ?: return@launchTry
val newSubsRaw = subsRaw.copy(apps = subsRaw.apps
.toMutableList()
.apply {
set(
indexOfFirst { a -> a.id == appRawVal.id },
appRawVal.copy(groups = appRawVal.groups.filter { g -> g.key != menuGroupRaw.key })
)
})
val newSubsRaw = subsRaw.copy(
apps = subsRaw.apps
.toMutableList()
.apply {
set(
indexOfFirst { a -> a.id == appRawVal.id },
appRawVal.copy(groups = appRawVal.groups.filter { g -> g.key != menuGroupRaw.key })
)
})
subsItemVal.subsFile.writeText(
json.encodeToString(
newSubsRaw
Expand All @@ -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(
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
7 changes: 3 additions & 4 deletions app/src/main/kotlin/li/songe/gkd/ui/SubsPage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -367,9 +368,7 @@ fun SubsPage(
Text(text = "复制", modifier = Modifier
.clickable {
ClipboardUtils.copyText(
json.encodeToString(
menuAppRawVal
)
json.encodeToJson5String(menuAppRawVal)
)
ToastUtils.showShort("复制成功")
menuAppRaw = null
Expand Down
84 changes: 84 additions & 0 deletions app/src/main/kotlin/li/songe/gkd/util/Json5.kt
Original file line number Diff line number Diff line change
@@ -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))
}

0 comments on commit 3c49b60

Please sign in to comment.