@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.
Files changed (43) hide show
  1. package/package.json +1 -1
  2. package/src/domains/creations/presentation/hooks/index.ts +2 -2
  3. package/src/domains/creations/presentation/hooks/{useMediaFilter.ts → useFilter.ts} +12 -7
  4. package/src/domains/creations/presentation/hooks/useGalleryFilters.ts +5 -6
  5. package/src/features/ai-hug/presentation/hooks/useAIHugFeature.ts +9 -113
  6. package/src/features/ai-kiss/presentation/hooks/useAIKissFeature.ts +9 -113
  7. package/src/features/image-to-video/infrastructure/services/image-to-video-executor.ts +5 -9
  8. package/src/features/image-to-video/presentation/hooks/useImageToVideoForm.ts +5 -0
  9. package/src/features/replace-background/index.ts +5 -50
  10. package/src/features/replace-background/presentation/components/index.ts +0 -12
  11. package/src/features/replace-background/presentation/hooks/index.ts +0 -3
  12. package/src/features/shared/dual-image-video/domain/types/dual-image-video.types.ts +67 -0
  13. package/src/features/shared/dual-image-video/domain/types/index.ts +13 -0
  14. package/src/features/shared/dual-image-video/index.ts +16 -0
  15. package/src/features/shared/dual-image-video/presentation/hooks/index.ts +5 -0
  16. package/src/features/shared/dual-image-video/presentation/hooks/useDualImageVideoFeature.ts +124 -0
  17. package/src/features/shared/index.ts +6 -0
  18. package/src/infrastructure/utils/index.ts +1 -0
  19. package/src/infrastructure/utils/progress-calculator.util.ts +31 -0
  20. package/src/infrastructure/utils/result-validator.util.ts +0 -214
  21. package/src/infrastructure/utils/url-extractor.util.ts +209 -0
  22. package/src/presentation/hooks/flow-state.utils.ts +101 -0
  23. package/src/presentation/hooks/useGenerationFlow.ts +47 -178
  24. package/src/presentation/types/flow-config.types.ts +5 -99
  25. package/src/presentation/types/flow-default-configs.ts +106 -0
  26. package/src/domains/creations/presentation/hooks/useStatusFilter.ts +0 -54
  27. package/src/features/replace-background/domain/entities/background.types.ts +0 -77
  28. package/src/features/replace-background/domain/entities/component.types.ts +0 -87
  29. package/src/features/replace-background/domain/entities/config.types.ts +0 -41
  30. package/src/features/replace-background/domain/entities/index.ts +0 -30
  31. package/src/features/replace-background/infrastructure/constants/index.ts +0 -5
  32. package/src/features/replace-background/infrastructure/constants/prompts.constants.ts +0 -15
  33. package/src/features/replace-background/infrastructure/index.ts +0 -5
  34. package/src/features/replace-background/presentation/components/BackgroundFeature.tsx +0 -143
  35. package/src/features/replace-background/presentation/components/ComparisonSlider.tsx +0 -187
  36. package/src/features/replace-background/presentation/components/ErrorDisplay.tsx +0 -60
  37. package/src/features/replace-background/presentation/components/FeatureHeader.tsx +0 -80
  38. package/src/features/replace-background/presentation/components/GenerateButton.tsx +0 -85
  39. package/src/features/replace-background/presentation/components/ImagePicker.tsx +0 -136
  40. package/src/features/replace-background/presentation/components/ModeSelector.tsx +0 -78
  41. package/src/features/replace-background/presentation/components/PromptInput.tsx +0 -142
  42. package/src/features/replace-background/presentation/components/ResultDisplay.tsx +0 -122
  43. package/src/features/replace-background/presentation/hooks/useBackgroundFeature.ts +0 -119
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-ai-generation-content",
3
- "version": "1.17.143",
3
+ "version": "1.17.145",
4
4
  "description": "Provider-agnostic AI generation orchestration for React Native",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -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 "./useStatusFilter";
10
- export { useMediaFilter } from "./useMediaFilter";
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
- * useMediaFilter Hook
3
- * Handles media type filtering (image, video, voice)
4
- * SOLID: Single Responsibility - Only handles media filter state
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 UseMediaFilterProps {
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 UseMediaFilterReturn {
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 useMediaFilter({
25
+ export function useFilter({
25
26
  options,
26
27
  t,
27
28
  defaultId = "all"
28
- }: UseMediaFilterProps): UseMediaFilterReturn {
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 { useStatusFilter } from "./useStatusFilter";
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 useStatusFilter>;
28
- readonly mediaFilter: ReturnType<typeof useMediaFilter>;
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 = useStatusFilter({ options: statusOptions, t });
46
- const mediaFilter = useMediaFilter({ options: mediaOptions, t });
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
- * Manages AI hug video generation state and actions
3
+ * Thin wrapper around useDualImageVideoFeature for ai-hug feature
4
+ * DRY: Uses shared base hook for common logic
4
5
  */
5
6
 
6
- import { useState, useCallback } from "react";
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
- const initialState: AIHugFeatureState = {
29
- sourceImageUri: null,
30
- targetImageUri: null,
31
- processedVideoUrl: null,
32
- isProcessing: false,
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
- * Manages AI kiss video generation state and actions
3
+ * Thin wrapper around useDualImageVideoFeature for ai-kiss feature
4
+ * DRY: Uses shared base hook for common logic
4
5
  */
5
6
 
6
- import { useState, useCallback } from "react";
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
- const initialState: AIKissFeatureState = {
29
- sourceImageUri: null,
30
- targetImageUri: null,
31
- processedVideoUrl: null,
32
- isProcessing: false,
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
- * Matches text-to-video pattern for consistency
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 queue status to progress
107
- if (status.status === "IN_QUEUE") {
108
- onProgress?.(10);
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 and removal feature for React Native
3
+ * AI-powered background replacement feature for React Native
4
4
  */
5
5
 
6
- // Domain Types - Legacy
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
- BackgroundFeature,
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";
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Dual Image Video Presentation Hooks
3
+ */
4
+
5
+ export { useDualImageVideoFeature } from "./useDualImageVideoFeature";