track last tap location to show android highlight menu in right place

This commit is contained in:
Satindar Dhillon 2022-11-29 22:28:16 -08:00
parent e3ccdc4b41
commit 5f2a667bec
6 changed files with 61 additions and 31 deletions

File diff suppressed because one or more lines are too long

View file

@ -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 presidents 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?,

View file

@ -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()
)
}
}

View file

@ -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

View file

@ -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',