pull/737/head
Robot 4 years ago
commit 0537499e69
  1. 1
      app/src/main/assets/updateLog.md
  2. 13
      app/src/main/java/io/legado/app/data/dao/SearchBookDao.kt
  3. 56
      app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceDialog.kt
  4. 15
      app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceViewModel.kt
  5. 14
      app/src/main/java/io/legado/app/ui/book/search/SearchActivity.kt
  6. 10
      app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt
  7. 11
      app/src/main/java/io/legado/app/ui/main/explore/ExploreFragment.kt
  8. 11
      app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceActivity.kt
  9. 5
      app/src/main/res/menu/change_source.xml

@ -7,6 +7,7 @@
* 修复bug * 修复bug
* 网络访问框架修改为RxHttp, 有bug及时反馈 * 网络访问框架修改为RxHttp, 有bug及时反馈
* 优化进度同步 * 优化进度同步
* 换源界面添加分组选择
**2020/12/11** **2020/12/11**
* 修复因修改进度同步导致的bug * 修复因修改进度同步导致的bug

@ -27,22 +27,27 @@ interface SearchBookDao {
select t1.name, t1.author, t1.origin, t1.originName, t1.coverUrl, t1.bookUrl, t1.type, t1.time, t1.intro, t1.kind, t1.latestChapterTitle, t1.tocUrl, t1.variable, t1.wordCount, t2.customOrder as originOrder select t1.name, t1.author, t1.origin, t1.originName, t1.coverUrl, t1.bookUrl, t1.type, t1.time, t1.intro, t1.kind, t1.latestChapterTitle, t1.tocUrl, t1.variable, t1.wordCount, t2.customOrder as originOrder
from searchBooks as t1 inner join book_sources as t2 from searchBooks as t1 inner join book_sources as t2
on t1.origin = t2.bookSourceUrl on t1.origin = t2.bookSourceUrl
where t1.name = :name and t1.author = :author and t2.enabled = 1 where t1.name = :name and t1.author = :author and t2.enabled = 1 and t2.bookSourceGroup like '%'||:sourceGroup||'%'
order by t2.customOrder order by t2.customOrder
""" """
) )
fun getByNameAuthorEnable(name: String, author: String): List<SearchBook> fun getChangeSourceSearch(name: String, author: String, sourceGroup: String): List<SearchBook>
@Query( @Query(
""" """
select t1.name, t1.author, t1.origin, t1.originName, t1.coverUrl, t1.bookUrl, t1.type, t1.time, t1.intro, t1.kind, t1.latestChapterTitle, t1.tocUrl, t1.variable, t1.wordCount, t2.customOrder as originOrder select t1.name, t1.author, t1.origin, t1.originName, t1.coverUrl, t1.bookUrl, t1.type, t1.time, t1.intro, t1.kind, t1.latestChapterTitle, t1.tocUrl, t1.variable, t1.wordCount, t2.customOrder as originOrder
from searchBooks as t1 inner join book_sources as t2 from searchBooks as t1 inner join book_sources as t2
on t1.origin = t2.bookSourceUrl on t1.origin = t2.bookSourceUrl
where t1.name = :name and t1.author = :author and originName like '%'||:key||'%' and t2.enabled = 1 where t1.name = :name and t1.author = :author and originName like '%'||:key||'%' and t2.enabled = 1 and t2.bookSourceGroup like '%'||:sourceGroup||'%'
order by t2.customOrder order by t2.customOrder
""" """
) )
fun getChangeSourceSearch(name: String, author: String, key: String): List<SearchBook> fun getChangeSourceSearch(
name: String,
author: String,
key: String,
sourceGroup: String
): List<SearchBook>
@Query( @Query(
""" """

@ -1,29 +1,26 @@
package io.legado.app.ui.book.changesource package io.legado.app.ui.book.changesource
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.*
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import io.legado.app.App
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.BaseDialogFragment import io.legado.app.base.BaseDialogFragment
import io.legado.app.constant.AppPattern
import io.legado.app.constant.PreferKey import io.legado.app.constant.PreferKey
import io.legado.app.data.entities.Book import io.legado.app.data.entities.Book
import io.legado.app.data.entities.SearchBook import io.legado.app.data.entities.SearchBook
import io.legado.app.databinding.DialogChangeSourceBinding import io.legado.app.databinding.DialogChangeSourceBinding
import io.legado.app.help.AppConfig import io.legado.app.help.AppConfig
import io.legado.app.lib.theme.primaryColor import io.legado.app.lib.theme.primaryColor
import io.legado.app.ui.book.source.manage.BookSourceActivity
import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.ui.widget.recycler.VerticalDivider
import io.legado.app.utils.applyTint import io.legado.app.utils.*
import io.legado.app.utils.getSize
import io.legado.app.utils.getViewModel
import io.legado.app.utils.putPrefBoolean
import io.legado.app.utils.viewbindingdelegate.viewBinding import io.legado.app.utils.viewbindingdelegate.viewBinding
@ -47,6 +44,7 @@ class ChangeSourceDialog : BaseDialogFragment(),
} }
private val binding by viewBinding(DialogChangeSourceBinding::bind) private val binding by viewBinding(DialogChangeSourceBinding::bind)
private val groups = linkedSetOf<String>()
private var callBack: CallBack? = null private var callBack: CallBack? = null
private lateinit var viewModel: ChangeSourceViewModel private lateinit var viewModel: ChangeSourceViewModel
lateinit var adapter: ChangeSourceAdapter lateinit var adapter: ChangeSourceAdapter
@ -90,6 +88,7 @@ class ChangeSourceDialog : BaseDialogFragment(),
binding.toolBar.menu.findItem(R.id.menu_load_info)?.isChecked = binding.toolBar.menu.findItem(R.id.menu_load_info)?.isChecked =
AppConfig.changeSourceLoadInfo AppConfig.changeSourceLoadInfo
binding.toolBar.menu.findItem(R.id.menu_load_toc)?.isChecked = AppConfig.changeSourceLoadToc binding.toolBar.menu.findItem(R.id.menu_load_toc)?.isChecked = AppConfig.changeSourceLoadToc
} }
private fun initRecyclerView() { private fun initRecyclerView() {
@ -150,6 +149,13 @@ class ChangeSourceDialog : BaseDialogFragment(),
adapter.setItems(it) adapter.setItems(it)
diffResult.dispatchUpdatesTo(adapter) diffResult.dispatchUpdatesTo(adapter)
}) })
App.db.bookSourceDao.liveGroupEnabled().observe(this, {
groups.clear()
it.map { group ->
groups.addAll(group.splitNotBlank(AppPattern.splitGroupRegex))
}
upGroupMenu()
})
} }
private val stopMenuItem: MenuItem? private val stopMenuItem: MenuItem?
@ -166,6 +172,18 @@ class ChangeSourceDialog : BaseDialogFragment(),
item.isChecked = !item.isChecked item.isChecked = !item.isChecked
} }
R.id.menu_stop -> viewModel.stopSearch() R.id.menu_stop -> viewModel.stopSearch()
R.id.menu_source_manage -> startActivity<BookSourceActivity>()
else -> if (item?.groupId == R.id.source_group) {
if (!item.isChecked) {
item.isChecked = true
if (item.title.toString() == getString(R.string.all_source)) {
putPrefString("searchGroup", "")
} else {
putPrefString("searchGroup", item.title.toString())
}
viewModel.stopSearch()
}
}
} }
return false return false
} }
@ -184,6 +202,28 @@ class ChangeSourceDialog : BaseDialogFragment(),
viewModel.disableSource(searchBook) viewModel.disableSource(searchBook)
} }
/**
* 更新分组菜单
*/
private fun upGroupMenu() {
val menu: Menu = binding.toolBar.menu
val selectedGroup = getPrefString("searchGroup") ?: ""
menu.removeGroup(R.id.source_group)
var item = menu.add(R.id.source_group, Menu.NONE, Menu.NONE, R.string.all_source)
if (selectedGroup == "") {
item?.isChecked = true
}
groups.sortedWith { o1, o2 ->
o1.cnCompare(o2)
}.map {
item = menu.add(R.id.source_group, Menu.NONE, Menu.NONE, it)
if (it == selectedGroup) {
item.isChecked = true
}
}
menu.setGroupCheckable(R.id.source_group, true, true)
}
interface CallBack { interface CallBack {
val oldBook: Book? val oldBook: Book?
fun changeTo(book: Book) fun changeTo(book: Book)

@ -17,6 +17,7 @@ import io.legado.app.help.AppConfig
import io.legado.app.help.coroutine.CompositeCoroutine import io.legado.app.help.coroutine.CompositeCoroutine
import io.legado.app.model.webBook.WebBook import io.legado.app.model.webBook.WebBook
import io.legado.app.utils.getPrefBoolean import io.legado.app.utils.getPrefBoolean
import io.legado.app.utils.getPrefString
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.ExecutorCoroutineDispatcher import kotlinx.coroutines.ExecutorCoroutineDispatcher
import kotlinx.coroutines.asCoroutineDispatcher import kotlinx.coroutines.asCoroutineDispatcher
@ -38,6 +39,7 @@ class ChangeSourceViewModel(application: Application) : BaseViewModel(applicatio
private val searchBooks = CopyOnWriteArraySet<SearchBook>() private val searchBooks = CopyOnWriteArraySet<SearchBook>()
private var postTime = 0L private var postTime = 0L
private val sendRunnable = Runnable { upAdapter() } private val sendRunnable = Runnable { upAdapter() }
private val searchGroup get() = App.INSTANCE.getPrefString("searchGroup") ?: ""
@Volatile @Volatile
private var searchIndex = -1 private var searchIndex = -1
@ -60,7 +62,9 @@ class ChangeSourceViewModel(application: Application) : BaseViewModel(applicatio
fun loadDbSearchBook() { fun loadDbSearchBook() {
execute { execute {
App.db.searchBookDao.getByNameAuthorEnable(name, author).let { searchBooks.clear()
upAdapter()
App.db.searchBookDao.getChangeSourceSearch(name, author, searchGroup).let {
searchBooks.addAll(it) searchBooks.addAll(it)
if (it.size <= 1) { if (it.size <= 1) {
upAdapter() upAdapter()
@ -98,7 +102,11 @@ class ChangeSourceViewModel(application: Application) : BaseViewModel(applicatio
private fun startSearch() { private fun startSearch() {
execute { execute {
bookSourceList.clear() bookSourceList.clear()
bookSourceList.addAll(App.db.bookSourceDao.allEnabled) if (searchGroup.isNullOrBlank()) {
bookSourceList.addAll(App.db.bookSourceDao.allEnabled)
} else {
bookSourceList.addAll(App.db.bookSourceDao.getEnabledByGroup(searchGroup))
}
searchStateData.postValue(true) searchStateData.postValue(true)
initSearchPool() initSearchPool()
for (i in 0 until threadCount) { for (i in 0 until threadCount) {
@ -191,7 +199,8 @@ class ChangeSourceViewModel(application: Application) : BaseViewModel(applicatio
if (key.isNullOrEmpty()) { if (key.isNullOrEmpty()) {
loadDbSearchBook() loadDbSearchBook()
} else { } else {
val items = App.db.searchBookDao.getChangeSourceSearch(name, author, screenKey) val items =
App.db.searchBookDao.getChangeSourceSearch(name, author, screenKey, searchGroup)
searchBooks.clear() searchBooks.clear()
searchBooks.addAll(items) searchBooks.addAll(items)
upAdapter() upAdapter()

@ -30,7 +30,6 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.jetbrains.anko.sdk27.listeners.onClick import org.jetbrains.anko.sdk27.listeners.onClick
import org.jetbrains.anko.startActivity import org.jetbrains.anko.startActivity
import java.text.Collator
class SearchActivity : VMBaseActivity<ActivityBookSearchBinding, SearchViewModel>(), class SearchActivity : VMBaseActivity<ActivityBookSearchBinding, SearchViewModel>(),
@ -245,13 +244,14 @@ class SearchActivity : VMBaseActivity<ActivityBookSearchBinding, SearchViewModel
if (selectedGroup == "") { if (selectedGroup == "") {
item?.isChecked = true item?.isChecked = true
} }
groups.sortedWith(Collator.getInstance(java.util.Locale.CHINESE)) groups.sortedWith { o1, o2 ->
.map { o1.cnCompare(o2)
item = menu?.add(R.id.source_group, Menu.NONE, Menu.NONE, it) }.map {
if (it == selectedGroup) { item = menu?.add(R.id.source_group, Menu.NONE, Menu.NONE, it)
item?.isChecked = true if (it == selectedGroup) {
} item?.isChecked = true
} }
}
menu?.setGroupCheckable(R.id.source_group, true, true) menu?.setGroupCheckable(R.id.source_group, true, true)
} }

@ -44,7 +44,6 @@ import org.jetbrains.anko.startActivity
import org.jetbrains.anko.startActivityForResult import org.jetbrains.anko.startActivityForResult
import org.jetbrains.anko.toast import org.jetbrains.anko.toast
import java.io.File import java.io.File
import java.text.Collator
class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceViewModel>(), class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceViewModel>(),
PopupMenu.OnMenuItemClickListener, PopupMenu.OnMenuItemClickListener,
@ -342,10 +341,11 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
private fun upGroupMenu() { private fun upGroupMenu() {
groupMenu?.removeGroup(R.id.source_group) groupMenu?.removeGroup(R.id.source_group)
groups.sortedWith(Collator.getInstance(java.util.Locale.CHINESE)) groups.sortedWith { o1, o2 ->
.map { o1.cnCompare(o2)
groupMenu?.add(R.id.source_group, Menu.NONE, Menu.NONE, it) }.map {
} groupMenu?.add(R.id.source_group, Menu.NONE, Menu.NONE, it)
}
} }
@SuppressLint("InflateParams") @SuppressLint("InflateParams")

@ -22,11 +22,11 @@ import io.legado.app.lib.theme.ATH
import io.legado.app.lib.theme.primaryTextColor import io.legado.app.lib.theme.primaryTextColor
import io.legado.app.ui.book.explore.ExploreShowActivity import io.legado.app.ui.book.explore.ExploreShowActivity
import io.legado.app.ui.book.source.edit.BookSourceEditActivity import io.legado.app.ui.book.source.edit.BookSourceEditActivity
import io.legado.app.utils.cnCompare
import io.legado.app.utils.getViewModel import io.legado.app.utils.getViewModel
import io.legado.app.utils.splitNotBlank import io.legado.app.utils.splitNotBlank
import io.legado.app.utils.startActivity import io.legado.app.utils.startActivity
import io.legado.app.utils.viewbindingdelegate.viewBinding import io.legado.app.utils.viewbindingdelegate.viewBinding
import java.text.Collator
/** /**
* 发现界面 * 发现界面
@ -126,10 +126,11 @@ class ExploreFragment : VMBaseFragment<ExploreViewModel>(R.layout.fragment_explo
private fun upGroupsMenu() { private fun upGroupsMenu() {
groupsMenu?.let { subMenu -> groupsMenu?.let { subMenu ->
subMenu.removeGroup(R.id.menu_group_text) subMenu.removeGroup(R.id.menu_group_text)
groups.sortedWith(Collator.getInstance(java.util.Locale.CHINESE)) groups.sortedWith { o1, o2 ->
.forEach { o1.cnCompare(o2)
subMenu.add(R.id.menu_group_text, Menu.NONE, Menu.NONE, it) }.forEach {
} subMenu.add(R.id.menu_group_text, Menu.NONE, Menu.NONE, it)
}
} }
} }

@ -40,8 +40,6 @@ import org.jetbrains.anko.startActivity
import org.jetbrains.anko.startActivityForResult import org.jetbrains.anko.startActivityForResult
import org.jetbrains.anko.toast import org.jetbrains.anko.toast
import java.io.File import java.io.File
import java.text.Collator
import java.util.*
class RssSourceActivity : VMBaseActivity<ActivityRssSourceBinding, RssSourceViewModel>(), class RssSourceActivity : VMBaseActivity<ActivityRssSourceBinding, RssSourceViewModel>(),
@ -197,10 +195,11 @@ class RssSourceActivity : VMBaseActivity<ActivityRssSourceBinding, RssSourceView
private fun upGroupMenu() { private fun upGroupMenu() {
groupMenu?.removeGroup(R.id.source_group) groupMenu?.removeGroup(R.id.source_group)
groups.sortedWith(Collator.getInstance(Locale.CHINESE)) groups.sortedWith { o1, o2 ->
.map { o1.cnCompare(o2)
groupMenu?.add(R.id.source_group, Menu.NONE, Menu.NONE, it) }.map {
} groupMenu?.add(R.id.source_group, Menu.NONE, Menu.NONE, it)
}
} }
private fun initLiveDataSource(key: String? = null) { private fun initLiveDataSource(key: String? = null) {

@ -18,6 +18,11 @@
app:showAsAction="always" app:showAsAction="always"
tools:ignore="AlwaysShowAction" /> tools:ignore="AlwaysShowAction" />
<item
android:id="@+id/book_source_manage"
android:title="@string/book_source_manage"
app:showAsAction="never" />
<item <item
android:id="@+id/menu_load_info" android:id="@+id/menu_load_info"
android:title="@string/load_info" android:title="@string/load_info"

Loading…
Cancel
Save