commit 7d3a96c52c2f50f3e362c95cbe1c9d27414dfc6f equwal <truex@equwal.com> 2026-09-21 17:27:04 -0700 Add "Share" to the panel "Share" opens the share sheet of Android with the selection, for an app that has no entry in the text selection menu: a flash card app, a notes app, a translator. The player pauses, the same as for "Look up".
README.md | 3 ++- app/src/androidTest/kotlin/space/subread/overlay/OverlayTest.kt | 6 ++++++ app/src/main/kotlin/space/subread/overlay/MediaListener.kt | 5 +++++ app/src/main/kotlin/space/subread/overlay/OverlayView.kt | 7 +++++++ app/src/main/kotlin/space/subread/overlay/Store.kt | 5 +++++ fastlane/metadata/android/en-US/full_description.txt | 2 +- 6 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md index c7c2dab..8146070 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,8 @@ On the panel: - `≡` moves the panel. - A tap selects the word under the finger. A drag selects more words. "Look up" pauses the player and sends the selection to the dictionary. - "Copy" copies it. + "Share" opens the share sheet of Android, for an app without an entry in + the text selection menu. "Copy" copies it. - `▶` starts the player again after a lookup. `⏸` pauses it. - `⋯` opens the timing row. `−0.5 s` and `+0.5 s` shift the subtitles. `◀ line` and `line ▶` make the line before, or the next line, the line of diff --git a/app/src/androidTest/kotlin/space/subread/overlay/OverlayTest.kt b/app/src/androidTest/kotlin/space/subread/overlay/OverlayTest.kt index cdbbaae..d62659d 100644 --- a/app/src/androidTest/kotlin/space/subread/overlay/OverlayTest.kt +++ b/app/src/androidTest/kotlin/space/subread/overlay/OverlayTest.kt @@ -66,11 +66,13 @@ class WordsTest { class OverlayViewTest { private val lookedUp = CopyOnWriteArrayList<String>() + private val shared = CopyOnWriteArrayList<String>() private val events = object : OverlayView.Events { override fun onDrag(dx: Float, dy: Float) = Unit override fun onDragEnd() = Unit override fun onClose() = Unit override fun onLookUp(word: String) { lookedUp += word } + override fun onShare(word: String) { shared += word } override fun onTogglePlay() = Unit override fun onShiftLines(steps: Int) = Unit override fun onNudge(ms: Long) = Unit @@ -112,6 +114,10 @@ class OverlayViewTest { panel.findViewsWithText(found, "Look up", android.view.View.FIND_VIEWS_WITH_TEXT) found.single().performClick() assertEquals(listOf("along is easy"), lookedUp) + found.clear() + panel.findViewsWithText(found, "Share", android.view.View.FIND_VIEWS_WITH_TEXT) + found.single().performClick() + assertEquals(listOf("along is easy"), shared) // The next line has no selection from the line before. panel.showLine("the next line") diff --git a/app/src/main/kotlin/space/subread/overlay/MediaListener.kt b/app/src/main/kotlin/space/subread/overlay/MediaListener.kt index c5a29aa..42914e7 100644 --- a/app/src/main/kotlin/space/subread/overlay/MediaListener.kt +++ b/app/src/main/kotlin/space/subread/overlay/MediaListener.kt @@ -142,6 +142,11 @@ class MediaListener : NotificationListenerService(), OverlayView.Events { } } + override fun onShare(word: String) { + follower.pause() + runCatching { startActivity(Lookup.share(word)) } + } + override fun onTogglePlay() { if (!follower.pause()) follower.play() } diff --git a/app/src/main/kotlin/space/subread/overlay/OverlayView.kt b/app/src/main/kotlin/space/subread/overlay/OverlayView.kt index 268d968..5c8ec7c 100644 --- a/app/src/main/kotlin/space/subread/overlay/OverlayView.kt +++ b/app/src/main/kotlin/space/subread/overlay/OverlayView.kt @@ -37,6 +37,8 @@ class OverlayView(context: Context, private val events: Events) : LinearLayout(c fun onDragEnd() fun onClose() fun onLookUp(word: String) + /** "Share": the selection goes to an app that the user picks in the share sheet. */ + fun onShare(word: String) /** The play button: pause the player when it plays, else start it. */ fun onTogglePlay() fun onShiftLines(steps: Int) @@ -85,6 +87,7 @@ class OverlayView(context: Context, private val events: Events) : LinearLayout(c lookUpRow.gravity = Gravity.END lookUpRow.addView(button("Copy", null) { copy() }, wrap()) + lookUpRow.addView(button("Share", null) { share() }, wrap()) lookUpRow.addView(button("Look up", null) { lookUp() }, wrap()) lookUpRow.visibility = View.GONE addView(lookUpRow, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)) @@ -193,6 +196,10 @@ class OverlayView(context: Context, private val events: Events) : LinearLayout(c events.onLookUp(selected() ?: return) } + private fun share() { + events.onShare(selected() ?: return) + } + private fun copy() { val word = selected() ?: return context.getSystemService(ClipboardManager::class.java).setPrimaryClip(ClipData.newPlainText("subtitle", word)) diff --git a/app/src/main/kotlin/space/subread/overlay/Store.kt b/app/src/main/kotlin/space/subread/overlay/Store.kt index 6180d97..8beabc7 100644 --- a/app/src/main/kotlin/space/subread/overlay/Store.kt +++ b/app/src/main/kotlin/space/subread/overlay/Store.kt @@ -68,6 +68,11 @@ object Lookup { /** The intent that each app with "process text" in its manifest takes. It is what a text selection menu sends. */ fun probe(): Intent = Intent(Intent.ACTION_PROCESS_TEXT).setType("text/plain") + /** The share sheet of Android: each app that takes a text, also one without "process text". */ + fun share(word: String): Intent = + Intent.createChooser(Intent(Intent.ACTION_SEND).setType("text/plain").putExtra(Intent.EXTRA_TEXT, word), null) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + fun intent(word: String, chosen: ComponentName?): Intent { val send = probe() .putExtra(Intent.EXTRA_PROCESS_TEXT, word) diff --git a/fastlane/metadata/android/en-US/full_description.txt b/fastlane/metadata/android/en-US/full_description.txt index 8b52840..1147b32 100644 --- a/fastlane/metadata/android/en-US/full_description.txt +++ b/fastlane/metadata/android/en-US/full_description.txt @@ -3,7 +3,7 @@ SubRead Overlay shows the lines of a subtitle file (.srt) over the app that play <b>What it does</b> * Works with each player that publishes an Android media session: Voice, VLC, mpv-android, podcast apps and more. No player needs a change. -* Tap a word to select it. Drag to select more words. "Look up" pauses the player and sends the selection to a dictionary, a translator or a flash card app. Each app with an entry in the text selection menu can be the target. A button on the panel starts the player again. +* Tap a word to select it. Drag to select more words. "Look up" pauses the player and sends the selection to a dictionary, a translator or a flash card app. Each app with an entry in the text selection menu can be the target. "Share" opens the share sheet of Android for the other apps. A button on the panel starts the player again. * On request the panel shows the line before and the line after too, and lets the player show through. * The line stays on the panel until the next line starts, so there is time to look a word up. * A timing row shifts the subtitles by half a second, or makes the line before or the next line the line of now.