@umituz/react-native-ai-generation-content 1.17.275 → 1.17.277
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.
|
|
3
|
+
"version": "1.17.277",
|
|
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,6 +27,8 @@ export interface CreationsTranslations {
|
|
|
27
27
|
readonly statusFilterTitle?: string;
|
|
28
28
|
readonly mediaFilterTitle?: string;
|
|
29
29
|
readonly clearFilter?: string;
|
|
30
|
+
readonly resultTitle?: string;
|
|
31
|
+
readonly resultLabel?: string;
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
export interface CreationsFilterConfig {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useMemo, useCallback } from "react";
|
|
1
|
+
import React, { useState, useMemo, useCallback } from "react";
|
|
2
2
|
import { View, FlatList, RefreshControl, StyleSheet } from "react-native";
|
|
3
3
|
import {
|
|
4
4
|
useAppDesignTokens,
|
|
@@ -14,7 +14,10 @@ import { useCreations } from "../hooks/useCreations";
|
|
|
14
14
|
import { useDeleteCreation } from "../hooks/useDeleteCreation";
|
|
15
15
|
import { useGalleryFilters } from "../hooks/useGalleryFilters";
|
|
16
16
|
import { GalleryHeader, CreationCard, GalleryEmptyStates } from "../components";
|
|
17
|
+
import { ResultPreviewScreen } from "../../../result-preview/presentation/components/ResultPreviewScreen";
|
|
18
|
+
import { useResultActions } from "../../../result-preview/presentation/hooks/useResultActions";
|
|
17
19
|
import { MEDIA_FILTER_OPTIONS, STATUS_FILTER_OPTIONS } from "../../domain/types/creation-filter";
|
|
20
|
+
import { getPreviewUrl } from "../../domain/utils";
|
|
18
21
|
import type { Creation } from "../../domain/entities/Creation";
|
|
19
22
|
import type { CreationsConfig } from "../../domain/value-objects/CreationsConfig";
|
|
20
23
|
import type { ICreationsRepository } from "../../domain/repositories/ICreationsRepository";
|
|
@@ -24,11 +27,9 @@ interface CreationsGalleryScreenProps {
|
|
|
24
27
|
readonly repository: ICreationsRepository;
|
|
25
28
|
readonly config: CreationsConfig;
|
|
26
29
|
readonly t: (key: string) => string;
|
|
27
|
-
readonly locale?: string;
|
|
28
30
|
readonly onEmptyAction?: () => void;
|
|
29
31
|
readonly emptyActionLabel?: string;
|
|
30
32
|
readonly showFilter?: boolean;
|
|
31
|
-
readonly onViewResult?: (creation: Creation) => void;
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
export function CreationsGalleryScreen({
|
|
@@ -39,15 +40,23 @@ export function CreationsGalleryScreen({
|
|
|
39
40
|
onEmptyAction,
|
|
40
41
|
emptyActionLabel,
|
|
41
42
|
showFilter = config.showFilter ?? true,
|
|
42
|
-
onViewResult,
|
|
43
43
|
}: CreationsGalleryScreenProps) {
|
|
44
44
|
const tokens = useAppDesignTokens();
|
|
45
45
|
const { share } = useSharing();
|
|
46
46
|
const alert = useAlert();
|
|
47
|
+
const [selectedCreation, setSelectedCreation] = useState<Creation | null>(null);
|
|
47
48
|
|
|
48
49
|
const { data: creations, isLoading, refetch } = useCreations({ userId, repository });
|
|
49
50
|
const deleteMutation = useDeleteCreation({ userId, repository });
|
|
50
51
|
|
|
52
|
+
const selectedImageUrl = selectedCreation ? (getPreviewUrl(selectedCreation.output) || selectedCreation.uri) : undefined;
|
|
53
|
+
|
|
54
|
+
const { isSharing, isSaving, handleDownload, handleShare } = useResultActions({
|
|
55
|
+
imageUrl: selectedImageUrl,
|
|
56
|
+
onSaveSuccess: () => alert.show(AlertType.SUCCESS, AlertMode.TOAST, t("result.saveSuccess"), t("result.saveSuccessMessage")),
|
|
57
|
+
onSaveError: () => alert.show(AlertType.ERROR, AlertMode.TOAST, t("common.error"), t("result.saveError")),
|
|
58
|
+
});
|
|
59
|
+
|
|
51
60
|
const statusOptions = config.filterConfig?.statusOptions ?? STATUS_FILTER_OPTIONS;
|
|
52
61
|
const mediaOptions = config.filterConfig?.mediaOptions ?? MEDIA_FILTER_OPTIONS;
|
|
53
62
|
const showStatusFilter = config.filterConfig?.showStatusFilter ?? true;
|
|
@@ -57,7 +66,7 @@ export function CreationsGalleryScreen({
|
|
|
57
66
|
|
|
58
67
|
useFocusEffect(useCallback(() => { void refetch(); }, [refetch]));
|
|
59
68
|
|
|
60
|
-
const
|
|
69
|
+
const handleShareCard = useCallback((c: Creation) => {
|
|
61
70
|
void share(c.uri, { dialogTitle: t("common.share") });
|
|
62
71
|
}, [share, t]);
|
|
63
72
|
|
|
@@ -80,6 +89,18 @@ export function CreationsGalleryScreen({
|
|
|
80
89
|
})();
|
|
81
90
|
}, [userId, repository, refetch]);
|
|
82
91
|
|
|
92
|
+
const handleCardPress = useCallback((item: Creation) => {
|
|
93
|
+
setSelectedCreation(item);
|
|
94
|
+
}, []);
|
|
95
|
+
|
|
96
|
+
const handleBack = useCallback(() => {
|
|
97
|
+
setSelectedCreation(null);
|
|
98
|
+
}, []);
|
|
99
|
+
|
|
100
|
+
const handleTryAgain = useCallback(() => {
|
|
101
|
+
setSelectedCreation(null);
|
|
102
|
+
}, []);
|
|
103
|
+
|
|
83
104
|
const filterButtons = useMemo(() => {
|
|
84
105
|
const buttons = [];
|
|
85
106
|
if (showStatusFilter) {
|
|
@@ -103,27 +124,17 @@ export function CreationsGalleryScreen({
|
|
|
103
124
|
return buttons;
|
|
104
125
|
}, [showStatusFilter, showMediaFilter, filters, t, config.translations]);
|
|
105
126
|
|
|
106
|
-
const handleCardPress = useCallback((item: Creation) => {
|
|
107
|
-
if (__DEV__) {
|
|
108
|
-
console.log("[CreationsGalleryScreen] Card pressed", {
|
|
109
|
-
creationId: item.id,
|
|
110
|
-
hasOnViewResult: !!onViewResult
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
onViewResult?.(item);
|
|
114
|
-
}, [onViewResult]);
|
|
115
|
-
|
|
116
127
|
const renderItem = useCallback(({ item }: { item: Creation }) => (
|
|
117
128
|
<CreationCard
|
|
118
129
|
creation={item}
|
|
119
130
|
callbacks={{
|
|
120
131
|
onPress: () => handleCardPress(item),
|
|
121
|
-
onShare: async () =>
|
|
132
|
+
onShare: async () => handleShareCard(item),
|
|
122
133
|
onDelete: () => handleDelete(item),
|
|
123
134
|
onFavorite: () => handleFavorite(item, !item.isFavorite),
|
|
124
135
|
}}
|
|
125
136
|
/>
|
|
126
|
-
), [
|
|
137
|
+
), [handleShareCard, handleDelete, handleFavorite, handleCardPress]);
|
|
127
138
|
|
|
128
139
|
const renderHeader = useMemo(() => {
|
|
129
140
|
if ((!creations || creations.length === 0) && !isLoading) return null;
|
|
@@ -155,6 +166,30 @@ export function CreationsGalleryScreen({
|
|
|
155
166
|
/>
|
|
156
167
|
), [isLoading, creations, filters.isFiltered, tokens, t, config, emptyActionLabel, onEmptyAction, filters.clearAllFilters]);
|
|
157
168
|
|
|
169
|
+
// Show result preview when a creation is selected
|
|
170
|
+
if (selectedCreation && selectedImageUrl) {
|
|
171
|
+
return (
|
|
172
|
+
<ResultPreviewScreen
|
|
173
|
+
imageUrl={selectedImageUrl}
|
|
174
|
+
isSaving={isSaving}
|
|
175
|
+
isSharing={isSharing}
|
|
176
|
+
onDownload={handleDownload}
|
|
177
|
+
onShare={handleShare}
|
|
178
|
+
onTryAgain={handleTryAgain}
|
|
179
|
+
onNavigateBack={handleBack}
|
|
180
|
+
translations={{
|
|
181
|
+
title: t(config.translations.resultTitle ?? "result.title"),
|
|
182
|
+
yourResult: t(config.translations.resultLabel ?? "result.yourResult"),
|
|
183
|
+
saveButton: t("result.saveButton"),
|
|
184
|
+
saving: t("result.saving"),
|
|
185
|
+
shareButton: t("result.shareButton"),
|
|
186
|
+
sharing: t("result.sharing"),
|
|
187
|
+
tryAnother: t("result.tryAnother"),
|
|
188
|
+
}}
|
|
189
|
+
/>
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
158
193
|
return (
|
|
159
194
|
<ScreenLayout scrollable={false}>
|
|
160
195
|
<FlatList
|
|
@@ -163,10 +198,7 @@ export function CreationsGalleryScreen({
|
|
|
163
198
|
keyExtractor={(item) => item.id}
|
|
164
199
|
ListHeaderComponent={renderHeader}
|
|
165
200
|
ListEmptyComponent={renderEmpty}
|
|
166
|
-
contentContainerStyle={[
|
|
167
|
-
styles.listContent,
|
|
168
|
-
(!filters.filtered || filters.filtered.length === 0) && styles.emptyContent
|
|
169
|
-
]}
|
|
201
|
+
contentContainerStyle={[styles.listContent, (!filters.filtered || filters.filtered.length === 0) && styles.emptyContent]}
|
|
170
202
|
showsVerticalScrollIndicator={false}
|
|
171
203
|
refreshControl={<RefreshControl refreshing={isLoading} onRefresh={() => void refetch()} tintColor={tokens.colors.primary} />}
|
|
172
204
|
/>
|
|
@@ -177,7 +209,6 @@ export function CreationsGalleryScreen({
|
|
|
177
209
|
}
|
|
178
210
|
|
|
179
211
|
const styles = StyleSheet.create({
|
|
180
|
-
container: { flex: 1 },
|
|
181
212
|
header: { borderBottomWidth: 1 },
|
|
182
213
|
listContent: { paddingHorizontal: 16, paddingTop: 16 },
|
|
183
214
|
emptyContent: { flexGrow: 1 },
|