@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.
- package/package.json +1 -1
- package/src/features/ai-hug/presentation/components/AIHugFeature.tsx +4 -0
- package/src/features/ai-hug/presentation/hooks/useAIHugFeature.ts +1 -0
- package/src/features/ai-kiss/presentation/components/AIKissFeature.tsx +4 -0
- package/src/features/ai-kiss/presentation/hooks/useAIKissFeature.ts +1 -0
- package/src/features/anime-selfie/presentation/components/AnimeSelfieFeature.tsx +4 -0
- package/src/features/anime-selfie/presentation/hooks/useAnimeSelfieFeature.ts +8 -2
- package/src/features/face-swap/domain/types/face-swap.types.ts +13 -41
- package/src/features/face-swap/domain/types/index.ts +0 -1
- package/src/features/face-swap/index.ts +1 -5
- package/src/features/face-swap/presentation/components/FaceSwapFeature.tsx +4 -0
- package/src/features/face-swap/presentation/hooks/index.ts +1 -4
- package/src/features/face-swap/presentation/hooks/useFaceSwapFeature.ts +20 -123
- package/src/features/hd-touch-up/presentation/components/HDTouchUpFeature.tsx +4 -0
- package/src/features/hd-touch-up/presentation/hooks/useHDTouchUpFeature.ts +8 -2
- package/src/features/image-to-image/domain/index.ts +1 -0
- package/src/features/image-to-image/domain/types/base.types.ts +193 -0
- package/src/features/image-to-image/domain/types/index.ts +1 -0
- package/src/features/image-to-image/index.ts +2 -0
- package/src/features/image-to-image/presentation/hooks/index.ts +3 -0
- package/src/features/image-to-image/presentation/hooks/useDualImageFeature.ts +160 -0
- package/src/features/image-to-image/presentation/hooks/useImageWithPromptFeature.ts +188 -0
- package/src/features/image-to-image/presentation/hooks/useSingleImageFeature.ts +138 -0
- package/src/features/image-to-image/presentation/index.ts +1 -0
- package/src/features/photo-restoration/presentation/components/PhotoRestoreFeature.tsx +4 -0
- package/src/features/photo-restoration/presentation/hooks/usePhotoRestoreFeature.ts +8 -2
- package/src/features/remove-background/domain/types/index.ts +0 -1
- package/src/features/remove-background/domain/types/remove-background.types.ts +14 -40
- package/src/features/remove-background/index.ts +1 -5
- package/src/features/remove-background/presentation/components/RemoveBackgroundFeature.tsx +4 -0
- package/src/features/remove-background/presentation/hooks/index.ts +1 -4
- package/src/features/remove-background/presentation/hooks/useRemoveBackgroundFeature.ts +18 -102
- package/src/features/remove-object/presentation/components/RemoveObjectFeature.tsx +4 -0
- package/src/features/remove-object/presentation/hooks/useRemoveObjectFeature.ts +8 -2
- package/src/features/replace-background/domain/types/index.ts +1 -2
- package/src/features/replace-background/domain/types/replace-background.types.ts +14 -39
- package/src/features/replace-background/index.ts +0 -1
- package/src/features/replace-background/presentation/components/ReplaceBackgroundFeature.tsx +4 -0
- package/src/features/replace-background/presentation/hooks/useReplaceBackgroundFeature.ts +32 -119
- package/src/features/shared/dual-image-video/domain/types/dual-image-video.types.ts +2 -0
- package/src/features/shared/dual-image-video/presentation/hooks/useDualImageVideoFeature.ts +7 -2
- package/src/features/upscaling/domain/types/upscale.types.ts +12 -42
- package/src/features/upscaling/index.ts +1 -5
- package/src/features/upscaling/presentation/components/UpscaleFeature.tsx +4 -0
- package/src/features/upscaling/presentation/hooks/index.ts +1 -4
- package/src/features/upscaling/presentation/hooks/useUpscaleFeature.ts +17 -107
- package/src/index.ts +6 -0
package/package.json
CHANGED
|
@@ -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
|
-
*
|
|
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
|
|
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
|
|
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
|
|
31
|
+
export type FaceSwapTranslations = BaseDualImageTranslations;
|
|
53
32
|
|
|
54
|
-
export interface FaceSwapFeatureConfig {
|
|
55
|
-
|
|
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
|
}
|
|
@@ -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(() => {
|
|
@@ -1,138 +1,35 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* useFaceSwapFeature Hook
|
|
3
|
-
*
|
|
3
|
+
* Uses base dual image hook for face swap processing
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
):
|
|
41
|
-
const { config, onSelectSourceImage, onSelectTargetImage, onSaveImage } = props;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
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
|
+
}
|