mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-09-13 05:19:04 +02:00
perf(library): page missing-file cleanup with safe SAF batch checks
This commit is contained in:
@@ -1115,6 +1115,13 @@ class MainActivity: FlutterFragmentActivity() {
|
||||
}
|
||||
result.success(exists)
|
||||
}
|
||||
"safExistsBatch" -> {
|
||||
val urisJson = call.argument<String>("uris_json") ?: "[]"
|
||||
val response = withContext(Dispatchers.IO) {
|
||||
safExistsBatch(urisJson)
|
||||
}
|
||||
result.success(response)
|
||||
}
|
||||
"isSafTreeAccessible" -> {
|
||||
val uriStr = call.argument<String>("tree_uri") ?: ""
|
||||
val accessible = withContext(Dispatchers.IO) {
|
||||
|
||||
@@ -1558,10 +1558,51 @@ internal fun MainActivity.scanSafTreeIncremental(
|
||||
return spill.result()
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve SAF file last-modified values for a list of content URIs.
|
||||
* Returns JSON object mapping uri -> lastModified (unix millis).
|
||||
*/
|
||||
// A failed DocumentsProvider query must never be mistaken for a missing file.
|
||||
// Unlike DocumentFile.exists(), this keeps null cursors/exceptions inconclusive.
|
||||
internal fun MainActivity.safExistsBatch(urisJson: String): String {
|
||||
val result = JSONObject()
|
||||
val uris = JSONArray(urisJson)
|
||||
val accessibleTrees = mutableMapOf<String, Boolean>()
|
||||
val permissions = contentResolver.persistedUriPermissions
|
||||
val projection = arrayOf(DocumentsContract.Document.COLUMN_DOCUMENT_ID)
|
||||
for (index in 0 until uris.length()) {
|
||||
val path = uris.optString(index)
|
||||
if (path.isBlank()) continue
|
||||
var status = "unknown"
|
||||
try {
|
||||
val uri = Uri.parse(path)
|
||||
val treeAccessible = if (DocumentsContract.isTreeUri(uri)) {
|
||||
val treeId = DocumentsContract.getTreeDocumentId(uri)
|
||||
val tree = DocumentsContract.buildTreeDocumentUri(uri.authority, treeId)
|
||||
accessibleTrees.getOrPut(tree.toString()) {
|
||||
val granted = permissions.any { it.uri == tree && it.isReadPermission }
|
||||
if (!granted) false else {
|
||||
val root = DocumentsContract.buildDocumentUriUsingTree(tree, treeId)
|
||||
contentResolver.query(root, projection, null, null, null)?.use {
|
||||
it.moveToFirst()
|
||||
} == true
|
||||
}
|
||||
}
|
||||
} else false
|
||||
contentResolver.query(uri, projection, null, null, null)?.use { cursor ->
|
||||
status = if (cursor.moveToFirst()) "found"
|
||||
else if (treeAccessible &&
|
||||
!cursor.extras.getBoolean(DocumentsContract.EXTRA_LOADING, false))
|
||||
"missing" else "unknown"
|
||||
}
|
||||
} catch (_: Exception) {
|
||||
// Revoked permission, offline storage and provider errors: retain row.
|
||||
}
|
||||
result.put(path, status)
|
||||
}
|
||||
return result.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve SAF file last-modified values for a list of content URIs.
|
||||
* Returns JSON object mapping uri -> lastModified (unix millis).
|
||||
*/
|
||||
internal fun MainActivity.getSafFileModTimes(urisJson: String): String {
|
||||
val result = JSONObject()
|
||||
val uris = try {
|
||||
|
||||
Reference in New Issue
Block a user