Refactor asset URL handling with AssetUrlCache data class

This commit is contained in:
2dust committed 2026-01-29 14:43:31 +08:00
1 parent d46bbdc219
commit 685d23f2d1
6 files changed
+38 -26

No files matched your search

@@ -0,0 +1,6 @@
package com.v2ray.ang.dto
data class AssetUrlCache(
val guid: String,
val assetUrl: AssetUrlItem
)
@@ -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<Pair<String, AssetUrlItem>> {
val assetUrlItems = mutableListOf<Pair<String, AssetUrlItem>>()
fun decodeAssetUrls(): List<AssetUrlCache> {
val assetUrlItems = mutableListOf<AssetUrlCache>()
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 }
}
/**
@@ -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) { _, _ ->
@@ -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)
}
}
@@ -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
}
@@ -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<Pair<String, AssetUrlItem>>()
private val assets = mutableListOf<AssetUrlCache>()
private val builtInGeoFiles = listOf("geosite.dat", "geoip.dat")
val itemCount: Int
get() = assets.size
fun getAssets(): List<Pair<String, AssetUrlItem>> = assets.toList()
fun getAssets(): List<AssetUrlCache> = assets.toList()
fun getAsset(position: Int): Pair<String, AssetUrlItem>? = 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<Pair<String, AssetUrlItem>>?,
decodedAssets: List<AssetUrlCache>?,
geoFilesSource: String
): List<Pair<String, AssetUrlItem>> {
): List<AssetUrlCache> {
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<String>()
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++