From 0d666a633f5b338b7b23d51670d7f17b06682c05 Mon Sep 17 00:00:00 2001 From: FooIbar <118464521+FooIbar@users.noreply.github.com> Date: Fri, 21 Jul 2023 16:48:20 +0800 Subject: [PATCH] Add dirname field for DownloadInfo --- app/src/main/java/com/hippo/ehviewer/EhDB.kt | 17 +++-- .../hippo/ehviewer/dao/DownloadDirnameDao.kt | 5 +- .../com/hippo/ehviewer/dao/DownloadInfo.kt | 3 + .../com/hippo/ehviewer/dao/DownloadsDao.kt | 2 +- .../ehviewer/download/DownloadManager.kt | 40 +++++----- .../com/hippo/ehviewer/spider/SpiderDen.kt | 6 +- .../com/hippo/ehviewer/ui/main/GalleryInfo.kt | 2 +- .../hippo/ehviewer/ui/scene/DownloadsScene.kt | 73 ++++++++----------- .../ehviewer/ui/scene/GalleryDetailScene.kt | 12 +-- .../ehviewer/ui/settings/DownloadScreen.kt | 27 ++----- 10 files changed, 81 insertions(+), 106 deletions(-) diff --git a/app/src/main/java/com/hippo/ehviewer/EhDB.kt b/app/src/main/java/com/hippo/ehviewer/EhDB.kt index 90d0c8669..6cd36ccac 100644 --- a/app/src/main/java/com/hippo/ehviewer/EhDB.kt +++ b/app/src/main/java/com/hippo/ehviewer/EhDB.kt @@ -94,6 +94,11 @@ object EhDB { dao.deleteByKey(gid) } + private suspend fun importDownloadDirname(downloadDirnameList: List) { + val dao = db.downloadDirnameDao() + dao.insertOrIgnore(downloadDirnameList) + } + suspend fun getAllDownloadLabelList() = db.downloadLabelDao().list() suspend fun addDownloadLabel(raw: DownloadLabel): DownloadLabel { @@ -248,8 +253,8 @@ object EhDB { } use { newDb -> db.galleryDao().list().let { newDb.galleryDao().insertOrIgnore(it) } db.downloadLabelDao().list().let { newDb.downloadLabelDao().insert(it) } + db.downloadDirnameDao().list().let { newDb.downloadDirnameDao().insertOrIgnore(it) } db.downloadsDao().list().let { newDb.downloadsDao().insert(it) } - db.downloadDirnameDao().list().let { newDb.downloadDirnameDao().insert(it) } db.historyDao().list().let { newDb.historyDao().insertOrIgnore(it) } db.quickSearchDao().list().let { newDb.quickSearchDao().insert(it) } db.localFavoritesDao().list().let { newDb.localFavoritesDao().insertOrIgnore(it) } @@ -281,13 +286,13 @@ object EhDB { DownloadManager.addDownloadLabel(downloadLabelList) } runCatching { - val downloadInfoList = oldDB.downloadsDao().joinList().asReversed() - DownloadManager.addDownload(downloadInfoList, false) + oldDB.downloadDirnameDao().list().let { + importDownloadDirname(it) + } } runCatching { - oldDB.downloadDirnameDao().list().forEach { - putDownloadDirname(it.gid, it.dirname) - } + val downloadInfoList = oldDB.downloadsDao().joinList().asReversed() + DownloadManager.addDownload(downloadInfoList, false) } runCatching { val historyInfoList = oldDB.historyDao().list() diff --git a/app/src/main/java/com/hippo/ehviewer/dao/DownloadDirnameDao.kt b/app/src/main/java/com/hippo/ehviewer/dao/DownloadDirnameDao.kt index aebe5f352..358a27529 100644 --- a/app/src/main/java/com/hippo/ehviewer/dao/DownloadDirnameDao.kt +++ b/app/src/main/java/com/hippo/ehviewer/dao/DownloadDirnameDao.kt @@ -2,6 +2,7 @@ package com.hippo.ehviewer.dao import androidx.room.Dao import androidx.room.Insert +import androidx.room.OnConflictStrategy import androidx.room.Query import androidx.room.Upsert @@ -13,8 +14,8 @@ interface DownloadDirnameDao { @Upsert suspend fun upsert(downloadDirname: DownloadDirname) - @Insert - suspend fun insert(downloadDirnameList: List) + @Insert(onConflict = OnConflictStrategy.IGNORE) + suspend fun insertOrIgnore(downloadDirnameList: List) @Query("DELETE FROM DOWNLOAD_DIRNAME WHERE GID = :gid") suspend fun deleteByKey(gid: Long) diff --git a/app/src/main/java/com/hippo/ehviewer/dao/DownloadInfo.kt b/app/src/main/java/com/hippo/ehviewer/dao/DownloadInfo.kt index 6d7178176..d34c466d8 100644 --- a/app/src/main/java/com/hippo/ehviewer/dao/DownloadInfo.kt +++ b/app/src/main/java/com/hippo/ehviewer/dao/DownloadInfo.kt @@ -65,6 +65,9 @@ data class DownloadInfo( @Relation(parentColumn = "GID", entityColumn = "GID") val galleryInfo: BaseGalleryInfo, + @ColumnInfo(name = "DIRNAME") + val dirname: String?, + @Embedded val downloadInfo: DownloadEntity = DownloadEntity(galleryInfo.gid), ) : GalleryInfo by galleryInfo, AbstractDownloadInfo by downloadInfo { diff --git a/app/src/main/java/com/hippo/ehviewer/dao/DownloadsDao.kt b/app/src/main/java/com/hippo/ehviewer/dao/DownloadsDao.kt index e6dc1cd69..6c5366bed 100644 --- a/app/src/main/java/com/hippo/ehviewer/dao/DownloadsDao.kt +++ b/app/src/main/java/com/hippo/ehviewer/dao/DownloadsDao.kt @@ -14,7 +14,7 @@ interface DownloadsDao { suspend fun list(): List @Transaction - @Query("SELECT * FROM DOWNLOADS ORDER BY POSITION DESC") + @Query("SELECT * FROM DOWNLOADS LEFT JOIN DOWNLOAD_DIRNAME USING(GID) ORDER BY POSITION DESC") suspend fun joinList(): List @Query("UPDATE DOWNLOADS SET POSITION = POSITION - :offset WHERE POSITION > :position") diff --git a/app/src/main/java/com/hippo/ehviewer/download/DownloadManager.kt b/app/src/main/java/com/hippo/ehviewer/download/DownloadManager.kt index 5b0520c17..d178775ef 100644 --- a/app/src/main/java/com/hippo/ehviewer/download/DownloadManager.kt +++ b/app/src/main/java/com/hippo/ehviewer/download/DownloadManager.kt @@ -27,7 +27,7 @@ import com.hippo.ehviewer.dao.DownloadLabel import com.hippo.ehviewer.image.Image import com.hippo.ehviewer.spider.SpiderQueen import com.hippo.ehviewer.spider.SpiderQueen.OnSpiderListener -import com.hippo.ehviewer.spider.getGalleryDownloadDir +import com.hippo.ehviewer.spider.putToDownloadDir import com.hippo.ehviewer.spider.readCompatFromUniFile import com.hippo.ehviewer.spider.write import com.hippo.ehviewer.util.AppConfig @@ -203,7 +203,7 @@ object DownloadManager : OnSpiderListener { } } else { // It is new download info - info = DownloadInfo(galleryInfo) + info = DownloadInfo(galleryInfo, galleryInfo.putToDownloadDir()) info.label = label info.state = DownloadInfo.STATE_WAIT info.position = allInfoList.size @@ -233,10 +233,8 @@ object DownloadManager : OnSpiderListener { // Make sure download is running ensureDownload() - launchIO { - // Add it to history - EhDB.putHistoryInfo(info.galleryInfo) - } + // Add it to history + EhDB.putHistoryInfo(info.galleryInfo) } } @@ -370,24 +368,19 @@ object DownloadManager : OnSpiderListener { } } - suspend fun addDownload(galleryInfo: BaseGalleryInfo, label: String?) { + suspend fun restoreDownload(galleryInfo: BaseGalleryInfo, dirname: String) { if (containDownloadInfo(galleryInfo.gid)) { // Contain return } // It is new download info - val info = DownloadInfo(galleryInfo) - info.label = label + val info = DownloadInfo(galleryInfo, dirname) info.state = DownloadInfo.STATE_NONE info.position = allInfoList.size - // Add to label download list - val list = getInfoListForLabel(info.label) - if (list == null) { - Log.e(TAG, "Can't find download info list with label: $label") - return - } + // Add to default label download list + val list = defaultInfoList list.addFirst(info) // Add to all download list and map @@ -465,7 +458,7 @@ object DownloadManager : OnSpiderListener { } } - suspend fun deleteDownload(gid: Long) { + suspend fun deleteDownload(gid: Long, deleteFiles: Boolean = false) { stopDownloadInternal(gid) val info = mAllInfoMap[gid] if (info != null) { @@ -491,6 +484,11 @@ object DownloadManager : OnSpiderListener { // Ensure download ensureDownload() + + if (deleteFiles) { + info.downloadDir?.delete() + EhDB.removeDownloadDirname(info.gid) + } } } @@ -531,10 +529,10 @@ object DownloadManager : OnSpiderListener { } suspend fun resetAllReadingProgress() = coroutineScope { - mAllInfoMap.keys.forEach { gid -> + allInfoList.forEach { info -> launch { runCatching { - resetReadingProgress(gid) + resetReadingProgress(info) Log.d(TAG, "Current thread: ${Thread.currentThread().name}") }.onFailure { Log.e(TAG, "Can't write SpiderInfo", it) @@ -543,8 +541,8 @@ object DownloadManager : OnSpiderListener { } } - private suspend fun resetReadingProgress(gid: Long) { - val downloadDir = getGalleryDownloadDir(gid) ?: return + private fun resetReadingProgress(info: DownloadInfo) { + val downloadDir = info.downloadDir ?: return val file = downloadDir.findFile(SpiderQueen.SPIDER_INFO_FILENAME) ?: return val spiderInfo = readCompatFromUniFile(file) ?: return spiderInfo.startPage = 0 @@ -1184,3 +1182,5 @@ var downloadLocation: UniFile downloadFragment = encodedFragment } } + +val DownloadInfo.downloadDir get() = dirname?.let { downloadLocation.subFile(it) } diff --git a/app/src/main/java/com/hippo/ehviewer/spider/SpiderDen.kt b/app/src/main/java/com/hippo/ehviewer/spider/SpiderDen.kt index 87a0a7ea0..dfc0424dd 100644 --- a/app/src/main/java/com/hippo/ehviewer/spider/SpiderDen.kt +++ b/app/src/main/java/com/hippo/ehviewer/spider/SpiderDen.kt @@ -44,7 +44,7 @@ import java.util.Locale import kotlin.io.path.readText import com.hippo.ehviewer.EhApplication.Companion.imageCache as sCache -class SpiderDen(private val mGalleryInfo: GalleryInfo) { +class SpiderDen(mGalleryInfo: GalleryInfo) { private val mGid = mGalleryInfo.gid var downloadDir: UniFile? = null @@ -56,7 +56,6 @@ class SpiderDen(private val mGalleryInfo: GalleryInfo) { suspend fun setMode(value: Int) { mode = value if (mode == SpiderQueen.MODE_DOWNLOAD && downloadDir == null) { - mGalleryInfo.putToDownloadDir() downloadDir = getGalleryDownloadDir(mGid)!!.apply { check(ensureDir()) { "Download directory $uri is not valid directory!" } } } } @@ -283,10 +282,11 @@ private fun findImageFile(dir: UniFile, index: Int): UniFile? { return COMPAT_IMAGE_EXTENSIONS.firstNotNullOfOrNull { dir.findFile(perFilename(index, it)) } } -suspend fun GalleryInfo.putToDownloadDir() { +suspend fun GalleryInfo.putToDownloadDir(): String { val title = getSuitableTitle(this) val dirname = FileUtils.sanitizeFilename("$gid-$title") EhDB.putDownloadDirname(gid, dirname) + return dirname } suspend fun getGalleryDownloadDir(gid: Long): UniFile? { diff --git a/app/src/main/java/com/hippo/ehviewer/ui/main/GalleryInfo.kt b/app/src/main/java/com/hippo/ehviewer/ui/main/GalleryInfo.kt index 7c846d29a..56cea8723 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/main/GalleryInfo.kt +++ b/app/src/main/java/com/hippo/ehviewer/ui/main/GalleryInfo.kt @@ -216,4 +216,4 @@ fun GalleryInfoGridItem( private const val MIN_ASPECT = 0.33F private const val MAX_ASPECT = 1.5F -private const val DEFAULT_ASPECT = 0.67F +const val DEFAULT_ASPECT = 0.67F diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/DownloadsScene.kt b/app/src/main/java/com/hippo/ehviewer/ui/scene/DownloadsScene.kt index 12d81c1f4..12870b5be 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/DownloadsScene.kt +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/DownloadsScene.kt @@ -75,9 +75,8 @@ import com.hippo.ehviewer.download.DownloadManager import com.hippo.ehviewer.download.DownloadManager.DownloadInfoListener import com.hippo.ehviewer.download.DownloadService import com.hippo.ehviewer.download.DownloadService.Companion.clear +import com.hippo.ehviewer.download.downloadDir import com.hippo.ehviewer.ktbuilder.imageRequest -import com.hippo.ehviewer.spider.getGalleryDownloadDir -import com.hippo.ehviewer.spider.putToDownloadDir import com.hippo.ehviewer.ui.legacy.AutoStaggeredGridLayoutManager import com.hippo.ehviewer.ui.legacy.BaseDialogBuilder import com.hippo.ehviewer.ui.legacy.CheckBoxDialogBuilder @@ -88,6 +87,7 @@ import com.hippo.ehviewer.ui.legacy.FastScroller.OnDragHandlerListener import com.hippo.ehviewer.ui.legacy.HandlerDrawable import com.hippo.ehviewer.ui.legacy.STRATEGY_MIN_SIZE import com.hippo.ehviewer.ui.legacy.ViewTransition +import com.hippo.ehviewer.ui.main.DEFAULT_ASPECT import com.hippo.ehviewer.ui.main.requestOf import com.hippo.ehviewer.ui.navToReader import com.hippo.ehviewer.ui.setMD3Content @@ -767,15 +767,12 @@ class DownloadsScene : val checked = mBuilder.isChecked Settings.removeImageFiles = checked if (checked) { - val files = arrayOfNulls(mDownloadInfoList.size) - for ((i, info) in mDownloadInfoList.withIndex()) { - // Put file - files[i] = getGalleryDownloadDir(info.gid) + mDownloadInfoList.forEach { info -> + // Delete file + info.downloadDir?.delete() // Remove download path EhDB.removeDownloadDirname(info.gid) } - // Delete file - files.forEach { it?.delete() } } } } @@ -867,23 +864,13 @@ class DownloadsScene : fun bind(info: DownloadInfo, isChecked: Boolean) { binding.root.isChecked = isChecked - lifecycleScope.launchIO { - val downloadDir = getGalleryDownloadDir(info.gid) ?: run { - info.putToDownloadDir() - getGalleryDownloadDir(info.gid)!! - } - downloadDir.ensureDir() - val thumbLocation = downloadDir.subFile(".thumb")!! - withUIContext { - binding.thumb.setMD3Content { - Card(onClick = ::onClick.partially1(binding.thumb)) { - CompanionAsyncThumb( - info = info, - path = thumbLocation, - modifier = Modifier.height(height).aspectRatio(0.6666667F), - ) - } - } + binding.thumb.setMD3Content { + Card(onClick = ::onClick.partially1(binding.thumb)) { + CompanionAsyncThumb( + info = info, + path = info.downloadDir?.subFile(".thumb"), + modifier = Modifier.height(height).aspectRatio(DEFAULT_ASPECT), + ) } } binding.title.text = EhUtils.getSuitableTitle(info) @@ -1172,14 +1159,14 @@ class DownloadsScene : @Composable private fun CompanionAsyncThumb( info: GalleryInfo, - path: UniFile, + path: UniFile?, modifier: Modifier = Modifier, ) { var contentScale by remember(info.gid) { mutableStateOf(ContentScale.Fit) } val coroutineScope = rememberCoroutineScope { Dispatchers.IO } val context = LocalContext.current var localReq by remember(info.gid) { - path.takeIf { it.isFile }?.uri?.let { + path?.takeIf { it.isFile }?.uri?.let { context.imageRequest { data(it.toString()) memoryCacheKey(info.thumbKey) @@ -1197,28 +1184,32 @@ private fun CompanionAsyncThumb( contentScale = ContentScale.Crop } } - coroutineScope.launch { - runCatching { - if (!path.exists() && path.ensureFile()) { - val key = info.thumbKey!! - imageCache.read(key) { - UniFile.fromFile(data.toFile())!!.openFileDescriptor("r").use { src -> - path.openFileDescriptor("w").use { dst -> - src sendTo dst + path?.let { + coroutineScope.launch { + runCatching { + if (!path.exists() && path.ensureFile()) { + val key = info.thumbKey!! + imageCache.read(key) { + UniFile.fromFile(data.toFile())!!.openFileDescriptor("r").use { src -> + path.openFileDescriptor("w").use { dst -> + src sendTo dst + } } } } + }.onFailure { + it.printStackTrace() } - }.onFailure { - it.printStackTrace() } } } if (state is AsyncImagePainter.State.Error) { - coroutineScope.launch { - if (path.exists()) { - path.delete() - localReq = null + path?.let { + coroutineScope.launch { + if (path.exists()) { + path.delete() + localReq = null + } } } } diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.kt b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.kt index b710d6967..482ec1494 100755 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.kt +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.kt @@ -133,7 +133,6 @@ import com.hippo.ehviewer.databinding.ItemGalleryCommentBinding import com.hippo.ehviewer.ktbuilder.imageRequest import com.hippo.ehviewer.spider.SpiderQueen import com.hippo.ehviewer.spider.SpiderQueen.Companion.MODE_READ -import com.hippo.ehviewer.spider.getGalleryDownloadDir import com.hippo.ehviewer.ui.CommonOperations import com.hippo.ehviewer.ui.GalleryInfoBottomSheet import com.hippo.ehviewer.ui.MainActivity @@ -1266,18 +1265,9 @@ class GalleryDetailScene : BaseScene() { } lifecycleScope.launchIO { - // Delete - EhDownloadManager.deleteDownload(mGalleryInfo.gid) - // Delete image files val checked = mBuilder.isChecked Settings.removeImageFiles = checked - if (checked) { - runCatching { - val file = getGalleryDownloadDir(mGalleryInfo.gid) - EhDB.removeDownloadDirname(mGalleryInfo.gid) - file?.delete() - } - } + EhDownloadManager.deleteDownload(mGalleryInfo.gid, checked) } } } diff --git a/app/src/main/java/com/hippo/ehviewer/ui/settings/DownloadScreen.kt b/app/src/main/java/com/hippo/ehviewer/ui/settings/DownloadScreen.kt index 6d0654c6c..679a36b47 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/settings/DownloadScreen.kt +++ b/app/src/main/java/com/hippo/ehviewer/ui/settings/DownloadScreen.kt @@ -158,23 +158,12 @@ fun DownloadScreen() { title = stringResource(id = R.string.settings_download_restore_download_items), summary = stringResource(id = R.string.settings_download_restore_download_items_summary), ) { - var restoreDirCount = 0 - suspend fun getRestoreItem(file: UniFile): RestoreItem? { + fun getRestoreItem(file: UniFile): RestoreItem? { if (!file.isDirectory) return null val siFile = file.findFile(SpiderQueen.SPIDER_INFO_FILENAME) ?: return null return runCatching { val spiderInfo = readCompatFromUniFile(siFile) ?: return null - val gid = spiderInfo.gid val dirname = file.name ?: return null - if (DownloadManager.containDownloadInfo(gid)) { - // Restore download dir to avoid redownload - val dbdirname = EhDB.getDownloadDirname(gid) - if (null == dbdirname || dirname != dbdirname) { - EhDB.putDownloadDirname(gid, dirname) - restoreDirCount++ - } - return null - } RestoreItem(dirname).also { it.gid = spiderInfo.gid it.token = spiderInfo.token @@ -194,15 +183,11 @@ fun DownloadScreen() { if (result == null) { launchSnackBar(restoreFailed) } else { - if (result.isEmpty()) { - launchSnackBar(RESTORE_COUNT_MSG(restoreDirCount)) - } else { - val count = result.filterNot { it.title.isNullOrBlank() }.map { - DownloadManager.addDownload(it, null) - EhDB.putDownloadDirname(it.gid, it.dirname) - }.size - launchSnackBar(RESTORE_COUNT_MSG(count + restoreDirCount)) - } + val count = result.filterNot { it.title.isNullOrBlank() }.map { + EhDB.putDownloadDirname(it.gid, it.dirname) + DownloadManager.restoreDownload(it, it.dirname) + }.size + launchSnackBar(RESTORE_COUNT_MSG(count)) } }.onFailure { it.printStackTrace()