@umituz/react-native-ai-generation-content 1.10.2 → 1.11.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
CHANGED
package/src/index.ts
CHANGED
|
@@ -157,6 +157,7 @@ export {
|
|
|
157
157
|
useGeneration,
|
|
158
158
|
usePendingJobs,
|
|
159
159
|
useBackgroundGeneration,
|
|
160
|
+
usePhotoGeneration,
|
|
160
161
|
} from "./presentation/hooks";
|
|
161
162
|
|
|
162
163
|
export type {
|
|
@@ -167,6 +168,13 @@ export type {
|
|
|
167
168
|
UseBackgroundGenerationOptions,
|
|
168
169
|
UseBackgroundGenerationReturn,
|
|
169
170
|
DirectExecutionResult,
|
|
171
|
+
UsePhotoGenerationReturn,
|
|
172
|
+
PhotoGenerationInput,
|
|
173
|
+
PhotoGenerationResult,
|
|
174
|
+
PhotoGenerationError,
|
|
175
|
+
PhotoGenerationConfig,
|
|
176
|
+
PhotoGenerationState,
|
|
177
|
+
PhotoGenerationStatus,
|
|
170
178
|
} from "./presentation/hooks";
|
|
171
179
|
|
|
172
180
|
// =============================================================================
|
|
@@ -20,3 +20,17 @@ export type {
|
|
|
20
20
|
UseBackgroundGenerationReturn,
|
|
21
21
|
DirectExecutionResult,
|
|
22
22
|
} from "./use-background-generation";
|
|
23
|
+
|
|
24
|
+
export { usePhotoGeneration } from "./usePhotoGeneration";
|
|
25
|
+
export type {
|
|
26
|
+
UsePhotoGenerationReturn,
|
|
27
|
+
} from "./usePhotoGeneration";
|
|
28
|
+
|
|
29
|
+
export type {
|
|
30
|
+
PhotoGenerationInput,
|
|
31
|
+
PhotoGenerationResult,
|
|
32
|
+
PhotoGenerationError,
|
|
33
|
+
PhotoGenerationConfig,
|
|
34
|
+
PhotoGenerationState,
|
|
35
|
+
PhotoGenerationStatus,
|
|
36
|
+
} from "./photo-generation.types";
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Photo Generation Types
|
|
3
|
+
* Generic types for photo-based AI generation workflows
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface PhotoGenerationInput<TMetadata = any> {
|
|
7
|
+
photos: Array<{ uri: string; base64: string }>;
|
|
8
|
+
metadata?: TMetadata;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface PhotoGenerationResult<TResult = any> {
|
|
12
|
+
success: boolean;
|
|
13
|
+
data?: TResult;
|
|
14
|
+
error?: PhotoGenerationError;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface PhotoGenerationError {
|
|
18
|
+
type: "network_error" | "policy_violation" | "save_failed" | "credit_failed" | "unknown";
|
|
19
|
+
message: string;
|
|
20
|
+
originalError?: Error;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface PhotoGenerationConfig<TInput, TResult, TSaveInput> {
|
|
24
|
+
generate: (input: TInput) => Promise<TResult>;
|
|
25
|
+
save?: (result: TResult, input: TInput) => Promise<TSaveInput>;
|
|
26
|
+
checkCredits?: () => Promise<boolean>;
|
|
27
|
+
checkNetwork?: () => Promise<boolean>;
|
|
28
|
+
deductCredits?: () => Promise<void>;
|
|
29
|
+
onSuccess?: (result: TResult) => void;
|
|
30
|
+
onError?: (error: PhotoGenerationError) => void;
|
|
31
|
+
onSaveComplete?: (saveResult: TSaveInput) => void;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface PhotoGenerationState<TResult = any> {
|
|
35
|
+
isGenerating: boolean;
|
|
36
|
+
result: TResult | null;
|
|
37
|
+
error: PhotoGenerationError | null;
|
|
38
|
+
progress: number;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export type PhotoGenerationStatus = "idle" | "validating" | "generating" | "saving" | "success" | "error";
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* usePhotoGeneration Hook
|
|
3
|
+
* Generic hook for photo-based AI generation workflows
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { useState, useCallback, useRef } from "react";
|
|
7
|
+
import type {
|
|
8
|
+
PhotoGenerationConfig,
|
|
9
|
+
PhotoGenerationState,
|
|
10
|
+
PhotoGenerationError,
|
|
11
|
+
PhotoGenerationStatus,
|
|
12
|
+
} from "./photo-generation.types";
|
|
13
|
+
|
|
14
|
+
export interface UsePhotoGenerationReturn<TResult> extends PhotoGenerationState<TResult> {
|
|
15
|
+
generate: <TInput>(input: TInput) => Promise<void>;
|
|
16
|
+
reset: () => void;
|
|
17
|
+
status: PhotoGenerationStatus;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const usePhotoGeneration = <TInput, TResult, TSaveInput = any>(
|
|
21
|
+
config: PhotoGenerationConfig<TInput, TResult, TSaveInput>,
|
|
22
|
+
): UsePhotoGenerationReturn<TResult> => {
|
|
23
|
+
const {
|
|
24
|
+
generate: generateFn,
|
|
25
|
+
save: saveFn,
|
|
26
|
+
checkCredits,
|
|
27
|
+
checkNetwork,
|
|
28
|
+
deductCredits,
|
|
29
|
+
onSuccess,
|
|
30
|
+
onError,
|
|
31
|
+
onSaveComplete,
|
|
32
|
+
} = config;
|
|
33
|
+
|
|
34
|
+
const [state, setState] = useState<PhotoGenerationState<TResult>>({
|
|
35
|
+
isGenerating: false,
|
|
36
|
+
result: null,
|
|
37
|
+
error: null,
|
|
38
|
+
progress: 0,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const [status, setStatus] = useState<PhotoGenerationStatus>("idle");
|
|
42
|
+
const isGeneratingRef = useRef(false);
|
|
43
|
+
|
|
44
|
+
const createError = useCallback(
|
|
45
|
+
(
|
|
46
|
+
type: PhotoGenerationError["type"],
|
|
47
|
+
message: string,
|
|
48
|
+
originalError?: Error,
|
|
49
|
+
): PhotoGenerationError => ({
|
|
50
|
+
type,
|
|
51
|
+
message,
|
|
52
|
+
originalError,
|
|
53
|
+
}),
|
|
54
|
+
[],
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const generate = useCallback(
|
|
58
|
+
async (input: TInput) => {
|
|
59
|
+
if (isGeneratingRef.current) {
|
|
60
|
+
if (__DEV__) console.warn("[usePhotoGeneration] Generation already in progress");
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
isGeneratingRef.current = true;
|
|
65
|
+
setState({ isGenerating: true, result: null, error: null, progress: 0 });
|
|
66
|
+
setStatus("validating");
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
// Check network connectivity
|
|
70
|
+
if (checkNetwork) {
|
|
71
|
+
const isOnline = await checkNetwork();
|
|
72
|
+
if (!isOnline) {
|
|
73
|
+
throw createError("network_error", "No internet connection");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Check credits
|
|
78
|
+
if (checkCredits) {
|
|
79
|
+
const hasCredits = await checkCredits();
|
|
80
|
+
if (!hasCredits) {
|
|
81
|
+
throw createError("credit_failed", "Insufficient credits");
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
setStatus("generating");
|
|
86
|
+
setState((prev) => ({ ...prev, progress: 20 }));
|
|
87
|
+
|
|
88
|
+
// Generate without timeout - let AI provider handle its own timeout
|
|
89
|
+
const result = await generateFn(input);
|
|
90
|
+
|
|
91
|
+
setState((prev) => ({ ...prev, progress: 60 }));
|
|
92
|
+
|
|
93
|
+
// Save result
|
|
94
|
+
if (saveFn) {
|
|
95
|
+
setStatus("saving");
|
|
96
|
+
try {
|
|
97
|
+
const saveResult = await saveFn(result, input);
|
|
98
|
+
onSaveComplete?.(saveResult);
|
|
99
|
+
} catch (saveError) {
|
|
100
|
+
throw createError(
|
|
101
|
+
"save_failed",
|
|
102
|
+
"Failed to save result",
|
|
103
|
+
saveError as Error,
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
setState((prev) => ({ ...prev, progress: 80 }));
|
|
109
|
+
|
|
110
|
+
// Deduct credits after successful generation
|
|
111
|
+
if (deductCredits) {
|
|
112
|
+
try {
|
|
113
|
+
await deductCredits();
|
|
114
|
+
} catch (deductError) {
|
|
115
|
+
if (__DEV__)
|
|
116
|
+
console.error("[usePhotoGeneration] Credit deduction failed", deductError);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
setState({
|
|
121
|
+
isGenerating: false,
|
|
122
|
+
result,
|
|
123
|
+
error: null,
|
|
124
|
+
progress: 100,
|
|
125
|
+
});
|
|
126
|
+
setStatus("success");
|
|
127
|
+
onSuccess?.(result);
|
|
128
|
+
} catch (error: any) {
|
|
129
|
+
const generationError =
|
|
130
|
+
error.type
|
|
131
|
+
? error
|
|
132
|
+
: error.name === "ContentPolicyViolationError"
|
|
133
|
+
? createError("policy_violation", "Content policy violation", error)
|
|
134
|
+
: createError("unknown", error.message || "Generation failed", error);
|
|
135
|
+
|
|
136
|
+
setState({
|
|
137
|
+
isGenerating: false,
|
|
138
|
+
result: null,
|
|
139
|
+
error: generationError,
|
|
140
|
+
progress: 0,
|
|
141
|
+
});
|
|
142
|
+
setStatus("error");
|
|
143
|
+
onError?.(generationError);
|
|
144
|
+
} finally {
|
|
145
|
+
isGeneratingRef.current = false;
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
[
|
|
149
|
+
generateFn,
|
|
150
|
+
saveFn,
|
|
151
|
+
checkCredits,
|
|
152
|
+
checkNetwork,
|
|
153
|
+
deductCredits,
|
|
154
|
+
onSuccess,
|
|
155
|
+
onError,
|
|
156
|
+
onSaveComplete,
|
|
157
|
+
createError,
|
|
158
|
+
],
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
const reset = useCallback(() => {
|
|
162
|
+
setState({ isGenerating: false, result: null, error: null, progress: 0 });
|
|
163
|
+
setStatus("idle");
|
|
164
|
+
isGeneratingRef.current = false;
|
|
165
|
+
}, []);
|
|
166
|
+
|
|
167
|
+
return {
|
|
168
|
+
...state,
|
|
169
|
+
generate,
|
|
170
|
+
reset,
|
|
171
|
+
status,
|
|
172
|
+
};
|
|
173
|
+
};
|