@umituz/react-native-ai-generation-content 1.20.38 → 1.20.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/domain/entities/flow-config.types.ts +174 -0
- package/src/domain/entities/index.ts +1 -0
- package/src/features/hd-touch-up/presentation/hooks/useHDTouchUpFeature.ts +1 -1
- package/src/features/photo-restoration/presentation/hooks/usePhotoRestoreFeature.ts +1 -1
- package/src/features/remove-background/presentation/hooks/useRemoveBackgroundFeature.ts +1 -1
- package/src/features/upscaling/presentation/hooks/useUpscaleFeature.ts +1 -1
- package/src/index.ts +22 -0
- package/src/infrastructure/flow/index.ts +7 -0
- package/src/infrastructure/flow/useFlow.ts +87 -0
- package/src/infrastructure/flow/useFlowStore.ts +145 -0
- package/src/presentation/components/AIGenerationConfig.tsx +0 -3
- package/src/presentation/components/flows/AIGenerateWizardFlow.tsx +2 -2
- package/src/presentation/components/flows/AIGenerateWizardFlow.types.ts +15 -2
- package/src/presentation/components/flows/useAIGenerateWizardFlow.ts +13 -6
- package/src/presentation/hooks/generation/orchestrator.ts +4 -1
- package/src/presentation/hooks/generation/useAIFeatureGeneration.ts +16 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-ai-generation-content",
|
|
3
|
-
"version": "1.20.
|
|
3
|
+
"version": "1.20.40",
|
|
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",
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flow Configuration Types
|
|
3
|
+
* Generic multi-step flow system for AI generation
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/** Step Types */
|
|
7
|
+
export enum StepType {
|
|
8
|
+
CATEGORY_SELECTION = "category_selection",
|
|
9
|
+
SCENARIO_SELECTION = "scenario_selection",
|
|
10
|
+
SCENARIO_PREVIEW = "scenario_preview",
|
|
11
|
+
PARTNER_UPLOAD = "partner_upload",
|
|
12
|
+
TEXT_INPUT = "text_input",
|
|
13
|
+
FEATURE_SELECTION = "feature_selection",
|
|
14
|
+
GENERATING = "generating",
|
|
15
|
+
RESULT_PREVIEW = "result_preview",
|
|
16
|
+
CUSTOM = "custom",
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Partner Configuration */
|
|
20
|
+
export interface PartnerConfig {
|
|
21
|
+
readonly partnerId: "A" | "B" | "single";
|
|
22
|
+
readonly showNameInput?: boolean;
|
|
23
|
+
readonly showFaceDetection?: boolean;
|
|
24
|
+
readonly showPhotoTips?: boolean;
|
|
25
|
+
readonly maxNameLength?: number;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Category Data - App provides */
|
|
29
|
+
export interface CategoryData {
|
|
30
|
+
readonly id: string;
|
|
31
|
+
readonly titleKey: string;
|
|
32
|
+
readonly descriptionKey?: string;
|
|
33
|
+
readonly icon: string;
|
|
34
|
+
readonly imageUrl?: string;
|
|
35
|
+
readonly subcategories?: readonly CategoryData[];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Scenario Data - App provides */
|
|
39
|
+
export interface ScenarioData {
|
|
40
|
+
readonly id: string;
|
|
41
|
+
readonly categoryId?: string;
|
|
42
|
+
readonly titleKey: string;
|
|
43
|
+
readonly descriptionKey: string;
|
|
44
|
+
readonly icon: string;
|
|
45
|
+
readonly imageUrl?: string;
|
|
46
|
+
readonly previewImageUrl?: string;
|
|
47
|
+
readonly aiPrompt: string;
|
|
48
|
+
readonly storyTemplate?: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Visual Style Option */
|
|
52
|
+
export interface VisualStyleData {
|
|
53
|
+
readonly id: string;
|
|
54
|
+
readonly icon: string;
|
|
55
|
+
readonly labelKey: string;
|
|
56
|
+
readonly promptModifier?: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Uploaded Image Data */
|
|
60
|
+
export interface UploadedImageData {
|
|
61
|
+
readonly uri: string;
|
|
62
|
+
readonly base64: string;
|
|
63
|
+
readonly mimeType: string;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Step Transition */
|
|
67
|
+
export interface StepTransition {
|
|
68
|
+
readonly next?: string | ((state: FlowState) => string | null);
|
|
69
|
+
readonly back?: string;
|
|
70
|
+
readonly skipIf?: (state: FlowState) => boolean;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Step Definition */
|
|
74
|
+
export interface StepDefinition<TConfig = unknown> {
|
|
75
|
+
readonly id: string;
|
|
76
|
+
readonly type: StepType;
|
|
77
|
+
readonly required?: boolean;
|
|
78
|
+
readonly config?: TConfig;
|
|
79
|
+
readonly transitions?: StepTransition;
|
|
80
|
+
readonly component?: React.ComponentType<StepComponentProps>;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Flow Generation Status */
|
|
84
|
+
export type FlowGenerationStatus = "idle" | "preparing" | "generating" | "completed" | "failed";
|
|
85
|
+
|
|
86
|
+
/** Flow State */
|
|
87
|
+
export interface FlowState {
|
|
88
|
+
readonly currentStepId: string;
|
|
89
|
+
readonly currentStepIndex: number;
|
|
90
|
+
readonly completedSteps: readonly string[];
|
|
91
|
+
readonly selectedCategory?: CategoryData;
|
|
92
|
+
readonly selectedScenario?: ScenarioData;
|
|
93
|
+
readonly partners: Record<string, UploadedImageData | undefined>;
|
|
94
|
+
readonly partnerNames: Record<string, string>;
|
|
95
|
+
readonly textInput?: string;
|
|
96
|
+
readonly visualStyle?: string;
|
|
97
|
+
readonly selectedFeatures: Record<string, readonly string[]>;
|
|
98
|
+
readonly customData: Record<string, unknown>;
|
|
99
|
+
readonly generationStatus: FlowGenerationStatus;
|
|
100
|
+
readonly generationProgress: number;
|
|
101
|
+
readonly generationResult?: unknown;
|
|
102
|
+
readonly generationError?: string;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** Flow Actions */
|
|
106
|
+
export interface FlowActions {
|
|
107
|
+
goToStep: (stepId: string) => void;
|
|
108
|
+
nextStep: () => void;
|
|
109
|
+
previousStep: () => void;
|
|
110
|
+
setCategory: (category: CategoryData | undefined) => void;
|
|
111
|
+
setScenario: (scenario: ScenarioData | undefined) => void;
|
|
112
|
+
setPartnerImage: (partnerId: string, image: UploadedImageData | undefined) => void;
|
|
113
|
+
setPartnerName: (partnerId: string, name: string) => void;
|
|
114
|
+
setTextInput: (text: string) => void;
|
|
115
|
+
setVisualStyle: (styleId: string) => void;
|
|
116
|
+
setSelectedFeatures: (featureType: string, ids: readonly string[]) => void;
|
|
117
|
+
setCustomData: (key: string, value: unknown) => void;
|
|
118
|
+
startGeneration: () => void;
|
|
119
|
+
updateProgress: (progress: number) => void;
|
|
120
|
+
setResult: (result: unknown) => void;
|
|
121
|
+
setError: (error: string) => void;
|
|
122
|
+
reset: () => void;
|
|
123
|
+
completeStep: (stepId: string) => void;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** Step Component Props */
|
|
127
|
+
export interface StepComponentProps {
|
|
128
|
+
readonly step: StepDefinition;
|
|
129
|
+
readonly state: FlowState;
|
|
130
|
+
readonly actions: FlowActions;
|
|
131
|
+
readonly onNext: () => void;
|
|
132
|
+
readonly onBack: () => void;
|
|
133
|
+
readonly isProcessing: boolean;
|
|
134
|
+
readonly progress: number;
|
|
135
|
+
readonly error: string | null;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** Flow Callbacks */
|
|
139
|
+
export interface FlowCallbacks {
|
|
140
|
+
onAuthRequired?: (resume: () => void) => void;
|
|
141
|
+
onCreditsExhausted?: () => void;
|
|
142
|
+
onGenerationStart?: () => void;
|
|
143
|
+
onGenerationSuccess?: (result: unknown) => void;
|
|
144
|
+
onGenerationError?: (error: string) => void;
|
|
145
|
+
onStepChange?: (stepId: string, index: number) => void;
|
|
146
|
+
onFlowComplete?: (result: unknown) => void;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** Flow Data Provider - App provides data */
|
|
150
|
+
export interface FlowDataProvider {
|
|
151
|
+
readonly categories?: readonly CategoryData[];
|
|
152
|
+
readonly scenarios?: readonly ScenarioData[];
|
|
153
|
+
readonly visualStyles?: readonly VisualStyleData[];
|
|
154
|
+
readonly surprisePrompts?: readonly string[];
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** Flow Configuration */
|
|
158
|
+
export interface FlowConfiguration {
|
|
159
|
+
readonly id: string;
|
|
160
|
+
readonly steps: readonly StepDefinition[];
|
|
161
|
+
readonly initialStepId?: string;
|
|
162
|
+
readonly callbacks?: FlowCallbacks;
|
|
163
|
+
readonly data?: FlowDataProvider;
|
|
164
|
+
readonly creditCost?: number;
|
|
165
|
+
readonly userId?: string;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** Flow Features */
|
|
169
|
+
export interface FlowFeatures {
|
|
170
|
+
readonly categorySelection: boolean;
|
|
171
|
+
readonly partnerCount: 0 | 1 | 2;
|
|
172
|
+
readonly textInput: boolean;
|
|
173
|
+
readonly scenarioSelection: boolean;
|
|
174
|
+
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { useSingleImageFeature, type BaseSingleImageHookReturn } from "../../../image-to-image";
|
|
7
|
-
import type { HDTouchUpFeatureConfig
|
|
7
|
+
import type { HDTouchUpFeatureConfig } from "../../domain/types";
|
|
8
8
|
|
|
9
9
|
export interface UseHDTouchUpFeatureProps {
|
|
10
10
|
config: HDTouchUpFeatureConfig;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { useSingleImageFeature, type BaseSingleImageHookReturn } from "../../../image-to-image";
|
|
7
|
-
import type { PhotoRestoreFeatureConfig
|
|
7
|
+
import type { PhotoRestoreFeatureConfig } from "../../domain/types";
|
|
8
8
|
|
|
9
9
|
export interface UsePhotoRestoreFeatureProps {
|
|
10
10
|
config: PhotoRestoreFeatureConfig;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { useSingleImageFeature, type BaseSingleImageHookReturn } from "../../../image-to-image";
|
|
7
|
-
import type { RemoveBackgroundFeatureConfig
|
|
7
|
+
import type { RemoveBackgroundFeatureConfig } from "../../domain/types";
|
|
8
8
|
|
|
9
9
|
export interface UseRemoveBackgroundFeatureProps {
|
|
10
10
|
config: RemoveBackgroundFeatureConfig;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { useSingleImageFeature, type BaseSingleImageHookReturn } from "../../../image-to-image";
|
|
7
|
-
import type { UpscaleFeatureConfig
|
|
7
|
+
import type { UpscaleFeatureConfig } from "../../domain/types";
|
|
8
8
|
|
|
9
9
|
export interface UseUpscaleFeatureProps {
|
|
10
10
|
config: UpscaleFeatureConfig;
|
package/src/index.ts
CHANGED
|
@@ -194,3 +194,25 @@ export type {
|
|
|
194
194
|
|
|
195
195
|
// AIGenerationWizard - Generic wizard for all AI generation flows
|
|
196
196
|
export * from "./features/wizard";
|
|
197
|
+
|
|
198
|
+
// Flow System - Dynamic multi-step flow management
|
|
199
|
+
export { createFlowStore, useFlow, resetFlowStore } from "./infrastructure/flow";
|
|
200
|
+
export type { FlowStoreType } from "./infrastructure/flow";
|
|
201
|
+
export { StepType } from "./domain/entities/flow-config.types";
|
|
202
|
+
export type {
|
|
203
|
+
StepDefinition,
|
|
204
|
+
FlowState,
|
|
205
|
+
FlowActions,
|
|
206
|
+
FlowConfiguration,
|
|
207
|
+
FlowCallbacks,
|
|
208
|
+
FlowDataProvider,
|
|
209
|
+
FlowFeatures,
|
|
210
|
+
StepComponentProps,
|
|
211
|
+
StepTransition,
|
|
212
|
+
PartnerConfig,
|
|
213
|
+
CategoryData,
|
|
214
|
+
ScenarioData,
|
|
215
|
+
VisualStyleData,
|
|
216
|
+
UploadedImageData,
|
|
217
|
+
FlowGenerationStatus,
|
|
218
|
+
} from "./domain/entities/flow-config.types";
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useFlow Hook
|
|
3
|
+
* Main hook for accessing flow state and actions
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { useRef, useCallback, useMemo } from "react";
|
|
7
|
+
import { createFlowStore, type FlowStoreType } from "./useFlowStore";
|
|
8
|
+
import type { FlowState, FlowActions, StepDefinition } from "../../domain/entities/flow-config.types";
|
|
9
|
+
|
|
10
|
+
interface UseFlowConfig {
|
|
11
|
+
steps: readonly StepDefinition[];
|
|
12
|
+
initialStepId?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface UseFlowReturn extends FlowState, FlowActions {
|
|
16
|
+
canGoNext: boolean;
|
|
17
|
+
canGoBack: boolean;
|
|
18
|
+
currentStep: StepDefinition | undefined;
|
|
19
|
+
totalSteps: number;
|
|
20
|
+
isFirstStep: boolean;
|
|
21
|
+
isLastStep: boolean;
|
|
22
|
+
hasPartner: (partnerId: string) => boolean;
|
|
23
|
+
getPartnerImage: (partnerId: string) => FlowState["partners"][string];
|
|
24
|
+
getPartnerName: (partnerId: string) => string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let flowStoreInstance: FlowStoreType | null = null;
|
|
28
|
+
|
|
29
|
+
export const useFlow = (config: UseFlowConfig): UseFlowReturn => {
|
|
30
|
+
const storeRef = useRef<FlowStoreType | null>(null);
|
|
31
|
+
|
|
32
|
+
if (!storeRef.current) {
|
|
33
|
+
if (!flowStoreInstance) {
|
|
34
|
+
flowStoreInstance = createFlowStore(config);
|
|
35
|
+
}
|
|
36
|
+
storeRef.current = flowStoreInstance;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const store = storeRef.current;
|
|
40
|
+
const state = store();
|
|
41
|
+
const totalSteps = config.steps.length;
|
|
42
|
+
|
|
43
|
+
const canGoNext = state.currentStepIndex < totalSteps - 1;
|
|
44
|
+
const canGoBack = state.currentStepIndex > 0;
|
|
45
|
+
const isFirstStep = state.currentStepIndex === 0;
|
|
46
|
+
const isLastStep = state.currentStepIndex === totalSteps - 1;
|
|
47
|
+
|
|
48
|
+
const currentStep = useMemo(
|
|
49
|
+
() => config.steps[state.currentStepIndex],
|
|
50
|
+
[config.steps, state.currentStepIndex],
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const hasPartner = useCallback(
|
|
54
|
+
(partnerId: string) => state.partners[partnerId] != null,
|
|
55
|
+
[state.partners],
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
const getPartnerImage = useCallback(
|
|
59
|
+
(partnerId: string) => state.partners[partnerId],
|
|
60
|
+
[state.partners],
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
const getPartnerName = useCallback(
|
|
64
|
+
(partnerId: string) => state.partnerNames[partnerId] ?? "",
|
|
65
|
+
[state.partnerNames],
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
...state,
|
|
70
|
+
canGoNext,
|
|
71
|
+
canGoBack,
|
|
72
|
+
currentStep,
|
|
73
|
+
totalSteps,
|
|
74
|
+
isFirstStep,
|
|
75
|
+
isLastStep,
|
|
76
|
+
hasPartner,
|
|
77
|
+
getPartnerImage,
|
|
78
|
+
getPartnerName,
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export const resetFlowStore = () => {
|
|
83
|
+
if (flowStoreInstance) {
|
|
84
|
+
flowStoreInstance.getState().reset();
|
|
85
|
+
}
|
|
86
|
+
flowStoreInstance = null;
|
|
87
|
+
};
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useFlowStore
|
|
3
|
+
* Zustand store for multi-step flow state management
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { createStore } from "@umituz/react-native-design-system";
|
|
7
|
+
import type {
|
|
8
|
+
FlowState,
|
|
9
|
+
FlowActions,
|
|
10
|
+
CategoryData,
|
|
11
|
+
ScenarioData,
|
|
12
|
+
UploadedImageData,
|
|
13
|
+
StepDefinition,
|
|
14
|
+
} from "../../domain/entities/flow-config.types";
|
|
15
|
+
|
|
16
|
+
interface FlowStoreState extends FlowState {
|
|
17
|
+
stepDefinitions: readonly StepDefinition[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const createInitialState = (): FlowState => ({
|
|
21
|
+
currentStepId: "",
|
|
22
|
+
currentStepIndex: 0,
|
|
23
|
+
completedSteps: [],
|
|
24
|
+
selectedCategory: undefined,
|
|
25
|
+
selectedScenario: undefined,
|
|
26
|
+
partners: {},
|
|
27
|
+
partnerNames: {},
|
|
28
|
+
textInput: undefined,
|
|
29
|
+
visualStyle: undefined,
|
|
30
|
+
selectedFeatures: {},
|
|
31
|
+
customData: {},
|
|
32
|
+
generationStatus: "idle",
|
|
33
|
+
generationProgress: 0,
|
|
34
|
+
generationResult: undefined,
|
|
35
|
+
generationError: undefined,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
interface FlowStoreConfig {
|
|
39
|
+
steps: readonly StepDefinition[];
|
|
40
|
+
initialStepId?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const createFlowStore = (config: FlowStoreConfig) => {
|
|
44
|
+
const initialStepId = config.initialStepId ?? config.steps[0]?.id ?? "";
|
|
45
|
+
const initialIndex = Math.max(0, config.steps.findIndex((s) => s.id === initialStepId));
|
|
46
|
+
|
|
47
|
+
const initialState: FlowStoreState = {
|
|
48
|
+
...createInitialState(),
|
|
49
|
+
currentStepId: initialStepId,
|
|
50
|
+
currentStepIndex: initialIndex,
|
|
51
|
+
stepDefinitions: config.steps,
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
return createStore<FlowStoreState, FlowActions>({
|
|
55
|
+
name: "flow_store",
|
|
56
|
+
initialState,
|
|
57
|
+
persist: false,
|
|
58
|
+
actions: (set, get) => ({
|
|
59
|
+
goToStep: (stepId: string) => {
|
|
60
|
+
const { stepDefinitions } = get();
|
|
61
|
+
const index = stepDefinitions.findIndex((s) => s.id === stepId);
|
|
62
|
+
if (index >= 0) {
|
|
63
|
+
set({ currentStepId: stepId, currentStepIndex: index, generationError: undefined });
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
nextStep: () => {
|
|
68
|
+
const { stepDefinitions, currentStepIndex, completedSteps, currentStepId } = get();
|
|
69
|
+
const nextIndex = currentStepIndex + 1;
|
|
70
|
+
if (nextIndex < stepDefinitions.length) {
|
|
71
|
+
const nextStep = stepDefinitions[nextIndex];
|
|
72
|
+
const newCompleted = completedSteps.includes(currentStepId)
|
|
73
|
+
? completedSteps
|
|
74
|
+
: [...completedSteps, currentStepId];
|
|
75
|
+
set({ currentStepId: nextStep.id, currentStepIndex: nextIndex, completedSteps: newCompleted });
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
previousStep: () => {
|
|
80
|
+
const { stepDefinitions, currentStepIndex } = get();
|
|
81
|
+
if (currentStepIndex > 0) {
|
|
82
|
+
const prevStep = stepDefinitions[currentStepIndex - 1];
|
|
83
|
+
set({ currentStepId: prevStep.id, currentStepIndex: currentStepIndex - 1 });
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
setCategory: (category: CategoryData | undefined) => set({ selectedCategory: category }),
|
|
88
|
+
setScenario: (scenario: ScenarioData | undefined) => set({ selectedScenario: scenario }),
|
|
89
|
+
|
|
90
|
+
setPartnerImage: (partnerId: string, image: UploadedImageData | undefined) => {
|
|
91
|
+
const { partners } = get();
|
|
92
|
+
set({ partners: { ...partners, [partnerId]: image } });
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
setPartnerName: (partnerId: string, name: string) => {
|
|
96
|
+
const { partnerNames } = get();
|
|
97
|
+
set({ partnerNames: { ...partnerNames, [partnerId]: name } });
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
setTextInput: (text: string) => set({ textInput: text }),
|
|
101
|
+
setVisualStyle: (styleId: string) => set({ visualStyle: styleId }),
|
|
102
|
+
|
|
103
|
+
setSelectedFeatures: (featureType: string, ids: readonly string[]) => {
|
|
104
|
+
const { selectedFeatures } = get();
|
|
105
|
+
set({ selectedFeatures: { ...selectedFeatures, [featureType]: ids } });
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
setCustomData: (key: string, value: unknown) => {
|
|
109
|
+
const { customData } = get();
|
|
110
|
+
set({ customData: { ...customData, [key]: value } });
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
startGeneration: () => {
|
|
114
|
+
set({ generationStatus: "preparing", generationProgress: 0, generationError: undefined });
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
updateProgress: (progress: number) => {
|
|
118
|
+
set({ generationProgress: progress, generationStatus: progress > 0 ? "generating" : "preparing" });
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
setResult: (result: unknown) => {
|
|
122
|
+
set({ generationResult: result, generationStatus: "completed", generationProgress: 100 });
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
setError: (error: string) => {
|
|
126
|
+
set({ generationError: error, generationStatus: "failed", generationProgress: 0 });
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
reset: () => {
|
|
130
|
+
const { stepDefinitions } = get();
|
|
131
|
+
const firstStepId = stepDefinitions[0]?.id ?? "";
|
|
132
|
+
set({ ...createInitialState(), currentStepId: firstStepId, stepDefinitions });
|
|
133
|
+
},
|
|
134
|
+
|
|
135
|
+
completeStep: (stepId: string) => {
|
|
136
|
+
const { completedSteps } = get();
|
|
137
|
+
if (!completedSteps.includes(stepId)) {
|
|
138
|
+
set({ completedSteps: [...completedSteps, stepId] });
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
}),
|
|
142
|
+
});
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
export type FlowStoreType = ReturnType<typeof createFlowStore>;
|
|
@@ -4,7 +4,6 @@ import { View, Image, StyleSheet } from "react-native";
|
|
|
4
4
|
import { AIGenerationHero } from "./AIGenerationHero";
|
|
5
5
|
import { AIGenerationForm } from "./AIGenerationForm";
|
|
6
6
|
import type { AIGenerationFormProps } from "./AIGenerationForm.types";
|
|
7
|
-
import { useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
8
7
|
|
|
9
8
|
export interface AIGenerationConfigProps extends Omit<AIGenerationFormProps, "isGenerating" | "progress"> {
|
|
10
9
|
readonly heroTitle: string;
|
|
@@ -24,8 +23,6 @@ export const AIGenerationConfig: React.FC<AIGenerationConfigProps> = ({
|
|
|
24
23
|
progress = 0,
|
|
25
24
|
...formProps
|
|
26
25
|
}) => {
|
|
27
|
-
const tokens = useAppDesignTokens();
|
|
28
|
-
|
|
29
26
|
return (
|
|
30
27
|
<View style={styles.container}>
|
|
31
28
|
{heroTitle && (
|
|
@@ -61,7 +61,7 @@ export const AIGenerateWizardFlow: React.FC<AIGenerateWizardFlowProps> = ({
|
|
|
61
61
|
<PartnerStepScreen
|
|
62
62
|
t={t}
|
|
63
63
|
onBack={handleBack}
|
|
64
|
-
onContinue={(img:
|
|
64
|
+
onContinue={(img: { uri: string; previewUrl?: string }) => {
|
|
65
65
|
setStepImage(isStep2 ? 1 : 0, { uri: img.uri, previewUrl: img.previewUrl || img.uri });
|
|
66
66
|
handleNext();
|
|
67
67
|
}}
|
|
@@ -184,7 +184,7 @@ export const AIGenerateWizardFlow: React.FC<AIGenerateWizardFlowProps> = ({
|
|
|
184
184
|
isGenerating={isGenerating}
|
|
185
185
|
progress={progress}
|
|
186
186
|
presets={presets}
|
|
187
|
-
onPresetPress={handleGenerate
|
|
187
|
+
onPresetPress={() => { void handleGenerate(); }}
|
|
188
188
|
prompt={prompt}
|
|
189
189
|
onPromptChange={setPrompt}
|
|
190
190
|
styles={styleOptions}
|
|
@@ -33,11 +33,24 @@ export interface AIGenerateWizardTranslations {
|
|
|
33
33
|
readonly maxFileSize: string;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
export interface StyleOption {
|
|
37
|
+
readonly id: string;
|
|
38
|
+
readonly label: string;
|
|
39
|
+
readonly icon?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface PresetOption {
|
|
43
|
+
readonly id: string;
|
|
44
|
+
readonly label: string;
|
|
45
|
+
readonly prompt?: string;
|
|
46
|
+
readonly icon?: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
36
49
|
export interface AIGenerateWizardFlowProps {
|
|
37
50
|
readonly featureType: string;
|
|
38
51
|
readonly translations: AIGenerateWizardTranslations;
|
|
39
|
-
readonly styleOptions:
|
|
40
|
-
readonly presets:
|
|
52
|
+
readonly styleOptions: StyleOption[];
|
|
53
|
+
readonly presets: PresetOption[];
|
|
41
54
|
readonly durationOptions: number[];
|
|
42
55
|
readonly onGenerate: (data: {
|
|
43
56
|
prompt: string;
|
|
@@ -3,9 +3,16 @@ import { useMemo, useCallback, useEffect } from "react";
|
|
|
3
3
|
import { useAIGenerateState, AIGenerateStep } from "../../hooks/generation/useAIGenerateState";
|
|
4
4
|
import { getAIFeatureConfig, hasAIFeature } from "../../screens/ai-feature/registry";
|
|
5
5
|
|
|
6
|
+
interface GenerationData {
|
|
7
|
+
prompt: string;
|
|
8
|
+
style: string;
|
|
9
|
+
duration: number;
|
|
10
|
+
images: { uri: string; previewUrl?: string }[];
|
|
11
|
+
}
|
|
12
|
+
|
|
6
13
|
interface UseAIGenerateWizardFlowProps {
|
|
7
14
|
featureType: string;
|
|
8
|
-
onGenerate: (data:
|
|
15
|
+
onGenerate: (data: GenerationData) => Promise<string | null | void>;
|
|
9
16
|
onBack?: () => void;
|
|
10
17
|
}
|
|
11
18
|
|
|
@@ -15,15 +22,15 @@ export function useAIGenerateWizardFlow({
|
|
|
15
22
|
onBack: onBackProp,
|
|
16
23
|
}: UseAIGenerateWizardFlowProps) {
|
|
17
24
|
const state = useAIGenerateState();
|
|
18
|
-
const {
|
|
19
|
-
currentStep, setCurrentStep,
|
|
20
|
-
setProgress, setResult, images, prompt, selectedStyle,
|
|
21
|
-
selectedDuration
|
|
25
|
+
const {
|
|
26
|
+
currentStep, setCurrentStep, setIsGenerating,
|
|
27
|
+
setProgress, setResult, images, prompt, selectedStyle,
|
|
28
|
+
selectedDuration
|
|
22
29
|
} = state;
|
|
23
30
|
|
|
24
31
|
const imageCountRequired = useMemo(() => {
|
|
25
32
|
if (!featureType || !hasAIFeature(featureType)) return 0;
|
|
26
|
-
const config = getAIFeatureConfig(featureType as
|
|
33
|
+
const config = getAIFeatureConfig(featureType as Parameters<typeof getAIFeatureConfig>[0]);
|
|
27
34
|
if (config.mode === "dual" || config.mode === "dual-video") return 2;
|
|
28
35
|
if (config.mode === "single" || config.mode === "single-with-prompt")
|
|
29
36
|
return 1;
|
|
@@ -70,7 +70,10 @@ export const useGenerationOrchestrator = <TInput, TResult>(
|
|
|
70
70
|
|
|
71
71
|
const offlineStore = useOfflineStore();
|
|
72
72
|
const { showError, showSuccess } = useAlert();
|
|
73
|
-
const defaultCredits = useDeductCredit({ userId, onCreditsExhausted }) as
|
|
73
|
+
const defaultCredits = useDeductCredit({ userId, onCreditsExhausted }) as {
|
|
74
|
+
checkCredits: (amount: number) => Promise<boolean>;
|
|
75
|
+
deductCredit: (amount: number) => Promise<void>;
|
|
76
|
+
};
|
|
74
77
|
|
|
75
78
|
// Use provided credit callbacks or default to useDeductCredit hook
|
|
76
79
|
const checkCredits = credits?.checkCredits ?? defaultCredits.checkCredits;
|
|
@@ -9,12 +9,25 @@ import { prepareImage } from "../../../infrastructure/utils";
|
|
|
9
9
|
import type { AIFeatureId } from "../../screens/ai-feature/types";
|
|
10
10
|
import type { ImageFeatureType, VideoFeatureType } from "../../../domain/interfaces";
|
|
11
11
|
|
|
12
|
+
interface AlertMessages {
|
|
13
|
+
success?: string;
|
|
14
|
+
error?: string;
|
|
15
|
+
network?: string;
|
|
16
|
+
credits?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface GenerationError {
|
|
20
|
+
type: string;
|
|
21
|
+
message: string;
|
|
22
|
+
originalError?: Error;
|
|
23
|
+
}
|
|
24
|
+
|
|
12
25
|
interface FeatureGenerationConfig {
|
|
13
26
|
featureType: AIFeatureId;
|
|
14
27
|
userId?: string;
|
|
15
|
-
alertMessages:
|
|
16
|
-
onSuccess?: (result:
|
|
17
|
-
onError?: (error:
|
|
28
|
+
alertMessages: AlertMessages;
|
|
29
|
+
onSuccess?: (result: string) => void;
|
|
30
|
+
onError?: (error: GenerationError) => void;
|
|
18
31
|
creditCost?: number;
|
|
19
32
|
onCreditsExhausted?: () => void;
|
|
20
33
|
}
|