Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport rotary updates #1742

Merged
merged 5 commits into from
Oct 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 20 additions & 10 deletions compose-layout/api/current.api
Original file line number Diff line number Diff line change
Expand Up @@ -311,9 +311,11 @@ package com.google.android.horologist.compose.rotaryinput {

@com.google.android.horologist.annotations.ExperimentalHorologistApi public final class DefaultSnapBehavior implements com.google.android.horologist.compose.rotaryinput.RotarySnapBehavior {
ctor public DefaultSnapBehavior(com.google.android.horologist.compose.rotaryinput.RotaryScrollAdapter rotaryScrollAdapter, com.google.android.horologist.compose.rotaryinput.SnapParameters snapParameters);
method public boolean bottomEdgeReached();
method @com.google.android.horologist.annotations.ExperimentalHorologistApi public void prepareSnapForItems(int moveForElements, boolean sequentialSnap);
method @com.google.android.horologist.annotations.ExperimentalHorologistApi public float snapThreshold(boolean duringSnap);
method @com.google.android.horologist.annotations.ExperimentalHorologistApi public suspend Object? startSnappingSession(boolean toClosestItem, kotlin.coroutines.Continuation<? super kotlin.Unit>);
method public suspend Object? snapToClosestItem(kotlin.coroutines.Continuation<? super kotlin.Unit>);
method public suspend Object? snapToTargetItem(kotlin.coroutines.Continuation<? super kotlin.Unit>);
method public boolean topEdgeReached();
}

public final class GenericMotionRotaryInputAccumulator {
Expand All @@ -330,7 +332,7 @@ package com.google.android.horologist.compose.rotaryinput {
@com.google.android.horologist.annotations.ExperimentalHorologistApi public final class RotaryDefaults {
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public boolean isLowResInput();
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public com.google.android.horologist.compose.rotaryinput.RotaryScrollHandler rememberFlingHandler(androidx.compose.foundation.gestures.ScrollableState scrollableState, optional androidx.compose.foundation.gestures.FlingBehavior? flingBehavior, optional boolean isLowRes);
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public com.google.android.horologist.compose.rotaryinput.RotaryScrollHandler rememberSnapHandler(com.google.android.horologist.compose.rotaryinput.RotaryScrollAdapter rotaryScrollAdapter, optional com.google.android.horologist.compose.rotaryinput.SnapParameters snapParameters);
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public com.google.android.horologist.compose.rotaryinput.RotaryScrollHandler rememberSnapHandler(com.google.android.horologist.compose.rotaryinput.RotaryScrollAdapter rotaryScrollAdapter, optional com.google.android.horologist.compose.rotaryinput.SnapParameters snapParameters, optional boolean isLowRes);
method @com.google.android.horologist.annotations.ExperimentalHorologistApi public com.google.android.horologist.compose.rotaryinput.SnapParameters snapParametersDefault();
field public static final com.google.android.horologist.compose.rotaryinput.RotaryDefaults INSTANCE;
}
Expand Down Expand Up @@ -374,10 +376,10 @@ package com.google.android.horologist.compose.rotaryinput {

public final class RotaryKt {
method @com.google.android.horologist.annotations.ExperimentalHorologistApi public static kotlinx.coroutines.flow.Flow<com.google.android.horologist.compose.rotaryinput.TimestampedDelta> batchRequestsWithinTimeframe(kotlinx.coroutines.flow.Flow<com.google.android.horologist.compose.rotaryinput.TimestampedDelta>, long timeframe);
method @com.google.android.horologist.annotations.ExperimentalHorologistApi public static androidx.compose.ui.Modifier rotaryHandler(androidx.compose.ui.Modifier, com.google.android.horologist.compose.rotaryinput.RotaryScrollHandler rotaryScrollHandler, optional long batchTimeframe, boolean reverseDirection, com.google.android.horologist.compose.rotaryinput.RotaryHapticHandler rotaryHaptics);
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static androidx.compose.ui.Modifier rotaryWithFling(androidx.compose.ui.Modifier, androidx.compose.ui.focus.FocusRequester focusRequester, androidx.compose.foundation.gestures.ScrollableState scrollableState, optional androidx.compose.foundation.gestures.FlingBehavior flingBehavior, optional com.google.android.horologist.compose.rotaryinput.RotaryHapticHandler rotaryHaptics, optional boolean reverseDirection);
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static androidx.compose.ui.Modifier rotaryWithScroll(androidx.compose.ui.Modifier, androidx.compose.ui.focus.FocusRequester focusRequester, androidx.compose.foundation.gestures.ScrollableState scrollableState, optional com.google.android.horologist.compose.rotaryinput.RotaryHapticHandler rotaryHaptics, optional boolean reverseDirection);
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static androidx.compose.ui.Modifier rotaryWithSnap(androidx.compose.ui.Modifier, androidx.compose.ui.focus.FocusRequester focusRequester, com.google.android.horologist.compose.rotaryinput.RotaryScrollAdapter rotaryScrollAdapter, optional com.google.android.horologist.compose.rotaryinput.RotaryHapticHandler rotaryHaptics, optional boolean reverseDirection);
method @com.google.android.horologist.annotations.ExperimentalHorologistApi public static androidx.compose.ui.Modifier rotaryHandler(androidx.compose.ui.Modifier, com.google.android.horologist.compose.rotaryinput.RotaryScrollHandler rotaryScrollHandler, boolean reverseDirection, com.google.android.horologist.compose.rotaryinput.RotaryHapticHandler rotaryHaptics);
method @Deprecated @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static androidx.compose.ui.Modifier rotaryWithFling(androidx.compose.ui.Modifier, androidx.compose.ui.focus.FocusRequester focusRequester, androidx.compose.foundation.gestures.ScrollableState scrollableState, optional androidx.compose.foundation.gestures.FlingBehavior flingBehavior, optional com.google.android.horologist.compose.rotaryinput.RotaryHapticHandler rotaryHaptics, optional boolean reverseDirection);
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static androidx.compose.ui.Modifier rotaryWithScroll(androidx.compose.ui.Modifier, androidx.compose.foundation.gestures.ScrollableState scrollableState, optional androidx.compose.ui.focus.FocusRequester focusRequester, optional androidx.compose.foundation.gestures.FlingBehavior? flingBehavior, optional com.google.android.horologist.compose.rotaryinput.RotaryHapticHandler rotaryHaptics, optional boolean reverseDirection);
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static androidx.compose.ui.Modifier rotaryWithSnap(androidx.compose.ui.Modifier, com.google.android.horologist.compose.rotaryinput.RotaryScrollAdapter rotaryScrollAdapter, optional androidx.compose.ui.focus.FocusRequester focusRequester, optional com.google.android.horologist.compose.rotaryinput.SnapParameters snapParameters, optional com.google.android.horologist.compose.rotaryinput.RotaryHapticHandler rotaryHaptics, optional boolean reverseDirection);
method @com.google.android.horologist.annotations.ExperimentalHorologistApi public static com.google.android.horologist.compose.rotaryinput.RotaryScrollAdapter toRotaryScrollAdapter(androidx.wear.compose.foundation.lazy.ScalingLazyListState);
}

Expand All @@ -386,6 +388,7 @@ package com.google.android.horologist.compose.rotaryinput {
method @com.google.android.horologist.annotations.ExperimentalHorologistApi public int currentItemIndex();
method @com.google.android.horologist.annotations.ExperimentalHorologistApi public float currentItemOffset();
method public androidx.compose.foundation.gestures.ScrollableState getScrollableState();
method @com.google.android.horologist.annotations.ExperimentalHorologistApi public int totalItemsCount();
property public abstract androidx.compose.foundation.gestures.ScrollableState scrollableState;
}

Expand All @@ -398,9 +401,11 @@ package com.google.android.horologist.compose.rotaryinput {
}

@com.google.android.horologist.annotations.ExperimentalHorologistApi public interface RotarySnapBehavior {
method public boolean bottomEdgeReached();
method public void prepareSnapForItems(int moveForElements, boolean sequentialSnap);
method @com.google.android.horologist.annotations.ExperimentalHorologistApi public float snapThreshold(boolean duringSnap);
method @com.google.android.horologist.annotations.ExperimentalHorologistApi public suspend Object? startSnappingSession(boolean toClosestItem, kotlin.coroutines.Continuation<? super kotlin.Unit>);
method public suspend Object? snapToClosestItem(kotlin.coroutines.Continuation<? super kotlin.Unit>);
method public suspend Object? snapToTargetItem(kotlin.coroutines.Continuation<? super kotlin.Unit>);
method public boolean topEdgeReached();
}

public final class RotaryVelocityTracker {
Expand All @@ -418,14 +423,19 @@ package com.google.android.horologist.compose.rotaryinput {
method public int currentItemIndex();
method public float currentItemOffset();
method public androidx.wear.compose.foundation.lazy.ScalingLazyListState getScrollableState();
method public int totalItemsCount();
property public androidx.wear.compose.foundation.lazy.ScalingLazyListState scrollableState;
}

public final class SnapParameters {
ctor public SnapParameters(int snapOffset);
ctor public SnapParameters(int snapOffset, float thresholdDivider, float resistanceFactor);
method public float getResistanceFactor();
method public int getSnapOffset();
method public float getThresholdDivider();
method @androidx.compose.runtime.Composable public float snapOffsetDp();
property public final float resistanceFactor;
property public final int snapOffset;
property public final float thresholdDivider;
}

@com.google.android.horologist.annotations.ExperimentalHorologistApi public final class TimestampedDelta {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ import com.google.android.horologist.annotations.ExperimentalHorologistApi
import com.google.android.horologist.compose.layout.ScalingLazyColumnState.RotaryMode
import com.google.android.horologist.compose.rotaryinput.rememberDisabledHaptic
import com.google.android.horologist.compose.rotaryinput.rememberRotaryHapticHandler
import com.google.android.horologist.compose.rotaryinput.rotaryWithFling
import com.google.android.horologist.compose.rotaryinput.rotaryWithScroll
import com.google.android.horologist.compose.rotaryinput.rotaryWithSnap
import com.google.android.horologist.compose.rotaryinput.toRotaryScrollAdapter
Expand Down Expand Up @@ -137,14 +136,7 @@ public fun ScalingLazyColumn(
rotaryHaptics = rotaryHaptics
)

RotaryMode.Fling -> modifier.rotaryWithFling(
focusRequester = focusRequester,
scrollableState = columnState.state,
reverseDirection = columnState.reverseLayout,
rotaryHaptics = rotaryHaptics
)

RotaryMode.Scroll -> modifier.rotaryWithScroll(
else -> modifier.rotaryWithScroll(
focusRequester = focusRequester,
scrollableState = columnState.state,
reverseDirection = columnState.reverseLayout,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ public fun rememberDisabledHaptic(): RotaryHapticHandler = remember {
@Composable
public fun rememberRotaryHapticHandler(
scrollableState: ScrollableState,
throttleThresholdMs: Long = 40,
throttleThresholdMs: Long = 30,
hapticsThresholdPx: Long = 50,
hapticsChannel: Channel<RotaryHapticsType> = rememberHapticChannel(),
rotaryHaptics: RotaryHapticFeedback = rememberDefaultRotaryHapticFeedback()
Expand Down Expand Up @@ -309,8 +309,11 @@ private class PixelWatchRotaryHapticFeedback(private val view: View) : RotaryHap
when (type) {
RotaryHapticsType.ScrollItemFocus -> {
view.performHapticFeedback(
if (Build.VERSION.SDK_INT >= 33) ROTARY_SCROLL_ITEM_FOCUS
else WEAR_SCROLL_ITEM_FOCUS
if (Build.VERSION.SDK_INT >= 33) {
ROTARY_SCROLL_ITEM_FOCUS
} else {
WEAR_SCROLL_ITEM_FOCUS
}
)
}

Expand Down Expand Up @@ -343,7 +346,7 @@ private class PixelWatchRotaryHapticFeedback(private val view: View) : RotaryHap
}

/**
* Implementation of [RotaryHapticFeedback] for Galaxy Watch 4 Classic
* Implementation of [RotaryHapticFeedback] for Galaxy Watch 4 and 6 Classic
*/
@ExperimentalHorologistApi
private class GalaxyWatchClassicHapticFeedback(private val view: View) : RotaryHapticFeedback {
Expand All @@ -369,7 +372,7 @@ private class GalaxyWatchClassicHapticFeedback(private val view: View) : RotaryH
}

private fun isGalaxyWatchClassic(): Boolean =
Build.MODEL.matches("SM-R8[89]5.".toRegex())
Build.MODEL.matches("SM-R(?:8[89][05]|9[56][05])".toRegex())

private fun isGooglePixelWatch(): Boolean =
Build.MODEL.startsWith("Google Pixel Watch")
Loading