@umituz/react-native-ai-generation-content 1.27.8 → 1.27.9
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/domains/generation/wizard/infrastructure/strategies/image-generation.strategy.ts +3 -30
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation.strategy.ts +3 -30
- package/src/domains/generation/wizard/infrastructure/strategies/wizard-strategy.constants.ts +0 -2
- package/src/features/image-to-video/README.md +414 -0
- package/src/features/image-to-video/domain/constants/animation.constants.ts +47 -0
- package/src/features/image-to-video/domain/constants/duration.constants.ts +13 -0
- package/src/features/image-to-video/domain/constants/form.constants.ts +22 -0
- package/src/features/image-to-video/domain/constants/index.ts +23 -0
- package/src/features/image-to-video/domain/constants/music.constants.ts +53 -0
- package/src/features/image-to-video/domain/index.ts +5 -0
- package/src/features/image-to-video/domain/types/animation.types.ts +20 -0
- package/src/features/image-to-video/domain/types/config.types.ts +56 -0
- package/src/features/image-to-video/domain/types/duration.types.ts +11 -0
- package/src/features/image-to-video/domain/types/form.types.ts +35 -0
- package/src/features/image-to-video/domain/types/image-to-video.types.ts +122 -0
- package/src/features/image-to-video/domain/types/index.ts +39 -0
- package/src/features/image-to-video/domain/types/music.types.ts +21 -0
- package/src/features/image-to-video/index.ts +116 -0
- package/src/features/image-to-video/infrastructure/index.ts +1 -0
- package/src/features/image-to-video/infrastructure/services/image-to-video-executor.ts +165 -0
- package/src/features/image-to-video/infrastructure/services/index.ts +5 -0
- package/src/features/image-to-video/presentation/components/AddMoreCard.tsx +52 -0
- package/src/features/image-to-video/presentation/components/AnimationStyleSelector.tsx +135 -0
- package/src/features/image-to-video/presentation/components/DurationSelector.tsx +110 -0
- package/src/features/image-to-video/presentation/components/EmptyGridState.tsx +69 -0
- package/src/features/image-to-video/presentation/components/GridImageItem.tsx +64 -0
- package/src/features/image-to-video/presentation/components/ImageSelectionGrid.styles.ts +84 -0
- package/src/features/image-to-video/presentation/components/ImageSelectionGrid.tsx +77 -0
- package/src/features/image-to-video/presentation/components/ImageSelectionGrid.types.ts +18 -0
- package/src/features/image-to-video/presentation/components/MusicMoodSelector.tsx +181 -0
- package/src/features/image-to-video/presentation/components/index.ts +30 -0
- package/src/features/image-to-video/presentation/hooks/index.ts +27 -0
- package/src/features/image-to-video/presentation/hooks/useFormState.ts +116 -0
- package/src/features/image-to-video/presentation/hooks/useGeneration.ts +85 -0
- package/src/features/image-to-video/presentation/hooks/useGenerationExecution.ts +143 -0
- package/src/features/image-to-video/presentation/hooks/useImageToVideoFeature.ts +107 -0
- package/src/features/image-to-video/presentation/hooks/useImageToVideoForm.ts +119 -0
- package/src/features/image-to-video/presentation/hooks/useImageToVideoValidation.ts +46 -0
- package/src/features/image-to-video/presentation/index.ts +5 -0
- package/src/features/text-to-image/README.md +394 -0
- package/src/features/text-to-image/domain/constants/index.ts +25 -0
- package/src/features/text-to-image/domain/constants/options.constants.ts +39 -0
- package/src/features/text-to-image/domain/constants/styles.constants.ts +34 -0
- package/src/features/text-to-image/domain/index.ts +7 -0
- package/src/features/text-to-image/domain/types/config.types.ts +75 -0
- package/src/features/text-to-image/domain/types/form.types.ts +58 -0
- package/src/features/text-to-image/domain/types/index.ts +38 -0
- package/src/features/text-to-image/domain/types/text-to-image.types.ts +58 -0
- package/src/features/text-to-image/index.ts +116 -0
- package/src/features/text-to-image/infrastructure/index.ts +1 -0
- package/src/features/text-to-image/infrastructure/services/index.ts +5 -0
- package/src/features/text-to-image/infrastructure/services/text-to-image-executor.ts +147 -0
- package/src/features/text-to-image/presentation/components/index.ts +30 -0
- package/src/features/text-to-image/presentation/hooks/index.ts +30 -0
- package/src/features/text-to-image/presentation/hooks/useFormState.ts +103 -0
- package/src/features/text-to-image/presentation/hooks/useGeneration.ts +134 -0
- package/src/features/text-to-image/presentation/hooks/useTextToImageFeature.ts +111 -0
- package/src/features/text-to-image/presentation/hooks/useTextToImageForm.ts +58 -0
- package/src/features/text-to-image/presentation/index.ts +7 -0
- package/src/features/text-to-video/README.md +412 -0
- package/src/features/text-to-video/domain/index.ts +1 -0
- package/src/features/text-to-video/domain/types/callback.types.ts +69 -0
- package/src/features/text-to-video/domain/types/component.types.ts +106 -0
- package/src/features/text-to-video/domain/types/config.types.ts +61 -0
- package/src/features/text-to-video/domain/types/index.ts +56 -0
- package/src/features/text-to-video/domain/types/request.types.ts +36 -0
- package/src/features/text-to-video/domain/types/state.types.ts +53 -0
- package/src/features/text-to-video/index.ts +68 -0
- package/src/features/text-to-video/infrastructure/index.ts +1 -0
- package/src/features/text-to-video/infrastructure/services/index.ts +5 -0
- package/src/features/text-to-video/infrastructure/services/text-to-video-executor.ts +141 -0
- package/src/features/text-to-video/presentation/components/FrameSelector.tsx +153 -0
- package/src/features/text-to-video/presentation/components/GenerationTabs.tsx +73 -0
- package/src/features/text-to-video/presentation/components/HeroSection.tsx +61 -0
- package/src/features/text-to-video/presentation/components/HintCarousel.tsx +96 -0
- package/src/features/text-to-video/presentation/components/OptionsPanel.tsx +121 -0
- package/src/features/text-to-video/presentation/components/index.ts +10 -0
- package/src/features/text-to-video/presentation/hooks/index.ts +17 -0
- package/src/features/text-to-video/presentation/hooks/useTextToVideoFeature.ts +187 -0
- package/src/features/text-to-video/presentation/hooks/useTextToVideoForm.ts +134 -0
- package/src/features/text-to-video/presentation/index.ts +7 -0
- package/src/index.ts +5 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Animation Types for Image-to-Video
|
|
3
|
+
* Defines animation style options
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface AnimationStyle {
|
|
7
|
+
id: string;
|
|
8
|
+
name: string;
|
|
9
|
+
description: string;
|
|
10
|
+
icon: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type AnimationStyleId =
|
|
14
|
+
| "ken_burns"
|
|
15
|
+
| "zoom_in"
|
|
16
|
+
| "zoom_out"
|
|
17
|
+
| "slide_left"
|
|
18
|
+
| "slide_right"
|
|
19
|
+
| "parallax"
|
|
20
|
+
| string;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config Types for Image-to-Video
|
|
3
|
+
* Defines callbacks and configuration options
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { ImageToVideoResult } from "./image-to-video.types";
|
|
7
|
+
import type { ImageToVideoFormState } from "./form.types";
|
|
8
|
+
|
|
9
|
+
export interface ImageToVideoCallbacks {
|
|
10
|
+
onGenerate: (formState: ImageToVideoFormState) => Promise<void>;
|
|
11
|
+
onSelectImages?: () => Promise<string[]>;
|
|
12
|
+
onSelectCustomAudio?: () => Promise<string | null>;
|
|
13
|
+
onCreditCheck?: (cost: number) => boolean;
|
|
14
|
+
onShowPaywall?: (cost: number) => void;
|
|
15
|
+
onSuccess?: (result: ImageToVideoResult) => void;
|
|
16
|
+
onError?: (error: string) => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface ImageToVideoFormConfig {
|
|
20
|
+
maxImages?: number;
|
|
21
|
+
creditCost?: number;
|
|
22
|
+
enableCustomAudio?: boolean;
|
|
23
|
+
enableMotionPrompt?: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface ImageToVideoTranslationsExtended {
|
|
27
|
+
sectionTitles: {
|
|
28
|
+
selectedImages: string;
|
|
29
|
+
animationStyle: string;
|
|
30
|
+
durationPerImage: string;
|
|
31
|
+
addMusic: string;
|
|
32
|
+
};
|
|
33
|
+
imageSelection: {
|
|
34
|
+
selectImages: string;
|
|
35
|
+
chooseUpTo: string;
|
|
36
|
+
addMore: string;
|
|
37
|
+
};
|
|
38
|
+
duration: {
|
|
39
|
+
totalVideo: string;
|
|
40
|
+
};
|
|
41
|
+
music: {
|
|
42
|
+
customAudioSelected: string;
|
|
43
|
+
};
|
|
44
|
+
hero: {
|
|
45
|
+
title: string;
|
|
46
|
+
subtitle: string;
|
|
47
|
+
};
|
|
48
|
+
generate: {
|
|
49
|
+
buttonText: string;
|
|
50
|
+
generatingText: string;
|
|
51
|
+
};
|
|
52
|
+
errors: {
|
|
53
|
+
noImages: string;
|
|
54
|
+
noImagesMessage: string;
|
|
55
|
+
};
|
|
56
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Form Types for Image-to-Video
|
|
3
|
+
* Defines form state and actions
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { AnimationStyleId } from "./animation.types";
|
|
7
|
+
import type { MusicMoodId } from "./music.types";
|
|
8
|
+
import type { VideoDuration } from "./duration.types";
|
|
9
|
+
|
|
10
|
+
export interface ImageToVideoFormState {
|
|
11
|
+
selectedImages: string[];
|
|
12
|
+
animationStyle: AnimationStyleId;
|
|
13
|
+
duration: VideoDuration;
|
|
14
|
+
musicMood: MusicMoodId;
|
|
15
|
+
customAudioUri: string | null;
|
|
16
|
+
motionPrompt: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface ImageToVideoFormActions {
|
|
20
|
+
setSelectedImages: (images: string[]) => void;
|
|
21
|
+
addImages: (images: string[]) => void;
|
|
22
|
+
removeImage: (index: number) => void;
|
|
23
|
+
setAnimationStyle: (style: AnimationStyleId) => void;
|
|
24
|
+
setDuration: (duration: VideoDuration) => void;
|
|
25
|
+
setMusicMood: (mood: MusicMoodId) => void;
|
|
26
|
+
setCustomAudioUri: (uri: string | null) => void;
|
|
27
|
+
setMotionPrompt: (prompt: string) => void;
|
|
28
|
+
reset: () => void;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface ImageToVideoFormDefaults {
|
|
32
|
+
animationStyle?: AnimationStyleId;
|
|
33
|
+
duration?: VideoDuration;
|
|
34
|
+
musicMood?: MusicMoodId;
|
|
35
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image-to-Video Feature Types
|
|
3
|
+
* Request, Result, Config types for image-to-video generation
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { AnimationStyleId } from "./animation.types";
|
|
7
|
+
import type { MusicMoodId } from "./music.types";
|
|
8
|
+
import type { VideoDuration } from "./duration.types";
|
|
9
|
+
|
|
10
|
+
export interface ImageToVideoOptions {
|
|
11
|
+
duration?: number;
|
|
12
|
+
motionStrength?: number;
|
|
13
|
+
aspectRatio?: "16:9" | "9:16" | "1:1";
|
|
14
|
+
fps?: number;
|
|
15
|
+
animationStyle?: AnimationStyleId;
|
|
16
|
+
musicMood?: MusicMoodId;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface ImageToVideoGenerateParams extends ImageToVideoOptions {
|
|
20
|
+
imageUri?: string;
|
|
21
|
+
motionPrompt?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface ImageToVideoRequest {
|
|
25
|
+
imageUri: string;
|
|
26
|
+
imageBase64?: string;
|
|
27
|
+
userId: string;
|
|
28
|
+
motionPrompt?: string;
|
|
29
|
+
options?: ImageToVideoOptions;
|
|
30
|
+
allImages?: string[];
|
|
31
|
+
customAudioUri?: string | null;
|
|
32
|
+
animationStyle?: AnimationStyleId;
|
|
33
|
+
duration?: VideoDuration;
|
|
34
|
+
musicMood?: MusicMoodId;
|
|
35
|
+
model?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface ImageToVideoResult {
|
|
39
|
+
success: boolean;
|
|
40
|
+
videoUrl?: string;
|
|
41
|
+
thumbnailUrl?: string;
|
|
42
|
+
error?: string;
|
|
43
|
+
requestId?: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface ImageToVideoGenerationState {
|
|
47
|
+
isGenerating: boolean;
|
|
48
|
+
progress: number;
|
|
49
|
+
error: string | null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface ImageToVideoFeatureState {
|
|
53
|
+
imageUri: string | null;
|
|
54
|
+
motionPrompt: string;
|
|
55
|
+
videoUrl: string | null;
|
|
56
|
+
thumbnailUrl: string | null;
|
|
57
|
+
isProcessing: boolean;
|
|
58
|
+
progress: number;
|
|
59
|
+
error: string | null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface ImageToVideoTranslations {
|
|
63
|
+
uploadTitle: string;
|
|
64
|
+
uploadSubtitle: string;
|
|
65
|
+
motionPromptPlaceholder: string;
|
|
66
|
+
generateButtonText: string;
|
|
67
|
+
processingText: string;
|
|
68
|
+
successText: string;
|
|
69
|
+
saveButtonText: string;
|
|
70
|
+
tryAnotherText: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export type ImageToVideoInputBuilder = (
|
|
74
|
+
imageBase64: string,
|
|
75
|
+
motionPrompt?: string,
|
|
76
|
+
options?: ImageToVideoOptions,
|
|
77
|
+
) => Record<string, unknown>;
|
|
78
|
+
|
|
79
|
+
export type ImageToVideoResultExtractor = (
|
|
80
|
+
result: unknown,
|
|
81
|
+
) => { videoUrl?: string; thumbnailUrl?: string } | undefined;
|
|
82
|
+
|
|
83
|
+
export interface ImageToVideoFeatureCallbacks {
|
|
84
|
+
onCreditCheck?: (cost: number) => Promise<boolean>;
|
|
85
|
+
onCreditDeduct?: (cost: number) => Promise<void>;
|
|
86
|
+
onAuthCheck?: () => boolean;
|
|
87
|
+
onShowPaywall?: (creditCost: number) => void;
|
|
88
|
+
onGenerationStart?: (data: ImageToVideoGenerationStartData) => Promise<void>;
|
|
89
|
+
onCreationSave?: (data: ImageToVideoCreationData) => Promise<void>;
|
|
90
|
+
onGenerate?: (result: ImageToVideoResult) => void;
|
|
91
|
+
onProgress?: (progress: number) => void;
|
|
92
|
+
onError?: (error: string) => void;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface ImageToVideoGenerationStartData {
|
|
96
|
+
creationId: string;
|
|
97
|
+
type: string;
|
|
98
|
+
imageUri: string;
|
|
99
|
+
metadata?: Record<string, unknown>;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export interface ImageToVideoCreationData {
|
|
103
|
+
creationId: string;
|
|
104
|
+
type: string;
|
|
105
|
+
videoUrl: string;
|
|
106
|
+
thumbnailUrl?: string;
|
|
107
|
+
imageUri: string;
|
|
108
|
+
metadata?: Record<string, unknown>;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export interface ImageToVideoFeatureConfig {
|
|
112
|
+
providerId?: string;
|
|
113
|
+
creditCost?: number;
|
|
114
|
+
model: string;
|
|
115
|
+
buildInput: ImageToVideoInputBuilder;
|
|
116
|
+
extractResult?: ImageToVideoResultExtractor;
|
|
117
|
+
prepareImage: (imageUri: string) => Promise<string>;
|
|
118
|
+
onImageSelect?: (uri: string) => void;
|
|
119
|
+
onProcessingStart?: () => void;
|
|
120
|
+
onProcessingComplete?: (result: ImageToVideoResult) => void;
|
|
121
|
+
onError?: (error: string) => void;
|
|
122
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// Animation Types
|
|
2
|
+
export type { AnimationStyle, AnimationStyleId } from "./animation.types";
|
|
3
|
+
|
|
4
|
+
// Music Types
|
|
5
|
+
export type { MusicMood, MusicMoodId } from "./music.types";
|
|
6
|
+
|
|
7
|
+
// Duration Types
|
|
8
|
+
export type { VideoDuration, DurationOption } from "./duration.types";
|
|
9
|
+
|
|
10
|
+
// Form Types
|
|
11
|
+
export type {
|
|
12
|
+
ImageToVideoFormState,
|
|
13
|
+
ImageToVideoFormActions,
|
|
14
|
+
ImageToVideoFormDefaults,
|
|
15
|
+
} from "./form.types";
|
|
16
|
+
|
|
17
|
+
// Config Types
|
|
18
|
+
export type {
|
|
19
|
+
ImageToVideoCallbacks,
|
|
20
|
+
ImageToVideoFormConfig,
|
|
21
|
+
ImageToVideoTranslationsExtended,
|
|
22
|
+
} from "./config.types";
|
|
23
|
+
|
|
24
|
+
// Core Feature Types
|
|
25
|
+
export type {
|
|
26
|
+
ImageToVideoOptions,
|
|
27
|
+
ImageToVideoGenerateParams,
|
|
28
|
+
ImageToVideoRequest,
|
|
29
|
+
ImageToVideoResult,
|
|
30
|
+
ImageToVideoGenerationState,
|
|
31
|
+
ImageToVideoFeatureState,
|
|
32
|
+
ImageToVideoTranslations,
|
|
33
|
+
ImageToVideoInputBuilder,
|
|
34
|
+
ImageToVideoResultExtractor,
|
|
35
|
+
ImageToVideoFeatureCallbacks,
|
|
36
|
+
ImageToVideoGenerationStartData,
|
|
37
|
+
ImageToVideoCreationData,
|
|
38
|
+
ImageToVideoFeatureConfig,
|
|
39
|
+
} from "./image-to-video.types";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Music Types for Image-to-Video
|
|
3
|
+
* Defines music mood options
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface MusicMood {
|
|
7
|
+
id: string;
|
|
8
|
+
name: string;
|
|
9
|
+
description: string;
|
|
10
|
+
icon: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type MusicMoodId =
|
|
14
|
+
| "none"
|
|
15
|
+
| "energetic"
|
|
16
|
+
| "calm"
|
|
17
|
+
| "happy"
|
|
18
|
+
| "emotional"
|
|
19
|
+
| "rhythmic"
|
|
20
|
+
| "custom"
|
|
21
|
+
| string;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image-to-Video Feature
|
|
3
|
+
* Provider-agnostic image-to-video generation feature
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// =============================================================================
|
|
7
|
+
// DOMAIN LAYER - Types
|
|
8
|
+
// =============================================================================
|
|
9
|
+
|
|
10
|
+
// Animation Types
|
|
11
|
+
export type { AnimationStyle, AnimationStyleId } from "./domain";
|
|
12
|
+
|
|
13
|
+
// Music Types
|
|
14
|
+
export type { MusicMood, MusicMoodId } from "./domain";
|
|
15
|
+
|
|
16
|
+
// Duration Types
|
|
17
|
+
export type { VideoDuration, DurationOption } from "./domain";
|
|
18
|
+
|
|
19
|
+
// Form Types
|
|
20
|
+
export type {
|
|
21
|
+
ImageToVideoFormState,
|
|
22
|
+
ImageToVideoFormActions,
|
|
23
|
+
ImageToVideoFormDefaults,
|
|
24
|
+
} from "./domain";
|
|
25
|
+
|
|
26
|
+
// Config Types
|
|
27
|
+
export type {
|
|
28
|
+
ImageToVideoCallbacks,
|
|
29
|
+
ImageToVideoFormConfig,
|
|
30
|
+
ImageToVideoTranslationsExtended,
|
|
31
|
+
} from "./domain";
|
|
32
|
+
|
|
33
|
+
// Core Feature Types
|
|
34
|
+
export type {
|
|
35
|
+
ImageToVideoOptions,
|
|
36
|
+
ImageToVideoGenerateParams,
|
|
37
|
+
ImageToVideoRequest,
|
|
38
|
+
ImageToVideoResult,
|
|
39
|
+
ImageToVideoGenerationState,
|
|
40
|
+
ImageToVideoFeatureState,
|
|
41
|
+
ImageToVideoTranslations,
|
|
42
|
+
ImageToVideoInputBuilder,
|
|
43
|
+
ImageToVideoResultExtractor,
|
|
44
|
+
ImageToVideoFeatureCallbacks,
|
|
45
|
+
ImageToVideoGenerationStartData,
|
|
46
|
+
ImageToVideoCreationData,
|
|
47
|
+
ImageToVideoFeatureConfig,
|
|
48
|
+
} from "./domain";
|
|
49
|
+
|
|
50
|
+
// =============================================================================
|
|
51
|
+
// DOMAIN LAYER - Constants
|
|
52
|
+
// =============================================================================
|
|
53
|
+
|
|
54
|
+
export {
|
|
55
|
+
DEFAULT_ANIMATION_STYLES as IMAGE_TO_VIDEO_ANIMATION_STYLES,
|
|
56
|
+
DEFAULT_ANIMATION_STYLE_ID as IMAGE_TO_VIDEO_DEFAULT_ANIMATION,
|
|
57
|
+
DEFAULT_MUSIC_MOODS as IMAGE_TO_VIDEO_MUSIC_MOODS,
|
|
58
|
+
DEFAULT_MUSIC_MOOD_ID as IMAGE_TO_VIDEO_DEFAULT_MUSIC,
|
|
59
|
+
DEFAULT_DURATION_OPTIONS as IMAGE_TO_VIDEO_DURATION_OPTIONS,
|
|
60
|
+
DEFAULT_VIDEO_DURATION as IMAGE_TO_VIDEO_DEFAULT_DURATION,
|
|
61
|
+
DEFAULT_FORM_VALUES as IMAGE_TO_VIDEO_FORM_DEFAULTS,
|
|
62
|
+
DEFAULT_FORM_CONFIG as IMAGE_TO_VIDEO_CONFIG,
|
|
63
|
+
} from "./domain";
|
|
64
|
+
|
|
65
|
+
// =============================================================================
|
|
66
|
+
// INFRASTRUCTURE LAYER
|
|
67
|
+
// =============================================================================
|
|
68
|
+
|
|
69
|
+
export { executeImageToVideo, hasImageToVideoSupport } from "./infrastructure";
|
|
70
|
+
export type { ExecuteImageToVideoOptions } from "./infrastructure";
|
|
71
|
+
|
|
72
|
+
// =============================================================================
|
|
73
|
+
// PRESENTATION LAYER - Hooks
|
|
74
|
+
// =============================================================================
|
|
75
|
+
|
|
76
|
+
export {
|
|
77
|
+
useImageToVideoFormState,
|
|
78
|
+
useImageToVideoGeneration,
|
|
79
|
+
useImageToVideoForm,
|
|
80
|
+
} from "./presentation";
|
|
81
|
+
export type {
|
|
82
|
+
UseImageToVideoFormStateOptions,
|
|
83
|
+
UseImageToVideoFormStateReturn,
|
|
84
|
+
UseImageToVideoGenerationOptions,
|
|
85
|
+
UseImageToVideoGenerationReturn,
|
|
86
|
+
UseImageToVideoFormOptions,
|
|
87
|
+
UseImageToVideoFormReturn,
|
|
88
|
+
} from "./presentation";
|
|
89
|
+
|
|
90
|
+
// Provider-based Feature Hook
|
|
91
|
+
export { useImageToVideoFeature } from "./presentation";
|
|
92
|
+
export type {
|
|
93
|
+
UseImageToVideoFeatureProps,
|
|
94
|
+
UseImageToVideoFeatureReturn,
|
|
95
|
+
} from "./presentation";
|
|
96
|
+
|
|
97
|
+
// =============================================================================
|
|
98
|
+
// PRESENTATION LAYER - Components
|
|
99
|
+
// =============================================================================
|
|
100
|
+
|
|
101
|
+
export {
|
|
102
|
+
ImageToVideoAnimationStyleSelector,
|
|
103
|
+
ImageToVideoDurationSelector,
|
|
104
|
+
ImageToVideoMusicMoodSelector,
|
|
105
|
+
ImageToVideoSelectionGrid,
|
|
106
|
+
ImageToVideoGenerateButton,
|
|
107
|
+
} from "./presentation";
|
|
108
|
+
|
|
109
|
+
export type {
|
|
110
|
+
ImageToVideoAnimationStyleSelectorProps,
|
|
111
|
+
ImageToVideoDurationSelectorProps,
|
|
112
|
+
ImageToVideoMusicMoodSelectorProps,
|
|
113
|
+
ImageToVideoSelectionGridProps,
|
|
114
|
+
ImageToVideoSelectionGridTranslations,
|
|
115
|
+
ImageToVideoGenerateButtonProps,
|
|
116
|
+
} from "./presentation";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./services";
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image-to-Video Executor
|
|
3
|
+
* Provider-agnostic image-to-video execution using active AI provider
|
|
4
|
+
* Uses progress mapper for consistent progress reporting
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { providerRegistry } from "../../../../infrastructure/services";
|
|
8
|
+
|
|
9
|
+
/** Map job status to progress percentage */
|
|
10
|
+
const getProgressFromJobStatus = (status: string): number => {
|
|
11
|
+
switch (status.toLowerCase()) {
|
|
12
|
+
case "queued": return 10;
|
|
13
|
+
case "in_queue": return 15;
|
|
14
|
+
case "processing": return 50;
|
|
15
|
+
case "in_progress": return 60;
|
|
16
|
+
case "completed": return 100;
|
|
17
|
+
default: return 30;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
import type {
|
|
21
|
+
ImageToVideoRequest,
|
|
22
|
+
ImageToVideoResult,
|
|
23
|
+
ImageToVideoInputBuilder,
|
|
24
|
+
ImageToVideoResultExtractor,
|
|
25
|
+
} from "../../domain/types";
|
|
26
|
+
|
|
27
|
+
declare const __DEV__: boolean;
|
|
28
|
+
|
|
29
|
+
export interface ExecuteImageToVideoOptions {
|
|
30
|
+
model: string;
|
|
31
|
+
buildInput: ImageToVideoInputBuilder;
|
|
32
|
+
extractResult?: ImageToVideoResultExtractor;
|
|
33
|
+
onProgress?: (progress: number) => void;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function defaultExtractResult(
|
|
37
|
+
result: unknown,
|
|
38
|
+
): { videoUrl?: string; thumbnailUrl?: string } | undefined {
|
|
39
|
+
if (typeof result !== "object" || result === null) return undefined;
|
|
40
|
+
|
|
41
|
+
const r = result as Record<string, unknown>;
|
|
42
|
+
|
|
43
|
+
if (typeof r.video === "string") {
|
|
44
|
+
return { videoUrl: r.video };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (r.video && typeof r.video === "object") {
|
|
48
|
+
const video = r.video as Record<string, unknown>;
|
|
49
|
+
if (typeof video.url === "string") {
|
|
50
|
+
return {
|
|
51
|
+
videoUrl: video.url,
|
|
52
|
+
thumbnailUrl:
|
|
53
|
+
typeof r.thumbnail === "string" ? r.thumbnail : undefined,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export async function executeImageToVideo(
|
|
62
|
+
request: ImageToVideoRequest,
|
|
63
|
+
options: ExecuteImageToVideoOptions,
|
|
64
|
+
): Promise<ImageToVideoResult> {
|
|
65
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
66
|
+
|
|
67
|
+
console.log("[ImageToVideoExecutor] executeImageToVideo() called");
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const provider = providerRegistry.getActiveProvider();
|
|
71
|
+
|
|
72
|
+
if (!provider) {
|
|
73
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
74
|
+
|
|
75
|
+
console.error("[ImageToVideoExecutor] No AI provider configured");
|
|
76
|
+
}
|
|
77
|
+
return { success: false, error: "No AI provider configured" };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (!provider.isInitialized()) {
|
|
81
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
82
|
+
|
|
83
|
+
console.error("[ImageToVideoExecutor] AI provider not initialized");
|
|
84
|
+
}
|
|
85
|
+
return { success: false, error: "AI provider not initialized" };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (!request.imageBase64) {
|
|
89
|
+
return { success: false, error: "Image base64 is required" };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const { model, buildInput, extractResult, onProgress } = options;
|
|
93
|
+
|
|
94
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
95
|
+
|
|
96
|
+
console.log(`[ImageToVideoExecutor] Provider: ${provider.providerId}, Model: ${model}`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
onProgress?.(5);
|
|
101
|
+
|
|
102
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
103
|
+
|
|
104
|
+
console.log("[ImageToVideoExecutor] Starting provider.subscribe()...");
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Build input directly - let buildInput handle base64 format
|
|
108
|
+
const input = buildInput(request.imageBase64, request.motionPrompt, request.options);
|
|
109
|
+
|
|
110
|
+
// Use subscribe for video generation (long-running operation with queue)
|
|
111
|
+
// subscribe provides progress updates unlike run()
|
|
112
|
+
const result = await provider.subscribe(model, input, {
|
|
113
|
+
onQueueUpdate: (status) => {
|
|
114
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
115
|
+
|
|
116
|
+
console.log("[ImageToVideoExecutor] Queue status:", status.status, "position:", status.queuePosition);
|
|
117
|
+
}
|
|
118
|
+
// Map provider status to progress using centralized mapper
|
|
119
|
+
const progress = getProgressFromJobStatus(status.status);
|
|
120
|
+
onProgress?.(progress);
|
|
121
|
+
},
|
|
122
|
+
timeoutMs: 300000, // 5 minutes timeout for video generation
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
126
|
+
|
|
127
|
+
console.log("[ImageToVideoExecutor] Subscribe resolved, result keys:", result ? Object.keys(result as object) : "null");
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
131
|
+
|
|
132
|
+
console.log("[ImageToVideoExecutor] provider.subscribe() completed");
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const extractor = extractResult || defaultExtractResult;
|
|
136
|
+
const extracted = extractor(result);
|
|
137
|
+
onProgress?.(100);
|
|
138
|
+
|
|
139
|
+
if (!extracted?.videoUrl) {
|
|
140
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
141
|
+
|
|
142
|
+
console.error("[ImageToVideoExecutor] No video URL in response");
|
|
143
|
+
}
|
|
144
|
+
return { success: false, error: "No video in response" };
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
success: true,
|
|
149
|
+
videoUrl: extracted.videoUrl,
|
|
150
|
+
thumbnailUrl: extracted.thumbnailUrl,
|
|
151
|
+
};
|
|
152
|
+
} catch (error) {
|
|
153
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
154
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
155
|
+
|
|
156
|
+
console.error("[ImageToVideoExecutor] Error:", message);
|
|
157
|
+
}
|
|
158
|
+
return { success: false, error: message };
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export function hasImageToVideoSupport(): boolean {
|
|
163
|
+
const provider = providerRegistry.getActiveProvider();
|
|
164
|
+
return provider !== null && provider.isInitialized();
|
|
165
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AddMoreCard Component
|
|
3
|
+
* Displays "Add More" button in the image grid
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React from "react";
|
|
7
|
+
import { TouchableOpacity } from "react-native";
|
|
8
|
+
import {
|
|
9
|
+
AtomicIcon,
|
|
10
|
+
AtomicText,
|
|
11
|
+
useAppDesignTokens,
|
|
12
|
+
} from "@umituz/react-native-design-system";
|
|
13
|
+
import type { ImageSelectionGridStyles } from "./ImageSelectionGrid.styles";
|
|
14
|
+
|
|
15
|
+
interface AddMoreCardProps {
|
|
16
|
+
styles: ImageSelectionGridStyles;
|
|
17
|
+
addMoreText: string;
|
|
18
|
+
onPress: () => void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function AddMoreCard({
|
|
22
|
+
styles,
|
|
23
|
+
addMoreText,
|
|
24
|
+
onPress,
|
|
25
|
+
}: AddMoreCardProps) {
|
|
26
|
+
const tokens = useAppDesignTokens();
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<TouchableOpacity
|
|
30
|
+
style={[
|
|
31
|
+
styles.addMoreCard,
|
|
32
|
+
{
|
|
33
|
+
backgroundColor: tokens.colors.surface,
|
|
34
|
+
borderColor: tokens.colors.borderLight,
|
|
35
|
+
},
|
|
36
|
+
]}
|
|
37
|
+
onPress={onPress}
|
|
38
|
+
activeOpacity={0.7}
|
|
39
|
+
>
|
|
40
|
+
<AtomicIcon name="add" size="lg" color="primary" />
|
|
41
|
+
<AtomicText
|
|
42
|
+
type="labelSmall"
|
|
43
|
+
style={[
|
|
44
|
+
styles.addMoreText,
|
|
45
|
+
{ color: tokens.colors.primary },
|
|
46
|
+
]}
|
|
47
|
+
>
|
|
48
|
+
{addMoreText}
|
|
49
|
+
</AtomicText>
|
|
50
|
+
</TouchableOpacity>
|
|
51
|
+
);
|
|
52
|
+
}
|