Socket
Socket
Sign inDemoInstall

@shopify/react-native-skia

Package Overview
Dependencies
Maintainers
24
Versions
139
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@shopify/react-native-skia - npm Package Compare versions

Comparing version 1.3.2 to 1.3.3

72

lib/commonjs/dom/nodes/datatypes/Fitting.js

@@ -8,8 +8,14 @@ "use strict";

var _typeddash = require("../../../renderer/typeddash");
const size = (width = 0, height = 0) => ({
width,
height
});
const size = (width = 0, height = 0) => {
"worklet";
return {
width,
height
};
};
exports.size = size;
const rect2rect = (src, dst) => {
"worklet";
const scaleX = dst.width / src.width;

@@ -30,28 +36,2 @@ const scaleY = dst.height / src.height;

exports.rect2rect = rect2rect;
const fitRects = (fit, rect, {
x,
y,
width,
height
}) => {
const sizes = applyBoxFit(fit, {
width: rect.width,
height: rect.height
}, {
width,
height
});
const src = inscribe(sizes.src, rect);
const dst = inscribe(sizes.dst, {
x,
y,
width,
height
});
return {
src,
dst
};
};
exports.fitRects = fitRects;
const inscribe = ({

@@ -61,2 +41,4 @@ width,

}, rect) => {
"worklet";
const halfWidthDelta = (rect.width - width) / 2.0;

@@ -72,2 +54,4 @@ const halfHeightDelta = (rect.height - height) / 2.0;

const applyBoxFit = (fit, input, output) => {
"worklet";
let src = size(),

@@ -133,2 +117,30 @@ dst = size();

};
const fitRects = (fit, rect, {
x,
y,
width,
height
}) => {
"worklet";
const sizes = applyBoxFit(fit, {
width: rect.width,
height: rect.height
}, {
width,
height
});
const src = inscribe(sizes.src, rect);
const dst = inscribe(sizes.dst, {
x,
y,
width,
height
});
return {
src,
dst
};
};
exports.fitRects = fitRects;
//# sourceMappingURL=Fitting.js.map

@@ -0,9 +1,21 @@

import type { SharedValue } from "react-native-reanimated";
import type { SkImage } from "../../skia/types";
import { type PlaybackOptions } from "./video";
type Animated<T> = SharedValue<T> | T;
interface PlaybackOptions {
looping: Animated<boolean>;
paused: Animated<boolean>;
seek: Animated<number | null>;
volume: Animated<number>;
}
export declare const useVideo: (source: string | null, userOptions?: Partial<PlaybackOptions>) => {
currentFrame: import("react-native-reanimated").SharedValue<SkImage | null>;
currentTime: import("react-native-reanimated").SharedValue<number>;
currentFrame: SharedValue<SkImage | null>;
currentTime: SharedValue<number>;
duration: number;
framerate: number;
rotationInDegrees: number;
rotation: import("../../skia/types").VideoRotation;
size: {
width: number;
height: number;
};
};
export {};

@@ -9,11 +9,26 @@ "use strict";

var _Skia = require("../../skia/Skia");
var _Platform = require("../../Platform");
var _ReanimatedProxy = _interopRequireDefault(require("./ReanimatedProxy"));
var _video = require("./video");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const setFrame = (video, currentFrame) => {
"worklet";
const img = video.nextImage();
if (img) {
if (currentFrame.value) {
currentFrame.value.dispose();
}
if (_Platform.Platform.OS === "android") {
currentFrame.value = img.makeNonTextureImage();
} else {
currentFrame.value = img;
}
}
};
const defaultOptions = {
playbackSpeed: 1,
looping: true,
paused: false,
seek: null,
currentTime: 0
currentTime: 0,
volume: 0
};

@@ -33,3 +48,3 @@ const useOption = value => {

const useVideo = (source, userOptions) => {
var _userOptions$paused, _userOptions$looping, _userOptions$seek, _userOptions$playback;
var _userOptions$paused, _userOptions$looping, _userOptions$seek, _userOptions$volume;
const video = (0, _react.useMemo)(() => source ? _Skia.Skia.Video(source) : null, [source]);

@@ -39,3 +54,3 @@ const isPaused = useOption((_userOptions$paused = userOptions === null || userOptions === void 0 ? void 0 : userOptions.paused) !== null && _userOptions$paused !== void 0 ? _userOptions$paused : defaultOptions.paused);

const seek = useOption((_userOptions$seek = userOptions === null || userOptions === void 0 ? void 0 : userOptions.seek) !== null && _userOptions$seek !== void 0 ? _userOptions$seek : defaultOptions.seek);
const playbackSpeed = useOption((_userOptions$playback = userOptions === null || userOptions === void 0 ? void 0 : userOptions.playbackSpeed) !== null && _userOptions$playback !== void 0 ? _userOptions$playback : defaultOptions.playbackSpeed);
const volume = useOption((_userOptions$volume = userOptions === null || userOptions === void 0 ? void 0 : userOptions.volume) !== null && _userOptions$volume !== void 0 ? _userOptions$volume : defaultOptions.volume);
const currentFrame = _ReanimatedProxy.default.useSharedValue(null);

@@ -52,12 +67,58 @@ const currentTime = _ReanimatedProxy.default.useSharedValue(0);

}, [video]);
const rotationInDegrees = (0, _react.useMemo)(() => {
var _video$getRotationInD;
return (_video$getRotationInD = video === null || video === void 0 ? void 0 : video.getRotationInDegrees()) !== null && _video$getRotationInD !== void 0 ? _video$getRotationInD : 0;
const size = (0, _react.useMemo)(() => {
var _video$size;
return (_video$size = video === null || video === void 0 ? void 0 : video.size()) !== null && _video$size !== void 0 ? _video$size : {
width: 0,
height: 0
};
}, [video]);
const rotation = (0, _react.useMemo)(() => {
var _video$rotation;
return (_video$rotation = video === null || video === void 0 ? void 0 : video.rotation()) !== null && _video$rotation !== void 0 ? _video$rotation : 0;
}, [video]);
const frameDuration = 1000 / framerate;
const currentFrameDuration = Math.floor(frameDuration);
_ReanimatedProxy.default.useAnimatedReaction(() => isPaused.value, paused => {
if (paused) {
video === null || video === void 0 || video.pause();
} else {
lastTimestamp.value = -1;
video === null || video === void 0 || video.play();
}
});
_ReanimatedProxy.default.useAnimatedReaction(() => seek.value, value => {
if (value !== null) {
video === null || video === void 0 || video.seek(value);
currentTime.value = value;
seek.value = null;
}
});
_ReanimatedProxy.default.useAnimatedReaction(() => volume.value, value => {
video === null || video === void 0 || video.setVolume(value);
});
_ReanimatedProxy.default.useFrameCallback(frameInfo => {
(0, _video.processVideoState)(video, duration, framerate, frameInfo.timestamp, {
paused: isPaused.value,
looping: looping.value,
playbackSpeed: playbackSpeed.value
}, currentTime, currentFrame, lastTimestamp, seek);
"worklet";
if (!video) {
return;
}
if (isPaused.value) {
return;
}
const currentTimestamp = frameInfo.timestamp;
if (lastTimestamp.value === -1) {
lastTimestamp.value = currentTimestamp;
}
const delta = currentTimestamp - lastTimestamp.value;
const isOver = currentTime.value + delta > duration;
if (isOver && looping.value) {
seek.value = 0;
currentTime.value = seek.value;
lastTimestamp.value = currentTimestamp;
}
if (delta >= currentFrameDuration && !isOver) {
setFrame(video, currentFrame);
currentTime.value += delta;
lastTimestamp.value = currentTimestamp;
}
});

@@ -75,3 +136,4 @@ (0, _react.useEffect)(() => {

framerate,
rotationInDegrees
rotation,
size
};

@@ -78,0 +140,0 @@ };

import type { ReactNode } from "react";
import React from "react";
import type { Fit } from "../../../dom/nodes";
import type { SkRect } from "../../../skia/types";
import type { SkRect, Transforms3d } from "../../../skia/types";
interface FitProps {

@@ -11,12 +11,4 @@ fit?: Fit;

}
export declare const fitbox: (fit: Fit, src: SkRect, dst: SkRect) => [{
translateX: number;
}, {
translateY: number;
}, {
scaleX: number;
}, {
scaleY: number;
}];
export declare const fitbox: (fit: Fit, src: SkRect, dst: SkRect, rotation?: 0 | 90 | 180 | 270) => Transforms3d;
export declare const FitBox: ({ fit, src, dst, children }: FitProps) => React.JSX.Element;
export {};

@@ -12,5 +12,34 @@ "use strict";

function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const fitbox = (fit, src, dst) => {
const rects = (0, _nodes.fitRects)(fit, src, dst);
return (0, _nodes.rect2rect)(rects.src, rects.dst);
const fitbox = (fit, src, dst, rotation = 0) => {
"worklet";
const rects = (0, _nodes.fitRects)(fit, rotation === 90 || rotation === 270 ? {
x: 0,
y: 0,
width: src.height,
height: src.width
} : src, dst);
const result = (0, _nodes.rect2rect)(rects.src, rects.dst);
if (rotation === 90) {
return [...result, {
translate: [src.height, 0]
}, {
rotate: Math.PI / 2
}];
}
if (rotation === 180) {
return [...result, {
translate: [src.width, src.height]
}, {
rotate: Math.PI
}];
}
if (rotation === 270) {
return [...result, {
translate: [0, src.width]
}, {
rotate: -Math.PI / 2
}];
}
return result;
};

@@ -17,0 +46,0 @@ exports.fitbox = fitbox;

@@ -9,4 +9,8 @@ "use strict";

var _types = require("../types");
const processTransform2d = transforms => (0, _types.processTransform)(_Skia.Skia.Matrix(), transforms);
const processTransform2d = transforms => {
"worklet";
return (0, _types.processTransform)(_Skia.Skia.Matrix(), transforms);
};
exports.processTransform2d = processTransform2d;
//# sourceMappingURL=Matrix.js.map

@@ -11,2 +11,4 @@ "use strict";

const processTransform = (m, transforms) => {
"worklet";
const m3 = (0, _Matrix.processTransform3d)(transforms);

@@ -13,0 +15,0 @@ m.concat(m3);

import type { SkImage } from "../Image";
import type { SkJSIInstance } from "../JsiInstance";
export type VideoRotation = 0 | 90 | 180 | 270;
export interface Video extends SkJSIInstance<"Video"> {

@@ -8,3 +9,10 @@ duration(): number;

seek(time: number): void;
getRotationInDegrees(): number;
rotation(): VideoRotation;
size(): {
width: number;
height: number;
};
pause(): void;
play(): void;
setVolume(volume: number): void;
}
import { exhaustiveCheck } from "../../../renderer/typeddash";
export const size = (width = 0, height = 0) => ({
width,
height
});
export const size = (width = 0, height = 0) => {
"worklet";
return {
width,
height
};
};
export const rect2rect = (src, dst) => {
"worklet";
const scaleX = dst.width / src.width;

@@ -21,27 +27,2 @@ const scaleY = dst.height / src.height;

};
export const fitRects = (fit, rect, {
x,
y,
width,
height
}) => {
const sizes = applyBoxFit(fit, {
width: rect.width,
height: rect.height
}, {
width,
height
});
const src = inscribe(sizes.src, rect);
const dst = inscribe(sizes.dst, {
x,
y,
width,
height
});
return {
src,
dst
};
};
const inscribe = ({

@@ -51,2 +32,4 @@ width,

}, rect) => {
"worklet";
const halfWidthDelta = (rect.width - width) / 2.0;

@@ -62,2 +45,4 @@ const halfHeightDelta = (rect.height - height) / 2.0;

const applyBoxFit = (fit, input, output) => {
"worklet";
let src = size(),

@@ -123,2 +108,29 @@ dst = size();

};
export const fitRects = (fit, rect, {
x,
y,
width,
height
}) => {
"worklet";
const sizes = applyBoxFit(fit, {
width: rect.width,
height: rect.height
}, {
width,
height
});
const src = inscribe(sizes.src, rect);
const dst = inscribe(sizes.dst, {
x,
y,
width,
height
});
return {
src,
dst
};
};
//# sourceMappingURL=Fitting.js.map

@@ -0,9 +1,21 @@

import type { SharedValue } from "react-native-reanimated";
import type { SkImage } from "../../skia/types";
import { type PlaybackOptions } from "./video";
type Animated<T> = SharedValue<T> | T;
interface PlaybackOptions {
looping: Animated<boolean>;
paused: Animated<boolean>;
seek: Animated<number | null>;
volume: Animated<number>;
}
export declare const useVideo: (source: string | null, userOptions?: Partial<PlaybackOptions>) => {
currentFrame: import("react-native-reanimated").SharedValue<SkImage | null>;
currentTime: import("react-native-reanimated").SharedValue<number>;
currentFrame: SharedValue<SkImage | null>;
currentTime: SharedValue<number>;
duration: number;
framerate: number;
rotationInDegrees: number;
rotation: import("../../skia/types").VideoRotation;
size: {
width: number;
height: number;
};
};
export {};
import { useEffect, useMemo } from "react";
import { Skia } from "../../skia/Skia";
import { Platform } from "../../Platform";
import Rea from "./ReanimatedProxy";
import { processVideoState } from "./video";
const setFrame = (video, currentFrame) => {
"worklet";
const img = video.nextImage();
if (img) {
if (currentFrame.value) {
currentFrame.value.dispose();
}
if (Platform.OS === "android") {
currentFrame.value = img.makeNonTextureImage();
} else {
currentFrame.value = img;
}
}
};
const defaultOptions = {
playbackSpeed: 1,
looping: true,
paused: false,
seek: null,
currentTime: 0
currentTime: 0,
volume: 0
};

@@ -25,3 +40,3 @@ const useOption = value => {

export const useVideo = (source, userOptions) => {
var _userOptions$paused, _userOptions$looping, _userOptions$seek, _userOptions$playback;
var _userOptions$paused, _userOptions$looping, _userOptions$seek, _userOptions$volume;
const video = useMemo(() => source ? Skia.Video(source) : null, [source]);

@@ -31,3 +46,3 @@ const isPaused = useOption((_userOptions$paused = userOptions === null || userOptions === void 0 ? void 0 : userOptions.paused) !== null && _userOptions$paused !== void 0 ? _userOptions$paused : defaultOptions.paused);

const seek = useOption((_userOptions$seek = userOptions === null || userOptions === void 0 ? void 0 : userOptions.seek) !== null && _userOptions$seek !== void 0 ? _userOptions$seek : defaultOptions.seek);
const playbackSpeed = useOption((_userOptions$playback = userOptions === null || userOptions === void 0 ? void 0 : userOptions.playbackSpeed) !== null && _userOptions$playback !== void 0 ? _userOptions$playback : defaultOptions.playbackSpeed);
const volume = useOption((_userOptions$volume = userOptions === null || userOptions === void 0 ? void 0 : userOptions.volume) !== null && _userOptions$volume !== void 0 ? _userOptions$volume : defaultOptions.volume);
const currentFrame = Rea.useSharedValue(null);

@@ -44,12 +59,58 @@ const currentTime = Rea.useSharedValue(0);

}, [video]);
const rotationInDegrees = useMemo(() => {
var _video$getRotationInD;
return (_video$getRotationInD = video === null || video === void 0 ? void 0 : video.getRotationInDegrees()) !== null && _video$getRotationInD !== void 0 ? _video$getRotationInD : 0;
const size = useMemo(() => {
var _video$size;
return (_video$size = video === null || video === void 0 ? void 0 : video.size()) !== null && _video$size !== void 0 ? _video$size : {
width: 0,
height: 0
};
}, [video]);
const rotation = useMemo(() => {
var _video$rotation;
return (_video$rotation = video === null || video === void 0 ? void 0 : video.rotation()) !== null && _video$rotation !== void 0 ? _video$rotation : 0;
}, [video]);
const frameDuration = 1000 / framerate;
const currentFrameDuration = Math.floor(frameDuration);
Rea.useAnimatedReaction(() => isPaused.value, paused => {
if (paused) {
video === null || video === void 0 || video.pause();
} else {
lastTimestamp.value = -1;
video === null || video === void 0 || video.play();
}
});
Rea.useAnimatedReaction(() => seek.value, value => {
if (value !== null) {
video === null || video === void 0 || video.seek(value);
currentTime.value = value;
seek.value = null;
}
});
Rea.useAnimatedReaction(() => volume.value, value => {
video === null || video === void 0 || video.setVolume(value);
});
Rea.useFrameCallback(frameInfo => {
processVideoState(video, duration, framerate, frameInfo.timestamp, {
paused: isPaused.value,
looping: looping.value,
playbackSpeed: playbackSpeed.value
}, currentTime, currentFrame, lastTimestamp, seek);
"worklet";
if (!video) {
return;
}
if (isPaused.value) {
return;
}
const currentTimestamp = frameInfo.timestamp;
if (lastTimestamp.value === -1) {
lastTimestamp.value = currentTimestamp;
}
const delta = currentTimestamp - lastTimestamp.value;
const isOver = currentTime.value + delta > duration;
if (isOver && looping.value) {
seek.value = 0;
currentTime.value = seek.value;
lastTimestamp.value = currentTimestamp;
}
if (delta >= currentFrameDuration && !isOver) {
setFrame(video, currentFrame);
currentTime.value += delta;
lastTimestamp.value = currentTimestamp;
}
});

@@ -67,5 +128,6 @@ useEffect(() => {

framerate,
rotationInDegrees
rotation,
size
};
};
//# sourceMappingURL=useVideo.js.map
import type { ReactNode } from "react";
import React from "react";
import type { Fit } from "../../../dom/nodes";
import type { SkRect } from "../../../skia/types";
import type { SkRect, Transforms3d } from "../../../skia/types";
interface FitProps {

@@ -11,12 +11,4 @@ fit?: Fit;

}
export declare const fitbox: (fit: Fit, src: SkRect, dst: SkRect) => [{
translateX: number;
}, {
translateY: number;
}, {
scaleX: number;
}, {
scaleY: number;
}];
export declare const fitbox: (fit: Fit, src: SkRect, dst: SkRect, rotation?: 0 | 90 | 180 | 270) => Transforms3d;
export declare const FitBox: ({ fit, src, dst, children }: FitProps) => React.JSX.Element;
export {};
import React, { useMemo } from "react";
import { fitRects, rect2rect } from "../../../dom/nodes";
import { Group } from "../Group";
export const fitbox = (fit, src, dst) => {
const rects = fitRects(fit, src, dst);
return rect2rect(rects.src, rects.dst);
export const fitbox = (fit, src, dst, rotation = 0) => {
"worklet";
const rects = fitRects(fit, rotation === 90 || rotation === 270 ? {
x: 0,
y: 0,
width: src.height,
height: src.width
} : src, dst);
const result = rect2rect(rects.src, rects.dst);
if (rotation === 90) {
return [...result, {
translate: [src.height, 0]
}, {
rotate: Math.PI / 2
}];
}
if (rotation === 180) {
return [...result, {
translate: [src.width, src.height]
}, {
rotate: Math.PI
}];
}
if (rotation === 270) {
return [...result, {
translate: [0, src.width]
}, {
rotate: -Math.PI / 2
}];
}
return result;
};

@@ -8,0 +37,0 @@ export const FitBox = ({

import { Skia } from "../Skia";
import { processTransform } from "../types";
export const processTransform2d = transforms => processTransform(Skia.Matrix(), transforms);
export const processTransform2d = transforms => {
"worklet";
return processTransform(Skia.Matrix(), transforms);
};
//# sourceMappingURL=Matrix.js.map
import { processTransform3d } from "./Matrix4";
export const isMatrix = obj => obj !== null && obj.__typename__ === "Matrix";
export const processTransform = (m, transforms) => {
"worklet";
const m3 = processTransform3d(transforms);

@@ -5,0 +7,0 @@ m.concat(m3);

import type { SkImage } from "../Image";
import type { SkJSIInstance } from "../JsiInstance";
export type VideoRotation = 0 | 90 | 180 | 270;
export interface Video extends SkJSIInstance<"Video"> {

@@ -8,3 +9,10 @@ duration(): number;

seek(time: number): void;
getRotationInDegrees(): number;
rotation(): VideoRotation;
size(): {
width: number;
height: number;
};
pause(): void;
play(): void;
setVolume(volume: number): void;
}

@@ -0,9 +1,21 @@

import type { SharedValue } from "react-native-reanimated";
import type { SkImage } from "../../skia/types";
import { type PlaybackOptions } from "./video";
type Animated<T> = SharedValue<T> | T;
interface PlaybackOptions {
looping: Animated<boolean>;
paused: Animated<boolean>;
seek: Animated<number | null>;
volume: Animated<number>;
}
export declare const useVideo: (source: string | null, userOptions?: Partial<PlaybackOptions>) => {
currentFrame: import("react-native-reanimated").SharedValue<SkImage | null>;
currentTime: import("react-native-reanimated").SharedValue<number>;
currentFrame: SharedValue<SkImage | null>;
currentTime: SharedValue<number>;
duration: number;
framerate: number;
rotationInDegrees: number;
rotation: import("../../skia/types").VideoRotation;
size: {
width: number;
height: number;
};
};
export {};
import type { ReactNode } from "react";
import React from "react";
import type { Fit } from "../../../dom/nodes";
import type { SkRect } from "../../../skia/types";
import type { SkRect, Transforms3d } from "../../../skia/types";
interface FitProps {

@@ -11,12 +11,4 @@ fit?: Fit;

}
export declare const fitbox: (fit: Fit, src: SkRect, dst: SkRect) => [{
translateX: number;
}, {
translateY: number;
}, {
scaleX: number;
}, {
scaleY: number;
}];
export declare const fitbox: (fit: Fit, src: SkRect, dst: SkRect, rotation?: 0 | 90 | 180 | 270) => Transforms3d;
export declare const FitBox: ({ fit, src, dst, children }: FitProps) => React.JSX.Element;
export {};
import type { SkImage } from "../Image";
import type { SkJSIInstance } from "../JsiInstance";
export type VideoRotation = 0 | 90 | 180 | 270;
export interface Video extends SkJSIInstance<"Video"> {

@@ -8,3 +9,10 @@ duration(): number;

seek(time: number): void;
getRotationInDegrees(): number;
rotation(): VideoRotation;
size(): {
width: number;
height: number;
};
pause(): void;
play(): void;
setVolume(volume: number): void;
}

@@ -10,3 +10,3 @@ {

"title": "React Native Skia",
"version": "1.3.2",
"version": "1.3.3",
"description": "High-performance React Native Graphics using Skia",

@@ -13,0 +13,0 @@ "main": "lib/module/index.js",

@@ -10,3 +10,6 @@ import { exhaustiveCheck } from "../../../renderer/typeddash";

export const size = (width = 0, height = 0) => ({ width, height });
export const size = (width = 0, height = 0) => {
"worklet";
return { width, height };
};

@@ -22,2 +25,3 @@ export const rect2rect = (

] => {
"worklet";
const scaleX = dst.width / src.width;

@@ -30,22 +34,2 @@ const scaleY = dst.height / src.height;

export const fitRects = (
fit: Fit,
rect: SkRect,
{ x, y, width, height }: SkRect
) => {
const sizes = applyBoxFit(
fit,
{ width: rect.width, height: rect.height },
{ width, height }
);
const src = inscribe(sizes.src, rect);
const dst = inscribe(sizes.dst, {
x,
y,
width,
height,
});
return { src, dst };
};
const inscribe = (

@@ -55,2 +39,3 @@ { width, height }: Size,

) => {
"worklet";
const halfWidthDelta = (rect.width - width) / 2.0;

@@ -67,2 +52,3 @@ const halfHeightDelta = (rect.height - height) / 2.0;

const applyBoxFit = (fit: Fit, input: Size, output: Size) => {
"worklet";
let src = size(),

@@ -130,1 +116,22 @@ dst = size();

};
export const fitRects = (
fit: Fit,
rect: SkRect,
{ x, y, width, height }: SkRect
) => {
"worklet";
const sizes = applyBoxFit(
fit,
{ width: rect.width, height: rect.height },
{ width, height }
);
const src = inscribe(sizes.src, rect);
const dst = inscribe(sizes.dst, {
x,
y,
width,
height,
});
return { src, dst };
};

@@ -1,2 +0,2 @@

import { type FrameInfo } from "react-native-reanimated";
import type { SharedValue, FrameInfo } from "react-native-reanimated";
import { useEffect, useMemo } from "react";

@@ -6,12 +6,31 @@

import type { SkImage, Video } from "../../skia/types";
import { Platform } from "../../Platform";
import Rea from "./ReanimatedProxy";
import {
processVideoState,
type Animated,
type PlaybackOptions,
} from "./video";
type Animated<T> = SharedValue<T> | T;
interface PlaybackOptions {
looping: Animated<boolean>;
paused: Animated<boolean>;
seek: Animated<number | null>;
volume: Animated<number>;
}
const setFrame = (video: Video, currentFrame: SharedValue<SkImage | null>) => {
"worklet";
const img = video.nextImage();
if (img) {
if (currentFrame.value) {
currentFrame.value.dispose();
}
if (Platform.OS === "android") {
currentFrame.value = img.makeNonTextureImage();
} else {
currentFrame.value = img;
}
}
};
const defaultOptions = {
playbackSpeed: 1,
looping: true,

@@ -21,2 +40,3 @@ paused: false,

currentTime: 0,
volume: 0,
};

@@ -46,5 +66,3 @@

const seek = useOption(userOptions?.seek ?? defaultOptions.seek);
const playbackSpeed = useOption(
userOptions?.playbackSpeed ?? defaultOptions.playbackSpeed
);
const volume = useOption(userOptions?.volume ?? defaultOptions.volume);
const currentFrame = Rea.useSharedValue<null | SkImage>(null);

@@ -55,22 +73,58 @@ const currentTime = Rea.useSharedValue(0);

const framerate = useMemo(() => video?.framerate() ?? 0, [video]);
const rotationInDegrees = useMemo(
() => video?.getRotationInDegrees() ?? 0,
[video]
const size = useMemo(() => video?.size() ?? { width: 0, height: 0 }, [video]);
const rotation = useMemo(() => video?.rotation() ?? 0, [video]);
const frameDuration = 1000 / framerate;
const currentFrameDuration = Math.floor(frameDuration);
Rea.useAnimatedReaction(
() => isPaused.value,
(paused) => {
if (paused) {
video?.pause();
} else {
lastTimestamp.value = -1;
video?.play();
}
}
);
Rea.useAnimatedReaction(
() => seek.value,
(value) => {
if (value !== null) {
video?.seek(value);
currentTime.value = value;
seek.value = null;
}
}
);
Rea.useAnimatedReaction(
() => volume.value,
(value) => {
video?.setVolume(value);
}
);
Rea.useFrameCallback((frameInfo: FrameInfo) => {
processVideoState(
video,
duration,
framerate,
frameInfo.timestamp,
{
paused: isPaused.value,
looping: looping.value,
playbackSpeed: playbackSpeed.value,
},
currentTime,
currentFrame,
lastTimestamp,
seek
);
"worklet";
if (!video) {
return;
}
if (isPaused.value) {
return;
}
const currentTimestamp = frameInfo.timestamp;
if (lastTimestamp.value === -1) {
lastTimestamp.value = currentTimestamp;
}
const delta = currentTimestamp - lastTimestamp.value;
const isOver = currentTime.value + delta > duration;
if (isOver && looping.value) {
seek.value = 0;
currentTime.value = seek.value;
lastTimestamp.value = currentTimestamp;
}
if (delta >= currentFrameDuration && !isOver) {
setFrame(video, currentFrame);
currentTime.value += delta;
lastTimestamp.value = currentTimestamp;
}
});

@@ -85,3 +139,10 @@

return { currentFrame, currentTime, duration, framerate, rotationInDegrees };
return {
currentFrame,
currentTime,
duration,
framerate,
rotation,
size,
};
};

@@ -5,3 +5,5 @@ import { Skia } from "../Skia";

export const processTransform2d = (transforms: Transforms3d) =>
processTransform(Skia.Matrix(), transforms);
export const processTransform2d = (transforms: Transforms3d) => {
"worklet";
return processTransform(Skia.Matrix(), transforms);
};

@@ -33,2 +33,3 @@ import type { SkJSIInstance } from "./JsiInstance";

) => {
"worklet";
const m3 = processTransform3d(transforms);

@@ -35,0 +36,0 @@ m.concat(m3);

import type { SkImage } from "../Image";
import type { SkJSIInstance } from "../JsiInstance";
export type VideoRotation = 0 | 90 | 180 | 270;
export interface Video extends SkJSIInstance<"Video"> {

@@ -9,3 +11,7 @@ duration(): number;

seek(time: number): void;
getRotationInDegrees(): number;
rotation(): VideoRotation;
size(): { width: number; height: number };
pause(): void;
play(): void;
setVolume(volume: number): void;
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc