@umituz/react-native-video-editor 1.2.0 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/domain/entities/video-project.types.ts +0 -19
- package/src/infrastructure/services/image-layer-operations.service.ts +0 -5
- package/src/infrastructure/services/layer-manipulation.service.ts +1 -15
- package/src/infrastructure/services/layer-operations/layer-transform.service.ts +2 -52
- package/src/infrastructure/services/layer-operations.service.ts +1 -18
- package/src/infrastructure/services/shape-layer-operations.service.ts +0 -5
- package/src/infrastructure/services/text-layer-operations.service.ts +0 -5
- package/src/presentation/components/LayerActionsMenu.tsx +1 -13
- package/src/presentation/components/text-layer/EditorActions.tsx +25 -0
- package/src/presentation/hooks/index.ts +28 -0
- package/src/presentation/hooks/useEditorActions.tsx +0 -3
- package/src/presentation/hooks/useEditorLayers.ts +1 -6
- package/src/presentation/hooks/useLayerActions.tsx +1 -39
- package/src/presentation/hooks/useLayerManipulation.ts +2 -31
- package/src/presentation/hooks/useMenuActions.tsx +0 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-video-editor",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "Professional video editor with layer-based timeline, text/image/shape/audio/animation layers, and export functionality",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -31,14 +31,6 @@ export interface Subtitle {
|
|
|
31
31
|
|
|
32
32
|
export type TransitionType = "fade" | "slide" | "zoom" | "wipe" | "none";
|
|
33
33
|
|
|
34
|
-
export type AnimationType =
|
|
35
|
-
| "fade"
|
|
36
|
-
| "slide"
|
|
37
|
-
| "bounce"
|
|
38
|
-
| "zoom"
|
|
39
|
-
| "rotate"
|
|
40
|
-
| "none";
|
|
41
|
-
|
|
42
34
|
export interface Position {
|
|
43
35
|
x: number;
|
|
44
36
|
y: number;
|
|
@@ -49,13 +41,6 @@ export interface Size {
|
|
|
49
41
|
height: number;
|
|
50
42
|
}
|
|
51
43
|
|
|
52
|
-
export interface Animation {
|
|
53
|
-
type: AnimationType;
|
|
54
|
-
duration: number;
|
|
55
|
-
delay?: number;
|
|
56
|
-
easing?: "linear" | "ease-in" | "ease-out" | "ease-in-out";
|
|
57
|
-
}
|
|
58
|
-
|
|
59
44
|
export interface Transition {
|
|
60
45
|
type: TransitionType;
|
|
61
46
|
duration: number;
|
|
@@ -90,7 +75,6 @@ export interface TextLayer {
|
|
|
90
75
|
| "900";
|
|
91
76
|
color: string;
|
|
92
77
|
textAlign: "left" | "center" | "right";
|
|
93
|
-
animation?: Animation;
|
|
94
78
|
}
|
|
95
79
|
|
|
96
80
|
export interface ImageLayer {
|
|
@@ -101,7 +85,6 @@ export interface ImageLayer {
|
|
|
101
85
|
size: Size;
|
|
102
86
|
rotation: number;
|
|
103
87
|
opacity: number;
|
|
104
|
-
animation?: Animation;
|
|
105
88
|
}
|
|
106
89
|
|
|
107
90
|
export interface VideoLayer {
|
|
@@ -115,7 +98,6 @@ export interface VideoLayer {
|
|
|
115
98
|
startTime: number;
|
|
116
99
|
endTime: number;
|
|
117
100
|
volume: number;
|
|
118
|
-
animation?: Animation;
|
|
119
101
|
}
|
|
120
102
|
|
|
121
103
|
export interface ShapeLayer {
|
|
@@ -129,7 +111,6 @@ export interface ShapeLayer {
|
|
|
129
111
|
fillColor: string;
|
|
130
112
|
borderColor?: string;
|
|
131
113
|
borderWidth?: number;
|
|
132
|
-
animation?: Animation;
|
|
133
114
|
}
|
|
134
115
|
|
|
135
116
|
export type Layer = TextLayer | ImageLayer | VideoLayer | ShapeLayer;
|
|
@@ -20,11 +20,6 @@ class ImageLayerOperationsService extends BaseLayerOperationsService<ImageLayer>
|
|
|
20
20
|
size: { width: 70, height: 40 },
|
|
21
21
|
rotation: 0,
|
|
22
22
|
opacity: layerData.opacity ?? 1,
|
|
23
|
-
animation: {
|
|
24
|
-
type: "fade",
|
|
25
|
-
duration: 500,
|
|
26
|
-
easing: "ease-in-out",
|
|
27
|
-
},
|
|
28
23
|
};
|
|
29
24
|
}
|
|
30
25
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Orchestrator service that delegates to specialized layer operation services
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import type { Scene
|
|
6
|
+
import type { Scene } from "../../domain/entities/video-project.types";
|
|
7
7
|
import type { LayerOperationResult, LayerOrderAction } from "../../domain/entities/video-project.types";
|
|
8
8
|
import { layerDeleteService } from "./layer-operations/layer-delete.service";
|
|
9
9
|
import { layerOrderService } from "./layer-operations/layer-order.service";
|
|
@@ -72,20 +72,6 @@ class LayerManipulationService {
|
|
|
72
72
|
height,
|
|
73
73
|
);
|
|
74
74
|
}
|
|
75
|
-
|
|
76
|
-
updateLayerAnimation(
|
|
77
|
-
scenes: Scene[],
|
|
78
|
-
sceneIndex: number,
|
|
79
|
-
layerId: string,
|
|
80
|
-
animation: Animation | undefined,
|
|
81
|
-
): LayerOperationResult {
|
|
82
|
-
return layerTransformService.updateLayerAnimation(
|
|
83
|
-
scenes,
|
|
84
|
-
sceneIndex,
|
|
85
|
-
layerId,
|
|
86
|
-
animation,
|
|
87
|
-
);
|
|
88
|
-
}
|
|
89
75
|
}
|
|
90
76
|
|
|
91
77
|
export const layerManipulationService = new LayerManipulationService();
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Layer Transform Service
|
|
3
|
-
* Single Responsibility: Handle layer position
|
|
3
|
+
* Single Responsibility: Handle layer position and size updates
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import type { Scene
|
|
6
|
+
import type { Scene } from "../../../domain/entities/video-project.types";
|
|
7
7
|
import type { LayerOperationResult } from "../../../domain/entities/video-project.types";
|
|
8
8
|
|
|
9
9
|
class LayerTransformService {
|
|
@@ -114,56 +114,6 @@ class LayerTransformService {
|
|
|
114
114
|
};
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Update layer animation
|
|
120
|
-
*/
|
|
121
|
-
updateLayerAnimation(
|
|
122
|
-
scenes: Scene[],
|
|
123
|
-
sceneIndex: number,
|
|
124
|
-
layerId: string,
|
|
125
|
-
animation: Animation | undefined,
|
|
126
|
-
): LayerOperationResult {
|
|
127
|
-
try {
|
|
128
|
-
if (sceneIndex < 0 || sceneIndex >= scenes.length) {
|
|
129
|
-
return {
|
|
130
|
-
success: false,
|
|
131
|
-
updatedScenes: scenes,
|
|
132
|
-
error: "Invalid scene index",
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
const updatedScenes = [...scenes];
|
|
137
|
-
const layerIndex = updatedScenes[sceneIndex].layers.findIndex(
|
|
138
|
-
(l) => l.id === layerId,
|
|
139
|
-
);
|
|
140
|
-
|
|
141
|
-
if (layerIndex === -1) {
|
|
142
|
-
return {
|
|
143
|
-
success: false,
|
|
144
|
-
updatedScenes: scenes,
|
|
145
|
-
error: "Layer not found",
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
const existingLayer = updatedScenes[sceneIndex].layers[layerIndex];
|
|
150
|
-
updatedScenes[sceneIndex].layers[layerIndex] = {
|
|
151
|
-
...existingLayer,
|
|
152
|
-
animation,
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
return { success: true, updatedScenes };
|
|
156
|
-
} catch (error) {
|
|
157
|
-
return {
|
|
158
|
-
success: false,
|
|
159
|
-
updatedScenes: scenes,
|
|
160
|
-
error:
|
|
161
|
-
error instanceof Error
|
|
162
|
-
? error.message
|
|
163
|
-
: "Failed to update layer animation",
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
117
|
}
|
|
168
118
|
|
|
169
119
|
export const layerTransformService = new LayerTransformService();
|
|
@@ -7,7 +7,7 @@ import { textLayerOperationsService } from "./text-layer-operations.service";
|
|
|
7
7
|
import { imageLayerOperationsService } from "./image-layer-operations.service";
|
|
8
8
|
import { shapeLayerOperationsService } from "./shape-layer-operations.service";
|
|
9
9
|
import { layerManipulationService } from "./layer-manipulation.service";
|
|
10
|
-
import type { Scene, TextLayer, ImageLayer
|
|
10
|
+
import type { Scene, TextLayer, ImageLayer } from "../../domain/entities/video-project.types";
|
|
11
11
|
import type {
|
|
12
12
|
LayerOperationResult,
|
|
13
13
|
LayerOrderAction,
|
|
@@ -176,23 +176,6 @@ class LayerOperationsService {
|
|
|
176
176
|
height,
|
|
177
177
|
);
|
|
178
178
|
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Update layer animation
|
|
182
|
-
*/
|
|
183
|
-
updateLayerAnimation(
|
|
184
|
-
scenes: Scene[],
|
|
185
|
-
sceneIndex: number,
|
|
186
|
-
layerId: string,
|
|
187
|
-
animation: Animation | undefined,
|
|
188
|
-
): LayerOperationResult {
|
|
189
|
-
return layerManipulationService.updateLayerAnimation(
|
|
190
|
-
scenes,
|
|
191
|
-
sceneIndex,
|
|
192
|
-
layerId,
|
|
193
|
-
animation,
|
|
194
|
-
);
|
|
195
|
-
}
|
|
196
179
|
}
|
|
197
180
|
|
|
198
181
|
export const layerOperationsService = new LayerOperationsService();
|
|
@@ -27,11 +27,6 @@ class ShapeLayerOperationsService extends BaseLayerOperationsService<ShapeLayer>
|
|
|
27
27
|
fillColor: layerData.fillColor ?? defaultColor,
|
|
28
28
|
borderColor: layerData.borderColor,
|
|
29
29
|
borderWidth: layerData.borderWidth,
|
|
30
|
-
animation: {
|
|
31
|
-
type: "fade",
|
|
32
|
-
duration: 500,
|
|
33
|
-
easing: "ease-in-out",
|
|
34
|
-
},
|
|
35
30
|
};
|
|
36
31
|
}
|
|
37
32
|
|
|
@@ -29,11 +29,6 @@ class TextLayerOperationsService extends BaseLayerOperationsService<TextLayer> {
|
|
|
29
29
|
fontWeight: (layerData.fontWeight as TextLayer["fontWeight"]) || "bold",
|
|
30
30
|
color: layerData.color || defaultColor,
|
|
31
31
|
textAlign: layerData.textAlign || "center",
|
|
32
|
-
animation: {
|
|
33
|
-
type: "fade",
|
|
34
|
-
duration: 500,
|
|
35
|
-
easing: "ease-in-out",
|
|
36
|
-
},
|
|
37
32
|
};
|
|
38
33
|
}
|
|
39
34
|
|
|
@@ -13,7 +13,6 @@ interface LayerActionsMenuProps {
|
|
|
13
13
|
layer: Layer;
|
|
14
14
|
onEditText: () => void;
|
|
15
15
|
onEditImage: () => void;
|
|
16
|
-
onAnimate: () => void;
|
|
17
16
|
onDuplicate: () => void;
|
|
18
17
|
onMoveFront: () => void;
|
|
19
18
|
onMoveUp: () => void;
|
|
@@ -26,7 +25,6 @@ export const LayerActionsMenu: React.FC<LayerActionsMenuProps> = ({
|
|
|
26
25
|
layer,
|
|
27
26
|
onEditText,
|
|
28
27
|
onEditImage,
|
|
29
|
-
onAnimate,
|
|
30
28
|
onDuplicate,
|
|
31
29
|
onMoveFront,
|
|
32
30
|
onMoveUp,
|
|
@@ -59,13 +57,6 @@ export const LayerActionsMenu: React.FC<LayerActionsMenuProps> = ({
|
|
|
59
57
|
|
|
60
58
|
// Common actions
|
|
61
59
|
items.push(
|
|
62
|
-
{
|
|
63
|
-
id: "animate",
|
|
64
|
-
label: layer.animation
|
|
65
|
-
? (t("editor.layers.actions.editAnimation") || "Edit Animation")
|
|
66
|
-
: (t("editor.layers.actions.addAnimation") || "Add Animation"),
|
|
67
|
-
icon: "sparkles-outline",
|
|
68
|
-
},
|
|
69
60
|
{
|
|
70
61
|
id: "duplicate",
|
|
71
62
|
label: t("editor.layers.actions.duplicate") || "Duplicate",
|
|
@@ -111,9 +102,6 @@ export const LayerActionsMenu: React.FC<LayerActionsMenuProps> = ({
|
|
|
111
102
|
case "edit-image":
|
|
112
103
|
onEditImage();
|
|
113
104
|
break;
|
|
114
|
-
case "animate":
|
|
115
|
-
onAnimate();
|
|
116
|
-
break;
|
|
117
105
|
case "duplicate":
|
|
118
106
|
onDuplicate();
|
|
119
107
|
break;
|
|
@@ -133,7 +121,7 @@ export const LayerActionsMenu: React.FC<LayerActionsMenuProps> = ({
|
|
|
133
121
|
onDelete();
|
|
134
122
|
break;
|
|
135
123
|
}
|
|
136
|
-
}, [onEditText, onEditImage,
|
|
124
|
+
}, [onEditText, onEditImage, onDuplicate, onMoveFront, onMoveUp, onMoveDown, onMoveBack, onDelete]);
|
|
137
125
|
|
|
138
126
|
return <ActionMenu actions={menuItems} onSelect={handleSelect} testID="layer-actions-menu" />;
|
|
139
127
|
};
|
|
@@ -14,6 +14,8 @@ interface EditorActionsProps {
|
|
|
14
14
|
onSave: () => void;
|
|
15
15
|
saveLabel: string;
|
|
16
16
|
isValid: boolean;
|
|
17
|
+
onRemove?: () => void;
|
|
18
|
+
removeLabel?: string;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
export const EditorActions: React.FC<EditorActionsProps> = ({
|
|
@@ -21,6 +23,8 @@ export const EditorActions: React.FC<EditorActionsProps> = ({
|
|
|
21
23
|
onSave,
|
|
22
24
|
saveLabel,
|
|
23
25
|
isValid,
|
|
26
|
+
onRemove,
|
|
27
|
+
removeLabel,
|
|
24
28
|
}) => {
|
|
25
29
|
const tokens = useAppDesignTokens();
|
|
26
30
|
const { t } = useLocalization();
|
|
@@ -29,6 +33,24 @@ export const EditorActions: React.FC<EditorActionsProps> = ({
|
|
|
29
33
|
<View
|
|
30
34
|
style={[styles.actions, { borderTopColor: tokens.colors.borderLight }]}
|
|
31
35
|
>
|
|
36
|
+
{onRemove && (
|
|
37
|
+
<TouchableOpacity
|
|
38
|
+
style={[
|
|
39
|
+
styles.actionButton,
|
|
40
|
+
styles.removeButton,
|
|
41
|
+
{ borderColor: tokens.colors.error },
|
|
42
|
+
]}
|
|
43
|
+
onPress={onRemove}
|
|
44
|
+
>
|
|
45
|
+
<AtomicText
|
|
46
|
+
type="bodyMedium"
|
|
47
|
+
style={{ color: tokens.colors.error }}
|
|
48
|
+
>
|
|
49
|
+
{removeLabel || t("common.buttons.remove")}
|
|
50
|
+
</AtomicText>
|
|
51
|
+
</TouchableOpacity>
|
|
52
|
+
)}
|
|
53
|
+
|
|
32
54
|
<TouchableOpacity
|
|
33
55
|
style={[
|
|
34
56
|
styles.actionButton,
|
|
@@ -83,6 +105,9 @@ const styles = StyleSheet.create({
|
|
|
83
105
|
alignItems: "center",
|
|
84
106
|
justifyContent: "center",
|
|
85
107
|
},
|
|
108
|
+
removeButton: {
|
|
109
|
+
borderWidth: 1,
|
|
110
|
+
},
|
|
86
111
|
cancelButton: {
|
|
87
112
|
borderWidth: 1,
|
|
88
113
|
},
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Presentation Hooks
|
|
3
|
+
* All hooks for the video editor presentation layer
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export { useAudioLayerForm } from "./useAudioLayerForm";
|
|
7
|
+
export { useCollageEditor } from "./useCollageEditor";
|
|
8
|
+
export { useDraggableLayerGestures } from "./useDraggableLayerGestures";
|
|
9
|
+
export { useEditorActions } from "./useEditorActions";
|
|
10
|
+
export { useEditorBottomSheet } from "./useEditorBottomSheet";
|
|
11
|
+
export { useEditorHistory } from "./useEditorHistory";
|
|
12
|
+
export { useEditorLayers } from "./useEditorLayers";
|
|
13
|
+
export { useEditorPlayback } from "./useEditorPlayback";
|
|
14
|
+
export { useEditorScenes } from "./useEditorScenes";
|
|
15
|
+
export { useExport } from "./useExport";
|
|
16
|
+
export { useExportActions } from "./useExportActions";
|
|
17
|
+
export { useExportForm } from "./useExportForm";
|
|
18
|
+
export { useImageLayerForm } from "./useImageLayerForm";
|
|
19
|
+
export { useImageLayerOperations } from "./useImageLayerOperations";
|
|
20
|
+
export { useLayerActions } from "./useLayerActions";
|
|
21
|
+
export { useLayerManipulation } from "./useLayerManipulation";
|
|
22
|
+
export { useMenuActions } from "./useMenuActions";
|
|
23
|
+
export { useSceneActions } from "./useSceneActions";
|
|
24
|
+
export { useShapeLayerForm } from "./useShapeLayerForm";
|
|
25
|
+
export { useShapeLayerOperations } from "./useShapeLayerOperations";
|
|
26
|
+
export { useSubtitleEditor } from "./useSubtitleEditor";
|
|
27
|
+
export { useTextLayerForm } from "./useTextLayerForm";
|
|
28
|
+
export { useTextLayerOperations } from "./useTextLayerOperations";
|
|
@@ -29,7 +29,6 @@ interface UseEditorActionsReturn {
|
|
|
29
29
|
handleEditImageLayer: (layerId: string) => void;
|
|
30
30
|
handleAddShape: () => void;
|
|
31
31
|
handleAudio: () => void;
|
|
32
|
-
handleAnimate: (layerId: string) => void;
|
|
33
32
|
handleLayerActionsPress: (layer: Layer) => void;
|
|
34
33
|
handleSceneLongPress: (index: number) => void;
|
|
35
34
|
handleExport: () => void;
|
|
@@ -63,7 +62,6 @@ export function useEditorActions({
|
|
|
63
62
|
bottomSheet,
|
|
64
63
|
handleEditLayer: layerActions.handleEditLayer,
|
|
65
64
|
handleEditImageLayer: layerActions.handleEditImageLayer,
|
|
66
|
-
handleAnimate: layerActions.handleAnimate,
|
|
67
65
|
});
|
|
68
66
|
|
|
69
67
|
const exportActions = useExportActions({
|
|
@@ -84,7 +82,6 @@ export function useEditorActions({
|
|
|
84
82
|
handleEditImageLayer: layerActions.handleEditImageLayer,
|
|
85
83
|
handleAddShape: layerActions.handleAddShape,
|
|
86
84
|
handleAudio: sceneActions.handleAudio,
|
|
87
|
-
handleAnimate: layerActions.handleAnimate,
|
|
88
85
|
handleLayerActionsPress: menuActions.handleLayerActionsPress,
|
|
89
86
|
handleSceneLongPress,
|
|
90
87
|
handleExport: exportActions.handleExport,
|
|
@@ -14,7 +14,7 @@ import type {
|
|
|
14
14
|
LayerOrderAction,
|
|
15
15
|
Scene,
|
|
16
16
|
} from "../../domain/entities/video-project.types";
|
|
17
|
-
import type { TextLayer, ImageLayer
|
|
17
|
+
import type { TextLayer, ImageLayer } from "../../domain/entities/video-project.types";
|
|
18
18
|
|
|
19
19
|
interface UseEditorLayersParams {
|
|
20
20
|
projectId: string;
|
|
@@ -37,10 +37,6 @@ export interface UseEditorLayersReturn {
|
|
|
37
37
|
duplicateLayer: (layerId: string) => void;
|
|
38
38
|
updateLayerPosition: (layerId: string, x: number, y: number) => void;
|
|
39
39
|
updateLayerSize: (layerId: string, width: number, height: number) => void;
|
|
40
|
-
updateLayerAnimation: (
|
|
41
|
-
layerId: string,
|
|
42
|
-
animation: Animation | undefined,
|
|
43
|
-
) => void;
|
|
44
40
|
}
|
|
45
41
|
|
|
46
42
|
export function useEditorLayers({
|
|
@@ -93,6 +89,5 @@ export function useEditorLayers({
|
|
|
93
89
|
duplicateLayer: layerManipulation.duplicateLayer,
|
|
94
90
|
updateLayerPosition: layerManipulation.updateLayerPosition,
|
|
95
91
|
updateLayerSize: layerManipulation.updateLayerSize,
|
|
96
|
-
updateLayerAnimation: layerManipulation.updateLayerAnimation,
|
|
97
92
|
};
|
|
98
93
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* useLayerActions Hook
|
|
3
|
-
* Single Responsibility: Layer action handlers (add, edit
|
|
3
|
+
* Single Responsibility: Layer action handlers (add, edit)
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { useCallback } from "react";
|
|
@@ -8,7 +8,6 @@ import { useLocalization } from "@umituz/react-native-settings";
|
|
|
8
8
|
import { TextLayerEditor } from "../components/TextLayerEditor";
|
|
9
9
|
import { ImageLayerEditor } from "../components/ImageLayerEditor";
|
|
10
10
|
import { ShapeLayerEditor } from "../components/ShapeLayerEditor";
|
|
11
|
-
import { AnimationEditor } from "../components/AnimationEditor";
|
|
12
11
|
import type { Scene, Layer } from "../../domain/entities/video-project.types";
|
|
13
12
|
import type { UseEditorLayersReturn } from "./useEditorLayers";
|
|
14
13
|
import type { UseEditorBottomSheetReturn } from "./useEditorBottomSheet";
|
|
@@ -26,7 +25,6 @@ interface UseLayerActionsReturn {
|
|
|
26
25
|
handleAddImage: () => void;
|
|
27
26
|
handleEditImageLayer: (layerId: string) => void;
|
|
28
27
|
handleAddShape: () => void;
|
|
29
|
-
handleAnimate: (layerId: string) => void;
|
|
30
28
|
}
|
|
31
29
|
|
|
32
30
|
export function useLayerActions({
|
|
@@ -120,47 +118,11 @@ export function useLayerActions({
|
|
|
120
118
|
});
|
|
121
119
|
}, [layers.addShapeLayer, openBottomSheet, closeBottomSheet, t]);
|
|
122
120
|
|
|
123
|
-
const handleAnimate = useCallback(
|
|
124
|
-
(layerId: string) => {
|
|
125
|
-
if (!currentScene) return;
|
|
126
|
-
const layer = currentScene.layers.find((l: Layer) => l.id === layerId);
|
|
127
|
-
if (!layer) return;
|
|
128
|
-
|
|
129
|
-
openBottomSheet({
|
|
130
|
-
title: layer.animation
|
|
131
|
-
? t("editor.layers.animation.edit")
|
|
132
|
-
: t("editor.layers.animation.add"),
|
|
133
|
-
children: (
|
|
134
|
-
<AnimationEditor
|
|
135
|
-
animation={layer.animation}
|
|
136
|
-
onSave={(animation) =>
|
|
137
|
-
layers.updateLayerAnimation(layerId, animation)
|
|
138
|
-
}
|
|
139
|
-
onRemove={
|
|
140
|
-
layer.animation
|
|
141
|
-
? () => layers.updateLayerAnimation(layerId, undefined)
|
|
142
|
-
: undefined
|
|
143
|
-
}
|
|
144
|
-
onCancel={closeBottomSheet}
|
|
145
|
-
/>
|
|
146
|
-
),
|
|
147
|
-
});
|
|
148
|
-
},
|
|
149
|
-
[
|
|
150
|
-
currentScene,
|
|
151
|
-
layers.updateLayerAnimation,
|
|
152
|
-
openBottomSheet,
|
|
153
|
-
closeBottomSheet,
|
|
154
|
-
t,
|
|
155
|
-
],
|
|
156
|
-
);
|
|
157
|
-
|
|
158
121
|
return {
|
|
159
122
|
handleAddText,
|
|
160
123
|
handleEditLayer,
|
|
161
124
|
handleAddImage,
|
|
162
125
|
handleEditImageLayer,
|
|
163
126
|
handleAddShape,
|
|
164
|
-
handleAnimate,
|
|
165
127
|
};
|
|
166
128
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* useLayerManipulation Hook
|
|
3
|
-
* Single Responsibility: Layer manipulation operations (delete, order, duplicate, position, size
|
|
3
|
+
* Single Responsibility: Layer manipulation operations (delete, order, duplicate, position, size)
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { useCallback } from "react";
|
|
7
7
|
import { Alert } from "react-native";
|
|
8
8
|
import { useLocalization } from "@umituz/react-native-settings";
|
|
9
9
|
import { layerOperationsService } from "../../infrastructure/services/layer-operations.service";
|
|
10
|
-
import type { Scene, LayerOrderAction
|
|
10
|
+
import type { Scene, LayerOrderAction } from "../../domain/entities/video-project.types";
|
|
11
11
|
|
|
12
12
|
interface UseLayerManipulationParams {
|
|
13
13
|
scenes: Scene[];
|
|
@@ -23,10 +23,6 @@ interface UseLayerManipulationReturn {
|
|
|
23
23
|
duplicateLayer: (layerId: string) => void;
|
|
24
24
|
updateLayerPosition: (layerId: string, x: number, y: number) => void;
|
|
25
25
|
updateLayerSize: (layerId: string, width: number, height: number) => void;
|
|
26
|
-
updateLayerAnimation: (
|
|
27
|
-
layerId: string,
|
|
28
|
-
animation: Animation | undefined,
|
|
29
|
-
) => void;
|
|
30
26
|
}
|
|
31
27
|
|
|
32
28
|
export function useLayerManipulation({
|
|
@@ -136,36 +132,11 @@ export function useLayerManipulation({
|
|
|
136
132
|
[scenes, sceneIndex, onUpdateScenes],
|
|
137
133
|
);
|
|
138
134
|
|
|
139
|
-
const updateLayerAnimation = useCallback(
|
|
140
|
-
(layerId: string, animation: Animation | undefined) => {
|
|
141
|
-
const result = layerOperationsService.updateLayerAnimation(
|
|
142
|
-
scenes,
|
|
143
|
-
sceneIndex,
|
|
144
|
-
layerId,
|
|
145
|
-
animation,
|
|
146
|
-
);
|
|
147
|
-
if (result.success) {
|
|
148
|
-
onUpdateScenes(result.updatedScenes);
|
|
149
|
-
onCloseBottomSheet();
|
|
150
|
-
Alert.alert(
|
|
151
|
-
t("editor.layers.animation.success"),
|
|
152
|
-
t(animation
|
|
153
|
-
? "editor.layers.animation.applied"
|
|
154
|
-
: "editor.layers.animation.removed"),
|
|
155
|
-
);
|
|
156
|
-
} else {
|
|
157
|
-
Alert.alert(t("editor.layers.animation.error"));
|
|
158
|
-
}
|
|
159
|
-
},
|
|
160
|
-
[scenes, sceneIndex, onUpdateScenes, onCloseBottomSheet, t],
|
|
161
|
-
);
|
|
162
|
-
|
|
163
135
|
return {
|
|
164
136
|
deleteLayer,
|
|
165
137
|
changeLayerOrder,
|
|
166
138
|
duplicateLayer,
|
|
167
139
|
updateLayerPosition,
|
|
168
140
|
updateLayerSize,
|
|
169
|
-
updateLayerAnimation,
|
|
170
141
|
};
|
|
171
142
|
}
|
|
@@ -15,7 +15,6 @@ interface UseMenuActionsParams {
|
|
|
15
15
|
bottomSheet: UseEditorBottomSheetReturn;
|
|
16
16
|
handleEditLayer: () => void;
|
|
17
17
|
handleEditImageLayer: (layerId: string) => void;
|
|
18
|
-
handleAnimate: (layerId: string) => void;
|
|
19
18
|
}
|
|
20
19
|
|
|
21
20
|
interface UseMenuActionsReturn {
|
|
@@ -27,7 +26,6 @@ export function useMenuActions({
|
|
|
27
26
|
bottomSheet,
|
|
28
27
|
handleEditLayer,
|
|
29
28
|
handleEditImageLayer,
|
|
30
|
-
handleAnimate,
|
|
31
29
|
}: UseMenuActionsParams): UseMenuActionsReturn {
|
|
32
30
|
const { openBottomSheet, closeBottomSheet } = bottomSheet;
|
|
33
31
|
|
|
@@ -59,11 +57,6 @@ export function useMenuActions({
|
|
|
59
57
|
const timer = setTimeout(() => handleEditImageLayer(layer.id), 300);
|
|
60
58
|
timersRef.current.push(timer);
|
|
61
59
|
}}
|
|
62
|
-
onAnimate={() => {
|
|
63
|
-
closeBottomSheet();
|
|
64
|
-
const timer = setTimeout(() => handleAnimate(layer.id), 300);
|
|
65
|
-
timersRef.current.push(timer);
|
|
66
|
-
}}
|
|
67
60
|
onDuplicate={() => {
|
|
68
61
|
closeBottomSheet();
|
|
69
62
|
layers.duplicateLayer(layer.id);
|
|
@@ -96,7 +89,6 @@ export function useMenuActions({
|
|
|
96
89
|
layers,
|
|
97
90
|
handleEditLayer,
|
|
98
91
|
handleEditImageLayer,
|
|
99
|
-
handleAnimate,
|
|
100
92
|
openBottomSheet,
|
|
101
93
|
closeBottomSheet,
|
|
102
94
|
],
|