@umituz/react-native-ai-generation-content 1.12.21 → 1.12.24
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 +33 -15
- package/src/domains/content-moderation/infrastructure/services/content-moderation.service.ts +4 -32
- package/src/domains/content-moderation/infrastructure/services/moderators/base.moderator.ts +1 -1
- package/src/domains/face-detection/infrastructure/validators/faceValidator.ts +1 -1
- package/src/domains/face-detection/presentation/components/FaceValidationStatus.tsx +3 -3
- package/src/domains/prompts/domain/entities/FuturePredictionConfig.ts +2 -1
- package/src/domains/prompts/domain/entities/GeneratedPrompt.ts +0 -1
- package/src/domains/prompts/domain/repositories/IAIPromptServices.ts +6 -12
- package/src/domains/prompts/infrastructure/repositories/PromptHistoryRepository.ts +42 -42
- package/src/domains/prompts/infrastructure/repositories/TemplateRepository.ts +42 -42
- package/src/domains/prompts/infrastructure/services/BackgroundRemovalService.ts +7 -7
- package/src/domains/prompts/infrastructure/services/ColorizationService.ts +7 -7
- package/src/domains/prompts/infrastructure/services/FaceSwapService.ts +19 -20
- package/src/domains/prompts/infrastructure/services/FuturePredictionService.ts +11 -31
- package/src/domains/prompts/infrastructure/services/ImageEnhancementService.ts +7 -7
- package/src/domains/prompts/infrastructure/services/PhotoRestorationService.ts +7 -7
- package/src/domains/prompts/infrastructure/services/PromptGenerationService.ts +13 -13
- package/src/domains/prompts/infrastructure/services/StyleTransferService.ts +8 -8
- package/src/domains/prompts/infrastructure/services/TextGenerationService.ts +7 -7
- package/src/domains/prompts/presentation/hooks/useAIServices.ts +30 -28
- package/src/domains/prompts/presentation/hooks/useFaceSwap.ts +1 -2
- package/src/domains/prompts/presentation/hooks/usePromptGeneration.ts +4 -5
- package/src/domains/prompts/presentation/hooks/useStyleTransfer.ts +1 -1
- package/src/domains/prompts/presentation/hooks/useTemplateRepository.ts +3 -3
- package/src/domains/prompts/presentation/theme/utils.ts +1 -1
- package/src/features/audio-generation/domain/entities.ts +39 -0
- package/src/features/audio-generation/index.ts +2 -0
- package/src/features/audio-generation/presentation/hooks.ts +39 -0
- package/src/{domains/feature-background → features/background}/presentation/components/BackgroundFeature.tsx +5 -4
- package/src/{domains/feature-background → features/background}/presentation/components/ComparisonSlider.tsx +45 -51
- package/src/{domains/feature-background → features/background}/presentation/components/ErrorDisplay.tsx +5 -3
- package/src/{domains/feature-background → features/background}/presentation/components/ModeSelector.tsx +2 -2
- package/src/{domains/feature-background → features/background}/presentation/hooks/useBackgroundFeature.ts +3 -2
- package/src/features/colorization/domain/entities.ts +46 -0
- package/src/features/colorization/index.ts +2 -0
- package/src/features/colorization/presentation/hooks.ts +39 -0
- package/src/features/face-swap/domain/entities.ts +48 -0
- package/src/features/face-swap/index.ts +2 -0
- package/src/features/face-swap/presentation/hooks.ts +41 -0
- package/src/features/future-prediction/domain/entities.ts +45 -0
- package/src/features/future-prediction/index.ts +2 -0
- package/src/features/future-prediction/presentation/hooks.ts +39 -0
- package/src/features/image-captioning/domain/entities.ts +47 -0
- package/src/features/image-captioning/index.ts +2 -0
- package/src/features/image-captioning/presentation/hooks.ts +39 -0
- package/src/features/inpainting/domain/entities.ts +58 -0
- package/src/features/inpainting/index.ts +2 -0
- package/src/features/inpainting/presentation/hooks.ts +39 -0
- package/src/features/photo-restoration/domain/entities.ts +48 -0
- package/src/features/photo-restoration/index.ts +2 -0
- package/src/features/photo-restoration/presentation/hooks.ts +39 -0
- package/src/features/sketch-to-image/domain/entities.ts +47 -0
- package/src/features/sketch-to-image/index.ts +2 -0
- package/src/features/sketch-to-image/presentation/hooks.ts +39 -0
- package/src/features/style-transfer/domain/entities.ts +52 -0
- package/src/features/style-transfer/index.ts +2 -0
- package/src/features/style-transfer/presentation/hooks.ts +39 -0
- package/src/features/text-to-image/domain/entities.ts +58 -0
- package/src/features/text-to-image/index.ts +2 -0
- package/src/features/text-to-image/presentation/hooks.ts +39 -0
- package/src/features/text-to-video/domain/entities.ts +52 -0
- package/src/features/text-to-video/index.ts +2 -0
- package/src/features/text-to-video/presentation/hooks.ts +39 -0
- package/src/features/upscaling/domain/entities.ts +42 -0
- package/src/features/upscaling/index.ts +2 -0
- package/src/features/upscaling/presentation/hooks.ts +39 -0
- package/src/index.ts +3 -6
- package/src/infrastructure/utils/status-checker.util.ts +4 -4
- package/src/infrastructure/wrappers/synchronous-generation.wrapper.ts +3 -3
- package/src/presentation/components/result/GenerationResultContent.tsx +21 -22
- package/src/presentation/components/result/ResultActions.tsx +51 -52
- package/src/presentation/components/result/ResultHeader.tsx +24 -25
- package/src/presentation/components/result/ResultImageCard.tsx +19 -20
- package/src/presentation/components/result/ResultStoryCard.tsx +23 -24
- package/src/presentation/hooks/photo-generation.types.ts +13 -4
- package/src/presentation/hooks/usePhotoGeneration.ts +30 -13
- package/src/domains/creations/application/services/CreationsService.ts +0 -72
- package/src/domains/creations/domain/entities/Creation.ts +0 -54
- package/src/domains/creations/domain/entities/index.ts +0 -6
- package/src/domains/creations/domain/repositories/ICreationsRepository.ts +0 -25
- package/src/domains/creations/domain/repositories/index.ts +0 -5
- package/src/domains/creations/domain/services/ICreationsStorageService.ts +0 -13
- package/src/domains/creations/domain/value-objects/CreationsConfig.ts +0 -77
- package/src/domains/creations/domain/value-objects/index.ts +0 -12
- package/src/domains/creations/index.ts +0 -84
- package/src/domains/creations/infrastructure/adapters/createRepository.ts +0 -54
- package/src/domains/creations/infrastructure/adapters/index.ts +0 -5
- package/src/domains/creations/infrastructure/repositories/CreationsRepository.ts +0 -263
- package/src/domains/creations/infrastructure/repositories/index.ts +0 -8
- package/src/domains/creations/infrastructure/services/CreationsStorageService.ts +0 -48
- package/src/domains/creations/presentation/components/CreationCard.tsx +0 -196
- package/src/domains/creations/presentation/components/CreationDetail/DetailActions.tsx +0 -76
- package/src/domains/creations/presentation/components/CreationDetail/DetailHeader.tsx +0 -81
- package/src/domains/creations/presentation/components/CreationDetail/DetailImage.tsx +0 -41
- package/src/domains/creations/presentation/components/CreationDetail/DetailStory.tsx +0 -67
- package/src/domains/creations/presentation/components/CreationDetail/index.ts +0 -4
- package/src/domains/creations/presentation/components/CreationImageViewer.tsx +0 -101
- package/src/domains/creations/presentation/components/CreationThumbnail.tsx +0 -63
- package/src/domains/creations/presentation/components/CreationsGalleryEmptyState.tsx +0 -77
- package/src/domains/creations/presentation/components/CreationsGrid.tsx +0 -87
- package/src/domains/creations/presentation/components/CreationsHomeCard.tsx +0 -176
- package/src/domains/creations/presentation/components/EmptyState.tsx +0 -75
- package/src/domains/creations/presentation/components/FilterBottomSheet.tsx +0 -157
- package/src/domains/creations/presentation/components/FilterChips.tsx +0 -105
- package/src/domains/creations/presentation/components/GalleryHeader.tsx +0 -157
- package/src/domains/creations/presentation/components/index.ts +0 -20
- package/src/domains/creations/presentation/hooks/index.ts +0 -9
- package/src/domains/creations/presentation/hooks/useCreations.ts +0 -33
- package/src/domains/creations/presentation/hooks/useCreationsFilter.ts +0 -90
- package/src/domains/creations/presentation/hooks/useDeleteCreation.ts +0 -51
- package/src/domains/creations/presentation/hooks/useDeleteMultipleCreations.ts +0 -57
- package/src/domains/creations/presentation/hooks/useToggleFavorite.ts +0 -59
- package/src/domains/creations/presentation/screens/CreationDetailScreen.tsx +0 -71
- package/src/domains/creations/presentation/screens/CreationsGalleryScreen.tsx +0 -264
- package/src/domains/creations/presentation/screens/index.ts +0 -5
- package/src/domains/creations/presentation/utils/filterUtils.ts +0 -52
- package/src/domains/creations/types.d.ts +0 -107
- /package/src/{domains/feature-background → features/background}/domain/entities/background.types.ts +0 -0
- /package/src/{domains/feature-background → features/background}/domain/entities/component.types.ts +0 -0
- /package/src/{domains/feature-background → features/background}/domain/entities/config.types.ts +0 -0
- /package/src/{domains/feature-background → features/background}/domain/entities/index.ts +0 -0
- /package/src/{domains/feature-background → features/background}/index.ts +0 -0
- /package/src/{domains/feature-background → features/background}/infrastructure/constants/index.ts +0 -0
- /package/src/{domains/feature-background → features/background}/infrastructure/constants/prompts.constants.ts +0 -0
- /package/src/{domains/feature-background → features/background}/presentation/components/FeatureHeader.tsx +0 -0
- /package/src/{domains/feature-background → features/background}/presentation/components/GenerateButton.tsx +0 -0
- /package/src/{domains/feature-background → features/background}/presentation/components/ImagePicker.tsx +0 -0
- /package/src/{domains/feature-background → features/background}/presentation/components/ProcessingModal.tsx +0 -0
- /package/src/{domains/feature-background → features/background}/presentation/components/PromptInput.tsx +0 -0
- /package/src/{domains/feature-background → features/background}/presentation/components/ResultDisplay.tsx +0 -0
- /package/src/{domains/feature-background → features/background}/presentation/components/index.ts +0 -0
- /package/src/{domains/feature-background → features/background}/presentation/hooks/index.ts +0 -0
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
* Composition of result components for CelebrationModal
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import React from "react";
|
|
7
|
-
import {
|
|
6
|
+
import * as React from "react";
|
|
7
|
+
import { useMemo } from "react";
|
|
8
|
+
import { ScrollView, StyleSheet, Dimensions, type ViewStyle, type StyleProp } from "react-native";
|
|
8
9
|
import { Animated } from "@umituz/react-native-design-system";
|
|
9
10
|
import { useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
10
11
|
import { ResultHeader } from "./ResultHeader";
|
|
@@ -35,7 +36,7 @@ export interface GenerationResultContentProps {
|
|
|
35
36
|
retry: string;
|
|
36
37
|
aiGenerated: string;
|
|
37
38
|
};
|
|
38
|
-
modalStyle?:
|
|
39
|
+
modalStyle?: StyleProp<ViewStyle>;
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
export const GenerationResultContent: React.FC<GenerationResultContentProps> = ({
|
|
@@ -49,7 +50,23 @@ export const GenerationResultContent: React.FC<GenerationResultContentProps> = (
|
|
|
49
50
|
modalStyle,
|
|
50
51
|
}) => {
|
|
51
52
|
const tokens = useAppDesignTokens();
|
|
52
|
-
|
|
53
|
+
|
|
54
|
+
const styles = useMemo(() => StyleSheet.create({
|
|
55
|
+
container: {
|
|
56
|
+
width: width - 40,
|
|
57
|
+
maxHeight: "90%",
|
|
58
|
+
backgroundColor: tokens.colors.backgroundPrimary,
|
|
59
|
+
borderRadius: 28,
|
|
60
|
+
overflow: "hidden",
|
|
61
|
+
},
|
|
62
|
+
scrollView: {
|
|
63
|
+
flex: 1,
|
|
64
|
+
},
|
|
65
|
+
scrollContent: {
|
|
66
|
+
paddingTop: 24,
|
|
67
|
+
paddingBottom: 20,
|
|
68
|
+
},
|
|
69
|
+
}), [tokens]);
|
|
53
70
|
|
|
54
71
|
return (
|
|
55
72
|
<Animated.View style={[styles.container, modalStyle]}>
|
|
@@ -73,21 +90,3 @@ export const GenerationResultContent: React.FC<GenerationResultContentProps> = (
|
|
|
73
90
|
</Animated.View>
|
|
74
91
|
);
|
|
75
92
|
};
|
|
76
|
-
|
|
77
|
-
const createStyles = (tokens: any) =>
|
|
78
|
-
StyleSheet.create({
|
|
79
|
-
container: {
|
|
80
|
-
width: width - 40,
|
|
81
|
-
maxHeight: "90%",
|
|
82
|
-
backgroundColor: tokens.colors.backgroundPrimary,
|
|
83
|
-
borderRadius: 28,
|
|
84
|
-
overflow: "hidden",
|
|
85
|
-
},
|
|
86
|
-
scrollView: {
|
|
87
|
-
flex: 1,
|
|
88
|
-
},
|
|
89
|
-
scrollContent: {
|
|
90
|
-
paddingTop: 24,
|
|
91
|
-
paddingBottom: 20,
|
|
92
|
-
},
|
|
93
|
-
});
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* Action buttons for generation results
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import React from "react";
|
|
6
|
+
import * as React from "react";
|
|
7
|
+
import { useMemo } from "react";
|
|
7
8
|
import { View, TouchableOpacity, StyleSheet } from "react-native";
|
|
8
9
|
import {
|
|
9
10
|
AtomicText,
|
|
@@ -34,56 +35,8 @@ export const ResultActions: React.FC<ResultActionsProps> = ({
|
|
|
34
35
|
translations,
|
|
35
36
|
}) => {
|
|
36
37
|
const tokens = useAppDesignTokens();
|
|
37
|
-
const styles = createStyles(tokens);
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
<View style={styles.container}>
|
|
41
|
-
{onRetry && (
|
|
42
|
-
<TouchableOpacity style={styles.retryButton} onPress={onRetry}>
|
|
43
|
-
<AtomicIcon name="refresh" size="sm" customColor={tokens.colors.primary} />
|
|
44
|
-
<AtomicText style={styles.retryText}>{translations.retry}</AtomicText>
|
|
45
|
-
</TouchableOpacity>
|
|
46
|
-
)}
|
|
47
|
-
|
|
48
|
-
<View style={styles.buttons}>
|
|
49
|
-
{onShare && (
|
|
50
|
-
<TouchableOpacity
|
|
51
|
-
style={[styles.button, styles.shareButton]}
|
|
52
|
-
onPress={onShare}
|
|
53
|
-
disabled={isSharing}
|
|
54
|
-
>
|
|
55
|
-
<AtomicIcon
|
|
56
|
-
name={isSharing ? "hourglass" : "share-social"}
|
|
57
|
-
size="md"
|
|
58
|
-
customColor="#fff"
|
|
59
|
-
/>
|
|
60
|
-
<AtomicText style={styles.shareText}>
|
|
61
|
-
{isSharing ? translations.sharing : translations.share}
|
|
62
|
-
</AtomicText>
|
|
63
|
-
</TouchableOpacity>
|
|
64
|
-
)}
|
|
65
|
-
|
|
66
|
-
{onSave && (
|
|
67
|
-
<TouchableOpacity
|
|
68
|
-
style={[styles.button, styles.saveButton]}
|
|
69
|
-
onPress={onSave}
|
|
70
|
-
disabled={isSaving}
|
|
71
|
-
>
|
|
72
|
-
<AtomicIcon
|
|
73
|
-
name={isSaving ? "hourglass" : "download"}
|
|
74
|
-
size="md"
|
|
75
|
-
customColor={tokens.colors.primary}
|
|
76
|
-
/>
|
|
77
|
-
<AtomicText style={styles.saveText}>{translations.save}</AtomicText>
|
|
78
|
-
</TouchableOpacity>
|
|
79
|
-
)}
|
|
80
|
-
</View>
|
|
81
|
-
</View>
|
|
82
|
-
);
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
const createStyles = (tokens: any) =>
|
|
86
|
-
StyleSheet.create({
|
|
39
|
+
const styles = useMemo(() => StyleSheet.create({
|
|
87
40
|
container: {
|
|
88
41
|
paddingHorizontal: 20,
|
|
89
42
|
paddingBottom: 20,
|
|
@@ -120,7 +73,7 @@ const createStyles = (tokens: any) =>
|
|
|
120
73
|
shareText: {
|
|
121
74
|
fontSize: 15,
|
|
122
75
|
fontWeight: "700",
|
|
123
|
-
color:
|
|
76
|
+
color: tokens.colors.onPrimary,
|
|
124
77
|
},
|
|
125
78
|
saveButton: {
|
|
126
79
|
backgroundColor: tokens.colors.surface,
|
|
@@ -132,4 +85,50 @@ const createStyles = (tokens: any) =>
|
|
|
132
85
|
fontWeight: "700",
|
|
133
86
|
color: tokens.colors.primary,
|
|
134
87
|
},
|
|
135
|
-
});
|
|
88
|
+
}), [tokens]);
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<View style={styles.container}>
|
|
92
|
+
{onRetry && (
|
|
93
|
+
<TouchableOpacity style={styles.retryButton} onPress={onRetry}>
|
|
94
|
+
<AtomicIcon name="refresh" size="sm" color="primary" />
|
|
95
|
+
<AtomicText style={styles.retryText}>{translations.retry}</AtomicText>
|
|
96
|
+
</TouchableOpacity>
|
|
97
|
+
)}
|
|
98
|
+
|
|
99
|
+
<View style={styles.buttons}>
|
|
100
|
+
{onShare && (
|
|
101
|
+
<TouchableOpacity
|
|
102
|
+
style={[styles.button, styles.shareButton]}
|
|
103
|
+
onPress={onShare}
|
|
104
|
+
disabled={isSharing}
|
|
105
|
+
>
|
|
106
|
+
<AtomicIcon
|
|
107
|
+
name={isSharing ? "hourglass" : "share-social"}
|
|
108
|
+
size="md"
|
|
109
|
+
color="onPrimary"
|
|
110
|
+
/>
|
|
111
|
+
<AtomicText style={styles.shareText}>
|
|
112
|
+
{isSharing ? translations.sharing : translations.share}
|
|
113
|
+
</AtomicText>
|
|
114
|
+
</TouchableOpacity>
|
|
115
|
+
)}
|
|
116
|
+
|
|
117
|
+
{onSave && (
|
|
118
|
+
<TouchableOpacity
|
|
119
|
+
style={[styles.button, styles.saveButton]}
|
|
120
|
+
onPress={onSave}
|
|
121
|
+
disabled={isSaving}
|
|
122
|
+
>
|
|
123
|
+
<AtomicIcon
|
|
124
|
+
name={isSaving ? "hourglass" : "download"}
|
|
125
|
+
size="md"
|
|
126
|
+
color="primary"
|
|
127
|
+
/>
|
|
128
|
+
<AtomicText style={styles.saveText}>{translations.save}</AtomicText>
|
|
129
|
+
</TouchableOpacity>
|
|
130
|
+
)}
|
|
131
|
+
</View>
|
|
132
|
+
</View>
|
|
133
|
+
);
|
|
134
|
+
};
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* Header with title and date badge
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import React from "react";
|
|
6
|
+
import * as React from "react";
|
|
7
|
+
import { useMemo } from "react";
|
|
7
8
|
import { View, StyleSheet } from "react-native";
|
|
8
9
|
import {
|
|
9
10
|
AtomicText,
|
|
@@ -18,29 +19,8 @@ export interface ResultHeaderProps {
|
|
|
18
19
|
|
|
19
20
|
export const ResultHeader: React.FC<ResultHeaderProps> = ({ title, date }) => {
|
|
20
21
|
const tokens = useAppDesignTokens();
|
|
21
|
-
const styles = createStyles(tokens);
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return (
|
|
26
|
-
<View style={styles.container}>
|
|
27
|
-
{title && <AtomicText style={styles.title}>{title}</AtomicText>}
|
|
28
|
-
{date && (
|
|
29
|
-
<View style={styles.badge}>
|
|
30
|
-
<AtomicIcon
|
|
31
|
-
name="calendar-outline"
|
|
32
|
-
size="sm"
|
|
33
|
-
customColor={tokens.colors.primary}
|
|
34
|
-
/>
|
|
35
|
-
<AtomicText style={styles.dateText}>{date}</AtomicText>
|
|
36
|
-
</View>
|
|
37
|
-
)}
|
|
38
|
-
</View>
|
|
39
|
-
);
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
const createStyles = (tokens: any) =>
|
|
43
|
-
StyleSheet.create({
|
|
23
|
+
const styles = useMemo(() => StyleSheet.create({
|
|
44
24
|
container: {
|
|
45
25
|
alignItems: "center",
|
|
46
26
|
paddingHorizontal: 24,
|
|
@@ -60,7 +40,7 @@ const createStyles = (tokens: any) =>
|
|
|
60
40
|
gap: 6,
|
|
61
41
|
paddingHorizontal: 14,
|
|
62
42
|
paddingVertical: 6,
|
|
63
|
-
backgroundColor:
|
|
43
|
+
backgroundColor: tokens.colors.primaryContainer,
|
|
64
44
|
borderRadius: 16,
|
|
65
45
|
},
|
|
66
46
|
dateText: {
|
|
@@ -68,4 +48,23 @@ const createStyles = (tokens: any) =>
|
|
|
68
48
|
fontWeight: "600",
|
|
69
49
|
color: tokens.colors.primary,
|
|
70
50
|
},
|
|
71
|
-
});
|
|
51
|
+
}), [tokens]);
|
|
52
|
+
|
|
53
|
+
if (!title && !date) return null;
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<View style={styles.container}>
|
|
57
|
+
{title && <AtomicText style={styles.title}>{title}</AtomicText>}
|
|
58
|
+
{date && (
|
|
59
|
+
<View style={styles.badge}>
|
|
60
|
+
<AtomicIcon
|
|
61
|
+
name="calendar-outline"
|
|
62
|
+
size="sm"
|
|
63
|
+
color="primary"
|
|
64
|
+
/>
|
|
65
|
+
<AtomicText style={styles.dateText}>{date}</AtomicText>
|
|
66
|
+
</View>
|
|
67
|
+
)}
|
|
68
|
+
</View>
|
|
69
|
+
);
|
|
70
|
+
};
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* Displays generated image with AI badge
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import React from "react";
|
|
6
|
+
import * as React from "react";
|
|
7
|
+
import { useMemo } from "react";
|
|
7
8
|
import { View, Image, StyleSheet } from "react-native";
|
|
8
9
|
import {
|
|
9
10
|
AtomicText,
|
|
@@ -21,23 +22,8 @@ export const ResultImageCard: React.FC<ResultImageCardProps> = ({
|
|
|
21
22
|
badgeText,
|
|
22
23
|
}) => {
|
|
23
24
|
const tokens = useAppDesignTokens();
|
|
24
|
-
const styles = createStyles(tokens);
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
<View style={styles.container}>
|
|
28
|
-
<View style={styles.frame}>
|
|
29
|
-
<Image source={{ uri: imageUrl }} style={styles.image} resizeMode="cover" />
|
|
30
|
-
<View style={styles.badge}>
|
|
31
|
-
<AtomicIcon name="sparkles" size="xs" customColor="#fff" />
|
|
32
|
-
<AtomicText style={styles.badgeText}>{badgeText}</AtomicText>
|
|
33
|
-
</View>
|
|
34
|
-
</View>
|
|
35
|
-
</View>
|
|
36
|
-
);
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
const createStyles = (tokens: any) =>
|
|
40
|
-
StyleSheet.create({
|
|
26
|
+
const styles = useMemo(() => StyleSheet.create({
|
|
41
27
|
container: {
|
|
42
28
|
paddingHorizontal: 20,
|
|
43
29
|
marginBottom: 20,
|
|
@@ -60,13 +46,26 @@ const createStyles = (tokens: any) =>
|
|
|
60
46
|
gap: 4,
|
|
61
47
|
paddingHorizontal: 10,
|
|
62
48
|
paddingVertical: 5,
|
|
63
|
-
backgroundColor: "rgba(0,0,0,0.6)",
|
|
49
|
+
backgroundColor: "rgba(0, 0, 0, 0.6)",
|
|
64
50
|
borderRadius: 12,
|
|
65
51
|
},
|
|
66
52
|
badgeText: {
|
|
67
53
|
fontSize: 10,
|
|
68
54
|
fontWeight: "700",
|
|
69
|
-
color: "#
|
|
55
|
+
color: "#FFFFFF",
|
|
70
56
|
letterSpacing: 0.5,
|
|
71
57
|
},
|
|
72
|
-
});
|
|
58
|
+
}), [tokens]);
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<View style={styles.container}>
|
|
62
|
+
<View style={styles.frame}>
|
|
63
|
+
<Image source={{ uri: imageUrl }} style={styles.image} resizeMode="cover" />
|
|
64
|
+
<View style={styles.badge}>
|
|
65
|
+
<AtomicIcon name="sparkles" size="xs" color="onPrimary" />
|
|
66
|
+
<AtomicText style={styles.badgeText}>{badgeText}</AtomicText>
|
|
67
|
+
</View>
|
|
68
|
+
</View>
|
|
69
|
+
</View>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* Displays story text with quote styling
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import React from "react";
|
|
6
|
+
import * as React from "react";
|
|
7
|
+
import { useMemo } from "react";
|
|
7
8
|
import { View, StyleSheet } from "react-native";
|
|
8
9
|
import {
|
|
9
10
|
AtomicText,
|
|
@@ -17,28 +18,8 @@ export interface ResultStoryCardProps {
|
|
|
17
18
|
|
|
18
19
|
export const ResultStoryCard: React.FC<ResultStoryCardProps> = ({ story }) => {
|
|
19
20
|
const tokens = useAppDesignTokens();
|
|
20
|
-
const styles = createStyles(tokens);
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
<View style={styles.outer}>
|
|
24
|
-
<LinearGradient
|
|
25
|
-
colors={[`${tokens.colors.primary}15`, `${tokens.colors.primary}05`]}
|
|
26
|
-
style={styles.container}
|
|
27
|
-
>
|
|
28
|
-
<AtomicText style={styles.quoteIcon}>"</AtomicText>
|
|
29
|
-
<AtomicText style={styles.text}>{story}</AtomicText>
|
|
30
|
-
<View style={styles.quoteEnd}>
|
|
31
|
-
<AtomicText style={[styles.quoteIcon, styles.quoteIconEnd]}>
|
|
32
|
-
"
|
|
33
|
-
</AtomicText>
|
|
34
|
-
</View>
|
|
35
|
-
</LinearGradient>
|
|
36
|
-
</View>
|
|
37
|
-
);
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
const createStyles = (tokens: any) =>
|
|
41
|
-
StyleSheet.create({
|
|
22
|
+
const styles = useMemo(() => StyleSheet.create({
|
|
42
23
|
outer: {
|
|
43
24
|
paddingHorizontal: 20,
|
|
44
25
|
marginBottom: 20,
|
|
@@ -47,7 +28,7 @@ const createStyles = (tokens: any) =>
|
|
|
47
28
|
padding: 20,
|
|
48
29
|
borderRadius: 16,
|
|
49
30
|
borderWidth: 1,
|
|
50
|
-
borderColor:
|
|
31
|
+
borderColor: tokens.colors.primaryContainer,
|
|
51
32
|
},
|
|
52
33
|
quoteIcon: {
|
|
53
34
|
fontSize: 40,
|
|
@@ -71,4 +52,22 @@ const createStyles = (tokens: any) =>
|
|
|
71
52
|
fontStyle: "italic",
|
|
72
53
|
fontWeight: "500",
|
|
73
54
|
},
|
|
74
|
-
});
|
|
55
|
+
}), [tokens]);
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<View style={styles.outer}>
|
|
59
|
+
<LinearGradient
|
|
60
|
+
colors={[tokens.colors.primaryContainer, tokens.colors.surface]}
|
|
61
|
+
style={styles.container}
|
|
62
|
+
>
|
|
63
|
+
<AtomicText style={styles.quoteIcon}>"</AtomicText>
|
|
64
|
+
<AtomicText style={styles.text}>{story}</AtomicText>
|
|
65
|
+
<View style={styles.quoteEnd}>
|
|
66
|
+
<AtomicText style={[styles.quoteIcon, styles.quoteIconEnd]}>
|
|
67
|
+
"
|
|
68
|
+
</AtomicText>
|
|
69
|
+
</View>
|
|
70
|
+
</LinearGradient>
|
|
71
|
+
</View>
|
|
72
|
+
);
|
|
73
|
+
};
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
* Generic types for photo-based AI generation workflows
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
export interface PhotoGenerationInput<TMetadata =
|
|
6
|
+
export interface PhotoGenerationInput<TMetadata = unknown> {
|
|
7
7
|
photos: Array<{ uri: string; base64: string }>;
|
|
8
8
|
metadata?: TMetadata;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export interface PhotoGenerationResult<TResult =
|
|
11
|
+
export interface PhotoGenerationResult<TResult = unknown> {
|
|
12
12
|
success: boolean;
|
|
13
13
|
data?: TResult;
|
|
14
14
|
error?: PhotoGenerationError;
|
|
@@ -20,18 +20,27 @@ export interface PhotoGenerationError {
|
|
|
20
20
|
originalError?: Error;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
export interface AlertMessages {
|
|
24
|
+
networkError: string;
|
|
25
|
+
policyViolation: string;
|
|
26
|
+
saveFailed: string;
|
|
27
|
+
creditFailed: string;
|
|
28
|
+
unknown: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
23
31
|
export interface PhotoGenerationConfig<TInput, TResult, TSaveInput> {
|
|
24
32
|
generate: (input: TInput) => Promise<TResult>;
|
|
25
33
|
save?: (result: TResult, input: TInput) => Promise<TSaveInput>;
|
|
26
|
-
buildMetadata?: (input: TInput) => Record<string,
|
|
34
|
+
buildMetadata?: (input: TInput) => Record<string, unknown>;
|
|
27
35
|
checkCredits?: () => Promise<boolean>;
|
|
28
36
|
deductCredits?: () => Promise<void>;
|
|
29
37
|
onSuccess?: (result: TResult) => void;
|
|
30
38
|
onError?: (error: PhotoGenerationError) => void;
|
|
31
39
|
onSaveComplete?: (saveResult: TSaveInput) => void;
|
|
40
|
+
alertMessages: AlertMessages;
|
|
32
41
|
}
|
|
33
42
|
|
|
34
|
-
export interface PhotoGenerationState<TResult =
|
|
43
|
+
export interface PhotoGenerationState<TResult = unknown> {
|
|
35
44
|
isGenerating: boolean;
|
|
36
45
|
result: TResult | null;
|
|
37
46
|
error: PhotoGenerationError | null;
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { useState, useCallback, useRef } from "react";
|
|
7
7
|
import { useOfflineStore } from "@umituz/react-native-offline";
|
|
8
|
+
import { useAlert } from "@umituz/react-native-design-system";
|
|
8
9
|
import type {
|
|
9
10
|
PhotoGenerationConfig,
|
|
10
11
|
PhotoGenerationState,
|
|
@@ -18,7 +19,7 @@ export interface UsePhotoGenerationReturn<TInput, TResult> extends PhotoGenerati
|
|
|
18
19
|
status: PhotoGenerationStatus;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
export const usePhotoGeneration = <TInput, TResult, TSaveInput =
|
|
22
|
+
export const usePhotoGeneration = <TInput, TResult, TSaveInput = unknown>(
|
|
22
23
|
config: PhotoGenerationConfig<TInput, TResult, TSaveInput>,
|
|
23
24
|
): UsePhotoGenerationReturn<TInput, TResult> => {
|
|
24
25
|
const {
|
|
@@ -29,6 +30,7 @@ export const usePhotoGeneration = <TInput, TResult, TSaveInput = any>(
|
|
|
29
30
|
onSuccess,
|
|
30
31
|
onError,
|
|
31
32
|
onSaveComplete,
|
|
33
|
+
alertMessages,
|
|
32
34
|
} = config;
|
|
33
35
|
|
|
34
36
|
const [state, setState] = useState<PhotoGenerationState<TResult>>({
|
|
@@ -41,6 +43,7 @@ export const usePhotoGeneration = <TInput, TResult, TSaveInput = any>(
|
|
|
41
43
|
const [status, setStatus] = useState<PhotoGenerationStatus>("idle");
|
|
42
44
|
const isGeneratingRef = useRef(false);
|
|
43
45
|
const offlineStore = useOfflineStore();
|
|
46
|
+
const { showError } = useAlert();
|
|
44
47
|
|
|
45
48
|
const createError = useCallback(
|
|
46
49
|
(
|
|
@@ -58,7 +61,6 @@ export const usePhotoGeneration = <TInput, TResult, TSaveInput = any>(
|
|
|
58
61
|
const generate = useCallback(
|
|
59
62
|
async (input: TInput) => {
|
|
60
63
|
if (isGeneratingRef.current) {
|
|
61
|
-
if (__DEV__) console.warn("[usePhotoGeneration] Generation already in progress");
|
|
62
64
|
return;
|
|
63
65
|
}
|
|
64
66
|
|
|
@@ -98,7 +100,7 @@ export const usePhotoGeneration = <TInput, TResult, TSaveInput = any>(
|
|
|
98
100
|
throw createError(
|
|
99
101
|
"save_failed",
|
|
100
102
|
"Failed to save result",
|
|
101
|
-
saveError
|
|
103
|
+
saveError instanceof Error ? saveError : new Error(String(saveError)),
|
|
102
104
|
);
|
|
103
105
|
}
|
|
104
106
|
}
|
|
@@ -109,9 +111,8 @@ export const usePhotoGeneration = <TInput, TResult, TSaveInput = any>(
|
|
|
109
111
|
if (deductCredits) {
|
|
110
112
|
try {
|
|
111
113
|
await deductCredits();
|
|
112
|
-
} catch
|
|
113
|
-
|
|
114
|
-
console.error("[usePhotoGeneration] Credit deduction failed", deductError);
|
|
114
|
+
} catch {
|
|
115
|
+
// Silently fail credit deduction as generation succeeded
|
|
115
116
|
}
|
|
116
117
|
}
|
|
117
118
|
|
|
@@ -123,13 +124,20 @@ export const usePhotoGeneration = <TInput, TResult, TSaveInput = any>(
|
|
|
123
124
|
});
|
|
124
125
|
setStatus("success");
|
|
125
126
|
onSuccess?.(result);
|
|
126
|
-
} catch (
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
127
|
+
} catch (err: unknown) {
|
|
128
|
+
let generationError: PhotoGenerationError;
|
|
129
|
+
|
|
130
|
+
if (err && typeof err === "object" && "type" in err && "message" in err) {
|
|
131
|
+
generationError = err as PhotoGenerationError;
|
|
132
|
+
} else if (err instanceof Error) {
|
|
133
|
+
if (err.name === "ContentPolicyViolationError") {
|
|
134
|
+
generationError = createError("policy_violation", "Content policy violation", err);
|
|
135
|
+
} else {
|
|
136
|
+
generationError = createError("unknown", err.message || "Generation failed", err);
|
|
137
|
+
}
|
|
138
|
+
} else {
|
|
139
|
+
generationError = createError("unknown", "Generation failed");
|
|
140
|
+
}
|
|
133
141
|
|
|
134
142
|
setState({
|
|
135
143
|
isGenerating: false,
|
|
@@ -138,6 +146,15 @@ export const usePhotoGeneration = <TInput, TResult, TSaveInput = any>(
|
|
|
138
146
|
progress: 0,
|
|
139
147
|
});
|
|
140
148
|
setStatus("error");
|
|
149
|
+
|
|
150
|
+
const errorMessage =
|
|
151
|
+
generationError.type === "network_error" ? alertMessages.networkError :
|
|
152
|
+
generationError.type === "policy_violation" ? alertMessages.policyViolation :
|
|
153
|
+
generationError.type === "save_failed" ? alertMessages.saveFailed :
|
|
154
|
+
generationError.type === "credit_failed" ? alertMessages.creditFailed :
|
|
155
|
+
alertMessages.unknown;
|
|
156
|
+
|
|
157
|
+
showError("Error", errorMessage);
|
|
141
158
|
onError?.(generationError);
|
|
142
159
|
} finally {
|
|
143
160
|
isGeneratingRef.current = false;
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { serverTimestamp, addDoc, collection } from "firebase/firestore";
|
|
2
|
-
import { generateUUID } from "@umituz/react-native-uuid";
|
|
3
|
-
import type { ICreationsRepository } from "../../domain/repositories/ICreationsRepository";
|
|
4
|
-
import type { ICreationsStorageService } from "../../domain/services/ICreationsStorageService";
|
|
5
|
-
import type { CreationType } from "../../domain/value-objects";
|
|
6
|
-
import { BaseRepository } from "@umituz/react-native-firebase";
|
|
7
|
-
|
|
8
|
-
export interface CreateCreationDTO {
|
|
9
|
-
userId: string;
|
|
10
|
-
type: CreationType;
|
|
11
|
-
prompt: string;
|
|
12
|
-
metadata?: Record<string, any>;
|
|
13
|
-
imageUri: string; // can be local file uri or base64
|
|
14
|
-
aspectRatio?: number;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export class CreationsService extends BaseRepository {
|
|
18
|
-
constructor(
|
|
19
|
-
private readonly repository: ICreationsRepository,
|
|
20
|
-
private readonly storageService: ICreationsStorageService,
|
|
21
|
-
private readonly collectionName: string = "creations" // Default to generic name, app can override via repo
|
|
22
|
-
) {
|
|
23
|
-
super();
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
async saveCreation(dto: CreateCreationDTO): Promise<string> {
|
|
27
|
-
const db = this.getDb();
|
|
28
|
-
if (!db) throw new Error("Firestore not initialized");
|
|
29
|
-
|
|
30
|
-
try {
|
|
31
|
-
const creationId = generateUUID();
|
|
32
|
-
|
|
33
|
-
const imageUrl = await this.storageService.uploadCreationImage(
|
|
34
|
-
dto.userId,
|
|
35
|
-
creationId,
|
|
36
|
-
dto.imageUri
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
await this.repository.create(dto.userId, {
|
|
40
|
-
id: creationId,
|
|
41
|
-
uri: imageUrl,
|
|
42
|
-
type: dto.type.id,
|
|
43
|
-
prompt: dto.prompt,
|
|
44
|
-
metadata: dto.metadata,
|
|
45
|
-
createdAt: new Date(),
|
|
46
|
-
isShared: false,
|
|
47
|
-
isFavorite: false,
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
return creationId;
|
|
51
|
-
} catch (error) {
|
|
52
|
-
console.error(error);
|
|
53
|
-
throw error;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
async getCreation(userId: string, id: string): Promise<any> {
|
|
58
|
-
return this.repository.getById(userId, id);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
async updateCreation(
|
|
62
|
-
userId: string,
|
|
63
|
-
id: string,
|
|
64
|
-
updates: { metadata?: Record<string, any> },
|
|
65
|
-
): Promise<boolean> {
|
|
66
|
-
return this.repository.update(userId, id, updates);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
async deleteCreation(userId: string, id: string): Promise<boolean> {
|
|
70
|
-
return this.repository.delete(userId, id);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Creation Entity
|
|
3
|
-
* Represents an AI-generated creation
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export interface Creation {
|
|
7
|
-
readonly id: string;
|
|
8
|
-
readonly uri: string;
|
|
9
|
-
readonly type: string;
|
|
10
|
-
readonly prompt?: string;
|
|
11
|
-
readonly metadata?: Record<string, any>;
|
|
12
|
-
readonly originalUri?: string;
|
|
13
|
-
readonly createdAt: Date;
|
|
14
|
-
readonly isShared: boolean;
|
|
15
|
-
readonly isFavorite: boolean;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface CreationDocument {
|
|
19
|
-
readonly uri?: string;
|
|
20
|
-
readonly prompt?: string;
|
|
21
|
-
readonly metadata?: Record<string, any>;
|
|
22
|
-
readonly originalImage?: string;
|
|
23
|
-
readonly originalImageUrl?: string;
|
|
24
|
-
readonly transformedImage?: string;
|
|
25
|
-
readonly transformedImageUrl?: string;
|
|
26
|
-
readonly transformationType?: string;
|
|
27
|
-
readonly type?: string;
|
|
28
|
-
readonly status?: string;
|
|
29
|
-
readonly isShared: boolean;
|
|
30
|
-
readonly isFavorite: boolean;
|
|
31
|
-
readonly createdAt: FirebaseTimestamp | Date; // Allow Date for writing
|
|
32
|
-
readonly completedAt?: FirebaseTimestamp | Date;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
interface FirebaseTimestamp {
|
|
36
|
-
toDate: () => Date;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export function mapDocumentToCreation(
|
|
40
|
-
id: string,
|
|
41
|
-
data: CreationDocument,
|
|
42
|
-
): Creation {
|
|
43
|
-
return {
|
|
44
|
-
id,
|
|
45
|
-
uri: data.transformedImageUrl || data.transformedImage || data.uri || "",
|
|
46
|
-
type: data.transformationType || data.type || "unknown",
|
|
47
|
-
prompt: data.prompt,
|
|
48
|
-
metadata: data.metadata,
|
|
49
|
-
originalUri: data.originalImageUrl || data.originalImage,
|
|
50
|
-
createdAt: (data.createdAt as any)?.toDate?.() || (data.createdAt instanceof Date ? data.createdAt : new Date()),
|
|
51
|
-
isShared: data.isShared ?? false,
|
|
52
|
-
isFavorite: data.isFavorite ?? false,
|
|
53
|
-
};
|
|
54
|
-
}
|