@umituz/react-native-ai-generation-content 1.20.45 → 1.20.47
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.20.
|
|
3
|
+
"version": "1.20.47",
|
|
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",
|
package/src/index.ts
CHANGED
|
@@ -56,11 +56,13 @@ export {
|
|
|
56
56
|
extractAudioUrl, extractImageUrls, cleanBase64, addBase64Prefix, preparePhoto, preparePhotos,
|
|
57
57
|
isValidBase64, getBase64Size, getBase64SizeMB, prepareImage, createDevCallbacks, createFeatureUtils,
|
|
58
58
|
showVideoGenerationSuccess, handleGenerationError, showContentModerationWarning,
|
|
59
|
+
saveMediaToGallery, shareMedia, createSaveHandler, createShareHandler, createMediaHandlers,
|
|
59
60
|
} from "./infrastructure/utils";
|
|
60
61
|
|
|
61
62
|
export type {
|
|
62
63
|
IntervalOptions, ProgressOptions, StatusCheckResult, ResultValidation, ValidateResultOptions,
|
|
63
64
|
PhotoInput, PreparedImage, ImageSelector, VideoSaver, AlertFunction, FeatureUtilsConfig, VideoAlertFunction,
|
|
65
|
+
MediaActionResult, MediaActionTranslations, ToastConfig,
|
|
64
66
|
} from "./infrastructure/utils";
|
|
65
67
|
|
|
66
68
|
export { enhancePromptWithLanguage, getSupportedLanguages, getLanguageName, ModerationWrapper, generateSynchronously } from "./infrastructure/wrappers";
|
|
@@ -72,6 +74,7 @@ export {
|
|
|
72
74
|
useAIGenerateState, AIGenerateStep,
|
|
73
75
|
useGenerationOrchestrator, useImageGeneration, useVideoGeneration, useAIFeatureGeneration,
|
|
74
76
|
createGenerationError, getAlertMessage, parseError,
|
|
77
|
+
useAIGenerateWizard, createWizardTranslations,
|
|
75
78
|
} from "./presentation/hooks";
|
|
76
79
|
|
|
77
80
|
export type {
|
|
@@ -84,6 +87,7 @@ export type {
|
|
|
84
87
|
SingleImageInput, DualImageInput, ImageGenerationInput, ImageGenerationConfig,
|
|
85
88
|
DualImageVideoInput, VideoGenerationConfig,
|
|
86
89
|
UploadedImage,
|
|
90
|
+
AIGenerateWizardConfig, AIGenerateWizardTranslations, UseAIGenerateWizardReturn,
|
|
87
91
|
} from "./presentation/hooks";
|
|
88
92
|
|
|
89
93
|
export {
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Media Actions Utilities
|
|
3
|
+
* Provides save to gallery and share functionality for generated media
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface MediaActionResult {
|
|
7
|
+
readonly success: boolean;
|
|
8
|
+
readonly error?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface MediaActionTranslations {
|
|
12
|
+
readonly success?: string;
|
|
13
|
+
readonly error?: string;
|
|
14
|
+
readonly permissionDenied?: string;
|
|
15
|
+
readonly saveFailed?: string;
|
|
16
|
+
readonly shareFailed?: string;
|
|
17
|
+
readonly shareNotAvailable?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface ToastConfig {
|
|
21
|
+
readonly show: (config: {
|
|
22
|
+
type: "success" | "error";
|
|
23
|
+
text1: string;
|
|
24
|
+
text2?: string;
|
|
25
|
+
}) => void;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Downloads a file from URL to local storage
|
|
30
|
+
* @param uri - URL or local path
|
|
31
|
+
* @param prefix - File name prefix
|
|
32
|
+
* @returns Local file path
|
|
33
|
+
*/
|
|
34
|
+
const downloadToLocal = async (
|
|
35
|
+
uri: string,
|
|
36
|
+
prefix: string = "media"
|
|
37
|
+
): Promise<string> => {
|
|
38
|
+
if (!uri.startsWith("http")) {
|
|
39
|
+
return uri;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const FileSystem = require("expo-file-system");
|
|
43
|
+
const fileExt = uri.split(".").pop()?.split("?")[0] || "jpg";
|
|
44
|
+
const fileRef =
|
|
45
|
+
FileSystem.documentDirectory + `${prefix}_${Date.now()}.${fileExt}`;
|
|
46
|
+
const { uri: downloadedUri } = await FileSystem.downloadAsync(uri, fileRef);
|
|
47
|
+
return downloadedUri;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Saves media to device gallery
|
|
52
|
+
* @param uri - URL or local path of the media
|
|
53
|
+
* @param translations - Optional translated messages
|
|
54
|
+
* @param toast - Optional toast instance for notifications
|
|
55
|
+
* @returns Result with success status
|
|
56
|
+
*/
|
|
57
|
+
export const saveMediaToGallery = async (
|
|
58
|
+
uri: string,
|
|
59
|
+
translations?: MediaActionTranslations,
|
|
60
|
+
toast?: ToastConfig
|
|
61
|
+
): Promise<MediaActionResult> => {
|
|
62
|
+
try {
|
|
63
|
+
const MediaLibrary = require("expo-media-library");
|
|
64
|
+
|
|
65
|
+
const { status } = await MediaLibrary.requestPermissionsAsync();
|
|
66
|
+
if (status !== "granted") {
|
|
67
|
+
const errorMsg = translations?.permissionDenied || "Permission denied";
|
|
68
|
+
toast?.show({
|
|
69
|
+
type: "error",
|
|
70
|
+
text1: translations?.error || "Error",
|
|
71
|
+
text2: errorMsg,
|
|
72
|
+
});
|
|
73
|
+
return { success: false, error: errorMsg };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const localUri = await downloadToLocal(uri, "download");
|
|
77
|
+
await MediaLibrary.saveToLibraryAsync(localUri);
|
|
78
|
+
|
|
79
|
+
toast?.show({
|
|
80
|
+
type: "success",
|
|
81
|
+
text1: translations?.success || "Success",
|
|
82
|
+
text2: "Saved to gallery",
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
return { success: true };
|
|
86
|
+
} catch (error) {
|
|
87
|
+
// Debug logging in development
|
|
88
|
+
try {
|
|
89
|
+
if ((global as Record<string, unknown>).__DEV__) {
|
|
90
|
+
console.error("[MediaActions] Save failed:", error);
|
|
91
|
+
}
|
|
92
|
+
} catch {
|
|
93
|
+
// Ignore if __DEV__ check fails
|
|
94
|
+
}
|
|
95
|
+
const errorMsg = translations?.saveFailed || "Failed to save media";
|
|
96
|
+
toast?.show({
|
|
97
|
+
type: "error",
|
|
98
|
+
text1: translations?.error || "Error",
|
|
99
|
+
text2: errorMsg,
|
|
100
|
+
});
|
|
101
|
+
return {
|
|
102
|
+
success: false,
|
|
103
|
+
error: error instanceof Error ? error.message : errorMsg,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Shares media using device share sheet
|
|
110
|
+
* @param uri - URL or local path of the media
|
|
111
|
+
* @param translations - Optional translated messages
|
|
112
|
+
* @param toast - Optional toast instance for notifications
|
|
113
|
+
* @returns Result with success status
|
|
114
|
+
*/
|
|
115
|
+
export const shareMedia = async (
|
|
116
|
+
uri: string,
|
|
117
|
+
translations?: MediaActionTranslations,
|
|
118
|
+
toast?: ToastConfig
|
|
119
|
+
): Promise<MediaActionResult> => {
|
|
120
|
+
try {
|
|
121
|
+
const Sharing = require("expo-sharing");
|
|
122
|
+
|
|
123
|
+
const isAvailable = await Sharing.isAvailableAsync();
|
|
124
|
+
if (!isAvailable) {
|
|
125
|
+
const errorMsg =
|
|
126
|
+
translations?.shareNotAvailable ||
|
|
127
|
+
"Sharing is not available on this device";
|
|
128
|
+
toast?.show({
|
|
129
|
+
type: "error",
|
|
130
|
+
text1: translations?.error || "Error",
|
|
131
|
+
text2: errorMsg,
|
|
132
|
+
});
|
|
133
|
+
return { success: false, error: errorMsg };
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const localUri = await downloadToLocal(uri, "share");
|
|
137
|
+
await Sharing.shareAsync(localUri);
|
|
138
|
+
|
|
139
|
+
return { success: true };
|
|
140
|
+
} catch (error) {
|
|
141
|
+
// Debug logging in development
|
|
142
|
+
try {
|
|
143
|
+
if ((global as Record<string, unknown>).__DEV__) {
|
|
144
|
+
console.error("[MediaActions] Share failed:", error);
|
|
145
|
+
}
|
|
146
|
+
} catch {
|
|
147
|
+
// Ignore if __DEV__ check fails
|
|
148
|
+
}
|
|
149
|
+
const errorMsg = translations?.shareFailed || "Failed to share media";
|
|
150
|
+
toast?.show({
|
|
151
|
+
type: "error",
|
|
152
|
+
text1: translations?.error || "Error",
|
|
153
|
+
text2: errorMsg,
|
|
154
|
+
});
|
|
155
|
+
return {
|
|
156
|
+
success: false,
|
|
157
|
+
error: error instanceof Error ? error.message : errorMsg,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Creates save handler for use in wizard flows
|
|
164
|
+
* @param translations - Translated messages
|
|
165
|
+
* @param toast - Toast instance for notifications
|
|
166
|
+
* @returns Save handler function
|
|
167
|
+
*/
|
|
168
|
+
export const createSaveHandler = (
|
|
169
|
+
translations?: MediaActionTranslations,
|
|
170
|
+
toast?: ToastConfig
|
|
171
|
+
) => {
|
|
172
|
+
return async (uri: string): Promise<void> => {
|
|
173
|
+
await saveMediaToGallery(uri, translations, toast);
|
|
174
|
+
};
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Creates share handler for use in wizard flows
|
|
179
|
+
* @param translations - Translated messages
|
|
180
|
+
* @param toast - Toast instance for notifications
|
|
181
|
+
* @returns Share handler function
|
|
182
|
+
*/
|
|
183
|
+
export const createShareHandler = (
|
|
184
|
+
translations?: MediaActionTranslations,
|
|
185
|
+
toast?: ToastConfig
|
|
186
|
+
) => {
|
|
187
|
+
return async (uri: string): Promise<void> => {
|
|
188
|
+
await shareMedia(uri, translations, toast);
|
|
189
|
+
};
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Creates both save and share handlers
|
|
194
|
+
* @param translations - Translated messages
|
|
195
|
+
* @param toast - Toast instance for notifications
|
|
196
|
+
* @returns Object with onSave and onShare handlers
|
|
197
|
+
*/
|
|
198
|
+
export const createMediaHandlers = (
|
|
199
|
+
translations?: MediaActionTranslations,
|
|
200
|
+
toast?: ToastConfig
|
|
201
|
+
) => {
|
|
202
|
+
return {
|
|
203
|
+
onSave: createSaveHandler(translations, toast),
|
|
204
|
+
onShare: createShareHandler(translations, toast),
|
|
205
|
+
};
|
|
206
|
+
};
|
|
@@ -63,3 +63,10 @@ export type {
|
|
|
63
63
|
|
|
64
64
|
export { useAIGenerateState, AIGenerateStep } from "./generation/useAIGenerateState";
|
|
65
65
|
export type { UploadedImage } from "./generation/useAIGenerateState";
|
|
66
|
+
|
|
67
|
+
export { useAIGenerateWizard, createWizardTranslations } from "./useAIGenerateWizard";
|
|
68
|
+
export type {
|
|
69
|
+
AIGenerateWizardConfig,
|
|
70
|
+
AIGenerateWizardTranslations,
|
|
71
|
+
UseAIGenerateWizardReturn,
|
|
72
|
+
} from "./useAIGenerateWizard";
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useAIGenerateWizard Hook
|
|
3
|
+
* Provides all necessary logic for AI generation wizard screens
|
|
4
|
+
* Centralizes save, share, and generation handling
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { useCallback, useMemo } from "react";
|
|
8
|
+
import {
|
|
9
|
+
saveMediaToGallery,
|
|
10
|
+
shareMedia,
|
|
11
|
+
type MediaActionTranslations,
|
|
12
|
+
type ToastConfig,
|
|
13
|
+
} from "../../infrastructure/utils/media-actions.util";
|
|
14
|
+
import { useAIFeatureGeneration } from "./generation";
|
|
15
|
+
import type { AlertMessages } from "./generation";
|
|
16
|
+
|
|
17
|
+
export interface AIGenerateWizardConfig {
|
|
18
|
+
readonly featureType: string;
|
|
19
|
+
readonly userId?: string;
|
|
20
|
+
readonly alertMessages?: AlertMessages;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface AIGenerateWizardTranslations {
|
|
24
|
+
readonly headerTitle: string;
|
|
25
|
+
readonly uploadSubtitle: string;
|
|
26
|
+
readonly uploadSubtitle2: string;
|
|
27
|
+
readonly continue: string;
|
|
28
|
+
readonly tapToUpload: string;
|
|
29
|
+
readonly selectPhoto: string;
|
|
30
|
+
readonly change: string;
|
|
31
|
+
readonly analyzing: string;
|
|
32
|
+
readonly error: string;
|
|
33
|
+
readonly uploadFailed: string;
|
|
34
|
+
readonly aiDisclosure: string;
|
|
35
|
+
readonly heroTitle: string;
|
|
36
|
+
readonly heroSubtitle: string;
|
|
37
|
+
readonly presetsTitle: string;
|
|
38
|
+
readonly showAdvancedLabel: string;
|
|
39
|
+
readonly hideAdvancedLabel: string;
|
|
40
|
+
readonly promptTitle: string;
|
|
41
|
+
readonly promptPlaceholder: string;
|
|
42
|
+
readonly styleTitle: string;
|
|
43
|
+
readonly durationTitle: string;
|
|
44
|
+
readonly generateButton: string;
|
|
45
|
+
readonly generatingButton: string;
|
|
46
|
+
readonly processingTitle: string;
|
|
47
|
+
readonly processingMessage: string;
|
|
48
|
+
readonly processingHint: string;
|
|
49
|
+
readonly successTitle: string;
|
|
50
|
+
readonly saveButton: string;
|
|
51
|
+
readonly shareButton: string;
|
|
52
|
+
readonly tryAgainButton: string;
|
|
53
|
+
readonly fileTooLarge: string;
|
|
54
|
+
readonly maxFileSize: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface UseAIGenerateWizardReturn {
|
|
58
|
+
readonly generate: (data: {
|
|
59
|
+
prompt: string;
|
|
60
|
+
style: string;
|
|
61
|
+
duration: number;
|
|
62
|
+
images: { uri: string }[];
|
|
63
|
+
}) => Promise<string | null | void>;
|
|
64
|
+
readonly handleSave: (uri: string) => Promise<void>;
|
|
65
|
+
readonly handleShare: (uri: string) => Promise<void>;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Hook that provides all AI generation wizard functionality
|
|
70
|
+
* Handles generation, save, and share operations
|
|
71
|
+
*/
|
|
72
|
+
export function useAIGenerateWizard(
|
|
73
|
+
config: AIGenerateWizardConfig,
|
|
74
|
+
translations: { error?: string; success?: string },
|
|
75
|
+
toast?: ToastConfig
|
|
76
|
+
): UseAIGenerateWizardReturn {
|
|
77
|
+
const { generate } = useAIFeatureGeneration({
|
|
78
|
+
featureType: config.featureType as never,
|
|
79
|
+
alertMessages: config.alertMessages ?? {
|
|
80
|
+
success: translations.success ?? "Generation successful",
|
|
81
|
+
error: translations.error ?? "Error",
|
|
82
|
+
creditLimit: "Insufficient credits",
|
|
83
|
+
},
|
|
84
|
+
userId: config.userId,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const mediaTranslations: MediaActionTranslations = useMemo(
|
|
88
|
+
() => ({
|
|
89
|
+
success: translations.success,
|
|
90
|
+
error: translations.error,
|
|
91
|
+
permissionDenied: "Permission denied",
|
|
92
|
+
saveFailed: "Failed to save media",
|
|
93
|
+
shareFailed: "Failed to share media",
|
|
94
|
+
shareNotAvailable: "Sharing is not available on this device",
|
|
95
|
+
}),
|
|
96
|
+
[translations]
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
const handleSave = useCallback(
|
|
100
|
+
async (uri: string): Promise<void> => {
|
|
101
|
+
await saveMediaToGallery(uri, mediaTranslations, toast);
|
|
102
|
+
},
|
|
103
|
+
[mediaTranslations, toast]
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
const handleShare = useCallback(
|
|
107
|
+
async (uri: string): Promise<void> => {
|
|
108
|
+
await shareMedia(uri, mediaTranslations, toast);
|
|
109
|
+
},
|
|
110
|
+
[mediaTranslations, toast]
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
generate,
|
|
115
|
+
handleSave,
|
|
116
|
+
handleShare,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Creates translations object from t function
|
|
122
|
+
* @param t - Translation function
|
|
123
|
+
* @param featureType - Feature type for feature-specific keys
|
|
124
|
+
* @returns Translations object for AIGenerateWizardFlow
|
|
125
|
+
*/
|
|
126
|
+
export function createWizardTranslations(
|
|
127
|
+
t: (key: string) => string,
|
|
128
|
+
featureType: string
|
|
129
|
+
): AIGenerateWizardTranslations {
|
|
130
|
+
const featureKey = featureType.replace(/-/g, "_");
|
|
131
|
+
return {
|
|
132
|
+
headerTitle: t(`home.ai_features.${featureKey}.title`),
|
|
133
|
+
uploadSubtitle: t("imageProcessing.upload.subtitle"),
|
|
134
|
+
uploadSubtitle2: t("imageProcessing.upload.subtitle_2"),
|
|
135
|
+
continue: t("common.actions.continue"),
|
|
136
|
+
tapToUpload: t("imageProcessing.upload.tapToUpload"),
|
|
137
|
+
selectPhoto: t("imageProcessing.upload.selectPhoto"),
|
|
138
|
+
change: t("imageProcessing.upload.change"),
|
|
139
|
+
analyzing: t("imageProcessing.upload.analyzing"),
|
|
140
|
+
error: t("common.error"),
|
|
141
|
+
uploadFailed: t("common.errors.upload_failed"),
|
|
142
|
+
aiDisclosure: t("imageProcessing.upload.aiDisclosure"),
|
|
143
|
+
heroTitle: "",
|
|
144
|
+
heroSubtitle: "",
|
|
145
|
+
presetsTitle: t("common.generation.presets.title"),
|
|
146
|
+
showAdvancedLabel: t("common.generation.advanced.show"),
|
|
147
|
+
hideAdvancedLabel: t("common.generation.advanced.hide"),
|
|
148
|
+
promptTitle: t("common.prompts.custom_prompt"),
|
|
149
|
+
promptPlaceholder: t("common.prompts.placeholder"),
|
|
150
|
+
styleTitle: t("common.generation.style_selector.video_title"),
|
|
151
|
+
durationTitle: t("common.generation.duration_selector.title"),
|
|
152
|
+
generateButton: t("common.actions.generate"),
|
|
153
|
+
generatingButton: t("common.actions.generating"),
|
|
154
|
+
processingTitle: t("common.generation.progress.title"),
|
|
155
|
+
processingMessage: t("common.generation.progress.hint"),
|
|
156
|
+
processingHint: t("common.generation.progress.backgroundHint"),
|
|
157
|
+
successTitle: t("common.generation.success"),
|
|
158
|
+
saveButton: t("common.actions.save"),
|
|
159
|
+
shareButton: t("common.actions.share"),
|
|
160
|
+
tryAgainButton: t("common.actions.try_again"),
|
|
161
|
+
fileTooLarge: t("common.errors.file_too_large"),
|
|
162
|
+
maxFileSize: t("common.errors.max_file_size"),
|
|
163
|
+
};
|
|
164
|
+
}
|