@umituz/react-native-ai-generation-content 1.17.147 → 1.17.149

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.
Files changed (47) hide show
  1. package/package.json +1 -1
  2. package/src/features/ai-hug/presentation/components/AIHugFeature.tsx +4 -0
  3. package/src/features/ai-hug/presentation/hooks/useAIHugFeature.ts +1 -0
  4. package/src/features/ai-kiss/presentation/components/AIKissFeature.tsx +4 -0
  5. package/src/features/ai-kiss/presentation/hooks/useAIKissFeature.ts +1 -0
  6. package/src/features/anime-selfie/presentation/components/AnimeSelfieFeature.tsx +4 -0
  7. package/src/features/anime-selfie/presentation/hooks/useAnimeSelfieFeature.ts +8 -2
  8. package/src/features/face-swap/domain/types/face-swap.types.ts +13 -41
  9. package/src/features/face-swap/domain/types/index.ts +0 -1
  10. package/src/features/face-swap/index.ts +1 -5
  11. package/src/features/face-swap/presentation/components/FaceSwapFeature.tsx +4 -0
  12. package/src/features/face-swap/presentation/hooks/index.ts +1 -4
  13. package/src/features/face-swap/presentation/hooks/useFaceSwapFeature.ts +20 -123
  14. package/src/features/hd-touch-up/presentation/components/HDTouchUpFeature.tsx +4 -0
  15. package/src/features/hd-touch-up/presentation/hooks/useHDTouchUpFeature.ts +8 -2
  16. package/src/features/image-to-image/domain/index.ts +1 -0
  17. package/src/features/image-to-image/domain/types/base.types.ts +193 -0
  18. package/src/features/image-to-image/domain/types/index.ts +1 -0
  19. package/src/features/image-to-image/index.ts +2 -0
  20. package/src/features/image-to-image/presentation/hooks/index.ts +3 -0
  21. package/src/features/image-to-image/presentation/hooks/useDualImageFeature.ts +160 -0
  22. package/src/features/image-to-image/presentation/hooks/useImageWithPromptFeature.ts +188 -0
  23. package/src/features/image-to-image/presentation/hooks/useSingleImageFeature.ts +138 -0
  24. package/src/features/image-to-image/presentation/index.ts +1 -0
  25. package/src/features/photo-restoration/presentation/components/PhotoRestoreFeature.tsx +4 -0
  26. package/src/features/photo-restoration/presentation/hooks/usePhotoRestoreFeature.ts +8 -2
  27. package/src/features/remove-background/domain/types/index.ts +0 -1
  28. package/src/features/remove-background/domain/types/remove-background.types.ts +14 -40
  29. package/src/features/remove-background/index.ts +1 -5
  30. package/src/features/remove-background/presentation/components/RemoveBackgroundFeature.tsx +4 -0
  31. package/src/features/remove-background/presentation/hooks/index.ts +1 -4
  32. package/src/features/remove-background/presentation/hooks/useRemoveBackgroundFeature.ts +18 -102
  33. package/src/features/remove-object/presentation/components/RemoveObjectFeature.tsx +4 -0
  34. package/src/features/remove-object/presentation/hooks/useRemoveObjectFeature.ts +8 -2
  35. package/src/features/replace-background/domain/types/index.ts +1 -2
  36. package/src/features/replace-background/domain/types/replace-background.types.ts +14 -39
  37. package/src/features/replace-background/index.ts +0 -1
  38. package/src/features/replace-background/presentation/components/ReplaceBackgroundFeature.tsx +4 -0
  39. package/src/features/replace-background/presentation/hooks/useReplaceBackgroundFeature.ts +32 -119
  40. package/src/features/shared/dual-image-video/domain/types/dual-image-video.types.ts +2 -0
  41. package/src/features/shared/dual-image-video/presentation/hooks/useDualImageVideoFeature.ts +7 -2
  42. package/src/features/upscaling/domain/types/upscale.types.ts +12 -42
  43. package/src/features/upscaling/index.ts +1 -5
  44. package/src/features/upscaling/presentation/components/UpscaleFeature.tsx +4 -0
  45. package/src/features/upscaling/presentation/hooks/index.ts +1 -4
  46. package/src/features/upscaling/presentation/hooks/useUpscaleFeature.ts +17 -107
  47. package/src/index.ts +6 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-ai-generation-content",
3
- "version": "1.17.147",
3
+ "version": "1.17.149",
4
4
  "description": "Provider-agnostic AI generation orchestration for React Native",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -29,6 +29,8 @@ export interface AIHugFeatureProps {
29
29
  onSaveVideo: (videoUrl: string) => Promise<void>;
30
30
  /** Custom video player renderer - required for video playback */
31
31
  renderVideoPlayer: (props: { videoUrl: string; size: number }) => React.ReactNode;
32
+ /** Called before processing starts. Return false to cancel. */
33
+ onBeforeProcess?: () => Promise<boolean>;
32
34
  /** Optional custom processing modal renderer */
33
35
  renderProcessingModal?: (props: {
34
36
  visible: boolean;
@@ -43,6 +45,7 @@ export const AIHugFeature: React.FC<AIHugFeatureProps> = ({
43
45
  onSelectTargetImage,
44
46
  onSaveVideo,
45
47
  renderVideoPlayer,
48
+ onBeforeProcess,
46
49
  renderProcessingModal,
47
50
  }) => {
48
51
  const tokens = useAppDesignTokens();
@@ -54,6 +57,7 @@ export const AIHugFeature: React.FC<AIHugFeatureProps> = ({
54
57
  onSelectSourceImage,
55
58
  onSelectTargetImage,
56
59
  onSaveVideo,
60
+ onBeforeProcess,
57
61
  });
58
62
 
59
63
  const handleProcess = useCallback(() => {
@@ -15,6 +15,7 @@ export interface UseAIHugFeatureProps {
15
15
  onSelectSourceImage: () => Promise<string | null>;
16
16
  onSelectTargetImage: () => Promise<string | null>;
17
17
  onSaveVideo: (videoUrl: string) => Promise<void>;
18
+ onBeforeProcess?: () => Promise<boolean>;
18
19
  }
19
20
 
20
21
  export interface UseAIHugFeatureReturn extends AIHugFeatureState {
@@ -24,6 +24,8 @@ export interface AIKissFeatureProps {
24
24
  onSaveVideo: (videoUrl: string) => Promise<void>;
25
25
  /** Custom video player renderer - required for video playback */
26
26
  renderVideoPlayer: (props: { videoUrl: string; size: number }) => React.ReactNode;
27
+ /** Called before processing starts. Return false to cancel. */
28
+ onBeforeProcess?: () => Promise<boolean>;
27
29
  renderProcessingModal?: (props: {
28
30
  visible: boolean;
29
31
  progress: number;
@@ -37,6 +39,7 @@ export const AIKissFeature: React.FC<AIKissFeatureProps> = ({
37
39
  onSelectTargetImage,
38
40
  onSaveVideo,
39
41
  renderVideoPlayer,
42
+ onBeforeProcess,
40
43
  renderProcessingModal,
41
44
  }) => {
42
45
  const tokens = useAppDesignTokens();
@@ -48,6 +51,7 @@ export const AIKissFeature: React.FC<AIKissFeatureProps> = ({
48
51
  onSelectSourceImage,
49
52
  onSelectTargetImage,
50
53
  onSaveVideo,
54
+ onBeforeProcess,
51
55
  });
52
56
 
53
57
  const handleProcess = useCallback(() => {
@@ -15,6 +15,7 @@ export interface UseAIKissFeatureProps {
15
15
  onSelectSourceImage: () => Promise<string | null>;
16
16
  onSelectTargetImage: () => Promise<string | null>;
17
17
  onSaveVideo: (videoUrl: string) => Promise<void>;
18
+ onBeforeProcess?: () => Promise<boolean>;
18
19
  }
19
20
 
20
21
  export interface UseAIKissFeatureReturn extends AIKissFeatureState {
@@ -21,6 +21,8 @@ export interface AnimeSelfieFeatureProps {
21
21
  translations: AnimeSelfieTranslations;
22
22
  onSelectImage: () => Promise<string | null>;
23
23
  onSaveImage: (imageUrl: string) => Promise<void>;
24
+ /** Called before processing starts. Return false to cancel. */
25
+ onBeforeProcess?: () => Promise<boolean>;
24
26
  renderProcessingModal?: (props: {
25
27
  visible: boolean;
26
28
  progress: number;
@@ -32,6 +34,7 @@ export const AnimeSelfieFeature: React.FC<AnimeSelfieFeatureProps> = ({
32
34
  translations,
33
35
  onSelectImage,
34
36
  onSaveImage,
37
+ onBeforeProcess,
35
38
  renderProcessingModal,
36
39
  }) => {
37
40
  const tokens = useAppDesignTokens();
@@ -42,6 +45,7 @@ export const AnimeSelfieFeature: React.FC<AnimeSelfieFeatureProps> = ({
42
45
  config,
43
46
  onSelectImage,
44
47
  onSaveImage,
48
+ onBeforeProcess,
45
49
  });
46
50
 
47
51
  const photoTranslations = useMemo(
@@ -15,6 +15,7 @@ export interface UseAnimeSelfieFeatureProps {
15
15
  config: AnimeSelfieFeatureConfig;
16
16
  onSelectImage: () => Promise<string | null>;
17
17
  onSaveImage: (imageUrl: string) => Promise<void>;
18
+ onBeforeProcess?: () => Promise<boolean>;
18
19
  }
19
20
 
20
21
  export interface UseAnimeSelfieFeatureReturn extends AnimeSelfieFeatureState {
@@ -35,7 +36,7 @@ const initialState: AnimeSelfieFeatureState = {
35
36
  export function useAnimeSelfieFeature(
36
37
  props: UseAnimeSelfieFeatureProps,
37
38
  ): UseAnimeSelfieFeatureReturn {
38
- const { config, onSelectImage, onSaveImage } = props;
39
+ const { config, onSelectImage, onSaveImage, onBeforeProcess } = props;
39
40
  const [state, setState] = useState<AnimeSelfieFeatureState>(initialState);
40
41
 
41
42
  const selectImage = useCallback(async () => {
@@ -58,6 +59,11 @@ export function useAnimeSelfieFeature(
58
59
  const process = useCallback(async () => {
59
60
  if (!state.imageUri) return;
60
61
 
62
+ if (onBeforeProcess) {
63
+ const canProceed = await onBeforeProcess();
64
+ if (!canProceed) return;
65
+ }
66
+
61
67
  setState((prev) => ({
62
68
  ...prev,
63
69
  isProcessing: true,
@@ -93,7 +99,7 @@ export function useAnimeSelfieFeature(
93
99
  }));
94
100
  config.onError?.(errorMessage);
95
101
  }
96
- }, [state.imageUri, config, handleProgress]);
102
+ }, [state.imageUri, config, handleProgress, onBeforeProcess]);
97
103
 
98
104
  const save = useCallback(async () => {
99
105
  if (!state.processedUrl) return;
@@ -1,8 +1,15 @@
1
1
  /**
2
2
  * Face Swap Feature Types
3
- * Request, Result, Config types for face swap generation
3
+ * Extends base image-to-image types for dual image processing
4
4
  */
5
5
 
6
+ import type {
7
+ BaseImageResult,
8
+ BaseDualImageState,
9
+ BaseDualImageTranslations,
10
+ DualImageConfig,
11
+ } from "../../../image-to-image/domain/types";
12
+
6
13
  export interface FaceSwapOptions {
7
14
  enhanceFace?: boolean;
8
15
  preserveSkinTone?: boolean;
@@ -17,47 +24,12 @@ export interface FaceSwapRequest {
17
24
  options?: FaceSwapOptions;
18
25
  }
19
26
 
20
- export interface FaceSwapResult {
21
- success: boolean;
22
- imageUrl?: string;
23
- imageBase64?: string;
24
- error?: string;
25
- requestId?: string;
26
- }
27
+ export type FaceSwapResult = BaseImageResult;
27
28
 
28
- export interface FaceSwapFeatureState {
29
- sourceImageUri: string | null;
30
- targetImageUri: string | null;
31
- processedUrl: string | null;
32
- isProcessing: boolean;
33
- progress: number;
34
- error: string | null;
35
- }
36
-
37
- export interface FaceSwapTranslations {
38
- sourceUploadTitle: string;
39
- sourceUploadSubtitle: string;
40
- targetUploadTitle: string;
41
- targetUploadSubtitle: string;
42
- uploadChange: string;
43
- uploadAnalyzing: string;
44
- description: string;
45
- processingText: string;
46
- processButtonText: string;
47
- successText: string;
48
- saveButtonText: string;
49
- tryAnotherText: string;
50
- }
29
+ export type FaceSwapFeatureState = BaseDualImageState;
51
30
 
52
- export type FaceSwapResultExtractor = (result: unknown) => string | undefined;
31
+ export type FaceSwapTranslations = BaseDualImageTranslations;
53
32
 
54
- export interface FaceSwapFeatureConfig {
55
- creditCost?: number;
56
- extractResult?: FaceSwapResultExtractor;
57
- prepareImage: (imageUri: string) => Promise<string>;
58
- onSourceImageSelect?: (uri: string) => void;
59
- onTargetImageSelect?: (uri: string) => void;
60
- onProcessingStart?: () => void;
61
- onProcessingComplete?: (result: FaceSwapResult) => void;
62
- onError?: (error: string) => void;
33
+ export interface FaceSwapFeatureConfig extends DualImageConfig<FaceSwapResult> {
34
+ defaultOptions?: FaceSwapOptions;
63
35
  }
@@ -8,6 +8,5 @@ export type {
8
8
  FaceSwapResult,
9
9
  FaceSwapFeatureState,
10
10
  FaceSwapTranslations,
11
- FaceSwapResultExtractor,
12
11
  FaceSwapFeatureConfig,
13
12
  } from "./face-swap.types";
@@ -11,15 +11,11 @@ export type {
11
11
  FaceSwapFeatureState,
12
12
  FaceSwapTranslations,
13
13
  FaceSwapFeatureConfig,
14
- FaceSwapResultExtractor,
15
14
  } from "./domain";
16
15
 
17
16
  // Presentation Hooks
18
17
  export { useFaceSwapFeature } from "./presentation";
19
- export type {
20
- UseFaceSwapFeatureProps,
21
- UseFaceSwapFeatureReturn,
22
- } from "./presentation";
18
+ export type { UseFaceSwapFeatureProps } from "./presentation";
23
19
 
24
20
  // Presentation Components
25
21
  export { FaceSwapFeature } from "./presentation";
@@ -22,6 +22,8 @@ export interface FaceSwapFeatureProps {
22
22
  onSelectSourceImage: () => Promise<string | null>;
23
23
  onSelectTargetImage: () => Promise<string | null>;
24
24
  onSaveImage: (imageUrl: string) => Promise<void>;
25
+ /** Called before processing starts. Return false to cancel. */
26
+ onBeforeProcess?: () => Promise<boolean>;
25
27
  renderProcessingModal?: (props: {
26
28
  visible: boolean;
27
29
  progress: number;
@@ -34,6 +36,7 @@ export const FaceSwapFeature: React.FC<FaceSwapFeatureProps> = ({
34
36
  onSelectSourceImage,
35
37
  onSelectTargetImage,
36
38
  onSaveImage,
39
+ onBeforeProcess,
37
40
  renderProcessingModal,
38
41
  }) => {
39
42
  const tokens = useAppDesignTokens();
@@ -45,6 +48,7 @@ export const FaceSwapFeature: React.FC<FaceSwapFeatureProps> = ({
45
48
  onSelectSourceImage,
46
49
  onSelectTargetImage,
47
50
  onSaveImage,
51
+ onBeforeProcess,
48
52
  });
49
53
 
50
54
  const handleProcess = useCallback(() => {
@@ -3,7 +3,4 @@
3
3
  */
4
4
 
5
5
  export { useFaceSwapFeature } from "./useFaceSwapFeature";
6
- export type {
7
- UseFaceSwapFeatureProps,
8
- UseFaceSwapFeatureReturn,
9
- } from "./useFaceSwapFeature";
6
+ export type { UseFaceSwapFeatureProps } from "./useFaceSwapFeature";
@@ -1,138 +1,35 @@
1
1
  /**
2
2
  * useFaceSwapFeature Hook
3
- * Manages face swap feature state and actions
3
+ * Uses base dual image hook for face swap processing
4
4
  */
5
5
 
6
- import { useState, useCallback } from "react";
7
- import { executeImageFeature } from "../../../../infrastructure/services";
8
- import type {
9
- FaceSwapFeatureState,
10
- FaceSwapFeatureConfig,
11
- FaceSwapResult,
12
- } from "../../domain/types";
6
+ import {
7
+ useDualImageFeature,
8
+ type BaseDualImageHookReturn,
9
+ } from "../../../image-to-image";
10
+ import type { FaceSwapFeatureConfig, FaceSwapResult } from "../../domain/types";
13
11
 
14
12
  export interface UseFaceSwapFeatureProps {
15
13
  config: FaceSwapFeatureConfig;
16
14
  onSelectSourceImage: () => Promise<string | null>;
17
15
  onSelectTargetImage: () => Promise<string | null>;
18
16
  onSaveImage: (imageUrl: string) => Promise<void>;
17
+ onBeforeProcess?: () => Promise<boolean>;
19
18
  }
20
19
 
21
- export interface UseFaceSwapFeatureReturn extends FaceSwapFeatureState {
22
- selectSourceImage: () => Promise<void>;
23
- selectTargetImage: () => Promise<void>;
24
- process: () => Promise<void>;
25
- save: () => Promise<void>;
26
- reset: () => void;
27
- }
28
-
29
- const initialState: FaceSwapFeatureState = {
30
- sourceImageUri: null,
31
- targetImageUri: null,
32
- processedUrl: null,
33
- isProcessing: false,
34
- progress: 0,
35
- error: null,
36
- };
37
-
38
20
  export function useFaceSwapFeature(
39
21
  props: UseFaceSwapFeatureProps,
40
- ): UseFaceSwapFeatureReturn {
41
- const { config, onSelectSourceImage, onSelectTargetImage, onSaveImage } = props;
42
- const [state, setState] = useState<FaceSwapFeatureState>(initialState);
43
-
44
- const selectSourceImage = useCallback(async () => {
45
- try {
46
- const uri = await onSelectSourceImage();
47
- if (uri) {
48
- setState((prev) => ({ ...prev, sourceImageUri: uri, error: null }));
49
- config.onSourceImageSelect?.(uri);
50
- }
51
- } catch (error) {
52
- const message = error instanceof Error ? error.message : String(error);
53
- setState((prev) => ({ ...prev, error: message }));
54
- }
55
- }, [onSelectSourceImage, config]);
56
-
57
- const selectTargetImage = useCallback(async () => {
58
- try {
59
- const uri = await onSelectTargetImage();
60
- if (uri) {
61
- setState((prev) => ({ ...prev, targetImageUri: uri, error: null }));
62
- config.onTargetImageSelect?.(uri);
63
- }
64
- } catch (error) {
65
- const message = error instanceof Error ? error.message : String(error);
66
- setState((prev) => ({ ...prev, error: message }));
67
- }
68
- }, [onSelectTargetImage, config]);
69
-
70
- const handleProgress = useCallback((progress: number) => {
71
- setState((prev) => ({ ...prev, progress }));
72
- }, []);
73
-
74
- const process = useCallback(async () => {
75
- if (!state.sourceImageUri || !state.targetImageUri) return;
76
-
77
- setState((prev) => ({
78
- ...prev,
79
- isProcessing: true,
80
- progress: 0,
81
- error: null,
82
- }));
83
-
84
- config.onProcessingStart?.();
85
-
86
- const sourceImageBase64 = await config.prepareImage(state.sourceImageUri);
87
- const targetImageBase64 = await config.prepareImage(state.targetImageUri);
88
-
89
- const result = await executeImageFeature(
90
- "face-swap",
91
- { imageBase64: sourceImageBase64, targetImageBase64 },
92
- { extractResult: config.extractResult, onProgress: handleProgress },
93
- );
94
-
95
- if (result.success && result.imageUrl) {
96
- setState((prev) => ({
97
- ...prev,
98
- isProcessing: false,
99
- processedUrl: result.imageUrl!,
100
- progress: 100,
101
- }));
102
- config.onProcessingComplete?.(result as FaceSwapResult);
103
- } else {
104
- const errorMessage = result.error || "Processing failed";
105
- setState((prev) => ({
106
- ...prev,
107
- isProcessing: false,
108
- error: errorMessage,
109
- progress: 0,
110
- }));
111
- config.onError?.(errorMessage);
112
- }
113
- }, [state.sourceImageUri, state.targetImageUri, config, handleProgress]);
114
-
115
- const save = useCallback(async () => {
116
- if (!state.processedUrl) return;
117
-
118
- try {
119
- await onSaveImage(state.processedUrl);
120
- } catch (error) {
121
- const message = error instanceof Error ? error.message : String(error);
122
- setState((prev) => ({ ...prev, error: message }));
123
- }
124
- }, [state.processedUrl, onSaveImage]);
125
-
126
- const reset = useCallback(() => {
127
- setState(initialState);
128
- }, []);
129
-
130
- return {
131
- ...state,
132
- selectSourceImage,
133
- selectTargetImage,
134
- process,
135
- save,
136
- reset,
137
- };
22
+ ): BaseDualImageHookReturn {
23
+ const { config, onSelectSourceImage, onSelectTargetImage, onSaveImage, onBeforeProcess } = props;
24
+
25
+ return useDualImageFeature<FaceSwapFeatureConfig, FaceSwapResult>(
26
+ { config, onSelectSourceImage, onSelectTargetImage, onSaveImage, onBeforeProcess },
27
+ {
28
+ buildInput: (sourceBase64, targetBase64, cfg) => ({
29
+ imageBase64: sourceBase64,
30
+ targetImageBase64: targetBase64,
31
+ options: cfg.defaultOptions,
32
+ }),
33
+ },
34
+ );
138
35
  }
@@ -21,6 +21,8 @@ export interface HDTouchUpFeatureProps {
21
21
  translations: HDTouchUpTranslations;
22
22
  onSelectImage: () => Promise<string | null>;
23
23
  onSaveImage: (imageUrl: string) => Promise<void>;
24
+ /** Called before processing starts. Return false to cancel. */
25
+ onBeforeProcess?: () => Promise<boolean>;
24
26
  renderProcessingModal?: (props: {
25
27
  visible: boolean;
26
28
  progress: number;
@@ -32,6 +34,7 @@ export const HDTouchUpFeature: React.FC<HDTouchUpFeatureProps> = ({
32
34
  translations,
33
35
  onSelectImage,
34
36
  onSaveImage,
37
+ onBeforeProcess,
35
38
  renderProcessingModal,
36
39
  }) => {
37
40
  const tokens = useAppDesignTokens();
@@ -42,6 +45,7 @@ export const HDTouchUpFeature: React.FC<HDTouchUpFeatureProps> = ({
42
45
  config,
43
46
  onSelectImage,
44
47
  onSaveImage,
48
+ onBeforeProcess,
45
49
  });
46
50
 
47
51
  const photoTranslations = useMemo(
@@ -15,6 +15,7 @@ export interface UseHDTouchUpFeatureProps {
15
15
  config: HDTouchUpFeatureConfig;
16
16
  onSelectImage: () => Promise<string | null>;
17
17
  onSaveImage: (imageUrl: string) => Promise<void>;
18
+ onBeforeProcess?: () => Promise<boolean>;
18
19
  }
19
20
 
20
21
  export interface UseHDTouchUpFeatureReturn extends HDTouchUpFeatureState {
@@ -35,7 +36,7 @@ const initialState: HDTouchUpFeatureState = {
35
36
  export function useHDTouchUpFeature(
36
37
  props: UseHDTouchUpFeatureProps,
37
38
  ): UseHDTouchUpFeatureReturn {
38
- const { config, onSelectImage, onSaveImage } = props;
39
+ const { config, onSelectImage, onSaveImage, onBeforeProcess } = props;
39
40
  const [state, setState] = useState<HDTouchUpFeatureState>(initialState);
40
41
 
41
42
  const selectImage = useCallback(async () => {
@@ -58,6 +59,11 @@ export function useHDTouchUpFeature(
58
59
  const process = useCallback(async () => {
59
60
  if (!state.imageUri) return;
60
61
 
62
+ if (onBeforeProcess) {
63
+ const canProceed = await onBeforeProcess();
64
+ if (!canProceed) return;
65
+ }
66
+
61
67
  setState((prev) => ({
62
68
  ...prev,
63
69
  isProcessing: true,
@@ -93,7 +99,7 @@ export function useHDTouchUpFeature(
93
99
  }));
94
100
  config.onError?.(errorMessage);
95
101
  }
96
- }, [state.imageUri, config, handleProgress]);
102
+ }, [state.imageUri, config, handleProgress, onBeforeProcess]);
97
103
 
98
104
  const save = useCallback(async () => {
99
105
  if (!state.processedUrl) return;
@@ -0,0 +1 @@
1
+ export * from "./types";
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Base Image-to-Image Types
3
+ * Common types for all image processing features
4
+ */
5
+
6
+ import type { ImageFeatureType } from "../../../../domain/interfaces";
7
+
8
+ /**
9
+ * Image processing categories
10
+ */
11
+ export type ImageProcessingCategory =
12
+ | "enhancement"
13
+ | "editing"
14
+ | "transformation"
15
+ | "composition";
16
+
17
+ /**
18
+ * Input mode for image processing
19
+ */
20
+ export type ImageInputMode = "single" | "single-with-prompt" | "dual";
21
+
22
+ /**
23
+ * Base result for all image processing features
24
+ */
25
+ export interface BaseImageResult {
26
+ success: boolean;
27
+ imageUrl?: string;
28
+ imageBase64?: string;
29
+ error?: string;
30
+ requestId?: string;
31
+ }
32
+
33
+ /**
34
+ * Base state for single image features
35
+ */
36
+ export interface BaseSingleImageState {
37
+ imageUri: string | null;
38
+ processedUrl: string | null;
39
+ isProcessing: boolean;
40
+ progress: number;
41
+ error: string | null;
42
+ }
43
+
44
+ /**
45
+ * Base state for single image + prompt features
46
+ */
47
+ export interface BaseImageWithPromptState extends BaseSingleImageState {
48
+ prompt: string;
49
+ }
50
+
51
+ /**
52
+ * Base state for dual image features
53
+ */
54
+ export interface BaseDualImageState {
55
+ sourceImageUri: string | null;
56
+ targetImageUri: string | null;
57
+ processedUrl: string | null;
58
+ isProcessing: boolean;
59
+ progress: number;
60
+ error: string | null;
61
+ }
62
+
63
+ /**
64
+ * Base translations for image features
65
+ */
66
+ export interface BaseImageTranslations {
67
+ uploadTitle: string;
68
+ uploadSubtitle: string;
69
+ uploadChange: string;
70
+ uploadAnalyzing: string;
71
+ description: string;
72
+ processingText: string;
73
+ processButtonText: string;
74
+ successText: string;
75
+ saveButtonText: string;
76
+ tryAnotherText: string;
77
+ beforeLabel?: string;
78
+ afterLabel?: string;
79
+ compareHint?: string;
80
+ }
81
+
82
+ /**
83
+ * Base translations for dual image features
84
+ */
85
+ export interface BaseDualImageTranslations {
86
+ sourceUploadTitle: string;
87
+ sourceUploadSubtitle: string;
88
+ targetUploadTitle: string;
89
+ targetUploadSubtitle: string;
90
+ uploadChange: string;
91
+ uploadAnalyzing: string;
92
+ description: string;
93
+ processingText: string;
94
+ processButtonText: string;
95
+ successText: string;
96
+ saveButtonText: string;
97
+ tryAnotherText: string;
98
+ }
99
+
100
+ /**
101
+ * Result extractor function type
102
+ */
103
+ export type ImageResultExtractor = (result: unknown) => string | undefined;
104
+
105
+ /**
106
+ * Base config for all image features
107
+ */
108
+ export interface BaseImageConfig<TResult extends BaseImageResult = BaseImageResult> {
109
+ featureType: ImageFeatureType;
110
+ creditCost?: number;
111
+ extractResult?: ImageResultExtractor;
112
+ prepareImage: (imageUri: string) => Promise<string>;
113
+ onProcessingStart?: () => void;
114
+ onProcessingComplete?: (result: TResult) => void;
115
+ onError?: (error: string) => void;
116
+ }
117
+
118
+ /**
119
+ * Config for single image features
120
+ */
121
+ export interface SingleImageConfig<TResult extends BaseImageResult = BaseImageResult>
122
+ extends BaseImageConfig<TResult> {
123
+ onImageSelect?: (uri: string) => void;
124
+ }
125
+
126
+ /**
127
+ * Config for dual image features
128
+ */
129
+ export interface DualImageConfig<TResult extends BaseImageResult = BaseImageResult>
130
+ extends BaseImageConfig<TResult> {
131
+ onSourceImageSelect?: (uri: string) => void;
132
+ onTargetImageSelect?: (uri: string) => void;
133
+ }
134
+
135
+ /**
136
+ * Base hook props for single image features
137
+ */
138
+ export interface BaseSingleImageHookProps<
139
+ TConfig extends SingleImageConfig = SingleImageConfig,
140
+ > {
141
+ config: TConfig;
142
+ onSelectImage: () => Promise<string | null>;
143
+ onSaveImage: (imageUrl: string) => Promise<void>;
144
+ /** Called before processing starts. Return false to cancel. */
145
+ onBeforeProcess?: () => Promise<boolean>;
146
+ }
147
+
148
+ /**
149
+ * Base hook props for dual image features
150
+ */
151
+ export interface BaseDualImageHookProps<
152
+ TConfig extends DualImageConfig = DualImageConfig,
153
+ > {
154
+ config: TConfig;
155
+ onSelectSourceImage: () => Promise<string | null>;
156
+ onSelectTargetImage: () => Promise<string | null>;
157
+ onSaveImage: (imageUrl: string) => Promise<void>;
158
+ /** Called before processing starts. Return false to cancel. */
159
+ onBeforeProcess?: () => Promise<boolean>;
160
+ }
161
+
162
+ /**
163
+ * Base hook return for single image features
164
+ */
165
+ export interface BaseSingleImageHookReturn extends BaseSingleImageState {
166
+ selectImage: () => Promise<void>;
167
+ process: () => Promise<void>;
168
+ save: () => Promise<void>;
169
+ reset: () => void;
170
+ }
171
+
172
+ /**
173
+ * Base hook return for dual image features
174
+ */
175
+ export interface BaseDualImageHookReturn extends BaseDualImageState {
176
+ selectSourceImage: () => Promise<void>;
177
+ selectTargetImage: () => Promise<void>;
178
+ process: () => Promise<void>;
179
+ save: () => Promise<void>;
180
+ reset: () => void;
181
+ }
182
+
183
+ /**
184
+ * Feature metadata for categorization
185
+ */
186
+ export interface ImageFeatureMetadata {
187
+ name: string;
188
+ category: ImageProcessingCategory;
189
+ inputMode: ImageInputMode;
190
+ featureType: ImageFeatureType;
191
+ requiresPrompt?: boolean;
192
+ requiresMask?: boolean;
193
+ }