mirror of
https://github.com/gedoor/legado.git
synced 2024-07-06 23:47:49 +08:00
优化
This commit is contained in:
parent
73dc85efee
commit
8f07d73bb1
@ -2,7 +2,11 @@ package io.legado.app.model
|
||||
|
||||
import io.legado.app.constant.AppLog
|
||||
import io.legado.app.data.appDb
|
||||
import io.legado.app.data.entities.*
|
||||
import io.legado.app.data.entities.Book
|
||||
import io.legado.app.data.entities.BookChapter
|
||||
import io.legado.app.data.entities.BookProgress
|
||||
import io.legado.app.data.entities.BookSource
|
||||
import io.legado.app.data.entities.ReadRecord
|
||||
import io.legado.app.help.AppWebDav
|
||||
import io.legado.app.help.book.BookHelp
|
||||
import io.legado.app.help.book.ContentProcessor
|
||||
@ -88,7 +92,7 @@ object ReadBook : CoroutineScope by MainScope() {
|
||||
upWebBook(book)
|
||||
lastBookPress = null
|
||||
webBookProgress = null
|
||||
TextFile.txtBuffer = null
|
||||
TextFile.clear()
|
||||
synchronized(this) {
|
||||
loadingChapters.clear()
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ object LocalBook {
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
@Throws(TocEmptyException::class)
|
||||
fun getChapterList(book: Book): ArrayList<BookChapter> {
|
||||
val chapters = when {
|
||||
book.isEpub -> {
|
||||
|
@ -16,56 +16,37 @@ import java.util.regex.Matcher
|
||||
import java.util.regex.Pattern
|
||||
import kotlin.math.min
|
||||
|
||||
class TextFile(private val book: Book) {
|
||||
class TextFile(private var book: Book) {
|
||||
|
||||
@Suppress("ConstPropertyName")
|
||||
companion object {
|
||||
private val padRegex = "^[\\n\\s]+".toRegex()
|
||||
private const val bufferSize = 8 * 1024 * 1024
|
||||
private var bufferStart = -1
|
||||
private var bufferEnd = -1
|
||||
var txtBuffer: ByteArray? = null
|
||||
var bookUrl = ""
|
||||
private const val txtBufferSize = 8 * 1024 * 1024
|
||||
private var textFile: TextFile? = null
|
||||
|
||||
@Synchronized
|
||||
private fun getTextFile(book: Book): TextFile {
|
||||
if (textFile == null || textFile?.book?.bookUrl != book.bookUrl) {
|
||||
textFile = TextFile(book)
|
||||
return textFile!!
|
||||
}
|
||||
textFile?.book = book
|
||||
return textFile!!
|
||||
}
|
||||
|
||||
@Throws(FileNotFoundException::class)
|
||||
fun getChapterList(book: Book): ArrayList<BookChapter> {
|
||||
return TextFile(book).getChapterList()
|
||||
return getTextFile(book).getChapterList()
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
@Throws(FileNotFoundException::class)
|
||||
fun getContent(book: Book, bookChapter: BookChapter): String {
|
||||
if (txtBuffer == null || bookUrl != book.bookUrl || bookChapter.start!! > bufferEnd || bookChapter.end!! < bufferStart) {
|
||||
bookUrl = book.bookUrl
|
||||
LocalBook.getBookInputStream(book).use { bis ->
|
||||
bufferStart = bufferSize * (bookChapter.start!! / bufferSize).toInt()
|
||||
txtBuffer = ByteArray(min(bufferSize, bis.available() - bufferStart))
|
||||
bufferEnd = bufferStart + txtBuffer!!.size
|
||||
bis.skip(bufferStart.toLong())
|
||||
bis.read(txtBuffer)
|
||||
}
|
||||
}
|
||||
return getTextFile(book).getContent(bookChapter)
|
||||
}
|
||||
|
||||
val count = (bookChapter.end!! - bookChapter.start!!).toInt()
|
||||
val buffer = ByteArray(count)
|
||||
|
||||
if (bookChapter.start!! < bufferEnd && bookChapter.end!! > bufferEnd || bookChapter.start!! < bufferStart && bookChapter.end!! > bufferStart) {
|
||||
/** 章节内容在缓冲区交界处 */
|
||||
LocalBook.getBookInputStream(book).use { bis ->
|
||||
bis.skip(bookChapter.start!!)
|
||||
bis.read(buffer)
|
||||
}
|
||||
} else {
|
||||
/** 章节内容在缓冲区内 */
|
||||
txtBuffer!!.copyInto(
|
||||
buffer,
|
||||
0,
|
||||
(bookChapter.start!! - bufferStart).toInt(),
|
||||
(bookChapter.end!! - bufferStart).toInt()
|
||||
)
|
||||
}
|
||||
|
||||
return String(buffer, book.fileCharset()).substringAfter(bookChapter.title)
|
||||
.replace(padRegex, " ")
|
||||
fun clear() {
|
||||
textFile = null
|
||||
}
|
||||
|
||||
}
|
||||
@ -83,10 +64,14 @@ class TextFile(private val book: Book) {
|
||||
|
||||
private var charset: Charset = book.fileCharset()
|
||||
|
||||
private var txtBuffer: ByteArray? = null
|
||||
private var bufferStart = -1L
|
||||
private var bufferEnd = -1L
|
||||
|
||||
/**
|
||||
* 获取目录
|
||||
*/
|
||||
@Throws(FileNotFoundException::class)
|
||||
@Throws(FileNotFoundException::class, SecurityException::class, EmptyFileException::class)
|
||||
fun getChapterList(): ArrayList<BookChapter> {
|
||||
if (book.charset == null || book.tocUrl.isBlank()) {
|
||||
LocalBook.getBookInputStream(book).use { bis ->
|
||||
@ -112,6 +97,43 @@ class TextFile(private val book: Book) {
|
||||
return toc
|
||||
}
|
||||
|
||||
fun getContent(chapter: BookChapter): String {
|
||||
val start = chapter.start!!
|
||||
val end = chapter.end!!
|
||||
if (txtBuffer == null || start > bufferEnd || end < bufferStart) {
|
||||
LocalBook.getBookInputStream(book).use { bis ->
|
||||
bufferStart = txtBufferSize * (start / txtBufferSize)
|
||||
txtBuffer = ByteArray(min(txtBufferSize, bis.available() - bufferStart.toInt()))
|
||||
bufferEnd = bufferStart + txtBuffer!!.size
|
||||
bis.skip(bufferStart)
|
||||
bis.read(txtBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
val count = (end - start).toInt()
|
||||
val buffer = ByteArray(count)
|
||||
|
||||
if (bufferEnd in start..end || bufferStart in start..end) {
|
||||
/** 章节内容在缓冲区交界处 */
|
||||
LocalBook.getBookInputStream(book).use { bis ->
|
||||
bis.skip(start)
|
||||
bis.read(buffer)
|
||||
}
|
||||
} else {
|
||||
/** 章节内容在缓冲区内 */
|
||||
txtBuffer!!.copyInto(
|
||||
buffer,
|
||||
0,
|
||||
(start - bufferStart).toInt(),
|
||||
(end - bufferStart).toInt()
|
||||
)
|
||||
}
|
||||
|
||||
return String(buffer, charset)
|
||||
.substringAfter(chapter.title)
|
||||
.replace(padRegex, " ")
|
||||
}
|
||||
|
||||
/**
|
||||
* 按规则解析目录
|
||||
*/
|
||||
@ -162,7 +184,7 @@ class TextFile(private val book: Book) {
|
||||
val chapterStart = matcher.start()
|
||||
//获取章节内容
|
||||
val chapterContent = blockContent.substring(seekPos, chapterStart)
|
||||
val chapterLength = chapterContent.toByteArray(charset).size
|
||||
val chapterLength = chapterContent.toByteArray(charset).size.toLong()
|
||||
val lastStart = toc.lastOrNull()?.start ?: curOffset
|
||||
if (book.getSplitLongChapter() && curOffset + chapterLength - lastStart > maxLengthWithToc) {
|
||||
toc.lastOrNull()?.let {
|
||||
@ -186,7 +208,7 @@ class TextFile(private val book: Book) {
|
||||
curChapter.start = curOffset + chapterLength
|
||||
toc.add(curChapter)
|
||||
} else if (seekPos == 0 && chapterStart != 0) {
|
||||
/*
|
||||
/**
|
||||
* 如果 seekPos == 0 && chapterStart != 0 表示当前block处前面有一段内容
|
||||
* 第一种情况一定是序章 第二种情况是上一个章节的内容
|
||||
*/
|
||||
@ -196,13 +218,18 @@ class TextFile(private val book: Book) {
|
||||
val qyChapter = BookChapter()
|
||||
qyChapter.title = "前言"
|
||||
qyChapter.start = curOffset
|
||||
qyChapter.end = curOffset + chapterLength.toLong()
|
||||
qyChapter.end = curOffset + chapterLength
|
||||
toc.add(qyChapter)
|
||||
book.intro = if (chapterContent.length <= 500) {
|
||||
chapterContent
|
||||
} else {
|
||||
chapterContent.substring(0, 500)
|
||||
}
|
||||
}
|
||||
//创建当前章节
|
||||
val curChapter = BookChapter()
|
||||
curChapter.title = matcher.group()
|
||||
curChapter.start = curOffset + chapterLength.toLong()
|
||||
curChapter.start = curOffset + chapterLength
|
||||
toc.add(curChapter)
|
||||
} else { //否则就block分割之后,上一个章节的剩余内容
|
||||
//获取上一章节
|
||||
@ -210,7 +237,7 @@ class TextFile(private val book: Book) {
|
||||
lastChapter.isVolume =
|
||||
chapterContent.substringAfter(lastChapter.title).isBlank()
|
||||
//将当前段落添加上一章去
|
||||
lastChapter.end = lastChapter.end!! + chapterLength.toLong()
|
||||
lastChapter.end = lastChapter.end!! + chapterLength
|
||||
//创建当前章节
|
||||
val curChapter = BookChapter()
|
||||
curChapter.title = matcher.group()
|
||||
@ -224,7 +251,7 @@ class TextFile(private val book: Book) {
|
||||
lastChapter.isVolume =
|
||||
chapterContent.substringAfter(lastChapter.title).isBlank()
|
||||
lastChapter.end =
|
||||
lastChapter.start!! + chapterContent.toByteArray(charset).size.toLong()
|
||||
lastChapter.start!! + chapterLength
|
||||
//创建当前章节
|
||||
val curChapter = BookChapter()
|
||||
curChapter.title = matcher.group()
|
||||
|
@ -1,45 +1,27 @@
|
||||
package io.legado.app.ui.book.explore
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import androidx.activity.viewModels
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import io.legado.app.R
|
||||
import io.legado.app.base.VMBaseActivity
|
||||
import io.legado.app.constant.AppLog
|
||||
import io.legado.app.data.appDb
|
||||
import io.legado.app.data.entities.Book
|
||||
import io.legado.app.data.entities.SearchBook
|
||||
import io.legado.app.databinding.ActivityExploreShowBinding
|
||||
import io.legado.app.databinding.DialogPageChoiceBinding
|
||||
import io.legado.app.databinding.ViewLoadMoreBinding
|
||||
import io.legado.app.help.coroutine.Coroutine
|
||||
import io.legado.app.lib.dialogs.alert
|
||||
import io.legado.app.lib.theme.backgroundColor
|
||||
import io.legado.app.model.webBook.WebBook
|
||||
import io.legado.app.ui.book.group.GroupSelectDialog
|
||||
import io.legado.app.ui.book.info.BookInfoActivity
|
||||
import io.legado.app.ui.widget.dialog.WaitDialog
|
||||
import io.legado.app.ui.widget.recycler.LoadMoreView
|
||||
import io.legado.app.ui.widget.recycler.VerticalDivider
|
||||
import io.legado.app.utils.showDialogFragment
|
||||
import io.legado.app.utils.startActivity
|
||||
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||
import kotlinx.coroutines.Dispatchers.Main
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class ExploreShowActivity : VMBaseActivity<ActivityExploreShowBinding, ExploreShowViewModel>(),
|
||||
ExploreShowAdapter.CallBack,
|
||||
GroupSelectDialog.CallBack {
|
||||
ExploreShowAdapter.CallBack {
|
||||
override val binding by viewBinding(ActivityExploreShowBinding::inflate)
|
||||
override val viewModel by viewModels<ExploreShowViewModel>()
|
||||
|
||||
private val adapter by lazy { ExploreShowAdapter(this, this) }
|
||||
private val loadMoreView by lazy { LoadMoreView(this) }
|
||||
private val waitDialog by lazy {
|
||||
WaitDialog(this)
|
||||
}
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
binding.titleBar.title = intent.getStringExtra("exploreName")
|
||||
@ -116,84 +98,4 @@ class ExploreShowActivity : VMBaseActivity<ActivityExploreShowBinding, ExploreSh
|
||||
putExtra("bookUrl", book.bookUrl)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCompatCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.explore_show, menu)
|
||||
return super.onCompatCreateOptionsMenu(menu)
|
||||
}
|
||||
|
||||
override fun onCompatOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.menu_add_all_to_bookshelf -> addAllToBookshelf()
|
||||
}
|
||||
return super.onCompatOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
private fun addAllToBookshelf() {
|
||||
showDialogFragment(GroupSelectDialog(0))
|
||||
}
|
||||
|
||||
override fun upGroup(requestCode: Int, groupId: Long) {
|
||||
|
||||
alert("选择页数范围") {
|
||||
val alertBinding = DialogPageChoiceBinding.inflate(layoutInflater).apply {
|
||||
root.setBackgroundColor(root.context.backgroundColor)
|
||||
}
|
||||
customView { alertBinding.root }
|
||||
yesButton {
|
||||
alertBinding.run {
|
||||
val start = editStart.text
|
||||
.runCatching {
|
||||
toString().toInt()
|
||||
}.getOrDefault(1)
|
||||
val end = editEnd.text
|
||||
.runCatching {
|
||||
toString().toInt()
|
||||
}.getOrDefault(9)
|
||||
addAllToBookshelf(start, end, groupId)
|
||||
}
|
||||
}
|
||||
noButton()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun addAllToBookshelf(start: Int, end: Int, groupId: Long) {
|
||||
val job = Coroutine.async {
|
||||
launch(Main) {
|
||||
waitDialog.setText("加载列表中...")
|
||||
waitDialog.show()
|
||||
}
|
||||
val searchBooks = viewModel.loadExploreBooks(start, end)
|
||||
val books = searchBooks.map {
|
||||
it.toBook()
|
||||
}
|
||||
launch(Main) {
|
||||
waitDialog.setText("添加书架中...")
|
||||
}
|
||||
books.forEach {
|
||||
appDb.bookDao.getBook(it.bookUrl)?.let { book ->
|
||||
book.group = book.group or groupId
|
||||
it.order = appDb.bookDao.minOrder - 1
|
||||
book.save()
|
||||
return@forEach
|
||||
}
|
||||
if (it.tocUrl.isEmpty()) {
|
||||
val source = appDb.bookSourceDao.getBookSource(it.origin)!!
|
||||
WebBook.getBookInfoAwait(source, it)
|
||||
}
|
||||
it.order = appDb.bookDao.minOrder - 1
|
||||
it.group = groupId
|
||||
it.save()
|
||||
}
|
||||
}.onError {
|
||||
AppLog.put("添加书架出错\n${it.localizedMessage}", it)
|
||||
}.onFinally {
|
||||
waitDialog.dismiss()
|
||||
}
|
||||
waitDialog.setOnCancelListener {
|
||||
job.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -70,18 +70,4 @@ class ExploreShowViewModel(application: Application) : BaseViewModel(application
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun loadExploreBooks(start: Int, end: Int): List<SearchBook> {
|
||||
val source = bookSource
|
||||
val url = exploreUrl
|
||||
if (source == null || url == null) return emptyList()
|
||||
val searchBooks = arrayListOf<SearchBook>()
|
||||
for (page in start..end) {
|
||||
val books = WebBook.exploreBookAwait(source, url, page)
|
||||
if (books.isEmpty()) break
|
||||
searchBooks.addAll(books)
|
||||
}
|
||||
searchBooks.reverse()
|
||||
return searchBooks
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,74 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/ll_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/background"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/edit_start"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:background="@drawable/bg_edit"
|
||||
android:hint="@string/start"
|
||||
android:importantForAutofill="no"
|
||||
android:inputType="number"
|
||||
android:lines="1"
|
||||
android:maxLength="5"
|
||||
android:minWidth="60dp"
|
||||
android:paddingLeft="5dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingRight="5dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:textColor="@color/primaryText"
|
||||
android:textCursorDrawable="@drawable/shape_text_cursor"
|
||||
android:textSize="14sp"
|
||||
tools:ignore="TouchTargetSizeCheck,TextContrastCheck" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginRight="5dp"
|
||||
android:text="@string/page_to"
|
||||
android:textColor="@color/primaryText"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/edit_end"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:background="@drawable/bg_edit"
|
||||
android:hint="@string/end"
|
||||
android:importantForAutofill="no"
|
||||
android:inputType="number"
|
||||
android:lines="1"
|
||||
android:maxLength="5"
|
||||
android:minWidth="60dp"
|
||||
android:paddingLeft="5dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingRight="5dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:textColor="@color/primaryText"
|
||||
android:textCursorDrawable="@drawable/shape_text_cursor"
|
||||
android:textSize="14sp"
|
||||
tools:ignore="TouchTargetSizeCheck,SpeakableTextPresentCheck,TextContrastCheck" />
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
</LinearLayout>
|
@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_add_all_to_bookshelf"
|
||||
android:title="@string/add_all_to_bookshelf" />
|
||||
|
||||
</menu>
|
@ -1117,8 +1117,6 @@
|
||||
<string name="test">测试</string>
|
||||
<string name="show_wait_up_count">显示等待更新数量</string>
|
||||
<string name="exit_app">退出软件</string>
|
||||
<string name="add_all_to_bookshelf">全部加入书架</string>
|
||||
<string name="page_to">页至</string>
|
||||
<string name="result_analyzed">Analyzed</string>
|
||||
<string name="bookshelf_px_4">Comprehensive</string>
|
||||
<string name="effective_replaces">起效的替换</string>
|
||||
|
@ -1120,8 +1120,6 @@
|
||||
<string name="test">测试</string>
|
||||
<string name="show_wait_up_count">显示等待更新数量</string>
|
||||
<string name="exit_app">退出软件</string>
|
||||
<string name="add_all_to_bookshelf">全部加入书架</string>
|
||||
<string name="page_to">页至</string>
|
||||
<string name="result_analyzed">Analyzed</string>
|
||||
<string name="bookshelf_px_4">Comprehensive</string>
|
||||
<string name="effective_replaces">起效的替换</string>
|
||||
|
@ -1120,8 +1120,6 @@
|
||||
<string name="test">测试</string>
|
||||
<string name="show_wait_up_count">显示等待更新数量</string>
|
||||
<string name="exit_app">退出软件</string>
|
||||
<string name="add_all_to_bookshelf">全部加入书架</string>
|
||||
<string name="page_to">页至</string>
|
||||
<string name="result_analyzed">Analyzed</string>
|
||||
<string name="bookshelf_px_4">Comprehensive</string>
|
||||
<string name="effective_replaces">起效的替换</string>
|
||||
|
@ -1116,8 +1116,6 @@ Còn </string>
|
||||
<string name="test">Kiểm tra</string>
|
||||
<string name="show_wait_up_count">Hiển thị số bản cập nhật đang đợi</string>
|
||||
<string name="exit_app">Thoát khỏi phần mềm</string>
|
||||
<string name="add_all_to_bookshelf">Thêm tất cả vào giá sách</string>
|
||||
<string name="page_to">Trang tới</string>
|
||||
<string name="result_analyzed">Analyzed</string>
|
||||
<string name="bookshelf_px_4">Comprehensive</string>
|
||||
<string name="effective_replaces">起效的替换</string>
|
||||
|
@ -1117,8 +1117,6 @@
|
||||
<string name="test">测试</string>
|
||||
<string name="show_wait_up_count">显示等待更新数量</string>
|
||||
<string name="exit_app">退出软件</string>
|
||||
<string name="add_all_to_bookshelf">全部加入书架</string>
|
||||
<string name="page_to">页至</string>
|
||||
<string name="result_analyzed">解析示例</string>
|
||||
<string name="bookshelf_px_4">綜合排序</string>
|
||||
<string name="effective_replaces">起效的替换</string>
|
||||
|
@ -1119,8 +1119,6 @@
|
||||
<string name="test">测试</string>
|
||||
<string name="show_wait_up_count">显示等待更新数量</string>
|
||||
<string name="exit_app">退出软件</string>
|
||||
<string name="add_all_to_bookshelf">全部加入书架</string>
|
||||
<string name="page_to">页至</string>
|
||||
<string name="result_analyzed">解析示例</string>
|
||||
<string name="bookshelf_px_4">綜合排序</string>
|
||||
<string name="effective_replaces">起效的替换</string>
|
||||
|
@ -1119,8 +1119,6 @@
|
||||
<string name="test">测试</string>
|
||||
<string name="show_wait_up_count">显示等待更新数量</string>
|
||||
<string name="exit_app">退出软件</string>
|
||||
<string name="add_all_to_bookshelf">全部加入书架</string>
|
||||
<string name="page_to">页至</string>
|
||||
<string name="result_analyzed">解析示例</string>
|
||||
<string name="bookshelf_px_4">综合排序</string>
|
||||
<string name="effective_replaces">起效的替换</string>
|
||||
|
@ -1120,8 +1120,6 @@
|
||||
<string name="test">Test</string>
|
||||
<string name="show_wait_up_count">Display the number of pending updates</string>
|
||||
<string name="exit_app">Exit</string>
|
||||
<string name="add_all_to_bookshelf">全部加入书架</string>
|
||||
<string name="page_to">页至</string>
|
||||
<string name="result_analyzed">Analyzed</string>
|
||||
<string name="bookshelf_px_4">Comprehensive</string>
|
||||
<string name="effective_replaces">Effective replacement</string>
|
||||
|
Loading…
Reference in New Issue
Block a user