@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 +1 -1
- package/src/domains/result-preview/presentation/components/ResultActionBar.tsx +49 -72
- package/src/domains/result-preview/presentation/components/ResultPreviewScreen.tsx +0 -4
- package/src/domains/result-preview/presentation/hooks/useResultActions.ts +23 -1
- package/src/domains/result-preview/presentation/types/result-preview.types.ts +0 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-ai-generation-content",
|
|
3
|
-
"version": "1.17.
|
|
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: "
|
|
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
|
-
|
|
42
|
-
|
|
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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
<
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
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
|
/**
|