@rafaelaugusto/jolt 0.1.0-beta.1 → 0.1.0-beta.11
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 +385 -18
- package/dist/animate.d.ts +19 -3
- package/dist/animate.d.ts.map +1 -1
- package/dist/animate.js +186 -14
- package/dist/animate.js.map +1 -1
- package/dist/color.d.ts +11 -0
- package/dist/color.d.ts.map +1 -0
- package/dist/color.js +73 -0
- package/dist/color.js.map +1 -0
- package/dist/config.d.ts +31 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +73 -0
- package/dist/config.js.map +1 -0
- package/dist/decay.d.ts +11 -0
- package/dist/decay.d.ts.map +1 -0
- package/dist/decay.js +22 -0
- package/dist/decay.js.map +1 -0
- package/dist/decoration.d.ts +18 -0
- package/dist/decoration.d.ts.map +1 -0
- package/dist/decoration.js +155 -0
- package/dist/decoration.js.map +1 -0
- package/dist/drag-input.d.ts +15 -0
- package/dist/drag-input.d.ts.map +1 -0
- package/dist/drag-input.js +66 -0
- package/dist/drag-input.js.map +1 -0
- package/dist/drag-physics.d.ts +20 -0
- package/dist/drag-physics.d.ts.map +1 -0
- package/dist/drag-physics.js +75 -0
- package/dist/drag-physics.js.map +1 -0
- package/dist/drag.d.ts +58 -0
- package/dist/drag.d.ts.map +1 -0
- package/dist/drag.js +324 -0
- package/dist/drag.js.map +1 -0
- package/dist/driver/android-color.d.ts +20 -0
- package/dist/driver/android-color.d.ts.map +1 -0
- package/dist/driver/android-color.js +136 -0
- package/dist/driver/android-color.js.map +1 -0
- package/dist/driver/android-decoration.d.ts +22 -0
- package/dist/driver/android-decoration.d.ts.map +1 -0
- package/dist/driver/android-decoration.js +139 -0
- package/dist/driver/android-decoration.js.map +1 -0
- 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 +89 -0
- package/dist/driver/android-gradient.js.map +1 -0
- package/dist/driver/android-playback.d.ts +13 -0
- package/dist/driver/android-playback.d.ts.map +1 -0
- package/dist/driver/android-playback.js +141 -0
- package/dist/driver/android-playback.js.map +1 -0
- package/dist/driver/android.d.ts +1 -1
- package/dist/driver/android.d.ts.map +1 -1
- package/dist/driver/android.js +165 -13
- package/dist/driver/android.js.map +1 -1
- package/dist/driver/index.d.ts +25 -2
- package/dist/driver/index.d.ts.map +1 -1
- package/dist/driver/index.js.map +1 -1
- package/dist/driver/ios-color.d.ts +16 -0
- package/dist/driver/ios-color.d.ts.map +1 -0
- package/dist/driver/ios-color.js +392 -0
- package/dist/driver/ios-color.js.map +1 -0
- package/dist/driver/ios-decoration.d.ts +17 -0
- package/dist/driver/ios-decoration.d.ts.map +1 -0
- package/dist/driver/ios-decoration.js +271 -0
- package/dist/driver/ios-decoration.js.map +1 -0
- 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 +109 -0
- package/dist/driver/ios-gradient.js.map +1 -0
- package/dist/driver/ios-layout.d.ts +9 -0
- package/dist/driver/ios-layout.d.ts.map +1 -0
- package/dist/driver/ios-layout.js +52 -0
- package/dist/driver/ios-layout.js.map +1 -0
- package/dist/driver/ios-playback.d.ts +10 -0
- package/dist/driver/ios-playback.d.ts.map +1 -0
- package/dist/driver/ios-playback.js +47 -0
- package/dist/driver/ios-playback.js.map +1 -0
- package/dist/driver/ios-shadow.d.ts +6 -0
- package/dist/driver/ios-shadow.d.ts.map +1 -0
- package/dist/driver/ios-shadow.js +52 -0
- package/dist/driver/ios-shadow.js.map +1 -0
- package/dist/driver/ios.d.ts.map +1 -1
- package/dist/driver/ios.js +163 -28
- package/dist/driver/ios.js.map +1 -1
- package/dist/engine.d.ts +75 -5
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +293 -23
- package/dist/engine.js.map +1 -1
- package/dist/gradient.d.ts +90 -0
- package/dist/gradient.d.ts.map +1 -0
- package/dist/gradient.js +247 -0
- package/dist/gradient.js.map +1 -0
- package/dist/haptics.d.ts +21 -0
- package/dist/haptics.d.ts.map +1 -0
- package/dist/haptics.js +120 -0
- package/dist/haptics.js.map +1 -0
- package/dist/image-effect-native.d.ts +26 -0
- package/dist/image-effect-native.d.ts.map +1 -0
- package/dist/image-effect-native.js +73 -0
- package/dist/image-effect-native.js.map +1 -0
- package/dist/image-effect.d.ts +50 -0
- package/dist/image-effect.d.ts.map +1 -0
- package/dist/image-effect.js +290 -0
- package/dist/image-effect.js.map +1 -0
- package/dist/image-owner.d.ts +3 -0
- package/dist/image-owner.d.ts.map +1 -0
- package/dist/image-owner.js +11 -0
- package/dist/image-owner.js.map +1 -0
- package/dist/index.d.ts +47 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -2
- package/dist/index.js.map +1 -1
- package/dist/interaction-surface.d.ts +12 -0
- package/dist/interaction-surface.d.ts.map +1 -0
- package/dist/interaction-surface.js +36 -0
- package/dist/interaction-surface.js.map +1 -0
- package/dist/items.d.ts +20 -0
- package/dist/items.d.ts.map +1 -0
- package/dist/items.js +109 -0
- package/dist/items.js.map +1 -0
- package/dist/keyboard.d.ts +41 -0
- package/dist/keyboard.d.ts.map +1 -0
- package/dist/keyboard.js +256 -0
- package/dist/keyboard.js.map +1 -0
- package/dist/label.d.ts +7 -0
- package/dist/label.d.ts.map +1 -0
- package/dist/label.js +60 -0
- package/dist/label.js.map +1 -0
- package/dist/layout.d.ts +13 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/layout.js +348 -0
- package/dist/layout.js.map +1 -0
- package/dist/liquid-grid.d.ts +3 -0
- package/dist/liquid-grid.d.ts.map +1 -0
- package/dist/liquid-grid.js +24 -0
- package/dist/liquid-grid.js.map +1 -0
- package/dist/liquid.d.ts +18 -0
- package/dist/liquid.d.ts.map +1 -0
- package/dist/liquid.js +234 -0
- package/dist/liquid.js.map +1 -0
- package/dist/loader.d.ts +19 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +173 -0
- package/dist/loader.js.map +1 -0
- package/dist/motion-scope.d.ts +39 -0
- package/dist/motion-scope.d.ts.map +1 -0
- package/dist/motion-scope.js +238 -0
- package/dist/motion-scope.js.map +1 -0
- package/dist/motion-states.d.ts +43 -0
- package/dist/motion-states.d.ts.map +1 -0
- package/dist/motion-states.js +220 -0
- package/dist/motion-states.js.map +1 -0
- package/dist/particles.d.ts +39 -0
- package/dist/particles.d.ts.map +1 -0
- package/dist/particles.js +265 -0
- package/dist/particles.js.map +1 -0
- package/dist/path.d.ts +12 -0
- package/dist/path.d.ts.map +1 -0
- package/dist/path.js +90 -0
- package/dist/path.js.map +1 -0
- package/dist/playback-group.d.ts +6 -0
- package/dist/playback-group.d.ts.map +1 -0
- package/dist/playback-group.js +141 -0
- package/dist/playback-group.js.map +1 -0
- package/dist/playback.d.ts +25 -0
- package/dist/playback.d.ts.map +1 -0
- package/dist/playback.js +35 -0
- package/dist/playback.js.map +1 -0
- package/dist/press.d.ts.map +1 -1
- package/dist/press.js +23 -7
- package/dist/press.js.map +1 -1
- package/dist/properties.d.ts +6 -3
- package/dist/properties.d.ts.map +1 -1
- package/dist/properties.js +26 -2
- package/dist/properties.js.map +1 -1
- package/dist/reveal.d.ts +25 -0
- package/dist/reveal.d.ts.map +1 -0
- package/dist/reveal.js +294 -0
- package/dist/reveal.js.map +1 -0
- package/dist/roll-diff.d.ts +22 -0
- package/dist/roll-diff.d.ts.map +1 -0
- package/dist/roll-diff.js +36 -0
- package/dist/roll-diff.js.map +1 -0
- package/dist/roll.d.ts +29 -0
- package/dist/roll.d.ts.map +1 -0
- package/dist/roll.js +442 -0
- package/dist/roll.js.map +1 -0
- package/dist/scroll-linked.d.ts +10 -0
- package/dist/scroll-linked.d.ts.map +1 -0
- package/dist/scroll-linked.js +58 -0
- package/dist/scroll-linked.js.map +1 -0
- package/dist/sequence.d.ts +10 -5
- package/dist/sequence.d.ts.map +1 -1
- package/dist/sequence.js +208 -14
- package/dist/sequence.js.map +1 -1
- package/dist/shimmer.d.ts +12 -0
- package/dist/shimmer.d.ts.map +1 -0
- package/dist/shimmer.js +161 -0
- package/dist/shimmer.js.map +1 -0
- package/dist/svg-path.d.ts +14 -0
- package/dist/svg-path.d.ts.map +1 -0
- package/dist/svg-path.js +281 -0
- package/dist/svg-path.js.map +1 -0
- package/dist/symbol-effect.d.ts +23 -0
- package/dist/symbol-effect.d.ts.map +1 -0
- package/dist/symbol-effect.js +187 -0
- package/dist/symbol-effect.js.map +1 -0
- package/dist/text-layout.d.ts +30 -0
- package/dist/text-layout.d.ts.map +1 -0
- package/dist/text-layout.js +185 -0
- package/dist/text-layout.js.map +1 -0
- package/dist/text.d.ts +17 -0
- package/dist/text.d.ts.map +1 -0
- package/dist/text.js +263 -0
- package/dist/text.js.map +1 -0
- package/dist/track.d.ts +3 -1
- package/dist/track.d.ts.map +1 -1
- package/dist/track.js +266 -13
- package/dist/track.js.map +1 -1
- package/dist/transition.d.ts +32 -1
- package/dist/transition.d.ts.map +1 -1
- package/dist/transition.js +58 -6
- package/dist/transition.js.map +1 -1
- package/dist/types.d.ts +48 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/vue/index.d.ts +95 -0
- package/dist/vue/index.d.ts.map +1 -0
- package/dist/vue/index.js +163 -0
- package/dist/vue/index.js.map +1 -0
- package/dist/zoom-native.d.ts +30 -0
- package/dist/zoom-native.d.ts.map +1 -0
- package/dist/zoom-native.js +56 -0
- package/dist/zoom-native.js.map +1 -0
- package/dist/zoomable.d.ts +48 -0
- package/dist/zoomable.d.ts.map +1 -0
- package/dist/zoomable.js +249 -0
- package/dist/zoomable.js.map +1 -0
- package/package.json +29 -5
- package/platforms/android/include.gradle +7 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/ColorTarget.java +102 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/DecorationTarget.java +154 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/GradientLayer.java +195 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/ImageEffect.java +288 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/KeyboardFollower.java +91 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/KeyboardObserver.java +97 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/NumberRoll.java +190 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/PhotoZoom.java +250 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/TextReveal.java +180 -0
- package/platforms/android/proguard-rules.pro +21 -0
- package/platforms/ios/build.xcconfig +1 -0
- package/platforms/ios/src/JoltImageEffect.h +25 -0
- package/platforms/ios/src/JoltImageEffect.mm +242 -0
- package/platforms/ios/src/JoltInteractiveAnimation.h +18 -0
- package/platforms/ios/src/JoltInteractiveAnimation.m +123 -0
- package/platforms/ios/src/JoltPhotoZoom.h +23 -0
- package/platforms/ios/src/JoltPhotoZoom.m +229 -0
- package/platforms/ios/src/module.modulemap +6 -0
- package/src/android-plugin.d.ts +184 -0
- package/src/animate.ts +249 -36
- package/src/color.ts +101 -0
- package/src/config.ts +84 -0
- package/src/decay.ts +45 -0
- package/src/decoration.ts +180 -0
- package/src/drag-input.ts +74 -0
- package/src/drag-physics.ts +110 -0
- package/src/drag.ts +395 -0
- package/src/driver/android-color.ts +170 -0
- package/src/driver/android-decoration.ts +182 -0
- package/src/driver/android-gradient.ts +109 -0
- package/src/driver/android-playback.ts +157 -0
- package/src/driver/android.ts +208 -20
- package/src/driver/index.ts +37 -2
- package/src/driver/ios-color.ts +441 -0
- package/src/driver/ios-decoration.ts +332 -0
- package/src/driver/ios-gradient.ts +114 -0
- package/src/driver/ios-layout.ts +63 -0
- package/src/driver/ios-playback.ts +51 -0
- package/src/driver/ios-shadow.ts +50 -0
- package/src/driver/ios.ts +193 -33
- package/src/engine.ts +321 -27
- package/src/gradient.ts +372 -0
- package/src/haptics.ts +148 -0
- package/src/image-effect-native.ts +129 -0
- package/src/image-effect.ts +336 -0
- package/src/image-owner.ts +12 -0
- package/src/index.ts +75 -4
- package/src/interaction-surface.ts +41 -0
- package/src/ios-plugin.d.ts +81 -0
- package/src/items.ts +140 -0
- package/src/keyboard.ts +291 -0
- package/src/label.ts +76 -0
- package/src/layout.ts +408 -0
- package/src/liquid-grid.ts +28 -0
- package/src/liquid.ts +287 -0
- package/src/loader.ts +202 -0
- package/src/motion-scope.ts +279 -0
- package/src/motion-states.ts +269 -0
- package/src/particles.ts +323 -0
- package/src/path.ts +124 -0
- package/src/playback-group.ts +143 -0
- package/src/playback.ts +62 -0
- package/src/press.ts +26 -10
- package/src/properties.ts +32 -6
- package/src/reveal.ts +374 -0
- package/src/roll-diff.ts +57 -0
- package/src/roll.ts +515 -0
- package/src/scroll-linked.ts +73 -0
- package/src/sequence.ts +204 -14
- package/src/shimmer.ts +180 -0
- package/src/svg-path.ts +355 -0
- package/src/symbol-effect.ts +226 -0
- package/src/text-layout.ts +228 -0
- package/src/text.ts +279 -0
- package/src/track.ts +347 -12
- package/src/transition.ts +93 -6
- package/src/types.ts +49 -1
- package/src/vue/index.ts +231 -0
- package/src/zoom-native.ts +124 -0
- package/src/zoomable.ts +330 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { Utils, type View } from '@nativescript/core'
|
|
2
|
+
import {
|
|
3
|
+
isWritingDecoration,
|
|
4
|
+
radiusKeys,
|
|
5
|
+
widthKeys,
|
|
6
|
+
validateDecorationTarget,
|
|
7
|
+
type DecorationProperty,
|
|
8
|
+
} from '../decoration.js'
|
|
9
|
+
import { androidPlayback, type AndroidPlayback } from './android-playback.js'
|
|
10
|
+
import type { PlaybackCommand } from '../playback.js'
|
|
11
|
+
import type { Track } from '../track.js'
|
|
12
|
+
interface NativeTarget {
|
|
13
|
+
getValue(): number
|
|
14
|
+
setValue(value: number): void
|
|
15
|
+
isSupported(): boolean
|
|
16
|
+
acquire(): void
|
|
17
|
+
release(): void
|
|
18
|
+
}
|
|
19
|
+
interface Handle {
|
|
20
|
+
control(elapsed: number, paused: boolean, command?: PlaybackCommand): void
|
|
21
|
+
cancel(): void
|
|
22
|
+
elapsed(): number
|
|
23
|
+
target: NativeTarget
|
|
24
|
+
}
|
|
25
|
+
const playing = new WeakMap<View, Map<DecorationProperty, Handle>>()
|
|
26
|
+
const ids = { borderRadius: 0, borderWidth: 1, elevation: 2, translationZ: 3 } as const
|
|
27
|
+
export function syncAndroidDecoration(view: View) {
|
|
28
|
+
for (const handle of playing.get(view)?.values() ?? [])
|
|
29
|
+
handle.target.setValue(handle.target.getValue())
|
|
30
|
+
}
|
|
31
|
+
export const presentedAndroidDecoration = (view: View, property: DecorationProperty) => {
|
|
32
|
+
const target = playing.get(view)?.get(property)?.target
|
|
33
|
+
return target ? target.getValue() / Utils.layout.getDisplayDensity() : undefined
|
|
34
|
+
}
|
|
35
|
+
export function playAndroidDecoration(
|
|
36
|
+
view: View,
|
|
37
|
+
track: Track,
|
|
38
|
+
onEnd: (finished?: boolean) => void,
|
|
39
|
+
): Handle {
|
|
40
|
+
const property = track.property as keyof typeof ids
|
|
41
|
+
const density = Utils.layout.getDisplayDensity()
|
|
42
|
+
const bridge = globalThis as unknown as {
|
|
43
|
+
org: {
|
|
44
|
+
rafaelaugusto: {
|
|
45
|
+
jolt: {
|
|
46
|
+
DecorationTarget: new (
|
|
47
|
+
view: android.view.View,
|
|
48
|
+
property: number,
|
|
49
|
+
value: number,
|
|
50
|
+
borderColor: number,
|
|
51
|
+
) => NativeTarget
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
let target: NativeTarget
|
|
57
|
+
try {
|
|
58
|
+
target = new bridge.org.rafaelaugusto.jolt.DecorationTarget(
|
|
59
|
+
view.nativeViewProtected,
|
|
60
|
+
ids[property],
|
|
61
|
+
track.values[0]! * density,
|
|
62
|
+
view.borderTopColor?.argb ?? 0,
|
|
63
|
+
)
|
|
64
|
+
} catch {
|
|
65
|
+
onEnd(false)
|
|
66
|
+
return {
|
|
67
|
+
cancel() {},
|
|
68
|
+
control() {},
|
|
69
|
+
elapsed: () => 0,
|
|
70
|
+
target: {
|
|
71
|
+
getValue: () => track.to * density,
|
|
72
|
+
setValue() {},
|
|
73
|
+
isSupported: () => false,
|
|
74
|
+
acquire() {},
|
|
75
|
+
release() {},
|
|
76
|
+
},
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const frames = Array.create(android.animation.Keyframe, track.values.length)
|
|
80
|
+
track.values.forEach((value, index) => {
|
|
81
|
+
frames[index] = android.animation.Keyframe.ofFloat(
|
|
82
|
+
track.times[index]!,
|
|
83
|
+
value * density,
|
|
84
|
+
)
|
|
85
|
+
})
|
|
86
|
+
const holders = Array.create(android.animation.PropertyValuesHolder, 1)
|
|
87
|
+
holders[0] = android.animation.PropertyValuesHolder.ofKeyframe('value', frames)
|
|
88
|
+
const animator = android.animation.ObjectAnimator.ofPropertyValuesHolder(
|
|
89
|
+
target as unknown as java.lang.Object,
|
|
90
|
+
holders,
|
|
91
|
+
)
|
|
92
|
+
animator.setDuration(Math.max(track.duration, 1))
|
|
93
|
+
animator.setStartDelay(track.delay)
|
|
94
|
+
animator.setInterpolator(new android.view.animation.LinearInterpolator())
|
|
95
|
+
if (track.repeat > 0) {
|
|
96
|
+
animator.setRepeatCount(
|
|
97
|
+
Number.isFinite(track.repeat)
|
|
98
|
+
? track.repeat
|
|
99
|
+
: android.animation.ValueAnimator.INFINITE,
|
|
100
|
+
)
|
|
101
|
+
animator.setRepeatMode(
|
|
102
|
+
track.reverse
|
|
103
|
+
? android.animation.ValueAnimator.REVERSE
|
|
104
|
+
: android.animation.ValueAnimator.RESTART,
|
|
105
|
+
)
|
|
106
|
+
}
|
|
107
|
+
let stopped = false
|
|
108
|
+
const changes = [
|
|
109
|
+
...radiusKeys,
|
|
110
|
+
...widthKeys,
|
|
111
|
+
'clipPath',
|
|
112
|
+
'cornerShape',
|
|
113
|
+
'boxShadow',
|
|
114
|
+
'androidElevation',
|
|
115
|
+
].map((name) => `${name}Change`)
|
|
116
|
+
const cleanup = () => {
|
|
117
|
+
if (stopped) return
|
|
118
|
+
stopped = true
|
|
119
|
+
view.off('unloaded', cancel)
|
|
120
|
+
for (const event of changes) view.style.off(event, external)
|
|
121
|
+
target.release()
|
|
122
|
+
if (playing.get(view)?.get(property) === handle) playing.get(view)?.delete(property)
|
|
123
|
+
}
|
|
124
|
+
let player: AndroidPlayback | undefined
|
|
125
|
+
const cancel = () => {
|
|
126
|
+
if (!stopped) {
|
|
127
|
+
cleanup()
|
|
128
|
+
player?.cancel()
|
|
129
|
+
onEnd(false)
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
const external = (event: { eventName: string }) => {
|
|
133
|
+
if (isWritingDecoration(view)) return
|
|
134
|
+
const own =
|
|
135
|
+
property === 'borderRadius'
|
|
136
|
+
? radiusKeys
|
|
137
|
+
: property === 'borderWidth'
|
|
138
|
+
? widthKeys
|
|
139
|
+
: property === 'elevation'
|
|
140
|
+
? ['androidElevation']
|
|
141
|
+
: []
|
|
142
|
+
void Promise.resolve().then(() => {
|
|
143
|
+
if (stopped) return
|
|
144
|
+
if (own.some((name) => event.eventName === `${name}Change`)) return cancel()
|
|
145
|
+
try {
|
|
146
|
+
validateDecorationTarget(view, property)
|
|
147
|
+
} catch {
|
|
148
|
+
cancel()
|
|
149
|
+
}
|
|
150
|
+
})
|
|
151
|
+
}
|
|
152
|
+
const handle: Handle = {
|
|
153
|
+
target,
|
|
154
|
+
elapsed: () => player?.elapsed() ?? 0,
|
|
155
|
+
control(time, paused, command) {
|
|
156
|
+
player?.control(time, paused, command)
|
|
157
|
+
},
|
|
158
|
+
cancel() {
|
|
159
|
+
cleanup()
|
|
160
|
+
player?.cancel()
|
|
161
|
+
},
|
|
162
|
+
}
|
|
163
|
+
const entries = playing.get(view) ?? new Map<DecorationProperty, Handle>()
|
|
164
|
+
playing.set(view, entries)
|
|
165
|
+
entries.set(property, handle)
|
|
166
|
+
view.on('unloaded', cancel)
|
|
167
|
+
for (const event of changes) view.style.on(event, external)
|
|
168
|
+
if (target.isSupported()) {
|
|
169
|
+
target.acquire()
|
|
170
|
+
target.setValue(track.values[0]! * density)
|
|
171
|
+
player = androidPlayback(animator, track, () => {
|
|
172
|
+
if (!stopped) {
|
|
173
|
+
cleanup()
|
|
174
|
+
onEnd()
|
|
175
|
+
}
|
|
176
|
+
})
|
|
177
|
+
} else {
|
|
178
|
+
cleanup()
|
|
179
|
+
onEnd(false)
|
|
180
|
+
}
|
|
181
|
+
return handle
|
|
182
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { Utils, type View } from '@nativescript/core'
|
|
2
|
+
import type { GradientFrame, GradientPainter, GradientType } from '../gradient.js'
|
|
3
|
+
|
|
4
|
+
const floats = (values: readonly number[]) => {
|
|
5
|
+
const array = Array.create('float', values.length)
|
|
6
|
+
values.forEach((value, i) => (array[i] = value))
|
|
7
|
+
return array
|
|
8
|
+
}
|
|
9
|
+
const ints = (values: readonly number[]) => {
|
|
10
|
+
const array = Array.create('int', values.length)
|
|
11
|
+
values.forEach((value, i) => (array[i] = value | 0))
|
|
12
|
+
return array
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** A gradient drawable stacked on the view's own background: above its color, below its children. */
|
|
16
|
+
export function androidGradient(
|
|
17
|
+
view: View,
|
|
18
|
+
type: GradientType,
|
|
19
|
+
): GradientPainter | undefined {
|
|
20
|
+
let layer: org.rafaelaugusto.jolt.GradientLayer
|
|
21
|
+
try {
|
|
22
|
+
layer = new org.rafaelaugusto.jolt.GradientLayer(
|
|
23
|
+
type === 'linear' ? 0 : type === 'radial' ? 1 : 2,
|
|
24
|
+
)
|
|
25
|
+
} catch {
|
|
26
|
+
// A JS-only update cannot install the native plugin.
|
|
27
|
+
return undefined
|
|
28
|
+
}
|
|
29
|
+
let stack: android.graphics.drawable.LayerDrawable | undefined
|
|
30
|
+
let queued = false
|
|
31
|
+
|
|
32
|
+
const wrap = () => {
|
|
33
|
+
const native = view.nativeViewProtected as android.view.View | undefined
|
|
34
|
+
if (!native) return
|
|
35
|
+
const corner = typeof view.borderRadius === 'number' ? view.borderRadius : 0
|
|
36
|
+
layer.setCorner(corner * Utils.layout.getDisplayDensity())
|
|
37
|
+
const background = native.getBackground()
|
|
38
|
+
if (stack && background === stack) return
|
|
39
|
+
const layers = Array.create(android.graphics.drawable.Drawable, 2)
|
|
40
|
+
layers[0] = background ?? new android.graphics.drawable.ColorDrawable(0)
|
|
41
|
+
layers[1] = layer
|
|
42
|
+
stack = new android.graphics.drawable.LayerDrawable(layers)
|
|
43
|
+
native.setBackground(stack)
|
|
44
|
+
}
|
|
45
|
+
// Core replaces the background drawable when its style changes; stack on the new one.
|
|
46
|
+
const rewrap = () => {
|
|
47
|
+
if (queued) return
|
|
48
|
+
queued = true
|
|
49
|
+
void Promise.resolve().then(() => {
|
|
50
|
+
queued = false
|
|
51
|
+
wrap()
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
view.on('loaded', wrap)
|
|
55
|
+
view.style.on('backgroundInternalChange', rewrap)
|
|
56
|
+
view.style.on('borderTopLeftRadiusChange', rewrap)
|
|
57
|
+
wrap()
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
paint(frame: GradientFrame) {
|
|
61
|
+
layer.paint(
|
|
62
|
+
ints(frame.colors),
|
|
63
|
+
floats(frame.stops),
|
|
64
|
+
frame.angle,
|
|
65
|
+
frame.x,
|
|
66
|
+
frame.y,
|
|
67
|
+
frame.radius,
|
|
68
|
+
)
|
|
69
|
+
},
|
|
70
|
+
play(frames, times, timing, onEnd) {
|
|
71
|
+
let active = true
|
|
72
|
+
layer.play(
|
|
73
|
+
floats(times),
|
|
74
|
+
ints(frames.flatMap((frame) => frame.colors)),
|
|
75
|
+
floats(frames.flatMap((frame) => frame.stops)),
|
|
76
|
+
floats(frames.flatMap((frame) => [frame.angle, frame.x, frame.y, frame.radius])),
|
|
77
|
+
Math.round(timing.duration),
|
|
78
|
+
Math.round(timing.delay),
|
|
79
|
+
timing.repeat === Infinity ? -1 : timing.repeat,
|
|
80
|
+
timing.reverse,
|
|
81
|
+
new org.rafaelaugusto.jolt.GradientLayer.Listener({
|
|
82
|
+
onEnd: (finished: boolean) => {
|
|
83
|
+
if (!active) return
|
|
84
|
+
active = false
|
|
85
|
+
onEnd(finished)
|
|
86
|
+
},
|
|
87
|
+
}),
|
|
88
|
+
)
|
|
89
|
+
return {
|
|
90
|
+
cancel() {
|
|
91
|
+
if (!active) return
|
|
92
|
+
active = false
|
|
93
|
+
layer.cancel()
|
|
94
|
+
onEnd(false)
|
|
95
|
+
},
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
remove() {
|
|
99
|
+
view.off('loaded', wrap)
|
|
100
|
+
view.style.off('backgroundInternalChange', rewrap)
|
|
101
|
+
view.style.off('borderTopLeftRadiusChange', rewrap)
|
|
102
|
+
layer.cancel()
|
|
103
|
+
const native = view.nativeViewProtected as android.view.View | undefined
|
|
104
|
+
if (native && stack && native.getBackground() === stack)
|
|
105
|
+
native.setBackground(stack.getDrawable(0))
|
|
106
|
+
stack = undefined
|
|
107
|
+
},
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import type { Track } from '../track.js'
|
|
2
|
+
import type { PlaybackClock, PlaybackCommand } from '../playback.js'
|
|
3
|
+
|
|
4
|
+
export interface AndroidPlayback {
|
|
5
|
+
cancel(): void
|
|
6
|
+
elapsed(): number
|
|
7
|
+
control(elapsed: number, paused: boolean, command?: PlaybackCommand): void
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/** Reuse native keyframes when seeking, including rewinding into a start delay. */
|
|
11
|
+
export function androidPlayback(
|
|
12
|
+
animator: android.animation.ValueAnimator,
|
|
13
|
+
track: Track,
|
|
14
|
+
onEnd: () => void,
|
|
15
|
+
onStart?: () => void,
|
|
16
|
+
onRelease?: () => void,
|
|
17
|
+
): AndroidPlayback {
|
|
18
|
+
let suppressed = false
|
|
19
|
+
let stopped = false
|
|
20
|
+
let started = false
|
|
21
|
+
let acquired = false
|
|
22
|
+
let origin = 0
|
|
23
|
+
let delay = track.delay
|
|
24
|
+
let held: number | undefined
|
|
25
|
+
animator.addListener(
|
|
26
|
+
new android.animation.Animator.AnimatorListener({
|
|
27
|
+
onAnimationStart() {
|
|
28
|
+
if (!suppressed && !stopped) {
|
|
29
|
+
started = true
|
|
30
|
+
if (!acquired) {
|
|
31
|
+
acquired = true
|
|
32
|
+
onStart?.()
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
onAnimationRepeat() {},
|
|
37
|
+
onAnimationCancel() {
|
|
38
|
+
if (!suppressed && !stopped) onRelease?.()
|
|
39
|
+
},
|
|
40
|
+
onAnimationEnd() {
|
|
41
|
+
if (suppressed || stopped || held !== undefined) return
|
|
42
|
+
stopped = true
|
|
43
|
+
onRelease?.()
|
|
44
|
+
onEnd()
|
|
45
|
+
},
|
|
46
|
+
}),
|
|
47
|
+
)
|
|
48
|
+
const elapsed = () =>
|
|
49
|
+
held ?? (started ? origin + delay + animator.getCurrentPlayTime() : origin)
|
|
50
|
+
const control = (
|
|
51
|
+
position: number,
|
|
52
|
+
paused: boolean,
|
|
53
|
+
command: PlaybackCommand = 'seek',
|
|
54
|
+
) => {
|
|
55
|
+
if (stopped) return
|
|
56
|
+
if (command === 'pause') {
|
|
57
|
+
held = position
|
|
58
|
+
animator.pause()
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
if (command === 'play') {
|
|
62
|
+
held = undefined
|
|
63
|
+
animator.resume()
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
suppressed = true
|
|
67
|
+
animator.cancel()
|
|
68
|
+
started = false
|
|
69
|
+
origin = Math.min(position, track.delay)
|
|
70
|
+
delay = Math.max(0, track.delay - position)
|
|
71
|
+
animator.setStartDelay(delay)
|
|
72
|
+
held = paused ? position : undefined
|
|
73
|
+
suppressed = false
|
|
74
|
+
animator.start()
|
|
75
|
+
if (paused) animator.pause()
|
|
76
|
+
if (position >= track.delay)
|
|
77
|
+
animator.setCurrentPlayTime(Math.max(0, position - track.delay))
|
|
78
|
+
}
|
|
79
|
+
animator.start()
|
|
80
|
+
return {
|
|
81
|
+
elapsed,
|
|
82
|
+
control,
|
|
83
|
+
cancel() {
|
|
84
|
+
if (stopped) return
|
|
85
|
+
stopped = true
|
|
86
|
+
onRelease?.()
|
|
87
|
+
animator.cancel()
|
|
88
|
+
},
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Share one native clock among active animations. Pause it when every owner
|
|
93
|
+
* is paused, and dispose it when the last owner settles. No frame callbacks. */
|
|
94
|
+
export function androidClockFactory() {
|
|
95
|
+
let animator: android.animation.ValueAnimator | undefined
|
|
96
|
+
let owners = 0,
|
|
97
|
+
running = 0,
|
|
98
|
+
accumulated = 0
|
|
99
|
+
const now = () => accumulated + (animator?.getCurrentPlayTime() ?? 0)
|
|
100
|
+
const start = () => {
|
|
101
|
+
if (animator) return
|
|
102
|
+
const values = Array.create('float', 2)
|
|
103
|
+
values[0] = 0
|
|
104
|
+
values[1] = 1
|
|
105
|
+
animator = android.animation.ValueAnimator.ofFloat(values)
|
|
106
|
+
animator.setDuration(60_000)
|
|
107
|
+
animator.setRepeatCount(android.animation.ValueAnimator.INFINITE)
|
|
108
|
+
animator.start()
|
|
109
|
+
}
|
|
110
|
+
const stop = () => {
|
|
111
|
+
accumulated = now()
|
|
112
|
+
animator?.cancel()
|
|
113
|
+
animator = undefined
|
|
114
|
+
}
|
|
115
|
+
return (_duration: number): PlaybackClock => {
|
|
116
|
+
start()
|
|
117
|
+
owners++
|
|
118
|
+
running++
|
|
119
|
+
let offset = 0,
|
|
120
|
+
anchor = now(),
|
|
121
|
+
paused = false,
|
|
122
|
+
stopped = false
|
|
123
|
+
const time = () => offset + (paused || stopped ? 0 : now() - anchor)
|
|
124
|
+
const pause = () => {
|
|
125
|
+
if (paused || stopped) return
|
|
126
|
+
offset = time()
|
|
127
|
+
paused = true
|
|
128
|
+
// getCurrentPlayTime keeps counting while a ValueAnimator is paused and
|
|
129
|
+
// corrects itself only on its next frame. Start a fresh marker on resume
|
|
130
|
+
// so command-time reads cannot jump forward and then backward.
|
|
131
|
+
if (--running === 0) stop()
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
time,
|
|
135
|
+
pause,
|
|
136
|
+
play() {
|
|
137
|
+
if (!paused || stopped) return
|
|
138
|
+
if (running++ === 0) start()
|
|
139
|
+
anchor = now()
|
|
140
|
+
paused = false
|
|
141
|
+
},
|
|
142
|
+
seek(ms) {
|
|
143
|
+
offset = ms
|
|
144
|
+
anchor = now()
|
|
145
|
+
},
|
|
146
|
+
cancel() {
|
|
147
|
+
if (stopped) return
|
|
148
|
+
pause()
|
|
149
|
+
stopped = true
|
|
150
|
+
if (--owners === 0) {
|
|
151
|
+
stop()
|
|
152
|
+
accumulated = 0
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|