pull/1023/head
parent
c06da6ac9b
commit
10861ffe9f
@ -0,0 +1,83 @@ |
|||||||
|
package io.legado.app.ui.main.bookshelf1 |
||||||
|
|
||||||
|
import android.content.Context |
||||||
|
import androidx.core.os.bundleOf |
||||||
|
import androidx.recyclerview.widget.DiffUtil |
||||||
|
import androidx.recyclerview.widget.RecyclerView |
||||||
|
import io.legado.app.data.entities.Book |
||||||
|
|
||||||
|
abstract class BaseBooksAdapter<VH : RecyclerView.ViewHolder>(val context: Context) : |
||||||
|
RecyclerView.Adapter<VH>() { |
||||||
|
|
||||||
|
val diffItemCallback: DiffUtil.ItemCallback<Book> |
||||||
|
get() = object : DiffUtil.ItemCallback<Book>() { |
||||||
|
|
||||||
|
override fun areItemsTheSame(oldItem: Book, newItem: Book): Boolean { |
||||||
|
return oldItem.name == newItem.name |
||||||
|
&& oldItem.author == newItem.author |
||||||
|
} |
||||||
|
|
||||||
|
override fun areContentsTheSame(oldItem: Book, newItem: Book): Boolean { |
||||||
|
return when { |
||||||
|
oldItem.durChapterTime != newItem.durChapterTime -> false |
||||||
|
oldItem.name != newItem.name -> false |
||||||
|
oldItem.author != newItem.author -> false |
||||||
|
oldItem.durChapterTitle != newItem.durChapterTitle -> false |
||||||
|
oldItem.latestChapterTitle != newItem.latestChapterTitle -> false |
||||||
|
oldItem.lastCheckCount != newItem.lastCheckCount -> false |
||||||
|
oldItem.getDisplayCover() != newItem.getDisplayCover() -> false |
||||||
|
oldItem.getUnreadChapterNum() != newItem.getUnreadChapterNum() -> false |
||||||
|
else -> true |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun getChangePayload(oldItem: Book, newItem: Book): Any? { |
||||||
|
val bundle = bundleOf() |
||||||
|
if (oldItem.name != newItem.name) { |
||||||
|
bundle.putString("name", newItem.name) |
||||||
|
} |
||||||
|
if (oldItem.author != newItem.author) { |
||||||
|
bundle.putString("author", newItem.author) |
||||||
|
} |
||||||
|
if (oldItem.durChapterTitle != newItem.durChapterTitle) { |
||||||
|
bundle.putString("dur", newItem.durChapterTitle) |
||||||
|
} |
||||||
|
if (oldItem.latestChapterTitle != newItem.latestChapterTitle) { |
||||||
|
bundle.putString("last", newItem.latestChapterTitle) |
||||||
|
} |
||||||
|
if (oldItem.getDisplayCover() != newItem.getDisplayCover()) { |
||||||
|
bundle.putString("cover", newItem.getDisplayCover()) |
||||||
|
} |
||||||
|
if (oldItem.lastCheckCount != newItem.lastCheckCount |
||||||
|
|| oldItem.durChapterTime != newItem.durChapterTime |
||||||
|
|| oldItem.getUnreadChapterNum() != newItem.getUnreadChapterNum() |
||||||
|
|| oldItem.lastCheckCount != newItem.lastCheckCount |
||||||
|
) { |
||||||
|
bundle.putBoolean("refresh", true) |
||||||
|
} |
||||||
|
if (bundle.isEmpty) return null |
||||||
|
return bundle |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
fun notification(bookUrl: String) { |
||||||
|
// for (i in 0 until itemCount) { |
||||||
|
// getItem(i)?.let { |
||||||
|
// if (it.bookUrl == bookUrl) { |
||||||
|
// notifyItemChanged(i, bundleOf(Pair("refresh", null))) |
||||||
|
// return |
||||||
|
// } |
||||||
|
// } |
||||||
|
// } |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
interface CallBack { |
||||||
|
fun onItemClick(position: Int) |
||||||
|
fun onItemLongClick(position: Int) |
||||||
|
fun isUpdate(bookUrl: String): Boolean |
||||||
|
fun getItemCount(): Int |
||||||
|
fun getItem(position: Int): Any |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,104 @@ |
|||||||
|
package io.legado.app.ui.main.bookshelf1 |
||||||
|
|
||||||
|
import android.content.Context |
||||||
|
import android.os.Bundle |
||||||
|
import android.view.LayoutInflater |
||||||
|
import android.view.ViewGroup |
||||||
|
import androidx.recyclerview.widget.RecyclerView |
||||||
|
import io.legado.app.constant.BookType |
||||||
|
import io.legado.app.data.entities.Book |
||||||
|
import io.legado.app.data.entities.BookGroup |
||||||
|
import io.legado.app.databinding.ItemBookshelfGridBinding |
||||||
|
import io.legado.app.help.AppConfig |
||||||
|
import io.legado.app.utils.invisible |
||||||
|
import splitties.views.onLongClick |
||||||
|
|
||||||
|
class BooksAdapterGrid(context: Context, private val callBack: CallBack) : |
||||||
|
BaseBooksAdapter<BooksAdapterGrid.ItemViewHolder>(context) { |
||||||
|
|
||||||
|
override fun getItemCount(): Int { |
||||||
|
return callBack.getItemCount() |
||||||
|
} |
||||||
|
|
||||||
|
override fun onCreateViewHolder( |
||||||
|
parent: ViewGroup, |
||||||
|
viewType: Int |
||||||
|
): ItemViewHolder { |
||||||
|
return ItemViewHolder( |
||||||
|
ItemBookshelfGridBinding.inflate(LayoutInflater.from(context), parent, false) |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
override fun onBindViewHolder( |
||||||
|
holder: ItemViewHolder, |
||||||
|
position: Int, |
||||||
|
payloads: MutableList<Any> |
||||||
|
) { |
||||||
|
holder.binding.run { |
||||||
|
val bundle = payloads.getOrNull(0) as? Bundle |
||||||
|
if (bundle == null) { |
||||||
|
super.onBindViewHolder(holder, position, payloads) |
||||||
|
} else { |
||||||
|
when (val item = callBack.getItem(position)) { |
||||||
|
is Book -> { |
||||||
|
bundle.keySet().forEach { |
||||||
|
when (it) { |
||||||
|
"name" -> tvName.text = item.name |
||||||
|
"cover" -> ivCover.load( |
||||||
|
item.getDisplayCover(), |
||||||
|
item.name, |
||||||
|
item.author |
||||||
|
) |
||||||
|
"refresh" -> upRefresh(this, item) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
is BookGroup -> { |
||||||
|
tvName.text = item.groupName |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { |
||||||
|
holder.binding.run { |
||||||
|
when (val item = callBack.getItem(position)) { |
||||||
|
is Book -> { |
||||||
|
tvName.text = item.name |
||||||
|
ivCover.load(item.getDisplayCover(), item.name, item.author) |
||||||
|
upRefresh(this, item) |
||||||
|
} |
||||||
|
is BookGroup -> { |
||||||
|
tvName.text = item.groupName |
||||||
|
} |
||||||
|
} |
||||||
|
root.setOnClickListener { |
||||||
|
callBack.onItemClick(position) |
||||||
|
} |
||||||
|
root.onLongClick { |
||||||
|
callBack.onItemLongClick(position) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private fun upRefresh(binding: ItemBookshelfGridBinding, item: Book) { |
||||||
|
if (item.origin != BookType.local && callBack.isUpdate(item.bookUrl)) { |
||||||
|
binding.bvUnread.invisible() |
||||||
|
binding.rlLoading.show() |
||||||
|
} else { |
||||||
|
binding.rlLoading.hide() |
||||||
|
if (AppConfig.showUnread) { |
||||||
|
binding.bvUnread.setBadgeCount(item.getUnreadChapterNum()) |
||||||
|
binding.bvUnread.setHighlight(item.lastCheckCount > 0) |
||||||
|
} else { |
||||||
|
binding.bvUnread.invisible() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class ItemViewHolder(val binding: ItemBookshelfGridBinding) : |
||||||
|
RecyclerView.ViewHolder(binding.root) |
||||||
|
|
||||||
|
} |
@ -0,0 +1,119 @@ |
|||||||
|
package io.legado.app.ui.main.bookshelf1 |
||||||
|
|
||||||
|
import android.content.Context |
||||||
|
import android.os.Bundle |
||||||
|
import android.view.LayoutInflater |
||||||
|
import android.view.ViewGroup |
||||||
|
import androidx.recyclerview.widget.RecyclerView |
||||||
|
import io.legado.app.constant.BookType |
||||||
|
import io.legado.app.data.entities.Book |
||||||
|
import io.legado.app.data.entities.BookGroup |
||||||
|
import io.legado.app.databinding.ItemBookshelfListBinding |
||||||
|
import io.legado.app.help.AppConfig |
||||||
|
import io.legado.app.utils.gone |
||||||
|
import io.legado.app.utils.invisible |
||||||
|
import io.legado.app.utils.visible |
||||||
|
import splitties.views.onLongClick |
||||||
|
|
||||||
|
class BooksAdapterList(context: Context, private val callBack: CallBack) : |
||||||
|
BaseBooksAdapter<BooksAdapterList.ItemViewHolder>(context) { |
||||||
|
|
||||||
|
override fun getItemCount(): Int { |
||||||
|
return callBack.getItemCount() |
||||||
|
} |
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { |
||||||
|
return ItemViewHolder( |
||||||
|
ItemBookshelfListBinding.inflate(LayoutInflater.from(context), parent, false) |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
override fun onBindViewHolder( |
||||||
|
holder: ItemViewHolder, |
||||||
|
position: Int, |
||||||
|
payloads: MutableList<Any> |
||||||
|
) { |
||||||
|
val bundle = payloads.getOrNull(0) as? Bundle |
||||||
|
if (bundle == null) { |
||||||
|
super.onBindViewHolder(holder, position, payloads) |
||||||
|
} else { |
||||||
|
holder.binding.run { |
||||||
|
when (val item = callBack.getItem(position)) { |
||||||
|
is Book -> { |
||||||
|
tvRead.text = item.durChapterTitle |
||||||
|
tvLast.text = item.latestChapterTitle |
||||||
|
bundle.keySet().forEach { |
||||||
|
when (it) { |
||||||
|
"name" -> tvName.text = item.name |
||||||
|
"author" -> tvAuthor.text = item.author |
||||||
|
"cover" -> ivCover.load( |
||||||
|
item.getDisplayCover(), |
||||||
|
item.name, |
||||||
|
item.author |
||||||
|
) |
||||||
|
"refresh" -> upRefresh(this, item) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
is BookGroup -> { |
||||||
|
tvName.text = item.groupName |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { |
||||||
|
holder.binding.run { |
||||||
|
when (val item = callBack.getItem(position)) { |
||||||
|
is Book -> { |
||||||
|
tvName.text = item.name |
||||||
|
tvAuthor.text = item.author |
||||||
|
tvRead.text = item.durChapterTitle |
||||||
|
tvLast.text = item.latestChapterTitle |
||||||
|
ivCover.load(item.getDisplayCover(), item.name, item.author) |
||||||
|
flHasNew.visible() |
||||||
|
ivAuthor.visible() |
||||||
|
ivLast.visible() |
||||||
|
ivRead.visible() |
||||||
|
upRefresh(this, item) |
||||||
|
} |
||||||
|
is BookGroup -> { |
||||||
|
tvName.text = item.groupName |
||||||
|
flHasNew.gone() |
||||||
|
ivAuthor.gone() |
||||||
|
ivLast.gone() |
||||||
|
ivRead.gone() |
||||||
|
tvAuthor.gone() |
||||||
|
tvLast.gone() |
||||||
|
tvRead.gone() |
||||||
|
} |
||||||
|
} |
||||||
|
root.setOnClickListener { |
||||||
|
callBack.onItemClick(position) |
||||||
|
} |
||||||
|
root.onLongClick { |
||||||
|
callBack.onItemLongClick(position) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private fun upRefresh(binding: ItemBookshelfListBinding, item: Book) { |
||||||
|
if (item.origin != BookType.local && callBack.isUpdate(item.bookUrl)) { |
||||||
|
binding.bvUnread.invisible() |
||||||
|
binding.rlLoading.show() |
||||||
|
} else { |
||||||
|
binding.rlLoading.hide() |
||||||
|
if (AppConfig.showUnread) { |
||||||
|
binding.bvUnread.setHighlight(item.lastCheckCount > 0) |
||||||
|
binding.bvUnread.setBadgeCount(item.getUnreadChapterNum()) |
||||||
|
} else { |
||||||
|
binding.bvUnread.invisible() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class ItemViewHolder(val binding: ItemBookshelfListBinding) : |
||||||
|
RecyclerView.ViewHolder(binding.root) |
||||||
|
|
||||||
|
} |
@ -0,0 +1,329 @@ |
|||||||
|
package io.legado.app.ui.main.bookshelf1 |
||||||
|
|
||||||
|
import android.annotation.SuppressLint |
||||||
|
import android.os.Bundle |
||||||
|
import android.view.Menu |
||||||
|
import android.view.MenuItem |
||||||
|
import android.view.View |
||||||
|
import androidx.appcompat.widget.SearchView |
||||||
|
import androidx.core.view.isGone |
||||||
|
import androidx.fragment.app.activityViewModels |
||||||
|
import androidx.fragment.app.viewModels |
||||||
|
import androidx.lifecycle.LiveData |
||||||
|
import androidx.recyclerview.widget.GridLayoutManager |
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager |
||||||
|
import androidx.recyclerview.widget.RecyclerView |
||||||
|
import io.legado.app.R |
||||||
|
import io.legado.app.base.VMBaseFragment |
||||||
|
import io.legado.app.constant.AppConst |
||||||
|
import io.legado.app.constant.BookType |
||||||
|
import io.legado.app.constant.EventBus |
||||||
|
import io.legado.app.constant.PreferKey |
||||||
|
import io.legado.app.data.appDb |
||||||
|
import io.legado.app.data.entities.Book |
||||||
|
import io.legado.app.data.entities.BookGroup |
||||||
|
import io.legado.app.databinding.DialogBookshelfConfigBinding |
||||||
|
import io.legado.app.databinding.DialogEditTextBinding |
||||||
|
import io.legado.app.databinding.FragmentBookshelf1Binding |
||||||
|
import io.legado.app.help.AppConfig |
||||||
|
import io.legado.app.lib.dialogs.alert |
||||||
|
import io.legado.app.lib.theme.ATH |
||||||
|
import io.legado.app.lib.theme.accentColor |
||||||
|
import io.legado.app.ui.audio.AudioPlayActivity |
||||||
|
import io.legado.app.ui.book.arrange.ArrangeBookActivity |
||||||
|
import io.legado.app.ui.book.cache.CacheActivity |
||||||
|
import io.legado.app.ui.book.group.GroupManageDialog |
||||||
|
import io.legado.app.ui.book.info.BookInfoActivity |
||||||
|
import io.legado.app.ui.book.local.ImportBookActivity |
||||||
|
import io.legado.app.ui.book.read.ReadBookActivity |
||||||
|
import io.legado.app.ui.book.search.SearchActivity |
||||||
|
import io.legado.app.ui.document.FilePicker |
||||||
|
import io.legado.app.ui.document.FilePickerParam |
||||||
|
import io.legado.app.ui.main.MainViewModel |
||||||
|
import io.legado.app.ui.main.bookshelf.BookshelfViewModel |
||||||
|
import io.legado.app.utils.* |
||||||
|
import io.legado.app.utils.viewbindingdelegate.viewBinding |
||||||
|
import kotlin.math.max |
||||||
|
|
||||||
|
/** |
||||||
|
* 书架界面 |
||||||
|
*/ |
||||||
|
class BookshelfFragment : VMBaseFragment<BookshelfViewModel>(R.layout.fragment_bookshelf1), |
||||||
|
SearchView.OnQueryTextListener, |
||||||
|
BaseBooksAdapter.CallBack { |
||||||
|
|
||||||
|
private val binding by viewBinding(FragmentBookshelf1Binding::bind) |
||||||
|
override val viewModel: BookshelfViewModel by viewModels() |
||||||
|
private val activityViewModel: MainViewModel by activityViewModels() |
||||||
|
private lateinit var booksAdapter: BaseBooksAdapter<*> |
||||||
|
private var groupId = AppConst.bookGroupNoneId |
||||||
|
private var bookGroupLiveData: LiveData<List<BookGroup>>? = null |
||||||
|
private var bookshelfLiveData: LiveData<List<Book>>? = null |
||||||
|
private var bookGroups: List<BookGroup> = emptyList() |
||||||
|
private var books: List<Book> = emptyList() |
||||||
|
|
||||||
|
private val importBookshelf = registerForActivityResult(FilePicker()) { |
||||||
|
it?.readText(requireContext())?.let { text -> |
||||||
|
viewModel.importBookshelf(text, groupId) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { |
||||||
|
setSupportToolbar(binding.titleBar.toolbar) |
||||||
|
initView() |
||||||
|
initGroupData() |
||||||
|
initBooksData() |
||||||
|
} |
||||||
|
|
||||||
|
override fun onCompatCreateOptionsMenu(menu: Menu) { |
||||||
|
menuInflater.inflate(R.menu.main_bookshelf, menu) |
||||||
|
} |
||||||
|
|
||||||
|
override fun onCompatOptionsItemSelected(item: MenuItem) { |
||||||
|
super.onCompatOptionsItemSelected(item) |
||||||
|
when (item.itemId) { |
||||||
|
R.id.menu_search -> startActivity<SearchActivity>() |
||||||
|
R.id.menu_update_toc -> activityViewModel.upToc(books) |
||||||
|
R.id.menu_bookshelf_layout -> configBookshelf() |
||||||
|
R.id.menu_group_manage -> GroupManageDialog() |
||||||
|
.show(childFragmentManager, "groupManageDialog") |
||||||
|
R.id.menu_add_local -> startActivity<ImportBookActivity>() |
||||||
|
R.id.menu_add_url -> addBookByUrl() |
||||||
|
R.id.menu_arrange_bookshelf -> startActivity<ArrangeBookActivity> { |
||||||
|
putExtra("groupId", groupId) |
||||||
|
} |
||||||
|
R.id.menu_download -> startActivity<CacheActivity> { |
||||||
|
putExtra("groupId", groupId) |
||||||
|
} |
||||||
|
R.id.menu_export_bookshelf -> viewModel.exportBookshelf(books) { |
||||||
|
activity?.share(it) |
||||||
|
} |
||||||
|
R.id.menu_import_bookshelf -> importBookshelfAlert() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private fun initView() { |
||||||
|
ATH.applyEdgeEffectColor(binding.rvBookshelf) |
||||||
|
binding.refreshLayout.setColorSchemeColors(accentColor) |
||||||
|
binding.refreshLayout.setOnRefreshListener { |
||||||
|
binding.refreshLayout.isRefreshing = false |
||||||
|
activityViewModel.upToc(books) |
||||||
|
} |
||||||
|
val bookshelfLayout = getPrefInt(PreferKey.bookshelfLayout) |
||||||
|
if (bookshelfLayout == 0) { |
||||||
|
binding.rvBookshelf.layoutManager = LinearLayoutManager(context) |
||||||
|
booksAdapter = BooksAdapterList(requireContext(), this) |
||||||
|
} else { |
||||||
|
binding.rvBookshelf.layoutManager = GridLayoutManager(context, bookshelfLayout + 2) |
||||||
|
booksAdapter = BooksAdapterGrid(requireContext(), this) |
||||||
|
} |
||||||
|
binding.rvBookshelf.adapter = booksAdapter |
||||||
|
booksAdapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() { |
||||||
|
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) { |
||||||
|
val layoutManager = binding.rvBookshelf.layoutManager |
||||||
|
if (positionStart == 0 && layoutManager is LinearLayoutManager) { |
||||||
|
val scrollTo = layoutManager.findFirstVisibleItemPosition() - itemCount |
||||||
|
binding.rvBookshelf.scrollToPosition(max(0, scrollTo)) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) { |
||||||
|
val layoutManager = binding.rvBookshelf.layoutManager |
||||||
|
if (toPosition == 0 && layoutManager is LinearLayoutManager) { |
||||||
|
val scrollTo = layoutManager.findFirstVisibleItemPosition() - itemCount |
||||||
|
binding.rvBookshelf.scrollToPosition(max(0, scrollTo)) |
||||||
|
} |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
private fun initGroupData() { |
||||||
|
bookGroupLiveData?.removeObservers(this) |
||||||
|
bookGroupLiveData = appDb.bookGroupDao.liveDataShow().apply { |
||||||
|
observe(viewLifecycleOwner) { |
||||||
|
if (it.size != bookGroups.size) { |
||||||
|
bookGroups = it |
||||||
|
booksAdapter.notifyDataSetChanged() |
||||||
|
} else { |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private fun initBooksData() { |
||||||
|
bookshelfLiveData?.removeObservers(this) |
||||||
|
bookshelfLiveData = when (groupId) { |
||||||
|
AppConst.bookGroupAllId -> appDb.bookDao.observeAll() |
||||||
|
AppConst.bookGroupLocalId -> appDb.bookDao.observeLocal() |
||||||
|
AppConst.bookGroupAudioId -> appDb.bookDao.observeAudio() |
||||||
|
AppConst.bookGroupNoneId -> appDb.bookDao.observeNoGroup() |
||||||
|
else -> appDb.bookDao.observeByGroup(groupId) |
||||||
|
}.apply { |
||||||
|
observe(viewLifecycleOwner) { list -> |
||||||
|
binding.tvEmptyMsg.isGone = list.isNotEmpty() |
||||||
|
books = when (getPrefInt(PreferKey.bookshelfSort)) { |
||||||
|
1 -> list.sortedByDescending { |
||||||
|
it.latestChapterTime |
||||||
|
} |
||||||
|
2 -> list.sortedWith { o1, o2 -> |
||||||
|
o1.name.cnCompare(o2.name) |
||||||
|
} |
||||||
|
3 -> list.sortedBy { |
||||||
|
it.order |
||||||
|
} |
||||||
|
else -> list.sortedByDescending { |
||||||
|
it.durChapterTime |
||||||
|
} |
||||||
|
} |
||||||
|
booksAdapter.notifyDataSetChanged() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun onQueryTextSubmit(query: String?): Boolean { |
||||||
|
startActivity<SearchActivity> { |
||||||
|
putExtra("key", query) |
||||||
|
} |
||||||
|
return false |
||||||
|
} |
||||||
|
|
||||||
|
override fun onQueryTextChange(newText: String?): Boolean { |
||||||
|
return false |
||||||
|
} |
||||||
|
|
||||||
|
@SuppressLint("InflateParams") |
||||||
|
private fun configBookshelf() { |
||||||
|
alert(titleResource = R.string.bookshelf_layout) { |
||||||
|
val bookshelfLayout = getPrefInt(PreferKey.bookshelfLayout) |
||||||
|
val bookshelfSort = getPrefInt(PreferKey.bookshelfSort) |
||||||
|
val alertBinding = |
||||||
|
DialogBookshelfConfigBinding.inflate(layoutInflater) |
||||||
|
.apply { |
||||||
|
rgLayout.checkByIndex(bookshelfLayout) |
||||||
|
rgSort.checkByIndex(bookshelfSort) |
||||||
|
swShowUnread.isChecked = AppConfig.showUnread |
||||||
|
} |
||||||
|
customView { alertBinding.root } |
||||||
|
okButton { |
||||||
|
alertBinding.apply { |
||||||
|
var changed = false |
||||||
|
if (bookshelfLayout != rgLayout.getCheckedIndex()) { |
||||||
|
putPrefInt(PreferKey.bookshelfLayout, rgLayout.getCheckedIndex()) |
||||||
|
changed = true |
||||||
|
} |
||||||
|
if (bookshelfSort != rgSort.getCheckedIndex()) { |
||||||
|
putPrefInt(PreferKey.bookshelfSort, rgSort.getCheckedIndex()) |
||||||
|
changed = true |
||||||
|
} |
||||||
|
if (AppConfig.showUnread != swShowUnread.isChecked) { |
||||||
|
AppConfig.showUnread = swShowUnread.isChecked |
||||||
|
changed = true |
||||||
|
} |
||||||
|
if (changed) { |
||||||
|
activity?.recreate() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
noButton() |
||||||
|
}.show() |
||||||
|
} |
||||||
|
|
||||||
|
@SuppressLint("InflateParams") |
||||||
|
private fun addBookByUrl() { |
||||||
|
alert(titleResource = R.string.add_book_url) { |
||||||
|
val alertBinding = DialogEditTextBinding.inflate(layoutInflater) |
||||||
|
customView { alertBinding.root } |
||||||
|
okButton { |
||||||
|
alertBinding.editView.text?.toString()?.let { |
||||||
|
viewModel.addBookByUrl(it) |
||||||
|
} |
||||||
|
} |
||||||
|
noButton() |
||||||
|
}.show() |
||||||
|
} |
||||||
|
|
||||||
|
fun gotoTop() { |
||||||
|
if (AppConfig.isEInkMode) { |
||||||
|
binding.rvBookshelf.scrollToPosition(0) |
||||||
|
} else { |
||||||
|
binding.rvBookshelf.smoothScrollToPosition(0) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private fun importBookshelfAlert() { |
||||||
|
alert(titleResource = R.string.import_bookshelf) { |
||||||
|
val alertBinding = DialogEditTextBinding.inflate(layoutInflater).apply { |
||||||
|
editView.hint = "url/json" |
||||||
|
} |
||||||
|
customView { alertBinding.root } |
||||||
|
okButton { |
||||||
|
alertBinding.editView.text?.toString()?.let { |
||||||
|
viewModel.importBookshelf(it, groupId) |
||||||
|
} |
||||||
|
} |
||||||
|
noButton() |
||||||
|
neutralButton(R.string.select_file) { |
||||||
|
importBookshelf.launch( |
||||||
|
FilePickerParam( |
||||||
|
mode = FilePicker.FILE, |
||||||
|
allowExtensions = arrayOf("txt", "json") |
||||||
|
) |
||||||
|
) |
||||||
|
} |
||||||
|
}.show() |
||||||
|
} |
||||||
|
|
||||||
|
override fun onItemClick(position: Int) { |
||||||
|
if (position < bookGroups.size) { |
||||||
|
val bookGroup = bookGroups[position] |
||||||
|
|
||||||
|
} else { |
||||||
|
val book = books[position - bookGroups.size] |
||||||
|
when (book.type) { |
||||||
|
BookType.audio -> |
||||||
|
startActivity<AudioPlayActivity> { |
||||||
|
putExtra("bookUrl", book.bookUrl) |
||||||
|
} |
||||||
|
else -> startActivity<ReadBookActivity> { |
||||||
|
putExtra("bookUrl", book.bookUrl) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun onItemLongClick(position: Int) { |
||||||
|
if (position < bookGroups.size) { |
||||||
|
|
||||||
|
} else { |
||||||
|
val book = books[position - bookGroups.size] |
||||||
|
startActivity<BookInfoActivity> { |
||||||
|
putExtra("name", book.name) |
||||||
|
putExtra("author", book.author) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun isUpdate(bookUrl: String): Boolean { |
||||||
|
return bookUrl in activityViewModel.updateList |
||||||
|
} |
||||||
|
|
||||||
|
override fun getItemCount(): Int { |
||||||
|
return bookGroups.size + books.size |
||||||
|
} |
||||||
|
|
||||||
|
override fun getItem(position: Int): Any { |
||||||
|
return if (position < bookGroups.size) { |
||||||
|
bookGroups[position] |
||||||
|
} else { |
||||||
|
books[position - bookGroups.size] |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun observeLiveBus() { |
||||||
|
super.observeLiveBus() |
||||||
|
observeEvent<String>(EventBus.UP_BOOK) { |
||||||
|
booksAdapter.notification(it) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,48 @@ |
|||||||
|
<?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="match_parent" |
||||||
|
android:orientation="vertical"> |
||||||
|
|
||||||
|
<io.legado.app.ui.widget.TitleBar |
||||||
|
android:id="@+id/title_bar" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
app:attachToActivity="false" |
||||||
|
app:contentLayout="@layout/view_search" |
||||||
|
app:layout_constraintTop_toTopOf="parent" |
||||||
|
app:title="@string/bookshelf" /> |
||||||
|
|
||||||
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout |
||||||
|
android:id="@+id/refresh_layout" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="0dp" |
||||||
|
app:layout_constraintTop_toBottomOf="@+id/title_bar" |
||||||
|
app:layout_constraintBottom_toBottomOf="parent"> |
||||||
|
|
||||||
|
<io.legado.app.ui.widget.recycler.RecyclerViewAtPager2 |
||||||
|
android:id="@+id/rv_bookshelf" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent" |
||||||
|
tools:listitem="@layout/item_bookshelf_list" /> |
||||||
|
|
||||||
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:id="@+id/tv_empty_msg" |
||||||
|
android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_gravity="center" |
||||||
|
android:layout_margin="16dp" |
||||||
|
android:gravity="center" |
||||||
|
android:text="@string/bookshelf_empty" |
||||||
|
android:visibility="gone" |
||||||
|
app:layout_constraintTop_toBottomOf="@+id/title_bar" |
||||||
|
app:layout_constraintBottom_toBottomOf="parent" |
||||||
|
app:layout_constraintLeft_toLeftOf="parent" |
||||||
|
app:layout_constraintRight_toRightOf="parent" |
||||||
|
tools:text="TextView" /> |
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout> |
Loading…
Reference in new issue