Keep built-in asset row identities stable across reloads (#6199)
Use a builtin: filename-based ID instead of generating a fresh UUID each time the asset list is rebuilt. This lets the existing GUID-keyed list and file-metadata map recognize the same built-in asset after reloads and download-source changes. Extract the fix and its two JVM regression tests from local/talkback-all-10. Preserve stored asset GUIDs, matching built-in replacement, locked flags, and URL behavior. No persisted IDs, accessibility semantics, metadata formatting, or editor behavior are changed.
This commit is contained in:
1 parent
e7dcec1eff
commit
1fd05e16b5
2 files changed
+48
-3
No files matched your search
@@ -11,7 +11,6 @@ import com.v2ray.ang.handler.MmkvManager
|
||||
import com.v2ray.ang.ui.base.BaseViewModel
|
||||
import com.v2ray.ang.util.HttpUtil
|
||||
import com.v2ray.ang.util.LogUtil
|
||||
import com.v2ray.ang.util.Utils
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.ensureActive
|
||||
@@ -50,7 +49,7 @@ class UserAssetViewModel(application: Application) : BaseViewModel(application)
|
||||
}.also { reloadJob = it }
|
||||
}
|
||||
|
||||
private fun buildAssetList(
|
||||
internal fun buildAssetList(
|
||||
decodedAssets: List<AssetUrlCache>?,
|
||||
geoFilesSource: String
|
||||
): List<AssetUrlCache> {
|
||||
@@ -59,7 +58,8 @@ class UserAssetViewModel(application: Application) : BaseViewModel(application)
|
||||
.filter { geoFile -> savedAssets.none { it.assetUrl.remarks == geoFile } }
|
||||
.map {
|
||||
AssetUrlCache(
|
||||
Utils.getUuid(),
|
||||
// Built-in rows have no persisted GUID; keep their UI identity across reloads.
|
||||
"builtin:$it",
|
||||
AssetUrlItem(
|
||||
it,
|
||||
String.format(AppConfig.GITHUB_DOWNLOAD_URL, geoFilesSource).concatUrl(it),
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.v2ray.ang.ui.userasset
|
||||
|
||||
import android.app.Application
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.dto.entities.AssetUrlCache
|
||||
import com.v2ray.ang.dto.entities.AssetUrlItem
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import org.mockito.Mockito.mock
|
||||
|
||||
class UserAssetViewModelTest {
|
||||
private val viewModel = UserAssetViewModel(mock(Application::class.java))
|
||||
|
||||
@Test
|
||||
fun builtInIdentitySurvivesReloadAndSourceChange() {
|
||||
val first = viewModel.buildAssetList(null, "first/source")
|
||||
val reloaded = viewModel.buildAssetList(emptyList(), "second/source")
|
||||
|
||||
assertEquals(3, first.size)
|
||||
assertEquals(first.size, first.map { it.guid }.distinct().size)
|
||||
assertEquals(first.map { it.guid }, reloaded.map { it.guid })
|
||||
assertTrue(reloaded.all { it.assetUrl.locked == true })
|
||||
assertEquals(
|
||||
AppConfig.GEOIP_ONLY_CN_PRIVATE_URL,
|
||||
reloaded.single { it.assetUrl.remarks == AppConfig.GEOIP_ONLY_CN_PRIVATE_DAT }.assetUrl.url,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun savedAssetKeepsItsIdentityAndReplacesMatchingBuiltIn() {
|
||||
val saved = AssetUrlCache("saved-guid", AssetUrlItem(AppConfig.GEOSITE_DAT, "https://example.invalid/geosite.dat"))
|
||||
val custom = AssetUrlCache("custom-guid", AssetUrlItem("custom.dat", "file"))
|
||||
val builtIns = viewModel.buildAssetList(emptyList(), "source")
|
||||
val rows = viewModel.buildAssetList(listOf(saved, custom), "source")
|
||||
|
||||
assertEquals(4, rows.size)
|
||||
assertEquals(saved, rows.single { it.assetUrl.remarks == saved.assetUrl.remarks })
|
||||
assertEquals(custom, rows.single { it.guid == custom.guid })
|
||||
assertEquals(
|
||||
builtIns.filter { it.assetUrl.remarks != AppConfig.GEOSITE_DAT }.map { it.guid },
|
||||
rows.filter { it.assetUrl.locked == true }.map { it.guid },
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user