pull/1630/head
kunfei 3 years ago
parent 55e8af89af
commit 400db881ad
  1. 34
      app/src/main/java/io/legado/app/help/BookHelp.kt
  2. 14
      app/src/main/java/io/legado/app/model/CacheBook.kt
  3. 2
      app/src/main/java/io/legado/app/ui/book/cache/CacheActivity.kt
  4. 4
      app/src/main/java/io/legado/app/ui/book/cache/CacheAdapter.kt
  5. 2
      app/src/main/java/io/legado/app/ui/book/read/BaseReadBookActivity.kt
  6. 103
      app/src/main/java/io/legado/app/ui/book/read/ContentEditDialog.kt
  7. 45
      app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt
  8. 25
      app/src/main/res/layout/dialog_content_edit.xml
  9. 4
      app/src/main/res/menu/book_read.xml
  10. 18
      app/src/main/res/menu/content_edit.xml
  11. 1
      app/src/main/res/values-es-rES/strings.xml
  12. 1
      app/src/main/res/values-ja-rJP/strings.xml
  13. 1
      app/src/main/res/values-pt-rBR/strings.xml
  14. 1
      app/src/main/res/values-zh-rHK/strings.xml
  15. 1
      app/src/main/res/values-zh-rTW/strings.xml
  16. 1
      app/src/main/res/values-zh/strings.xml
  17. 1
      app/src/main/res/values/strings.xml

@ -72,7 +72,7 @@ object BookHelp {
postEvent(EventBus.SAVE_CONTENT, bookChapter) postEvent(EventBus.SAVE_CONTENT, bookChapter)
} }
private fun saveText( fun saveText(
book: Book, book: Book,
bookChapter: BookChapter, bookChapter: BookChapter,
content: String content: String
@ -208,23 +208,20 @@ object BookHelp {
* 读取章节内容 * 读取章节内容
*/ */
fun getContent(book: Book, bookChapter: BookChapter): String? { fun getContent(book: Book, bookChapter: BookChapter): String? {
if (book.isLocalTxt() || book.isUmd()) { val file = downloadDir.getFile(
return LocalBook.getContent(book, bookChapter) cacheFolderName,
} else if (book.isEpub() && !hasContent(book, bookChapter)) { book.getFolderName(),
bookChapter.getFileName()
)
if (file.exists()) {
return file.readText()
}
if (book.isLocalBook()) {
val string = LocalBook.getContent(book, bookChapter) val string = LocalBook.getContent(book, bookChapter)
string?.let { if (string != null && book.isEpub()) {
saveText(book, bookChapter, it) saveText(book, bookChapter, string)
} }
return string return string
} else {
val file = downloadDir.getFile(
cacheFolderName,
book.getFolderName(),
bookChapter.getFileName()
)
if (file.exists()) {
return file.readText()
}
} }
return null return null
} }
@ -366,9 +363,9 @@ object BookHelp {
val chapterName1 = StringUtils.fullToHalf(chapterName).replace(regexA, "") val chapterName1 = StringUtils.fullToHalf(chapterName).replace(regexA, "")
return StringUtils.stringToInt( return StringUtils.stringToInt(
( (
chapterNamePattern1.matcher(chapterName1).takeIf { it.find() } chapterNamePattern1.matcher(chapterName1).takeIf { it.find() }
?: chapterNamePattern2.matcher(chapterName1).takeIf { it.find() } ?: chapterNamePattern2.matcher(chapterName1).takeIf { it.find() }
)?.group(1) )?.group(1)
?: "-1" ?: "-1"
) )
} }
@ -380,6 +377,7 @@ object BookHelp {
return@lazy "[^\\w\\u4E00-\\u9FEF〇\\u3400-\\u4DBF\\u20000-\\u2A6DF\\u2A700-\\u2EBEF]".toRegex() return@lazy "[^\\w\\u4E00-\\u9FEF〇\\u3400-\\u4DBF\\u20000-\\u2A6DF\\u2A700-\\u2EBEF]".toRegex()
} }
@Suppress("RegExpUnnecessaryNonCapturingGroup")
private val regexB by lazy { private val regexB by lazy {
//章节序号,排除处于结尾的状况,避免将章节名替换为空字串 //章节序号,排除处于结尾的状况,避免将章节名替换为空字串
return@lazy "^.*?第(?:[\\d零〇一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+)[章节篇回集话](?!$)|^(?:[\\d零〇一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+[,:、])*(?:[\\d零〇一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+)(?:[,:、](?!$)|\\.(?=[^\\d]))".toRegex() return@lazy "^.*?第(?:[\\d零〇一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+)[章节篇回集话](?!$)|^(?:[\\d零〇一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+[,:、])*(?:[\\d零〇一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+)(?:[,:、](?!$)|\\.(?=[^\\d]))".toRegex()

@ -54,12 +54,14 @@ object CacheBook {
return cacheBook return cacheBook
} }
fun start(context: Context, bookUrl: String, start: Int, end: Int) { fun start(context: Context, book: Book, start: Int, end: Int) {
context.startService<CacheBookService> { if (!book.isLocalBook()) {
action = IntentAction.start context.startService<CacheBookService> {
putExtra("bookUrl", bookUrl) action = IntentAction.start
putExtra("start", start) putExtra("bookUrl", book.bookUrl)
putExtra("end", end) putExtra("start", start)
putExtra("end", end)
}
} }
} }

@ -113,7 +113,7 @@ class CacheActivity : VMBaseActivity<ActivityCacheBookBinding, CacheViewModel>()
adapter.getItems().forEach { book -> adapter.getItems().forEach { book ->
CacheBook.start( CacheBook.start(
this@CacheActivity, this@CacheActivity,
book.bookUrl, book,
book.durChapterIndex, book.durChapterIndex,
book.totalChapterNum book.totalChapterNum
) )

@ -70,10 +70,10 @@ class CacheAdapter(context: Context, private val callBack: CallBack) :
if (it.isRun()) { if (it.isRun()) {
CacheBook.remove(context, book.bookUrl) CacheBook.remove(context, book.bookUrl)
} else { } else {
CacheBook.start(context, book.bookUrl, 0, book.totalChapterNum) CacheBook.start(context, book, 0, book.totalChapterNum)
} }
} ?: let { } ?: let {
CacheBook.start(context, book.bookUrl, 0, book.totalChapterNum) CacheBook.start(context, book, 0, book.totalChapterNum)
} }
} }
} }

@ -231,7 +231,7 @@ abstract class BaseReadBookActivity :
alertBinding.run { alertBinding.run {
val start = editStart.text?.toString()?.toInt() ?: 0 val start = editStart.text?.toString()?.toInt() ?: 0
val end = editEnd.text?.toString()?.toInt() ?: book.totalChapterNum val end = editEnd.text?.toString()?.toInt() ?: book.totalChapterNum
CacheBook.start(this@BaseReadBookActivity, book.bookUrl, start - 1, end - 1) CacheBook.start(this@BaseReadBookActivity, book, start - 1, end - 1)
} }
} }
noButton() noButton()

@ -0,0 +1,103 @@
package io.legado.app.ui.book.read
import android.app.Application
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.viewModels
import io.legado.app.R
import io.legado.app.base.BaseDialogFragment
import io.legado.app.base.BaseViewModel
import io.legado.app.data.appDb
import io.legado.app.databinding.DialogContentEditBinding
import io.legado.app.help.BookHelp
import io.legado.app.help.ContentProcessor
import io.legado.app.lib.theme.primaryColor
import io.legado.app.model.ReadBook
import io.legado.app.model.webBook.WebBook
import io.legado.app.utils.applyTint
import io.legado.app.utils.setLayout
import io.legado.app.utils.viewbindingdelegate.viewBinding
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
/**
* 内容编辑
*/
class ContentEditDialog : BaseDialogFragment(R.layout.dialog_content_edit) {
val binding by viewBinding(DialogContentEditBinding::bind)
val viewModel by viewModels<ContentEditViewModel>()
override fun onStart() {
super.onStart()
setLayout(ViewGroup.LayoutParams.MATCH_PARENT, 0.9f)
}
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
binding.toolBar.setBackgroundColor(primaryColor)
binding.toolBar.title = ReadBook.curTextChapter?.title
initMenu()
viewModel.initContent {
binding.contentView.setText(it)
}
}
private fun initMenu() {
binding.toolBar.inflateMenu(R.menu.content_edit)
binding.toolBar.menu.applyTint(requireContext())
binding.toolBar.setOnMenuItemClickListener {
when (it.itemId) {
R.id.menu_save -> launch {
binding.contentView.text?.toString()?.let { content ->
withContext(IO) {
val book = ReadBook.book ?: return@withContext
val chapter = appDb.bookChapterDao
.getChapter(book.bookUrl, ReadBook.durChapterIndex)
?: return@withContext
BookHelp.saveText(book, chapter, content)
}
}
ReadBook.loadContent(ReadBook.durChapterIndex, resetPageOffset = false)
dismiss()
}
R.id.menu_reset -> viewModel.initContent(true) { content ->
binding.contentView.setText(content)
}
}
return@setOnMenuItemClickListener true
}
}
class ContentEditViewModel(application: Application) : BaseViewModel(application) {
var content: String? = null
fun initContent(reset: Boolean = false, success: (String) -> Unit) {
execute {
val book = ReadBook.book ?: return@execute null
val chapter = appDb.bookChapterDao
.getChapter(book.bookUrl, ReadBook.durChapterIndex)
?: return@execute null
if (reset) {
content = null
BookHelp.delContent(book, chapter)
if (!book.isLocalBook()) ReadBook.bookSource?.let { bookSource ->
WebBook.getContentAwait(this, bookSource, book, chapter)
}
}
return@execute content ?: let {
val contentProcessor = ContentProcessor.get(book.name, book.origin)
val content = BookHelp.getContent(book, chapter) ?: return@let null
contentProcessor.getContent(book, chapter, content, includeTitle = false)
.joinToString("\n")
}
}.onSuccess {
success.invoke(it ?: "")
}
}
}
}

@ -96,24 +96,25 @@ class ReadBookActivity : BaseReadBookActivity(),
viewModel.replaceRuleChanged() viewModel.replaceRuleChanged()
} }
} }
private val searchContentActivity = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { private val searchContentActivity =
it ?: return@registerForActivityResult registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
it.data?.let { data -> it ?: return@registerForActivityResult
val key = data.getLongExtra("key", System.currentTimeMillis()) it.data?.let { data ->
val searchResult = IntentData.get<SearchResult>("searchResult$key") val key = data.getLongExtra("key", System.currentTimeMillis())
val searchResultList = IntentData.get<List<SearchResult>>("searchResultList$key") val searchResult = IntentData.get<SearchResult>("searchResult$key")
if (searchResult != null && searchResultList != null) { val searchResultList = IntentData.get<List<SearchResult>>("searchResultList$key")
viewModel.searchContentQuery = searchResult.query if (searchResult != null && searchResultList != null) {
binding.searchMenu.upSearchResultList(searchResultList) viewModel.searchContentQuery = searchResult.query
isShowingSearchResult = true binding.searchMenu.upSearchResultList(searchResultList)
binding.searchMenu.updateSearchResultIndex(searchResultList.indexOf(searchResult)) isShowingSearchResult = true
binding.searchMenu.selectedSearchResult?.let { currentResult -> binding.searchMenu.updateSearchResultIndex(searchResultList.indexOf(searchResult))
skipToSearch(currentResult) binding.searchMenu.selectedSearchResult?.let { currentResult ->
showActionMenu() skipToSearch(currentResult)
showActionMenu()
}
} }
} }
} }
}
private var menu: Menu? = null private var menu: Menu? = null
val textActionMenu: TextActionMenu by lazy { val textActionMenu: TextActionMenu by lazy {
TextActionMenu(this, this) TextActionMenu(this, this)
@ -288,9 +289,7 @@ class ReadBookActivity : BaseReadBookActivity(),
showDialogFragment(BookmarkDialog(bookmark)) showDialogFragment(BookmarkDialog(bookmark))
} }
} }
R.id.menu_copy_text -> showDialogFragment( R.id.menu_edit_content -> showDialogFragment(ContentEditDialog())
TextDialog(ReadBook.curTextChapter?.getContent())
)
R.id.menu_update_toc -> ReadBook.book?.let { R.id.menu_update_toc -> ReadBook.book?.let {
if (it.isEpub()) { if (it.isEpub()) {
BookHelp.clearCache(it) BookHelp.clearCache(it)
@ -945,7 +944,7 @@ class ReadBookActivity : BaseReadBookActivity(),
private fun skipToSearch(searchResult: SearchResult) { private fun skipToSearch(searchResult: SearchResult) {
val previousResult = binding.searchMenu.previousSearchResult val previousResult = binding.searchMenu.previousSearchResult
fun jumpToPosition(){ fun jumpToPosition() {
ReadBook.curTextChapter?.let { ReadBook.curTextChapter?.let {
binding.searchMenu.updateSearchInfo() binding.searchMenu.updateSearchInfo()
val positions = viewModel.searchResultPositions(it, searchResult) val positions = viewModel.searchResultPositions(it, searchResult)
@ -954,10 +953,12 @@ class ReadBookActivity : BaseReadBookActivity(),
isSelectingSearchResult = true isSelectingSearchResult = true
binding.readView.curPage.selectStartMoveIndex(0, positions[1], positions[2]) binding.readView.curPage.selectStartMoveIndex(0, positions[1], positions[2])
when (positions[3]) { when (positions[3]) {
0 -> binding.readView.curPage.selectEndMoveIndex( 0 -> binding.readView.curPage.selectEndMoveIndex(
0, positions[1], positions[2] + viewModel.searchContentQuery.length - 1 0,
positions[1],
positions[2] + viewModel.searchContentQuery.length - 1
) )
1 -> binding.readView.curPage.selectEndMoveIndex( 1 -> binding.readView.curPage.selectEndMoveIndex(
0, positions[1] + 1, positions[4] 0, positions[1] + 1, positions[4]
) )
//consider change page, jump to scroll position //consider change page, jump to scroll position

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@color/background"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="@+id/tool_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="?attr/actionBarStyle"
app:title="code edit"
app:popupTheme="@style/AppTheme.PopupOverlay"
app:titleTextAppearance="@style/ToolbarTitle" />
<io.legado.app.lib.theme.view.ThemeEditText
android:id="@+id/content_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="12dp"
android:textIsSelectable="true" />
</LinearLayout>

@ -71,8 +71,8 @@
app:showAsAction="never" /> app:showAsAction="never" />
<item <item
android:id="@+id/menu_copy_text" android:id="@+id/menu_edit_content"
android:title="@string/copy_text" android:title="@string/edit_content"
app:showAsAction="never" /> app:showAsAction="never" />
<item <item

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="AlwaysShowAction">
<item
android:id="@+id/menu_save"
android:icon="@drawable/ic_save"
android:title="@string/action_save"
app:showAsAction="always" />
<item
android:id="@+id/menu_reset"
android:title="@string/reset"
app:showAsAction="never" />
</menu>

@ -938,5 +938,6 @@
<string name="menu_refresh_dur">刷新当前章节</string> <string name="menu_refresh_dur">刷新当前章节</string>
<string name="menu_refresh_after">刷新之后章节</string> <string name="menu_refresh_after">刷新之后章节</string>
<string name="menu_refresh_all">刷新全部章节</string> <string name="menu_refresh_all">刷新全部章节</string>
<string name="edit_content">编辑内容</string>
<!-- string end --> <!-- string end -->
</resources> </resources>

@ -941,5 +941,6 @@
<string name="menu_refresh_dur">刷新当前章节</string> <string name="menu_refresh_dur">刷新当前章节</string>
<string name="menu_refresh_after">刷新之后章节</string> <string name="menu_refresh_after">刷新之后章节</string>
<string name="menu_refresh_all">刷新全部章节</string> <string name="menu_refresh_all">刷新全部章节</string>
<string name="edit_content">编辑内容</string>
<!-- string end --> <!-- string end -->
</resources> </resources>

@ -941,5 +941,6 @@
<string name="menu_refresh_dur">刷新当前章节</string> <string name="menu_refresh_dur">刷新当前章节</string>
<string name="menu_refresh_after">刷新之后章节</string> <string name="menu_refresh_after">刷新之后章节</string>
<string name="menu_refresh_all">刷新全部章节</string> <string name="menu_refresh_all">刷新全部章节</string>
<string name="edit_content">编辑内容</string>
<!-- string end --> <!-- string end -->
</resources> </resources>

@ -938,5 +938,6 @@
<string name="menu_refresh_dur">刷新当前章节</string> <string name="menu_refresh_dur">刷新当前章节</string>
<string name="menu_refresh_after">刷新之后章节</string> <string name="menu_refresh_after">刷新之后章节</string>
<string name="menu_refresh_all">刷新全部章节</string> <string name="menu_refresh_all">刷新全部章节</string>
<string name="edit_content">编辑内容</string>
<!-- string end --> <!-- string end -->
</resources> </resources>

@ -940,5 +940,6 @@
<string name="menu_refresh_dur">刷新当前章节</string> <string name="menu_refresh_dur">刷新当前章节</string>
<string name="menu_refresh_after">刷新之后章节</string> <string name="menu_refresh_after">刷新之后章节</string>
<string name="menu_refresh_all">刷新全部章节</string> <string name="menu_refresh_all">刷新全部章节</string>
<string name="edit_content">编辑内容</string>
<!-- string end --> <!-- string end -->
</resources> </resources>

@ -940,5 +940,6 @@
<string name="menu_refresh_dur">刷新当前章节</string> <string name="menu_refresh_dur">刷新当前章节</string>
<string name="menu_refresh_after">刷新之后章节</string> <string name="menu_refresh_after">刷新之后章节</string>
<string name="menu_refresh_all">刷新全部章节</string> <string name="menu_refresh_all">刷新全部章节</string>
<string name="edit_content">编辑内容</string>
<!-- string end --> <!-- string end -->
</resources> </resources>

@ -941,5 +941,6 @@
<string name="menu_refresh_dur">刷新当前章节</string> <string name="menu_refresh_dur">刷新当前章节</string>
<string name="menu_refresh_after">刷新之后章节</string> <string name="menu_refresh_after">刷新之后章节</string>
<string name="menu_refresh_all">刷新全部章节</string> <string name="menu_refresh_all">刷新全部章节</string>
<string name="edit_content">编辑内容</string>
<!-- string end --> <!-- string end -->
</resources> </resources>

Loading…
Cancel
Save