[go: nahoru, domu]

[Text Selection] Fix crashes of longpress the blank area in non-empty text.

Bug:187437299
Test: Manually tested.
Test: ./gradlew test

RelNote: Fix crashes of longpress the blank area in non-empty text.
Change-Id: I33ab5d732fc3564ec4fe99b16234a980f51684a8
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/selection/SelectionManager.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/selection/SelectionManager.kt
index 25e8c89..1774fd4 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/selection/SelectionManager.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/selection/SelectionManager.kt
@@ -203,6 +203,21 @@
                 hideSelectionToolbar()
             }
 
+        selectionRegistrar.>
+            { selectableId ->
+                val (newSelection, newSubselection) = mergeSelections(
+                    selectableId = selectableId,
+                    previousSelection = selection,
+                )
+                if (newSelection != selection) {
+                    selectionRegistrar.subselections = newSubselection
+                    onSelectionChange(newSelection)
+                }
+
+                focusRequester.requestFocus()
+                hideSelectionToolbar()
+            }
+
         selectionRegistrar.>
             { layoutCoordinates, startPosition, endPosition, selectionMode ->
                 val startPositionOrCurrent = if (startPosition == null) {
@@ -356,6 +371,24 @@
         return Pair(newSelection, subselections)
     }
 
+    internal fun mergeSelections(
+        previousSelection: Selection? = null,
+        selectableId: Long
+    ): Pair<Selection?, Map<Long, Selection>> {
+        val subselections = mutableMapOf<Long, Selection>()
+        val newSelection = selectionRegistrar.sort(requireContainerCoordinates())
+            .fastFold(null) { mergedSelection: Selection?, selectable: Selectable ->
+                val selection = if (selectable.selectableId == selectableId)
+                    selectable.getSelectAllSelection() else null
+                selection?.let { subselections[selectable.selectableId] = it }
+                merge(mergedSelection, selection)
+            }
+        if (previousSelection != newSelection) hapticFeedBack?.performHapticFeedback(
+            HapticFeedbackType.TextHandleMove
+        )
+        return Pair(newSelection, subselections)
+    }
+
     internal fun getSelectedText(): AnnotatedString? {
         val selectables = selectionRegistrar.sort(requireContainerCoordinates())
         var selectedText: AnnotatedString? = null