kunfei 4 سال پیش
والد
کامیت
81690565d7

+ 16 - 18
app/src/main/java/io/legado/app/help/BookHelp.kt

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

+ 8 - 6
app/src/main/java/io/legado/app/model/CacheBook.kt

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

+ 1 - 1
app/src/main/java/io/legado/app/ui/book/cache/CacheActivity.kt

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

+ 2 - 2
app/src/main/java/io/legado/app/ui/book/cache/CacheAdapter.kt

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

+ 1 - 1
app/src/main/java/io/legado/app/ui/book/read/BaseReadBookActivity.kt

@@ -231,7 +231,7 @@ abstract class BaseReadBookActivity :
                     alertBinding.run {
                         val start = editStart.text?.toString()?.toInt() ?: 0
                         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()

+ 103 - 0
app/src/main/java/io/legado/app/ui/book/read/ContentEditDialog.kt

@@ -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 ?: "")
+            }
+        }
+
+    }
+
+}

+ 23 - 22
app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt

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

+ 25 - 0
app/src/main/res/layout/dialog_content_edit.xml

@@ -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>

+ 2 - 2
app/src/main/res/menu/book_read.xml

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

+ 18 - 0
app/src/main/res/menu/content_edit.xml

@@ -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>

+ 1 - 0
app/src/main/res/values-es-rES/strings.xml

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

+ 1 - 0
app/src/main/res/values-ja-rJP/strings.xml

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

+ 1 - 0
app/src/main/res/values-pt-rBR/strings.xml

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

+ 1 - 0
app/src/main/res/values-zh-rHK/strings.xml

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

+ 1 - 0
app/src/main/res/values-zh-rTW/strings.xml

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

+ 1 - 0
app/src/main/res/values-zh/strings.xml

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

+ 1 - 0
app/src/main/res/values/strings.xml

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