@@ -116,43 +116,83 @@ class PlaceholderManager(
116116 ).lastOrNull()
117117 val currentType = currentItem?.attributes?.getValue(TYPE_ATTRIBUTE )
118118 if (currentType != null && shouldMergeItem(currentType)) {
119- val adapter = adapters[type]
120- ? : throw IllegalArgumentException (" Adapter for inserted type not found. Register it with `registerAdapter` method" )
121- val currentAttributes = mutableMapOf<String , String >()
122- val uuid = currentItem.attributes.getValue(UUID_ATTRIBUTE )
123- for (i in 0 until currentItem.attributes.length) {
124- val name = currentItem.attributes.getQName(i)
125- val value = currentItem.attributes.getValue(name)
126- currentAttributes[name] = value
127- }
128- val updatedAttributes = updateItem(currentAttributes, currentType)
129- removeItem { aztecAttributes ->
130- aztecAttributes.getValue(UUID_ATTRIBUTE ) == uuid
131- }
132- val attrs = AztecAttributes ().apply {
133- updatedAttributes.forEach { (key, value) ->
134- setValue(key, value)
135- }
136- }
137- attrs.setValue(UUID_ATTRIBUTE , uuid)
138- attrs.setValue(TYPE_ATTRIBUTE , type)
139- val drawable = buildPlaceholderDrawable(adapter, attrs)
140- aztecText.insertMediaSpan(AztecPlaceholderSpan (aztecText.context, drawable, 0 , attrs,
141- this , aztecText, WeakReference (adapter), TAG = htmlTag))
142- insertContentOverSpanWithId(uuid)
119+ updateSpan(type, currentItem, updateItem, currentType)
143120 } else {
144121 insertItem(type, * updateItem(null , null ).toList().toTypedArray())
145122 }
146123 }
147124
125+ private suspend fun updateSpan (
126+ type : String ,
127+ currentItem : AztecPlaceholderSpan ,
128+ updateItem : (currentAttributes: Map <String , String >, currentType: String ) -> Map <String , String >,
129+ currentType : String
130+ ) {
131+ val adapter = adapters[type]
132+ ? : throw IllegalArgumentException (" Adapter for inserted type not found. Register it with `registerAdapter` method" )
133+ val currentAttributes = mutableMapOf<String , String >()
134+ val uuid = currentItem.attributes.getValue(UUID_ATTRIBUTE )
135+ for (i in 0 until currentItem.attributes.length) {
136+ val name = currentItem.attributes.getQName(i)
137+ val value = currentItem.attributes.getValue(name)
138+ currentAttributes[name] = value
139+ }
140+ val updatedAttributes = updateItem(currentAttributes, currentType)
141+ removeItem(uuid)
142+ val attrs = AztecAttributes ().apply {
143+ updatedAttributes.forEach { (key, value) ->
144+ setValue(key, value)
145+ }
146+ }
147+ attrs.setValue(UUID_ATTRIBUTE , uuid)
148+ attrs.setValue(TYPE_ATTRIBUTE , type)
149+ val drawable = buildPlaceholderDrawable(adapter, attrs)
150+ aztecText.insertMediaSpan(AztecPlaceholderSpan (aztecText.context, drawable, 0 , attrs,
151+ this , aztecText, WeakReference (adapter), TAG = htmlTag))
152+ insertContentOverSpanWithId(uuid)
153+ }
154+
155+ /* *
156+ * Use this function to either update or remove an item. The decision whether to remove or update will be made
157+ * based upon the results of the parameter functions. An example of usage is a gallery of images. If the user wants
158+ * to remove one image in the gallery, they would call this method. If the removed image is one of many, they might
159+ * want to update the current parameters instead of removing the entire gallery. However, if the removed image is
160+ * the last one in the gallery, they will probably want to remove the entire gallery.
161+ * @param uuid UUID of the span we want to remove or update
162+ * @param shouldUpdateItem This function should return true if the span can be updated, false if it should be removed
163+ * @param updateItem Function that updates the selected item
164+ */
165+ suspend fun removeOrUpdate (uuid : String , shouldUpdateItem : (Attributes ) -> Boolean , updateItem : (currentAttributes: Map <String , String >) -> Map <String , String >): Boolean {
166+ val currentItem = aztecText.editableText.getSpans(0 , aztecText.length(), AztecPlaceholderSpan ::class .java).find {
167+ it.attributes.getValue(UUID_ATTRIBUTE ) == uuid
168+ } ? : return false
169+ if (shouldUpdateItem(currentItem.attributes)) {
170+ val type = currentItem.attributes.getValue(TYPE_ATTRIBUTE )
171+ updateSpan(type, currentItem, updateItem = { attributes, _ ->
172+ updateItem(attributes)
173+ }, type)
174+ } else {
175+ removeItem(uuid)
176+ }
177+ return true
178+ }
179+
148180 /* *
149- * Call this method to remove a placeholder from both the AztecText and the overlaying layer programatically .
181+ * Call this method to remove a placeholder from both the AztecText and the overlaying layer programmatically .
150182 * @param predicate determines whether a span should be removed
151183 */
152184 fun removeItem (predicate : (Attributes ) -> Boolean ) {
153185 aztecText.removeMedia { predicate(it) }
154186 }
155187
188+ /* *
189+ * Call this method to remove a placeholder from both the AztecText and the overlaying layer programmatically.
190+ * @param uuid of the removed item
191+ */
192+ fun removeItem (uuid : String ) {
193+ aztecText.removeMedia { it.getValue(UUID_ATTRIBUTE ) == uuid }
194+ }
195+
156196 private suspend fun buildPlaceholderDrawable (adapter : PlaceholderAdapter , attrs : AztecAttributes ): Drawable {
157197 val drawable = ContextCompat .getDrawable(aztecText.context, android.R .color.transparent)!!
158198 updateDrawableBounds(adapter, attrs, drawable)
0 commit comments