@umituz/react-native-ai-generation-content 1.17.143 → 1.17.145
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/domains/creations/presentation/hooks/index.ts +2 -2
- package/src/domains/creations/presentation/hooks/{useMediaFilter.ts → useFilter.ts} +12 -7
- package/src/domains/creations/presentation/hooks/useGalleryFilters.ts +5 -6
- package/src/features/ai-hug/presentation/hooks/useAIHugFeature.ts +9 -113
- package/src/features/ai-kiss/presentation/hooks/useAIKissFeature.ts +9 -113
- package/src/features/image-to-video/infrastructure/services/image-to-video-executor.ts +5 -9
- package/src/features/image-to-video/presentation/hooks/useImageToVideoForm.ts +5 -0
- package/src/features/replace-background/index.ts +5 -50
- package/src/features/replace-background/presentation/components/index.ts +0 -12
- package/src/features/replace-background/presentation/hooks/index.ts +0 -3
- package/src/features/shared/dual-image-video/domain/types/dual-image-video.types.ts +67 -0
- package/src/features/shared/dual-image-video/domain/types/index.ts +13 -0
- package/src/features/shared/dual-image-video/index.ts +16 -0
- package/src/features/shared/dual-image-video/presentation/hooks/index.ts +5 -0
- package/src/features/shared/dual-image-video/presentation/hooks/useDualImageVideoFeature.ts +124 -0
- package/src/features/shared/index.ts +6 -0
- package/src/infrastructure/utils/index.ts +1 -0
- package/src/infrastructure/utils/progress-calculator.util.ts +31 -0
- package/src/infrastructure/utils/result-validator.util.ts +0 -214
- package/src/infrastructure/utils/url-extractor.util.ts +209 -0
- package/src/presentation/hooks/flow-state.utils.ts +101 -0
- package/src/presentation/hooks/useGenerationFlow.ts +47 -178
- package/src/presentation/types/flow-config.types.ts +5 -99
- package/src/presentation/types/flow-default-configs.ts +106 -0
- package/src/domains/creations/presentation/hooks/useStatusFilter.ts +0 -54
- package/src/features/replace-background/domain/entities/background.types.ts +0 -77
- package/src/features/replace-background/domain/entities/component.types.ts +0 -87
- package/src/features/replace-background/domain/entities/config.types.ts +0 -41
- package/src/features/replace-background/domain/entities/index.ts +0 -30
- package/src/features/replace-background/infrastructure/constants/index.ts +0 -5
- package/src/features/replace-background/infrastructure/constants/prompts.constants.ts +0 -15
- package/src/features/replace-background/infrastructure/index.ts +0 -5
- package/src/features/replace-background/presentation/components/BackgroundFeature.tsx +0 -143
- package/src/features/replace-background/presentation/components/ComparisonSlider.tsx +0 -187
- package/src/features/replace-background/presentation/components/ErrorDisplay.tsx +0 -60
- package/src/features/replace-background/presentation/components/FeatureHeader.tsx +0 -80
- package/src/features/replace-background/presentation/components/GenerateButton.tsx +0 -85
- package/src/features/replace-background/presentation/components/ImagePicker.tsx +0 -136
- package/src/features/replace-background/presentation/components/ModeSelector.tsx +0 -78
- package/src/features/replace-background/presentation/components/PromptInput.tsx +0 -142
- package/src/features/replace-background/presentation/components/ResultDisplay.tsx +0 -122
- package/src/features/replace-background/presentation/hooks/useBackgroundFeature.ts +0 -119
package/package.json
CHANGED
|
@@ -6,6 +6,6 @@ export { useCreations } from "./useCreations";
|
|
|
6
6
|
export { useDeleteCreation } from "./useDeleteCreation";
|
|
7
7
|
export { useCreationsFilter } from "./useCreationsFilter";
|
|
8
8
|
export { useAdvancedFilter } from "./useAdvancedFilter";
|
|
9
|
-
export { useStatusFilter } from "./
|
|
10
|
-
export {
|
|
9
|
+
export { useFilter, useStatusFilter, useMediaFilter } from "./useFilter";
|
|
10
|
+
export type { UseFilterProps, UseFilterReturn } from "./useFilter";
|
|
11
11
|
export { useGalleryFilters } from "./useGalleryFilters";
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* SOLID: Single Responsibility - Only handles
|
|
2
|
+
* useFilter Hook
|
|
3
|
+
* Generic filter state management for any filter type
|
|
4
|
+
* SOLID: Single Responsibility - Only handles filter state
|
|
5
|
+
* DRY: Replaces duplicate useMediaFilter and useStatusFilter
|
|
5
6
|
*/
|
|
6
7
|
|
|
7
8
|
import { useState, useCallback, useMemo } from "react";
|
|
8
9
|
import type { FilterOption } from "../../domain/types/creation-filter";
|
|
9
10
|
|
|
10
|
-
interface
|
|
11
|
+
export interface UseFilterProps {
|
|
11
12
|
readonly options: FilterOption[];
|
|
12
13
|
readonly t: (key: string) => string;
|
|
13
14
|
readonly defaultId?: string;
|
|
14
15
|
}
|
|
15
16
|
|
|
16
|
-
interface
|
|
17
|
+
export interface UseFilterReturn {
|
|
17
18
|
readonly selectedId: string;
|
|
18
19
|
readonly filterOptions: FilterOption[];
|
|
19
20
|
readonly hasActiveFilter: boolean;
|
|
@@ -21,11 +22,11 @@ interface UseMediaFilterReturn {
|
|
|
21
22
|
readonly clearFilter: () => void;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
export function
|
|
25
|
+
export function useFilter({
|
|
25
26
|
options,
|
|
26
27
|
t,
|
|
27
28
|
defaultId = "all"
|
|
28
|
-
}:
|
|
29
|
+
}: UseFilterProps): UseFilterReturn {
|
|
29
30
|
const [selectedId, setSelectedId] = useState(defaultId);
|
|
30
31
|
|
|
31
32
|
const filterOptions = useMemo(() =>
|
|
@@ -52,3 +53,7 @@ export function useMediaFilter({
|
|
|
52
53
|
clearFilter
|
|
53
54
|
};
|
|
54
55
|
}
|
|
56
|
+
|
|
57
|
+
// Backward compatibility aliases
|
|
58
|
+
export const useMediaFilter = useFilter;
|
|
59
|
+
export const useStatusFilter = useFilter;
|
|
@@ -7,8 +7,7 @@
|
|
|
7
7
|
import { useState, useCallback } from "react";
|
|
8
8
|
import type { Creation } from "../../domain/entities/Creation";
|
|
9
9
|
import type { FilterOption } from "../../domain/types/creation-filter";
|
|
10
|
-
import {
|
|
11
|
-
import { useMediaFilter } from "./useMediaFilter";
|
|
10
|
+
import { useFilter } from "./useFilter";
|
|
12
11
|
import { useCreationsFilter } from "./useCreationsFilter";
|
|
13
12
|
|
|
14
13
|
interface UseGalleryFiltersProps {
|
|
@@ -24,8 +23,8 @@ interface UseGalleryFiltersReturn {
|
|
|
24
23
|
readonly activeFiltersCount: number;
|
|
25
24
|
readonly statusFilterVisible: boolean;
|
|
26
25
|
readonly mediaFilterVisible: boolean;
|
|
27
|
-
readonly statusFilter: ReturnType<typeof
|
|
28
|
-
readonly mediaFilter: ReturnType<typeof
|
|
26
|
+
readonly statusFilter: ReturnType<typeof useFilter>;
|
|
27
|
+
readonly mediaFilter: ReturnType<typeof useFilter>;
|
|
29
28
|
readonly openStatusFilter: () => void;
|
|
30
29
|
readonly closeStatusFilter: () => void;
|
|
31
30
|
readonly openMediaFilter: () => void;
|
|
@@ -42,8 +41,8 @@ export function useGalleryFilters({
|
|
|
42
41
|
const [statusFilterVisible, setStatusFilterVisible] = useState(false);
|
|
43
42
|
const [mediaFilterVisible, setMediaFilterVisible] = useState(false);
|
|
44
43
|
|
|
45
|
-
const statusFilter =
|
|
46
|
-
const mediaFilter =
|
|
44
|
+
const statusFilter = useFilter({ options: statusOptions, t });
|
|
45
|
+
const mediaFilter = useFilter({ options: mediaOptions, t });
|
|
47
46
|
|
|
48
47
|
const { filtered, isFiltered, activeFiltersCount } = useCreationsFilter({
|
|
49
48
|
creations,
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* useAIHugFeature Hook
|
|
3
|
-
*
|
|
3
|
+
* Thin wrapper around useDualImageVideoFeature for ai-hug feature
|
|
4
|
+
* DRY: Uses shared base hook for common logic
|
|
4
5
|
*/
|
|
5
6
|
|
|
6
|
-
import {
|
|
7
|
-
import { executeVideoFeature } from "../../../../infrastructure/services";
|
|
7
|
+
import { useDualImageVideoFeature } from "../../../shared/dual-image-video";
|
|
8
8
|
import type {
|
|
9
|
-
AIHugFeatureState,
|
|
10
9
|
AIHugFeatureConfig,
|
|
10
|
+
AIHugFeatureState,
|
|
11
11
|
} from "../../domain/types";
|
|
12
12
|
|
|
13
13
|
export interface UseAIHugFeatureProps {
|
|
@@ -25,113 +25,9 @@ export interface UseAIHugFeatureReturn extends AIHugFeatureState {
|
|
|
25
25
|
reset: () => void;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
progress: 0,
|
|
34
|
-
error: null,
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export function useAIHugFeature(
|
|
38
|
-
props: UseAIHugFeatureProps,
|
|
39
|
-
): UseAIHugFeatureReturn {
|
|
40
|
-
const { config, onSelectSourceImage, onSelectTargetImage, onSaveVideo } = props;
|
|
41
|
-
const [state, setState] = useState<AIHugFeatureState>(initialState);
|
|
42
|
-
|
|
43
|
-
const selectSourceImage = useCallback(async () => {
|
|
44
|
-
try {
|
|
45
|
-
const uri = await onSelectSourceImage();
|
|
46
|
-
if (uri) {
|
|
47
|
-
setState((prev) => ({ ...prev, sourceImageUri: uri, error: null }));
|
|
48
|
-
config.onSourceImageSelect?.(uri);
|
|
49
|
-
}
|
|
50
|
-
} catch (error) {
|
|
51
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
52
|
-
setState((prev) => ({ ...prev, error: message }));
|
|
53
|
-
}
|
|
54
|
-
}, [onSelectSourceImage, config]);
|
|
55
|
-
|
|
56
|
-
const selectTargetImage = useCallback(async () => {
|
|
57
|
-
try {
|
|
58
|
-
const uri = await onSelectTargetImage();
|
|
59
|
-
if (uri) {
|
|
60
|
-
setState((prev) => ({ ...prev, targetImageUri: uri, error: null }));
|
|
61
|
-
config.onTargetImageSelect?.(uri);
|
|
62
|
-
}
|
|
63
|
-
} catch (error) {
|
|
64
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
65
|
-
setState((prev) => ({ ...prev, error: message }));
|
|
66
|
-
}
|
|
67
|
-
}, [onSelectTargetImage, config]);
|
|
68
|
-
|
|
69
|
-
const handleProgress = useCallback((progress: number) => {
|
|
70
|
-
setState((prev) => ({ ...prev, progress }));
|
|
71
|
-
}, []);
|
|
72
|
-
|
|
73
|
-
const process = useCallback(async () => {
|
|
74
|
-
if (!state.sourceImageUri || !state.targetImageUri) return;
|
|
75
|
-
|
|
76
|
-
setState((prev) => ({
|
|
77
|
-
...prev,
|
|
78
|
-
isProcessing: true,
|
|
79
|
-
progress: 0,
|
|
80
|
-
error: null,
|
|
81
|
-
}));
|
|
82
|
-
|
|
83
|
-
config.onProcessingStart?.();
|
|
84
|
-
|
|
85
|
-
const sourceImageBase64 = await config.prepareImage(state.sourceImageUri);
|
|
86
|
-
const targetImageBase64 = await config.prepareImage(state.targetImageUri);
|
|
87
|
-
|
|
88
|
-
const result = await executeVideoFeature(
|
|
89
|
-
"ai-hug",
|
|
90
|
-
{ sourceImageBase64, targetImageBase64 },
|
|
91
|
-
{ extractResult: config.extractResult, onProgress: handleProgress },
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
if (result.success && result.videoUrl) {
|
|
95
|
-
setState((prev) => ({
|
|
96
|
-
...prev,
|
|
97
|
-
isProcessing: false,
|
|
98
|
-
processedVideoUrl: result.videoUrl!,
|
|
99
|
-
progress: 100,
|
|
100
|
-
}));
|
|
101
|
-
config.onProcessingComplete?.({ success: true, videoUrl: result.videoUrl });
|
|
102
|
-
} else {
|
|
103
|
-
const errorMessage = result.error || "Processing failed";
|
|
104
|
-
setState((prev) => ({
|
|
105
|
-
...prev,
|
|
106
|
-
isProcessing: false,
|
|
107
|
-
error: errorMessage,
|
|
108
|
-
progress: 0,
|
|
109
|
-
}));
|
|
110
|
-
config.onError?.(errorMessage);
|
|
111
|
-
}
|
|
112
|
-
}, [state.sourceImageUri, state.targetImageUri, config, handleProgress]);
|
|
113
|
-
|
|
114
|
-
const save = useCallback(async () => {
|
|
115
|
-
if (!state.processedVideoUrl) return;
|
|
116
|
-
|
|
117
|
-
try {
|
|
118
|
-
await onSaveVideo(state.processedVideoUrl);
|
|
119
|
-
} catch (error) {
|
|
120
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
121
|
-
setState((prev) => ({ ...prev, error: message }));
|
|
122
|
-
}
|
|
123
|
-
}, [state.processedVideoUrl, onSaveVideo]);
|
|
124
|
-
|
|
125
|
-
const reset = useCallback(() => {
|
|
126
|
-
setState(initialState);
|
|
127
|
-
}, []);
|
|
128
|
-
|
|
129
|
-
return {
|
|
130
|
-
...state,
|
|
131
|
-
selectSourceImage,
|
|
132
|
-
selectTargetImage,
|
|
133
|
-
process,
|
|
134
|
-
save,
|
|
135
|
-
reset,
|
|
136
|
-
};
|
|
28
|
+
export function useAIHugFeature(props: UseAIHugFeatureProps): UseAIHugFeatureReturn {
|
|
29
|
+
return useDualImageVideoFeature({
|
|
30
|
+
featureType: "ai-hug",
|
|
31
|
+
...props,
|
|
32
|
+
});
|
|
137
33
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* useAIKissFeature Hook
|
|
3
|
-
*
|
|
3
|
+
* Thin wrapper around useDualImageVideoFeature for ai-kiss feature
|
|
4
|
+
* DRY: Uses shared base hook for common logic
|
|
4
5
|
*/
|
|
5
6
|
|
|
6
|
-
import {
|
|
7
|
-
import { executeVideoFeature } from "../../../../infrastructure/services";
|
|
7
|
+
import { useDualImageVideoFeature } from "../../../shared/dual-image-video";
|
|
8
8
|
import type {
|
|
9
|
-
AIKissFeatureState,
|
|
10
9
|
AIKissFeatureConfig,
|
|
10
|
+
AIKissFeatureState,
|
|
11
11
|
} from "../../domain/types";
|
|
12
12
|
|
|
13
13
|
export interface UseAIKissFeatureProps {
|
|
@@ -25,113 +25,9 @@ export interface UseAIKissFeatureReturn extends AIKissFeatureState {
|
|
|
25
25
|
reset: () => void;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
progress: 0,
|
|
34
|
-
error: null,
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export function useAIKissFeature(
|
|
38
|
-
props: UseAIKissFeatureProps,
|
|
39
|
-
): UseAIKissFeatureReturn {
|
|
40
|
-
const { config, onSelectSourceImage, onSelectTargetImage, onSaveVideo } = props;
|
|
41
|
-
const [state, setState] = useState<AIKissFeatureState>(initialState);
|
|
42
|
-
|
|
43
|
-
const selectSourceImage = useCallback(async () => {
|
|
44
|
-
try {
|
|
45
|
-
const uri = await onSelectSourceImage();
|
|
46
|
-
if (uri) {
|
|
47
|
-
setState((prev) => ({ ...prev, sourceImageUri: uri, error: null }));
|
|
48
|
-
config.onSourceImageSelect?.(uri);
|
|
49
|
-
}
|
|
50
|
-
} catch (error) {
|
|
51
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
52
|
-
setState((prev) => ({ ...prev, error: message }));
|
|
53
|
-
}
|
|
54
|
-
}, [onSelectSourceImage, config]);
|
|
55
|
-
|
|
56
|
-
const selectTargetImage = useCallback(async () => {
|
|
57
|
-
try {
|
|
58
|
-
const uri = await onSelectTargetImage();
|
|
59
|
-
if (uri) {
|
|
60
|
-
setState((prev) => ({ ...prev, targetImageUri: uri, error: null }));
|
|
61
|
-
config.onTargetImageSelect?.(uri);
|
|
62
|
-
}
|
|
63
|
-
} catch (error) {
|
|
64
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
65
|
-
setState((prev) => ({ ...prev, error: message }));
|
|
66
|
-
}
|
|
67
|
-
}, [onSelectTargetImage, config]);
|
|
68
|
-
|
|
69
|
-
const handleProgress = useCallback((progress: number) => {
|
|
70
|
-
setState((prev) => ({ ...prev, progress }));
|
|
71
|
-
}, []);
|
|
72
|
-
|
|
73
|
-
const process = useCallback(async () => {
|
|
74
|
-
if (!state.sourceImageUri || !state.targetImageUri) return;
|
|
75
|
-
|
|
76
|
-
setState((prev) => ({
|
|
77
|
-
...prev,
|
|
78
|
-
isProcessing: true,
|
|
79
|
-
progress: 0,
|
|
80
|
-
error: null,
|
|
81
|
-
}));
|
|
82
|
-
|
|
83
|
-
config.onProcessingStart?.();
|
|
84
|
-
|
|
85
|
-
const sourceImageBase64 = await config.prepareImage(state.sourceImageUri);
|
|
86
|
-
const targetImageBase64 = await config.prepareImage(state.targetImageUri);
|
|
87
|
-
|
|
88
|
-
const result = await executeVideoFeature(
|
|
89
|
-
"ai-kiss",
|
|
90
|
-
{ sourceImageBase64, targetImageBase64 },
|
|
91
|
-
{ extractResult: config.extractResult, onProgress: handleProgress },
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
if (result.success && result.videoUrl) {
|
|
95
|
-
setState((prev) => ({
|
|
96
|
-
...prev,
|
|
97
|
-
isProcessing: false,
|
|
98
|
-
processedVideoUrl: result.videoUrl!,
|
|
99
|
-
progress: 100,
|
|
100
|
-
}));
|
|
101
|
-
config.onProcessingComplete?.({ success: true, videoUrl: result.videoUrl });
|
|
102
|
-
} else {
|
|
103
|
-
const errorMessage = result.error || "Processing failed";
|
|
104
|
-
setState((prev) => ({
|
|
105
|
-
...prev,
|
|
106
|
-
isProcessing: false,
|
|
107
|
-
error: errorMessage,
|
|
108
|
-
progress: 0,
|
|
109
|
-
}));
|
|
110
|
-
config.onError?.(errorMessage);
|
|
111
|
-
}
|
|
112
|
-
}, [state.sourceImageUri, state.targetImageUri, config, handleProgress]);
|
|
113
|
-
|
|
114
|
-
const save = useCallback(async () => {
|
|
115
|
-
if (!state.processedVideoUrl) return;
|
|
116
|
-
|
|
117
|
-
try {
|
|
118
|
-
await onSaveVideo(state.processedVideoUrl);
|
|
119
|
-
} catch (error) {
|
|
120
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
121
|
-
setState((prev) => ({ ...prev, error: message }));
|
|
122
|
-
}
|
|
123
|
-
}, [state.processedVideoUrl, onSaveVideo]);
|
|
124
|
-
|
|
125
|
-
const reset = useCallback(() => {
|
|
126
|
-
setState(initialState);
|
|
127
|
-
}, []);
|
|
128
|
-
|
|
129
|
-
return {
|
|
130
|
-
...state,
|
|
131
|
-
selectSourceImage,
|
|
132
|
-
selectTargetImage,
|
|
133
|
-
process,
|
|
134
|
-
save,
|
|
135
|
-
reset,
|
|
136
|
-
};
|
|
28
|
+
export function useAIKissFeature(props: UseAIKissFeatureProps): UseAIKissFeatureReturn {
|
|
29
|
+
return useDualImageVideoFeature({
|
|
30
|
+
featureType: "ai-kiss",
|
|
31
|
+
...props,
|
|
32
|
+
});
|
|
137
33
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Image-to-Video Executor
|
|
3
3
|
* Provider-agnostic image-to-video execution using active AI provider
|
|
4
|
-
*
|
|
4
|
+
* Uses progress mapper for consistent progress reporting
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { providerRegistry } from "../../../../infrastructure/services";
|
|
8
|
+
import { getProgressFromJobStatus } from "../../../../infrastructure/utils";
|
|
8
9
|
import type {
|
|
9
10
|
ImageToVideoRequest,
|
|
10
11
|
ImageToVideoResult,
|
|
@@ -103,14 +104,9 @@ export async function executeImageToVideo(
|
|
|
103
104
|
// eslint-disable-next-line no-console
|
|
104
105
|
console.log("[ImageToVideoExecutor] Queue status:", status.status, "position:", status.queuePosition);
|
|
105
106
|
}
|
|
106
|
-
// Map
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
} else if (status.status === "IN_PROGRESS") {
|
|
110
|
-
onProgress?.(50);
|
|
111
|
-
} else if (status.status === "COMPLETED") {
|
|
112
|
-
onProgress?.(90);
|
|
113
|
-
}
|
|
107
|
+
// Map provider status to progress using centralized mapper
|
|
108
|
+
const progress = getProgressFromJobStatus(status.status);
|
|
109
|
+
onProgress?.(progress);
|
|
114
110
|
},
|
|
115
111
|
timeoutMs: 300000, // 5 minutes timeout for video generation
|
|
116
112
|
});
|
|
@@ -63,27 +63,32 @@ export function useImageToVideoForm(
|
|
|
63
63
|
|
|
64
64
|
const handleSelectImages = useCallback(async () => {
|
|
65
65
|
if (__DEV__) {
|
|
66
|
+
// eslint-disable-next-line no-console
|
|
66
67
|
console.log("[useImageToVideoForm] handleSelectImages called");
|
|
67
68
|
}
|
|
68
69
|
if (callbacks.onSelectImages) {
|
|
69
70
|
try {
|
|
70
71
|
const images = await callbacks.onSelectImages();
|
|
71
72
|
if (__DEV__) {
|
|
73
|
+
// eslint-disable-next-line no-console
|
|
72
74
|
console.log("[useImageToVideoForm] Images selected:", images.length);
|
|
73
75
|
}
|
|
74
76
|
if (images.length > 0) {
|
|
75
77
|
actions.addImages(images);
|
|
76
78
|
if (__DEV__) {
|
|
79
|
+
// eslint-disable-next-line no-console
|
|
77
80
|
console.log("[useImageToVideoForm] Images added to state");
|
|
78
81
|
}
|
|
79
82
|
}
|
|
80
83
|
} catch (error) {
|
|
81
84
|
if (__DEV__) {
|
|
85
|
+
// eslint-disable-next-line no-console
|
|
82
86
|
console.error("[useImageToVideoForm] Error selecting images:", error);
|
|
83
87
|
}
|
|
84
88
|
}
|
|
85
89
|
} else {
|
|
86
90
|
if (__DEV__) {
|
|
91
|
+
// eslint-disable-next-line no-console
|
|
87
92
|
console.warn("[useImageToVideoForm] No onSelectImages callback provided");
|
|
88
93
|
}
|
|
89
94
|
}
|
|
@@ -1,31 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Replace Background Feature
|
|
3
|
-
* AI-powered background replacement
|
|
3
|
+
* AI-powered background replacement feature for React Native
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
// Domain Types
|
|
7
|
-
export type {
|
|
8
|
-
BackgroundProcessRequest,
|
|
9
|
-
BackgroundProcessResult,
|
|
10
|
-
BackgroundFeatureState,
|
|
11
|
-
SamplePrompt,
|
|
12
|
-
StudioMode,
|
|
13
|
-
StudioModeConfig,
|
|
14
|
-
ComparisonState,
|
|
15
|
-
ImagePickerProps,
|
|
16
|
-
PromptInputProps,
|
|
17
|
-
GenerateButtonProps,
|
|
18
|
-
ResultDisplayProps,
|
|
19
|
-
ErrorDisplayProps,
|
|
20
|
-
FeatureHeaderProps,
|
|
21
|
-
ModeSelectorProps,
|
|
22
|
-
ComparisonSliderProps,
|
|
23
|
-
ProcessRequestParams,
|
|
24
|
-
BackgroundFeatureConfig,
|
|
25
|
-
UseBackgroundFeatureConfig,
|
|
26
|
-
} from "./domain/entities";
|
|
27
|
-
|
|
28
|
-
// Domain Types - Provider-Agnostic
|
|
6
|
+
// Domain Types
|
|
29
7
|
export type {
|
|
30
8
|
ReplaceBackgroundMode,
|
|
31
9
|
ReplaceBackgroundOptions,
|
|
@@ -37,36 +15,13 @@ export type {
|
|
|
37
15
|
ReplaceBackgroundResultExtractor,
|
|
38
16
|
} from "./domain/types";
|
|
39
17
|
|
|
40
|
-
// Constants
|
|
41
|
-
export { DEFAULT_SAMPLE_PROMPTS } from "./infrastructure/constants";
|
|
42
|
-
|
|
43
18
|
// Presentation Components
|
|
44
|
-
export {
|
|
45
|
-
|
|
46
|
-
ReplaceBackgroundFeature,
|
|
47
|
-
ImagePicker,
|
|
48
|
-
PromptInput,
|
|
49
|
-
GenerateButton,
|
|
50
|
-
ResultDisplay,
|
|
51
|
-
ErrorDisplay,
|
|
52
|
-
FeatureHeader,
|
|
53
|
-
ComparisonSlider,
|
|
54
|
-
ModeSelector,
|
|
55
|
-
} from "./presentation/components";
|
|
56
|
-
|
|
57
|
-
export type {
|
|
58
|
-
BackgroundFeatureProps,
|
|
59
|
-
ReplaceBackgroundFeatureProps,
|
|
60
|
-
} from "./presentation/components";
|
|
19
|
+
export { ReplaceBackgroundFeature } from "./presentation/components";
|
|
20
|
+
export type { ReplaceBackgroundFeatureProps } from "./presentation/components";
|
|
61
21
|
|
|
62
22
|
// Presentation Hooks
|
|
63
|
-
export {
|
|
64
|
-
useBackgroundFeature,
|
|
65
|
-
useReplaceBackgroundFeature,
|
|
66
|
-
} from "./presentation/hooks";
|
|
67
|
-
|
|
23
|
+
export { useReplaceBackgroundFeature } from "./presentation/hooks";
|
|
68
24
|
export type {
|
|
69
|
-
UseBackgroundFeatureReturn,
|
|
70
25
|
UseReplaceBackgroundFeatureProps,
|
|
71
26
|
UseReplaceBackgroundFeatureReturn,
|
|
72
27
|
} from "./presentation/hooks";
|
|
@@ -2,17 +2,5 @@
|
|
|
2
2
|
* Presentation Components Export
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
export { BackgroundFeature } from "./BackgroundFeature";
|
|
6
|
-
export type { BackgroundFeatureProps } from "./BackgroundFeature";
|
|
7
|
-
|
|
8
5
|
export { ReplaceBackgroundFeature } from "./ReplaceBackgroundFeature";
|
|
9
6
|
export type { ReplaceBackgroundFeatureProps } from "./ReplaceBackgroundFeature";
|
|
10
|
-
|
|
11
|
-
export { ImagePicker } from "./ImagePicker";
|
|
12
|
-
export { PromptInput } from "./PromptInput";
|
|
13
|
-
export { GenerateButton } from "./GenerateButton";
|
|
14
|
-
export { ResultDisplay } from "./ResultDisplay";
|
|
15
|
-
export { ErrorDisplay } from "./ErrorDisplay";
|
|
16
|
-
export { FeatureHeader } from "./FeatureHeader";
|
|
17
|
-
export { ComparisonSlider } from "./ComparisonSlider";
|
|
18
|
-
export { ModeSelector } from "./ModeSelector";
|
|
@@ -2,9 +2,6 @@
|
|
|
2
2
|
* Presentation Hooks Export
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
export { useBackgroundFeature } from "./useBackgroundFeature";
|
|
6
|
-
export type { UseBackgroundFeatureReturn } from "./useBackgroundFeature";
|
|
7
|
-
|
|
8
5
|
export { useReplaceBackgroundFeature } from "./useReplaceBackgroundFeature";
|
|
9
6
|
export type {
|
|
10
7
|
UseReplaceBackgroundFeatureProps,
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dual Image Video Feature Types
|
|
3
|
+
* Shared types for video features that take two images (ai-hug, ai-kiss, etc.)
|
|
4
|
+
* DRY: Consolidates common types from ai-hug and ai-kiss features
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { VideoFeatureType } from "../../../../../domain/interfaces/ai-provider.interface";
|
|
8
|
+
|
|
9
|
+
export interface DualImageVideoFeatureState {
|
|
10
|
+
sourceImageUri: string | null;
|
|
11
|
+
targetImageUri: string | null;
|
|
12
|
+
processedVideoUrl: string | null;
|
|
13
|
+
isProcessing: boolean;
|
|
14
|
+
progress: number;
|
|
15
|
+
error: string | null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface DualImageVideoResult {
|
|
19
|
+
success: boolean;
|
|
20
|
+
videoUrl?: string;
|
|
21
|
+
error?: string;
|
|
22
|
+
requestId?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type DualImageVideoResultExtractor = (result: unknown) => string | undefined;
|
|
26
|
+
|
|
27
|
+
export interface DualImageVideoFeatureConfig {
|
|
28
|
+
creditCost?: number;
|
|
29
|
+
extractResult?: DualImageVideoResultExtractor;
|
|
30
|
+
prepareImage: (imageUri: string) => Promise<string>;
|
|
31
|
+
onSourceImageSelect?: (uri: string) => void;
|
|
32
|
+
onTargetImageSelect?: (uri: string) => void;
|
|
33
|
+
onProcessingStart?: () => void;
|
|
34
|
+
onProcessingComplete?: (result: DualImageVideoResult) => void;
|
|
35
|
+
onError?: (error: string) => void;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface DualImageVideoTranslations {
|
|
39
|
+
sourceUploadTitle: string;
|
|
40
|
+
sourceUploadSubtitle: string;
|
|
41
|
+
targetUploadTitle: string;
|
|
42
|
+
targetUploadSubtitle: string;
|
|
43
|
+
uploadChange: string;
|
|
44
|
+
uploadAnalyzing: string;
|
|
45
|
+
description: string;
|
|
46
|
+
processingText: string;
|
|
47
|
+
processButtonText: string;
|
|
48
|
+
successText: string;
|
|
49
|
+
saveButtonText: string;
|
|
50
|
+
tryAnotherText: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface UseDualImageVideoFeatureProps {
|
|
54
|
+
featureType: VideoFeatureType;
|
|
55
|
+
config: DualImageVideoFeatureConfig;
|
|
56
|
+
onSelectSourceImage: () => Promise<string | null>;
|
|
57
|
+
onSelectTargetImage: () => Promise<string | null>;
|
|
58
|
+
onSaveVideo: (videoUrl: string) => Promise<void>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface UseDualImageVideoFeatureReturn extends DualImageVideoFeatureState {
|
|
62
|
+
selectSourceImage: () => Promise<void>;
|
|
63
|
+
selectTargetImage: () => Promise<void>;
|
|
64
|
+
process: () => Promise<void>;
|
|
65
|
+
save: () => Promise<void>;
|
|
66
|
+
reset: () => void;
|
|
67
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dual Image Video Domain Types
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export type {
|
|
6
|
+
DualImageVideoFeatureState,
|
|
7
|
+
DualImageVideoResult,
|
|
8
|
+
DualImageVideoResultExtractor,
|
|
9
|
+
DualImageVideoFeatureConfig,
|
|
10
|
+
DualImageVideoTranslations,
|
|
11
|
+
UseDualImageVideoFeatureProps,
|
|
12
|
+
UseDualImageVideoFeatureReturn,
|
|
13
|
+
} from "./dual-image-video.types";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dual Image Video Feature (Shared)
|
|
3
|
+
* Base infrastructure for video features using two source images
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export type {
|
|
7
|
+
DualImageVideoFeatureState,
|
|
8
|
+
DualImageVideoResult,
|
|
9
|
+
DualImageVideoResultExtractor,
|
|
10
|
+
DualImageVideoFeatureConfig,
|
|
11
|
+
DualImageVideoTranslations,
|
|
12
|
+
UseDualImageVideoFeatureProps,
|
|
13
|
+
UseDualImageVideoFeatureReturn,
|
|
14
|
+
} from "./domain/types";
|
|
15
|
+
|
|
16
|
+
export { useDualImageVideoFeature } from "./presentation/hooks";
|