@@ -12,6 +12,9 @@ import android.view.View
1212import android.view.ViewTreeObserver
1313import android.widget.FrameLayout
1414import androidx.core.content.ContextCompat
15+ import kotlinx.coroutines.CoroutineScope
16+ import kotlinx.coroutines.launch
17+ import kotlinx.coroutines.runBlocking
1518import org.wordpress.aztec.AztecAttributes
1619import org.wordpress.aztec.AztecContentChangeWatcher
1720import org.wordpress.aztec.AztecText
@@ -33,6 +36,7 @@ import kotlin.math.min
3336class PlaceholderManager (
3437 private val aztecText : AztecText ,
3538 private val container : FrameLayout ,
39+ private val coroutineScope : CoroutineScope ,
3640 private val htmlTag : String = DEFAULT_HTML_TAG
3741) : AztecContentChangeWatcher.AztecTextChangeObserver,
3842 IHtmlTagHandler ,
@@ -67,7 +71,7 @@ class PlaceholderManager(
6771 * @param type placeholder type
6872 * @param attributes other attributes passed to the view. For example a `src` for an image.
6973 */
70- fun insertItem (type : String , vararg attributes : Pair <String , String >) {
74+ suspend fun insertItem (type : String , vararg attributes : Pair <String , String >) {
7175 val adapter = adapters[type]
7276 ? : throw IllegalArgumentException (" Adapter for inserted type not found. Register it with `registerAdapter` method" )
7377 val attrs = getAttributesForMedia(type, attributes)
@@ -97,21 +101,21 @@ class PlaceholderManager(
97101 aztecText.refreshText(false )
98102 }
99103
100- private fun buildPlaceholderDrawable (adapter : PlaceholderAdapter , attrs : AztecAttributes ): Drawable {
104+ private suspend fun buildPlaceholderDrawable (adapter : PlaceholderAdapter , attrs : AztecAttributes ): Drawable {
101105 val drawable = ContextCompat .getDrawable(aztecText.context, android.R .color.transparent)!!
102106 updateDrawableBounds(adapter, attrs, drawable)
103107 return drawable
104108 }
105109
106- private fun updateAllBelowSelection (selectionStart : Int ) {
110+ private suspend fun updateAllBelowSelection (selectionStart : Int ) {
107111 positionToId.filter {
108112 it.elementPosition >= selectionStart - 1
109113 }.forEach {
110114 insertContentOverSpanWithId(it.uuid, it.elementPosition)
111115 }
112116 }
113117
114- private fun insertContentOverSpanWithId (uuid : String , currentPosition : Int? = null) {
118+ private suspend fun insertContentOverSpanWithId (uuid : String , currentPosition : Int? = null) {
115119 var aztecAttributes: AztecAttributes ? = null
116120 val predicate = object : AztecText .AttributePredicate {
117121 override fun matches (attrs : Attributes ): Boolean {
@@ -127,15 +131,15 @@ class PlaceholderManager(
127131 insertInPosition(aztecAttributes ? : return , targetPosition, currentPosition)
128132 }
129133
130- private fun insertInPosition (attrs : AztecAttributes , targetPosition : Int , currentPosition : Int? = null) {
134+ private suspend fun insertInPosition (attrs : AztecAttributes , targetPosition : Int , currentPosition : Int? = null) {
131135 if (! validateAttributes(attrs)) {
132136 return
133137 }
134138 val uuid = attrs.getValue(UUID_ATTRIBUTE )
135139 val type = attrs.getValue(TYPE_ATTRIBUTE )
136140 val textViewLayout: Layout = aztecText.layout
137141 val parentTextViewRect = Rect ()
138- val targetLineOffset = getLineForOffset(targetPosition)
142+ val targetLineOffset = textViewLayout. getLineForOffset(targetPosition)
139143 if (currentPosition != null ) {
140144 if (targetLineOffset != 0 && currentPosition == targetPosition) {
141145 return
@@ -177,19 +181,6 @@ class PlaceholderManager(
177181 }
178182 }
179183
180- private fun getLineForOffset (offset : Int ): Int {
181- var counter = 0
182- var index = 0
183- for (line in aztecText.text.split(" \n " )) {
184- counter + = line.length + 1
185- if (counter > offset) {
186- break
187- }
188- index + = 1
189- }
190- return index
191- }
192-
193184 private fun validateAttributes (attributes : AztecAttributes ): Boolean {
194185 return attributes.hasAttribute(UUID_ATTRIBUTE ) &&
195186 attributes.hasAttribute(TYPE_ATTRIBUTE ) &&
@@ -210,7 +201,9 @@ class PlaceholderManager(
210201 * Called when the aztec text content changes.
211202 */
212203 override fun onContentChanged () {
213- updateAllBelowSelection(aztecText.selectionStart)
204+ coroutineScope.launch {
205+ updateAllBelowSelection(aztecText.selectionStart)
206+ }
214207 }
215208
216209 /* *
@@ -255,7 +248,7 @@ class PlaceholderManager(
255248 val adapter = adapters[type] ? : return false
256249 val aztecAttributes = AztecAttributes (attributes)
257250 aztecAttributes.setValue(UUID_ATTRIBUTE , UUID .randomUUID().toString())
258- val drawable = buildPlaceholderDrawable(adapter, aztecAttributes)
251+ val drawable = runBlocking { buildPlaceholderDrawable(adapter, aztecAttributes) }
259252 val span = AztecPlaceholderSpan (
260253 context = aztecText.context,
261254 drawable = drawable,
@@ -291,8 +284,8 @@ class PlaceholderManager(
291284 spans.forEach {
292285 val type = it.attributes.getValue(TYPE_ATTRIBUTE )
293286 val adapter = adapters[type] ? : return
294- updateDrawableBounds(adapter, it.attributes, it.drawable)
295- aztecText.post {
287+ coroutineScope.launch {
288+ updateDrawableBounds(adapter, it.attributes, it.drawable)
296289 aztecText.refreshText(false )
297290 insertInPosition(it.attributes, aztecText.editableText.getSpanStart(it))
298291 }
@@ -301,7 +294,7 @@ class PlaceholderManager(
301294 })
302295 }
303296
304- private fun updateDrawableBounds (adapter : PlaceholderAdapter , attrs : AztecAttributes , drawable : Drawable ? ) {
297+ private suspend fun updateDrawableBounds (adapter : PlaceholderAdapter , attrs : AztecAttributes , drawable : Drawable ? ) {
305298 val editorWidth = if (aztecText.width > 0 ) aztecText.width else aztecText.maxImagesWidth
306299 if (drawable?.bounds?.right != editorWidth) {
307300 drawable?.setBounds(0 , 0 , adapter.calculateWidth(attrs, editorWidth), adapter.calculateHeight(attrs, editorWidth))
@@ -335,15 +328,15 @@ class PlaceholderManager(
335328 * @param placeholderUuid the placeholder UUID
336329 * @param attrs aztec attributes of the view
337330 */
338- fun createView (context : Context , placeholderUuid : String , attrs : AztecAttributes ): View
331+ suspend fun createView (context : Context , placeholderUuid : String , attrs : AztecAttributes ): View
339332
340333 /* *
341334 * Called after the view is measured. Use this method if you need the actual width and height of the view to
342335 * draw your media.
343336 * @param view the frame layout wrapping the custom view
344337 * @param placeholderUuid the placeholder ID
345338 */
346- fun onViewCreated (view : View , placeholderUuid : String ) {}
339+ suspend fun onViewCreated (view : View , placeholderUuid : String ) {}
347340
348341 /* *
349342 * Called when the placeholder is deleted by the user. Use this method if you need to clear your data when the
@@ -374,18 +367,18 @@ class PlaceholderManager(
374367 * Returns width of the view based on the HTML attributes. Use this method to either set fixed width or to
375368 * calculate width based on the view.
376369 */
377- fun getWidth (attrs : AztecAttributes ): Proportion = Proportion .Ratio (1.0f )
370+ suspend fun getWidth (attrs : AztecAttributes ): Proportion = Proportion .Ratio (1.0f )
378371
379372 /* *
380373 * Returns height of the view based on the HTML attributes. Use this method to either set fixed height or to
381374 * calculate width based on the view.
382375 */
383- fun getHeight (attrs : AztecAttributes ): Proportion
376+ suspend fun getHeight (attrs : AztecAttributes ): Proportion
384377
385378 /* *
386379 * Returns height of the view based on the width and the placeholder height.
387380 */
388- fun calculateHeight (attrs : AztecAttributes , windowWidth : Int ): Int {
381+ suspend fun calculateHeight (attrs : AztecAttributes , windowWidth : Int ): Int {
389382 return getHeight(attrs).let { height ->
390383 when (height) {
391384 is Proportion .Fixed -> height.value
@@ -404,7 +397,7 @@ class PlaceholderManager(
404397 /* *
405398 * Returns height of the view based on the width and the placeholder height.
406399 */
407- fun calculateWidth (attrs : AztecAttributes , windowWidth : Int ): Int {
400+ suspend fun calculateWidth (attrs : AztecAttributes , windowWidth : Int ): Int {
408401 return getWidth(attrs).let { width ->
409402 when (width) {
410403 is Proportion .Fixed -> min(windowWidth, width.value)
0 commit comments