@shopify/react-native-skia 1.9.0 → 1.10.0
Sign up to get free protection for your applications and to get access to all the features.
- package/cpp/api/JsiSkCanvas.h +1 -1
- package/lib/commonjs/index.d.ts +1 -1
- package/lib/commonjs/index.js +8 -8
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/renderer/Canvas.d.ts +9 -10
- package/lib/commonjs/renderer/Canvas.js +67 -59
- package/lib/commonjs/renderer/Canvas.js.map +1 -1
- package/lib/commonjs/renderer/CanvasOld.d.ts +11 -0
- package/lib/commonjs/renderer/CanvasOld.js +96 -0
- package/lib/commonjs/renderer/CanvasOld.js.map +1 -0
- package/lib/commonjs/sksg/Container.js +12 -8
- package/lib/commonjs/sksg/Container.js.map +1 -1
- package/lib/commonjs/sksg/HostConfig2.d.ts +19 -0
- package/lib/commonjs/sksg/HostConfig2.js +159 -0
- package/lib/commonjs/sksg/HostConfig2.js.map +1 -0
- package/lib/commonjs/sksg/Recorder/Core.d.ts +42 -37
- package/lib/commonjs/sksg/Recorder/Core.js +46 -38
- package/lib/commonjs/sksg/Recorder/Core.js.map +1 -1
- package/lib/commonjs/sksg/Recorder/Player.js +6 -2
- package/lib/commonjs/sksg/Recorder/Player.js.map +1 -1
- package/lib/commonjs/sksg/Recorder/Recorder.d.ts +4 -0
- package/lib/commonjs/sksg/Recorder/Recorder.js +14 -2
- package/lib/commonjs/sksg/Recorder/Recorder.js.map +1 -1
- package/lib/commonjs/sksg/Recorder/Visitor.js +6 -0
- package/lib/commonjs/sksg/Recorder/Visitor.js.map +1 -1
- package/lib/module/index.d.ts +1 -1
- package/lib/module/index.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/renderer/Canvas.d.ts +9 -10
- package/lib/module/renderer/Canvas.js +65 -55
- package/lib/module/renderer/Canvas.js.map +1 -1
- package/lib/module/renderer/CanvasOld.d.ts +11 -0
- package/lib/module/renderer/CanvasOld.js +87 -0
- package/lib/module/renderer/CanvasOld.js.map +1 -0
- package/lib/module/sksg/Container.js +12 -8
- package/lib/module/sksg/Container.js.map +1 -1
- package/lib/module/sksg/HostConfig2.d.ts +19 -0
- package/lib/module/sksg/HostConfig2.js +152 -0
- package/lib/module/sksg/HostConfig2.js.map +1 -0
- package/lib/module/sksg/Recorder/Core.d.ts +42 -37
- package/lib/module/sksg/Recorder/Core.js +44 -37
- package/lib/module/sksg/Recorder/Core.js.map +1 -1
- package/lib/module/sksg/Recorder/Player.js +7 -3
- package/lib/module/sksg/Recorder/Player.js.map +1 -1
- package/lib/module/sksg/Recorder/Recorder.d.ts +4 -0
- package/lib/module/sksg/Recorder/Recorder.js +14 -2
- package/lib/module/sksg/Recorder/Recorder.js.map +1 -1
- package/lib/module/sksg/Recorder/Visitor.js +6 -0
- package/lib/module/sksg/Recorder/Visitor.js.map +1 -1
- package/lib/typescript/lib/commonjs/renderer/Canvas.d.ts +2 -2
- package/lib/typescript/lib/commonjs/renderer/CanvasOld.d.ts +3 -0
- package/lib/typescript/lib/commonjs/sksg/HostConfig2.d.ts +44 -0
- package/lib/typescript/lib/commonjs/sksg/Recorder/Core.d.ts +1 -0
- package/lib/typescript/lib/commonjs/sksg/Recorder/Recorder.d.ts +2 -0
- package/lib/typescript/lib/module/index.d.ts +1 -1
- package/lib/typescript/lib/module/renderer/Canvas.d.ts +1 -3
- package/lib/typescript/lib/module/renderer/CanvasOld.d.ts +3 -0
- package/lib/typescript/lib/module/sksg/HostConfig2.d.ts +43 -0
- package/lib/typescript/lib/module/sksg/Recorder/Core.d.ts +1 -0
- package/lib/typescript/lib/module/sksg/Recorder/Recorder.d.ts +2 -0
- package/lib/typescript/src/index.d.ts +1 -1
- package/lib/typescript/src/renderer/Canvas.d.ts +9 -10
- package/lib/typescript/src/renderer/CanvasOld.d.ts +11 -0
- package/lib/typescript/src/sksg/HostConfig2.d.ts +19 -0
- package/lib/typescript/src/sksg/Recorder/Core.d.ts +42 -37
- package/lib/typescript/src/sksg/Recorder/Recorder.d.ts +4 -0
- package/package.json +3 -2
- package/src/index.ts +1 -1
- package/src/renderer/Canvas.tsx +80 -78
- package/src/renderer/CanvasOld.tsx +126 -0
- package/src/sksg/Container.ts +7 -4
- package/src/sksg/HostConfig2.ts +247 -0
- package/src/sksg/Recorder/Core.ts +11 -0
- package/src/sksg/Recorder/Player.ts +7 -3
- package/src/sksg/Recorder/Recorder.ts +16 -2
- package/src/sksg/Recorder/Visitor.ts +6 -0
- package/lib/commonjs/renderer/Canvas2.d.ts +0 -10
- package/lib/commonjs/renderer/Canvas2.js +0 -104
- package/lib/commonjs/renderer/Canvas2.js.map +0 -1
- package/lib/commonjs/renderer/Canvas2.web.d.ts +0 -3
- package/lib/commonjs/renderer/Canvas2.web.js +0 -9
- package/lib/commonjs/renderer/Canvas2.web.js.map +0 -1
- package/lib/module/renderer/Canvas2.d.ts +0 -10
- package/lib/module/renderer/Canvas2.js +0 -97
- package/lib/module/renderer/Canvas2.js.map +0 -1
- package/lib/module/renderer/Canvas2.web.d.ts +0 -3
- package/lib/module/renderer/Canvas2.web.js +0 -3
- package/lib/module/renderer/Canvas2.web.js.map +0 -1
- package/lib/typescript/lib/commonjs/renderer/Canvas2.d.ts +0 -3
- package/lib/typescript/lib/commonjs/renderer/Canvas2.web.d.ts +0 -2
- package/lib/typescript/lib/module/renderer/Canvas2.d.ts +0 -1
- package/lib/typescript/lib/module/renderer/Canvas2.web.d.ts +0 -1
- package/lib/typescript/src/renderer/Canvas2.d.ts +0 -10
- package/lib/typescript/src/renderer/Canvas2.web.d.ts +0 -3
- package/src/renderer/Canvas2.tsx +0 -128
- package/src/renderer/Canvas2.web.tsx +0 -6
package/src/renderer/Canvas.tsx
CHANGED
@@ -1,32 +1,24 @@
|
|
1
|
-
import
|
2
|
-
|
1
|
+
import {
|
2
|
+
forwardRef,
|
3
3
|
useCallback,
|
4
|
+
useEffect,
|
5
|
+
useImperativeHandle,
|
4
6
|
useMemo,
|
5
|
-
forwardRef,
|
6
7
|
useRef,
|
7
8
|
} from "react";
|
8
|
-
import type {
|
9
|
-
|
10
|
-
ReactNode,
|
11
|
-
MutableRefObject,
|
12
|
-
ForwardedRef,
|
13
|
-
FunctionComponent,
|
14
|
-
} from "react";
|
15
|
-
import type { LayoutChangeEvent } from "react-native";
|
9
|
+
import type { LayoutChangeEvent, ViewProps } from "react-native";
|
10
|
+
import type { SharedValue } from "react-native-reanimated";
|
16
11
|
|
17
|
-
import {
|
12
|
+
import { SkiaViewNativeId } from "../views/SkiaViewNativeId";
|
13
|
+
import SkiaPictureViewNativeComponent from "../specs/SkiaPictureViewNativeComponent";
|
14
|
+
import type { SkRect, SkSize } from "../skia/types";
|
15
|
+
import { SkiaSGRoot } from "../sksg/Reconciler";
|
16
|
+
import { Skia } from "../skia";
|
18
17
|
import type { SkiaBaseViewProps } from "../views";
|
19
18
|
|
20
|
-
|
21
|
-
|
22
|
-
export const useCanvasRef = () => useRef<SkiaDomView>(null);
|
23
|
-
|
24
|
-
export interface CanvasProps extends SkiaBaseViewProps {
|
25
|
-
ref?: RefObject<SkiaDomView>;
|
26
|
-
children: ReactNode;
|
27
|
-
mode?: "default" | "continuous";
|
28
|
-
}
|
19
|
+
const NativeSkiaPictureView = SkiaPictureViewNativeComponent;
|
29
20
|
|
21
|
+
// TODO: no need to go through the JS thread for this
|
30
22
|
const useOnSizeEvent = (
|
31
23
|
resultValue: SkiaBaseViewProps["onSize"],
|
32
24
|
onLayout?: (event: LayoutChangeEvent) => void
|
@@ -46,39 +38,40 @@ const useOnSizeEvent = (
|
|
46
38
|
);
|
47
39
|
};
|
48
40
|
|
49
|
-
export
|
41
|
+
export interface CanvasProps extends ViewProps {
|
42
|
+
debug?: boolean;
|
43
|
+
opaque?: boolean;
|
44
|
+
onSize?: SharedValue<SkSize>;
|
45
|
+
mode?: "continuous" | "default";
|
46
|
+
}
|
47
|
+
|
48
|
+
export const Canvas = forwardRef(
|
50
49
|
(
|
51
50
|
{
|
52
|
-
|
53
|
-
style,
|
51
|
+
mode,
|
54
52
|
debug,
|
55
|
-
|
56
|
-
|
53
|
+
opaque,
|
54
|
+
children,
|
55
|
+
onSize,
|
57
56
|
onLayout: _onLayout,
|
58
|
-
...
|
59
|
-
},
|
60
|
-
|
57
|
+
...viewProps
|
58
|
+
}: CanvasProps,
|
59
|
+
ref
|
61
60
|
) => {
|
62
|
-
const
|
63
|
-
const
|
64
|
-
|
65
|
-
const
|
66
|
-
|
67
|
-
}, [
|
68
|
-
const getNativeId = useCallback(() => {
|
69
|
-
const id = innerRef.current?.nativeId ?? -1;
|
70
|
-
return id;
|
71
|
-
}, [innerRef]);
|
61
|
+
const rafId = useRef<number | null>(null);
|
62
|
+
const onLayout = useOnSizeEvent(onSize, _onLayout);
|
63
|
+
// Native ID
|
64
|
+
const nativeId = useMemo(() => {
|
65
|
+
return SkiaViewNativeId.current++;
|
66
|
+
}, []);
|
72
67
|
|
73
|
-
|
74
|
-
|
75
|
-
[redraw, getNativeId]
|
76
|
-
);
|
68
|
+
// Root
|
69
|
+
const root = useMemo(() => new SkiaSGRoot(Skia, nativeId), [nativeId]);
|
77
70
|
|
78
|
-
// Render
|
71
|
+
// Render effects
|
79
72
|
useEffect(() => {
|
80
73
|
root.render(children);
|
81
|
-
}, [children, root
|
74
|
+
}, [children, root]);
|
82
75
|
|
83
76
|
useEffect(() => {
|
84
77
|
return () => {
|
@@ -86,41 +79,50 @@ export const Canvas = forwardRef<SkiaDomView, CanvasProps>(
|
|
86
79
|
};
|
87
80
|
}, [root]);
|
88
81
|
|
82
|
+
const requestRedraw = useCallback(() => {
|
83
|
+
rafId.current = requestAnimationFrame(() => {
|
84
|
+
root.render(children);
|
85
|
+
if (mode === "continuous") {
|
86
|
+
requestRedraw();
|
87
|
+
}
|
88
|
+
});
|
89
|
+
}, [children, mode, root]);
|
90
|
+
|
91
|
+
useEffect(() => {
|
92
|
+
if (mode === "continuous") {
|
93
|
+
console.warn("The `mode` property in `Canvas` is deprecated.");
|
94
|
+
requestRedraw();
|
95
|
+
}
|
96
|
+
return () => {
|
97
|
+
if (rafId.current !== null) {
|
98
|
+
cancelAnimationFrame(rafId.current);
|
99
|
+
}
|
100
|
+
};
|
101
|
+
}, [mode, requestRedraw]);
|
102
|
+
// Component methods
|
103
|
+
useImperativeHandle(ref, () => ({
|
104
|
+
makeImageSnapshot: (rect?: SkRect) => {
|
105
|
+
return SkiaViewApi.makeImageSnapshot(nativeId, rect);
|
106
|
+
},
|
107
|
+
makeImageSnapshotAsync: (rect?: SkRect) => {
|
108
|
+
return SkiaViewApi.makeImageSnapshotAsync(nativeId, rect);
|
109
|
+
},
|
110
|
+
redraw: () => {
|
111
|
+
SkiaViewApi.requestRedraw(nativeId);
|
112
|
+
},
|
113
|
+
getNativeId: () => {
|
114
|
+
return nativeId;
|
115
|
+
},
|
116
|
+
}));
|
89
117
|
return (
|
90
|
-
<
|
91
|
-
|
92
|
-
|
93
|
-
root={root.dom}
|
94
|
-
onLayout={onLayout}
|
118
|
+
<NativeSkiaPictureView
|
119
|
+
collapsable={false}
|
120
|
+
nativeID={`${nativeId}`}
|
95
121
|
debug={debug}
|
96
|
-
|
97
|
-
{
|
122
|
+
opaque={opaque}
|
123
|
+
onLayout={onLayout}
|
124
|
+
{...viewProps}
|
98
125
|
/>
|
99
126
|
);
|
100
127
|
}
|
101
|
-
)
|
102
|
-
|
103
|
-
/**
|
104
|
-
* Combines a list of refs into a single ref. This can be used to provide
|
105
|
-
* both a forwarded ref and an internal ref keeping the same functionality
|
106
|
-
* on both of the refs.
|
107
|
-
* @param refs Array of refs to combine
|
108
|
-
* @returns A single ref that can be used in a ref prop.
|
109
|
-
*/
|
110
|
-
const useCombinedRefs = <T,>(
|
111
|
-
...refs: Array<MutableRefObject<T> | ForwardedRef<T>>
|
112
|
-
) => {
|
113
|
-
const targetRef = React.useRef<T>(null);
|
114
|
-
React.useEffect(() => {
|
115
|
-
refs.forEach((ref) => {
|
116
|
-
if (ref) {
|
117
|
-
if (typeof ref === "function") {
|
118
|
-
ref(targetRef.current);
|
119
|
-
} else {
|
120
|
-
ref.current = targetRef.current;
|
121
|
-
}
|
122
|
-
}
|
123
|
-
});
|
124
|
-
}, [refs]);
|
125
|
-
return targetRef;
|
126
|
-
};
|
128
|
+
);
|
@@ -0,0 +1,126 @@
|
|
1
|
+
import React, {
|
2
|
+
useEffect,
|
3
|
+
useCallback,
|
4
|
+
useMemo,
|
5
|
+
forwardRef,
|
6
|
+
useRef,
|
7
|
+
} from "react";
|
8
|
+
import type {
|
9
|
+
RefObject,
|
10
|
+
ReactNode,
|
11
|
+
MutableRefObject,
|
12
|
+
ForwardedRef,
|
13
|
+
FunctionComponent,
|
14
|
+
} from "react";
|
15
|
+
import type { LayoutChangeEvent } from "react-native";
|
16
|
+
|
17
|
+
import { SkiaDomView } from "../views";
|
18
|
+
import type { SkiaBaseViewProps } from "../views";
|
19
|
+
|
20
|
+
import { SkiaRoot } from "./Reconciler";
|
21
|
+
|
22
|
+
export const useCanvasRef = () => useRef<SkiaDomView>(null);
|
23
|
+
|
24
|
+
export interface CanvasOldProps extends SkiaBaseViewProps {
|
25
|
+
ref?: RefObject<SkiaDomView>;
|
26
|
+
children: ReactNode;
|
27
|
+
mode?: "default" | "continuous";
|
28
|
+
}
|
29
|
+
|
30
|
+
const useOnSizeEvent = (
|
31
|
+
resultValue: SkiaBaseViewProps["onSize"],
|
32
|
+
onLayout?: (event: LayoutChangeEvent) => void
|
33
|
+
) => {
|
34
|
+
return useCallback(
|
35
|
+
(event: LayoutChangeEvent) => {
|
36
|
+
if (onLayout) {
|
37
|
+
onLayout(event);
|
38
|
+
}
|
39
|
+
const { width, height } = event.nativeEvent.layout;
|
40
|
+
|
41
|
+
if (resultValue) {
|
42
|
+
resultValue.value = { width, height };
|
43
|
+
}
|
44
|
+
},
|
45
|
+
[onLayout, resultValue]
|
46
|
+
);
|
47
|
+
};
|
48
|
+
|
49
|
+
export const CanvasOld = forwardRef<SkiaDomView, CanvasOldProps>(
|
50
|
+
(
|
51
|
+
{
|
52
|
+
children,
|
53
|
+
style,
|
54
|
+
debug,
|
55
|
+
mode = "default",
|
56
|
+
onSize: _onSize,
|
57
|
+
onLayout: _onLayout,
|
58
|
+
...props
|
59
|
+
},
|
60
|
+
forwardedRef
|
61
|
+
) => {
|
62
|
+
const onLayout = useOnSizeEvent(_onSize, _onLayout);
|
63
|
+
const innerRef = useCanvasRef();
|
64
|
+
const ref = useCombinedRefs(forwardedRef, innerRef);
|
65
|
+
const redraw = useCallback(() => {
|
66
|
+
innerRef.current?.redraw();
|
67
|
+
}, [innerRef]);
|
68
|
+
const getNativeId = useCallback(() => {
|
69
|
+
const id = innerRef.current?.nativeId ?? -1;
|
70
|
+
return id;
|
71
|
+
}, [innerRef]);
|
72
|
+
|
73
|
+
const root = useMemo(
|
74
|
+
() => new SkiaRoot(redraw, getNativeId),
|
75
|
+
[redraw, getNativeId]
|
76
|
+
);
|
77
|
+
|
78
|
+
// Render effect
|
79
|
+
useEffect(() => {
|
80
|
+
root.render(children);
|
81
|
+
}, [children, root, redraw]);
|
82
|
+
|
83
|
+
useEffect(() => {
|
84
|
+
return () => {
|
85
|
+
root.unmount();
|
86
|
+
};
|
87
|
+
}, [root]);
|
88
|
+
|
89
|
+
return (
|
90
|
+
<SkiaDomView
|
91
|
+
ref={ref}
|
92
|
+
style={style}
|
93
|
+
root={root.dom}
|
94
|
+
onLayout={onLayout}
|
95
|
+
debug={debug}
|
96
|
+
mode={mode}
|
97
|
+
{...props}
|
98
|
+
/>
|
99
|
+
);
|
100
|
+
}
|
101
|
+
) as FunctionComponent<CanvasOldProps & React.RefAttributes<SkiaDomView>>;
|
102
|
+
|
103
|
+
/**
|
104
|
+
* Combines a list of refs into a single ref. This can be used to provide
|
105
|
+
* both a forwarded ref and an internal ref keeping the same functionality
|
106
|
+
* on both of the refs.
|
107
|
+
* @param refs Array of refs to combine
|
108
|
+
* @returns A single ref that can be used in a ref prop.
|
109
|
+
*/
|
110
|
+
const useCombinedRefs = <T,>(
|
111
|
+
...refs: Array<MutableRefObject<T> | ForwardedRef<T>>
|
112
|
+
) => {
|
113
|
+
const targetRef = React.useRef<T>(null);
|
114
|
+
React.useEffect(() => {
|
115
|
+
refs.forEach((ref) => {
|
116
|
+
if (ref) {
|
117
|
+
if (typeof ref === "function") {
|
118
|
+
ref(targetRef.current);
|
119
|
+
} else {
|
120
|
+
ref.current = targetRef.current;
|
121
|
+
}
|
122
|
+
}
|
123
|
+
});
|
124
|
+
}, [refs]);
|
125
|
+
return targetRef;
|
126
|
+
};
|
package/src/sksg/Container.ts
CHANGED
@@ -14,10 +14,9 @@ const drawOnscreen = (Skia: Skia, nativeId: number, recording: Recording) => {
|
|
14
14
|
|
15
15
|
const rec = Skia.PictureRecorder();
|
16
16
|
const canvas = rec.beginRecording();
|
17
|
-
//
|
17
|
+
//const start = performance.now();
|
18
18
|
|
19
19
|
const ctx = createDrawingContext(Skia, recording.paintPool, canvas);
|
20
|
-
//console.log(recording.commands);
|
21
20
|
replay(ctx, recording.commands);
|
22
21
|
const picture = rec.finishRecordingAsPicture();
|
23
22
|
//const end = performance.now();
|
@@ -42,7 +41,7 @@ export abstract class Container {
|
|
42
41
|
this.recording.paintPool,
|
43
42
|
canvas
|
44
43
|
);
|
45
|
-
//console.log(this.
|
44
|
+
//console.log(this.recording.commands);
|
46
45
|
replay(ctx, this.recording.commands);
|
47
46
|
}
|
48
47
|
|
@@ -88,13 +87,17 @@ class ReanimatedContainer extends Container {
|
|
88
87
|
commands: record.commands,
|
89
88
|
paintPool: record.paintPool,
|
90
89
|
};
|
90
|
+
const { nativeId, Skia, recording } = this;
|
91
91
|
if (animationValues.size > 0) {
|
92
|
-
const { nativeId, Skia, recording } = this;
|
93
92
|
this.mapperId = Rea.startMapper(() => {
|
94
93
|
"worklet";
|
95
94
|
drawOnscreen(Skia, nativeId, recording!);
|
96
95
|
}, Array.from(animationValues));
|
97
96
|
}
|
97
|
+
Rea.runOnUI(() => {
|
98
|
+
"worklet";
|
99
|
+
drawOnscreen(Skia, nativeId, recording!);
|
100
|
+
})();
|
98
101
|
}
|
99
102
|
}
|
100
103
|
|
@@ -0,0 +1,247 @@
|
|
1
|
+
/*global NodeJS*/
|
2
|
+
import type { Fiber, HostConfig } from "react-reconciler";
|
3
|
+
import { DefaultEventPriority } from "react-reconciler/constants";
|
4
|
+
|
5
|
+
import type { NodeType } from "../dom/types";
|
6
|
+
import { shallowEq } from "../renderer/typeddash";
|
7
|
+
|
8
|
+
import type { Container } from "./Container";
|
9
|
+
import type { Node } from "./Node";
|
10
|
+
|
11
|
+
const DEBUG = false;
|
12
|
+
export const debug = (...args: Parameters<typeof console.log>) => {
|
13
|
+
if (DEBUG) {
|
14
|
+
console.log(...args);
|
15
|
+
}
|
16
|
+
};
|
17
|
+
|
18
|
+
type Instance = Node<unknown>;
|
19
|
+
|
20
|
+
type Props = object;
|
21
|
+
type TextInstance = Node<unknown>;
|
22
|
+
type SuspenseInstance = Instance;
|
23
|
+
type HydratableInstance = Instance;
|
24
|
+
type PublicInstance = Instance;
|
25
|
+
type HostContext = null;
|
26
|
+
type UpdatePayload = Container;
|
27
|
+
type ChildSet = unknown;
|
28
|
+
type TimeoutHandle = NodeJS.Timeout;
|
29
|
+
type NoTimeout = -1;
|
30
|
+
|
31
|
+
type SkiaHostConfig = HostConfig<
|
32
|
+
NodeType,
|
33
|
+
Props,
|
34
|
+
Container,
|
35
|
+
Instance,
|
36
|
+
TextInstance,
|
37
|
+
SuspenseInstance,
|
38
|
+
HydratableInstance,
|
39
|
+
PublicInstance,
|
40
|
+
HostContext,
|
41
|
+
UpdatePayload,
|
42
|
+
ChildSet,
|
43
|
+
TimeoutHandle,
|
44
|
+
NoTimeout
|
45
|
+
>;
|
46
|
+
|
47
|
+
const appendNode = (parent: Node<unknown>, child: Node<unknown>) => {
|
48
|
+
parent.children.push(child);
|
49
|
+
};
|
50
|
+
|
51
|
+
const removeNode = (parent: Node<unknown>, child: Node<unknown>) => {
|
52
|
+
parent.children.splice(parent.children.indexOf(child), 1);
|
53
|
+
};
|
54
|
+
|
55
|
+
const insertBefore = (
|
56
|
+
parent: Node<unknown>,
|
57
|
+
child: Node<unknown>,
|
58
|
+
before: Node<unknown>
|
59
|
+
) => {
|
60
|
+
parent.children.splice(parent.children.indexOf(before), 0, child);
|
61
|
+
};
|
62
|
+
|
63
|
+
export const sksgHostConfig: SkiaHostConfig = {
|
64
|
+
/**
|
65
|
+
* This function is used by the reconciler in order to calculate current time for prioritising work.
|
66
|
+
*/
|
67
|
+
supportsMutation: true,
|
68
|
+
isPrimaryRenderer: false,
|
69
|
+
supportsPersistence: false,
|
70
|
+
supportsHydration: false,
|
71
|
+
//supportsMicrotask: true,
|
72
|
+
|
73
|
+
scheduleTimeout: setTimeout,
|
74
|
+
cancelTimeout: clearTimeout,
|
75
|
+
noTimeout: -1,
|
76
|
+
|
77
|
+
appendChildToContainer(container, child) {
|
78
|
+
debug("appendChildToContainer");
|
79
|
+
container.root.push(child);
|
80
|
+
},
|
81
|
+
|
82
|
+
appendChild(parent, child) {
|
83
|
+
debug("appendChild", parent, child);
|
84
|
+
appendNode(parent, child);
|
85
|
+
},
|
86
|
+
|
87
|
+
getRootHostContext: (_rootContainerInstance: Container) => {
|
88
|
+
debug("getRootHostContext");
|
89
|
+
return null;
|
90
|
+
},
|
91
|
+
|
92
|
+
getChildHostContext(_parentHostContext, _type, _rootContainerInstance) {
|
93
|
+
debug("getChildHostContext");
|
94
|
+
return null;
|
95
|
+
},
|
96
|
+
|
97
|
+
shouldSetTextContent(_type, _props) {
|
98
|
+
return false;
|
99
|
+
},
|
100
|
+
|
101
|
+
createTextInstance(
|
102
|
+
_text,
|
103
|
+
_rootContainerInstance,
|
104
|
+
_hostContext,
|
105
|
+
_internalInstanceHandle
|
106
|
+
) {
|
107
|
+
debug("createTextInstance");
|
108
|
+
// return SpanNode({}, text) as SkNode;
|
109
|
+
throw new Error("Text nodes are not supported yet");
|
110
|
+
},
|
111
|
+
|
112
|
+
createInstance(
|
113
|
+
type,
|
114
|
+
propsWithChildren,
|
115
|
+
_container,
|
116
|
+
_hostContext,
|
117
|
+
_internalInstanceHandle
|
118
|
+
) {
|
119
|
+
debug("createInstance", type);
|
120
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
121
|
+
const { children, ...props } = propsWithChildren as any;
|
122
|
+
debug("createInstance", type);
|
123
|
+
const instance = {
|
124
|
+
type,
|
125
|
+
props,
|
126
|
+
children: [],
|
127
|
+
};
|
128
|
+
return instance;
|
129
|
+
},
|
130
|
+
|
131
|
+
appendInitialChild(parentInstance, child) {
|
132
|
+
debug("appendInitialChild");
|
133
|
+
appendNode(parentInstance, child);
|
134
|
+
},
|
135
|
+
|
136
|
+
finalizeInitialChildren(
|
137
|
+
parentInstance,
|
138
|
+
_type,
|
139
|
+
_props,
|
140
|
+
_rootContainerInstance,
|
141
|
+
_hostContext
|
142
|
+
) {
|
143
|
+
debug("finalizeInitialChildren", parentInstance);
|
144
|
+
return false;
|
145
|
+
},
|
146
|
+
|
147
|
+
commitMount() {
|
148
|
+
// if finalizeInitialChildren = true
|
149
|
+
debug("commitMount");
|
150
|
+
},
|
151
|
+
|
152
|
+
prepareForCommit(_containerInfo) {
|
153
|
+
debug("prepareForCommit");
|
154
|
+
return null;
|
155
|
+
},
|
156
|
+
|
157
|
+
resetAfterCommit(container) {
|
158
|
+
debug("resetAfterCommit");
|
159
|
+
container.redraw();
|
160
|
+
},
|
161
|
+
|
162
|
+
getPublicInstance(node: Instance) {
|
163
|
+
debug("getPublicInstance");
|
164
|
+
return node;
|
165
|
+
},
|
166
|
+
|
167
|
+
prepareUpdate: (
|
168
|
+
_instance,
|
169
|
+
type,
|
170
|
+
oldProps,
|
171
|
+
newProps,
|
172
|
+
rootContainerInstance,
|
173
|
+
_hostContext
|
174
|
+
) => {
|
175
|
+
debug("prepareUpdate");
|
176
|
+
const propsAreEqual = shallowEq(oldProps, newProps);
|
177
|
+
if (propsAreEqual) {
|
178
|
+
return null;
|
179
|
+
}
|
180
|
+
debug("update ", type);
|
181
|
+
return rootContainerInstance;
|
182
|
+
},
|
183
|
+
|
184
|
+
commitUpdate(
|
185
|
+
instance,
|
186
|
+
_updatePayload,
|
187
|
+
type,
|
188
|
+
prevProps,
|
189
|
+
nextProps,
|
190
|
+
_internalHandle
|
191
|
+
) {
|
192
|
+
debug("commitUpdate: ", type);
|
193
|
+
if (shallowEq(prevProps, nextProps)) {
|
194
|
+
return;
|
195
|
+
}
|
196
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
197
|
+
const { children, ...props } = nextProps as any;
|
198
|
+
instance.props = props;
|
199
|
+
},
|
200
|
+
|
201
|
+
commitTextUpdate: (
|
202
|
+
_textInstance: TextInstance,
|
203
|
+
_oldText: string,
|
204
|
+
_newText: string
|
205
|
+
) => {
|
206
|
+
// textInstance.instance = newText;
|
207
|
+
},
|
208
|
+
|
209
|
+
clearContainer: (container) => {
|
210
|
+
debug("clearContainer");
|
211
|
+
container.root = [];
|
212
|
+
},
|
213
|
+
|
214
|
+
preparePortalMount: () => {
|
215
|
+
debug("preparePortalMount");
|
216
|
+
},
|
217
|
+
|
218
|
+
removeChild: (parent, child) => {
|
219
|
+
removeNode(parent, child);
|
220
|
+
},
|
221
|
+
|
222
|
+
removeChildFromContainer: (container, child) => {
|
223
|
+
container.root.splice(container.root.indexOf(child), 1);
|
224
|
+
},
|
225
|
+
|
226
|
+
insertInContainerBefore: (container, child, before) => {
|
227
|
+
container.root.splice(container.root.indexOf(before), 0, child);
|
228
|
+
},
|
229
|
+
|
230
|
+
insertBefore: (parent, child, before) => {
|
231
|
+
insertBefore(parent, child, before);
|
232
|
+
},
|
233
|
+
|
234
|
+
// see https://github.com/pmndrs/react-three-fiber/pull/2360#discussion_r916356874
|
235
|
+
getCurrentEventPriority: () => DefaultEventPriority,
|
236
|
+
beforeActiveInstanceBlur: () => {},
|
237
|
+
afterActiveInstanceBlur: () => {},
|
238
|
+
detachDeletedInstance: () => {},
|
239
|
+
|
240
|
+
getInstanceFromNode: function (_node): Fiber | null | undefined {
|
241
|
+
return null;
|
242
|
+
},
|
243
|
+
prepareScopeUpdate: function (_scopeInstance, _instance): void {},
|
244
|
+
getInstanceFromScope: function (_scopeInstance): Instance | null {
|
245
|
+
return null;
|
246
|
+
},
|
247
|
+
};
|
@@ -27,6 +27,7 @@ import type {
|
|
27
27
|
|
28
28
|
// export enum CommandType {
|
29
29
|
// // Context
|
30
|
+
// Group = "Group",
|
30
31
|
// SavePaint = "SavePaint",
|
31
32
|
// RestorePaint = "RestorePaint",
|
32
33
|
// SaveCTM = "SaveCTM",
|
@@ -68,6 +69,7 @@ import type {
|
|
68
69
|
// }
|
69
70
|
export enum CommandType {
|
70
71
|
// Context
|
72
|
+
Group,
|
71
73
|
SavePaint,
|
72
74
|
RestorePaint,
|
73
75
|
SaveCTM,
|
@@ -133,6 +135,15 @@ export const isCommand = <T extends CommandType>(
|
|
133
135
|
return command.type === type;
|
134
136
|
};
|
135
137
|
|
138
|
+
interface GroupCommand extends Command<CommandType.Group> {
|
139
|
+
children: Command[];
|
140
|
+
}
|
141
|
+
|
142
|
+
export const isGroup = (command: Command): command is GroupCommand => {
|
143
|
+
"worklet";
|
144
|
+
return command.type === CommandType.Group;
|
145
|
+
};
|
146
|
+
|
136
147
|
interface Props {
|
137
148
|
[CommandType.DrawImage]: ImageProps;
|
138
149
|
[CommandType.DrawCircle]: CircleProps;
|
@@ -43,14 +43,18 @@ import {
|
|
43
43
|
CommandType,
|
44
44
|
isCommand,
|
45
45
|
isDrawCommand,
|
46
|
+
isGroup,
|
46
47
|
materializeProps,
|
47
48
|
type Command,
|
48
49
|
} from "./Core";
|
49
50
|
import type { DrawingContext } from "./DrawingContext";
|
50
51
|
|
51
|
-
|
52
|
+
function play(ctx: DrawingContext, command: Command) {
|
52
53
|
"worklet";
|
53
|
-
|
54
|
+
if (isGroup(command)) {
|
55
|
+
command.children.forEach((child) => play(ctx, child));
|
56
|
+
return;
|
57
|
+
}
|
54
58
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
55
59
|
materializeProps(command as any);
|
56
60
|
if (isCommand(command, CommandType.SaveBackdropFilter)) {
|
@@ -150,7 +154,7 @@ const play = (ctx: DrawingContext, command: Command) => {
|
|
150
154
|
ctx.paints.pop();
|
151
155
|
});
|
152
156
|
}
|
153
|
-
}
|
157
|
+
}
|
154
158
|
|
155
159
|
export const replay = (ctx: DrawingContext, commands: Command[]) => {
|
156
160
|
"worklet";
|
@@ -46,8 +46,13 @@ interface AnimationValues {
|
|
46
46
|
|
47
47
|
export class Recorder {
|
48
48
|
commands: Command[] = [];
|
49
|
+
cursors: Command[][] = [];
|
49
50
|
animationValues: Set<SharedValue<unknown>> = new Set();
|
50
51
|
|
52
|
+
constructor() {
|
53
|
+
this.cursors.push(this.commands);
|
54
|
+
}
|
55
|
+
|
51
56
|
getRecording(): Recording & AnimationValues {
|
52
57
|
return {
|
53
58
|
commands: this.commands,
|
@@ -64,7 +69,6 @@ export class Recorder {
|
|
64
69
|
const prop = props[key];
|
65
70
|
if (isSharedValue(prop)) {
|
66
71
|
this.animationValues.add(prop);
|
67
|
-
props[key] = prop.value;
|
68
72
|
animatedProps[key] = prop;
|
69
73
|
hasAnimatedProps = true;
|
70
74
|
}
|
@@ -85,7 +89,17 @@ export class Recorder {
|
|
85
89
|
command.animatedProps = animatedProps;
|
86
90
|
}
|
87
91
|
}
|
88
|
-
this.
|
92
|
+
this.cursors[this.cursors.length - 1].push(command);
|
93
|
+
}
|
94
|
+
|
95
|
+
saveGroup() {
|
96
|
+
const children: Command[] = [];
|
97
|
+
this.add({ type: CommandType.Group, children });
|
98
|
+
this.cursors.push(children);
|
99
|
+
}
|
100
|
+
|
101
|
+
restoreGroup() {
|
102
|
+
this.cursors.pop();
|
89
103
|
}
|
90
104
|
|
91
105
|
savePaint(props: AnimatedProps<PaintProps>) {
|