@umituz/react-native-ai-generation-content 1.90.2 → 1.90.4
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 +3 -3
- package/src/domain/interfaces/app-services-auth.interface.ts +27 -0
- package/src/domain/interfaces/app-services-composite.interface.ts +29 -0
- package/src/domain/interfaces/app-services-optional.interface.ts +42 -0
- package/src/domain/interfaces/app-services.interface.ts +0 -79
- package/src/domain/interfaces/index.ts +3 -0
- package/src/domains/background/infrastructure/services/job-poller-index.ts +7 -0
- package/src/domains/background/infrastructure/services/job-poller-utils.ts +127 -0
- package/src/domains/background/infrastructure/services/job-poller.service.ts +85 -140
- package/src/domains/background/infrastructure/utils/polling-interval.util.ts +1 -1
- package/src/domains/background/presentation/hooks/use-background-generation.ts +1 -1
- package/src/domains/content-moderation/index.ts +7 -13
- package/src/domains/content-moderation/infrastructure/services/content-moderation.service.ts +1 -1
- package/src/domains/content-moderation/infrastructure/services/moderators/image.moderator.ts +34 -8
- package/src/domains/content-moderation/infrastructure/services/moderators/text.moderator.ts +15 -4
- package/src/domains/content-moderation/infrastructure/services/moderators/video.moderator.ts +34 -8
- package/src/domains/content-moderation/infrastructure/services/moderators/voice.moderator.ts +19 -8
- package/src/domains/content-moderation/infrastructure/services/pattern-matcher.service.ts +1 -2
- package/src/domains/creations/domain/types/creation-categories.constants.ts +57 -0
- package/src/domains/creations/domain/types/creation-categories.helpers.ts +67 -0
- package/src/domains/creations/domain/types/creation-categories.ts +7 -114
- package/src/domains/creations/domain/utils/creation-display.util.ts +1 -1
- package/src/domains/creations/domain/utils/status-helpers.ts +1 -1
- package/src/domains/creations/presentation/hooks/creation-validators.ts +31 -29
- package/src/domains/creations/presentation/hooks/job-poller-index.ts +10 -0
- package/src/domains/creations/presentation/hooks/job-poller-utils.filters.ts +34 -0
- package/src/domains/creations/presentation/hooks/job-poller-utils.logger.ts +76 -0
- package/src/domains/creations/presentation/hooks/job-poller-utils.stale-handlers.ts +52 -0
- package/src/domains/creations/presentation/hooks/job-poller-utils.ts +8 -0
- package/src/domains/creations/presentation/hooks/useCreations.ts +1 -1
- package/src/domains/creations/presentation/hooks/useProcessingJobsPoller.ts +18 -235
- package/src/domains/creations/presentation/screens/CreationsGalleryScreen.tsx +1 -2
- package/src/domains/creations/presentation-exports.ts +2 -2
- package/src/domains/face-detection/domain/entities/FaceDetection.ts +4 -3
- package/src/domains/face-detection/presentation/hooks/useFaceDetection.ts +24 -21
- package/src/domains/generation/infrastructure/appearance-analysis/index.ts +5 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/builder-couple-preparation.ts +58 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/builder-couple-prompt.ts +69 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/builder-couple-resolution.ts +77 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/builder-couple.ts +54 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/builder-index.ts +8 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/builder-scenario.ts +112 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/builder.ts +7 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/index.ts +20 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/types.ts +44 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/utils/builder-end-logger.ts +18 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/utils/builder-start-logger.ts +57 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/utils/builder-step-logger.ts +106 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/utils/index.ts +8 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/utils/types.ts +49 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/utils.ts +8 -0
- package/src/domains/generation/infrastructure/flow/flow-store-actions.ts +105 -0
- package/src/domains/generation/infrastructure/flow/flow-store-initial-state.ts +26 -0
- package/src/domains/generation/infrastructure/flow/useFlowStore.ts +4 -116
- package/src/domains/generation/presentation/useAIGeneration.hook.ts +1 -1
- package/src/domains/generation/wizard/infrastructure/strategies/image-generation-strategy-index.ts +7 -0
- package/src/domains/generation/wizard/infrastructure/strategies/image-generation.executor.ts +2 -12
- package/src/domains/generation/wizard/infrastructure/strategies/image-generation.executor.types.ts +11 -0
- package/src/domains/generation/wizard/infrastructure/strategies/image-generation.executor.utils.ts +12 -0
- package/src/domains/generation/wizard/infrastructure/strategies/image-generation.strategy.ts +1 -220
- package/src/domains/generation/wizard/infrastructure/strategies/image-input-builder.ts +66 -0
- package/src/domains/generation/wizard/infrastructure/strategies/image-input-extraction.ts +88 -0
- package/src/domains/generation/wizard/infrastructure/strategies/image-input-prompt-builder.ts +74 -0
- package/src/domains/generation/wizard/infrastructure/strategies/image-input-style-enhancements.ts +35 -0
- package/src/domains/generation/wizard/infrastructure/strategies/image-strategy-factory.ts +41 -0
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation-executor-index.ts +10 -0
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation-executor.ts +76 -0
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation-input-builder.ts +46 -0
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation-result-types.ts +17 -0
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation-submission.ts +61 -0
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation.audio-extractor.ts +27 -0
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation.executor.ts +2 -176
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation.input-builder.ts +90 -0
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation.strategy.ts +3 -108
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation.types.ts +0 -130
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation.validation.ts +136 -0
- package/src/domains/generation/wizard/presentation/hooks/photo-upload/index.ts +40 -0
- package/src/domains/generation/wizard/presentation/hooks/photo-upload/types.ts +37 -0
- package/src/domains/generation/wizard/presentation/hooks/photo-upload/usePhotoUploadStateLogic.ts +142 -0
- package/src/domains/generation/wizard/presentation/hooks/use-video-queue-utils.ts +102 -0
- package/src/domains/generation/wizard/presentation/hooks/usePhotoBlockingGeneration.handlers.ts +97 -0
- package/src/domains/generation/wizard/presentation/hooks/usePhotoBlockingGeneration.saver.ts +54 -0
- package/src/domains/generation/wizard/presentation/hooks/usePhotoBlockingGeneration.ts +22 -87
- package/src/domains/generation/wizard/presentation/hooks/usePhotoUploadState.ts +8 -177
- package/src/domains/generation/wizard/presentation/hooks/useVideoQueueGeneration.ts +1 -295
- package/src/domains/generation/wizard/presentation/hooks/useWizardGeneration.ts +1 -1
- package/src/domains/generation/wizard/presentation/hooks/video-queue/index.ts +77 -0
- package/src/domains/generation/wizard/presentation/hooks/video-queue/use-video-queue-utils.ts +123 -0
- package/src/domains/generation/wizard/presentation/hooks/video-queue/useVideoQueueGenerationCallbacks.ts +119 -0
- package/src/domains/generation/wizard/presentation/hooks/video-queue/useVideoQueueGenerationPolling.ts +75 -0
- package/src/domains/generation/wizard/presentation/hooks/video-queue/useVideoQueueGenerationRefs.ts +65 -0
- package/src/domains/generation/wizard/presentation/hooks/video-queue/useVideoQueueGenerationStart.ts +123 -0
- package/src/domains/generation/wizard/presentation/hooks/video-queue-index.ts +9 -0
- package/src/domains/image-to-video/domain/types/image-to-video-state.types.ts +11 -4
- package/src/domains/text-to-image/domain/constants/index.ts +5 -6
- package/src/domains/text-to-image/domain/types/text-to-image.types.ts +43 -22
- package/src/domains/text-to-video/domain/types/request.types.ts +32 -9
- package/src/domains/text-to-video/domain/types/state.types.ts +22 -22
- package/src/domains/text-to-video/presentation/hooks/useTextToVideoForm.handlers.ts +44 -0
- package/src/domains/text-to-video/presentation/hooks/useTextToVideoForm.ts +5 -51
- package/src/domains/text-to-video/presentation/hooks/useTextToVideoForm.types.ts +33 -0
- package/src/exports/features.ts +1 -1
- package/src/infrastructure/services/generation-orchestrator.service.ts +2 -2
- package/src/infrastructure/utils/couple-input-context.ts +13 -0
- package/src/infrastructure/utils/couple-input-index.ts +9 -0
- package/src/infrastructure/utils/couple-input-photorealistic.ts +40 -0
- package/src/infrastructure/utils/couple-input-refiner.ts +101 -0
- package/src/infrastructure/utils/couple-input-resolver.ts +71 -0
- package/src/infrastructure/utils/couple-input-types.ts +11 -0
- package/src/infrastructure/utils/couple-input.util.ts +3 -176
- package/src/infrastructure/utils/photo-generation/photo-preparation.util.ts +1 -1
- package/src/infrastructure/validation/base-validator.ts +3 -26
- package/src/infrastructure/validation/base-validator.types.ts +32 -0
- package/src/presentation/hooks/generation/index.ts +1 -1
- package/src/presentation/hooks/generation/orchestrator-abort-logs.ts +48 -0
- package/src/presentation/hooks/generation/orchestrator-execution-logs.ts +67 -0
- package/src/presentation/hooks/generation/orchestrator-index.ts +14 -0
- package/src/presentation/hooks/generation/orchestrator-start-logs.ts +65 -0
- package/src/presentation/hooks/generation/orchestrator-state-utils.ts +17 -0
- package/src/presentation/hooks/generation/orchestrator-types.ts +55 -0
- package/src/presentation/hooks/generation/orchestrator-utils-index.ts +29 -0
- package/src/presentation/hooks/generation/orchestrator-utils.ts +25 -0
- package/src/presentation/hooks/generation/useDualImageGeneration.ts +1 -1
- package/src/presentation/hooks/generation/useImageGeneration.ts +1 -1
- package/src/presentation/hooks/generation/useVideoGeneration.ts +1 -1
- package/src/shared/hooks/factories/generation-hook-index.ts +12 -0
- package/src/shared/hooks/factories/generation-hook-types.ts +47 -0
- package/src/shared/hooks/factories/generation-hook-utils.ts +94 -0
- package/src/shared/hooks/factories/index.ts +1 -1
- package/src/shared/index.ts +1 -1
- package/src/shared/utils/calculations/aspect-ratio-calculations.ts +30 -0
- package/src/shared/utils/calculations/base64-calculations.ts +26 -0
- package/src/shared/utils/calculations/confidence-calculations.ts +21 -0
- package/src/shared/utils/calculations/cost-calculations-index.ts +43 -0
- package/src/shared/utils/calculations/cost-calculations.ts +25 -0
- package/src/shared/utils/calculations/credit-calculations.ts +37 -0
- package/src/shared/utils/calculations/index.ts +46 -0
- package/src/shared/utils/calculations/math-utilities.ts +32 -0
- package/src/shared/utils/calculations/memory-calculations.ts +33 -0
- package/src/shared/utils/calculations/pagination-calculations.ts +38 -0
- package/src/shared/utils/calculations/percentage-calculations.ts +33 -0
- package/src/shared/utils/calculations/time-calculations.ts +99 -0
- package/src/shared/utils/credit.ts +1 -1
- package/src/shared-kernel/application/hooks/index.ts +8 -0
- package/src/shared-kernel/application/hooks/use-feature-state.ts +106 -0
- package/src/shared-kernel/application/hooks/use-generation-handler.ts +110 -0
- package/src/shared-kernel/base-types/base-callbacks.types.ts +73 -0
- package/src/shared-kernel/base-types/base-feature-state.types.ts +77 -0
- package/src/shared-kernel/base-types/base-generation.types.ts +69 -0
- package/src/shared-kernel/base-types/index.ts +30 -0
- package/src/shared-kernel/domain/base-generation-strategy.ts +146 -0
- package/src/shared-kernel/domain/index.ts +7 -0
- package/src/shared-kernel/index.ts +17 -0
- package/src/shared-kernel/infrastructure/validation/common-validators.ts +126 -0
- package/src/shared-kernel/infrastructure/validation/common-validators.types.ts +33 -0
- package/src/shared-kernel/infrastructure/validation/error-handler.ts +52 -0
- package/src/shared-kernel/infrastructure/validation/error-handler.types.ts +38 -0
- package/src/shared-kernel/infrastructure/validation/error-handler.utils.ts +79 -0
- package/src/shared-kernel/infrastructure/validation/index.ts +70 -0
- package/src/domains/content-moderation/infrastructure/services/index.ts +0 -8
- package/src/domains/creations/domain/constants/index.ts +0 -12
- package/src/domains/creations/domain/utils/index.ts +0 -12
- package/src/domains/generation/infrastructure/couple-generation-builder.ts +0 -374
- package/src/domains/image-to-video/domain/index.ts +0 -2
- package/src/domains/image-to-video/infrastructure/index.ts +0 -1
- package/src/domains/image-to-video/presentation/index.ts +0 -5
- package/src/domains/text-to-video/domain/index.ts +0 -1
- package/src/domains/text-to-video/presentation/index.ts +0 -7
- package/src/presentation/hooks/generation/orchestrator.ts +0 -276
- package/src/shared/hooks/factories/createGenerationHook.ts +0 -253
- package/src/shared/utils/calculations.util.ts +0 -366
package/src/domains/generation/wizard/presentation/hooks/photo-upload/usePhotoUploadStateLogic.ts
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic Photo Upload State Hook - Core Logic
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { useCallback, useRef, useEffect } from "react";
|
|
6
|
+
import { useMedia, MediaQuality, MediaValidationError, MEDIA_CONSTANTS } from "@umituz/react-native-design-system/media";
|
|
7
|
+
import type { UploadedImage } from "../../../../presentation/hooks/generation/useAIGenerateState";
|
|
8
|
+
import type { PhotoUploadConfig, PhotoUploadError, PhotoUploadTranslations } from "./types";
|
|
9
|
+
|
|
10
|
+
export function usePhotoUploadStateLogic(
|
|
11
|
+
config: PhotoUploadConfig | undefined,
|
|
12
|
+
translations: PhotoUploadTranslations,
|
|
13
|
+
initialImage: UploadedImage | undefined,
|
|
14
|
+
stepId: string | undefined,
|
|
15
|
+
onError: ((error: PhotoUploadError) => void) | undefined,
|
|
16
|
+
setImage: (image: UploadedImage | null) => void,
|
|
17
|
+
) {
|
|
18
|
+
const { pickImage, isLoading } = useMedia();
|
|
19
|
+
const timeoutRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);
|
|
20
|
+
|
|
21
|
+
// Use refs to avoid effect re-runs on callback changes
|
|
22
|
+
const onErrorRef = useRef(onError);
|
|
23
|
+
const translationsRef = useRef(translations);
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
onErrorRef.current = onError;
|
|
27
|
+
translationsRef.current = translations;
|
|
28
|
+
}, [onError, translations]);
|
|
29
|
+
|
|
30
|
+
const maxFileSizeMB = config?.maxFileSizeMB ?? MEDIA_CONSTANTS.MAX_IMAGE_SIZE_MB;
|
|
31
|
+
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
34
|
+
console.log("[usePhotoUploadState] Step changed, resetting image", { stepId, hasInitialImage: !!initialImage });
|
|
35
|
+
}
|
|
36
|
+
setImage(initialImage || null);
|
|
37
|
+
}, [stepId, initialImage, setImage]);
|
|
38
|
+
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
// Clear any existing timeout first
|
|
41
|
+
if (timeoutRef.current) {
|
|
42
|
+
clearTimeout(timeoutRef.current);
|
|
43
|
+
timeoutRef.current = undefined;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (isLoading) {
|
|
47
|
+
timeoutRef.current = setTimeout(() => {
|
|
48
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
49
|
+
console.warn("[usePhotoUploadState] Image picker timeout - possible stuck state (DEV warning only)");
|
|
50
|
+
}
|
|
51
|
+
// NOTE: Do NOT call onError here — the picker may still complete successfully.
|
|
52
|
+
// Showing a modal alert while the picker is open blocks the UI.
|
|
53
|
+
}, 30000);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return () => {
|
|
57
|
+
if (timeoutRef.current) {
|
|
58
|
+
clearTimeout(timeoutRef.current);
|
|
59
|
+
timeoutRef.current = undefined;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
}, [isLoading]);
|
|
63
|
+
|
|
64
|
+
const clearImage = useCallback(() => {
|
|
65
|
+
setImage(null);
|
|
66
|
+
}, [setImage]);
|
|
67
|
+
|
|
68
|
+
const handlePickImage = useCallback(async () => {
|
|
69
|
+
try {
|
|
70
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
71
|
+
console.log("[usePhotoUploadState] Starting image pick");
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const result = await pickImage({
|
|
75
|
+
allowsEditing: true,
|
|
76
|
+
aspect: [1, 1],
|
|
77
|
+
quality: MediaQuality.MEDIUM,
|
|
78
|
+
maxFileSizeMB,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
if (result.error) {
|
|
82
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
83
|
+
console.log("[usePhotoUploadState] Validation error", result.error);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (result.error === MediaValidationError.FILE_TOO_LARGE) {
|
|
87
|
+
onErrorRef.current?.({
|
|
88
|
+
title: translationsRef.current.fileTooLarge,
|
|
89
|
+
message: translationsRef.current.maxFileSize.replace("{size}", maxFileSizeMB.toString()),
|
|
90
|
+
});
|
|
91
|
+
} else if (result.error === MediaValidationError.PERMISSION_DENIED) {
|
|
92
|
+
onErrorRef.current?.({
|
|
93
|
+
title: translationsRef.current.error,
|
|
94
|
+
message: translationsRef.current.permissionDenied ?? "Permission to access media library is required",
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (result.canceled || !result.assets || result.assets.length === 0) {
|
|
101
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
102
|
+
console.log("[usePhotoUploadState] Image pick canceled");
|
|
103
|
+
}
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const selectedAsset = result.assets[0];
|
|
108
|
+
if (!selectedAsset) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const uploadedImage: UploadedImage = {
|
|
113
|
+
uri: selectedAsset.uri,
|
|
114
|
+
previewUrl: selectedAsset.uri,
|
|
115
|
+
width: selectedAsset.width,
|
|
116
|
+
height: selectedAsset.height,
|
|
117
|
+
fileSize: selectedAsset.fileSize,
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
setImage(uploadedImage);
|
|
121
|
+
|
|
122
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
123
|
+
const fileSizeMB = (selectedAsset.fileSize ?? 0) / (1024 * 1024);
|
|
124
|
+
console.log("[usePhotoUploadState] Image selected", {
|
|
125
|
+
width: uploadedImage.width,
|
|
126
|
+
height: uploadedImage.height,
|
|
127
|
+
fileSizeMB: fileSizeMB.toFixed(2),
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
} catch (error) {
|
|
131
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
132
|
+
console.error("[usePhotoUploadState] Error picking image", error);
|
|
133
|
+
}
|
|
134
|
+
onErrorRef.current?.({
|
|
135
|
+
title: translationsRef.current.error,
|
|
136
|
+
message: translationsRef.current.uploadFailed,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}, [pickImage, maxFileSizeMB, setImage]);
|
|
140
|
+
|
|
141
|
+
return { handlePickImage, clearImage, isLoading };
|
|
142
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Video Queue Generation Hook - Utility Functions
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { GenerationUrls } from "./generation-result.utils";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Clear polling interval
|
|
9
|
+
*/
|
|
10
|
+
export function createClearPolling(
|
|
11
|
+
pollingRef: React.MutableRefObject<ReturnType<typeof setInterval> | null>
|
|
12
|
+
) {
|
|
13
|
+
return () => {
|
|
14
|
+
if (pollingRef.current) {
|
|
15
|
+
clearInterval(pollingRef.current);
|
|
16
|
+
pollingRef.current = null;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Reset all refs to initial state
|
|
23
|
+
*/
|
|
24
|
+
export function createResetRefs(
|
|
25
|
+
clearPolling: () => void,
|
|
26
|
+
creationIdRef: React.MutableRefObject<string | null>,
|
|
27
|
+
requestIdRef: React.MutableRefObject<string | null>,
|
|
28
|
+
modelRef: React.MutableRefObject<string | null>,
|
|
29
|
+
isGeneratingRef: React.MutableRefObject<boolean>,
|
|
30
|
+
isPollingRef: React.MutableRefObject<boolean>,
|
|
31
|
+
consecutiveErrorsRef: React.MutableRefObject<number>,
|
|
32
|
+
pollStartTimeRef: React.MutableRefObject<number | null>,
|
|
33
|
+
setIsGenerating: (value: boolean) => void
|
|
34
|
+
) {
|
|
35
|
+
return () => {
|
|
36
|
+
clearPolling();
|
|
37
|
+
creationIdRef.current = null;
|
|
38
|
+
requestIdRef.current = null;
|
|
39
|
+
modelRef.current = null;
|
|
40
|
+
isGeneratingRef.current = false;
|
|
41
|
+
isPollingRef.current = false;
|
|
42
|
+
consecutiveErrorsRef.current = 0;
|
|
43
|
+
pollStartTimeRef.current = null;
|
|
44
|
+
setIsGenerating(false);
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Extract duration, resolution, and aspect ratio from input
|
|
50
|
+
*/
|
|
51
|
+
export function extractInputMetadata(input: unknown): {
|
|
52
|
+
duration?: number;
|
|
53
|
+
resolution?: string;
|
|
54
|
+
aspectRatio?: string;
|
|
55
|
+
} {
|
|
56
|
+
const inputData = input as Record<string, unknown>;
|
|
57
|
+
return {
|
|
58
|
+
duration: typeof inputData?.duration === "number" ? inputData.duration : undefined,
|
|
59
|
+
resolution: typeof inputData?.resolution === "string" ? inputData.resolution : undefined,
|
|
60
|
+
aspectRatio: typeof inputData?.aspectRatio === "string" ? inputData.aspectRatio : undefined,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Validate completion data
|
|
66
|
+
*/
|
|
67
|
+
export function validateCompletionData(
|
|
68
|
+
creationId: string | null,
|
|
69
|
+
userId: string | null,
|
|
70
|
+
uri: string
|
|
71
|
+
): boolean {
|
|
72
|
+
return !!(creationId && userId && uri && uri.trim() !== "");
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Log completion data for debugging
|
|
77
|
+
*/
|
|
78
|
+
export function logCompletion(
|
|
79
|
+
creationId: string | null,
|
|
80
|
+
userId: string | null,
|
|
81
|
+
urls: GenerationUrls,
|
|
82
|
+
hasOnSuccess: boolean
|
|
83
|
+
): void {
|
|
84
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
85
|
+
console.log("[VideoQueue] ✅ handleComplete called", {
|
|
86
|
+
creationId,
|
|
87
|
+
userId,
|
|
88
|
+
hasVideoUrl: !!urls.videoUrl,
|
|
89
|
+
hasImageUrl: !!urls.imageUrl,
|
|
90
|
+
hasOnSuccess,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Log error for debugging
|
|
97
|
+
*/
|
|
98
|
+
export function logError(message: string, data: Record<string, unknown>): void {
|
|
99
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
100
|
+
console.error("[VideoQueue] ❌", message, data);
|
|
101
|
+
}
|
|
102
|
+
}
|
package/src/domains/generation/wizard/presentation/hooks/usePhotoBlockingGeneration.handlers.ts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* usePhotoBlockingGeneration Handlers
|
|
3
|
+
* Success and error handlers for photo blocking generation
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { CreationPersistence } from "../../infrastructure/utils/creation-persistence.util";
|
|
7
|
+
|
|
8
|
+
interface HandleSuccessProps {
|
|
9
|
+
readonly creationIdRef: React.MutableRefObject<string | null>;
|
|
10
|
+
readonly userId: string | undefined;
|
|
11
|
+
readonly persistence: CreationPersistence;
|
|
12
|
+
readonly deductCredits?: (cost: number) => Promise<boolean>;
|
|
13
|
+
readonly creditCost?: number;
|
|
14
|
+
readonly onSuccess?: (result: unknown) => void;
|
|
15
|
+
readonly onCreditsExhausted?: () => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface HandleErrorProps {
|
|
19
|
+
readonly creationIdRef: React.MutableRefObject<string | null>;
|
|
20
|
+
readonly userId: string | undefined;
|
|
21
|
+
readonly persistence: CreationPersistence;
|
|
22
|
+
readonly onError?: (error: string) => void;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function createSuccessHandler(props: HandleSuccessProps) {
|
|
26
|
+
const {
|
|
27
|
+
creationIdRef,
|
|
28
|
+
userId,
|
|
29
|
+
persistence,
|
|
30
|
+
deductCredits,
|
|
31
|
+
creditCost,
|
|
32
|
+
onSuccess,
|
|
33
|
+
onCreditsExhausted,
|
|
34
|
+
} = props;
|
|
35
|
+
|
|
36
|
+
return async (result: unknown) => {
|
|
37
|
+
const typedResult = result as { imageUrl?: string; videoUrl?: string; audioUrl?: string; logSessionId?: string };
|
|
38
|
+
const creationId = creationIdRef.current;
|
|
39
|
+
const resultUri = typedResult.imageUrl || typedResult.videoUrl || typedResult.audioUrl;
|
|
40
|
+
|
|
41
|
+
if (creationId && userId && resultUri) {
|
|
42
|
+
try {
|
|
43
|
+
await persistence.updateToCompleted(userId, creationId, {
|
|
44
|
+
uri: resultUri,
|
|
45
|
+
imageUrl: typedResult.imageUrl,
|
|
46
|
+
videoUrl: typedResult.videoUrl,
|
|
47
|
+
audioUrl: typedResult.audioUrl,
|
|
48
|
+
logSessionId: typedResult.logSessionId,
|
|
49
|
+
});
|
|
50
|
+
} catch (err) {
|
|
51
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
52
|
+
console.error("[PhotoBlockingGeneration] updateToCompleted error:", err);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
creationIdRef.current = null;
|
|
58
|
+
|
|
59
|
+
// Deduct credits after successful generation
|
|
60
|
+
if (deductCredits && creditCost) {
|
|
61
|
+
try {
|
|
62
|
+
const deducted = await deductCredits(creditCost);
|
|
63
|
+
if (!deducted) {
|
|
64
|
+
onCreditsExhausted?.();
|
|
65
|
+
}
|
|
66
|
+
} catch (err) {
|
|
67
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
68
|
+
console.error("[PhotoBlockingGeneration] deductCredits error:", err);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
onSuccess?.(result);
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function createErrorHandler(props: HandleErrorProps) {
|
|
78
|
+
const { creationIdRef, userId, persistence, onError } = props;
|
|
79
|
+
|
|
80
|
+
return async (err: { message: string; originalError?: Error & { logSessionId?: string } }) => {
|
|
81
|
+
const creationId = creationIdRef.current;
|
|
82
|
+
const logSessionId = err.originalError?.logSessionId;
|
|
83
|
+
|
|
84
|
+
if (creationId && userId) {
|
|
85
|
+
try {
|
|
86
|
+
await persistence.updateToFailed(userId, creationId, err.message, logSessionId);
|
|
87
|
+
} catch (updateErr) {
|
|
88
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
89
|
+
console.error("[PhotoBlockingGeneration] updateToFailed error:", updateErr);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
creationIdRef.current = null;
|
|
95
|
+
onError?.(err.message);
|
|
96
|
+
};
|
|
97
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* usePhotoBlockingGeneration Saver
|
|
3
|
+
* Handles saving creation to processing state
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { CreationPersistence } from "../../infrastructure/utils/creation-persistence.util";
|
|
7
|
+
import type { WizardScenarioData } from "./wizard-generation.types";
|
|
8
|
+
|
|
9
|
+
interface SaveCreationProps {
|
|
10
|
+
readonly userId: string | undefined;
|
|
11
|
+
readonly scenario: WizardScenarioData;
|
|
12
|
+
readonly persistence: CreationPersistence;
|
|
13
|
+
readonly creditCost?: number;
|
|
14
|
+
readonly creationIdRef: React.MutableRefObject<string | null>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export async function saveCreationToProcessing(
|
|
18
|
+
props: SaveCreationProps,
|
|
19
|
+
input: unknown,
|
|
20
|
+
prompt: string,
|
|
21
|
+
): Promise<void> {
|
|
22
|
+
const { userId, scenario, persistence, creditCost, creationIdRef } = props;
|
|
23
|
+
|
|
24
|
+
if (!userId || !prompt) return;
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
// Extract generation parameters from input (for image generation, no duration/resolution)
|
|
28
|
+
const inputData = input as Record<string, unknown>;
|
|
29
|
+
const duration = typeof inputData?.duration === "number" ? inputData.duration : undefined;
|
|
30
|
+
const resolution = typeof inputData?.resolution === "string" ? inputData.resolution : undefined;
|
|
31
|
+
const aspectRatio = typeof inputData?.aspectRatio === "string" ? inputData.aspectRatio : undefined;
|
|
32
|
+
|
|
33
|
+
const result = await persistence.saveAsProcessing(userId, {
|
|
34
|
+
scenarioId: scenario.id,
|
|
35
|
+
scenarioTitle: scenario.title || scenario.id,
|
|
36
|
+
prompt,
|
|
37
|
+
duration,
|
|
38
|
+
resolution,
|
|
39
|
+
creditCost,
|
|
40
|
+
aspectRatio,
|
|
41
|
+
provider: scenario.providerId ?? "fal",
|
|
42
|
+
outputType: scenario.outputType,
|
|
43
|
+
});
|
|
44
|
+
creationIdRef.current = result.creationId;
|
|
45
|
+
|
|
46
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
47
|
+
console.log("[PhotoBlockingGeneration] Saved as processing:", result.creationId);
|
|
48
|
+
}
|
|
49
|
+
} catch (err) {
|
|
50
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
51
|
+
console.error("[PhotoBlockingGeneration] saveAsProcessing error:", err);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -12,6 +12,8 @@ import type { CreationPersistence } from "../../infrastructure/utils/creation-pe
|
|
|
12
12
|
import type { WizardStrategy } from "../../infrastructure/strategies/wizard-strategy.types";
|
|
13
13
|
import type { WizardScenarioData } from "./wizard-generation.types";
|
|
14
14
|
import type { AlertMessages } from "../../../../../presentation/hooks/generation/types";
|
|
15
|
+
import { createSuccessHandler, createErrorHandler } from "./usePhotoBlockingGeneration.handlers";
|
|
16
|
+
import { saveCreationToProcessing } from "./usePhotoBlockingGeneration.saver";
|
|
15
17
|
|
|
16
18
|
|
|
17
19
|
interface UsePhotoBlockingGenerationProps {
|
|
@@ -51,66 +53,25 @@ export function usePhotoBlockingGeneration(
|
|
|
51
53
|
const creationIdRef = useRef<string | null>(null);
|
|
52
54
|
|
|
53
55
|
const handleSuccess = useCallback(
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
imageUrl: typedResult.imageUrl,
|
|
64
|
-
videoUrl: typedResult.videoUrl,
|
|
65
|
-
audioUrl: typedResult.audioUrl,
|
|
66
|
-
logSessionId: typedResult.logSessionId,
|
|
67
|
-
});
|
|
68
|
-
} catch (err) {
|
|
69
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
70
|
-
console.error("[PhotoBlockingGeneration] updateToCompleted error:", err);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
creationIdRef.current = null;
|
|
76
|
-
|
|
77
|
-
// Deduct credits after successful generation
|
|
78
|
-
if (deductCredits && creditCost) {
|
|
79
|
-
try {
|
|
80
|
-
const deducted = await deductCredits(creditCost);
|
|
81
|
-
if (!deducted) {
|
|
82
|
-
onCreditsExhausted?.();
|
|
83
|
-
}
|
|
84
|
-
} catch (err) {
|
|
85
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
86
|
-
console.error("[PhotoBlockingGeneration] deductCredits error:", err);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
onSuccess?.(result);
|
|
92
|
-
},
|
|
56
|
+
createSuccessHandler({
|
|
57
|
+
creationIdRef,
|
|
58
|
+
userId,
|
|
59
|
+
persistence,
|
|
60
|
+
deductCredits,
|
|
61
|
+
creditCost,
|
|
62
|
+
onSuccess,
|
|
63
|
+
onCreditsExhausted,
|
|
64
|
+
}),
|
|
93
65
|
[userId, persistence, deductCredits, creditCost, onSuccess, onCreditsExhausted],
|
|
94
66
|
);
|
|
95
67
|
|
|
96
68
|
const handleError = useCallback(
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
await persistence.updateToFailed(userId, creationId, err.message, logSessionId);
|
|
104
|
-
} catch (updateErr) {
|
|
105
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
106
|
-
console.error("[PhotoBlockingGeneration] updateToFailed error:", updateErr);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
creationIdRef.current = null;
|
|
112
|
-
onError?.(err.message);
|
|
113
|
-
},
|
|
69
|
+
createErrorHandler({
|
|
70
|
+
creationIdRef,
|
|
71
|
+
userId,
|
|
72
|
+
persistence,
|
|
73
|
+
onError,
|
|
74
|
+
}),
|
|
114
75
|
[userId, persistence, onError],
|
|
115
76
|
);
|
|
116
77
|
|
|
@@ -124,37 +85,11 @@ export function usePhotoBlockingGeneration(
|
|
|
124
85
|
const startGeneration = useCallback(
|
|
125
86
|
async (input: unknown, prompt: string) => {
|
|
126
87
|
// Save to Firestore first
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
const resolution = typeof inputData?.resolution === "string" ? inputData.resolution : undefined;
|
|
133
|
-
|
|
134
|
-
const aspectRatio = typeof inputData?.aspectRatio === "string" ? inputData.aspectRatio : undefined;
|
|
135
|
-
|
|
136
|
-
const result = await persistence.saveAsProcessing(userId, {
|
|
137
|
-
scenarioId: scenario.id,
|
|
138
|
-
scenarioTitle: scenario.title || scenario.id,
|
|
139
|
-
prompt,
|
|
140
|
-
duration,
|
|
141
|
-
resolution,
|
|
142
|
-
creditCost,
|
|
143
|
-
aspectRatio,
|
|
144
|
-
provider: scenario.providerId ?? "fal",
|
|
145
|
-
outputType: scenario.outputType,
|
|
146
|
-
});
|
|
147
|
-
creationIdRef.current = result.creationId;
|
|
148
|
-
|
|
149
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
150
|
-
console.log("[PhotoBlockingGeneration] Saved as processing:", result.creationId);
|
|
151
|
-
}
|
|
152
|
-
} catch (err) {
|
|
153
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
154
|
-
console.error("[PhotoBlockingGeneration] saveAsProcessing error:", err);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
88
|
+
await saveCreationToProcessing(
|
|
89
|
+
{ userId, scenario, persistence, creditCost, creationIdRef },
|
|
90
|
+
input,
|
|
91
|
+
prompt,
|
|
92
|
+
);
|
|
158
93
|
|
|
159
94
|
// Start blocking generation
|
|
160
95
|
await generate(input);
|