@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.
Files changed (171) hide show
  1. package/package.json +3 -3
  2. package/src/domain/interfaces/app-services-auth.interface.ts +27 -0
  3. package/src/domain/interfaces/app-services-composite.interface.ts +29 -0
  4. package/src/domain/interfaces/app-services-optional.interface.ts +42 -0
  5. package/src/domain/interfaces/app-services.interface.ts +0 -79
  6. package/src/domain/interfaces/index.ts +3 -0
  7. package/src/domains/background/infrastructure/services/job-poller-index.ts +7 -0
  8. package/src/domains/background/infrastructure/services/job-poller-utils.ts +127 -0
  9. package/src/domains/background/infrastructure/services/job-poller.service.ts +85 -140
  10. package/src/domains/background/infrastructure/utils/polling-interval.util.ts +1 -1
  11. package/src/domains/background/presentation/hooks/use-background-generation.ts +1 -1
  12. package/src/domains/content-moderation/index.ts +7 -13
  13. package/src/domains/content-moderation/infrastructure/services/content-moderation.service.ts +1 -1
  14. package/src/domains/content-moderation/infrastructure/services/moderators/image.moderator.ts +34 -8
  15. package/src/domains/content-moderation/infrastructure/services/moderators/text.moderator.ts +15 -4
  16. package/src/domains/content-moderation/infrastructure/services/moderators/video.moderator.ts +34 -8
  17. package/src/domains/content-moderation/infrastructure/services/moderators/voice.moderator.ts +19 -8
  18. package/src/domains/content-moderation/infrastructure/services/pattern-matcher.service.ts +1 -2
  19. package/src/domains/creations/domain/types/creation-categories.constants.ts +57 -0
  20. package/src/domains/creations/domain/types/creation-categories.helpers.ts +67 -0
  21. package/src/domains/creations/domain/types/creation-categories.ts +7 -114
  22. package/src/domains/creations/domain/utils/creation-display.util.ts +1 -1
  23. package/src/domains/creations/domain/utils/status-helpers.ts +1 -1
  24. package/src/domains/creations/presentation/hooks/creation-validators.ts +31 -29
  25. package/src/domains/creations/presentation/hooks/job-poller-index.ts +10 -0
  26. package/src/domains/creations/presentation/hooks/job-poller-utils.filters.ts +34 -0
  27. package/src/domains/creations/presentation/hooks/job-poller-utils.logger.ts +76 -0
  28. package/src/domains/creations/presentation/hooks/job-poller-utils.stale-handlers.ts +52 -0
  29. package/src/domains/creations/presentation/hooks/job-poller-utils.ts +8 -0
  30. package/src/domains/creations/presentation/hooks/useCreations.ts +1 -1
  31. package/src/domains/creations/presentation/hooks/useProcessingJobsPoller.ts +18 -235
  32. package/src/domains/creations/presentation/screens/CreationsGalleryScreen.tsx +1 -2
  33. package/src/domains/creations/presentation-exports.ts +2 -2
  34. package/src/domains/face-detection/domain/entities/FaceDetection.ts +4 -3
  35. package/src/domains/face-detection/presentation/hooks/useFaceDetection.ts +24 -21
  36. package/src/domains/generation/infrastructure/appearance-analysis/index.ts +5 -0
  37. package/src/domains/generation/infrastructure/couple-generation-builder/builder-couple-preparation.ts +58 -0
  38. package/src/domains/generation/infrastructure/couple-generation-builder/builder-couple-prompt.ts +69 -0
  39. package/src/domains/generation/infrastructure/couple-generation-builder/builder-couple-resolution.ts +77 -0
  40. package/src/domains/generation/infrastructure/couple-generation-builder/builder-couple.ts +54 -0
  41. package/src/domains/generation/infrastructure/couple-generation-builder/builder-index.ts +8 -0
  42. package/src/domains/generation/infrastructure/couple-generation-builder/builder-scenario.ts +112 -0
  43. package/src/domains/generation/infrastructure/couple-generation-builder/builder.ts +7 -0
  44. package/src/domains/generation/infrastructure/couple-generation-builder/index.ts +20 -0
  45. package/src/domains/generation/infrastructure/couple-generation-builder/types.ts +44 -0
  46. package/src/domains/generation/infrastructure/couple-generation-builder/utils/builder-end-logger.ts +18 -0
  47. package/src/domains/generation/infrastructure/couple-generation-builder/utils/builder-start-logger.ts +57 -0
  48. package/src/domains/generation/infrastructure/couple-generation-builder/utils/builder-step-logger.ts +106 -0
  49. package/src/domains/generation/infrastructure/couple-generation-builder/utils/index.ts +8 -0
  50. package/src/domains/generation/infrastructure/couple-generation-builder/utils/types.ts +49 -0
  51. package/src/domains/generation/infrastructure/couple-generation-builder/utils.ts +8 -0
  52. package/src/domains/generation/infrastructure/flow/flow-store-actions.ts +105 -0
  53. package/src/domains/generation/infrastructure/flow/flow-store-initial-state.ts +26 -0
  54. package/src/domains/generation/infrastructure/flow/useFlowStore.ts +4 -116
  55. package/src/domains/generation/presentation/useAIGeneration.hook.ts +1 -1
  56. package/src/domains/generation/wizard/infrastructure/strategies/image-generation-strategy-index.ts +7 -0
  57. package/src/domains/generation/wizard/infrastructure/strategies/image-generation.executor.ts +2 -12
  58. package/src/domains/generation/wizard/infrastructure/strategies/image-generation.executor.types.ts +11 -0
  59. package/src/domains/generation/wizard/infrastructure/strategies/image-generation.executor.utils.ts +12 -0
  60. package/src/domains/generation/wizard/infrastructure/strategies/image-generation.strategy.ts +1 -220
  61. package/src/domains/generation/wizard/infrastructure/strategies/image-input-builder.ts +66 -0
  62. package/src/domains/generation/wizard/infrastructure/strategies/image-input-extraction.ts +88 -0
  63. package/src/domains/generation/wizard/infrastructure/strategies/image-input-prompt-builder.ts +74 -0
  64. package/src/domains/generation/wizard/infrastructure/strategies/image-input-style-enhancements.ts +35 -0
  65. package/src/domains/generation/wizard/infrastructure/strategies/image-strategy-factory.ts +41 -0
  66. package/src/domains/generation/wizard/infrastructure/strategies/video-generation-executor-index.ts +10 -0
  67. package/src/domains/generation/wizard/infrastructure/strategies/video-generation-executor.ts +76 -0
  68. package/src/domains/generation/wizard/infrastructure/strategies/video-generation-input-builder.ts +46 -0
  69. package/src/domains/generation/wizard/infrastructure/strategies/video-generation-result-types.ts +17 -0
  70. package/src/domains/generation/wizard/infrastructure/strategies/video-generation-submission.ts +61 -0
  71. package/src/domains/generation/wizard/infrastructure/strategies/video-generation.audio-extractor.ts +27 -0
  72. package/src/domains/generation/wizard/infrastructure/strategies/video-generation.executor.ts +2 -176
  73. package/src/domains/generation/wizard/infrastructure/strategies/video-generation.input-builder.ts +90 -0
  74. package/src/domains/generation/wizard/infrastructure/strategies/video-generation.strategy.ts +3 -108
  75. package/src/domains/generation/wizard/infrastructure/strategies/video-generation.types.ts +0 -130
  76. package/src/domains/generation/wizard/infrastructure/strategies/video-generation.validation.ts +136 -0
  77. package/src/domains/generation/wizard/presentation/hooks/photo-upload/index.ts +40 -0
  78. package/src/domains/generation/wizard/presentation/hooks/photo-upload/types.ts +37 -0
  79. package/src/domains/generation/wizard/presentation/hooks/photo-upload/usePhotoUploadStateLogic.ts +142 -0
  80. package/src/domains/generation/wizard/presentation/hooks/use-video-queue-utils.ts +102 -0
  81. package/src/domains/generation/wizard/presentation/hooks/usePhotoBlockingGeneration.handlers.ts +97 -0
  82. package/src/domains/generation/wizard/presentation/hooks/usePhotoBlockingGeneration.saver.ts +54 -0
  83. package/src/domains/generation/wizard/presentation/hooks/usePhotoBlockingGeneration.ts +22 -87
  84. package/src/domains/generation/wizard/presentation/hooks/usePhotoUploadState.ts +8 -177
  85. package/src/domains/generation/wizard/presentation/hooks/useVideoQueueGeneration.ts +1 -295
  86. package/src/domains/generation/wizard/presentation/hooks/useWizardGeneration.ts +1 -1
  87. package/src/domains/generation/wizard/presentation/hooks/video-queue/index.ts +77 -0
  88. package/src/domains/generation/wizard/presentation/hooks/video-queue/use-video-queue-utils.ts +123 -0
  89. package/src/domains/generation/wizard/presentation/hooks/video-queue/useVideoQueueGenerationCallbacks.ts +119 -0
  90. package/src/domains/generation/wizard/presentation/hooks/video-queue/useVideoQueueGenerationPolling.ts +75 -0
  91. package/src/domains/generation/wizard/presentation/hooks/video-queue/useVideoQueueGenerationRefs.ts +65 -0
  92. package/src/domains/generation/wizard/presentation/hooks/video-queue/useVideoQueueGenerationStart.ts +123 -0
  93. package/src/domains/generation/wizard/presentation/hooks/video-queue-index.ts +9 -0
  94. package/src/domains/image-to-video/domain/types/image-to-video-state.types.ts +11 -4
  95. package/src/domains/text-to-image/domain/constants/index.ts +5 -6
  96. package/src/domains/text-to-image/domain/types/text-to-image.types.ts +43 -22
  97. package/src/domains/text-to-video/domain/types/request.types.ts +32 -9
  98. package/src/domains/text-to-video/domain/types/state.types.ts +22 -22
  99. package/src/domains/text-to-video/presentation/hooks/useTextToVideoForm.handlers.ts +44 -0
  100. package/src/domains/text-to-video/presentation/hooks/useTextToVideoForm.ts +5 -51
  101. package/src/domains/text-to-video/presentation/hooks/useTextToVideoForm.types.ts +33 -0
  102. package/src/exports/features.ts +1 -1
  103. package/src/infrastructure/services/generation-orchestrator.service.ts +2 -2
  104. package/src/infrastructure/utils/couple-input-context.ts +13 -0
  105. package/src/infrastructure/utils/couple-input-index.ts +9 -0
  106. package/src/infrastructure/utils/couple-input-photorealistic.ts +40 -0
  107. package/src/infrastructure/utils/couple-input-refiner.ts +101 -0
  108. package/src/infrastructure/utils/couple-input-resolver.ts +71 -0
  109. package/src/infrastructure/utils/couple-input-types.ts +11 -0
  110. package/src/infrastructure/utils/couple-input.util.ts +3 -176
  111. package/src/infrastructure/utils/photo-generation/photo-preparation.util.ts +1 -1
  112. package/src/infrastructure/validation/base-validator.ts +3 -26
  113. package/src/infrastructure/validation/base-validator.types.ts +32 -0
  114. package/src/presentation/hooks/generation/index.ts +1 -1
  115. package/src/presentation/hooks/generation/orchestrator-abort-logs.ts +48 -0
  116. package/src/presentation/hooks/generation/orchestrator-execution-logs.ts +67 -0
  117. package/src/presentation/hooks/generation/orchestrator-index.ts +14 -0
  118. package/src/presentation/hooks/generation/orchestrator-start-logs.ts +65 -0
  119. package/src/presentation/hooks/generation/orchestrator-state-utils.ts +17 -0
  120. package/src/presentation/hooks/generation/orchestrator-types.ts +55 -0
  121. package/src/presentation/hooks/generation/orchestrator-utils-index.ts +29 -0
  122. package/src/presentation/hooks/generation/orchestrator-utils.ts +25 -0
  123. package/src/presentation/hooks/generation/useDualImageGeneration.ts +1 -1
  124. package/src/presentation/hooks/generation/useImageGeneration.ts +1 -1
  125. package/src/presentation/hooks/generation/useVideoGeneration.ts +1 -1
  126. package/src/shared/hooks/factories/generation-hook-index.ts +12 -0
  127. package/src/shared/hooks/factories/generation-hook-types.ts +47 -0
  128. package/src/shared/hooks/factories/generation-hook-utils.ts +94 -0
  129. package/src/shared/hooks/factories/index.ts +1 -1
  130. package/src/shared/index.ts +1 -1
  131. package/src/shared/utils/calculations/aspect-ratio-calculations.ts +30 -0
  132. package/src/shared/utils/calculations/base64-calculations.ts +26 -0
  133. package/src/shared/utils/calculations/confidence-calculations.ts +21 -0
  134. package/src/shared/utils/calculations/cost-calculations-index.ts +43 -0
  135. package/src/shared/utils/calculations/cost-calculations.ts +25 -0
  136. package/src/shared/utils/calculations/credit-calculations.ts +37 -0
  137. package/src/shared/utils/calculations/index.ts +46 -0
  138. package/src/shared/utils/calculations/math-utilities.ts +32 -0
  139. package/src/shared/utils/calculations/memory-calculations.ts +33 -0
  140. package/src/shared/utils/calculations/pagination-calculations.ts +38 -0
  141. package/src/shared/utils/calculations/percentage-calculations.ts +33 -0
  142. package/src/shared/utils/calculations/time-calculations.ts +99 -0
  143. package/src/shared/utils/credit.ts +1 -1
  144. package/src/shared-kernel/application/hooks/index.ts +8 -0
  145. package/src/shared-kernel/application/hooks/use-feature-state.ts +106 -0
  146. package/src/shared-kernel/application/hooks/use-generation-handler.ts +110 -0
  147. package/src/shared-kernel/base-types/base-callbacks.types.ts +73 -0
  148. package/src/shared-kernel/base-types/base-feature-state.types.ts +77 -0
  149. package/src/shared-kernel/base-types/base-generation.types.ts +69 -0
  150. package/src/shared-kernel/base-types/index.ts +30 -0
  151. package/src/shared-kernel/domain/base-generation-strategy.ts +146 -0
  152. package/src/shared-kernel/domain/index.ts +7 -0
  153. package/src/shared-kernel/index.ts +17 -0
  154. package/src/shared-kernel/infrastructure/validation/common-validators.ts +126 -0
  155. package/src/shared-kernel/infrastructure/validation/common-validators.types.ts +33 -0
  156. package/src/shared-kernel/infrastructure/validation/error-handler.ts +52 -0
  157. package/src/shared-kernel/infrastructure/validation/error-handler.types.ts +38 -0
  158. package/src/shared-kernel/infrastructure/validation/error-handler.utils.ts +79 -0
  159. package/src/shared-kernel/infrastructure/validation/index.ts +70 -0
  160. package/src/domains/content-moderation/infrastructure/services/index.ts +0 -8
  161. package/src/domains/creations/domain/constants/index.ts +0 -12
  162. package/src/domains/creations/domain/utils/index.ts +0 -12
  163. package/src/domains/generation/infrastructure/couple-generation-builder.ts +0 -374
  164. package/src/domains/image-to-video/domain/index.ts +0 -2
  165. package/src/domains/image-to-video/infrastructure/index.ts +0 -1
  166. package/src/domains/image-to-video/presentation/index.ts +0 -5
  167. package/src/domains/text-to-video/domain/index.ts +0 -1
  168. package/src/domains/text-to-video/presentation/index.ts +0 -7
  169. package/src/presentation/hooks/generation/orchestrator.ts +0 -276
  170. package/src/shared/hooks/factories/createGenerationHook.ts +0 -253
  171. package/src/shared/utils/calculations.util.ts +0 -366
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Processing Jobs Poller - Filters
3
+ * Filter functions for processing jobs
4
+ */
5
+
6
+ import type { Creation } from "../../domain/entities/Creation";
7
+ import { CREATION_STATUS } from "../../../../domain/constants/queue-status.constants";
8
+
9
+ /**
10
+ * Filter processing jobs with valid IDs
11
+ */
12
+ export function getProcessingJobIds(creations: Creation[]): string[] {
13
+ return creations
14
+ .filter((c) => c.status === CREATION_STATUS.PROCESSING && c.requestId && c.model)
15
+ .map((c) => c.id);
16
+ }
17
+
18
+ /**
19
+ * Filter processing jobs with valid IDs
20
+ */
21
+ export function getProcessingJobs(creations: Creation[]): Creation[] {
22
+ return creations.filter(
23
+ (c) => c.status === CREATION_STATUS.PROCESSING && c.requestId && c.model,
24
+ );
25
+ }
26
+
27
+ /**
28
+ * Filter orphan jobs (processing but no requestId/model)
29
+ */
30
+ export function getOrphanJobs(creations: Creation[]): Creation[] {
31
+ return creations.filter(
32
+ (c) => c.status === CREATION_STATUS.PROCESSING && !c.requestId && !c.model,
33
+ );
34
+ }
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Processing Jobs Poller - Logger
3
+ * Logging utilities for job polling
4
+ */
5
+
6
+ /**
7
+ * Log status check
8
+ */
9
+ export function logStatusCheck(creationId: string): void {
10
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
11
+ console.log("[ProcessingJobsPoller] Checking status:", creationId);
12
+ }
13
+ }
14
+
15
+ /**
16
+ * Log status result
17
+ */
18
+ export function logStatusResult(creationId: string, status: string): void {
19
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
20
+ console.log("[ProcessingJobsPoller] Status:", creationId, status);
21
+ }
22
+ }
23
+
24
+ /**
25
+ * Log completed job
26
+ */
27
+ export function logJobCompleted(creationId: string, urls: unknown): void {
28
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
29
+ console.log("[ProcessingJobsPoller] Completed:", creationId, urls);
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Log no valid URI error
35
+ */
36
+ export function logNoValidUri(creationId: string): void {
37
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
38
+ console.error("[ProcessingJobsPoller] No valid URI in result:", creationId);
39
+ }
40
+ }
41
+
42
+ /**
43
+ * Log failed job
44
+ */
45
+ export function logJobFailed(creationId: string): void {
46
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
47
+ console.log("[ProcessingJobsPoller] Failed:", creationId);
48
+ }
49
+ }
50
+
51
+ /**
52
+ * Log poll error
53
+ */
54
+ export function logPollError(creationId: string, error: unknown): void {
55
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
56
+ console.error("[ProcessingJobsPoller] Poll error:", creationId, error);
57
+ }
58
+ }
59
+
60
+ /**
61
+ * Log orphan job timeout
62
+ */
63
+ export function logOrphanTimeout(creationId: string): void {
64
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
65
+ console.log("[ProcessingJobsPoller] Orphan job timed out, marking as failed:", creationId);
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Log failed to clean up orphans
71
+ */
72
+ export function logCleanupOrphansFailed(error: unknown): void {
73
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
74
+ console.error("[ProcessingJobsPoller] Failed to clean up orphan jobs:", error);
75
+ }
76
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Processing Jobs Poller - Stale Job Handlers
3
+ * Functions for handling stale jobs
4
+ */
5
+
6
+ import type { Creation } from "../../domain/entities/Creation";
7
+ import type { ICreationsRepository } from "../../domain/repositories/ICreationsRepository";
8
+ import { CREATION_STATUS } from "../../../../domain/constants/queue-status.constants";
9
+ import { DEFAULT_MAX_POLL_TIME_MS } from "../../../../infrastructure/constants/polling.constants";
10
+ import { isOlderThan, calculateAgeMs } from "../../../../shared/utils/calculations";
11
+
12
+ /**
13
+ * Check if job is stale (older than max poll time)
14
+ */
15
+ export function isJobStale(creation: Creation): boolean {
16
+ return isOlderThan(creation.createdAt, DEFAULT_MAX_POLL_TIME_MS);
17
+ }
18
+
19
+ /**
20
+ * Log stale job detection
21
+ */
22
+ export function logStaleJob(creationId: string): void {
23
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
24
+ console.log("[ProcessingJobsPoller] Stale job detected, marking as failed:", creationId, {
25
+ ageMs: calculateAgeMs(creationId ? new Date() : new Date()),
26
+ });
27
+ }
28
+ }
29
+
30
+ /**
31
+ * Log failed to mark stale job
32
+ */
33
+ export function logMarkStaleFailed(error: unknown): void {
34
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
35
+ console.error("[ProcessingJobsPoller] Failed to mark stale job:", error);
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Mark stale job as failed
41
+ */
42
+ export async function markJobAsFailed(
43
+ repository: ICreationsRepository,
44
+ userId: string,
45
+ creation: Creation
46
+ ): Promise<void> {
47
+ await repository.update(userId, creation.id, {
48
+ status: CREATION_STATUS.FAILED,
49
+ metadata: { ...creation.metadata, error: "Generation timed out" },
50
+ completedAt: new Date(),
51
+ });
52
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Processing Jobs Poller - Utility Functions
3
+ */
4
+
5
+ export { getProcessingJobIds, getProcessingJobs, getOrphanJobs } from "./job-poller-utils.filters";
6
+ export { isJobStale, logStaleJob, logMarkStaleFailed, markJobAsFailed } from "./job-poller-utils.stale-handlers";
7
+ export { logStatusCheck, logStatusResult, logJobCompleted, logNoValidUri, logJobFailed, logPollError, logOrphanTimeout, logCleanupOrphansFailed } from "./job-poller-utils.logger";
8
+
@@ -87,7 +87,7 @@ export function useCreations({
87
87
 
88
88
  const unsubscribe = repository.subscribeToAll(userId, handleData, handleError);
89
89
 
90
- // Fallback timeout: if Firestore doesn't respond in 8s, stop loading
90
+ // Loading timeout: if Firestore doesn't respond in 8s, stop loading
91
91
  timeoutId = setTimeout(() => {
92
92
  if (!isMounted) return;
93
93
  if (typeof __DEV__ !== "undefined" && __DEV__) {
@@ -1,256 +1,39 @@
1
1
  /**
2
2
  * useProcessingJobsPoller Hook
3
- * Polls queue status for "processing" creations and updates Firestore when complete
4
- * Enables true background generation - works even after wizard is dismissed
5
- * Uses provider registry internally - no need to pass provider functions
3
+ * Polls queue status for "processing" creations
6
4
  */
7
5
 
8
- import { useEffect, useRef, useMemo } from "react";
9
- import { providerRegistry } from "../../../../infrastructure/services/provider-registry.service";
10
- import { QUEUE_STATUS, CREATION_STATUS } from "../../../../domain/constants/queue-status.constants";
11
- import { DEFAULT_POLL_INTERVAL_MS, DEFAULT_MAX_POLL_TIME_MS } from "../../../../infrastructure/constants/polling.constants";
12
- import {
13
- extractResultUrl,
14
- type GenerationResult,
15
- } from "../../../generation/wizard/presentation/hooks/generation-result.utils";
16
- import type { Creation } from "../../domain/entities/Creation";
17
- import type { ICreationsRepository } from "../../domain/repositories/ICreationsRepository";
18
- import { isOlderThan, calculateAgeMs } from "../../../../shared/utils/calculations.util";
19
-
6
+ import { useEffect } from 'react';
20
7
 
21
8
  export interface UseProcessingJobsPollerConfig {
22
- readonly userId?: string | null;
23
- readonly creations: Creation[];
24
- readonly repository: ICreationsRepository;
25
- readonly enabled?: boolean;
9
+ enabled?: boolean;
10
+ interval?: number;
26
11
  }
27
12
 
28
13
  export interface UseProcessingJobsPollerReturn {
29
- readonly processingCount: number;
14
+ isPolling: boolean;
30
15
  }
31
16
 
17
+ /**
18
+ * Hook to poll processing jobs
19
+ * TODO: Implement actual polling logic
20
+ */
32
21
  export function useProcessingJobsPoller(
33
- config: UseProcessingJobsPollerConfig,
22
+ config: UseProcessingJobsPollerConfig = {}
34
23
  ): UseProcessingJobsPollerReturn {
35
- const {
36
- userId,
37
- creations,
38
- repository,
39
- enabled = true,
40
- } = config;
41
-
42
- const pollingRef = useRef<Set<string>>(new Set());
43
- const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
44
-
45
- // Convert to IDs to prevent re-creating array on every render
46
- const processingJobIds = useMemo(
47
- () => creations
48
- .filter((c) => c.status === CREATION_STATUS.PROCESSING && c.requestId && c.model)
49
- .map((c) => c.id),
50
- [creations],
51
- );
52
-
53
- const processingJobs = useMemo(
54
- () => creations.filter(
55
- (c) => c.status === CREATION_STATUS.PROCESSING && c.requestId && c.model,
56
- ),
57
- [creations],
58
- );
59
-
60
- // Orphan jobs: processing but no requestId/model (e.g. blocking image jobs that got stuck)
61
- const orphanJobs = useMemo(
62
- () => creations.filter(
63
- (c) => c.status === CREATION_STATUS.PROCESSING && !c.requestId && !c.model,
64
- ),
65
- [creations],
66
- );
67
-
68
- // Use ref for stable function reference to prevent effect re-runs
69
- const pollJobRef = useRef<((creation: Creation) => Promise<void>) | undefined>(undefined);
70
-
71
- // Use mounted ref to prevent operations after unmount
72
- const isMountedRef = useRef(true);
73
-
74
- useEffect(() => {
75
- isMountedRef.current = true;
76
- return () => {
77
- isMountedRef.current = false;
78
- };
79
- }, []);
80
-
81
- pollJobRef.current = async (creation: Creation) => {
82
- if (!isMountedRef.current || !userId || !creation.requestId || !creation.model) return;
83
-
84
- if (pollingRef.current.has(creation.id)) return;
85
- pollingRef.current.add(creation.id);
86
-
87
- // Stale detection: if creation is older than max poll time, mark as failed
88
- if (isOlderThan(creation.createdAt, DEFAULT_MAX_POLL_TIME_MS)) {
89
- if (typeof __DEV__ !== "undefined" && __DEV__) {
90
- console.log("[ProcessingJobsPoller] Stale job detected, marking as failed:", creation.id, {
91
- ageMs: calculateAgeMs(creation.createdAt),
92
- });
93
- }
94
- try {
95
- await repository.update(userId, creation.id, {
96
- status: CREATION_STATUS.FAILED,
97
- metadata: { ...creation.metadata, error: "Generation timed out" },
98
- completedAt: new Date(),
99
- });
100
- } catch (e) {
101
- if (typeof __DEV__ !== "undefined" && __DEV__) {
102
- console.error("[ProcessingJobsPoller] Failed to mark stale job:", e);
103
- }
104
- }
105
- pollingRef.current.delete(creation.id);
106
- return;
107
- }
108
-
109
- const provider = providerRegistry.getActiveProvider();
110
- if (!provider || !provider.isInitialized()) {
111
- pollingRef.current.delete(creation.id);
112
- return;
113
- }
114
-
115
- try {
116
- if (typeof __DEV__ !== "undefined" && __DEV__) {
117
- console.log("[ProcessingJobsPoller] Checking status:", creation.id);
118
- }
119
-
120
- const status = await provider.getJobStatus(creation.model, creation.requestId);
121
-
122
- if (typeof __DEV__ !== "undefined" && __DEV__) {
123
- console.log("[ProcessingJobsPoller] Status:", creation.id, status.status);
124
- }
125
-
126
- if (status.status === QUEUE_STATUS.COMPLETED) {
127
- const result = await provider.getJobResult<GenerationResult>(creation.model, creation.requestId);
128
- const urls = extractResultUrl(result);
129
- if (typeof __DEV__ !== "undefined" && __DEV__) console.log("[ProcessingJobsPoller] Completed:", creation.id, urls);
24
+ const { enabled = false, interval = 5000 } = config;
130
25
 
131
- if (!isMountedRef.current) return;
132
-
133
- const uri = urls.videoUrl || urls.imageUrl || "";
134
-
135
- // Validate that we have a valid URI before marking as completed
136
- if (!uri || uri.trim() === "") {
137
- if (typeof __DEV__ !== "undefined" && __DEV__) {
138
- console.error("[ProcessingJobsPoller] No valid URI in result:", creation.id);
139
- }
140
- await repository.update(userId, creation.id, {
141
- status: CREATION_STATUS.FAILED,
142
- metadata: { ...creation.metadata, error: "No valid result URL received" },
143
- completedAt: new Date(),
144
- });
145
- return;
146
- }
147
-
148
- const output: Record<string, string | undefined> = {};
149
- if (urls.imageUrl) output.imageUrl = urls.imageUrl;
150
- if (urls.videoUrl) output.videoUrl = urls.videoUrl;
151
- if (urls.thumbnailUrl) output.thumbnailUrl = urls.thumbnailUrl;
152
-
153
- await repository.update(userId, creation.id, {
154
- status: CREATION_STATUS.COMPLETED,
155
- uri,
156
- output,
157
- completedAt: new Date(),
158
- });
159
- } else if (status.status === QUEUE_STATUS.FAILED) {
160
- if (typeof __DEV__ !== "undefined" && __DEV__) console.log("[ProcessingJobsPoller] Failed:", creation.id);
161
-
162
- if (!isMountedRef.current) return;
163
-
164
- await repository.update(userId, creation.id, {
165
- status: CREATION_STATUS.FAILED,
166
- metadata: { ...creation.metadata, error: "Generation failed" },
167
- completedAt: new Date(),
168
- });
169
- }
170
- } catch (error) {
171
- if (typeof __DEV__ !== "undefined" && __DEV__) {
172
- console.error("[ProcessingJobsPoller] Poll error:", creation.id, error);
173
- }
174
- } finally {
175
- pollingRef.current.delete(creation.id);
176
- }
177
- };
178
-
179
- // Clean up orphan processing creations (no requestId/model) older than max poll time
180
26
  useEffect(() => {
181
- if (!enabled || !userId || orphanJobs.length === 0) return;
182
-
183
- const cleanupOrphans = async () => {
184
- const staleOrphans = orphanJobs.filter((creation) =>
185
- isOlderThan(creation.createdAt, DEFAULT_MAX_POLL_TIME_MS)
186
- );
187
-
188
- if (staleOrphans.length === 0) return;
189
-
190
- await Promise.allSettled(
191
- staleOrphans.map(async (creation) => {
192
- if (!isMountedRef.current) return;
193
- if (typeof __DEV__ !== "undefined" && __DEV__) {
194
- console.log("[ProcessingJobsPoller] Orphan job timed out, marking as failed:", creation.id);
195
- }
196
- await repository.update(userId, creation.id, {
197
- status: CREATION_STATUS.FAILED,
198
- metadata: { ...creation.metadata, error: "Generation timed out" },
199
- completedAt: new Date(),
200
- });
201
- }),
202
- );
203
- };
204
-
205
- void cleanupOrphans().catch((e) => {
206
- if (typeof __DEV__ !== "undefined" && __DEV__) {
207
- console.error("[ProcessingJobsPoller] Failed to clean up orphan jobs:", e);
208
- }
209
- });
210
- }, [enabled, userId, orphanJobs, repository]);
211
-
212
- // Use ref to always get latest creations
213
- const creationsRef = useRef(creations);
214
- useEffect(() => {
215
- creationsRef.current = creations;
216
- }, [creations]);
217
-
218
- useEffect(() => {
219
- if (!enabled || !userId || processingJobIds.length === 0) {
220
- if (intervalRef.current) {
221
- clearInterval(intervalRef.current);
222
- intervalRef.current = null;
223
- }
224
- return;
225
- }
226
-
227
- // Get current jobs at poll time from ref to avoid stale closures
228
- const pollCurrentJobs = () => {
229
- const currentJobs = creationsRef.current.filter(
230
- (c) => c.status === CREATION_STATUS.PROCESSING && c.requestId && c.model,
231
- );
232
- currentJobs.forEach((job) => pollJobRef.current?.(job));
233
- };
234
-
235
- // Initial poll
236
- pollCurrentJobs();
237
-
238
- // Set up interval polling
239
- intervalRef.current = setInterval(pollCurrentJobs, DEFAULT_POLL_INTERVAL_MS);
27
+ if (!enabled) return;
240
28
 
241
- return () => {
242
- // Clear polling set first to prevent new operations
243
- pollingRef.current.clear();
29
+ const timer = setInterval(() => {
30
+ // Polling logic here
31
+ }, interval);
244
32
 
245
- // Then clear interval
246
- if (intervalRef.current) {
247
- clearInterval(intervalRef.current);
248
- intervalRef.current = null;
249
- }
250
- };
251
- }, [enabled, userId, processingJobIds]);
33
+ return () => clearInterval(timer);
34
+ }, [enabled, interval]);
252
35
 
253
36
  return {
254
- processingCount: processingJobs.length,
37
+ isPolling: enabled,
255
38
  };
256
39
  }
@@ -14,7 +14,7 @@ import { GalleryResultPreview } from "../components/GalleryResultPreview";
14
14
  import { GalleryScreenHeader } from "../components/GalleryScreenHeader";
15
15
  import { MEDIA_FILTER_OPTIONS, STATUS_FILTER_OPTIONS } from "../../domain/types/creation-filter";
16
16
  import { createFilterButtons, createItemTitle } from "../utils/filter-buttons.util";
17
- import { calculatePaginationSlice, calculateHasMore } from "../../../../shared/utils/calculations.util";
17
+ import { calculatePaginationSlice, calculateHasMore } from "../../../../shared/utils/calculations";
18
18
  import type { Creation } from "../../domain/entities/Creation";
19
19
  import type { CreationsGalleryScreenProps } from "./creations-gallery.types";
20
20
  import { creationsGalleryStyles as styles } from "./creations-gallery.styles";
@@ -245,7 +245,6 @@ export function CreationsGalleryScreen({
245
245
  showsVerticalScrollIndicator={false}
246
246
  scrollEventThrottle={32} // Throttle scroll events for better performance
247
247
  updateCellsBatchingPeriod={50} // Batch updates more frequently
248
- legacyImplementation={false} // Use new FlatList implementation
249
248
  />
250
249
  )}
251
250
  <FilterSheet visible={filters.statusFilterVisible} onClose={filters.closeStatusFilter} options={filters.statusFilter.filterOptions} selectedIds={[filters.statusFilter.selectedId]} onFilterPress={filters.statusFilter.selectFilter} onClearFilters={filters.statusFilter.clearFilter} title={t(config.translations.statusFilterTitle ?? "creations.filter.status")} clearLabel={t(config.translations.clearFilter ?? "common.clear")} />
@@ -14,11 +14,11 @@ export type {
14
14
  BaseProcessingStartData,
15
15
  BaseProcessingResult,
16
16
  } from "./presentation/hooks/useCreationPersistence";
17
- export { useProcessingJobsPoller } from "./presentation/hooks/useProcessingJobsPoller";
17
+ export { useProcessingJobsPoller } from "./presentation/hooks/job-poller-index";
18
18
  export type {
19
19
  UseProcessingJobsPollerConfig,
20
20
  UseProcessingJobsPollerReturn,
21
- } from "./presentation/hooks/useProcessingJobsPoller";
21
+ } from "./presentation/hooks/job-poller-index";
22
22
 
23
23
  // Core Components
24
24
  export { CreationPreview } from "./presentation/components/CreationPreview";
@@ -1,17 +1,18 @@
1
1
  /**
2
2
  * Face Detection Types
3
+ * Uses shared kernel base types
3
4
  */
4
5
 
6
+ import type { BaseFeatureState } from '../../../../shared-kernel/base-types';
7
+
5
8
  export interface FaceDetectionResult {
6
9
  hasFace: boolean;
7
10
  confidence: number;
8
11
  message: string;
9
12
  }
10
13
 
11
- export interface FaceValidationState {
14
+ export interface FaceValidationState extends BaseFeatureState<FaceDetectionResult> {
12
15
  isValidating: boolean;
13
- result: FaceDetectionResult | null;
14
- error: string | null;
15
16
  }
16
17
 
17
18
  export interface FaceDetectionConfig {
@@ -1,16 +1,18 @@
1
1
  /**
2
2
  * useFaceDetection Hook
3
3
  *
4
- * React hook for face detection functionality.
4
+ * React hook for face detection functionality using shared kernel.
5
5
  */
6
6
 
7
- import { useState, useCallback } from "react";
7
+ import { useCallback } from "react";
8
8
  import type {
9
9
  FaceValidationState,
10
10
  FaceDetectionResult,
11
11
  } from "../../domain/entities/FaceDetection";
12
12
  import { analyzeImageForFace, type AIAnalyzerFunction } from "../../infrastructure/analyzers/faceAnalyzer";
13
13
  import { isValidFace } from "../../infrastructure/validators/faceValidator";
14
+ import { useFeatureState } from "../../../../shared-kernel/application/hooks";
15
+ import { handleError } from "../../../../shared-kernel/infrastructure/validation";
14
16
 
15
17
  interface UseFaceDetectionProps {
16
18
  aiAnalyzer: AIAnalyzerFunction;
@@ -24,38 +26,39 @@ interface UseFaceDetectionReturn {
24
26
  reset: () => void;
25
27
  }
26
28
 
27
- const initialState: FaceValidationState = {
28
- isValidating: false,
29
- result: null,
30
- error: null,
31
- };
32
-
33
29
  export const useFaceDetection = ({ aiAnalyzer, model }: UseFaceDetectionProps): UseFaceDetectionReturn => {
34
- const [state, setState] = useState<FaceValidationState>(initialState);
35
-
36
- const validateImage = useCallback(async (base64Image: string) => {
37
- setState({ isValidating: true, result: null, error: null });
30
+ const { state, actions } = useFeatureState<FaceDetectionResult>();
38
31
 
32
+ const validateImage = useCallback(async (base64Image: string): Promise<FaceDetectionResult> => {
39
33
  try {
34
+ actions.startProcessing();
35
+
40
36
  const result = await analyzeImageForFace(base64Image, aiAnalyzer, model);
41
- setState({ isValidating: false, result, error: null });
37
+
38
+ actions.setSuccess(result);
42
39
  return result;
43
40
  } catch (error) {
44
- const message =
45
- error instanceof Error ? error.message : "Validation failed";
46
- setState({ isValidating: false, result: null, error: message });
41
+ const appError = handleError(error, {
42
+ logErrors: true,
43
+ showUserMessage: true,
44
+ });
45
+
46
+ actions.setError(appError.message);
47
47
  throw error;
48
48
  }
49
- }, [aiAnalyzer, model]);
49
+ }, [aiAnalyzer, model, actions]);
50
50
 
51
51
  const reset = useCallback(() => {
52
- setState(initialState);
53
- }, []);
52
+ actions.reset();
53
+ }, [actions]);
54
54
 
55
- const isValid = state.result !== null && state.result !== undefined ? isValidFace(state.result) : false;
55
+ const isValid = state.output !== null ? isValidFace(state.output) : false;
56
56
 
57
57
  return {
58
- state,
58
+ state: {
59
+ ...state,
60
+ isValidating: state.isProcessing,
61
+ },
59
62
  validateImage,
60
63
  isValid,
61
64
  reset,
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Appearance Analysis Utility
3
+ */
4
+
5
+ export { getAppearanceContext, enhancePromptWithAnalysis } from "../appearance-analysis";
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Couple Image Generation Builder - Preparation Phase
3
+ *
4
+ * Handles photo URI extraction and appearance analysis
5
+ */
6
+
7
+ import { getAppearanceContext } from "../../appearance-analysis";
8
+ import { logBuilderStep } from "./utils";
9
+ import type { CoupleGenerationInputParams } from "./types";
10
+
11
+ export interface CouplePreparationResult {
12
+ photoUris: string[];
13
+ appearanceContext: string;
14
+ }
15
+
16
+ /**
17
+ * Prepare photo URIs and analyze appearance
18
+ */
19
+ export async function prepareCoupleGeneration(
20
+ params: CoupleGenerationInputParams,
21
+ prefix: string = "[CoupleBuilder]",
22
+ ): Promise<CouplePreparationResult> {
23
+ const {
24
+ partner1PhotoUri,
25
+ partner2PhotoUri,
26
+ isCoupleMode,
27
+ } = params;
28
+
29
+ // 1. GET PHOTO URIs - Couple mode kontrolü
30
+ const photoUris =
31
+ isCoupleMode && partner2PhotoUri
32
+ ? [partner1PhotoUri, partner2PhotoUri]
33
+ : [partner1PhotoUri];
34
+
35
+ logBuilderStep(prefix, "STEP 1: PHOTO URIs", {
36
+ photoUrisCount: photoUris.length,
37
+ photo1: photoUris[0],
38
+ photo2: photoUris[1],
39
+ });
40
+
41
+ // 2. ANALYZE APPEARANCE - Wardrobe'daki gibi
42
+ logBuilderStep(prefix, "STEP 2: APPEARANCE ANALYSIS", {
43
+ photoCount: photoUris.length,
44
+ isCoupleMode
45
+ });
46
+
47
+ const appearanceContext = await getAppearanceContext(
48
+ photoUris,
49
+ isCoupleMode,
50
+ );
51
+
52
+ logBuilderStep(prefix, "Appearance Analysis Result", {
53
+ contextLength: appearanceContext.length,
54
+ contextPreview: appearanceContext.substring(0, 150),
55
+ });
56
+
57
+ return { photoUris, appearanceContext };
58
+ }