diff --git a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchListActivity.kt b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchListActivity.kt index 3474f446d..ec1cbc0c7 100644 --- a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchListActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchListActivity.kt @@ -20,6 +20,7 @@ import kotlinx.android.synthetic.main.view_tab_layout.* class SearchListActivity : VMBaseActivity(R.layout.activity_search_list) { + // todo: 完善搜索界面UI override val viewModel: SearchListViewModel get() = getViewModel(SearchListViewModel::class.java) @@ -51,7 +52,9 @@ class SearchListActivity : VMBaseActivity(R.layout.activity searchView?.setOnSearchClickListener { tab_layout.gone() } searchView?.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextSubmit(query: String): Boolean { - viewModel.startContentSearch(query) + if (viewModel.lastQuery != query){ + viewModel.startContentSearch(query) + } return false } diff --git a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchListAdapter.kt b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchListAdapter.kt index e2f2f1ac4..8f8a83a88 100644 --- a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchListAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchListAdapter.kt @@ -3,6 +3,7 @@ package io.legado.app.ui.book.searchContent import android.content.Context import android.os.Build import android.text.Html +import android.util.Log import android.view.View import androidx.annotation.RequiresApi import androidx.core.text.HtmlCompat @@ -22,15 +23,10 @@ class SearchListAdapter(context: Context, val callback: Callback) : val cacheFileNames = hashSetOf() - @RequiresApi(Build.VERSION_CODES.N) override fun convert(holder: ItemViewHolder, item: SearchResult, payloads: MutableList) { with(holder.itemView) { if (payloads.isEmpty()) { - // set search result color here tv_search_result.text = HtmlCompat.fromHtml(item.presentText, HtmlCompat.FROM_HTML_MODE_LEGACY) - } else { - //to do - } } } @@ -43,10 +39,6 @@ class SearchListAdapter(context: Context, val callback: Callback) : } } - private fun upHasCache(itemView: View, isDur: Boolean, cached: Boolean) = itemView.apply { - tv_search_result.paint.isFakeBoldText = cached - } - interface Callback { fun openSearchResult(searchResult: SearchResult) } diff --git a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchListFragment.kt b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchListFragment.kt index c25fdd58c..7a6915856 100644 --- a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchListFragment.kt +++ b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchListFragment.kt @@ -81,16 +81,6 @@ class SearchListFragment : VMBaseFragment(R.layout.fragment } } - /* - private fun initDoc() { - tocLiveData?.removeObservers(this@SearchListFragment) - tocLiveData = App.db.bookChapterDao().observeByBook(viewModel.bookUrl) - tocLiveData?.observe(viewLifecycleOwner, { - adapter.setItems(it) - }) - } - */ - private fun initCacheFileNames(book: Book) { launch(IO) { adapter.cacheFileNames.addAll(BookHelp.getChapterFiles(book)) @@ -113,14 +103,21 @@ class SearchListFragment : VMBaseFragment(R.layout.fragment override fun startContentSearch(newText: String?) { if (!newText.isNullOrBlank()) { + adapter.clearItems() + viewModel.lastQuery = newText App.db.bookChapterDao().getChapterList(viewModel.bookUrl).map{ launch(IO) { val beginTime = System.currentTimeMillis() - if (isLocalBook || - adapter.cacheFileNames.contains(BookHelp.formatChapterName(it)) + if (isLocalBook + || adapter.cacheFileNames.contains(BookHelp.formatChapterName(it)) ) { - val value = searchChapter(newText, it) - searchResultCounts += value + val searchResults = searchChapter(newText, it) + if (searchResults.size > 0 ){ + searchResultCounts += searchResults.size + withContext(Main){ + adapter.addItems(searchResults) + } + } } val finishedTime = System.currentTimeMillis() - beginTime Log.d("Jason", "Search finished, the total time cost is $finishedTime") @@ -131,15 +128,17 @@ class SearchListFragment : VMBaseFragment(R.layout.fragment } - private suspend fun searchChapter(query: String, chapter: BookChapter?): Int { + private fun searchChapter(query: String, chapter: BookChapter?): MutableList { val startTime = System.currentTimeMillis() - val searchResult: MutableList = mutableListOf() + val searchResults: MutableList = mutableListOf() var positions : List? = listOf() if (chapter != null){ Log.d("Jason", "Search ${chapter.title}") viewModel.book?.let { bookSource -> val bookContent = BookHelp.getContent(bookSource, chapter) if (bookContent != null){ + //todo: 搜索替换后的正文 + //todo: 计算搜索结果所在的pageIndex直接跳转 /* replace content, let's focus on original content first chapter.title = when (AppConfig.chineseConverterType) { 1 -> HanLP.convertToSimplifiedChinese(chapter.title) @@ -168,30 +167,28 @@ class SearchListFragment : VMBaseFragment(R.layout.fragment */ positions = countMatches(bookContent, query) positions?.map{ - searchResult.add( - SearchResult(index = 0, - text = constructText(bookContent, it), - chapterTitle = chapter.title, - query = query, - pageSize = 0, // to be finished - chapterIndex = chapter.index, // to be finished - pageIndex = 0, // to be finished - ) + val result = SearchResult(index = 0, + text = constructText(bookContent, it), + chapterTitle = chapter.title, + query = query, + pageSize = 0, // to be finished + chapterIndex = chapter.index, // to be finished + pageIndex = 0, // to be finished ) + searchResults.add(result) + Log.d("Jason", result.presentText) } - adapter.addItems(searchResult) Log.d("Jason", "Search ${chapter.title} finished, the appeared count is ${positions!!.size}") } } val endTime = System.currentTimeMillis() - startTime Log.d("Jason", "Search ${chapter.title} finished, the time cost is $endTime") } - return positions!!.size + return searchResults } private fun countMatches(content: String, pattern: String): List { val position : MutableList = mutableListOf() - var count = 0 var index = content.indexOf(pattern) while(index >= 0){ position.add(index) @@ -201,8 +198,11 @@ class SearchListFragment : VMBaseFragment(R.layout.fragment } private fun constructText(content: String, position: Int): String{ - - val length = 10 + // 构建关键词周边文字,在搜索结果里显示 + // todo: 判断段落,只在关键词所在段落内分割 + // todo: 利用标点符号分割完整的句 + // todo: length和设置结合,自由调整周边文字长度 + val length = 20 var po1 = position - length var po2 = position + length if (po1 <0) { @@ -211,18 +211,7 @@ class SearchListFragment : VMBaseFragment(R.layout.fragment if (po2 > content.length){ po2 = content.length } - return content.substring(po1, po2) - /* - if (position >= length && position <= content.length - length){ - return content.substring(position - length, position + length) - } - else if (position <= length){ - return content.substring(0, position + length) - } - else if (position >= content.length - length){ - return content.substring(position - length, content.length) - } - */ + return "..." + content.substring(po1, po2) } val isLocalBook: Boolean diff --git a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchListViewModel.kt b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchListViewModel.kt index 153f61416..81c223d30 100644 --- a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchListViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchListViewModel.kt @@ -10,6 +10,7 @@ class SearchListViewModel(application: Application) : BaseViewModel(application) var bookUrl: String = "" var book: Book? = null var searchCallBack: SearchListCallBack? = null + var lastQuery: String = "" fun initBook(bookUrl: String, success: () -> Unit) { this.bookUrl = bookUrl diff --git a/app/src/main/res/layout/item_search_list.xml b/app/src/main/res/layout/item_search_list.xml index 3624ae1e4..2dcaf1436 100644 --- a/app/src/main/res/layout/item_search_list.xml +++ b/app/src/main/res/layout/item_search_list.xml @@ -9,9 +9,9 @@