fix(CustomExport): 修复自定义导出进度条错误的问题
This commit is contained in:
+59
-70
@@ -35,7 +35,6 @@ import kotlinx.coroutines.Job
|
|||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import androidx.core.widget.doOnTextChanged
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cache/download 缓存界面
|
* cache/download 缓存界面
|
||||||
@@ -136,6 +135,7 @@ class CacheActivity : VMBaseActivity<ActivityCacheBookBinding, CacheViewModel>()
|
|||||||
CacheBook.stop(this@CacheActivity)
|
CacheBook.stop(this@CacheActivity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.menu_export_all -> exportAll()
|
R.id.menu_export_all -> exportAll()
|
||||||
R.id.menu_enable_replace -> AppConfig.exportUseReplace = !item.isChecked
|
R.id.menu_enable_replace -> AppConfig.exportUseReplace = !item.isChecked
|
||||||
// 更改菜单状态[enableCustomExport]
|
// 更改菜单状态[enableCustomExport]
|
||||||
@@ -147,6 +147,7 @@ class CacheActivity : VMBaseActivity<ActivityCacheBookBinding, CacheViewModel>()
|
|||||||
R.id.menu_export_folder -> {
|
R.id.menu_export_folder -> {
|
||||||
selectExportFolder(-1)
|
selectExportFolder(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.menu_export_file_name -> alertExportFileName()
|
R.id.menu_export_file_name -> alertExportFileName()
|
||||||
R.id.menu_export_type -> showExportTypeConfig()
|
R.id.menu_export_type -> showExportTypeConfig()
|
||||||
R.id.menu_export_charset -> showCharsetConfig()
|
R.id.menu_export_charset -> showCharsetConfig()
|
||||||
@@ -184,6 +185,7 @@ class CacheActivity : VMBaseActivity<ActivityCacheBookBinding, CacheViewModel>()
|
|||||||
2 -> booksDownload.sortedWith { o1, o2 ->
|
2 -> booksDownload.sortedWith { o1, o2 ->
|
||||||
o1.name.cnCompare(o2.name)
|
o1.name.cnCompare(o2.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
3 -> booksDownload.sortedBy { it.order }
|
3 -> booksDownload.sortedBy { it.order }
|
||||||
else -> booksDownload.sortedByDescending { it.durChapterTime }
|
else -> booksDownload.sortedByDescending { it.durChapterTime }
|
||||||
}
|
}
|
||||||
@@ -247,8 +249,8 @@ class CacheActivity : VMBaseActivity<ActivityCacheBookBinding, CacheViewModel>()
|
|||||||
val path = ACache.get().getAsString(exportBookPathKey)
|
val path = ACache.get().getAsString(exportBookPathKey)
|
||||||
if (path.isNullOrEmpty()) {
|
if (path.isNullOrEmpty()) {
|
||||||
selectExportFolder(position)
|
selectExportFolder(position)
|
||||||
} else if (AppConfig.enableCustomExport) {// 启用自定义导出
|
} else if (AppConfig.enableCustomExport && AppConfig.exportType == 1) {// 启用自定义导出 and 导出类型为Epub
|
||||||
configExportSection(path, position);
|
configExportSection(path, position)
|
||||||
} else {
|
} else {
|
||||||
startExport(path, position)
|
startExport(path, position)
|
||||||
}
|
}
|
||||||
@@ -272,76 +274,63 @@ class CacheActivity : VMBaseActivity<ActivityCacheBookBinding, CacheViewModel>()
|
|||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
private fun configExportSection(path: String, position: Int) {
|
private fun configExportSection(path: String, position: Int) {
|
||||||
if (AppConfig.enableCustomExport) {
|
val alertBinding = DialogSelectSectionExportBinding.inflate(layoutInflater)
|
||||||
val alertBinding = DialogSelectSectionExportBinding.inflate(layoutInflater)
|
.apply {
|
||||||
.apply {
|
cbAllExport.isChecked = true
|
||||||
|
cbSelectExport.isChecked = false
|
||||||
|
etEpubSize.isEnabled = false
|
||||||
|
etInputScope.isEnabled = false
|
||||||
|
tvAllExport.setOnClickListener {
|
||||||
cbAllExport.isChecked = true
|
cbAllExport.isChecked = true
|
||||||
cbSelectExport.isChecked = false
|
|
||||||
etEpubSize.isEnabled = false
|
|
||||||
etInputScope.isEnabled = false
|
|
||||||
tvAllExport.setOnClickListener {
|
|
||||||
cbAllExport.isChecked = true
|
|
||||||
}
|
|
||||||
tvSelectExport.setOnClickListener {
|
|
||||||
cbSelectExport.isChecked = true
|
|
||||||
}
|
|
||||||
cbSelectExport.onCheckedChangeListener = { _, isChecked ->
|
|
||||||
if (isChecked) {
|
|
||||||
etEpubSize.isEnabled = true
|
|
||||||
etInputScope.isEnabled = true
|
|
||||||
cbAllExport.isChecked = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cbAllExport.onCheckedChangeListener = { _, isChecked ->
|
|
||||||
if (isChecked) {
|
|
||||||
etEpubSize.isEnabled = false
|
|
||||||
etInputScope.isEnabled = false
|
|
||||||
cbSelectExport.isChecked = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
etInputScope.onFocusChangeListener =
|
|
||||||
View.OnFocusChangeListener { v, hasFocus ->
|
|
||||||
if (hasFocus) {
|
|
||||||
etInputScope.hint = "例如:1-5,8,10-18"
|
|
||||||
} else {
|
|
||||||
etInputScope.hint = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
etInputScope.doOnTextChanged { text, start, before, count ->
|
|
||||||
var a: Int = 1
|
|
||||||
a = 2
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
val alertDialog = alert(titleResource = R.string.select_section_export) {
|
tvSelectExport.setOnClickListener {
|
||||||
customView { alertBinding.root }
|
cbSelectExport.isChecked = true
|
||||||
positiveButton("确认")
|
}
|
||||||
//okButton {
|
cbSelectExport.onCheckedChangeListener = { _, isChecked ->
|
||||||
// alertBinding.apply {
|
if (isChecked) {
|
||||||
// it.dismiss()
|
etEpubSize.isEnabled = true
|
||||||
// if (cbAllExport.isChecked) {
|
etInputScope.isEnabled = true
|
||||||
// // export all sections of the book.
|
cbAllExport.isChecked = false
|
||||||
// startExport(path, position)
|
}
|
||||||
// } else if (cbSelectExport.isChecked) {
|
}
|
||||||
//
|
cbAllExport.onCheckedChangeListener = { _, isChecked ->
|
||||||
// }
|
if (isChecked) {
|
||||||
// }
|
etEpubSize.isEnabled = false
|
||||||
//}
|
etInputScope.isEnabled = false
|
||||||
cancelButton()
|
cbSelectExport.isChecked = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
etInputScope.onFocusChangeListener =
|
||||||
|
View.OnFocusChangeListener { _, hasFocus ->
|
||||||
|
if (hasFocus) {
|
||||||
|
etInputScope.hint = "例如:1-5,8,10-18"
|
||||||
|
} else {
|
||||||
|
etInputScope.hint = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
|
val alertDialog = alert(titleResource = R.string.select_section_export) {
|
||||||
alertBinding.apply {
|
customView { alertBinding.root }
|
||||||
val text = etInputScope.text
|
positiveButton("确认")
|
||||||
if (!verificationField(text.toString())) {
|
cancelButton()
|
||||||
etInputScope.error = "请输入正确的范围"
|
}
|
||||||
} else {
|
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
|
||||||
etInputScope.error = null
|
alertBinding.apply {
|
||||||
val toInt = etEpubSize.text.toString().toInt()
|
if (cbAllExport.isChecked) {
|
||||||
startExport(path, position, toInt, text.toString())
|
startExport(path, position)
|
||||||
alertDialog.hide();
|
alertDialog.hide()
|
||||||
}
|
return@apply
|
||||||
}
|
}
|
||||||
|
val text = etInputScope.text
|
||||||
|
if (!verificationField(text.toString())) {
|
||||||
|
etInputScope.error = "请输入正确的范围"
|
||||||
|
return@apply
|
||||||
|
}
|
||||||
|
etInputScope.error = null
|
||||||
|
val toInt = etEpubSize.text.toString().toInt()
|
||||||
|
startExport(path, position, toInt, text.toString())
|
||||||
|
alertDialog.hide()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -376,7 +365,7 @@ class CacheActivity : VMBaseActivity<ActivityCacheBookBinding, CacheViewModel>()
|
|||||||
if (exportPosition >= 0) {
|
if (exportPosition >= 0) {
|
||||||
adapter.getItem(exportPosition)?.let { book ->
|
adapter.getItem(exportPosition)?.let { book ->
|
||||||
when (AppConfig.exportType) {
|
when (AppConfig.exportType) {
|
||||||
1 -> viewModel.exportEPUB(path, book, size, scope)
|
1 -> viewModel.exportEPUBs(path, book, size, scope)
|
||||||
// 目前仅支持 epub
|
// 目前仅支持 epub
|
||||||
//else -> viewModel.export(path, book)
|
//else -> viewModel.export(path, book)
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-13
@@ -268,8 +268,8 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
result.add(s.toInt() - 1)
|
result.add(s.toInt() - 1)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
val left = v[0].toInt();
|
val left = v[0].toInt()
|
||||||
val right = v[1].toInt();
|
val right = v[1].toInt()
|
||||||
if (left > right)
|
if (left > right)
|
||||||
return IntArray(0)
|
return IntArray(0)
|
||||||
for (i in left..right)
|
for (i in left..right)
|
||||||
@@ -290,7 +290,7 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
* @author Discut
|
* @author Discut
|
||||||
* @since 2023/5/22
|
* @since 2023/5/22
|
||||||
*/
|
*/
|
||||||
fun exportEPUB(path: String, book: Book, size: Int = 1, scope: String) {
|
fun exportEPUBs(path: String, book: Book, size: Int = 1, scope: String) {
|
||||||
if (exportProgress.contains(book.bookUrl)) return
|
if (exportProgress.contains(book.bookUrl)) return
|
||||||
CustomExporter(this).let {
|
CustomExporter(this).let {
|
||||||
it.scope = paresScope(scope)
|
it.scope = paresScope(scope)
|
||||||
@@ -627,13 +627,23 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
|
|
||||||
//////end of EPUB
|
//////end of EPUB
|
||||||
|
|
||||||
|
//////start of custom exporter
|
||||||
/**
|
/**
|
||||||
* 自定义Exporter
|
* 自定义Exporter
|
||||||
|
*
|
||||||
|
* @since 2023/5/23
|
||||||
*/
|
*/
|
||||||
class CustomExporter(private val context: CacheViewModel) {
|
class CustomExporter(private val context: CacheViewModel) {
|
||||||
var scope: IntArray = IntArray(0);
|
var scope: IntArray = IntArray(0)
|
||||||
var size: Int = 1;
|
var size: Int = 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出Epub
|
||||||
|
*
|
||||||
|
* from [io.legado.app.ui.book.cache.CacheViewModel.exportEPUB]
|
||||||
|
* @param path 导出的路径
|
||||||
|
* @param book 书籍
|
||||||
|
*/
|
||||||
fun exportEPUB(
|
fun exportEPUB(
|
||||||
path: String,
|
path: String,
|
||||||
book: Book
|
book: Book
|
||||||
@@ -653,7 +663,6 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
val doc = DocumentFile.fromTreeUri(context.context, uri)
|
val doc = DocumentFile.fromTreeUri(context.context, uri)
|
||||||
?: throw NoStackTraceException("获取导出文档失败")
|
?: throw NoStackTraceException("获取导出文档失败")
|
||||||
book.totalChapterNum
|
book.totalChapterNum
|
||||||
// TODO
|
|
||||||
exportEpub(doc, book)
|
exportEpub(doc, book)
|
||||||
} else {
|
} else {
|
||||||
context.exportEpub(File(path).createFolderIfNotExist(), book)
|
context.exportEpub(File(path).createFolderIfNotExist(), book)
|
||||||
@@ -683,7 +692,7 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
epubList.forEachIndexed { index, epubBook ->
|
epubList.forEachIndexed { index, epubBook ->
|
||||||
//设置正文
|
//设置正文
|
||||||
this.setEpubContent(contentModel, book, epubBook, index)
|
this.setEpubContent(contentModel, book, epubBook, index)
|
||||||
save2Drive(book.name+index+".epub", epubBook, doc)
|
save2Drive(book.name + index + ".epub", epubBook, doc)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -703,17 +712,18 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
//正文
|
//正文
|
||||||
val useReplace = AppConfig.exportUseReplace && book.getUseReplaceRule()
|
val useReplace = AppConfig.exportUseReplace && book.getUseReplaceRule()
|
||||||
val contentProcessor = ContentProcessor.get(book.name, book.origin)
|
val contentProcessor = ContentProcessor.get(book.name, book.origin)
|
||||||
var chapterList: MutableList<BookChapter> = ArrayList();
|
var chapterList: MutableList<BookChapter> = ArrayList()
|
||||||
appDb.bookChapterDao.getChapterList(book.bookUrl).forEachIndexed { index, chapter ->
|
appDb.bookChapterDao.getChapterList(book.bookUrl).forEachIndexed { index, chapter ->
|
||||||
if (scope.indexOf(index) >= 0) {
|
if (scope.indexOf(index) >= 0) {
|
||||||
chapterList.add(chapter)
|
chapterList.add(chapter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
val totalChapterNum = book.totalChapterNum / scope.size
|
||||||
chapterList = chapterList.subList(epubBookIndex * size, (epubBookIndex + 1) * size)
|
chapterList = chapterList.subList(epubBookIndex * size, (epubBookIndex + 1) * size)
|
||||||
chapterList.forEachIndexed { index, chapter ->
|
chapterList.forEachIndexed { index, chapter ->
|
||||||
coroutineContext.ensureActive()
|
coroutineContext.ensureActive()
|
||||||
context.upAdapterLiveData.postValue(book.bookUrl)
|
context.upAdapterLiveData.postValue(book.bookUrl)
|
||||||
context.exportProgress[book.bookUrl] = index
|
context.exportProgress[book.bookUrl] = totalChapterNum * (epubBookIndex * size + index)
|
||||||
BookHelp.getContent(book, chapter).let { content ->
|
BookHelp.getContent(book, chapter).let { content ->
|
||||||
var content1 = context.fixPic(
|
var content1 = context.fixPic(
|
||||||
epubBook,
|
epubBook,
|
||||||
@@ -758,7 +768,7 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
private fun createEpubs(doc: DocumentFile, book: Book): Pair<String, List<EpubBook>> {
|
private fun createEpubs(doc: DocumentFile, book: Book): Pair<String, List<EpubBook>> {
|
||||||
val paresNumOfEpub = paresNumOfEpub(scope.size, size)
|
val paresNumOfEpub = paresNumOfEpub(scope.size, size)
|
||||||
val result: MutableList<EpubBook> = ArrayList(paresNumOfEpub)
|
val result: MutableList<EpubBook> = ArrayList(paresNumOfEpub)
|
||||||
var contentModel = "";
|
var contentModel = ""
|
||||||
for (i in 1..paresNumOfEpub) {
|
for (i in 1..paresNumOfEpub) {
|
||||||
val filename = book.getExportFileName("epub")
|
val filename = book.getExportFileName("epub")
|
||||||
DocumentUtils.delete(doc, filename)
|
DocumentUtils.delete(doc, filename)
|
||||||
@@ -798,11 +808,11 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
*/
|
*/
|
||||||
private fun paresNumOfEpub(total: Int, size: Int): Int {
|
private fun paresNumOfEpub(total: Int, size: Int): Int {
|
||||||
val i = total % size
|
val i = total % size
|
||||||
var result = total / size;
|
var result = total / size
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
result++;
|
result++
|
||||||
}
|
}
|
||||||
return result;
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
package io.legado.app.ui.book.cache
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.View
|
|
||||||
import io.legado.app.R
|
|
||||||
import io.legado.app.base.BaseDialogFragment
|
|
||||||
import io.legado.app.databinding.DialogSelectSectionExportBinding
|
|
||||||
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
|
||||||
|
|
||||||
class CustomExportSectionDialog() : BaseDialogFragment(R.layout.dialog_select_section_export) {
|
|
||||||
|
|
||||||
private val binding by viewBinding(DialogSelectSectionExportBinding::bind)
|
|
||||||
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
<string name="delete_all">删除所有</string>
|
<string name="delete_all">删除所有</string>
|
||||||
<string name="replace">替换</string>
|
<string name="replace">替换</string>
|
||||||
<string name="replace_purify">替换净化</string>
|
<string name="replace_purify">替换净化</string>
|
||||||
<string name="custom_export_section">自定义导出章节</string>
|
<string name="custom_export_section">自定义Epub导出章节</string>
|
||||||
<string name="replace_purify_desc">配置替换净化规则</string>
|
<string name="replace_purify_desc">配置替换净化规则</string>
|
||||||
<string name="not_available">暂无</string>
|
<string name="not_available">暂无</string>
|
||||||
<string name="enable">启用</string>
|
<string name="enable">启用</string>
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
<string name="edit">Edit</string>
|
<string name="edit">Edit</string>
|
||||||
<string name="delete">Delete</string>
|
<string name="delete">Delete</string>
|
||||||
<string name="delete_all">Delete all</string>
|
<string name="delete_all">Delete all</string>
|
||||||
<string name="custom_export_section">Custom export chapter</string>
|
<string name="custom_export_section">Custom export chapter of epub</string>
|
||||||
<string name="replace">Replace</string>
|
<string name="replace">Replace</string>
|
||||||
<string name="replace_purify">Replacement</string>
|
<string name="replace_purify">Replacement</string>
|
||||||
<string name="replace_purify_desc">Configure replacement rules</string>
|
<string name="replace_purify_desc">Configure replacement rules</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user