@umituz/react-native-ai-generation-content 1.17.0 → 1.17.2
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 +13 -14
- package/src/domains/creations/domain/entities/Creation.ts +33 -2
- package/src/domains/creations/domain/entities/index.ts +1 -1
- package/src/domains/creations/domain/types/creation-categories.ts +133 -0
- package/src/domains/creations/domain/types/creation-filter.ts +131 -0
- package/src/domains/creations/domain/types/creation-types.ts +63 -0
- package/src/domains/creations/domain/types/index.ts +44 -0
- package/src/domains/creations/domain/utils/creation-helpers.ts +134 -0
- package/src/domains/creations/domain/utils/index.ts +8 -0
- package/src/domains/creations/domain/utils/preview-helpers.ts +84 -0
- package/src/domains/creations/domain/utils/status-helpers.ts +90 -0
- package/src/domains/creations/index.ts +95 -21
- package/src/domains/creations/infrastructure/repositories/CreationsRepository.ts +14 -1
- package/src/domains/creations/presentation/components/CreationActions.tsx +120 -0
- package/src/domains/creations/presentation/components/CreationBadges.tsx +111 -0
- package/src/domains/creations/presentation/components/CreationCard.tsx +201 -102
- package/src/domains/creations/presentation/components/CreationPreview.tsx +117 -0
- package/src/domains/creations/presentation/components/CreationsFilterBar.tsx +254 -0
- package/src/domains/creations/presentation/components/CreationsGrid.tsx +121 -68
- package/src/domains/creations/presentation/components/CreationsHomeCard.tsx +1 -1
- package/src/domains/creations/presentation/components/index.ts +23 -3
- package/src/domains/creations/presentation/hooks/index.ts +1 -0
- package/src/domains/creations/presentation/hooks/useAdvancedFilter.ts +261 -0
- package/src/domains/creations/presentation/screens/CreationsGalleryScreen.tsx +8 -6
- package/src/domains/face-detection/infrastructure/validators/faceValidator.ts +1 -1
- package/src/domains/prompts/infrastructure/services/PromptGenerationService.ts +1 -1
- package/src/domains/prompts/presentation/hooks/useFaceSwap.ts +2 -2
- package/src/domains/prompts/presentation/hooks/usePromptGeneration.ts +4 -4
- package/src/features/ai-hug/domain/index.ts +5 -0
- package/src/features/ai-hug/domain/types/ai-hug.types.ts +72 -0
- package/src/features/ai-hug/domain/types/index.ts +14 -0
- package/src/features/ai-hug/index.ts +27 -0
- package/src/features/ai-hug/infrastructure/index.ts +5 -0
- package/src/features/ai-hug/infrastructure/services/ai-hug-executor.ts +96 -0
- package/src/features/ai-hug/infrastructure/services/index.ts +6 -0
- package/src/features/ai-hug/presentation/hooks/index.ts +9 -0
- package/src/features/ai-hug/presentation/hooks/useAIHugFeature.ts +157 -0
- package/src/features/ai-hug/presentation/index.ts +5 -0
- package/src/features/ai-kiss/domain/index.ts +5 -0
- package/src/features/ai-kiss/domain/types/ai-kiss.types.ts +72 -0
- package/src/features/ai-kiss/domain/types/index.ts +14 -0
- package/src/features/ai-kiss/index.ts +27 -0
- package/src/features/ai-kiss/infrastructure/index.ts +5 -0
- package/src/features/ai-kiss/infrastructure/services/ai-kiss-executor.ts +96 -0
- package/src/features/ai-kiss/infrastructure/services/index.ts +6 -0
- package/src/features/ai-kiss/presentation/hooks/index.ts +9 -0
- package/src/features/ai-kiss/presentation/hooks/useAIKissFeature.ts +157 -0
- package/src/features/ai-kiss/presentation/index.ts +5 -0
- package/src/features/anime-selfie/domain/index.ts +5 -0
- package/src/features/anime-selfie/domain/types/anime-selfie.types.ts +72 -0
- package/src/features/anime-selfie/domain/types/index.ts +15 -0
- package/src/features/anime-selfie/index.ts +28 -0
- package/src/features/anime-selfie/infrastructure/index.ts +5 -0
- package/src/features/anime-selfie/infrastructure/services/anime-selfie-executor.ts +95 -0
- package/src/features/anime-selfie/infrastructure/services/index.ts +6 -0
- package/src/features/anime-selfie/presentation/hooks/index.ts +9 -0
- package/src/features/anime-selfie/presentation/hooks/useAnimeSelfieFeature.ts +138 -0
- package/src/features/anime-selfie/presentation/index.ts +5 -0
- package/src/features/background/domain/types/index.ts +15 -0
- package/src/features/background/domain/types/replace-background.types.ts +82 -0
- package/src/features/background/index.ts +31 -3
- package/src/features/background/infrastructure/index.ts +5 -0
- package/src/features/background/infrastructure/services/index.ts +6 -0
- package/src/features/background/infrastructure/services/replace-background-executor.ts +95 -0
- package/src/features/background/presentation/hooks/index.ts +6 -1
- package/src/features/background/presentation/hooks/useReplaceBackgroundFeature.ts +160 -0
- package/src/features/face-swap/domain/index.ts +5 -0
- package/src/features/face-swap/domain/types/face-swap.types.ts +72 -0
- package/src/features/face-swap/domain/types/index.ts +14 -0
- package/src/features/face-swap/index.ts +27 -1
- package/src/features/face-swap/infrastructure/index.ts +5 -0
- package/src/features/face-swap/infrastructure/services/face-swap-executor.ts +96 -0
- package/src/features/face-swap/infrastructure/services/index.ts +6 -0
- package/src/features/face-swap/presentation/hooks/index.ts +9 -0
- package/src/features/face-swap/presentation/hooks/useFaceSwapFeature.ts +157 -0
- package/src/features/face-swap/presentation/index.ts +5 -0
- package/src/features/image-to-video/domain/index.ts +1 -0
- package/src/features/image-to-video/domain/types/image-to-video.types.ts +71 -0
- package/src/features/image-to-video/domain/types/index.ts +10 -0
- package/src/features/image-to-video/index.ts +27 -0
- package/src/features/image-to-video/infrastructure/index.ts +1 -0
- package/src/features/image-to-video/infrastructure/services/image-to-video-executor.ts +112 -0
- package/src/features/image-to-video/infrastructure/services/index.ts +5 -0
- package/src/features/image-to-video/presentation/hooks/index.ts +5 -0
- package/src/features/image-to-video/presentation/hooks/useImageToVideoFeature.ts +121 -0
- package/src/features/image-to-video/presentation/index.ts +1 -0
- package/src/features/photo-restoration/domain/types/index.ts +2 -5
- package/src/features/photo-restoration/domain/types/photo-restore.types.ts +14 -0
- package/src/features/photo-restoration/index.ts +3 -8
- package/src/features/photo-restoration/infrastructure/services/index.ts +1 -6
- package/src/features/photo-restoration/infrastructure/services/photo-restore-executor.ts +64 -30
- package/src/features/photo-restoration/presentation/hooks/usePhotoRestoreFeature.ts +11 -6
- package/src/features/remove-background/domain/index.ts +5 -0
- package/src/features/remove-background/domain/types/index.ts +14 -0
- package/src/features/remove-background/domain/types/remove-background.types.ts +69 -0
- package/src/features/remove-background/index.ts +27 -0
- package/src/features/remove-background/infrastructure/index.ts +5 -0
- package/src/features/remove-background/infrastructure/services/index.ts +6 -0
- package/src/features/remove-background/infrastructure/services/remove-background-executor.ts +95 -0
- package/src/features/remove-background/presentation/hooks/index.ts +9 -0
- package/src/features/remove-background/presentation/hooks/useRemoveBackgroundFeature.ts +137 -0
- package/src/features/remove-background/presentation/index.ts +5 -0
- package/src/features/remove-object/domain/index.ts +5 -0
- package/src/features/remove-object/domain/types/index.ts +14 -0
- package/src/features/remove-object/domain/types/remove-object.types.ts +77 -0
- package/src/features/remove-object/index.ts +27 -0
- package/src/features/remove-object/infrastructure/index.ts +5 -0
- package/src/features/remove-object/infrastructure/services/index.ts +6 -0
- package/src/features/remove-object/infrastructure/services/remove-object-executor.ts +99 -0
- package/src/features/remove-object/presentation/hooks/index.ts +9 -0
- package/src/features/remove-object/presentation/hooks/useRemoveObjectFeature.ts +168 -0
- package/src/features/remove-object/presentation/index.ts +5 -0
- package/src/features/text-to-image/domain/index.ts +1 -0
- package/src/features/text-to-image/domain/types/index.ts +10 -0
- package/src/features/text-to-image/domain/types/text-to-image.types.ts +66 -0
- package/src/features/text-to-image/index.ts +27 -1
- package/src/features/text-to-image/infrastructure/index.ts +1 -0
- package/src/features/text-to-image/infrastructure/services/index.ts +5 -0
- package/src/features/text-to-image/infrastructure/services/text-to-image-executor.ts +113 -0
- package/src/features/text-to-image/presentation/hooks/index.ts +5 -0
- package/src/features/text-to-image/presentation/hooks/useTextToImageFeature.ts +111 -0
- package/src/features/text-to-image/presentation/index.ts +1 -0
- package/src/features/text-to-video/domain/index.ts +1 -0
- package/src/features/text-to-video/domain/types/index.ts +10 -0
- package/src/features/text-to-video/domain/types/text-to-video.types.ts +65 -0
- package/src/features/text-to-video/index.ts +27 -1
- package/src/features/text-to-video/infrastructure/index.ts +1 -0
- package/src/features/text-to-video/infrastructure/services/index.ts +5 -0
- package/src/features/text-to-video/infrastructure/services/text-to-video-executor.ts +108 -0
- package/src/features/text-to-video/presentation/hooks/index.ts +5 -0
- package/src/features/text-to-video/presentation/hooks/useTextToVideoFeature.ts +111 -0
- package/src/features/text-to-video/presentation/index.ts +1 -0
- package/src/features/text-to-voice/domain/index.ts +1 -0
- package/src/features/text-to-voice/domain/types/index.ts +10 -0
- package/src/features/text-to-voice/domain/types/text-to-voice.types.ts +65 -0
- package/src/features/text-to-voice/index.ts +27 -0
- package/src/features/text-to-voice/infrastructure/index.ts +1 -0
- package/src/features/text-to-voice/infrastructure/services/index.ts +5 -0
- package/src/features/text-to-voice/infrastructure/services/text-to-voice-executor.ts +111 -0
- package/src/features/text-to-voice/presentation/hooks/index.ts +5 -0
- package/src/features/text-to-voice/presentation/hooks/useTextToVoiceFeature.ts +105 -0
- package/src/features/text-to-voice/presentation/index.ts +1 -0
- package/src/features/upscaling/domain/types/index.ts +0 -1
- package/src/features/upscaling/domain/types/upscale.types.ts +14 -0
- package/src/features/upscaling/index.ts +3 -11
- package/src/features/upscaling/infrastructure/services/index.ts +1 -6
- package/src/features/upscaling/infrastructure/services/upscale-executor.ts +64 -30
- package/src/features/upscaling/presentation/hooks/useUpscaleFeature.ts +12 -7
- package/src/index.ts +63 -0
- package/src/features/face-swap/domain/entities.ts +0 -48
- package/src/features/photo-restoration/domain/types/provider.types.ts +0 -23
- package/src/features/photo-restoration/infrastructure/services/photo-restore-provider-registry.ts +0 -77
- package/src/features/text-to-image/domain/entities.ts +0 -58
- package/src/features/text-to-video/domain/entities.ts +0 -52
- package/src/features/upscaling/domain/types/provider.types.ts +0 -23
- package/src/features/upscaling/infrastructure/services/upscale-provider-registry.ts +0 -77
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image-to-Video Executor
|
|
3
|
+
* Provider-agnostic image-to-video execution using active AI provider
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { providerRegistry } from "../../../../infrastructure/services";
|
|
7
|
+
import { cleanBase64 } from "../../../../infrastructure/utils";
|
|
8
|
+
import type {
|
|
9
|
+
ImageToVideoRequest,
|
|
10
|
+
ImageToVideoResult,
|
|
11
|
+
ImageToVideoInputBuilder,
|
|
12
|
+
ImageToVideoResultExtractor,
|
|
13
|
+
} from "../../domain/types";
|
|
14
|
+
|
|
15
|
+
declare const __DEV__: boolean;
|
|
16
|
+
|
|
17
|
+
export interface ExecuteImageToVideoOptions {
|
|
18
|
+
model: string;
|
|
19
|
+
buildInput: ImageToVideoInputBuilder;
|
|
20
|
+
extractResult?: ImageToVideoResultExtractor;
|
|
21
|
+
onProgress?: (progress: number) => void;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function defaultExtractResult(
|
|
25
|
+
result: unknown,
|
|
26
|
+
): { videoUrl?: string; thumbnailUrl?: string } | undefined {
|
|
27
|
+
if (typeof result !== "object" || result === null) return undefined;
|
|
28
|
+
|
|
29
|
+
const r = result as Record<string, unknown>;
|
|
30
|
+
|
|
31
|
+
if (typeof r.video === "string") {
|
|
32
|
+
return { videoUrl: r.video };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (r.video && typeof r.video === "object") {
|
|
36
|
+
const video = r.video as Record<string, unknown>;
|
|
37
|
+
if (typeof video.url === "string") {
|
|
38
|
+
return {
|
|
39
|
+
videoUrl: video.url,
|
|
40
|
+
thumbnailUrl:
|
|
41
|
+
typeof r.thumbnail === "string" ? r.thumbnail : undefined,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export async function executeImageToVideo(
|
|
50
|
+
request: ImageToVideoRequest,
|
|
51
|
+
options: ExecuteImageToVideoOptions,
|
|
52
|
+
): Promise<ImageToVideoResult> {
|
|
53
|
+
const provider = providerRegistry.getActiveProvider();
|
|
54
|
+
|
|
55
|
+
if (!provider) {
|
|
56
|
+
return { success: false, error: "No AI provider configured" };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (!provider.isInitialized()) {
|
|
60
|
+
return { success: false, error: "AI provider not initialized" };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (!request.imageBase64) {
|
|
64
|
+
return { success: false, error: "Image base64 is required" };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const { model, buildInput, extractResult, onProgress } = options;
|
|
68
|
+
|
|
69
|
+
if (__DEV__) {
|
|
70
|
+
// eslint-disable-next-line no-console
|
|
71
|
+
console.log(`[ImageToVideo] Provider: ${provider.providerId}, Model: ${model}`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
onProgress?.(10);
|
|
76
|
+
|
|
77
|
+
const imageBase64 = cleanBase64(request.imageBase64);
|
|
78
|
+
onProgress?.(30);
|
|
79
|
+
|
|
80
|
+
const input = buildInput(imageBase64, request.motionPrompt, request.options);
|
|
81
|
+
onProgress?.(40);
|
|
82
|
+
|
|
83
|
+
const result = await provider.run(model, input);
|
|
84
|
+
onProgress?.(90);
|
|
85
|
+
|
|
86
|
+
const extractor = extractResult || defaultExtractResult;
|
|
87
|
+
const extracted = extractor(result);
|
|
88
|
+
onProgress?.(100);
|
|
89
|
+
|
|
90
|
+
if (!extracted?.videoUrl) {
|
|
91
|
+
return { success: false, error: "No video in response" };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
success: true,
|
|
96
|
+
videoUrl: extracted.videoUrl,
|
|
97
|
+
thumbnailUrl: extracted.thumbnailUrl,
|
|
98
|
+
};
|
|
99
|
+
} catch (error) {
|
|
100
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
101
|
+
if (__DEV__) {
|
|
102
|
+
// eslint-disable-next-line no-console
|
|
103
|
+
console.error("[ImageToVideo] Error:", message);
|
|
104
|
+
}
|
|
105
|
+
return { success: false, error: message };
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function hasImageToVideoSupport(): boolean {
|
|
110
|
+
const provider = providerRegistry.getActiveProvider();
|
|
111
|
+
return provider !== null && provider.isInitialized();
|
|
112
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image-to-Video Feature Hook
|
|
3
|
+
* Provider-agnostic hook for image-to-video generation
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { useState, useCallback } from "react";
|
|
7
|
+
import { executeImageToVideo } from "../../infrastructure/services";
|
|
8
|
+
import type {
|
|
9
|
+
ImageToVideoFeatureState,
|
|
10
|
+
ImageToVideoFeatureConfig,
|
|
11
|
+
ImageToVideoResult,
|
|
12
|
+
ImageToVideoOptions,
|
|
13
|
+
} from "../../domain/types";
|
|
14
|
+
|
|
15
|
+
export interface UseImageToVideoFeatureProps {
|
|
16
|
+
config: ImageToVideoFeatureConfig;
|
|
17
|
+
userId: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface UseImageToVideoFeatureReturn {
|
|
21
|
+
state: ImageToVideoFeatureState;
|
|
22
|
+
setImageUri: (uri: string) => void;
|
|
23
|
+
setMotionPrompt: (prompt: string) => void;
|
|
24
|
+
generate: (options?: ImageToVideoOptions) => Promise<ImageToVideoResult>;
|
|
25
|
+
reset: () => void;
|
|
26
|
+
isReady: boolean;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const initialState: ImageToVideoFeatureState = {
|
|
30
|
+
imageUri: null,
|
|
31
|
+
motionPrompt: "",
|
|
32
|
+
videoUrl: null,
|
|
33
|
+
thumbnailUrl: null,
|
|
34
|
+
isProcessing: false,
|
|
35
|
+
progress: 0,
|
|
36
|
+
error: null,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export function useImageToVideoFeature(
|
|
40
|
+
props: UseImageToVideoFeatureProps,
|
|
41
|
+
): UseImageToVideoFeatureReturn {
|
|
42
|
+
const { config, userId } = props;
|
|
43
|
+
const [state, setState] = useState<ImageToVideoFeatureState>(initialState);
|
|
44
|
+
|
|
45
|
+
const setImageUri = useCallback(
|
|
46
|
+
(uri: string) => {
|
|
47
|
+
setState((prev) => ({ ...prev, imageUri: uri, error: null }));
|
|
48
|
+
config.onImageSelect?.(uri);
|
|
49
|
+
},
|
|
50
|
+
[config],
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const setMotionPrompt = useCallback((prompt: string) => {
|
|
54
|
+
setState((prev) => ({ ...prev, motionPrompt: prompt }));
|
|
55
|
+
}, []);
|
|
56
|
+
|
|
57
|
+
const generate = useCallback(
|
|
58
|
+
async (options?: ImageToVideoOptions): Promise<ImageToVideoResult> => {
|
|
59
|
+
if (!state.imageUri) {
|
|
60
|
+
const error = "Image is required";
|
|
61
|
+
setState((prev) => ({ ...prev, error }));
|
|
62
|
+
return { success: false, error };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
setState((prev) => ({
|
|
66
|
+
...prev,
|
|
67
|
+
isProcessing: true,
|
|
68
|
+
progress: 0,
|
|
69
|
+
error: null,
|
|
70
|
+
}));
|
|
71
|
+
|
|
72
|
+
config.onProcessingStart?.();
|
|
73
|
+
|
|
74
|
+
const imageBase64 = await config.prepareImage(state.imageUri);
|
|
75
|
+
|
|
76
|
+
const result = await executeImageToVideo(
|
|
77
|
+
{
|
|
78
|
+
imageUri: state.imageUri,
|
|
79
|
+
imageBase64,
|
|
80
|
+
userId,
|
|
81
|
+
motionPrompt: state.motionPrompt || undefined,
|
|
82
|
+
options,
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
model: config.model,
|
|
86
|
+
buildInput: config.buildInput,
|
|
87
|
+
extractResult: config.extractResult,
|
|
88
|
+
onProgress: (progress) => {
|
|
89
|
+
setState((prev) => ({ ...prev, progress }));
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
if (result.success && result.videoUrl) {
|
|
95
|
+
setState((prev) => ({
|
|
96
|
+
...prev,
|
|
97
|
+
videoUrl: result.videoUrl ?? null,
|
|
98
|
+
thumbnailUrl: result.thumbnailUrl ?? null,
|
|
99
|
+
isProcessing: false,
|
|
100
|
+
progress: 100,
|
|
101
|
+
}));
|
|
102
|
+
} else {
|
|
103
|
+
const error = result.error || "Generation failed";
|
|
104
|
+
setState((prev) => ({ ...prev, isProcessing: false, error }));
|
|
105
|
+
config.onError?.(error);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
config.onProcessingComplete?.(result);
|
|
109
|
+
return result;
|
|
110
|
+
},
|
|
111
|
+
[state.imageUri, state.motionPrompt, userId, config],
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
const reset = useCallback(() => {
|
|
115
|
+
setState(initialState);
|
|
116
|
+
}, []);
|
|
117
|
+
|
|
118
|
+
const isReady = state.imageUri !== null && !state.isProcessing;
|
|
119
|
+
|
|
120
|
+
return { state, setImageUri, setMotionPrompt, generate, reset, isReady };
|
|
121
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./hooks";
|
|
@@ -5,9 +5,6 @@ export type {
|
|
|
5
5
|
PhotoRestoreFeatureState,
|
|
6
6
|
PhotoRestoreTranslations,
|
|
7
7
|
PhotoRestoreFeatureConfig,
|
|
8
|
+
PhotoRestoreInputBuilder,
|
|
9
|
+
PhotoRestoreResultExtractor,
|
|
8
10
|
} from "./photo-restore.types";
|
|
9
|
-
|
|
10
|
-
export type {
|
|
11
|
-
IPhotoRestoreProvider,
|
|
12
|
-
PhotoRestoreProviderEntry,
|
|
13
|
-
} from "./provider.types";
|
|
@@ -11,6 +11,7 @@ export interface PhotoRestoreOptions {
|
|
|
11
11
|
|
|
12
12
|
export interface PhotoRestoreRequest {
|
|
13
13
|
imageUri: string;
|
|
14
|
+
imageBase64?: string;
|
|
14
15
|
userId: string;
|
|
15
16
|
options?: PhotoRestoreOptions;
|
|
16
17
|
}
|
|
@@ -47,9 +48,22 @@ export interface PhotoRestoreTranslations {
|
|
|
47
48
|
compareHint?: string;
|
|
48
49
|
}
|
|
49
50
|
|
|
51
|
+
export type PhotoRestoreInputBuilder = (
|
|
52
|
+
base64: string,
|
|
53
|
+
options?: PhotoRestoreOptions,
|
|
54
|
+
) => Record<string, unknown>;
|
|
55
|
+
|
|
56
|
+
export type PhotoRestoreResultExtractor = (
|
|
57
|
+
result: unknown,
|
|
58
|
+
) => string | undefined;
|
|
59
|
+
|
|
50
60
|
export interface PhotoRestoreFeatureConfig {
|
|
51
61
|
providerId?: string;
|
|
52
62
|
creditCost?: number;
|
|
63
|
+
model: string;
|
|
64
|
+
buildInput: PhotoRestoreInputBuilder;
|
|
65
|
+
extractResult?: PhotoRestoreResultExtractor;
|
|
66
|
+
prepareImage: (imageUri: string) => Promise<string>;
|
|
53
67
|
onImageSelect?: (uri: string) => void;
|
|
54
68
|
onProcessingStart?: () => void;
|
|
55
69
|
onProcessingComplete?: (result: PhotoRestoreResult) => void;
|
|
@@ -11,17 +11,12 @@ export type {
|
|
|
11
11
|
PhotoRestoreFeatureState,
|
|
12
12
|
PhotoRestoreTranslations,
|
|
13
13
|
PhotoRestoreFeatureConfig,
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
PhotoRestoreInputBuilder,
|
|
15
|
+
PhotoRestoreResultExtractor,
|
|
16
16
|
} from "./domain";
|
|
17
17
|
|
|
18
18
|
// Infrastructure Services
|
|
19
|
-
export {
|
|
20
|
-
photoRestoreProviderRegistry,
|
|
21
|
-
executePhotoRestore,
|
|
22
|
-
getAvailablePhotoRestoreProvider,
|
|
23
|
-
hasPhotoRestoreProvider,
|
|
24
|
-
} from "./infrastructure";
|
|
19
|
+
export { executePhotoRestore, hasPhotoRestoreSupport } from "./infrastructure";
|
|
25
20
|
export type { ExecutePhotoRestoreOptions } from "./infrastructure";
|
|
26
21
|
|
|
27
22
|
// Presentation Hooks
|
|
@@ -1,7 +1,2 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export {
|
|
3
|
-
executePhotoRestore,
|
|
4
|
-
getAvailablePhotoRestoreProvider,
|
|
5
|
-
hasPhotoRestoreProvider,
|
|
6
|
-
} from "./photo-restore-executor";
|
|
1
|
+
export { executePhotoRestore, hasPhotoRestoreSupport } from "./photo-restore-executor";
|
|
7
2
|
export type { ExecutePhotoRestoreOptions } from "./photo-restore-executor";
|
|
@@ -1,64 +1,98 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Photo Restore Executor
|
|
3
|
-
*
|
|
3
|
+
* Provider-agnostic photo restore execution using active AI provider
|
|
4
|
+
* Model and input format are provided via options from app level
|
|
5
|
+
*
|
|
6
|
+
* Note: imageBase64 must be provided in the request. Image URI to base64
|
|
7
|
+
* conversion should be handled at the app level before calling this executor.
|
|
4
8
|
*/
|
|
5
9
|
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
10
|
+
import { providerRegistry } from "../../../../infrastructure/services";
|
|
11
|
+
import { cleanBase64 } from "../../../../infrastructure/utils";
|
|
12
|
+
import type {
|
|
13
|
+
PhotoRestoreRequest,
|
|
14
|
+
PhotoRestoreResult,
|
|
15
|
+
PhotoRestoreInputBuilder,
|
|
16
|
+
PhotoRestoreResultExtractor,
|
|
17
|
+
} from "../../domain/types";
|
|
8
18
|
|
|
9
19
|
declare const __DEV__: boolean;
|
|
10
20
|
|
|
11
21
|
export interface ExecutePhotoRestoreOptions {
|
|
12
|
-
|
|
22
|
+
model: string;
|
|
23
|
+
buildInput: PhotoRestoreInputBuilder;
|
|
24
|
+
extractResult?: PhotoRestoreResultExtractor;
|
|
13
25
|
onProgress?: (progress: number) => void;
|
|
14
26
|
}
|
|
15
27
|
|
|
28
|
+
function defaultExtractResult(result: unknown): string | undefined {
|
|
29
|
+
if (typeof result !== "object" || result === null) return undefined;
|
|
30
|
+
|
|
31
|
+
const r = result as Record<string, unknown>;
|
|
32
|
+
|
|
33
|
+
if (typeof r.image === "string") return r.image;
|
|
34
|
+
if (Array.isArray(r.images) && r.images[0]?.url) return r.images[0].url;
|
|
35
|
+
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
|
|
16
39
|
export async function executePhotoRestore(
|
|
17
40
|
request: PhotoRestoreRequest,
|
|
18
|
-
options
|
|
41
|
+
options: ExecutePhotoRestoreOptions,
|
|
19
42
|
): Promise<PhotoRestoreResult> {
|
|
20
|
-
const provider =
|
|
43
|
+
const provider = providerRegistry.getActiveProvider();
|
|
21
44
|
|
|
22
45
|
if (!provider) {
|
|
23
|
-
return {
|
|
24
|
-
success: false,
|
|
25
|
-
error: "No photo restore provider available",
|
|
26
|
-
};
|
|
46
|
+
return { success: false, error: "No AI provider configured" };
|
|
27
47
|
}
|
|
28
48
|
|
|
29
|
-
if (!provider.
|
|
30
|
-
return {
|
|
31
|
-
success: false,
|
|
32
|
-
error: `Provider ${provider.providerId} is not available`,
|
|
33
|
-
};
|
|
49
|
+
if (!provider.isInitialized()) {
|
|
50
|
+
return { success: false, error: "AI provider not initialized" };
|
|
34
51
|
}
|
|
35
52
|
|
|
53
|
+
if (!request.imageBase64) {
|
|
54
|
+
return { success: false, error: "Image base64 is required" };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const { model, buildInput, extractResult, onProgress } = options;
|
|
58
|
+
|
|
36
59
|
if (__DEV__) {
|
|
37
60
|
// eslint-disable-next-line no-console
|
|
38
|
-
console.log(`[
|
|
61
|
+
console.log(`[PhotoRestore] Provider: ${provider.providerId}, Model: ${model}`);
|
|
39
62
|
}
|
|
40
63
|
|
|
41
64
|
try {
|
|
42
|
-
|
|
65
|
+
onProgress?.(10);
|
|
66
|
+
|
|
67
|
+
const base64 = cleanBase64(request.imageBase64);
|
|
68
|
+
onProgress?.(30);
|
|
69
|
+
|
|
70
|
+
const input = buildInput(base64, request.options);
|
|
71
|
+
onProgress?.(40);
|
|
72
|
+
|
|
73
|
+
const result = await provider.run(model, input);
|
|
74
|
+
onProgress?.(90);
|
|
75
|
+
|
|
76
|
+
const extractor = extractResult || defaultExtractResult;
|
|
77
|
+
const imageUrl = extractor(result);
|
|
78
|
+
onProgress?.(100);
|
|
79
|
+
|
|
80
|
+
if (!imageUrl) {
|
|
81
|
+
return { success: false, error: "No image in response" };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return { success: true, imageUrl };
|
|
43
85
|
} catch (error) {
|
|
44
86
|
const message = error instanceof Error ? error.message : String(error);
|
|
45
|
-
|
|
46
87
|
if (__DEV__) {
|
|
47
88
|
// eslint-disable-next-line no-console
|
|
48
|
-
console.error("[
|
|
89
|
+
console.error("[PhotoRestore] Error:", message);
|
|
49
90
|
}
|
|
50
|
-
|
|
51
|
-
return {
|
|
52
|
-
success: false,
|
|
53
|
-
error: message,
|
|
54
|
-
};
|
|
91
|
+
return { success: false, error: message };
|
|
55
92
|
}
|
|
56
93
|
}
|
|
57
94
|
|
|
58
|
-
export function
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
export function hasPhotoRestoreProvider(providerId: string): boolean {
|
|
63
|
-
return photoRestoreProviderRegistry.hasProvider(providerId);
|
|
95
|
+
export function hasPhotoRestoreSupport(): boolean {
|
|
96
|
+
const provider = providerRegistry.getActiveProvider();
|
|
97
|
+
return provider !== null && provider.isInitialized();
|
|
64
98
|
}
|
|
@@ -14,7 +14,7 @@ import type {
|
|
|
14
14
|
declare const __DEV__: boolean;
|
|
15
15
|
|
|
16
16
|
export interface UsePhotoRestoreFeatureProps {
|
|
17
|
-
config
|
|
17
|
+
config: PhotoRestoreFeatureConfig;
|
|
18
18
|
userId: string;
|
|
19
19
|
onSelectImage: () => Promise<string | null>;
|
|
20
20
|
onSaveImage: (imageUrl: string) => Promise<void>;
|
|
@@ -46,7 +46,7 @@ export function usePhotoRestoreFeature(
|
|
|
46
46
|
const uri = await onSelectImage();
|
|
47
47
|
if (uri) {
|
|
48
48
|
setState((prev) => ({ ...prev, imageUri: uri, error: null }));
|
|
49
|
-
config
|
|
49
|
+
config.onImageSelect?.(uri);
|
|
50
50
|
}
|
|
51
51
|
} catch (error) {
|
|
52
52
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -68,20 +68,25 @@ export function usePhotoRestoreFeature(
|
|
|
68
68
|
error: null,
|
|
69
69
|
}));
|
|
70
70
|
|
|
71
|
-
config
|
|
71
|
+
config.onProcessingStart?.();
|
|
72
72
|
|
|
73
73
|
if (__DEV__) {
|
|
74
74
|
// eslint-disable-next-line no-console
|
|
75
75
|
console.log("[usePhotoRestoreFeature] Starting photo restore process");
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
const imageBase64 = await config.prepareImage(state.imageUri);
|
|
79
|
+
|
|
78
80
|
const result: PhotoRestoreResult = await executePhotoRestore(
|
|
79
81
|
{
|
|
80
82
|
imageUri: state.imageUri,
|
|
83
|
+
imageBase64,
|
|
81
84
|
userId,
|
|
82
85
|
},
|
|
83
86
|
{
|
|
84
|
-
|
|
87
|
+
model: config.model,
|
|
88
|
+
buildInput: config.buildInput,
|
|
89
|
+
extractResult: config.extractResult,
|
|
85
90
|
onProgress: handleProgress,
|
|
86
91
|
},
|
|
87
92
|
);
|
|
@@ -94,7 +99,7 @@ export function usePhotoRestoreFeature(
|
|
|
94
99
|
processedUrl: url,
|
|
95
100
|
progress: 100,
|
|
96
101
|
}));
|
|
97
|
-
config
|
|
102
|
+
config.onProcessingComplete?.(result);
|
|
98
103
|
} else {
|
|
99
104
|
const errorMessage = result.error || "Processing failed";
|
|
100
105
|
setState((prev) => ({
|
|
@@ -103,7 +108,7 @@ export function usePhotoRestoreFeature(
|
|
|
103
108
|
error: errorMessage,
|
|
104
109
|
progress: 0,
|
|
105
110
|
}));
|
|
106
|
-
config
|
|
111
|
+
config.onError?.(errorMessage);
|
|
107
112
|
}
|
|
108
113
|
}, [state.imageUri, userId, config, handleProgress]);
|
|
109
114
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remove Background Domain Types Index
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export type {
|
|
6
|
+
RemoveBackgroundOptions,
|
|
7
|
+
RemoveBackgroundRequest,
|
|
8
|
+
RemoveBackgroundResult,
|
|
9
|
+
RemoveBackgroundFeatureState,
|
|
10
|
+
RemoveBackgroundTranslations,
|
|
11
|
+
RemoveBackgroundInputBuilder,
|
|
12
|
+
RemoveBackgroundResultExtractor,
|
|
13
|
+
RemoveBackgroundFeatureConfig,
|
|
14
|
+
} from "./remove-background.types";
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remove Background Feature Types
|
|
3
|
+
* Request, Result, Config types for background removal
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface RemoveBackgroundOptions {
|
|
7
|
+
refineEdges?: boolean;
|
|
8
|
+
outputFormat?: "png" | "webp";
|
|
9
|
+
backgroundColor?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface RemoveBackgroundRequest {
|
|
13
|
+
imageUri: string;
|
|
14
|
+
imageBase64?: string;
|
|
15
|
+
userId: string;
|
|
16
|
+
options?: RemoveBackgroundOptions;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface RemoveBackgroundResult {
|
|
20
|
+
success: boolean;
|
|
21
|
+
imageUrl?: string;
|
|
22
|
+
imageBase64?: string;
|
|
23
|
+
error?: string;
|
|
24
|
+
requestId?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface RemoveBackgroundFeatureState {
|
|
28
|
+
imageUri: string | null;
|
|
29
|
+
processedUrl: string | null;
|
|
30
|
+
isProcessing: boolean;
|
|
31
|
+
progress: number;
|
|
32
|
+
error: string | null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface RemoveBackgroundTranslations {
|
|
36
|
+
uploadTitle: string;
|
|
37
|
+
uploadSubtitle: string;
|
|
38
|
+
uploadChange: string;
|
|
39
|
+
uploadAnalyzing: string;
|
|
40
|
+
description: string;
|
|
41
|
+
processingText: string;
|
|
42
|
+
processButtonText: string;
|
|
43
|
+
successText: string;
|
|
44
|
+
saveButtonText: string;
|
|
45
|
+
tryAnotherText: string;
|
|
46
|
+
beforeLabel?: string;
|
|
47
|
+
afterLabel?: string;
|
|
48
|
+
compareHint?: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type RemoveBackgroundInputBuilder = (
|
|
52
|
+
base64: string,
|
|
53
|
+
options?: RemoveBackgroundOptions,
|
|
54
|
+
) => Record<string, unknown>;
|
|
55
|
+
|
|
56
|
+
export type RemoveBackgroundResultExtractor = (result: unknown) => string | undefined;
|
|
57
|
+
|
|
58
|
+
export interface RemoveBackgroundFeatureConfig {
|
|
59
|
+
providerId?: string;
|
|
60
|
+
creditCost?: number;
|
|
61
|
+
model: string;
|
|
62
|
+
buildInput: RemoveBackgroundInputBuilder;
|
|
63
|
+
extractResult?: RemoveBackgroundResultExtractor;
|
|
64
|
+
prepareImage: (imageUri: string) => Promise<string>;
|
|
65
|
+
onImageSelect?: (uri: string) => void;
|
|
66
|
+
onProcessingStart?: () => void;
|
|
67
|
+
onProcessingComplete?: (result: RemoveBackgroundResult) => void;
|
|
68
|
+
onError?: (error: string) => void;
|
|
69
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remove Background Feature
|
|
3
|
+
* Provider-agnostic background removal feature
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Domain Types
|
|
7
|
+
export type {
|
|
8
|
+
RemoveBackgroundOptions,
|
|
9
|
+
RemoveBackgroundRequest,
|
|
10
|
+
RemoveBackgroundResult,
|
|
11
|
+
RemoveBackgroundFeatureState,
|
|
12
|
+
RemoveBackgroundTranslations,
|
|
13
|
+
RemoveBackgroundFeatureConfig,
|
|
14
|
+
RemoveBackgroundInputBuilder,
|
|
15
|
+
RemoveBackgroundResultExtractor,
|
|
16
|
+
} from "./domain";
|
|
17
|
+
|
|
18
|
+
// Infrastructure Services
|
|
19
|
+
export { executeRemoveBackground, hasRemoveBackgroundSupport } from "./infrastructure";
|
|
20
|
+
export type { ExecuteRemoveBackgroundOptions } from "./infrastructure";
|
|
21
|
+
|
|
22
|
+
// Presentation Hooks
|
|
23
|
+
export { useRemoveBackgroundFeature } from "./presentation";
|
|
24
|
+
export type {
|
|
25
|
+
UseRemoveBackgroundFeatureProps,
|
|
26
|
+
UseRemoveBackgroundFeatureReturn,
|
|
27
|
+
} from "./presentation";
|