@rafaelaugusto/jolt 0.1.0-beta.9 → 0.1.0-rc.2
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.
- package/README.md +167 -21
- package/dist/animate.d.ts +25 -4
- package/dist/animate.d.ts.map +1 -1
- package/dist/animate.js +67 -26
- package/dist/animate.js.map +1 -1
- package/dist/blur/index.d.ts +6 -0
- package/dist/blur/index.d.ts.map +1 -0
- package/dist/blur/index.js +196 -0
- package/dist/blur/index.js.map +1 -0
- package/dist/blur/native.d.ts +17 -0
- package/dist/blur/native.d.ts.map +1 -0
- package/dist/blur/native.js +44 -0
- package/dist/blur/native.js.map +1 -0
- package/dist/blur/types.d.ts +32 -0
- package/dist/blur/types.d.ts.map +1 -0
- package/dist/blur/types.js +2 -0
- package/dist/blur/types.js.map +1 -0
- package/dist/bottom-sheet/geometry.d.ts +18 -0
- package/dist/bottom-sheet/geometry.d.ts.map +1 -0
- package/dist/bottom-sheet/geometry.js +51 -0
- package/dist/bottom-sheet/geometry.js.map +1 -0
- package/dist/bottom-sheet/index.d.ts +56 -0
- package/dist/bottom-sheet/index.d.ts.map +1 -0
- package/dist/bottom-sheet/index.js +462 -0
- package/dist/bottom-sheet/index.js.map +1 -0
- package/dist/bottom-sheet/native.d.ts +11 -0
- package/dist/bottom-sheet/native.d.ts.map +1 -0
- package/dist/bottom-sheet/native.js +173 -0
- package/dist/bottom-sheet/native.js.map +1 -0
- package/dist/config.d.ts +9 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +40 -1
- package/dist/config.js.map +1 -1
- package/dist/decay.d.ts +1 -0
- package/dist/decay.d.ts.map +1 -1
- package/dist/decay.js +7 -0
- package/dist/decay.js.map +1 -1
- package/dist/drag-physics.d.ts +6 -1
- package/dist/drag-physics.d.ts.map +1 -1
- package/dist/drag.d.ts +17 -3
- package/dist/drag.d.ts.map +1 -1
- package/dist/drag.js +34 -11
- package/dist/drag.js.map +1 -1
- package/dist/driver/android-gradient.d.ts +5 -0
- package/dist/driver/android-gradient.d.ts.map +1 -0
- package/dist/driver/android-gradient.js +99 -0
- package/dist/driver/android-gradient.js.map +1 -0
- package/dist/driver/android-particles.d.ts +6 -0
- package/dist/driver/android-particles.d.ts.map +1 -0
- package/dist/driver/android-particles.js +93 -0
- package/dist/driver/android-particles.js.map +1 -0
- package/dist/driver/android.d.ts.map +1 -1
- package/dist/driver/android.js +27 -1
- package/dist/driver/android.js.map +1 -1
- package/dist/driver/frame.d.ts +3 -0
- package/dist/driver/frame.d.ts.map +1 -0
- package/dist/driver/frame.js +7 -0
- package/dist/driver/frame.js.map +1 -0
- package/dist/driver/index.d.ts +4 -0
- package/dist/driver/index.d.ts.map +1 -1
- package/dist/driver/index.js.map +1 -1
- package/dist/driver/ios-gradient.d.ts +5 -0
- package/dist/driver/ios-gradient.d.ts.map +1 -0
- package/dist/driver/ios-gradient.js +131 -0
- package/dist/driver/ios-gradient.js.map +1 -0
- package/dist/driver/ios-scroll-delegate.d.ts +4 -0
- package/dist/driver/ios-scroll-delegate.d.ts.map +1 -0
- package/dist/driver/ios-scroll-delegate.js +26 -0
- package/dist/driver/ios-scroll-delegate.js.map +1 -0
- package/dist/driver/ios.d.ts.map +1 -1
- package/dist/driver/ios.js +9 -0
- package/dist/driver/ios.js.map +1 -1
- package/dist/easing.d.ts +3 -1
- package/dist/easing.d.ts.map +1 -1
- package/dist/easing.js +18 -1
- package/dist/easing.js.map +1 -1
- package/dist/engine.d.ts +31 -2
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +194 -42
- package/dist/engine.js.map +1 -1
- package/dist/gesture-native.d.ts +28 -0
- package/dist/gesture-native.d.ts.map +1 -0
- package/dist/gesture-native.js +61 -0
- package/dist/gesture-native.js.map +1 -0
- package/dist/gestures/index.d.ts +69 -0
- package/dist/gestures/index.d.ts.map +1 -0
- package/dist/gestures/index.js +262 -0
- package/dist/gestures/index.js.map +1 -0
- package/dist/glass/index.d.ts +55 -0
- package/dist/glass/index.d.ts.map +1 -0
- package/dist/glass/index.js +205 -0
- package/dist/glass/index.js.map +1 -0
- package/dist/gradient-binding.d.ts +38 -0
- package/dist/gradient-binding.d.ts.map +1 -0
- package/dist/gradient-binding.js +128 -0
- package/dist/gradient-binding.js.map +1 -0
- package/dist/gradient.d.ts +105 -0
- package/dist/gradient.d.ts.map +1 -0
- package/dist/gradient.js +514 -0
- package/dist/gradient.js.map +1 -0
- package/dist/gravity.d.ts +13 -0
- package/dist/gravity.d.ts.map +1 -0
- package/dist/gravity.js +84 -0
- package/dist/gravity.js.map +1 -0
- package/dist/haptics.d.ts.map +1 -1
- package/dist/haptics.js +101 -28
- package/dist/haptics.js.map +1 -1
- package/dist/image-effect.d.ts +1 -0
- package/dist/image-effect.d.ts.map +1 -1
- package/dist/image-effect.js +10 -2
- package/dist/image-effect.js.map +1 -1
- package/dist/index.d.ts +19 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -4
- package/dist/index.js.map +1 -1
- package/dist/inspector/index.d.ts +86 -0
- package/dist/inspector/index.d.ts.map +1 -0
- package/dist/inspector/index.js +419 -0
- package/dist/inspector/index.js.map +1 -0
- package/dist/inspector/plot.d.ts +4 -0
- package/dist/inspector/plot.d.ts.map +1 -0
- package/dist/inspector/plot.js +23 -0
- package/dist/inspector/plot.js.map +1 -0
- package/dist/inspector/probe.d.ts +19 -0
- package/dist/inspector/probe.d.ts.map +1 -0
- package/dist/inspector/probe.js +37 -0
- package/dist/inspector/probe.js.map +1 -0
- package/dist/inspector/tuning.d.ts +19 -0
- package/dist/inspector/tuning.d.ts.map +1 -0
- package/dist/inspector/tuning.js +37 -0
- package/dist/inspector/tuning.js.map +1 -0
- package/dist/interactive-navigation/index.d.ts +44 -0
- package/dist/interactive-navigation/index.d.ts.map +1 -0
- package/dist/interactive-navigation/index.js +350 -0
- package/dist/interactive-navigation/index.js.map +1 -0
- package/dist/keyboard.d.ts +24 -0
- package/dist/keyboard.d.ts.map +1 -1
- package/dist/keyboard.js +199 -6
- package/dist/keyboard.js.map +1 -1
- package/dist/live-spring-driver.d.ts +52 -0
- package/dist/live-spring-driver.d.ts.map +1 -0
- package/dist/live-spring-driver.js +104 -0
- package/dist/live-spring-driver.js.map +1 -0
- package/dist/mixer.d.ts +55 -0
- package/dist/mixer.d.ts.map +1 -0
- package/dist/mixer.js +286 -0
- package/dist/mixer.js.map +1 -0
- package/dist/motion-scope.d.ts +8 -2
- package/dist/motion-scope.d.ts.map +1 -1
- package/dist/motion-scope.js +24 -3
- package/dist/motion-scope.js.map +1 -1
- package/dist/motion-states.d.ts +19 -7
- package/dist/motion-states.d.ts.map +1 -1
- package/dist/motion-states.js +116 -26
- package/dist/motion-states.js.map +1 -1
- package/dist/motion-value.d.ts +227 -0
- package/dist/motion-value.d.ts.map +1 -0
- package/dist/motion-value.js +1074 -0
- package/dist/motion-value.js.map +1 -0
- package/dist/native/index.d.ts +10 -0
- package/dist/native/index.d.ts.map +1 -0
- package/dist/native/index.js +6 -0
- package/dist/native/index.js.map +1 -0
- package/dist/native-properties.d.ts +28 -0
- package/dist/native-properties.d.ts.map +1 -0
- package/dist/native-properties.js +154 -0
- package/dist/native-properties.js.map +1 -0
- package/dist/native-property-driver.d.ts +19 -0
- package/dist/native-property-driver.d.ts.map +1 -0
- package/dist/native-property-driver.js +69 -0
- package/dist/native-property-driver.js.map +1 -0
- package/dist/native-property.d.ts +37 -0
- package/dist/native-property.d.ts.map +1 -0
- package/dist/native-property.js +285 -0
- package/dist/native-property.js.map +1 -0
- package/dist/particles.d.ts +5 -2
- package/dist/particles.d.ts.map +1 -1
- package/dist/particles.js +16 -10
- package/dist/particles.js.map +1 -1
- package/dist/path.d.ts.map +1 -1
- package/dist/path.js +2 -2
- package/dist/path.js.map +1 -1
- package/dist/physics/index.d.ts +139 -0
- package/dist/physics/index.d.ts.map +1 -0
- package/dist/physics/index.js +316 -0
- package/dist/physics/index.js.map +1 -0
- package/dist/physics/native.d.ts +54 -0
- package/dist/physics/native.d.ts.map +1 -0
- package/dist/physics/native.js +64 -0
- package/dist/physics/native.js.map +1 -0
- package/dist/playback-group.d.ts.map +1 -1
- package/dist/playback-group.js +17 -1
- package/dist/playback-group.js.map +1 -1
- package/dist/playback.d.ts +15 -0
- package/dist/playback.d.ts.map +1 -1
- package/dist/playback.js +23 -0
- package/dist/playback.js.map +1 -1
- package/dist/predictive-back/index.d.ts +45 -0
- package/dist/predictive-back/index.d.ts.map +1 -0
- package/dist/predictive-back/index.js +220 -0
- package/dist/predictive-back/index.js.map +1 -0
- package/dist/predictive-back/presentation.d.ts +4 -0
- package/dist/predictive-back/presentation.d.ts.map +1 -0
- package/dist/predictive-back/presentation.js +3 -0
- package/dist/predictive-back/presentation.js.map +1 -0
- package/dist/press.d.ts.map +1 -1
- package/dist/press.js +11 -2
- package/dist/press.js.map +1 -1
- package/dist/reorder/handle.d.ts +6 -0
- package/dist/reorder/handle.d.ts.map +1 -0
- package/dist/reorder/handle.js +10 -0
- package/dist/reorder/handle.js.map +1 -0
- package/dist/reorder/index.d.ts +10 -0
- package/dist/reorder/index.d.ts.map +1 -0
- package/dist/reorder/index.js +233 -0
- package/dist/reorder/index.js.map +1 -0
- package/dist/reorder/list-view.d.ts +5 -0
- package/dist/reorder/list-view.d.ts.map +1 -0
- package/dist/reorder/list-view.js +238 -0
- package/dist/reorder/list-view.js.map +1 -0
- package/dist/reorder/model.d.ts +6 -0
- package/dist/reorder/model.d.ts.map +1 -0
- package/dist/reorder/model.js +30 -0
- package/dist/reorder/model.js.map +1 -0
- package/dist/reorder/surface.d.ts +6 -0
- package/dist/reorder/surface.d.ts.map +1 -0
- package/dist/reorder/surface.js +10 -0
- package/dist/reorder/surface.js.map +1 -0
- package/dist/reorder/types.d.ts +92 -0
- package/dist/reorder/types.d.ts.map +1 -0
- package/dist/reorder/types.js +2 -0
- package/dist/reorder/types.js.map +1 -0
- package/dist/sampling.d.ts +35 -0
- package/dist/sampling.d.ts.map +1 -0
- package/dist/sampling.js +123 -0
- package/dist/sampling.js.map +1 -0
- package/dist/scene-appearance.d.ts +14 -0
- package/dist/scene-appearance.d.ts.map +1 -0
- package/dist/scene-appearance.js +68 -0
- package/dist/scene-appearance.js.map +1 -0
- package/dist/scene-camera.d.ts +5 -0
- package/dist/scene-camera.d.ts.map +1 -0
- package/dist/scene-camera.js +23 -0
- package/dist/scene-camera.js.map +1 -0
- package/dist/scene-shader.d.ts +18 -0
- package/dist/scene-shader.d.ts.map +1 -0
- package/dist/scene-shader.js +76 -0
- package/dist/scene-shader.js.map +1 -0
- package/dist/scroll-header/geometry.d.ts +18 -0
- package/dist/scroll-header/geometry.d.ts.map +1 -0
- package/dist/scroll-header/geometry.js +46 -0
- package/dist/scroll-header/geometry.js.map +1 -0
- package/dist/scroll-header/index.d.ts +48 -0
- package/dist/scroll-header/index.d.ts.map +1 -0
- package/dist/scroll-header/index.js +399 -0
- package/dist/scroll-header/index.js.map +1 -0
- package/dist/scroll-header/native.d.ts +28 -0
- package/dist/scroll-header/native.d.ts.map +1 -0
- package/dist/scroll-header/native.js +43 -0
- package/dist/scroll-header/native.js.map +1 -0
- package/dist/sensors/index.d.ts +69 -0
- package/dist/sensors/index.d.ts.map +1 -0
- package/dist/sensors/index.js +149 -0
- package/dist/sensors/index.js.map +1 -0
- package/dist/sensors/native.d.ts +20 -0
- package/dist/sensors/native.d.ts.map +1 -0
- package/dist/sensors/native.js +48 -0
- package/dist/sensors/native.js.map +1 -0
- package/dist/sequence.d.ts +24 -0
- package/dist/sequence.d.ts.map +1 -1
- package/dist/sequence.js +181 -19
- package/dist/sequence.js.map +1 -1
- package/dist/shapes/android.d.ts +3 -0
- package/dist/shapes/android.d.ts.map +1 -0
- package/dist/shapes/android.js +51 -0
- package/dist/shapes/android.js.map +1 -0
- package/dist/shapes/index.d.ts +6 -0
- package/dist/shapes/index.d.ts.map +1 -0
- package/dist/shapes/index.js +238 -0
- package/dist/shapes/index.js.map +1 -0
- package/dist/shapes/ios.d.ts +3 -0
- package/dist/shapes/ios.d.ts.map +1 -0
- package/dist/shapes/ios.js +164 -0
- package/dist/shapes/ios.js.map +1 -0
- package/dist/shapes/native.d.ts +18 -0
- package/dist/shapes/native.d.ts.map +1 -0
- package/dist/shapes/native.js +10 -0
- package/dist/shapes/native.js.map +1 -0
- package/dist/shapes/path.d.ts +10 -0
- package/dist/shapes/path.d.ts.map +1 -0
- package/dist/shapes/path.js +106 -0
- package/dist/shapes/path.js.map +1 -0
- package/dist/shapes/types.d.ts +55 -0
- package/dist/shapes/types.d.ts.map +1 -0
- package/dist/shapes/types.js +11 -0
- package/dist/shapes/types.js.map +1 -0
- package/dist/shared-layout/index.d.ts +40 -0
- package/dist/shared-layout/index.d.ts.map +1 -0
- package/dist/shared-layout/index.js +267 -0
- package/dist/shared-layout/index.js.map +1 -0
- package/dist/shared-layout/native.d.ts +15 -0
- package/dist/shared-layout/native.d.ts.map +1 -0
- package/dist/shared-layout/native.js +79 -0
- package/dist/shared-layout/native.js.map +1 -0
- package/dist/shared-layout/timing.d.ts +9 -0
- package/dist/shared-layout/timing.d.ts.map +1 -0
- package/dist/shared-layout/timing.js +68 -0
- package/dist/shared-layout/timing.js.map +1 -0
- package/dist/shared-navigation/entry.d.ts +51 -0
- package/dist/shared-navigation/entry.d.ts.map +1 -0
- package/dist/shared-navigation/entry.js +619 -0
- package/dist/shared-navigation/entry.js.map +1 -0
- package/dist/shared-navigation/index.d.ts +58 -0
- package/dist/shared-navigation/index.d.ts.map +1 -0
- package/dist/shared-navigation/index.js +318 -0
- package/dist/shared-navigation/index.js.map +1 -0
- package/dist/shared-navigation/return-signal.d.ts +16 -0
- package/dist/shared-navigation/return-signal.d.ts.map +1 -0
- package/dist/shared-navigation/return-signal.js +35 -0
- package/dist/shared-navigation/return-signal.js.map +1 -0
- package/dist/shared-navigation/return-target.d.ts +32 -0
- package/dist/shared-navigation/return-target.d.ts.map +1 -0
- package/dist/shared-navigation/return-target.js +168 -0
- package/dist/shared-navigation/return-target.js.map +1 -0
- package/dist/shared-navigation/scope.d.ts +4 -0
- package/dist/shared-navigation/scope.d.ts.map +1 -0
- package/dist/shared-navigation/scope.js +2 -0
- package/dist/shared-navigation/scope.js.map +1 -0
- package/dist/shared-navigation/targets.d.ts +6 -0
- package/dist/shared-navigation/targets.d.ts.map +1 -0
- package/dist/shared-navigation/targets.js +36 -0
- package/dist/shared-navigation/targets.js.map +1 -0
- package/dist/size-layout.d.ts +19 -0
- package/dist/size-layout.d.ts.map +1 -0
- package/dist/size-layout.js +216 -0
- package/dist/size-layout.js.map +1 -0
- package/dist/size.d.ts +19 -0
- package/dist/size.d.ts.map +1 -0
- package/dist/size.js +251 -0
- package/dist/size.js.map +1 -0
- package/dist/spring.d.ts +2 -0
- package/dist/spring.d.ts.map +1 -1
- package/dist/spring.js +11 -0
- package/dist/spring.js.map +1 -1
- package/dist/svg-path.d.ts +18 -0
- package/dist/svg-path.d.ts.map +1 -1
- package/dist/svg-path.js +3 -2
- package/dist/svg-path.js.map +1 -1
- package/dist/testing/clock.d.ts +40 -0
- package/dist/testing/clock.d.ts.map +1 -0
- package/dist/testing/clock.js +116 -0
- package/dist/testing/clock.js.map +1 -0
- package/dist/testing/handoff-recorder.d.ts +8 -0
- package/dist/testing/handoff-recorder.d.ts.map +1 -0
- package/dist/testing/handoff-recorder.js +77 -0
- package/dist/testing/handoff-recorder.js.map +1 -0
- package/dist/testing/index.d.ts +5 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +5 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/native.d.ts +46 -0
- package/dist/testing/native.d.ts.map +1 -0
- package/dist/testing/native.js +313 -0
- package/dist/testing/native.js.map +1 -0
- package/dist/testing/presentation.d.ts +11 -0
- package/dist/testing/presentation.d.ts.map +1 -0
- package/dist/testing/presentation.js +45 -0
- package/dist/testing/presentation.js.map +1 -0
- package/dist/testing/replay.d.ts +39 -0
- package/dist/testing/replay.d.ts.map +1 -0
- package/dist/testing/replay.js +99 -0
- package/dist/testing/replay.js.map +1 -0
- package/dist/testing/scroll-handoff-native.d.ts +10 -0
- package/dist/testing/scroll-handoff-native.d.ts.map +1 -0
- package/dist/testing/scroll-handoff-native.js +151 -0
- package/dist/testing/scroll-handoff-native.js.map +1 -0
- package/dist/testing/scroll-handoff.d.ts +25 -0
- package/dist/testing/scroll-handoff.d.ts.map +1 -0
- package/dist/testing/scroll-handoff.js +127 -0
- package/dist/testing/scroll-handoff.js.map +1 -0
- package/dist/testing/sensors.d.ts +13 -0
- package/dist/testing/sensors.d.ts.map +1 -0
- package/dist/testing/sensors.js +26 -0
- package/dist/testing/sensors.js.map +1 -0
- package/dist/testing/trace.d.ts +101 -0
- package/dist/testing/trace.d.ts.map +1 -0
- package/dist/testing/trace.js +263 -0
- package/dist/testing/trace.js.map +1 -0
- package/dist/timed-animation.d.ts +38 -0
- package/dist/timed-animation.d.ts.map +1 -0
- package/dist/timed-animation.js +177 -0
- package/dist/timed-animation.js.map +1 -0
- package/dist/track.d.ts +3 -0
- package/dist/track.d.ts.map +1 -1
- package/dist/track.js +281 -40
- package/dist/track.js.map +1 -1
- package/dist/transition.d.ts +54 -2
- package/dist/transition.d.ts.map +1 -1
- package/dist/transition.js +128 -8
- package/dist/transition.js.map +1 -1
- package/dist/types.d.ts +10 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/value-observers.d.ts +22 -0
- package/dist/value-observers.d.ts.map +1 -0
- package/dist/value-observers.js +122 -0
- package/dist/value-observers.js.map +1 -0
- package/dist/value-track.d.ts +13 -0
- package/dist/value-track.d.ts.map +1 -0
- package/dist/value-track.js +59 -0
- package/dist/value-track.js.map +1 -0
- package/dist/vue/index.d.ts +33 -3
- package/dist/vue/index.d.ts.map +1 -1
- package/dist/vue/index.js +118 -3
- package/dist/vue/index.js.map +1 -1
- package/dist/zoomable.d.ts +1 -1
- package/dist/zoomable.d.ts.map +1 -1
- package/package.json +68 -3
- package/platforms/android/include.gradle +10 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/BlurEffect.java +89 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/CircleMath.java +158 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/CircleWorld.java +221 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/GestureSession.java +227 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/GestureSurface.java +54 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/GradientLayer.java +224 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/KeyboardFrame.java +53 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/KeyboardFrameFollower.java +57 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/KeyboardObserver.java +97 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/LiveSpring.java +277 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/MotionProbe.java +70 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/ParticleEmitter.java +192 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/ParticleSimulation.java +114 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/PredictiveBackSession.java +212 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/ReorderHandle.java +25 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/ReorderSession.java +213 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/ReorderSurface.java +27 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/ScrollHeader.java +84 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/SensorMath.java +28 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/SensorSource.java +217 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/ShapeLayer.java +120 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/SharedLayoutFlight.java +287 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/SharedNavigationScene.java +115 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/SpringState.java +39 -0
- package/platforms/android/proguard-rules.pro +20 -0
- package/platforms/ios/build.xcconfig +1 -1
- package/platforms/ios/src/JoltBlur.h +14 -0
- package/platforms/ios/src/JoltBlur.m +86 -0
- package/platforms/ios/src/JoltCircleMath.h +191 -0
- package/platforms/ios/src/JoltCircleWorld.h +18 -0
- package/platforms/ios/src/JoltCircleWorld.m +218 -0
- package/platforms/ios/src/JoltGestureSession.h +23 -0
- package/platforms/ios/src/JoltGestureSession.m +251 -0
- package/platforms/ios/src/JoltInteractiveNavigation.h +23 -0
- package/platforms/ios/src/JoltInteractiveNavigation.m +255 -0
- package/platforms/ios/src/JoltLiveSpring.h +29 -0
- package/platforms/ios/src/JoltLiveSpring.m +243 -0
- package/platforms/ios/src/JoltMotionProbe.h +9 -0
- package/platforms/ios/src/JoltMotionProbe.m +72 -0
- package/platforms/ios/src/JoltReorderSession.h +15 -0
- package/platforms/ios/src/JoltReorderSession.m +205 -0
- package/platforms/ios/src/JoltScrollHeader.h +13 -0
- package/platforms/ios/src/JoltScrollHeader.m +101 -0
- package/platforms/ios/src/JoltSensorMath.h +39 -0
- package/platforms/ios/src/JoltSensorSource.h +13 -0
- package/platforms/ios/src/JoltSensorSource.m +201 -0
- package/platforms/ios/src/JoltSharedLayoutFlight.h +19 -0
- package/platforms/ios/src/JoltSharedLayoutFlight.m +250 -0
- package/platforms/ios/src/JoltSpringState.h +35 -0
- package/platforms/ios/src/module.modulemap +10 -0
- package/src/android-plugin.d.ts +464 -0
- package/src/animate.ts +129 -15
- package/src/blur/index.ts +195 -0
- package/src/blur/native.ts +70 -0
- package/src/blur/types.ts +32 -0
- package/src/bottom-sheet/geometry.ts +84 -0
- package/src/bottom-sheet/index.ts +536 -0
- package/src/bottom-sheet/native.ts +214 -0
- package/src/config.ts +39 -1
- package/src/decay.ts +9 -0
- package/src/drag.ts +67 -21
- package/src/driver/android-gradient.ts +116 -0
- package/src/driver/android-particles.ts +118 -0
- package/src/driver/android.ts +31 -1
- package/src/driver/frame.ts +10 -0
- package/src/driver/index.ts +4 -0
- package/src/driver/ios-gradient.ts +136 -0
- package/src/driver/ios-scroll-delegate.ts +23 -0
- package/src/driver/ios.ts +10 -0
- package/src/easing.ts +21 -1
- package/src/engine.ts +209 -60
- package/src/gesture-native.ts +139 -0
- package/src/gestures/index.ts +365 -0
- package/src/glass/index.ts +218 -0
- package/src/gradient-binding.ts +158 -0
- package/src/gradient.ts +663 -0
- package/src/gravity.ts +107 -0
- package/src/haptics.ts +106 -28
- package/src/image-effect.ts +10 -2
- package/src/index.ts +56 -7
- package/src/inspector/index.ts +523 -0
- package/src/inspector/plot.ts +27 -0
- package/src/inspector/probe.ts +50 -0
- package/src/inspector/tuning.ts +51 -0
- package/src/interactive-navigation/index.ts +427 -0
- package/src/ios-plugin.d.ts +280 -0
- package/src/keyboard.ts +231 -7
- package/src/live-spring-driver.ts +181 -0
- package/src/mixer.ts +312 -0
- package/src/motion-scope.ts +39 -6
- package/src/motion-states.ts +149 -42
- package/src/motion-value.ts +1289 -0
- package/src/native/index.ts +30 -0
- package/src/native-properties.ts +188 -0
- package/src/native-property-driver.ts +123 -0
- package/src/native-property.ts +366 -0
- package/src/particles.ts +18 -17
- package/src/path.ts +2 -1
- package/src/physics/index.ts +476 -0
- package/src/physics/native.ts +121 -0
- package/src/playback-group.ts +17 -1
- package/src/playback.ts +41 -0
- package/src/predictive-back/index.ts +280 -0
- package/src/predictive-back/presentation.ts +6 -0
- package/src/press.ts +10 -2
- package/src/reorder/handle.ts +9 -0
- package/src/reorder/index.ts +243 -0
- package/src/reorder/list-view.ts +262 -0
- package/src/reorder/model.ts +47 -0
- package/src/reorder/surface.ts +10 -0
- package/src/reorder/types.ts +87 -0
- package/src/sampling.ts +173 -0
- package/src/scene-appearance.ts +92 -0
- package/src/scene-camera.ts +30 -0
- package/src/scene-shader.ts +139 -0
- package/src/scroll-header/geometry.ts +88 -0
- package/src/scroll-header/index.ts +530 -0
- package/src/scroll-header/native.ts +89 -0
- package/src/sensors/index.ts +246 -0
- package/src/sensors/native.ts +72 -0
- package/src/sequence.ts +209 -20
- package/src/shapes/android.ts +63 -0
- package/src/shapes/index.ts +267 -0
- package/src/shapes/ios.ts +194 -0
- package/src/shapes/native.ts +27 -0
- package/src/shapes/path.ts +127 -0
- package/src/shapes/types.ts +63 -0
- package/src/shared-layout/index.ts +343 -0
- package/src/shared-layout/native.ts +138 -0
- package/src/shared-layout/timing.ts +87 -0
- package/src/shared-navigation/entry.ts +695 -0
- package/src/shared-navigation/index.ts +414 -0
- package/src/shared-navigation/return-signal.ts +41 -0
- package/src/shared-navigation/return-target.ts +197 -0
- package/src/shared-navigation/scope.ts +3 -0
- package/src/shared-navigation/targets.ts +38 -0
- package/src/size-layout.ts +237 -0
- package/src/size.ts +302 -0
- package/src/spring.ts +18 -0
- package/src/svg-path.ts +8 -3
- package/src/testing/clock.ts +128 -0
- package/src/testing/handoff-recorder.ts +98 -0
- package/src/testing/index.ts +4 -0
- package/src/testing/native.ts +386 -0
- package/src/testing/presentation.ts +46 -0
- package/src/testing/replay.ts +149 -0
- package/src/testing/scroll-handoff-native.ts +201 -0
- package/src/testing/scroll-handoff.ts +140 -0
- package/src/testing/sensors.ts +41 -0
- package/src/testing/trace.ts +340 -0
- package/src/timed-animation.ts +192 -0
- package/src/track.ts +334 -38
- package/src/transition.ts +197 -9
- package/src/types.ts +11 -1
- package/src/value-observers.ts +147 -0
- package/src/value-track.ts +71 -0
- package/src/vue/index.ts +147 -1
- package/src/zoomable.ts +1 -1
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
#import "JoltReorderSession.h"
|
|
2
|
+
|
|
3
|
+
@implementation JoltReorderHandle
|
|
4
|
+
- (BOOL)canBecomeFirstResponder { return YES; }
|
|
5
|
+
- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
|
|
6
|
+
[self becomeFirstResponder]; return [super beginTrackingWithTouch:touch withEvent:event];
|
|
7
|
+
}
|
|
8
|
+
- (NSArray<UIKeyCommand *> *)keyCommands {
|
|
9
|
+
if (!self.onMove) return [super keyCommands];
|
|
10
|
+
UIKeyCommand *up = [UIKeyCommand keyCommandWithInput:UIKeyInputUpArrow modifierFlags:UIKeyModifierAlternate action:@selector(moveUp:)];
|
|
11
|
+
UIKeyCommand *down = [UIKeyCommand keyCommandWithInput:UIKeyInputDownArrow modifierFlags:UIKeyModifierAlternate action:@selector(moveDown:)];
|
|
12
|
+
if (@available(iOS 15.0, *)) { up.wantsPriorityOverSystemBehavior = YES; down.wantsPriorityOverSystemBehavior = YES; }
|
|
13
|
+
return @[up, down];
|
|
14
|
+
}
|
|
15
|
+
- (void)moveUp:(UIKeyCommand *)command { if (self.onMove) self.onMove(-1); }
|
|
16
|
+
- (void)moveDown:(UIKeyCommand *)command { if (self.onMove) self.onMove(1); }
|
|
17
|
+
@end
|
|
18
|
+
|
|
19
|
+
@interface JoltReorderCellState : NSObject
|
|
20
|
+
@property(nonatomic) CATransform3D transform;
|
|
21
|
+
@property(nonatomic) BOOL cellClips, contentClips;
|
|
22
|
+
@property(nonatomic) CGFloat alpha, offset;
|
|
23
|
+
@property(nonatomic) NSInteger index;
|
|
24
|
+
@end
|
|
25
|
+
@implementation JoltReorderCellState
|
|
26
|
+
@end
|
|
27
|
+
|
|
28
|
+
@interface JoltReorderSession () <UIGestureRecognizerDelegate>
|
|
29
|
+
@property(nonatomic, weak) UITableView *list;
|
|
30
|
+
@property(nonatomic) UILongPressGestureRecognizer *press;
|
|
31
|
+
@property(nonatomic) NSHashTable<UIView *> *handles;
|
|
32
|
+
@property(nonatomic) NSMapTable<UITableViewCell *, JoltReorderCellState *> *cells;
|
|
33
|
+
@property(nonatomic) UIView *overlay;
|
|
34
|
+
@property(nonatomic) CADisplayLink *clock;
|
|
35
|
+
@property(nonatomic, copy) void (^onState)(NSInteger, NSInteger, NSInteger);
|
|
36
|
+
@property(nonatomic) NSInteger from, target, count, generation;
|
|
37
|
+
@property(nonatomic) CGFloat edgeSize, edgeSpeed, height, grabOffset, pointerY, pointerX;
|
|
38
|
+
@property(nonatomic) CGSize viewport;
|
|
39
|
+
@property(nonatomic) double previousTime;
|
|
40
|
+
@property(nonatomic) BOOL enabled, disposed, handlesOnly, reduced, settling, scrollEnabled, cancelling;
|
|
41
|
+
@property(nonatomic, readwrite) BOOL active;
|
|
42
|
+
@end
|
|
43
|
+
|
|
44
|
+
@implementation JoltReorderSession
|
|
45
|
+
+ (instancetype)attach:(UITableView *)list options:(NSString *)options onState:(void (^)(NSInteger, NSInteger, NSInteger))onState {
|
|
46
|
+
if (![list isKindOfClass:UITableView.class]) @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Reorder requires a UITableView" userInfo:nil];
|
|
47
|
+
NSDictionary *config = [NSJSONSerialization JSONObjectWithData:[options dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];
|
|
48
|
+
JoltReorderSession *s = [self new]; s.list = list; s.onState = onState; s.enabled = YES;
|
|
49
|
+
s.edgeSize = [config[@"edgeSize"] doubleValue]; s.edgeSpeed = [config[@"edgeSpeed"] doubleValue];
|
|
50
|
+
s.reduced = [config[@"reducedMotion"] boolValue]; s.handlesOnly = [config[@"handles"] boolValue];
|
|
51
|
+
s.handles = [NSHashTable weakObjectsHashTable]; s.cells = [NSMapTable weakToStrongObjectsMapTable];
|
|
52
|
+
s.press = [[UILongPressGestureRecognizer alloc] initWithTarget:s action:@selector(pressed:)];
|
|
53
|
+
s.press.minimumPressDuration = [config[@"longPress"] doubleValue] / 1000.; s.press.numberOfTouchesRequired = 1;
|
|
54
|
+
s.press.allowableMovement = 10; s.press.delegate = s;
|
|
55
|
+
[list addGestureRecognizer:s.press];
|
|
56
|
+
return s;
|
|
57
|
+
}
|
|
58
|
+
- (void)registerHandle:(UIView *)view { if (!self.disposed && view) [self.handles addObject:view]; }
|
|
59
|
+
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)recognizer shouldReceiveTouch:(UITouch *)touch {
|
|
60
|
+
if (self.active) { [self cancel]; return NO; }
|
|
61
|
+
if (!self.enabled || self.disposed || self.active || !self.list.window) return NO;
|
|
62
|
+
if (!self.handlesOnly) return YES;
|
|
63
|
+
for (UIView *view = touch.view; view && view != self.list; view = view.superview)
|
|
64
|
+
if ([self.handles containsObject:view]) return YES;
|
|
65
|
+
return NO;
|
|
66
|
+
}
|
|
67
|
+
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)recognizer {
|
|
68
|
+
NSIndexPath *path = [self.list indexPathForRowAtPoint:[recognizer locationInView:self.list]];
|
|
69
|
+
return path && path.section == 0 && self.list.numberOfSections == 1 && !self.list.dragging && !self.list.decelerating;
|
|
70
|
+
}
|
|
71
|
+
- (void)emit:(NSInteger)state detail:(NSInteger)detail { if (!self.disposed && self.onState) self.onState(state, self.from, detail); }
|
|
72
|
+
- (void)pressed:(UILongPressGestureRecognizer *)press {
|
|
73
|
+
if (press.state == UIGestureRecognizerStateBegan) [self begin];
|
|
74
|
+
else if (press.state == UIGestureRecognizerStateChanged && self.active && !self.settling) {
|
|
75
|
+
CGPoint p = [press locationInView:self.list.window]; self.pointerY = p.y; self.pointerX = p.x; [self update];
|
|
76
|
+
} else if (press.state == UIGestureRecognizerStateEnded && self.active) [self drop];
|
|
77
|
+
else if (press.state == UIGestureRecognizerStateCancelled || press.state == UIGestureRecognizerStateFailed) [self cancel];
|
|
78
|
+
}
|
|
79
|
+
- (void)begin {
|
|
80
|
+
UITableView *list = self.list;
|
|
81
|
+
NSIndexPath *path = [list indexPathForRowAtPoint:[self.press locationInView:list]];
|
|
82
|
+
UITableViewCell *cell = path ? [list cellForRowAtIndexPath:path] : nil;
|
|
83
|
+
if (!cell || path.section != 0 || !list.window) return;
|
|
84
|
+
UIView *snapshot = [cell snapshotViewAfterScreenUpdates:NO];
|
|
85
|
+
if (!snapshot) return;
|
|
86
|
+
CGRect frame = [list convertRect:[list rectForRowAtIndexPath:path] toView:list.window];
|
|
87
|
+
self.overlay = snapshot; snapshot.frame = frame; snapshot.userInteractionEnabled = NO;
|
|
88
|
+
snapshot.accessibilityElementsHidden = YES;
|
|
89
|
+
snapshot.layer.shadowColor = UIColor.blackColor.CGColor; snapshot.layer.shadowRadius = 12;
|
|
90
|
+
snapshot.layer.shadowOpacity = .18; snapshot.layer.shadowOffset = CGSizeMake(0, 6);
|
|
91
|
+
[list.window addSubview:snapshot];
|
|
92
|
+
CGPoint p = [self.press locationInView:list.window];
|
|
93
|
+
self.pointerY = p.y; self.pointerX = p.x; self.grabOffset = p.y - CGRectGetMidY(frame);
|
|
94
|
+
self.height = frame.size.height; self.viewport = list.bounds.size;
|
|
95
|
+
self.count = [list numberOfRowsInSection:0]; self.from = self.target = path.row;
|
|
96
|
+
self.scrollEnabled = list.scrollEnabled; list.scrollEnabled = NO;
|
|
97
|
+
self.active = YES; self.settling = NO; self.previousTime = CACurrentMediaTime(); self.generation++;
|
|
98
|
+
[self emit:1 detail:self.from];
|
|
99
|
+
if (!self.active || self.disposed) return;
|
|
100
|
+
self.clock = [CADisplayLink displayLinkWithTarget:self selector:@selector(tick:)];
|
|
101
|
+
[self.clock addToRunLoop:NSRunLoop.mainRunLoop forMode:NSRunLoopCommonModes];
|
|
102
|
+
[self update];
|
|
103
|
+
}
|
|
104
|
+
- (void)tick:(CADisplayLink *)clock {
|
|
105
|
+
if (!self.active || self.settling) return;
|
|
106
|
+
UITableView *list = self.list;
|
|
107
|
+
if (!list.window || !CGSizeEqualToSize(self.viewport, list.bounds.size) || self.count != [list numberOfRowsInSection:0]) {
|
|
108
|
+
[self finish:NO detail:1]; return;
|
|
109
|
+
}
|
|
110
|
+
double now = CACurrentMediaTime(), dt = MIN(.04, MAX(0, now - self.previousTime)); self.previousTime = now;
|
|
111
|
+
CGRect viewport = [list convertRect:list.bounds toView:list.window];
|
|
112
|
+
CGFloat inset = MIN(self.edgeSize, viewport.size.height / 3), distance = 0;
|
|
113
|
+
if (self.pointerY < CGRectGetMinY(viewport) + inset) distance = -MIN(1, (CGRectGetMinY(viewport) + inset - self.pointerY) / inset);
|
|
114
|
+
else if (self.pointerY > CGRectGetMaxY(viewport) - inset) distance = MIN(1, (self.pointerY - CGRectGetMaxY(viewport) + inset) / inset);
|
|
115
|
+
CGFloat top = -list.adjustedContentInset.top, bottom = MAX(top, list.contentSize.height - list.bounds.size.height + list.adjustedContentInset.bottom);
|
|
116
|
+
CGFloat next = MAX(top, MIN(bottom, list.contentOffset.y + distance * self.edgeSpeed * dt));
|
|
117
|
+
if (fabs(next - list.contentOffset.y) > .01) { [list setContentOffset:CGPointMake(list.contentOffset.x, next) animated:NO]; [list layoutIfNeeded]; }
|
|
118
|
+
[self update];
|
|
119
|
+
}
|
|
120
|
+
- (void)restore:(UITableViewCell *)cell state:(JoltReorderCellState *)state {
|
|
121
|
+
[cell.contentView.layer removeAnimationForKey:@"jolt.reorder"];
|
|
122
|
+
cell.contentView.layer.sublayerTransform = state.transform; cell.alpha = state.alpha; state.offset = 0;
|
|
123
|
+
cell.clipsToBounds = state.cellClips; cell.contentView.clipsToBounds = state.contentClips;
|
|
124
|
+
}
|
|
125
|
+
- (void)update {
|
|
126
|
+
if (!self.active || self.settling) return;
|
|
127
|
+
UITableView *list = self.list;
|
|
128
|
+
CGFloat center = self.pointerY - self.grabOffset;
|
|
129
|
+
CGPoint inList = [list convertPoint:CGPointMake(self.pointerX, center) fromView:list.window];
|
|
130
|
+
CGFloat draggedTop = inList.y - self.height / 2;
|
|
131
|
+
self.overlay.center = CGPointMake(self.overlay.center.x, center);
|
|
132
|
+
NSArray<NSIndexPath *> *paths = [[list indexPathsForVisibleRows] sortedArrayUsingSelector:@selector(compare:)];
|
|
133
|
+
NSInteger destination = self.from;
|
|
134
|
+
for (NSIndexPath *path in paths) {
|
|
135
|
+
if (path.section || path.row == self.from) continue;
|
|
136
|
+
CGRect frame = [list rectForRowAtIndexPath:path];
|
|
137
|
+
CGFloat midpoint = CGRectGetMidY(frame) - (path.row > self.from ? self.height : 0);
|
|
138
|
+
NSInteger insertion = path.row - (path.row > self.from ? 1 : 0);
|
|
139
|
+
destination = insertion;
|
|
140
|
+
if (draggedTop < midpoint) break;
|
|
141
|
+
destination = insertion + 1;
|
|
142
|
+
}
|
|
143
|
+
self.target = MAX(0, MIN(self.count - 1, destination));
|
|
144
|
+
NSSet *visible = [NSSet setWithArray:list.visibleCells];
|
|
145
|
+
for (UITableViewCell *cell in self.cells.keyEnumerator.allObjects)
|
|
146
|
+
if (![visible containsObject:cell]) { [self restore:cell state:[self.cells objectForKey:cell]]; [self.cells removeObjectForKey:cell]; }
|
|
147
|
+
for (NSIndexPath *path in paths) {
|
|
148
|
+
UITableViewCell *cell = [list cellForRowAtIndexPath:path]; if (!cell) continue;
|
|
149
|
+
JoltReorderCellState *state = [self.cells objectForKey:cell];
|
|
150
|
+
if (state && state.index != path.row) { [self restore:cell state:state]; [self.cells removeObjectForKey:cell]; state = nil; }
|
|
151
|
+
if (!state) { state = [JoltReorderCellState new]; state.transform = cell.contentView.layer.sublayerTransform; state.cellClips = cell.clipsToBounds; state.contentClips = cell.contentView.clipsToBounds; state.alpha = cell.alpha; state.index = path.row; [self.cells setObject:state forKey:cell]; }
|
|
152
|
+
cell.clipsToBounds = NO; cell.contentView.clipsToBounds = NO;
|
|
153
|
+
cell.alpha = path.row == self.from ? 0 : state.alpha;
|
|
154
|
+
CGFloat offset = path.row > self.from && path.row <= self.target ? -self.height : path.row < self.from && path.row >= self.target ? self.height : 0;
|
|
155
|
+
if (fabs(offset - state.offset) < .01) continue;
|
|
156
|
+
// UITableView owns cell/contentView frames. Move only the contents of
|
|
157
|
+
// the layer so height estimation and recycling cannot corrupt geometry.
|
|
158
|
+
CALayer *layer = cell.contentView.layer;
|
|
159
|
+
CATransform3D previous = ((CALayer *)layer.presentationLayer ?: layer).sublayerTransform;
|
|
160
|
+
state.offset = offset; layer.sublayerTransform = CATransform3DTranslate(state.transform, 0, offset, 0);
|
|
161
|
+
[layer removeAnimationForKey:@"jolt.reorder"];
|
|
162
|
+
if (!self.reduced) {
|
|
163
|
+
CASpringAnimation *spring = [CASpringAnimation animationWithKeyPath:@"sublayerTransform"];
|
|
164
|
+
spring.mass = 1; spring.stiffness = 360; spring.damping = 34;
|
|
165
|
+
spring.fromValue = [NSValue valueWithCATransform3D:previous]; spring.toValue = [NSValue valueWithCATransform3D:layer.sublayerTransform]; spring.duration = spring.settlingDuration;
|
|
166
|
+
[layer addAnimation:spring forKey:@"jolt.reorder"];
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
- (void)drop {
|
|
171
|
+
if (!self.active || self.settling) return;
|
|
172
|
+
self.settling = YES; [self.clock invalidate]; self.clock = nil;
|
|
173
|
+
NSInteger generation = self.generation;
|
|
174
|
+
CGRect row = [self.list rectForRowAtIndexPath:[NSIndexPath indexPathForRow:self.target inSection:0]];
|
|
175
|
+
CGFloat top = self.target > self.from ? CGRectGetMaxY(row) - self.height : row.origin.y;
|
|
176
|
+
CGPoint end = [self.list convertPoint:CGPointMake(row.origin.x + row.size.width / 2, top + self.height / 2) toView:self.list.window];
|
|
177
|
+
if (self.reduced) { [self finish:YES detail:0]; return; }
|
|
178
|
+
[UIView animateWithDuration:.18 delay:0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseOut animations:^{ self.overlay.center = end; } completion:^(BOOL finished) {
|
|
179
|
+
if (self.active && generation == self.generation) [self finish:YES detail:0];
|
|
180
|
+
}];
|
|
181
|
+
}
|
|
182
|
+
- (void)finish:(BOOL)commit detail:(NSInteger)detail {
|
|
183
|
+
if (!self.active) return;
|
|
184
|
+
self.active = NO; self.settling = NO; self.generation++;
|
|
185
|
+
[self.clock invalidate]; self.clock = nil;
|
|
186
|
+
[self.overlay.layer removeAllAnimations]; [self.overlay removeFromSuperview]; self.overlay = nil;
|
|
187
|
+
for (UITableViewCell *cell in self.cells.keyEnumerator.allObjects) [self restore:cell state:[self.cells objectForKey:cell]];
|
|
188
|
+
[self.cells removeAllObjects]; self.list.scrollEnabled = self.scrollEnabled;
|
|
189
|
+
[self emit:commit ? 2 : 3 detail:commit ? self.target : detail];
|
|
190
|
+
}
|
|
191
|
+
- (void)cancel {
|
|
192
|
+
if (self.cancelling) return;
|
|
193
|
+
self.cancelling = YES;
|
|
194
|
+
[self finish:NO detail:0];
|
|
195
|
+
if (self.press.enabled) { self.press.enabled = NO; self.press.enabled = YES; }
|
|
196
|
+
self.cancelling = NO;
|
|
197
|
+
}
|
|
198
|
+
- (void)setEnabled:(BOOL)value { _enabled = value; if (!value) [self cancel]; }
|
|
199
|
+
- (void)setReducedMotion:(BOOL)value { self.reduced = value; }
|
|
200
|
+
- (void)dispose {
|
|
201
|
+
if (self.disposed) return;
|
|
202
|
+
[self cancel]; self.disposed = YES; [self.list removeGestureRecognizer:self.press]; self.onState = nil;
|
|
203
|
+
[self.handles removeAllObjects];
|
|
204
|
+
}
|
|
205
|
+
@end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#import <UIKit/UIKit.h>
|
|
2
|
+
#import "JoltLiveSpring.h"
|
|
3
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
4
|
+
@interface JoltScrollHeader : NSObject
|
|
5
|
+
+ (instancetype)attach:(UITableView *)list node:(JoltLiveSpring *)node title:(UIView *)title toolbarTitle:(UIView *)toolbarTitle toolbar:(UIView *)toolbar diagnostic:(nullable UILabel *)diagnostic options:(NSString *)options onState:(void (^)(void))onState;
|
|
6
|
+
+ (NSInteger)activeCount;
|
|
7
|
+
- (void)configure:(NSString *)options;
|
|
8
|
+
- (NSString *)snapshot;
|
|
9
|
+
- (void)scroll:(double)offset animated:(BOOL)animated;
|
|
10
|
+
- (void)setEnabled:(BOOL)enabled;
|
|
11
|
+
- (void)dispose;
|
|
12
|
+
@end
|
|
13
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#import "JoltScrollHeader.h"
|
|
2
|
+
#import <QuartzCore/QuartzCore.h>
|
|
3
|
+
|
|
4
|
+
@interface JoltScrollHeaderDelegate : NSObject <UITableViewDelegate>
|
|
5
|
+
@property(nonatomic) id<UITableViewDelegate> forwarded;
|
|
6
|
+
@property(nonatomic) double spacer, rowHeight;
|
|
7
|
+
@end
|
|
8
|
+
@implementation JoltScrollHeaderDelegate
|
|
9
|
+
- (BOOL)respondsToSelector:(SEL)selector { return [super respondsToSelector:selector] || [self.forwarded respondsToSelector:selector]; }
|
|
10
|
+
- (id)forwardingTargetForSelector:(SEL)selector { return self.forwarded; }
|
|
11
|
+
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)path { return path.row == 0 ? self.spacer : self.rowHeight; }
|
|
12
|
+
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)path { return path.row == 0 ? self.spacer : self.rowHeight; }
|
|
13
|
+
@end
|
|
14
|
+
|
|
15
|
+
@interface JoltScrollHeader ()
|
|
16
|
+
@property(nonatomic) JoltScrollHeaderDelegate *proxy;
|
|
17
|
+
@property(nonatomic,weak) UITableView *list;
|
|
18
|
+
@property(nonatomic) JoltLiveSpring *node;
|
|
19
|
+
@property(nonatomic,weak) UIView *title, *toolbarTitle, *toolbar;
|
|
20
|
+
@property(nonatomic,weak) UILabel *diagnostic;
|
|
21
|
+
@property(nonatomic,copy) void (^onState)(void);
|
|
22
|
+
@property(nonatomic) BOOL observing, disposed, titleHidden, toolbarTitleHidden, toolbarTouch;
|
|
23
|
+
@property(nonatomic) double handoff, minimumOffset, maximumOffset, range, spacer, rowHeight, offset;
|
|
24
|
+
@property(nonatomic) CGFloat estimatedSectionHeaderHeight, estimatedSectionFooterHeight;
|
|
25
|
+
@property(nonatomic) NSInteger phase, updates, callbacks;
|
|
26
|
+
@end
|
|
27
|
+
static NSInteger JoltScrollHeaderActive = 0;
|
|
28
|
+
static void *JoltScrollHeaderContext = &JoltScrollHeaderContext;
|
|
29
|
+
@implementation JoltScrollHeader
|
|
30
|
+
+ (NSInteger)activeCount { return JoltScrollHeaderActive; }
|
|
31
|
+
+ (instancetype)attach:(UITableView *)list node:(JoltLiveSpring *)node title:(UIView *)title toolbarTitle:(UIView *)toolbarTitle toolbar:(UIView *)toolbar diagnostic:(UILabel *)diagnostic options:(NSString *)options onState:(void (^)(void))onState {
|
|
32
|
+
if(![list isKindOfClass:UITableView.class]) [NSException raise:NSInvalidArgumentException format:@"scrollHeader requires UITableView"];
|
|
33
|
+
JoltScrollHeader *owner=[self new];owner.list=list;owner.node=node;owner.title=title;owner.toolbarTitle=toolbarTitle;owner.toolbar=toolbar;owner.diagnostic=diagnostic;owner.onState=onState;
|
|
34
|
+
owner.titleHidden=title.accessibilityElementsHidden;owner.toolbarTitleHidden=toolbarTitle.accessibilityElementsHidden;owner.toolbarTouch=toolbar.userInteractionEnabled;owner.phase=-1;owner.offset=NAN;
|
|
35
|
+
owner.proxy=[JoltScrollHeaderDelegate new];owner.proxy.forwarded=list.delegate;
|
|
36
|
+
// Flat lists have no section headers/footers. UIKit's automatic estimates
|
|
37
|
+
// otherwise adjust the scroll anchor during width/safe-area changes.
|
|
38
|
+
owner.estimatedSectionHeaderHeight=list.estimatedSectionHeaderHeight;
|
|
39
|
+
owner.estimatedSectionFooterHeight=list.estimatedSectionFooterHeight;
|
|
40
|
+
list.estimatedSectionHeaderHeight=0;list.estimatedSectionFooterHeight=0;
|
|
41
|
+
[owner configure:options];list.delegate=owner.proxy;[list reloadData];[list layoutIfNeeded];[owner setEnabled:YES];return owner;
|
|
42
|
+
}
|
|
43
|
+
- (void)configure:(NSString *)options {
|
|
44
|
+
NSDictionary *config=[NSJSONSerialization JSONObjectWithData:[options dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];
|
|
45
|
+
self.handoff=[config[@"handoff"] doubleValue];self.range=[config[@"range"] doubleValue];self.spacer=[config[@"spacer"] doubleValue];self.rowHeight=[config[@"rowHeight"] doubleValue];
|
|
46
|
+
self.proxy.spacer=self.spacer;self.proxy.rowHeight=self.rowHeight;
|
|
47
|
+
[self.list reloadData];
|
|
48
|
+
if(self.observing)[self update:YES];
|
|
49
|
+
}
|
|
50
|
+
- (void)setEnabled:(BOOL)enabled {
|
|
51
|
+
if(self.disposed || enabled==self.observing)return;
|
|
52
|
+
self.observing=enabled;
|
|
53
|
+
if(enabled) {
|
|
54
|
+
for(NSString *key in @[@"contentOffset",@"contentSize",@"bounds"]) [self.list addObserver:self forKeyPath:key options:0 context:JoltScrollHeaderContext];
|
|
55
|
+
JoltScrollHeaderActive++;[self update:YES];
|
|
56
|
+
} else {
|
|
57
|
+
for(NSString *key in @[@"contentOffset",@"contentSize",@"bounds"]) [self.list removeObserver:self forKeyPath:key context:JoltScrollHeaderContext];
|
|
58
|
+
JoltScrollHeaderActive--;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
- (void)observeValueForKeyPath:(NSString *)key ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
|
|
62
|
+
if(context==JoltScrollHeaderContext) [self update:NO];
|
|
63
|
+
else [super observeValueForKeyPath:key ofObject:object change:change context:context];
|
|
64
|
+
}
|
|
65
|
+
- (void)update:(BOOL)force {
|
|
66
|
+
if(self.disposed || !self.list)return;
|
|
67
|
+
double offset=self.list.contentOffset.y+self.list.adjustedContentInset.top;
|
|
68
|
+
if(!isfinite(offset) || (!force && fabs(offset-self.offset)<.001))return;
|
|
69
|
+
self.offset=offset;self.minimumOffset=MIN(self.minimumOffset,offset);self.maximumOffset=MAX(self.maximumOffset,offset);self.updates++;
|
|
70
|
+
// Existing native value graph applies all derived bindings in one transaction.
|
|
71
|
+
[self.node setTarget:offset];
|
|
72
|
+
BOOL compact=offset>=self.range*self.handoff;
|
|
73
|
+
self.title.accessibilityElementsHidden=self.titleHidden || compact;
|
|
74
|
+
self.toolbarTitle.accessibilityElementsHidden=self.toolbarTitleHidden || !compact;
|
|
75
|
+
self.toolbar.userInteractionEnabled=self.toolbarTouch && compact;
|
|
76
|
+
NSInteger phase=offset<=.5?0:offset>=self.range-.5?2:1;
|
|
77
|
+
if(phase!=self.phase){self.phase=phase;self.callbacks++;if(self.onState)self.onState();}
|
|
78
|
+
if(self.diagnostic)self.diagnostic.text=[NSString stringWithFormat:@"y %.0f · range %.0f · native %ld · JS %ld",offset,self.range,(long)self.updates,(long)self.callbacks];
|
|
79
|
+
}
|
|
80
|
+
- (NSString *)snapshot {
|
|
81
|
+
NSArray *rows=self.list.indexPathsForVisibleRows;
|
|
82
|
+
NSInteger first=rows.count?((NSIndexPath *)rows.firstObject).row:0;
|
|
83
|
+
NSDictionary *value=@{@"minimumOffset":@(self.minimumOffset),@"maximumOffset":@(self.maximumOffset),@"offset":@(isfinite(self.offset)?self.offset:0),@"phase":@[@"expanded",@"between",@"collapsed"][MAX(0,self.phase)],@"updates":@(self.updates),@"callbacks":@(self.callbacks),@"first":@(first),@"visible":@(rows.count),@"total":@([self.list numberOfRowsInSection:0])};
|
|
84
|
+
return [[NSString alloc]initWithData:[NSJSONSerialization dataWithJSONObject:value options:0 error:nil] encoding:NSUTF8StringEncoding];
|
|
85
|
+
}
|
|
86
|
+
- (void)scroll:(double)offset animated:(BOOL)animated {
|
|
87
|
+
if(self.disposed || !isfinite(offset))return;
|
|
88
|
+
UIEdgeInsets inset=self.list.adjustedContentInset;
|
|
89
|
+
double maximum=MAX(0,self.list.contentSize.height+inset.top+inset.bottom-self.list.bounds.size.height);
|
|
90
|
+
[self.list setContentOffset:CGPointMake(self.list.contentOffset.x,MIN(maximum,MAX(0,offset))-inset.top) animated:animated];
|
|
91
|
+
if(!animated)[self update:YES];
|
|
92
|
+
}
|
|
93
|
+
- (void)dispose {
|
|
94
|
+
if(self.disposed)return;[self setEnabled:NO];self.disposed=YES;
|
|
95
|
+
self.title.accessibilityElementsHidden=self.titleHidden;self.toolbarTitle.accessibilityElementsHidden=self.toolbarTitleHidden;self.toolbar.userInteractionEnabled=self.toolbarTouch;
|
|
96
|
+
if(self.list.delegate==self.proxy)self.list.delegate=self.proxy.forwarded;
|
|
97
|
+
if(self.list.estimatedSectionHeaderHeight==0)self.list.estimatedSectionHeaderHeight=self.estimatedSectionHeaderHeight;
|
|
98
|
+
if(self.list.estimatedSectionFooterHeight==0)self.list.estimatedSectionFooterHeight=self.estimatedSectionFooterHeight;
|
|
99
|
+
self.proxy=nil;self.node=nil;self.onState=nil;
|
|
100
|
+
}
|
|
101
|
+
@end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// Canonical sensor math: device-to-reference Hamilton quaternions, xyzw.
|
|
2
|
+
#ifndef JOLT_SENSOR_MATH_H
|
|
3
|
+
#define JOLT_SENSOR_MATH_H
|
|
4
|
+
#include <math.h>
|
|
5
|
+
#include <stdbool.h>
|
|
6
|
+
#include <string.h>
|
|
7
|
+
static inline bool JoltSensorNormalize(double *q) {
|
|
8
|
+
double length = 0;
|
|
9
|
+
for (int i = 0; i < 4; i++) { if (!isfinite(q[i])) return false; length += q[i]*q[i]; }
|
|
10
|
+
length = sqrt(length);
|
|
11
|
+
if (!isfinite(length) || length < 1e-8) return false;
|
|
12
|
+
for (int i = 0; i < 4; i++) q[i] /= length;
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
static inline void JoltSensorMultiply(const double *a, const double *b, double *result) {
|
|
16
|
+
double q[] = { a[3]*b[0]+a[0]*b[3]+a[1]*b[2]-a[2]*b[1],
|
|
17
|
+
a[3]*b[1]-a[0]*b[2]+a[1]*b[3]+a[2]*b[0],
|
|
18
|
+
a[3]*b[2]+a[0]*b[1]-a[1]*b[0]+a[2]*b[3],
|
|
19
|
+
a[3]*b[3]-a[0]*b[0]-a[1]*b[1]-a[2]*b[2] };
|
|
20
|
+
memcpy(result, q, sizeof(q));
|
|
21
|
+
}
|
|
22
|
+
static inline void JoltSensorInverse(const double *q, double *result) {
|
|
23
|
+
for (int i=0;i<4;i++) result[i] = i == 3 ? q[i] : -q[i];
|
|
24
|
+
}
|
|
25
|
+
static inline void JoltSensorVector(const double *v, double degrees, double *out) {
|
|
26
|
+
double a = degrees*M_PI/180, c=cos(a), s=sin(a);
|
|
27
|
+
out[0]=c*v[0]+s*v[1]; out[1]=-s*v[0]+c*v[1]; out[2]=v[2];
|
|
28
|
+
}
|
|
29
|
+
static inline void JoltSensorRotation(const double *q, double degrees, const double *previous, double *out) {
|
|
30
|
+
double r[4]; JoltSensorVector(q, degrees, r); r[3]=q[3];
|
|
31
|
+
double dot=0; for(int i=0;i<4;i++) dot += r[i]*previous[i];
|
|
32
|
+
if(dot < 0) for(int i=0;i<4;i++) r[i]=-r[i];
|
|
33
|
+
double x=r[0], y=r[1], z=r[2], w=r[3];
|
|
34
|
+
out[0]=atan2(2*(w*x+y*z), 1-2*(x*x+y*y));
|
|
35
|
+
out[1]=asin(fmax(-1,fmin(1,2*(w*y-z*x))));
|
|
36
|
+
out[2]=atan2(2*(w*z+x*y),1-2*(y*y+z*z));
|
|
37
|
+
memcpy(out+3,r,sizeof(r));
|
|
38
|
+
}
|
|
39
|
+
#endif
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#import <Foundation/Foundation.h>
|
|
2
|
+
#import "JoltLiveSpring.h"
|
|
3
|
+
@interface JoltSensorSource : NSObject
|
|
4
|
+
+ (instancetype)create:(NSString *)kind options:(NSString *)options onState:(void (^)(void))onState;
|
|
5
|
+
+ (NSUInteger)activeCount;
|
|
6
|
+
+ (NSUInteger)sourceCount;
|
|
7
|
+
- (void)connect:(JoltLiveSpring *)node index:(NSInteger)index;
|
|
8
|
+
- (void)setEnabled:(BOOL)enabled paused:(BOOL)paused;
|
|
9
|
+
- (void)recenter;
|
|
10
|
+
- (void)replay:(NSString *)trace;
|
|
11
|
+
- (NSString *)snapshot;
|
|
12
|
+
- (void)dispose;
|
|
13
|
+
@end
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
#import "JoltSensorSource.h"
|
|
2
|
+
#import "JoltSensorMath.h"
|
|
3
|
+
#import <CoreMotion/CoreMotion.h>
|
|
4
|
+
#import <UIKit/UIKit.h>
|
|
5
|
+
#import <QuartzCore/QuartzCore.h>
|
|
6
|
+
|
|
7
|
+
@interface JoltSensorSource () {
|
|
8
|
+
double reference[4], relative[4], output[7], pending[4];
|
|
9
|
+
}
|
|
10
|
+
@property(nonatomic) BOOL rotation, interfaceCoordinates, enabled, disposed, dirty, rebase, reset, available;
|
|
11
|
+
@property(nonatomic) double interval, timestamp, pendingTimestamp, receivedAt, committedAt, processingMs;
|
|
12
|
+
@property(nonatomic) NSUInteger samples, frames, callbacks, replayIndex;
|
|
13
|
+
@property(nonatomic) NSString *status, *error, *configurationError;
|
|
14
|
+
@property(nonatomic) NSMutableArray *nodes;
|
|
15
|
+
@property(nonatomic,copy) void (^onState)(void);
|
|
16
|
+
@property(nonatomic) NSArray *trace;
|
|
17
|
+
@property(nonatomic) double replayStart, replayElapsed, replayOrientation;
|
|
18
|
+
- (void)receive:(const double *)values timestamp:(double)timestamp;
|
|
19
|
+
- (void)frame:(double)now;
|
|
20
|
+
- (void)state:(NSString *)state;
|
|
21
|
+
@end
|
|
22
|
+
|
|
23
|
+
@implementation JoltSensorSource
|
|
24
|
+
static NSMutableArray<JoltSensorSource *> *sources;
|
|
25
|
+
static CMMotionManager *manager;
|
|
26
|
+
static CADisplayLink *sensorDisplayLink;
|
|
27
|
+
static BOOL suspended;
|
|
28
|
+
static double hardwareInterval;
|
|
29
|
+
+ (void)initialize {
|
|
30
|
+
if (self != JoltSensorSource.class) return;
|
|
31
|
+
sources = [NSMutableArray new];
|
|
32
|
+
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(background) name:UIApplicationDidEnterBackgroundNotification object:nil];
|
|
33
|
+
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(foreground) name:UIApplicationWillEnterForegroundNotification object:nil];
|
|
34
|
+
}
|
|
35
|
+
+ (void)background {
|
|
36
|
+
suspended=YES;
|
|
37
|
+
for(JoltSensorSource *s in sources) if(s.trace && s.replayStart) { s.replayElapsed=MAX(0,CACurrentMediaTime()*1000-s.replayStart); s.replayStart=0; }
|
|
38
|
+
[self refresh];
|
|
39
|
+
}
|
|
40
|
+
+ (void)foreground {
|
|
41
|
+
suspended=NO;
|
|
42
|
+
for(JoltSensorSource *s in sources) { s.rebase=YES; s.receivedAt=CACurrentMediaTime()*1000; s.replayStart=0; }
|
|
43
|
+
[self refresh];
|
|
44
|
+
}
|
|
45
|
+
+ (void)refresh {
|
|
46
|
+
double interval=INFINITY; BOOL ticking=NO;
|
|
47
|
+
for(JoltSensorSource *s in sources) if(s.enabled && !s.disposed && !suspended) {
|
|
48
|
+
if(s.trace) ticking=YES;
|
|
49
|
+
else if(s.available && !s.error) { interval=MIN(interval,s.interval); ticking=YES; }
|
|
50
|
+
}
|
|
51
|
+
if(isfinite(interval)) {
|
|
52
|
+
// Updating a shared rate must not restart Core Motion's arbitrary heading reference.
|
|
53
|
+
if(manager.deviceMotionActive && hardwareInterval!=interval) {
|
|
54
|
+
hardwareInterval=interval; manager.deviceMotionUpdateInterval=interval/1000;
|
|
55
|
+
}
|
|
56
|
+
if(!manager.deviceMotionActive) {
|
|
57
|
+
for(JoltSensorSource *s in sources) if(s.enabled && !s.trace) s.rebase=YES;
|
|
58
|
+
hardwareInterval=interval;
|
|
59
|
+
manager.deviceMotionUpdateInterval=interval/1000;
|
|
60
|
+
[manager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXArbitraryZVertical toQueue:NSOperationQueue.mainQueue withHandler:^(CMDeviceMotion *motion,NSError *error){
|
|
61
|
+
if(suspended) return;
|
|
62
|
+
if(error) {
|
|
63
|
+
for(JoltSensorSource *s in [sources copy]) if(s.enabled && !s.trace) { s.error=error.localizedDescription ?: @"motion-access-failed"; [s state:@"error"]; }
|
|
64
|
+
[self refresh]; return;
|
|
65
|
+
}
|
|
66
|
+
if(!motion) return;
|
|
67
|
+
CMQuaternion q=motion.attitude.quaternion;
|
|
68
|
+
// Core Motion reports reference-to-device attitude; canonical inputs are device-to-reference.
|
|
69
|
+
double rotation[]={-q.x,-q.y,-q.z,q.w};
|
|
70
|
+
double gravity[]={motion.gravity.x*9.80665,motion.gravity.y*9.80665,motion.gravity.z*9.80665};
|
|
71
|
+
for(JoltSensorSource *s in [sources copy]) if(s.enabled && !s.trace && !s.error)
|
|
72
|
+
[s receive:s.rotation ? rotation : gravity timestamp:motion.timestamp*1000];
|
|
73
|
+
}];
|
|
74
|
+
}
|
|
75
|
+
} else { [manager stopDeviceMotionUpdates]; hardwareInterval=0; }
|
|
76
|
+
if(ticking && !sensorDisplayLink) {
|
|
77
|
+
sensorDisplayLink=[CADisplayLink displayLinkWithTarget:self selector:@selector(tick:)];
|
|
78
|
+
[sensorDisplayLink addToRunLoop:NSRunLoop.mainRunLoop forMode:NSRunLoopCommonModes];
|
|
79
|
+
} else if(!ticking && sensorDisplayLink) { [sensorDisplayLink invalidate]; sensorDisplayLink=nil; }
|
|
80
|
+
}
|
|
81
|
+
+ (void)tick:(CADisplayLink *)link {
|
|
82
|
+
for(JoltSensorSource *s in [sources copy]) if(s.enabled && !suspended) [s frame:link.timestamp*1000];
|
|
83
|
+
}
|
|
84
|
+
+ (NSUInteger)activeCount { return manager.deviceMotionActive ? 1 : 0; }
|
|
85
|
+
+ (NSUInteger)sourceCount { return sources.count; }
|
|
86
|
+
+ (instancetype)create:(NSString *)kind options:(NSString *)options onState:(void (^)(void))onState {
|
|
87
|
+
if(!manager) manager=[CMMotionManager new];
|
|
88
|
+
NSDictionary *config=[NSJSONSerialization JSONObjectWithData:[options dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];
|
|
89
|
+
JoltSensorSource *s=[self new];
|
|
90
|
+
s.rotation=[kind isEqual:@"rotation"]; s.interfaceCoordinates=[config[@"coordinates"] isEqual:@"interface"];
|
|
91
|
+
s.interval=[config[@"interval"] doubleValue];
|
|
92
|
+
if(s.interval==0) s.interval=1000.0/MAX(60,UIScreen.mainScreen.maximumFramesPerSecond);
|
|
93
|
+
s.interval=MAX(5,MIN(1000,s.interval)); s.timestamp=-1;
|
|
94
|
+
s.available=manager.deviceMotionAvailable; s.nodes=[NSMutableArray new];
|
|
95
|
+
for(int i=0;i<(s.rotation?7:3);i++) [s.nodes addObject:NSNull.null];
|
|
96
|
+
s->reference[3]=s->relative[3]=s->output[6]=1; s.rebase=YES;
|
|
97
|
+
id usage=NSBundle.mainBundle.infoDictionary[@"NSMotionUsageDescription"];
|
|
98
|
+
if(s.available && (![usage isKindOfClass:NSString.class] || ![usage length])) s.configurationError=@"missing-motion-usage-description";
|
|
99
|
+
s.error=s.configurationError;
|
|
100
|
+
s.status=s.error?@"error":(s.available?@"idle":@"unavailable"); s.onState=onState;
|
|
101
|
+
[sources addObject:s]; return s;
|
|
102
|
+
}
|
|
103
|
+
- (void)connect:(JoltLiveSpring *)node index:(NSInteger)index { if(index>=0 && index<self.nodes.count) self.nodes[index]=node; }
|
|
104
|
+
- (void)state:(NSString *)state {
|
|
105
|
+
if([self.status isEqual:state]) return;
|
|
106
|
+
self.status=state;
|
|
107
|
+
if(self.onState) { self.callbacks++; self.onState(); }
|
|
108
|
+
}
|
|
109
|
+
- (void)setEnabled:(BOOL)enabled paused:(BOOL)paused {
|
|
110
|
+
if(self.disposed) return;
|
|
111
|
+
BOOL changed=self.enabled!=enabled; self.enabled=enabled;
|
|
112
|
+
if(changed) {
|
|
113
|
+
self.dirty=NO; self.committedAt=0; self.rebase=YES;
|
|
114
|
+
if(enabled) { self.receivedAt=CACurrentMediaTime()*1000; self.error=self.configurationError; self.replayStart=0; }
|
|
115
|
+
else if(self.trace && self.replayStart) {
|
|
116
|
+
self.replayElapsed=MAX(0,CACurrentMediaTime()*1000-self.replayStart); self.replayStart=0;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if(!enabled) [self state:paused?@"paused":(self.available?@"idle":@"unavailable")];
|
|
120
|
+
else if(changed) [self state:self.trace?@"replaying":(self.error?@"error":(self.available?@"starting":@"unavailable"))];
|
|
121
|
+
[JoltSensorSource refresh];
|
|
122
|
+
}
|
|
123
|
+
- (void)recenter { if(!self.disposed && self.rotation) { self.reset=YES; self.rebase=YES; } }
|
|
124
|
+
- (void)replay:(NSString *)trace {
|
|
125
|
+
if(self.disposed) return;
|
|
126
|
+
NSArray *frames=[NSJSONSerialization JSONObjectWithData:[trace dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];
|
|
127
|
+
if(![frames isKindOfClass:NSArray.class] || frames.count<2) return;
|
|
128
|
+
self.trace=frames; self.replayIndex=0; self.replayStart=0; self.replayElapsed=0; self.error=nil;
|
|
129
|
+
self.reset=YES; self.rebase=YES; self.dirty=NO; self.committedAt=0;
|
|
130
|
+
if(self.enabled) [self state:@"replaying"];
|
|
131
|
+
[JoltSensorSource refresh];
|
|
132
|
+
}
|
|
133
|
+
- (void)receive:(const double *)values timestamp:(double)timestamp {
|
|
134
|
+
if(!isfinite(timestamp) || timestamp<0) return;
|
|
135
|
+
if(!self.trace && self.timestamp>=0 && timestamp<=self.pendingTimestamp) return;
|
|
136
|
+
int count=self.rotation?4:3;
|
|
137
|
+
for(int i=0;i<count;i++) if(!isfinite(values[i])) return;
|
|
138
|
+
double input[4]={0}; memcpy(input,values,count*sizeof(double));
|
|
139
|
+
if(self.rotation && !JoltSensorNormalize(input)) return;
|
|
140
|
+
memcpy(pending,input,sizeof(input)); self.pendingTimestamp=timestamp; self.samples++; self.dirty=YES;
|
|
141
|
+
self.receivedAt=CACurrentMediaTime()*1000;
|
|
142
|
+
}
|
|
143
|
+
- (double)orientation {
|
|
144
|
+
if(!self.interfaceCoordinates) return 0;
|
|
145
|
+
if(self.trace) return self.replayOrientation;
|
|
146
|
+
for(UIScene *scene in UIApplication.sharedApplication.connectedScenes) if([scene isKindOfClass:UIWindowScene.class] && scene.activationState==UISceneActivationStateForegroundActive) {
|
|
147
|
+
switch(((UIWindowScene *)scene).interfaceOrientation) {
|
|
148
|
+
case UIInterfaceOrientationLandscapeLeft:return 90;
|
|
149
|
+
case UIInterfaceOrientationLandscapeRight:return 270;
|
|
150
|
+
case UIInterfaceOrientationPortraitUpsideDown:return 180;
|
|
151
|
+
default:return 0;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return 0;
|
|
155
|
+
}
|
|
156
|
+
- (void)frame:(double)now {
|
|
157
|
+
if(self.disposed || self.error) return;
|
|
158
|
+
if(self.trace) {
|
|
159
|
+
if(!self.replayStart) self.replayStart=now-self.replayElapsed;
|
|
160
|
+
double elapsed=now-self.replayStart;
|
|
161
|
+
while(self.replayIndex<self.trace.count && [self.trace[self.replayIndex][@"time"] doubleValue]<=elapsed) {
|
|
162
|
+
NSDictionary *sample=self.trace[self.replayIndex++]; NSArray *values=sample[@"values"];
|
|
163
|
+
if(values.count!=(self.rotation?4:3)) continue;
|
|
164
|
+
double input[4]={0}; for(int i=0;i<values.count;i++) input[i]=[values[i] doubleValue];
|
|
165
|
+
self.replayOrientation=[sample[@"orientation"] doubleValue];
|
|
166
|
+
[self receive:input timestamp:[sample[@"time"] doubleValue]];
|
|
167
|
+
}
|
|
168
|
+
} else if(self.available && now-self.receivedAt>MAX(3000,self.interval*3)) {
|
|
169
|
+
self.error=@"no-data"; [self state:@"error"]; [JoltSensorSource refresh]; return;
|
|
170
|
+
}
|
|
171
|
+
if(self.dirty && (!self.committedAt || now-self.committedAt>=self.interval-0.5)) {
|
|
172
|
+
double start=CACurrentMediaTime();
|
|
173
|
+
if(self.rotation) {
|
|
174
|
+
if(self.rebase) {
|
|
175
|
+
if(self.reset) { memset(relative,0,sizeof(relative)); relative[3]=1; }
|
|
176
|
+
double inverse[4]; JoltSensorInverse(relative,inverse); JoltSensorMultiply(pending,inverse,reference);
|
|
177
|
+
self.rebase=NO; self.reset=NO;
|
|
178
|
+
}
|
|
179
|
+
double inverse[4]; JoltSensorInverse(reference,inverse); JoltSensorMultiply(inverse,pending,relative);
|
|
180
|
+
JoltSensorRotation(relative,[self orientation],output+3,output);
|
|
181
|
+
} else JoltSensorVector(pending,[self orientation],output);
|
|
182
|
+
for(int i=0;i<self.nodes.count;i++) if(self.nodes[i]!=NSNull.null) [self.nodes[i] setSensorInput:output[i]];
|
|
183
|
+
self.dirty=NO; self.timestamp=self.pendingTimestamp; self.frames++; self.committedAt=now;
|
|
184
|
+
self.processingMs+=(CACurrentMediaTime()-start)*1000;
|
|
185
|
+
if(!self.trace) [self state:@"active"];
|
|
186
|
+
}
|
|
187
|
+
if(self.trace && self.replayIndex>=self.trace.count && !self.dirty) {
|
|
188
|
+
self.trace=nil; self.replayStart=0; self.replayElapsed=0; self.rebase=YES; self.receivedAt=now; self.error=self.configurationError;
|
|
189
|
+
[self state:self.error?@"error":self.available?@"starting":@"unavailable"]; [JoltSensorSource refresh];
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
- (NSString *)snapshot {
|
|
193
|
+
NSMutableArray *values=[NSMutableArray new];for(int i=0;i<(self.rotation?7:3);i++)[values addObject:@(output[i])];
|
|
194
|
+
NSDictionary *snapshot=@{@"status":self.status,@"available":@(self.available),@"error":self.error?:NSNull.null,@"timestamp":self.timestamp<0?NSNull.null:@(self.timestamp),@"samples":@(self.samples),@"frames":@(self.frames),@"callbacks":@(self.callbacks),@"processingMs":@(self.processingMs),@"interval":@(self.interval),@"values":values};
|
|
195
|
+
return [[NSString alloc]initWithData:[NSJSONSerialization dataWithJSONObject:snapshot options:0 error:nil] encoding:NSUTF8StringEncoding];
|
|
196
|
+
}
|
|
197
|
+
- (void)dispose {
|
|
198
|
+
if(self.disposed)return; self.disposed=YES;self.enabled=NO;self.status=@"disposed";self.onState=nil;
|
|
199
|
+
self.trace=nil;[self.nodes removeAllObjects];[sources removeObject:self];[JoltSensorSource refresh];
|
|
200
|
+
}
|
|
201
|
+
@end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#import <UIKit/UIKit.h>
|
|
2
|
+
@interface JoltSharedLayoutFlight : UIView
|
|
3
|
+
+ (instancetype)capture:(UIView *)view image:(BOOL)image radius:(double)radius maxPixels:(double)maxPixels;
|
|
4
|
+
+ (instancetype)captureNavigationImage:(UIView *)view radius:(double)radius maxPixels:(double)maxPixels;
|
|
5
|
+
- (NSString *)prepareNavigationImage:(UIView *)view radius:(double)radius maxPixels:(double)maxPixels;
|
|
6
|
+
+ (instancetype)captureClippedNavigationImage:(UIView *)view radius:(double)radius maxPixels:(double)maxPixels;
|
|
7
|
+
+ (NSInteger)activeCount;
|
|
8
|
+
- (BOOL)holdPage:(UIView *)page maxPixels:(double)maxPixels;
|
|
9
|
+
- (void)fade:(double)duration onEnd:(void (^)(BOOL))onEnd;
|
|
10
|
+
- (double)pixels;
|
|
11
|
+
- (NSString *)state;
|
|
12
|
+
- (NSString *)prepare:(UIView *)view image:(BOOL)image radius:(double)radius maxPixels:(double)maxPixels;
|
|
13
|
+
- (BOOL)freeze:(double)maxPixels;
|
|
14
|
+
- (void)play:(NSString *)configuration onEnd:(void (^)(BOOL))onEnd;
|
|
15
|
+
- (BOOL)beginInteractive:(NSString *)geometry;
|
|
16
|
+
- (void)updateInteractive:(double)progress;
|
|
17
|
+
- (BOOL)destinationIsStable;
|
|
18
|
+
- (void)dispose;
|
|
19
|
+
@end
|