@umituz/react-native-ai-generation-content 1.37.9 → 1.37.11
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/creations/presentation/screens/CreationsGalleryScreen.tsx +5 -22
- package/src/domains/creations/presentation/screens/creations-gallery.styles.ts +11 -0
- package/src/domains/creations/presentation/screens/creations-gallery.types.ts +18 -0
- package/src/domains/generation/infrastructure/flow/scenario-configs.ts +69 -0
- package/src/domains/generation/infrastructure/flow/{step-builder.ts → step-builders.ts} +3 -86
- package/src/domains/generation/wizard/configs/image-to-video.config.ts +1 -1
- package/src/domains/generation/wizard/configs/text-to-image.config.ts +2 -1
- package/src/domains/generation/wizard/configs/text-to-video.config.ts +1 -1
- package/src/domains/generation/wizard/domain/entities/wizard-feature.types.ts +118 -0
- package/src/domains/generation/wizard/domain/entities/wizard-step.types.ts +96 -0
- package/src/domains/generation/wizard/index.ts +7 -3
- package/src/domains/generation/wizard/infrastructure/builders/dynamic-step-builder.ts +3 -6
- package/src/domains/generation/wizard/infrastructure/utils/index.ts +4 -1
- package/src/domains/generation/wizard/infrastructure/utils/primitive-extractors.ts +119 -0
- package/src/domains/generation/wizard/infrastructure/utils/wizard-field-extractors.ts +65 -0
- package/src/domains/generation/wizard/presentation/components/GenericWizardFlow.tsx +1 -1
- package/src/domains/generation/wizard/presentation/components/WizardFlowContent.tsx +1 -1
- package/src/domains/generation/wizard/presentation/components/WizardStepRenderer.utils.ts +1 -1
- package/src/domains/generation/wizard/presentation/hooks/useWizardGeneration.ts +17 -50
- package/src/domains/generation/wizard/presentation/hooks/wizard-generation.types.ts +39 -0
- package/src/domains/scenarios/configs/wizard-config-resolver.ts +1 -1
- package/src/domains/scenarios/configs/wizard-input.types.ts +1 -1
- package/src/domains/scenarios/configs/wizard-step-factories.ts +1 -1
- package/src/features/image-to-video/presentation/hooks/image-to-video-feature.types.ts +59 -0
- package/src/features/image-to-video/presentation/hooks/useImageToVideoFeature.ts +15 -55
- package/src/domains/generation/wizard/domain/entities/wizard-config.types.ts +0 -230
- package/src/domains/generation/wizard/infrastructure/utils/wizard-data-extractors.ts +0 -232
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Primitive Data Extractors
|
|
3
|
+
* Type-safe utilities for extracting primitive values from unknown data
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// ============================================================================
|
|
7
|
+
// Type Guards
|
|
8
|
+
// ============================================================================
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Check if value is a non-null object
|
|
12
|
+
*/
|
|
13
|
+
export function isObject(value: unknown): value is Record<string, unknown> {
|
|
14
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Check if object has a specific property
|
|
19
|
+
*/
|
|
20
|
+
export function hasProperty<K extends string>(
|
|
21
|
+
obj: Record<string, unknown>,
|
|
22
|
+
key: K,
|
|
23
|
+
): obj is Record<K, unknown> {
|
|
24
|
+
return key in obj;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// ============================================================================
|
|
28
|
+
// String Extractors
|
|
29
|
+
// ============================================================================
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Extracts string from various input formats:
|
|
33
|
+
* - Direct string: "my text"
|
|
34
|
+
* - Object with text field: { text: "my text" }
|
|
35
|
+
* - Object with uri field (fallback): { uri: "my text" }
|
|
36
|
+
*/
|
|
37
|
+
export function extractString(value: unknown): string | undefined {
|
|
38
|
+
if (typeof value === "string") {
|
|
39
|
+
return value;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (isObject(value)) {
|
|
43
|
+
if (hasProperty(value, "text") && typeof value.text === "string") {
|
|
44
|
+
return value.text;
|
|
45
|
+
}
|
|
46
|
+
if (hasProperty(value, "uri") && typeof value.uri === "string") {
|
|
47
|
+
return value.uri;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Extracts and trims string, returning undefined if empty
|
|
56
|
+
*/
|
|
57
|
+
export function extractTrimmedString(value: unknown): string | undefined {
|
|
58
|
+
const str = extractString(value);
|
|
59
|
+
const trimmed = str?.trim();
|
|
60
|
+
return trimmed && trimmed.length > 0 ? trimmed : undefined;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// ============================================================================
|
|
64
|
+
// Number Extractors
|
|
65
|
+
// ============================================================================
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Extracts number from various input formats:
|
|
69
|
+
* - Direct number: 5
|
|
70
|
+
* - Object with value field: { value: 5 }
|
|
71
|
+
* - Object with selection field: { selection: 5 }
|
|
72
|
+
*/
|
|
73
|
+
export function extractNumber(value: unknown): number | undefined {
|
|
74
|
+
if (typeof value === "number" && !Number.isNaN(value)) {
|
|
75
|
+
return value;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (isObject(value)) {
|
|
79
|
+
if (hasProperty(value, "value") && typeof value.value === "number") {
|
|
80
|
+
return value.value;
|
|
81
|
+
}
|
|
82
|
+
if (hasProperty(value, "selection") && typeof value.selection === "number") {
|
|
83
|
+
return value.selection;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ============================================================================
|
|
91
|
+
// Selection Extractors
|
|
92
|
+
// ============================================================================
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Extracts selection value (string or string array) from wizard data
|
|
96
|
+
*/
|
|
97
|
+
export function extractSelection(value: unknown): string | string[] | undefined {
|
|
98
|
+
if (typeof value === "string") {
|
|
99
|
+
return value;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (Array.isArray(value) && value.every((v) => typeof v === "string")) {
|
|
103
|
+
return value as string[];
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (isObject(value)) {
|
|
107
|
+
if (hasProperty(value, "selection")) {
|
|
108
|
+
const selection = value.selection;
|
|
109
|
+
if (typeof selection === "string") {
|
|
110
|
+
return selection;
|
|
111
|
+
}
|
|
112
|
+
if (Array.isArray(selection) && selection.every((v) => typeof v === "string")) {
|
|
113
|
+
return selection as string[];
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wizard Field Extractors
|
|
3
|
+
* Specialized extractors for wizard-specific data fields
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { extractTrimmedString, extractNumber } from "./primitive-extractors";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Extracts prompt from wizard data with fallback chain
|
|
10
|
+
* Checks multiple keys in order: prompt, motion_prompt, text, userPrompt
|
|
11
|
+
*/
|
|
12
|
+
export function extractPrompt(
|
|
13
|
+
wizardData: Record<string, unknown>,
|
|
14
|
+
fallback?: string,
|
|
15
|
+
): string | undefined {
|
|
16
|
+
const promptKeys = ["prompt", "motion_prompt", "text", "userPrompt"];
|
|
17
|
+
|
|
18
|
+
for (const key of promptKeys) {
|
|
19
|
+
if (key in wizardData) {
|
|
20
|
+
const extracted = extractTrimmedString(wizardData[key]);
|
|
21
|
+
if (extracted) {
|
|
22
|
+
return extracted;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return fallback?.trim() || undefined;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Extracts duration from wizard data
|
|
32
|
+
* Handles both direct number and object with value field
|
|
33
|
+
*/
|
|
34
|
+
export function extractDuration(
|
|
35
|
+
wizardData: Record<string, unknown>,
|
|
36
|
+
): number | undefined {
|
|
37
|
+
const durationData = wizardData.duration;
|
|
38
|
+
const extracted = extractNumber(durationData);
|
|
39
|
+
if (extracted !== undefined && extracted > 0) {
|
|
40
|
+
return extracted;
|
|
41
|
+
}
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Extracts aspect ratio from wizard data
|
|
47
|
+
* Common values: "16:9", "9:16", "1:1", "4:3"
|
|
48
|
+
*/
|
|
49
|
+
export function extractAspectRatio(
|
|
50
|
+
wizardData: Record<string, unknown>,
|
|
51
|
+
): string | undefined {
|
|
52
|
+
const aspectRatioData = wizardData.aspect_ratio;
|
|
53
|
+
return extractTrimmedString(aspectRatioData);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Extracts resolution from wizard data
|
|
58
|
+
* Common values: "720p", "1080p", "default"
|
|
59
|
+
*/
|
|
60
|
+
export function extractResolution(
|
|
61
|
+
wizardData: Record<string, unknown>,
|
|
62
|
+
): string | undefined {
|
|
63
|
+
const resolutionData = wizardData.resolution;
|
|
64
|
+
return extractTrimmedString(resolutionData);
|
|
65
|
+
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import React, { useMemo } from "react";
|
|
8
8
|
import type { StepType } from "../../../../../domain/entities/flow-config.types";
|
|
9
|
-
import type { WizardFeatureConfig } from "../../domain/entities/wizard-
|
|
9
|
+
import type { WizardFeatureConfig } from "../../domain/entities/wizard-feature.types";
|
|
10
10
|
import type { WizardScenarioData } from "../hooks/useWizardGeneration";
|
|
11
11
|
import type { AlertMessages } from "../../../../../presentation/hooks/generation/types";
|
|
12
12
|
import { validateScenario } from "../utilities/validateScenario";
|
|
@@ -8,7 +8,7 @@ import { View, StyleSheet } from "react-native";
|
|
|
8
8
|
import { useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
9
9
|
import { useFlow } from "../../../infrastructure/flow/useFlow";
|
|
10
10
|
import { StepType, type StepDefinition } from "../../../../../domain/entities/flow-config.types";
|
|
11
|
-
import type { WizardFeatureConfig } from "../../domain/entities/wizard-
|
|
11
|
+
import type { WizardFeatureConfig } from "../../domain/entities/wizard-feature.types";
|
|
12
12
|
import { buildFlowStepsFromWizard } from "../../infrastructure/builders/dynamic-step-builder";
|
|
13
13
|
import { useWizardGeneration, type WizardScenarioData } from "../hooks/useWizardGeneration";
|
|
14
14
|
import type { AlertMessages } from "../../../../../presentation/hooks/generation/types";
|
|
@@ -3,7 +3,7 @@ import type {
|
|
|
3
3
|
TextInputStepConfig,
|
|
4
4
|
PhotoUploadStepConfig,
|
|
5
5
|
SelectionStepConfig,
|
|
6
|
-
} from "../../domain/entities/wizard-
|
|
6
|
+
} from "../../domain/entities/wizard-step.types";
|
|
7
7
|
import type { UploadedImage } from "../../../../../presentation/hooks/generation/useAIGenerateState";
|
|
8
8
|
|
|
9
9
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
@@ -6,45 +6,21 @@
|
|
|
6
6
|
|
|
7
7
|
import { useEffect, useRef, useMemo, useCallback } from "react";
|
|
8
8
|
import { useGenerationOrchestrator } from "../../../../../presentation/hooks/generation";
|
|
9
|
-
import type { AlertMessages } from "../../../../../presentation/hooks/generation/types";
|
|
10
9
|
import { usePendingJobs } from "../../../../../presentation/hooks/use-pending-jobs";
|
|
11
10
|
import { createWizardStrategy, buildWizardInput } from "../../infrastructure/strategies";
|
|
11
|
+
import type {
|
|
12
|
+
UseWizardGenerationProps,
|
|
13
|
+
UseWizardGenerationReturn,
|
|
14
|
+
} from "./wizard-generation.types";
|
|
12
15
|
|
|
13
16
|
declare const __DEV__: boolean;
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
readonly aiPrompt?: string;
|
|
22
|
-
readonly outputType?: WizardOutputType;
|
|
23
|
-
/** Input type - determines required photo count. Default: "single" */
|
|
24
|
-
readonly inputType?: ScenarioInputType;
|
|
25
|
-
readonly model?: string;
|
|
26
|
-
readonly title?: string;
|
|
27
|
-
readonly description?: string;
|
|
28
|
-
[key: string]: unknown;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export interface UseWizardGenerationProps {
|
|
32
|
-
readonly scenario: WizardScenarioData;
|
|
33
|
-
readonly wizardData: Record<string, unknown>;
|
|
34
|
-
readonly userId?: string;
|
|
35
|
-
readonly isGeneratingStep: boolean;
|
|
36
|
-
/** Required - alert messages for error states */
|
|
37
|
-
readonly alertMessages: AlertMessages;
|
|
38
|
-
readonly onSuccess?: (result: unknown) => void;
|
|
39
|
-
readonly onError?: (error: string) => void;
|
|
40
|
-
readonly onCreditsExhausted?: () => void;
|
|
41
|
-
/** Enable background job tracking for CreationsGallery display */
|
|
42
|
-
readonly trackAsBackgroundJob?: boolean;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export interface UseWizardGenerationReturn {
|
|
46
|
-
readonly isGenerating: boolean;
|
|
47
|
-
}
|
|
18
|
+
export type {
|
|
19
|
+
WizardOutputType,
|
|
20
|
+
WizardScenarioData,
|
|
21
|
+
UseWizardGenerationProps,
|
|
22
|
+
UseWizardGenerationReturn,
|
|
23
|
+
} from "./wizard-generation.types";
|
|
48
24
|
|
|
49
25
|
export const useWizardGeneration = (
|
|
50
26
|
props: UseWizardGenerationProps,
|
|
@@ -64,7 +40,6 @@ export const useWizardGeneration = (
|
|
|
64
40
|
const hasStarted = useRef(false);
|
|
65
41
|
const currentJobIdRef = useRef<string | null>(null);
|
|
66
42
|
|
|
67
|
-
// Background job tracking
|
|
68
43
|
const { addJob, updateJob, removeJob } = usePendingJobs();
|
|
69
44
|
|
|
70
45
|
useEffect(() => {
|
|
@@ -84,14 +59,12 @@ export const useWizardGeneration = (
|
|
|
84
59
|
});
|
|
85
60
|
}, [scenario]);
|
|
86
61
|
|
|
87
|
-
// Handle generation success - remove job from queue
|
|
88
62
|
const handleSuccess = useCallback(
|
|
89
63
|
(result: unknown) => {
|
|
90
64
|
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
91
65
|
console.log("[useWizardGeneration] Success");
|
|
92
66
|
}
|
|
93
67
|
|
|
94
|
-
// Remove job from pending queue (creation is saved)
|
|
95
68
|
if (trackAsBackgroundJob && currentJobIdRef.current) {
|
|
96
69
|
removeJob(currentJobIdRef.current);
|
|
97
70
|
currentJobIdRef.current = null;
|
|
@@ -102,14 +75,12 @@ export const useWizardGeneration = (
|
|
|
102
75
|
[trackAsBackgroundJob, removeJob, onSuccess],
|
|
103
76
|
);
|
|
104
77
|
|
|
105
|
-
// Handle generation error - update job status
|
|
106
78
|
const handleError = useCallback(
|
|
107
79
|
(err: { message: string }) => {
|
|
108
80
|
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
109
81
|
console.log("[useWizardGeneration] Error:", err.message);
|
|
110
82
|
}
|
|
111
83
|
|
|
112
|
-
// Update job to failed status
|
|
113
84
|
if (trackAsBackgroundJob && currentJobIdRef.current) {
|
|
114
85
|
updateJob({
|
|
115
86
|
id: currentJobIdRef.current,
|
|
@@ -122,16 +93,13 @@ export const useWizardGeneration = (
|
|
|
122
93
|
[trackAsBackgroundJob, updateJob, onError],
|
|
123
94
|
);
|
|
124
95
|
|
|
125
|
-
const { generate, isGenerating } = useGenerationOrchestrator(
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
onError: handleError,
|
|
133
|
-
},
|
|
134
|
-
);
|
|
96
|
+
const { generate, isGenerating } = useGenerationOrchestrator(strategy, {
|
|
97
|
+
userId,
|
|
98
|
+
alertMessages,
|
|
99
|
+
onCreditsExhausted,
|
|
100
|
+
onSuccess: handleSuccess,
|
|
101
|
+
onError: handleError,
|
|
102
|
+
});
|
|
135
103
|
|
|
136
104
|
useEffect(() => {
|
|
137
105
|
if (isGeneratingStep && !hasStarted.current && !isGenerating) {
|
|
@@ -152,7 +120,6 @@ export const useWizardGeneration = (
|
|
|
152
120
|
return;
|
|
153
121
|
}
|
|
154
122
|
|
|
155
|
-
// Create background job for tracking
|
|
156
123
|
if (trackAsBackgroundJob && scenario.outputType) {
|
|
157
124
|
const jobId = `wizard-${scenario.id}-${Date.now()}`;
|
|
158
125
|
currentJobIdRef.current = jobId;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wizard Generation Types
|
|
3
|
+
* Types and interfaces for useWizardGeneration hook
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { AlertMessages } from "../../../../../presentation/hooks/generation/types";
|
|
7
|
+
import type { ScenarioInputType } from "../../../../scenarios/domain/Scenario";
|
|
8
|
+
|
|
9
|
+
export type WizardOutputType = "image" | "video";
|
|
10
|
+
|
|
11
|
+
export interface WizardScenarioData {
|
|
12
|
+
readonly id: string;
|
|
13
|
+
readonly aiPrompt?: string;
|
|
14
|
+
readonly outputType?: WizardOutputType;
|
|
15
|
+
/** Input type - determines required photo count. Default: "single" */
|
|
16
|
+
readonly inputType?: ScenarioInputType;
|
|
17
|
+
readonly model?: string;
|
|
18
|
+
readonly title?: string;
|
|
19
|
+
readonly description?: string;
|
|
20
|
+
[key: string]: unknown;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface UseWizardGenerationProps {
|
|
24
|
+
readonly scenario: WizardScenarioData;
|
|
25
|
+
readonly wizardData: Record<string, unknown>;
|
|
26
|
+
readonly userId?: string;
|
|
27
|
+
readonly isGeneratingStep: boolean;
|
|
28
|
+
/** Required - alert messages for error states */
|
|
29
|
+
readonly alertMessages: AlertMessages;
|
|
30
|
+
readonly onSuccess?: (result: unknown) => void;
|
|
31
|
+
readonly onError?: (error: string) => void;
|
|
32
|
+
readonly onCreditsExhausted?: () => void;
|
|
33
|
+
/** Enable background job tracking for CreationsGallery display */
|
|
34
|
+
readonly trackAsBackgroundJob?: boolean;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface UseWizardGenerationReturn {
|
|
38
|
+
readonly isGenerating: boolean;
|
|
39
|
+
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Main resolver for getting wizard configurations
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import type { WizardFeatureConfig } from "../../generation/wizard/domain/entities/wizard-
|
|
6
|
+
import type { WizardFeatureConfig } from "../../generation/wizard/domain/entities/wizard-feature.types";
|
|
7
7
|
import { getConfiguredScenario } from "../infrastructure/scenario-registry";
|
|
8
8
|
import { WizardInputType, type WizardConfigOptions } from "./wizard-input.types";
|
|
9
9
|
import { detectWizardInputType, SCENARIO_TO_WIZARD_INPUT_MAP } from "./wizard-input-detector";
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Type definitions for wizard input classification
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import type { WizardFeatureConfig } from "../../generation/wizard/domain/entities/wizard-
|
|
6
|
+
import type { WizardFeatureConfig } from "../../generation/wizard/domain/entities/wizard-feature.types";
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Input Type Classification
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Factory functions for creating wizard step configurations
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import type { WizardFeatureConfig } from "../../generation/wizard/domain/entities/wizard-
|
|
6
|
+
import type { WizardFeatureConfig } from "../../generation/wizard/domain/entities/wizard-feature.types";
|
|
7
7
|
import { WizardInputType, type WizardConfigFactory } from "./wizard-input.types";
|
|
8
8
|
|
|
9
9
|
function createDualImageConfig(scenarioId: string): WizardFeatureConfig {
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image-to-Video Feature Types
|
|
3
|
+
* Types, interfaces, and constants for the image-to-video feature hook
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type {
|
|
7
|
+
ImageToVideoFeatureState,
|
|
8
|
+
ImageToVideoFeatureConfig,
|
|
9
|
+
ImageToVideoResult,
|
|
10
|
+
ImageToVideoFeatureCallbacks,
|
|
11
|
+
ImageToVideoGenerateParams,
|
|
12
|
+
} from "../../domain/types";
|
|
13
|
+
import type { AlertMessages } from "../../../../presentation/hooks/generation";
|
|
14
|
+
|
|
15
|
+
export const INITIAL_STATE: ImageToVideoFeatureState = {
|
|
16
|
+
imageUri: null,
|
|
17
|
+
motionPrompt: "",
|
|
18
|
+
videoUrl: null,
|
|
19
|
+
thumbnailUrl: null,
|
|
20
|
+
isProcessing: false,
|
|
21
|
+
progress: 0,
|
|
22
|
+
error: null,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const DEFAULT_ALERT_MESSAGES: AlertMessages = {
|
|
26
|
+
networkError: "No internet connection. Please check your network.",
|
|
27
|
+
policyViolation: "Content not allowed. Please try again.",
|
|
28
|
+
saveFailed: "Failed to save. Please try again.",
|
|
29
|
+
creditFailed: "Credit operation failed. Please try again.",
|
|
30
|
+
unknown: "An error occurred. Please try again.",
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export interface UseImageToVideoFeatureProps {
|
|
34
|
+
config: ImageToVideoFeatureConfig;
|
|
35
|
+
callbacks?: ImageToVideoFeatureCallbacks;
|
|
36
|
+
userId: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface UseImageToVideoFeatureReturn {
|
|
40
|
+
state: ImageToVideoFeatureState;
|
|
41
|
+
setImageUri: (uri: string) => void;
|
|
42
|
+
setMotionPrompt: (prompt: string) => void;
|
|
43
|
+
generate: (params?: ImageToVideoGenerateParams) => Promise<ImageToVideoResult>;
|
|
44
|
+
reset: () => void;
|
|
45
|
+
isReady: boolean;
|
|
46
|
+
canGenerate: boolean;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface VideoGenerationInput {
|
|
50
|
+
imageUri: string;
|
|
51
|
+
imageBase64: string;
|
|
52
|
+
motionPrompt: string;
|
|
53
|
+
options?: Omit<ImageToVideoGenerateParams, "imageUri" | "motionPrompt">;
|
|
54
|
+
creationId: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function generateCreationId(): string {
|
|
58
|
+
return `image-to-video_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
59
|
+
}
|
|
@@ -7,68 +7,28 @@ import { useState, useCallback, useMemo } from "react";
|
|
|
7
7
|
import {
|
|
8
8
|
useGenerationOrchestrator,
|
|
9
9
|
type GenerationStrategy,
|
|
10
|
-
type AlertMessages,
|
|
11
10
|
} from "../../../../presentation/hooks/generation";
|
|
12
11
|
import { executeImageToVideo } from "../../infrastructure/services";
|
|
13
|
-
import type {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
12
|
+
import type { ImageToVideoResult } from "../../domain/types";
|
|
13
|
+
import {
|
|
14
|
+
INITIAL_STATE,
|
|
15
|
+
DEFAULT_ALERT_MESSAGES,
|
|
16
|
+
generateCreationId,
|
|
17
|
+
type UseImageToVideoFeatureProps,
|
|
18
|
+
type UseImageToVideoFeatureReturn,
|
|
19
|
+
type VideoGenerationInput,
|
|
20
|
+
} from "./image-to-video-feature.types";
|
|
20
21
|
|
|
21
22
|
declare const __DEV__: boolean;
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
thumbnailUrl: null,
|
|
28
|
-
isProcessing: false,
|
|
29
|
-
progress: 0,
|
|
30
|
-
error: null,
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
const DEFAULT_ALERT_MESSAGES: AlertMessages = {
|
|
34
|
-
networkError: "No internet connection. Please check your network.",
|
|
35
|
-
policyViolation: "Content not allowed. Please try again.",
|
|
36
|
-
saveFailed: "Failed to save. Please try again.",
|
|
37
|
-
creditFailed: "Credit operation failed. Please try again.",
|
|
38
|
-
unknown: "An error occurred. Please try again.",
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export interface UseImageToVideoFeatureProps {
|
|
42
|
-
config: ImageToVideoFeatureConfig;
|
|
43
|
-
callbacks?: ImageToVideoFeatureCallbacks;
|
|
44
|
-
userId: string;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export interface UseImageToVideoFeatureReturn {
|
|
48
|
-
state: ImageToVideoFeatureState;
|
|
49
|
-
setImageUri: (uri: string) => void;
|
|
50
|
-
setMotionPrompt: (prompt: string) => void;
|
|
51
|
-
generate: (params?: ImageToVideoGenerateParams) => Promise<ImageToVideoResult>;
|
|
52
|
-
reset: () => void;
|
|
53
|
-
isReady: boolean;
|
|
54
|
-
canGenerate: boolean;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
interface VideoGenerationInput {
|
|
58
|
-
imageUri: string;
|
|
59
|
-
imageBase64: string;
|
|
60
|
-
motionPrompt: string;
|
|
61
|
-
options?: Omit<ImageToVideoGenerateParams, "imageUri" | "motionPrompt">;
|
|
62
|
-
creationId: string;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function generateCreationId(): string {
|
|
66
|
-
return `image-to-video_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
67
|
-
}
|
|
24
|
+
export type {
|
|
25
|
+
UseImageToVideoFeatureProps,
|
|
26
|
+
UseImageToVideoFeatureReturn,
|
|
27
|
+
} from "./image-to-video-feature.types";
|
|
68
28
|
|
|
69
29
|
export function useImageToVideoFeature(props: UseImageToVideoFeatureProps): UseImageToVideoFeatureReturn {
|
|
70
30
|
const { config, callbacks, userId } = props;
|
|
71
|
-
const [state, setState] = useState
|
|
31
|
+
const [state, setState] = useState(INITIAL_STATE);
|
|
72
32
|
|
|
73
33
|
const strategy: GenerationStrategy<VideoGenerationInput, ImageToVideoResult> = useMemo(
|
|
74
34
|
() => ({
|
|
@@ -157,7 +117,7 @@ export function useImageToVideoFeature(props: UseImageToVideoFeatureProps): UseI
|
|
|
157
117
|
}, []);
|
|
158
118
|
|
|
159
119
|
const generate = useCallback(
|
|
160
|
-
async (params?:
|
|
120
|
+
async (params?: Parameters<UseImageToVideoFeatureReturn["generate"]>[0]): Promise<ImageToVideoResult> => {
|
|
161
121
|
const { imageUri: paramImageUri, motionPrompt: paramMotionPrompt, ...options } = params || {};
|
|
162
122
|
const effectiveImageUri = paramImageUri || state.imageUri;
|
|
163
123
|
const effectiveMotionPrompt = paramMotionPrompt ?? state.motionPrompt;
|