mirror of
https://github.com/gedoor/legado.git
synced 2024-08-30 09:23:26 +08:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
8f66913e45
@ -11,6 +11,17 @@
|
|||||||
* 正文出现缺字漏字、内容缺失、排版错乱等情况,有可能是净化规则或简繁转换出现问题。
|
* 正文出现缺字漏字、内容缺失、排版错乱等情况,有可能是净化规则或简繁转换出现问题。
|
||||||
* 漫画源看书显示乱码,**阅读与其他软件的源并不通用**,请导入阅读的支持的漫画源!
|
* 漫画源看书显示乱码,**阅读与其他软件的源并不通用**,请导入阅读的支持的漫画源!
|
||||||
|
|
||||||
|
**2023/03/10**
|
||||||
|
* 远程书籍添加webDav多配置
|
||||||
|
* 更新文件类书源详情页界面逻辑
|
||||||
|
* 尝试修复语音朗读
|
||||||
|
* 修复特定情况下书籍导入界面计数错误
|
||||||
|
* 修复阅读界面导航栏更新不及时
|
||||||
|
* 修复某些以空白开头的链接的拼接
|
||||||
|
* 导入某些不规范的本地书源文件提示空
|
||||||
|
* 修复某些空白备份恢复的错误弹窗
|
||||||
|
* 修复章节都在一个xhtml里面的epub的内容解析
|
||||||
|
|
||||||
**2023/03/03**
|
**2023/03/03**
|
||||||
|
|
||||||
* 朗读速度添加数值显示
|
* 朗读速度添加数值显示
|
||||||
|
@ -25,6 +25,8 @@ object AppConst {
|
|||||||
|
|
||||||
const val MAX_THREAD = 9
|
const val MAX_THREAD = 9
|
||||||
|
|
||||||
|
const val DEFAULT_WEBDAV_ID = -1L
|
||||||
|
|
||||||
val SCRIPT_ENGINE: RhinoScriptEngine by lazy {
|
val SCRIPT_ENGINE: RhinoScriptEngine by lazy {
|
||||||
RhinoScriptEngine()
|
RhinoScriptEngine()
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package io.legado.app.lib.webdav
|
package io.legado.app.lib.webdav
|
||||||
|
|
||||||
import io.legado.app.data.appDb
|
import io.legado.app.data.appDb
|
||||||
|
import io.legado.app.data.entities.Server.WebDavConfig
|
||||||
import io.legado.app.exception.NoStackTraceException
|
import io.legado.app.exception.NoStackTraceException
|
||||||
import okhttp3.Credentials
|
import okhttp3.Credentials
|
||||||
import java.nio.charset.Charset
|
import java.nio.charset.Charset
|
||||||
@ -29,4 +30,6 @@ data class Authorization(
|
|||||||
} ?: throw WebDavException("Unexpected WebDav Authorization")
|
} ?: throw WebDavException("Unexpected WebDav Authorization")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constructor(webDavConfig: WebDavConfig): this(webDavConfig.username, webDavConfig.password)
|
||||||
|
|
||||||
}
|
}
|
@ -137,38 +137,35 @@ class EpubFile(var book: Book) {
|
|||||||
}
|
}
|
||||||
/*获取当前章节文本*/
|
/*获取当前章节文本*/
|
||||||
epubBook?.let { epubBook ->
|
epubBook?.let { epubBook ->
|
||||||
val nextUrl = chapter.getVariable("nextUrl")
|
val nextChapterFirstResourceHref = chapter.getVariable("nextUrl")?.substringBeforeLast("#")
|
||||||
|
val currentChapterFirstResourceHref = chapter.url.substringBeforeLast("#")
|
||||||
val startFragmentId = chapter.startFragmentId
|
val startFragmentId = chapter.startFragmentId
|
||||||
val endFragmentId = chapter.endFragmentId
|
val endFragmentId = chapter.endFragmentId
|
||||||
val elements = Elements()
|
val elements = Elements()
|
||||||
var hasMoreResources = false
|
var findChapterFirstSource = false
|
||||||
val includeNextChapterResource = !endFragmentId.isNullOrBlank()
|
val includeNextChapterResource = !endFragmentId.isNullOrBlank()
|
||||||
/*一些书籍依靠href索引的resource会包含多个章节,需要依靠fragmentId来截取到当前章节的内容*/
|
/*一些书籍依靠href索引的resource会包含多个章节,需要依靠fragmentId来截取到当前章节的内容*/
|
||||||
/*注:这里较大增加了内容加载的时间,所以首次获取内容后可存储到本地cache,减少重复加载*/
|
/*注:这里较大增加了内容加载的时间,所以首次获取内容后可存储到本地cache,减少重复加载*/
|
||||||
for (res in epubBook.contents) {
|
for (res in epubBook.contents) {
|
||||||
val isFirstResource = chapter.url.substringBeforeLast("#") == res.href
|
if (!findChapterFirstSource) {
|
||||||
val isNextChapterResource = res.href == nextUrl?.substringBeforeLast("#")
|
if (currentChapterFirstResourceHref == res.href) findChapterFirstSource = true
|
||||||
if (isFirstResource) {
|
// 第一个xhtml文件
|
||||||
// add first resource to elements
|
|
||||||
elements.add(
|
elements.add(
|
||||||
/* pass endFragmentId if only has one resource */
|
|
||||||
getBody(res, startFragmentId, endFragmentId)
|
getBody(res, startFragmentId, endFragmentId)
|
||||||
)
|
)
|
||||||
// check current resource
|
if (currentChapterFirstResourceHref == nextChapterFirstResourceHref) break
|
||||||
if (isNextChapterResource) {
|
continue
|
||||||
/* FragmentId should not be same in same resource */
|
}
|
||||||
if (!endFragmentId.isNullOrBlank() && endFragmentId == startFragmentId)
|
if (nextChapterFirstResourceHref != res.href) {
|
||||||
AppLog.putDebug("Epub: Resource (${res.href}) has same FragmentId, check the file: ${book.bookUrl}")
|
// 其余部分
|
||||||
break
|
|
||||||
}
|
|
||||||
hasMoreResources = true
|
|
||||||
} else if (hasMoreResources) {
|
|
||||||
if (isNextChapterResource) {
|
|
||||||
if (includeNextChapterResource) elements.add(getBody(res, null/* FragmentId may be same in different resources, pass null */, endFragmentId))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
// rest resource should not have fragmentId, pass null
|
|
||||||
elements.add(getBody(res, null, null))
|
elements.add(getBody(res, null, null))
|
||||||
|
} else {
|
||||||
|
// 下一章节的第一个xhtml
|
||||||
|
if (includeNextChapterResource) {
|
||||||
|
//有Fragment 则添加到上一章节
|
||||||
|
elements.add(getBody(res, null, endFragmentId))
|
||||||
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//title标签中的内容不需要显示在正文中,去除
|
//title标签中的内容不需要显示在正文中,去除
|
||||||
|
@ -30,7 +30,7 @@ import java.io.File
|
|||||||
class RemoteBookActivity : BaseImportBookActivity<ActivityImportBookBinding, RemoteBookViewModel>(),
|
class RemoteBookActivity : BaseImportBookActivity<ActivityImportBookBinding, RemoteBookViewModel>(),
|
||||||
RemoteBookAdapter.CallBack,
|
RemoteBookAdapter.CallBack,
|
||||||
SelectActionBar.CallBack,
|
SelectActionBar.CallBack,
|
||||||
ServerConfigDialog.Callback {
|
ServersDialog.Callback {
|
||||||
override val binding by viewBinding(ActivityImportBookBinding::inflate)
|
override val binding by viewBinding(ActivityImportBookBinding::inflate)
|
||||||
override val viewModel by viewModels<RemoteBookViewModel>()
|
override val viewModel by viewModels<RemoteBookViewModel>()
|
||||||
private val adapter by lazy { RemoteBookAdapter(this, this) }
|
private val adapter by lazy { RemoteBookAdapter(this, this) }
|
||||||
|
@ -80,17 +80,10 @@ class RemoteBookViewModel(application: Application) : BaseViewModel(application)
|
|||||||
|
|
||||||
fun initData(onSuccess: () -> Unit) {
|
fun initData(onSuccess: () -> Unit) {
|
||||||
execute {
|
execute {
|
||||||
val server = appDb.serverDao.get(AppConfig.remoteServerId)
|
appDb.serverDao.get(AppConfig.remoteServerId)?.getWebDavConfig()?.let {
|
||||||
val serverConfig = server?.getConfigJsonObject()
|
val authorization = Authorization(it)
|
||||||
if (serverConfig != null && serverConfig.has("url")) {
|
remoteBookWebDav = RemoteBookWebDav(it.url, authorization, AppConfig.remoteServerId)
|
||||||
val url = serverConfig.getString("url")
|
return@execute
|
||||||
if (url.isNotBlank()) {
|
|
||||||
val user = serverConfig.getString("user")
|
|
||||||
val password = serverConfig.getString("password")
|
|
||||||
val authorization = Authorization(user, password)
|
|
||||||
remoteBookWebDav = RemoteBookWebDav(url, authorization, 10001)
|
|
||||||
return@execute
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
remoteBookWebDav = AppWebDav.defaultBookWebDav
|
remoteBookWebDav = AppWebDav.defaultBookWebDav
|
||||||
?: throw NoStackTraceException("webDav没有配置")
|
?: throw NoStackTraceException("webDav没有配置")
|
||||||
|
@ -67,7 +67,6 @@ class ServerConfigDialog() : BaseDialogFragment(R.layout.dialog_webdav_server, t
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun upConfigView(server: Server?) {
|
private fun upConfigView(server: Server?) {
|
||||||
binding.etId.setText(server?.id?.toString())
|
|
||||||
binding.etName.setText(server?.name)
|
binding.etName.setText(server?.name)
|
||||||
binding.spType.setSelection(
|
binding.spType.setSelection(
|
||||||
when (server?.type) {
|
when (server?.type) {
|
||||||
@ -109,14 +108,7 @@ class ServerConfigDialog() : BaseDialogFragment(R.layout.dialog_webdav_server, t
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getServer(): Server? {
|
private fun getServer(): Server? {
|
||||||
val id = kotlin.runCatching {
|
val server = viewModel.mServer?.copy() ?: Server()
|
||||||
binding.etId.text.toString().toLong()
|
|
||||||
}.getOrNull()
|
|
||||||
if (id == null) {
|
|
||||||
toastOnUi("id不能为空")
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
val server = viewModel.mServer?.copy(id = id) ?: Server(id = id)
|
|
||||||
server.name = binding.etName.text.toString()
|
server.name = binding.etName.text.toString()
|
||||||
server.type = when (binding.spType.selectedItemPosition) {
|
server.type = when (binding.spType.selectedItemPosition) {
|
||||||
else -> Server.TYPE.WEBDAV
|
else -> Server.TYPE.WEBDAV
|
||||||
@ -139,15 +131,15 @@ class ServerConfigDialog() : BaseDialogFragment(R.layout.dialog_webdav_server, t
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun onDismiss(dialog: DialogInterface) {
|
// override fun onDismiss(dialog: DialogInterface) {
|
||||||
super.onDismiss(dialog)
|
// super.onDismiss(dialog)
|
||||||
((parentFragment as? Callback) ?: (activity as? Callback))
|
// ((parentFragment as? Callback) ?: (activity as? Callback))
|
||||||
?.onDialogDismiss("serverConfig")
|
// ?.onDialogDismiss("serverConfig")
|
||||||
}
|
// }
|
||||||
|
|
||||||
interface Callback {
|
// interface Callback {
|
||||||
|
|
||||||
fun onDialogDismiss(tag: String)
|
// fun onDialogDismiss(tag: String)
|
||||||
|
|
||||||
}
|
// }
|
||||||
}
|
}
|
@ -10,6 +10,7 @@ import androidx.appcompat.widget.Toolbar
|
|||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
|
import io.legado.app.constant.AppConst.DEFAULT_WEBDAV_ID
|
||||||
import io.legado.app.base.BaseDialogFragment
|
import io.legado.app.base.BaseDialogFragment
|
||||||
import io.legado.app.base.adapter.ItemViewHolder
|
import io.legado.app.base.adapter.ItemViewHolder
|
||||||
import io.legado.app.base.adapter.RecyclerAdapter
|
import io.legado.app.base.adapter.RecyclerAdapter
|
||||||
@ -61,7 +62,7 @@ class ServersDialog : BaseDialogFragment(R.layout.dialog_recycler_view),
|
|||||||
binding.tvFooterLeft.text = getString(R.string.text_default)
|
binding.tvFooterLeft.text = getString(R.string.text_default)
|
||||||
binding.tvFooterLeft.visible()
|
binding.tvFooterLeft.visible()
|
||||||
binding.tvFooterLeft.setOnClickListener {
|
binding.tvFooterLeft.setOnClickListener {
|
||||||
AppConfig.remoteServerId = 0
|
AppConfig.remoteServerId = DEFAULT_WEBDAV_ID
|
||||||
dismissAllowingStateLoss()
|
dismissAllowingStateLoss()
|
||||||
}
|
}
|
||||||
binding.tvCancel.visible()
|
binding.tvCancel.visible()
|
||||||
|
@ -28,21 +28,6 @@
|
|||||||
app:popupTheme="@style/AppTheme.PopupOverlay"
|
app:popupTheme="@style/AppTheme.PopupOverlay"
|
||||||
app:titleTextAppearance="@style/ToolbarTitle" />
|
app:titleTextAppearance="@style/ToolbarTitle" />
|
||||||
|
|
||||||
<io.legado.app.ui.widget.text.TextInputLayout
|
|
||||||
android:id="@+id/til_id"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:hint="ID"
|
|
||||||
tools:ignore="HardcodedText">
|
|
||||||
|
|
||||||
<io.legado.app.lib.theme.view.ThemeEditText
|
|
||||||
android:id="@+id/et_id"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:numeric="integer"
|
|
||||||
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
|
|
||||||
</io.legado.app.ui.widget.text.TextInputLayout>
|
|
||||||
|
|
||||||
<io.legado.app.ui.widget.text.TextInputLayout
|
<io.legado.app.ui.widget.text.TextInputLayout
|
||||||
android:id="@+id/til_name"
|
android:id="@+id/til_name"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
Loading…
Reference in New Issue
Block a user