|
@@ -4,7 +4,6 @@ import android.app.Application
|
|
|
import android.graphics.Bitmap
|
|
import android.graphics.Bitmap
|
|
|
import android.graphics.drawable.Drawable
|
|
import android.graphics.drawable.Drawable
|
|
|
import android.net.Uri
|
|
import android.net.Uri
|
|
|
-import android.os.Build
|
|
|
|
|
import androidx.documentfile.provider.DocumentFile
|
|
import androidx.documentfile.provider.DocumentFile
|
|
|
import androidx.lifecycle.MutableLiveData
|
|
import androidx.lifecycle.MutableLiveData
|
|
|
import com.bumptech.glide.Glide
|
|
import com.bumptech.glide.Glide
|
|
@@ -15,7 +14,6 @@ import io.legado.app.R
|
|
|
import io.legado.app.base.BaseViewModel
|
|
import io.legado.app.base.BaseViewModel
|
|
|
import io.legado.app.constant.AppConst
|
|
import io.legado.app.constant.AppConst
|
|
|
import io.legado.app.constant.AppPattern
|
|
import io.legado.app.constant.AppPattern
|
|
|
-import io.legado.app.constant.BookType
|
|
|
|
|
import io.legado.app.data.appDb
|
|
import io.legado.app.data.appDb
|
|
|
import io.legado.app.data.entities.Book
|
|
import io.legado.app.data.entities.Book
|
|
|
import io.legado.app.data.entities.BookChapter
|
|
import io.legado.app.data.entities.BookChapter
|
|
@@ -24,6 +22,7 @@ import io.legado.app.help.AppWebDav
|
|
|
import io.legado.app.help.book.BookHelp
|
|
import io.legado.app.help.book.BookHelp
|
|
|
import io.legado.app.help.book.ContentProcessor
|
|
import io.legado.app.help.book.ContentProcessor
|
|
|
import io.legado.app.help.config.AppConfig
|
|
import io.legado.app.help.config.AppConfig
|
|
|
|
|
+import io.legado.app.help.coroutine.Coroutine
|
|
|
import io.legado.app.help.coroutine.OrderCoroutine
|
|
import io.legado.app.help.coroutine.OrderCoroutine
|
|
|
import io.legado.app.utils.*
|
|
import io.legado.app.utils.*
|
|
|
import kotlinx.coroutines.*
|
|
import kotlinx.coroutines.*
|
|
@@ -37,75 +36,40 @@ import splitties.init.appCtx
|
|
|
import java.io.ByteArrayOutputStream
|
|
import java.io.ByteArrayOutputStream
|
|
|
import java.io.File
|
|
import java.io.File
|
|
|
import java.io.FileOutputStream
|
|
import java.io.FileOutputStream
|
|
|
-import java.io.IOException
|
|
|
|
|
import java.nio.charset.Charset
|
|
import java.nio.charset.Charset
|
|
|
import java.nio.file.*
|
|
import java.nio.file.*
|
|
|
-import java.nio.file.attribute.BasicFileAttributes
|
|
|
|
|
import java.util.*
|
|
import java.util.*
|
|
|
import java.util.concurrent.ConcurrentHashMap
|
|
import java.util.concurrent.ConcurrentHashMap
|
|
|
import kotlin.coroutines.coroutineContext
|
|
import kotlin.coroutines.coroutineContext
|
|
|
-import kotlin.io.path.name
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CacheViewModel(application: Application) : BaseViewModel(application) {
|
|
class CacheViewModel(application: Application) : BaseViewModel(application) {
|
|
|
val upAdapterLiveData = MutableLiveData<String>()
|
|
val upAdapterLiveData = MutableLiveData<String>()
|
|
|
- val cacheLiveData = MutableLiveData<String>()
|
|
|
|
|
val exportProgress = ConcurrentHashMap<String, Int>()
|
|
val exportProgress = ConcurrentHashMap<String, Int>()
|
|
|
val exportMsg = ConcurrentHashMap<String, String>()
|
|
val exportMsg = ConcurrentHashMap<String, String>()
|
|
|
private val mutex = Mutex()
|
|
private val mutex = Mutex()
|
|
|
val cacheChapters = hashMapOf<String, HashSet<String>>()
|
|
val cacheChapters = hashMapOf<String, HashSet<String>>()
|
|
|
|
|
+ var loadChapterCoroutine: Coroutine<Unit>? = null
|
|
|
|
|
|
|
|
@Volatile
|
|
@Volatile
|
|
|
private var exportNumber = 0
|
|
private var exportNumber = 0
|
|
|
|
|
|
|
|
- init {
|
|
|
|
|
- loadCacheFiles()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private fun loadCacheFiles() {
|
|
|
|
|
- execute {
|
|
|
|
|
- //直接获取全部缓存信息,避免切换分组重新获取
|
|
|
|
|
- val books = appDb.bookDao.getByTypeOnLine(BookType.text or BookType.image)
|
|
|
|
|
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
|
|
|
- val visitor = object : SimpleFileVisitor<Path>() {
|
|
|
|
|
-
|
|
|
|
|
- var names: HashSet<String>? = null
|
|
|
|
|
-
|
|
|
|
|
- override fun preVisitDirectory(
|
|
|
|
|
- dir: Path,
|
|
|
|
|
- attrs: BasicFileAttributes?
|
|
|
|
|
- ): FileVisitResult {
|
|
|
|
|
- if (dir.name != "book_cache") {
|
|
|
|
|
- names = hashSetOf()
|
|
|
|
|
- }
|
|
|
|
|
- return FileVisitResult.CONTINUE
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- override fun visitFile(
|
|
|
|
|
- file: Path,
|
|
|
|
|
- attrs: BasicFileAttributes?
|
|
|
|
|
- ): FileVisitResult {
|
|
|
|
|
- names!!.add(file.name)
|
|
|
|
|
- return FileVisitResult.CONTINUE
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- override fun postVisitDirectory(dir: Path, exc: IOException?): FileVisitResult {
|
|
|
|
|
- if (dir.name != "book_cache") {
|
|
|
|
|
- cacheChapters[dir.name] = names!!
|
|
|
|
|
- cacheLiveData.postValue(dir.name)
|
|
|
|
|
|
|
+ fun loadCacheFiles(books: List<Book>) {
|
|
|
|
|
+ loadChapterCoroutine?.cancel()
|
|
|
|
|
+ loadChapterCoroutine = execute {
|
|
|
|
|
+ books.forEach { book ->
|
|
|
|
|
+ val chapterCaches = hashSetOf<String>()
|
|
|
|
|
+ val cacheNames = BookHelp.getChapterFiles(book)
|
|
|
|
|
+ if (cacheNames.isNotEmpty()) {
|
|
|
|
|
+ appDb.bookChapterDao.getChapterList(book.bookUrl).forEach { chapter ->
|
|
|
|
|
+ if (cacheNames.contains(chapter.getFileName())) {
|
|
|
|
|
+ chapterCaches.add(chapter.url)
|
|
|
}
|
|
}
|
|
|
- return FileVisitResult.CONTINUE
|
|
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- withContext(Dispatchers.IO) {
|
|
|
|
|
- Files.walkFileTree(Paths.get(BookHelp.cachePath), emptySet(), 2, visitor)
|
|
|
|
|
- }
|
|
|
|
|
- return@execute
|
|
|
|
|
- }
|
|
|
|
|
- books.forEach { book ->
|
|
|
|
|
- val cacheNames = BookHelp.getChapterFiles(book)
|
|
|
|
|
- cacheChapters[book.getFolderName()] = cacheNames
|
|
|
|
|
- cacheLiveData.postValue(book.getFolderName())
|
|
|
|
|
|
|
+ cacheChapters[book.bookUrl] = chapterCaches
|
|
|
|
|
+ upAdapterLiveData.postValue(book.bookUrl)
|
|
|
|
|
+ ensureActive()
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|