Merge remote-tracking branch 'origin/master' into epublazy
This commit is contained in:
@@ -249,7 +249,7 @@
|
|||||||
android:screenOrientation="behind" />
|
android:screenOrientation="behind" />
|
||||||
<!-- 书籍管理 -->
|
<!-- 书籍管理 -->
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.book.arrange.ArrangeBookActivity"
|
android:name=".ui.book.manage.BookshelfManageActivity"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
android:screenOrientation="behind" />
|
android:screenOrientation="behind" />
|
||||||
<!-- 书源调试 -->
|
<!-- 书源调试 -->
|
||||||
|
|||||||
@@ -11,6 +11,12 @@
|
|||||||
* 正文出现缺字漏字、内容缺失、排版错乱等情况,有可能是净化规则或简繁转换出现问题。
|
* 正文出现缺字漏字、内容缺失、排版错乱等情况,有可能是净化规则或简繁转换出现问题。
|
||||||
* 漫画源看书显示乱码,**阅读与其他软件的源并不通用**,请导入阅读的支持的漫画源!
|
* 漫画源看书显示乱码,**阅读与其他软件的源并不通用**,请导入阅读的支持的漫画源!
|
||||||
|
|
||||||
|
**2022/04/07**
|
||||||
|
|
||||||
|
* 实现epub的懒加载 by ag2s20150909
|
||||||
|
* 解决txt无法导入
|
||||||
|
* 优化换源
|
||||||
|
|
||||||
**2022/04/05**
|
**2022/04/05**
|
||||||
|
|
||||||
* 更新cronet: 100.0.4896.79
|
* 更新cronet: 100.0.4896.79
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ object AppConst {
|
|||||||
SimpleDateFormat("yy-MM-dd-HH-mm-ss")
|
SimpleDateFormat("yy-MM-dd-HH-mm-ss")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const val rootGroupId = -100L
|
||||||
const val bookGroupAllId = -1L
|
const val bookGroupAllId = -1L
|
||||||
const val bookGroupLocalId = -2L
|
const val bookGroupLocalId = -2L
|
||||||
const val bookGroupAudioId = -3L
|
const val bookGroupAudioId = -3L
|
||||||
|
|||||||
@@ -287,10 +287,6 @@ data class Book(
|
|||||||
newBook.customTag = customTag
|
newBook.customTag = customTag
|
||||||
newBook.canUpdate = canUpdate
|
newBook.canUpdate = canUpdate
|
||||||
newBook.readConfig = readConfig
|
newBook.readConfig = readConfig
|
||||||
if (appDb.bookDao.has(bookUrl) == true) {
|
|
||||||
delete()
|
|
||||||
appDb.bookDao.insert(newBook)
|
|
||||||
}
|
|
||||||
return newBook
|
return newBook
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -276,9 +276,17 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
|
|||||||
val autoChangeSource: Boolean
|
val autoChangeSource: Boolean
|
||||||
get() = appCtx.getPrefBoolean(PreferKey.autoChangeSource, true)
|
get() = appCtx.getPrefBoolean(PreferKey.autoChangeSource, true)
|
||||||
|
|
||||||
val changeSourceLoadInfo get() = appCtx.getPrefBoolean(PreferKey.changeSourceLoadInfo)
|
var changeSourceLoadInfo: Boolean
|
||||||
|
get() = appCtx.getPrefBoolean(PreferKey.changeSourceLoadInfo)
|
||||||
|
set(value) {
|
||||||
|
appCtx.putPrefBoolean(PreferKey.changeSourceLoadInfo, value)
|
||||||
|
}
|
||||||
|
|
||||||
val changeSourceLoadToc get() = appCtx.getPrefBoolean(PreferKey.changeSourceLoadToc)
|
var changeSourceLoadToc: Boolean
|
||||||
|
get() = appCtx.getPrefBoolean(PreferKey.changeSourceLoadToc)
|
||||||
|
set(value) {
|
||||||
|
appCtx.putPrefBoolean(PreferKey.changeSourceLoadToc, value)
|
||||||
|
}
|
||||||
|
|
||||||
val importKeepName get() = appCtx.getPrefBoolean(PreferKey.importKeepName)
|
val importKeepName get() = appCtx.getPrefBoolean(PreferKey.importKeepName)
|
||||||
|
|
||||||
|
|||||||
@@ -24,34 +24,43 @@ class FileAssociationViewModel(application: Application) : BaseAssociationViewMo
|
|||||||
@Suppress("BlockingMethodInNonBlockingContext")
|
@Suppress("BlockingMethodInNonBlockingContext")
|
||||||
fun dispatchIndent(uri: Uri, finally: (title: String, msg: String) -> Unit) {
|
fun dispatchIndent(uri: Uri, finally: (title: String, msg: String) -> Unit) {
|
||||||
execute {
|
execute {
|
||||||
|
lateinit var fileName: String
|
||||||
|
lateinit var content: String
|
||||||
//如果是普通的url,需要根据返回的内容判断是什么
|
//如果是普通的url,需要根据返回的内容判断是什么
|
||||||
if (uri.scheme == "file" || uri.scheme == "content") {
|
if (uri.scheme == "file" || uri.scheme == "content") {
|
||||||
val content = if (uri.scheme == "file") {
|
if (uri.scheme == "file") {
|
||||||
File(uri.path.toString()).readText()
|
val file = File(uri.path.toString())
|
||||||
|
content = file.readText()
|
||||||
|
fileName = file.name
|
||||||
} else {
|
} else {
|
||||||
DocumentFile.fromSingleUri(context, uri)?.readText(context)
|
val file = DocumentFile.fromSingleUri(context, uri)
|
||||||
} ?: throw NoStackTraceException("文件不存在")
|
content = file?.readText(context) ?: throw NoStackTraceException("文件不存在")
|
||||||
|
fileName = file.name ?: ""
|
||||||
|
}
|
||||||
when {
|
when {
|
||||||
content.isJson() -> when {
|
content.isJson() -> {
|
||||||
content.contains("bookSourceUrl") ->
|
//暂时根据文件内容判断属于什么
|
||||||
importBookSourceLive.postValue(content)
|
when {
|
||||||
content.contains("sourceUrl") ->
|
content.contains("bookSourceUrl") ->
|
||||||
importRssSourceLive.postValue(content)
|
importBookSourceLive.postValue(content)
|
||||||
content.contains("pattern") ->
|
content.contains("sourceUrl") ->
|
||||||
importReplaceRuleLive.postValue(content)
|
importRssSourceLive.postValue(content)
|
||||||
content.contains("themeName") ->
|
content.contains("pattern") ->
|
||||||
importTheme(content, finally)
|
importReplaceRuleLive.postValue(content)
|
||||||
content.contains("name") && content.contains("rule") ->
|
content.contains("themeName") ->
|
||||||
importTextTocRule(content, finally)
|
importTheme(content, finally)
|
||||||
content.contains("name") && content.contains("url") ->
|
content.contains("name") && content.contains("rule") ->
|
||||||
importHttpTTS(content, finally)
|
importTextTocRule(content, finally)
|
||||||
else -> errorLiveData.postValue("格式不对")
|
content.contains("name") && content.contains("url") ->
|
||||||
|
importHttpTTS(content, finally)
|
||||||
|
else -> errorLiveData.postValue("格式不对")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
(uri.path ?: uri.toString()).matches(bookFileRegex) -> {
|
fileName.matches(bookFileRegex) -> {
|
||||||
importBookLiveData.postValue(uri)
|
importBookLiveData.postValue(uri)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
throw NoStackTraceException("暂未支持的本地书籍格式(TXT/UMD/EPUB)")
|
throw NoStackTraceException("$fileName 暂未支持的本地书籍格式(TXT/UMD/EPUB)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import io.legado.app.constant.BookType
|
|||||||
import io.legado.app.constant.EventBus
|
import io.legado.app.constant.EventBus
|
||||||
import io.legado.app.constant.Status
|
import io.legado.app.constant.Status
|
||||||
import io.legado.app.constant.Theme
|
import io.legado.app.constant.Theme
|
||||||
|
import io.legado.app.data.appDb
|
||||||
import io.legado.app.data.entities.Book
|
import io.legado.app.data.entities.Book
|
||||||
import io.legado.app.data.entities.BookChapter
|
import io.legado.app.data.entities.BookChapter
|
||||||
import io.legado.app.data.entities.BookSource
|
import io.legado.app.data.entities.BookSource
|
||||||
@@ -212,6 +213,7 @@ class AudioPlayActivity :
|
|||||||
launch {
|
launch {
|
||||||
withContext(IO) {
|
withContext(IO) {
|
||||||
AudioPlay.book?.changeTo(book, toc)
|
AudioPlay.book?.changeTo(book, toc)
|
||||||
|
appDb.bookDao.insert(book)
|
||||||
}
|
}
|
||||||
startActivity<ReadBookActivity> {
|
startActivity<ReadBookActivity> {
|
||||||
putExtra("bookUrl", book.bookUrl)
|
putExtra("bookUrl", book.bookUrl)
|
||||||
|
|||||||
@@ -78,7 +78,9 @@ class AudioPlayViewModel(application: Application) : BaseViewModel(application)
|
|||||||
|
|
||||||
fun changeTo(source: BookSource, book: Book, toc: List<BookChapter>) {
|
fun changeTo(source: BookSource, book: Book, toc: List<BookChapter>) {
|
||||||
execute {
|
execute {
|
||||||
AudioPlay.book = AudioPlay.book!!.changeTo(book, toc)
|
AudioPlay.book?.changeTo(book, toc)
|
||||||
|
appDb.bookDao.insert(book)
|
||||||
|
AudioPlay.book = book
|
||||||
AudioPlay.bookSource = source
|
AudioPlay.bookSource = source
|
||||||
appDb.bookChapterDao.insert(*toc.toTypedArray())
|
appDb.bookChapterDao.insert(*toc.toTypedArray())
|
||||||
AudioPlay.upDurChapter(book)
|
AudioPlay.upDurChapter(book)
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import io.legado.app.R
|
|||||||
import io.legado.app.base.BaseDialogFragment
|
import io.legado.app.base.BaseDialogFragment
|
||||||
import io.legado.app.constant.AppPattern
|
import io.legado.app.constant.AppPattern
|
||||||
import io.legado.app.constant.EventBus
|
import io.legado.app.constant.EventBus
|
||||||
import io.legado.app.constant.PreferKey
|
|
||||||
import io.legado.app.data.appDb
|
import io.legado.app.data.appDb
|
||||||
import io.legado.app.data.entities.Book
|
import io.legado.app.data.entities.Book
|
||||||
import io.legado.app.data.entities.BookChapter
|
import io.legado.app.data.entities.BookChapter
|
||||||
@@ -207,12 +206,12 @@ class ChangeBookSourceDialog() : BaseDialogFragment(R.layout.dialog_book_change_
|
|||||||
item.isChecked = !item.isChecked
|
item.isChecked = !item.isChecked
|
||||||
viewModel.refresh()
|
viewModel.refresh()
|
||||||
}
|
}
|
||||||
R.id.menu_load_toc -> {
|
R.id.menu_load_info -> {
|
||||||
putPrefBoolean(PreferKey.changeSourceLoadToc, !item.isChecked)
|
AppConfig.changeSourceLoadInfo = !item.isChecked
|
||||||
item.isChecked = !item.isChecked
|
item.isChecked = !item.isChecked
|
||||||
}
|
}
|
||||||
R.id.menu_load_info -> {
|
R.id.menu_load_toc -> {
|
||||||
putPrefBoolean(PreferKey.changeSourceLoadInfo, !item.isChecked)
|
AppConfig.changeSourceLoadToc = !item.isChecked
|
||||||
item.isChecked = !item.isChecked
|
item.isChecked = !item.isChecked
|
||||||
}
|
}
|
||||||
R.id.menu_start_stop -> viewModel.startOrStopSearch()
|
R.id.menu_start_stop -> viewModel.startOrStopSearch()
|
||||||
|
|||||||
@@ -184,12 +184,11 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a
|
|||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun loadBookInfo(scope: CoroutineScope, source: BookSource, book: Book) {
|
private suspend fun loadBookInfo(scope: CoroutineScope, source: BookSource, book: Book) {
|
||||||
val mBook = WebBook.getBookInfoAwait(scope, source, book)
|
WebBook.getBookInfoAwait(scope, source, book)
|
||||||
if (context.getPrefBoolean(PreferKey.changeSourceLoadToc)) {
|
if (context.getPrefBoolean(PreferKey.changeSourceLoadToc)) {
|
||||||
loadBookToc(scope, source, mBook)
|
loadBookToc(scope, source, book)
|
||||||
} else {
|
} else {
|
||||||
//从详情页里获取最新章节
|
//从详情页里获取最新章节
|
||||||
book.latestChapterTitle = mBook.latestChapterTitle
|
|
||||||
val searchBook = book.toSearchBook()
|
val searchBook = book.toSearchBook()
|
||||||
searchCallback?.searchSuccess(searchBook)
|
searchCallback?.searchSuccess(searchBook)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import io.legado.app.R
|
|||||||
import io.legado.app.base.BaseDialogFragment
|
import io.legado.app.base.BaseDialogFragment
|
||||||
import io.legado.app.constant.AppPattern
|
import io.legado.app.constant.AppPattern
|
||||||
import io.legado.app.constant.EventBus
|
import io.legado.app.constant.EventBus
|
||||||
import io.legado.app.constant.PreferKey
|
|
||||||
import io.legado.app.data.appDb
|
import io.legado.app.data.appDb
|
||||||
import io.legado.app.data.entities.Book
|
import io.legado.app.data.entities.Book
|
||||||
import io.legado.app.data.entities.BookChapter
|
import io.legado.app.data.entities.BookChapter
|
||||||
@@ -231,12 +230,12 @@ class ChangeChapterSourceDialog() : BaseDialogFragment(R.layout.dialog_chapter_c
|
|||||||
item.isChecked = !item.isChecked
|
item.isChecked = !item.isChecked
|
||||||
viewModel.refresh()
|
viewModel.refresh()
|
||||||
}
|
}
|
||||||
R.id.menu_load_toc -> {
|
R.id.menu_load_info -> {
|
||||||
putPrefBoolean(PreferKey.changeSourceLoadToc, !item.isChecked)
|
AppConfig.changeSourceLoadInfo = !item.isChecked
|
||||||
item.isChecked = !item.isChecked
|
item.isChecked = !item.isChecked
|
||||||
}
|
}
|
||||||
R.id.menu_load_info -> {
|
R.id.menu_load_toc -> {
|
||||||
putPrefBoolean(PreferKey.changeSourceLoadInfo, !item.isChecked)
|
AppConfig.changeSourceLoadToc = !item.isChecked
|
||||||
item.isChecked = !item.isChecked
|
item.isChecked = !item.isChecked
|
||||||
}
|
}
|
||||||
R.id.menu_start_stop -> viewModel.startOrStopSearch()
|
R.id.menu_start_stop -> viewModel.startOrStopSearch()
|
||||||
|
|||||||
@@ -270,7 +270,7 @@ class BookInfoActivity :
|
|||||||
showDialogFragment(
|
showDialogFragment(
|
||||||
ChangeCoverDialog(it.name, it.author)
|
ChangeCoverDialog(it.name, it.author)
|
||||||
)
|
)
|
||||||
}
|
} ?: toastOnUi("Book is null")
|
||||||
}
|
}
|
||||||
ivCover.setOnLongClickListener {
|
ivCover.setOnLongClickListener {
|
||||||
viewModel.bookData.value?.getDisplayCover()?.let { path ->
|
viewModel.bookData.value?.getDisplayCover()?.let { path ->
|
||||||
@@ -281,7 +281,7 @@ class BookInfoActivity :
|
|||||||
tvRead.setOnClickListener {
|
tvRead.setOnClickListener {
|
||||||
viewModel.bookData.value?.let {
|
viewModel.bookData.value?.let {
|
||||||
readBook(it)
|
readBook(it)
|
||||||
}
|
} ?: toastOnUi("Book is null")
|
||||||
}
|
}
|
||||||
tvShelf.setOnClickListener {
|
tvShelf.setOnClickListener {
|
||||||
if (viewModel.inBookshelf) {
|
if (viewModel.inBookshelf) {
|
||||||
@@ -297,12 +297,12 @@ class BookInfoActivity :
|
|||||||
startActivity<BookSourceEditActivity> {
|
startActivity<BookSourceEditActivity> {
|
||||||
putExtra("sourceUrl", it.origin)
|
putExtra("sourceUrl", it.origin)
|
||||||
}
|
}
|
||||||
}
|
} ?: toastOnUi("Book is null")
|
||||||
}
|
}
|
||||||
tvChangeSource.setOnClickListener {
|
tvChangeSource.setOnClickListener {
|
||||||
viewModel.bookData.value?.let {
|
viewModel.bookData.value?.let { book ->
|
||||||
showDialogFragment(ChangeBookSourceDialog(it.name, it.author))
|
showDialogFragment(ChangeBookSourceDialog(book.name, book.author))
|
||||||
}
|
} ?: toastOnUi("Book is null")
|
||||||
}
|
}
|
||||||
tvTocView.setOnClickListener {
|
tvTocView.setOnClickListener {
|
||||||
if (!viewModel.inBookshelf) {
|
if (!viewModel.inBookshelf) {
|
||||||
@@ -320,7 +320,7 @@ class BookInfoActivity :
|
|||||||
showDialogFragment(
|
showDialogFragment(
|
||||||
GroupSelectDialog(it.group)
|
GroupSelectDialog(it.group)
|
||||||
)
|
)
|
||||||
}
|
} ?: toastOnUi("Book is null")
|
||||||
}
|
}
|
||||||
tvAuthor.setOnClickListener {
|
tvAuthor.setOnClickListener {
|
||||||
startActivity<SearchActivity> {
|
startActivity<SearchActivity> {
|
||||||
|
|||||||
@@ -39,17 +39,17 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
val bookUrl = intent.getStringExtra("bookUrl") ?: ""
|
val bookUrl = intent.getStringExtra("bookUrl") ?: ""
|
||||||
appDb.bookDao.getBook(name, author)?.let {
|
appDb.bookDao.getBook(name, author)?.let {
|
||||||
inBookshelf = true
|
inBookshelf = true
|
||||||
setBook(it)
|
upBook(it)
|
||||||
return@execute
|
return@execute
|
||||||
}
|
}
|
||||||
if (bookUrl.isNotBlank()) {
|
if (bookUrl.isNotBlank()) {
|
||||||
appDb.searchBookDao.getSearchBook(bookUrl)?.toBook()?.let {
|
appDb.searchBookDao.getSearchBook(bookUrl)?.toBook()?.let {
|
||||||
setBook(it)
|
upBook(it)
|
||||||
return@execute
|
return@execute
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
appDb.searchBookDao.getFirstByNameAuthor(name, author)?.toBook()?.let {
|
appDb.searchBookDao.getFirstByNameAuthor(name, author)?.toBook()?.let {
|
||||||
setBook(it)
|
upBook(it)
|
||||||
return@execute
|
return@execute
|
||||||
}
|
}
|
||||||
throw NoStackTraceException("未找到书籍")
|
throw NoStackTraceException("未找到书籍")
|
||||||
@@ -63,12 +63,12 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
val name = intent.getStringExtra("name") ?: ""
|
val name = intent.getStringExtra("name") ?: ""
|
||||||
val author = intent.getStringExtra("author") ?: ""
|
val author = intent.getStringExtra("author") ?: ""
|
||||||
appDb.bookDao.getBook(name, author)?.let { book ->
|
appDb.bookDao.getBook(name, author)?.let { book ->
|
||||||
setBook(book)
|
upBook(book)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setBook(book: Book) {
|
private fun upBook(book: Book) {
|
||||||
execute {
|
execute {
|
||||||
durChapterIndex = book.durChapterIndex
|
durChapterIndex = book.durChapterIndex
|
||||||
bookData.postValue(book)
|
bookData.postValue(book)
|
||||||
@@ -176,15 +176,19 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun changeTo(source: BookSource, newBook: Book, toc: List<BookChapter>) {
|
fun changeTo(source: BookSource, book: Book, toc: List<BookChapter>) {
|
||||||
changeSourceCoroutine?.cancel()
|
changeSourceCoroutine?.cancel()
|
||||||
changeSourceCoroutine = execute {
|
changeSourceCoroutine = execute {
|
||||||
bookSource = source
|
bookSource = source
|
||||||
bookData.value!!.changeTo(newBook, toc)
|
bookData.value?.changeTo(book, toc)
|
||||||
bookData.postValue(newBook)
|
if (inBookshelf) {
|
||||||
|
appDb.bookDao.insert(book)
|
||||||
|
appDb.bookChapterDao.insert(*toc.toTypedArray())
|
||||||
|
}
|
||||||
|
bookData.postValue(book)
|
||||||
chapterListData.postValue(toc)
|
chapterListData.postValue(toc)
|
||||||
}.onFinally {
|
}.onFinally {
|
||||||
postEvent(EventBus.SOURCE_CHANGED, newBook.bookUrl)
|
postEvent(EventBus.SOURCE_CHANGED, book.bookUrl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
package io.legado.app.ui.book.arrange
|
package io.legado.app.ui.book.manage
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
@@ -15,7 +15,7 @@ import io.legado.app.lib.theme.backgroundColor
|
|||||||
import io.legado.app.ui.widget.recycler.DragSelectTouchHelper
|
import io.legado.app.ui.widget.recycler.DragSelectTouchHelper
|
||||||
import io.legado.app.ui.widget.recycler.ItemTouchCallback
|
import io.legado.app.ui.widget.recycler.ItemTouchCallback
|
||||||
|
|
||||||
class ArrangeBookAdapter(context: Context, val callBack: CallBack) :
|
class BookAdapter(context: Context, val callBack: CallBack) :
|
||||||
RecyclerAdapter<Book, ItemArrangeBookBinding>(context),
|
RecyclerAdapter<Book, ItemArrangeBookBinding>(context),
|
||||||
|
|
||||||
ItemTouchCallback.Callback {
|
ItemTouchCallback.Callback {
|
||||||
+18
-10
@@ -1,4 +1,4 @@
|
|||||||
package io.legado.app.ui.book.arrange
|
package io.legado.app.ui.book.manage
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
@@ -39,19 +39,20 @@ import kotlinx.coroutines.launch
|
|||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
|
||||||
class ArrangeBookActivity : VMBaseActivity<ActivityArrangeBookBinding, ArrangeBookViewModel>(),
|
class BookshelfManageActivity :
|
||||||
|
VMBaseActivity<ActivityArrangeBookBinding, BookshelfManageViewModel>(),
|
||||||
PopupMenu.OnMenuItemClickListener,
|
PopupMenu.OnMenuItemClickListener,
|
||||||
SelectActionBar.CallBack,
|
SelectActionBar.CallBack,
|
||||||
ArrangeBookAdapter.CallBack,
|
BookAdapter.CallBack,
|
||||||
SourcePickerDialog.Callback,
|
SourcePickerDialog.Callback,
|
||||||
GroupSelectDialog.CallBack {
|
GroupSelectDialog.CallBack {
|
||||||
|
|
||||||
override val binding by viewBinding(ActivityArrangeBookBinding::inflate)
|
override val binding by viewBinding(ActivityArrangeBookBinding::inflate)
|
||||||
override val viewModel by viewModels<ArrangeBookViewModel>()
|
override val viewModel by viewModels<BookshelfManageViewModel>()
|
||||||
override val groupList: ArrayList<BookGroup> = arrayListOf()
|
override val groupList: ArrayList<BookGroup> = arrayListOf()
|
||||||
private val groupRequestCode = 22
|
private val groupRequestCode = 22
|
||||||
private val addToGroupRequestCode = 34
|
private val addToGroupRequestCode = 34
|
||||||
private val adapter by lazy { ArrangeBookAdapter(this, this) }
|
private val adapter by lazy { BookAdapter(this, this) }
|
||||||
private var booksFlowJob: Job? = null
|
private var booksFlowJob: Job? = null
|
||||||
private var menu: Menu? = null
|
private var menu: Menu? = null
|
||||||
private var groupId: Long = -1
|
private var groupId: Long = -1
|
||||||
@@ -70,7 +71,7 @@ class ArrangeBookActivity : VMBaseActivity<ActivityArrangeBookBinding, ArrangeBo
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onCompatCreateOptionsMenu(menu: Menu): Boolean {
|
override fun onCompatCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
menuInflater.inflate(R.menu.arrange_book, menu)
|
menuInflater.inflate(R.menu.bookshelf_manage, menu)
|
||||||
return super.onCompatCreateOptionsMenu(menu)
|
return super.onCompatCreateOptionsMenu(menu)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +108,7 @@ class ArrangeBookActivity : VMBaseActivity<ActivityArrangeBookBinding, ArrangeBo
|
|||||||
// Note: need judge selection first, so add ItemTouchHelper after it.
|
// Note: need judge selection first, so add ItemTouchHelper after it.
|
||||||
ItemTouchHelper(itemTouchCallback).attachToRecyclerView(binding.recyclerView)
|
ItemTouchHelper(itemTouchCallback).attachToRecyclerView(binding.recyclerView)
|
||||||
binding.selectActionBar.setMainActionText(R.string.move_to_group)
|
binding.selectActionBar.setMainActionText(R.string.move_to_group)
|
||||||
binding.selectActionBar.inflateMenu(R.menu.arrange_book_sel)
|
binding.selectActionBar.inflateMenu(R.menu.bookshelf_menage_sel)
|
||||||
binding.selectActionBar.setOnMenuItemClickListener(this)
|
binding.selectActionBar.setOnMenuItemClickListener(this)
|
||||||
binding.selectActionBar.setCallBack(this)
|
binding.selectActionBar.setCallBack(this)
|
||||||
binding.composeView.setContent {
|
binding.composeView.setContent {
|
||||||
@@ -139,6 +140,7 @@ class ArrangeBookActivity : VMBaseActivity<ActivityArrangeBookBinding, ArrangeBo
|
|||||||
booksFlowJob?.cancel()
|
booksFlowJob?.cancel()
|
||||||
booksFlowJob = launch {
|
booksFlowJob = launch {
|
||||||
when (groupId) {
|
when (groupId) {
|
||||||
|
AppConst.rootGroupId -> appDb.bookDao.flowNoGroup()
|
||||||
AppConst.bookGroupAllId -> appDb.bookDao.flowAll()
|
AppConst.bookGroupAllId -> appDb.bookDao.flowAll()
|
||||||
AppConst.bookGroupLocalId -> appDb.bookDao.flowLocal()
|
AppConst.bookGroupLocalId -> appDb.bookDao.flowLocal()
|
||||||
AppConst.bookGroupAudioId -> appDb.bookDao.flowAudio()
|
AppConst.bookGroupAudioId -> appDb.bookDao.flowAudio()
|
||||||
@@ -146,12 +148,18 @@ class ArrangeBookActivity : VMBaseActivity<ActivityArrangeBookBinding, ArrangeBo
|
|||||||
else -> appDb.bookDao.flowByGroup(groupId)
|
else -> appDb.bookDao.flowByGroup(groupId)
|
||||||
}.conflate().map { books ->
|
}.conflate().map { books ->
|
||||||
when (getPrefInt(PreferKey.bookshelfSort)) {
|
when (getPrefInt(PreferKey.bookshelfSort)) {
|
||||||
1 -> books.sortedByDescending { it.latestChapterTime }
|
1 -> books.sortedByDescending {
|
||||||
|
it.latestChapterTime
|
||||||
|
}
|
||||||
2 -> books.sortedWith { o1, o2 ->
|
2 -> books.sortedWith { o1, o2 ->
|
||||||
o1.name.cnCompare(o2.name)
|
o1.name.cnCompare(o2.name)
|
||||||
}
|
}
|
||||||
3 -> books.sortedBy { it.order }
|
3 -> books.sortedBy {
|
||||||
else -> books.sortedByDescending { it.durChapterTime }
|
it.order
|
||||||
|
}
|
||||||
|
else -> books.sortedByDescending {
|
||||||
|
it.durChapterTime
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}.conflate().collect { books ->
|
}.conflate().collect { books ->
|
||||||
adapter.setItems(books)
|
adapter.setItems(books)
|
||||||
+3
-2
@@ -1,4 +1,4 @@
|
|||||||
package io.legado.app.ui.book.arrange
|
package io.legado.app.ui.book.manage
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
@@ -10,7 +10,7 @@ import io.legado.app.help.coroutine.Coroutine
|
|||||||
import io.legado.app.model.webBook.WebBook
|
import io.legado.app.model.webBook.WebBook
|
||||||
|
|
||||||
|
|
||||||
class ArrangeBookViewModel(application: Application) : BaseViewModel(application) {
|
class BookshelfManageViewModel(application: Application) : BaseViewModel(application) {
|
||||||
|
|
||||||
val batchChangeSourceState = mutableStateOf(false)
|
val batchChangeSourceState = mutableStateOf(false)
|
||||||
val batchChangeSourceSize = mutableStateOf(0)
|
val batchChangeSourceSize = mutableStateOf(0)
|
||||||
@@ -50,6 +50,7 @@ class ArrangeBookViewModel(application: Application) : BaseViewModel(application
|
|||||||
.getOrNull()?.let { newBook ->
|
.getOrNull()?.let { newBook ->
|
||||||
val toc = WebBook.getChapterListAwait(this, source, newBook)
|
val toc = WebBook.getChapterListAwait(this, source, newBook)
|
||||||
book.changeTo(newBook, toc)
|
book.changeTo(newBook, toc)
|
||||||
|
appDb.bookDao.insert(newBook)
|
||||||
appDb.bookChapterDao.insert(*toc.toTypedArray())
|
appDb.bookChapterDao.insert(*toc.toTypedArray())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package io.legado.app.ui.book.arrange
|
package io.legado.app.ui.book.manage
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.material.AlertDialog
|
import androidx.compose.material.AlertDialog
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package io.legado.app.ui.book.arrange
|
package io.legado.app.ui.book.manage
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
@@ -724,6 +724,7 @@ class ReadBookActivity : BaseReadBookActivity(),
|
|||||||
ReadAloud.stop(this)
|
ReadAloud.stop(this)
|
||||||
launch {
|
launch {
|
||||||
ReadBook.book?.changeTo(book, toc)
|
ReadBook.book?.changeTo(book, toc)
|
||||||
|
appDb.bookDao.insert(book)
|
||||||
}
|
}
|
||||||
startActivity<AudioPlayActivity> {
|
startActivity<AudioPlayActivity> {
|
||||||
putExtra("bookUrl", book.bookUrl)
|
putExtra("bookUrl", book.bookUrl)
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
changeSourceCoroutine?.cancel()
|
changeSourceCoroutine?.cancel()
|
||||||
changeSourceCoroutine = execute {
|
changeSourceCoroutine = execute {
|
||||||
ReadBook.upMsg(context.getString(R.string.loading))
|
ReadBook.upMsg(context.getString(R.string.loading))
|
||||||
ReadBook.book!!.changeTo(book, toc)
|
ReadBook.book?.changeTo(book, toc)
|
||||||
val nextChapter = toc.getOrElse(book.durChapterIndex) {
|
val nextChapter = toc.getOrElse(book.durChapterIndex) {
|
||||||
toc.first()
|
toc.first()
|
||||||
}
|
}
|
||||||
@@ -206,17 +206,17 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
bookChapter = toc[book.durChapterIndex],
|
bookChapter = toc[book.durChapterIndex],
|
||||||
nextChapterUrl = nextChapter.url
|
nextChapterUrl = nextChapter.url
|
||||||
)
|
)
|
||||||
|
appDb.bookDao.insert(book)
|
||||||
appDb.bookChapterDao.insert(*toc.toTypedArray())
|
appDb.bookChapterDao.insert(*toc.toTypedArray())
|
||||||
ReadBook.resetData(book)
|
ReadBook.resetData(book)
|
||||||
ReadBook.upMsg(null)
|
ReadBook.upMsg(null)
|
||||||
ReadBook.loadContent(resetPageOffset = true)
|
ReadBook.loadContent(resetPageOffset = true)
|
||||||
}.timeout(60000)
|
}.onError {
|
||||||
.onError {
|
context.toastOnUi("换源失败\n${it.localizedMessage}")
|
||||||
context.toastOnUi("换源失败\n${it.localizedMessage}")
|
ReadBook.upMsg(null)
|
||||||
ReadBook.upMsg(null)
|
}.onFinally {
|
||||||
}.onFinally {
|
postEvent(EventBus.SOURCE_CHANGED, book.bookUrl)
|
||||||
postEvent(EventBus.SOURCE_CHANGED, book.bookUrl)
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -19,10 +19,10 @@ import io.legado.app.help.DirectLinkUpload
|
|||||||
import io.legado.app.help.config.AppConfig
|
import io.legado.app.help.config.AppConfig
|
||||||
import io.legado.app.lib.dialogs.alert
|
import io.legado.app.lib.dialogs.alert
|
||||||
import io.legado.app.ui.about.AppLogDialog
|
import io.legado.app.ui.about.AppLogDialog
|
||||||
import io.legado.app.ui.book.arrange.ArrangeBookActivity
|
|
||||||
import io.legado.app.ui.book.cache.CacheActivity
|
import io.legado.app.ui.book.cache.CacheActivity
|
||||||
import io.legado.app.ui.book.group.GroupManageDialog
|
import io.legado.app.ui.book.group.GroupManageDialog
|
||||||
import io.legado.app.ui.book.local.ImportBookActivity
|
import io.legado.app.ui.book.local.ImportBookActivity
|
||||||
|
import io.legado.app.ui.book.manage.BookshelfManageActivity
|
||||||
import io.legado.app.ui.book.search.SearchActivity
|
import io.legado.app.ui.book.search.SearchActivity
|
||||||
import io.legado.app.ui.document.HandleFileContract
|
import io.legado.app.ui.document.HandleFileContract
|
||||||
import io.legado.app.ui.main.MainViewModel
|
import io.legado.app.ui.main.MainViewModel
|
||||||
@@ -80,7 +80,7 @@ abstract class BaseBookshelfFragment(layoutId: Int) : VMBaseFragment<BookshelfVi
|
|||||||
R.id.menu_group_manage -> showDialogFragment<GroupManageDialog>()
|
R.id.menu_group_manage -> showDialogFragment<GroupManageDialog>()
|
||||||
R.id.menu_add_local -> startActivity<ImportBookActivity>()
|
R.id.menu_add_local -> startActivity<ImportBookActivity>()
|
||||||
R.id.menu_add_url -> addBookByUrl()
|
R.id.menu_add_url -> addBookByUrl()
|
||||||
R.id.menu_arrange_bookshelf -> startActivity<ArrangeBookActivity> {
|
R.id.menu_bookshelf_manage -> startActivity<BookshelfManageActivity> {
|
||||||
putExtra("groupId", groupId)
|
putExtra("groupId", groupId)
|
||||||
}
|
}
|
||||||
R.id.menu_download -> startActivity<CacheActivity> {
|
R.id.menu_download -> startActivity<CacheActivity> {
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ class BookshelfFragment2 : BaseBookshelfFragment(R.layout.fragment_bookshelf1),
|
|||||||
BaseBooksAdapter.CallBack {
|
BaseBooksAdapter.CallBack {
|
||||||
|
|
||||||
private val binding by viewBinding(FragmentBookshelf1Binding::bind)
|
private val binding by viewBinding(FragmentBookshelf1Binding::bind)
|
||||||
private val rootGroupId = -100L
|
|
||||||
private val bookshelfLayout by lazy {
|
private val bookshelfLayout by lazy {
|
||||||
getPrefInt(PreferKey.bookshelfLayout)
|
getPrefInt(PreferKey.bookshelfLayout)
|
||||||
}
|
}
|
||||||
@@ -56,7 +55,7 @@ class BookshelfFragment2 : BaseBookshelfFragment(R.layout.fragment_bookshelf1),
|
|||||||
}
|
}
|
||||||
private var bookGroups: List<BookGroup> = emptyList()
|
private var bookGroups: List<BookGroup> = emptyList()
|
||||||
private var booksFlowJob: Job? = null
|
private var booksFlowJob: Job? = null
|
||||||
override var groupId = rootGroupId
|
override var groupId = AppConst.rootGroupId
|
||||||
override var books: List<Book> = emptyList()
|
override var books: List<Book> = emptyList()
|
||||||
|
|
||||||
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
@@ -121,7 +120,7 @@ class BookshelfFragment2 : BaseBookshelfFragment(R.layout.fragment_bookshelf1),
|
|||||||
booksFlowJob?.cancel()
|
booksFlowJob?.cancel()
|
||||||
booksFlowJob = launch {
|
booksFlowJob = launch {
|
||||||
when (groupId) {
|
when (groupId) {
|
||||||
rootGroupId -> appDb.bookDao.flowRoot()
|
AppConst.rootGroupId -> appDb.bookDao.flowRoot()
|
||||||
AppConst.bookGroupAllId -> appDb.bookDao.flowAll()
|
AppConst.bookGroupAllId -> appDb.bookDao.flowAll()
|
||||||
AppConst.bookGroupLocalId -> appDb.bookDao.flowLocal()
|
AppConst.bookGroupLocalId -> appDb.bookDao.flowLocal()
|
||||||
AppConst.bookGroupAudioId -> appDb.bookDao.flowAudio()
|
AppConst.bookGroupAudioId -> appDb.bookDao.flowAudio()
|
||||||
@@ -212,7 +211,7 @@ class BookshelfFragment2 : BaseBookshelfFragment(R.layout.fragment_bookshelf1),
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount(): Int {
|
override fun getItemCount(): Int {
|
||||||
return if (groupId == rootGroupId) {
|
return if (groupId == AppConst.rootGroupId) {
|
||||||
bookGroups.size + books.size
|
bookGroups.size + books.size
|
||||||
} else {
|
} else {
|
||||||
books.size
|
books.size
|
||||||
@@ -220,7 +219,7 @@ class BookshelfFragment2 : BaseBookshelfFragment(R.layout.fragment_bookshelf1),
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemType(position: Int): Int {
|
override fun getItemType(position: Int): Int {
|
||||||
if (groupId != rootGroupId) {
|
if (groupId != AppConst.rootGroupId) {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
if (position < bookGroups.size) {
|
if (position < bookGroups.size) {
|
||||||
@@ -230,7 +229,7 @@ class BookshelfFragment2 : BaseBookshelfFragment(R.layout.fragment_bookshelf1),
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getItem(position: Int): Any? {
|
override fun getItem(position: Int): Any? {
|
||||||
if (groupId != rootGroupId) {
|
if (groupId != AppConst.rootGroupId) {
|
||||||
return books.getOrNull(position)
|
return books.getOrNull(position)
|
||||||
}
|
}
|
||||||
if (position < bookGroups.size) {
|
if (position < bookGroups.size) {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
android:id="@+id/title_bar"
|
android:id="@+id/title_bar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:title="@string/arrange_bookshelf"
|
app:title="@string/bookshelf_management"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
|||||||
@@ -28,6 +28,12 @@
|
|||||||
android:title="@string/add_url"
|
android:title="@string/add_url"
|
||||||
app:showAsAction="never" />
|
app:showAsAction="never" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_bookshelf_manage"
|
||||||
|
android:icon="@drawable/ic_arrange"
|
||||||
|
android:title="@string/bookshelf_management"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/menu_download"
|
android:id="@+id/menu_download"
|
||||||
android:icon="@drawable/ic_download_line"
|
android:icon="@drawable/ic_download_line"
|
||||||
@@ -46,12 +52,6 @@
|
|||||||
android:title="@string/bookshelf_layout"
|
android:title="@string/bookshelf_layout"
|
||||||
app:showAsAction="never" />
|
app:showAsAction="never" />
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/menu_arrange_bookshelf"
|
|
||||||
android:icon="@drawable/ic_arrange"
|
|
||||||
android:title="@string/arrange_bookshelf"
|
|
||||||
app:showAsAction="never" />
|
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/menu_export_bookshelf"
|
android:id="@+id/menu_export_bookshelf"
|
||||||
android:icon="@drawable/ic_export"
|
android:icon="@drawable/ic_export"
|
||||||
|
|||||||
@@ -267,7 +267,7 @@
|
|||||||
<string name="load_over_time">Tiempo límite de carga</string>
|
<string name="load_over_time">Tiempo límite de carga</string>
|
||||||
<string name="join_group">Siga:%s</string>
|
<string name="join_group">Siga:%s</string>
|
||||||
<string name="copy_complete">Copiado con éxito</string>
|
<string name="copy_complete">Copiado con éxito</string>
|
||||||
<string name="arrange_bookshelf">Organización de estantería</string>
|
<string name="bookshelf_management">Organización de estantería</string>
|
||||||
<string name="clear_bookshelf_s">Esto borrará a todos los libros. Por favor, tenga cuidado.</string>
|
<string name="clear_bookshelf_s">Esto borrará a todos los libros. Por favor, tenga cuidado.</string>
|
||||||
<string name="search_book_source">Buscar fuentes de libros</string>
|
<string name="search_book_source">Buscar fuentes de libros</string>
|
||||||
<string name="search_rss_source">Buscar fuentes de suscripción</string>
|
<string name="search_rss_source">Buscar fuentes de suscripción</string>
|
||||||
|
|||||||
@@ -271,7 +271,7 @@
|
|||||||
<string name="load_over_time">Loading timeout</string>
|
<string name="load_over_time">Loading timeout</string>
|
||||||
<string name="join_group">Follow:%s</string>
|
<string name="join_group">Follow:%s</string>
|
||||||
<string name="copy_complete">Copied successfully</string>
|
<string name="copy_complete">Copied successfully</string>
|
||||||
<string name="arrange_bookshelf">Bookshelf arrangement</string>
|
<string name="bookshelf_management">Bookshelf management</string>
|
||||||
<string name="clear_bookshelf_s">It will delete all books. Be careful,please.</string>
|
<string name="clear_bookshelf_s">It will delete all books. Be careful,please.</string>
|
||||||
<string name="search_book_source">Search book sources</string>
|
<string name="search_book_source">Search book sources</string>
|
||||||
<string name="search_rss_source">Search subscription sources</string>
|
<string name="search_rss_source">Search subscription sources</string>
|
||||||
|
|||||||
@@ -271,7 +271,7 @@
|
|||||||
<string name="load_over_time">Tempo limite de carregamento</string>
|
<string name="load_over_time">Tempo limite de carregamento</string>
|
||||||
<string name="join_group">Siga:%s</string>
|
<string name="join_group">Siga:%s</string>
|
||||||
<string name="copy_complete">Copiado com sucesso</string>
|
<string name="copy_complete">Copiado com sucesso</string>
|
||||||
<string name="arrange_bookshelf">A organização da estante</string>
|
<string name="bookshelf_management">A organização da estante</string>
|
||||||
<string name="clear_bookshelf_s">Isto excluirá todos os livros. Por favor, tenha cuidado.</string>
|
<string name="clear_bookshelf_s">Isto excluirá todos os livros. Por favor, tenha cuidado.</string>
|
||||||
<string name="search_book_source">Pesquisar fontes de livros</string>
|
<string name="search_book_source">Pesquisar fontes de livros</string>
|
||||||
<string name="search_rss_source">Buscar fontes de assinatura</string>
|
<string name="search_rss_source">Buscar fontes de assinatura</string>
|
||||||
|
|||||||
@@ -268,7 +268,7 @@
|
|||||||
<string name="load_over_time">加載超時</string>
|
<string name="load_over_time">加載超時</string>
|
||||||
<string name="join_group">關注: %s</string>
|
<string name="join_group">關注: %s</string>
|
||||||
<string name="copy_complete">拷貝咗</string>
|
<string name="copy_complete">拷貝咗</string>
|
||||||
<string name="arrange_bookshelf">整理書架</string>
|
<string name="bookshelf_management">書架管理</string>
|
||||||
<string name="clear_bookshelf_s">這將會刪除所有書籍,請謹慎操作。</string>
|
<string name="clear_bookshelf_s">這將會刪除所有書籍,請謹慎操作。</string>
|
||||||
<string name="search_book_source">搜索書源</string>
|
<string name="search_book_source">搜索書源</string>
|
||||||
<string name="search_rss_source">搜索訂閲源</string>
|
<string name="search_rss_source">搜索訂閲源</string>
|
||||||
|
|||||||
@@ -270,7 +270,7 @@
|
|||||||
<string name="load_over_time">載入超時</string>
|
<string name="load_over_time">載入超時</string>
|
||||||
<string name="join_group">關注:%s</string>
|
<string name="join_group">關注:%s</string>
|
||||||
<string name="copy_complete">已複製</string>
|
<string name="copy_complete">已複製</string>
|
||||||
<string name="arrange_bookshelf">整理書架</string>
|
<string name="bookshelf_management">書架管理</string>
|
||||||
<string name="clear_bookshelf_s">這將會刪除所有書籍,請謹慎操作。</string>
|
<string name="clear_bookshelf_s">這將會刪除所有書籍,請謹慎操作。</string>
|
||||||
<string name="search_book_source">搜尋書源</string>
|
<string name="search_book_source">搜尋書源</string>
|
||||||
<string name="search_rss_source">搜尋訂閱源</string>
|
<string name="search_rss_source">搜尋訂閱源</string>
|
||||||
|
|||||||
@@ -270,7 +270,7 @@
|
|||||||
<string name="load_over_time">加载超时</string>
|
<string name="load_over_time">加载超时</string>
|
||||||
<string name="join_group">关注:%s</string>
|
<string name="join_group">关注:%s</string>
|
||||||
<string name="copy_complete">已拷贝</string>
|
<string name="copy_complete">已拷贝</string>
|
||||||
<string name="arrange_bookshelf">整理书架</string>
|
<string name="bookshelf_management">书架管理</string>
|
||||||
<string name="clear_bookshelf_s">这将会删除所有书籍,请谨慎操作。</string>
|
<string name="clear_bookshelf_s">这将会删除所有书籍,请谨慎操作。</string>
|
||||||
<string name="search_book_source">搜索书源</string>
|
<string name="search_book_source">搜索书源</string>
|
||||||
<string name="search_rss_source">搜索订阅源</string>
|
<string name="search_rss_source">搜索订阅源</string>
|
||||||
|
|||||||
@@ -271,7 +271,7 @@
|
|||||||
<string name="load_over_time">Loading timeout</string>
|
<string name="load_over_time">Loading timeout</string>
|
||||||
<string name="join_group">Follow:%s</string>
|
<string name="join_group">Follow:%s</string>
|
||||||
<string name="copy_complete">Copied successfully</string>
|
<string name="copy_complete">Copied successfully</string>
|
||||||
<string name="arrange_bookshelf">Bookshelf arrangement</string>
|
<string name="bookshelf_management">Bookshelf management</string>
|
||||||
<string name="clear_bookshelf_s">It will delete all books. Be careful,please.</string>
|
<string name="clear_bookshelf_s">It will delete all books. Be careful,please.</string>
|
||||||
<string name="search_book_source">Search book sources</string>
|
<string name="search_book_source">Search book sources</string>
|
||||||
<string name="search_rss_source">Search subscription sources</string>
|
<string name="search_rss_source">Search subscription sources</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user