diff --git a/folioreader/res/values/strings.xml b/folioreader/res/values/strings.xml index 60c32e3a8..9d944130e 100644 --- a/folioreader/res/values/strings.xml +++ b/folioreader/res/values/strings.xml @@ -84,10 +84,6 @@ please enter a note Contents - javascript:highlightSearchResult(\"%s\", %d) - javascript:makeSearchResultsInvisible() - javascript:resetSearchResults() - Hello blank fragment Starting drag! @@ -100,7 +96,6 @@ application/xhtml+xml text/html - BackCompat Search Configuration @@ -118,5 +113,7 @@ javascript:computeLastReadCfi() javascript:scrollToCfi(\"%s\") + javascript:highlightSearchLocator(\"%s\") + javascript:clearSelection() diff --git a/folioreader/src/main/assets/js/Bridge.js b/folioreader/src/main/assets/js/Bridge.js index 24ba8b288..a2e41dcf9 100755 --- a/folioreader/src/main/assets/js/Bridge.js +++ b/folioreader/src/main/assets/js/Bridge.js @@ -27,11 +27,6 @@ var horizontalIntervalPeriod = 1000; var horizontalIntervalCounter = 0; var horizontalIntervalLimit = 3000; -var searchResults = []; -var lastSearchQuery = null; -var testCounter = 0; -var searchResultsInvisible = true; - var viewportRect; // Class manipulation @@ -118,7 +113,7 @@ function audioMarkID(className, id) { audioMarkClass = className var el = document.getElementById(id); - scrollToNode(el); + scrollToNodeOrRange(el); el.classList.add(className) } @@ -210,7 +205,7 @@ function getSentenceWithIndex(className) { var text = sentence.innerText || sentence.textContent; - scrollToNode(sentence); + scrollToNodeOrRange(sentence); if (audioMarkClass) { removeAllClasses(audioMarkClass); @@ -497,7 +492,7 @@ var LoadingView = { function goToHighlight(highlightId) { var element = document.getElementById(highlightId.toString()); if (element) - scrollToNode(element); + scrollToNodeOrRange(element); LoadingView.hide(); } @@ -505,7 +500,7 @@ function goToHighlight(highlightId) { function goToAnchor(anchorId) { var element = document.getElementById(anchorId); if (element) - scrollToNode(element); + scrollToNodeOrRange(element); LoadingView.hide(); } @@ -550,8 +545,12 @@ function scrollToFirst() { LoadingView.hide(); } -function getCompatMode() { - FolioWebView.setCompatMode(document.compatMode); +function checkCompatMode() { + if (document.compatMode === "BackCompat") { + console.error("-> Web page loaded in Quirks mode. Please report to developer " + + "for debugging with current EPUB file, as many features might stop working " + + "(ex. Horizontal scroll feature).") + } } function horizontalRecheck() { @@ -674,10 +673,10 @@ function bodyOrHtml() { } /** - * @param {(Element|Text)} node - * @returns {(Element|Text)} node + * @param {(Element|Text|Range)} nodeOrRange + * @returns {(Element|Text|Range)} nodeOrRange */ -function scrollToNode(node) { +function scrollToNodeOrRange(nodeOrRange) { var scrollingElement = bodyOrHtml(); var direction = FolioWebView.getDirection(); @@ -688,26 +687,28 @@ function scrollToNode(node) { // For Direction.HORIZONTAL var nodeOffsetLeft; - switch (node.nodeType) { + if (nodeOrRange instanceof Range || nodeOrRange.nodeType === Node.TEXT_NODE) { - case Node.TEXT_NODE: + var rect; + if (nodeOrRange.nodeType && nodeOrRange.nodeType === Node.TEXT_NODE) { var range = document.createRange(); - range.selectNode(node); - var rect = RangeFix.getBoundingClientRect(range); - nodeOffsetTop = scrollingElement.scrollTop + rect.top; - nodeOffsetHeight = rect.height; - nodeOffsetLeft = scrollingElement.scrollLeft + rect.left; - break; + range.selectNode(nodeOrRange); + rect = RangeFix.getBoundingClientRect(range); + } else { + rect = RangeFix.getBoundingClientRect(nodeOrRange); + } + nodeOffsetTop = scrollingElement.scrollTop + rect.top; + nodeOffsetHeight = rect.height; + nodeOffsetLeft = scrollingElement.scrollLeft + rect.left; - case Node.ELEMENT_NODE: - nodeOffsetTop = node.offsetTop; - nodeOffsetHeight = node.offsetHeight; - nodeOffsetLeft = node.offsetLeft; - break; + } else if (nodeOrRange.nodeType === Node.ELEMENT_NODE) { - default: - console.error("-> Illegal Argument Exception, node.nodeType found " + node.nodeType); - return null; + nodeOffsetTop = nodeOrRange.offsetTop; + nodeOffsetHeight = nodeOrRange.offsetHeight; + nodeOffsetLeft = nodeOrRange.offsetLeft; + + } else { + throw("-> Illegal Argument Exception, nodeOrRange -> " + nodeOrRange); } switch (direction) { @@ -747,204 +748,28 @@ function scrollToNode(node) { break; } - return node; + return nodeOrRange; } -// Testing purpose calls -function test() { - - ++testCounter; - console.log("-> testCounter = " + testCounter); - - var searchQuery = "look"; - - if (testCounter == 1) { - - getCompatMode(); +function highlightSearchLocator(rangeCfi) { - if (FolioWebView.getDirection() == Direction.HORIZONTAL) - initHorizontalDirection(); - - highlightSearchResult(searchQuery, 1); - - } else if (testCounter == 2) { - - makeSearchResultsInvisible(); - - } else if (testCounter == 3) { - - highlightSearchResult(searchQuery, 2); - - } else if (testCounter == 4) { - - } -} + try { + var $obj = EPUBcfi.Interpreter.getRangeTargetElements(rangeCfi, document); -function highlightSearchResult(searchQuery, occurrenceInChapter) { + var range = document.createRange(); + range.setStart($obj.startElement, $obj.startOffset); + range.setEnd($obj.endElement, $obj.endOffset); - if (searchQuery == lastSearchQuery) { - makeSearchResultsInvisible(); - } else { - resetSearchResults(); - searchResults = applySearchResultClass(searchQuery); - console.debug("-> Search Query Found = " + searchResults.length); + window.getSelection().removeAllRanges(); + window.getSelection().addRange(range); + scrollToNodeOrRange(range); + } catch (e) { + console.error("-> " + e); } - applySearchResultVisibleClass(occurrenceInChapter); LoadingView.hide(); } -function applySearchResultClass(searchQuery) { - - var searchQueryRegExp = new RegExp(escapeRegExp(searchQuery), "i"); - - var searchResults = []; - var searchChildNodesArray = []; - var elementArray = []; - var textNodeArray = []; - - var bodyElement = document.getElementsByTagName('body')[0]; - var elementsInBody = bodyElement.getElementsByTagName('*'); - - for (var i = 0; i < elementsInBody.length; i++) { - - var childNodes = elementsInBody[i].childNodes; - - for (var j = 0; j < childNodes.length; j++) { - - if (childNodes[j].nodeType == Node.TEXT_NODE && - childNodes[j].nodeValue.trim().length) { - //console.log("-> " + childNodes[j].nodeValue); - - if (childNodes[j].nodeValue.match(searchQueryRegExp)) { - //console.log("-> Found -> " + childNodes[j].nodeValue); - - searchChildNodesArray.push( - getSearchChildNodes(childNodes[j].nodeValue, searchQuery)); - - elementArray.push(elementsInBody[i]); - textNodeArray.push(childNodes[j]); - } - } - } - } - - for (var i = 0; i < searchChildNodesArray.length; i++) { - - var searchChildNodes = searchChildNodesArray[i]; - - for (var j = 0; j < searchChildNodes.length; j++) { - - if (searchChildNodes[j].className == "search-result") - searchResults.push(searchChildNodes[j]); - elementArray[i].insertBefore(searchChildNodes[j], textNodeArray[i]); - } - - elementArray[i].removeChild(textNodeArray[i]); - } - - lastSearchQuery = searchQuery; - return searchResults; -} - -function getSearchChildNodes(text, searchQuery) { - - var arrayIndex = []; - var matchIndexStart = -1; - var textChunk = ""; - var searchChildNodes = []; - - for (var i = 0, j = 0; i < text.length; i++) { - - textChunk += text[i]; - - if (text[i].match(new RegExp(escapeRegExp(searchQuery[j]), "i"))) { - - if (matchIndexStart == -1) - matchIndexStart = i; - - if (searchQuery.length == j + 1) { - - var textNode = document.createTextNode( - textChunk.substring(0, textChunk.length - searchQuery.length)); - - var searchNode = document.createElement("span"); - searchNode.className = "search-result"; - var queryTextNode = document.createTextNode( - text.substring(matchIndexStart, matchIndexStart + searchQuery.length)); - searchNode.appendChild(queryTextNode); - - searchChildNodes.push(textNode); - searchChildNodes.push(searchNode); - - arrayIndex.push(matchIndexStart); - matchIndexStart = -1; - j = 0; - textChunk = ""; - - } else { - j++; - } - - } else { - matchIndexStart = -1; - j = 0; - } - } - - if (textChunk !== "") { - var textNode = document.createTextNode(textChunk); - searchChildNodes.push(textNode); - } - - return searchChildNodes; -} - -function makeSearchResultsVisible() { - - for (var i = 0; i < searchResults.length; i++) { - searchResults[i].className = "search-result-visible"; - } - searchResultsInvisible = false; -} - -function makeSearchResultsInvisible() { - - if (searchResultsInvisible) - return; - for (var i = 0; i < searchResults.length; i++) { - if (searchResults[i].className == "search-result-visible") - searchResults[i].className = "search-result-invisible"; - } - searchResultsInvisible = true; -} - -function applySearchResultVisibleClass(occurrenceInChapter) { - - var searchResult = searchResults[occurrenceInChapter - 1]; - if (searchResult === undefined) - return; - searchResult.className = "search-result-visible"; - searchResultsInvisible = false; - - scrollToNode(searchResult); -} - -function resetSearchResults() { - - for (var i = 0; i < searchResults.length; i++) { - searchResults[i].outerHTML = searchResults[i].innerHTML; - } - - searchResults = []; - lastSearchQuery = null; - searchResultsInvisible = true; -} - -function escapeRegExp(str) { - return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"); -} - /** * Returns JSON of selection rect * @param {Element} [element] @@ -1022,7 +847,7 @@ function computeLastReadCfi() { cfi = EPUBcfi.Generator.generateElementCFIComponent(node); } - cfi = EPUBcfi.Generator.generateCompleteCFI("", cfi); + cfi = EPUBcfi.Generator.generateCompleteCFI("/0!", cfi); viewportRect = null; FolioPageFragment.storeLastReadCfi(cfi); } @@ -1078,8 +903,8 @@ function getFirstVisibleNode(node) { function scrollToCfi(cfi) { try { - var $node = EPUBcfi.Interpreter.getTargetElementWithPartialCFI(cfi, document); - scrollToNode($node[0]); + var $node = EPUBcfi.Interpreter.getTargetElement(cfi, document); + scrollToNodeOrRange($node[0]); } catch (e) { console.error("-> " + e); } diff --git a/folioreader/src/main/java/com/folioreader/loaders/SearchLoader.kt b/folioreader/src/main/java/com/folioreader/loaders/SearchLoader.kt index 6297783c0..90a5a2b92 100644 --- a/folioreader/src/main/java/com/folioreader/loaders/SearchLoader.kt +++ b/folioreader/src/main/java/com/folioreader/loaders/SearchLoader.kt @@ -6,8 +6,8 @@ import android.net.Uri import android.os.Bundle import android.support.v4.content.AsyncTaskLoader import android.util.Log -import com.folioreader.model.search.SearchItemType -import com.folioreader.model.search.SearchLocator +import com.folioreader.model.locators.SearchItemType +import com.folioreader.model.locators.SearchLocator import com.folioreader.ui.folio.activity.SearchActivity import com.folioreader.ui.folio.adapter.ListViewType import com.folioreader.ui.folio.adapter.SearchAdapter @@ -151,7 +151,13 @@ class SearchLoader : AsyncTaskLoader { searchLocatorList.add(titleLocator) } - val searchResultItem = SearchLocator(locator, SearchItemType.SEARCH_RESULT_ITEM) + val primaryContents = StringBuilder() + .append(locator.text?.before ?: "") + .append(locator.text?.hightlight ?: "") + .append(locator.text?.after ?: "") + .toString() + val searchResultItem = SearchLocator(locator, primaryContents, + SearchItemType.SEARCH_RESULT_ITEM) searchLocatorList.add(searchResultItem) } diff --git a/folioreader/src/main/java/com/folioreader/model/search/SearchLocator.kt b/folioreader/src/main/java/com/folioreader/model/locators/SearchLocator.kt similarity index 75% rename from folioreader/src/main/java/com/folioreader/model/search/SearchLocator.kt rename to folioreader/src/main/java/com/folioreader/model/locators/SearchLocator.kt index fafe5d3f9..d10699c23 100644 --- a/folioreader/src/main/java/com/folioreader/model/search/SearchLocator.kt +++ b/folioreader/src/main/java/com/folioreader/model/locators/SearchLocator.kt @@ -1,4 +1,4 @@ -package com.folioreader.model.search +package com.folioreader.model.locators import android.os.Parcel import android.os.Parcelable @@ -6,16 +6,23 @@ import org.readium.r2.shared.Locations import org.readium.r2.shared.Locator import org.readium.r2.shared.LocatorText -// TODO -> Move to locator package +enum class SearchItemType { + UNKNOWN_ITEM, + SEARCH_COUNT_ITEM, + RESOURCE_TITLE_ITEM, + SEARCH_RESULT_ITEM +} + class SearchLocator : Locator, Parcelable { - var primaryContents: String? = text?.before + text?.hightlight + text?.after + var primaryContents: String var searchItemType: SearchItemType - constructor() : this(Locator("", 0, "", Locations(), null), SearchItemType.UNKNOWN_ITEM) + constructor() : this(Locator("", 0, "", Locations(), null), "", SearchItemType.UNKNOWN_ITEM) - constructor(locator: Locator, searchItemType: SearchItemType) : + constructor(locator: Locator, primaryContents: String, searchItemType: SearchItemType) : super(locator.href, locator.created, locator.title, locator.locations, locator.text) { + this.primaryContents = primaryContents this.searchItemType = searchItemType } @@ -26,7 +33,7 @@ class SearchLocator : Locator, Parcelable { parcel.readString()!!, parcel.readSerializable() as Locations, parcel.readSerializable() as LocatorText? - ), SearchItemType.valueOf(parcel.readString()!!)) + ), parcel.readString()!!, SearchItemType.valueOf(parcel.readString()!!)) override fun writeToParcel(parcel: Parcel, flags: Int) { parcel.writeString(href) @@ -34,6 +41,7 @@ class SearchLocator : Locator, Parcelable { parcel.writeString(title) parcel.writeSerializable(locations) parcel.writeSerializable(text) + parcel.writeString(primaryContents) parcel.writeString(searchItemType.name) } diff --git a/folioreader/src/main/java/com/folioreader/model/search/SearchItem.kt b/folioreader/src/main/java/com/folioreader/model/search/SearchItem.kt deleted file mode 100644 index dc67fa605..000000000 --- a/folioreader/src/main/java/com/folioreader/model/search/SearchItem.kt +++ /dev/null @@ -1,65 +0,0 @@ -package com.folioreader.model.search - -import android.os.Parcel -import android.os.Parcelable -import org.readium.r2.streamer.r2_streamer_java.SearchResult - -class SearchItem : SearchResult, Parcelable { - - var primaryContents: String? = null - lateinit var searchItemType: SearchItemType - - constructor(parcel: Parcel) : this() { - searchIndex = parcel.readInt() - href = parcel.readString() - title = parcel.readString() - searchQuery = parcel.readString() - matchQuery = parcel.readString() - sentence = parcel.readString() - textBefore = parcel.readString() - textAfter = parcel.readString() - occurrenceInChapter = parcel.readInt() - primaryContents = parcel.readString() - searchItemType = SearchItemType.valueOf(parcel.readString()!!) - } - - constructor() : super() - constructor(searchIndex: Int, href: String?, title: String?, - searchQuery: String?, matchQuery: String?, sentence: String?, - textBefore: String?, textAfter: String?, occurrenceInChapter: Int) : - super(searchIndex, href, title, searchQuery, matchQuery, - sentence, textBefore, textAfter, occurrenceInChapter) - - constructor(searchResult: SearchResult) : this(searchResult.searchIndex, searchResult.href, - searchResult.title, searchResult.searchQuery, searchResult.matchQuery, - searchResult.sentence, searchResult.textBefore, searchResult.textAfter, - searchResult.occurrenceInChapter) - - override fun writeToParcel(parcel: Parcel, flags: Int) { - parcel.writeInt(searchIndex) - parcel.writeString(href) - parcel.writeString(title) - parcel.writeString(searchQuery) - parcel.writeString(matchQuery) - parcel.writeString(sentence) - parcel.writeString(textBefore) - parcel.writeString(textAfter) - parcel.writeInt(occurrenceInChapter) - parcel.writeString(primaryContents) - parcel.writeString(searchItemType.name) - } - - override fun describeContents(): Int { - return 0 - } - - companion object CREATOR : Parcelable.Creator { - override fun createFromParcel(parcel: Parcel): SearchItem { - return SearchItem(parcel) - } - - override fun newArray(size: Int): Array { - return arrayOfNulls(size) - } - } -} \ No newline at end of file diff --git a/folioreader/src/main/java/com/folioreader/model/search/SearchItemType.kt b/folioreader/src/main/java/com/folioreader/model/search/SearchItemType.kt deleted file mode 100644 index 4a37aea6d..000000000 --- a/folioreader/src/main/java/com/folioreader/model/search/SearchItemType.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.folioreader.model.search - -enum class SearchItemType { - UNKNOWN_ITEM, - SEARCH_COUNT_ITEM, - RESOURCE_TITLE_ITEM, - SEARCH_RESULT_ITEM -} \ No newline at end of file diff --git a/folioreader/src/main/java/com/folioreader/ui/folio/activity/FolioActivity.kt b/folioreader/src/main/java/com/folioreader/ui/folio/activity/FolioActivity.kt index 2c5431fd7..eb90a2f7f 100644 --- a/folioreader/src/main/java/com/folioreader/ui/folio/activity/FolioActivity.kt +++ b/folioreader/src/main/java/com/folioreader/ui/folio/activity/FolioActivity.kt @@ -53,7 +53,7 @@ import com.folioreader.model.DisplayUnit import com.folioreader.model.HighlightImpl import com.folioreader.model.event.MediaOverlayPlayPauseEvent import com.folioreader.model.locators.ReadLocator -import com.folioreader.model.search.SearchItem +import com.folioreader.model.locators.SearchLocator import com.folioreader.ui.folio.adapter.FolioPageFragmentAdapter import com.folioreader.ui.folio.adapter.SearchAdapter import com.folioreader.ui.folio.fragment.FolioPageFragment @@ -103,10 +103,12 @@ class FolioActivity : AppCompatActivity(), FolioActivityCallback, MediaControlle private var mEpubRawId = 0 private var mediaControllerFragment: MediaControllerFragment? = null private var direction: Config.Direction = Config.Direction.VERTICAL + private var searchUri: Uri? = null private var searchAdapterDataBundle: Bundle? = null private var searchQuery: CharSequence? = null - private var searchItem: SearchItem? = null + private var searchLocator: SearchLocator? = null + private var displayMetrics: DisplayMetrics? = null private var density: Float = 0.toFloat() private var topActivity: Boolean? = null @@ -164,11 +166,8 @@ class FolioActivity : AppCompatActivity(), FolioActivityCallback, MediaControlle Log.v(LOG_TAG, "-> searchReceiver -> onReceive -> " + intent.action!!) val action = intent.action ?: return - when (action) { - ACTION_SEARCH_CLEAR -> - //TODO -> rename reset to clear - resetSearchResults() + ACTION_SEARCH_CLEAR -> clearSearchLocator() } } } @@ -510,7 +509,7 @@ class FolioActivity : AppCompatActivity(), FolioActivityCallback, MediaControlle var folioPageFragment: FolioPageFragment? = currentFragment ?: return entryReadLocator = folioPageFragment!!.getLastReadLocator() - val searchItemVisible = folioPageFragment.searchItemVisible + val searchLocatorVisible = folioPageFragment.searchLocatorVisible direction = newDirection @@ -520,10 +519,10 @@ class FolioActivity : AppCompatActivity(), FolioActivityCallback, MediaControlle mFolioPageViewPager!!.adapter = mFolioPageFragmentAdapter mFolioPageViewPager!!.currentItem = currentChapterIndex - folioPageFragment = currentFragment - if (folioPageFragment == null) return - if (searchItemVisible != null) - folioPageFragment.highlightSearchItem(searchItemVisible) + folioPageFragment = currentFragment ?: return + searchLocatorVisible?.let { + folioPageFragment.highlightSearchLocator(searchLocatorVisible) + } } fun initDistractionFreeMode(savedInstanceState: Bundle?) { @@ -755,15 +754,15 @@ class FolioActivity : AppCompatActivity(), FolioActivityCallback, MediaControlle if (resultCode == SearchActivity.ResultCode.ITEM_SELECTED.value) { - searchItem = data.getParcelableExtra(EXTRA_SEARCH_ITEM) + searchLocator = data.getParcelableExtra(EXTRA_SEARCH_ITEM) // In case if SearchActivity is recreated due to screen rotation then FolioActivity // will also be recreated, so mFolioPageViewPager might be null. if (mFolioPageViewPager == null) return - currentChapterIndex = getChapterIndex(Constants.HREF, searchItem!!.href) + currentChapterIndex = getChapterIndex(Constants.HREF, searchLocator!!.href) mFolioPageViewPager!!.currentItem = currentChapterIndex val folioPageFragment = currentFragment ?: return - folioPageFragment.highlightSearchItem(searchItem!!) - searchItem = null + folioPageFragment.highlightSearchLocator(searchLocator!!) + searchLocator = null } } else if (requestCode == RequestCode.CONTENT_HIGHLIGHT.value && resultCode == Activity.RESULT_OK && @@ -851,14 +850,14 @@ class FolioActivity : AppCompatActivity(), FolioActivityCallback, MediaControlle mFolioPageViewPager!!.adapter = mFolioPageFragmentAdapter // In case if SearchActivity is recreated due to screen rotation then FolioActivity - // will also be recreated, so searchItem is checked here. - if (searchItem != null) { + // will also be recreated, so searchLocator is checked here. + if (searchLocator != null) { - currentChapterIndex = getChapterIndex(Constants.HREF, searchItem!!.href) + currentChapterIndex = getChapterIndex(Constants.HREF, searchLocator!!.href) mFolioPageViewPager!!.currentItem = currentChapterIndex val folioPageFragment = currentFragment ?: return - folioPageFragment.highlightSearchItem(searchItem!!) - searchItem = null + folioPageFragment.highlightSearchLocator(searchLocator!!) + searchLocator = null } else { @@ -981,13 +980,13 @@ class FolioActivity : AppCompatActivity(), FolioActivityCallback, MediaControlle return direction } - private fun resetSearchResults() { - Log.v(LOG_TAG, "-> resetSearchResults") + private fun clearSearchLocator() { + Log.v(LOG_TAG, "-> clearSearchLocator") val fragments = mFolioPageFragmentAdapter!!.fragments for (i in fragments.indices) { val folioPageFragment = fragments[i] as FolioPageFragment? - folioPageFragment?.resetSearchResults() + folioPageFragment?.clearSearchLocator() } val savedStateList = mFolioPageFragmentAdapter!!.savedStateList @@ -995,7 +994,7 @@ class FolioActivity : AppCompatActivity(), FolioActivityCallback, MediaControlle for (i in savedStateList.indices) { val savedState = savedStateList[i] val bundle = FolioPageFragmentAdapter.getBundleFromSavedState(savedState) - bundle?.putParcelable(FolioPageFragment.BUNDLE_SEARCH_ITEM, null) + bundle?.putParcelable(FolioPageFragment.BUNDLE_SEARCH_LOCATOR, null) } } } diff --git a/folioreader/src/main/java/com/folioreader/ui/folio/activity/SearchActivity.kt b/folioreader/src/main/java/com/folioreader/ui/folio/activity/SearchActivity.kt index a8bac78b0..07a8c8b8f 100644 --- a/folioreader/src/main/java/com/folioreader/ui/folio/activity/SearchActivity.kt +++ b/folioreader/src/main/java/com/folioreader/ui/folio/activity/SearchActivity.kt @@ -262,8 +262,7 @@ class SearchActivity : AppCompatActivity(), LoaderManager.LoaderCallbacks, supportLoaderManager.restartLoader(SEARCH_LOADER, null, this@SearchActivity) val intent = Intent(FolioActivity.ACTION_SEARCH_CLEAR) - LocalBroadcastManager.getInstance(this@SearchActivity) - .sendBroadcast(intent) + LocalBroadcastManager.getInstance(this@SearchActivity).sendBroadcast(intent) } return false } diff --git a/folioreader/src/main/java/com/folioreader/ui/folio/adapter/SearchAdapter.kt b/folioreader/src/main/java/com/folioreader/ui/folio/adapter/SearchAdapter.kt index 29e76c4af..0a0e7ec44 100644 --- a/folioreader/src/main/java/com/folioreader/ui/folio/adapter/SearchAdapter.kt +++ b/folioreader/src/main/java/com/folioreader/ui/folio/adapter/SearchAdapter.kt @@ -13,8 +13,8 @@ import android.view.View import android.view.ViewGroup import android.widget.TextView import com.folioreader.R -import com.folioreader.model.search.SearchItemType -import com.folioreader.model.search.SearchLocator +import com.folioreader.model.locators.SearchItemType +import com.folioreader.model.locators.SearchLocator class SearchAdapter : RecyclerView.Adapter { @@ -161,7 +161,7 @@ class SearchAdapter : RecyclerView.Adapter { when (searchLocator.searchItemType) { SearchItemType.SEARCH_COUNT_ITEM -> { - val count: Int = searchLocator.primaryContents?.toInt()!! + val count: Int = searchLocator.primaryContents.toInt() textViewCount.text = context.resources.getQuantityString( R.plurals.numberOfSearchResults, count, count) textViewCount.visibility = View.VISIBLE diff --git a/folioreader/src/main/java/com/folioreader/ui/folio/fragment/FolioPageFragment.kt b/folioreader/src/main/java/com/folioreader/ui/folio/fragment/FolioPageFragment.kt index 01c7625c2..0e5fef549 100644 --- a/folioreader/src/main/java/com/folioreader/ui/folio/fragment/FolioPageFragment.kt +++ b/folioreader/src/main/java/com/folioreader/ui/folio/fragment/FolioPageFragment.kt @@ -30,7 +30,7 @@ import com.folioreader.model.HighLight import com.folioreader.model.HighlightImpl import com.folioreader.model.event.* import com.folioreader.model.locators.ReadLocator -import com.folioreader.model.search.SearchItem +import com.folioreader.model.locators.SearchLocator import com.folioreader.model.sqlite.HighLightTable import com.folioreader.ui.base.HtmlTask import com.folioreader.ui.base.HtmlTaskCallback @@ -68,7 +68,7 @@ class FolioPageFragment : Fragment(), private const val BUNDLE_BOOK_TITLE = "BUNDLE_BOOK_TITLE" private const val BUNDLE_SPINE_ITEM = "BUNDLE_SPINE_ITEM" private const val BUNDLE_READ_LOCATOR_CONFIG_CHANGE = "BUNDLE_READ_LOCATOR_CONFIG_CHANGE" - const val BUNDLE_SEARCH_ITEM = "BUNDLE_SEARCH_ITEM" + const val BUNDLE_SEARCH_LOCATOR = "BUNDLE_SEARCH_LOCATOR" @JvmStatic fun newInstance(spineIndex: Int, bookTitle: String, spineRef: Link, bookId: String): FolioPageFragment { @@ -117,7 +117,7 @@ class FolioPageFragment : Fragment(), private var mediaController: MediaController? = null private var mConfig: Config? = null private var mBookId: String? = null - var searchItemVisible: SearchItem? = null + var searchLocatorVisible: SearchLocator? = null private val webviewUrl: String get() = Constants.LOCALHOST + Uri.encode(mBookTitle) + spineItem!!.href @@ -145,9 +145,7 @@ class FolioPageFragment : Fragment(), spineItem = arguments!!.getSerializable(BUNDLE_SPINE_ITEM) as Link mBookId = arguments!!.getString(FolioReader.EXTRA_BOOK_ID) - if (savedInstanceState != null) { - searchItemVisible = savedInstanceState.getParcelable(BUNDLE_SEARCH_ITEM) - } + searchLocatorVisible = savedInstanceState?.getParcelable(BUNDLE_SEARCH_LOCATOR) if (spineItem != null) { // SMIL Parsing not yet implemented in r2-streamer-kotlin @@ -395,7 +393,7 @@ class FolioPageFragment : Fragment(), override fun onPageFinished(view: WebView, url: String) { - mWebview!!.loadUrl("javascript:getCompatMode()") + mWebview!!.loadUrl("javascript:checkCompatMode()") mWebview!!.loadUrl("javascript:alert(getReadingTime())") if (mActivityCallback!!.direction == Config.Direction.HORIZONTAL) @@ -412,12 +410,11 @@ class FolioPageFragment : Fragment(), if (mIsPageReloaded) { - if (searchItemVisible != null) { - val escapedSearchQuery = searchItemVisible!!.searchQuery - .replace("\"", "\\\"") - val call = String.format(getString(R.string.highlight_search_result), - escapedSearchQuery, searchItemVisible!!.occurrenceInChapter) - mWebview!!.loadUrl(call) + if (searchLocatorVisible != null) { + val callHighlightSearchLocator = String.format( + getString(R.string.callHighlightSearchLocator), + searchLocatorVisible?.locations?.cfi) + mWebview!!.loadUrl(callHighlightSearchLocator) } else if (isCurrentFragment) { val cfi = lastReadLocator!!.locations.cfi @@ -443,12 +440,11 @@ class FolioPageFragment : Fragment(), mWebview!!.loadUrl(String.format(getString(R.string.go_to_highlight), highlightId)) highlightId = null - } else if (searchItemVisible != null) { - val escapedSearchQuery = searchItemVisible!!.searchQuery - .replace("\"", "\\\"") - val call = String.format(getString(R.string.highlight_search_result), - escapedSearchQuery, searchItemVisible!!.occurrenceInChapter) - mWebview!!.loadUrl(call) + } else if (searchLocatorVisible != null) { + val callHighlightSearchLocator = String.format( + getString(R.string.callHighlightSearchLocator), + searchLocatorVisible?.locations?.cfi) + mWebview!!.loadUrl(callHighlightSearchLocator) } else if (isCurrentFragment) { @@ -739,12 +735,10 @@ class FolioPageFragment : Fragment(), */ override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) - this.outState = outState + Log.v(LOG_TAG, "-> onSaveInstanceState -> ${spineItem?.href}") - if (isCurrentFragment) - Log.v(LOG_TAG, "-> onSaveInstanceState") - - outState.putParcelable(BUNDLE_SEARCH_ITEM, searchItemVisible) + this.outState = outState + outState.putParcelable(BUNDLE_SEARCH_LOCATOR, searchLocatorVisible) } fun highlight(style: HighlightImpl.HighlightStyle, isAlreadyCreated: Boolean) { @@ -821,22 +815,22 @@ class FolioPageFragment : Fragment(), } } - fun highlightSearchItem(searchItem: SearchItem) { - Log.v(LOG_TAG, "-> highlightSearchItem") - this.searchItemVisible = searchItem + fun highlightSearchLocator(searchLocator: SearchLocator) { + Log.v(LOG_TAG, "-> highlightSearchLocator") + this.searchLocatorVisible = searchLocator if (loadingView != null && loadingView!!.visibility != View.VISIBLE) { loadingView!!.show() - val escapedSearchQuery = searchItem.searchQuery.replace("\"", "\\\"") - val call = String.format(getString(R.string.highlight_search_result), - escapedSearchQuery, searchItem.occurrenceInChapter) - mWebview!!.loadUrl(call) + val callHighlightSearchLocator = String.format( + getString(R.string.callHighlightSearchLocator), + searchLocatorVisible?.locations?.cfi) + mWebview!!.loadUrl(callHighlightSearchLocator) } } - fun resetSearchResults() { - Log.v(LOG_TAG, "-> resetSearchResults -> " + spineItem!!.href!!) - mWebview!!.loadUrl(getString(R.string.reset_search_results)) - searchItemVisible = null + fun clearSearchLocator() { + Log.v(LOG_TAG, "-> clearSearchLocator -> " + spineItem!!.href!!) + mWebview!!.loadUrl(getString(R.string.callClearSelection)) + searchLocatorVisible = null } } diff --git a/folioreader/src/main/java/com/folioreader/view/FolioWebView.kt b/folioreader/src/main/java/com/folioreader/view/FolioWebView.kt index 640da42d1..492c35da8 100644 --- a/folioreader/src/main/java/com/folioreader/view/FolioWebView.kt +++ b/folioreader/src/main/java/com/folioreader/view/FolioWebView.kt @@ -360,16 +360,6 @@ class FolioWebView : WebView { } } - @JavascriptInterface - fun setCompatMode(compatMode: String) { - Log.v(LOG_TAG, "-> setCompatMode -> compatMode = $compatMode") - if (compatMode == context.getString(R.string.back_compat)) { - Log.e(LOG_TAG, "-> Web page loaded in Quirks mode. Please report to developer " + - "for debugging with current EPUB file as many features might stop working " + - "(ex. Horizontal scroll feature).") - } - } - fun setParentFragment(parentFragment: FolioPageFragment) { this.parentFragment = parentFragment } @@ -451,8 +441,7 @@ class FolioWebView : WebView { if (lastScrollType == LastScrollType.USER) { //Log.d(LOG_TAG, "-> onScrollChanged -> scroll initiated by user"); - loadUrl(context.getString(R.string.make_search_results_invisible)) - parentFragment.searchItemVisible = null + parentFragment.searchLocatorVisible = null } lastScrollType = null diff --git a/folioreader/src/test/java/com/folioreader/android/ExampleUnitTest.kt b/folioreader/src/test/java/com/folioreader/android/ExampleUnitTest.kt new file mode 100644 index 000000000..21b401854 --- /dev/null +++ b/folioreader/src/test/java/com/folioreader/android/ExampleUnitTest.kt @@ -0,0 +1,35 @@ +package com.folioreader.android + +import org.junit.Assert.assertEquals +import org.junit.Test +import org.readium.r2.shared.Locations +import org.readium.r2.shared.Locator + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see [Testing documentation](http://d.android.com/tools/testing) + */ +class ExampleUnitTest { + + @Test + fun addition_isCorrect() { + assertEquals(4, (2 + 2).toLong()) + } + + @Test + fun testNullability() { + + var locator = Locator("", 0, "", Locations(), null) + + //var string: String = locator.text?.before + locator.text?.hightlight + locator.text?.after + + var string: String = StringBuilder() + .append(locator.text?.before) + .append(locator.text?.hightlight ?: "") + .append(locator.text?.after ?: "") + .toString() + + println(string) + } +} \ No newline at end of file diff --git a/sample/src/main/assets/Locators/LastReadLocators/last_read_locator_1.json b/sample/src/main/assets/Locators/LastReadLocators/last_read_locator_1.json index dac0d02cd..c744a5ad2 100644 --- a/sample/src/main/assets/Locators/LastReadLocators/last_read_locator_1.json +++ b/sample/src/main/assets/Locators/LastReadLocators/last_read_locator_1.json @@ -3,6 +3,6 @@ "href": "/OEBPS/ch03.xhtml", "created": 1539934158390, "locations": { - "cfi": "epubcfi(/4/4)" + "cfi": "epubcfi(/0!/4/4)" } } \ No newline at end of file diff --git a/sample/src/main/assets/Locators/LastReadLocators/last_read_locator_2.json b/sample/src/main/assets/Locators/LastReadLocators/last_read_locator_2.json index f70318866..3b1a45331 100644 --- a/sample/src/main/assets/Locators/LastReadLocators/last_read_locator_2.json +++ b/sample/src/main/assets/Locators/LastReadLocators/last_read_locator_2.json @@ -3,6 +3,6 @@ "href": "/OEBPS/ch03.xhtml", "created": 1539934158390, "locations": { - "cfi": "epubcfi(/4/4/8/1:0)" + "cfi": "epubcfi(/0!/4/4/8/1:0)" } } \ No newline at end of file