Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/add support to epub text searching #228

Merged
merged 4 commits into from
Sep 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README-CHANGES.xml
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@
<c:change date="2023-08-12T00:00:00+00:00" summary="Fixed crash when time tracking is not enabled."/>
</c:changes>
</c:release>
<c:release date="2023-09-21T11:16:25+00:00" is-open="true" ticket-system="org.nypl.jira" version="1.6.0">
<c:release date="2023-09-21T15:45:38+00:00" is-open="true" ticket-system="org.nypl.jira" version="1.6.0">
<c:changes>
<c:change date="2023-08-24T00:00:00+00:00" summary="Updated Kotlin version to 1.9.0"/>
<c:change date="2023-08-28T00:00:00+00:00" summary="Fixed crash when opening an audiobook with a null manifest."/>
Expand All @@ -321,11 +321,12 @@
<c:ticket id="PP-443"/>
</c:tickets>
</c:change>
<c:change date="2023-09-21T11:16:25+00:00" summary="Correctly update the Accounts UI when resuming from the lock screen.">
<c:change date="2023-09-21T00:00:00+00:00" summary="Correctly update the Accounts UI when resuming from the lock screen.">
<c:tickets>
<c:ticket id="PP-307"/>
</c:tickets>
</c:change>
<c:change date="2023-09-21T15:45:38+00:00" summary="Added support to EPUB text searching."/>
</c:changes>
</c:release>
</c:releases>
Expand Down
2 changes: 2 additions & 0 deletions simplified-app-palace/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,7 @@ dependencies {
implementation(libs.androidx.lifecycle.process)
implementation(libs.androidx.lifecycle.runtime)
implementation(libs.androidx.lifecycle.viewmodel)
implementation(libs.androidx.lifecycle.viewmodel.ktx)
implementation(libs.androidx.lifecycle.viewmodel.savedstate)
implementation(libs.androidx.loader)
implementation(libs.androidx.localbroadcastmanager)
Expand Down Expand Up @@ -512,6 +513,7 @@ dependencies {
implementation(libs.jackson.databind)
implementation(libs.javax.inject)
implementation(libs.joda.time)
implementation(libs.jsoup)
implementation(libs.koi.core)
implementation(libs.kotlin.reflect)
implementation(libs.kotlin.stdlib)
Expand Down
7 changes: 7 additions & 0 deletions simplified-viewer-epub-readium2/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ dependencies {
implementation(libs.androidx.coordinatorlayout)
implementation(libs.androidx.core)
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.cursoradapter)
implementation(libs.androidx.customview)
implementation(libs.androidx.drawerlayout)
implementation(libs.androidx.fragment)
Expand All @@ -41,7 +42,12 @@ dependencies {
implementation(libs.androidx.lifecycle.livedata.core.ktx)
implementation(libs.androidx.lifecycle.livedata.ktx)
implementation(libs.androidx.lifecycle.viewmodel)
implementation(libs.androidx.lifecycle.viewmodel.ktx)
implementation(libs.androidx.lifecycle.viewmodel.savedstate)
implementation(libs.androidx.paging.common)
implementation(libs.androidx.paging.common.ktx)
implementation(libs.androidx.paging.runtime)
implementation(libs.androidx.paging.runtime.ktx)
implementation(libs.androidx.preference)
implementation(libs.androidx.recycler.view)
implementation(libs.androidx.savedstate)
Expand All @@ -51,6 +57,7 @@ dependencies {
implementation(libs.io7m.jfunctional)
implementation(libs.irradia.mime.api)
implementation(libs.joda.time)
implementation(libs.jsoup)
implementation(libs.kotlin.reflect)
implementation(libs.kotlin.stdlib)
implementation(libs.palace.drm.core)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import org.librarysimplified.r2.api.SR2Event.SR2CommandEvent.SR2CommandEventComp
import org.librarysimplified.r2.api.SR2Event.SR2CommandEvent.SR2CommandEventCompleted.SR2CommandExecutionSucceeded
import org.librarysimplified.r2.api.SR2Event.SR2CommandEvent.SR2CommandExecutionRunningLong
import org.librarysimplified.r2.api.SR2Event.SR2CommandEvent.SR2CommandExecutionStarted
import org.librarysimplified.r2.api.SR2Event.SR2CommandEvent.SR2CommandSearchResults
import org.librarysimplified.r2.api.SR2Event.SR2Error.SR2ChapterNonexistent
import org.librarysimplified.r2.api.SR2Event.SR2Error.SR2WebViewInaccessible
import org.librarysimplified.r2.api.SR2Event.SR2ExternalLinkSelected
Expand All @@ -39,10 +40,12 @@ import org.librarysimplified.r2.views.SR2ReaderViewEvent
import org.librarysimplified.r2.views.SR2ReaderViewEvent.SR2ReaderViewBookEvent.SR2BookLoadingFailed
import org.librarysimplified.r2.views.SR2ReaderViewEvent.SR2ReaderViewControllerEvent.SR2ControllerBecameAvailable
import org.librarysimplified.r2.views.SR2ReaderViewEvent.SR2ReaderViewNavigationEvent.SR2ReaderViewNavigationClose
import org.librarysimplified.r2.views.SR2ReaderViewEvent.SR2ReaderViewNavigationEvent.SR2ReaderViewNavigationOpenSearch
import org.librarysimplified.r2.views.SR2ReaderViewEvent.SR2ReaderViewNavigationEvent.SR2ReaderViewNavigationOpenTOC
import org.librarysimplified.r2.views.SR2ReaderViewModel
import org.librarysimplified.r2.views.SR2ReaderViewModelFactory
import org.librarysimplified.r2.views.SR2TOCFragment
import org.librarysimplified.r2.views.search.SR2SearchFragment
import org.librarysimplified.services.api.Services
import org.nypl.drm.core.AdobeAdeptFileAsset
import org.nypl.drm.core.AxisNowFileAsset
Expand Down Expand Up @@ -121,6 +124,7 @@ class Reader2Activity : AppCompatActivity(R.layout.reader2) {
private lateinit var parameters: Reader2ActivityParameters
private lateinit var readerFragment: Fragment
private lateinit var readerModel: SR2ReaderViewModel
private lateinit var searchFragment: Fragment
private lateinit var tocFragment: Fragment
private var controller: SR2ControllerType? = null
private var controllerSubscription: Disposable? = null
Expand Down Expand Up @@ -189,29 +193,25 @@ class Reader2Activity : AppCompatActivity(R.layout.reader2) {
WebView.setWebContentsDebuggingEnabled(true)
}

if (savedInstanceState == null) {
this.readerFragment =
this.supportFragmentManager.fragmentFactory.instantiate(
this.classLoader,
SR2ReaderFragment::class.java.name
)
this.tocFragment =
this.supportFragmentManager.fragmentFactory.instantiate(
this.classLoader,
SR2TOCFragment::class.java.name
)
this.readerFragment =
this.supportFragmentManager.fragmentFactory.instantiate(
this.classLoader,
SR2ReaderFragment::class.java.name
)
this.searchFragment =
this.supportFragmentManager.fragmentFactory.instantiate(
this.classLoader,
SR2SearchFragment::class.java.name
)
this.tocFragment =
this.supportFragmentManager.fragmentFactory.instantiate(
this.classLoader,
SR2TOCFragment::class.java.name
)

this.supportFragmentManager.beginTransaction()
.replace(R.id.reader2FragmentHost, this.readerFragment, READER_FRAGMENT_TAG)
.add(R.id.reader2FragmentHost, this.tocFragment, TOC_FRAGMENT_TAG)
.hide(this.tocFragment)
.commit()
} else {
this.readerFragment =
this.supportFragmentManager.findFragmentByTag(READER_FRAGMENT_TAG) as SR2ReaderFragment
this.tocFragment =
this.supportFragmentManager.findFragmentByTag(TOC_FRAGMENT_TAG) as SR2TOCFragment
}
this.supportFragmentManager.beginTransaction()
.add(R.id.reader2FragmentHost, this.readerFragment)
.commit()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We aren't reusing fragment instances anymore?

Not that I mind, but ... does this have lifecycle repercussions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are. This adds the reader fragment and then all the operations on fragments are just showing/hiding the current instances (or add one if it's not added already) so there's no recreation of fragments. In the end, when we leave the screen all the instances are destroyed alongside with the activity

}

override fun onStart() {
Expand Down Expand Up @@ -326,6 +326,10 @@ class Reader2Activity : AppCompatActivity(R.layout.reader2) {

is SR2BookLoadingFailed ->
this.onBookLoadingFailed(event.exception)

SR2ReaderViewNavigationOpenSearch -> {
this.openSearch()
}
}
}

Expand Down Expand Up @@ -435,6 +439,8 @@ class Reader2Activity : AppCompatActivity(R.layout.reader2) {
override fun onBackPressed() {
if (this.tocFragment.isVisible) {
this.tocClose()
} else if (this.searchFragment.isVisible) {
this.searchClose()
} else {
super.onBackPressed()
}
Expand Down Expand Up @@ -516,7 +522,8 @@ class Reader2Activity : AppCompatActivity(R.layout.reader2) {
is SR2CommandExecutionStarted,
is SR2CommandExecutionRunningLong,
is SR2CommandExecutionSucceeded,
is SR2CommandExecutionFailed -> {
is SR2CommandExecutionFailed,
is SR2CommandSearchResults -> {
// Nothing
}
}
Expand Down Expand Up @@ -545,20 +552,53 @@ class Reader2Activity : AppCompatActivity(R.layout.reader2) {

this.logger.debug("TOC opening")

val currentTocFragment = this.tocFragment
this.tocFragment =
this.supportFragmentManager.fragmentFactory.instantiate(
this.classLoader,
SR2TOCFragment::class.java.name
)
this.supportFragmentManager.beginTransaction()
.remove(currentTocFragment)
.add(R.id.reader2FragmentHost, this.tocFragment)
val transaction = this.supportFragmentManager.beginTransaction()
.hide(this.readerFragment)
.show(this.tocFragment)

if (this.tocFragment.isAdded) {
transaction.show(tocFragment)
} else {
transaction.add(R.id.reader2FragmentHost, this.tocFragment)
}

transaction.commit()
}

/**
* Close the searching screen
*/

private fun searchClose() {
this.uiThread.checkIsUIThread()

this.logger.debug("Search closing")
this.supportFragmentManager.beginTransaction()
.hide(this.searchFragment)
.show(this.readerFragment)
.commit()
}

/**
* Open the searching screen
*/

private fun openSearch() {
this.uiThread.checkIsUIThread()

this.logger.debug("Search opening")

val transaction = this.supportFragmentManager.beginTransaction()
.hide(this.readerFragment)

if (this.searchFragment.isAdded) {
transaction.show(searchFragment)
} else {
transaction.add(R.id.reader2FragmentHost, this.searchFragment)
}

transaction.commit()
}

/**
* Loading a book failed.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,15 @@ import org.librarysimplified.r2.views.SR2ControllerReference
import org.librarysimplified.r2.views.SR2ReaderFragment
import org.librarysimplified.r2.views.SR2ReaderParameters
import org.librarysimplified.r2.views.SR2ReaderViewEvent
import org.librarysimplified.r2.views.SR2ReaderViewEvent.SR2ReaderViewBookEvent.SR2BookLoadingFailed
import org.librarysimplified.r2.views.SR2ReaderViewEvent.SR2ReaderViewControllerEvent.SR2ControllerBecameAvailable
import org.librarysimplified.r2.views.SR2ReaderViewEvent.SR2ReaderViewNavigationEvent.SR2ReaderViewNavigationClose
import org.librarysimplified.r2.views.SR2ReaderViewEvent.SR2ReaderViewNavigationEvent.SR2ReaderViewNavigationOpenSearch
import org.librarysimplified.r2.views.SR2ReaderViewEvent.SR2ReaderViewNavigationEvent.SR2ReaderViewNavigationOpenTOC
import org.librarysimplified.r2.views.SR2ReaderViewModel
import org.librarysimplified.r2.views.SR2ReaderViewModelFactory
import org.librarysimplified.r2.views.SR2TOCFragment
import org.librarysimplified.r2.views.search.SR2SearchFragment
import org.librarysimplified.services.api.Services
import org.nypl.simplified.accessibility.AccessibilityServiceType
import org.nypl.simplified.books.book_registry.BookPreviewStatus
Expand Down Expand Up @@ -81,6 +87,7 @@ class BookPreviewActivity : AppCompatActivity(R.layout.activity_book_preview) {
private lateinit var previewContainer: FrameLayout
private lateinit var readerFragment: SR2ReaderFragment
private lateinit var readerModel: SR2ReaderViewModel
private lateinit var searchFragment: SR2SearchFragment
private lateinit var tocFragment: SR2TOCFragment

private var file: File? = null
Expand Down Expand Up @@ -116,6 +123,8 @@ class BookPreviewActivity : AppCompatActivity(R.layout.activity_book_preview) {
override fun onBackPressed() {
if (::tocFragment.isInitialized && this.tocFragment.isVisible) {
this.closeTOC()
} else if (::searchFragment.isInitialized && this.searchFragment.isVisible) {
this.closeSearch()
} else {
if (file?.exists() == true) {
file?.delete()
Expand All @@ -132,20 +141,20 @@ class BookPreviewActivity : AppCompatActivity(R.layout.activity_book_preview) {
this.uiThread.checkIsUIThread()

return when (event) {
SR2ReaderViewEvent.SR2ReaderViewNavigationEvent.SR2ReaderViewNavigationClose -> {
SR2ReaderViewNavigationClose -> {
onBackPressed()
}
SR2ReaderViewEvent.SR2ReaderViewNavigationEvent.SR2ReaderViewNavigationOpenTOC -> {
SR2ReaderViewNavigationOpenTOC -> {
openTOC()
}
is SR2ReaderViewEvent.SR2ReaderViewControllerEvent.SR2ControllerBecameAvailable -> {
is SR2ControllerBecameAvailable -> {
this.onControllerBecameAvailable(event.reference)
}
is SR2ReaderViewEvent.SR2ReaderViewBookEvent.SR2BookLoadingFailed -> {
is SR2BookLoadingFailed -> {
handlePreviewDownloadFailed()
}
else -> {
// do nothing
SR2ReaderViewNavigationOpenSearch -> {
openSearch()
}
}
}
Expand Down Expand Up @@ -232,6 +241,10 @@ class BookPreviewActivity : AppCompatActivity(R.layout.activity_book_preview) {
parameters = parameters
)

searchFragment = SR2SearchFragment.create(
parameters = parameters
)

tocFragment = SR2TOCFragment.create(
parameters = parameters
)
Expand Down Expand Up @@ -268,6 +281,33 @@ class BookPreviewActivity : AppCompatActivity(R.layout.activity_book_preview) {
.commit()
}

private fun openSearch() {
this.uiThread.checkIsUIThread()

this.logger.debug("Search opening")

val transaction = this.supportFragmentManager.beginTransaction()
.hide(readerFragment)

if (searchFragment.isAdded) {
transaction.show(searchFragment)
} else {
transaction.add(R.id.preview_container, searchFragment)
}

transaction.commitAllowingStateLoss()
}

private fun closeSearch() {
this.uiThread.checkIsUIThread()

this.logger.debug("Search closing")
this.supportFragmentManager.beginTransaction()
.hide(this.searchFragment)
.show(this.readerFragment)
.commit()
}

private fun getReaderParameters(file: File): SR2ReaderParameters {
return SR2ReaderParameters(
contentProtections = listOf(),
Expand Down