@umituz/react-native-ai-generation-content 1.90.2 → 1.90.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/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/domains/background/infrastructure/services/job-poller-index.ts +7 -0
- package/src/domains/background/infrastructure/services/job-poller-utils.ts +130 -0
- 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/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/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 +5 -111
- 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/screens/CreationsGalleryScreen.tsx +1 -1
- 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/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 +113 -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 +75 -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 +42 -0
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation-executor-index.ts +11 -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 +62 -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 -175
- 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 -129
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation.validation.ts +136 -0
- package/src/domains/generation/wizard/presentation/hooks/photo-upload/index.ts +39 -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 +103 -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 +82 -0
- package/src/domains/generation/wizard/presentation/hooks/video-queue/useVideoQueueGenerationCallbacks.ts +120 -0
- package/src/domains/generation/wizard/presentation/hooks/video-queue/useVideoQueueGenerationPolling.ts +76 -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/types/text-to-image.types.ts +44 -22
- package/src/domains/text-to-video/domain/types/request.types.ts +33 -9
- package/src/domains/text-to-video/domain/types/state.types.ts +29 -9
- 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/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 +8 -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 +14 -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 +1 -27
- 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 +107 -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 +28 -0
- package/src/domains/background/infrastructure/services/job-poller.service.ts +0 -234
- package/src/domains/creations/presentation/hooks/useProcessingJobsPoller.ts +0 -256
- package/src/domains/generation/infrastructure/couple-generation-builder.ts +0 -374
- 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
|
@@ -2,298 +2,4 @@
|
|
|
2
2
|
* Video Queue Generation Hook
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import { pollQueueStatus } from "./videoQueuePoller";
|
|
8
|
-
import {
|
|
9
|
-
DEFAULT_POLL_INTERVAL_MS,
|
|
10
|
-
DEFAULT_MAX_POLL_TIME_MS,
|
|
11
|
-
} from "../../../../../infrastructure/constants/polling.constants";
|
|
12
|
-
import type { GenerationUrls } from "./generation-result.utils";
|
|
13
|
-
import type {
|
|
14
|
-
UseVideoQueueGenerationProps,
|
|
15
|
-
UseVideoQueueGenerationReturn,
|
|
16
|
-
} from "./use-video-queue-generation.types";
|
|
17
|
-
|
|
18
|
-
export function useVideoQueueGeneration(props: UseVideoQueueGenerationProps): UseVideoQueueGenerationReturn {
|
|
19
|
-
const { userId, scenario, persistence, strategy, creditCost, deductCredits, onSuccess, onError } = props;
|
|
20
|
-
|
|
21
|
-
const creationIdRef = useRef<string | null>(null);
|
|
22
|
-
const requestIdRef = useRef<string | null>(null);
|
|
23
|
-
const modelRef = useRef<string | null>(null);
|
|
24
|
-
const pollingRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
|
25
|
-
const isGeneratingRef = useRef(false);
|
|
26
|
-
const isPollingRef = useRef(false);
|
|
27
|
-
const consecutiveErrorsRef = useRef(0);
|
|
28
|
-
const pollStartTimeRef = useRef<number | null>(null);
|
|
29
|
-
const [isGenerating, setIsGenerating] = useState(false);
|
|
30
|
-
|
|
31
|
-
const clearPolling = useCallback(() => {
|
|
32
|
-
if (pollingRef.current) {
|
|
33
|
-
clearInterval(pollingRef.current);
|
|
34
|
-
pollingRef.current = null;
|
|
35
|
-
}
|
|
36
|
-
}, []);
|
|
37
|
-
|
|
38
|
-
useEffect(() => {
|
|
39
|
-
return () => {
|
|
40
|
-
clearPolling();
|
|
41
|
-
isGeneratingRef.current = false;
|
|
42
|
-
isPollingRef.current = false;
|
|
43
|
-
consecutiveErrorsRef.current = 0;
|
|
44
|
-
pollStartTimeRef.current = null;
|
|
45
|
-
// NOTE: Do NOT null creationIdRef/requestIdRef/modelRef here.
|
|
46
|
-
// In-flight poll callbacks may still resolve after unmount and need
|
|
47
|
-
// these refs to properly save the completed generation to Firestore.
|
|
48
|
-
// They are cleaned up by resetRefs() after handleComplete/handleError.
|
|
49
|
-
setIsGenerating(false);
|
|
50
|
-
};
|
|
51
|
-
}, [clearPolling]);
|
|
52
|
-
|
|
53
|
-
const resetRefs = useCallback(() => {
|
|
54
|
-
clearPolling();
|
|
55
|
-
creationIdRef.current = null;
|
|
56
|
-
requestIdRef.current = null;
|
|
57
|
-
modelRef.current = null;
|
|
58
|
-
isGeneratingRef.current = false;
|
|
59
|
-
isPollingRef.current = false;
|
|
60
|
-
consecutiveErrorsRef.current = 0;
|
|
61
|
-
pollStartTimeRef.current = null;
|
|
62
|
-
setIsGenerating(false);
|
|
63
|
-
}, [clearPolling]);
|
|
64
|
-
|
|
65
|
-
const handleComplete = useCallback(
|
|
66
|
-
async (urls: GenerationUrls) => {
|
|
67
|
-
clearPolling();
|
|
68
|
-
|
|
69
|
-
const creationId = creationIdRef.current;
|
|
70
|
-
const uri = (urls.videoUrl || urls.imageUrl) ?? "";
|
|
71
|
-
|
|
72
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
73
|
-
console.log("[VideoQueue] ✅ handleComplete called", {
|
|
74
|
-
creationId,
|
|
75
|
-
userId,
|
|
76
|
-
hasVideoUrl: !!urls.videoUrl,
|
|
77
|
-
hasImageUrl: !!urls.imageUrl,
|
|
78
|
-
hasOnSuccess: !!onSuccess
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (!creationId || !userId || !uri || uri.trim() === "") {
|
|
83
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
84
|
-
console.error("[VideoQueue] ❌ Invalid completion data:", { creationId, userId, uri });
|
|
85
|
-
}
|
|
86
|
-
resetRefs();
|
|
87
|
-
onError?.("Invalid completion data - no valid URL received");
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
let persistenceSucceeded = true;
|
|
92
|
-
if (creationId && userId) {
|
|
93
|
-
try {
|
|
94
|
-
await persistence.updateToCompleted(userId, creationId, {
|
|
95
|
-
uri,
|
|
96
|
-
imageUrl: urls.imageUrl,
|
|
97
|
-
videoUrl: urls.videoUrl,
|
|
98
|
-
thumbnailUrl: urls.thumbnailUrl,
|
|
99
|
-
generationStartedAt: pollStartTimeRef.current ?? undefined,
|
|
100
|
-
});
|
|
101
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
102
|
-
console.log("[VideoQueue] ✅ Updated completion status in Firestore");
|
|
103
|
-
}
|
|
104
|
-
} catch (error) {
|
|
105
|
-
persistenceSucceeded = false;
|
|
106
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
107
|
-
console.error("[VideoQueue] ❌ Failed to update completion status:", error);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
resetRefs();
|
|
113
|
-
|
|
114
|
-
// Deduct credits after successful generation
|
|
115
|
-
if (deductCredits && creditCost) {
|
|
116
|
-
await deductCredits(creditCost).catch((err) => {
|
|
117
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
118
|
-
console.error("[VideoQueue] deductCredits error:", err);
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
124
|
-
console.log("[VideoQueue] 🎯 Calling onSuccess callback now...", { persistenceSucceeded });
|
|
125
|
-
}
|
|
126
|
-
onSuccess?.(urls);
|
|
127
|
-
|
|
128
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
129
|
-
console.log("[VideoQueue] ✅ onSuccess callback completed");
|
|
130
|
-
}
|
|
131
|
-
},
|
|
132
|
-
[userId, persistence, deductCredits, creditCost, onSuccess, onError, resetRefs, clearPolling],
|
|
133
|
-
);
|
|
134
|
-
|
|
135
|
-
const handleError = useCallback(
|
|
136
|
-
async (errorMsg: string) => {
|
|
137
|
-
clearPolling();
|
|
138
|
-
const creationId = creationIdRef.current;
|
|
139
|
-
if (creationId && userId) {
|
|
140
|
-
try {
|
|
141
|
-
await persistence.updateToFailed(userId, creationId, errorMsg);
|
|
142
|
-
} catch (error) {
|
|
143
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
144
|
-
console.error("[VideoQueue] Failed to update error status:", error);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
resetRefs();
|
|
149
|
-
onError?.(errorMsg);
|
|
150
|
-
},
|
|
151
|
-
[userId, persistence, onError, resetRefs, clearPolling],
|
|
152
|
-
);
|
|
153
|
-
|
|
154
|
-
// Use a ref to hold the latest handleComplete/handleError to avoid stale closures
|
|
155
|
-
// in the setInterval callback
|
|
156
|
-
const handleCompleteRef = useRef(handleComplete);
|
|
157
|
-
const handleErrorRef = useRef(handleError);
|
|
158
|
-
useEffect(() => { handleCompleteRef.current = handleComplete; }, [handleComplete]);
|
|
159
|
-
useEffect(() => { handleErrorRef.current = handleError; }, [handleError]);
|
|
160
|
-
|
|
161
|
-
const pollStatus = useCallback(async () => {
|
|
162
|
-
const requestId = requestIdRef.current;
|
|
163
|
-
const model = modelRef.current;
|
|
164
|
-
if (!requestId || !model) return;
|
|
165
|
-
|
|
166
|
-
// Check max poll time
|
|
167
|
-
if (pollStartTimeRef.current !== null) {
|
|
168
|
-
const elapsed = Date.now() - pollStartTimeRef.current;
|
|
169
|
-
if (elapsed >= DEFAULT_MAX_POLL_TIME_MS) {
|
|
170
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
171
|
-
console.warn("[VideoQueue] ⏰ Max poll time exceeded, aborting");
|
|
172
|
-
}
|
|
173
|
-
await handleErrorRef.current("Generation timed out. Please try again.");
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
try {
|
|
179
|
-
await pollQueueStatus({
|
|
180
|
-
requestId,
|
|
181
|
-
model,
|
|
182
|
-
isPollingRef,
|
|
183
|
-
pollingRef,
|
|
184
|
-
consecutiveErrorsRef,
|
|
185
|
-
onComplete: handleCompleteRef.current,
|
|
186
|
-
onError: handleErrorRef.current,
|
|
187
|
-
});
|
|
188
|
-
} catch (error) {
|
|
189
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
190
|
-
console.error("[VideoQueue] Unexpected poll error:", error);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}, []);
|
|
194
|
-
|
|
195
|
-
// Keep a stable ref to pollStatus for the setInterval closure
|
|
196
|
-
const pollStatusRef = useRef(pollStatus);
|
|
197
|
-
useEffect(() => { pollStatusRef.current = pollStatus; }, [pollStatus]);
|
|
198
|
-
|
|
199
|
-
const startGeneration = useCallback(
|
|
200
|
-
async (input: unknown, prompt: string) => {
|
|
201
|
-
if (!strategy.submitToQueue) {
|
|
202
|
-
onError?.("Queue submission not available");
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
if (isGeneratingRef.current) return;
|
|
206
|
-
|
|
207
|
-
isGeneratingRef.current = true;
|
|
208
|
-
setIsGenerating(true);
|
|
209
|
-
|
|
210
|
-
let creationId: string | null = null;
|
|
211
|
-
if (userId && prompt) {
|
|
212
|
-
try {
|
|
213
|
-
const inputData = input as Record<string, unknown>;
|
|
214
|
-
const duration = typeof inputData?.duration === "number" ? inputData.duration : undefined;
|
|
215
|
-
const resolution = typeof inputData?.resolution === "string" ? inputData.resolution : undefined;
|
|
216
|
-
const aspectRatio = typeof inputData?.aspectRatio === "string" ? inputData.aspectRatio : undefined;
|
|
217
|
-
|
|
218
|
-
const result = await persistence.saveAsProcessing(userId, {
|
|
219
|
-
scenarioId: scenario.id,
|
|
220
|
-
scenarioTitle: scenario.title || scenario.id,
|
|
221
|
-
prompt,
|
|
222
|
-
duration,
|
|
223
|
-
resolution,
|
|
224
|
-
creditCost,
|
|
225
|
-
aspectRatio,
|
|
226
|
-
provider: "fal",
|
|
227
|
-
outputType: scenario.outputType,
|
|
228
|
-
});
|
|
229
|
-
creationId = result.creationId;
|
|
230
|
-
creationIdRef.current = creationId;
|
|
231
|
-
// Record the actual DB-level start time for accurate durationMs
|
|
232
|
-
pollStartTimeRef.current = result.startedAt.getTime();
|
|
233
|
-
} catch (error) {
|
|
234
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
235
|
-
console.error("[VideoQueue] Failed to save processing creation:", error);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
let queueResult;
|
|
241
|
-
try {
|
|
242
|
-
queueResult = await strategy.submitToQueue(input);
|
|
243
|
-
} catch (error) {
|
|
244
|
-
if (creationId && userId) {
|
|
245
|
-
try {
|
|
246
|
-
await persistence.updateToFailed(userId, creationId, error instanceof Error ? error.message : "Queue submission failed");
|
|
247
|
-
} catch (persistError) {
|
|
248
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
249
|
-
console.error("[VideoQueue] Failed to persist submission error:", persistError);
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
isGeneratingRef.current = false;
|
|
254
|
-
setIsGenerating(false);
|
|
255
|
-
onError?.(error instanceof Error ? error.message : "Queue submission failed");
|
|
256
|
-
return;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
if (!queueResult.success || !queueResult.requestId || !queueResult.model) {
|
|
260
|
-
if (creationId && userId) {
|
|
261
|
-
try {
|
|
262
|
-
await persistence.updateToFailed(userId, creationId, queueResult.error || "Queue submission failed");
|
|
263
|
-
} catch (persistError) {
|
|
264
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
265
|
-
console.error("[VideoQueue] Failed to persist queue failure:", persistError);
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
isGeneratingRef.current = false;
|
|
270
|
-
setIsGenerating(false);
|
|
271
|
-
onError?.(queueResult.error || "Queue submission failed");
|
|
272
|
-
return;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
requestIdRef.current = queueResult.requestId;
|
|
276
|
-
modelRef.current = queueResult.model;
|
|
277
|
-
|
|
278
|
-
if (creationId && userId && queueResult.requestId && queueResult.model) {
|
|
279
|
-
try {
|
|
280
|
-
await persistence.updateRequestId(userId, creationId, queueResult.requestId, queueResult.model);
|
|
281
|
-
} catch (error) {
|
|
282
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
283
|
-
console.error("[VideoQueue] Failed to update request ID:", error);
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// Start polling: use DB-level startedAt if available, otherwise fallback to now
|
|
289
|
-
if (pollStartTimeRef.current === null) {
|
|
290
|
-
pollStartTimeRef.current = Date.now();
|
|
291
|
-
}
|
|
292
|
-
pollingRef.current = setInterval(() => void pollStatusRef.current(), DEFAULT_POLL_INTERVAL_MS);
|
|
293
|
-
void pollStatusRef.current();
|
|
294
|
-
},
|
|
295
|
-
[userId, scenario, persistence, strategy, creditCost, onError],
|
|
296
|
-
);
|
|
297
|
-
|
|
298
|
-
return { isGenerating, startGeneration };
|
|
299
|
-
}
|
|
5
|
+
export { useVideoQueueGeneration } from "./video-queue";
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { useEffect, useReducer, useMemo, useRef } from "react";
|
|
7
7
|
import { createWizardStrategy } from "../../infrastructure/strategies";
|
|
8
8
|
import { createCreationPersistence } from "../../infrastructure/utils/creation-persistence.util";
|
|
9
|
-
import { useVideoQueueGeneration } from "./
|
|
9
|
+
import { useVideoQueueGeneration } from "./video-queue-index";
|
|
10
10
|
import { usePhotoBlockingGeneration } from "./usePhotoBlockingGeneration";
|
|
11
11
|
import { generationReducer, INITIAL_STATE } from "./generationStateMachine";
|
|
12
12
|
import { executeWizardGeneration } from "./generationExecutor";
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Video Queue Generation Hook
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { useEffect } from "react";
|
|
6
|
+
import type { GenerationUrls } from "../generation-result.utils";
|
|
7
|
+
import type {
|
|
8
|
+
UseVideoQueueGenerationProps,
|
|
9
|
+
UseVideoQueueGenerationReturn,
|
|
10
|
+
} from "../use-video-queue-generation.types";
|
|
11
|
+
import {
|
|
12
|
+
createClearPolling,
|
|
13
|
+
createResetRefs,
|
|
14
|
+
} from "./use-video-queue-utils";
|
|
15
|
+
import { useVideoQueueGenerationRefs, useVideoQueueGenerationState } from "./useVideoQueueGenerationRefs";
|
|
16
|
+
import { useCompletionHandler, useErrorHandler } from "./useVideoQueueGenerationCallbacks";
|
|
17
|
+
import { usePollStatus, useCallbackRefs } from "./useVideoQueueGenerationPolling";
|
|
18
|
+
import { useStartGeneration } from "./useVideoQueueGenerationStart";
|
|
19
|
+
|
|
20
|
+
export function useVideoQueueGeneration(props: UseVideoQueueGenerationProps): UseVideoQueueGenerationReturn {
|
|
21
|
+
const refs = useVideoQueueGenerationRefs();
|
|
22
|
+
const state = useVideoQueueGenerationState();
|
|
23
|
+
|
|
24
|
+
const clearPolling = (() => {
|
|
25
|
+
const { pollingRef } = refs;
|
|
26
|
+
return () => {
|
|
27
|
+
if (pollingRef.current) {
|
|
28
|
+
clearInterval(pollingRef.current);
|
|
29
|
+
pollingRef.current = null;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
})();
|
|
33
|
+
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
return () => {
|
|
36
|
+
clearPolling();
|
|
37
|
+
refs.isGeneratingRef.current = false;
|
|
38
|
+
refs.isPollingRef.current = false;
|
|
39
|
+
refs.consecutiveErrorsRef.current = 0;
|
|
40
|
+
refs.pollStartTimeRef.current = null;
|
|
41
|
+
// NOTE: Do NOT null creationIdRef/requestIdRef/modelRef here.
|
|
42
|
+
// In-flight poll callbacks may still resolve after unmount and need
|
|
43
|
+
// these refs to properly save the completed generation to Firestore.
|
|
44
|
+
// They are cleaned up by resetRefs() after handleComplete/handleError.
|
|
45
|
+
state.setIsGenerating(false);
|
|
46
|
+
};
|
|
47
|
+
}, [clearPolling, refs, state]);
|
|
48
|
+
|
|
49
|
+
const resetRefs = (() => {
|
|
50
|
+
const {
|
|
51
|
+
creationIdRef,
|
|
52
|
+
requestIdRef,
|
|
53
|
+
modelRef,
|
|
54
|
+
isGeneratingRef,
|
|
55
|
+
isPollingRef,
|
|
56
|
+
consecutiveErrorsRef,
|
|
57
|
+
pollStartTimeRef,
|
|
58
|
+
} = refs;
|
|
59
|
+
const { setIsGenerating } = state;
|
|
60
|
+
|
|
61
|
+
return () => {
|
|
62
|
+
creationIdRef.current = null;
|
|
63
|
+
requestIdRef.current = null;
|
|
64
|
+
modelRef.current = null;
|
|
65
|
+
isGeneratingRef.current = false;
|
|
66
|
+
isPollingRef.current = false;
|
|
67
|
+
consecutiveErrorsRef.current = 0;
|
|
68
|
+
pollStartTimeRef.current = null;
|
|
69
|
+
setIsGenerating(false);
|
|
70
|
+
};
|
|
71
|
+
})();
|
|
72
|
+
|
|
73
|
+
const handleComplete = useCompletionHandler(props, refs, state, clearPolling, resetRefs);
|
|
74
|
+
const handleError = useErrorHandler(props, refs, clearPolling, resetRefs);
|
|
75
|
+
const pollStatus = usePollStatus(refs);
|
|
76
|
+
const startGeneration = useStartGeneration(props, refs, state, clearPolling);
|
|
77
|
+
|
|
78
|
+
// Sync callback refs
|
|
79
|
+
useCallbackRefs(handleComplete, handleError, pollStatus, refs);
|
|
80
|
+
|
|
81
|
+
return { isGenerating: state.isGenerating, startGeneration };
|
|
82
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Video Queue Generation Hook - Completion and Error Handlers
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { useCallback } from "react";
|
|
6
|
+
import type { GenerationUrls } from "../../generation-result.utils";
|
|
7
|
+
import type {
|
|
8
|
+
UseVideoQueueGenerationProps,
|
|
9
|
+
} from "../use-video-queue-generation.types";
|
|
10
|
+
import {
|
|
11
|
+
logCompletion,
|
|
12
|
+
logError,
|
|
13
|
+
validateCompletionData,
|
|
14
|
+
} from "./use-video-queue-utils";
|
|
15
|
+
import type { VideoQueueRefs, VideoQueueState } from "./useVideoQueueGenerationRefs";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Create completion handler callback
|
|
19
|
+
*/
|
|
20
|
+
export function useCompletionHandler(
|
|
21
|
+
props: UseVideoQueueGenerationProps,
|
|
22
|
+
refs: VideoQueueRefs,
|
|
23
|
+
state: VideoQueueState,
|
|
24
|
+
clearPolling: () => void,
|
|
25
|
+
resetRefs: () => void,
|
|
26
|
+
) {
|
|
27
|
+
const { userId, persistence, strategy, creditCost, deductCredits, onSuccess, onError } = props;
|
|
28
|
+
const { setIsGenerating } = state;
|
|
29
|
+
|
|
30
|
+
return useCallback(
|
|
31
|
+
async (urls: GenerationUrls) => {
|
|
32
|
+
clearPolling();
|
|
33
|
+
|
|
34
|
+
const creationId = refs.creationIdRef.current;
|
|
35
|
+
const uri = (urls.videoUrl || urls.imageUrl) ?? "";
|
|
36
|
+
|
|
37
|
+
logCompletion(creationId, userId, urls, !!onSuccess);
|
|
38
|
+
|
|
39
|
+
if (!validateCompletionData(creationId, userId, uri)) {
|
|
40
|
+
logError("Invalid completion data:", { creationId, userId, uri });
|
|
41
|
+
resetRefs();
|
|
42
|
+
onError?.("Invalid completion data - no valid URL received");
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
let persistenceSucceeded = true;
|
|
47
|
+
if (creationId && userId) {
|
|
48
|
+
try {
|
|
49
|
+
await persistence.updateToCompleted(userId, creationId, {
|
|
50
|
+
uri,
|
|
51
|
+
imageUrl: urls.imageUrl,
|
|
52
|
+
videoUrl: urls.videoUrl,
|
|
53
|
+
thumbnailUrl: urls.thumbnailUrl,
|
|
54
|
+
generationStartedAt: refs.pollStartTimeRef.current ?? undefined,
|
|
55
|
+
});
|
|
56
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
57
|
+
console.log("[VideoQueue] ✅ Updated completion status in Firestore");
|
|
58
|
+
}
|
|
59
|
+
} catch (error) {
|
|
60
|
+
persistenceSucceeded = false;
|
|
61
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
62
|
+
console.error("[VideoQueue] ❌ Failed to update completion status:", error);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
resetRefs();
|
|
68
|
+
|
|
69
|
+
// Deduct credits after successful generation
|
|
70
|
+
if (deductCredits && creditCost) {
|
|
71
|
+
await deductCredits(creditCost).catch((err) => {
|
|
72
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
73
|
+
console.error("[VideoQueue] deductCredits error:", err);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
79
|
+
console.log("[VideoQueue] 🎯 Calling onSuccess callback now...", { persistenceSucceeded });
|
|
80
|
+
}
|
|
81
|
+
onSuccess?.(urls);
|
|
82
|
+
|
|
83
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
84
|
+
console.log("[VideoQueue] ✅ onSuccess callback completed");
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
[userId, persistence, deductCredits, creditCost, onSuccess, onError, resetRefs, clearPolling, refs],
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Create error handler callback
|
|
93
|
+
*/
|
|
94
|
+
export function useErrorHandler(
|
|
95
|
+
props: UseVideoQueueGenerationProps,
|
|
96
|
+
refs: VideoQueueRefs,
|
|
97
|
+
clearPolling: () => void,
|
|
98
|
+
resetRefs: () => void,
|
|
99
|
+
) {
|
|
100
|
+
const { userId, persistence, onError } = props;
|
|
101
|
+
|
|
102
|
+
return useCallback(
|
|
103
|
+
async (errorMsg: string) => {
|
|
104
|
+
clearPolling();
|
|
105
|
+
const creationId = refs.creationIdRef.current;
|
|
106
|
+
if (creationId && userId) {
|
|
107
|
+
try {
|
|
108
|
+
await persistence.updateToFailed(userId, creationId, errorMsg);
|
|
109
|
+
} catch (error) {
|
|
110
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
111
|
+
console.error("[VideoQueue] Failed to update error status:", error);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
resetRefs();
|
|
116
|
+
onError?.(errorMsg);
|
|
117
|
+
},
|
|
118
|
+
[userId, persistence, onError, resetRefs, clearPolling, refs],
|
|
119
|
+
);
|
|
120
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Video Queue Generation Hook - Polling Logic
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { useCallback, useEffect } from "react";
|
|
6
|
+
import { pollQueueStatus } from "../videoQueuePoller";
|
|
7
|
+
import {
|
|
8
|
+
DEFAULT_POLL_INTERVAL_MS,
|
|
9
|
+
DEFAULT_MAX_POLL_TIME_MS,
|
|
10
|
+
} from "../../../../../infrastructure/constants/polling.constants";
|
|
11
|
+
import type { VideoQueueRefs } from "./useVideoQueueGenerationRefs";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Create poll status callback
|
|
15
|
+
*/
|
|
16
|
+
export function usePollStatus(
|
|
17
|
+
refs: VideoQueueRefs,
|
|
18
|
+
): () => Promise<void> {
|
|
19
|
+
const { requestIdRef, modelRef, isPollingRef, pollingRef, consecutiveErrorsRef, pollStartTimeRef, handleCompleteRef, handleErrorRef } = refs;
|
|
20
|
+
|
|
21
|
+
return useCallback(async () => {
|
|
22
|
+
const requestId = requestIdRef.current;
|
|
23
|
+
const model = modelRef.current;
|
|
24
|
+
if (!requestId || !model) return;
|
|
25
|
+
|
|
26
|
+
// Check max poll time
|
|
27
|
+
if (pollStartTimeRef.current !== null) {
|
|
28
|
+
const elapsed = Date.now() - pollStartTimeRef.current;
|
|
29
|
+
if (elapsed >= DEFAULT_MAX_POLL_TIME_MS) {
|
|
30
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
31
|
+
console.warn("[VideoQueue] ⏰ Max poll time exceeded, aborting");
|
|
32
|
+
}
|
|
33
|
+
await handleErrorRef.current("Generation timed out. Please try again.");
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
await pollQueueStatus({
|
|
40
|
+
requestId,
|
|
41
|
+
model,
|
|
42
|
+
isPollingRef,
|
|
43
|
+
pollingRef,
|
|
44
|
+
consecutiveErrorsRef,
|
|
45
|
+
onComplete: handleCompleteRef.current,
|
|
46
|
+
onError: handleErrorRef.current,
|
|
47
|
+
});
|
|
48
|
+
} catch (error) {
|
|
49
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
50
|
+
console.error("[VideoQueue] Unexpected poll error:", error);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}, [requestIdRef, modelRef, isPollingRef, pollingRef, consecutiveErrorsRef, pollStartTimeRef, handleCompleteRef, handleErrorRef]);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Hook to sync callback refs
|
|
58
|
+
*/
|
|
59
|
+
export function useCallbackRefs(
|
|
60
|
+
handleComplete: (urls: import("../../generation-result.utils").GenerationUrls) => Promise<void>,
|
|
61
|
+
handleError: (errorMsg: string) => Promise<void>,
|
|
62
|
+
pollStatus: () => Promise<void>,
|
|
63
|
+
refs: VideoQueueRefs,
|
|
64
|
+
) {
|
|
65
|
+
useEffect(() => {
|
|
66
|
+
refs.handleCompleteRef.current = handleComplete;
|
|
67
|
+
}, [handleComplete, refs]);
|
|
68
|
+
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
refs.handleErrorRef.current = handleError;
|
|
71
|
+
}, [handleError, refs]);
|
|
72
|
+
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
refs.pollStatusRef.current = pollStatus;
|
|
75
|
+
}, [pollStatus, refs]);
|
|
76
|
+
}
|
package/src/domains/generation/wizard/presentation/hooks/video-queue/useVideoQueueGenerationRefs.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Video Queue Generation Hook - Refs and State Management
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { useRef, useState } from "react";
|
|
6
|
+
|
|
7
|
+
export interface VideoQueueRefs {
|
|
8
|
+
readonly creationIdRef: React.MutableRefObject<string | null>;
|
|
9
|
+
readonly requestIdRef: React.MutableRefObject<string | null>;
|
|
10
|
+
readonly modelRef: React.MutableRefObject<string | null>;
|
|
11
|
+
readonly pollingRef: React.MutableRefObject<ReturnType<typeof setInterval> | null>;
|
|
12
|
+
readonly isGeneratingRef: React.MutableRefObject<boolean>;
|
|
13
|
+
readonly isPollingRef: React.MutableRefObject<boolean>;
|
|
14
|
+
readonly consecutiveErrorsRef: React.MutableRefObject<number>;
|
|
15
|
+
readonly pollStartTimeRef: React.MutableRefObject<number | null>;
|
|
16
|
+
readonly handleCompleteRef: React.MutableRefObject<(urls: import("../generation-result.utils").GenerationUrls) => Promise<void>>;
|
|
17
|
+
readonly handleErrorRef: React.MutableRefObject<(errorMsg: string) => Promise<void>>;
|
|
18
|
+
readonly pollStatusRef: React.MutableRefObject<() => Promise<void>>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface VideoQueueState {
|
|
22
|
+
readonly isGenerating: boolean;
|
|
23
|
+
readonly setIsGenerating: React.Dispatch<React.SetStateAction<boolean>>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Initialize refs for video queue generation
|
|
28
|
+
*/
|
|
29
|
+
export function useVideoQueueGenerationRefs(): VideoQueueRefs {
|
|
30
|
+
const creationIdRef = useRef<string | null>(null);
|
|
31
|
+
const requestIdRef = useRef<string | null>(null);
|
|
32
|
+
const modelRef = useRef<string | null>(null);
|
|
33
|
+
const pollingRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
|
34
|
+
const isGeneratingRef = useRef(false);
|
|
35
|
+
const isPollingRef = useRef(false);
|
|
36
|
+
const consecutiveErrorsRef = useRef(0);
|
|
37
|
+
const pollStartTimeRef = useRef<number | null>(null);
|
|
38
|
+
|
|
39
|
+
// Placeholders for callback refs - will be set by the hook
|
|
40
|
+
const handleCompleteRef = useRef<VideoQueueRefs["handleCompleteRef"]["current"]>(async () => {});
|
|
41
|
+
const handleErrorRef = useRef<VideoQueueRefs["handleErrorRef"]["current"]>(async () => {});
|
|
42
|
+
const pollStatusRef = useRef<VideoQueueRefs["pollStatusRef"]["current"]>(async () => {});
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
creationIdRef,
|
|
46
|
+
requestIdRef,
|
|
47
|
+
modelRef,
|
|
48
|
+
pollingRef,
|
|
49
|
+
isGeneratingRef,
|
|
50
|
+
isPollingRef,
|
|
51
|
+
consecutiveErrorsRef,
|
|
52
|
+
pollStartTimeRef,
|
|
53
|
+
handleCompleteRef,
|
|
54
|
+
handleErrorRef,
|
|
55
|
+
pollStatusRef,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Initialize state for video queue generation
|
|
61
|
+
*/
|
|
62
|
+
export function useVideoQueueGenerationState(): VideoQueueState {
|
|
63
|
+
const [isGenerating, setIsGenerating] = useState(false);
|
|
64
|
+
return { isGenerating, setIsGenerating };
|
|
65
|
+
}
|