@umituz/react-native-ai-generation-content 1.17.259 → 1.17.261

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.17.259",
3
+ "version": "1.17.261",
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",
@@ -18,11 +18,9 @@ export const ResultActionBar: React.FC<ResultActionBarProps> = ({
18
18
  onDownload,
19
19
  onShare,
20
20
  onTryAgain,
21
- onRate,
22
21
  saveButtonText,
23
22
  shareButtonText,
24
23
  tryAgainButtonText,
25
- rateButtonText,
26
24
  }) => {
27
25
  const tokens = useAppDesignTokens();
28
26
 
@@ -30,38 +28,28 @@ export const ResultActionBar: React.FC<ResultActionBarProps> = ({
30
28
  () =>
31
29
  StyleSheet.create({
32
30
  container: {
33
- marginTop: tokens.spacing.xl,
34
- paddingHorizontal: tokens.spacing.md,
35
- },
36
- gridContainer: {
37
31
  flexDirection: "row",
38
- justifyContent: "space-between",
32
+ justifyContent: "center",
33
+ flexWrap: "wrap",
39
34
  gap: tokens.spacing.md,
35
+ paddingHorizontal: tokens.spacing.lg,
36
+ marginTop: tokens.spacing.xl,
40
37
  },
41
- actionButton: {
42
- flex: 1,
43
- alignItems: "center",
44
- gap: tokens.spacing.sm,
45
- },
46
- iconContainer: {
47
- width: 56,
48
- height: 56,
49
- borderRadius: 28,
38
+ button: {
39
+ flexDirection: "row",
50
40
  alignItems: "center",
51
41
  justifyContent: "center",
52
- },
53
- iconContainerSecondary: {
54
- backgroundColor: tokens.colors.backgroundSecondary,
55
- borderWidth: 1,
56
- borderColor: tokens.colors.border,
57
- },
58
- iconContainerPrimary: {
42
+ paddingVertical: 12,
43
+ paddingHorizontal: 20,
44
+ borderRadius: 16,
45
+ gap: 8,
46
+ minWidth: 110,
59
47
  backgroundColor: tokens.colors.primary,
60
48
  },
61
- label: {
62
- fontSize: 12,
63
- fontWeight: "500",
64
- color: tokens.colors.textSecondary,
49
+ buttonText: {
50
+ fontWeight: "700",
51
+ color: tokens.colors.textInverse,
52
+ fontSize: 15,
65
53
  },
66
54
  }),
67
55
  [tokens],
@@ -69,53 +57,42 @@ export const ResultActionBar: React.FC<ResultActionBarProps> = ({
69
57
 
70
58
  return (
71
59
  <View style={styles.container}>
72
- <View style={styles.gridContainer}>
73
- <TouchableOpacity
74
- style={styles.actionButton}
75
- onPress={onDownload}
76
- disabled={isSaving}
77
- >
78
- <View style={[styles.iconContainer, styles.iconContainerSecondary]}>
79
- {isSaving ? (
80
- <ActivityIndicator color={tokens.colors.primary} />
81
- ) : (
82
- <AtomicIcon name="download" size="md" color="textPrimary" />
83
- )}
84
- </View>
85
- <AtomicText style={styles.label}>{saveButtonText}</AtomicText>
86
- </TouchableOpacity>
87
-
88
- <TouchableOpacity
89
- style={styles.actionButton}
90
- onPress={onShare}
91
- disabled={isSharing}
92
- >
93
- <View style={[styles.iconContainer, styles.iconContainerPrimary]}>
94
- {isSharing ? (
95
- <ActivityIndicator color="#FFFFFF" />
96
- ) : (
97
- <AtomicIcon name="share" size="md" color="onPrimary" />
98
- )}
99
- </View>
100
- <AtomicText style={styles.label}>{shareButtonText}</AtomicText>
101
- </TouchableOpacity>
102
-
103
- <TouchableOpacity style={styles.actionButton} onPress={onTryAgain}>
104
- <View style={[styles.iconContainer, styles.iconContainerSecondary]}>
105
- <AtomicIcon name="refresh" size="md" color="textPrimary" />
106
- </View>
107
- <AtomicText style={styles.label}>{tryAgainButtonText}</AtomicText>
108
- </TouchableOpacity>
60
+ <TouchableOpacity
61
+ style={styles.button}
62
+ onPress={onDownload}
63
+ disabled={isSaving}
64
+ activeOpacity={0.7}
65
+ >
66
+ {isSaving ? (
67
+ <ActivityIndicator color={tokens.colors.textInverse} size="small" />
68
+ ) : (
69
+ <AtomicIcon name="download-outline" size="sm" color="onPrimary" />
70
+ )}
71
+ <AtomicText style={styles.buttonText}>{saveButtonText}</AtomicText>
72
+ </TouchableOpacity>
109
73
 
110
- {onRate && rateButtonText && (
111
- <TouchableOpacity style={styles.actionButton} onPress={onRate}>
112
- <View style={[styles.iconContainer, styles.iconContainerSecondary]}>
113
- <AtomicIcon name="thumbs-up" size="md" color="textPrimary" />
114
- </View>
115
- <AtomicText style={styles.label}>{rateButtonText}</AtomicText>
116
- </TouchableOpacity>
74
+ <TouchableOpacity
75
+ style={styles.button}
76
+ onPress={onShare}
77
+ disabled={isSharing}
78
+ activeOpacity={0.7}
79
+ >
80
+ {isSharing ? (
81
+ <ActivityIndicator color={tokens.colors.textInverse} size="small" />
82
+ ) : (
83
+ <AtomicIcon name="share-social-outline" size="sm" color="onPrimary" />
117
84
  )}
118
- </View>
85
+ <AtomicText style={styles.buttonText}>{shareButtonText}</AtomicText>
86
+ </TouchableOpacity>
87
+
88
+ <TouchableOpacity
89
+ style={styles.button}
90
+ onPress={onTryAgain}
91
+ activeOpacity={0.7}
92
+ >
93
+ <AtomicIcon name="refresh-outline" size="sm" color="onPrimary" />
94
+ <AtomicText style={styles.buttonText}>{tryAgainButtonText}</AtomicText>
95
+ </TouchableOpacity>
119
96
  </View>
120
97
  );
121
98
  };
@@ -93,13 +93,9 @@ export const ResultPreviewScreen: React.FC<ResultPreviewScreenProps> = ({
93
93
  onDownload={onDownload}
94
94
  onShare={onShare}
95
95
  onTryAgain={onTryAgain}
96
- onRate={onRate}
97
96
  saveButtonText={translations.saveButton}
98
- saveButtonLoadingText={translations.saving}
99
97
  shareButtonText={translations.shareButton}
100
- shareButtonLoadingText={translations.sharing}
101
98
  tryAgainButtonText={translations.tryAnother}
102
- rateButtonText={translations.rateButton}
103
99
  />
104
100
  </View>
105
101
  {recentCreations && recentCreations.length > 0 && translations.recentCreations && translations.viewAll && (
@@ -118,6 +118,26 @@ export const useResultActions = (
118
118
  }
119
119
  }, [imageUrl, onSaveSuccess, onSaveError]);
120
120
 
121
+ /**
122
+ * Download image from URL to file
123
+ */
124
+ const downloadUrlToFile = async (url: string): Promise<string> => {
125
+ const timestamp = Date.now();
126
+ const filename = `ai_generation_${timestamp}.jpg`;
127
+ const file = new File(Paths.cache, filename);
128
+
129
+ const response = await fetch(url);
130
+ if (!response.ok) {
131
+ throw new Error(`Failed to download image: ${response.statusText}`);
132
+ }
133
+
134
+ const arrayBuffer = await response.arrayBuffer();
135
+ const bytes = new Uint8Array(arrayBuffer);
136
+ file.write(bytes);
137
+
138
+ return file.uri;
139
+ };
140
+
121
141
  /**
122
142
  * Share image
123
143
  */
@@ -134,9 +154,11 @@ export const useResultActions = (
134
154
  const normalizedUrl = toDataUrl(imageUrl);
135
155
  let shareUrl = normalizedUrl;
136
156
 
137
- // If it's a base64 string, save to file first for sharing
157
+ // Download to file for sharing (works for both base64 and remote URLs)
138
158
  if (isBase64DataUrl(normalizedUrl)) {
139
159
  shareUrl = await saveBase64ToFile(normalizedUrl);
160
+ } else if (normalizedUrl.startsWith("http")) {
161
+ shareUrl = await downloadUrlToFile(normalizedUrl);
140
162
  }
141
163
 
142
164
  // Use expo-sharing for cross-platform file sharing
@@ -63,20 +63,12 @@ export interface ResultActionBarProps {
63
63
  onShare: () => void;
64
64
  /** Try again callback */
65
65
  onTryAgain: () => void;
66
- /** Rate callback (optional) */
67
- onRate?: () => void;
68
66
  /** Save button text */
69
67
  saveButtonText: string;
70
- /** Save button text when loading */
71
- saveButtonLoadingText: string;
72
68
  /** Share button text */
73
69
  shareButtonText: string;
74
- /** Share button text when loading */
75
- shareButtonLoadingText: string;
76
70
  /** Try again button text */
77
71
  tryAgainButtonText: string;
78
- /** Rate button text (optional) */
79
- rateButtonText?: string;
80
72
  }
81
73
 
82
74
  /**