章节增加字数统计字段,网络书籍增加字数统计 (#4437)

This commit is contained in:
niuhb
2024-12-15 16:20:44 +08:00
committed by GitHub
parent e784e22c5c
commit 4865a72409
8 changed files with 1977 additions and 20 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -63,7 +63,7 @@ val appDb by lazy {
}
@Database(
version = 72,
version = 73,
exportSchema = true,
entities = [Book::class, BookGroup::class, BookSource::class, BookChapter::class,
ReplaceRule::class, SearchBook::class, SearchKeyword::class, Cookie::class,
@@ -100,6 +100,7 @@ val appDb by lazy {
AutoMigration(from = 69, to = 70),
AutoMigration(from = 70, to = 71),
AutoMigration(from = 71, to = 72),
AutoMigration(from = 72, to = 73),
]
)
abstract class AppDatabase : RoomDatabase() {

View File

@@ -51,6 +51,7 @@ data class BookChapter(
var isPay: Boolean = false, // 是否已购买
var resourceUrl: String? = null, // 音频真实URL
var tag: String? = null, // 更新时间或其他章节附加信息
var wordCount: String? = null, // 本章节字数
var start: Long? = null, // 章节起始位置
var end: Long? = null, // 章节终止位置
var startFragmentId: String? = null, //EPUB书籍当前章节的fragmentId

View File

@@ -148,6 +148,8 @@ object BookHelp {
book.getFolderName(),
bookChapter.getFileName(),
).writeText(content)
bookChapter.wordCount = StringUtils.wordCountFormat(content.length)
appDb.bookChapterDao.update(bookChapter)
}
suspend fun saveImages(

View File

@@ -142,7 +142,7 @@ class TextFile(private var book: Book) {
* 按规则解析目录
*/
private fun analyze(pattern: Pattern?): Pair<ArrayList<BookChapter>, Int> {
if (pattern?.pattern().isNullOrEmpty()) {
if (pattern == null || pattern.pattern().isNullOrEmpty()) {
return analyze()
}
val toc = arrayListOf<BookChapter>()
@@ -227,7 +227,7 @@ class TextFile(private var book: Book) {
qyChapter.title = "前言"
qyChapter.start = curOffset
qyChapter.end = curOffset + chapterLength
qyChapter.tag = StringUtils.wordCountFormat(chapterContent.length)
qyChapter.wordCount = StringUtils.wordCountFormat(chapterContent.length)
toc.add(qyChapter)
book.intro = if (chapterContent.length <= 500) {
chapterContent
@@ -248,7 +248,7 @@ class TextFile(private var book: Book) {
//将当前段落添加上一章去
lastChapter.end = lastChapter.end!! + chapterLength
lastChapterWordCount += chapterContent.length
lastChapter.tag = StringUtils.wordCountFormat(lastChapterWordCount)
lastChapter.wordCount = StringUtils.wordCountFormat(lastChapterWordCount)
//创建当前章节
val curChapter = BookChapter()
curChapter.title = matcher.group()
@@ -265,7 +265,7 @@ class TextFile(private var book: Book) {
chapterContent.substringAfter(lastChapter.title).isBlank()
lastChapter.end =
lastChapter.start!! + chapterLength
lastChapter.tag = StringUtils.wordCountFormat(chapterContent.length)
lastChapter.wordCount = StringUtils.wordCountFormat(chapterContent.length)
//创建当前章节
val curChapter = BookChapter()
curChapter.title = matcher.group()
@@ -276,7 +276,7 @@ class TextFile(private var book: Book) {
curChapter.title = matcher.group()
curChapter.start = curOffset
curChapter.end = curOffset
curChapter.tag = StringUtils.wordCountFormat(chapterContent.length)
curChapter.wordCount = StringUtils.wordCountFormat(chapterContent.length)
toc.add(curChapter)
}
bookWordCount += chapterContent.length
@@ -293,7 +293,7 @@ class TextFile(private var book: Book) {
//设置上一章的结尾
toc.lastOrNull()?.let {
it.end = curOffset
it.tag = StringUtils.wordCountFormat(lastChapterWordCount)
it.wordCount = StringUtils.wordCountFormat(lastChapterWordCount)
}
}
toc.lastOrNull()?.let { chapter ->
@@ -383,7 +383,7 @@ class TextFile(private var book: Book) {
chapter.title = "${blockPos}章($chapterPos)"
chapter.start = toc.lastOrNull()?.end ?: curOffset
chapter.end = chapter.start!! + end - chapterOffset
chapter.tag = StringUtils.wordCountFormat(content.length)
chapter.wordCount = StringUtils.wordCountFormat(content.length)
toc.add(chapter)
//减去已经被分配的长度
strLength -= (end - chapterOffset)
@@ -407,13 +407,13 @@ class TextFile(private var book: Book) {
chapter.title = "${blockPos}章(${chapterPos})"
chapter.start = toc.lastOrNull()?.end ?: curOffset
chapter.end = chapter.start!! + bufferStart
chapter.tag = StringUtils.wordCountFormat(content.length)
chapter.wordCount = StringUtils.wordCountFormat(content.length)
toc.add(chapter)
} else {
val wordCount = lastChapterWordCount + content.length
toc.lastOrNull()?.let {
it.end = it.end!! + bufferStart
it.tag = StringUtils.wordCountFormat(wordCount)
it.wordCount = StringUtils.wordCountFormat(wordCount)
}
}
}

View File

@@ -4,6 +4,7 @@ import android.text.TextUtils
import com.script.ScriptBindings
import com.script.rhino.RhinoScriptEngine
import io.legado.app.R
import io.legado.app.data.appDb
import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookChapter
import io.legado.app.data.entities.BookSource
@@ -162,6 +163,7 @@ object BookChapterList {
list.getOrElse(book.simulatedTotalChapterNum() - 1) { list.last() }
.getDisplayTitle(replaceRules, book.getUseReplaceRule())
coroutineContext.ensureActive()
getWordCount(list, book)
return list
}
@@ -267,4 +269,17 @@ object BookChapterList {
return Pair(chapterList, nextUrlList)
}
private fun getWordCount(list: ArrayList<BookChapter>, book: Book) {
val chapterList = appDb.bookChapterDao.getChapterList(book.bookUrl)
if (chapterList.isNotEmpty()){
val map = chapterList.associateBy({ it.getFileName() }, { it.wordCount })
for (bookChapter in list) {
val wordCount = map[bookChapter.getFileName()]
if(wordCount != null){
bookChapter.wordCount = wordCount
}
}
}
}
}

View File

@@ -138,13 +138,22 @@ class ChapterListAdapter(context: Context, val callback: Callback) :
//普通章节 保持不变
tvChapterItem.background =
ThemeUtils.resolveDrawable(context, android.R.attr.selectableItemBackground)
}
if (!item.tag.isNullOrEmpty() && !item.isVolume) {
//卷名不显示tag(更新时间规则)
tvTag.text = item.tag
tvTag.visible()
} else {
tvTag.gone()
//卷名不显示
if (!item.tag.isNullOrEmpty()) {
//更新时间规则
tvTag.text = item.tag
tvTag.visible()
} else {
tvTag.gone()
}
if (!item.wordCount.isNullOrEmpty()) {
//章节字数
tvWordCount.text = item.wordCount
tvWordCount.visible()
} else {
tvWordCount.gone()
}
}
upHasCache(binding, isDur, cached)
} else {

View File

@@ -15,8 +15,19 @@
android:singleLine="true"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/iv_checked"
app:layout_constraintBottom_toTopOf="@id/tv_tag" />
app:layout_constraintRight_toLeftOf="@+id/iv_checked" />
<TextView
android:id="@+id/tv_word_count"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="12sp"
android:visibility="gone"
android:singleLine="true"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_chapter_name"
app:layout_constraintRight_toLeftOf="@+id/tv_tag" />
<TextView
android:id="@+id/tv_tag"
@@ -27,7 +38,7 @@
android:singleLine="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_chapter_name"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintLeft_toRightOf="@id/tv_word_count"
app:layout_constraintRight_toLeftOf="@+id/iv_checked" />
<ImageView