@umituz/react-native-ai-generation-content 1.17.148 → 1.17.150

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 (27) 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/presentation/components/FaceSwapFeature.tsx +4 -0
  9. package/src/features/face-swap/presentation/hooks/useFaceSwapFeature.ts +3 -2
  10. package/src/features/hd-touch-up/presentation/components/HDTouchUpFeature.tsx +4 -0
  11. package/src/features/hd-touch-up/presentation/hooks/useHDTouchUpFeature.ts +8 -2
  12. package/src/features/image-to-image/domain/types/base.types.ts +4 -0
  13. package/src/features/image-to-image/presentation/hooks/useDualImageFeature.ts +8 -2
  14. package/src/features/image-to-image/presentation/hooks/useImageWithPromptFeature.ts +10 -2
  15. package/src/features/image-to-image/presentation/hooks/useSingleImageFeature.ts +8 -2
  16. package/src/features/photo-restoration/presentation/components/PhotoRestoreFeature.tsx +4 -0
  17. package/src/features/photo-restoration/presentation/hooks/usePhotoRestoreFeature.ts +8 -2
  18. package/src/features/remove-background/presentation/components/RemoveBackgroundFeature.tsx +4 -0
  19. package/src/features/remove-background/presentation/hooks/useRemoveBackgroundFeature.ts +3 -2
  20. package/src/features/remove-object/presentation/components/RemoveObjectFeature.tsx +4 -0
  21. package/src/features/remove-object/presentation/hooks/useRemoveObjectFeature.ts +8 -2
  22. package/src/features/replace-background/presentation/components/ReplaceBackgroundFeature.tsx +4 -0
  23. package/src/features/replace-background/presentation/hooks/useReplaceBackgroundFeature.ts +3 -2
  24. package/src/features/shared/dual-image-video/domain/types/dual-image-video.types.ts +2 -0
  25. package/src/features/shared/dual-image-video/presentation/hooks/useDualImageVideoFeature.ts +7 -2
  26. package/src/features/upscaling/presentation/components/UpscaleFeature.tsx +4 -0
  27. package/src/features/upscaling/presentation/hooks/useUpscaleFeature.ts +3 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-ai-generation-content",
3
- "version": "1.17.148",
3
+ "version": "1.17.150",
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;
@@ -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(() => {
@@ -14,15 +14,16 @@ export interface UseFaceSwapFeatureProps {
14
14
  onSelectSourceImage: () => Promise<string | null>;
15
15
  onSelectTargetImage: () => Promise<string | null>;
16
16
  onSaveImage: (imageUrl: string) => Promise<void>;
17
+ onBeforeProcess?: () => Promise<boolean>;
17
18
  }
18
19
 
19
20
  export function useFaceSwapFeature(
20
21
  props: UseFaceSwapFeatureProps,
21
22
  ): BaseDualImageHookReturn {
22
- const { config, onSelectSourceImage, onSelectTargetImage, onSaveImage } = props;
23
+ const { config, onSelectSourceImage, onSelectTargetImage, onSaveImage, onBeforeProcess } = props;
23
24
 
24
25
  return useDualImageFeature<FaceSwapFeatureConfig, FaceSwapResult>(
25
- { config, onSelectSourceImage, onSelectTargetImage, onSaveImage },
26
+ { config, onSelectSourceImage, onSelectTargetImage, onSaveImage, onBeforeProcess },
26
27
  {
27
28
  buildInput: (sourceBase64, targetBase64, cfg) => ({
28
29
  imageBase64: sourceBase64,
@@ -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;
@@ -141,6 +141,8 @@ export interface BaseSingleImageHookProps<
141
141
  config: TConfig;
142
142
  onSelectImage: () => Promise<string | null>;
143
143
  onSaveImage: (imageUrl: string) => Promise<void>;
144
+ /** Called before processing starts. Return false to cancel. */
145
+ onBeforeProcess?: () => Promise<boolean>;
144
146
  }
145
147
 
146
148
  /**
@@ -153,6 +155,8 @@ export interface BaseDualImageHookProps<
153
155
  onSelectSourceImage: () => Promise<string | null>;
154
156
  onSelectTargetImage: () => Promise<string | null>;
155
157
  onSaveImage: (imageUrl: string) => Promise<void>;
158
+ /** Called before processing starts. Return false to cancel. */
159
+ onBeforeProcess?: () => Promise<boolean>;
156
160
  }
157
161
 
158
162
  /**
@@ -37,7 +37,7 @@ export function useDualImageFeature<
37
37
  props: BaseDualImageHookProps<TConfig>,
38
38
  options?: DualImageFeatureOptions<TConfig>,
39
39
  ): BaseDualImageHookReturn {
40
- const { config, onSelectSourceImage, onSelectTargetImage, onSaveImage } = props;
40
+ const { config, onSelectSourceImage, onSelectTargetImage, onSaveImage, onBeforeProcess } = props;
41
41
  const [state, setState] = useState<BaseDualImageState>(INITIAL_STATE);
42
42
 
43
43
  const selectSourceImage = useCallback(async () => {
@@ -73,6 +73,12 @@ export function useDualImageFeature<
73
73
  const process = useCallback(async () => {
74
74
  if (!state.sourceImageUri || !state.targetImageUri) return;
75
75
 
76
+ // Check if processing is allowed (credit check, etc.)
77
+ if (onBeforeProcess) {
78
+ const canProceed = await onBeforeProcess();
79
+ if (!canProceed) return;
80
+ }
81
+
76
82
  setState((prev) => ({
77
83
  ...prev,
78
84
  isProcessing: true,
@@ -126,7 +132,7 @@ export function useDualImageFeature<
126
132
  }));
127
133
  config.onError?.(message);
128
134
  }
129
- }, [state.sourceImageUri, state.targetImageUri, config, options, handleProgress]);
135
+ }, [state.sourceImageUri, state.targetImageUri, config, options, handleProgress, onBeforeProcess]);
130
136
 
131
137
  const save = useCallback(async () => {
132
138
  if (!state.processedUrl) return;
@@ -32,6 +32,8 @@ export interface ImageWithPromptHookProps<
32
32
  config: TConfig;
33
33
  onSelectImage: () => Promise<string | null>;
34
34
  onSaveImage: (imageUrl: string) => Promise<void>;
35
+ /** Called before processing starts. Return false to cancel. */
36
+ onBeforeProcess?: () => Promise<boolean>;
35
37
  }
36
38
 
37
39
  export interface ImageWithPromptHookReturn extends BaseImageWithPromptState {
@@ -58,7 +60,7 @@ export function useImageWithPromptFeature<
58
60
  props: ImageWithPromptHookProps<TConfig>,
59
61
  options?: ImageWithPromptOptions,
60
62
  ): ImageWithPromptHookReturn {
61
- const { config, onSelectImage, onSaveImage } = props;
63
+ const { config, onSelectImage, onSaveImage, onBeforeProcess } = props;
62
64
  const [state, setState] = useState<BaseImageWithPromptState>({
63
65
  ...INITIAL_STATE,
64
66
  prompt: config.defaultPrompt || "",
@@ -92,6 +94,12 @@ export function useImageWithPromptFeature<
92
94
  const process = useCallback(async () => {
93
95
  if (!state.imageUri) return;
94
96
 
97
+ // Check if processing is allowed (credit check, etc.)
98
+ if (onBeforeProcess) {
99
+ const canProceed = await onBeforeProcess();
100
+ if (!canProceed) return;
101
+ }
102
+
95
103
  if (options?.promptRequired && !state.prompt.trim()) {
96
104
  const error = "Prompt is required";
97
105
  setState((prev) => ({ ...prev, error }));
@@ -149,7 +157,7 @@ export function useImageWithPromptFeature<
149
157
  }));
150
158
  config.onError?.(message);
151
159
  }
152
- }, [state.imageUri, state.prompt, config, options, handleProgress]);
160
+ }, [state.imageUri, state.prompt, config, options, handleProgress, onBeforeProcess]);
153
161
 
154
162
  const save = useCallback(async () => {
155
163
  if (!state.processedUrl) return;
@@ -32,7 +32,7 @@ export function useSingleImageFeature<
32
32
  props: BaseSingleImageHookProps<TConfig>,
33
33
  options?: SingleImageFeatureOptions<TConfig>,
34
34
  ): BaseSingleImageHookReturn {
35
- const { config, onSelectImage, onSaveImage } = props;
35
+ const { config, onSelectImage, onSaveImage, onBeforeProcess } = props;
36
36
  const [state, setState] = useState<BaseSingleImageState>(INITIAL_STATE);
37
37
 
38
38
  const selectImage = useCallback(async () => {
@@ -55,6 +55,12 @@ export function useSingleImageFeature<
55
55
  const process = useCallback(async () => {
56
56
  if (!state.imageUri) return;
57
57
 
58
+ // Check if processing is allowed (credit check, etc.)
59
+ if (onBeforeProcess) {
60
+ const canProceed = await onBeforeProcess();
61
+ if (!canProceed) return;
62
+ }
63
+
58
64
  setState((prev) => ({
59
65
  ...prev,
60
66
  isProcessing: true,
@@ -105,7 +111,7 @@ export function useSingleImageFeature<
105
111
  }));
106
112
  config.onError?.(message);
107
113
  }
108
- }, [state.imageUri, config, options, handleProgress]);
114
+ }, [state.imageUri, config, options, handleProgress, onBeforeProcess]);
109
115
 
110
116
  const save = useCallback(async () => {
111
117
  if (!state.processedUrl) return;
@@ -25,6 +25,8 @@ export interface PhotoRestoreFeatureProps {
25
25
  onSelectImage: () => Promise<string | null>;
26
26
  /** Save image callback */
27
27
  onSaveImage: (imageUrl: string) => Promise<void>;
28
+ /** Called before processing starts. Return false to cancel. */
29
+ onBeforeProcess?: () => Promise<boolean>;
28
30
  /** Optional custom processing modal renderer */
29
31
  renderProcessingModal?: (props: {
30
32
  visible: boolean;
@@ -37,6 +39,7 @@ export const PhotoRestoreFeature: React.FC<PhotoRestoreFeatureProps> = ({
37
39
  translations,
38
40
  onSelectImage,
39
41
  onSaveImage,
42
+ onBeforeProcess,
40
43
  renderProcessingModal,
41
44
  }) => {
42
45
  const tokens = useAppDesignTokens();
@@ -45,6 +48,7 @@ export const PhotoRestoreFeature: React.FC<PhotoRestoreFeatureProps> = ({
45
48
  config,
46
49
  onSelectImage,
47
50
  onSaveImage,
51
+ onBeforeProcess,
48
52
  });
49
53
 
50
54
  const photoTranslations = useMemo(
@@ -15,6 +15,7 @@ export interface UsePhotoRestoreFeatureProps {
15
15
  config: PhotoRestoreFeatureConfig;
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 UsePhotoRestoreFeatureReturn extends PhotoRestoreFeatureState {
@@ -35,7 +36,7 @@ const initialState: PhotoRestoreFeatureState = {
35
36
  export function usePhotoRestoreFeature(
36
37
  props: UsePhotoRestoreFeatureProps,
37
38
  ): UsePhotoRestoreFeatureReturn {
38
- const { config, onSelectImage, onSaveImage } = props;
39
+ const { config, onSelectImage, onSaveImage, onBeforeProcess } = props;
39
40
  const [state, setState] = useState<PhotoRestoreFeatureState>(initialState);
40
41
 
41
42
  const selectImage = useCallback(async () => {
@@ -58,6 +59,11 @@ export function usePhotoRestoreFeature(
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 usePhotoRestoreFeature(
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;
@@ -21,6 +21,8 @@ export interface RemoveBackgroundFeatureProps {
21
21
  translations: RemoveBackgroundTranslations;
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 RemoveBackgroundFeature: React.FC<RemoveBackgroundFeatureProps> = (
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 RemoveBackgroundFeature: React.FC<RemoveBackgroundFeatureProps> = (
42
45
  config,
43
46
  onSelectImage,
44
47
  onSaveImage,
48
+ onBeforeProcess,
45
49
  });
46
50
 
47
51
  const photoTranslations = useMemo(
@@ -16,15 +16,16 @@ export interface UseRemoveBackgroundFeatureProps {
16
16
  config: RemoveBackgroundFeatureConfig;
17
17
  onSelectImage: () => Promise<string | null>;
18
18
  onSaveImage: (imageUrl: string) => Promise<void>;
19
+ onBeforeProcess?: () => Promise<boolean>;
19
20
  }
20
21
 
21
22
  export function useRemoveBackgroundFeature(
22
23
  props: UseRemoveBackgroundFeatureProps,
23
24
  ): BaseSingleImageHookReturn {
24
- const { config, onSelectImage, onSaveImage } = props;
25
+ const { config, onSelectImage, onSaveImage, onBeforeProcess } = props;
25
26
 
26
27
  return useSingleImageFeature<RemoveBackgroundFeatureConfig, RemoveBackgroundResult>(
27
- { config, onSelectImage, onSaveImage },
28
+ { config, onSelectImage, onSaveImage, onBeforeProcess },
28
29
  {
29
30
  buildInput: (imageBase64, cfg) => ({
30
31
  imageBase64,
@@ -25,6 +25,8 @@ export interface RemoveObjectFeatureProps {
25
25
  translations: RemoveObjectTranslations;
26
26
  onSelectImage: () => Promise<string | null>;
27
27
  onSaveImage: (imageUrl: string) => Promise<void>;
28
+ /** Called before processing starts. Return false to cancel. */
29
+ onBeforeProcess?: () => Promise<boolean>;
28
30
  renderProcessingModal?: (props: {
29
31
  visible: boolean;
30
32
  progress: number;
@@ -36,6 +38,7 @@ export const RemoveObjectFeature: React.FC<RemoveObjectFeatureProps> = ({
36
38
  translations,
37
39
  onSelectImage,
38
40
  onSaveImage,
41
+ onBeforeProcess,
39
42
  renderProcessingModal,
40
43
  }) => {
41
44
  const tokens = useAppDesignTokens();
@@ -46,6 +49,7 @@ export const RemoveObjectFeature: React.FC<RemoveObjectFeatureProps> = ({
46
49
  config,
47
50
  onSelectImage,
48
51
  onSaveImage,
52
+ onBeforeProcess,
49
53
  });
50
54
 
51
55
  const photoTranslations = useMemo(
@@ -16,6 +16,7 @@ export interface UseRemoveObjectFeatureProps {
16
16
  onSelectImage: () => Promise<string | null>;
17
17
  onSelectMask?: () => Promise<string | null>;
18
18
  onSaveImage: (imageUrl: string) => Promise<void>;
19
+ onBeforeProcess?: () => Promise<boolean>;
19
20
  }
20
21
 
21
22
  export interface UseRemoveObjectFeatureReturn extends RemoveObjectFeatureState {
@@ -40,7 +41,7 @@ const initialState: RemoveObjectFeatureState = {
40
41
  export function useRemoveObjectFeature(
41
42
  props: UseRemoveObjectFeatureProps,
42
43
  ): UseRemoveObjectFeatureReturn {
43
- const { config, onSelectImage, onSelectMask, onSaveImage } = props;
44
+ const { config, onSelectImage, onSelectMask, onSaveImage, onBeforeProcess } = props;
44
45
  const [state, setState] = useState<RemoveObjectFeatureState>(initialState);
45
46
 
46
47
  const selectImage = useCallback(async () => {
@@ -82,6 +83,11 @@ export function useRemoveObjectFeature(
82
83
  const process = useCallback(async () => {
83
84
  if (!state.imageUri) return;
84
85
 
86
+ if (onBeforeProcess) {
87
+ const canProceed = await onBeforeProcess();
88
+ if (!canProceed) return;
89
+ }
90
+
85
91
  setState((prev) => ({
86
92
  ...prev,
87
93
  isProcessing: true,
@@ -124,7 +130,7 @@ export function useRemoveObjectFeature(
124
130
  }));
125
131
  config.onError?.(errorMessage);
126
132
  }
127
- }, [state.imageUri, state.maskUri, state.prompt, config, handleProgress]);
133
+ }, [state.imageUri, state.maskUri, state.prompt, config, handleProgress, onBeforeProcess]);
128
134
 
129
135
  const save = useCallback(async () => {
130
136
  if (!state.processedUrl) return;
@@ -25,6 +25,8 @@ export interface ReplaceBackgroundFeatureProps {
25
25
  translations: ReplaceBackgroundTranslations;
26
26
  onSelectImage: () => Promise<string | null>;
27
27
  onSaveImage: (imageUrl: string) => Promise<void>;
28
+ /** Called before processing starts. Return false to cancel. */
29
+ onBeforeProcess?: () => Promise<boolean>;
28
30
  renderProcessingModal?: (props: {
29
31
  visible: boolean;
30
32
  progress: number;
@@ -36,6 +38,7 @@ export const ReplaceBackgroundFeature: React.FC<ReplaceBackgroundFeatureProps> =
36
38
  translations,
37
39
  onSelectImage,
38
40
  onSaveImage,
41
+ onBeforeProcess,
39
42
  renderProcessingModal,
40
43
  }) => {
41
44
  const tokens = useAppDesignTokens();
@@ -46,6 +49,7 @@ export const ReplaceBackgroundFeature: React.FC<ReplaceBackgroundFeatureProps> =
46
49
  config,
47
50
  onSelectImage,
48
51
  onSaveImage,
52
+ onBeforeProcess,
49
53
  });
50
54
 
51
55
  const photoTranslations = useMemo(
@@ -18,6 +18,7 @@ export interface UseReplaceBackgroundFeatureProps {
18
18
  config: ReplaceBackgroundFeatureConfig;
19
19
  onSelectImage: () => Promise<string | null>;
20
20
  onSaveImage: (imageUrl: string) => Promise<void>;
21
+ onBeforeProcess?: () => Promise<boolean>;
21
22
  }
22
23
 
23
24
  export interface UseReplaceBackgroundFeatureReturn extends ImageWithPromptHookReturn {
@@ -28,11 +29,11 @@ export interface UseReplaceBackgroundFeatureReturn extends ImageWithPromptHookRe
28
29
  export function useReplaceBackgroundFeature(
29
30
  props: UseReplaceBackgroundFeatureProps,
30
31
  ): UseReplaceBackgroundFeatureReturn {
31
- const { config, onSelectImage, onSaveImage } = props;
32
+ const { config, onSelectImage, onSaveImage, onBeforeProcess } = props;
32
33
  const [mode, setMode] = useState<ReplaceBackgroundMode>(config.defaultMode || "replace");
33
34
 
34
35
  const baseHook = useImageWithPromptFeature<ReplaceBackgroundFeatureConfig, ReplaceBackgroundResult>(
35
- { config, onSelectImage, onSaveImage },
36
+ { config, onSelectImage, onSaveImage, onBeforeProcess },
36
37
  {
37
38
  buildInput: (imageBase64, prompt) => ({
38
39
  imageBase64,
@@ -56,6 +56,8 @@ export interface UseDualImageVideoFeatureProps {
56
56
  onSelectSourceImage: () => Promise<string | null>;
57
57
  onSelectTargetImage: () => Promise<string | null>;
58
58
  onSaveVideo: (videoUrl: string) => Promise<void>;
59
+ /** Called before processing starts. Return false to cancel. */
60
+ onBeforeProcess?: () => Promise<boolean>;
59
61
  }
60
62
 
61
63
  export interface UseDualImageVideoFeatureReturn extends DualImageVideoFeatureState {
@@ -24,7 +24,7 @@ const initialState: DualImageVideoFeatureState = {
24
24
  export function useDualImageVideoFeature(
25
25
  props: UseDualImageVideoFeatureProps,
26
26
  ): UseDualImageVideoFeatureReturn {
27
- const { featureType, config, onSelectSourceImage, onSelectTargetImage, onSaveVideo } = props;
27
+ const { featureType, config, onSelectSourceImage, onSelectTargetImage, onSaveVideo, onBeforeProcess } = props;
28
28
  const [state, setState] = useState<DualImageVideoFeatureState>(initialState);
29
29
 
30
30
  const selectSourceImage = useCallback(async () => {
@@ -60,6 +60,11 @@ export function useDualImageVideoFeature(
60
60
  const process = useCallback(async () => {
61
61
  if (!state.sourceImageUri || !state.targetImageUri) return;
62
62
 
63
+ if (onBeforeProcess) {
64
+ const canProceed = await onBeforeProcess();
65
+ if (!canProceed) return;
66
+ }
67
+
63
68
  setState((prev) => ({
64
69
  ...prev,
65
70
  isProcessing: true,
@@ -96,7 +101,7 @@ export function useDualImageVideoFeature(
96
101
  }));
97
102
  config.onError?.(errorMessage);
98
103
  }
99
- }, [state.sourceImageUri, state.targetImageUri, featureType, config, handleProgress]);
104
+ }, [state.sourceImageUri, state.targetImageUri, featureType, config, handleProgress, onBeforeProcess]);
100
105
 
101
106
  const save = useCallback(async () => {
102
107
  if (!state.processedVideoUrl) return;
@@ -28,6 +28,8 @@ export interface UpscaleFeatureProps {
28
28
  onSelectImage: () => Promise<string | null>;
29
29
  /** Save image callback */
30
30
  onSaveImage: (imageUrl: string) => Promise<void>;
31
+ /** Called before processing starts. Return false to cancel. */
32
+ onBeforeProcess?: () => Promise<boolean>;
31
33
  /** Optional custom processing modal renderer */
32
34
  renderProcessingModal?: (props: {
33
35
  visible: boolean;
@@ -40,6 +42,7 @@ export const UpscaleFeature: React.FC<UpscaleFeatureProps> = ({
40
42
  translations,
41
43
  onSelectImage,
42
44
  onSaveImage,
45
+ onBeforeProcess,
43
46
  renderProcessingModal,
44
47
  }) => {
45
48
  const tokens = useAppDesignTokens();
@@ -48,6 +51,7 @@ export const UpscaleFeature: React.FC<UpscaleFeatureProps> = ({
48
51
  config,
49
52
  onSelectImage,
50
53
  onSaveImage,
54
+ onBeforeProcess,
51
55
  });
52
56
 
53
57
  const photoTranslations = useMemo(
@@ -13,15 +13,16 @@ export interface UseUpscaleFeatureProps {
13
13
  config: UpscaleFeatureConfig;
14
14
  onSelectImage: () => Promise<string | null>;
15
15
  onSaveImage: (imageUrl: string) => Promise<void>;
16
+ onBeforeProcess?: () => Promise<boolean>;
16
17
  }
17
18
 
18
19
  export function useUpscaleFeature(
19
20
  props: UseUpscaleFeatureProps,
20
21
  ): BaseSingleImageHookReturn {
21
- const { config, onSelectImage, onSaveImage } = props;
22
+ const { config, onSelectImage, onSaveImage, onBeforeProcess } = props;
22
23
 
23
24
  return useSingleImageFeature<UpscaleFeatureConfig, UpscaleResult>(
24
- { config, onSelectImage, onSaveImage },
25
+ { config, onSelectImage, onSaveImage, onBeforeProcess },
25
26
  {
26
27
  buildInput: (imageBase64, cfg) => ({
27
28
  imageBase64,