Skip to content

Commit 3d2408c

Browse files
committed
perf: subs state
1 parent a64825e commit 3d2408c

File tree

7 files changed

+71
-53
lines changed

7 files changed

+71
-53
lines changed

app/src/main/kotlin/li/songe/gkd/data/RawSubscription.kt

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import kotlinx.serialization.json.jsonPrimitive
1616
import kotlinx.serialization.json.long
1717
import li.songe.gkd.service.typeInfo
1818
import li.songe.gkd.util.LOCAL_SUBS_IDS
19+
import li.songe.gkd.util.distinctByIfAny
20+
import li.songe.gkd.util.filterIfNotAll
1921
import li.songe.gkd.util.json
2022
import li.songe.gkd.util.toast
2123
import li.songe.json5.Json5
@@ -782,7 +784,7 @@ data class RawSubscription(
782784
is JsonArray -> groupsJson
783785
}).map { jsonElement ->
784786
jsonToGroupRaw(jsonElement)
785-
}.distinctBy { it.key },
787+
}.distinctByIfAny { it.key },
786788
)
787789
}
788790

@@ -824,7 +826,7 @@ data class RawSubscription(
824826
jsonToGlobalApp(
825827
jsonElement.jsonObject, index
826828
)
827-
}?.distinctBy { it.id },
829+
}?.distinctByIfAny { it.id },
828830
action = getString(jsonObject, "action"),
829831
preKeys = getIntIArray(jsonObject, "preKeys"),
830832
excludeMatches = getStringIArray(jsonObject, "excludeMatches"),
@@ -865,7 +867,7 @@ data class RawSubscription(
865867
jsonToGlobalApp(
866868
jsonElement.jsonObject, index
867869
)
868-
}?.distinctBy { it.id },
870+
}?.distinctByIfAny { it.id },
869871
rules = (jsonObject["rules"]?.jsonArray?.map { jsonElement ->
870872
jsonToGlobalRule(jsonElement.jsonObject)
871873
} ?: emptyList()).distinctNotNullBy { it.key },
@@ -892,13 +894,7 @@ data class RawSubscription(
892894
jsonElement.jsonObject,
893895
index
894896
)
895-
} ?: emptyList()).distinctBy { it.id }.run {
896-
if (any { it.groups.isEmpty() }) {
897-
filterNot { it.groups.isEmpty() }
898-
} else {
899-
this
900-
}
901-
},
897+
} ?: emptyList()).filterIfNotAll { it.groups.isNotEmpty() }.distinctByIfAny { it.id },
902898
categories = (rootJson["categories"]?.jsonArray?.mapIndexed { index, jsonElement ->
903899
RawCategory(
904900
key = getInt(jsonElement.jsonObject, "key")
@@ -907,10 +903,10 @@ data class RawSubscription(
907903
?: error("miss categories[$index].name"),
908904
enable = getBoolean(jsonElement.jsonObject, "enable"),
909905
)
910-
} ?: emptyList()).distinctBy { it.key },
906+
} ?: emptyList()).filterIfNotAll { it.name.isNotEmpty() }.distinctByIfAny { it.key },
911907
globalGroups = (rootJson["globalGroups"]?.jsonArray?.mapIndexed { index, jsonElement ->
912908
jsonToGlobalGroup(jsonElement.jsonObject, index)
913-
} ?: emptyList()).distinctBy { it.key }
909+
} ?: emptyList()).distinctByIfAny { it.key }
914910
)
915911
}
916912

app/src/main/kotlin/li/songe/gkd/data/SubsItem.kt

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,10 @@ import androidx.room.PrimaryKey
1010
import androidx.room.Query
1111
import androidx.room.Transaction
1212
import androidx.room.Update
13-
import kotlinx.coroutines.Dispatchers
1413
import kotlinx.coroutines.flow.Flow
1514
import kotlinx.serialization.Serializable
16-
import li.songe.gkd.appScope
17-
import li.songe.gkd.db.DbSet
1815
import li.songe.gkd.util.LOCAL_SUBS_IDS
1916
import li.songe.gkd.util.format
20-
import li.songe.gkd.util.launchTry
21-
import li.songe.gkd.util.subsFolder
22-
import li.songe.gkd.util.subsIdToRawFlow
23-
import li.songe.gkd.util.toast
2417

2518
@Serializable
2619
@Entity(
@@ -80,28 +73,7 @@ data class SubsItem(
8073
fun queryAll(): List<SubsItem>
8174

8275
@Query("DELETE FROM subs_item WHERE id IN (:ids)")
83-
suspend fun deleteById(vararg ids: Long)
76+
suspend fun deleteById(vararg ids: Long): Int
8477
}
8578

8679
}
87-
88-
89-
fun deleteSubscription(vararg subsIds: Long) {
90-
appScope.launchTry(Dispatchers.IO) {
91-
DbSet.subsItemDao.deleteById(*subsIds)
92-
DbSet.subsConfigDao.deleteBySubsId(*subsIds)
93-
DbSet.actionLogDao.deleteBySubsId(*subsIds)
94-
DbSet.categoryConfigDao.deleteBySubsId(*subsIds)
95-
val newMap = subsIdToRawFlow.value.toMutableMap()
96-
subsIds.forEach { id ->
97-
newMap.remove(id)
98-
subsFolder.resolve("$id.json").apply {
99-
if (exists()) {
100-
delete()
101-
}
102-
}
103-
}
104-
subsIdToRawFlow.value = newMap
105-
toast("删除订阅成功")
106-
}
107-
}

app/src/main/kotlin/li/songe/gkd/debug/HttpService.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ import li.songe.gkd.data.GkdAction
3636
import li.songe.gkd.data.RawSubscription
3737
import li.songe.gkd.data.RpcError
3838
import li.songe.gkd.data.SubsItem
39-
import li.songe.gkd.data.deleteSubscription
4039
import li.songe.gkd.data.selfAppInfo
4140
import li.songe.gkd.db.DbSet
4241
import li.songe.gkd.debug.SnapshotExt.captureSnapshot
@@ -48,6 +47,7 @@ import li.songe.gkd.util.LOCAL_HTTP_SUBS_ID
4847
import li.songe.gkd.util.OnCreate
4948
import li.songe.gkd.util.OnDestroy
5049
import li.songe.gkd.util.SERVER_SCRIPT_URL
50+
import li.songe.gkd.util.deleteSubscription
5151
import li.songe.gkd.util.getIpAddressInLocalNetwork
5252
import li.songe.gkd.util.isPortAvailable
5353
import li.songe.gkd.util.keepNullJson

app/src/main/kotlin/li/songe/gkd/ui/component/SubsSheet.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,13 @@ import com.ramcosta.composedestinations.utils.toDestinationsNavigator
5050
import kotlinx.coroutines.flow.MutableStateFlow
5151
import kotlinx.coroutines.launch
5252
import li.songe.gkd.META
53-
import li.songe.gkd.data.deleteSubscription
5453
import li.songe.gkd.ui.style.EmptyHeight
5554
import li.songe.gkd.ui.style.itemHorizontalPadding
5655
import li.songe.gkd.util.LOCAL_SUBS_ID
5756
import li.songe.gkd.util.LocalMainViewModel
5857
import li.songe.gkd.util.LocalNavController
5958
import li.songe.gkd.util.checkSubsUpdate
59+
import li.songe.gkd.util.deleteSubscription
6060
import li.songe.gkd.util.launchAsFn
6161
import li.songe.gkd.util.launchTry
6262
import li.songe.gkd.util.subsIdToRawFlow

app/src/main/kotlin/li/songe/gkd/ui/home/SubsManagePage.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ import kotlinx.coroutines.flow.update
6767
import kotlinx.coroutines.launch
6868
import li.songe.gkd.MainActivity
6969
import li.songe.gkd.data.Value
70-
import li.songe.gkd.data.deleteSubscription
7170
import li.songe.gkd.data.importData
7271
import li.songe.gkd.db.DbSet
7372
import li.songe.gkd.ui.component.AnimationFloatingActionButton
@@ -84,6 +83,7 @@ import li.songe.gkd.util.SafeR
8483
import li.songe.gkd.util.ShortUrlSet
8584
import li.songe.gkd.util.UpdateTimeOption
8685
import li.songe.gkd.util.checkSubsUpdate
86+
import li.songe.gkd.util.deleteSubscription
8787
import li.songe.gkd.util.findOption
8888
import li.songe.gkd.util.getUpDownTransform
8989
import li.songe.gkd.util.launchAsFn

app/src/main/kotlin/li/songe/gkd/util/CollectionExt.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,19 @@ fun <T> Set<T>.switchItem(t: T): Set<T> {
77
plus(t)
88
}
99
}
10+
11+
inline fun <T> Iterable<T>.filterIfNotAll(predicate: (T) -> Boolean): List<T> {
12+
return if (count() > 1 && !all(predicate)) {
13+
filter(predicate)
14+
} else {
15+
this as? List ?: toList()
16+
}
17+
}
18+
19+
inline fun <T, K> Iterable<T>.distinctByIfAny(selector: (T) -> K): List<T> {
20+
return if (count() > 1 && any { v1 -> any { v2 -> v1 !== v2 && selector(v1) == selector(v2) } }) {
21+
distinctBy(selector)
22+
} else {
23+
this as? List ?: toList()
24+
}
25+
}

app/src/main/kotlin/li/songe/gkd/util/SubsState.kt

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import kotlinx.coroutines.flow.flowOn
1313
import kotlinx.coroutines.flow.map
1414
import kotlinx.coroutines.flow.stateIn
1515
import kotlinx.coroutines.flow.update
16+
import kotlinx.coroutines.sync.withLock
1617
import kotlinx.coroutines.withContext
1718
import li.songe.gkd.appScope
1819
import li.songe.gkd.data.AppRule
@@ -90,26 +91,59 @@ val usedSubsEntriesFlow by lazy {
9091
fun updateSubscription(subscription: RawSubscription) {
9192
appScope.launchTry {
9293
updateSubsMutex.withLock {
94+
val subsId = subscription.id
95+
val subsName = subscription.name
9396
val newMap = subsIdToRawFlow.value.toMutableMap()
94-
if (subscription.id < 0 && newMap[subscription.id]?.version == subscription.version) {
95-
newMap[subscription.id] = subscription.copy(version = subscription.version + 1)
97+
if (subsId < 0 && newMap[subsId]?.version == subscription.version) {
98+
newMap[subsId] = subscription.run {
99+
copy(
100+
version = version + 1,
101+
apps = apps.filterIfNotAll { it.groups.isNotEmpty() }
102+
.distinctByIfAny { it.id },
103+
)
104+
}
96105
} else {
97-
newMap[subscription.id] = subscription
106+
newMap[subsId] = subscription
98107
}
99108
subsIdToRawFlow.value = newMap
100-
if (subsLoadErrorsFlow.value.contains(subscription.id)) {
109+
if (subsLoadErrorsFlow.value.contains(subsId)) {
101110
subsLoadErrorsFlow.update {
102111
it.toMutableMap().apply {
103-
remove(subscription.id)
112+
remove(subsId)
104113
}
105114
}
106115
}
107116
withContext(Dispatchers.IO) {
108-
DbSet.subsItemDao.updateMtime(subscription.id, System.currentTimeMillis())
109-
subsFolder.resolve("${subscription.id}.json")
110-
.writeText(json.encodeToString(subscription))
117+
DbSet.subsItemDao.updateMtime(subsId, System.currentTimeMillis())
118+
subsFolder.resolve("${subsId}.json")
119+
.writeText(json.encodeToString(newMap[subsId]))
120+
}
121+
LogUtils.d("更新订阅文件:id=${subsId},name=${subsName}")
122+
}
123+
}
124+
}
125+
126+
fun deleteSubscription(vararg subsIds: Long) {
127+
appScope.launchTry(Dispatchers.IO) {
128+
updateSubsMutex.mutex.withLock {
129+
val deleteSize = DbSet.subsItemDao.deleteById(*subsIds)
130+
if (deleteSize > 0) {
131+
DbSet.subsConfigDao.deleteBySubsId(*subsIds)
132+
DbSet.actionLogDao.deleteBySubsId(*subsIds)
133+
DbSet.categoryConfigDao.deleteBySubsId(*subsIds)
134+
val newMap = subsIdToRawFlow.value.toMutableMap()
135+
subsIds.forEach { id ->
136+
newMap.remove(id)
137+
subsFolder.resolve("$id.json").apply {
138+
if (exists()) {
139+
delete()
140+
}
141+
}
142+
}
143+
subsIdToRawFlow.value = newMap
144+
toast("删除订阅成功")
145+
LogUtils.d("deleteSubscription", subsIds)
111146
}
112-
LogUtils.d("更新订阅文件:id=${subscription.id},name=${subscription.name}")
113147
}
114148
}
115149
}

0 commit comments

Comments
 (0)