mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
track last tap location to show android highlight menu in right place
This commit is contained in:
parent
e3ccdc4b41
commit
5f2a667bec
6 changed files with 61 additions and 31 deletions
File diff suppressed because one or more lines are too long
|
|
@ -29,16 +29,6 @@ data class CreateHighlightParams(
|
|||
)
|
||||
}
|
||||
|
||||
//2022-11-29 13:41:56.273 13373-14177/app.omnivore.omnivore D/wv: received actionID from Android:
|
||||
// mergeHighlight, {
|
||||
// "prefix":"In what may be its final public hearing, the committee intends to present new theevidence about the former president’s state of mind and central role in the plan to overturn ",
|
||||
// "suffix":"2020 election.",
|
||||
// "quote":"",
|
||||
// "id":"646a3b52-a134-469e-8ea3-26aad47f74c3",
|
||||
// "shortId":"IK35C_Hp","patch":"@@ -307,32 +307,73 @@\n to overturn the\n+%3Comnivore_highlight%3E%3C/omnivore_highlight%3E\n 2020 election.P\n",
|
||||
// "articleId":"14bb47ff-af23-461b-8ce3-1afe6b8bdc5b",
|
||||
// "overlapHighlightIdList":[""]}
|
||||
|
||||
data class MergeHighlightsParams(
|
||||
val shortId: String?,
|
||||
val highlightID: String?,
|
||||
|
|
|
|||
|
|
@ -148,6 +148,8 @@ fun WebReader(
|
|||
Box {
|
||||
AndroidView(factory = {
|
||||
OmnivoreWebView(it).apply {
|
||||
viewModel = webReaderViewModel
|
||||
|
||||
layoutParams = ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT
|
||||
|
|
@ -162,13 +164,20 @@ fun WebReader(
|
|||
}
|
||||
|
||||
val javascriptInterface = AndroidWebKitMessenger { actionID, json ->
|
||||
Log.d("wv", "received actionID from Android: $actionID, $json")
|
||||
webReaderViewModel.hasTappedExistingHighlight = false
|
||||
|
||||
when (actionID) {
|
||||
"userTap" -> {
|
||||
val tapCoordinates = Gson().fromJson(json, ActionTapCoordinates::class.java)
|
||||
Log.d("wvt", "received tap action: $tapCoordinates")
|
||||
webReaderViewModel.lastTappedLocationRect = tapCoordinates.asRect()
|
||||
}
|
||||
"existingHighlightTap" -> {
|
||||
isExistingHighlightSelected = true
|
||||
actionTapCoordinates = Gson().fromJson(json, ActionTapCoordinates::class.java)
|
||||
val actionTapCoordinates = Gson().fromJson(json, ActionTapCoordinates::class.java)
|
||||
Log.d("wv", "receive existing highlight tap action: $actionTapCoordinates")
|
||||
startActionMode(null, ActionMode.TYPE_PRIMARY)
|
||||
webReaderViewModel.hasTappedExistingHighlight = true
|
||||
webReaderViewModel.lastTappedLocationRect = actionTapCoordinates.asRect()
|
||||
startActionMode(null, ActionMode.TYPE_FLOATING)
|
||||
}
|
||||
else -> {
|
||||
webReaderViewModel.handleIncomingWebMessage(actionID, json)
|
||||
|
|
@ -199,15 +208,14 @@ fun WebReader(
|
|||
}
|
||||
|
||||
class OmnivoreWebView(context: Context) : WebView(context) {
|
||||
var isExistingHighlightSelected = false
|
||||
var actionTapCoordinates: ActionTapCoordinates? = null
|
||||
var viewModel: WebReaderViewModel? = null
|
||||
|
||||
private val actionModeCallback = object : ActionMode.Callback2() {
|
||||
// Called when the action mode is created; startActionMode() was called
|
||||
override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
|
||||
if (isExistingHighlightSelected) {
|
||||
if (viewModel?.hasTappedExistingHighlight == true) {
|
||||
Log.d("wv", "inflating existing highlight menu")
|
||||
mode.menuInflater.inflate(R.menu.highlight_selection_menu, menu)
|
||||
isExistingHighlightSelected = false
|
||||
} else {
|
||||
mode.menuInflater.inflate(R.menu.text_selection_menu, menu)
|
||||
}
|
||||
|
|
@ -253,18 +261,23 @@ class OmnivoreWebView(context: Context) : WebView(context) {
|
|||
|
||||
// Called when the user exits the action mode
|
||||
override fun onDestroyActionMode(mode: ActionMode) {
|
||||
Log.d("Loggo", "destroying menu: $mode")
|
||||
isExistingHighlightSelected = false
|
||||
actionTapCoordinates = null
|
||||
Log.d("wv", "destroying menu: $mode")
|
||||
viewModel?.hasTappedExistingHighlight = false
|
||||
}
|
||||
|
||||
override fun onGetContentRect(mode: ActionMode?, view: View?, outRect: Rect?) {
|
||||
Log.d("Loggo", "outRect: $outRect, View: $view")
|
||||
outRect?.set(left, top, right, bottom)
|
||||
Log.d("wv", "outRect: $outRect, View: $view")
|
||||
if (viewModel?.lastTappedLocationRect != null) {
|
||||
Log.d("wv", "setting rect based on last tapped rect")
|
||||
outRect?.set(viewModel!!.lastTappedLocationRect!!)
|
||||
} else {
|
||||
outRect?.set(left, top, right, bottom)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun startActionMode(callback: ActionMode.Callback?): ActionMode {
|
||||
Log.d("wv", "startActionMode:callback called")
|
||||
return super.startActionMode(actionModeCallback)
|
||||
}
|
||||
|
||||
|
|
@ -272,11 +285,12 @@ class OmnivoreWebView(context: Context) : WebView(context) {
|
|||
originalView: View?,
|
||||
callback: ActionMode.Callback?
|
||||
): ActionMode {
|
||||
Log.d("wv", "startActionMode:originalView:callback called")
|
||||
return super.startActionModeForChild(originalView, actionModeCallback)
|
||||
}
|
||||
|
||||
override fun startActionMode(callback: ActionMode.Callback?, type: Int): ActionMode {
|
||||
Log.d("Loggo", "startActionMode:type called")
|
||||
Log.d("wv", "startActionMode:type called")
|
||||
return super.startActionMode(actionModeCallback, type)
|
||||
}
|
||||
}
|
||||
|
|
@ -293,4 +307,13 @@ data class ActionTapCoordinates(
|
|||
val rectY: Double,
|
||||
val rectWidth: Double,
|
||||
val rectHeight: Double,
|
||||
)
|
||||
) {
|
||||
fun asRect(): Rect {
|
||||
return Rect(
|
||||
rectX.toInt(),
|
||||
rectY.toInt(),
|
||||
rectX.toInt(),
|
||||
rectY.toInt()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package app.omnivore.omnivore.ui.reader
|
||||
|
||||
import android.graphics.Rect
|
||||
import android.util.Log
|
||||
import androidx.compose.foundation.ScrollState
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
|
|
@ -39,6 +40,9 @@ class WebReaderViewModel @Inject constructor(
|
|||
val annotationLiveData = MutableLiveData<String?>(null)
|
||||
val javascriptActionLoopUUIDLiveData = MutableLiveData(lastJavascriptActionLoopUUID)
|
||||
|
||||
var hasTappedExistingHighlight = false
|
||||
var lastTappedLocationRect: Rect? = null
|
||||
|
||||
fun loadItem(slug: String) {
|
||||
viewModelScope.launch {
|
||||
val articleQueryResult = networker.linkedItem(slug)
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -270,6 +270,20 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
|
|||
return
|
||||
}
|
||||
|
||||
const rect = (target as Element).getBoundingClientRect()
|
||||
|
||||
const rectAttributes = {
|
||||
rectX: rect.x,
|
||||
rectY: rect.y,
|
||||
rectWidth: rect.width,
|
||||
rectHeight: rect.height,
|
||||
}
|
||||
|
||||
window?.AndroidWebKitMessenger?.handleIdentifiableMessage(
|
||||
'userTap',
|
||||
JSON.stringify(rectAttributes)
|
||||
)
|
||||
|
||||
focusedHighlightMousePos.current = { pageX, pageY }
|
||||
|
||||
if ((target as Element).hasAttribute(highlightIdAttribute)) {
|
||||
|
|
@ -283,13 +297,9 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
|
|||
if (highlight) {
|
||||
// In the native app we post a message with the rect of the
|
||||
// highlight, so the app can display a native menu
|
||||
const rect = (target as Element).getBoundingClientRect()
|
||||
const message = {
|
||||
rectX: rect.x,
|
||||
rectY: rect.y,
|
||||
rectWidth: rect.width,
|
||||
rectHeight: rect.height,
|
||||
highlightID: highlight.id,
|
||||
...rectAttributes,
|
||||
}
|
||||
window?.webkit?.messageHandlers.viewerAction?.postMessage({
|
||||
actionID: 'showMenu',
|
||||
|
|
|
|||
Loading…
Reference in a new issue