Skip to content

Commit 261bc3d

Browse files
committed
Merge branch 'feature/whereami'
2 parents 8b5b705 + e68fd68 commit 261bc3d

5 files changed

Lines changed: 142 additions & 5 deletions

File tree

org.librarysimplified.r2.api/src/main/java/org/librarysimplified/r2/api/SR2ControllerType.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.librarysimplified.r2.api
22

3+
import android.content.res.Resources
34
import android.webkit.WebView
45
import io.reactivex.Observable
56
import java.io.Closeable
@@ -99,4 +100,13 @@ interface SR2ControllerType :
99100
*/
100101

101102
fun isFixedLayout(): Boolean
103+
104+
/**
105+
* Get a human-readable string that describes where the user currently is in the book. For
106+
* example, "Chapter 1: A Chapter, Page 3".
107+
*
108+
* @return A human-readable string representing the current position in the book
109+
*/
110+
111+
fun whereAmI(resources: Resources): String
102112
}

org.librarysimplified.r2.vanilla/src/main/java/org/librarysimplified/r2/vanilla/internal/SR2Controller.kt

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.librarysimplified.r2.vanilla.internal
22

33
import android.app.Application
4+
import android.content.res.Resources
45
import android.webkit.WebResourceResponse
56
import android.webkit.WebView
67
import io.reactivex.Observable
@@ -38,6 +39,7 @@ import org.librarysimplified.r2.api.SR2PrintPageEntry
3839
import org.librarysimplified.r2.api.SR2Theme
3940
import org.librarysimplified.r2.ui_thread.SR2UIThread
4041
import org.librarysimplified.r2.vanilla.BuildConfig
42+
import org.librarysimplified.r2.vanilla.R
4143
import org.readium.r2.shared.ExperimentalReadiumApi
4244
import org.readium.r2.shared.publication.Href
4345
import org.readium.r2.shared.publication.Layout
@@ -211,6 +213,8 @@ internal class SR2Controller private constructor(
211213
}
212214
}
213215

216+
@Volatile
217+
private var latestPositionEvent: SR2ReadingPositionChanged? = null
214218
private val errorAttributes =
215219
ConcurrentHashMap<String, String>()
216220
private val subscriptions =
@@ -1005,7 +1009,7 @@ internal class SR2Controller private constructor(
10051009
currentTarget.node.navigationPoint.locator.chapterHref
10061010
val targetTitle =
10071011
currentTarget.node.title
1008-
controller.publishEvent(
1012+
val newEvent =
10091013
SR2ReadingPositionChanged(
10101014
chapterHref = targetHref,
10111015
chapterTitle = targetTitle,
@@ -1015,8 +1019,9 @@ internal class SR2Controller private constructor(
10151019
bookProgress = controller.currentBookProgress,
10161020
estimatedBookPageCurrent = estimate?.first,
10171021
estimatedBookPageTotal = estimate?.second,
1018-
),
1019-
)
1022+
)
1023+
controller.latestPositionEvent = newEvent
1024+
controller.publishEvent(newEvent)
10201025
} else {
10211026
controller.logger.warn(
10221027
"{} onReadingPositionChanged: currentTarget -> null",
@@ -1188,6 +1193,28 @@ internal class SR2Controller private constructor(
11881193
null -> false
11891194
}
11901195

1196+
override fun whereAmI(resources: Resources): String {
1197+
val mostRecent = this.latestPositionEvent
1198+
if (mostRecent != null) {
1199+
val bookPage =
1200+
mostRecent.estimatedBookPageCurrent ?: mostRecent.currentPage ?: 0
1201+
1202+
val builder = StringBuilder()
1203+
builder.append(resources.getString(R.string.whereAmI_bookPage, bookPage))
1204+
1205+
val title = mostRecent.chapterTitle
1206+
if (title != null) {
1207+
builder.append(resources.getString(R.string.whereAmI_chapter, title))
1208+
}
1209+
val bookProgress = mostRecent.bookProgressPercent
1210+
if (bookProgress != null) {
1211+
builder.append(resources.getString(R.string.whereAmI_bookProgress, bookProgress))
1212+
}
1213+
return builder.toString()
1214+
}
1215+
return ""
1216+
}
1217+
11911218
override fun viewConnect(webView: WebView) {
11921219
this.logger.debug("{} viewConnect", this.name())
11931220

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
3+
<resources>
4+
<string name="whereAmI_bookPage">You are currently at book page %1$d.</string>
5+
<string name="whereAmI_chapter">Chapter %1$s.</string>
6+
<string name="whereAmI_bookProgress">Your current progress in the book is %1$d percent.</string>
7+
</resources>

org.librarysimplified.r2.views/src/main/java/org/librarysimplified/r2/views/SR2ReaderFragment.kt

Lines changed: 93 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,18 @@ import android.widget.ProgressBar
1717
import android.widget.TextView
1818
import android.widget.Toast
1919
import androidx.annotation.Dimension
20-
import androidx.core.view.ViewCompat
2120
import androidx.core.view.WindowInsetsCompat
21+
import androidx.core.view.ViewCompat
22+
import androidx.core.view.accessibility.AccessibilityViewCommand
23+
import androidx.core.view.updatePadding
2224
import androidx.core.view.updatePadding
2325
import io.reactivex.disposables.CompositeDisposable
2426
import io.reactivex.disposables.Disposables
2527
import org.librarysimplified.r2.api.SR2ColorScheme.DARK_TEXT_LIGHT_BACKGROUND
2628
import org.librarysimplified.r2.api.SR2ColorScheme.DARK_TEXT_ON_SEPIA
2729
import org.librarysimplified.r2.api.SR2ColorScheme.LIGHT_TEXT_DARK_BACKGROUND
2830
import org.librarysimplified.r2.api.SR2Command
31+
import org.librarysimplified.r2.api.SR2ControllerType
2932
import org.librarysimplified.r2.api.SR2Event
3033
import org.librarysimplified.r2.api.SR2Event.SR2BookmarkEvent.SR2BookmarkCreated
3134
import org.librarysimplified.r2.api.SR2Event.SR2BookmarkEvent.SR2BookmarkDeleted
@@ -460,10 +463,12 @@ class SR2ReaderFragment : SR2Fragment() {
460463
true
461464
}
462465
}
466+
467+
this.setupWhereAmIAccessibilityAction(event.controller)
463468
}
464469

465470
is SR2ControllerBecameUnavailable -> {
466-
// Nothing to do here.
471+
this.removeWhereAmIAccessibilityAction()
467472
}
468473
}
469474
}
@@ -707,4 +712,90 @@ class SR2ReaderFragment : SR2Fragment() {
707712
this.loadingView.visibility = loadingVisibility
708713
}
709714
}
715+
716+
/**
717+
* Set up the "Where am I?" TalkBack custom accessibility action on all non-WebView views.
718+
* The action appears in the TalkBack context menu when any of these views have focus.
719+
*/
720+
721+
private fun setupWhereAmIAccessibilityAction(controller: SR2ControllerType,) {
722+
val label = this.getString(R.string.accessibilityWhereAmI)
723+
val command =
724+
AccessibilityViewCommand { _, _ ->
725+
val positionDescription = controller.whereAmI(this.resources)
726+
this.webView.announceForAccessibility(positionDescription)
727+
true
728+
}
729+
730+
// Add the action to all non-WebView views that TalkBack can focus
731+
val views =
732+
listOf(
733+
this.root,
734+
this.container,
735+
this.toolbar,
736+
this.titleText,
737+
this.titleTouch,
738+
this.titleTouchIcon,
739+
this.uiShow,
740+
this.uiShowIcon,
741+
this.loadingView,
742+
this.progressContainer,
743+
this.progressViewContainer,
744+
this.progressViewBorder,
745+
this.progressViewFill,
746+
this.positionPageView,
747+
this.positionTitleView,
748+
this.positionPercentView,
749+
this.buttonBack,
750+
this.buttonBackIcon,
751+
this.buttonBookmark,
752+
this.buttonBookmarkIcon,
753+
this.buttonSearch,
754+
this.buttonSearchIcon,
755+
this.buttonSettings,
756+
this.buttonSettingsIcon,
757+
this.centerTouch,
758+
)
759+
for (view in views) {
760+
ViewCompat.addAccessibilityAction(view, label, command)
761+
}
762+
}
763+
764+
/**
765+
* Remove the "Where am I?" TalkBack custom accessibility action from all non-WebView views.
766+
*/
767+
768+
private fun removeWhereAmIAccessibilityAction() {
769+
val views =
770+
listOf(
771+
this.root,
772+
this.container,
773+
this.toolbar,
774+
this.titleText,
775+
this.titleTouch,
776+
this.titleTouchIcon,
777+
this.uiShow,
778+
this.uiShowIcon,
779+
this.loadingView,
780+
this.progressContainer,
781+
this.progressViewContainer,
782+
this.progressViewBorder,
783+
this.progressViewFill,
784+
this.positionPageView,
785+
this.positionTitleView,
786+
this.positionPercentView,
787+
this.buttonBack,
788+
this.buttonBackIcon,
789+
this.buttonBookmark,
790+
this.buttonBookmarkIcon,
791+
this.buttonSearch,
792+
this.buttonSearchIcon,
793+
this.buttonSettings,
794+
this.buttonSettingsIcon,
795+
this.centerTouch,
796+
)
797+
for (view in views) {
798+
ViewCompat.setAccessibilityDelegate(view, null)
799+
}
800+
}
710801
}

org.librarysimplified.r2.views/src/main/res/values/sr2_strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@
6767
<string name="accessibilitySetSizeSmaller">Decrease text size.</string>
6868
<string name="accessibilityBrightnessSlider">Brightness adjustment slider</string>
6969

70+
<string name="accessibilityWhereAmI">Where am I?</string>
71+
7072
<string name="accessibilitySetPageButtonsOff">Turn off page buttons.</string>
7173
<string name="accessibilitySetPageButtonsSmall">Set page buttons to small.</string>
7274
<string name="accessibilitySetPageButtonsMedium">Set page buttons to medium size.</string>

0 commit comments

Comments
 (0)