@umituz/react-native-ai-generation-content 1.17.163 → 1.17.165
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 +2 -1
- package/src/domains/creations/presentation/hooks/useCreationPersistence.ts +5 -1
- package/src/features/image-to-image/domain/types/base.types.ts +26 -2
- package/src/features/image-to-image/presentation/hooks/useDualImageFeature.ts +14 -6
- package/src/features/image-to-image/presentation/hooks/useImageWithPromptFeature.ts +11 -7
- package/src/features/image-to-image/presentation/hooks/useSingleImageFeature.ts +10 -6
- package/src/features/photo-restoration/domain/types/photo-restore.types.ts +3 -3
- package/src/features/photo-restoration/presentation/hooks/usePhotoRestoreFeature.ts +38 -22
- package/src/features/remove-object/domain/types/remove-object.types.ts +3 -3
- package/src/features/remove-object/presentation/hooks/useRemoveObjectFeature.ts +45 -29
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-ai-generation-content",
|
|
3
|
-
"version": "1.17.
|
|
3
|
+
"version": "1.17.165",
|
|
4
4
|
"description": "Provider-agnostic AI generation orchestration for React Native",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "src/index.ts",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"url": "git+https://github.com/umituz/react-native-ai-generation-content.git"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
+
"@umituz/react-native-auth": "latest",
|
|
41
42
|
"@umituz/react-native-design-system": "latest",
|
|
42
43
|
"@umituz/react-native-filesystem": "latest",
|
|
43
44
|
"@umituz/react-native-firebase": "latest",
|
|
@@ -73,6 +73,10 @@ export function useCreationPersistence(
|
|
|
73
73
|
if (!userId) return;
|
|
74
74
|
|
|
75
75
|
const { creationId, ...rest } = data;
|
|
76
|
+
const cleanMetadata = Object.fromEntries(
|
|
77
|
+
Object.entries(rest).filter(([, v]) => v !== undefined && v !== null),
|
|
78
|
+
);
|
|
79
|
+
|
|
76
80
|
const creation: Creation = {
|
|
77
81
|
id: creationId,
|
|
78
82
|
uri: "",
|
|
@@ -81,7 +85,7 @@ export function useCreationPersistence(
|
|
|
81
85
|
createdAt: new Date(),
|
|
82
86
|
isShared: false,
|
|
83
87
|
isFavorite: false,
|
|
84
|
-
metadata:
|
|
88
|
+
metadata: cleanMetadata,
|
|
85
89
|
};
|
|
86
90
|
|
|
87
91
|
repository.create(userId, creation);
|
|
@@ -102,6 +102,30 @@ export interface BaseDualImageTranslations {
|
|
|
102
102
|
*/
|
|
103
103
|
export type ImageResultExtractor = (result: unknown) => string | undefined;
|
|
104
104
|
|
|
105
|
+
/**
|
|
106
|
+
* Single image processing start data
|
|
107
|
+
*/
|
|
108
|
+
export interface SingleImageProcessingStartData {
|
|
109
|
+
creationId: string;
|
|
110
|
+
imageUri: string;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Dual image processing start data
|
|
115
|
+
*/
|
|
116
|
+
export interface DualImageProcessingStartData {
|
|
117
|
+
creationId: string;
|
|
118
|
+
sourceImageUri: string;
|
|
119
|
+
targetImageUri: string;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Base result with optional creationId for persistence
|
|
124
|
+
*/
|
|
125
|
+
export interface BaseImageResultWithCreationId extends BaseImageResult {
|
|
126
|
+
creationId?: string;
|
|
127
|
+
}
|
|
128
|
+
|
|
105
129
|
/**
|
|
106
130
|
* Base config for all image features
|
|
107
131
|
*/
|
|
@@ -110,9 +134,9 @@ export interface BaseImageConfig<TResult extends BaseImageResult = BaseImageResu
|
|
|
110
134
|
creditCost?: number;
|
|
111
135
|
extractResult?: ImageResultExtractor;
|
|
112
136
|
prepareImage: (imageUri: string) => Promise<string>;
|
|
113
|
-
onProcessingStart?: () => void;
|
|
137
|
+
onProcessingStart?: (data: { creationId: string; [key: string]: unknown }) => void;
|
|
114
138
|
onProcessingComplete?: (result: TResult) => void;
|
|
115
|
-
onError?: (error: string) => void;
|
|
139
|
+
onError?: (error: string, creationId?: string) => void;
|
|
116
140
|
}
|
|
117
141
|
|
|
118
142
|
/**
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* Base hook for dual image processing features (e.g., face-swap)
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { useState, useCallback } from "react";
|
|
6
|
+
import { useState, useCallback, useRef } from "react";
|
|
7
|
+
import { generateUUID } from "@umituz/react-native-uuid";
|
|
7
8
|
import { executeImageFeature } from "../../../../infrastructure/services";
|
|
8
9
|
import type {
|
|
9
10
|
BaseDualImageState,
|
|
@@ -39,6 +40,7 @@ export function useDualImageFeature<
|
|
|
39
40
|
): BaseDualImageHookReturn {
|
|
40
41
|
const { config, onSelectSourceImage, onSelectTargetImage, onSaveImage, onBeforeProcess } = props;
|
|
41
42
|
const [state, setState] = useState<BaseDualImageState>(INITIAL_STATE);
|
|
43
|
+
const creationIdRef = useRef<string | null>(null);
|
|
42
44
|
|
|
43
45
|
const selectSourceImage = useCallback(async () => {
|
|
44
46
|
try {
|
|
@@ -73,12 +75,14 @@ export function useDualImageFeature<
|
|
|
73
75
|
const process = useCallback(async () => {
|
|
74
76
|
if (!state.sourceImageUri || !state.targetImageUri) return;
|
|
75
77
|
|
|
76
|
-
// Check if processing is allowed (credit check, etc.)
|
|
77
78
|
if (onBeforeProcess) {
|
|
78
79
|
const canProceed = await onBeforeProcess();
|
|
79
80
|
if (!canProceed) return;
|
|
80
81
|
}
|
|
81
82
|
|
|
83
|
+
const creationId = generateUUID();
|
|
84
|
+
creationIdRef.current = creationId;
|
|
85
|
+
|
|
82
86
|
setState((prev) => ({
|
|
83
87
|
...prev,
|
|
84
88
|
isProcessing: true,
|
|
@@ -86,7 +90,11 @@ export function useDualImageFeature<
|
|
|
86
90
|
error: null,
|
|
87
91
|
}));
|
|
88
92
|
|
|
89
|
-
config.onProcessingStart?.(
|
|
93
|
+
config.onProcessingStart?.({
|
|
94
|
+
creationId,
|
|
95
|
+
sourceImageUri: state.sourceImageUri,
|
|
96
|
+
targetImageUri: state.targetImageUri,
|
|
97
|
+
});
|
|
90
98
|
|
|
91
99
|
try {
|
|
92
100
|
const [sourceBase64, targetBase64] = await Promise.all([
|
|
@@ -111,7 +119,7 @@ export function useDualImageFeature<
|
|
|
111
119
|
processedUrl: result.imageUrl!,
|
|
112
120
|
progress: 100,
|
|
113
121
|
}));
|
|
114
|
-
config.onProcessingComplete?.(result as TResult);
|
|
122
|
+
config.onProcessingComplete?.({ ...result, creationId } as unknown as TResult);
|
|
115
123
|
} else {
|
|
116
124
|
const errorMessage = result.error || "Processing failed";
|
|
117
125
|
setState((prev) => ({
|
|
@@ -120,7 +128,7 @@ export function useDualImageFeature<
|
|
|
120
128
|
error: errorMessage,
|
|
121
129
|
progress: 0,
|
|
122
130
|
}));
|
|
123
|
-
config.onError?.(errorMessage);
|
|
131
|
+
config.onError?.(errorMessage, creationId);
|
|
124
132
|
}
|
|
125
133
|
} catch (error) {
|
|
126
134
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -130,7 +138,7 @@ export function useDualImageFeature<
|
|
|
130
138
|
error: message,
|
|
131
139
|
progress: 0,
|
|
132
140
|
}));
|
|
133
|
-
config.onError?.(message);
|
|
141
|
+
config.onError?.(message, creationIdRef.current ?? undefined);
|
|
134
142
|
}
|
|
135
143
|
}, [state.sourceImageUri, state.targetImageUri, config, options, handleProgress, onBeforeProcess]);
|
|
136
144
|
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* Base hook for image + prompt processing features (e.g., replace-background)
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { useState, useCallback } from "react";
|
|
6
|
+
import { useState, useCallback, useRef } from "react";
|
|
7
|
+
import { generateUUID } from "@umituz/react-native-uuid";
|
|
7
8
|
import { executeImageFeature } from "../../../../infrastructure/services";
|
|
8
9
|
import type {
|
|
9
10
|
BaseImageWithPromptState,
|
|
@@ -65,6 +66,7 @@ export function useImageWithPromptFeature<
|
|
|
65
66
|
...INITIAL_STATE,
|
|
66
67
|
prompt: config.defaultPrompt || "",
|
|
67
68
|
});
|
|
69
|
+
const creationIdRef = useRef<string | null>(null);
|
|
68
70
|
|
|
69
71
|
const selectImage = useCallback(async () => {
|
|
70
72
|
try {
|
|
@@ -94,7 +96,6 @@ export function useImageWithPromptFeature<
|
|
|
94
96
|
const process = useCallback(async () => {
|
|
95
97
|
if (!state.imageUri) return;
|
|
96
98
|
|
|
97
|
-
// Check if processing is allowed (credit check, etc.)
|
|
98
99
|
if (onBeforeProcess) {
|
|
99
100
|
const canProceed = await onBeforeProcess();
|
|
100
101
|
if (!canProceed) return;
|
|
@@ -103,10 +104,13 @@ export function useImageWithPromptFeature<
|
|
|
103
104
|
if (options?.promptRequired && !state.prompt.trim()) {
|
|
104
105
|
const error = "Prompt is required";
|
|
105
106
|
setState((prev) => ({ ...prev, error }));
|
|
106
|
-
config.onError?.(error);
|
|
107
|
+
config.onError?.(error, creationIdRef.current ?? undefined);
|
|
107
108
|
return;
|
|
108
109
|
}
|
|
109
110
|
|
|
111
|
+
const creationId = generateUUID();
|
|
112
|
+
creationIdRef.current = creationId;
|
|
113
|
+
|
|
110
114
|
setState((prev) => ({
|
|
111
115
|
...prev,
|
|
112
116
|
isProcessing: true,
|
|
@@ -114,7 +118,7 @@ export function useImageWithPromptFeature<
|
|
|
114
118
|
error: null,
|
|
115
119
|
}));
|
|
116
120
|
|
|
117
|
-
config.onProcessingStart?.();
|
|
121
|
+
config.onProcessingStart?.({ creationId, imageUri: state.imageUri });
|
|
118
122
|
|
|
119
123
|
try {
|
|
120
124
|
const imageBase64 = await config.prepareImage(state.imageUri);
|
|
@@ -136,7 +140,7 @@ export function useImageWithPromptFeature<
|
|
|
136
140
|
processedUrl: result.imageUrl!,
|
|
137
141
|
progress: 100,
|
|
138
142
|
}));
|
|
139
|
-
config.onProcessingComplete?.(result as TResult);
|
|
143
|
+
config.onProcessingComplete?.({ ...result, creationId } as unknown as TResult);
|
|
140
144
|
} else {
|
|
141
145
|
const errorMessage = result.error || "Processing failed";
|
|
142
146
|
setState((prev) => ({
|
|
@@ -145,7 +149,7 @@ export function useImageWithPromptFeature<
|
|
|
145
149
|
error: errorMessage,
|
|
146
150
|
progress: 0,
|
|
147
151
|
}));
|
|
148
|
-
config.onError?.(errorMessage);
|
|
152
|
+
config.onError?.(errorMessage, creationId);
|
|
149
153
|
}
|
|
150
154
|
} catch (error) {
|
|
151
155
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -155,7 +159,7 @@ export function useImageWithPromptFeature<
|
|
|
155
159
|
error: message,
|
|
156
160
|
progress: 0,
|
|
157
161
|
}));
|
|
158
|
-
config.onError?.(message);
|
|
162
|
+
config.onError?.(message, creationIdRef.current ?? undefined);
|
|
159
163
|
}
|
|
160
164
|
}, [state.imageUri, state.prompt, config, options, handleProgress, onBeforeProcess]);
|
|
161
165
|
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* Base hook for single image processing features
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { useState, useCallback } from "react";
|
|
6
|
+
import { useState, useCallback, useRef } from "react";
|
|
7
|
+
import { generateUUID } from "@umituz/react-native-uuid";
|
|
7
8
|
import { executeImageFeature } from "../../../../infrastructure/services";
|
|
8
9
|
import type {
|
|
9
10
|
BaseSingleImageState,
|
|
@@ -34,6 +35,7 @@ export function useSingleImageFeature<
|
|
|
34
35
|
): BaseSingleImageHookReturn {
|
|
35
36
|
const { config, onSelectImage, onSaveImage, onBeforeProcess } = props;
|
|
36
37
|
const [state, setState] = useState<BaseSingleImageState>(INITIAL_STATE);
|
|
38
|
+
const creationIdRef = useRef<string | null>(null);
|
|
37
39
|
|
|
38
40
|
const selectImage = useCallback(async () => {
|
|
39
41
|
try {
|
|
@@ -55,12 +57,14 @@ export function useSingleImageFeature<
|
|
|
55
57
|
const process = useCallback(async () => {
|
|
56
58
|
if (!state.imageUri) return;
|
|
57
59
|
|
|
58
|
-
// Check if processing is allowed (credit check, etc.)
|
|
59
60
|
if (onBeforeProcess) {
|
|
60
61
|
const canProceed = await onBeforeProcess();
|
|
61
62
|
if (!canProceed) return;
|
|
62
63
|
}
|
|
63
64
|
|
|
65
|
+
const creationId = generateUUID();
|
|
66
|
+
creationIdRef.current = creationId;
|
|
67
|
+
|
|
64
68
|
setState((prev) => ({
|
|
65
69
|
...prev,
|
|
66
70
|
isProcessing: true,
|
|
@@ -68,7 +72,7 @@ export function useSingleImageFeature<
|
|
|
68
72
|
error: null,
|
|
69
73
|
}));
|
|
70
74
|
|
|
71
|
-
config.onProcessingStart?.();
|
|
75
|
+
config.onProcessingStart?.({ creationId, imageUri: state.imageUri });
|
|
72
76
|
|
|
73
77
|
try {
|
|
74
78
|
const imageBase64 = await config.prepareImage(state.imageUri);
|
|
@@ -90,7 +94,7 @@ export function useSingleImageFeature<
|
|
|
90
94
|
processedUrl: result.imageUrl!,
|
|
91
95
|
progress: 100,
|
|
92
96
|
}));
|
|
93
|
-
config.onProcessingComplete?.(result as TResult);
|
|
97
|
+
config.onProcessingComplete?.({ ...result, creationId } as unknown as TResult);
|
|
94
98
|
} else {
|
|
95
99
|
const errorMessage = result.error || "Processing failed";
|
|
96
100
|
setState((prev) => ({
|
|
@@ -99,7 +103,7 @@ export function useSingleImageFeature<
|
|
|
99
103
|
error: errorMessage,
|
|
100
104
|
progress: 0,
|
|
101
105
|
}));
|
|
102
|
-
config.onError?.(errorMessage);
|
|
106
|
+
config.onError?.(errorMessage, creationId);
|
|
103
107
|
}
|
|
104
108
|
} catch (error) {
|
|
105
109
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -109,7 +113,7 @@ export function useSingleImageFeature<
|
|
|
109
113
|
error: message,
|
|
110
114
|
progress: 0,
|
|
111
115
|
}));
|
|
112
|
-
config.onError?.(message);
|
|
116
|
+
config.onError?.(message, creationIdRef.current ?? undefined);
|
|
113
117
|
}
|
|
114
118
|
}, [state.imageUri, config, options, handleProgress, onBeforeProcess]);
|
|
115
119
|
|
|
@@ -57,7 +57,7 @@ export interface PhotoRestoreFeatureConfig {
|
|
|
57
57
|
extractResult?: PhotoRestoreResultExtractor;
|
|
58
58
|
prepareImage: (imageUri: string) => Promise<string>;
|
|
59
59
|
onImageSelect?: (uri: string) => void;
|
|
60
|
-
onProcessingStart?: () => void;
|
|
61
|
-
onProcessingComplete?: (result: PhotoRestoreResult) => void;
|
|
62
|
-
onError?: (error: string) => void;
|
|
60
|
+
onProcessingStart?: (data: { creationId: string; imageUri: string }) => void;
|
|
61
|
+
onProcessingComplete?: (result: PhotoRestoreResult & { creationId?: string }) => void;
|
|
62
|
+
onError?: (error: string, creationId?: string) => void;
|
|
63
63
|
}
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* Manages photo restore feature state and actions
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { useState, useCallback } from "react";
|
|
6
|
+
import { useState, useCallback, useRef } from "react";
|
|
7
|
+
import { generateUUID } from "@umituz/react-native-uuid";
|
|
7
8
|
import { executeImageFeature } from "../../../../infrastructure/services";
|
|
8
9
|
import type {
|
|
9
10
|
PhotoRestoreFeatureState,
|
|
@@ -38,6 +39,7 @@ export function usePhotoRestoreFeature(
|
|
|
38
39
|
): UsePhotoRestoreFeatureReturn {
|
|
39
40
|
const { config, onSelectImage, onSaveImage, onBeforeProcess } = props;
|
|
40
41
|
const [state, setState] = useState<PhotoRestoreFeatureState>(initialState);
|
|
42
|
+
const creationIdRef = useRef<string | null>(null);
|
|
41
43
|
|
|
42
44
|
const selectImage = useCallback(async () => {
|
|
43
45
|
try {
|
|
@@ -64,6 +66,9 @@ export function usePhotoRestoreFeature(
|
|
|
64
66
|
if (!canProceed) return;
|
|
65
67
|
}
|
|
66
68
|
|
|
69
|
+
const creationId = generateUUID();
|
|
70
|
+
creationIdRef.current = creationId;
|
|
71
|
+
|
|
67
72
|
setState((prev) => ({
|
|
68
73
|
...prev,
|
|
69
74
|
isProcessing: true,
|
|
@@ -71,33 +76,44 @@ export function usePhotoRestoreFeature(
|
|
|
71
76
|
error: null,
|
|
72
77
|
}));
|
|
73
78
|
|
|
74
|
-
config.onProcessingStart?.();
|
|
75
|
-
|
|
76
|
-
const imageBase64 = await config.prepareImage(state.imageUri);
|
|
77
|
-
|
|
78
|
-
const result = await executeImageFeature(
|
|
79
|
-
"photo-restore",
|
|
80
|
-
{ imageBase64 },
|
|
81
|
-
{ extractResult: config.extractResult, onProgress: handleProgress },
|
|
82
|
-
);
|
|
79
|
+
config.onProcessingStart?.({ creationId, imageUri: state.imageUri });
|
|
83
80
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
81
|
+
try {
|
|
82
|
+
const imageBase64 = await config.prepareImage(state.imageUri);
|
|
83
|
+
|
|
84
|
+
const result = await executeImageFeature(
|
|
85
|
+
"photo-restore",
|
|
86
|
+
{ imageBase64 },
|
|
87
|
+
{ extractResult: config.extractResult, onProgress: handleProgress },
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
if (result.success && result.imageUrl) {
|
|
91
|
+
setState((prev) => ({
|
|
92
|
+
...prev,
|
|
93
|
+
isProcessing: false,
|
|
94
|
+
processedUrl: result.imageUrl!,
|
|
95
|
+
progress: 100,
|
|
96
|
+
}));
|
|
97
|
+
config.onProcessingComplete?.({ ...result, creationId } as PhotoRestoreResult & { creationId?: string });
|
|
98
|
+
} else {
|
|
99
|
+
const errorMessage = result.error || "Processing failed";
|
|
100
|
+
setState((prev) => ({
|
|
101
|
+
...prev,
|
|
102
|
+
isProcessing: false,
|
|
103
|
+
error: errorMessage,
|
|
104
|
+
progress: 0,
|
|
105
|
+
}));
|
|
106
|
+
config.onError?.(errorMessage, creationId);
|
|
107
|
+
}
|
|
108
|
+
} catch (error) {
|
|
109
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
94
110
|
setState((prev) => ({
|
|
95
111
|
...prev,
|
|
96
112
|
isProcessing: false,
|
|
97
|
-
error:
|
|
113
|
+
error: message,
|
|
98
114
|
progress: 0,
|
|
99
115
|
}));
|
|
100
|
-
config.onError?.(
|
|
116
|
+
config.onError?.(message, creationIdRef.current ?? undefined);
|
|
101
117
|
}
|
|
102
118
|
}, [state.imageUri, config, handleProgress, onBeforeProcess]);
|
|
103
119
|
|
|
@@ -63,7 +63,7 @@ export interface RemoveObjectFeatureConfig {
|
|
|
63
63
|
prepareImage: (imageUri: string) => Promise<string>;
|
|
64
64
|
onImageSelect?: (uri: string) => void;
|
|
65
65
|
onMaskSelect?: (uri: string) => void;
|
|
66
|
-
onProcessingStart?: () => void;
|
|
67
|
-
onProcessingComplete?: (result: RemoveObjectResult) => void;
|
|
68
|
-
onError?: (error: string) => void;
|
|
66
|
+
onProcessingStart?: (data: { creationId: string; imageUri: string }) => void;
|
|
67
|
+
onProcessingComplete?: (result: RemoveObjectResult & { creationId?: string }) => void;
|
|
68
|
+
onError?: (error: string, creationId?: string) => void;
|
|
69
69
|
}
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* Manages remove object feature state and actions
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { useState, useCallback } from "react";
|
|
6
|
+
import { useState, useCallback, useRef } from "react";
|
|
7
|
+
import { generateUUID } from "@umituz/react-native-uuid";
|
|
7
8
|
import { executeImageFeature } from "../../../../infrastructure/services";
|
|
8
9
|
import type {
|
|
9
10
|
RemoveObjectFeatureState,
|
|
@@ -43,6 +44,7 @@ export function useRemoveObjectFeature(
|
|
|
43
44
|
): UseRemoveObjectFeatureReturn {
|
|
44
45
|
const { config, onSelectImage, onSelectMask, onSaveImage, onBeforeProcess } = props;
|
|
45
46
|
const [state, setState] = useState<RemoveObjectFeatureState>(initialState);
|
|
47
|
+
const creationIdRef = useRef<string | null>(null);
|
|
46
48
|
|
|
47
49
|
const selectImage = useCallback(async () => {
|
|
48
50
|
try {
|
|
@@ -88,6 +90,9 @@ export function useRemoveObjectFeature(
|
|
|
88
90
|
if (!canProceed) return;
|
|
89
91
|
}
|
|
90
92
|
|
|
93
|
+
const creationId = generateUUID();
|
|
94
|
+
creationIdRef.current = creationId;
|
|
95
|
+
|
|
91
96
|
setState((prev) => ({
|
|
92
97
|
...prev,
|
|
93
98
|
isProcessing: true,
|
|
@@ -95,40 +100,51 @@ export function useRemoveObjectFeature(
|
|
|
95
100
|
error: null,
|
|
96
101
|
}));
|
|
97
102
|
|
|
98
|
-
config.onProcessingStart?.();
|
|
99
|
-
|
|
100
|
-
const imageBase64 = await config.prepareImage(state.imageUri);
|
|
101
|
-
const maskBase64 = state.maskUri
|
|
102
|
-
? await config.prepareImage(state.maskUri)
|
|
103
|
-
: undefined;
|
|
104
|
-
|
|
105
|
-
const result = await executeImageFeature(
|
|
106
|
-
"remove-object",
|
|
107
|
-
{
|
|
108
|
-
imageBase64,
|
|
109
|
-
targetImageBase64: maskBase64,
|
|
110
|
-
prompt: state.prompt || undefined,
|
|
111
|
-
},
|
|
112
|
-
{ extractResult: config.extractResult, onProgress: handleProgress },
|
|
113
|
-
);
|
|
103
|
+
config.onProcessingStart?.({ creationId, imageUri: state.imageUri });
|
|
114
104
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
105
|
+
try {
|
|
106
|
+
const imageBase64 = await config.prepareImage(state.imageUri);
|
|
107
|
+
const maskBase64 = state.maskUri
|
|
108
|
+
? await config.prepareImage(state.maskUri)
|
|
109
|
+
: undefined;
|
|
110
|
+
|
|
111
|
+
const result = await executeImageFeature(
|
|
112
|
+
"remove-object",
|
|
113
|
+
{
|
|
114
|
+
imageBase64,
|
|
115
|
+
targetImageBase64: maskBase64,
|
|
116
|
+
prompt: state.prompt || undefined,
|
|
117
|
+
},
|
|
118
|
+
{ extractResult: config.extractResult, onProgress: handleProgress },
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
if (result.success && result.imageUrl) {
|
|
122
|
+
setState((prev) => ({
|
|
123
|
+
...prev,
|
|
124
|
+
isProcessing: false,
|
|
125
|
+
processedUrl: result.imageUrl!,
|
|
126
|
+
progress: 100,
|
|
127
|
+
}));
|
|
128
|
+
config.onProcessingComplete?.({ ...result, creationId } as RemoveObjectResult & { creationId?: string });
|
|
129
|
+
} else {
|
|
130
|
+
const errorMessage = result.error || "Processing failed";
|
|
131
|
+
setState((prev) => ({
|
|
132
|
+
...prev,
|
|
133
|
+
isProcessing: false,
|
|
134
|
+
error: errorMessage,
|
|
135
|
+
progress: 0,
|
|
136
|
+
}));
|
|
137
|
+
config.onError?.(errorMessage, creationId);
|
|
138
|
+
}
|
|
139
|
+
} catch (error) {
|
|
140
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
125
141
|
setState((prev) => ({
|
|
126
142
|
...prev,
|
|
127
143
|
isProcessing: false,
|
|
128
|
-
error:
|
|
144
|
+
error: message,
|
|
129
145
|
progress: 0,
|
|
130
146
|
}));
|
|
131
|
-
config.onError?.(
|
|
147
|
+
config.onError?.(message, creationIdRef.current ?? undefined);
|
|
132
148
|
}
|
|
133
149
|
}, [state.imageUri, state.maskUri, state.prompt, config, handleProgress, onBeforeProcess]);
|
|
134
150
|
|