@umituz/react-native-video-editor 1.0.1 → 1.0.3
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 +6 -1
- package/src/domain/entities/index.ts +5 -3
- package/src/domain/entities/video-project.types.ts +1 -1
- package/src/index.ts +25 -1
- package/src/infrastructure/constants/animation-layer.constants.ts +1 -1
- package/src/infrastructure/services/image-layer-operations.service.ts +1 -1
- package/src/infrastructure/services/layer-manipulation.service.ts +1 -1
- package/src/infrastructure/services/layer-operations/layer-delete.service.ts +1 -1
- package/src/infrastructure/services/layer-operations/layer-duplicate.service.ts +1 -1
- package/src/infrastructure/services/layer-operations/layer-order.service.ts +1 -1
- package/src/infrastructure/services/layer-operations/layer-transform.service.ts +1 -1
- package/src/infrastructure/services/layer-operations.service.ts +1 -1
- package/src/infrastructure/services/scene-operations.service.ts +1 -1
- package/src/infrastructure/services/shape-layer-operations.service.ts +1 -1
- package/src/infrastructure/services/text-layer-operations.service.ts +1 -1
- package/src/player/index.ts +31 -0
- package/src/player/infrastructure/services/player-control.service.ts +95 -0
- package/src/player/presentation/components/VideoPlayer.tsx +135 -0
- package/src/player/presentation/hooks/useVideoPlayerControl.ts +82 -0
- package/src/player/presentation/hooks/useVideoVisibility.ts +62 -0
- package/src/player/types/index.ts +74 -0
- package/src/presentation/components/AnimationEditor.tsx +1 -1
- package/src/presentation/components/AudioEditor.tsx +1 -1
- package/src/presentation/components/DraggableLayer.tsx +1 -1
- package/src/presentation/components/EditorPreviewArea.tsx +1 -1
- package/src/presentation/components/EditorTimeline.tsx +1 -1
- package/src/presentation/components/EditorToolPanel.tsx +1 -1
- package/src/presentation/components/ExportDialog.tsx +1 -1
- package/src/presentation/components/ImageLayerEditor.tsx +1 -1
- package/src/presentation/components/LayerActionsMenu.tsx +1 -1
- package/src/presentation/components/ShapeLayerEditor.tsx +1 -1
- package/src/presentation/components/TextLayerEditor.tsx +1 -1
- package/src/presentation/components/animation-layer/AnimationTypeSelector.tsx +1 -1
- package/src/presentation/components/draggable-layer/LayerContent.tsx +1 -1
- package/src/presentation/components/export/ExportActions.tsx +2 -2
- package/src/presentation/components/export/ExportProgress.tsx +1 -1
- package/src/presentation/components/export/ProjectInfoBox.tsx +1 -1
- package/src/presentation/hooks/useAnimationLayerForm.ts +1 -1
- package/src/presentation/hooks/useAudioLayerForm.ts +1 -1
- package/src/presentation/hooks/useEditorActions.tsx +1 -1
- package/src/presentation/hooks/useEditorHistory.ts +1 -1
- package/src/presentation/hooks/useEditorLayers.ts +1 -1
- package/src/presentation/hooks/useEditorPlayback.ts +1 -1
- package/src/presentation/hooks/useEditorScenes.ts +1 -1
- package/src/presentation/hooks/useExport.ts +34 -19
- package/src/presentation/hooks/useExportActions.tsx +1 -1
- package/src/presentation/hooks/useExportForm.ts +1 -1
- package/src/presentation/hooks/useImageLayerForm.ts +1 -1
- package/src/presentation/hooks/useImageLayerOperations.ts +1 -1
- package/src/presentation/hooks/useLayerActions.tsx +1 -1
- package/src/presentation/hooks/useLayerManipulation.ts +1 -1
- package/src/presentation/hooks/useShapeLayerForm.ts +1 -1
- package/src/presentation/hooks/useTextLayerForm.ts +1 -1
- package/src/presentation/hooks/useTextLayerOperations.ts +1 -1
- package/src/infrastructure/services/export-orchestrator.service.ts +0 -122
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Video Player Types
|
|
3
|
+
* Core type definitions for video playback functionality
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { VideoPlayer } from "expo-video";
|
|
7
|
+
import type { ViewStyle } from "react-native";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Configuration for video player initialization
|
|
11
|
+
*/
|
|
12
|
+
export interface VideoPlayerConfig {
|
|
13
|
+
readonly source: string | null;
|
|
14
|
+
readonly loop?: boolean;
|
|
15
|
+
readonly muted?: boolean;
|
|
16
|
+
readonly autoPlay?: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Current state of the video player
|
|
21
|
+
*/
|
|
22
|
+
export interface VideoPlayerState {
|
|
23
|
+
readonly isPlaying: boolean;
|
|
24
|
+
readonly isPlayerValid: boolean;
|
|
25
|
+
readonly isLoading: boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Video player control actions
|
|
30
|
+
*/
|
|
31
|
+
export interface VideoPlayerControls {
|
|
32
|
+
readonly play: () => void;
|
|
33
|
+
readonly pause: () => void;
|
|
34
|
+
readonly toggle: () => void;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Combined hook return type
|
|
39
|
+
*/
|
|
40
|
+
export interface UseVideoPlayerControlResult {
|
|
41
|
+
readonly player: VideoPlayer | null;
|
|
42
|
+
readonly state: VideoPlayerState;
|
|
43
|
+
readonly controls: VideoPlayerControls;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Visibility hook configuration
|
|
48
|
+
*/
|
|
49
|
+
export interface VideoVisibilityConfig {
|
|
50
|
+
readonly isVisible: boolean;
|
|
51
|
+
readonly player: VideoPlayer | null;
|
|
52
|
+
readonly isPlayerValid: boolean;
|
|
53
|
+
readonly onPlayingChange?: (isPlaying: boolean) => void;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Video player component props
|
|
58
|
+
*/
|
|
59
|
+
export interface VideoPlayerProps {
|
|
60
|
+
readonly source: string | null;
|
|
61
|
+
readonly isVisible?: boolean;
|
|
62
|
+
readonly loop?: boolean;
|
|
63
|
+
readonly muted?: boolean;
|
|
64
|
+
readonly autoPlay?: boolean;
|
|
65
|
+
readonly showControls?: boolean;
|
|
66
|
+
readonly nativeControls?: boolean;
|
|
67
|
+
readonly onPlayingChange?: (isPlaying: boolean) => void;
|
|
68
|
+
readonly onError?: (error: Error) => void;
|
|
69
|
+
readonly style?: ViewStyle;
|
|
70
|
+
readonly contentFit?: "contain" | "cover" | "fill";
|
|
71
|
+
readonly thumbnailUrl?: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export type { VideoPlayer } from "expo-video";
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import React from "react";
|
|
7
7
|
import { View, ScrollView, StyleSheet } from "react-native";
|
|
8
8
|
import { useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
9
|
-
import type { Animation } from "
|
|
9
|
+
import type { Animation } from "../../../domain/entities";
|
|
10
10
|
import { useAnimationLayerForm } from "../../hooks/useAnimationLayerForm";
|
|
11
11
|
import {
|
|
12
12
|
DURATIONS,
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
AtomicText,
|
|
11
11
|
useAppDesignTokens,
|
|
12
12
|
} from "@umituz/react-native-design-system";
|
|
13
|
-
import type { Audio } from "
|
|
13
|
+
import type { Audio } from "../../../domain/entities";
|
|
14
14
|
import { useAudioLayerForm } from "../../hooks/useAudioLayerForm";
|
|
15
15
|
import { AUDIO_FILE_TYPES } from "../../constants/audio-layer.constants";
|
|
16
16
|
import {
|
|
@@ -8,7 +8,7 @@ import { StyleSheet } from "react-native";
|
|
|
8
8
|
import { GestureDetector } from "react-native-gesture-handler";
|
|
9
9
|
import Animated, { useAnimatedStyle } from "react-native-reanimated";
|
|
10
10
|
import { useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
11
|
-
import type { Layer } from "
|
|
11
|
+
import type { Layer } from "../../../domain/entities";
|
|
12
12
|
import { useDraggableLayerGestures } from "../../hooks/useDraggableLayerGestures";
|
|
13
13
|
import { LayerContent } from "./draggable-layer/LayerContent";
|
|
14
14
|
import { ResizeHandles } from "./draggable-layer/ResizeHandles";
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
useAppDesignTokens,
|
|
12
12
|
} from "@umituz/react-native-design-system";
|
|
13
13
|
import { DraggableLayer } from "./DraggableLayer";
|
|
14
|
-
import type { Scene, Layer, ImageLayer } from "
|
|
14
|
+
import type { Scene, Layer, ImageLayer } from "../../../domain/entities";
|
|
15
15
|
|
|
16
16
|
const { width } = Dimensions.get("window");
|
|
17
17
|
const PREVIEW_ASPECT_RATIO = 16 / 9;
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
useAppDesignTokens,
|
|
12
12
|
} from "@umituz/react-native-design-system";
|
|
13
13
|
import { useLocalization } from "@umituz/react-native-localization";
|
|
14
|
-
import type { VideoProject, Scene } from "
|
|
14
|
+
import type { VideoProject, Scene } from "../../../domain/entities";
|
|
15
15
|
|
|
16
16
|
export interface EditorTimelineProps {
|
|
17
17
|
project: VideoProject;
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
useAppDesignTokens,
|
|
18
18
|
} from "@umituz/react-native-design-system";
|
|
19
19
|
import { useLocalization } from "@umituz/react-native-localization";
|
|
20
|
-
import type { Audio } from "
|
|
20
|
+
import type { Audio } from "../../../domain/entities";
|
|
21
21
|
|
|
22
22
|
export interface EditorToolPanelProps {
|
|
23
23
|
onAddText: () => void;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import React, { useCallback } from "react";
|
|
7
7
|
import { View, ScrollView, StyleSheet } from "react-native";
|
|
8
8
|
import { useLocalization } from "@umituz/react-native-localization";
|
|
9
|
-
import type { ExportSettings, VideoProject } from "
|
|
9
|
+
import type { ExportSettings, VideoProject } from "../../../domain/entities";
|
|
10
10
|
import { useExportForm } from "../../hooks/useExportForm";
|
|
11
11
|
import { useExport } from "../../hooks/useExport";
|
|
12
12
|
import {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import React, { useCallback } from "react";
|
|
7
7
|
import { View, ScrollView, StyleSheet, Alert } from "react-native";
|
|
8
8
|
import { useImagePicker } from "@/domains/media";
|
|
9
|
-
import type { ImageLayer } from "
|
|
9
|
+
import type { ImageLayer } from "../../../domain/entities";
|
|
10
10
|
import { useImageLayerForm } from "../../hooks/useImageLayerForm";
|
|
11
11
|
import { IMAGE_PICKER_OPTIONS } from "../../constants/image-layer.constants";
|
|
12
12
|
import {
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
AtomicIcon,
|
|
11
11
|
useAppDesignTokens,
|
|
12
12
|
} from "@umituz/react-native-design-system";
|
|
13
|
-
import type { Layer, ImageLayer } from "
|
|
13
|
+
import type { Layer, ImageLayer } from "../../../domain/entities";
|
|
14
14
|
|
|
15
15
|
export interface LayerActionsMenuProps {
|
|
16
16
|
layer: Layer;
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
AtomicIcon,
|
|
11
11
|
useAppDesignTokens,
|
|
12
12
|
} from "@umituz/react-native-design-system";
|
|
13
|
-
import type { ShapeLayer } from "
|
|
13
|
+
import type { ShapeLayer } from "../../../domain/entities";
|
|
14
14
|
import { useShapeLayerForm } from "../../hooks/useShapeLayerForm";
|
|
15
15
|
import {
|
|
16
16
|
BORDER_WIDTHS,
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import React from "react";
|
|
7
7
|
import { View, ScrollView, StyleSheet } from "react-native";
|
|
8
8
|
import { useLocalization } from "@umituz/react-native-localization";
|
|
9
|
-
import type { TextLayer } from "
|
|
9
|
+
import type { TextLayer } from "../../../domain/entities";
|
|
10
10
|
import { useTextLayerForm } from "../../hooks/useTextLayerForm";
|
|
11
11
|
import {
|
|
12
12
|
FONT_FAMILIES,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
useAppDesignTokens,
|
|
12
12
|
} from "@umituz/react-native-design-system";
|
|
13
13
|
import { ANIMATION_TYPES } from "../../../constants/animation-layer.constants";
|
|
14
|
-
import type { AnimationType } from "
|
|
14
|
+
import type { AnimationType } from "../../../domain/entities";
|
|
15
15
|
|
|
16
16
|
interface AnimationTypeSelectorProps {
|
|
17
17
|
selectedType: AnimationType;
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
AtomicIcon,
|
|
10
10
|
useAppDesignTokens,
|
|
11
11
|
} from "@umituz/react-native-design-system";
|
|
12
|
-
import type { Layer, TextLayer, ImageLayer, ShapeLayer } from "
|
|
12
|
+
import type { Layer, TextLayer, ImageLayer, ShapeLayer } from "../../../domain/entities";
|
|
13
13
|
|
|
14
14
|
interface LayerContentProps {
|
|
15
15
|
layer: Layer;
|
|
@@ -8,11 +8,11 @@ import {
|
|
|
8
8
|
View,
|
|
9
9
|
StyleSheet,
|
|
10
10
|
TouchableOpacity,
|
|
11
|
-
ActivityIndicator,
|
|
12
11
|
} from "react-native";
|
|
13
12
|
import {
|
|
14
13
|
AtomicText,
|
|
15
14
|
AtomicIcon,
|
|
15
|
+
AtomicSpinner,
|
|
16
16
|
useAppDesignTokens,
|
|
17
17
|
} from "@umituz/react-native-design-system";
|
|
18
18
|
|
|
@@ -64,7 +64,7 @@ export const ExportActions: React.FC<ExportActionsProps> = ({
|
|
|
64
64
|
disabled={isExporting}
|
|
65
65
|
>
|
|
66
66
|
{isExporting ? (
|
|
67
|
-
<
|
|
67
|
+
<AtomicSpinner size="sm" color="white" />
|
|
68
68
|
) : (
|
|
69
69
|
<AtomicIcon name="Download" size="sm" color="onSurface" />
|
|
70
70
|
)}
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
AtomicText,
|
|
10
10
|
useAppDesignTokens,
|
|
11
11
|
} from "@umituz/react-native-design-system";
|
|
12
|
-
import type { ExportProgress as ExportProgressType } from "
|
|
12
|
+
import type { ExportProgress as ExportProgressType } from "../../hooks/useExport";
|
|
13
13
|
|
|
14
14
|
interface ExportProgressProps {
|
|
15
15
|
progress: ExportProgressType;
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
AtomicIcon,
|
|
11
11
|
useAppDesignTokens,
|
|
12
12
|
} from "@umituz/react-native-design-system";
|
|
13
|
-
import type { VideoProject } from "
|
|
13
|
+
import type { VideoProject } from "../../../domain/entities";
|
|
14
14
|
|
|
15
15
|
interface ProjectInfoBoxProps {
|
|
16
16
|
project: VideoProject;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { useState, useCallback } from "react";
|
|
7
|
-
import type { Animation, AnimationType } from "
|
|
7
|
+
import type { Animation, AnimationType } from "../../../domain/entities";
|
|
8
8
|
import type { Easing } from "../constants/animation-layer.constants";
|
|
9
9
|
|
|
10
10
|
export interface AnimationLayerFormState {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Single Responsibility: Compose editor action handlers
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import type { VideoProject } from "
|
|
6
|
+
import type { VideoProject } from "../../../domain/entities";
|
|
7
7
|
import type { UseEditorLayersReturn } from "./useEditorLayers";
|
|
8
8
|
import type { UseEditorScenesReturn } from "./useEditorScenes";
|
|
9
9
|
import type { UseEditorBottomSheetReturn } from "./useEditorBottomSheet";
|
|
@@ -15,7 +15,7 @@ const useHistoryStore = () => ({
|
|
|
15
15
|
canUndo: () => false,
|
|
16
16
|
canRedo: () => false,
|
|
17
17
|
});
|
|
18
|
-
import type { VideoProject } from "
|
|
18
|
+
import type { VideoProject } from "../../../domain/entities";
|
|
19
19
|
|
|
20
20
|
export interface UseEditorHistoryParams {
|
|
21
21
|
project: VideoProject | undefined;
|
|
@@ -13,7 +13,7 @@ import type {
|
|
|
13
13
|
AddShapeLayerData,
|
|
14
14
|
LayerOrderAction,
|
|
15
15
|
} from "../types";
|
|
16
|
-
import type { TextLayer, ImageLayer, Animation } from "
|
|
16
|
+
import type { TextLayer, ImageLayer, Animation } from "../../../domain/entities";
|
|
17
17
|
|
|
18
18
|
export interface UseEditorLayersParams {
|
|
19
19
|
projectId: string;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { useCallback } from "react";
|
|
7
7
|
import { Alert } from "react-native";
|
|
8
8
|
import { sceneOperationsService } from "../infrastructure/services/scene-operations.service";
|
|
9
|
-
import type { Audio } from "
|
|
9
|
+
import type { Audio } from "../../../domain/entities";
|
|
10
10
|
|
|
11
11
|
export interface UseEditorScenesParams {
|
|
12
12
|
scenes: any[];
|
|
@@ -1,12 +1,34 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* useExport Hook
|
|
3
3
|
* Manages export state and operations
|
|
4
|
+
* Package-driven: Export function is injected from app
|
|
4
5
|
*/
|
|
5
6
|
|
|
6
|
-
import { useState, useCallback
|
|
7
|
-
import type { ExportSettings, VideoProject } from "
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
import { useState, useCallback } from "react";
|
|
8
|
+
import type { ExportSettings, VideoProject } from "../../domain/entities";
|
|
9
|
+
|
|
10
|
+
export interface ExportProgress {
|
|
11
|
+
status: "preparing" | "encoding" | "saving" | "complete" | "error";
|
|
12
|
+
phase: string;
|
|
13
|
+
progress: number;
|
|
14
|
+
message?: string;
|
|
15
|
+
currentFrame?: number;
|
|
16
|
+
totalFrames?: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface ExportResult {
|
|
20
|
+
success: boolean;
|
|
21
|
+
uri?: string;
|
|
22
|
+
error?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface UseExportConfig {
|
|
26
|
+
exportFunction: (
|
|
27
|
+
project: VideoProject,
|
|
28
|
+
settings: ExportSettings,
|
|
29
|
+
onProgress: (progress: ExportProgress) => void,
|
|
30
|
+
) => Promise<ExportResult>;
|
|
31
|
+
}
|
|
10
32
|
|
|
11
33
|
export interface UseExportReturn {
|
|
12
34
|
isExporting: boolean;
|
|
@@ -14,43 +36,36 @@ export interface UseExportReturn {
|
|
|
14
36
|
exportVideo: (
|
|
15
37
|
project: VideoProject,
|
|
16
38
|
settings: ExportSettings,
|
|
17
|
-
) => Promise<
|
|
39
|
+
) => Promise<ExportResult>;
|
|
18
40
|
resetExport: () => void;
|
|
19
41
|
}
|
|
20
42
|
|
|
21
43
|
/**
|
|
22
44
|
* Hook for managing export operations
|
|
45
|
+
* @param config - Configuration with export function injected from app
|
|
23
46
|
*/
|
|
24
|
-
export function useExport(): UseExportReturn {
|
|
47
|
+
export function useExport(config: UseExportConfig): UseExportReturn {
|
|
25
48
|
const [isExporting, setIsExporting] = useState(false);
|
|
26
49
|
const [exportProgress, setExportProgress] = useState<ExportProgress | null>(
|
|
27
50
|
null,
|
|
28
51
|
);
|
|
29
52
|
|
|
30
|
-
useEffect(() => {
|
|
31
|
-
exportOrchestratorService.requestNotificationPermissions();
|
|
32
|
-
}, []);
|
|
33
|
-
|
|
34
53
|
const exportVideo = useCallback(
|
|
35
54
|
async (
|
|
36
55
|
project: VideoProject,
|
|
37
56
|
settings: ExportSettings,
|
|
38
|
-
): Promise<
|
|
57
|
+
): Promise<ExportResult> => {
|
|
39
58
|
setIsExporting(true);
|
|
40
59
|
setExportProgress(null);
|
|
41
60
|
|
|
42
|
-
const result = await
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
(progress) => {
|
|
46
|
-
setExportProgress(progress);
|
|
47
|
-
},
|
|
48
|
-
);
|
|
61
|
+
const result = await config.exportFunction(project, settings, (progress) => {
|
|
62
|
+
setExportProgress(progress);
|
|
63
|
+
});
|
|
49
64
|
|
|
50
65
|
setIsExporting(false);
|
|
51
66
|
return result;
|
|
52
67
|
},
|
|
53
|
-
[],
|
|
68
|
+
[config],
|
|
54
69
|
);
|
|
55
70
|
|
|
56
71
|
const resetExport = useCallback(() => {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { useCallback } from "react";
|
|
7
7
|
import { ExportDialog } from "../presentation/components/ExportDialog";
|
|
8
|
-
import type { VideoProject, ExportSettings } from "
|
|
8
|
+
import type { VideoProject, ExportSettings } from "../../../domain/entities";
|
|
9
9
|
import type { UseEditorBottomSheetReturn } from "./useEditorBottomSheet";
|
|
10
10
|
|
|
11
11
|
export interface UseExportActionsParams {
|
|
@@ -7,7 +7,7 @@ import { useCallback } from "react";
|
|
|
7
7
|
import { Alert } from "react-native";
|
|
8
8
|
import { layerOperationsService } from "../infrastructure/services/layer-operations.service";
|
|
9
9
|
import type { AddImageLayerData } from "../types";
|
|
10
|
-
import type { ImageLayer } from "
|
|
10
|
+
import type { ImageLayer } from "../../../domain/entities";
|
|
11
11
|
|
|
12
12
|
export interface UseImageLayerOperationsParams {
|
|
13
13
|
scenes: any[];
|
|
@@ -8,7 +8,7 @@ import { TextLayerEditor } from "../presentation/components/TextLayerEditor";
|
|
|
8
8
|
import { ImageLayerEditor } from "../presentation/components/ImageLayerEditor";
|
|
9
9
|
import { ShapeLayerEditor } from "../presentation/components/ShapeLayerEditor";
|
|
10
10
|
import { AnimationEditor } from "../presentation/components/AnimationEditor";
|
|
11
|
-
import type { ImageLayer } from "
|
|
11
|
+
import type { ImageLayer } from "../../../domain/entities";
|
|
12
12
|
import type { UseEditorLayersReturn } from "./useEditorLayers";
|
|
13
13
|
import type { UseEditorBottomSheetReturn } from "./useEditorBottomSheet";
|
|
14
14
|
|
|
@@ -7,7 +7,7 @@ import { useCallback } from "react";
|
|
|
7
7
|
import { Alert } from "react-native";
|
|
8
8
|
import { layerOperationsService } from "../infrastructure/services/layer-operations.service";
|
|
9
9
|
import type { LayerOrderAction } from "../types";
|
|
10
|
-
import type { Animation } from "
|
|
10
|
+
import type { Animation } from "../../../domain/entities";
|
|
11
11
|
|
|
12
12
|
export interface UseLayerManipulationParams {
|
|
13
13
|
scenes: any[];
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { useState, useCallback } from "react";
|
|
7
7
|
import { useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
8
|
-
import type { ShapeLayer } from "
|
|
8
|
+
import type { ShapeLayer } from "../../../domain/entities";
|
|
9
9
|
import type { ShapeType } from "../constants/shape-layer.constants";
|
|
10
10
|
|
|
11
11
|
export interface ShapeLayerFormState {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { useState, useCallback } from "react";
|
|
7
7
|
import { useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
8
|
-
import type { TextLayer } from "
|
|
8
|
+
import type { TextLayer } from "../../../domain/entities";
|
|
9
9
|
|
|
10
10
|
export interface TextLayerFormState {
|
|
11
11
|
text: string;
|
|
@@ -7,7 +7,7 @@ import { useCallback } from "react";
|
|
|
7
7
|
import { Alert } from "react-native";
|
|
8
8
|
import { layerOperationsService } from "../infrastructure/services/layer-operations.service";
|
|
9
9
|
import type { AddTextLayerData } from "../types";
|
|
10
|
-
import type { TextLayer } from "
|
|
10
|
+
import type { TextLayer } from "../../../domain/entities";
|
|
11
11
|
|
|
12
12
|
export interface UseTextLayerOperationsParams {
|
|
13
13
|
scenes: any[];
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Export Orchestrator Service
|
|
3
|
-
* Handles export business logic and notifications
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import * as Device from "expo-device";
|
|
7
|
-
import { Alert } from "react-native";
|
|
8
|
-
import { notificationService } from "@umituz/react-native-notifications";
|
|
9
|
-
import {
|
|
10
|
-
videoExportService,
|
|
11
|
-
ExportProgress,
|
|
12
|
-
} from "@domains/video/infrastructure/services/video-export.service";
|
|
13
|
-
import type { ExportSettings, VideoProject } from "@domains/video";
|
|
14
|
-
|
|
15
|
-
export interface ExportResult {
|
|
16
|
-
success: boolean;
|
|
17
|
-
uri?: string;
|
|
18
|
-
error?: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export interface ExportOrchestratorService {
|
|
22
|
-
exportVideo: (
|
|
23
|
-
project: VideoProject,
|
|
24
|
-
settings: ExportSettings,
|
|
25
|
-
onProgress: (progress: ExportProgress) => void,
|
|
26
|
-
) => Promise<ExportResult>;
|
|
27
|
-
requestNotificationPermissions: () => Promise<void>;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
class ExportOrchestratorServiceImpl implements ExportOrchestratorService {
|
|
31
|
-
async requestNotificationPermissions(): Promise<void> {
|
|
32
|
-
if (Device.isDevice) {
|
|
33
|
-
await notificationService.requestPermissions();
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async exportVideo(
|
|
38
|
-
project: VideoProject,
|
|
39
|
-
settings: ExportSettings,
|
|
40
|
-
onProgress: (progress: ExportProgress) => void,
|
|
41
|
-
): Promise<ExportResult> {
|
|
42
|
-
const projectToExport: VideoProject = {
|
|
43
|
-
...project,
|
|
44
|
-
exportSettings: settings,
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
try {
|
|
48
|
-
const result = await videoExportService.exportVideo(
|
|
49
|
-
projectToExport,
|
|
50
|
-
onProgress,
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
if (result.success) {
|
|
54
|
-
await this.showSuccessNotification(project.title, result.uri);
|
|
55
|
-
this.showSuccessAlert();
|
|
56
|
-
return { success: true, uri: result.uri };
|
|
57
|
-
} else {
|
|
58
|
-
await this.showFailureNotification(project.title, result.error);
|
|
59
|
-
this.showFailureAlert(result.error);
|
|
60
|
-
return { success: false, error: result.error };
|
|
61
|
-
}
|
|
62
|
-
} catch (error) {
|
|
63
|
-
await this.showFailureNotification(
|
|
64
|
-
project.title,
|
|
65
|
-
"An unexpected error occurred",
|
|
66
|
-
);
|
|
67
|
-
this.showFailureAlert("An unexpected error occurred");
|
|
68
|
-
return {
|
|
69
|
-
success: false,
|
|
70
|
-
error: error instanceof Error ? error.message : "Unknown error",
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
private async showSuccessNotification(
|
|
76
|
-
projectTitle: string,
|
|
77
|
-
uri?: string,
|
|
78
|
-
): Promise<void> {
|
|
79
|
-
if (!Device.isDevice) return;
|
|
80
|
-
|
|
81
|
-
try {
|
|
82
|
-
await notificationService.notifications.scheduleNotification({
|
|
83
|
-
title: "Export Complete",
|
|
84
|
-
body: `${projectTitle} has been exported successfully!`,
|
|
85
|
-
trigger: { type: "date", date: new Date() },
|
|
86
|
-
data: { uri: uri || "" },
|
|
87
|
-
});
|
|
88
|
-
} catch (error) {
|
|
89
|
-
// Silent failure - notification is optional
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
private async showFailureNotification(
|
|
94
|
-
projectTitle: string,
|
|
95
|
-
error?: string,
|
|
96
|
-
): Promise<void> {
|
|
97
|
-
if (!Device.isDevice) return;
|
|
98
|
-
|
|
99
|
-
try {
|
|
100
|
-
await notificationService.notifications.scheduleNotification({
|
|
101
|
-
title: "Export Failed",
|
|
102
|
-
body: `Failed to export ${projectTitle}: ${error || "Unknown error"}`,
|
|
103
|
-
trigger: { type: "date", date: new Date() },
|
|
104
|
-
});
|
|
105
|
-
} catch (error) {
|
|
106
|
-
// Silent failure - notification is optional
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
private showSuccessAlert(): void {
|
|
111
|
-
Alert.alert(
|
|
112
|
-
"Export Complete",
|
|
113
|
-
"Your video has been exported successfully!",
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
private showFailureAlert(error?: string): void {
|
|
118
|
-
Alert.alert("Export Failed", error || "An error occurred during export");
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
export const exportOrchestratorService = new ExportOrchestratorServiceImpl();
|