From ec9e554d0d34be407f808cbbd4fd17a5e3e7a463 Mon Sep 17 00:00:00 2001 From: Jason Yao Date: Sun, 13 Sep 2020 23:33:34 -0400 Subject: [PATCH] add and delete add data class searchList delete durchapterindex --- .../book/searchContent/SearchListActivity.kt | 3 +- .../book/searchContent/SearchListAdapter.kt | 39 ++---- .../book/searchContent/SearchListFragment.kt | 118 ++++++++++-------- .../app/ui/book/searchContent/SearchResult.kt | 22 ++++ app/src/main/res/layout/item_search_list.xml | 16 +-- 5 files changed, 107 insertions(+), 91 deletions(-) create mode 100644 app/src/main/java/io/legado/app/ui/book/searchContent/SearchResult.kt 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 bb8d0cb49..3474f446d 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 @@ -45,6 +45,7 @@ class SearchListActivity : VMBaseActivity(R.layout.activity searchView?.onActionViewCollapsed() searchView?.setOnCloseListener { tab_layout.visible() + //to do clean false } searchView?.setOnSearchClickListener { tab_layout.gone() } @@ -62,7 +63,7 @@ class SearchListActivity : VMBaseActivity(R.layout.activity return super.onCompatCreateOptionsMenu(menu) } - private inner class TabFragmentPageAdapter internal constructor(fm: FragmentManager) : + private inner class TabFragmentPageAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { override fun getItem(position: Int): Fragment { return SearchListFragment() 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 3c5d28971..e2f2f1ac4 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 @@ -1,7 +1,11 @@ package io.legado.app.ui.book.searchContent import android.content.Context +import android.os.Build +import android.text.Html import android.view.View +import androidx.annotation.RequiresApi +import androidx.core.text.HtmlCompat import io.legado.app.R import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.SimpleRecyclerAdapter @@ -10,32 +14,23 @@ import io.legado.app.help.BookHelp import io.legado.app.lib.theme.accentColor import io.legado.app.utils.getCompatColor import io.legado.app.utils.visible -import kotlinx.android.synthetic.main.item_bookmark.view.tv_chapter_name -import kotlinx.android.synthetic.main.item_chapter_list.view.* +import kotlinx.android.synthetic.main.item_search_list.view.* import org.jetbrains.anko.sdk27.listeners.onClick class SearchListAdapter(context: Context, val callback: Callback) : - SimpleRecyclerAdapter(context, R.layout.item_search_list) { + SimpleRecyclerAdapter(context, R.layout.item_search_list) { val cacheFileNames = hashSetOf() - override fun convert(holder: ItemViewHolder, item: BookChapter, payloads: MutableList) { + @RequiresApi(Build.VERSION_CODES.N) + override fun convert(holder: ItemViewHolder, item: SearchResult, payloads: MutableList) { with(holder.itemView) { - val isDur = callback.durChapterIndex() == item.index - val cached = callback.isLocalBook - || cacheFileNames.contains(BookHelp.formatChapterName(item)) if (payloads.isEmpty()) { // set search result color here - if (isDur) { - tv_chapter_name.setTextColor(context.accentColor) - } else { - tv_chapter_name.setTextColor(context.getCompatColor(R.color.primaryText)) - } - tv_chapter_name.text = item.title - - upHasCache(this, isDur, cached) + tv_search_result.text = HtmlCompat.fromHtml(item.presentText, HtmlCompat.FROM_HTML_MODE_LEGACY) } else { - upHasCache(this, isDur, cached) + //to do + } } } @@ -49,18 +44,10 @@ class SearchListAdapter(context: Context, val callback: Callback) : } private fun upHasCache(itemView: View, isDur: Boolean, cached: Boolean) = itemView.apply { - tv_chapter_name.paint.isFakeBoldText = cached - iv_checked.setImageResource(R.drawable.ic_outline_cloud_24) - iv_checked.visible(!cached) - if (isDur) { - iv_checked.setImageResource(R.drawable.ic_check) - iv_checked.visible() - } + tv_search_result.paint.isFakeBoldText = cached } interface Callback { - val isLocalBook: Boolean - fun openSearchResult(bookChapter: BookChapter) - fun durChapterIndex(): Int + fun openSearchResult(searchResult: SearchResult) } } \ No newline at end of file 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 46ec1f9d9..c25fdd58c 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 @@ -32,10 +32,9 @@ class SearchListFragment : VMBaseFragment(R.layout.fragment get() = getViewModelOfActivity(SearchListViewModel::class.java) lateinit var adapter: SearchListAdapter - private var durChapterIndex = 0 private lateinit var mLayoutManager: UpLinearLayoutManager private var tocLiveData: LiveData>? = null - private var scrollToDurChapter = false + private var searchResultCounts = 0 override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { viewModel.searchCallBack = this @@ -69,35 +68,28 @@ class SearchListFragment : VMBaseFragment(R.layout.fragment mLayoutManager.scrollToPositionWithOffset(adapter.itemCount - 1, 0) } } - tv_current_search_info.onClick { - mLayoutManager.scrollToPositionWithOffset(durChapterIndex, 0) - } } @SuppressLint("SetTextI18n") private fun initBook() { launch { - initDoc() viewModel.book?.let { - durChapterIndex = it.durChapterIndex tv_current_search_info.text = - "${it.durChapterTitle}(${it.durChapterIndex + 1}/${it.totalChapterNum})" + "搜索结果:$searchResultCounts" initCacheFileNames(it) } } } + /* private fun initDoc() { tocLiveData?.removeObservers(this@SearchListFragment) tocLiveData = App.db.bookChapterDao().observeByBook(viewModel.bookUrl) tocLiveData?.observe(viewLifecycleOwner, { adapter.setItems(it) - if (!scrollToDurChapter) { - mLayoutManager.scrollToPositionWithOffset(durChapterIndex, 0) - scrollToDurChapter = true - } }) } + */ private fun initCacheFileNames(book: Book) { launch(IO) { @@ -120,46 +112,34 @@ class SearchListFragment : VMBaseFragment(R.layout.fragment } override fun startContentSearch(newText: String?) { - if (newText.isNullOrBlank()) { - initDoc() - } else { - var count: Int = 0 - val beginTime = System.currentTimeMillis() + if (!newText.isNullOrBlank()) { App.db.bookChapterDao().getChapterList(viewModel.bookUrl).map{ launch(IO) { + val beginTime = System.currentTimeMillis() if (isLocalBook || adapter.cacheFileNames.contains(BookHelp.formatChapterName(it)) ) { val value = searchChapter(newText, it) - count += value + searchResultCounts += value } + val finishedTime = System.currentTimeMillis() - beginTime + Log.d("Jason", "Search finished, the total time cost is $finishedTime") + Log.d("Jason", "Search finished, the total count is $searchResultCounts") } } - //adapter.setItems(list) - val finishedTime = System.currentTimeMillis() - beginTime - Log.d("Jason", "Search finished, the total time cost is $finishedTime") - Log.d("Jason", "Search finished, the total count is $count") - //tocLiveData?.removeObservers(this) - //tocLiveData = App.db.bookChapterDao().liveDataSearch(viewModel.bookUrl, newText) - //tocLiveData?.observe(viewLifecycleOwner, { - //adapter.setItems(it) - //}) - } + } } - - private suspend fun searchChapter(query: String, chapter: BookChapter?): Int { - - val startTime = System.currentTimeMillis() - val searchResult: MutableList = mutableListOf() - var count = 0 + val searchResult: 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){ /* replace content, let's focus on original content first chapter.title = when (AppConfig.chineseConverterType) { 1 -> HanLP.convertToSimplifiedChinese(chapter.title) @@ -186,35 +166,73 @@ class SearchListFragment : VMBaseFragment(R.layout.fragment } }?.awaitAll() */ - count = bookContent?.let { countMatches(it, query) }!! - Log.d("Jason", "Search ${chapter.title} finished, the appeared count is $count") + 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 + ) + ) + } + 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 count + return positions!!.size } - fun countMatches(string: String, pattern: String): Int { - val matcher = Pattern.compile(pattern).matcher(string) - + private fun countMatches(content: String, pattern: String): List { + val position : MutableList = mutableListOf() var count = 0 - while (matcher.find()) { - count++ + var index = content.indexOf(pattern) + while(index >= 0){ + position.add(index) + index = content.indexOf(pattern, index + 1); } - return count + return position } + private fun constructText(content: String, position: Int): String{ - override val isLocalBook: Boolean - get() = viewModel.book?.isLocalBook() == true - - override fun durChapterIndex(): Int { - return durChapterIndex + val length = 10 + var po1 = position - length + var po2 = position + length + if (po1 <0) { + po1 = 0 + } + 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) + } + */ } - override fun openSearchResult(bookChapter: BookChapter) { - activity?.setResult(RESULT_OK, Intent().putExtra("index", bookChapter.index)) + val isLocalBook: Boolean + get() = viewModel.book?.isLocalBook() == true + + override fun openSearchResult(searchResult: SearchResult) { + val searchData = Intent() + searchData.putExtra("index", searchResult.chapterIndex) + searchData.putExtra("pageIndex", searchResult.pageIndex) + activity?.setResult(RESULT_OK, searchData) activity?.finish() } diff --git a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchResult.kt b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchResult.kt new file mode 100644 index 000000000..5b0268026 --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchResult.kt @@ -0,0 +1,22 @@ +package io.legado.app.ui.book.searchContent + +data class SearchResult( + var index: Int = 0, + var text: String = "", + var chapterTitle: String = "", + val query: String, + var pageSize: Int = 0, + var chapterIndex: Int = 0, + var pageIndex: Int = 0, +) { + val presentText: String + get(){ + val sub1 = text.substring(0, text.indexOf(query)) + val sub2 = text.substring(text.indexOf(query) + query.length, text.length) + return "$sub1 " + + "$query" + + "$sub2 " + + "($chapterTitle)" + } + +} \ No newline at end of file diff --git a/app/src/main/res/layout/item_search_list.xml b/app/src/main/res/layout/item_search_list.xml index 0b8bab809..3624ae1e4 100644 --- a/app/src/main/res/layout/item_search_list.xml +++ b/app/src/main/res/layout/item_search_list.xml @@ -8,24 +8,12 @@ android:padding="12dp"> - - + app:layout_constraintRight_toLeftOf="parent" /> \ No newline at end of file