From 685d23f2d11070fe24d17971a85cb053042e6eb9 Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Thu, 29 Jan 2026 14:43:31 +0800 Subject: [PATCH] Refactor asset URL handling with AssetUrlCache data class --- .../java/com/v2ray/ang/dto/AssetUrlCache.kt | 6 +++++ .../java/com/v2ray/ang/handler/MmkvManager.kt | 9 ++++--- .../com/v2ray/ang/ui/UserAssetActivity.kt | 8 +++--- .../java/com/v2ray/ang/ui/UserAssetAdapter.kt | 12 ++++----- .../com/v2ray/ang/ui/UserAssetUrlActivity.kt | 2 +- .../v2ray/ang/viewmodel/UserAssetViewModel.kt | 27 +++++++++++-------- 6 files changed, 38 insertions(+), 26 deletions(-) create mode 100644 V2rayNG/app/src/main/java/com/v2ray/ang/dto/AssetUrlCache.kt diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/dto/AssetUrlCache.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/dto/AssetUrlCache.kt new file mode 100644 index 00000000..92b37530 --- /dev/null +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/dto/AssetUrlCache.kt @@ -0,0 +1,6 @@ +package com.v2ray.ang.dto + +data class AssetUrlCache( + val guid: String, + val assetUrl: AssetUrlItem +) \ No newline at end of file diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/handler/MmkvManager.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/MmkvManager.kt index 697ea0b8..ca3c4e1d 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/handler/MmkvManager.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/MmkvManager.kt @@ -3,6 +3,7 @@ package com.v2ray.ang.handler import com.tencent.mmkv.MMKV import com.v2ray.ang.AppConfig.PREF_IS_BOOTED import com.v2ray.ang.AppConfig.PREF_ROUTING_RULESET +import com.v2ray.ang.dto.AssetUrlCache import com.v2ray.ang.dto.AssetUrlItem import com.v2ray.ang.dto.ProfileItem import com.v2ray.ang.dto.RulesetItem @@ -398,16 +399,16 @@ object MmkvManager { * * @return The list of asset URLs. */ - fun decodeAssetUrls(): List> { - val assetUrlItems = mutableListOf>() + fun decodeAssetUrls(): List { + val assetUrlItems = mutableListOf() assetStorage.allKeys()?.forEach { key -> val json = assetStorage.decodeString(key) if (!json.isNullOrBlank()) { val item = JsonUtil.fromJson(json, AssetUrlItem::class.java)?: AssetUrlItem() - assetUrlItems.add(Pair(key, item)) + assetUrlItems.add(AssetUrlCache(key, item)) } } - return assetUrlItems.sortedBy { (_, value) -> value.addedTime } + return assetUrlItems.sortedBy { it.assetUrl.addedTime } } /** diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/UserAssetActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/UserAssetActivity.kt index b1e2b22d..5fd5ab30 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/UserAssetActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/UserAssetActivity.kt @@ -102,7 +102,7 @@ class UserAssetActivity : HelperBaseActivity() { ) val assetList = MmkvManager.decodeAssetUrls() - if (assetList.any { it.second.remarks == assetItem.remarks && it.first != assetId }) { + if (assetList.any { it.assetUrl.remarks == assetItem.remarks && it.guid != assetId }) { toast(R.string.msg_remark_is_duplicate) } else { MmkvManager.encodeAsset(assetId, assetItem) @@ -211,10 +211,10 @@ class UserAssetActivity : HelperBaseActivity() { } override fun onRemove(guid: String, position: Int) { - val asset = viewModel.getAsset(position)?.takeIf { it.first == guid } - ?: viewModel.getAssets().find { it.first == guid } + val asset = viewModel.getAsset(position)?.takeIf { it.guid == guid } + ?: viewModel.getAssets().find { it.guid == guid } ?: return - val file = extDir.listFiles()?.find { it.name == asset.second.remarks } + val file = extDir.listFiles()?.find { it.name == asset.assetUrl.remarks } AlertDialog.Builder(ownerActivity).setMessage(R.string.del_config_comfirm) .setPositiveButton(android.R.string.ok) { _, _ -> diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/UserAssetAdapter.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/UserAssetAdapter.kt index 6ba38088..ed982c21 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/UserAssetAdapter.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/UserAssetAdapter.kt @@ -34,9 +34,9 @@ class UserAssetAdapter( @SuppressLint("SetTextI18n") override fun onBindViewHolder(holder: UserAssetViewHolder, position: Int) { val item = viewModel.getAsset(position) ?: return - val file = extDir.listFiles()?.find { it.name == item.second.remarks } + val file = extDir.listFiles()?.find { it.name == item.assetUrl.remarks } - holder.itemUserAssetBinding.assetName.text = item.second.remarks + holder.itemUserAssetBinding.assetName.text = item.assetUrl.remarks if (file != null) { val dateFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM) @@ -47,10 +47,10 @@ class UserAssetAdapter( holder.itemUserAssetBinding.root.context.getString(R.string.msg_file_not_found) } - if (item.second.locked == true) { + if (item.assetUrl.locked == true) { holder.itemUserAssetBinding.layoutEdit.visibility = View.GONE } else { - holder.itemUserAssetBinding.layoutEdit.visibility = if (item.second.url == "file") { + holder.itemUserAssetBinding.layoutEdit.visibility = if (item.assetUrl.url == "file") { View.GONE } else { View.VISIBLE @@ -58,10 +58,10 @@ class UserAssetAdapter( } holder.itemUserAssetBinding.layoutEdit.setOnClickListener { - adapterListener?.onEdit(item.first, position) + adapterListener?.onEdit(item.guid, position) } holder.itemUserAssetBinding.layoutRemove.setOnClickListener { - adapterListener?.onRemove(item.first, position) + adapterListener?.onRemove(item.guid, position) } } diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/UserAssetUrlActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/UserAssetUrlActivity.kt index 06657d3a..7a5464fd 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/UserAssetUrlActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/UserAssetUrlActivity.kt @@ -93,7 +93,7 @@ class UserAssetUrlActivity : BaseActivity() { // check remarks unique val assetList = MmkvManager.decodeAssetUrls() - if (assetList.any { it.second.remarks == assetItem.remarks && it.first != assetId }) { + if (assetList.any { it.assetUrl.remarks == assetItem.remarks && it.guid != assetId }) { toast(R.string.msg_remark_is_duplicate) return false } diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/UserAssetViewModel.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/UserAssetViewModel.kt index faf03a74..c92548f8 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/UserAssetViewModel.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/UserAssetViewModel.kt @@ -3,6 +3,7 @@ package com.v2ray.ang.viewmodel import android.util.Log import androidx.lifecycle.ViewModel import com.v2ray.ang.AppConfig +import com.v2ray.ang.dto.AssetUrlCache import com.v2ray.ang.dto.AssetUrlItem import com.v2ray.ang.extension.concatUrl import com.v2ray.ang.handler.MmkvManager @@ -13,15 +14,15 @@ import java.io.FileOutputStream import java.net.HttpURLConnection class UserAssetViewModel : ViewModel() { - private val assets = mutableListOf>() + private val assets = mutableListOf() private val builtInGeoFiles = listOf("geosite.dat", "geoip.dat") val itemCount: Int get() = assets.size - fun getAssets(): List> = assets.toList() + fun getAssets(): List = assets.toList() - fun getAsset(position: Int): Pair? = assets.getOrNull(position) + fun getAsset(position: Int): AssetUrlCache? = assets.getOrNull(position) fun reload(geoFilesSource: String) { val decoded = MmkvManager.decodeAssetUrls() @@ -30,17 +31,20 @@ class UserAssetViewModel : ViewModel() { } private fun buildAssetList( - decodedAssets: List>?, + decodedAssets: List?, geoFilesSource: String - ): List> { + ): List { val savedAssets = decodedAssets ?: emptyList() val builtInItems = builtInGeoFiles - .filter { geoFile -> savedAssets.none { it.second.remarks == geoFile } } + .filter { geoFile -> savedAssets.none { it.assetUrl.remarks == geoFile } } .map { - Utils.getUuid() to AssetUrlItem( - it, - String.format(AppConfig.GITHUB_DOWNLOAD_URL, geoFilesSource).concatUrl(it), - locked = true + AssetUrlCache( + Utils.getUuid(), + AssetUrlItem( + it, + String.format(AppConfig.GITHUB_DOWNLOAD_URL, geoFilesSource).concatUrl(it), + locked = true + ) ) } return builtInItems + savedAssets @@ -51,7 +55,8 @@ class UserAssetViewModel : ViewModel() { var successCount = 0 val failures = mutableListOf() - snapshot.forEach { (_, item) -> + snapshot.forEach { cache -> + val item = cache.assetUrl val portsToTry = if (httpPort == 0) listOf(0) else listOf(httpPort, 0) if (portsToTry.any { tryDownload(item, extDir, it) }) { successCount++