Merge remote-tracking branch 'origin/master'

This commit is contained in:
kunfei
2023-03-17 08:40:36 +08:00
7 changed files with 76 additions and 24 deletions
@@ -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)
}
}