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