@@ -27,7 +27,6 @@ import androidx.compose.foundation.layout.fillMaxSize
2727import androidx.compose.material3.Surface
2828import androidx.compose.runtime.Composable
2929import androidx.compose.runtime.getValue
30- import androidx.compose.runtime.mutableFloatStateOf
3130import androidx.compose.runtime.mutableIntStateOf
3231import androidx.compose.runtime.mutableStateOf
3332import androidx.compose.runtime.remember
@@ -37,11 +36,10 @@ import androidx.compose.ui.ExperimentalComposeUiApi
3736import androidx.compose.ui.Modifier
3837import androidx.compose.ui.graphics.Color
3938import androidx.compose.ui.input.pointer.pointerInteropFilter
40- import androidx.compose.ui.platform.LocalDensity
41- import androidx.compose.ui.unit.dp
4239import kotlinx.coroutines.Job
4340import kotlinx.coroutines.delay
4441import kotlinx.coroutines.launch
42+ import net.newpipe.newplayer.ui.common.getPixelsPerCentimeter
4543import kotlin.math.abs
4644
4745private const val TAG = " GestureSurface"
@@ -63,12 +61,20 @@ internal fun GestureSurface(
6361 content : @Composable () -> Unit = {}
6462) {
6563
66- var lastTouchedPosition by remember {
64+ var movementEventsUnlocked by remember {
65+ mutableStateOf(false )
66+ }
67+
68+ var ignoreMovementWhileFingerDown by remember {
69+ mutableStateOf(false )
70+ }
71+
72+ var fingerDownPosition by remember {
6773 mutableStateOf(TouchedPosition (0f , 0f ))
6874 }
6975
70- var yMovementSum by remember {
71- mutableFloatStateOf( 0f )
76+ var lastTouchPosition by remember {
77+ mutableStateOf( TouchedPosition ( 0f , 0f ) )
7278 }
7379
7480 var lastFingerDownTime by remember {
@@ -125,7 +131,7 @@ internal fun GestureSurface(
125131 regularTabJob = composableScope.launch {
126132 delay(ENTER_MULTITAB_MODE_DELAY )
127133
128- val isMultitab = isAMultitapEvent();
134+ val isMultitab = isAMultitapEvent();
129135 val fingerDownUpOk = fingerDownAndUpHappenedInShortEnoughTimeForARegularTab()
130136 if (multitapAmount <= 0 && fingerDownUpOk) {
131137 onRegularTap()
@@ -136,11 +142,13 @@ internal fun GestureSurface(
136142 }
137143 }
138144
139-
140145 val handleActionDown = { event: MotionEvent ->
141146 Log .d(TAG , " finger down" )
142- lastTouchedPosition = TouchedPosition (event.x, event.y)
143- yMovementSum = 0f
147+ fingerDownPosition = TouchedPosition (event.x, event.y)
148+ lastTouchPosition = fingerDownPosition
149+ movementEventsUnlocked = false
150+ ignoreMovementWhileFingerDown = false
151+
144152 if (isAMultitapEvent()) {
145153 onMultitap();
146154 } else {
@@ -151,36 +159,48 @@ internal fun GestureSurface(
151159 }
152160
153161 val handleActionUp = { onMultiTap: (Int ) -> Unit , onRegularTap: () -> Unit ->
154- Log .d(TAG , " finger up" );
162+ Log .d(TAG , " finger up" )
155163 onUp()
156- yMovementSum = 0f
157- lastFingerUpTime = System .currentTimeMillis();
164+ lastFingerUpTime = System .currentTimeMillis()
165+ movementEventsUnlocked = false
166+ ignoreMovementWhileFingerDown = false
158167 true
159168 }
160169
161- val rangeAtWhichItsIntendedMovement = with (LocalDensity .current) {
162- 15 .dp.toPx()
163- }
170+ // prevents detecting movement when actually a tap was intended
171+ val deadZoneRange = 0.1 * getPixelsPerCentimeter()
164172
165- val handleMove = { event: MotionEvent , lambda: (movement: TouchedPosition ) -> Unit ->
166- val currentTouchedPosition = TouchedPosition (event.x, event.y)
167- val movement = currentTouchedPosition - lastTouchedPosition
168173
169- lastTouchedPosition = currentTouchedPosition
174+ val handleMove =
175+ { event: MotionEvent , onFilteredMovementEvent: (movement: TouchedPosition ) -> Unit ->
176+ val currentTouchedPosition = TouchedPosition (event.x, event.y)
177+ val movement = currentTouchedPosition - lastTouchPosition
178+ val vectorFromFingerDownEvent = currentTouchedPosition - fingerDownPosition
170179
171- yMovementSum + = abs(movement.y)
180+ lastTouchPosition = currentTouchedPosition
172181
173- if (yMovementSum < rangeAtWhichItsIntendedMovement) {
174- Log .d(TAG , " cancel regular tab" )
175- regularTabJob?.cancel()
176- }
182+ if (! movementEventsUnlocked && deadZoneRange < vectorFromFingerDownEvent.distance()) {
183+ movementEventsUnlocked = true
184+ if (regularTabJob?.isActive ? : false ) {
185+ Log .d(TAG , " cancel regular tab" )
186+ regularTabJob?.cancel()
187+ }
188+ // if user starts to swipe sideways the movements should be totally ignore
189+ // for as long as the user keeps the finger on the screen.
190+ if (abs(vectorFromFingerDownEvent.y) <= abs(vectorFromFingerDownEvent.x)) {
191+ ignoreMovementWhileFingerDown = true
192+ }
193+ }
177194
178- // filter out left and right movements as these are not important for the app
179- if (abs(movement.x) <= abs(movement.y)) {
180- lambda(movement)
195+ if (movementEventsUnlocked && ! ignoreMovementWhileFingerDown) {
196+ Log .d(TAG , " movement event: distance" )
197+ // filter out left and right movements as these are not important for the app
198+ if (abs(movement.x) <= abs(movement.y)) {
199+ onFilteredMovementEvent(movement)
200+ }
201+ }
202+ true
181203 }
182- true
183- }
184204
185205 Box (modifier = modifier.pointerInteropFilter {
186206 when (it.action) {
@@ -194,4 +214,5 @@ internal fun GestureSurface(
194214 content()
195215 Surface (color = color, modifier = Modifier .fillMaxSize()) {}
196216 }
197- }
217+ }
218+
0 commit comments