|
|
|
@ -22,9 +22,9 @@ import io.legado.app.help.AppWebDav |
|
|
|
|
import io.legado.app.help.BookHelp |
|
|
|
|
import io.legado.app.help.ContentProcessor |
|
|
|
|
import io.legado.app.help.config.AppConfig |
|
|
|
|
import io.legado.app.help.coroutine.OrderCoroutine |
|
|
|
|
import io.legado.app.utils.* |
|
|
|
|
import kotlinx.coroutines.delay |
|
|
|
|
import kotlinx.coroutines.ensureActive |
|
|
|
|
import kotlinx.coroutines.* |
|
|
|
|
import kotlinx.coroutines.sync.Mutex |
|
|
|
|
import kotlinx.coroutines.sync.withLock |
|
|
|
|
import me.ag2s.epublib.domain.* |
|
|
|
@ -104,10 +104,13 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { |
|
|
|
|
val bookDoc = DocumentUtils.createFileIfNotExist(doc, filename) |
|
|
|
|
?: throw NoStackTraceException("创建文档失败,请尝试重新设置导出文件夹") |
|
|
|
|
val stringBuilder = StringBuilder() |
|
|
|
|
val exportToWebDav = AppConfig.exportToWebDav |
|
|
|
|
context.contentResolver.openOutputStream(bookDoc.uri, "wa")?.use { bookOs -> |
|
|
|
|
getAllContents(book) { text, srcList -> |
|
|
|
|
bookOs.write(text.toByteArray(Charset.forName(AppConfig.exportCharset))) |
|
|
|
|
stringBuilder.append(text) |
|
|
|
|
if (exportToWebDav) { |
|
|
|
|
stringBuilder.append(text) |
|
|
|
|
} |
|
|
|
|
srcList?.forEach { |
|
|
|
|
val vFile = BookHelp.getImage(book, it.third) |
|
|
|
|
if (vFile.exists()) { |
|
|
|
@ -133,9 +136,12 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { |
|
|
|
|
val bookPath = FileUtils.getPath(file, filename) |
|
|
|
|
val bookFile = FileUtils.createFileWithReplace(bookPath) |
|
|
|
|
val stringBuilder = StringBuilder() |
|
|
|
|
val exportToWebDav = AppConfig.exportToWebDav |
|
|
|
|
getAllContents(book) { text, srcList -> |
|
|
|
|
bookFile.appendText(text, Charset.forName(AppConfig.exportCharset)) |
|
|
|
|
stringBuilder.append(text) |
|
|
|
|
if (exportToWebDav) { |
|
|
|
|
stringBuilder.append(text) |
|
|
|
|
} |
|
|
|
|
srcList?.forEach { |
|
|
|
|
val vFile = BookHelp.getImage(book, it.third) |
|
|
|
|
if (vFile.exists()) { |
|
|
|
@ -171,37 +177,61 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { |
|
|
|
|
) |
|
|
|
|
}" |
|
|
|
|
append(qy, null) |
|
|
|
|
appDb.bookChapterDao.getChapterList(book.bookUrl).forEachIndexed { index, chapter -> |
|
|
|
|
coroutineContext.ensureActive() |
|
|
|
|
upAdapterLiveData.postValue(book.bookUrl) |
|
|
|
|
exportProgress[book.bookUrl] = index |
|
|
|
|
BookHelp.getContent(book, chapter).let { content -> |
|
|
|
|
val content1 = contentProcessor |
|
|
|
|
.getContent( |
|
|
|
|
book, |
|
|
|
|
chapter, |
|
|
|
|
content ?: "null", |
|
|
|
|
includeTitle = !AppConfig.exportNoChapterName, |
|
|
|
|
useReplace = useReplace, |
|
|
|
|
chineseConvert = false, |
|
|
|
|
reSegment = false |
|
|
|
|
).joinToString("\n") |
|
|
|
|
if (AppConfig.exportPictureFile) { |
|
|
|
|
//txt导出图片文件 |
|
|
|
|
val srcList = arrayListOf<Triple<String, Int, String>>() |
|
|
|
|
content?.split("\n")?.forEachIndexed { index, text -> |
|
|
|
|
val matcher = AppPattern.imgPattern.matcher(text) |
|
|
|
|
while (matcher.find()) { |
|
|
|
|
matcher.group(1)?.let { |
|
|
|
|
val src = NetworkUtils.getAbsoluteURL(chapter.url, it) |
|
|
|
|
srcList.add(Triple(chapter.title, index, src)) |
|
|
|
|
} |
|
|
|
|
if (AppConfig.parallelExportBook) { |
|
|
|
|
val oc = |
|
|
|
|
OrderCoroutine<Pair<String, ArrayList<Triple<String, Int, String>>?>>(AppConfig.threadCount) |
|
|
|
|
appDb.bookChapterDao.getChapterList(book.bookUrl).forEach { chapter -> |
|
|
|
|
oc.submit { getExportData(book, chapter, contentProcessor, useReplace) } |
|
|
|
|
} |
|
|
|
|
oc.collect { index, result -> |
|
|
|
|
upAdapterLiveData.postValue(book.bookUrl) |
|
|
|
|
exportProgress[book.bookUrl] = index |
|
|
|
|
append.invoke(result.first, result.second) |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
appDb.bookChapterDao.getChapterList(book.bookUrl).forEachIndexed { index, chapter -> |
|
|
|
|
coroutineContext.ensureActive() |
|
|
|
|
upAdapterLiveData.postValue(book.bookUrl) |
|
|
|
|
exportProgress[book.bookUrl] = index |
|
|
|
|
val result = getExportData(book, chapter, contentProcessor, useReplace) |
|
|
|
|
append.invoke(result.first, result.second) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private suspend fun getExportData( |
|
|
|
|
book: Book, |
|
|
|
|
chapter: BookChapter, |
|
|
|
|
contentProcessor: ContentProcessor, |
|
|
|
|
useReplace: Boolean |
|
|
|
|
): Pair<String, ArrayList<Triple<String, Int, String>>?> { |
|
|
|
|
BookHelp.getContent(book, chapter).let { content -> |
|
|
|
|
val content1 = contentProcessor |
|
|
|
|
.getContent( |
|
|
|
|
book, |
|
|
|
|
chapter, |
|
|
|
|
content ?: "null", |
|
|
|
|
includeTitle = !AppConfig.exportNoChapterName, |
|
|
|
|
useReplace = useReplace, |
|
|
|
|
chineseConvert = false, |
|
|
|
|
reSegment = false |
|
|
|
|
).joinToString("\n") |
|
|
|
|
if (AppConfig.exportPictureFile) { |
|
|
|
|
//txt导出图片文件 |
|
|
|
|
val srcList = arrayListOf<Triple<String, Int, String>>() |
|
|
|
|
content?.split("\n")?.forEachIndexed { index, text -> |
|
|
|
|
val matcher = AppPattern.imgPattern.matcher(text) |
|
|
|
|
while (matcher.find()) { |
|
|
|
|
matcher.group(1)?.let { |
|
|
|
|
val src = NetworkUtils.getAbsoluteURL(chapter.url, it) |
|
|
|
|
srcList.add(Triple(chapter.title, index, src)) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
append.invoke("\n\n$content1", srcList) |
|
|
|
|
} else { |
|
|
|
|
append.invoke("\n\n$content1", null) |
|
|
|
|
} |
|
|
|
|
return Pair("\n\n$content1", srcList) |
|
|
|
|
} else { |
|
|
|
|
return Pair("\n\n$content1", null) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -422,7 +452,10 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { |
|
|
|
|
.asBitmap() |
|
|
|
|
.load(book.getDisplayCover()) |
|
|
|
|
.into(object : CustomTarget<Bitmap>() { |
|
|
|
|
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) { |
|
|
|
|
override fun onResourceReady( |
|
|
|
|
resource: Bitmap, |
|
|
|
|
transition: Transition<in Bitmap>? |
|
|
|
|
) { |
|
|
|
|
val stream = ByteArrayOutputStream() |
|
|
|
|
resource.compress(Bitmap.CompressFormat.JPEG, 100, stream) |
|
|
|
|
val byteArray: ByteArray = stream.toByteArray() |
|
|
|
@ -491,8 +524,10 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { |
|
|
|
|
while (matcher.find()) { |
|
|
|
|
matcher.group(1)?.let { |
|
|
|
|
val src = NetworkUtils.getAbsoluteURL(chapter.url, it) |
|
|
|
|
val originalHref = "${MD5Utils.md5Encode16(src)}.${BookHelp.getImageSuffix(src)}" |
|
|
|
|
val href = "Images/${MD5Utils.md5Encode16(src)}.${BookHelp.getImageSuffix(src)}" |
|
|
|
|
val originalHref = |
|
|
|
|
"${MD5Utils.md5Encode16(src)}.${BookHelp.getImageSuffix(src)}" |
|
|
|
|
val href = |
|
|
|
|
"Images/${MD5Utils.md5Encode16(src)}.${BookHelp.getImageSuffix(src)}" |
|
|
|
|
val vFile = BookHelp.getImage(book, src) |
|
|
|
|
val fp = FileResourceProvider(vFile.parent) |
|
|
|
|
if (vFile.exists()) { |
|
|
|
|