From 8aca5e4ef29264ceb580a6ae3e95ffbc38a392b2 Mon Sep 17 00:00:00 2001 From: zarzet <42882290+zarzet@users.noreply.github.com> Date: Sun, 18 Oct 2026 22:28:23 +0700 Subject: [PATCH] refactor(android): drop unreachable dispatch cases and dead channel handlers RustCoreBackend.invokeApplication handled readFileMetadata, editFileMetadata and cancelNativeDataJob, but MainActivity intercepts all three first: the metadata methods are in nativeBackendMethods and dispatchBackendApplication answers cancelNativeDataJob before it calls invokeApplication. No Kotlin code calls invokeApplication with those names. Dart never sends these channel methods, so their handlers go on every platform: - shareMultipleContentUris (Android) and getAvailableLyricsProviders (Android and iOS) have no Dart caller. - scanLibraryFolderIncrementalFromSnapshot and scanSafTreeIncrementalFromSnapshot are called only from the Dart host branch of the library scan, which runs only when supportsCoreBackend is false, that is never on Android or iOS. The unreachable Dart wrappers are removed separately. The allowlist and the when cases in MainActivity stay in sync (70 names). The UniFFI exports get_available_lyrics_providers_json and scan_library_folder_incremental_from_snapshot were used only by the removed handlers; the backend methods behind them stay. --- .../kotlin/com/zarz/spotiflac/CoreBackend.kt | 1 - .../kotlin/com/zarz/spotiflac/MainActivity.kt | 49 ------------------- .../com/zarz/spotiflac/SelectedCoreBackend.kt | 26 ---------- ios/Runner/CoreBackend.swift | 1 - rust_backend/crates/mobile/src/lyrics.rs | 6 --- rust_backend/crates/mobile/src/tags.rs | 14 ------ 6 files changed, 97 deletions(-) diff --git a/android/app/src/main/kotlin/com/zarz/spotiflac/CoreBackend.kt b/android/app/src/main/kotlin/com/zarz/spotiflac/CoreBackend.kt index a2618434..3cfe05db 100644 --- a/android/app/src/main/kotlin/com/zarz/spotiflac/CoreBackend.kt +++ b/android/app/src/main/kotlin/com/zarz/spotiflac/CoreBackend.kt @@ -190,7 +190,6 @@ internal interface CoreBackend { fun setLibraryCoverCacheDirectory(path: String) fun scanLibraryFolderToNdjsonFile(folder: String, output: String): Long fun scanLibraryFolderIncremental(folder: String, existing: String): String - fun scanLibraryFolderIncrementalFromSnapshot(folder: String, snapshot: String): String fun getLibraryScanProgress(): String fun cancelLibraryScan() fun pauseLibraryScan() diff --git a/android/app/src/main/kotlin/com/zarz/spotiflac/MainActivity.kt b/android/app/src/main/kotlin/com/zarz/spotiflac/MainActivity.kt index dd9c31d4..7e222088 100644 --- a/android/app/src/main/kotlin/com/zarz/spotiflac/MainActivity.kt +++ b/android/app/src/main/kotlin/com/zarz/spotiflac/MainActivity.kt @@ -93,10 +93,8 @@ class MainActivity: FlutterFragmentActivity() { "setLibraryCoverCacheDir", "scanLibraryFolderToNDJSONFile", "scanLibraryFolderIncremental", - "scanLibraryFolderIncrementalFromSnapshot", "scanSafTreeToNDJSONFile", "scanSafTreeIncremental", - "scanSafTreeIncrementalFromSnapshot", "getLibraryScanProgress", "cancelLibraryScan", "pauseLibraryScan", @@ -119,7 +117,6 @@ class MainActivity: FlutterFragmentActivity() { "safClosePlaybackLease", "openContentUri", "shareContentUri", - "shareMultipleContentUris", "getSafFileModTimes", "safCreateFromPath", "safCreateIfAbsentFromPath", @@ -1499,28 +1496,6 @@ class MainActivity: FlutterFragmentActivity() { result.error("share_failed", e.message, null) } } - "shareMultipleContentUris" -> { - val uriStrings = call.argument>("uris") ?: emptyList() - val title = call.argument("title") ?: "" - try { - val uris = ArrayList(uriStrings.size) - for (s in uriStrings) { - uris.add(Uri.parse(s)) - } - val shareIntent = Intent(Intent.ACTION_SEND_MULTIPLE).apply { - putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris) - setType("audio/*") - addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - if (title.isNotBlank()) { - putExtra(Intent.EXTRA_SUBJECT, title) - } - } - startActivity(Intent.createChooser(shareIntent, title.ifBlank { "Share" })) - result.success(true) - } catch (e: Exception) { - result.error("share_failed", e.message, null) - } - } "rewriteSplitArtistTags" -> { val filePath = call.argument("file_path") ?: "" val artist = call.argument("artist") ?: "" @@ -2015,20 +1990,6 @@ class MainActivity: FlutterFragmentActivity() { } result.success(response) } - "scanLibraryFolderIncrementalFromSnapshot" -> { - val folderPath = call.argument("folder_path") ?: "" - val snapshotPath = call.argument("snapshot_path") ?: "" - val response = withContext(Dispatchers.IO) { - safScanActive = false - bridgeJsonResult( - coreBackend.scanLibraryFolderIncrementalFromSnapshot( - folderPath, - snapshotPath, - ) - ) - } - result.success(response) - } "scanSafTreeToNDJSONFile" -> { val treeUri = call.argument("tree_uri") ?: "" val outputPath = call.argument("output_path") ?: "" @@ -2045,16 +2006,6 @@ class MainActivity: FlutterFragmentActivity() { } result.success(response) } - "scanSafTreeIncrementalFromSnapshot" -> { - val treeUri = call.argument("tree_uri") ?: "" - val snapshotPath = call.argument("snapshot_path") ?: "" - val response = withContext(Dispatchers.IO) { - val existingFiles = - loadExistingFilesFromSnapshot(snapshotPath) - scanSafTreeIncremental(treeUri, existingFiles) - } - result.success(response) - } "getSafFileModTimes" -> { val uris = call.argument("uris") ?: "[]" val response = withContext(Dispatchers.IO) { diff --git a/android/app/src/rust/kotlin/com/zarz/spotiflac/SelectedCoreBackend.kt b/android/app/src/rust/kotlin/com/zarz/spotiflac/SelectedCoreBackend.kt index ce9a3778..3855a863 100644 --- a/android/app/src/rust/kotlin/com/zarz/spotiflac/SelectedCoreBackend.kt +++ b/android/app/src/rust/kotlin/com/zarz/spotiflac/SelectedCoreBackend.kt @@ -358,18 +358,6 @@ internal object RustCoreBackend : CoreBackend { it.scanLibraryFolderIncremental(File(folder).canonicalPath, existing, null) } - override fun scanLibraryFolderIncrementalFromSnapshot(folder: String, snapshot: String): String = - withLibraryDirectories(listOf(folder)) { current -> - if (snapshot.isEmpty()) current.scanLibraryFolderIncremental(File(folder).canonicalPath, "{}", null) - else { - val staged = workspace.createTemporaryFile("library_snapshot_", ".ndjson") - try { - File(snapshot).copyTo(staged, overwrite = true) - current.scanLibraryFolderIncrementalFromSnapshot(File(folder).canonicalPath, staged.canonicalPath, null) - } finally { staged.delete() } - } - } - override fun getLibraryScanProgress(): String = synchronized(this) { manager }?.getLibraryScanProgress() ?: "{}" @@ -598,10 +586,6 @@ internal object RustCoreBackend : CoreBackend { return (0 until values.length()).map { values.getString(it) } } when (method) { - "cancelNativeDataJob" -> { - NativeDataJobs.cancel(string("request_id")) - return null - } "cancelExtensionRequest" -> synchronized(this) { requestRegistry().cancel(string("request_id")) return null @@ -656,15 +640,6 @@ internal object RustCoreBackend : CoreBackend { } "buildFilename" -> return buildFilename(string("template"), string("metadata", "{}")) "sanitizeFilename" -> return sanitizeFilename(string("filename")) - "readFileMetadata", "editFileMetadata" -> return try { - if (method == "readFileMetadata") { - readFileMetadata(string("file_path"), string("display_name")) - } else { - editFileMetadata(string("file_path"), string("metadata_json", "{}")) - } - } catch (error: Exception) { - JSONObject().put("error", error.message ?: "File metadata operation failed").toString() - } "getLogsSince" -> return synchronized(this) { manager?.environment()?.use { environment -> environment.logBuffer().use { it.since((args["index"] as? Number)?.toLong() ?: 0L) } @@ -773,7 +748,6 @@ internal object RustCoreBackend : CoreBackend { "getProviderPriority", "getMetadataProviderPriority" -> { JSONObject(current.providerPriorities()).optJSONArray(if (method == "getProviderPriority") "download" else "metadata")?.toString() ?: "[]" } - "getAvailableLyricsProviders" -> current.getAvailableLyricsProvidersJson() "searchTracksWithMetadataProviders" -> current.searchMetadataProviders( string("query"), (args["limit"] as? Number)?.toLong() ?: 20L, diff --git a/ios/Runner/CoreBackend.swift b/ios/Runner/CoreBackend.swift index 07e5861b..86a060ea 100644 --- a/ios/Runner/CoreBackend.swift +++ b/ios/Runner/CoreBackend.swift @@ -855,7 +855,6 @@ final class RustCoreBackend: CoreBackend { let priorities = try JSONSerialization.jsonObject(with: Data(current.providerPriorities().utf8)) as! [String: Any] let value = priorities[method == "getProviderPriority" ? "download" : "metadata"] as? [String] ?? [] return String(decoding: try JSONSerialization.data(withJSONObject: value), as: UTF8.self) - case "getAvailableLyricsProviders": return try current.getAvailableLyricsProvidersJson() default: throw failure("Rust application method is not connected yet: \(method)") } } diff --git a/rust_backend/crates/mobile/src/lyrics.rs b/rust_backend/crates/mobile/src/lyrics.rs index fd63b4d6..449f3235 100644 --- a/rust_backend/crates/mobile/src/lyrics.rs +++ b/rust_backend/crates/mobile/src/lyrics.rs @@ -88,12 +88,6 @@ impl ExtensionManager { .map_err(ExtensionManagerError::Operation) } - pub fn get_available_lyrics_providers_json(&self) -> Result { - self.inner - .get_available_lyrics_providers_json() - .map_err(ExtensionManagerError::Operation) - } - pub fn set_lyrics_fetch_options_json( &self, options_json: String, diff --git a/rust_backend/crates/mobile/src/tags.rs b/rust_backend/crates/mobile/src/tags.rs index 2e8e2f10..9da7a016 100644 --- a/rust_backend/crates/mobile/src/tags.rs +++ b/rust_backend/crates/mobile/src/tags.rs @@ -140,20 +140,6 @@ impl ExtensionManager { .map_err(ExtensionManagerError::Operation) } - pub fn scan_library_folder_incremental_from_snapshot( - &self, - folder: String, - snapshot: String, - lease: Option>, - ) -> Result { - self.inner - .scan_library_folder_incremental_from_snapshot(&folder, &snapshot, &|| { - check_lease(lease.as_deref()) - }) - .map(|value| value.to_string()) - .map_err(ExtensionManagerError::Operation) - } - pub fn scan_library_folder_to_ndjson_file( &self, folder: String,