react-native-reanimated 2.10.0 → 2.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/Common/cpp/AnimatedSensor/AnimatedSensorModule.cpp +3 -0
  2. package/Common/cpp/{headers/AnimatedSensor → AnimatedSensor}/AnimatedSensorModule.h +0 -0
  3. package/Common/cpp/LayoutAnimations/LayoutAnimationsProxy.cpp +2 -0
  4. package/Common/cpp/{headers/LayoutAnimations → LayoutAnimations}/LayoutAnimationsProxy.h +0 -0
  5. package/Common/cpp/NativeModules/NativeReanimatedModule.cpp +2 -0
  6. package/Common/cpp/{headers/NativeModules → NativeModules}/NativeReanimatedModule.h +5 -0
  7. package/Common/cpp/NativeModules/NativeReanimatedModuleSpec.cpp +2 -0
  8. package/Common/cpp/{headers/NativeModules → NativeModules}/NativeReanimatedModuleSpec.h +1 -1
  9. package/Common/cpp/{headers/Registries → Registries}/EventHandlerRegistry.h +0 -0
  10. package/Common/cpp/Registries/MapperRegistry.cpp +3 -1
  11. package/Common/cpp/{headers/Registries → Registries}/MapperRegistry.h +0 -0
  12. package/Common/cpp/Registries/WorkletsCache.cpp +3 -0
  13. package/Common/cpp/{headers/Registries → Registries}/WorkletsCache.h +0 -0
  14. package/Common/cpp/{headers/SharedItems → SharedItems}/FrozenObject.h +0 -0
  15. package/Common/cpp/{headers/SharedItems → SharedItems}/HostFunctionHandler.h +0 -0
  16. package/Common/cpp/SharedItems/MutableValue.cpp +2 -0
  17. package/Common/cpp/{headers/SharedItems → SharedItems}/MutableValue.h +0 -0
  18. package/Common/cpp/{headers/SharedItems → SharedItems}/MutableValueSetterProxy.h +0 -0
  19. package/Common/cpp/{headers/SharedItems → SharedItems}/RemoteObject.h +0 -0
  20. package/Common/cpp/{headers/SharedItems → SharedItems}/RuntimeManager.h +0 -0
  21. package/Common/cpp/SharedItems/ShareableValue.cpp +7 -2
  22. package/Common/cpp/{headers/SharedItems → SharedItems}/ShareableValue.h +0 -0
  23. package/Common/cpp/{headers/SharedItems → SharedItems}/SharedParent.h +0 -0
  24. package/Common/cpp/{headers/SharedItems → SharedItems}/ValueWrapper.h +0 -0
  25. package/Common/cpp/{headers/SpecTools → SpecTools}/ErrorHandler.h +0 -0
  26. package/Common/cpp/{headers/Tools → Tools}/FeaturesConfig.h +0 -0
  27. package/Common/cpp/Tools/JSIStoreValueUser.cpp +2 -2
  28. package/Common/cpp/{headers/Tools → Tools}/JSIStoreValueUser.h +0 -0
  29. package/Common/cpp/{headers/Tools → Tools}/Mapper.h +0 -0
  30. package/Common/cpp/{headers/Tools → Tools}/PlatformDepMethodsHolder.h +0 -0
  31. package/Common/cpp/{headers/Tools → Tools}/ReanimatedHiddenHeaders.h +1 -1
  32. package/Common/cpp/{headers/Tools → Tools}/RuntimeDecorator.h +0 -0
  33. package/Common/cpp/{headers/Tools → Tools}/Scheduler.h +0 -0
  34. package/Common/cpp/Tools/SingleInstanceChecker.h +58 -0
  35. package/Common/cpp/{headers/Tools → Tools}/WorkletEventHandler.h +0 -0
  36. package/RNReanimated.podspec +19 -75
  37. package/android/.gradle/7.5.1/checksums/checksums.lock +0 -0
  38. package/android/.gradle/7.5.1/checksums/md5-checksums.bin +0 -0
  39. package/android/.gradle/7.5.1/checksums/sha1-checksums.bin +0 -0
  40. package/android/.gradle/7.5.1/dependencies-accessors/dependencies-accessors.lock +0 -0
  41. package/android/.gradle/{7.2 → 7.5.1}/dependencies-accessors/gc.properties +0 -0
  42. package/android/.gradle/7.5.1/executionHistory/executionHistory.bin +0 -0
  43. package/android/.gradle/7.5.1/executionHistory/executionHistory.lock +0 -0
  44. package/android/.gradle/{7.2 → 7.5.1}/fileChanges/last-build.bin +0 -0
  45. package/android/.gradle/7.5.1/fileHashes/fileHashes.bin +0 -0
  46. package/android/.gradle/7.5.1/fileHashes/fileHashes.lock +0 -0
  47. package/android/.gradle/{7.2 → 7.5.1}/fileHashes/resourceHashesCache.bin +0 -0
  48. package/android/.gradle/{7.2 → 7.5.1}/gc.properties +0 -0
  49. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  50. package/android/.gradle/buildOutputCleanup/cache.properties +2 -2
  51. package/android/.gradle/buildOutputCleanup/outputFiles.bin +0 -0
  52. package/android/.gradle/file-system.probe +0 -0
  53. package/android/CMakeLists.txt +56 -65
  54. package/android/build.gradle +422 -120
  55. package/android/gradle/wrapper/gradle-wrapper.properties +1 -1
  56. package/android/react-native-reanimated-66-hermes.aar +0 -0
  57. package/android/react-native-reanimated-66-jsc.aar +0 -0
  58. package/android/react-native-reanimated-67-hermes.aar +0 -0
  59. package/android/react-native-reanimated-67-jsc.aar +0 -0
  60. package/android/react-native-reanimated-68-hermes.aar +0 -0
  61. package/android/react-native-reanimated-68-jsc.aar +0 -0
  62. package/android/react-native-reanimated-69-hermes.aar +0 -0
  63. package/android/react-native-reanimated-69-jsc.aar +0 -0
  64. package/android/react-native-reanimated-70-hermes.aar +0 -0
  65. package/android/react-native-reanimated-70-jsc.aar +0 -0
  66. package/android/src/main/cpp/AndroidErrorHandler.cpp +3 -4
  67. package/android/src/main/cpp/{headers/AndroidErrorHandler.h → AndroidErrorHandler.h} +1 -4
  68. package/android/src/main/cpp/AndroidLogger.cpp +4 -1
  69. package/android/src/main/cpp/{headers/AndroidLogger.h → AndroidLogger.h} +0 -0
  70. package/android/src/main/cpp/{headers/AndroidScheduler.h → AndroidScheduler.h} +0 -0
  71. package/android/src/main/cpp/{headers/JNIHelper.h → JNIHelper.h} +0 -0
  72. package/android/src/main/cpp/{headers/LayoutAnimations.h → LayoutAnimations.h} +0 -0
  73. package/android/src/main/cpp/NativeProxy.cpp +6 -8
  74. package/android/src/main/cpp/{headers/NativeProxy.h → NativeProxy.h} +0 -0
  75. package/android/src/main/cpp/{headers/TurboModule.h → TurboModule.h} +0 -0
  76. package/android/src/main/java/com/swmansion/reanimated/NativeProxy.java +4 -5
  77. package/android/src/main/java/com/swmansion/reanimated/keyboardObserver/ReanimatedKeyboardEventListener.java +2 -1
  78. package/android/src/main/java/com/swmansion/reanimated/layoutReanimation/AnimationsManager.java +2 -2
  79. package/android/src/main/java/com/swmansion/reanimated/layoutReanimation/ReanimatedUIManager.java +1 -1
  80. package/android/{rnVersionPatch/62 → src/reactNativeVersionPatch/UIImplementation/64/com/swmansion/reanimated}/layoutReanimation/ReanimatedUIImplementation.java +0 -0
  81. package/android/src/{main/java → reactNativeVersionPatch/UIImplementation/latest}/com/swmansion/reanimated/layoutReanimation/ReanimatedUIImplementation.java +0 -0
  82. package/android/src/reactNativeVersionPatch/messageQueueThread/67/com/swmansion/reanimated/ReanimatedMessageQueueThread.java +12 -0
  83. package/android/src/reactNativeVersionPatch/messageQueueThread/latest/com/swmansion/reanimated/ReanimatedMessageQueueThread.java +12 -0
  84. package/android/{rnVersionPatch/62 → src/reactNativeVersionPatch/nativeHierarchyManager/62/com/swmansion/reanimated}/layoutReanimation/ReanimatedNativeHierarchyManager.java +0 -0
  85. package/android/src/{main/java → reactNativeVersionPatch/nativeHierarchyManager/latest}/com/swmansion/reanimated/layoutReanimation/ReanimatedNativeHierarchyManager.java +0 -0
  86. package/ios/{REAModule.m → REAModule.mm} +29 -0
  87. package/ios/keyboardObserver/REAKeyboardEventObserver.m +1 -1
  88. package/ios/native/NativeProxy.mm +4 -2
  89. package/ios/native/REAInitializer.h +2 -2
  90. package/ios/native/REAInitializer.mm +2 -2
  91. package/ios/native/UIResponder+Reanimated.mm +1 -1
  92. package/lib/createAnimatedComponent.js +3 -4
  93. package/lib/index.web.js +2 -0
  94. package/lib/reanimated2/NativeMethods.js +79 -30
  95. package/lib/reanimated2/frameCallback/FrameCallbackRegistryJS.js +4 -4
  96. package/lib/reanimated2/frameCallback/FrameCallbackRegistryUI.js +47 -18
  97. package/lib/reanimated2/globals.d.ts +38 -12
  98. package/lib/reanimated2/hook/index.js +1 -0
  99. package/lib/reanimated2/hook/useScrollViewOffset.js +27 -0
  100. package/lib/reanimated2/utils.js +10 -3
  101. package/lib/types/index.web.d.ts +1 -0
  102. package/lib/types/reanimated2/NativeMethods.d.ts +4 -11
  103. package/lib/types/reanimated2/commonTypes.d.ts +8 -0
  104. package/lib/types/reanimated2/frameCallback/FrameCallbackRegistryJS.d.ts +4 -3
  105. package/lib/types/reanimated2/frameCallback/FrameCallbackRegistryUI.d.ts +17 -7
  106. package/lib/types/reanimated2/hook/index.d.ts +1 -0
  107. package/lib/types/reanimated2/hook/useAnimatedScrollHandler.d.ts +1 -2
  108. package/lib/types/reanimated2/hook/useFrameCallback.d.ts +2 -1
  109. package/lib/types/reanimated2/hook/useScrollViewOffset.d.ts +4 -0
  110. package/lib/types/reanimated2/utils.d.ts +5 -1
  111. package/package.json +8 -6
  112. package/plugin.js +1 -1
  113. package/react-native-reanimated.d.ts +13 -9
  114. package/scripts/reanimated_utils.rb +77 -0
  115. package/src/createAnimatedComponent.tsx +2 -3
  116. package/src/index.web.ts +2 -0
  117. package/src/reanimated2/NativeMethods.ts +104 -48
  118. package/src/reanimated2/commonTypes.ts +9 -0
  119. package/src/reanimated2/frameCallback/FrameCallbackRegistryJS.ts +6 -9
  120. package/src/reanimated2/frameCallback/FrameCallbackRegistryUI.ts +78 -27
  121. package/src/reanimated2/globals.d.ts +38 -12
  122. package/src/reanimated2/hook/index.ts +1 -0
  123. package/src/reanimated2/hook/useAnimatedScrollHandler.ts +3 -1
  124. package/src/reanimated2/hook/useFrameCallback.ts +2 -1
  125. package/src/reanimated2/hook/useScrollViewOffset.ts +37 -0
  126. package/src/reanimated2/utils.ts +12 -5
  127. package/android/.gradle/7.2/dependencies-accessors/dependencies-accessors.lock +0 -0
  128. package/android/.gradle/7.2/executionHistory/executionHistory.bin +0 -0
  129. package/android/.gradle/7.2/executionHistory/executionHistory.lock +0 -0
  130. package/android/.gradle/7.2/fileHashes/fileHashes.bin +0 -0
  131. package/android/.gradle/7.2/fileHashes/fileHashes.lock +0 -0
  132. package/android/.gradle/checksums/checksums.lock +0 -0
  133. package/android/.gradle/checksums/md5-checksums.bin +0 -0
  134. package/android/.gradle/checksums/sha1-checksums.bin +0 -0
  135. package/android/rnVersionPatch/63/layoutReanimation/ReanimatedUIImplementation.java +0 -68
  136. package/android/rnVersionPatch/64/layoutReanimation/ReanimatedUIImplementation.java +0 -68
  137. package/android/rnVersionPatch/65/.gitkeep +0 -0
  138. package/android/rnVersionPatch/66/.gitkeep +0 -0
  139. package/android/rnVersionPatch/67/.gitkeep +0 -0
  140. package/android/rnVersionPatch/68/.gitkeep +0 -0
  141. package/android/rnVersionPatch/69/.gitkeep +0 -0
  142. package/android/rnVersionPatch/70/.gitkeep +0 -0
  143. package/android/rnVersionPatch/backup/.gitkeep +0 -0
  144. package/android/src/main/java/com/swmansion/reanimated/AndroidErrorHandler.java +0 -8
  145. package/lib/reanimated2/__mocks__/NativeReanimated.native.js +0 -20
  146. package/lib/types/reanimated2/__mocks__/NativeReanimated.native.d.ts +0 -13
@@ -1,10 +1,9 @@
1
1
  /* global _WORKLET _measure _scrollTo _setGestureState */
2
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
3
- // @ts-nocheck
4
2
  import { Component } from 'react';
5
3
  import { findNodeHandle } from 'react-native';
6
- import { RefObjectFunction } from './commonTypes';
7
- import { shouldBeUseWeb } from './PlatformChecker';
4
+ import { MeasuredDimensions } from './commonTypes';
5
+ import { RefObjectFunction } from './hook/commonTypes';
6
+ import { isChromeDebugger, isWeb, shouldBeUseWeb } from './PlatformChecker';
8
7
 
9
8
  export function getTag(
10
9
  view: null | number | React.Component<any, any> | React.ComponentClass<any>
@@ -12,64 +11,121 @@ export function getTag(
12
11
  return findNodeHandle(view);
13
12
  }
14
13
 
15
- export interface MeasuredDimensions {
16
- x: number;
17
- y: number;
18
- width: number;
19
- height: number;
20
- pageX: number;
21
- pageY: number;
22
- }
23
-
24
- const isNativeIndefined = shouldBeUseWeb();
14
+ const isNative = !shouldBeUseWeb();
25
15
 
26
- export function measure(
16
+ export let measure: (
27
17
  animatedRef: RefObjectFunction<Component>
28
- ): MeasuredDimensions {
29
- 'worklet';
30
- if (!_WORKLET || isNativeIndefined) {
31
- console.warn(
32
- '[reanimated.measure] method cannot be used for web or Chrome Debugger'
33
- );
18
+ ) => MeasuredDimensions | null;
19
+
20
+ if (isWeb()) {
21
+ measure = (animatedRef: RefObjectFunction<Component>) => {
22
+ const element = animatedRef() as unknown as HTMLElement; // TODO: fix typing of animated refs on web
23
+ const viewportOffset = element.getBoundingClientRect();
34
24
  return {
35
- x: NaN,
36
- y: NaN,
37
- width: NaN,
38
- height: NaN,
39
- pageX: NaN,
40
- pageY: NaN,
25
+ width: element.offsetWidth,
26
+ height: element.offsetHeight,
27
+ x: element.offsetLeft,
28
+ y: element.offsetTop,
29
+ pageX: viewportOffset.left,
30
+ pageY: viewportOffset.top,
41
31
  };
42
- }
43
- const viewTag = animatedRef();
44
- const result = _measure(viewTag);
45
- if (result.x === -1234567) {
46
- throw new Error(`The view with tag ${viewTag} could not be measured`);
47
- }
48
- if (isNaN(result.x)) {
49
- console.warn(
50
- 'Trying to measure a component which gets view-flattened on Android. To disable view-flattening, set `collapsable={false}` on this component.'
51
- );
52
- }
53
- return result;
32
+ };
33
+ } else if (isChromeDebugger()) {
34
+ measure = (_animatedRef: RefObjectFunction<Component>) => {
35
+ console.warn('[Reanimated] measure() cannot be used with Chrome Debugger.');
36
+ return null;
37
+ };
38
+ } else {
39
+ measure = (animatedRef: RefObjectFunction<Component>) => {
40
+ 'worklet';
41
+ if (!_WORKLET) {
42
+ console.warn(
43
+ '[Reanimated] measure() was called from the main JS context. Measure is ' +
44
+ 'only available in the UI runtime. This may also happen if measure() ' +
45
+ 'was called by a worklet in the useAnimatedStyle hook, because useAnimatedStyle ' +
46
+ 'calls the given worklet on the JS runtime during render. If you want to ' +
47
+ 'prevent this warning then wrap the call with `if (_WORKLET)`. Then it will ' +
48
+ 'only be called on the UI runtime after the render has been completed.'
49
+ );
50
+ return null;
51
+ }
52
+
53
+ const viewTag = animatedRef();
54
+ if (viewTag === -1) {
55
+ console.warn(
56
+ `[Reanimated] The view with tag ${viewTag} is not a valid argument for measure(). This may be because the view is not currently rendered, which may not be a bug (e.g. an off-screen FlatList item).`
57
+ );
58
+ return null;
59
+ }
60
+
61
+ const measured = _measure(viewTag);
62
+ if (measured === null) {
63
+ console.warn(
64
+ `[Reanimated] The view with tag ${viewTag} has some undefined, not-yet-computed or meaningless value of \`LayoutMetrics\` type. This may be because the view is not currently rendered, which may not be a bug (e.g. an off-screen FlatList item).`
65
+ );
66
+ return null;
67
+ } else if (measured.x === -1234567) {
68
+ console.warn(
69
+ `[Reanimated] The view with tag ${viewTag} returned an invalid measurement response.`
70
+ );
71
+ return null;
72
+ } else if (isNaN(measured.x)) {
73
+ console.warn(
74
+ `[Reanimated] The view with tag ${viewTag} gets view-flattened on Android. To disable view-flattening, set \`collapsable={false}\` on this component.`
75
+ );
76
+ return null;
77
+ } else {
78
+ return measured;
79
+ }
80
+ };
54
81
  }
55
82
 
56
- export function scrollTo(
83
+ export let scrollTo: (
57
84
  animatedRef: RefObjectFunction<Component>,
58
85
  x: number,
59
86
  y: number,
60
87
  animated: boolean
61
- ): void {
62
- 'worklet';
63
- if (!_WORKLET || isNativeIndefined) {
64
- return;
65
- }
66
- const viewTag = animatedRef();
67
- _scrollTo(viewTag, x, y, animated);
88
+ ) => void;
89
+
90
+ if (isWeb()) {
91
+ scrollTo = (
92
+ animatedRef: RefObjectFunction<Component>,
93
+ x: number,
94
+ y: number,
95
+ animated: boolean
96
+ ) => {
97
+ 'worklet';
98
+ const element = animatedRef() as unknown as HTMLElement;
99
+ // @ts-ignore same call as in react-native-web
100
+ element.scrollTo({ x, y, animated });
101
+ };
102
+ } else if (isNative) {
103
+ scrollTo = (
104
+ animatedRef: RefObjectFunction<Component>,
105
+ x: number,
106
+ y: number,
107
+ animated: boolean
108
+ ) => {
109
+ 'worklet';
110
+ if (!_WORKLET) {
111
+ return;
112
+ }
113
+ const viewTag = animatedRef();
114
+ _scrollTo(viewTag, x, y, animated);
115
+ };
116
+ } else {
117
+ scrollTo = (
118
+ _animatedRef: RefObjectFunction<Component>,
119
+ _x: number,
120
+ _y: number
121
+ ) => {
122
+ // no-op
123
+ };
68
124
  }
69
125
 
70
126
  export function setGestureState(handlerTag: number, newState: number): void {
71
127
  'worklet';
72
- if (!_WORKLET || isNativeIndefined) {
128
+ if (!_WORKLET || !isNative) {
73
129
  console.warn(
74
130
  '[Reanimated] You can not use setGestureState in non-worklet function.'
75
131
  );
@@ -160,3 +160,12 @@ export type AnimatedKeyboardInfo = {
160
160
  height: SharedValue<number>;
161
161
  state: SharedValue<KeyboardState>;
162
162
  };
163
+
164
+ export interface MeasuredDimensions {
165
+ x: number;
166
+ y: number;
167
+ width: number;
168
+ height: number;
169
+ pageX: number;
170
+ pageY: number;
171
+ }
@@ -1,5 +1,5 @@
1
1
  import { runOnUI } from '../core';
2
- import { prepareUIRegistry } from './FrameCallbackRegistryUI';
2
+ import { FrameInfo, prepareUIRegistry } from './FrameCallbackRegistryUI';
3
3
 
4
4
  export default class FrameCallbackRegistryJS {
5
5
  private nextCallbackId = 0;
@@ -8,7 +8,7 @@ export default class FrameCallbackRegistryJS {
8
8
  prepareUIRegistry();
9
9
  }
10
10
 
11
- registerFrameCallback(callback: () => void): number {
11
+ registerFrameCallback(callback: (frameInfo: FrameInfo) => void): number {
12
12
  if (!callback) {
13
13
  return -1;
14
14
  }
@@ -24,20 +24,17 @@ export default class FrameCallbackRegistryJS {
24
24
  return callbackId;
25
25
  }
26
26
 
27
- unregisterFrameCallback(frameCallbackId: number): void {
27
+ unregisterFrameCallback(callbackId: number): void {
28
28
  runOnUI(() => {
29
29
  'worklet';
30
- global._frameCallbackRegistry.unregisterFrameCallback(frameCallbackId);
30
+ global._frameCallbackRegistry.unregisterFrameCallback(callbackId);
31
31
  })();
32
32
  }
33
33
 
34
- manageStateFrameCallback(frameCallbackId: number, state: boolean): void {
34
+ manageStateFrameCallback(callbackId: number, state: boolean): void {
35
35
  runOnUI(() => {
36
36
  'worklet';
37
- global._frameCallbackRegistry.manageStateFrameCallback(
38
- frameCallbackId,
39
- state
40
- );
37
+ global._frameCallbackRegistry.manageStateFrameCallback(callbackId, state);
41
38
  })();
42
39
  }
43
40
  }
@@ -1,61 +1,112 @@
1
1
  import { runOnUI } from '../core';
2
2
 
3
- export default interface FrameCallbackRegistryUI {
4
- frameCallbackRegistry: Map<number, () => void>;
5
- frameCallbackActive: Set<number>;
6
- isFrameCallbackRunning: boolean;
3
+ type CallbackDetails = {
4
+ callback: (frameInfo: FrameInfo) => void;
5
+ startTime: number | null;
6
+ };
7
+
8
+ export type FrameInfo = {
9
+ timestamp: number;
10
+ timeSincePreviousFrame: number | null;
11
+ timeSinceFirstFrame: number;
12
+ };
13
+
14
+ export interface FrameCallbackRegistryUI {
15
+ frameCallbackRegistry: Map<number, CallbackDetails>;
16
+ activeFrameCallbacks: Set<number>;
17
+ previousFrameTimestamp: number | null;
7
18
  runCallbacks: () => void;
8
- registerFrameCallback: (callback: () => void, callbackId: number) => void;
9
- unregisterFrameCallback: (frameCallbackId: number) => void;
10
- manageStateFrameCallback: (frameCallbackId: number, state: boolean) => void;
19
+ registerFrameCallback: (
20
+ callback: (frameInfo: FrameInfo) => void,
21
+ callbackId: number
22
+ ) => void;
23
+ unregisterFrameCallback: (callbackId: number) => void;
24
+ manageStateFrameCallback: (callbackId: number, state: boolean) => void;
11
25
  }
12
26
 
13
27
  export const prepareUIRegistry = runOnUI(() => {
14
28
  'worklet';
15
29
 
16
30
  const frameCallbackRegistry: FrameCallbackRegistryUI = {
17
- frameCallbackRegistry: new Map<number, () => void>(),
18
- frameCallbackActive: new Set<number>(),
19
- isFrameCallbackRunning: false,
31
+ frameCallbackRegistry: new Map<number, CallbackDetails>(),
32
+ activeFrameCallbacks: new Set<number>(),
33
+ previousFrameTimestamp: null,
20
34
 
21
35
  runCallbacks() {
22
- const loop = () => {
23
- this.frameCallbackActive.forEach((key: number) => {
24
- const callback = this.frameCallbackRegistry.get(key);
25
- callback!();
36
+ const loop = (timestamp: number) => {
37
+ if (this.previousFrameTimestamp === null) {
38
+ this.previousFrameTimestamp = timestamp;
39
+ }
40
+
41
+ const delta = timestamp - this.previousFrameTimestamp;
42
+
43
+ this.activeFrameCallbacks.forEach((callbackId: number) => {
44
+ const callbackDetails = this.frameCallbackRegistry.get(callbackId)!;
45
+
46
+ const { startTime } = callbackDetails;
47
+
48
+ if (startTime === null) {
49
+ // First frame
50
+ callbackDetails.startTime = timestamp;
51
+
52
+ callbackDetails.callback({
53
+ timestamp,
54
+ timeSincePreviousFrame: null,
55
+ timeSinceFirstFrame: 0,
56
+ });
57
+ } else {
58
+ // Next frame
59
+ callbackDetails.callback({
60
+ timestamp,
61
+ timeSincePreviousFrame: delta,
62
+ timeSinceFirstFrame: timestamp - startTime,
63
+ });
64
+ }
26
65
  });
27
66
 
28
- if (this.frameCallbackActive.size > 0) {
67
+ if (this.activeFrameCallbacks.size > 0) {
68
+ this.previousFrameTimestamp = timestamp;
29
69
  requestAnimationFrame(loop);
30
70
  } else {
31
- this.isFrameCallbackRunning = false;
71
+ this.previousFrameTimestamp = null;
32
72
  }
33
73
  };
34
74
 
35
- if (!this.isFrameCallbackRunning) {
75
+ // runCallback() should only be called after registering a callback,
76
+ // so if there is only one active callback, then it means that there were
77
+ // zero previously and the loop isn't running yet.
78
+ if (this.activeFrameCallbacks.size === 1) {
36
79
  requestAnimationFrame(loop);
37
- this.isFrameCallbackRunning = true;
38
80
  }
39
81
  },
40
82
 
41
- registerFrameCallback(callback: () => void, callbackId: number) {
42
- this.frameCallbackRegistry.set(callbackId, callback);
83
+ registerFrameCallback(
84
+ callback: (frameInfo: FrameInfo) => void,
85
+ callbackId: number
86
+ ) {
87
+ this.frameCallbackRegistry.set(callbackId, {
88
+ callback: callback,
89
+ startTime: null,
90
+ });
43
91
  },
44
92
 
45
- unregisterFrameCallback(frameCallbackId: number) {
46
- this.manageStateFrameCallback(frameCallbackId, false);
47
- this.frameCallbackRegistry.delete(frameCallbackId);
93
+ unregisterFrameCallback(callbackId: number) {
94
+ this.manageStateFrameCallback(callbackId, false);
95
+ this.frameCallbackRegistry.delete(callbackId);
48
96
  },
49
97
 
50
- manageStateFrameCallback(frameCallbackId: number, state: boolean) {
51
- if (frameCallbackId === -1) {
98
+ manageStateFrameCallback(callbackId: number, state: boolean) {
99
+ if (callbackId === -1) {
52
100
  return;
53
101
  }
54
102
  if (state) {
55
- this.frameCallbackActive.add(frameCallbackId);
103
+ this.activeFrameCallbacks.add(callbackId);
56
104
  this.runCallbacks();
57
105
  } else {
58
- this.frameCallbackActive.delete(frameCallbackId);
106
+ const callback = this.frameCallbackRegistry.get(callbackId)!;
107
+ callback.startTime = null;
108
+
109
+ this.activeFrameCallbacks.delete(callbackId);
59
110
  }
60
111
  },
61
112
  };
@@ -1,13 +1,19 @@
1
- import { AnimatedStyle, StyleProps } from './commonTypes';
2
- import { ReanimatedConsole } from './core';
3
- import FrameCallbackRegistryUI from './frameCallback/FrameCallbackRegistryUI';
4
- import { MeasuredDimensions } from './NativeMethods';
5
- import { NativeReanimated } from './NativeReanimated/NativeReanimated';
1
+ import type {
2
+ AnimatedStyle,
3
+ StyleProps,
4
+ MeasuredDimensions,
5
+ } from './commonTypes';
6
+ import type { ReanimatedConsole } from './core';
7
+ import type { NativeReanimated } from './NativeReanimated/NativeReanimated';
8
+ import type { FrameCallbackRegistryUI } from './frameCallback/FrameCallbackRegistryUI';
9
+
6
10
  declare global {
7
11
  const _WORKLET: boolean;
8
- const _frameTimestamp: number;
12
+ const _frameTimestamp: number | null;
9
13
  const _eventTimestamp: number;
14
+ const __reanimatedModuleProxy: NativeReanimated;
10
15
  const _setGlobalConsole: (console?: ReanimatedConsole) => void;
16
+ const _log: (s: string) => void;
11
17
  const _getCurrentTime: () => number;
12
18
  const _stopObservingProgress: (tag: number, flag: boolean) => void;
13
19
  const _startObservingProgress: (
@@ -28,20 +34,40 @@ declare global {
28
34
  animated: boolean
29
35
  ) => void;
30
36
  const _chronoNow: () => number;
37
+ const performance: { now: () => number };
38
+ const LayoutAnimationRepository: {
39
+ configs: Record<string, unknown>;
40
+ registerConfig(tag: number, config: Record<string, unknown>): void;
41
+ removeConfig(tag: number): void;
42
+ startAnimationForTag(tag: number, type: string, yogaValues: unknown): void;
43
+ };
31
44
  const ReanimatedDataMock: {
32
45
  now: () => number;
33
46
  };
34
47
  const _frameCallbackRegistry: FrameCallbackRegistryUI;
35
48
  namespace NodeJS {
36
49
  interface Global {
37
- _setGlobalConsole: (console?: ReanimatedConsole) => void;
38
- _log: (s: string) => void;
39
- _setGestureState: () => void;
40
50
  _WORKLET: boolean;
41
- __reanimatedModuleProxy: NativeReanimated;
51
+ _IS_FABRIC: boolean;
42
52
  _frameTimestamp: number | null;
43
- _measure: () => MeasuredDimensions;
44
- _scrollTo: () => void;
53
+ _eventTimestamp: number;
54
+ __reanimatedModuleProxy: NativeReanimated;
55
+ _setGlobalConsole: (console?: ReanimatedConsole) => void;
56
+ _log: (s: string) => void;
57
+ _getCurrentTime: () => number;
58
+ _stopObservingProgress: (tag: number, flag: boolean) => void;
59
+ _startObservingProgress: (
60
+ tag: number,
61
+ flag: { value: boolean; _value: boolean }
62
+ ) => void;
63
+ _setGestureState: (handlerTag: number, newState: number) => void;
64
+ _measure: (viewTag: number) => MeasuredDimensions;
65
+ _scrollTo: (
66
+ viewTag: number,
67
+ x: number,
68
+ y: number,
69
+ animated: boolean
70
+ ) => void;
45
71
  _chronoNow: () => number;
46
72
  performance: { now: () => number };
47
73
  LayoutAnimationRepository: {
@@ -27,3 +27,4 @@ export { useAnimatedSensor, SensorType } from './useAnimatedSensor';
27
27
  export { useFrameCallback } from './useFrameCallback';
28
28
  export type { FrameCallback } from './useFrameCallback';
29
29
  export { useAnimatedKeyboard } from './useAnimatedKeyboard';
30
+ export { useScrollViewOffset } from './useScrollViewOffset';
@@ -10,7 +10,9 @@ export interface ScrollHandler<TContext extends Context>
10
10
  (event: NativeScrollEvent, context?: TContext): void;
11
11
  }
12
12
 
13
- interface ScrollEvent extends NativeScrollEvent, NativeEvent<ScrollEvent> {
13
+ export interface ScrollEvent
14
+ extends NativeScrollEvent,
15
+ NativeEvent<ScrollEvent> {
14
16
  eventName: string;
15
17
  }
16
18
  export interface ScrollHandlers<TContext extends Context> {
@@ -1,5 +1,6 @@
1
1
  import { useEffect, useRef } from 'react';
2
2
  import FrameCallbackRegistryJS from '../frameCallback/FrameCallbackRegistryJS';
3
+ import { FrameInfo } from '../frameCallback/FrameCallbackRegistryUI';
3
4
 
4
5
  export type FrameCallback = {
5
6
  setActive: (isActive: boolean) => void;
@@ -9,7 +10,7 @@ export type FrameCallback = {
9
10
  const frameCallbackRegistry = new FrameCallbackRegistryJS();
10
11
 
11
12
  export function useFrameCallback(
12
- callback: () => void,
13
+ callback: (frameInfo: FrameInfo) => void,
13
14
  autostart = true
14
15
  ): FrameCallback {
15
16
  const ref = useRef<FrameCallback>({
@@ -0,0 +1,37 @@
1
+ import { RefObject, useEffect, useRef } from 'react';
2
+
3
+ import type Animated from 'react-native-reanimated';
4
+ import { ScrollEvent } from './useAnimatedScrollHandler';
5
+ import { SharedValue } from '../commonTypes';
6
+ import { findNodeHandle } from 'react-native';
7
+ import { useEvent } from './utils';
8
+ import { useSharedValue } from './useSharedValue';
9
+
10
+ const subscribeForEvents = [
11
+ 'onScroll',
12
+ 'onScrollBeginDrag',
13
+ 'onScrollEndDrag',
14
+ 'onMomentumScrollBegin',
15
+ 'onMomentumScrollEnd',
16
+ ];
17
+
18
+ export function useScrollViewOffset(
19
+ aref: RefObject<Animated.ScrollView>
20
+ ): SharedValue<number> {
21
+ const offsetRef = useRef(useSharedValue(0));
22
+
23
+ const event = useEvent<ScrollEvent>((event: ScrollEvent) => {
24
+ 'worklet';
25
+ offsetRef.current.value =
26
+ event.contentOffset.x === 0
27
+ ? event.contentOffset.y
28
+ : event.contentOffset.x;
29
+ }, subscribeForEvents);
30
+
31
+ useEffect(() => {
32
+ const viewTag = findNodeHandle(aref.current);
33
+ event.current?.registerForEvents(viewTag as number);
34
+ }, [aref.current]);
35
+
36
+ return offsetRef.current;
37
+ }
@@ -7,15 +7,22 @@ export interface ComponentCoords {
7
7
  y: number;
8
8
  }
9
9
 
10
+ /**
11
+ * Given an absolute position and a component ref, returns the relative
12
+ * position in the component's local coordinate space.
13
+ */
10
14
  export function getRelativeCoords(
11
15
  parentRef: RefObjectFunction<Component>,
12
- x: number,
13
- y: number
14
- ): ComponentCoords {
16
+ absoluteX: number,
17
+ absoluteY: number
18
+ ): ComponentCoords | null {
15
19
  'worklet';
16
20
  const parentCoords = measure(parentRef);
21
+ if (parentCoords === null) {
22
+ return null;
23
+ }
17
24
  return {
18
- x: x - parentCoords.x,
19
- y: y - parentCoords.y,
25
+ x: absoluteX - parentCoords.x,
26
+ y: absoluteY - parentCoords.y,
20
27
  };
21
28
  }
@@ -1,68 +0,0 @@
1
- package com.facebook.react.uimanager;
2
-
3
- import androidx.annotation.Nullable;
4
- import com.facebook.react.bridge.ReactApplicationContext;
5
- import com.facebook.react.bridge.ReadableArray;
6
- import com.facebook.react.uimanager.events.EventDispatcher;
7
- import com.swmansion.reanimated.layoutReanimation.ReanimatedNativeHierarchyManager;
8
- import java.util.List;
9
-
10
- public class ReanimatedUIImplementation extends UIImplementation {
11
- public ReanimatedUIImplementation(
12
- ReactApplicationContext reactContext,
13
- UIManagerModule.ViewManagerResolver viewManagerResolver,
14
- EventDispatcher eventDispatcher,
15
- int minTimeLeftInFrameForNonBatchedOperationMs) {
16
- this(
17
- reactContext,
18
- new ViewManagerRegistry(viewManagerResolver),
19
- eventDispatcher,
20
- minTimeLeftInFrameForNonBatchedOperationMs);
21
- }
22
-
23
- public ReanimatedUIImplementation(
24
- ReactApplicationContext reactContext,
25
- List<ViewManager> viewManagerList,
26
- EventDispatcher eventDispatcher,
27
- int minTimeLeftInFrameForNonBatchedOperationMs) {
28
- this(
29
- reactContext,
30
- new ViewManagerRegistry(viewManagerList),
31
- eventDispatcher,
32
- minTimeLeftInFrameForNonBatchedOperationMs);
33
- }
34
-
35
- public ReanimatedUIImplementation(
36
- ReactApplicationContext reactContext,
37
- ViewManagerRegistry viewManagerRegistry,
38
- EventDispatcher eventDispatcher,
39
- int minTimeLeftInFrameForNonBatchedOperationMs) {
40
- super(
41
- reactContext,
42
- viewManagerRegistry,
43
- new UIViewOperationQueue(
44
- reactContext,
45
- new ReanimatedNativeHierarchyManager(viewManagerRegistry, reactContext),
46
- minTimeLeftInFrameForNonBatchedOperationMs),
47
- eventDispatcher);
48
- }
49
-
50
- /**
51
- * Invoked when there is a mutation in a node tree.
52
- *
53
- * @param tag react tag of the node we want to manage
54
- * @param indicesToRemove ordered (asc) list of indicies at which view should be removed
55
- * @param viewsToAdd ordered (asc based on mIndex property) list of tag-index pairs that represent
56
- * a view which should be added at the specified index
57
- * @param tagsToDelete list of tags corresponding to views that should be removed
58
- */
59
- public void manageChildren(
60
- int viewTag,
61
- @Nullable ReadableArray moveFrom,
62
- @Nullable ReadableArray moveTo,
63
- @Nullable ReadableArray addChildTags,
64
- @Nullable ReadableArray addAtIndices,
65
- @Nullable ReadableArray removeFrom) {
66
- super.manageChildren(viewTag, moveFrom, moveTo, addChildTags, addAtIndices, removeFrom);
67
- }
68
- }