Minor download location cleanup

This commit is contained in:
arkon 2023-11-25 16:51:32 -05:00
parent f1778ac5b4
commit 21ae04d25d
2 changed files with 54 additions and 41 deletions

View File

@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.data.download
import android.app.Application
import android.content.Context
import android.net.Uri
import androidx.core.net.toUri
import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.extension.ExtensionManager
import eu.kanade.tachiyomi.source.Source
@ -19,6 +18,7 @@ import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
@ -64,7 +64,7 @@ class DownloadCache(
private val provider: DownloadProvider = Injekt.get(),
private val sourceManager: SourceManager = Injekt.get(),
private val extensionManager: ExtensionManager = Injekt.get(),
private val storagePreferences: StoragePreferences = Injekt.get(),
storagePreferences: StoragePreferences = Injekt.get(),
) {
private val scope = CoroutineScope(Dispatchers.IO)
@ -95,16 +95,9 @@ class DownloadCache(
get() = File(context.cacheDir, "dl_index_cache")
private val rootDownloadsDirLock = Mutex()
private var rootDownloadsDir = RootDirectory(getDirectoryFromPreference())
private var rootDownloadsDir = RootDirectory(provider.downloadsDir)
init {
storagePreferences.baseStorageDirectory().changes()
.onEach {
rootDownloadsDir = RootDirectory(getDirectoryFromPreference())
invalidateCache()
}
.launchIn(scope)
// Attempt to read cache file
scope.launch {
rootDownloadsDirLock.withLock {
@ -119,6 +112,14 @@ class DownloadCache(
}
}
}
storagePreferences.baseStorageDirectory().changes()
.drop(1)
.onEach {
rootDownloadsDir = RootDirectory(provider.downloadsDir)
invalidateCache()
}
.launchIn(scope)
}
/**
@ -293,17 +294,6 @@ class DownloadCache(
renewalJob?.cancel()
}
/**
* Returns the downloads directory from the user's preferences.
*/
private fun getDirectoryFromPreference(): UniFile {
return storagePreferences.baseStorageDirectory().get().let {
UniFile.fromUri(context, it.toUri()).also {
it?.createDirectory(StoragePreferences.DOWNLOADS_DIR)
}
}
}
/**
* Renews the downloads cache.
*/
@ -335,7 +325,7 @@ class DownloadCache(
val sourceMap = sources.associate { provider.getSourceDirName(it).lowercase() to it.id }
rootDownloadsDirLock.withLock {
val sourceDirs = rootDownloadsDir.dir.listFiles().orEmpty()
val sourceDirs = rootDownloadsDir.dir?.listFiles().orEmpty()
.filter { it.isDirectory && !it.name.isNullOrBlank() }
.mapNotNull { dir ->
val sourceId = sourceMap[dir.name!!.lowercase()]
@ -348,12 +338,12 @@ class DownloadCache(
sourceDirs.values
.map { sourceDir ->
async {
sourceDir.mangaDirs = sourceDir.dir.listFiles().orEmpty()
sourceDir.mangaDirs = sourceDir.dir?.listFiles().orEmpty()
.filter { it.isDirectory && !it.name.isNullOrBlank() }
.associate { it.name!! to MangaDirectory(it) }
sourceDir.mangaDirs.values.forEach { mangaDir ->
val chapterDirs = mangaDir.dir.listFiles().orEmpty()
val chapterDirs = mangaDir.dir?.listFiles().orEmpty()
.mapNotNull {
when {
// Ignore incomplete downloads
@ -430,7 +420,7 @@ class DownloadCache(
@Serializable
private class RootDirectory(
@Serializable(with = UniFileAsStringSerializer::class)
val dir: UniFile,
val dir: UniFile?,
var sourceDirs: Map<Long, SourceDirectory> = mapOf(),
)
@ -440,7 +430,7 @@ private class RootDirectory(
@Serializable
private class SourceDirectory(
@Serializable(with = UniFileAsStringSerializer::class)
val dir: UniFile,
val dir: UniFile?,
var mangaDirs: Map<String, MangaDirectory> = mapOf(),
)
@ -450,17 +440,26 @@ private class SourceDirectory(
@Serializable
private class MangaDirectory(
@Serializable(with = UniFileAsStringSerializer::class)
val dir: UniFile,
val dir: UniFile?,
var chapterDirs: MutableSet<String> = mutableSetOf(),
)
private object UniFileAsStringSerializer : KSerializer<UniFile> {
private object UniFileAsStringSerializer : KSerializer<UniFile?> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("UniFile", PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: UniFile) {
return encoder.encodeString(value.uri.toString())
override fun serialize(encoder: Encoder, value: UniFile?) {
return if (value == null) {
encoder.encodeNull()
} else {
encoder.encodeString(value.uri.toString())
}
}
override fun deserialize(decoder: Decoder): UniFile {
return UniFile.fromUri(Injekt.get<Application>(), Uri.parse(decoder.decodeString()))
override fun deserialize(decoder: Decoder): UniFile? {
return if (decoder.decodeNotNullMark()) {
UniFile.fromUri(Injekt.get<Application>(), Uri.parse(decoder.decodeString()))
} else {
decoder.decodeNull()
}
}
}

View File

@ -5,6 +5,10 @@ import androidx.core.net.toUri
import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.util.storage.DiskUtil
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import logcat.LogPriority
import tachiyomi.core.i18n.stringResource
import tachiyomi.core.util.system.logcat
@ -23,17 +27,27 @@ import uy.kohesive.injekt.api.get
*/
class DownloadProvider(
private val context: Context,
private val storagePreferences: StoragePreferences = Injekt.get(),
storagePreferences: StoragePreferences = Injekt.get(),
) {
private val downloadsDir: UniFile?
get() = storagePreferences.baseStorageDirectory().get().let {
UniFile.fromUri(context, it.toUri())
?.createDirectory(StoragePreferences.DOWNLOADS_DIR)
?.also { dir ->
DiskUtil.createNoMediaFile(dir, context)
}
}
private val scope = CoroutineScope(Dispatchers.IO)
private var _downloadsDir: UniFile? =
storagePreferences.baseStorageDirectory().get().let(::getDownloadsLocation)
val downloadsDir: UniFile?
get() = _downloadsDir
init {
storagePreferences.baseStorageDirectory().changes()
.onEach { _downloadsDir = getDownloadsLocation(it) }
.launchIn(scope)
}
private fun getDownloadsLocation(dir: String): UniFile? {
return UniFile.fromUri(context, dir.toUri())
?.createDirectory(StoragePreferences.DOWNLOADS_DIR)
?.also { DiskUtil.createNoMediaFile(it, context) }
}
/**
* Returns the download directory for a manga. For internal use only.