@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 +1 -1
- package/src/domains/generation/wizard/infrastructure/utils/media-url-extractor.ts +34 -0
- package/src/domains/generation/wizard/presentation/components/WizardStepRenderer.tsx +10 -5
- package/src/domains/result-preview/presentation/components/ResultPreviewScreen.tsx +16 -8
- package/src/domains/result-preview/presentation/types/result-preview.types.ts +6 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-ai-generation-content",
|
|
3
|
-
"version": "1.26.
|
|
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
|
|
102
|
-
|
|
103
|
-
|
|
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={
|
|
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
|
|
61
|
-
|
|
62
|
-
if (!
|
|
63
|
-
|
|
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
|
|
66
|
-
}, [imageUrl]);
|
|
69
|
+
return url;
|
|
70
|
+
}, [imageUrl, videoUrl, isVideo]);
|
|
67
71
|
|
|
68
|
-
if (!
|
|
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
|
-
|
|
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
|
-
/**
|
|
98
|
-
imageUrl
|
|
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 */
|