diff --git a/Android/project/app/build.gradle.kts b/Android/project/app/build.gradle.kts index 4aaf1623..e7e5ae1e 100644 --- a/Android/project/app/build.gradle.kts +++ b/Android/project/app/build.gradle.kts @@ -31,7 +31,21 @@ android { kotlinOptions { jvmTarget = "1.8" } - sourceSets["main"].assets.srcDir("../../../apps/client/dist") + val clientDist = file("../../../apps/client/dist") + val webAssets = layout.buildDirectory.dir("generated/web-assets") + val prepareWebAssets = tasks.register("prepareWebAssets") { + from(clientDist) + into(webAssets.map { it.dir("public") }) + doFirst { + check(clientDist.isDirectory) { + "Client assets are missing. Run 'pnpm --dir apps/client build' first." + } + } + } + + sourceSets["main"].assets.srcDir(webAssets) + tasks.matching { it.name.startsWith("merge") && it.name.endsWith("Assets") } + .configureEach { dependsOn(prepareWebAssets) } } dependencies { diff --git a/Android/project/app/src/main/kotlin/com/xmedia/archive/data/ArchiveDao.kt b/Android/project/app/src/main/kotlin/com/xmedia/archive/data/ArchiveDao.kt index c8536d99..6355beda 100644 --- a/Android/project/app/src/main/kotlin/com/xmedia/archive/data/ArchiveDao.kt +++ b/Android/project/app/src/main/kotlin/com/xmedia/archive/data/ArchiveDao.kt @@ -42,6 +42,9 @@ interface ArchiveDao { @Query("DELETE FROM media WHERE jobId NOT IN (SELECT id FROM jobs)") suspend fun deleteOrphanMedia() + @Query("UPDATE jobs SET status = 'queued', progress = 0, error = NULL, updatedAt = :updatedAt WHERE status IN ('resolving', 'downloading')") + suspend fun requeueInterrupted(updatedAt: String): Int + @Transaction suspend fun replaceMedia(jobId: String, media: List) { deleteMedia(jobId) diff --git a/Android/project/app/src/main/kotlin/com/xmedia/archive/plugin/LocalArchivePlugin.kt b/Android/project/app/src/main/kotlin/com/xmedia/archive/plugin/LocalArchivePlugin.kt index 4fcb4d77..3bc7e8d9 100644 --- a/Android/project/app/src/main/kotlin/com/xmedia/archive/plugin/LocalArchivePlugin.kt +++ b/Android/project/app/src/main/kotlin/com/xmedia/archive/plugin/LocalArchivePlugin.kt @@ -2,6 +2,8 @@ package com.xmedia.archive.plugin import android.content.Intent import android.net.Uri +import android.os.Build +import android.provider.DocumentsContract import com.getcapacitor.JSObject import com.getcapacitor.Plugin import com.getcapacitor.PluginCall @@ -71,6 +73,30 @@ class LocalArchivePlugin : Plugin() { @PluginMethod fun openMedia(call: PluginCall) = launchMediaIntent(call, Intent.ACTION_VIEW) + @PluginMethod + fun openMediaFolder(call: PluginCall) { + val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply { + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION) + addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + putExtra( + DocumentsContract.EXTRA_INITIAL_URI, + DocumentsContract.buildTreeDocumentUri( + "com.android.externalstorage.documents", + "primary:Download/X Media Archive", + ), + ) + } + } + runCatching { + context.startActivity(intent) + call.resolve() + }.onFailure { error -> + call.reject(error.message ?: "无法打开媒体文件夹") + } + } + @PluginMethod fun shareMedia(call: PluginCall) = launchMediaIntent(call, Intent.ACTION_SEND) diff --git a/Android/project/app/src/main/kotlin/com/xmedia/archive/repository/ArchiveRepository.kt b/Android/project/app/src/main/kotlin/com/xmedia/archive/repository/ArchiveRepository.kt index ba51b282..a7caeacc 100644 --- a/Android/project/app/src/main/kotlin/com/xmedia/archive/repository/ArchiveRepository.kt +++ b/Android/project/app/src/main/kotlin/com/xmedia/archive/repository/ArchiveRepository.kt @@ -52,6 +52,8 @@ class ArchiveRepository(context: Context) { suspend fun update(job: JobEntity) = dao.upsertJob(job.copy(updatedAt = Instant.now().toString())) + suspend fun requeueInterrupted() = dao.requeueInterrupted(Instant.now().toString()) + suspend fun replaceMedia(jobId: String, media: List) = dao.replaceMedia(jobId, media) suspend fun clearHistory(): Int { diff --git a/Android/project/app/src/main/kotlin/com/xmedia/archive/service/DownloadForegroundService.kt b/Android/project/app/src/main/kotlin/com/xmedia/archive/service/DownloadForegroundService.kt index 51b04d55..2b971f3e 100644 --- a/Android/project/app/src/main/kotlin/com/xmedia/archive/service/DownloadForegroundService.kt +++ b/Android/project/app/src/main/kotlin/com/xmedia/archive/service/DownloadForegroundService.kt @@ -59,6 +59,7 @@ class DownloadForegroundService : Service() { private suspend fun runQueue() { try { + repository.requeueInterrupted() while (true) { val jobs = ArchiveDatabase.get(this).dao().listJobs().filter { it.status == JobStatus.QUEUED.name.lowercase() } if (jobs.isEmpty()) break diff --git a/Android/project/app/src/main/res/values/styles.xml b/Android/project/app/src/main/res/values/styles.xml index 8b002102..df059c18 100644 --- a/Android/project/app/src/main/res/values/styles.xml +++ b/Android/project/app/src/main/res/values/styles.xml @@ -1,6 +1,6 @@ -