Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -37,6 +37,10 @@ object BookType {
|
||||
*/
|
||||
const val local = 0b100000000
|
||||
|
||||
/**
|
||||
* 512 压缩包 表明书籍文件是从压缩包内解压来的
|
||||
*/
|
||||
const val archive = 0b1000000000
|
||||
|
||||
@Target(AnnotationTarget.VALUE_PARAMETER)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
|
||||
@@ -355,7 +355,7 @@ object DatabaseMigrations {
|
||||
db.execSQL(
|
||||
"""
|
||||
update books set type = type | ${BookType.local}
|
||||
where origin = '${BookType.localTag}' or origin like '${BookType.webDavTag}%'
|
||||
where origin like '${BookType.localTag}%' or origin like '${BookType.webDavTag}%'
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -55,6 +55,19 @@ val Book.isWebFile: Boolean
|
||||
val Book.isUpError: Boolean
|
||||
get() = isType(BookType.updateError)
|
||||
|
||||
val Book.isArchive: Boolean
|
||||
get() = isType(BookType.archive)
|
||||
|
||||
val Book.archiveName: String?
|
||||
get() {
|
||||
return if (isArchive) {
|
||||
// local_book::archive.rar
|
||||
origin.substring(BookType.localTag.length + 2)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun Book.contains(word: String?): Boolean {
|
||||
if (word.isNullOrEmpty()) {
|
||||
return true
|
||||
@@ -139,7 +152,7 @@ fun Book.removeLocalUriCache() {
|
||||
|
||||
fun Book.getRemoteUrl(): String? {
|
||||
if (origin.startsWith(BookType.webDavTag)) {
|
||||
return origin.substring(8)
|
||||
return origin.substring(BookType.webDavTag.length)
|
||||
}
|
||||
return null
|
||||
}
|
||||
@@ -175,7 +188,7 @@ fun Book.upType() {
|
||||
BookSourceType.file -> BookType.webFile
|
||||
else -> BookType.text
|
||||
}
|
||||
if (origin == "loc_book" || origin.startsWith(BookType.webDavTag)) {
|
||||
if (origin == BookType.localTag || origin.startsWith(BookType.webDavTag)) {
|
||||
type = type or BookType.local
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,18 +190,24 @@ object LocalBook {
|
||||
|
||||
/* 导入压缩包内的书籍 */
|
||||
fun importArchiveFile(
|
||||
uri: Uri,
|
||||
archiveFileUri: Uri,
|
||||
saveFileName: String? = null,
|
||||
filter: ((String) -> Boolean)? = null
|
||||
): List<Book> {
|
||||
val files = ArchiveUtils.deCompress(uri, filter = filter)
|
||||
val archiveFileDoc = FileDoc.fromUri(archiveFileUri, false)
|
||||
val files = ArchiveUtils.deCompress(archiveFileDoc, filter = filter)
|
||||
if (files.isEmpty()) throw NoStackTraceException(appCtx.getString(R.string.unsupport_archivefile_entry))
|
||||
return files.map {
|
||||
saveBookFile(
|
||||
FileInputStream(it),
|
||||
saveFileName ?: it.name
|
||||
).let {
|
||||
importFile(it)
|
||||
importFile(it).apply {
|
||||
//附加压缩包文件名 以便判断书籍导入界面压缩包是否导入
|
||||
origin = "${BookType.localTag}::${archiveFileDoc.name}"
|
||||
addType(BookType.archive)
|
||||
save()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,9 +13,7 @@ import io.legado.app.lib.dialogs.alert
|
||||
import io.legado.app.lib.theme.primaryTextColor
|
||||
import io.legado.app.ui.book.read.ReadBookActivity
|
||||
import io.legado.app.ui.document.HandleFileContract
|
||||
import io.legado.app.utils.applyTint
|
||||
import io.legado.app.utils.hideSoftInput
|
||||
import io.legado.app.utils.startActivity
|
||||
import io.legado.app.utils.*
|
||||
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||
|
||||
import kotlin.coroutines.resume
|
||||
|
||||
@@ -11,6 +11,7 @@ import androidx.documentfile.provider.DocumentFile
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import io.legado.app.R
|
||||
import io.legado.app.constant.AppConst
|
||||
import io.legado.app.constant.AppPattern
|
||||
import io.legado.app.constant.PreferKey
|
||||
import io.legado.app.data.appDb
|
||||
import io.legado.app.databinding.DialogEditTextBinding
|
||||
@@ -132,7 +133,7 @@ class ImportBookActivity : BaseImportBookActivity<ImportBookViewModel>(),
|
||||
initRootDoc()
|
||||
}
|
||||
launch {
|
||||
appDb.bookDao.flowLocalUri().conflate().collect {
|
||||
appDb.bookDao.flowLocal().conflate().collect {
|
||||
adapter.upBookHas(it)
|
||||
}
|
||||
}
|
||||
@@ -300,6 +301,21 @@ class ImportBookActivity : BaseImportBookActivity<ImportBookViewModel>(),
|
||||
binding.selectActionBar.upCountView(adapter.selectedUris.size, adapter.checkableCount)
|
||||
}
|
||||
|
||||
override fun startRead(bookUrl: String) = startReadBook(bookUrl)
|
||||
override fun startRead(fileDoc: FileDoc) {
|
||||
if (!ArchiveUtils.isArchive(fileDoc.name)) {
|
||||
startReadBook(fileDoc.toString())
|
||||
} else {
|
||||
val fileNames = ArchiveUtils.getArchiveFilesName(fileDoc) {
|
||||
it.matches(AppPattern.bookFileRegex)
|
||||
}
|
||||
if (fileNames.size == 1) {
|
||||
appDb.bookDao.getBookByFileName(fileNames[0])?.let {
|
||||
startReadBook(it.bookUrl)
|
||||
}
|
||||
} else {
|
||||
//onArchiveFileClick(fileNames)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,7 +8,10 @@ import io.legado.app.R
|
||||
import io.legado.app.base.adapter.ItemViewHolder
|
||||
import io.legado.app.base.adapter.RecyclerAdapter
|
||||
import io.legado.app.constant.AppConst
|
||||
import io.legado.app.data.entities.Book
|
||||
import io.legado.app.databinding.ItemImportBookBinding
|
||||
import io.legado.app.help.book.archiveName
|
||||
import io.legado.app.help.book.isArchive
|
||||
import io.legado.app.utils.*
|
||||
|
||||
|
||||
@@ -16,7 +19,7 @@ class ImportBookAdapter(context: Context, val callBack: CallBack) :
|
||||
RecyclerAdapter<FileDoc, ItemImportBookBinding>(context) {
|
||||
val selectedUris = hashSetOf<String>()
|
||||
var checkableCount = 0
|
||||
private val bookNamesOnBookShelf = arrayListOf<String>()
|
||||
private val bookOrArchiveNamesOnBookShelf = arrayListOf<String>()
|
||||
|
||||
override fun getViewBinding(parent: ViewGroup): ItemImportBookBinding {
|
||||
return ItemImportBookBinding.inflate(inflater, parent, false)
|
||||
@@ -41,7 +44,7 @@ class ImportBookAdapter(context: Context, val callBack: CallBack) :
|
||||
llBrief.gone()
|
||||
cbSelect.isChecked = false
|
||||
} else {
|
||||
if (bookNamesOnBookShelf.contains(item.name)) {
|
||||
if (isOnBookShelf(item)) {
|
||||
ivIcon.setImageResource(R.drawable.ic_book_has)
|
||||
ivIcon.visible()
|
||||
cbSelect.invisible()
|
||||
@@ -67,7 +70,7 @@ class ImportBookAdapter(context: Context, val callBack: CallBack) :
|
||||
getItem(holder.layoutPosition)?.let {
|
||||
if (it.isDir) {
|
||||
callBack.nextDoc(it)
|
||||
} else if (!bookNamesOnBookShelf.contains(it.name)) {
|
||||
} else if (!isOnBookShelf(it)) {
|
||||
if (!selectedUris.contains(it.toString())) {
|
||||
selectedUris.add(it.toString())
|
||||
} else {
|
||||
@@ -77,18 +80,30 @@ class ImportBookAdapter(context: Context, val callBack: CallBack) :
|
||||
callBack.upCountView()
|
||||
} else {
|
||||
/* 点击开始阅读 */
|
||||
callBack.startRead(it.toString())
|
||||
callBack.startRead(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun isOnBookShelf(fileDoc: FileDoc): Boolean {
|
||||
return bookOrArchiveNamesOnBookShelf.contains(fileDoc.name)
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
fun upBookHas(bookUrls: List<String>) {
|
||||
bookNamesOnBookShelf.clear()
|
||||
bookUrls.forEach {
|
||||
val path = Uri.decode(it)
|
||||
bookNamesOnBookShelf.add(FileUtils.getName(path))
|
||||
fun upBookHas(books: List<Book>) {
|
||||
bookOrArchiveNamesOnBookShelf.clear()
|
||||
books.forEach {
|
||||
if (it.isArchive) {
|
||||
bookOrArchiveNamesOnBookShelf.add(
|
||||
it.archiveName!!
|
||||
)
|
||||
} else {
|
||||
val path = Uri.decode(it.bookUrl)
|
||||
bookOrArchiveNamesOnBookShelf.add(
|
||||
FileUtils.getName(path)
|
||||
)
|
||||
}
|
||||
}
|
||||
notifyDataSetChanged()
|
||||
upCheckableCount()
|
||||
@@ -97,7 +112,7 @@ class ImportBookAdapter(context: Context, val callBack: CallBack) :
|
||||
private fun upCheckableCount() {
|
||||
checkableCount = 0
|
||||
getItems().forEach {
|
||||
if (!it.isDir && !bookNamesOnBookShelf.contains(it.name)) {
|
||||
if (!it.isDir && !isOnBookShelf(it)) {
|
||||
checkableCount++
|
||||
}
|
||||
}
|
||||
@@ -108,7 +123,7 @@ class ImportBookAdapter(context: Context, val callBack: CallBack) :
|
||||
fun selectAll(selectAll: Boolean) {
|
||||
if (selectAll) {
|
||||
getItems().forEach {
|
||||
if (!it.isDir && !bookNamesOnBookShelf.contains(it.name)) {
|
||||
if (!it.isDir && !isOnBookShelf(it)) {
|
||||
selectedUris.add(it.toString())
|
||||
}
|
||||
}
|
||||
@@ -121,7 +136,7 @@ class ImportBookAdapter(context: Context, val callBack: CallBack) :
|
||||
|
||||
fun revertSelection() {
|
||||
getItems().forEach {
|
||||
if (!it.isDir && !bookNamesOnBookShelf.contains(it.name)) {
|
||||
if (!it.isDir && !isOnBookShelf(it)) {
|
||||
if (selectedUris.contains(it.toString())) {
|
||||
selectedUris.remove(it.toString())
|
||||
} else {
|
||||
@@ -144,7 +159,7 @@ class ImportBookAdapter(context: Context, val callBack: CallBack) :
|
||||
interface CallBack {
|
||||
fun nextDoc(fileDoc: FileDoc)
|
||||
fun upCountView()
|
||||
fun startRead(bookUrl: String)
|
||||
fun startRead(fileDoc: FileDoc)
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user