Add dirname field for DownloadInfo

This commit is contained in:
FooIbar authored and tarsin committed 2023-07-21 20:36:19 +08:00
1 parent b24679adbd
commit 0d666a633f
10 files changed
+81 -106

No files matched your search

+11 -6
View File
@@ -94,6 +94,11 @@ object EhDB {
dao.deleteByKey(gid)
}
private suspend fun importDownloadDirname(downloadDirnameList: List<DownloadDirname>) {
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()
@@ -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<DownloadDirname>)
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insertOrIgnore(downloadDirnameList: List<DownloadDirname>)
@Query("DELETE FROM DOWNLOAD_DIRNAME WHERE GID = :gid")
suspend fun deleteByKey(gid: Long)
@@ -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 {
@@ -14,7 +14,7 @@ interface DownloadsDao {
suspend fun list(): List<DownloadEntity>
@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<DownloadInfo>
@Query("UPDATE DOWNLOADS SET POSITION = POSITION - :offset WHERE POSITION > :position")
@@ -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) }
@@ -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? {
@@ -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
@@ -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<UniFile>(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
}
}
}
}
@@ -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)
}
}
}
@@ -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()