@umituz/react-native-ai-generation-content 1.83.20 → 1.83.21

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.83.20",
3
+ "version": "1.83.21",
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",
@@ -27,29 +27,23 @@ function CreationCardSkeleton({ tokens }: { tokens: DesignTokens }) {
27
27
  const styles = createSkeletonStyles(tokens);
28
28
  return (
29
29
  <View style={styles.card}>
30
- {/* Thumbnail skeleton */}
30
+ {/* Full-width image skeleton */}
31
31
  <AtomicSkeleton
32
32
  pattern="custom"
33
- custom={[{ width: 100, height: 100, borderRadius: 0 }]}
33
+ custom={[{ width: "100%" as unknown as number, height: 200, borderRadius: 0 }]}
34
34
  />
35
- {/* Content skeleton */}
36
- <View style={styles.content}>
37
- <View style={styles.textArea}>
38
- <AtomicSkeleton
39
- pattern="custom"
40
- custom={[
41
- { width: 120, height: 18, borderRadius: 4, marginBottom: 8 },
42
- { width: 100, height: 14, borderRadius: 4 },
43
- ]}
44
- />
45
- </View>
46
- {/* Action buttons skeleton */}
35
+ {/* Bottom bar skeleton */}
36
+ <View style={styles.bottomBar}>
37
+ <AtomicSkeleton
38
+ pattern="custom"
39
+ custom={[{ width: 140, height: 16, borderRadius: 4 }]}
40
+ />
47
41
  <View style={styles.actions}>
48
- {[1, 2, 3, 4].map((id) => (
42
+ {[1, 2, 3].map((id) => (
49
43
  <AtomicSkeleton
50
44
  key={id}
51
45
  pattern="custom"
52
- custom={[{ width: 36, height: 36, borderRadius: 18 }]}
46
+ custom={[{ width: 32, height: 32, borderRadius: 16 }]}
53
47
  />
54
48
  ))}
55
49
  </View>
@@ -131,19 +125,16 @@ const createStyles = (tokens: DesignTokens) => StyleSheet.create({
131
125
 
132
126
  const createSkeletonStyles = (tokens: DesignTokens) => StyleSheet.create({
133
127
  card: {
134
- flexDirection: 'row',
135
128
  backgroundColor: tokens.colors.surface,
136
129
  borderRadius: tokens.spacing.md,
137
130
  overflow: 'hidden',
138
131
  marginBottom: tokens.spacing.md,
139
132
  },
140
- content: {
141
- flex: 1,
142
- padding: tokens.spacing.md,
133
+ bottomBar: {
134
+ flexDirection: 'row',
135
+ alignItems: 'center',
143
136
  justifyContent: 'space-between',
144
- },
145
- textArea: {
146
- gap: tokens.spacing.xs,
137
+ padding: tokens.spacing.md,
147
138
  },
148
139
  actions: {
149
140
  flexDirection: 'row',
@@ -36,11 +36,13 @@ export const GalleryHeader: React.FC<GalleryHeaderProps> = ({
36
36
  return (
37
37
  <View style={[styles.headerArea, style]}>
38
38
  <View>
39
- <View style={styles.titleRow}>
40
- <AtomicText style={styles.title}>{title}</AtomicText>
41
- </View>
39
+ {title ? (
40
+ <View style={styles.titleRow}>
41
+ <AtomicText style={styles.title}>{title}</AtomicText>
42
+ </View>
43
+ ) : null}
42
44
  <AtomicText style={styles.subtitle}>
43
- {count} {countLabel}
45
+ {countLabel}
44
46
  </AtomicText>
45
47
  </View>
46
48
  {showFilter && filterButtons.length > 0 && (
@@ -70,7 +70,22 @@ export function useCreations({
70
70
 
71
71
  const unsubscribe = repository.subscribeToAll(userId, onDataCallback, onErrorCallback);
72
72
 
73
+ // Fallback timeout: if Firestore doesn't respond in 10s, stop loading
74
+ const timeoutId = setTimeout(() => {
75
+ setIsLoading((prev) => {
76
+ if (prev) {
77
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
78
+ console.warn("[useCreations] Loading timeout - setting empty state");
79
+ }
80
+ setData((currentData) => currentData ?? []);
81
+ return false;
82
+ }
83
+ return prev;
84
+ });
85
+ }, 10000);
86
+
73
87
  return () => {
88
+ clearTimeout(timeoutId);
74
89
  if (typeof __DEV__ !== "undefined" && __DEV__) {
75
90
  console.log("[useCreations] Cleaning up realtime listener");
76
91
  }
@@ -104,20 +104,23 @@ export function CreationsGalleryScreen({
104
104
  />
105
105
  ), [callbacks, getItemTitle]);
106
106
 
107
+ const hasScreenHeader = Boolean(onBack);
108
+
107
109
  const renderHeader = useMemo(() => {
108
110
  if (!creations?.length && !isLoading) return null;
111
+ if (isLoading) return null;
109
112
  return (
110
113
  <View style={[styles.header, { backgroundColor: tokens.colors.surface, borderBottomColor: tokens.colors.border }]}>
111
114
  <GalleryHeader
112
- title={t(config.translations.title)}
115
+ title={hasScreenHeader ? "" : t(config.translations.title)}
113
116
  count={filters.filtered.length}
114
- countLabel={t(config.translations.photoCount)}
117
+ countLabel={t(config.translations.photoCount, { count: filters.filtered.length })}
115
118
  showFilter={showFilter}
116
119
  filterButtons={filterButtons}
117
120
  />
118
121
  </View>
119
122
  );
120
- }, [creations, isLoading, filters.filtered.length, showFilter, filterButtons, t, config, tokens]);
123
+ }, [creations, isLoading, filters.filtered.length, showFilter, filterButtons, t, config, tokens, hasScreenHeader]);
121
124
 
122
125
  const renderEmpty = useMemo(() => (
123
126
  <GalleryEmptyStates