@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-ai-generation-content",
3
- "version": "1.17.163",
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: rest as Record<string, unknown>,
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
- if (result.success && result.imageUrl) {
85
- setState((prev) => ({
86
- ...prev,
87
- isProcessing: false,
88
- processedUrl: result.imageUrl!,
89
- progress: 100,
90
- }));
91
- config.onProcessingComplete?.(result as PhotoRestoreResult);
92
- } else {
93
- const errorMessage = result.error || "Processing failed";
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: errorMessage,
113
+ error: message,
98
114
  progress: 0,
99
115
  }));
100
- config.onError?.(errorMessage);
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
- if (result.success && result.imageUrl) {
116
- setState((prev) => ({
117
- ...prev,
118
- isProcessing: false,
119
- processedUrl: result.imageUrl!,
120
- progress: 100,
121
- }));
122
- config.onProcessingComplete?.(result as RemoveObjectResult);
123
- } else {
124
- const errorMessage = result.error || "Processing failed";
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: errorMessage,
144
+ error: message,
129
145
  progress: 0,
130
146
  }));
131
- config.onError?.(errorMessage);
147
+ config.onError?.(message, creationIdRef.current ?? undefined);
132
148
  }
133
149
  }, [state.imageUri, state.maskUri, state.prompt, config, handleProgress, onBeforeProcess]);
134
150