@umituz/react-native-ai-generation-content 1.37.26 → 1.37.28
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/creations/domain/utils/preview-helpers.ts +19 -0
- package/src/domains/creations/presentation/components/CreationCard.tsx +6 -0
- package/src/domains/creations/presentation/components/CreationVideoPreview.tsx +15 -11
- package/src/domains/creations/presentation/components/GalleryHeader.tsx +0 -18
- package/src/domains/creations/presentation/screens/CreationsGalleryScreen.tsx +0 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-ai-generation-content",
|
|
3
|
-
"version": "1.37.
|
|
3
|
+
"version": "1.37.28",
|
|
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",
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Utility functions for creation preview/thumbnail extraction
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import { isImageUrl } from "@umituz/react-native-design-system";
|
|
6
7
|
import type { CreationOutput } from "../entities/Creation";
|
|
7
8
|
|
|
8
9
|
// Re-export for convenience
|
|
@@ -82,3 +83,21 @@ export function getPrimaryMediaUrl(output?: CreationOutput): string | null {
|
|
|
82
83
|
null
|
|
83
84
|
);
|
|
84
85
|
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Determine if thumbnail URL is valid and should be displayed
|
|
89
|
+
* - Must exist
|
|
90
|
+
* - Must be an image URL (not a video URL)
|
|
91
|
+
* - Content must not be in progress
|
|
92
|
+
*/
|
|
93
|
+
export function shouldShowThumbnail(
|
|
94
|
+
thumbnailUrl?: string | null,
|
|
95
|
+
inProgress?: boolean
|
|
96
|
+
): boolean {
|
|
97
|
+
if (!thumbnailUrl || inProgress) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Thumbnail must be an image, not a video
|
|
102
|
+
return isImageUrl(thumbnailUrl);
|
|
103
|
+
}
|
|
@@ -40,6 +40,11 @@ export function CreationCard({
|
|
|
40
40
|
creationId: creation.id,
|
|
41
41
|
hasOnPress: !!callbacks.onPress,
|
|
42
42
|
callbacksKeys: Object.keys(callbacks),
|
|
43
|
+
status: creation.status,
|
|
44
|
+
type: creation.type,
|
|
45
|
+
output: creation.output,
|
|
46
|
+
hasThumbnailUrl: !!creation.output?.thumbnailUrl,
|
|
47
|
+
thumbnailUrl: creation.output?.thumbnailUrl,
|
|
43
48
|
});
|
|
44
49
|
}
|
|
45
50
|
|
|
@@ -119,6 +124,7 @@ export function CreationCard({
|
|
|
119
124
|
<View style={styles.previewContainer} pointerEvents="box-none">
|
|
120
125
|
<CreationPreview
|
|
121
126
|
uri={previewUrl}
|
|
127
|
+
thumbnailUrl={creation.output?.thumbnailUrl}
|
|
122
128
|
status={creation.status}
|
|
123
129
|
type={creation.type as CreationTypeId}
|
|
124
130
|
/>
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
} from "@umituz/react-native-design-system";
|
|
13
13
|
import type { CreationStatus, CreationTypeId } from "../../domain/types";
|
|
14
14
|
import { isInProgress } from "../../domain/utils";
|
|
15
|
+
import { shouldShowThumbnail } from "../../domain/utils/preview-helpers";
|
|
15
16
|
|
|
16
17
|
export interface CreationVideoPreviewProps {
|
|
17
18
|
/** Thumbnail image URL (optional) */
|
|
@@ -30,14 +31,6 @@ export interface CreationVideoPreviewProps {
|
|
|
30
31
|
readonly showLoadingIndicator?: boolean;
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
/** Check if URL is a video URL (mp4, mov, etc.) */
|
|
34
|
-
function isVideoUrl(url?: string | null): boolean {
|
|
35
|
-
if (!url) return false;
|
|
36
|
-
const videoExtensions = [".mp4", ".mov", ".avi", ".webm", ".mkv"];
|
|
37
|
-
const lowerUrl = url.toLowerCase();
|
|
38
|
-
return videoExtensions.some((ext) => lowerUrl.includes(ext));
|
|
39
|
-
}
|
|
40
|
-
|
|
41
34
|
export function CreationVideoPreview({
|
|
42
35
|
thumbnailUrl,
|
|
43
36
|
videoUrl: _videoUrl,
|
|
@@ -48,9 +41,20 @@ export function CreationVideoPreview({
|
|
|
48
41
|
}: CreationVideoPreviewProps) {
|
|
49
42
|
const tokens = useAppDesignTokens();
|
|
50
43
|
const inProgress = isInProgress(status);
|
|
44
|
+
const hasThumbnail = shouldShowThumbnail(thumbnailUrl, inProgress);
|
|
51
45
|
|
|
52
|
-
//
|
|
53
|
-
|
|
46
|
+
// Debug logging
|
|
47
|
+
if (__DEV__) {
|
|
48
|
+
console.log("[CreationVideoPreview]", {
|
|
49
|
+
thumbnailUrl,
|
|
50
|
+
status,
|
|
51
|
+
inProgress,
|
|
52
|
+
hasThumbnail,
|
|
53
|
+
willShowSpinner: inProgress && showLoadingIndicator,
|
|
54
|
+
willShowThumbnail: hasThumbnail,
|
|
55
|
+
willShowPlaceholder: !inProgress && !hasThumbnail,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
54
58
|
|
|
55
59
|
const styles = useMemo(
|
|
56
60
|
() =>
|
|
@@ -119,7 +123,7 @@ export function CreationVideoPreview({
|
|
|
119
123
|
}
|
|
120
124
|
|
|
121
125
|
// Show thumbnail with play icon overlay
|
|
122
|
-
if (hasThumbnail) {
|
|
126
|
+
if (hasThumbnail && thumbnailUrl) {
|
|
123
127
|
return (
|
|
124
128
|
<View style={styles.container}>
|
|
125
129
|
<Image
|
|
@@ -19,10 +19,6 @@ interface GalleryHeaderProps {
|
|
|
19
19
|
readonly filterButtons?: FilterButtonConfig[];
|
|
20
20
|
readonly showFilter?: boolean;
|
|
21
21
|
readonly style?: ViewStyle;
|
|
22
|
-
/** Number of pending/processing jobs to show as badge */
|
|
23
|
-
readonly pendingCount?: number;
|
|
24
|
-
/** Label for pending badge tooltip */
|
|
25
|
-
readonly pendingLabel?: string;
|
|
26
22
|
}
|
|
27
23
|
|
|
28
24
|
export const GalleryHeader: React.FC<GalleryHeaderProps> = ({
|
|
@@ -32,8 +28,6 @@ export const GalleryHeader: React.FC<GalleryHeaderProps> = ({
|
|
|
32
28
|
filterButtons = [],
|
|
33
29
|
showFilter = true,
|
|
34
30
|
style,
|
|
35
|
-
pendingCount = 0,
|
|
36
|
-
pendingLabel,
|
|
37
31
|
}) => {
|
|
38
32
|
const tokens = useAppDesignTokens();
|
|
39
33
|
const styles = useStyles(tokens);
|
|
@@ -102,18 +96,6 @@ const useStyles = (tokens: DesignTokens) =>
|
|
|
102
96
|
fontWeight: "700",
|
|
103
97
|
color: tokens.colors.textPrimary,
|
|
104
98
|
},
|
|
105
|
-
pendingBadge: {
|
|
106
|
-
flexDirection: "row",
|
|
107
|
-
alignItems: "center",
|
|
108
|
-
gap: 4,
|
|
109
|
-
paddingHorizontal: 8,
|
|
110
|
-
paddingVertical: 4,
|
|
111
|
-
borderRadius: 12,
|
|
112
|
-
},
|
|
113
|
-
pendingBadgeText: {
|
|
114
|
-
fontSize: 12,
|
|
115
|
-
fontWeight: "600",
|
|
116
|
-
},
|
|
117
99
|
subtitle: {
|
|
118
100
|
fontSize: 14,
|
|
119
101
|
color: tokens.colors.textSecondary,
|
|
@@ -120,8 +120,6 @@ export function CreationsGalleryScreen({
|
|
|
120
120
|
countLabel={t(config.translations.photoCount)}
|
|
121
121
|
showFilter={showFilter}
|
|
122
122
|
filterButtons={filterButtons}
|
|
123
|
-
pendingCount={filters.processingCount}
|
|
124
|
-
pendingLabel={t("creations.processing")}
|
|
125
123
|
/>
|
|
126
124
|
</View>
|
|
127
125
|
);
|