1 /*
<lambda>null2  * Copyright 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.compose.foundation.interaction
18 
19 import androidx.compose.runtime.Composable
20 import androidx.compose.runtime.LaunchedEffect
21 import androidx.compose.runtime.State
22 import androidx.compose.runtime.mutableStateOf
23 import androidx.compose.runtime.remember
24 import kotlinx.coroutines.flow.collect
25 
26 // An interface, not a sealed class, to allow adding new types here in a safe way (and not break
27 // exhaustive when clauses)
28 /**
29  * An interaction related to drag events.
30  *
31  * @see androidx.compose.foundation.gestures.draggable
32  * @see Start
33  * @see Stop
34  * @see Cancel
35  */
36 interface DragInteraction : Interaction {
37     /**
38      * An interaction representing a drag event on a component.
39      *
40      * @see androidx.compose.foundation.gestures.draggable
41      * @see Stop
42      * @see Cancel
43      */
44     class Start : DragInteraction
45 
46     /**
47      * An interaction representing the stopping of a [Start] event on a component.
48      *
49      * @property start the source [Start] interaction that is being stopped
50      * @see androidx.compose.foundation.gestures.draggable
51      * @see Start
52      */
53     class Stop(val start: Start) : DragInteraction
54 
55     /**
56      * An interaction representing the cancellation of a [Start] event on a component.
57      *
58      * @property start the source [Start] interaction that is being cancelled
59      * @see androidx.compose.foundation.gestures.draggable
60      * @see Start
61      */
62     class Cancel(val start: Start) : DragInteraction
63 }
64 
65 /**
66  * Subscribes to this [MutableInteractionSource] and returns a [State] representing whether this
67  * component is dragged or not.
68  *
69  * [DragInteraction] is typically set by interactions such as
70  * [androidx.compose.foundation.gestures.draggable] and
71  * [androidx.compose.foundation.gestures.scrollable], and higher level components such as
72  * [androidx.compose.foundation.lazy.LazyRow], available through
73  * [androidx.compose.foundation.lazy.LazyListState.interactionSource].
74  *
75  * @return [State] representing whether this component is being dragged or not
76  */
77 @Composable
InteractionSourcenull78 fun InteractionSource.collectIsDraggedAsState(): State<Boolean> {
79     val isDragged = remember { mutableStateOf(false) }
80     LaunchedEffect(this) {
81         val dragInteractions = mutableListOf<DragInteraction.Start>()
82         interactions.collect { interaction ->
83             when (interaction) {
84                 is DragInteraction.Start -> dragInteractions.add(interaction)
85                 is DragInteraction.Stop -> dragInteractions.remove(interaction.start)
86                 is DragInteraction.Cancel -> dragInteractions.remove(interaction.start)
87             }
88             isDragged.value = dragInteractions.isNotEmpty()
89         }
90     }
91     return isDragged
92 }
93