mirror of
https://github.com/gedoor/legado.git
synced 2025-08-10 00:52:30 +00:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -44,9 +44,6 @@ interface BookDao {
|
||||
)
|
||||
fun flowLocalNoGroup(): Flow<List<Book>>
|
||||
|
||||
@Query("SELECT bookUrl FROM books WHERE type & ${BookType.local} > 0")
|
||||
fun flowLocalUri(): Flow<List<String>>
|
||||
|
||||
@Query("SELECT * FROM books WHERE (`group` & :group) > 0")
|
||||
fun flowByGroup(group: Long): Flow<List<Book>>
|
||||
|
||||
@@ -104,7 +101,7 @@ interface BookDao {
|
||||
@Query("select 1 from books where bookUrl = :bookUrl")
|
||||
fun has(bookUrl: String): Boolean?
|
||||
|
||||
@Query("select 1 from books where originName = :fileName")
|
||||
@Query("select 1 from books where originName = :fileName or origin like '%' || :fileName")
|
||||
fun hasFile(fileName: String): Boolean?
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
|
||||
@@ -62,7 +62,8 @@ val Book.archiveName: String?
|
||||
get() {
|
||||
return if (isArchive) {
|
||||
// local_book::archive.rar
|
||||
origin.substring(BookType.localTag.length + 2)
|
||||
// webDav::https://...../archive.rar
|
||||
origin.substringAfter("::").substringAfterLast("/")
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
@@ -213,12 +213,27 @@ object LocalBook {
|
||||
}
|
||||
|
||||
/* 批量导入 支持自动导入压缩包的支持书籍 */
|
||||
fun importFiles(uri: Uri): List<Book> {
|
||||
val books = mutableListOf<Book>()
|
||||
val fileDoc = FileDoc.fromUri(uri, false)
|
||||
if (ArchiveUtils.isArchive(fileDoc.name)) {
|
||||
books.addAll(
|
||||
importArchiveFile(uri) {
|
||||
it.matches(AppPattern.bookFileRegex)
|
||||
}
|
||||
)
|
||||
} else {
|
||||
books.add(importFile(uri))
|
||||
}
|
||||
return books
|
||||
}
|
||||
|
||||
fun importFiles(uris: List<Uri>) {
|
||||
var errorCount = 0
|
||||
uris.forEach { uri ->
|
||||
val fileDoc = FileDoc.fromUri(uri, false)
|
||||
kotlin.runCatching {
|
||||
if (ArchiveUtils.isArchive(fileDoc.name)) {
|
||||
if (ArchiveUtils.isArchive(fileDoc.name)) {
|
||||
importArchiveFile(uri) {
|
||||
it.matches(AppPattern.bookFileRegex)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.legado.app.model.remote
|
||||
|
||||
import android.net.Uri
|
||||
import io.legado.app.constant.AppPattern.archiveFileRegex
|
||||
import io.legado.app.constant.AppPattern.bookFileRegex
|
||||
import io.legado.app.constant.BookType
|
||||
import io.legado.app.data.entities.Book
|
||||
@@ -39,7 +40,8 @@ class RemoteBookWebDav(
|
||||
val remoteWebDavFileList: List<WebDavFile> = WebDav(path, authorization).listFiles()
|
||||
//转化远程文件信息到本地对象
|
||||
remoteWebDavFileList.forEach { webDavFile ->
|
||||
if (webDavFile.isDir || bookFileRegex.matches(webDavFile.displayName)) {
|
||||
if (webDavFile.isDir || bookFileRegex.matches(webDavFile.displayName) || archiveFileRegex.matches(webDavFile.displayName)
|
||||
) {
|
||||
//扩展名符合阅读的格式则认为是书籍
|
||||
remoteBooks.add(RemoteBook(webDavFile))
|
||||
}
|
||||
|
||||
@@ -98,15 +98,16 @@ abstract class BaseImportBookActivity<VM : ViewModel> : VMBaseActivity<ActivityI
|
||||
it.matches(AppPattern.bookFileRegex)
|
||||
}
|
||||
if (fileNames.size == 1) {
|
||||
appDb.bookDao.getBookByFileName(fileNames[0])?.let {
|
||||
val name = fileNames[0]
|
||||
appDb.bookDao.getBookByFileName(name)?.let {
|
||||
startReadBook(it.bookUrl)
|
||||
} ?: toastOnUi(R.string.no_book_found_bookshelf)
|
||||
} ?: showImportAlert(fileDoc, name)
|
||||
} else {
|
||||
showSelectBookReadAlert(fileNames)
|
||||
showSelectBookReadAlert(fileDoc, fileNames)
|
||||
}
|
||||
}
|
||||
|
||||
private fun showSelectBookReadAlert(fileNames: List<String>) {
|
||||
private fun showSelectBookReadAlert(fileDoc: FileDoc, fileNames: List<String>) {
|
||||
if (fileNames.isEmpty()) {
|
||||
toastOnUi(R.string.unsupport_archivefile_entry)
|
||||
return
|
||||
@@ -117,7 +118,29 @@ abstract class BaseImportBookActivity<VM : ViewModel> : VMBaseActivity<ActivityI
|
||||
) { _, name, _ ->
|
||||
appDb.bookDao.getBookByFileName(name)?.let {
|
||||
startReadBook(it.bookUrl)
|
||||
} ?: toastOnUi(R.string.no_book_found_bookshelf)
|
||||
} ?: showImportAlert(fileDoc, name)
|
||||
}
|
||||
}
|
||||
|
||||
open fun addArchiveToBookShelf(
|
||||
fileDoc: FileDoc,
|
||||
fileName: String,
|
||||
onSuccess: (String) -> Unit
|
||||
) {
|
||||
}
|
||||
|
||||
/* 提示是否重新导入所点击的压缩文件 */
|
||||
private fun showImportAlert(fileDoc: FileDoc, fileName: String) {
|
||||
alert(
|
||||
R.string.draw,
|
||||
R.string.no_book_found_bookshelf
|
||||
) {
|
||||
okButton {
|
||||
addArchiveToBookShelf(fileDoc, fileName) {
|
||||
startReadBook(it)
|
||||
}
|
||||
}
|
||||
noButton()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -131,11 +131,6 @@ class ImportBookActivity : BaseImportBookActivity<ImportBookViewModel>(),
|
||||
viewModel.dataFlowStart = {
|
||||
initRootDoc()
|
||||
}
|
||||
launch {
|
||||
appDb.bookDao.flowLocal().conflate().collect {
|
||||
adapter.upBookHas(it)
|
||||
}
|
||||
}
|
||||
launch {
|
||||
viewModel.dataFlow.conflate().collect { docs ->
|
||||
adapter.setItems(docs)
|
||||
@@ -308,4 +303,11 @@ class ImportBookActivity : BaseImportBookActivity<ImportBookViewModel>(),
|
||||
}
|
||||
}
|
||||
|
||||
override fun addArchiveToBookShelf(
|
||||
fileDoc: FileDoc,
|
||||
fileName: String,
|
||||
onSuccess: (String) -> Unit
|
||||
) {
|
||||
viewModel.addArchiveToBookShelf(fileDoc, fileName, onSuccess)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ 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.model.localBook.LocalBook
|
||||
import io.legado.app.utils.*
|
||||
|
||||
|
||||
@@ -19,7 +20,6 @@ class ImportBookAdapter(context: Context, val callBack: CallBack) :
|
||||
RecyclerAdapter<FileDoc, ItemImportBookBinding>(context) {
|
||||
val selectedUris = hashSetOf<String>()
|
||||
var checkableCount = 0
|
||||
private val bookOrArchiveNamesOnBookShelf = arrayListOf<String>()
|
||||
|
||||
override fun getViewBinding(parent: ViewGroup): ItemImportBookBinding {
|
||||
return ItemImportBookBinding.inflate(inflater, parent, false)
|
||||
@@ -87,26 +87,7 @@ class ImportBookAdapter(context: Context, val callBack: CallBack) :
|
||||
}
|
||||
|
||||
private fun isOnBookShelf(fileDoc: FileDoc): Boolean {
|
||||
return bookOrArchiveNamesOnBookShelf.contains(fileDoc.name)
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
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()
|
||||
return LocalBook.isOnBookShelf(fileDoc.name)
|
||||
}
|
||||
|
||||
private fun upCheckableCount() {
|
||||
|
||||
@@ -97,6 +97,18 @@ class ImportBookViewModel(application: Application) : BaseViewModel(application)
|
||||
}
|
||||
}
|
||||
|
||||
fun addArchiveToBookShelf(
|
||||
fileDoc: FileDoc,
|
||||
fileName: String,
|
||||
onSuccess: (String) -> Unit
|
||||
) {
|
||||
LocalBook.importArchiveFile(fileDoc.uri, fileName) {
|
||||
it.contains(fileName)
|
||||
}.firstOrNull()?.run {
|
||||
onSuccess.invoke(bookUrl)
|
||||
}
|
||||
}
|
||||
|
||||
fun deleteDoc(uriList: HashSet<String>, finally: () -> Unit) {
|
||||
execute {
|
||||
uriList.forEach {
|
||||
|
||||
@@ -124,18 +124,17 @@ class RemoteBookViewModel(application: Application) : BaseViewModel(application)
|
||||
|
||||
fun addToBookshelf(remoteBooks: HashSet<RemoteBook>, finally: () -> Unit) {
|
||||
execute {
|
||||
val bookWebDav = remoteBookWebDav
|
||||
?: throw NoStackTraceException("没有配置webDav")
|
||||
remoteBooks.forEach { remoteBook ->
|
||||
val bookWebDav = remoteBookWebDav
|
||||
?: throw NoStackTraceException("没有配置webDav")
|
||||
val downloadBookPath = bookWebDav.downloadRemoteBook(remoteBook)
|
||||
downloadBookPath.let {
|
||||
val localBook = LocalBook.importFile(it)
|
||||
localBook.origin = BookType.webDavTag + CustomUrl(remoteBook.path)
|
||||
val downloadBookUri = bookWebDav.downloadRemoteBook(remoteBook)
|
||||
LocalBook.importFiles(downloadBookUri).forEach { book ->
|
||||
book.origin = BookType.webDavTag + CustomUrl(remoteBook.path)
|
||||
.putAttribute(
|
||||
"serverID",
|
||||
bookWebDav.serverID
|
||||
).toString()
|
||||
localBook.save()
|
||||
book.save()
|
||||
remoteBook.isOnBookShelf = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +77,21 @@ object UrlUtil {
|
||||
conn.instanceFollowRedirects = false
|
||||
conn.connect()
|
||||
|
||||
if (AppConfig.recordLog || BuildConfig.DEBUG) {
|
||||
val headers = conn.headerFields
|
||||
val headersString = buildString {
|
||||
headers.forEach { (key, value) ->
|
||||
value.forEach {
|
||||
append(key)
|
||||
append(": ")
|
||||
append(it)
|
||||
append("\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
AppLog.put("${url.toString()} response header:\n$headersString")
|
||||
}
|
||||
|
||||
// val fileSize = conn.getContentLengthLong() / 1024
|
||||
/** Content-Disposition 存在三种情况 文件名应该用引号 有些用空格
|
||||
* filename="filename"
|
||||
@@ -114,21 +129,7 @@ object UrlUtil {
|
||||
val newUrl= URL(URLDecoder.decode(redirectUrl, "UTF-8"))
|
||||
getFileNameFromPath(newUrl)
|
||||
} else {
|
||||
AppLog.put("Cannot obtain URL file name, enable recordLog for detail")
|
||||
if (AppConfig.recordLog || BuildConfig.DEBUG) {
|
||||
val headers = conn.headerFields
|
||||
val headersString = buildString {
|
||||
headers.forEach { (key, value) ->
|
||||
value.forEach {
|
||||
append(key)
|
||||
append(": ")
|
||||
append(it)
|
||||
append("\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
AppLog.put("${url.toString()} response header:\n$headersString")
|
||||
}
|
||||
AppLog.put("Cannot obtain URL file name, enable recordLog for response header")
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1083,5 +1083,5 @@
|
||||
<string name="unsupport_archivefile_entry">Cannot find supported files in archive</string>
|
||||
<string name="no_books_dir">没有设置书籍保存位置!</string>
|
||||
<string name="delete_alert">删除提醒</string>
|
||||
<string name="no_book_found_bookshelf">No book found in bookshelf</string>
|
||||
<string name="no_book_found_bookshelf">No book found in bookshelf, import again ?</string>
|
||||
</resources>
|
||||
|
||||
@@ -1086,5 +1086,5 @@
|
||||
<string name="unsupport_archivefile_entry">Cannot find supported files in archive</string>
|
||||
<string name="no_books_dir">没有设置书籍保存位置!</string>
|
||||
<string name="delete_alert">删除提醒</string>
|
||||
<string name="no_book_found_bookshelf">No book found in bookshelf</string>
|
||||
<string name="no_book_found_bookshelf">No book found in bookshelf, import again ?</string>
|
||||
</resources>
|
||||
|
||||
@@ -1086,5 +1086,5 @@
|
||||
<string name="unsupport_archivefile_entry">Cannot find supported files in archive</string>
|
||||
<string name="no_books_dir">没有设置书籍保存位置!</string>
|
||||
<string name="delete_alert">删除提醒</string>
|
||||
<string name="no_book_found_bookshelf">No book found in bookshelf</string>
|
||||
<string name="no_book_found_bookshelf">No book found in bookshelf, import again ?</string>
|
||||
</resources>
|
||||
|
||||
@@ -1083,5 +1083,5 @@
|
||||
<string name="unsupport_archivefile_entry">压缩文件内没有支持的文件</string>
|
||||
<string name="no_books_dir">没有设置书籍保存位置!</string>
|
||||
<string name="delete_alert">删除提醒</string>
|
||||
<string name="no_book_found_bookshelf">未在书架上找到所选书籍</string>
|
||||
<string name="no_book_found_bookshelf">未在书架上找到所选书籍, 是否重新导入?</string>
|
||||
</resources>
|
||||
|
||||
@@ -1085,5 +1085,5 @@
|
||||
<string name="unsupport_archivefile_entry">压缩文件内没有支持的文件</string>
|
||||
<string name="no_books_dir">没有设置书籍保存位置!</string>
|
||||
<string name="delete_alert">删除提醒</string>
|
||||
<string name="no_book_found_bookshelf">未在书架上找到所选书籍</string>
|
||||
<string name="no_book_found_bookshelf">未在书架上找到所选书籍, 是否重新导入?</string>
|
||||
</resources>
|
||||
|
||||
@@ -1085,5 +1085,5 @@
|
||||
<string name="unsupport_archivefile_entry">压缩文件内没有支持的文件</string>
|
||||
<string name="no_books_dir">没有设置书籍保存位置!</string>
|
||||
<string name="delete_alert">删除提醒</string>
|
||||
<string name="no_book_found_bookshelf">未在书架上找到所选书籍</string>
|
||||
<string name="no_book_found_bookshelf">未在书架上找到所选书籍, 是否重新导入?</string>
|
||||
</resources>
|
||||
|
||||
@@ -1086,5 +1086,5 @@
|
||||
<string name="unsupport_archivefile_entry">Cannot find supported files in archive</string>
|
||||
<string name="no_books_dir">没有设置书籍保存位置!</string>
|
||||
<string name="delete_alert">删除提醒</string>
|
||||
<string name="no_book_found_bookshelf">No book found in bookshelf</string>
|
||||
<string name="no_book_found_bookshelf">No book found in bookshelf, import again ?</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user