添加排版一键导入

pull/1155/head
gedoor 3 years ago
parent e46cb97808
commit 5453c15049
  1. 17
      app/src/main/assets/updateLog.md
  2. 1
      app/src/main/java/io/legado/app/help/JsExtensions.kt
  3. 59
      app/src/main/java/io/legado/app/help/ReadBookConfig.kt
  4. 1
      app/src/main/java/io/legado/app/ui/association/OnLineImportActivity.kt
  5. 23
      app/src/main/java/io/legado/app/ui/association/OnLineImportViewModel.kt
  6. 59
      app/src/main/java/io/legado/app/ui/book/read/config/BgTextConfigDialog.kt

@ -8,13 +8,16 @@
* 正文出现缺字漏字、内容缺失、排版错乱等情况,有可能是净化规则出现问题。先关闭替换净化并刷新,再观察是否正常。如果正常说明净化规则存在误杀,如果关闭后仍然出现相关问题,请点击源链接查看原文与正文是否相同,如果不同,再进行反馈。 * 正文出现缺字漏字、内容缺失、排版错乱等情况,有可能是净化规则出现问题。先关闭替换净化并刷新,再观察是否正常。如果正常说明净化规则存在误杀,如果关闭后仍然出现相关问题,请点击源链接查看原文与正文是否相同,如果不同,再进行反馈。
* 漫画源看书显示乱码,**阅读与其他软件的源并不通用**,请导入阅读的支持的漫画源! * 漫画源看书显示乱码,**阅读与其他软件的源并不通用**,请导入阅读的支持的漫画源!
**2021/07/21** **2021/07/22**
* 非关键规则添加try防止报错中断解析 1. 非关键规则添加try防止报错中断解析
* 添加获取封面的api 2. 添加获取封面的api
* 获取正文api使用替换规则 3. 获取正文api使用替换规则
* 添加一个ronet版本,网络访问使用Chromium内核 4. 添加一个ronet版本,网络访问使用Chromium内核
* web书架增加【最近一次更新书籍信息的时间】 5. web书架增加【最近一次更新书籍信息的时间】
* 采用Flow替换LiveData,优化资源使用 6. 采用Flow替换LiveData,优化资源使用
7. 统一网络一键导入路径legado://import/{path}?src={url}
* path: bookSource,rssSource,replaceRule,textTocRule,httpTTS,theme,readConfig
* 添加了txt小说规则,在线朗读引擎,主题,排版 的一键导入支持,老url依然可用
**2021/07/16** **2021/07/16**
1. js扩展函数添加删除本地文件方法 1. js扩展函数添加删除本地文件方法

@ -346,7 +346,6 @@ interface JsExtensions {
} }
val bos = ByteArrayOutputStream() val bos = ByteArrayOutputStream()
val zis = ZipInputStream(ByteArrayInputStream(bytes)) val zis = ZipInputStream(ByteArrayInputStream(bytes))
var entry: ZipEntry? = zis.nextEntry var entry: ZipEntry? = zis.nextEntry
while (entry != null) { while (entry != null) {
if (entry.name.equals(path)) { if (entry.name.equals(path)) {

@ -10,6 +10,8 @@ import io.legado.app.constant.PreferKey
import io.legado.app.help.coroutine.Coroutine import io.legado.app.help.coroutine.Coroutine
import io.legado.app.ui.book.read.page.provider.ChapterProvider import io.legado.app.ui.book.read.page.provider.ChapterProvider
import io.legado.app.utils.* import io.legado.app.utils.*
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.withContext
import splitties.init.appCtx import splitties.init.appCtx
import java.io.File import java.io.File
@ -355,6 +357,63 @@ object ReadBookConfig {
return exportConfig return exportConfig
} }
suspend fun import(byteArray: ByteArray): Config {
return withContext(IO) {
val configZipPath = FileUtils.getPath(appCtx.externalCache, configFileName)
FileUtils.deleteFile(configZipPath)
val zipFile = FileUtils.createFileIfNotExist(configZipPath)
zipFile.writeBytes(byteArray)
val configDirPath = FileUtils.getPath(appCtx.externalCache, "readConfig")
FileUtils.deleteFile(configDirPath)
@Suppress("BlockingMethodInNonBlockingContext")
ZipUtils.unzipFile(zipFile, FileUtils.createFolderIfNotExist(configDirPath))
val configDir = FileUtils.createFolderIfNotExist(configDirPath)
val configFile = FileUtils.getFile(configDir, "readConfig.json")
val config: Config = GSON.fromJsonObject(configFile.readText())!!
if (config.textFont.isNotEmpty()) {
val fontName = FileUtils.getName(config.textFont)
val fontPath =
FileUtils.getPath(appCtx.externalFiles, "font", fontName)
if (!FileUtils.exist(fontPath)) {
FileUtils.getFile(configDir, fontName).copyTo(File(fontPath))
}
config.textFont = fontPath
}
if (config.bgType == 2) {
val bgName = FileUtils.getName(config.bgStr)
val bgPath = FileUtils.getPath(appCtx.externalFiles, "bg", bgName)
if (!FileUtils.exist(bgPath)) {
val bgFile = FileUtils.getFile(configDir, bgName)
if (bgFile.exists()) {
bgFile.copyTo(File(bgPath))
}
}
}
if (config.bgTypeNight == 2) {
val bgName = FileUtils.getName(config.bgStrNight)
val bgPath = FileUtils.getPath(appCtx.externalFiles, "bg", bgName)
if (!FileUtils.exist(bgPath)) {
val bgFile = FileUtils.getFile(configDir, bgName)
if (bgFile.exists()) {
bgFile.copyTo(File(bgPath))
}
}
}
if (config.bgTypeEInk == 2) {
val bgName = FileUtils.getName(config.bgStrEInk)
@Suppress("BlockingMethodInNonBlockingContext") val bgPath =
FileUtils.getPath(appCtx.externalFiles, "bg", bgName)
if (!FileUtils.exist(bgPath)) {
val bgFile = FileUtils.getFile(configDir, bgName)
if (bgFile.exists()) {
bgFile.copyTo(File(bgPath))
}
}
}
return@withContext config
}
}
@Keep @Keep
class Config( class Config(
var name: String = "", var name: String = "",

@ -33,6 +33,7 @@ class OnLineImportActivity :
"textTocRule" -> viewModel.importTextTocRule(url, this::finallyDialog) "textTocRule" -> viewModel.importTextTocRule(url, this::finallyDialog)
"httpTTS" -> viewModel.importHttpTTS(url, this::finallyDialog) "httpTTS" -> viewModel.importHttpTTS(url, this::finallyDialog)
"theme" -> viewModel.importTheme(url, this::finallyDialog) "theme" -> viewModel.importTheme(url, this::finallyDialog)
"readConfig" -> viewModel.importReadConfig(url, this::finallyDialog)
else -> { else -> {
} }
} }

@ -6,6 +6,7 @@ import io.legado.app.base.BaseViewModel
import io.legado.app.data.appDb import io.legado.app.data.appDb
import io.legado.app.data.entities.HttpTTS import io.legado.app.data.entities.HttpTTS
import io.legado.app.data.entities.TxtTocRule import io.legado.app.data.entities.TxtTocRule
import io.legado.app.help.ReadBookConfig
import io.legado.app.help.ThemeConfig import io.legado.app.help.ThemeConfig
import io.legado.app.help.http.newCall import io.legado.app.help.http.newCall
import io.legado.app.help.http.okHttpClient import io.legado.app.help.http.okHttpClient
@ -85,4 +86,26 @@ class OnLineImportViewModel(app: App) : BaseViewModel(app) {
} }
} }
fun importReadConfig(url: String, finally: (title: String, msg: String) -> Unit) {
execute {
@Suppress("BlockingMethodInNonBlockingContext")
val bytes = okHttpClient.newCall {
url(url)
}.bytes()
val config = ReadBookConfig.import(bytes)
ReadBookConfig.configList.forEachIndexed { index, c ->
if (c.name == config.name) {
ReadBookConfig.configList[index] = config
return@execute config.name
}
ReadBookConfig.configList.add(config)
return@execute config.name
}
}.onSuccess {
finally.invoke(context.getString(R.string.success), "导入排版成功")
}.onError {
finally.invoke(context.getString(R.string.error), it.localizedMessage ?: "未知错误")
}
}
} }

@ -308,6 +308,7 @@ class BgTextConfigDialog : BaseDialogFragment() {
private fun importNetConfig(url: String) { private fun importNetConfig(url: String) {
execute { execute {
@Suppress("BlockingMethodInNonBlockingContext")
okHttpClient.newCall { okHttpClient.newCall {
url(url) url(url)
}.bytes().let { }.bytes().let {
@ -318,9 +319,9 @@ class BgTextConfigDialog : BaseDialogFragment() {
} }
} }
@Suppress("BlockingMethodInNonBlockingContext")
private fun importConfig(uri: Uri) { private fun importConfig(uri: Uri) {
execute { execute {
@Suppress("BlockingMethodInNonBlockingContext")
importConfig(uri.readBytes(requireContext())!!) importConfig(uri.readBytes(requireContext())!!)
}.onError { }.onError {
it.printStackTrace() it.printStackTrace()
@ -328,61 +329,13 @@ class BgTextConfigDialog : BaseDialogFragment() {
} }
} }
@Suppress("BlockingMethodInNonBlockingContext") @Suppress("BlockingMethodInNonBlockingContext", "BlockingMethodInNonBlockingContext")
private fun importConfig(byteArray: ByteArray) { private fun importConfig(byteArray: ByteArray) {
execute { execute {
val configZipPath = FileUtils.getPath(requireContext().externalCache, configFileName) ReadBookConfig.import(byteArray)
FileUtils.deleteFile(configZipPath)
val zipFile = FileUtils.createFileIfNotExist(configZipPath)
zipFile.writeBytes(byteArray)
val configDirPath = FileUtils.getPath(requireContext().externalCache, "readConfig")
FileUtils.deleteFile(configDirPath)
ZipUtils.unzipFile(zipFile, FileUtils.createFolderIfNotExist(configDirPath))
val configDir = FileUtils.createFolderIfNotExist(configDirPath)
val configFile = FileUtils.getFile(configDir, "readConfig.json")
val config: ReadBookConfig.Config = GSON.fromJsonObject(configFile.readText())!!
if (config.textFont.isNotEmpty()) {
val fontName = FileUtils.getName(config.textFont)
val fontPath =
FileUtils.getPath(requireContext().externalFiles, "font", fontName)
if (!FileUtils.exist(fontPath)) {
FileUtils.getFile(configDir, fontName).copyTo(File(fontPath))
}
config.textFont = fontPath
}
if (config.bgType == 2) {
val bgName = FileUtils.getName(config.bgStr)
val bgPath = FileUtils.getPath(requireContext().externalFiles, "bg", bgName)
if (!FileUtils.exist(bgPath)) {
val bgFile = FileUtils.getFile(configDir, bgName)
if (bgFile.exists()) {
bgFile.copyTo(File(bgPath))
}
}
}
if (config.bgTypeNight == 2) {
val bgName = FileUtils.getName(config.bgStrNight)
val bgPath = FileUtils.getPath(requireContext().externalFiles, "bg", bgName)
if (!FileUtils.exist(bgPath)) {
val bgFile = FileUtils.getFile(configDir, bgName)
if (bgFile.exists()) {
bgFile.copyTo(File(bgPath))
}
}
}
if (config.bgTypeEInk == 2) {
val bgName = FileUtils.getName(config.bgStrEInk)
val bgPath = FileUtils.getPath(requireContext().externalFiles, "bg", bgName)
if (!FileUtils.exist(bgPath)) {
val bgFile = FileUtils.getFile(configDir, bgName)
if (bgFile.exists()) {
bgFile.copyTo(File(bgPath))
}
}
}
ReadBookConfig.durConfig = config
postEvent(EventBus.UP_CONFIG, true)
}.onSuccess { }.onSuccess {
ReadBookConfig.durConfig = it
postEvent(EventBus.UP_CONFIG, true)
toastOnUi("导入成功") toastOnUi("导入成功")
}.onError { }.onError {
it.printStackTrace() it.printStackTrace()

Loading…
Cancel
Save