@umituz/react-native-ai-generation-content 1.26.54 → 1.26.56

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-ai-generation-content",
3
- "version": "1.26.54",
3
+ "version": "1.26.56",
4
4
  "description": "Provider-agnostic AI generation orchestration for React Native with result preview components",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Media URL Extractor
3
+ * Extracts media URL from generation result object
4
+ */
5
+
6
+ interface MediaUrlResult {
7
+ readonly url: string;
8
+ readonly isVideo: boolean;
9
+ }
10
+
11
+ /**
12
+ * Extract media URL from generation result
13
+ * Supports multiple result formats from different AI providers
14
+ */
15
+ export function extractMediaUrl(result: unknown): MediaUrlResult | null {
16
+ if (!result || typeof result !== "object") return null;
17
+
18
+ const data = result as Record<string, unknown>;
19
+ const output = data.output as Record<string, unknown> | undefined;
20
+
21
+ // Try to get video URL first
22
+ const videoUrl = output?.videoUrl || data.videoUrl || data.video_url;
23
+ if (videoUrl && typeof videoUrl === "string") {
24
+ return { url: videoUrl, isVideo: true };
25
+ }
26
+
27
+ // Try to get image URL
28
+ const imageUrl = output?.imageUrl || data.imageUrl || data.image_url || data.uri;
29
+ if (imageUrl && typeof imageUrl === "string") {
30
+ return { url: imageUrl, isVideo: false };
31
+ }
32
+
33
+ return null;
34
+ }
@@ -4,16 +4,17 @@
4
4
  */
5
5
 
6
6
  import React from "react";
7
+ import { getMediaTypeFromUrl } from "@umituz/react-native-design-system";
7
8
  import { StepType, type StepDefinition } from "../../../../../domain/entities/flow-config.types";
8
9
  import type { WizardStepConfig } from "../../domain/entities/wizard-config.types";
9
10
  import type { WizardScenarioData } from "../hooks/useWizardGeneration";
10
11
  import type { UploadedImage } from "../../../../../presentation/hooks/generation/useAIGenerateState";
11
- import type { Creation } from "../../../../creations/domain/entities/Creation";
12
12
  import { GenericPhotoUploadScreen } from "../screens/GenericPhotoUploadScreen";
13
13
  import { GeneratingScreen } from "../screens/GeneratingScreen";
14
14
  import { ScenarioPreviewScreen } from "../../../../scenarios/presentation/screens/ScenarioPreviewScreen";
15
15
  import type { ScenarioData } from "../../../../scenarios/domain/scenario.types";
16
16
  import { ResultPreviewScreen } from "../../../../result-preview/presentation/components/ResultPreviewScreen";
17
+ import { extractMediaUrl } from "../../infrastructure/utils/media-url-extractor";
17
18
 
18
19
  export interface WizardStepRendererProps {
19
20
  readonly step: StepDefinition | undefined;
@@ -98,12 +99,16 @@ export const WizardStepRenderer: React.FC<WizardStepRendererProps> = ({
98
99
  if (renderResult) {
99
100
  return renderResult(generationResult);
100
101
  }
101
- const creation = generationResult as Creation;
102
- const imageUrl = creation?.output?.imageUrl || creation?.uri || "";
103
- if (!imageUrl) return null;
102
+ const media = extractMediaUrl(generationResult);
103
+ if (!media) return null;
104
+
105
+ const mediaType = getMediaTypeFromUrl(media.url);
106
+ const isVideo = media.isVideo || mediaType === "video";
107
+
104
108
  return (
105
109
  <ResultPreviewScreen
106
- imageUrl={imageUrl}
110
+ imageUrl={isVideo ? undefined : media.url}
111
+ videoUrl={isVideo ? media.url : undefined}
107
112
  isSaving={isSaving}
108
113
  isSharing={isSharing}
109
114
  onDownload={onDownload}
@@ -14,10 +14,12 @@ import {
14
14
  import { ResultImageCard } from "./ResultImageCard";
15
15
  import { ResultActionBar } from "./ResultActionBar";
16
16
  import { RecentCreationsSection } from "./RecentCreationsSection";
17
+ import { VideoResultPlayer } from "../../../../presentation/components/display/VideoResultPlayer";
17
18
  import type { ResultPreviewScreenProps } from "../types/result-preview.types";
18
19
 
19
20
  export const ResultPreviewScreen: React.FC<ResultPreviewScreenProps> = ({
20
21
  imageUrl,
22
+ videoUrl,
21
23
  isSaving,
22
24
  isSharing,
23
25
  onDownload,
@@ -36,6 +38,7 @@ export const ResultPreviewScreen: React.FC<ResultPreviewScreenProps> = ({
36
38
  showRating = false,
37
39
  }) => {
38
40
  const tokens = useAppDesignTokens();
41
+ const isVideo = Boolean(videoUrl);
39
42
 
40
43
  const styles = useMemo(
41
44
  () =>
@@ -57,15 +60,16 @@ export const ResultPreviewScreen: React.FC<ResultPreviewScreenProps> = ({
57
60
  [tokens],
58
61
  );
59
62
 
60
- const displayImageUrl = useMemo(() => {
61
- if (!imageUrl) return null;
62
- if (!imageUrl.startsWith("http") && !imageUrl.startsWith("data:image")) {
63
- return `data:image/jpeg;base64,${imageUrl}`;
63
+ const displayMediaUrl = useMemo(() => {
64
+ const url = videoUrl || imageUrl;
65
+ if (!url) return null;
66
+ if (!isVideo && !url.startsWith("http") && !url.startsWith("data:image")) {
67
+ return `data:image/jpeg;base64,${url}`;
64
68
  }
65
- return imageUrl;
66
- }, [imageUrl]);
69
+ return url;
70
+ }, [imageUrl, videoUrl, isVideo]);
67
71
 
68
- if (!displayImageUrl) return null;
72
+ if (!displayMediaUrl) return null;
69
73
 
70
74
  return (
71
75
  <ScreenLayout scrollable edges={["left", "right"]} backgroundColor={tokens.colors.backgroundPrimary}>
@@ -75,7 +79,11 @@ export const ResultPreviewScreen: React.FC<ResultPreviewScreenProps> = ({
75
79
  {!hideLabel && (
76
80
  <AtomicText style={styles.title}>{translations.yourResult}</AtomicText>
77
81
  )}
78
- <ResultImageCard imageUrl={displayImageUrl} />
82
+ {isVideo ? (
83
+ <VideoResultPlayer uri={displayMediaUrl} />
84
+ ) : (
85
+ <ResultImageCard imageUrl={displayMediaUrl} />
86
+ )}
79
87
  <ResultActionBar
80
88
  isSaving={isSaving}
81
89
  isSharing={isSharing}
@@ -94,8 +94,10 @@ export interface RecentCreation {
94
94
  * Result preview screen props
95
95
  */
96
96
  export interface ResultPreviewScreenProps {
97
- /** Result data to display */
98
- imageUrl: string;
97
+ /** Image URL to display */
98
+ imageUrl?: string;
99
+ /** Video URL to display */
100
+ videoUrl?: string;
99
101
  /** Result display state */
100
102
  isSaving: boolean;
101
103
  isSharing: boolean;
@@ -157,6 +159,8 @@ export interface ResultPreviewTranslations {
157
159
  export interface UseResultActionsOptions {
158
160
  /** Image URL to save/share */
159
161
  imageUrl?: string;
162
+ /** Video URL to save/share */
163
+ videoUrl?: string;
160
164
  /** Callback on save success */
161
165
  onSaveSuccess?: () => void;
162
166
  /** Callback on save error */