@umituz/react-native-ai-generation-content 1.44.4 → 1.45.0
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 +2 -2
- package/src/domains/generation/wizard/infrastructure/strategies/image-generation.types.ts +2 -0
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation.strategy.ts +2 -2
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation.types.ts +2 -0
- package/src/domains/generation/wizard/infrastructure/strategies/wizard-strategy.factory.ts +5 -3
- package/src/domains/generation/wizard/presentation/components/GenericWizardFlow.tsx +4 -0
- package/src/domains/generation/wizard/presentation/components/WizardFlow.types.ts +2 -0
- package/src/domains/generation/wizard/presentation/components/WizardFlowContent.tsx +4 -0
- package/src/domains/generation/wizard/presentation/hooks/useWizardGeneration.ts +6 -2
- package/src/domains/generation/wizard/presentation/hooks/wizard-generation.types.ts +2 -0
- package/src/features/image-to-video/presentation/screens/ImageToVideoWizardFlow.tsx +4 -2
- package/src/features/text-to-image/presentation/screens/TextToImageWizardFlow.tsx +4 -2
- package/src/features/text-to-video/presentation/screens/TextToVideoWizardFlow.tsx +4 -2
- package/src/presentation/hooks/generation/orchestrator.ts +13 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-ai-generation-content",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.45.0",
|
|
4
4
|
"description": "Provider-agnostic AI generation orchestration for React Native with result preview components",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "src/index.ts",
|
package/src/domains/generation/wizard/infrastructure/strategies/image-generation.strategy.ts
CHANGED
|
@@ -80,7 +80,7 @@ function applyStyleEnhancements(prompt: string, wizardData: Record<string, unkno
|
|
|
80
80
|
// ============================================================================
|
|
81
81
|
|
|
82
82
|
export function createImageStrategy(options: CreateImageStrategyOptions): WizardStrategy {
|
|
83
|
-
const { scenario } = options;
|
|
83
|
+
const { scenario, creditCost } = options;
|
|
84
84
|
|
|
85
85
|
return {
|
|
86
86
|
execute: async (input: unknown) => {
|
|
@@ -98,6 +98,6 @@ export function createImageStrategy(options: CreateImageStrategyOptions): Wizard
|
|
|
98
98
|
return { imageUrl: result.imageUrl };
|
|
99
99
|
},
|
|
100
100
|
|
|
101
|
-
getCreditCost: () =>
|
|
101
|
+
getCreditCost: () => creditCost,
|
|
102
102
|
};
|
|
103
103
|
}
|
|
@@ -23,4 +23,6 @@ export interface WizardImageResult {
|
|
|
23
23
|
export interface CreateImageStrategyOptions {
|
|
24
24
|
readonly scenario: WizardScenarioData;
|
|
25
25
|
readonly collectionName?: string;
|
|
26
|
+
/** Credit cost for this generation - REQUIRED, determined by the app */
|
|
27
|
+
readonly creditCost: number;
|
|
26
28
|
}
|
package/src/domains/generation/wizard/infrastructure/strategies/video-generation.strategy.ts
CHANGED
|
@@ -70,7 +70,7 @@ export async function buildVideoInput(
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
export function createVideoStrategy(options: CreateVideoStrategyOptions): WizardStrategy {
|
|
73
|
-
const { scenario } = options;
|
|
73
|
+
const { scenario, creditCost } = options;
|
|
74
74
|
const videoFeatureType = getVideoFeatureType(scenario.id);
|
|
75
75
|
|
|
76
76
|
return {
|
|
@@ -95,6 +95,6 @@ export function createVideoStrategy(options: CreateVideoStrategyOptions): Wizard
|
|
|
95
95
|
return { videoUrl: result.videoUrl };
|
|
96
96
|
},
|
|
97
97
|
|
|
98
|
-
getCreditCost: () =>
|
|
98
|
+
getCreditCost: () => creditCost,
|
|
99
99
|
};
|
|
100
100
|
}
|
|
@@ -27,6 +27,8 @@ export interface WizardVideoResult {
|
|
|
27
27
|
export interface CreateVideoStrategyOptions {
|
|
28
28
|
readonly scenario: WizardScenarioData;
|
|
29
29
|
readonly collectionName?: string;
|
|
30
|
+
/** Credit cost for this generation - REQUIRED, determined by the app */
|
|
31
|
+
readonly creditCost: number;
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
export interface PhotoValidationResult {
|
|
@@ -18,6 +18,8 @@ export type { WizardStrategy } from "./wizard-strategy.types";
|
|
|
18
18
|
export interface CreateWizardStrategyOptions {
|
|
19
19
|
readonly scenario: WizardScenarioData;
|
|
20
20
|
readonly collectionName?: string;
|
|
21
|
+
/** Credit cost for this generation - REQUIRED, determined by the app */
|
|
22
|
+
readonly creditCost: number;
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
// ============================================================================
|
|
@@ -25,14 +27,14 @@ export interface CreateWizardStrategyOptions {
|
|
|
25
27
|
// ============================================================================
|
|
26
28
|
|
|
27
29
|
export function createWizardStrategy(options: CreateWizardStrategyOptions): WizardStrategy {
|
|
28
|
-
const { scenario, collectionName } = options;
|
|
30
|
+
const { scenario, collectionName, creditCost } = options;
|
|
29
31
|
|
|
30
32
|
if (scenario.outputType === "image") {
|
|
31
|
-
return createImageStrategy({ scenario, collectionName });
|
|
33
|
+
return createImageStrategy({ scenario, collectionName, creditCost });
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
// Default to video strategy for video outputType or undefined
|
|
35
|
-
return createVideoStrategy({ scenario, collectionName });
|
|
37
|
+
return createVideoStrategy({ scenario, collectionName, creditCost });
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
// ============================================================================
|
|
@@ -24,6 +24,8 @@ export interface GenericWizardFlowProps {
|
|
|
24
24
|
readonly scenarioId?: string;
|
|
25
25
|
readonly userId?: string;
|
|
26
26
|
readonly alertMessages: AlertMessages;
|
|
27
|
+
/** Credit cost for this generation - REQUIRED, determined by the app */
|
|
28
|
+
readonly creditCost: number;
|
|
27
29
|
readonly skipResultStep?: boolean;
|
|
28
30
|
readonly onStepChange?: (stepId: string, stepType: StepType | string) => void;
|
|
29
31
|
readonly onGenerationStart?: (
|
|
@@ -49,6 +51,7 @@ export const GenericWizardFlow: React.FC<GenericWizardFlowProps> = (props) => {
|
|
|
49
51
|
scenarioId,
|
|
50
52
|
userId,
|
|
51
53
|
alertMessages,
|
|
54
|
+
creditCost,
|
|
52
55
|
skipResultStep = false,
|
|
53
56
|
onStepChange,
|
|
54
57
|
onGenerationStart,
|
|
@@ -104,6 +107,7 @@ export const GenericWizardFlow: React.FC<GenericWizardFlowProps> = (props) => {
|
|
|
104
107
|
validatedScenario={validatedScenario}
|
|
105
108
|
userId={userId}
|
|
106
109
|
alertMessages={alertMessages}
|
|
110
|
+
creditCost={creditCost}
|
|
107
111
|
skipResultStep={skipResultStep}
|
|
108
112
|
onStepChange={onStepChange}
|
|
109
113
|
onGenerationStart={onGenerationStart}
|
|
@@ -17,6 +17,8 @@ export interface BaseWizardFlowProps {
|
|
|
17
17
|
readonly creditBalance: number;
|
|
18
18
|
/** Are credits loaded */
|
|
19
19
|
readonly isCreditsLoaded: boolean;
|
|
20
|
+
/** Credit cost for this generation - REQUIRED, determined by the app */
|
|
21
|
+
readonly creditCost: number;
|
|
20
22
|
/** Show auth modal with callback */
|
|
21
23
|
readonly onShowAuthModal: (callback: () => void) => void;
|
|
22
24
|
/** Show paywall */
|
|
@@ -25,6 +25,8 @@ export interface WizardFlowContentProps {
|
|
|
25
25
|
readonly validatedScenario: WizardScenarioData;
|
|
26
26
|
readonly userId?: string;
|
|
27
27
|
readonly alertMessages: AlertMessages;
|
|
28
|
+
/** Credit cost for this generation - REQUIRED, determined by the app */
|
|
29
|
+
readonly creditCost: number;
|
|
28
30
|
readonly skipResultStep?: boolean;
|
|
29
31
|
readonly onStepChange?: (stepId: string, stepType: StepType | string) => void;
|
|
30
32
|
readonly onGenerationStart?: (
|
|
@@ -49,6 +51,7 @@ export const WizardFlowContent: React.FC<WizardFlowContentProps> = (props) => {
|
|
|
49
51
|
validatedScenario,
|
|
50
52
|
userId,
|
|
51
53
|
alertMessages,
|
|
54
|
+
creditCost,
|
|
52
55
|
skipResultStep = false,
|
|
53
56
|
onStepChange,
|
|
54
57
|
onGenerationStart,
|
|
@@ -127,6 +130,7 @@ export const WizardFlowContent: React.FC<WizardFlowContentProps> = (props) => {
|
|
|
127
130
|
userId,
|
|
128
131
|
isGeneratingStep: currentStep?.type === StepType.GENERATING,
|
|
129
132
|
alertMessages,
|
|
133
|
+
creditCost,
|
|
130
134
|
onSuccess: handlers.handleGenerationComplete,
|
|
131
135
|
onError: onGenerationError,
|
|
132
136
|
onCreditsExhausted,
|
|
@@ -33,6 +33,7 @@ export const useWizardGeneration = (
|
|
|
33
33
|
userId,
|
|
34
34
|
isGeneratingStep,
|
|
35
35
|
alertMessages,
|
|
36
|
+
creditCost,
|
|
36
37
|
onSuccess,
|
|
37
38
|
onError,
|
|
38
39
|
onCreditsExhausted,
|
|
@@ -45,8 +46,11 @@ export const useWizardGeneration = (
|
|
|
45
46
|
// Persistence utility - separate from strategy
|
|
46
47
|
const persistence = useMemo(() => createCreationPersistence(), []);
|
|
47
48
|
|
|
48
|
-
// Strategy - only handles execution
|
|
49
|
-
const strategy = useMemo(
|
|
49
|
+
// Strategy - only handles execution, creditCost is passed from app
|
|
50
|
+
const strategy = useMemo(
|
|
51
|
+
() => createWizardStrategy({ scenario, creditCost }),
|
|
52
|
+
[scenario, creditCost],
|
|
53
|
+
);
|
|
50
54
|
|
|
51
55
|
const handleSuccess = useCallback(
|
|
52
56
|
async (result: unknown) => {
|
|
@@ -27,6 +27,8 @@ export interface UseWizardGenerationProps {
|
|
|
27
27
|
readonly isGeneratingStep: boolean;
|
|
28
28
|
/** Required - alert messages for error states */
|
|
29
29
|
readonly alertMessages: AlertMessages;
|
|
30
|
+
/** Credit cost for this generation - REQUIRED, determined by the app */
|
|
31
|
+
readonly creditCost: number;
|
|
30
32
|
readonly onSuccess?: (result: unknown) => void;
|
|
31
33
|
readonly onError?: (error: string) => void;
|
|
32
34
|
readonly onCreditsExhausted?: () => void;
|
|
@@ -33,6 +33,7 @@ export const ImageToVideoWizardFlow: React.FC<ImageToVideoWizardFlowProps> = (pr
|
|
|
33
33
|
hasPremium,
|
|
34
34
|
creditBalance,
|
|
35
35
|
isCreditsLoaded,
|
|
36
|
+
creditCost,
|
|
36
37
|
onShowAuthModal,
|
|
37
38
|
onShowPaywall,
|
|
38
39
|
onGenerationComplete,
|
|
@@ -63,10 +64,10 @@ export const ImageToVideoWizardFlow: React.FC<ImageToVideoWizardFlowProps> = (pr
|
|
|
63
64
|
const handleGenerationStart = useCallback(
|
|
64
65
|
(_data: Record<string, unknown>, proceed: () => void) => {
|
|
65
66
|
if (!isAuthenticated) { onShowAuthModal(proceed); return; }
|
|
66
|
-
if (!hasPremium && isCreditsLoaded && creditBalance <
|
|
67
|
+
if (!hasPremium && isCreditsLoaded && creditBalance < creditCost) { onShowPaywall(); return; }
|
|
67
68
|
proceed();
|
|
68
69
|
},
|
|
69
|
-
[isAuthenticated, hasPremium, creditBalance, isCreditsLoaded, onShowAuthModal, onShowPaywall],
|
|
70
|
+
[isAuthenticated, hasPremium, creditBalance, creditCost, isCreditsLoaded, onShowAuthModal, onShowPaywall],
|
|
70
71
|
);
|
|
71
72
|
|
|
72
73
|
return (
|
|
@@ -76,6 +77,7 @@ export const ImageToVideoWizardFlow: React.FC<ImageToVideoWizardFlowProps> = (pr
|
|
|
76
77
|
scenario={scenario}
|
|
77
78
|
userId={userId}
|
|
78
79
|
alertMessages={alertMessages ?? defaultAlerts}
|
|
80
|
+
creditCost={creditCost}
|
|
79
81
|
onGenerationStart={handleGenerationStart}
|
|
80
82
|
onGenerationComplete={onGenerationComplete}
|
|
81
83
|
onGenerationError={onGenerationError}
|
|
@@ -33,6 +33,7 @@ export const TextToImageWizardFlow: React.FC<TextToImageWizardFlowProps> = (prop
|
|
|
33
33
|
hasPremium,
|
|
34
34
|
creditBalance,
|
|
35
35
|
isCreditsLoaded,
|
|
36
|
+
creditCost,
|
|
36
37
|
onShowAuthModal,
|
|
37
38
|
onShowPaywall,
|
|
38
39
|
onGenerationComplete,
|
|
@@ -63,10 +64,10 @@ export const TextToImageWizardFlow: React.FC<TextToImageWizardFlowProps> = (prop
|
|
|
63
64
|
const handleGenerationStart = useCallback(
|
|
64
65
|
(_data: Record<string, unknown>, proceed: () => void) => {
|
|
65
66
|
if (!isAuthenticated) { onShowAuthModal(proceed); return; }
|
|
66
|
-
if (!hasPremium && isCreditsLoaded && creditBalance <
|
|
67
|
+
if (!hasPremium && isCreditsLoaded && creditBalance < creditCost) { onShowPaywall(); return; }
|
|
67
68
|
proceed();
|
|
68
69
|
},
|
|
69
|
-
[isAuthenticated, hasPremium, creditBalance, isCreditsLoaded, onShowAuthModal, onShowPaywall],
|
|
70
|
+
[isAuthenticated, hasPremium, creditBalance, creditCost, isCreditsLoaded, onShowAuthModal, onShowPaywall],
|
|
70
71
|
);
|
|
71
72
|
|
|
72
73
|
return (
|
|
@@ -76,6 +77,7 @@ export const TextToImageWizardFlow: React.FC<TextToImageWizardFlowProps> = (prop
|
|
|
76
77
|
scenario={scenario}
|
|
77
78
|
userId={userId}
|
|
78
79
|
alertMessages={alertMessages ?? defaultAlerts}
|
|
80
|
+
creditCost={creditCost}
|
|
79
81
|
onGenerationStart={handleGenerationStart}
|
|
80
82
|
onGenerationComplete={onGenerationComplete}
|
|
81
83
|
onGenerationError={onGenerationError}
|
|
@@ -33,6 +33,7 @@ export const TextToVideoWizardFlow: React.FC<TextToVideoWizardFlowProps> = (prop
|
|
|
33
33
|
hasPremium,
|
|
34
34
|
creditBalance,
|
|
35
35
|
isCreditsLoaded,
|
|
36
|
+
creditCost,
|
|
36
37
|
onShowAuthModal,
|
|
37
38
|
onShowPaywall,
|
|
38
39
|
onGenerationComplete,
|
|
@@ -63,10 +64,10 @@ export const TextToVideoWizardFlow: React.FC<TextToVideoWizardFlowProps> = (prop
|
|
|
63
64
|
const handleGenerationStart = useCallback(
|
|
64
65
|
(_data: Record<string, unknown>, proceed: () => void) => {
|
|
65
66
|
if (!isAuthenticated) { onShowAuthModal(proceed); return; }
|
|
66
|
-
if (!hasPremium && isCreditsLoaded && creditBalance <
|
|
67
|
+
if (!hasPremium && isCreditsLoaded && creditBalance < creditCost) { onShowPaywall(); return; }
|
|
67
68
|
proceed();
|
|
68
69
|
},
|
|
69
|
-
[isAuthenticated, hasPremium, creditBalance, isCreditsLoaded, onShowAuthModal, onShowPaywall],
|
|
70
|
+
[isAuthenticated, hasPremium, creditBalance, creditCost, isCreditsLoaded, onShowAuthModal, onShowPaywall],
|
|
70
71
|
);
|
|
71
72
|
|
|
72
73
|
return (
|
|
@@ -76,6 +77,7 @@ export const TextToVideoWizardFlow: React.FC<TextToVideoWizardFlowProps> = (prop
|
|
|
76
77
|
scenario={scenario}
|
|
77
78
|
userId={userId}
|
|
78
79
|
alertMessages={alertMessages ?? defaultAlerts}
|
|
80
|
+
creditCost={creditCost}
|
|
79
81
|
onGenerationStart={handleGenerationStart}
|
|
80
82
|
onGenerationComplete={onGenerationComplete}
|
|
81
83
|
onGenerationError={onGenerationError}
|
|
@@ -36,7 +36,7 @@ export const useGenerationOrchestrator = <TInput, TResult>(
|
|
|
36
36
|
|
|
37
37
|
const offlineStore = useOfflineStore();
|
|
38
38
|
const { showError, showSuccess } = useAlert();
|
|
39
|
-
const { deductCredit } = useDeductCredit({ userId, onCreditsExhausted });
|
|
39
|
+
const { deductCredit, checkCredits } = useDeductCredit({ userId, onCreditsExhausted });
|
|
40
40
|
|
|
41
41
|
useEffect(() => {
|
|
42
42
|
isMountedRef.current = true;
|
|
@@ -93,6 +93,17 @@ export const useGenerationOrchestrator = <TInput, TResult>(
|
|
|
93
93
|
try {
|
|
94
94
|
if (!offlineStore.isOnline) throw createGenerationError("network", alertMessages.networkError);
|
|
95
95
|
|
|
96
|
+
// Pre-validate credits before generation to catch concurrent consumption
|
|
97
|
+
const creditCost = strategy.getCreditCost();
|
|
98
|
+
const hasEnoughCredits = await checkCredits(creditCost);
|
|
99
|
+
if (!hasEnoughCredits) {
|
|
100
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
101
|
+
console.log("[Orchestrator] Pre-validation: insufficient credits");
|
|
102
|
+
}
|
|
103
|
+
onCreditsExhausted?.();
|
|
104
|
+
throw createGenerationError("credits", alertMessages.creditFailed);
|
|
105
|
+
}
|
|
106
|
+
|
|
96
107
|
return await handleModeration({
|
|
97
108
|
input,
|
|
98
109
|
moderation,
|
|
@@ -118,7 +129,7 @@ export const useGenerationOrchestrator = <TInput, TResult>(
|
|
|
118
129
|
isGeneratingRef.current = false;
|
|
119
130
|
}
|
|
120
131
|
},
|
|
121
|
-
[moderation, alertMessages, offlineStore.isOnline, executeGeneration, showError, onError, handleLifecycleComplete],
|
|
132
|
+
[moderation, alertMessages, offlineStore.isOnline, strategy, checkCredits, onCreditsExhausted, executeGeneration, showError, onError, handleLifecycleComplete],
|
|
122
133
|
);
|
|
123
134
|
|
|
124
135
|
const reset = useCallback(() => {
|