From 27c4db752ce599a99876021c1019cfb549153a30 Mon Sep 17 00:00:00 2001 From: arkon Date: Sat, 25 Nov 2023 22:31:26 -0500 Subject: [PATCH] Actually use configured storage location for local source Fixes #10178 --- .../settings/screen/SettingsDataScreen.kt | 2 + .../tachiyomi/data/backup/BackupCreateJob.kt | 14 +++-- .../data/download/DownloadProvider.kt | 27 ++-------- .../java/eu/kanade/tachiyomi/di/AppModule.kt | 4 +- domain/build.gradle.kts | 2 + .../domain/storage/service/StorageManager.kt | 54 +++++++++++++++++++ .../storage/service/StoragePreferences.kt | 5 -- .../tachiyomi/source/local/LocalSource.kt | 4 +- .../source/local/io/LocalSourceFileSystem.kt | 10 ++-- 9 files changed, 76 insertions(+), 46 deletions(-) create mode 100644 domain/src/main/java/tachiyomi/domain/storage/service/StorageManager.kt diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsDataScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsDataScreen.kt index 461ec4eeb..341cf2bb5 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsDataScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsDataScreen.kt @@ -42,6 +42,7 @@ 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 @@ -100,6 +101,7 @@ object SettingsDataScreen : SearchableSettings { val file = UniFile.fromUri(context, uri) storageDirPref.set(file.uri.toString()) + Injekt.get().invalidateCache() } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreateJob.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreateJob.kt index c28d12f26..825d66c93 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreateJob.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreateJob.kt @@ -21,7 +21,7 @@ import eu.kanade.tachiyomi.util.system.workManager import logcat.LogPriority import tachiyomi.core.util.system.logcat import tachiyomi.domain.backup.service.BackupPreferences -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.util.Date @@ -43,6 +43,8 @@ class BackupCreateJob(private val context: Context, workerParams: WorkerParamete val uri = inputData.getString(LOCATION_URI_KEY)?.toUri() ?: getAutomaticBackupLocation() + ?: return Result.failure() + val flags = inputData.getInt(BACKUP_FLAGS_KEY, BackupCreateFlags.AutomaticDefaults) try { @@ -75,13 +77,9 @@ class BackupCreateJob(private val context: Context, workerParams: WorkerParamete ) } - private fun getAutomaticBackupLocation(): Uri { - val storagePreferences = Injekt.get() - return storagePreferences.baseStorageDirectory().get().let { - val dir = UniFile.fromUri(context, it.toUri()) - .createDirectory(StoragePreferences.BACKUP_DIR) - dir.uri - } + private fun getAutomaticBackupLocation(): Uri? { + val storageManager = Injekt.get() + return storageManager.getAutomaticBackupsDirectory()?.uri } companion object { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadProvider.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadProvider.kt index 59ed6b2f8..77dbfd264 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadProvider.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadProvider.kt @@ -1,20 +1,15 @@ package eu.kanade.tachiyomi.data.download import android.content.Context -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 import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.manga.model.Manga -import tachiyomi.domain.storage.service.StoragePreferences +import tachiyomi.domain.storage.service.StorageManager import tachiyomi.i18n.MR import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -27,27 +22,11 @@ import uy.kohesive.injekt.api.get */ class DownloadProvider( private val context: Context, - storagePreferences: StoragePreferences = Injekt.get(), + private val storageManager: StorageManager = Injekt.get(), ) { - 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) } - } + get() = storageManager.getDownloadsDirectory() /** * Returns the download directory for a manga. For internal use only. diff --git a/app/src/main/java/eu/kanade/tachiyomi/di/AppModule.kt b/app/src/main/java/eu/kanade/tachiyomi/di/AppModule.kt index 2744644f8..3477cb296 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/di/AppModule.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/di/AppModule.kt @@ -35,6 +35,7 @@ import tachiyomi.data.Mangas import tachiyomi.data.StringListColumnAdapter import tachiyomi.data.UpdateStrategyColumnAdapter import tachiyomi.domain.source.service.SourceManager +import tachiyomi.domain.storage.service.StorageManager import tachiyomi.source.local.image.LocalCoverManager import tachiyomi.source.local.io.LocalSourceFileSystem import uy.kohesive.injekt.api.InjektModule @@ -125,8 +126,9 @@ class AppModule(val app: Application) : InjektModule { addSingletonFactory { ImageSaver(app) } addSingletonFactory { AndroidStorageFolderProvider(app) } - addSingletonFactory { LocalSourceFileSystem(app, get()) } + addSingletonFactory { LocalSourceFileSystem(get()) } addSingletonFactory { LocalCoverManager(app, get()) } + addSingletonFactory { StorageManager(app, get()) } // Asynchronously init expensive components for a faster cold start ContextCompat.getMainExecutor(app).execute { diff --git a/domain/build.gradle.kts b/domain/build.gradle.kts index 2ce1a4d55..4df15c79a 100644 --- a/domain/build.gradle.kts +++ b/domain/build.gradle.kts @@ -19,6 +19,8 @@ dependencies { implementation(platform(kotlinx.coroutines.bom)) implementation(kotlinx.bundles.coroutines) + implementation(libs.unifile) + api(libs.sqldelight.android.paging) testImplementation(libs.bundles.test) diff --git a/domain/src/main/java/tachiyomi/domain/storage/service/StorageManager.kt b/domain/src/main/java/tachiyomi/domain/storage/service/StorageManager.kt new file mode 100644 index 000000000..a1fff4269 --- /dev/null +++ b/domain/src/main/java/tachiyomi/domain/storage/service/StorageManager.kt @@ -0,0 +1,54 @@ +package tachiyomi.domain.storage.service + +import android.content.Context +import androidx.core.net.toUri +import com.hippo.unifile.UniFile +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 + +class StorageManager( + private val context: Context, + storagePreferences: StoragePreferences, +) { + + private val scope = CoroutineScope(Dispatchers.IO) + + private var baseDir: UniFile? = storagePreferences.baseStorageDirectory().get().let(::getBaseDir) + + init { + storagePreferences.baseStorageDirectory().changes() + .onEach { baseDir = getBaseDir(it) } + .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) + } + } + } + + fun getAutomaticBackupsDirectory(): UniFile? { + return baseDir?.createDirectory(AUTOMATIC_BACKUPS_PATH) + } + + fun getDownloadsDirectory(): UniFile? { + return baseDir?.createDirectory(DOWNLOADS_PATH) + } + + fun getLocalSourceDirectory(): UniFile? { + return baseDir?.createDirectory(LOCAL_SOURCE_PATH) + } +} + +private const val AUTOMATIC_BACKUPS_PATH = "autobackup" +private const val DOWNLOADS_PATH = "downloads" +private const val LOCAL_SOURCE_PATH = "local" diff --git a/domain/src/main/java/tachiyomi/domain/storage/service/StoragePreferences.kt b/domain/src/main/java/tachiyomi/domain/storage/service/StoragePreferences.kt index e930ebaa4..8f7c3fcc6 100644 --- a/domain/src/main/java/tachiyomi/domain/storage/service/StoragePreferences.kt +++ b/domain/src/main/java/tachiyomi/domain/storage/service/StoragePreferences.kt @@ -9,9 +9,4 @@ class StoragePreferences( ) { fun baseStorageDirectory() = preferenceStore.getString("storage_dir", folderProvider.path()) - - companion object { - const val BACKUP_DIR = "autobackup" - const val DOWNLOADS_DIR = "downloads" - } } diff --git a/source-local/src/androidMain/kotlin/tachiyomi/source/local/LocalSource.kt b/source-local/src/androidMain/kotlin/tachiyomi/source/local/LocalSource.kt index 1c91597d0..f971caa1d 100644 --- a/source-local/src/androidMain/kotlin/tachiyomi/source/local/LocalSource.kt +++ b/source-local/src/androidMain/kotlin/tachiyomi/source/local/LocalSource.kt @@ -310,8 +310,10 @@ actual class LocalSource( fun getFormat(chapter: SChapter): Format { try { + val (mangaDirName, chapterName) = chapter.url.split(File.separator, limit = 2) return fileSystem.getBaseDirectory() - ?.findFile(chapter.url) + ?.findFile(mangaDirName) + ?.findFile(chapterName) ?.let(Format.Companion::valueOf) ?: throw Exception(context.stringResource(MR.strings.chapter_not_found)) } catch (e: Format.UnknownFormatException) { diff --git a/source-local/src/androidMain/kotlin/tachiyomi/source/local/io/LocalSourceFileSystem.kt b/source-local/src/androidMain/kotlin/tachiyomi/source/local/io/LocalSourceFileSystem.kt index a5ce8a513..8642ac21b 100644 --- a/source-local/src/androidMain/kotlin/tachiyomi/source/local/io/LocalSourceFileSystem.kt +++ b/source-local/src/androidMain/kotlin/tachiyomi/source/local/io/LocalSourceFileSystem.kt @@ -1,18 +1,14 @@ package tachiyomi.source.local.io -import android.content.Context -import androidx.core.net.toUri import com.hippo.unifile.UniFile -import tachiyomi.core.storage.FolderProvider +import tachiyomi.domain.storage.service.StorageManager actual class LocalSourceFileSystem( - private val context: Context, - private val folderProvider: FolderProvider, + private val storageManager: StorageManager, ) { actual fun getBaseDirectory(): UniFile? { - return UniFile.fromUri(context, folderProvider.path().toUri()) - ?.createDirectory("local") + return storageManager.getLocalSourceDirectory() } actual fun getFilesInBaseDirectory(): List {