Skip to content

Commit

Permalink
fix: ignore duplicated events
Browse files Browse the repository at this point in the history
  • Loading branch information
kirillzyusko committed Dec 14, 2023
1 parent a30e729 commit d67faa5
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,29 @@ import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableMap
import com.facebook.react.uimanager.events.Event

data class KeyboardTransitionEventData(
val event: String,
val height: Double,
val progress: Double,
val duration: Int,
val target: Int,
)

@Suppress("detekt:LongParameterList")
class KeyboardTransitionEvent(
surfaceId: Int,
viewId: Int,
private val event: String,
private val height: Double,
private val progress: Double,
private val duration: Int,
private val target: Int,
private val data: KeyboardTransitionEventData,
) : Event<KeyboardTransitionEvent>(surfaceId, viewId) {
override fun getEventName() = event
override fun getEventName() = data.event

// All events for a given view can be coalesced?
override fun getCoalescingKey(): Short = 0

override fun getEventData(): WritableMap? = Arguments.createMap().apply {
putDouble("progress", progress)
putDouble("height", height)
putInt("duration", duration)
putInt("target", target)
putDouble("progress", data.progress)
putDouble("height", data.height)
putInt("duration", data.duration)
putInt("target", data.target)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import com.facebook.react.views.textinput.ReactEditText
import com.facebook.react.views.view.ReactViewGroup
import com.reactnativekeyboardcontroller.InteractiveKeyboardProvider
import com.reactnativekeyboardcontroller.events.KeyboardTransitionEvent
import com.reactnativekeyboardcontroller.events.KeyboardTransitionEventData
import com.reactnativekeyboardcontroller.extensions.dispatchEvent
import com.reactnativekeyboardcontroller.extensions.dp
import kotlin.math.abs
Expand All @@ -42,6 +43,7 @@ class KeyboardAnimationCallback(
private var duration = 0
private var viewTagFocused = -1
private var animation: ValueAnimator? = null
private var lastEventDispatched: KeyboardTransitionEventData? = null

// listeners
private val focusListener = OnGlobalFocusChangeListener { oldFocus, newFocus ->
Expand All @@ -55,23 +57,17 @@ class KeyboardAnimationCallback(
// 2. event should be send only when keyboard is visible, since this event arrives earlier -> `tag` will be
// 100% included in onStart/onMove/onEnd lifecycles, but triggering onStart/onEnd several time
// can bring breaking changes
context.dispatchEvent(
view.id,
KeyboardTransitionEvent(
surfaceId,
view.id,
this.dispatchEventToJS(
KeyboardTransitionEventData(
"topKeyboardMoveStart",
this.persistentKeyboardHeight,
1.0,
0,
viewTagFocused,
),
)
context.dispatchEvent(
view.id,
KeyboardTransitionEvent(
surfaceId,
view.id,
this.dispatchEventToJS(
KeyboardTransitionEventData(
"topKeyboardMoveEnd",
this.persistentKeyboardHeight,
1.0,
Expand Down Expand Up @@ -159,11 +155,8 @@ class KeyboardAnimationCallback(
)

Log.i(TAG, "HEIGHT:: $keyboardHeight TAG:: $viewTagFocused")
context.dispatchEvent(
view.id,
KeyboardTransitionEvent(
surfaceId,
view.id,
this.dispatchEventToJS(
KeyboardTransitionEventData(
"topKeyboardMoveStart",
keyboardHeight,
if (!isKeyboardVisible) 0.0 else 1.0,
Expand Down Expand Up @@ -207,11 +200,8 @@ class KeyboardAnimationCallback(
)

val event = if (InteractiveKeyboardProvider.isInteractive) "topKeyboardMoveInteractive" else "topKeyboardMove"
context.dispatchEvent(
view.id,
KeyboardTransitionEvent(
surfaceId,
view.id,
this.dispatchEventToJS(
KeyboardTransitionEventData(
event,
height,
progress,
Expand Down Expand Up @@ -247,11 +237,8 @@ class KeyboardAnimationCallback(
"KeyboardController::" + if (!isKeyboardVisible) "keyboardDidHide" else "keyboardDidShow",
getEventParams(keyboardHeight),
)
context.dispatchEvent(
view.id,
KeyboardTransitionEvent(
surfaceId,
view.id,
this.dispatchEventToJS(
KeyboardTransitionEventData(
"topKeyboardMoveEnd",
keyboardHeight,
if (!isKeyboardVisible) 0.0 else 1.0,
Expand Down Expand Up @@ -288,11 +275,8 @@ class KeyboardAnimationCallback(
}

this.emitEvent("KeyboardController::keyboardWillShow", getEventParams(keyboardHeight))
context.dispatchEvent(
view.id,
KeyboardTransitionEvent(
surfaceId,
view.id,
this.dispatchEventToJS(
KeyboardTransitionEventData(
"topKeyboardMoveStart",
keyboardHeight,
1.0,
Expand All @@ -305,11 +289,8 @@ class KeyboardAnimationCallback(
ValueAnimator.ofFloat(this.persistentKeyboardHeight.toFloat(), keyboardHeight.toFloat())
animation.addUpdateListener { animator ->
val toValue = animator.animatedValue as Float
context.dispatchEvent(
view.id,
KeyboardTransitionEvent(
surfaceId,
view.id,
this.dispatchEventToJS(
KeyboardTransitionEventData(
"topKeyboardMove",
toValue.toDouble(),
toValue.toDouble() / keyboardHeight,
Expand All @@ -320,11 +301,8 @@ class KeyboardAnimationCallback(
}
animation.doOnEnd {
this.emitEvent("KeyboardController::keyboardDidShow", getEventParams(keyboardHeight))
context.dispatchEvent(
view.id,
KeyboardTransitionEvent(
surfaceId,
view.id,
this.dispatchEventToJS(
KeyboardTransitionEventData(
"topKeyboardMoveEnd",
keyboardHeight,
1.0,
Expand Down Expand Up @@ -372,6 +350,20 @@ class KeyboardAnimationCallback(
return params
}

private fun dispatchEventToJS(event: KeyboardTransitionEventData) {
if (event != lastEventDispatched) {
lastEventDispatched = event
context.dispatchEvent(
view.id,
KeyboardTransitionEvent(
surfaceId,
view.id,
data = event,
),
)
}
}

companion object {
private const val DEFAULT_ANIMATION_TIME = 250
}
Expand Down
22 changes: 19 additions & 3 deletions example/src/screens/Examples/InteractiveKeyboard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import {
useKeyboardHandler,
} from 'react-native-keyboard-controller';
import Reanimated, {
scrollTo,
useAnimatedRef,
useAnimatedScrollHandler,
useAnimatedStyle,
useSharedValue,
} from 'react-native-reanimated';
Expand All @@ -17,7 +20,7 @@ import styles from './styles';

const AnimatedTextInput = Reanimated.createAnimatedComponent(TextInput);

const useKeyboardAnimation = () => {
const useKeyboardAnimation = ({ref, scroll}) => {
const progress = useSharedValue(0);
const height = useSharedValue(0);
useKeyboardHandler({
Expand All @@ -30,6 +33,8 @@ const useKeyboardAnimation = () => {
onInteractive: (e) => {
'worklet';

scrollTo(ref, 0, scroll.value, false);

progress.value = e.progress;
height.value = e.height;
},
Expand All @@ -41,8 +46,16 @@ const useKeyboardAnimation = () => {
type Props = StackScreenProps<ExamplesStackParamList>;

function InteractiveKeyboard({ navigation }: Props) {
const aRef = useAnimatedRef();
const scroll = useSharedValue(0);
const [interpolator, setInterpolator] = useState<'ios' | 'linear'>('linear');
const { height } = useKeyboardAnimation();
const { height } = useKeyboardAnimation({ref: aRef, scroll: scroll});

const onScroll = useAnimatedScrollHandler({
onScroll: (e) => {
scroll.value = e.contentOffset.y;
},
})

useEffect(() => {
navigation.setOptions({
Expand Down Expand Up @@ -76,7 +89,8 @@ function InteractiveKeyboard({ navigation }: Props) {
);
const fakeView = useAnimatedStyle(
() => ({
height: height.value,
// TODO: don't update when onInteractive is fired
// height: height.value,
}),
[]
);
Expand All @@ -89,6 +103,8 @@ function InteractiveKeyboard({ navigation }: Props) {
showOnSwipeUp
>
<Reanimated.ScrollView
ref={aRef}
onScroll={onScroll}
showsVerticalScrollIndicator={false}
style={scrollViewStyle}
>
Expand Down

0 comments on commit d67faa5

Please sign in to comment.