parent
dd1a19745a
commit
36f400d542
5 changed files with 54 additions and 44 deletions
|
@ -22,7 +22,7 @@ android {
|
|||
defaultConfig {
|
||||
applicationId = "eu.kanade.tachiyomi"
|
||||
|
||||
versionCode = 112
|
||||
versionCode = 113
|
||||
versionName = "0.14.7"
|
||||
|
||||
buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"")
|
||||
|
|
|
@ -41,7 +41,6 @@ import eu.kanade.tachiyomi.data.backup.BackupCreateJob
|
|||
import eu.kanade.tachiyomi.data.backup.BackupFileValidator
|
||||
import eu.kanade.tachiyomi.data.backup.BackupRestoreJob
|
||||
import eu.kanade.tachiyomi.data.cache.ChapterCache
|
||||
import eu.kanade.tachiyomi.data.download.DownloadCache
|
||||
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
||||
import eu.kanade.tachiyomi.util.system.DeviceUtil
|
||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
|
@ -98,7 +97,6 @@ object SettingsDataScreen : SearchableSettings {
|
|||
UniFile.fromUri(context, uri)?.let {
|
||||
storageDirPref.set(it.uri.toString())
|
||||
}
|
||||
Injekt.get<DownloadCache>().invalidateCache()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -381,12 +381,7 @@ object Migrations {
|
|||
newKey = { Preference.privateKey(it) },
|
||||
)
|
||||
}
|
||||
if (oldVersion < 111) {
|
||||
File(context.cacheDir, "dl_index_cache")
|
||||
.takeIf { it.exists() }
|
||||
?.delete()
|
||||
}
|
||||
if (oldVersion < 112) {
|
||||
if (oldVersion < 113) {
|
||||
val prefsToReplace = listOf(
|
||||
"pref_download_only",
|
||||
"incognito_mode",
|
||||
|
@ -406,6 +401,9 @@ object Migrations {
|
|||
filterPredicate = { it.key in prefsToReplace },
|
||||
newKey = { Preference.appStateKey(it) },
|
||||
)
|
||||
|
||||
// Deleting old download cache index files, but might as well clear it all out
|
||||
context.cacheDir.deleteRecursively()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ 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
|
||||
|
@ -48,7 +47,7 @@ import tachiyomi.core.util.system.logcat
|
|||
import tachiyomi.domain.chapter.model.Chapter
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
import tachiyomi.domain.storage.service.StoragePreferences
|
||||
import tachiyomi.domain.storage.service.StorageManager
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.io.File
|
||||
|
@ -66,7 +65,7 @@ class DownloadCache(
|
|||
private val provider: DownloadProvider = Injekt.get(),
|
||||
private val sourceManager: SourceManager = Injekt.get(),
|
||||
private val extensionManager: ExtensionManager = Injekt.get(),
|
||||
storagePreferences: StoragePreferences = Injekt.get(),
|
||||
private val storageManager: StorageManager = Injekt.get(),
|
||||
) {
|
||||
|
||||
private val scope = CoroutineScope(Dispatchers.IO)
|
||||
|
@ -74,7 +73,7 @@ class DownloadCache(
|
|||
private val _changes: Channel<Unit> = Channel(Channel.UNLIMITED)
|
||||
val changes = _changes.receiveAsFlow()
|
||||
.onStart { emit(Unit) }
|
||||
.shareIn(scope, SharingStarted.Eagerly, 1)
|
||||
.shareIn(scope, SharingStarted.Lazily, 1)
|
||||
|
||||
/**
|
||||
* The interval after which this cache should be invalidated. 1 hour shouldn't cause major
|
||||
|
@ -94,10 +93,10 @@ class DownloadCache(
|
|||
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
|
||||
|
||||
private val diskCacheFile: File
|
||||
get() = File(context.cacheDir, "dl_index_cache_v2")
|
||||
get() = File(context.cacheDir, "dl_index_cache_v3")
|
||||
|
||||
private val rootDownloadsDirLock = Mutex()
|
||||
private var rootDownloadsDir = RootDirectory(provider.downloadsDir)
|
||||
private var rootDownloadsDir = RootDirectory(storageManager.getDownloadsDirectory())
|
||||
|
||||
init {
|
||||
// Attempt to read cache file
|
||||
|
@ -115,12 +114,8 @@ class DownloadCache(
|
|||
}
|
||||
}
|
||||
|
||||
storagePreferences.baseStorageDirectory().changes()
|
||||
.drop(1)
|
||||
.onEach {
|
||||
rootDownloadsDir = RootDirectory(provider.downloadsDir)
|
||||
invalidateCache()
|
||||
}
|
||||
storageManager.changes
|
||||
.onEach { invalidateCache() }
|
||||
.launchIn(scope)
|
||||
}
|
||||
|
||||
|
@ -294,6 +289,8 @@ class DownloadCache(
|
|||
fun invalidateCache() {
|
||||
lastRenew = 0L
|
||||
renewalJob?.cancel()
|
||||
diskCacheFile.delete()
|
||||
renewCache()
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -310,23 +307,26 @@ class DownloadCache(
|
|||
_isInitializing.emit(true)
|
||||
}
|
||||
|
||||
var sources = getSources()
|
||||
|
||||
// Try to wait until extensions and sources have loaded
|
||||
withTimeoutOrNull(30.seconds) {
|
||||
while (!extensionManager.isInitialized) {
|
||||
delay(2.seconds)
|
||||
}
|
||||
var sources = getSources()
|
||||
if (sources.isEmpty()) {
|
||||
withTimeoutOrNull(30.seconds) {
|
||||
while (!extensionManager.isInitialized) {
|
||||
delay(2.seconds)
|
||||
}
|
||||
|
||||
while (sources.isEmpty()) {
|
||||
delay(2.seconds)
|
||||
sources = getSources()
|
||||
while (extensionManager.availableExtensionsFlow.value.isNotEmpty() && sources.isEmpty()) {
|
||||
delay(2.seconds)
|
||||
sources = getSources()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val sourceMap = sources.associate { provider.getSourceDirName(it).lowercase() to it.id }
|
||||
|
||||
rootDownloadsDirLock.withLock {
|
||||
rootDownloadsDir = RootDirectory(storageManager.getDownloadsDirectory())
|
||||
|
||||
val sourceDirs = rootDownloadsDir.dir?.listFiles().orEmpty()
|
||||
.filter { it.isDirectory && !it.name.isNullOrBlank() }
|
||||
.mapNotNull { dir ->
|
||||
|
@ -371,10 +371,9 @@ class DownloadCache(
|
|||
}.also {
|
||||
it.invokeOnCompletion(onCancelling = true) { exception ->
|
||||
if (exception != null && exception !is CancellationException) {
|
||||
logcat(LogPriority.ERROR, exception) { "Failed to create download cache" }
|
||||
logcat(LogPriority.ERROR, exception) { "DownloadCache: failed to create cache" }
|
||||
}
|
||||
lastRenew = System.currentTimeMillis()
|
||||
|
||||
notifyChanges()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,14 @@ import com.hippo.unifile.UniFile
|
|||
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.drop
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.receiveAsFlow
|
||||
import kotlinx.coroutines.flow.shareIn
|
||||
|
||||
class StorageManager(
|
||||
private val context: Context,
|
||||
|
@ -16,24 +22,33 @@ class StorageManager(
|
|||
|
||||
private val scope = CoroutineScope(Dispatchers.IO)
|
||||
|
||||
private var baseDir: UniFile? = storagePreferences.baseStorageDirectory().get().let(::getBaseDir)
|
||||
private var baseDir: UniFile? = getBaseDir(storagePreferences.baseStorageDirectory().get())
|
||||
|
||||
private val _changes: Channel<Unit> = Channel(Channel.UNLIMITED)
|
||||
val changes = _changes.receiveAsFlow()
|
||||
.shareIn(scope, SharingStarted.Lazily, 1)
|
||||
|
||||
init {
|
||||
storagePreferences.baseStorageDirectory().changes()
|
||||
.onEach { baseDir = getBaseDir(it) }
|
||||
.drop(1)
|
||||
.distinctUntilChanged()
|
||||
.onEach { uri ->
|
||||
baseDir = getBaseDir(uri)
|
||||
baseDir?.let { parent ->
|
||||
parent.createDirectory(AUTOMATIC_BACKUPS_PATH)
|
||||
parent.createDirectory(LOCAL_SOURCE_PATH)
|
||||
parent.createDirectory(DOWNLOADS_PATH).also {
|
||||
DiskUtil.createNoMediaFile(it, context)
|
||||
}
|
||||
}
|
||||
_changes.send(Unit)
|
||||
}
|
||||
.launchIn(scope)
|
||||
}
|
||||
|
||||
private fun getBaseDir(path: String): UniFile? {
|
||||
val file = UniFile.fromUri(context, path.toUri())
|
||||
|
||||
return file.takeIf { it?.exists() == true }?.also { parent ->
|
||||
parent.createDirectory(AUTOMATIC_BACKUPS_PATH)
|
||||
parent.createDirectory(LOCAL_SOURCE_PATH)
|
||||
parent.createDirectory(DOWNLOADS_PATH).also {
|
||||
DiskUtil.createNoMediaFile(it, context)
|
||||
}
|
||||
}
|
||||
private fun getBaseDir(uri: String): UniFile? {
|
||||
return UniFile.fromUri(context, uri.toUri())
|
||||
.takeIf { it?.exists() == true }
|
||||
}
|
||||
|
||||
fun getAutomaticBackupsDirectory(): UniFile? {
|
||||
|
|
Reference in a new issue