kunfei 4 years ago
parent
commit
b79232ffdd

+ 14 - 14
app/src/main/java/io/legado/app/ui/book/local/ImportBookActivity.kt

@@ -41,8 +41,6 @@ class ImportBookActivity : VMBaseActivity<ActivityImportBookBinding, ImportBookV
 
     override val binding by viewBinding(ActivityImportBookBinding::inflate)
     override val viewModel by viewModels<ImportBookViewModel>()
-    private var rootDoc: FileDoc? = null
-    private val subDocs = arrayListOf<FileDoc>()
     private val adapter by lazy { ImportBookAdapter(this, this) }
     private var scanDocJob: Job? = null
 
@@ -59,6 +57,7 @@ class ImportBookActivity : VMBaseActivity<ActivityImportBookBinding, ImportBookV
     }
 
     override fun onActivityCreated(savedInstanceState: Bundle?) {
+        binding.titleBar.setTitle(R.string.book_local)
         initView()
         initEvent()
         initData()
@@ -148,6 +147,7 @@ class ImportBookActivity : VMBaseActivity<ActivityImportBookBinding, ImportBookV
     private fun initRootDoc() {
         val lastPath = AppConfig.importBookPath
         when {
+            viewModel.rootDoc != null -> upPath()
             lastPath.isNullOrEmpty() -> {
                 binding.tvEmptyMsg.visible()
                 selectFolder.launch()
@@ -160,9 +160,9 @@ class ImportBookActivity : VMBaseActivity<ActivityImportBookBinding, ImportBookV
                         binding.tvEmptyMsg.visible()
                         selectFolder.launch()
                     } else {
-                        subDocs.clear()
-                        rootDoc = FileDoc.fromDocumentFile(doc)
-                        upDocs(rootDoc!!)
+                        viewModel.subDocs.clear()
+                        viewModel.rootDoc = FileDoc.fromDocumentFile(doc)
+                        upDocs(viewModel.rootDoc!!)
                     }
                 }.onFailure {
                     binding.tvEmptyMsg.visible()
@@ -184,8 +184,8 @@ class ImportBookActivity : VMBaseActivity<ActivityImportBookBinding, ImportBookV
             .rationale(R.string.tip_perm_request_storage)
             .onGranted {
                 kotlin.runCatching {
-                    rootDoc = FileDoc.fromFile(File(path))
-                    subDocs.clear()
+                    viewModel.rootDoc = FileDoc.fromFile(File(path))
+                    viewModel.subDocs.clear()
                     upPath()
                 }.onFailure {
                     binding.tvEmptyMsg.visible()
@@ -205,7 +205,7 @@ class ImportBookActivity : VMBaseActivity<ActivityImportBookBinding, ImportBookV
 
     @Synchronized
     private fun upPath() {
-        rootDoc?.let {
+        viewModel.rootDoc?.let {
             scanDocJob?.cancel()
             upDocs(it)
         }
@@ -215,7 +215,7 @@ class ImportBookActivity : VMBaseActivity<ActivityImportBookBinding, ImportBookV
         binding.tvEmptyMsg.gone()
         var path = rootDoc.name + File.separator
         var lastDoc = rootDoc
-        for (doc in subDocs) {
+        for (doc in viewModel.subDocs) {
             lastDoc = doc
             path = path + doc.name + File.separator
         }
@@ -229,9 +229,9 @@ class ImportBookActivity : VMBaseActivity<ActivityImportBookBinding, ImportBookV
      * 扫描当前文件夹及所有子文件夹
      */
     private fun scanFolder() {
-        rootDoc?.let { doc ->
+        viewModel.rootDoc?.let { doc ->
             adapter.clearItems()
-            val lastDoc = subDocs.lastOrNull() ?: doc
+            val lastDoc = viewModel.subDocs.lastOrNull() ?: doc
             binding.refreshProgressBar.isAutoLoading = true
             scanDocJob?.cancel()
             scanDocJob = launch(IO) {
@@ -261,14 +261,14 @@ class ImportBookActivity : VMBaseActivity<ActivityImportBookBinding, ImportBookV
 
     @Synchronized
     override fun nextDoc(fileDoc: FileDoc) {
-        subDocs.add(fileDoc)
+        viewModel.subDocs.add(fileDoc)
         upPath()
     }
 
     @Synchronized
     private fun goBackDir(): Boolean {
-        return if (subDocs.isNotEmpty()) {
-            subDocs.removeAt(subDocs.lastIndex)
+        return if (viewModel.subDocs.isNotEmpty()) {
+            viewModel.subDocs.removeAt(viewModel.subDocs.lastIndex)
             upPath()
             true
         } else {

+ 2 - 2
app/src/main/java/io/legado/app/ui/book/local/ImportBookAdapter.kt

@@ -14,9 +14,9 @@ import io.legado.app.utils.*
 
 class ImportBookAdapter(context: Context, val callBack: CallBack) :
     RecyclerAdapter<FileDoc, ItemImportBookBinding>(context) {
-    var selectedUris = hashSetOf<String>()
+    val selectedUris = hashSetOf<String>()
     var checkableCount = 0
-    private var bookFileNames = arrayListOf<String>()
+    private val bookFileNames = arrayListOf<String>()
 
     override fun getViewBinding(parent: ViewGroup): ItemImportBookBinding {
         return ItemImportBookBinding.inflate(inflater, parent, false)

+ 2 - 0
app/src/main/java/io/legado/app/ui/book/local/ImportBookViewModel.kt

@@ -21,6 +21,8 @@ import java.io.File
 import java.util.*
 
 class ImportBookViewModel(application: Application) : BaseViewModel(application) {
+    var rootDoc: FileDoc? = null
+    val subDocs = arrayListOf<FileDoc>()
     var sort = context.getPrefInt(PreferKey.localBookImportSort)
     var dataCallback: DataCallback? = null
     var dataFlowStart: (() -> Unit)? = null

+ 1 - 1
app/src/main/java/io/legado/app/ui/book/remote/RemoteBook.kt

@@ -6,7 +6,7 @@ data class RemoteBook(
     val size: Long,
     val contentType: String,
     val lastModify: Long,
-    val isOnBookShelf: Boolean
+    var isOnBookShelf: Boolean
 ) {
 
     val isDir by lazy {

+ 50 - 38
app/src/main/java/io/legado/app/ui/book/remote/RemoteBookActivity.kt

@@ -1,6 +1,5 @@
 package io.legado.app.ui.book.remote
 
-import android.annotation.SuppressLint
 import android.os.Bundle
 import android.view.Menu
 import android.view.MenuItem
@@ -9,37 +8,42 @@ import androidx.core.view.isGone
 import androidx.recyclerview.widget.LinearLayoutManager
 import io.legado.app.R
 import io.legado.app.base.VMBaseActivity
-
-
-import io.legado.app.databinding.ActivityRemoteBookBinding
+import io.legado.app.databinding.ActivityImportBookBinding
+import io.legado.app.lib.theme.backgroundColor
 import io.legado.app.ui.book.remote.manager.RemoteBookWebDav
+import io.legado.app.ui.widget.SelectActionBar
 import io.legado.app.ui.widget.dialog.WaitDialog
-import io.legado.app.utils.toastOnUi
-
 import io.legado.app.utils.viewbindingdelegate.viewBinding
 import kotlinx.coroutines.flow.conflate
 import kotlinx.coroutines.launch
+import java.io.File
 
 /**
  * 展示远程书籍
  * @author qianfanguojin
  * @time 2022/05/12
  */
-class RemoteBookActivity : VMBaseActivity<ActivityRemoteBookBinding, RemoteBookViewModel>(),
-    RemoteBookAdapter.CallBack {
-    override val binding by viewBinding(ActivityRemoteBookBinding::inflate)
+class RemoteBookActivity : VMBaseActivity<ActivityImportBookBinding, RemoteBookViewModel>(),
+    RemoteBookAdapter.CallBack,
+    SelectActionBar.CallBack {
+    override val binding by viewBinding(ActivityImportBookBinding::inflate)
     override val viewModel by viewModels<RemoteBookViewModel>()
     private val adapter by lazy { RemoteBookAdapter(this, this) }
     private val waitDialog by lazy { WaitDialog(this) }
 
     override fun onActivityCreated(savedInstanceState: Bundle?) {
+        binding.titleBar.setTitle(R.string.remote_book)
         initView()
         initData()
+        initEvent()
     }
 
     private fun initView() {
+        binding.layTop.setBackgroundColor(backgroundColor)
         binding.recyclerView.layoutManager = LinearLayoutManager(this)
         binding.recyclerView.adapter = adapter
+        binding.selectActionBar.setMainActionText(R.string.add_to_shelf)
+        binding.selectActionBar.setCallBack(this)
     }
 
     private fun initData() {
@@ -51,7 +55,14 @@ class RemoteBookActivity : VMBaseActivity<ActivityRemoteBookBinding, RemoteBookV
                 adapter.setItems(remoteBooks)
             }
         }
-        viewModel.loadRemoteBookList(RemoteBookWebDav.rootBookUrl)
+        upPath()
+    }
+
+    private fun initEvent() {
+        binding.tvGoBack.setOnClickListener {
+            viewModel.dirList.removeLastOrNull()
+            upPath()
+        }
     }
 
     override fun onCompatCreateOptionsMenu(menu: Menu): Boolean {
@@ -62,46 +73,47 @@ class RemoteBookActivity : VMBaseActivity<ActivityRemoteBookBinding, RemoteBookV
     override fun onCompatOptionsItemSelected(item: MenuItem): Boolean {
         when (item.itemId) {
             R.id.menu_refresh -> {
-                viewModel.loadRemoteBookList(
-                    viewModel.dirList.lastOrNull()?.path ?: RemoteBookWebDav.rootBookUrl
-                )
+                upPath()
             }
         }
         return super.onCompatOptionsItemSelected(item)
     }
 
-    override fun finish() {
-        if (viewModel.dirList.isEmpty()) {
-            super.finish()
-        } else {
-            viewModel.dirList.removeLastOrNull()
-            val remoteBook = viewModel.dirList.lastOrNull()
-            viewModel.dataCallback?.clear()
-            if (remoteBook != null) {
-                binding.titleBar.title = remoteBook.filename
-                viewModel.loadRemoteBookList(remoteBook.path)
-            } else {
-                binding.titleBar.setTitle(R.string.remote_book)
-                viewModel.loadRemoteBookList(RemoteBookWebDav.rootBookUrl)
-            }
-        }
+    override fun revertSelection() {
+        adapter.revertSelection()
     }
 
-    override fun openDir(remoteBook: RemoteBook) {
-        viewModel.dirList.add(remoteBook)
-        binding.titleBar.title = remoteBook.filename
-        viewModel.dataCallback?.clear()
-        viewModel.loadRemoteBookList(remoteBook.path)
+    override fun selectAll(selectAll: Boolean) {
+        adapter.selectAll(selectAll)
     }
 
-    @SuppressLint("NotifyDataSetChanged")
-    override fun addToBookshelf(remoteBook: RemoteBook) {
+    override fun onClickSelectBarMainAction() {
         waitDialog.show()
-        viewModel.addToBookshelf(remoteBook, success = {
-            toastOnUi(getString(R.string.download_book_success))
+        viewModel.addToBookshelf(adapter.selected) {
             adapter.notifyDataSetChanged()
-        }) {
             waitDialog.dismiss()
         }
     }
+
+    private fun upPath() {
+        var path = "books" + File.separator
+        viewModel.dirList.forEach {
+            path = path + it.filename + File.separator
+        }
+        binding.tvPath.text = path
+        viewModel.dataCallback?.clear()
+        adapter.selected.clear()
+        viewModel.loadRemoteBookList(
+            viewModel.dirList.lastOrNull()?.path ?: RemoteBookWebDav.rootBookUrl
+        )
+    }
+
+    override fun openDir(remoteBook: RemoteBook) {
+        viewModel.dirList.add(remoteBook)
+        upPath()
+    }
+
+    override fun upCountView() {
+        binding.selectActionBar.upCountView(adapter.selected.size, adapter.checkableCount)
+    }
 }

+ 96 - 22
app/src/main/java/io/legado/app/ui/book/remote/RemoteBookAdapter.kt

@@ -1,13 +1,17 @@
 package io.legado.app.ui.book.remote
 
+import android.annotation.SuppressLint
 import android.content.Context
 import android.view.ViewGroup
-import androidx.core.view.isGone
-import cn.hutool.core.date.LocalDateTimeUtil
+import io.legado.app.R
 import io.legado.app.base.adapter.ItemViewHolder
 import io.legado.app.base.adapter.RecyclerAdapter
-import io.legado.app.databinding.ItemRemoteBookBinding
+import io.legado.app.constant.AppConst
+import io.legado.app.databinding.ItemImportBookBinding
 import io.legado.app.utils.ConvertUtils
+import io.legado.app.utils.gone
+import io.legado.app.utils.invisible
+import io.legado.app.utils.visible
 
 
 /**
@@ -15,14 +19,16 @@ import io.legado.app.utils.ConvertUtils
  * @author qianfanguojin
  */
 class RemoteBookAdapter(context: Context, val callBack: CallBack) :
-    RecyclerAdapter<RemoteBook, ItemRemoteBookBinding>(context) {
+    RecyclerAdapter<RemoteBook, ItemImportBookBinding>(context) {
+    var selected = hashSetOf<RemoteBook>()
+    var checkableCount = 0
 
-    override fun getViewBinding(parent: ViewGroup): ItemRemoteBookBinding {
-        return ItemRemoteBookBinding.inflate(inflater, parent, false)
+    override fun getViewBinding(parent: ViewGroup): ItemImportBookBinding {
+        return ItemImportBookBinding.inflate(inflater, parent, false)
     }
 
     override fun onCurrentListChanged() {
-
+        upCheckableCount()
     }
 
     /**
@@ -30,39 +36,107 @@ class RemoteBookAdapter(context: Context, val callBack: CallBack) :
      */
     override fun convert(
         holder: ItemViewHolder,
-        binding: ItemRemoteBookBinding,
+        binding: ItemImportBookBinding,
         item: RemoteBook,
         payloads: MutableList<Any>
     ) {
         binding.run {
-            tvName.text = item.filename.substringBeforeLast(".")
-            tvContentType.text = item.contentType
-            tvSize.text = ConvertUtils.formatFileSize(item.size)
-            tvDate.text =
-                LocalDateTimeUtil.format(LocalDateTimeUtil.of(item.lastModify), "yyyy-MM-dd")
-            llInfo.isGone = item.isDir
-            tvContentType.isGone = item.isDir
-            btnDownload.isGone = item.isDir
+            if (payloads.isEmpty()) {
+                if (item.isDir) {
+                    ivIcon.setImageResource(R.drawable.ic_folder)
+                    ivIcon.visible()
+                    cbSelect.invisible()
+                    llBrief.gone()
+                    cbSelect.isChecked = false
+                } else {
+                    if (item.isOnBookShelf) {
+                        ivIcon.setImageResource(R.drawable.ic_book_has)
+                        ivIcon.visible()
+                        cbSelect.invisible()
+                    } else {
+                        ivIcon.invisible()
+                        cbSelect.visible()
+                    }
+                    llBrief.visible()
+                    tvTag.text = item.contentType
+                    tvSize.text = ConvertUtils.formatFileSize(item.size)
+                    tvDate.text = AppConst.dateFormat.format(item.lastModify)
+                    cbSelect.isChecked = selected.contains(item)
+                }
+                tvName.text = item.filename
+            } else {
+                cbSelect.isChecked = selected.contains(item)
+            }
         }
     }
 
-    override fun registerListener(holder: ItemViewHolder, binding: ItemRemoteBookBinding) {
-        binding.root.setOnClickListener {
+    override fun registerListener(holder: ItemViewHolder, binding: ItemImportBookBinding) {
+        holder.itemView.setOnClickListener {
             getItem(holder.layoutPosition)?.let {
                 if (it.isDir) {
                     callBack.openDir(it)
+                } else if (!it.isOnBookShelf) {
+                    if (!selected.contains(it)) {
+                        selected.add(it)
+                    } else {
+                        selected.remove(it)
+                    }
+                    notifyItemChanged(holder.layoutPosition, true)
+                    callBack.upCountView()
                 }
             }
         }
-        binding.btnDownload.setOnClickListener {
-            getItem(holder.layoutPosition)?.let {
-                callBack.addToBookshelf(it)
+    }
+
+    private fun upCheckableCount() {
+        checkableCount = 0
+        getItems().forEach {
+            if (!it.isDir && !it.isOnBookShelf) {
+                checkableCount++
+            }
+        }
+        callBack.upCountView()
+    }
+
+    @SuppressLint("NotifyDataSetChanged")
+    fun selectAll(selectAll: Boolean) {
+        if (selectAll) {
+            getItems().forEach {
+                if (!it.isDir && !it.isOnBookShelf) {
+                    selected.add(it)
+                }
             }
+        } else {
+            selected.clear()
         }
+        notifyDataSetChanged()
+        callBack.upCountView()
     }
 
+    fun revertSelection() {
+        getItems().forEach {
+            if (!it.isDir) {
+                if (selected.contains(it)) {
+                    selected.remove(it)
+                } else {
+                    selected.add(it)
+                }
+            }
+        }
+        callBack.upCountView()
+    }
+
+    fun removeSelection() {
+        for (i in getItems().lastIndex downTo 0) {
+            if (getItem(i) in selected) {
+                removeItem(i)
+            }
+        }
+    }
+
+
     interface CallBack {
         fun openDir(remoteBook: RemoteBook)
-        fun addToBookshelf(remoteBook: RemoteBook)
+        fun upCountView()
     }
 }

+ 11 - 21
app/src/main/java/io/legado/app/ui/book/remote/RemoteBookViewModel.kt

@@ -1,8 +1,8 @@
 package io.legado.app.ui.book.remote
 
 import android.app.Application
-import android.net.Uri
 import io.legado.app.base.BaseViewModel
+import io.legado.app.constant.AppLog
 import io.legado.app.model.localBook.LocalBook
 import io.legado.app.ui.book.remote.manager.RemoteBookWebDav
 import io.legado.app.utils.toastOnUi
@@ -62,33 +62,23 @@ class RemoteBookViewModel(application: Application): BaseViewModel(application){
         }
     }
 
-    fun addToBookshelf(uriList: HashSet<String>, finally: () -> Unit) {
+    fun addToBookshelf(remoteBooks: HashSet<RemoteBook>, finally: () -> Unit) {
         execute {
-            uriList.forEach {
-                LocalBook.importFile(Uri.parse(it))
+            remoteBooks.forEach { remoteBook ->
+                val downloadBookPath = RemoteBookWebDav.getRemoteBook(remoteBook)
+                downloadBookPath?.let {
+                    LocalBook.importFile(it)
+                    remoteBook.isOnBookShelf = true
+                }
             }
-        }.onFinally {
-            finally.invoke()
-        }
-    }
-
-    /**
-     * 添加书籍到本地书架
-     */
-    fun addToBookshelf(remoteBook: RemoteBook, success: () -> Unit, finally: () -> Unit) {
-        execute {
-            val downloadBookPath = RemoteBookWebDav.getRemoteBook(remoteBook)
-            downloadBookPath?.let {
-                LocalBook.importFile(it)
-            }
-        }.onSuccess {
-            success.invoke()
         }.onError {
-            context.toastOnUi(it.localizedMessage)
+            AppLog.put("导入出错\n${it.localizedMessage}", it)
+            context.toastOnUi("导入出错\n${it.localizedMessage}")
         }.onFinally {
             finally.invoke()
         }
     }
+
     interface DataCallback {
 
         fun setItems(remoteFiles: List<RemoteBook>)

+ 4 - 1
app/src/main/java/io/legado/app/ui/book/remote/manager/RemoteBookWebDav.kt

@@ -108,7 +108,10 @@ object RemoteBookWebDav : RemoteBookManager() {
     }
 
     override suspend fun delete(remoteBookUrl: String): Boolean {
-        TODO("Not yet implemented")
+        AppWebDav.authorization?.let {
+            return WebDav(remoteBookUrl, it).delete()
+        }
+        return false
     }
 
 }

+ 1 - 2
app/src/main/res/layout/activity_import_book.xml

@@ -9,8 +9,7 @@
         android:id="@+id/titleBar"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        app:layout_constraintTop_toTopOf="parent"
-        app:title="@string/book_local" />
+        app:layout_constraintTop_toTopOf="parent" />
 
     <!--path-->
     <LinearLayout

+ 0 - 67
app/src/main/res/layout/activity_remote_book.xml

@@ -1,67 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    xmlns:tools="http://schemas.android.com/tools">
-
-    <io.legado.app.ui.widget.TitleBar
-        android:id="@+id/title_bar"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        app:layout_constraintTop_toTopOf="parent"
-        app:title="@string/remote_book" />
-
-    <io.legado.app.ui.widget.anima.RefreshProgressBar
-        android:id="@+id/refresh_progress_bar"
-        android:layout_width="match_parent"
-        android:layout_height="2dp"
-        app:layout_constraintTop_toBottomOf="@id/title_bar" />
-
-    <io.legado.app.ui.widget.dynamiclayout.DynamicFrameLayout
-        android:id="@+id/content_view"
-        android:layout_width="match_parent"
-        android:layout_height="0dp"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintTop_toBottomOf="@id/refresh_progress_bar">
-
-        <androidx.recyclerview.widget.RecyclerView
-            android:id="@+id/recycler_view"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent" />
-
-        <io.legado.app.ui.widget.anima.RotateLoading
-            android:id="@+id/rotate_loading"
-            android:layout_width="36dp"
-            android:layout_height="36dp"
-            android:layout_margin="6dp"
-            android:visibility="gone"
-            android:layout_gravity="center"
-            app:loading_width="2dp" />
-
-    </io.legado.app.ui.widget.dynamiclayout.DynamicFrameLayout>
-
-    <!--    <io.legado.app.ui.widget.SelectActionBar-->
-    <!--        android:id="@+id/select_action_bar"-->
-    <!--        android:layout_width="match_parent"-->
-    <!--        android:layout_height="wrap_content"-->
-    <!--        app:layout_constraintBottom_toBottomOf="parent"-->
-    <!--        app:layout_constraintTop_toBottomOf="@id/content_view"-->
-    <!--        />-->
-
-    <TextView
-        android:id="@+id/tv_empty_msg"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_margin="16dp"
-        android:gravity="center"
-        android:visibility="gone"
-        android:text="webDav books文件夹为空"
-        app:layout_constraintTop_toBottomOf="@+id/title_bar"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintLeft_toLeftOf="parent"
-        app:layout_constraintRight_toRightOf="parent"
-        tools:text="Empty" />
-
-
-</androidx.constraintlayout.widget.ConstraintLayout>

+ 0 - 108
app/src/main/res/layout/item_remote_book.xml

@@ -1,108 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content">
-
-    <io.legado.app.ui.widget.image.CoverImageView
-        android:id="@+id/iv_cover"
-        android:layout_width="66dp"
-        android:layout_height="90dp"
-        android:layout_margin="8dp"
-        android:contentDescription="@string/img_cover"
-        android:scaleType="centerCrop"
-        android:src="@drawable/image_cover_default"
-        android:transitionName="img_cover"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintLeft_toLeftOf="parent"
-        app:layout_constraintTop_toTopOf="parent"
-        tools:ignore="UnusedAttribute" />
-
-    <TextView
-        android:id="@+id/tv_name"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_margin="8dp"
-        android:text="@string/app_name"
-        android:textColor="@color/primaryText"
-        android:textSize="16sp"
-        app:layout_constraintBottom_toTopOf="@+id/ll_info"
-        app:layout_constraintStart_toEndOf="@+id/iv_cover"
-        app:layout_constraintTop_toTopOf="parent" />
-
-    <LinearLayout
-        android:id="@+id/ll_info"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_margin="8dp"
-        android:gravity="top"
-        android:orientation="horizontal"
-        app:layout_constraintBottom_toTopOf="@+id/tv_content_type"
-        app:layout_constraintLeft_toRightOf="@+id/iv_cover"
-        app:layout_constraintTop_toBottomOf="@+id/tv_name"
-        app:layout_constraintRight_toLeftOf="@+id/btn_download">
-
-        <TextView
-            android:id="@+id/tv_size"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:ellipsize="end"
-            android:lines="1"
-            android:textColor="@color/tv_text_summary"
-            android:textSize="13sp"
-            tools:ignore="TextContrastCheck"
-            tools:text="128kb" />
-
-        <TextView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:ellipsize="end"
-            android:lines="1"
-            android:text="@string/separator"
-            android:textColor="@color/tv_text_summary"
-            android:textSize="11sp"
-            tools:ignore="TextContrastCheck" />
-
-        <TextView
-            android:id="@+id/tv_date"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:ellipsize="end"
-            android:lines="1"
-            android:textColor="@color/tv_text_summary"
-            android:textSize="13sp"
-            tools:ignore="TextContrastCheck"
-            tools:text="2022-12-7" />
-
-    </LinearLayout>
-
-    <io.legado.app.ui.widget.text.AccentBgTextView
-        android:id="@+id/tv_content_type"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_margin="8dp"
-        android:maxWidth="50dp"
-        android:singleLine="true"
-        android:paddingStart="5dp"
-        android:paddingEnd="5dp"
-        android:text="TXT"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintLeft_toRightOf="@+id/iv_cover"
-        app:layout_constraintTop_toBottomOf="@id/ll_info"
-        app:radius="2dp"
-        tools:ignore="HardcodedText,RtlHardcoded" />
-
-    <io.legado.app.ui.widget.text.AccentStrokeTextView
-        android:id="@+id/btn_download"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_margin="8dp"
-        android:padding="6dp"
-        android:text="@string/nb_file_add_shelf"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintRight_toRightOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/tv_name"
-        tools:text="加入书架" />
-
-</androidx.constraintlayout.widget.ConstraintLayout>