mirror of
https://github.com/LiveFastEatTrashRaccoon/RaccoonForLemmy.git
synced 2025-02-03 13:47:31 +01:00
* chore: cleanup markdown click event * chore: prevent clicks on markdown while handling links; closes #259
This commit is contained in:
parent
239aecb83c
commit
a4615d964f
@ -34,7 +34,6 @@ import com.github.diegoberaldin.raccoonforlemmy.core.markdown.model.MarkdownColo
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.markdown.model.MarkdownPadding
|
import com.github.diegoberaldin.raccoonforlemmy.core.markdown.model.MarkdownPadding
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.markdown.model.MarkdownTypography
|
import com.github.diegoberaldin.raccoonforlemmy.core.markdown.model.MarkdownTypography
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.markdown.model.ReferenceLinkHandlerImpl
|
import com.github.diegoberaldin.raccoonforlemmy.core.markdown.model.ReferenceLinkHandlerImpl
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.datetime.DateTime
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.datetime.DateTime
|
||||||
import io.noties.markwon.image.AsyncDrawableSpan
|
import io.noties.markwon.image.AsyncDrawableSpan
|
||||||
import org.intellij.markdown.flavours.MarkdownFlavourDescriptor
|
import org.intellij.markdown.flavours.MarkdownFlavourDescriptor
|
||||||
@ -75,10 +74,7 @@ actual fun CustomMarkdown(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
BoxWithConstraints(
|
BoxWithConstraints(
|
||||||
modifier = modifier.onClick(
|
modifier = modifier
|
||||||
onClick = onClick ?: {},
|
|
||||||
onDoubleClick = onDoubleClick ?: {},
|
|
||||||
)
|
|
||||||
) {
|
) {
|
||||||
val style = LocalMarkdownTypography.current.text
|
val style = LocalMarkdownTypography.current.text
|
||||||
val fontScale = LocalDensity.current.fontScale * 1.25f
|
val fontScale = LocalDensity.current.fontScale * 1.25f
|
||||||
@ -116,7 +112,10 @@ actual fun CustomMarkdown(
|
|||||||
val currentTime = DateTime.epochMillis()
|
val currentTime = DateTime.epochMillis()
|
||||||
if ((currentTime - lastClickTime) < 300) return false
|
if ((currentTime - lastClickTime) < 300) return false
|
||||||
lastClickTime = currentTime
|
lastClickTime = currentTime
|
||||||
|
if (!markwonProvider.isHandlingLink.value) {
|
||||||
|
cancelPendingInputEvents()
|
||||||
onClick?.invoke()
|
onClick?.invoke()
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +123,10 @@ actual fun CustomMarkdown(
|
|||||||
val currentTime = DateTime.epochMillis()
|
val currentTime = DateTime.epochMillis()
|
||||||
if ((currentTime - lastClickTime) < 300) return false
|
if ((currentTime - lastClickTime) < 300) return false
|
||||||
lastClickTime = currentTime
|
lastClickTime = currentTime
|
||||||
|
if (!markwonProvider.isHandlingLink.value) {
|
||||||
|
cancelPendingInputEvents()
|
||||||
onDoubleClick?.invoke()
|
onDoubleClick?.invoke()
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +135,12 @@ actual fun CustomMarkdown(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
setOnTouchListener { _, evt -> gestureDetector.onTouchEvent(evt) }
|
setOnTouchListener { v, evt ->
|
||||||
|
if (evt.action == MotionEvent.ACTION_UP) {
|
||||||
|
v.performClick()
|
||||||
|
}
|
||||||
|
gestureDetector.onTouchEvent(evt)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
update = { textView ->
|
update = { textView ->
|
||||||
@ -157,8 +164,6 @@ private fun createTextView(
|
|||||||
typeface: Typeface? = null,
|
typeface: Typeface? = null,
|
||||||
style: TextStyle,
|
style: TextStyle,
|
||||||
@IdRes viewId: Int? = null,
|
@IdRes viewId: Int? = null,
|
||||||
onClick: (() -> Unit)? = null,
|
|
||||||
onLongClick: ((View) -> Boolean)? = null,
|
|
||||||
): TextView {
|
): TextView {
|
||||||
val mergedStyle = style.merge(
|
val mergedStyle = style.merge(
|
||||||
TextStyle(
|
TextStyle(
|
||||||
@ -168,8 +173,6 @@ private fun createTextView(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
return TextView(context).apply {
|
return TextView(context).apply {
|
||||||
onClick?.let { setOnClickListener { onClick() } }
|
|
||||||
onLongClick?.let { setOnLongClickListener(it) }
|
|
||||||
setTextColor(textColor.toArgb())
|
setTextColor(textColor.toArgb())
|
||||||
setTextSize(TypedValue.COMPLEX_UNIT_SP, mergedStyle.fontSize.value)
|
setTextSize(TypedValue.COMPLEX_UNIT_SP, mergedStyle.fontSize.value)
|
||||||
width = maxWidth
|
width = maxWidth
|
||||||
|
@ -14,7 +14,7 @@ import kotlinx.coroutines.launch
|
|||||||
import org.commonmark.node.Image
|
import org.commonmark.node.Image
|
||||||
import org.commonmark.node.Node
|
import org.commonmark.node.Node
|
||||||
|
|
||||||
private const val TRIGGER_UPDATE_INTERVAL = 250L
|
private const val TRIGGER_UPDATE_INTERVAL = 500L
|
||||||
|
|
||||||
class ClickableImagesPlugin private constructor(
|
class ClickableImagesPlugin private constructor(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
|
@ -14,6 +14,12 @@ import io.noties.markwon.html.HtmlPlugin
|
|||||||
import io.noties.markwon.image.ImagesPlugin
|
import io.noties.markwon.image.ImagesPlugin
|
||||||
import io.noties.markwon.image.gif.GifMediaDecoder
|
import io.noties.markwon.image.gif.GifMediaDecoder
|
||||||
import io.noties.markwon.linkify.LinkifyPlugin
|
import io.noties.markwon.linkify.LinkifyPlugin
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class DefaultMarkwonProvider(
|
class DefaultMarkwonProvider(
|
||||||
context: Context,
|
context: Context,
|
||||||
@ -21,7 +27,10 @@ class DefaultMarkwonProvider(
|
|||||||
onOpenImage: ((String) -> Unit)?,
|
onOpenImage: ((String) -> Unit)?,
|
||||||
onImageTriggerUpdate: (() -> Unit)?,
|
onImageTriggerUpdate: (() -> Unit)?,
|
||||||
) : MarkwonProvider {
|
) : MarkwonProvider {
|
||||||
|
|
||||||
override val markwon: Markwon
|
override val markwon: Markwon
|
||||||
|
override val isHandlingLink = MutableStateFlow(false)
|
||||||
|
private val scope = CoroutineScope(SupervisorJob())
|
||||||
|
|
||||||
init {
|
init {
|
||||||
markwon = Markwon.builder(context)
|
markwon = Markwon.builder(context)
|
||||||
@ -31,13 +40,9 @@ class DefaultMarkwonProvider(
|
|||||||
.usePlugin(TablePlugin.create(context))
|
.usePlugin(TablePlugin.create(context))
|
||||||
.usePlugin(HtmlPlugin.create())
|
.usePlugin(HtmlPlugin.create())
|
||||||
.usePlugin(
|
.usePlugin(
|
||||||
ImagesPlugin.create(
|
ImagesPlugin.create { plugin ->
|
||||||
object : ImagesPlugin.ImagesConfigure {
|
|
||||||
override fun configureImages(plugin: ImagesPlugin) {
|
|
||||||
plugin.addMediaDecoder(GifMediaDecoder.create(true))
|
plugin.addMediaDecoder(GifMediaDecoder.create(true))
|
||||||
}
|
|
||||||
},
|
},
|
||||||
),
|
|
||||||
)
|
)
|
||||||
.usePlugin(MarkwonSpoilerPlugin.create(true))
|
.usePlugin(MarkwonSpoilerPlugin.create(true))
|
||||||
.usePlugin(
|
.usePlugin(
|
||||||
@ -53,7 +58,12 @@ class DefaultMarkwonProvider(
|
|||||||
override fun configureConfiguration(builder: MarkwonConfiguration.Builder) {
|
override fun configureConfiguration(builder: MarkwonConfiguration.Builder) {
|
||||||
builder.linkResolver { view, link ->
|
builder.linkResolver { view, link ->
|
||||||
view.cancelPendingInputEvents()
|
view.cancelPendingInputEvents()
|
||||||
|
isHandlingLink.value = true
|
||||||
onOpenUrl?.invoke(link)
|
onOpenUrl?.invoke(link)
|
||||||
|
scope.launch {
|
||||||
|
delay(300)
|
||||||
|
isHandlingLink.value = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.core.markdown.provider
|
package com.github.diegoberaldin.raccoonforlemmy.core.markdown.provider
|
||||||
|
|
||||||
import io.noties.markwon.Markwon
|
import io.noties.markwon.Markwon
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
|
||||||
interface MarkwonProvider {
|
interface MarkwonProvider {
|
||||||
val markwon: Markwon
|
val markwon: Markwon
|
||||||
|
val isHandlingLink: StateFlow<Boolean>
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user