@technotoil/image-video-editor 0.1.4 → 0.1.6
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/android/src/main/java/com/technotoil/image_videoeditor/MediaEditorModule.kt +2 -2
- package/lib/commonjs/screens/EditorScreen.js +61 -33
- package/lib/commonjs/screens/EditorScreen.js.map +1 -1
- package/lib/commonjs/screens/PickScreen.js +280 -172
- package/lib/commonjs/screens/PickScreen.js.map +1 -1
- package/lib/module/screens/EditorScreen.js +61 -33
- package/lib/module/screens/EditorScreen.js.map +1 -1
- package/lib/module/screens/PickScreen.js +280 -172
- package/lib/module/screens/PickScreen.js.map +1 -1
- package/package.json +1 -1
- package/src/screens/EditorScreen.tsx +57 -32
- package/src/screens/PickScreen.tsx +118 -16
|
@@ -449,11 +449,11 @@ class MediaEditorModule(private val reactContext: ReactApplicationContext) :
|
|
|
449
449
|
if (File(fontPath).exists()) {
|
|
450
450
|
val textFilters = mutableListOf<String>()
|
|
451
451
|
for (i in 0 until overlays.size()) {
|
|
452
|
-
val o = overlays.getMap(i)
|
|
452
|
+
val o = overlays.getMap(i) ?: continue
|
|
453
453
|
val text = o.getString("text") ?: continue
|
|
454
454
|
val x = if (o.hasKey("x")) o.getDouble("x") else 0.0
|
|
455
455
|
val y = if (o.hasKey("y")) o.getDouble("y") else 0.0
|
|
456
|
-
val colorHex = if (o.hasKey("color")) o.getString("color") else "#FFFFFF"
|
|
456
|
+
val colorHex = if (o.hasKey("color")) o.getString("color") ?: "#FFFFFF" else "#FFFFFF"
|
|
457
457
|
val fontSize = if (o.hasKey("fontSize")) o.getDouble("fontSize") else 24.0
|
|
458
458
|
|
|
459
459
|
val safeText = text.replace(":", "\\:").replace("'", "\\'")
|
|
@@ -1027,13 +1027,14 @@ function EditorScreen({
|
|
|
1027
1027
|
const containerHeight = showMusicModal ? SCREEN_WIDTH * 0.72 : SCREEN_WIDTH * 1.25;
|
|
1028
1028
|
const maxPan = (0, _react.useMemo)(() => {
|
|
1029
1029
|
// If no cropRatio, we still want to allow panning/zooming if zoomScale > 1
|
|
1030
|
-
|
|
1031
|
-
let
|
|
1032
|
-
let imgH = dimensions.height;
|
|
1030
|
+
let imgW = dimensions.width || item.width || 1080;
|
|
1031
|
+
let imgH = dimensions.height || item.height || 1920;
|
|
1033
1032
|
if ((imageOptions.rotateDegrees || 0) % 180 !== 0) {
|
|
1034
|
-
|
|
1035
|
-
|
|
1033
|
+
const temp = imgW;
|
|
1034
|
+
imgW = imgH;
|
|
1035
|
+
imgH = temp;
|
|
1036
1036
|
}
|
|
1037
|
+
const actualRatio = typeof cropRatio === 'number' ? cropRatio : imgW / (imgH || 1);
|
|
1037
1038
|
const baseH = actualRatio <= 1 ? containerHeight - 24 : (SCREEN_WIDTH - 24) / actualRatio;
|
|
1038
1039
|
const baseW = actualRatio > 1 ? SCREEN_WIDTH - 24 : baseH * actualRatio;
|
|
1039
1040
|
const boxW = baseW * (cropRatio === 'custom' ? cropResizeScaleX : cropResizeScale);
|
|
@@ -1047,7 +1048,7 @@ function EditorScreen({
|
|
|
1047
1048
|
boxW,
|
|
1048
1049
|
boxH
|
|
1049
1050
|
};
|
|
1050
|
-
}, [cropRatio, dimensions, imageOptions.rotateDegrees, zoomScale, cropResizeScale, cropResizeScaleX, cropResizeScaleY, showMusicModal, containerHeight]);
|
|
1051
|
+
}, [cropRatio, dimensions, item, imageOptions.rotateDegrees, zoomScale, cropResizeScale, cropResizeScaleX, cropResizeScaleY, showMusicModal, containerHeight]);
|
|
1051
1052
|
const maxPanRef = (0, _react.useRef)(maxPan);
|
|
1052
1053
|
(0, _react.useEffect)(() => {
|
|
1053
1054
|
maxPanRef.current = maxPan;
|
|
@@ -1093,11 +1094,12 @@ function EditorScreen({
|
|
|
1093
1094
|
}
|
|
1094
1095
|
})).current;
|
|
1095
1096
|
const activeOptions = (0, _react.useMemo)(() => {
|
|
1096
|
-
let imgW = dimensions.width;
|
|
1097
|
-
let imgH = dimensions.height;
|
|
1097
|
+
let imgW = dimensions.width || item.width || 1080;
|
|
1098
|
+
let imgH = dimensions.height || item.height || 1920;
|
|
1098
1099
|
if ((imageOptions.rotateDegrees || 0) % 180 !== 0) {
|
|
1099
|
-
|
|
1100
|
-
|
|
1100
|
+
const temp = imgW;
|
|
1101
|
+
imgW = imgH;
|
|
1102
|
+
imgH = temp;
|
|
1101
1103
|
}
|
|
1102
1104
|
const actualRatio = typeof cropRatio === 'number' ? cropRatio : imgW / (imgH || 1);
|
|
1103
1105
|
const scale = maxPan.scale;
|
|
@@ -1129,7 +1131,7 @@ function EditorScreen({
|
|
|
1129
1131
|
...(hasCrop ? {
|
|
1130
1132
|
crop: finalCrop
|
|
1131
1133
|
} : {}),
|
|
1132
|
-
imageAspectRatio:
|
|
1134
|
+
imageAspectRatio: imgW / (imgH || 1),
|
|
1133
1135
|
frameScale: imageOptions.frame ? frameConfig.scale : 1,
|
|
1134
1136
|
frameOffsetY: imageOptions.frame ? frameConfig.offsetY || 0 : 0,
|
|
1135
1137
|
overlays: overlays.map(o => ({
|
|
@@ -1142,7 +1144,7 @@ function EditorScreen({
|
|
|
1142
1144
|
})),
|
|
1143
1145
|
frameUri: imageOptions.frame && FRAME_IMAGES[imageOptions.frame] ? _reactNative.Image.resolveAssetSource(FRAME_IMAGES[imageOptions.frame]).uri : undefined
|
|
1144
1146
|
};
|
|
1145
|
-
}, [imageOptions, cropOffset, maxPan, dimensions, cropRatio, straightenAngle, overlays]);
|
|
1147
|
+
}, [imageOptions, cropOffset, maxPan, dimensions, item, cropRatio, straightenAngle, overlays]);
|
|
1146
1148
|
|
|
1147
1149
|
// For visual trim
|
|
1148
1150
|
|
|
@@ -2242,10 +2244,9 @@ function EditorScreen({
|
|
|
2242
2244
|
cumulativeMusicOffsetMs += newDuration;
|
|
2243
2245
|
}
|
|
2244
2246
|
} else {
|
|
2245
|
-
if (
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
outUri = await (0, _MediaEditor.trimVideo)(targetItem.uri, {
|
|
2247
|
+
if (targetItem.type === 'image') {
|
|
2248
|
+
if (selectedMusic) {
|
|
2249
|
+
const outUri = await (0, _MediaEditor.trimVideo)(targetItem.uri, {
|
|
2249
2250
|
isImage: true,
|
|
2250
2251
|
musicUri: selectedMusic.url,
|
|
2251
2252
|
musicOffsetMs: cumulativeMusicOffsetMs,
|
|
@@ -2258,9 +2259,17 @@ function EditorScreen({
|
|
|
2258
2259
|
grayscale: false
|
|
2259
2260
|
});
|
|
2260
2261
|
cumulativeMusicOffsetMs += 10000;
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2262
|
+
updatedItems[i] = {
|
|
2263
|
+
...targetItem,
|
|
2264
|
+
uri: outUri,
|
|
2265
|
+
thumbnailUri: outUri
|
|
2266
|
+
};
|
|
2267
|
+
}
|
|
2268
|
+
} else {
|
|
2269
|
+
const needsTrim = selectedMusic || maxVideoDurationMs && (!targetItem.durationMs || targetItem.durationMs > maxVideoDurationMs);
|
|
2270
|
+
if (needsTrim) {
|
|
2271
|
+
const safeEndMs = maxVideoDurationMs ? Math.min(targetItem.durationMs || 10000, maxVideoDurationMs) : targetItem.durationMs || 10000;
|
|
2272
|
+
const outUri = await (0, _MediaEditor.trimVideo)(targetItem.uri, {
|
|
2264
2273
|
startMs: 0,
|
|
2265
2274
|
endMs: safeEndMs,
|
|
2266
2275
|
mute: isMuted,
|
|
@@ -2276,13 +2285,24 @@ function EditorScreen({
|
|
|
2276
2285
|
saturation: 1,
|
|
2277
2286
|
grayscale: false
|
|
2278
2287
|
});
|
|
2288
|
+
let newThumb = undefined;
|
|
2289
|
+
try {
|
|
2290
|
+
newThumb = await (0, _FrameGrabber.captureFrame)(outUri, {
|
|
2291
|
+
timeMs: 0
|
|
2292
|
+
});
|
|
2293
|
+
} catch (e) {
|
|
2294
|
+
console.warn('Could not generate filtered thumb', e);
|
|
2295
|
+
}
|
|
2296
|
+
updatedItems[i] = {
|
|
2297
|
+
...targetItem,
|
|
2298
|
+
uri: outUri,
|
|
2299
|
+
thumbnailUri: newThumb ? newThumb : targetItem.thumbnailUri,
|
|
2300
|
+
durationMs: safeEndMs
|
|
2301
|
+
};
|
|
2279
2302
|
cumulativeMusicOffsetMs += safeEndMs;
|
|
2303
|
+
} else {
|
|
2304
|
+
cumulativeMusicOffsetMs += targetItem.durationMs || 10000;
|
|
2280
2305
|
}
|
|
2281
|
-
updatedItems[i] = {
|
|
2282
|
-
...targetItem,
|
|
2283
|
-
uri: outUri,
|
|
2284
|
-
thumbnailUri: targetItem.type === 'image' ? outUri : targetItem.thumbnailUri
|
|
2285
|
-
};
|
|
2286
2306
|
}
|
|
2287
2307
|
}
|
|
2288
2308
|
}
|
|
@@ -2818,32 +2838,40 @@ function EditorScreen({
|
|
|
2818
2838
|
},
|
|
2819
2839
|
style: styles.filmstripImage
|
|
2820
2840
|
}, idx)), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
2841
|
+
ref: leftOverlayRef,
|
|
2821
2842
|
style: [styles.timelineOverlay, {
|
|
2822
2843
|
left: 0,
|
|
2823
|
-
width:
|
|
2844
|
+
width: startX.current
|
|
2824
2845
|
}]
|
|
2825
2846
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
2847
|
+
ref: rightOverlayRef,
|
|
2826
2848
|
style: [styles.timelineOverlay, {
|
|
2827
|
-
left:
|
|
2849
|
+
left: endX.current,
|
|
2828
2850
|
right: 0
|
|
2829
2851
|
}]
|
|
2830
2852
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
2853
|
+
ref: selectionRangeRef,
|
|
2831
2854
|
style: [styles.selectionRange, {
|
|
2832
|
-
left:
|
|
2833
|
-
width:
|
|
2834
|
-
}]
|
|
2855
|
+
left: startX.current,
|
|
2856
|
+
width: endX.current - startX.current
|
|
2857
|
+
}],
|
|
2858
|
+
...middlePan.panHandlers
|
|
2835
2859
|
})]
|
|
2836
2860
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
2861
|
+
ref: leftHandleRef,
|
|
2837
2862
|
style: [styles.customHandle, styles.customHandleLeft, {
|
|
2838
|
-
left:
|
|
2863
|
+
left: startX.current - 16
|
|
2839
2864
|
}],
|
|
2865
|
+
...startPan.panHandlers,
|
|
2840
2866
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
2841
2867
|
style: styles.handleBarLine
|
|
2842
2868
|
})
|
|
2843
2869
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
2870
|
+
ref: rightHandleRef,
|
|
2844
2871
|
style: [styles.customHandle, styles.customHandleRight, {
|
|
2845
|
-
left:
|
|
2872
|
+
left: endX.current - 16
|
|
2846
2873
|
}],
|
|
2874
|
+
...endPan.panHandlers,
|
|
2847
2875
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
2848
2876
|
style: styles.handleBarLine
|
|
2849
2877
|
})
|
|
@@ -3462,8 +3490,8 @@ function EditorScreen({
|
|
|
3462
3490
|
keyExtractor: it => it.id,
|
|
3463
3491
|
initialScrollIndex: activeIndex,
|
|
3464
3492
|
getItemLayout: (_, index) => ({
|
|
3465
|
-
length:
|
|
3466
|
-
offset:
|
|
3493
|
+
length: SNAP_INTERVAL,
|
|
3494
|
+
offset: SNAP_INTERVAL * index,
|
|
3467
3495
|
index
|
|
3468
3496
|
}),
|
|
3469
3497
|
horizontal: true,
|