mirror of
https://github.com/gedoor/legado.git
synced 2024-07-06 23:47:49 +08:00
Merge pull request #3063 from h11128/check-source-content
添加换源加载字数选项,显示当前章节或者最新章节字数
This commit is contained in:
commit
58a9bcaee1
@ -61,6 +61,7 @@ object PreferKey {
|
||||
const val changeSourceCheckAuthor = "changeSourceCheckAuthor"
|
||||
const val changeSourceLoadToc = "changeSourceLoadToc"
|
||||
const val changeSourceLoadInfo = "changeSourceLoadInfo"
|
||||
const val changeSourceLoadWordCount = "changeSourceLoadWordCount"
|
||||
const val chineseConverterType = "chineseConverterType"
|
||||
const val launcherIcon = "launcherIcon"
|
||||
const val textSelectAble = "selectText"
|
||||
|
@ -21,7 +21,7 @@ val appDb by lazy {
|
||||
}
|
||||
|
||||
@Database(
|
||||
version = 66,
|
||||
version = 67,
|
||||
exportSchema = true,
|
||||
entities = [Book::class, BookGroup::class, BookSource::class, BookChapter::class,
|
||||
ReplaceRule::class, SearchBook::class, SearchKeyword::class, Cookie::class,
|
||||
@ -51,7 +51,8 @@ val appDb by lazy {
|
||||
AutoMigration(from = 62, to = 63),
|
||||
AutoMigration(from = 63, to = 64),
|
||||
AutoMigration(from = 64, to = 65, spec = DatabaseMigrations.Migration_64_65::class),
|
||||
AutoMigration(from = 65, to = 66)
|
||||
AutoMigration(from = 65, to = 66),
|
||||
AutoMigration(from = 66, to = 67)
|
||||
]
|
||||
)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
|
@ -15,7 +15,7 @@ interface SearchBookDao {
|
||||
@Query(
|
||||
"""select t1.name, t1.author, t1.origin, t1.originName, t1.coverUrl, t1.bookUrl,
|
||||
t1.type, t1.time, t1.intro, t1.kind, t1.latestChapterTitle, t1.tocUrl, t1.variable,
|
||||
t1.wordCount, t2.customOrder as originOrder
|
||||
t1.wordCount, t2.customOrder as originOrder, t1.chapterWordCountText, t1.respondTime, t1.chapterWordCount
|
||||
from searchBooks as t1 inner join book_sources as t2
|
||||
on t1.origin = t2.bookSourceUrl
|
||||
where t1.name = :name and t1.author like '%'||:author||'%'
|
||||
@ -27,7 +27,7 @@ interface SearchBookDao {
|
||||
@Query(
|
||||
"""select t1.name, t1.author, t1.origin, t1.originName, t1.coverUrl, t1.bookUrl,
|
||||
t1.type, t1.time, t1.intro, t1.kind, t1.latestChapterTitle, t1.tocUrl, t1.variable,
|
||||
t1.wordCount, t2.customOrder as originOrder
|
||||
t1.wordCount, t2.customOrder as originOrder, t1.chapterWordCountText, t1.respondTime, t1.chapterWordCount
|
||||
from searchBooks as t1 inner join book_sources as t2
|
||||
on t1.origin = t2.bookSourceUrl
|
||||
where t1.name = :name and t1.author like '%'||:author||'%'
|
||||
@ -45,7 +45,9 @@ interface SearchBookDao {
|
||||
|
||||
@Query(
|
||||
"""
|
||||
select t1.name, t1.author, t1.origin, t1.originName, t1.coverUrl, t1.bookUrl, t1.type, t1.time, t1.intro, t1.kind, t1.latestChapterTitle, t1.tocUrl, t1.variable, t1.wordCount, t2.customOrder as originOrder
|
||||
select t1.name, t1.author, t1.origin, t1.originName, t1.coverUrl, t1.bookUrl,
|
||||
t1.type, t1.time, t1.intro, t1.kind, t1.latestChapterTitle, t1.tocUrl, t1.variable,
|
||||
t1.wordCount, t2.customOrder as originOrder, t1.chapterWordCountText, t1.respondTime, t1.chapterWordCount
|
||||
from searchBooks as t1 inner join book_sources as t2
|
||||
on t1.origin = t2.bookSourceUrl
|
||||
where t1.name = :name and t1.author = :author and t1.coverUrl is not null and t1.coverUrl <> '' and t2.enabled = 1
|
||||
|
@ -41,7 +41,12 @@ data class SearchBook(
|
||||
var tocUrl: String = "",
|
||||
var time: Long = System.currentTimeMillis(),
|
||||
override var variable: String? = null,
|
||||
var originOrder: Int = 0
|
||||
var originOrder: Int = 0,
|
||||
var chapterWordCountText: String? = null,
|
||||
@ColumnInfo(defaultValue = "-1")
|
||||
var chapterWordCount: Int = -1,
|
||||
@ColumnInfo(defaultValue = "-1")
|
||||
var respondTime: Int = -1
|
||||
) : Parcelable, BaseBook, Comparable<SearchBook> {
|
||||
|
||||
@Ignore
|
||||
|
@ -330,6 +330,12 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
appCtx.putPrefBoolean(PreferKey.changeSourceLoadToc, value)
|
||||
}
|
||||
|
||||
var changeSourceLoadWordCount: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.changeSourceLoadWordCount)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.changeSourceLoadWordCount, value)
|
||||
}
|
||||
|
||||
var contentSelectSpeakMod: Int
|
||||
get() = appCtx.getPrefInt(PreferKey.contentSelectSpeakMod)
|
||||
set(value) {
|
||||
|
@ -13,6 +13,7 @@ import io.legado.app.base.adapter.DiffRecyclerAdapter
|
||||
import io.legado.app.base.adapter.ItemViewHolder
|
||||
import io.legado.app.data.entities.SearchBook
|
||||
import io.legado.app.databinding.ItemChangeSourceBinding
|
||||
import io.legado.app.help.config.AppConfig
|
||||
import io.legado.app.utils.getCompatColor
|
||||
import io.legado.app.utils.gone
|
||||
import io.legado.app.utils.invisible
|
||||
@ -55,6 +56,8 @@ class ChangeBookSourceAdapter(
|
||||
tvOrigin.text = item.originName
|
||||
tvAuthor.text = item.author
|
||||
tvLast.text = item.getDisplayLastChapterTitle()
|
||||
tvCurrentChapterWordCount.text = item.chapterWordCountText
|
||||
tvRespondTime.text = context.getString(R.string.respondTime, item.respondTime)
|
||||
if (callBack.oldBookUrl == item.bookUrl) {
|
||||
ivChecked.visible()
|
||||
} else {
|
||||
@ -82,13 +85,37 @@ class ChangeBookSourceAdapter(
|
||||
} else if (score < 0) {
|
||||
binding.ivGood.gone()
|
||||
binding.ivBad.visible()
|
||||
DrawableCompat.setTint(binding.ivGood.drawable, appCtx.getCompatColor(R.color.md_red_100))
|
||||
DrawableCompat.setTint(binding.ivBad.drawable, appCtx.getCompatColor(R.color.md_blue_A200))
|
||||
DrawableCompat.setTint(
|
||||
binding.ivGood.drawable,
|
||||
appCtx.getCompatColor(R.color.md_red_100)
|
||||
)
|
||||
DrawableCompat.setTint(
|
||||
binding.ivBad.drawable,
|
||||
appCtx.getCompatColor(R.color.md_blue_A200)
|
||||
)
|
||||
} else {
|
||||
binding.ivGood.visible()
|
||||
binding.ivBad.visible()
|
||||
DrawableCompat.setTint(binding.ivGood.drawable, appCtx.getCompatColor(R.color.md_red_100))
|
||||
DrawableCompat.setTint(binding.ivBad.drawable, appCtx.getCompatColor(R.color.md_blue_100))
|
||||
DrawableCompat.setTint(
|
||||
binding.ivGood.drawable,
|
||||
appCtx.getCompatColor(R.color.md_red_100)
|
||||
)
|
||||
DrawableCompat.setTint(
|
||||
binding.ivBad.drawable,
|
||||
appCtx.getCompatColor(R.color.md_blue_100)
|
||||
)
|
||||
}
|
||||
|
||||
if (AppConfig.changeSourceLoadWordCount && !item.chapterWordCountText.isNullOrBlank()) {
|
||||
tvCurrentChapterWordCount.visible()
|
||||
} else {
|
||||
tvCurrentChapterWordCount.gone()
|
||||
}
|
||||
|
||||
if (AppConfig.changeSourceLoadWordCount && item.respondTime >= 0) {
|
||||
tvRespondTime.visible()
|
||||
} else {
|
||||
tvRespondTime.gone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,9 +9,9 @@ import androidx.appcompat.widget.SearchView
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.Lifecycle.State.STARTED
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import androidx.lifecycle.Lifecycle.State.STARTED
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import io.legado.app.R
|
||||
@ -111,6 +111,8 @@ class ChangeBookSourceDialog() : BaseDialogFragment(R.layout.dialog_book_change_
|
||||
?.isChecked = AppConfig.changeSourceLoadInfo
|
||||
binding.toolBar.menu.findItem(R.id.menu_load_toc)
|
||||
?.isChecked = AppConfig.changeSourceLoadToc
|
||||
binding.toolBar.menu.findItem(R.id.menu_load_word_count)
|
||||
?.isChecked = AppConfig.changeSourceLoadWordCount
|
||||
}
|
||||
|
||||
private fun initRecyclerView() {
|
||||
@ -218,6 +220,11 @@ class ChangeBookSourceDialog() : BaseDialogFragment(R.layout.dialog_book_change_
|
||||
AppConfig.changeSourceLoadToc = !item.isChecked
|
||||
item.isChecked = !item.isChecked
|
||||
}
|
||||
R.id.menu_load_word_count -> {
|
||||
AppConfig.changeSourceLoadWordCount = !item.isChecked
|
||||
item.isChecked = !item.isChecked
|
||||
viewModel.onLoadWordCountChecked(item.isChecked)
|
||||
}
|
||||
R.id.menu_start_stop -> viewModel.startOrStopSearch()
|
||||
R.id.menu_source_manage -> startActivity<BookSourceActivity>()
|
||||
R.id.menu_refresh_list -> viewModel.startRefreshList()
|
||||
|
@ -8,6 +8,7 @@ import androidx.lifecycle.viewModelScope
|
||||
import io.legado.app.base.BaseViewModel
|
||||
import io.legado.app.constant.AppConst
|
||||
import io.legado.app.constant.AppPattern
|
||||
import io.legado.app.constant.EventBus
|
||||
import io.legado.app.constant.PreferKey
|
||||
import io.legado.app.data.appDb
|
||||
import io.legado.app.data.entities.Book
|
||||
@ -19,17 +20,17 @@ import io.legado.app.help.config.AppConfig
|
||||
import io.legado.app.help.config.SourceConfig
|
||||
import io.legado.app.help.coroutine.CompositeCoroutine
|
||||
import io.legado.app.help.coroutine.Coroutine
|
||||
import io.legado.app.model.ReadBook
|
||||
import io.legado.app.model.webBook.WebBook
|
||||
import io.legado.app.utils.getPrefBoolean
|
||||
import io.legado.app.utils.postEvent
|
||||
import io.legado.app.utils.toastOnUi
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.Dispatchers.IO
|
||||
import kotlinx.coroutines.ExecutorCoroutineDispatcher
|
||||
import kotlinx.coroutines.asCoroutineDispatcher
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.util.*
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.Executors
|
||||
@ -146,6 +147,7 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a
|
||||
stopSearch()
|
||||
appDb.searchBookDao.clear(name, author)
|
||||
searchBooks.clear()
|
||||
searchCallback?.upAdapter()
|
||||
bookSourceList.clear()
|
||||
val searchGroup = AppConfig.searchGroup
|
||||
if (searchGroup.isBlank()) {
|
||||
@ -182,14 +184,17 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a
|
||||
if ((AppConfig.changeSourceCheckAuthor && searchBook.author.contains(author))
|
||||
|| !AppConfig.changeSourceCheckAuthor
|
||||
) {
|
||||
if (searchBook.latestChapterTitle.isNullOrEmpty()) {
|
||||
if (AppConfig.changeSourceLoadInfo || AppConfig.changeSourceLoadToc) {
|
||||
when {
|
||||
searchBook.latestChapterTitle.isNullOrEmpty() &&
|
||||
(AppConfig.changeSourceLoadInfo || AppConfig.changeSourceLoadToc) -> {
|
||||
loadBookInfo(source, searchBook.toBook())
|
||||
} else {
|
||||
}
|
||||
searchBook.chapterWordCountText.isNullOrBlank() && AppConfig.changeSourceLoadWordCount -> {
|
||||
loadBookToc(source, searchBook.toBook())
|
||||
}
|
||||
else -> {
|
||||
searchCallback?.searchSuccess(searchBook)
|
||||
}
|
||||
} else {
|
||||
searchCallback?.searchSuccess(searchBook)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -219,7 +224,37 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a
|
||||
val chapters = WebBook.getChapterListAwait(source, book).getOrThrow()
|
||||
tocMap[book.bookUrl] = chapters
|
||||
bookMap[book.bookUrl] = book
|
||||
val searchBook: SearchBook = book.toSearchBook()
|
||||
if (context.getPrefBoolean(PreferKey.changeSourceLoadWordCount)) {
|
||||
loadBookWordCount(source, book, chapters)
|
||||
} else {
|
||||
val searchBook = book.toSearchBook()
|
||||
searchCallback?.searchSuccess(searchBook)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun loadBookWordCount(
|
||||
source: BookSource,
|
||||
book: Book,
|
||||
chapters: List<BookChapter>
|
||||
) = coroutineScope {
|
||||
val chapterIndex = ReadBook.curTextChapter?.chapter?.index ?: (chapters.size - 1)
|
||||
val bookChapter = chapters.getOrNull(chapterIndex)
|
||||
val startTime = System.currentTimeMillis()
|
||||
val pair = try {
|
||||
if (bookChapter == null) throw NoStackTraceException("章节缺失,总章节数${chapters.size}")
|
||||
if (!isActive) return@coroutineScope
|
||||
WebBook.getContentAwait(source, book, bookChapter, null, false).length.let {
|
||||
it to "第${chapterIndex + 1}章 字数:${it}"
|
||||
}
|
||||
} catch (t: Throwable) {
|
||||
-1 to "第${chapterIndex + 1}章 获取字数失败:${t.localizedMessage}"
|
||||
}
|
||||
val endTime = System.currentTimeMillis()
|
||||
val searchBook = book.toSearchBook().apply {
|
||||
chapterWordCountText = pair.second
|
||||
chapterWordCount = pair.first
|
||||
respondTime = (endTime - startTime).toInt()
|
||||
}
|
||||
searchCallback?.searchSuccess(searchBook)
|
||||
}
|
||||
|
||||
@ -240,15 +275,24 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a
|
||||
}
|
||||
}
|
||||
|
||||
fun onLoadWordCountChecked(isChecked: Boolean) {
|
||||
postEvent(EventBus.SOURCE_CHANGED, "")
|
||||
if (isChecked) {
|
||||
startRefreshList(searchBooks.filter { it.chapterWordCountText == null })
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新列表
|
||||
*/
|
||||
fun startRefreshList() {
|
||||
fun startRefreshList(refreshList: List<SearchBook> = searchBooks) {
|
||||
execute {
|
||||
if (refreshList.isEmpty()) return@execute
|
||||
stopSearch()
|
||||
searchBookList.clear()
|
||||
searchBookList.addAll(searchBooks)
|
||||
searchBooks.clear()
|
||||
searchBookList.addAll(refreshList)
|
||||
searchBooks.removeAll(refreshList)
|
||||
searchCallback?.upAdapter()
|
||||
searchStateData.postValue(true)
|
||||
initSearchPool()
|
||||
for (i in 0 until threadCount) {
|
||||
|
@ -42,6 +42,7 @@
|
||||
android:layout_marginTop="10dp"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/primaryText"
|
||||
tools:text="bookSourceName"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toLeftOf="@+id/tv_author"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
@ -53,6 +54,7 @@
|
||||
android:layout_marginTop="10dp"
|
||||
android:maxWidth="160dp"
|
||||
android:singleLine="true"
|
||||
tools:text="author"
|
||||
android:textColor="@color/secondaryText"
|
||||
app:layout_constraintRight_toLeftOf="@+id/iv_checked"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
@ -64,12 +66,39 @@
|
||||
android:layout_marginLeft="30dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:singleLine="true"
|
||||
tools:text="latest chapter name"
|
||||
android:textColor="@color/secondaryText"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toLeftOf="@+id/iv_checked"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tv_origin" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_current_chapter_word_count"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="30dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:singleLine="false"
|
||||
tools:text="word count"
|
||||
android:textColor="@color/secondaryText"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tv_last" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_respond_time"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="30dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:singleLine="false"
|
||||
tools:text="respond time"
|
||||
android:textColor="@color/secondaryText"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tv_current_chapter_word_count" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/iv_checked"
|
||||
android:layout_width="40dp"
|
||||
|
@ -34,6 +34,12 @@
|
||||
android:checkable="true"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_load_word_count"
|
||||
android:title="@string/load_word_count"
|
||||
android:checkable="true"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_load_info"
|
||||
android:title="@string/load_info"
|
||||
|
@ -874,6 +874,7 @@
|
||||
<string name="upload_url">上传URL</string>
|
||||
<string name="download_url_rule">downloadUrlRule(downloadUrls)</string>
|
||||
<string name="sort_by_respondTime">Ordenar por tiempo de respuesta</string>
|
||||
<string name="respondTime">tiempo de respuesta: %1$d ms</string>
|
||||
<string name="export_success">导出成功</string>
|
||||
<string name="path">路径</string>
|
||||
<string name="direct_link_upload_rule">直链上传规则</string>
|
||||
@ -1099,4 +1100,5 @@
|
||||
<string name="only_latest_backup_t">仅保留最新备份</string>
|
||||
<string name="only_latest_backup_s">本地备份仅保留最新备份文件</string>
|
||||
<string name="webdav_application_authorization_error">Fail to authorize WebDav application</string>
|
||||
<string name="load_word_count">Cargar palabras del libro</string>
|
||||
</resources>
|
||||
|
@ -877,6 +877,7 @@
|
||||
<string name="upload_url">上传URL</string>
|
||||
<string name="download_url_rule">downloadUrlRule(downloadUrls)</string>
|
||||
<string name="sort_by_respondTime">Sort by respond time</string>
|
||||
<string name="respondTime">respondTime: %1$d ms</string>
|
||||
<string name="export_success">导出成功</string>
|
||||
<string name="path">路径</string>
|
||||
<string name="direct_link_upload_rule">直链上传规则</string>
|
||||
@ -1102,4 +1103,5 @@
|
||||
<string name="only_latest_backup_t">仅保留最新备份</string>
|
||||
<string name="only_latest_backup_s">本地备份仅保留最新备份文件</string>
|
||||
<string name="webdav_application_authorization_error">Fail to authorize WebDav application</string>
|
||||
<string name="load_word_count">Load word count</string>
|
||||
</resources>
|
||||
|
@ -875,6 +875,7 @@
|
||||
<string name="upload_url">上传URL</string>
|
||||
<string name="download_url_rule">downloadUrlRule(downloadUrls)</string>
|
||||
<string name="sort_by_respondTime">Classificar por tempo de resposta</string>
|
||||
<string name="respondTime">tempo de resposta: %1$d ms</string>
|
||||
<string name="export_success">导出成功</string>
|
||||
<string name="path">路径</string>
|
||||
<string name="direct_link_upload_rule">直链上传规则</string>
|
||||
@ -1102,4 +1103,5 @@
|
||||
<string name="only_latest_backup_t">仅保留最新备份</string>
|
||||
<string name="only_latest_backup_s">本地备份仅保留最新备份文件</string>
|
||||
<string name="webdav_application_authorization_error">Fail to authorize WebDav application</string>
|
||||
<string name="load_word_count">Carregar os palavras do livro</string>
|
||||
</resources>
|
||||
|
@ -874,6 +874,7 @@
|
||||
<string name="upload_url">上傳URL</string>
|
||||
<string name="download_url_rule">下载URL规则(downloadUrls)</string>
|
||||
<string name="sort_by_respondTime">響應時間排序</string>
|
||||
<string name="respondTime">響應時間:%1$d ms</string>
|
||||
<string name="export_success">導出成功</string>
|
||||
<string name="path">路徑</string>
|
||||
<string name="direct_link_upload_rule">直鏈上傳規則</string>
|
||||
@ -1099,4 +1100,5 @@
|
||||
<string name="only_latest_backup_t">仅保留最新备份</string>
|
||||
<string name="only_latest_backup_s">本地备份仅保留最新备份文件</string>
|
||||
<string name="webdav_application_authorization_error">webDav应用验证失败</string>
|
||||
<string name="load_word_count">加載字數</string>
|
||||
</resources>
|
||||
|
@ -876,6 +876,7 @@
|
||||
<string name="upload_url">上傳URL</string>
|
||||
<string name="download_url_rule">下载URL规则(downloadUrls)</string>
|
||||
<string name="sort_by_respondTime">反應時間排序</string>
|
||||
<string name="respondTime">反應時間:%1$d ms</string>
|
||||
<string name="export_success">匯出成功</string>
|
||||
<string name="path">路徑</string>
|
||||
<string name="direct_link_upload_rule">直鏈上傳規則</string>
|
||||
@ -1101,4 +1102,5 @@
|
||||
<string name="only_latest_backup_t">仅保留最新备份</string>
|
||||
<string name="only_latest_backup_s">本地备份仅保留最新备份文件</string>
|
||||
<string name="webdav_application_authorization_error">webDav应用验证失败</string>
|
||||
<string name="load_word_count">加載字數</string>
|
||||
</resources>
|
||||
|
@ -878,6 +878,7 @@
|
||||
<string name="upload_url">上传 URL</string>
|
||||
<string name="download_url_rule">下载URL规则(downloadUrls)</string>
|
||||
<string name="sort_by_respondTime">响应时间排序</string>
|
||||
<string name="respondTime">响应时间:%1$d ms</string>
|
||||
<string name="export_success">导出成功</string>
|
||||
<string name="path">路径</string>
|
||||
<string name="direct_link_upload_rule">直链上传规则</string>
|
||||
@ -1101,4 +1102,5 @@
|
||||
<string name="only_latest_backup_t">仅保留最新备份</string>
|
||||
<string name="only_latest_backup_s">本地备份仅保留最新备份文件</string>
|
||||
<string name="webdav_application_authorization_error">webDav应用验证失败</string>
|
||||
<string name="load_word_count">加载字数</string>
|
||||
</resources>
|
||||
|
@ -1102,4 +1102,6 @@
|
||||
<string name="only_latest_backup_t">仅保留最新备份</string>
|
||||
<string name="only_latest_backup_s">本地备份仅保留最新备份文件</string>
|
||||
<string name="webdav_application_authorization_error">Fail to authorize WebDav application</string>
|
||||
<string name="respondTime">respondTime: %1$d ms</string>
|
||||
<string name="load_word_count">Load word count</string>
|
||||
</resources>
|
||||
|
Loading…
Reference in New Issue
Block a user